|
|
1.1 root 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: #include "readcpu.h"
13: //#include "machdep/m68k.h"
14: #include "m68k.h"
15: #include "compat.h"
16: #include "maccess.h"
17: #include "events.h"
18: #include "memory.h"
19: #include "custom.h"
20:
21: /* Possible exceptions sources for M68000_Exception() and Exception() */
22: #define M68000_EXC_SRC_CPU 1 /* Direct CPU exception */
23: #define M68000_EXC_SRC_AUTOVEC 2 /* Auto-vector exception (e.g. VBL) */
24: #define M68000_EXC_SRC_INT_MFP 3 /* MFP interrupt exception */
25: #define M68000_EXC_SRC_INT_DSP 4 /* DSP interrupt exception */
26:
27:
28: /* Special flags */
29: #define SPCFLAG_DEBUGGER 1
30: #define SPCFLAG_STOP 2
31: #define SPCFLAG_BUSERROR 4
32: #define SPCFLAG_INT 8
33: #define SPCFLAG_BRK 0x10
34: #define SPCFLAG_EXTRA_CYCLES 0x20
35: #define SPCFLAG_TRACE 0x40
36: #define SPCFLAG_DOTRACE 0x80
37: #define SPCFLAG_DOINT 0x100
38: #define SPCFLAG_MFP 0x200
39: #define SPCFLAG_EXEC 0x400
40: #define SPCFLAG_MODE_CHANGE 0x800
41:
42:
43: #ifndef SET_CFLG
44:
45: #define SET_CFLG(x) (CFLG() = (x))
46: #define SET_NFLG(x) (NFLG() = (x))
47: #define SET_VFLG(x) (VFLG() = (x))
48: #define SET_ZFLG(x) (ZFLG() = (x))
49: #define SET_XFLG(x) (XFLG() = (x))
50:
51: #define GET_CFLG() CFLG()
52: #define GET_NFLG() NFLG()
53: #define GET_VFLG() VFLG()
54: #define GET_ZFLG() ZFLG()
55: #define GET_XFLG() XFLG()
56:
57: #define CLEAR_CZNV() do { \
58: SET_CFLG (0); \
59: SET_ZFLG (0); \
60: SET_NFLG (0); \
61: SET_VFLG (0); \
62: } while (0)
63:
64: #define COPY_CARRY() (SET_XFLG (GET_CFLG ()))
65: #endif
66:
67: extern const int areg_byteinc[];
68: extern const int imm8_table[];
69:
70: extern int movem_index1[256];
71: extern int movem_index2[256];
72: extern int movem_next[256];
73:
74: #ifdef FPUEMU
75: extern int fpp_movem_index1[256];
76: extern int fpp_movem_index2[256];
77: extern int fpp_movem_next[256];
78: #endif
79:
80: extern int OpcodeFamily;
81:
82: typedef unsigned long REGPARAM3 cpuop_func (uae_u32) REGPARAM;
83: typedef void REGPARAM3 cpuop_func_ce (uae_u32) REGPARAM;
84:
85: struct cputbl {
86: cpuop_func *handler;
87: uae_u16 opcode;
88: };
89:
90: #ifdef JIT
91: typedef unsigned long REGPARAM3 compop_func (uae_u32) REGPARAM;
92:
93: struct comptbl {
94: compop_func *handler;
95: uae_u32 opcode;
96: int specific;
97: };
98: #endif
99:
100: extern unsigned long REGPARAM3 op_illg (uae_u32) REGPARAM;
101:
102: typedef uae_u8 flagtype;
103:
104: #ifdef FPUEMU
105: /* You can set this to long double to be more accurate. However, the
106: resulting alignment issues will cost a lot of performance in some
107: apps */
108: #define USE_LONG_DOUBLE 0
109:
110: #if USE_LONG_DOUBLE
111: typedef long double fptype;
112: #define LDPTR tbyte ptr
113: #else
114: typedef double fptype;
115: #define LDPTR qword ptr
116: #endif
117: #endif
118:
119: #define CPU_PIPELINE_MAX 2
120: #define CPU000_MEM_CYCLE 4
121: #define CPU000_CLOCK_MULT 2
122: #define CPU020_MEM_CYCLE 3
123: #define CPU020_CLOCK_MULT 4
124:
125: #define CACHELINES020 64
126: struct cache020
127: {
128: uae_u32 data;
129: uae_u32 tag;
130: bool valid;
131: };
132:
133: #define CACHELINES030 16
134: struct cache030
135: {
136: uae_u32 data[4];
137: bool valid[4];
138: uae_u32 tag;
139: };
140:
141: #define CACHESETS040 64
142: #define CACHELINES040 4
143: struct cache040
144: {
145: uae_u32 data[CACHELINES040][4];
146: bool valid[CACHELINES040];
147: uae_u32 tag[CACHELINES040];
148: };
149:
150:
151: struct regstruct
152: {
153: uae_u32 regs[16];
154:
155: uae_u32 pc;
156: uae_u8 *pc_p;
157: uae_u8 *pc_oldp;
158:
159: uae_u16 irc, ir;
160: uae_u32 spcflags;
161:
162: uaecptr usp, isp, msp;
163: uae_u16 sr;
164: flagtype t1;
165: flagtype t0;
166: flagtype s;
167: flagtype m;
168: flagtype x;
169: flagtype stopped;
170: int intmask;
171: int ipl, ipl_pin;
172:
173: uae_u32 vbr, sfc, dfc;
174:
175: #ifdef FPUEMU
176: fptype fp[8];
177: fptype fp_result;
178:
179: uae_u32 fpcr, fpsr, fpiar;
180: uae_u32 fpsr_highbyte;
181: #endif
182: #ifndef CPUEMU_68000_ONLY
183: uae_u32 cacr, caar;
184: uae_u32 itt0, itt1, dtt0, dtt1;
185: uae_u32 tcr, mmusr, urp, srp, buscr;
186: uae_u32 mmu_fslw, mmu_fault_addr;
187: uae_u16 mmu_ssw;
188: uae_u32 wb3_data;
189: uae_u16 wb3_status;
190: int mmu_enabled;
191: int mmu_pagesize_8k;
192: uae_u32 fault_pc;
193: #endif
194:
195: uae_u32 pcr;
196: uae_u32 address_space_mask;
197:
198: uae_u8 panic;
199: uae_u32 panic_pc, panic_addr;
200:
201: uae_u32 prefetch020data[CPU_PIPELINE_MAX];
202: uae_u32 prefetch020addr[CPU_PIPELINE_MAX];
203: int ce020memcycles;
204: };
205:
206: extern struct regstruct regs;
207:
208: STATIC_INLINE uae_u32 munge24 (uae_u32 x)
209: {
210: return x & regs.address_space_mask;
211: }
212:
213: extern int mmu_enabled, mmu_triggered;
214: extern int cpu_cycles;
215: extern int cpucycleunit;
216: STATIC_INLINE void set_special (uae_u32 x)
217: {
218: regs.spcflags |= x;
219: cycles_do_special ();
220: }
221:
222: STATIC_INLINE void unset_special (uae_u32 x)
223: {
224: regs.spcflags &= ~x;
225: }
226:
227: #define m68k_dreg(r,num) ((r).regs[(num)])
228: #define m68k_areg(r,num) (((r).regs + 8)[(num)])
229:
230: STATIC_INLINE void m68k_setpc (uaecptr newpc)
231: {
232: regs.pc_p = regs.pc_oldp = get_real_address (newpc);
233: regs.fault_pc = regs.pc = newpc;
234: }
235:
236: STATIC_INLINE uaecptr m68k_getpc (void)
237: {
238: return (uaecptr)(regs.pc + ((uae_u8*)regs.pc_p - (uae_u8*)regs.pc_oldp));
239: }
240: #define M68K_GETPC m68k_getpc()
241:
242: STATIC_INLINE uaecptr m68k_getpc_p (uae_u8 *p)
243: {
244: return (uaecptr)(regs.pc + ((uae_u8*)p - (uae_u8*)regs.pc_oldp));
245: }
246:
247: STATIC_INLINE void fill_prefetch_0 (void)
248: {
249: }
250:
251: #define fill_prefetch_2 fill_prefetch_0
252:
253: STATIC_INLINE void m68k_incpc (int o)
254: {
255: regs.pc_p += o;
256: }
257:
258: STATIC_INLINE void m68k_setpc_mmu (uaecptr newpc)
259: {
260: regs.fault_pc = regs.pc = newpc;
261: regs.pc_p = regs.pc_oldp = 0;
262: }
263: STATIC_INLINE void m68k_setpci (uaecptr newpc)
264: {
265: regs.fault_pc = regs.pc = newpc;
266: }
267: STATIC_INLINE uaecptr m68k_getpci (void)
268: {
269: return regs.pc;
270: }
271: STATIC_INLINE void m68k_incpci (int o)
272: {
273: regs.pc += o;
274: }
275:
276: STATIC_INLINE void m68k_do_rts (void)
277: {
278: uae_u32 newpc = get_long (m68k_areg (regs, 7));
279: m68k_setpc (newpc);
280: m68k_areg (regs, 7) += 4;
281: }
282: STATIC_INLINE void m68k_do_rtsi (void)
283: {
284: m68k_setpci (get_long (m68k_areg (regs, 7)));
285: m68k_areg (regs, 7) += 4;
286: }
287:
288: STATIC_INLINE void m68k_do_bsr (uaecptr oldpc, uae_s32 offset)
289: {
290: m68k_areg (regs, 7) -= 4;
291: put_long (m68k_areg (regs, 7), oldpc);
292: m68k_incpc (offset);
293: }
294: STATIC_INLINE void m68k_do_bsri (uaecptr oldpc, uae_s32 offset)
295: {
296: m68k_areg (regs, 7) -= 4;
297: put_long (m68k_areg (regs, 7), oldpc);
298: m68k_incpci (offset);
299: }
300:
301: STATIC_INLINE uae_u32 get_ibyte (int o)
302: {
303: return do_get_mem_byte((uae_u8 *)((regs).pc_p + (o) + 1));
304: }
305: STATIC_INLINE uae_u32 get_iword (int o)
306: {
307: return do_get_mem_word((uae_u16 *)((regs).pc_p + (o)));
308: }
309: STATIC_INLINE uae_u32 get_ilong (int o)
310: {
311: return do_get_mem_long((uae_u32 *)((regs).pc_p + (o)));
312: }
313:
314: #define get_iwordi(o) get_wordi(o)
315: #define get_ilongi(o) get_longi(o)
316:
317: /* These are only used by the 68020/68881 code, and therefore don't
318: * need to handle prefetch. */
319: STATIC_INLINE uae_u32 next_ibyte (void)
320: {
321: uae_u32 r = get_ibyte (0);
322: m68k_incpc (2);
323: return r;
324: }
325: STATIC_INLINE uae_u32 next_iword (void)
326: {
327: uae_u32 r = get_iword (0);
328: m68k_incpc (2);
329: return r;
330: }
331: STATIC_INLINE uae_u32 next_iwordi (void)
332: {
333: uae_u32 r = get_iwordi (m68k_getpci ());
334: m68k_incpc (2);
335: return r;
336: }
337: STATIC_INLINE uae_u32 next_ilong (void)
338: {
339: uae_u32 r = get_ilong (0);
340: m68k_incpc (4);
341: return r;
342: }
343: STATIC_INLINE uae_u32 next_ilongi (void)
344: {
345: uae_u32 r = get_ilongi (m68k_getpci ());
346: m68k_incpc (4);
347: return r;
348: }
349:
350: extern uae_u32 (*x_get_byte)(uaecptr addr);
351: extern uae_u32 (*x_get_word)(uaecptr addr);
352: extern uae_u32 (*x_get_long)(uaecptr addr);
353: extern void (*x_put_byte)(uaecptr addr, uae_u32 v);
354: extern void (*x_put_word)(uaecptr addr, uae_u32 v);
355: extern void (*x_put_long)(uaecptr addr, uae_u32 v);
356: extern uae_u32 (*x_next_iword)(void);
357: extern uae_u32 (*x_next_ilong)(void);
358:
359: extern uae_u32 REGPARAM3 x_get_disp_ea_020 (uae_u32 base, uae_u32 dp) REGPARAM;
360: extern uae_u32 REGPARAM3 x_get_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width) REGPARAM;
361: extern void REGPARAM3 x_put_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width) REGPARAM;
362:
363: extern void m68k_setstopped (void);
364: extern void m68k_resumestopped (void);
365:
366: extern uae_u32 REGPARAM3 get_disp_ea_020 (uae_u32 base, uae_u32 dp) REGPARAM;
367: extern uae_u32 REGPARAM3 get_disp_ea_000 (uae_u32 base, uae_u32 dp) REGPARAM;
368: extern uae_u32 REGPARAM3 get_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width) REGPARAM;
369: extern void REGPARAM3 put_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width) REGPARAM;
370:
371: extern void m68k_disasm_ea (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr);
372: extern void m68k_disasm (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt);
373: extern int get_cpu_model (void);
374:
375: extern void REGPARAM3 MakeSR (void) REGPARAM;
376: extern void REGPARAM3 MakeFromSR (void) REGPARAM;
377: extern void MakeSR (void);
378: extern void MakeFromSR (void);
379: extern void REGPARAM3 Exception (int, uaecptr, int) REGPARAM;
380: extern void NMI (void);
381: extern void NMI_delayed (void);
382: extern void prepare_interrupt (uae_u32);
383: extern void doint (void);
384: extern void dump_counts (void);
385: extern int m68k_move2c (int, uae_u32 *);
386: extern int m68k_movec2 (int, uae_u32 *);
387: extern void m68k_divl (uae_u32, uae_u32, uae_u16, uaecptr);
388: extern void m68k_mull (uae_u32, uae_u32, uae_u16);
389: extern void init_m68k (void);
390: extern void init_m68k_full (void);
391: extern void m68k_go (int);
392: extern void m68k_dumpstate (FILE *, uaecptr *);
393: extern void m68k_disasm (FILE *, uaecptr, uaecptr *, int);
394: extern void sm68k_disasm (TCHAR*, TCHAR*, uaecptr addr, uaecptr *nextpc);
395: extern void m68k_reset (int);
396: extern int getDivu68kCycles (uae_u32 dividend, uae_u16 divisor);
397: extern int getDivs68kCycles (uae_s32 dividend, uae_s16 divisor);
398: extern void m68k_do_rte (void);
399:
400: extern void mmu_op (uae_u32, uae_u32);
401: extern void mmu_op30 (uaecptr, uae_u32, uae_u16, uaecptr);
402:
403: extern void fpuop_arithmetic(uae_u32, uae_u16);
404: extern void fpuop_dbcc(uae_u32, uae_u16);
405: extern void fpuop_scc(uae_u32, uae_u16);
406: extern void fpuop_trapcc(uae_u32, uaecptr, uae_u16);
407: extern void fpuop_bcc(uae_u32, uaecptr, uae_u32);
408: extern void fpuop_save(uae_u32);
409: extern void fpuop_restore(uae_u32);
410: extern uae_u32 fpp_get_fpsr (void);
411: extern void fpu_reset (void);
412: extern void fpux_save (int*);
413: extern void fpux_restore (int*);
414:
415: extern void exception3 (uae_u32 opcode, uaecptr addr, uaecptr fault);
416: extern void exception3i (uae_u32 opcode, uaecptr addr, uaecptr fault);
417: extern void exception2 (uaecptr addr, uaecptr fault);
418: extern void cpureset (void);
419:
420: extern void fill_prefetch_slow (void);
421:
422: #define CPU_OP_NAME(a) op ## a
423:
424: /* 68060 */
425: extern const struct cputbl op_smalltbl_0_ff[];
426: extern const struct cputbl op_smalltbl_20_ff[]; // CE
427: /* 68040 */
428: extern const struct cputbl op_smalltbl_1_ff[];
429: extern const struct cputbl op_smalltbl_21_ff[]; // CE
430: extern const struct cputbl op_smalltbl_31_ff[]; // MMU
431: /* 68030 */
432: extern const struct cputbl op_smalltbl_2_ff[];
433: extern const struct cputbl op_smalltbl_22_ff[]; // CE
434: /* 68020 */
435: extern const struct cputbl op_smalltbl_3_ff[];
436: extern const struct cputbl op_smalltbl_23_ff[]; // CE
437: /* 68010 */
438: extern const struct cputbl op_smalltbl_4_ff[];
439: /* 68000 */
440: extern const struct cputbl op_smalltbl_5_ff[];
441: /* 68000 slow but compatible. */
442: extern const struct cputbl op_smalltbl_11_ff[];
443: /* 68000 slow but compatible and cycle-exact. */
444: extern const struct cputbl op_smalltbl_12_ff[];
445:
446: extern cpuop_func *cpufunctbl[65536] ASM_SYM_FOR_FUNC ("cpufunctbl");
447:
448: /* Added for hatari_glue.c */
449: extern void build_cpufunctbl(void);
450:
451: #ifdef JIT
452: extern void flush_icache (uaecptr, int);
453: extern void compemu_reset (void);
454: extern bool check_prefs_changed_comp (void);
455: #else
456: #define flush_icache(uaecptr, int) do {} while (0)
457: #endif
458: extern void flush_dcache (uaecptr, int);
459: extern void flush_mmu (uaecptr, int);
460:
461: extern int movec_illg (int regno);
462: extern uae_u32 val_move2c (int regno);
463: extern void val_move2c2 (int regno, uae_u32 val);
464: struct cpum2c {
465: int regno;
466: const TCHAR *regname;
467: };
468: extern struct cpum2c m2cregs[];
469:
470: /* Family of the latest instruction executed (to check for pairing) */
471: extern int OpcodeFamily; /* see instrmnem in readcpu.h */
472:
473: /* How many cycles to add to the current instruction in case a "misaligned" bus acces is made */
474: /* (used when addressing mode is d8(an,ix)) */
475: extern int BusCyclePenalty;
476:
477: STATIC_INLINE uae_u32 get_iword_prefetch (uae_s32 o)
478: {
479: /* Laurent : let's see this later
480: uae_u32 currpc = m68k_getpc ();
481: uae_u32 addr = currpc + o;
482: uae_u32 offs = addr - prefetch_pc;
483: uae_u32 v;
484: if (offs > 3) {
485: refill_prefetch (currpc, o);
486: offs = addr - prefetch_pc;
487: }
488: v = do_get_mem_word (((uae_u8 *)&prefetch) + offs);
489: if (offs >= 2)
490: refill_prefetch (currpc, 2);
491: */
492: /* printf ("get_iword PC %lx ADDR %lx OFFS %lx V %lx\n", currpc, addr, offs, v); */
493: //return v;
494: return 0;
495: }
496:
497: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.