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 (19 years, 5 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

# Content
1 /*
2 * UAE - The Un*x Amiga Emulator
3 *
4 * MC68000 emulation
5 *
6 * Copyright 1995 Bernd Schmidt
7 */
8
9 #ifndef NEWCPU_H
10 #define NEWCPU_H
11
12 #ifndef FLIGHT_RECORDER
13 #define FLIGHT_RECORDER 0
14 #endif
15
16 #include "m68k.h"
17 #include "readcpu.h"
18 #include "spcflags.h"
19
20 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 #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 #define cpuop_end() do { cpuop_tag("end"); } while (0)
41
42 typedef void REGPARAM2 cpuop_func (uae_u32) REGPARAM;
43
44 struct cputbl {
45 cpuop_func *handler;
46 uae_u16 specific;
47 uae_u16 opcode;
48 };
49
50 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 extern void REGPARAM2 op_illg (uae_u32) REGPARAM;
63
64 typedef char flagtype;
65
66 struct regstruct {
67 uae_u32 regs[16];
68
69 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
86 #if USE_PREFETCH_BUFFER
87 /* 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 #endif
94 };
95
96 extern regstruct regs, lastint_regs;
97
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 #if USE_PREFETCH_BUFFER
112 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 #endif
135
136 #define m68k_incpc(o) (regs.pc_p += (o))
137
138 static __inline__ void fill_prefetch_0 (void)
139 {
140 #if USE_PREFETCH_BUFFER
141 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 #endif
150 }
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 #if REAL_ADDRESSING || DIRECT_ADDRESSING
190 regs.pc_p = get_real_address(newpc);
191 #else
192 regs.pc_p = regs.pc_oldp = get_real_address(newpc);
193 regs.pc = newpc;
194 #endif
195 }
196
197 static __inline__ uaecptr m68k_getpc (void)
198 {
199 #if REAL_ADDRESSING || DIRECT_ADDRESSING
200 return get_virtual_address(regs.pc_p);
201 #else
202 return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp);
203 #endif
204 }
205
206 #define m68k_setpc_fast m68k_setpc
207 #define m68k_setpc_bcc m68k_setpc
208 #define m68k_setpc_rte m68k_setpc
209
210 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 static __inline__ void m68k_setstopped (int stop)
231 {
232 regs.stopped = stop;
233 /* A traced STOP instruction drops through immediately without
234 actually stopping. */
235 if (stop && (regs.spcflags & SPCFLAG_DOTRACE) == 0)
236 SPCFLAGS_SET( SPCFLAG_STOP );
237 }
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 extern int m68k_move2c (int, uae_u32 *);
249 extern int m68k_movec2 (int, uae_u32 *);
250 extern void m68k_divl (uae_u32, uae_u32, uae_u16, uaecptr);
251 extern void m68k_mull (uae_u32, uae_u32, uae_u16);
252 extern void m68k_emulop (uae_u32);
253 extern void m68k_emulop_return (void);
254 extern void init_m68k (void);
255 extern void exit_m68k (void);
256 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 extern int m68k_do_specialties(void);
261
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 extern struct cputbl op_smalltbl_0_ff[];
275 /* 68020 */
276 extern struct cputbl op_smalltbl_1_ff[];
277 /* 68010 */
278 extern struct cputbl op_smalltbl_2_ff[];
279 /* 68000 */
280 extern struct cputbl op_smalltbl_3_ff[];
281 /* 68000 slow but compatible. */
282 extern struct cputbl op_smalltbl_4_ff[];
283
284 #if FLIGHT_RECORDER
285 extern void m68k_record_step(uaecptr) REGPARAM;
286 #endif
287 extern void m68k_do_execute(void);
288 extern void m68k_execute(void);
289 #if USE_JIT
290 #if defined(X86_ASSEMBLY) || defined(X86_64_ASSEMBLY)
291 /* This is generated code */
292 extern void (*m68k_compile_execute)(void);
293 #else
294 extern void m68k_do_compile_execute(void);
295 extern void m68k_compile_execute(void);
296 #endif
297 #endif
298 #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
312 #endif /* NEWCPU_H */