1 /* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */
2
3 #define IN_REG68K_C
4
5 #include "generator.h"
6 #include "registers.h"
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11
12 // not recommended for wxWidgets linkage
13 #ifdef USE_SETJMP
14 #include <setjmp.h>
15 #endif
16
17 #include "reg68k.h"
18 #include "cpu68k.h"
19 #include "ui.h"
20 #include "vars.h"
21
22 // __CYGWIN__ wrapper added by Ray Arachelian for LisaEm to prevent crashes in reg68k_ext exec
23 #ifdef __CYGWIN__
24 uint32 reg68k_pc;
25 uint32 *reg68k_regs;
26 t_sr reg68k_sr;
27 #else
28 #if (!(defined(PROCESSOR_ARM) || defined(PROCESSOR_SPARC) || defined(PROCESSOR_INTEL) ))
29 uint32 reg68k_pc;
30 uint32 *reg68k_regs;
31 t_sr reg68k_sr;
32 #endif
33 #endif
34
35 #define LISA_REBOOTED(x) { ALERT_LOG(0,"rebooting? reg68k_pc:%08x,pc24:%08x %16llx",reg68k_pc,pc24,cpu68k_clocks); return x;}
36 #define LISA_POWEREDOFF(x) { save_pram(); profile_unmount(); lisa_powered_off(); return x;}
37
38
39 static int dbx=0;
40
41
42 static int insetjmpland=0;
43
44
45 static uint32 last_cpu68k_clocks=0;
46
47 static uint32 last_bus_error_pc=0;
48
49 static int nmi_error_trap=0;
50 static uint32 last_nmi_error_pc=0;
51
52 static uint32 nmi_pc=0, nmi_addr_err=0, nmi_clk=0, nmi_stop=0;
53
54
55 uint16 InstructionRegister;
56 uint8 CPU_function_code; // cpu function code state output bits (FC2/Fc1/FC0). // fc2= supervisor mode, fc1/0=program/data access
57 //
58 // should set to CPU_function_code=(reg68k_sr.sr_struct.s<<2) | 1; for normal access
59 // CPU_function_code=(reg68k_sr.sr_struct.s<<2) | 2; for execution/program access.
60 //
61
62 #define SET_CPU_FNC_DATA() {CPU_function_code=(reg68k_sr.sr_struct.s? 4:0) | 1;}
63 #define SET_CPU_FNC_CODE() {CPU_function_code=(reg68k_sr.sr_struct.s? 4:0) | 2;}
64
65
66 uint8 CPU_READ_MODE; // 1=read, 0=write (for addr/bus error exceptions)
67
68 uint32 pc24=0, lastpc24=0, page;
69 static int loopy_vector=0; // prevent fetch from calling this again.
70
71
72
73
74 /*** forward references ***/
75 #ifdef DEBUG
76 void dumpmmu(uint8 c, FILE *out);
77 void validate_mmu_segments(char *from);
78 void printregs(FILE *buglog,char *tag);
79 void extprintregs(FILE *buglog,char *tag);
80
81 #endif
82
83 extern char *slrname(uint16 slr); // from memory.c
84
85 // Make sure that the bitfield unions work correctly - if they're in the wrong order, they won't. This double checks
86 // that ./configure got the right order.
87 //
88
89
reg68k_sanity_check_bitorder(void)90 void reg68k_sanity_check_bitorder(void)
91 {
92 int bad=0; uint16 x;
93 int64 i64;
94 int32 i32;
95 union
96 {
97 uint32 l;
98 uint8 c[4];
99 } e;
100
101
102 union {
103 struct {
104 uint8 h:4;
105 uint8 i0:1;
106 uint8 i1:1;
107 uint8 i2:1;
108 uint8 i3:1;
109 } hi;
110 uint8 i;
111 }bf;
112
113 x=reg68k_sr.sr_int;
114
115 reg68k_sr.sr_int=0x2700;
116 #define IMSK (reg68k_sr.sr_struct.i0 | (reg68k_sr.sr_struct.i1<<1) | (reg68k_sr.sr_struct.i2<<2) )
117
118 if (sizeof(reg68k_sr)!=2) {bad=1;
119 DEBUG_LOG(0,"expected reg68k_sr to be two bytes! it is %d instead!",sizeof(reg68k_sr));
120 messagebox("Sanity Check Failed! reg68k_sr is not 2 bytes!", "Compilation Failure!");
121 }
122
123 if (sizeof(uint8) !=1 ) {bad=1; DEBUG_LOG(0,"Size of uint8 is not 1"); messagebox("Sanity check failed sizeof(uint8)!=1","Sanity check failed");}
124 if (sizeof(uint16) !=2 ) {bad=1; DEBUG_LOG(0,"Size of uint16 is not 2"); messagebox("Sanity check failed sizeof(uint16)!=2","Sanity check failed");}
125 if (sizeof(uint32) !=4 ) {bad=1; DEBUG_LOG(0,"Size of uint32 is not 4"); messagebox("Sanity check failed sizeof(uint32)!=4","Sanity check failed");}
126 #ifdef uint64
127 if (sizeof(uint64) !=8 ) {bad=1; DEBUG_LOG(0,"Size of uint64 is not 8"); messagebox("Sanity check failed sizeof(uint64)!=8","Sanity check failed");}
128 #endif
129
130 if (sizeof(int8) !=1 ) {bad=1; DEBUG_LOG(0,"Size of int8 is not 1"); messagebox("Sanity check failed sizeof(int8)!=1","Sanity check failed");}
131 if (sizeof(int16) !=2 ) {bad=1; DEBUG_LOG(0,"Size of int16 is not 2"); messagebox("Sanity check failed sizeof(int16)!=2","Sanity check failed");}
132 if (sizeof(int32) !=4 ) {bad=1; DEBUG_LOG(0,"Size of int32 is not 4"); messagebox("Sanity check failed sizeof(int32)!=4","Sanity check failed");}
133 #ifdef int64
134 if (sizeof(int64) !=8 ) {bad=1; DEBUG_LOG(0,"Size of int64 is not 8"); messagebox("Sanity check failed sizeof(int64)!=8","Sanity check failed");}
135 #endif
136
137 e.l=0xdeadbeef;
138 #ifdef WORDS_BIGENDIAN
139 if (e.c[0]!=0xde && e.c[1]!=0xad && e.c[2]!=0xbe && e.c[3]!=0xef )
140 {bad=1; DEBUG_LOG(0,"Endian Mismatch - BIGENDIAN defined, but fails test"); messagebox("Sanity check failed: BIGENDIAN defined, but fails test","Sanity check failed");}
141 #else
142 if (e.c[0]!=0xef && e.c[1]!=0xbe && e.c[2]!=0xad && e.c[3]!=0xde )
143 {bad=1; DEBUG_LOG(0,"Endian Mismatch - LITTLE ENDIAN defined, but fails test"); messagebox("Sanity check failed: LITTLE ENDIAN defined, but fails test","Sanity check failed");}
144
145 #endif
146
147 i64=-1;
148 i32=-1;
149
150 i64=(i64>>1);
151 i32=(i32>>1);
152
153 if (i64!=-1) {bad=1; DEBUG_LOG(0,"64 bit signed right shift of -1 !=-1"); messagebox("Sanity check failed: 64 bit signed right shift of -1 !=-1","Sanity check failed");}
154 if (i32!=-1) {bad=1; DEBUG_LOG(0,"32 bit signed right shift of -1 !=-1"); messagebox("Sanity check failed: 32 bit signed right shift of -1 !=-1","Sanity check failed");}
155
156 bf.i=0xf3;
157
158 if (sizeof(bf)!=1) {bad=1; DEBUG_LOG(0,"sizeof(uint8) bitfield!=1!"); messagebox("Sanity check failed: sizeof(uint8) bitfield!=1!","Sanity Check Failure!");}
159
160 #ifdef BYTES_HIGHFIRST
161 // bf.i=f3 bf.hi.h=f bf.hi.i0,1,2,3=0 0 1 1
162 if (bf.hi.h !=15) {bad=1; DEBUG_LOG(0,"bitfield/BYTES_HIGHFIRST hi.h!=f"); messagebox("Sanity check failed: bitfield/BYTES_HIGHFIRST hi.h!=f ","Sanity Check Failure");}
163 if (bf.hi.i0 !=0 ) {bad=1; DEBUG_LOG(0,"bitfield/BYTES_HIGHFIRST hi.i0!=0"); messagebox("Sanity check failed: bitfield/BYTES_HIGHFIRST hi.i0!=0","Sanity Check Failure");}
164 if (bf.hi.i1 !=0 ) {bad=1; DEBUG_LOG(0,"bitfield/BYTES_HIGHFIRST hi.i1!=0"); messagebox("Sanity check failed: bitfield/BYTES_HIGHFIRST hi.i1!=0","Sanity Check Failure");}
165 if (bf.hi.i2 !=1 ) {bad=1; DEBUG_LOG(0,"bitfield/BYTES_HIGHFIRST hi.i2!=1"); messagebox("Sanity check failed: bitfield/BYTES_HIGHFIRST hi.i2!=1","Sanity Check Failure");}
166 if (bf.hi.i3 !=1 ) {bad=1; DEBUG_LOG(0,"bitfield/BYTES_HIGHFIRST hi.i3!=1"); messagebox("Sanity check failed: bitfield/BYTES_HIGHFIRST hi.i3!=1","Sanity Check Failure");}
167
168
169 #else
170 // bf.i=f3 bf.hi.h=3 bf.hi.i0,1,2,3=1 1 1 1
171 if (bf.hi.h !=3 ) {bad=1; DEBUG_LOG(0,"bitfield/!BYTES_HIGHFIRST hi.h!=3"); messagebox("Sanity check failed: bitfield/!BYTES_HIGHFIRST hi.h!=3","Sanity Check Failure");}
172 if (bf.hi.i0 !=1 ) {bad=1; DEBUG_LOG(0,"bitfield/!BYTES_HIGHFIRST hi.i0!=1"); messagebox("Sanity check failed: bitfield/!BYTES_HIGHFIRST hi.i0!=1","Sanity Check Failure");}
173 if (bf.hi.i1 !=1 ) {bad=1; DEBUG_LOG(0,"bitfield/!BYTES_HIGHFIRST hi.i1!=1"); messagebox("Sanity check failed: bitfield/!BYTES_HIGHFIRST hi.i1!=1","Sanity Check Failure");}
174 if (bf.hi.i2 !=1 ) {bad=1; DEBUG_LOG(0,"bitfield/!BYTES_HIGHFIRST hi.i2!=1"); messagebox("Sanity check failed: bitfield/!BYTES_HIGHFIRST hi.i2!=1","Sanity Check Failure");}
175 if (bf.hi.i3 !=1 ) {bad=1; DEBUG_LOG(0,"bitfield/!BYTES_HIGHFIRST hi.i3!=1"); messagebox("Sanity check failed: bitfield/!BYTES_HIGHFIRST hi.i3!=1","Sanity Check Failure");}
176 #endif
177
178
179 reg68k_sr.sr_int=0x2700; if (IMSK!=7) {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expect 7 got %d %c%c%c%c%c%c%c imsk:%d ",IMSK,(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'), (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}
180 reg68k_sr.sr_int=0x2600; if (IMSK!=6) {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expect 6 got %d %c%c%c%c%c%c%c imsk:%d ",IMSK,(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'), (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}
181 reg68k_sr.sr_int=0x2500; if (IMSK!=5) {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expect 5 got %d %c%c%c%c%c%c%c imsk:%d ",IMSK,(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'), (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}
182 reg68k_sr.sr_int=0x2400; if (IMSK!=4) {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expect 4 got %d %c%c%c%c%c%c%c imsk:%d ",IMSK,(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'), (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}
183 reg68k_sr.sr_int=0x2300; if (IMSK!=3) {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expect 3 got %d %c%c%c%c%c%c%c imsk:%d ",IMSK,(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'), (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}
184 reg68k_sr.sr_int=0x2200; if (IMSK!=2) {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expect 2 got %d %c%c%c%c%c%c%c imsk:%d ",IMSK,(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'), (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}
185 reg68k_sr.sr_int=0x2100; if (IMSK!=1) {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expect 1 got %d %c%c%c%c%c%c%c imsk:%d ",IMSK,(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'), (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}
186 reg68k_sr.sr_int=0x2000; if (IMSK!=0) {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expect 0 got %d %c%c%c%c%c%c%c imsk:%d ",IMSK,(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'), (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}
187
188 reg68k_sr.sr_int=0x2000; if (!reg68k_sr.sr_struct.s) {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expected Supervisor Bit on %c%c%c%c%c%c%c imsk:%d ",(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'), (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}
189 reg68k_sr.sr_int=0x0000; if ( reg68k_sr.sr_struct.s) {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expected Supervisor Bit off %c%c%c%c%c%c%c imsk:%d ",(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'), (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}
190 reg68k_sr.sr_int=0x2700; if (!reg68k_sr.sr_struct.s) {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expected Supervisor Bit on %c%c%c%c%c%c%c imsk:%d ",(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'), (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}
191 reg68k_sr.sr_int=0x0700; if ( reg68k_sr.sr_struct.s) {DEBUG_LOG(0,"BIT ORDER IS WRONG! Expected Supervisor Bit off %c%c%c%c%c%c%c imsk:%d ",(reg68k_sr.sr_struct.t ? 't':'.'),(reg68k_sr.sr_struct.s ? 'S':'.'),(reg68k_sr.sr_struct.z ? 'z':'.'),(reg68k_sr.sr_struct.x ? 'x':'.'),(reg68k_sr.sr_struct.n ? 'n':'.'),(reg68k_sr.sr_struct.v ? 'v':'.'), (reg68k_sr.sr_struct.c ? 'c':'.'),((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 ))); bad=1;}
192
193 reg68k_sr.sr_int=x;
194
195
196 if (bad) {
197 EXIT(1938,0,"Sanity Check Failed! reg68k_sr int does not match bitfields!", "Compilation Failure!");
198 }
199 }
200
201
niceascii(char c)202 char niceascii(char c)
203 { c &=127;
204 if (c<31) c|=32;
205 if (c==127) c='.';
206 return c;
207 }
208
209
210 void lisa_addrerror(uint32 addr);
211
212 char *getvector(int v);
213 static int atexitset=0;
214
215 // MMU Test Patterns. 1 assumes X flag is preset before. 2 assumes X=0
216 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
217 uint16 mmupattern1[17]={0xa55a,0x4ab5,0x956b,0x2ad6,0x55ad,0xab5a,0x56b4,0xad69,0x5ad2,0xb5a5,0x6b4a,0xd695,0xad2a,0x5a55,0xb4ab,0x6956,0xd2ad};
218 uint16 mmupattern2[17]={0xa55a,0x4ab4,0x9569,0x2ad2,0x55a5,0xab4a,0x5694,0xad29,0x5a52,0xb4a5,0x694a,0xd295,0xa52a,0x4a55,0x94ab,0x2956,0x52ad};
219
220 static uint8 pending_vector_bitmap=0;
221
222 #ifdef DEBUG
223 extern void append_floppy_log(char *s);
224 #endif
225
226 // only two are available: empty or dual parallel
get_nmi_pending_irq(void)227 int get_nmi_pending_irq(void) {return 0;}
228
get_exs2_pending_irq_empty(void)229 int get_exs2_pending_irq_empty(void) {return 0;}
get_exs1_pending_irq_empty(void)230 int get_exs1_pending_irq_empty(void) {return 0;}
get_exs0_pending_irq_empty(void)231 int get_exs0_pending_irq_empty(void) {return 0;}
232
233
get_exs0_pending_irq_2xpar(void)234 int get_exs0_pending_irq_2xpar(void) { return (via[3].via[IFR]&via[3].via[IER])||((via[4].via[IFR]&via[4].via[IER]));}
get_exs1_pending_irq_2xpar(void)235 int get_exs1_pending_irq_2xpar(void) { return (via[5].via[IFR]&via[5].via[IER])||((via[6].via[IFR]&via[6].via[IER]));}
get_exs2_pending_irq_2xpar(void)236 int get_exs2_pending_irq_2xpar(void) { return (via[7].via[IFR]&via[7].via[IER])||((via[8].via[IFR]&via[8].via[IER]));}
237
238
239
240 // These is here in this file because they are shared IRQs, it belongs more in the via6522.c file but there is a
241 // videoirq and floppy component too, so it should be in a shared place. Might as well be static inline for speed.
242
get_irq1_pending_irq(void)243 int get_irq1_pending_irq(void )
244 {
245 // this is just a fixup for the COPS VIA, doesn't affect the rest of this.
246 if (via[1].via[IER] & via[1].via[IFR] & 0x7f) via[1].via[IFR] |=0x80; else via[1].via[IFR] &=0x7f;
247
248 // IRQ1 is the only shared IRQ - Vertical Retrace, Floppy FDIR, and VIA2 (Parallel Port) all use it.
249 // fix via IFR bit 0x80's so bit 7 is properly reflecting enabled IRQ's. Correct these bits before checking.
250 if (via[2].via[IER] & via[2].via[IFR] & 0x7f) via[2].via[IFR] |=0x80; else via[2].via[IFR] &=0x7f;
251
252 DEBUG_LOG(0,"IRQ1: vertical:%d fdir:%d VIA2-IFR bits:%s%s%s%s%s%s%s%s returning:%d",
253 (verticallatch && (videoirq & 1)), floppy_FDIR ,
254 (via[2].via[IFR] & VIA_IRQ_BIT_CA2 ? "0:CA2 ": " " ),
255 (via[2].via[IFR] & VIA_IRQ_BIT_CA1 ? "1:CA1 ": " " ),
256 (via[2].via[IFR] & VIA_IRQ_BIT_SR ? "2:SR ": " " ),
257 (via[2].via[IFR] & VIA_IRQ_BIT_CB2 ? "3:CB2 ": " " ),
258 (via[2].via[IFR] & VIA_IRQ_BIT_CB1 ? "4:CB1 ": " " ),
259 (via[2].via[IFR] & VIA_IRQ_BIT_T2 ? "5:T2 ": " " ),
260 (via[2].via[IFR] & VIA_IRQ_BIT_T1 ? "6:T1 ": " " ),
261 (via[2].via[IFR] & VIA_IRQ_BIT_SET_CLR_ANY ? "7:ANY ": "None"),
262
263 ((verticallatch && (videoirq & 1)) || floppy_FDIR || (via[2].via[IFR] & 0x80)));
264
265
266
267 return ((verticallatch && (videoirq & 1)) || floppy_FDIR || (via[2].via[IFR] & 0x80)); //was vertical, not verticallatch
268 }
269
270
271 #ifdef PARANOID
272 #define HIGHEST(x) (highest=((x)>highest ? (x):highest))
273 #else
274 #define HIGHEST(x) (highest=(x))
275 #endif
276 // re/calculates the pending_vector_bitmap and returns the highest IRQ to be serviced.
277
278 // this is mirrored from cops.c
get_cops_pending_irq(void)279 static inline int get_cops_pending_irq(void )
280 {
281 // bit 7 of IFR indicates whether any VIA1 IRQ's have been fired, so check to see if any of them have, then set bit 7
282 if (via[1].via[IER] & via[1].via[IFR] & 0x7f)
283 {
284 via[1].via[IFR] |=0x80;
285 return 0x80;
286 }
287
288 via[1].via[IFR] &=0x7f;
289 return 0;
290 }
291
292
293
294
295
get_pending_vector(void)296 static inline uint8 get_pending_vector(void)
297 {
298 int highest=0;
299
300
301 //---- recalculated pending vector bitmap, and find the highest IRQ to be serviced ------------
302
303
304 #ifdef DEBUG
305 pending_vector_bitmap= // no such thing as IRQ0 on 68000
306 (get_irq1_pending_irq() ? BIT1:0) | // VTIR/FDIR/VIA2 IRQ1
307 (get_cops_pending_irq() ? BIT2:0) | // COPS/VIA1 IRQ2
308 (get_exs2_pending_irq() ? BIT3:0) | // Expansion slot 2 IRQ3
309 (get_exs1_pending_irq() ? BIT4:0) | // Expansion slot 1 IRQ4
310 (get_exs0_pending_irq() ? BIT5:0) | // Expansion slot 0 IRQ5
311 (get_scc_pending_irq() ? BIT6:0) | // SCC IRQ6
312 (get_nmi_pending_irq() ? BIT7:0) ; // NMI IRQ7
313
314 highest=highest_bit_num(pending_vector_bitmap);
315 if (highest==0xff) highest=0;
316
317 DEBUG_LOG(0,"IRQ1:: vertical retrace:%d floppy_FDIR:%d via2_IFR:%02x IRQ2:via1_IFR:%02x",
318 (vertical && (videoirq & 1)),
319 floppy_FDIR,
320 via[2].via[IFR],
321 via[1].via[IFR]);
322
323 if (highest==1 && floppy_FDIR && (!((regs.sr.sr_int>>8)&7))) append_floppy_log("get_pending_vector:Floppy FDIR IRQ1 is about to be taken if called\n");
324
325 DEBUG_LOG(0,"Next pending vector is:%d, map is:%s%s%s%s%s%s%s",highest,
326 ((pending_vector_bitmap & BIT1) ? "v1":"."),
327 ((pending_vector_bitmap & BIT2) ? "v2":"."),
328 ((pending_vector_bitmap & BIT3) ? "v3":"."),
329 ((pending_vector_bitmap & BIT4) ? "v4":"."),
330 ((pending_vector_bitmap & BIT5) ? "v5":"."),
331 ((pending_vector_bitmap & BIT6) ? "v6":"."),
332 ((pending_vector_bitmap & BIT7) ? "v7":".") );
333
334
335 #else
336
337 if (get_nmi_pending_irq() ) {highest=7;pending_vector_bitmap=BIT7;}
338 else if (get_scc_pending_irq() ) {highest=6;pending_vector_bitmap=BIT6;}
339 else if (get_exs0_pending_irq() ) {highest=5;pending_vector_bitmap=BIT5;}
340 else if (get_exs1_pending_irq() ) {highest=4;pending_vector_bitmap=BIT4;}
341 else if (get_exs2_pending_irq() ) {highest=3;pending_vector_bitmap=BIT3;}
342 else if (get_cops_pending_irq() ) {highest=2;pending_vector_bitmap=BIT2;}
343 else if (get_irq1_pending_irq() ) {highest=1;pending_vector_bitmap=BIT1;}
344
345 #endif
346
347
348
349 return highest;
350 }
351
352
353 #ifdef DEBUG
354 static char templine[1024];
355 #endif
356
357 #define IS_VECTOR_AVAILABLE_INT(avno) ( ((reg68k_sr.sr_int >> 8) & 7)<(avno) || (avno)==7)
358 #define IS_VECTOR_AVAILABLE_EXT(avno) ( ((regs.sr.sr_int >> 8) & 7)<(avno) || (avno)==7)
359
is_vector_available(int avno)360 int is_vector_available(int avno)
361 {
362 if (insetjmpland) return (IS_VECTOR_AVAILABLE_INT(avno));
363 return IS_VECTOR_AVAILABLE_EXT(avno);
364 }
365
366
367
368
fire_pending_external_autovector(void)369 static inline void fire_pending_external_autovector(void)
370 {
371 uint8 i=get_pending_vector();
372 DEBUG_LOG(0,"Firing pending IRQ:%d if it meets the mask",i);
373
374
375 if (IS_VECTOR_AVAILABLE_EXT(i))
376 {
377 #ifdef DEBUG
378 snprintf(templine,1024,"fire_pending_ext_av:Firing IRQ1 while floppy_FDIR is set. mask:%d",((regs.sr.sr_int>>8) & 7) );
379 if (i==1 && floppy_FDIR) append_floppy_log(templine);
380 #endif
381
382 reg68k_external_autovector(i);
383
384 }
385 }
386
fire_pending_internal_autovector(void)387 static inline void fire_pending_internal_autovector(void)
388 {
389 uint8 i=get_pending_vector();
390 DEBUG_LOG(0,"Firing pending IRQ:%d if it meets the mask",i);
391 if (IS_VECTOR_AVAILABLE_INT(i))
392 {
393 #ifdef DEBUG
394 snprintf(templine,1024,"fire_pending_int_av:Firing IRQ1 while floppy_FDIR is set. mask:%d",((reg68k_sr.sr_int>>8) & 7) );
395 if (i==1 && floppy_FDIR) append_floppy_log("fire_pending_int_av:Firing IRQ1 while floppy_FDIR is set");
396 #endif
397 reg68k_internal_autovector(i);
398 }
399 #ifdef DEBUG
400 else
401 {
402 DEBUG_LOG(0,"Could not fire IRQ:%d because it did not meet the mask.",i);
403 }
404 #endif
405
406 }
407
408 #ifdef DEBUG
409
410
check_mmu_pattern(uint32 x)411 void check_mmu_pattern(uint32 x)
412 {
413 int i,found=0;
414
415 for (i=0; i<17; i++)
416 {
417 if (x==mmupattern1[i])
418 {found=1; fprintf(buglog,"MMUPATTERN: %4x found at %2d in 1 con:%d @pc=%08x a0=%08x reg#:%d\n",mmupattern1[i],i,1+(segment1|segment2),pc24,reg68k_regs[8],reg68k_regs[8]>>17); break;}
419 if (x==mmupattern2[i]) {found=2; fprintf(buglog,"MMUPATTERN: %4x found at %2d in 2 con:%d @pc=%08x a0=%08x reg#:%d\n",mmupattern2[i],i,1+(segment1|segment2),pc24,reg68k_regs[8],reg68k_regs[8]>>17); break;}
420 }
421 if ( !found) fprintf(buglog,"MMUPATTERN: %4x not found con:%d @pc=%08x a0=%08x reg#:%d\n",x,1+(segment1|segment2),pc24,reg68k_regs[8],reg68k_regs[8]>>17);
422 }
423
dumpmmupage(uint8 c,uint8 i,FILE * out)424 void dumpmmupage(uint8 c, uint8 i, FILE *out)
425 {
426 char s[1024];
427
428 int16 pagestart, pageend;
429 lisa_mem_t rfn, wfn;
430 uint32 mymaxlisaram=maxlisaram;
431
432 if (maxlisaram==1024*1024) mymaxlisaram+=0x80000;
433
434 get_slr_page_range(c,i,&pagestart,&pageend,&rfn,&wfn);
435 fprintf(out,"mmu[%d][%d].slr:%04x in->(%08x-%08x) base:%08x->sor:%04x %s ch:%d pgrange:%d-%d arange: out-> %08x-%08x r/wfn:%d:%d\n",
436 c,i,
437 mmu_all[c][i].slr,
438 i<<17,
439 (i<<17) | 0x1FFFF,
440
441 mmu_all[c][i].sor<<9,mmu_all[c][i].sor,
442 printslr(s,1024,mmu_all[c][i].slr),
443 mmu_all[c][i].changed,pagestart,pageend,
444
445 ((((mmu_all[c][i].sor & 0xfff)+pagestart)<<9)),
446 (((((mmu_all[c][i].sor & 0xfff)+pageend)<<9)+511)),rfn,wfn );
447
448 if ((unsigned)(((mmu_all[c][i].sor & 0xfff)+pagestart)<<9)>mymaxlisaram)
449 {fprintf(out,"**** START RANGE OVER MAXLISARAM (%08x)!!!!!! chopped to 2mb it's:%08x, unchopped:%08x****\n\n",mymaxlisaram,
450 (((((mmu_all[c][i].sor & 0xfff)+pagestart)<<9)) & TWOMEGMLIM),
451 (((mmu_all[c][i].sor & 0xfff)+pagestart)<<9) );}
452
453 if ((unsigned)((((mmu_all[c][i].sor & 0xfff)+pageend)<<9)+511)>mymaxlisaram)
454 {fprintf(out,"**** END RANGE OVER MAXLISARAM (%08x)!!!!!! chopped to 2mb it's:%08x, unchopped:%08x****\n\n",mymaxlisaram,
455 (((((mmu_all[c][i].sor & 0xfff)+pageend)<<9)+511) & TWOMEGMLIM),
456 (((((mmu_all[c][i].sor & 0xfff)+pageend)<<9)+511)) );}
457
458
459 }
460
dumpmmu(uint8 c,FILE * out)461 void dumpmmu(uint8 c, FILE *out)
462 {
463 //char s[1024];
464 int i,f;
465
466 //int16 pagestart, pageend;
467 //lisa_mem_t rfn, wfn;
468
469 fprintf(out,"\nmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm dump_mmu mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm\n\n");
470
471 for (i=0; i<128; i++)
472 {
473 dumpmmupage(c,i,out);
474 // keep,might want to re-enable this later
475 /*
476 get_slr_page_range(c,i,&pagestart,&pageend,&rfn,&wfn);
477 fprintf(out,"mmu[%d][%d].slr:%04x in->(%08x-%08x) base:%08x->sor:%04x %s ch:%d pgrange:%d-%d arange: out-> %08x-%08x r/wfn:%d:%d\n",
478 c,i,
479 mmu_all[c][i].slr,
480 i<<17,
481 (i<<17) | 0x1FFFF,
482
483 mmu_all[c][i].sor<<9,mmu_all[c][i].sor,
484 printslr(s,1024,mmu_all[c][i].slr),
485 mmu_all[c][i].changed,pagestart,pageend,
486
487 ((((mmu_all[c][i].sor & 0xfff)+pagestart)<<9)),
488 (((((mmu_all[c][i].sor & 0xfff)+pageend)<<9)+511)),rfn,wfn );
489
490 // is this +i before + pagestart i.e i+pagestart) and i+pageend) needed/allowed here?
491 if ((unsigned)(((mmu_all[c][i].sor & 0xfff)+pagestart)<<9)>maxlisaram)
492 {fprintf(out,"**** START RANGE OVER MAXLISARAM (%08x)!!!!!! chopped to 2mb it's:%08x, unchopped:%08x****\n\n",maxlisaram,
493 (((((mmu_all[c][i].sor & 0xfff)+pagestart)<<9)) & TWOMEGMLIM),
494 (((mmu_all[c][i].sor & 0xfff)+pagestart)<<9) );}
495
496 if ((unsigned)((((mmu_all[c][i].sor & 0xfff)+pageend)<<9)+511)>maxlisaram)
497 {fprintf(out,"**** END RANGE OVER MAXLISARAM (%08x)!!!!!! chopped to 2mb it's:%08x, unchopped:%08x****\n\n",maxlisaram,
498 (((((mmu_all[c][i].sor & 0xfff)+pageend)<<9)+511) & TWOMEGMLIM),
499 (((((mmu_all[c][i].sor & 0xfff)+pageend)<<9)+511)) );}
500 */
501 }
502
503 fflush(out);
504 fprintf(out,"\n\n");
505 for ( i=0; i<32768; i++)
506 {
507 fprintf(out,"%08x-%08x mmu[%d] mmu_t[%d][%04x].addr=%08x rfn=%s wfn=%s ipct:%s out:%08x-%08x",
508 (i*512),(i*512)+511,(i*512)>>17,
509 c,i,
510 mmu_trans_all[c][i].address,
511 mspace(mmu_trans_all[c][i].readfn),
512 mspace(mmu_trans_all[c][i].writefn),
513 (mmu_trans_all[c][i].table ? "yes":"no"),
514 ((i*512)+mmu_trans_all[c][i].address),((i*512)+511+mmu_trans_all[c][i].address)
515 );
516
517 // 1000000000000000
518 // 5432109876543210
519 if (mmu_trans_all[c][i].readfn==sio_mmu)
520 {
521 f=rmmuslr2fn(mmu_all[c][i>>8].slr,i);
522 fprintf(out,"mmu_sio: (%d) %s",f,mspace(f));
523 }
524 fprintf(out,"\n");
525 }
526 fflush(out);
527 }
528
529
dumpallmmu(void)530 void dumpallmmu(void)
531 {
532 //long i;
533 FILE *out;
534 static char filename[128];
535 static int instance;
536
537 debug_log_enabled=1;
538 #ifdef DEBUG
539 debug_on("mmu-dump");
540 #endif
541
542 instance++;
543 snprintf(filename,128,"/log/lisaem-output-mmu-%08x-%d.txt",pc24,instance);
544 DEBUG_LOG(0,filename);
545 out=fopen(filename,"wt");
546
547 //fprintf(out,"SRC::init_7E70SLR is set to: r/w %04x/%04x\n",mmu_trans_all[0][0x7e70].readfn,mmu_trans_all[0][0x7e70].writefn);
548
549 //dump_scc();
550 #ifdef DEBUG
551 if (insetjmpland) printregs(out,"");
552 #endif
553 dumpmmu(0,out); dumpmmu(1,out); dumpmmu(2,out); dumpmmu(3,out); dumpmmu(4,out);
554
555 //if (insetjmpland) printregs(buglog,"");
556
557 fclose(out);
558 }
559
560
561 #endif
562
563
564
reg68k_external_step(void)565 unsigned int reg68k_external_step(void)
566 {
567 static t_ipc ipc;
568 static t_iib *piib;
569 static unsigned long clks;
570
571 /* !!! entering global register usage area !!! */
572 #ifdef USE_SETJMP
573 jmp_buf jb;
574
575
576 if (!setjmp(jb))
577 #endif
578 {
579 /* move PC and register block into global processor register variables */
580 reg68k_pc = regs.pc;
581 reg68k_regs = regs.regs;
582 reg68k_sr.sr_int = regs.sr.sr_int;
583
584 regs.pending = get_pending_vector();
585 if (regs.pending && ((reg68k_sr.sr_int >> 8) & 7) < regs.pending)
586 reg68k_internal_autovector(regs.pending);
587
588 if (!(piib = cpu68k_iibtable[fetchword(reg68k_pc)]))
589 DEBUG_LOG(1,"Invalid instruction @ %08X\n", reg68k_pc); // RA
590
591 #if DEBUG
592 if (!piib) DEBUG_LOG(0,"about to pass NULL IIB");
593 #endif
594
595 cpu68k_ipc(reg68k_pc, piib,&ipc);
596 if (!abort_opcode)
597 cpu68k_functable[fetchword(reg68k_pc) * 2 + 1] (&ipc);
598 /* restore global registers back to permanent storage */
599 regs.pc = reg68k_pc; regs.sr = reg68k_sr;
600 #ifdef USE_SETJMP
601 longjmp(jb, 1);
602 #endif
603 }
604 cpu68k_clocks += ipc.clks;
605 DEBUG_LOG(0,"cpu68k_clocks:%016llx this opcode:%d",cpu68k_clocks,ipc.clks);
606 return clks; /* number of clocks done */
607 }
608
getreg(uint8 regnum)609 uint32 getreg(uint8 regnum) //16=pc, 17=sp 0=7Dregs 8-15Aregs
610 {
611 if (!insetjmpland)
612 {
613 if (regnum==16) return regs.pc;
614 if (regnum==17) return regs.sp;
615 if (regnum<16 ) return regs.regs[regnum];
616
617 }
618
619 else {
620 if (regnum==16) return reg68k_pc;
621 if (regnum==17) return regs.sp;
622 if (regnum<16 ) return reg68k_regs[regnum];
623 }
624 return 0xdeadbeef;
625
626 }
627
628
629 #ifdef DEBUG
printregs(FILE * buglog,char * tag)630 void printregs(FILE *buglog,char *tag)
631 {
632
633
634 if (!debug_log_enabled) return;
635 if (!insetjmpland) {extprintregs(buglog,tag); return;}
636
637 fprintf(buglog,"%sD 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x 6:%08x 7:%08x %c%c%c%c%c%c%c imsk:%d pnd:%s%s%s%s%s%s%s (%d/%d/%s cx:%d)SRC:\n",tag,
638 reg68k_regs[0], reg68k_regs[1], reg68k_regs[2], reg68k_regs[3], reg68k_regs[4],
639 reg68k_regs[5], reg68k_regs[6], reg68k_regs[7],
640 (reg68k_sr.sr_struct.t ? 't':'.'),
641 (reg68k_sr.sr_struct.s ? 'S':'.'),
642 (reg68k_sr.sr_struct.z ? 'z':'.'),
643 (reg68k_sr.sr_struct.x ? 'x':'.'),
644 (reg68k_sr.sr_struct.n ? 'n':'.'),
645 (reg68k_sr.sr_struct.v ? 'v':'.'),
646 (reg68k_sr.sr_struct.c ? 'c':'.'),
647 ((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 )),
648
649 (pending_vector_bitmap & 1) ? "1":"",
650 (pending_vector_bitmap & 2) ? "2":"",
651 (pending_vector_bitmap & 4) ? "3":"",
652 (pending_vector_bitmap & 8) ? "4":"",
653 (pending_vector_bitmap & 16) ? "5":"",
654 (pending_vector_bitmap & 32) ? "6":"",
655 (pending_vector_bitmap & 64) ? "7":"",
656
657 segment1,segment2,start ? "START":"normal",context );
658
659 fprintf(buglog,"%sA 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x 6:%08x 7:%08x SP:%08x PC:%08x SRC:\n\n",tag,
660 reg68k_regs[8], reg68k_regs[9], reg68k_regs[10],reg68k_regs[11],reg68k_regs[12],
661 reg68k_regs[13],reg68k_regs[14],reg68k_regs[15],regs.sp,reg68k_pc);
662 fflush(buglog);
663 }
664
665 /*
666 reg68k_pc = regs.pc;
667 reg68k_regs = regs.regs;
668 reg68k_sr = regs.sr;
669 */
extprintregs(FILE * buglog,char * tag)670 void extprintregs(FILE *buglog,char *tag)
671 {
672
673
674 if (!debug_log_enabled) return;
675 if (insetjmpland) {printregs(buglog,tag); return;}
676
677
678 // the SRC: at the end is so I can grep the output and see both registers and source code. :)
679 fprintf(buglog,"%sD 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x 6:%08x 7:%08x %c%c%c%c%c%c%c irqmsk:%d %d/%d/%d context:%d SRC:\n",tag,
680 regs.regs[0], regs.regs[1], regs.regs[2], regs.regs[3], regs.regs[4],
681 regs.regs[5], regs.regs[6], regs.regs[7],
682 (regs.sr.sr_struct.t ? 't':'.'),
683 (regs.sr.sr_struct.s ? 'S':'.'),
684 (regs.sr.sr_struct.z ? 'z':'.'),
685 (regs.sr.sr_struct.x ? 'x':'.'),
686 (regs.sr.sr_struct.n ? 'n':'.'),
687 (regs.sr.sr_struct.v ? 'v':'.'),
688 (regs.sr.sr_struct.c ? 'c':'.'),
689 ((regs.sr.sr_struct.i2 ? 4:0 )+(regs.sr.sr_struct.i1 ? 2:0 )+(regs.sr.sr_struct.i0 ? 1:0 )),
690 segment1,segment2,start,context );
691
692 fprintf(buglog,"%sA 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x 6:%08x 7:%08x SP:%08x PC:%08x SRC:\n\n",tag,
693 regs.regs[8], regs.regs[9], regs.regs[10],regs.regs[11],regs.regs[12],
694 regs.regs[13],regs.regs[14],regs.regs[15],regs.sp,regs.pc);
695 fflush(buglog);
696 }
697 #endif
698
699
dumpram(char * reason)700 void dumpram(char *reason)
701 {
702 FILE *ramdump;
703 char filename[256];
704 uint32 i,j; //,k;
705 uint16 slr, sor; //, mfn;
706 //uint32 a9 =((pc24) & 0x00ffffff)>>9;
707 //uint32 a17=((pc24) & 0x00ffffff)>>17;
708 uint32 mad; //filter; mtd;
709 //lisa_mem_t fn;
710
711 snprintf(filename,256,"/log/lisaem-output-ramdump-%s-%08x.%016llx",reason,pc24,cpu68k_clocks);
712 ramdump=fopen(filename,"wt");
713
714 fprintf(ramdump,"context:%d segment1:%d, segment2:%d, start:%d pc24:%08x\n\n",context,segment1,segment2,start,pc24);
715
716
717 fprintf(ramdump,"ramsize:%08x, lastcx:%d, cx:%d seg1:%d, seg2:%d, start:%d, mmudirty:%08x,%08x,%08x,%08x,%08x\n",
718 maxlisaram,
719 lastcontext, context,
720 segment1, segment2, start,
721 mmudirty_all[0],mmudirty_all[1],mmudirty_all[2],mmudirty_all[3],mmudirty_all[4]);
722
723 fprintf(ramdump,"diag1:%d, diag2:%d, soft:%d, hard:%d, vert:%d, vidlatch:%02x, lastvidlatch:%02x, vidlatchaddr:%08x, lastvidlatchadr:%08x",
724 diag1, diag2,
725 softmem,
726 hardmem,
727 vertical,
728 videolatch, lastvideolatch, videolatchaddress, lastvideolatchaddress);
729
730 //videoramdirty,
731 //videoximgdirty,
732
733 fprintf(ramdump,"regs D 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x 6:%08x 7:%08x SR:%02x %c%c%c%c%c%c%c irqmsk:%d %d/%d/%d context:%d\n",
734 reg68k_regs[0], reg68k_regs[1], reg68k_regs[2], reg68k_regs[3], reg68k_regs[4],
735 reg68k_regs[5], reg68k_regs[6], reg68k_regs[7], reg68k_sr.sr_int,
736 (reg68k_sr.sr_struct.t ? 't':'.'),
737 (reg68k_sr.sr_struct.s ? 'S':'.'),
738 (reg68k_sr.sr_struct.z ? 'z':'.'),
739 (reg68k_sr.sr_struct.x ? 'x':'.'),
740 (reg68k_sr.sr_struct.n ? 'n':'.'),
741 (reg68k_sr.sr_struct.v ? 'v':'.'),
742 (reg68k_sr.sr_struct.c ? 'c':'.'),
743 ((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 )),
744 segment1,segment2,start,context );
745
746 fprintf(ramdump,"regs A 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x 6:%08x 7:%08x SP:%08x PC:%08x\n\n\n",
747 reg68k_regs[8], reg68k_regs[9], reg68k_regs[10],reg68k_regs[11],reg68k_regs[12],
748 reg68k_regs[13],reg68k_regs[14],reg68k_regs[15],regs.sp,reg68k_pc);
749
750
751 for (i=0; i<5; i++)
752 for ( j=0; j<128; j++)
753 {
754 slr=mmu_all[i][j].slr;
755 sor=mmu_all[i][j].sor;
756
757 mad=((sor & 0x0fff)<<9) & TWOMEGMLIM;
758
759 fprintf(ramdump,"mmu[%d][%3d].slr:%04x,sor:%04x %08x-%08x::-->(%08x) type::%s\n",
760 i,j,slr,sor,((uint32)j<<17),((uint32)j<<17)+((1<<17)-1),mad,
761 slrname(slr)
762 );
763 }
764 fflush(ramdump);
765
766
767
768 for ( i=0; i<maxlisaram; i+=16)
769 {
770 if (lisaram[i+0]|lisaram[i+1]|lisaram[i+2]| lisaram[i+3]| lisaram[i+4]| lisaram[i+5]| lisaram[i+6]| lisaram[i+7]|
771 lisaram[i+8]|lisaram[i+9]|lisaram[i+10]|lisaram[i+11]|lisaram[i+12]|lisaram[i+13]|lisaram[i+14]|lisaram[i+15])
772 fprintf(ramdump,"RAM %06x: %02x %02x %02x %02x %02x %02x %02x %02x:%02x %02x %02x %02x %02x %02x %02x %02x |%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
773 i,
774 lisaram[i+0],lisaram[i+1],lisaram[i+2], lisaram[i+3], lisaram[i+4], lisaram[i+5], lisaram[i+6], lisaram[i+7],
775 lisaram[i+8],lisaram[i+9],lisaram[i+10],lisaram[i+11],lisaram[i+12],lisaram[i+13],lisaram[i+14],lisaram[i+15],
776 ((lisaram[i+0 ]>' ' && lisaram[i+0 ]<127) ? lisaram[i+0 ]:'.'),
777 ((lisaram[i+1 ]>' ' && lisaram[i+1 ]<127) ? lisaram[i+1 ]:'.'),
778 ((lisaram[i+2 ]>' ' && lisaram[i+2 ]<127) ? lisaram[i+2 ]:'.'),
779 ((lisaram[i+3 ]>' ' && lisaram[i+3 ]<127) ? lisaram[i+3 ]:'.'),
780 ((lisaram[i+4 ]>' ' && lisaram[i+4 ]<127) ? lisaram[i+4 ]:'.'),
781 ((lisaram[i+5 ]>' ' && lisaram[i+5 ]<127) ? lisaram[i+5 ]:'.'),
782 ((lisaram[i+6 ]>' ' && lisaram[i+6 ]<127) ? lisaram[i+6 ]:'.'),
783 ((lisaram[i+7 ]>' ' && lisaram[i+7 ]<127) ? lisaram[i+7 ]:'.'),
784 ((lisaram[i+8 ]>' ' && lisaram[i+8 ]<127) ? lisaram[i+8 ]:'.'),
785 ((lisaram[i+9 ]>' ' && lisaram[i+9 ]<127) ? lisaram[i+9 ]:'.'),
786 ((lisaram[i+10]>' ' && lisaram[i+10]<127) ? lisaram[i+10]:'.'),
787 ((lisaram[i+11]>' ' && lisaram[i+11]<127) ? lisaram[i+11]:'.'),
788 ((lisaram[i+12]>' ' && lisaram[i+12]<127) ? lisaram[i+12]:'.'),
789 ((lisaram[i+13]>' ' && lisaram[i+13]<127) ? lisaram[i+13]:'.'),
790 ((lisaram[i+14]>' ' && lisaram[i+14]<127) ? lisaram[i+14]:'.'),
791 ((lisaram[i+15]>' ' && lisaram[i+15]<127) ? lisaram[i+15]:'.') );
792 }
793
794
795 fflush(ramdump);
796 fclose(ramdump);
797 }
798
799
800
801 extern void xxxcheckcontext(uint8 c, char *text);
802
xdumpram(void)803 void xdumpram(void) {dumpram("atexit");}
804
805
806 #ifdef DEBUG
807
808 extern char *gettimername(uint8 t);
809 #ifdef LOOKAHEAD
810 static int been_here_before=0;
811 #endif
812
813 #ifdef PROCNAME_DEBUG
is_valid_procname(uint8 c)814 int is_valid_procname(uint8 c)
815 {
816 c &=0x7f;
817 if (c>='A' && c<='Z') return 1;
818 if (c=='_' || c==' ') return 1;
819 if (c>='0' && c<='9') return 1;
820 return 0;
821 }
822
is_valid_procname_w(uint16 w)823 int is_valid_procname_w(uint16 w)
824 {
825 return (is_valid_procname(w>>8) && is_valid_procname(w & 0x7f) );
826 }
827 #endif
828 #endif
829
830
get_address_mmu_rfn_type(uint32 addr)831 int get_address_mmu_rfn_type(uint32 addr)
832 {
833 addr=addr & 0x00ffffff;
834 return mmu_trans[(addr>>9) & 32767].readfn;
835 }
836
837 extern long get_wx_millis(void);
838
839
reg68k_external_execute(int32 clocks)840 int32 reg68k_external_execute(int32 clocks)
841 {
842 XTIMER entry=cpu68k_clocks;
843 XTIMER entry_stop=cpu68k_clocks+clocks;
844 XTIMER clks_stop=cpu68k_clocks+clocks;
845
846 // remove these.
847 XTIMER entrystop=cpu68k_clocks_stop;
848 // remove these.
849
850
851
852 #ifdef DEBUG
853
854 static char text[1024];
855
856 #ifdef SUPPRESS_LOOP_DISASM
857 int32 suppress_printregs=0;
858 int32 last_regs_idx=0;
859 t_regs last_regs[MAX_LOOP_REGS]; // last opcode register values
860 #endif
861
862 #endif
863
864
865
866 #define MAX_INSTR_PER_CALL 1000
867
868 static t_ipc *ipc;
869 static mmu_trans_t *mt;
870 static uint32 last_pc;
871
872 #ifdef USE_SETJMP
873 jmp_buf jb;
874 #endif
875
876 //#ifdef DEBUG
877 // if ( !atexitset)
878 // {
879 // atexit(dump_scc);
880 // atexit(dumpallmmu);
881 // atexit(xdumpram);
882 // atexit(dumpvia);
883 // atexitset=1;
884 // }
885
886 // if (insetjmpland)
887 // {fprintf(buglog,"*** DANGER Entering %s:%s:%d from %s setjmpland*****\n",__FILE__,__FUNCTION__,__LINE__,(insetjmpland ? "inside" : "outside")); fflush(buglog); EXIT(1);}
888 //
889 //#endif
890
891 #ifdef USE_SETJMP
892 if (!setjmp(jb))
893 #endif
894 {
895
896 /* move PC and register block into global variables */
897 reg68k_pc = regs.pc;//20060129// & 0x00ffffff;
898 reg68k_regs = regs.regs;
899 reg68k_sr.sr_int = regs.sr.sr_int;
900 insetjmpland=1;
901 // ALERT_LOG(0,"entry reg68k_pc:%08x,pc24:%08x mmutrans:%08x clock:%16llx",reg68k_pc,pc24,cpu68k_clocks,CHK_MMU_TRANS(pc24));
902
903 last_bus_error_pc=0;
904
905
906 // this sets cpu68k_clocks_stop
907
908
909 if ( (reg68k_pc) & 1 || (regs.pc &1) ) LISA_REBOOTED(0);
910
911
912 get_next_timer_event();
913
914
915
916 #ifdef DISASM_SKIPPED_OPCODES
917 if (debug_log_enabled && pc24>lastpc24 && lastpc24>0)
918 if ( (pc24-lastpc24)<128)
919 {
920 uint32 cursor=lastpc24;
921 char text[1024];
922 static t_ipc myipc;
923 static t_iib *mypiib;
924
925 DEBUG_LOG(0,"disassembling skipped opcodes between %08x-%08x",cursor,pc24);
926
927 pc24 = reg68k_pc & 0x00ffffff;
928
929
930 while (cursor<pc24)
931 {
932 abort_opcode=2;
933 if (!(mypiib = cpu68k_iibtable[fetchword(cursor)]))
934 {DEBUG_LOG(1,"Invalid instruction @ %08X\n", cursor); cursor=pc24;
935 break;
936 }
937 if (abort_opcode==1) cursor=pc24;
938 abort_opcode=2;
939 #ifdef DEBUG
940 if (!mypiib) DEBUG_LOG(0,"About to send null IPC!");
941 #endif
942 cpu68k_ipc(cursor, mypiib,&myipc); if (abort_opcode==1) cursor=pc24;
943
944 abort_opcode=2; diss68k_gettext(&myipc, text); if (abort_opcode==1) cursor=pc24;
945
946 fprintf(buglog,"\nx:%08x (skipped) opcode=%04x %s +%d clks SRC:\n",cursor,myipc.opcode,text,myipc.clks);
947
948 cursor +=myipc.wordlen*2; if (!myipc.wordlen) {EXIT(14,0,"*** Doh! ipc.wordlen=0 **");}
949 }
950 if (abort_opcode==1) DEBUG_LOG(0,"**DANGER*** GOT abort_opcode!******\n");
951 debug_log_enabled=1;
952 }
953 #endif
954 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
955
956 lastpc24=pc24;
957 clks_stop=MIN(clks_stop,cpu68k_clocks_stop);
958
959 DEBUG_LOG(0,"\n\ncpu68k_clocks is:%016llx before entering do-while loop\nwill expire at %016llx",cpu68k_clocks,
960 clks_stop);
961
962 do {
963 abort_opcode=0;
964 SET_CPU_FNC_CODE();
965
966
967 pc24 = reg68k_pc & 0x00ffffff;
968 if (reg68k_pc & 1) LISA_REBOOTED(0);
969
970
971 /* C ROM */ if (lisarom[0x3ffc]==0x02 && lisarom[0x3ffd]==0x11 && pc24==0xfe0270) ALERT_LOG(0,"C ROM 0x275:%02x",lisarom[0x0275]);
972
973
974
975 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
976 // disassemble skipped code (within reason)
977 // 1/0000d42e (lisacx 0 0/0/0) opcode=303c MOVE.W
978 // 2005.04.15 hack to get at the LisaTest Video test routines.
979
980 // Screenshot
981 //if (pc24==0xd5ec) ascii_screendump();
982
983
984 #ifdef LOOKAHEAD
985 if (pc24==LOOKSTARTADDR && been_here_before==0)
986 {
987 uint32 cursor=pc24;
988 char text[1024];
989 static t_ipc myipc;
990 static t_iib *mypiib;
991
992 been_here_before=1;
993 debug_off();
994 debug_on("lookahead"); debug_log_enabled=1;
995
996 DEBUG_LOG(0,"lookahead disassembling skipped opcodes between %08x-%08x",cursor,pc24);
997
998 pc24 = reg68k_pc & 0x00ffffff;
999
1000
1001 while (cursor<LOOKENDADDR)
1002 {
1003 abort_opcode=2;
1004 if (!(mypiib = cpu68k_iibtable[fetchword(cursor)]))
1005 {DEBUG_LOG(1,"Invalid instruction @ %08X\n", cursor); cursor=pc24;
1006 break;
1007 }
1008 if (abort_opcode==1) cursor=LOOKENDADDR;
1009 abort_opcode=2;
1010 #ifdef DEBUG
1011 if (!mypiib) DEBUG_LOG(0,"About to send null IPC!");
1012 #endif
1013 cpu68k_ipc(cursor, mypiib,&myipc); if (abort_opcode==1) cursor=LOOKENDADDR;
1014
1015 abort_opcode=2; diss68k_gettext(&myipc, text); if (abort_opcode==1) cursor=LOOKENDADDR;
1016
1017 if (mypiib->clocks!=myipc.clks) DEBUG_LOG(0,"ERROR:iib clocks:%d != ipc clocks:%d !", mypiib->clocks , myipc.clks);
1018 fprintf(buglog,"\nL:%08x opcode=%04x %-70s +%d clks",cursor,myipc.opcode,text,myipc.clks);
1019
1020 cursor +=myipc.wordlen*2; if (!myipc.wordlen) {EXIT(14,0,"*** Doh! ipc.wordlen=0 **");}
1021 }
1022 if (abort_opcode==1) DEBUG_LOG(0,"**DANGER*** GOT abort_opcode!******\n");
1023 debug_log_enabled=0; debug_off();
1024 }
1025 #endif
1026
1027
1028
1029
1030 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
1031
1032
1033 mt=&mmu_trans[(pc24>>9) & 32767];
1034 if (mt->readfn==bad_page)
1035 {
1036 DEBUG_LOG(0,"\n\nCurrent opcode lives inside a bad_page, throwing lisa_mmu_exception @ %d/%08x. Previous IR=%04x",
1037 context,pc24,InstructionRegister);
1038 DEBUG_LOG(0,"mmu_trans[%04x] segment #%d\n\n",(pc24>>9) & 32767,(pc24>>17));
1039 //fflush(buglog);dumpmmupage(context, (pc24>>17), buglog); fflush(buglog);
1040 lisa_mmu_exception(pc24);
1041 break; // this break here causes the "fucked timing" danger warning - it can be ignored
1042 }
1043
1044
1045
1046 lastsflag=reg68k_sr.sr_struct.s;
1047
1048 #ifdef DEBUG
1049
1050 #ifdef SUPPRESS_LOOP_DISASM
1051
1052 if (!suppress_printregs)
1053 {
1054 if (debug_log_enabled) {printregs(buglog,"");}
1055 }
1056 else
1057 {
1058 int32 i; int32 j=(suppress_printregs & 32767); int flag=0;
1059 char line[1024], buf[1024];
1060
1061 snprintf(line,1024,"loop:: %08x: ",pc24);
1062
1063 // might want to change j to be the previous instruction - but doesn't matter very much I suppose
1064 for (i=0; i<8; i++) if (last_regs[j].regs[i]!=reg68k_regs[i]) {snprintf(buf,1024,"D%d:%08x ",i,reg68k_regs[i]); strncat(line,buf,1024);flag=1;}
1065 for (i=8; i<16; i++) if (last_regs[j].regs[i]!=reg68k_regs[i]) {snprintf(buf,1024,"A%d:%08x ",i-8,reg68k_regs[i]); strncat(line,buf,1024);flag=1;}
1066 if (last_regs[j].sr.sr_int!=reg68k_sr.sr_int)
1067 {flag=1;
1068 snprintf(buf,1024,"%c%c%c%c%c%c%c imsk:%d ",
1069 (reg68k_sr.sr_struct.t ? 't':'.'),
1070 (reg68k_sr.sr_struct.s ? 'S':'.'),
1071 (reg68k_sr.sr_struct.z ? 'z':'.'),
1072 (reg68k_sr.sr_struct.x ? 'x':'.'),
1073 (reg68k_sr.sr_struct.n ? 'n':'.'),
1074 (reg68k_sr.sr_struct.v ? 'v':'.'),
1075 (reg68k_sr.sr_struct.c ? 'c':'.'),
1076 ((reg68k_sr.sr_struct.i2 ? 4:0 )+(reg68k_sr.sr_struct.i1 ? 2:0 )+(reg68k_sr.sr_struct.i0 ? 1:0 )) );
1077 strncat(line,buf,1024);
1078 }
1079 if (flag) fprintf(buglog,"%s\n",line);
1080 }
1081 #else
1082 if (debug_log_enabled) {printregs(buglog,"");} // printlisatime(buglog);}
1083 #endif
1084 #endif
1085
1086 // get the page and the mmu_translation table entry for this pc24
1087 page=pc24>>9; mt=&mmu_trans[page];
1088
1089
1090
1091 // Is this page table allocated? If not allocate it as needed.
1092 if (mt!=NULL && mt->table!=NULL)
1093 {
1094 ipc=&(mt->table->ipc[(pc24 & 0x1ff)>>1]);
1095
1096 // we have an IPC, now check it to see that it matches what's in there
1097 // this is a sanity check against moved pages, but not against self
1098 // modifying code which only changes operands - that would be too slow
1099 // to check.
1100
1101 #ifdef DEBUG
1102 dbx=debug_log_enabled; //20070723//debug_log_enabled=0;
1103 #endif
1104
1105 abort_opcode=2;
1106 #ifndef EVALUATE_EACH_IPC
1107 if (ipc->opcode != (fetchword(pc24)))
1108 #endif
1109 {
1110 if (abort_opcode==1) break;
1111
1112
1113 if (!mt->table) mt->table=get_ipct(); //we can skip fre_ipct
1114
1115 cpu68k_makeipclist(pc24); if (abort_opcode==1) break;
1116 ipc=&(mt->table->ipc[(pc24 & 0x1ff)>>1]);
1117 }
1118 abort_opcode=0;
1119
1120
1121 #ifdef DEBUG
1122 {
1123 #ifdef ICACHE_DEBUG
1124 if (dbx && pc24>16)
1125 {
1126 int i; uint8 c,nice[1024], hex[1024], tmp[1024];
1127
1128 nice[0]=0; hex[0]=0;
1129
1130 for (i=0; i<32; i++)
1131 {
1132 abort_opcode=2;
1133 c=lisa_ram_safe_getbyte(context,(pc24-16+i));
1134 if (i & 1) snprintf(tmp,1024,"%02x ",c);
1135 else snprintf(tmp,1024,"%02x",c);
1136
1137 strncat(hex,tmp,1024);
1138 nice[i]=niceascii(c);
1139 }
1140
1141 debug_log_enabled|=dbx; // re-enable debug log only after icache fetches to prevent verbosity
1142
1143 fprintf(buglog,"%08x:%s|%s clk:%016llx\n",pc24-16,hex,nice,cpu68k_clocks);
1144 //DEBUG_LOG(0,"icache:%04x:%04x:%04x:%04x:%04x clk:%08x",ipc->opcode,icache2,icache4, icache6, icache8,cpu68k_clocks);
1145 abort_opcode=0;
1146 }
1147 else debug_log_enabled=dbx;
1148 #else
1149 debug_log_enabled|=dbx;
1150 #endif
1151 }
1152 #endif
1153
1154 } // end of if (mt!=NULL && mt->table!=NULL)
1155 else // need to make this IPC table
1156 {
1157 //if ( !mt) { fprintf(buglog,"Doh! mt is null! bye!"); EXIT(4); }
1158 abort_opcode=2; mt->table=get_ipct(); if (abort_opcode==1) break;
1159 abort_opcode=0;
1160
1161 abort_opcode=2;
1162 cpu68k_makeipclist(pc24);
1163 if (abort_opcode==1) break;
1164
1165 #ifdef DEBUG
1166 if ( !mt->table) {DEBUG_LOG(-1,"reg68k_extern_exec: got a null mt->table from makeipclist!");}
1167 #endif
1168
1169 ipc=&(mt->table->ipc[(pc24 & 0x1ff)>>1]);
1170 }
1171
1172 // If the page isn't RAM or ROM, then we can't execute it.
1173 // I can get rid of this check to speed things up... but...
1174
1175 #ifdef DEBUG
1176 if (mt->readfn!=ram && mt->readfn!=sio_rom && mt->readfn!=sio_mmu)
1177 {
1178 EXIT(397,0,"Woot! Trying to execute from non-ram/rom! Living dangerously!"
1179 "Bye Bye! PC24= %08x ipc# %d mt->readfn=%d %s\n",pc24,(pc24 & 0x1ff)>>1,mt->readfn,mspace(mt->readfn));
1180 }
1181 else
1182 #endif
1183 {
1184
1185
1186 // keep this can use for debugger later
1187 #ifdef xxxHALT_AT
1188 if ( (pc24==0xfe06f2 || pc24==0xfe14F2 || pc24==0xfe144a pc==0xfe) && mt->readfn==sio_rom)
1189 {
1190 EXIT(398,0,"compiled in halt.");
1191 }
1192 #endif
1193
1194
1195
1196 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1197 #ifdef DEBUG
1198
1199
1200
1201 if (debug_log_enabled)
1202 {
1203 if (mt->readfn==sio_mmu && rom_source_file && dtc_rom_fseeks && ((pc24 & 0xffff)<0x3fff))
1204 { char buff[1024];
1205 fseek(rom_source_file,dtc_rom_fseeks[pc24 & 0x3fff],SEEK_SET);
1206 fgets(buff,1024,rom_source_file); if (strlen(buff)>5) fprintf(buglog,"%08x: SRC: %s\n",pc24,buff);
1207 }
1208
1209 #ifdef SUPPRESS_LOOP_DISASM
1210 {
1211 int i,j,k=0;
1212
1213 suppress_printregs=0;
1214
1215 j=last_regs_idx;
1216 do {j--; if (j<0) j=MAX_LOOP_REGS-1;
1217 if (pc24==last_regs[j].pc) k=1;
1218 } while (j!=last_regs_idx && !k);
1219
1220 // copy to current register
1221 j=last_regs_idx+1; if (j>=MAX_LOOP_REGS) j=0;
1222
1223 last_regs[j].pc=pc24;
1224 last_regs[j].sp=regs.sp;
1225 last_regs[j].sr.sr_int=reg68k_sr.sr_int;
1226 for (i=0; i<16; i++) last_regs[j].regs[i]=reg68k_regs[i];
1227 last_regs_idx=j;
1228
1229
1230 if ((ipc->opcode & 0xf000)==0xa000)
1231 {
1232 char temp[256];
1233 snprintf(temp,256,"::%08x ",fetchlong(pc24+2));
1234 strncat(text,temp,256);
1235 }
1236 #endif
1237
1238 #ifdef PROCNAME_DEBUG
1239 { uint16 w,w1,w2,w3;
1240
1241 w=lisa_ram_safe_getword(context,(pc24-2));
1242 //DEBUG_LOG(0,"entering procedure: got 5th word:%04x",w);
1243 if (w<0x00f0)
1244 {
1245 w3=lisa_ram_safe_getword(context,(pc24-10));
1246 // DEBUG_LOG(0,"entering procedure got word in 0th spot:%04x is valid & 0x8000:%d is valid:%d",w3,(w3 & 0x8000),
1247 // is_valid_procname_w(w3 & 0x7f7f));
1248 if ( (w3 & 0x8000) && is_valid_procname_w(w3 & 0x7f7f) )
1249 {
1250 w2=lisa_ram_safe_getword(context,(pc24-8));
1251 w1=lisa_ram_safe_getword(context,(pc24-6));
1252 w =lisa_ram_safe_getword(context,(pc24-4));
1253
1254 // DEBUG_LOG(0,"entering procedure Got words:%04x %04x %04x %04x",w3,w2,w1,w);
1255
1256 if (is_valid_procname_w(w) && is_valid_procname_w(w1) && is_valid_procname_w(w2) )
1257 fprintf(buglog,"\n\n****** Entering Procedure: %c%c%c%c%c%c%c%c *********\n\n",
1258 ((w3>>8) & 0x7f),(w3 & 0x7f),
1259 ((w2>>8) & 0x7f),(w2 & 0x7f),
1260 ((w1>>8) & 0x7f),(w1 & 0x7f),
1261 ((w >>8) & 0x7f),(w & 0x7f) );
1262
1263 }
1264 }
1265 }
1266 #endif // end of PROCNAME_DEBUG
1267
1268
1269 if (!k)
1270 {if (ipc->opcode!=0xe350)
1271 abort_opcode=2; diss68k_gettext(ipc, text);
1272 fprintf(buglog,"%d/%08x (lisacx %d %d/%d/%d) opcode=%04x %s SRC:clk:%016llx +%ld clks\n",context,pc24,
1273 (segment1|segment2),segment1,segment2,start,ipc->opcode,text,cpu68k_clocks, ipc->clks);
1274 }
1275 else suppress_printregs=32768|j;
1276 }
1277 }
1278 last_cpu68k_clocks=cpu68k_clocks;
1279 #endif
1280
1281 // Cheat to skip over big wait loop in NMI code
1282 #ifdef SKIP_BIGWAIT_NMI_CODE
1283 if (lisa_os_boot_mouse_x_ptr==0xfec)
1284 {/////////////////////////////////////////////////////////////////////////////////////////
1285
1286 if ( ipc->opcode==0x5381)
1287 {
1288 // hack to speed up lisatest?
1289 if (pc24==0xd36e && reg68k_regs[1]==0x3d090) reg68k_regs[1]=1;
1290 if (pc24==0xdd52 && reg68k_regs[1]>1 ) {reg68k_regs[1]=1;}
1291 }
1292 else // 2005.04.05 06:22am - Turn Debugging on LisaTest CPU ErrorLevel
1293 if (pc24==0x0000d2c8 && ipc->opcode==0xb3cb && reg68k_regs[6]==0x00000018 && reg68k_regs[8]<0x001ff000)
1294 {
1295 debug_on("LisaTest-cpu-errorlogic"); debug_log_enabled=1; debug_log_enabled=1; last_dbe=1;
1296 reg68k_regs[8]=0x001fff00; reg68k_regs[9]=0x001fff00;
1297 memerror=0xFFF8;
1298 DEBUG_LOG(0,"LisaTest CPU Error Logic - enabling debug 2005.04.05");
1299 }
1300
1301
1302 }///////////////////////////////////////////////////////////////////////////////////////////
1303 #endif
1304
1305
1306
1307
1308
1309 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1310
1311 if (abort_opcode==1) {EXITR(476,0,"MMU/BUS/Address exception occured on opcode fetch!\n");}
1312 abort_opcode=0; // clear any addr/bus errors/traps/etc that may have occured.
1313
1314 InstructionRegister=ipc->opcode;
1315
1316
1317
1318 #ifdef CPU_CORE_TESTER
1319 {
1320 char texttext[1024];
1321
1322 abort_opcode=2; diss68k_gettext(ipc, text);
1323 snprintf(texttext,1024,"opcode:%s (%04x) @%d/%08x icache:%02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x\n",
1324 text,ipc->opcode,context,reg68k_pc,
1325 lisa_ram_safe_getbyte(context,pc24+0),
1326 lisa_ram_safe_getbyte(context,pc24+1),
1327 lisa_ram_safe_getbyte(context,pc24+2),
1328 lisa_ram_safe_getbyte(context,pc24+3),
1329
1330 lisa_ram_safe_getbyte(context,pc24+4),
1331 lisa_ram_safe_getbyte(context,pc24+5),
1332 lisa_ram_safe_getbyte(context,pc24+6),
1333 lisa_ram_safe_getbyte(context,pc24+7),
1334
1335 lisa_ram_safe_getbyte(context,pc24+8),
1336 lisa_ram_safe_getbyte(context,pc24+9),
1337 lisa_ram_safe_getbyte(context,pc24+10),
1338 lisa_ram_safe_getbyte(context,pc24+11),
1339
1340 lisa_ram_safe_getbyte(context,pc24+12),
1341 lisa_ram_safe_getbyte(context,pc24+13),
1342 lisa_ram_safe_getbyte(context,pc24+14),
1343 lisa_ram_safe_getbyte(context,pc24+15) );
1344
1345 corecpu_start_opcode(texttext, context);
1346
1347 }
1348 #endif
1349
1350 // ALERT_LOG(0,"pc:%08x opcode:%04x mmu trans:%08x opcode mem:%02x%02x",reg68k_pc,ipc->opcode,
1351 // CHK_MMU_TRANS(reg68k_pc),lisaram[CHK_MMU_TRANS(reg68k_pc)],lisaram[CHK_MMU_TRANS(reg68k_pc+1)]);
1352
1353 // {
1354 // char text[1024];
1355 // diss68k_gettext(ipc, text);
1356 //
1357 // ALERT_LOG(0,"%08x %s",reg68k_pc,text);
1358 // }
1359 #ifdef DEBUG
1360 dbx=debug_log_enabled; //20070723//debug_log_enabled=0;
1361 #endif
1362
1363
1364 if (ipc->function) // if the IPC is valid, and loaded
1365 {SET_CPU_FNC_DATA(); ipc->function(ipc);} // execute the function, else rebuild the IPC
1366 else {
1367 static t_iib *piib;
1368
1369 if (!(piib = cpu68k_iibtable[fetchword(reg68k_pc)]))
1370 ALERT_LOG(1,"Invalid instruction @ %08X\n", reg68k_pc); // RA
1371
1372
1373 SET_CPU_FNC_CODE();
1374 #ifdef DEBUG
1375 if (!ipc) DEBUG_LOG(0,"About to send null IPC!");
1376 if (!piib) DEBUG_LOG(0,"About to send null IPC!");
1377 #endif
1378
1379 cpu68k_ipc(reg68k_pc,piib,ipc);
1380
1381 if (piib->clocks!=ipc->clks)
1382 DEBUG_LOG(0,"ERROR:iib clocks:%d != ipc clocks:%d !", piib->clocks , ipc->clks);
1383
1384 DEBUG_LOG(0,"Got an IPC without a function at %08x, opcode is:%04x doing it manually - like it's just 0000 OR ",reg68k_pc,ipc->opcode);
1385
1386 if (abort_opcode==1) break;
1387
1388
1389 ipc->function=cpu68k_functable[fetchword(reg68k_pc) * 2 + 1];
1390
1391
1392 //cpu68k_functable[fetchword(reg68k_pc) * 2 + 1] (&ipc); (&ipc);
1393
1394 SET_CPU_FNC_DATA();
1395 if (abort_opcode==1) {DEBUG_LOG(0,"MMU/BUS/Address exception occured on opcode fetch!\n"); fflush(buglog); break;}
1396 else {
1397 InstructionRegister=ipc->opcode;
1398 abort_opcode=0;
1399 if (ipc->function) ipc->function(ipc);
1400 else { EXITR(277,0,"No ipc function at %d/%08x, even after attempting to get one!\n",context,pc24);}
1401 }
1402 } // if we have it, execute, else loop is done. :)
1403
1404 #ifdef DEBUG
1405 debug_log_enabled|=dbx;
1406 #endif
1407
1408
1409 #ifdef CPU_CORE_TESTER
1410 corecpu_complete_opcode(context);
1411 #endif
1412
1413
1414
1415
1416 #ifdef XXXDEBUG
1417
1418
1419 /*
1420 if ((pc24 & 0x00ff0000)!=0x00fe0000 && (reg68k_pc & 0x00ff0000)==0x00fe0000)
1421 ALERT_LOG(0,"Entering ROM from operating system at %08x from %08x %s\n"
1422 "D 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x 6:%08x 7:%08x\n"
1423 "A 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x 6:%08x 7:%08x\n",
1424 reg68k_pc,pc24,get_rom_label(reg68k_pc),
1425 reg68k_regs[0], reg68k_regs[1], reg68k_regs[2], reg68k_regs[3], reg68k_regs[4], reg68k_regs[5], reg68k_regs[6], reg68k_regs[7],
1426 reg68k_regs[8], reg68k_regs[9], reg68k_regs[10],reg68k_regs[11],reg68k_regs[12],reg68k_regs[13],reg68k_regs[14],reg68k_regs[15]
1427 );
1428 */
1429 if (reg68k_pc==0x00fe0090 || pc24==0x00fe0090)
1430 {
1431 ALERT_LOG(0,"ENT Entering ROM profile read. ROMLESS")
1432 int i;
1433 uint8 b;
1434
1435 b=fetchbyte(0x1b3);
1436
1437 ALERT_LOG(0,"ENT Booting up reg68k_pc:%08x from pc24:%08x %s. reg68k_sr.sr_int=%04x regs.sp=%08x 1b3:%02x ROMLESS\n"
1438 "ENT D 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x 6:%08x 7:%08x ROMLESS\n"
1439 "ENT A 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x 6:%08x 7:%08x ROMLESS\n",
1440 reg68k_pc,pc24,get_rom_label(reg68k_pc),reg68k_sr.sr_int,regs.sp,b,
1441 reg68k_regs[0], reg68k_regs[1], reg68k_regs[2], reg68k_regs[3], reg68k_regs[4], reg68k_regs[5], reg68k_regs[6], reg68k_regs[7],
1442 reg68k_regs[8], reg68k_regs[9], reg68k_regs[10],reg68k_regs[11],reg68k_regs[12],reg68k_regs[13],reg68k_regs[14],reg68k_regs[15]
1443 );
1444
1445 }
1446
1447
1448 // if (reg68k_pc==0x00fe1fee)
1449 // {
1450 //
1451 // ALERT_LOG(0,"RET Return from ROM profile read. ROMLESS")
1452 // int i;
1453 // uint8 b;
1454 //
1455 // b=fetchbyte(0x1b3);
1456 //
1457 // ALERT_LOG(0,"RET Booting up reg68k_pc:%08x from pc24:%08x %s. reg68k_sr.sr_int=%04x regs.sp=%08x 1b3:%02x ROMLESS\n"
1458 // "RET D 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x 6:%08x 7:%08x ROMLESS\n"
1459 // "RET A 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x 6:%08x 7:%08x ROMLESS\n",
1460 // reg68k_pc,pc24,get_rom_label(reg68k_pc),reg68k_sr.sr_int,regs.sp,b,
1461 // reg68k_regs[0], reg68k_regs[1], reg68k_regs[2], reg68k_regs[3], reg68k_regs[4], reg68k_regs[5], reg68k_regs[6], reg68k_regs[7],
1462 // reg68k_regs[8], reg68k_regs[9], reg68k_regs[10],reg68k_regs[11],reg68k_regs[12],reg68k_regs[13],reg68k_regs[14],reg68k_regs[15]
1463 // );
1464 //
1465 // }
1466
1467 if (reg68k_pc==0x00020000)
1468 {
1469 int i;
1470 uint8 b;
1471
1472 b=fetchbyte(0x1b3);
1473
1474 ALERT_LOG(0,"INT Booting up reg68k_pc:%08x from pc24:%08x %s. reg68k_sr.sr_int=%04x regs.sp=%08x 1b3:%02x ROMLESS\n"
1475 "INT D 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x 6:%08x 7:%08x ROMLESS\n"
1476 "INT A 0:%08x 1:%08x 2:%08x 3:%08x 4:%08x 5:%08x 6:%08x 7:%08x ROMLESS\n",
1477 reg68k_pc,pc24,get_rom_label(reg68k_pc),reg68k_sr.sr_int,regs.sp,b,
1478 reg68k_regs[0], reg68k_regs[1], reg68k_regs[2], reg68k_regs[3], reg68k_regs[4], reg68k_regs[5], reg68k_regs[6], reg68k_regs[7],
1479 reg68k_regs[8], reg68k_regs[9], reg68k_regs[10],reg68k_regs[11],reg68k_regs[12],reg68k_regs[13],reg68k_regs[14],reg68k_regs[15]
1480 );
1481
1482
1483 }
1484 #endif
1485
1486
1487 pc24 = reg68k_pc; //20060321// & 0x00ffffff;
1488
1489 abort_opcode=0;
1490
1491 #ifdef DEBUG
1492 if (ipc->clks >160) {DEBUG_LOG(0,"***INSANELY FUCKED UP IPC STRUCT TIMING! ***BUG**** ipc->clks==%d",ipc->clks);cpu68k_printipc(ipc);}
1493 #endif
1494 //else DEBUG_LOG(0,"ipc->clks this cycle:%ld",ipc->clks);
1495
1496 cpu68k_clocks+=ipc->clks;
1497 } // if execute from ram/rom else statement
1498
1499 #ifdef DEBUG
1500 if (0==reg68k_pc)
1501 {
1502 DEBUG_LOG(0,"pc=0 LastPC24=%08x pc24=%08x abort_opcode:%d",lastpc24,pc24,abort_opcode);
1503 }
1504 #endif
1505 clks_stop=MIN(clks_stop,cpu68k_clocks_stop);
1506
1507 } while (clks_stop>cpu68k_clocks && !regs.stop);
1508
1509
1510 #ifdef DEBUG
1511 DEBUG_LOG(0,"pc=%08x cpu68k_clocks is:%016llx stop is :%016llx diff:%016llx regs.stop is %d event:%d %s after exiting do-while loop",
1512 reg68k_pc, cpu68k_clocks,cpu68k_clocks_stop,
1513 cpu68k_clocks_stop-cpu68k_clocks, regs.stop,
1514 next_timer_id(),gettimername(next_timer_id() ) );
1515
1516 printregs(buglog,"");
1517 #endif
1518
1519 last_pc=reg68k_pc;
1520 regs.pc = reg68k_pc; regs.sr.sr_int = reg68k_sr.sr_int;
1521
1522
1523 // handle NMI - NMI unlike Bus Error occurs AFTER the current opcode completes. ////////////////////////////////////////////
1524 if (nmi_clk && nmi_pc)
1525 { // regs.stop=nmi_stop; // NMI can only occur on memory access resulting in soft parity error, not while cpu is stopped
1526 regs.stop=0;
1527 reg68k_internal_vector(0x1f, reg68k_pc,nmi_addr_err); // 7 is wrong for vector, right for autovector.
1528 nmi_addr_err=0; nmi_clk=0; nmi_pc=0; nmi_stop=0; // clear flags
1529 regs.stop=0;
1530 }
1531 else // NMI did not occur, instead, see if there's a pending IRQ, or we're very close to one.
1532 {
1533 // check for the next pending IRQ's.
1534 if (cpu68k_clocks+10>=cpu68k_clocks_stop)
1535 {
1536 //long x=get_wx_millis();
1537 fire_pending_internal_autovector();
1538 //long y=get_wx_millis();
1539 check_current_timer_irq();
1540 //long z=get_wx_millis();
1541
1542 //ALERT_LOG(0,"irq timings: fire_pending_int_auto:%ldms, check_current_timer_irq:%ldms, total:%ldms",y-x,z-y,z-x);
1543 }
1544 }
1545
1546 if (regs.stop) cpu68k_clocks=cpu68k_clocks_stop;
1547
1548 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1549 insetjmpland=0;
1550 #ifdef USE_SETJMP
1551 longjmp(jb, 1);
1552 #endif
1553 }
1554
1555 return entry_stop-cpu68k_clocks; // how many cycles left over if positive, negative if did too many.
1556 }
1557
1558
1559
1560
reg68k_external_autovector(int avno)1561 void reg68k_external_autovector(int avno)
1562 {
1563 #ifdef USE_SETJMP
1564 jmp_buf jb;
1565 #endif
1566
1567
1568 if (insetjmpland)
1569 {DEBUG_LOG(0,"*** DANGER Entering %s:%s:%d from %s setjmpland***** vector:%d\n",__FILE__,__FUNCTION__,__LINE__,(insetjmpland ? "inside" : "outside"),avno); fflush(buglog);
1570 reg68k_internal_autovector(avno);
1571 return;
1572 }
1573 #ifdef USE_SETJMP
1574 if (!setjmp(jb))
1575 #endif
1576 {
1577 /* move PC and register block into global processor register variables */
1578 reg68k_pc = regs.pc;
1579 reg68k_regs = regs.regs;
1580 reg68k_sr.sr_int = regs.sr.sr_int;
1581 DEBUG_LOG(0,"Inside setjmp land, about to call internal_autovector:%d reg68k_pc:%08x reg68k_sr:%08x",avno,reg68k_pc,reg68k_sr.sr_int);
1582 insetjmpland=1;
1583
1584 reg68k_internal_autovector(avno);
1585
1586 DEBUG_LOG(0,"Autovector:%d reg68k_pc:%08x reg68k_sr:%08x regs.pc:%08x regs.sr:%08x, exiting setjmp land",avno,reg68k_pc,reg68k_sr.sr_int,regs.pc,regs.sr.sr_int);
1587 /* restore global registers back to permanent storage */
1588 regs.pc = reg68k_pc;
1589 regs.sr.sr_int = reg68k_sr.sr_int;
1590
1591 insetjmpland=0;
1592 #ifdef USE_SETJMP
1593 longjmp(jb, 1);
1594 #endif
1595 }
1596 }
1597
1598
reg68k_external_vector(int vector,uint32 oldpc,uint32 addr_error)1599 void reg68k_external_vector(int vector, uint32 oldpc,uint32 addr_error)
1600 {
1601 #ifdef USE_SETJMP
1602 jmp_buf jb;
1603 #endif
1604
1605 DEBUG_LOG(0,"VECTOR: %d, OLDPC:%08x memerr@:%08x",vector,oldpc,addr_error);
1606 if (insetjmpland)
1607 {fprintf(buglog,"*** DANGER Entering %s:%s:%d from %s setjmpland*****\n",__FILE__,__FUNCTION__,__LINE__,(insetjmpland ? "inside" : "outside")); fflush(buglog);
1608 reg68k_internal_vector(vector,oldpc,addr_error);
1609 return;
1610 }
1611
1612 #ifdef USE_SETJMP
1613 if (!setjmp(jb))
1614 #endif
1615 {
1616 /* move PC and register block into global processor register variables */
1617
1618 DEBUG_LOG(0,"In setjmp land vector:%d oldpc:%08x regs.pc:%08x regs.sr:%x",vector,oldpc,regs.pc,regs.sr.sr_int);
1619
1620 reg68k_pc = regs.pc;
1621 reg68k_regs = regs.regs;
1622 reg68k_sr.sr_int = regs.sr.sr_int;
1623 insetjmpland=1;
1624
1625 DEBUG_LOG(0,"Calling internal_vector from external reg68k_pc:%08x reg68k_sr:%x",reg68k_pc,reg68k_sr.sr_int);
1626 reg68k_internal_vector(vector,oldpc,addr_error);
1627 DEBUG_LOG(0,"Done with internal_vector vector:%d reg68k_pc:%08x reg68k_sr:%08x regs.pc:%08x regs.sr:%08x, exiting setjmp land",
1628 vector,
1629 reg68k_pc,
1630 reg68k_sr.sr_int,regs.pc,regs.sr.sr_int);
1631
1632
1633 /* restore global registers back to permanent storage */
1634 regs.pc = reg68k_pc;
1635 regs.sr.sr_int = reg68k_sr.sr_int;
1636
1637 insetjmpland=0;
1638 #ifdef USE_SETJMP
1639 longjmp(jb, 1);
1640 #endif
1641 }
1642 }
1643
1644
1645
1646
1647
1648
1649
1650
1651 // called by mmuflush to make sure that the correct context is set!
reg68k_update_supervisor_internal(void)1652 void reg68k_update_supervisor_internal(void) {lastsflag=reg68k_sr.sr_struct.s;}
reg68k_update_supervisor_external(void)1653 void reg68k_update_supervisor_external(void) {lastsflag=regs.sr.sr_struct.s;}
1654
1655 // Macros for 68000 Vector operations - these are turned into macro's to make the source code more readable and still faster than fn's
1656
1657 #define A7PUSH_BYTE(x) {abort_opcode=2; reg68k_regs[15] -= 1; storebyte(reg68k_regs[15], (x));}
1658 #define A7PUSH_WORD(x) {abort_opcode=2; reg68k_regs[15] -= 2; storeword(reg68k_regs[15], (x));}
1659 #define A7PUSH_LONG(x) {abort_opcode=2; reg68k_regs[15] -= 4; storelong(reg68k_regs[15], (x));}
1660 #define GETVECTOR(x) (fetchlong((x)*4))
1661 #define SWAPA7withSSP() {reg68k_regs[15] ^= regs.sp; regs.sp ^= reg68k_regs[15]; reg68k_regs[15] ^= regs.sp;}
1662 #define SETSUPERVISOR(x) {reg68k_sr.sr_struct.s = (x);}
1663 #define GETSUPERVISOR() (reg68k_sr.sr_struct.s)
1664
1665 /* reg68k_internal_autovector - go to autovector - this call assumes global
1666 registers are already setup
1667 interrupts must not occur during cpu68k_frozen, as this flag indicates
1668 that we are catching up events due to a dma transfer. Since the dma
1669 transfer is triggered by a memory write at which stage the current value
1670 of the PC is not written anywhere (due to being in the middle of a 68k
1671 block and it's in a local register), we MUST NOT use regs.pc - this
1672 routine uses reg68k_pc but this is loaded by reg68k_external_autovector,
1673 which is called by event_nextevent() and therefore will be a *WRONG*
1674 reg68k_pc!
1675 */
1676
1677
1678
reg68k_internal_autovector(int avno)1679 void reg68k_internal_autovector(int avno)
1680 {
1681
1682 reg68k_internal_vector(V_AUTO + avno - 1,reg68k_pc,0); //-1
1683
1684
1685 #ifdef DISABLED_2005_02_02
1686 int curlevel = (reg68k_sr.sr_int >> 8) & 7;
1687 uint32 tmpaddr;
1688 uint16 saved_sr=reg68k_sr.sr_int;
1689
1690 if (!insetjmpland)
1691 {fprintf(buglog,"*** DANGER Entering %s:%s:%d from %s setjmpland*****\n",__FILE__,__FUNCTION__,__LINE__,(insetjmpland ? "inside" : "outside")); fflush(buglog);
1692 reg68k_external_autovector(avno);
1693 return;
1694 }
1695
1696 DEBUG_LOG(0,"curlevel:%d avno:%d cpufrozen: %ld",curlevel,avno,cpu68k_frozen);
1697 fflush(buglog); fflush(stdout);
1698
1699 if ((curlevel < avno || avno == 7) && !cpu68k_frozen)
1700 {
1701 #ifdef DEBUG
1702 if (avno==1 && floppy_FDIR) append_floppy_log("reg68k_int_av_ ***Firing IRQ1 because FDIR is set***\n");
1703 #endif
1704
1705 if (regs.stop && nmi_clk && nmi_pc) {regs.stop=0; nmi_addr_err=0; nmi_clk=0; nmi_pc=0; nmi_stop=0;} // clear flags
1706 else if (regs.stop)
1707 {
1708 DEBUG_LOG(0,"exiting from STOP opcode @%08x - will continue at %08x after ISR handles IRQ:%d.",reg68k_pc,reg68k_pc+4,vno);
1709 reg68k_pc += 4; /* autovector whilst in a STOP instruction */
1710 regs.stop = 0;
1711 regs.pc = reg68k_pc; regs.sr = reg68k_sr;
1712 }
1713
1714
1715 if (!GETSUPERVISOR()) {
1716 SWAPA7withSSP();
1717 SETSUPERVISOR(1);
1718
1719 DEBUG_LOG(0,"S mode change SP:%08x/A7:%08x swapped.",reg68k_regs[15],regs.sp);
1720
1721 // if (segment1|segment2)
1722 {
1723 //lastsflag=reg68k_sr.sr_struct.s;
1724 regs.pc = reg68k_pc; regs.sr = reg68k_sr;
1725 SET_MMU_DIRTY(0xdec0de);
1726 mmuflush(0x3000);
1727 fprintf(buglog,"post mmuflush context=%d s1/s2=%d/%d start=%d\n",context,segment1,segment2,start);
1728 }
1729 // Supervisor flag set causes context change
1730 }
1731 lastsflag=reg68k_sr.sr_struct.s;
1732
1733 A7PUSH_LONG(reg68k_pc); if (abort_opcode==1) {EXIT(779,0,"Doh! got abort_opcode=%d on storeword of SR!\n",abort_opcode); }
1734 A7PUSH_WORD(saved_sr); if (abort_opcode==1) {EXIT(780,0,"Doh! got abort_opcode=1 on storeword of SR!\n");}
1735
1736 // insert format/vector here // RA for 68010+ disable for 68000/68008.
1737 // FV=0x1000 | ((V_AUTO + avno - 1) * 4);
1738 //or FV=0x0000 | ((V_AUTO + avno - 1) * 4);
1739 //reg68k_regs[15] -= 2;
1740 //storeword(reg68k_regs[15], FV);
1741 ////////////////////////////////
1742
1743 reg68k_sr.sr_struct.t = 0;
1744 reg68k_sr.sr_int &= ~0x0700;
1745 reg68k_sr.sr_int |= avno << 8;
1746 tmpaddr = reg68k_pc;
1747
1748 DEBUG_LOG(0,"autovector#%d V_AUTO:%08x Vector address: %d * 4 = %08x",avno,V_AUTO,(V_AUTO + avno - 1),((V_AUTO + avno - 1)*4));
1749
1750 abort_opcode=0;
1751 reg68k_pc = fetchlong((V_AUTO + avno - 1) * 4);
1752 if (abort_opcode==1) {EXIT(781,0,"Doh! got abort_opcode=1 while fetching vector for IRQ!\n"); }
1753
1754 DEBUG_LOG(0,"INTERNAL AUTOVECTOR %d: oldpc %x -> newpc is %x\n", avno, tmpaddr, reg68k_pc);
1755
1756 // if (avno<7 && avno) pending_vector_bitmap &= ~(1<<(avno-1));
1757
1758 // regs.pending = get_pending_vector();
1759 // restore regs to extern
1760 regs.pc = reg68k_pc;
1761 regs.sr.sr_int = reg68k_sr.sr_int;
1762
1763 }
1764 else
1765 {
1766
1767 // if (avno<7 && avno) pending_vector_bitmap |= (1<<(avno-1));
1768 // regs.pending = get_pending_vector();
1769 // if (!regs.pending || regs.pending < avno)
1770 // {
1771 // printregs(buglog,"");
1772 // DEBUG_LOG(0,"INTERNAL AUTOVECTOR %d: was not taken because IRQ level:%d filtered it. set pending to it...SR:%04x:%04x %s\n\n",avno,curlevel,regs.sr.sr_int,reg68k_sr.sr_int,
1773 // ((regs.sr.sr_int!=reg68k_sr.sr_int) ? "DANGER":"ok"));
1774 //
1775 // regs.pending = avno;
1776 // }
1777 // //regs.pending = 0;
1778
1779 }
1780 #endif
1781 }
1782
1783
reg68k_internal_vector(int vno,uint32 oldpc,uint32 addr_error)1784 void reg68k_internal_vector(int vno, uint32 oldpc, uint32 addr_error)
1785 {
1786 static uint32 lastoldpc;
1787 static int32 lastclk;
1788 static int lastvno;
1789 uint16 saved_sr=reg68k_sr.sr_int;
1790
1791 int avno=(vno-V_AUTO+1);
1792 int curlevel = (reg68k_sr.sr_int >> 8) & 7;
1793 //unused//static uint32 tmpaddr;
1794 uint16 busfunctioncode;
1795 uint8 old_supervisor=reg68k_sr.sr_struct.s;
1796
1797 if (vno==V_LINE15 && romless && (reg68k_pc & 0x00ff0000)==0x00fe0000)
1798 {
1799 if (romless_entry()) return;
1800 }
1801
1802
1803 /*-----------------12/8/2003 9:56PM-----------------
1804 * needs to do this: RA
1805 *
1806 * SSP-2 ->SSP // push FV -- 680010+ only
1807 * Format/Vector Offset -> (SSP)
1808 * SSP-4->4->SSP // push PC
1809 * PC->(SSP)
1810 * SSP-2 ->SSP // push SR
1811 * SR->(SSP)
1812 * Vector Address->PC // PC=Vector
1813 *
1814 * --------------------------------------------------*/
1815
1816
1817 // #ifdef DEBUG
1818 // validate_mmu_segments("reg68k internal_vector");
1819 // #endif
1820
1821 // avoid bus/addr error repeats on multi-operand opcodes...
1822 if (lastclk==cpu68k_clocks && lastvno==vno)
1823 {
1824 DEBUG_LOG(0,"Suppressing internal_vector - VECTOR:%d, oldpc:%08x clk:%016llx",vno,oldpc,cpu68k_clocks);
1825 return;
1826 }
1827
1828 lastclk =cpu68k_clocks; lastvno =vno; lastoldpc =oldpc;
1829
1830
1831 if (!insetjmpland)
1832 {fprintf(buglog,"*** DANGER Entering %s:%s:%d from %s setjmpland - unclean sloppy code*****\n",__FILE__,__FUNCTION__,__LINE__,(insetjmpland ? "inside" : "outside")); fflush(buglog);
1833 reg68k_external_vector(vno,oldpc,addr_error);
1834 return;
1835 }
1836
1837 #ifdef DEBUG
1838
1839 DEBUG_LOG(0,"Entering: internal_vector - VECTOR:%d, addr_err:%08x oldpc:%08x, pc24:%08x, reg68k_pc:%08x",
1840 vno,addr_error,oldpc,pc24,reg68k_pc);
1841
1842 if (oldpc!=reg68k_pc && vno<32)
1843 DEBUG_LOG(0,"DANGER DANGER DANGER oldpc:%08x is not reg68k_pc:%08x, pc24:%08x oldpc24:%08x vector:%d",oldpc, reg68k_pc,pc24,lastpc24,vno);
1844
1845 if (vno==37) lisaos_trap5(); // log LisaOS trap #5 calls by name
1846 printregs(buglog,"irqdone");
1847
1848
1849 #endif
1850
1851 if (avno>0 && avno<8) // If it's an autovector, check the IRQ mask before allowing it to occur.
1852 {
1853 DEBUG_LOG(0,"PC:%08x AutoVector is:%d vector:%d curlevel is %d cpu stop status is:%d",reg68k_pc,avno,vno,curlevel,regs.stop);
1854 if (! (IS_VECTOR_AVAILABLE_INT(avno))) {DEBUG_LOG(0,"Vector requested is not available (INTMASK too low)");return;}
1855 }
1856 else avno=0; // clear avno since it wasn't an autovector - this saves time later on the avno check.
1857
1858
1859 if (!GETSUPERVISOR()) {
1860
1861 SWAPA7withSSP();
1862 SETSUPERVISOR(1);
1863 // 2005.02.01 - removed if statement to force flush here on switch from user to supervisor mode
1864 //if (segment1|segment2) // if we're not in supervisor space already, flush the mmu
1865 {DEBUG_LOG(0,"Turning Supervisor flag on while in internal_vector flushing mmu context=%d s1/s2=%d/%d start=%d\n",context,segment1,segment2,start);
1866 SET_MMU_DIRTY(0xdec0de); mmuflush(0x3000);
1867 DEBUG_LOG(0,"post mmuflush context=%d s1/s2=%d/%d start=%d\n",context,segment1,segment2,start);
1868 }
1869
1870 DEBUG_LOG(5,"S mode change SP:%08x/A7:%08x swapped.",reg68k_regs[15],regs.sp);
1871 lastsflag=reg68k_sr.sr_struct.s; regs.pc = reg68k_pc; regs.sr.sr_int = reg68k_sr.sr_int;
1872 }
1873
1874 // might be a retake of the same addr/bus error on same opcode. doh! ie: when btst is done (read, write) two bus errors can occur
1875 // this is here because the previous run would have set Supervisor, and if it was already set before that, that's fine too
1876 // the problem is the following fetchlong can't be done until mmu context is set, and mmu is flushed, else gremlins
1877
1878
1879 {
1880 abort_opcode=2;
1881 uint32 x=GETVECTOR(vno);
1882
1883 if (x==0xaf) {
1884 ALERT_LOG(0,"Got bus error whilst trying to fetch vector:%d - PC:%d/%08x",vno,context,oldpc);
1885 SET_MMU_DIRTY(0xdec0de); mmuflush(0x3000);
1886 x=GETVECTOR(vno);
1887 if (x==0xaf) ALERT_LOG(0,"Failed again after trying to flush mmu! Something is very wrong!");
1888 ALERT_LOG(0,"Attempting the old fetchlong method, if you don't see the result, we're recursive");
1889 abort_opcode=2;
1890 x=fetchlong(vno*4);
1891 ALERT_LOG(0,"Got back from fetchlong:%08x",x);
1892 }
1893
1894 if (x==0xaf || x==oldpc) {loopy_vector--; abort_opcode=0;//DEBUG_LOG(0,"retake of same vector");
1895 return;}
1896 }
1897 if (abort_opcode==1) {EXIT(782,0,"Doh! got abort_opcode=1 on vector fetch in %s!\n",__FUNCTION__); }
1898 abort_opcode=0;
1899
1900 if (regs.stop && nmi_clk && nmi_pc) {regs.stop=0; nmi_addr_err=0; nmi_clk=0; nmi_pc=0; nmi_stop=0;} // clear flags
1901 else if (regs.stop)
1902 {
1903 DEBUG_LOG(0,"exiting from STOP opcode @%08x - will continue at %08x after ISR handles IRQ:%d.",reg68k_pc,reg68k_pc+4,vno);
1904 oldpc+=4;
1905 regs.stop = 0;
1906 reg68k_pc=oldpc;
1907 pc24=oldpc;
1908 regs.pc = oldpc; regs.sr = reg68k_sr;
1909 }
1910
1911 if (vno==2 || vno==3)
1912 {
1913 if ((InstructionRegister & 0xff00)==0x4a00) {oldpc+=2;}
1914 else if ((InstructionRegister & 0xff00)==0x4e00)
1915 {
1916 if ((InstructionRegister & 0x00f0)==0x00d0) {oldpc+=2;}
1917 else if ((InstructionRegister & 0x00ff)==0x0075) {oldpc+=2; regs.sp+=4;}
1918 else if ((InstructionRegister & 0x00ff)==0x0073) {oldpc+=0;}
1919 else if ((InstructionRegister & 0x00ff)==0x00f9) {oldpc+=2;}
1920 else if ((InstructionRegister & 0x00ff)==0x00b9) {oldpc+=6;}
1921 else if ((InstructionRegister & 0x00ff)==0x00a8) {oldpc+=4;}
1922 else if ((InstructionRegister & 0x00ff)==0x0090) {oldpc+=2;}
1923 else {
1924 ALERT_LOG(0,"\n\n\7*** DANGER *** Unhandled opcode in buserror:%04x\n\n\7",InstructionRegister);
1925 oldpc+=(cpu68k_iibtable[InstructionRegister]->wordlen<<1);
1926 }
1927 }
1928 }
1929
1930 DEBUG_LOG(0,"PUSH PC %08x context:%d",oldpc,context);
1931 A7PUSH_LONG(oldpc); // ? (oldpc+(cpu68k_iibtable[InstructionRegister]->wordlen<<1)) : oldpc);
1932 if (abort_opcode==1) {EXIT(783,0,"Doh! got abort_opcode=1 on push pc %s!\n",__FUNCTION__); }
1933 DEBUG_LOG(0,"PUSH SR %04x context:%d",saved_sr,context);
1934 A7PUSH_WORD(saved_sr);
1935 if (abort_opcode==1) {EXIT(784,0,"Doh! got abort_opcode=1 on push sr in %s!\n",__FUNCTION__); }
1936 // "Short format 0 only four words are to be removed from the top of the stack. SR and PC are loaded from the stack frame."
1937 abort_opcode=0;
1938
1939 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1940 if (vno==2 || vno==3) // PUSH IS IN THIS ORDER: ---> PC,SR,IR,ADDR,BUSFN
1941 { // memerror=(uint16)(( CHK_MMU_TRANS(addr_error) )>>5);
1942
1943 memerror=(uint16)(( addr_error )>>5);
1944
1945 busfunctioncode=CPU_function_code | (CPU_READ_MODE<<4) |1;
1946
1947 cpu68k_clocks+=(116*2); // Addr/Bus // *2 2005.04.13.18:43
1948
1949 DEBUG_LOG(0,"BUS_OR_ADDR: ADDR error:%d at PC:%08x pc24:%08x addr:%08x clk:%016llx - pushing extended exception frame for 68000",
1950 vno,oldpc,pc24,addr_error,cpu68k_clocks);
1951
1952 DEBUG_LOG(0,"PUSH IR:%04x context:%d",InstructionRegister,context); A7PUSH_WORD(InstructionRegister); if (abort_opcode==1) {EXIT(784,0,"Doh! got abort_opcode=1 on push IR in %s!\n",__FUNCTION__); }
1953 DEBUG_LOG(0,"PUSH AE:%08x context:%d",addr_error,context); A7PUSH_LONG(addr_error); if (abort_opcode==1) {EXIT(784,0,"Doh! got abort_opcode=1 on push ADDRC in %s!\n",__FUNCTION__); }
1954 DEBUG_LOG(0,"PUSH BF:%04x context:%d",busfunctioncode,context); A7PUSH_WORD(busfunctioncode); if (abort_opcode==1) {EXIT(784,0,"Doh! got abort_opcode=1 on push BUSFN in %s!\n",__FUNCTION__); }
1955
1956 // prevent autovectors from interrupting BUS/ADDR exception ISR's.
1957 //DEBUG_LOG(0,"Set Mask to 7 for BUS/ADDR Exception");
1958
1959 // this might not be such a good idea
1960 // reg68k_sr.sr_int |=(7 << 8); // no need for &= since we turn on all 3 bits.
1961 regs.pc = reg68k_pc; regs.sr.sr_int = reg68k_sr.sr_int;
1962 }
1963 else // is this an autovector? if so handle that.
1964 { if (avno) //2005.02.02 - code refactoring/consolidation
1965 {
1966 #ifdef DEBUG
1967 if (avno==1 && floppy_FDIR) append_floppy_log("reg68k_int_av_ ***Firing IRQ1 because FDIR is set***\n");
1968 #endif
1969
1970 //reg68k_sr.sr_struct.t = 0; // disable trace bit - no need for it - it's handled below
1971 reg68k_sr.sr_int &= ~0x0700; // clear IRQ Mask
1972 reg68k_sr.sr_int |= (avno<<8); // set IRQ mask to avno
1973 //tmpaddr = reg68k_pc; // not used
1974
1975 DEBUG_LOG(0,"autovector#%d V_AUTO:%08x Vector address: %d * 4 = %08x",vno-V_AUTO+1,V_AUTO,vno,(vno*4));
1976
1977 //abort_opcode=2;reg68k_pc = GETVECTOR(vno); if (abort_opcode==1) {fprintf(buglog,"Doh! got abort_opcode=1 while fetching vector for IRQ!\n"); EXIT(781);}
1978 }
1979
1980 cpu68k_clocks+=87; // IRQ1-7
1981
1982 }
1983
1984
1985 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1986
1987 abort_opcode=2; reg68k_pc=GETVECTOR(vno); // should turn this into vector 15 - spurious IRQ
1988 if (abort_opcode==1) {EXIT(58,0,"Doh got abort_opcode=1 on vector fetch in %s - BYE BYE\n",__FUNCTION__); }
1989 abort_opcode=0;
1990
1991 DEBUG_LOG(0,"SRC: VECTOR IRQ: %s oldpc:%08x -> newpc:%08x A7=%08x SP=%08x Mode pre-IRQ:%s\n",
1992 getvector(vno), oldpc, reg68k_pc,reg68k_regs[15],regs.sp, (old_supervisor ? "Supervisor":"User"));
1993
1994 regs.pending = get_pending_vector(); // not sure that I need this any longer - RA
1995
1996 if (0==reg68k_pc) {debug_on("reg68k_pc=0"); EXIT(59,0,"reg68k_pc got nullified. bye"); }
1997 if (reg68k_pc& 1) LISA_REBOOTED();
1998
1999 reg68k_sr.sr_struct.t=0; // turn off trace on trap.
2000 regs.pc = reg68k_pc; regs.sr.sr_int = reg68k_sr.sr_int; // flush to external copy of regs
2001 DEBUG_LOG(0,"Done with vector fn. regs.pc=%08x reg68k_pc:%08x",regs.pc,reg68k_pc);
2002
2003 abort_opcode=0;
2004 return;
2005 }
2006
2007
2008 #ifdef DEBUG
print_pc_and_regs(char * text)2009 void print_pc_and_regs(char *text)
2010 {
2011 fprintf(buglog,"\n\n%s PC%08x\n",text, reg68k_pc); fflush(buglog);
2012 printregs(buglog,""); fflush(buglog);
2013 }
2014 #endif
2015
lisa_buserror(uint32 addr_error)2016 void lisa_buserror(uint32 addr_error)
2017 {
2018 reg68k_internal_vector(2 ,reg68k_pc, addr_error);
2019 abort_opcode=1;
2020 }
2021
2022 #define LINE(x) DEBUG_LOG(0,"%s:%s:%d %s LINE LOG" ,__FILE__,__FUNCTION__,__LINE__,x); fflush(buglog);
2023
lisa_mmu_exception(uint32 addr_error)2024 void lisa_mmu_exception(uint32 addr_error)
2025 {
2026 char temp[1024];
2027
2028 //20060105 memerror=(uint16)(( CHK_MMU_TRANS(addr_error)+(maxlisaram!=RAM1024K ? 0:RAM512K) )>>5);
2029 memerror=(uint16)(( CHK_MMU_TRANS(addr_error) )>>5);
2030 /*
2031 ALERT_LOG(0,"MMU BUSERROR: IR:%04x @ %d/@%08x :: buserr@addr:%08x -> phys-addr:%08x SOR:%04x SLR:%04x %s",
2032 InstructionRegister,context,reg68k_pc,
2033 addr_error,
2034 CHK_MMU_REGST(addr_error),
2035 mmu[(addr_error & MMUSEGFILT)>>17].sor,
2036 mmu[(addr_error & MMUSEGFILT)>>17].slr,
2037 printslr(temp,1024, mmu[(addr_error & MMUSEGFILT)>>17].slr)
2038 );
2039 */
2040 reg68k_internal_vector(2,reg68k_pc,addr_error);
2041 abort_opcode=1;
2042 }
2043
2044
lisa_addrerror(uint32 addr_error)2045 void lisa_addrerror(uint32 addr_error)
2046 {
2047 ALERT_LOG(0,"Odd Address Exception @%08x PC=%08x clk:%016llx ",addr_error,reg68k_pc,cpu68k_clocks);
2048
2049 DEBUG_LOG(0,"ADDRESS EXCEPTION @%08x PC=%08x",addr_error,reg68k_pc);
2050 reg68k_internal_vector(3,reg68k_pc,addr_error);
2051 abort_opcode=1;
2052 }
2053
2054
2055 // this may only be called from internal land!
lisa_nmi_vector(uint32 addr_error)2056 void lisa_nmi_vector(uint32 addr_error)
2057 {
2058 //unused//uint32 pc_before_nmi=reg68k_pc;
2059
2060 //20060105memerror=(uint16)(( CHK_MMU_TRANS(addr_error)+(maxlisaram!=RAM1024K ? 0:RAM512K) )>>5);
2061 memerror=(uint16)(( CHK_MMU_TRANS(addr_error) )>>5);
2062
2063 // ALERT_LOG(0,"NMI @%08x PC=%08x clk:%016llx memerr latch:%04x - resucitated memlatch:%08x",addr_error,reg68k_pc,cpu68k_clocks,memerror,(uint32)(memerror<<5));
2064 DEBUG_LOG(0,"NMI Exception @%08x (phys:%08x) PC=%08x clk:%016llx ",
2065 addr_error,
2066 (CHK_MMU_TRANS(addr_error)),
2067 reg68k_pc,
2068 cpu68k_clocks);
2069
2070 DEBUG_LOG(0,"NMI ERROR: current state: context:%d seg1:%d seg2:%d start:%d",context,segment1,segment2,start);
2071
2072
2073
2074
2075 nmi_pc = reg68k_pc;
2076 nmi_addr_err= addr_error;
2077 nmi_clk = cpu68k_clocks;
2078 nmi_stop = regs.stop;
2079
2080 regs.stop=1;
2081 return;
2082
2083 ///////////// old dead code////////////////// CODEKARMA CODE KARMA CLEANUP CLEAN UP
2084 return;
2085
2086
2087
2088 #ifdef disabled_2005_02_01
2089 DEBUG_LOG(0,"NMI @%08x pc24==%08x reg68k_pc:%08",addr_error,pc24,reg68k_pc);
2090
2091 if (abort_opcode || last_nmi_error_pc==reg68k_pc) {fprintf(buglog,"suppressing NMI - abort_opcode=1\n"); return;}
2092
2093 //#ifdef DEBUG
2094 if (nmi_error_trap>3 || last_nmi_error_pc==pc24) {EXIT(786,0,"NMI on top of NMI!\n"); };
2095 last_nmi_error_pc=reg68k_pc;
2096 nmi_error_trap++;
2097 //#endif
2098
2099 DEBUG_LOG(0,"*** SRC: Lisa NMI - likely for parity test @ %08x pc=%08x ***",addr_error,reg68k_pc);
2100
2101 // Be sure to change from regs68k.pc to reg68k_pc if changing this to internal!
2102
2103 DEBUG_LOG(0,"int VECTOR 1F (autovector 6 NMI. mem addr:%08x, reg68k_pc:%08x pc24:%08x lastpc24:%08x",addr_error,reg68k_pc,pc24, lastpc24);
2104
2105 // reg68k_external_autovector(7); // using 7 now ???
2106
2107 if (!insetjmpland)
2108 {EXIT(1,0,"*** DANGER Entering %s:%s:%d from %s setjmpland*****\n",__FILE__,__FUNCTION__,__LINE__,(insetjmpland ? "inside" : "outside"));}
2109
2110 reg68k_internal_vector(0x1f, reg68k_pc,addr_error); // 7 is wrong for vector, right for autovector.
2111 abort_opcode=1; // not tru // NMI is an IRQ - DOES not abort an opcode. Just signals after completion of opcode
2112
2113 DEBUG_LOG(0,"Done with external_vector call. reg68k_pc is now %08x, it originally was %08x",reg68k_pc,pc_before_nmi);
2114 if (pc24 & 1) fprintf(buglog,"%s:%s:%d PC24 is now odd!!!!%08x\n",__FILE__,__FUNCTION__,__LINE__,pc24);
2115 //#ifdef DEBUG
2116 nmi_error_trap--;
2117 //#endif
2118 #endif
2119 }
2120
lisa_external_nmi_vector(uint32 addr_error)2121 void lisa_external_nmi_vector(uint32 addr_error)
2122 {
2123 uint32 pc_before_nmi=reg68k_pc;
2124
2125 DEBUG_LOG(0,"External NMI vector @%08x PC=%08x clk:%016llx ",addr_error,reg68k_pc,cpu68k_clocks);
2126
2127 DEBUG_LOG(0,"\n** NMI @%08x pc24==%08x\n",addr_error,pc24);
2128 DEBUG_LOG(0,"NMI extern ");
2129
2130 if (abort_opcode || last_nmi_error_pc==reg68k_pc) {fprintf(buglog,"suppressing NMI - abort_opcode=1\n"); return;}
2131
2132 //#ifdef DEBUG
2133 if (nmi_error_trap>3 || last_nmi_error_pc==pc24) {EXIT(786,0,"NMI on top of NMI!\n"); };
2134 last_nmi_error_pc=reg68k_pc;
2135 nmi_error_trap++;
2136 //#endif
2137
2138 DEBUG_LOG(0,"*** SRC: Lisa NMI - likely for parity test @ %08x pc=%08x ***",addr_error,reg68k_pc);
2139
2140 // Be sure to change from regs68k.pc to reg68k_pc if changing this to internal!
2141
2142 DEBUG_LOG(0,"int VECTOR 1F (autovector 6 NMI. mem addr:%08x, reg68k_pc:%08x pc24:%08x lastpc24:%08x",addr_error,reg68k_pc,pc24, lastpc24);
2143
2144 if (!insetjmpland)
2145 {EXIT(1,0,"*** DANGER Entering %s:%s:%d from %s setjmpland*****\n",__FILE__,__FUNCTION__,__LINE__,(insetjmpland ? "inside" : "outside"));}
2146
2147 // reg68k_external_autovector(7); // using 7 now ???
2148 memerror=(uint16)(( CHK_MMU_TRANS(addr_error) )>>5);
2149 reg68k_external_vector(0x1f, reg68k_pc,addr_error); // 7 is wrong for vector, right for autovector. // DANGER DANGER was pc24
2150 abort_opcode=1; /// VERY STRANGE THAT THIS NEEDS TO BE SO!!! Something odd about this???
2151
2152 DEBUG_LOG(0,"Done with external_vector call. reg68k_pc is now %08x, it originally was %08x",reg68k_pc,pc_before_nmi);
2153 if (reg68k_pc & 1) fprintf(buglog,"%s:%s:%d reg68k_pc is now odd!!!!%08x\n",__FILE__,__FUNCTION__,__LINE__,pc24);
2154 //#ifdef DEBUG
2155 nmi_error_trap--;
2156 //#endif
2157 }
2158
2159
2160