ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/newcpu.h
Revision: 1.15
Committed: 2005-06-11T06:43:24Z (18 years, 11 months ago) by gbeauche
Content type: text/plain
Branch: MAIN
CVS Tags: nigel-build-17
Changes since 1.14: +13 -0 lines
Log Message:
Much improved responsiveness on NetBSD systems.

On those systems, it's really hard to get high resolution timings and the
system oftens fails to honour a timeout in less than 20 ms. The idea here
is to have an average m68k instruction count (countdown quantum) that
triggers real interrupt checks. The quantum is calibrated every 10 ticks
and has a 1000 Hz resolution on average.

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * UAE - The Un*x Amiga Emulator
3     *
4     * MC68000 emulation
5     *
6     * Copyright 1995 Bernd Schmidt
7     */
8    
9 gbeauche 1.4 #ifndef NEWCPU_H
10     #define NEWCPU_H
11    
12 gbeauche 1.10 #ifndef FLIGHT_RECORDER
13     #define FLIGHT_RECORDER 0
14     #endif
15    
16 gbeauche 1.8 #include "m68k.h"
17     #include "readcpu.h"
18     #include "spcflags.h"
19    
20 cebix 1.1 extern int areg_byteinc[];
21     extern int imm8_table[];
22    
23     extern int movem_index1[256];
24     extern int movem_index2[256];
25     extern int movem_next[256];
26    
27     extern int broken_in;
28    
29 gbeauche 1.8 #ifdef X86_ASSEMBLY
30     /* This hack seems to force all register saves (pushl %reg) to be moved to the
31     begining of the function, thus making it possible to cpuopti to remove them
32     since m68k_run_1 will save those registers before calling the instruction
33     handler */
34     # define cpuop_tag(tag) __asm__ __volatile__ ( "#cpuop_" tag )
35     #else
36     # define cpuop_tag(tag) ;
37     #endif
38    
39     #define cpuop_begin() do { cpuop_tag("begin"); } while (0)
40 gbeauche 1.12 #define cpuop_end() do { cpuop_tag("end"); } while (0)
41 cebix 1.1
42 gbeauche 1.12 typedef void REGPARAM2 cpuop_func (uae_u32) REGPARAM;
43 gbeauche 1.8
44 cebix 1.1 struct cputbl {
45     cpuop_func *handler;
46 gbeauche 1.8 uae_u16 specific;
47 cebix 1.1 uae_u16 opcode;
48     };
49    
50 gbeauche 1.10 extern cpuop_func *cpufunctbl[65536] ASM_SYM_FOR_FUNC ("cpufunctbl");
51    
52     #if USE_JIT
53     typedef void compop_func (uae_u32) REGPARAM;
54    
55     struct comptbl {
56     compop_func *handler;
57     uae_u32 specific;
58     uae_u32 opcode;
59     };
60     #endif
61    
62 gbeauche 1.12 extern void REGPARAM2 op_illg (uae_u32) REGPARAM;
63 cebix 1.1
64     typedef char flagtype;
65    
66 gbeauche 1.8 struct regstruct {
67     uae_u32 regs[16];
68 cebix 1.1
69 gbeauche 1.8 uae_u32 pc;
70     uae_u8 * pc_p;
71     uae_u8 * pc_oldp;
72    
73     spcflags_t spcflags;
74     int intmask;
75    
76     uae_u32 vbr, sfc, dfc;
77     uaecptr usp, isp, msp;
78     uae_u16 sr;
79     flagtype t1;
80     flagtype t0;
81     flagtype s;
82     flagtype m;
83     flagtype x;
84     flagtype stopped;
85 cebix 1.1
86 gbeauche 1.8 #if USE_PREFETCH_BUFFER
87 cebix 1.1 /* Fellow sources say this is 4 longwords. That's impossible. It needs
88     * to be at least a longword. The HRM has some cryptic comment about two
89     * instructions being on the same longword boundary.
90     * The way this is implemented now seems like a good compromise.
91     */
92     uae_u32 prefetch;
93 gbeauche 1.8 #endif
94     };
95    
96     extern regstruct regs, lastint_regs;
97 cebix 1.1
98     #define m68k_dreg(r,num) ((r).regs[(num)])
99     #define m68k_areg(r,num) (((r).regs + 8)[(num)])
100    
101     #define get_ibyte(o) do_get_mem_byte((uae_u8 *)(regs.pc_p + (o) + 1))
102     #define get_iword(o) do_get_mem_word((uae_u16 *)(regs.pc_p + (o)))
103     #define get_ilong(o) do_get_mem_long((uae_u32 *)(regs.pc_p + (o)))
104    
105     #ifdef HAVE_GET_WORD_UNSWAPPED
106     #define GET_OPCODE (do_get_mem_word_unswapped (regs.pc_p))
107     #else
108     #define GET_OPCODE (get_iword (0))
109     #endif
110    
111 gbeauche 1.8 #if USE_PREFETCH_BUFFER
112 cebix 1.1 static __inline__ uae_u32 get_ibyte_prefetch (uae_s32 o)
113     {
114     if (o > 3 || o < 0)
115     return do_get_mem_byte((uae_u8 *)(regs.pc_p + o + 1));
116    
117     return do_get_mem_byte((uae_u8 *)(((uae_u8 *)&regs.prefetch) + o + 1));
118     }
119     static __inline__ uae_u32 get_iword_prefetch (uae_s32 o)
120     {
121     if (o > 3 || o < 0)
122     return do_get_mem_word((uae_u16 *)(regs.pc_p + o));
123    
124     return do_get_mem_word((uae_u16 *)(((uae_u8 *)&regs.prefetch) + o));
125     }
126     static __inline__ uae_u32 get_ilong_prefetch (uae_s32 o)
127     {
128     if (o > 3 || o < 0)
129     return do_get_mem_long((uae_u32 *)(regs.pc_p + o));
130     if (o == 0)
131     return do_get_mem_long(&regs.prefetch);
132     return (do_get_mem_word (((uae_u16 *)&regs.prefetch) + 1) << 16) | do_get_mem_word ((uae_u16 *)(regs.pc_p + 4));
133     }
134 gbeauche 1.8 #endif
135 cebix 1.1
136     #define m68k_incpc(o) (regs.pc_p += (o))
137    
138     static __inline__ void fill_prefetch_0 (void)
139     {
140 gbeauche 1.4 #if USE_PREFETCH_BUFFER
141 cebix 1.1 uae_u32 r;
142     #ifdef UNALIGNED_PROFITABLE
143     r = *(uae_u32 *)regs.pc_p;
144     regs.prefetch = r;
145     #else
146     r = do_get_mem_long ((uae_u32 *)regs.pc_p);
147     do_put_mem_long (&regs.prefetch, r);
148     #endif
149 gbeauche 1.4 #endif
150 cebix 1.1 }
151    
152     #if 0
153     static __inline__ void fill_prefetch_2 (void)
154     {
155     uae_u32 r = do_get_mem_long (&regs.prefetch) << 16;
156     uae_u32 r2 = do_get_mem_word (((uae_u16 *)regs.pc_p) + 1);
157     r |= r2;
158     do_put_mem_long (&regs.prefetch, r);
159     }
160     #else
161     #define fill_prefetch_2 fill_prefetch_0
162     #endif
163    
164     /* These are only used by the 68020/68881 code, and therefore don't
165     * need to handle prefetch. */
166     static __inline__ uae_u32 next_ibyte (void)
167     {
168     uae_u32 r = get_ibyte (0);
169     m68k_incpc (2);
170     return r;
171     }
172    
173     static __inline__ uae_u32 next_iword (void)
174     {
175     uae_u32 r = get_iword (0);
176     m68k_incpc (2);
177     return r;
178     }
179    
180     static __inline__ uae_u32 next_ilong (void)
181     {
182     uae_u32 r = get_ilong (0);
183     m68k_incpc (4);
184     return r;
185     }
186    
187     static __inline__ void m68k_setpc (uaecptr newpc)
188     {
189 gbeauche 1.4 #if REAL_ADDRESSING || DIRECT_ADDRESSING
190     regs.pc_p = get_real_address(newpc);
191     #else
192 cebix 1.1 regs.pc_p = regs.pc_oldp = get_real_address(newpc);
193     regs.pc = newpc;
194 gbeauche 1.4 #endif
195 cebix 1.1 }
196    
197     static __inline__ uaecptr m68k_getpc (void)
198     {
199 gbeauche 1.4 #if REAL_ADDRESSING || DIRECT_ADDRESSING
200     return get_virtual_address(regs.pc_p);
201     #else
202 cebix 1.1 return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp);
203 gbeauche 1.4 #endif
204 cebix 1.1 }
205    
206     #define m68k_setpc_fast m68k_setpc
207     #define m68k_setpc_bcc m68k_setpc
208     #define m68k_setpc_rte m68k_setpc
209    
210 gbeauche 1.5 static __inline__ void m68k_do_rts(void)
211     {
212     m68k_setpc(get_long(m68k_areg(regs, 7)));
213     m68k_areg(regs, 7) += 4;
214     }
215    
216     static __inline__ void m68k_do_bsr(uaecptr oldpc, uae_s32 offset)
217     {
218     m68k_areg(regs, 7) -= 4;
219     put_long(m68k_areg(regs, 7), oldpc);
220     m68k_incpc(offset);
221     }
222    
223     static __inline__ void m68k_do_jsr(uaecptr oldpc, uaecptr dest)
224     {
225     m68k_areg(regs, 7) -= 4;
226     put_long(m68k_areg(regs, 7), oldpc);
227     m68k_setpc(dest);
228     }
229    
230 cebix 1.1 static __inline__ void m68k_setstopped (int stop)
231     {
232     regs.stopped = stop;
233 gbeauche 1.7 /* A traced STOP instruction drops through immediately without
234     actually stopping. */
235     if (stop && (regs.spcflags & SPCFLAG_DOTRACE) == 0)
236 gbeauche 1.8 SPCFLAGS_SET( SPCFLAG_STOP );
237 cebix 1.1 }
238    
239     extern uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp);
240     extern uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp);
241    
242     extern uae_s32 ShowEA (int reg, amodes mode, wordsizes size, char *buf);
243    
244     extern void MakeSR (void);
245     extern void MakeFromSR (void);
246     extern void Exception (int, uaecptr);
247     extern void dump_counts (void);
248 gbeauche 1.6 extern int m68k_move2c (int, uae_u32 *);
249     extern int m68k_movec2 (int, uae_u32 *);
250 cebix 1.1 extern void m68k_divl (uae_u32, uae_u32, uae_u16, uaecptr);
251     extern void m68k_mull (uae_u32, uae_u32, uae_u16);
252 gbeauche 1.8 extern void m68k_emulop (uae_u32);
253     extern void m68k_emulop_return (void);
254 cebix 1.1 extern void init_m68k (void);
255 gbeauche 1.3 extern void exit_m68k (void);
256 cebix 1.1 extern void m68k_dumpstate (uaecptr *);
257     extern void m68k_disasm (uaecptr, uaecptr *, int);
258     extern void m68k_reset (void);
259     extern void m68k_enter_debugger(void);
260 gbeauche 1.8 extern int m68k_do_specialties(void);
261 cebix 1.1
262     extern void mmu_op (uae_u32, uae_u16);
263    
264     /* Opcode of faulting instruction */
265     extern uae_u16 last_op_for_exception_3;
266     /* PC at fault time */
267     extern uaecptr last_addr_for_exception_3;
268     /* Address that generated the exception */
269     extern uaecptr last_fault_for_exception_3;
270    
271     #define CPU_OP_NAME(a) op ## a
272    
273     /* 68020 + 68881 */
274 gbeauche 1.8 extern struct cputbl op_smalltbl_0_ff[];
275 cebix 1.1 /* 68020 */
276 gbeauche 1.8 extern struct cputbl op_smalltbl_1_ff[];
277 cebix 1.1 /* 68010 */
278 gbeauche 1.8 extern struct cputbl op_smalltbl_2_ff[];
279 cebix 1.1 /* 68000 */
280 gbeauche 1.8 extern struct cputbl op_smalltbl_3_ff[];
281 cebix 1.1 /* 68000 slow but compatible. */
282 gbeauche 1.8 extern struct cputbl op_smalltbl_4_ff[];
283 cebix 1.1
284 gbeauche 1.10 #if FLIGHT_RECORDER
285 gbeauche 1.14 extern void m68k_record_step(uaecptr) REGPARAM;
286 gbeauche 1.10 #endif
287 gbeauche 1.8 extern void m68k_do_execute(void);
288     extern void m68k_execute(void);
289 gbeauche 1.10 #if USE_JIT
290 gbeauche 1.13 #if defined(X86_ASSEMBLY) || defined(X86_64_ASSEMBLY)
291 gbeauche 1.11 /* This is generated code */
292     extern void (*m68k_compile_execute)(void);
293     #else
294 gbeauche 1.10 extern void m68k_do_compile_execute(void);
295     extern void m68k_compile_execute(void);
296 gbeauche 1.11 #endif
297 gbeauche 1.10 #endif
298 gbeauche 1.15 #ifdef USE_CPU_EMUL_SERVICES
299     extern int32 emulated_ticks;
300     extern void cpu_do_check_ticks(void);
301    
302     static inline void cpu_check_ticks(void)
303     {
304     if (--emulated_ticks <= 0)
305     cpu_do_check_ticks();
306     }
307     #else
308     #define cpu_check_ticks()
309     #define cpu_do_check_ticks()
310     #endif
311 gbeauche 1.8
312 gbeauche 1.4 #endif /* NEWCPU_H */