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