1 #include <stdint.h>
2 #include <stdbool.h>
3 
4 #include "emulator.h"
5 #include "portability.h"
6 #include "dbvz.h"
7 #include "m5XXBus.h"
8 #include "m68k/m68kcpu.h"
9 
10 
11 //memory speed hack, used by cyclone, cyclone always crashed so I decided to just port over one of its biggest speed ups and only use musashi
12 #if M68K_SEPARATE_READS
13 static uintptr_t memBase;
14 
15 
flx68000PcLongJump(uint32_t newPc)16 void flx68000PcLongJump(uint32_t newPc){
17    uintptr_t dataBufferHost;
18    uint32_t dataBufferGuest;
19    uint32_t windowSize;
20 
21    switch(dbvzBankType[DBVZ_START_BANK(newPc)]){
22       case DBVZ_CHIP_A0_ROM:
23          dataBufferHost = (uintptr_t)palmRom;
24          dataBufferGuest = dbvzChipSelects[DBVZ_CHIP_A0_ROM].start;
25          windowSize = dbvzChipSelects[DBVZ_CHIP_A0_ROM].mask + 1;
26          break;
27 
28       case DBVZ_CHIP_DX_RAM:
29          dataBufferHost = (uintptr_t)palmRam;
30          dataBufferGuest = dbvzChipSelects[DBVZ_CHIP_DX_RAM].start;
31          windowSize = dbvzChipSelects[DBVZ_CHIP_DX_RAM].mask + 1;
32          break;
33 
34       case DBVZ_CHIP_REGISTERS:
35          //needed for when EMU_NO_SAFETY is set and a function is run in the launcher
36          dataBufferHost = (uintptr_t)dbvzReg;
37          dataBufferGuest = DBVZ_BANK_ADDRESS(DBVZ_START_BANK(newPc));
38          windowSize = DBVZ_REG_SIZE;
39          break;
40    }
41 
42    memBase = dataBufferHost - dataBufferGuest - windowSize * ((newPc - dataBufferGuest) / windowSize);
43 }
44 
45 //everything must be 16 bit aligned(except 8 bit accesses) due to 68K unaligned access rules,
46 //32 bit reads are 2 16 bit reads because on some platforms 32 bit reads that arnt on 32 bit boundrys will crash the program
47 #if defined(EMU_BIG_ENDIAN)
m68k_read_immediate_16(uint32_t address)48 uint16_t m68k_read_immediate_16(uint32_t address){
49    return *(uint16_t*)(memBase + address);
50 }
m68k_read_immediate_32(uint32_t address)51 uint32_t m68k_read_immediate_32(uint32_t address){
52    return *(uint16_t*)(memBase + address) << 16 | *(uint16_t*)(memBase + address + 2);
53 }
m68k_read_pcrelative_8(uint32_t address)54 uint8_t  m68k_read_pcrelative_8(uint32_t address){
55    return *(uint8_t*)(memBase + address);
56 }
m68k_read_pcrelative_16(uint32_t address)57 uint16_t  m68k_read_pcrelative_16(uint32_t address){
58    return *(uint16_t*)(memBase + address);
59 }
m68k_read_pcrelative_32(uint32_t address)60 uint32_t  m68k_read_pcrelative_32(uint32_t address){
61    return *(uint16_t*)(memBase + address) << 16 | *(uint16_t*)(memBase + address + 2);
62 }
63 #else
m68k_read_immediate_16(uint32_t address)64 uint16_t m68k_read_immediate_16(uint32_t address){
65    return *(uint16_t*)(memBase + address);
66 }
m68k_read_immediate_32(uint32_t address)67 uint32_t m68k_read_immediate_32(uint32_t address){
68    return *(uint16_t*)(memBase + address) << 16 | *(uint16_t*)(memBase + address + 2);
69 }
m68k_read_pcrelative_8(uint32_t address)70 uint8_t  m68k_read_pcrelative_8(uint32_t address){
71    return *(uint8_t*)(memBase + (address ^ 1));
72 }
m68k_read_pcrelative_16(uint32_t address)73 uint16_t  m68k_read_pcrelative_16(uint32_t address){
74    return *(uint16_t*)(memBase + address);
75 }
m68k_read_pcrelative_32(uint32_t address)76 uint32_t  m68k_read_pcrelative_32(uint32_t address){
77    return *(uint16_t*)(memBase + address) << 16 | *(uint16_t*)(memBase + address + 2);
78 }
79 #endif
80 #endif
81 
flx68000Reset(void)82 void flx68000Reset(void){
83    static bool inited = false;
84 
85    if(!inited){
86       m68k_init();
87       m68k_set_cpu_type(M68K_CPU_TYPE_DBVZ);
88 
89       inited = true;
90    }
91 
92    m68k_pulse_reset();
93 }
94 
flx68000StateSize(void)95 uint32_t flx68000StateSize(void){
96    uint32_t size = 0;
97 
98    size += sizeof(uint32_t) * 50;//m68ki_cpu
99 
100    return size;
101 }
102 
flx68000SaveState(uint8_t * data)103 void flx68000SaveState(uint8_t* data){
104    uint32_t offset = 0;
105    uint8_t index;
106 
107    for(index = 0; index < 16; index++){
108       writeStateValue32(data + offset, m68ki_cpu.dar[index]);
109       offset += sizeof(uint32_t);
110    }
111    writeStateValue32(data + offset, m68ki_cpu.ppc);
112    offset += sizeof(uint32_t);
113    writeStateValue32(data + offset, m68ki_cpu.pc);
114    offset += sizeof(uint32_t);
115    for(index = 0; index < 7; index++){
116       writeStateValue32(data + offset, m68ki_cpu.sp[index]);
117       offset += sizeof(uint32_t);
118    }
119    writeStateValue32(data + offset, m68ki_cpu.vbr);
120    offset += sizeof(uint32_t);
121    writeStateValue32(data + offset, m68ki_cpu.sfc);
122    offset += sizeof(uint32_t);
123    writeStateValue32(data + offset, m68ki_cpu.dfc);
124    offset += sizeof(uint32_t);
125    writeStateValue32(data + offset, m68ki_cpu.cacr);
126    offset += sizeof(uint32_t);
127    writeStateValue32(data + offset, m68ki_cpu.caar);
128    offset += sizeof(uint32_t);
129    writeStateValue32(data + offset, m68ki_cpu.ir);
130    offset += sizeof(uint32_t);
131    writeStateValue32(data + offset, m68ki_cpu.t1_flag);
132    offset += sizeof(uint32_t);
133    writeStateValue32(data + offset, m68ki_cpu.t0_flag);
134    offset += sizeof(uint32_t);
135    writeStateValue32(data + offset, m68ki_cpu.s_flag);
136    offset += sizeof(uint32_t);
137    writeStateValue32(data + offset, m68ki_cpu.m_flag);
138    offset += sizeof(uint32_t);
139    writeStateValue32(data + offset, m68ki_cpu.x_flag);
140    offset += sizeof(uint32_t);
141    writeStateValue32(data + offset, m68ki_cpu.n_flag);
142    offset += sizeof(uint32_t);
143    writeStateValue32(data + offset, m68ki_cpu.not_z_flag);
144    offset += sizeof(uint32_t);
145    writeStateValue32(data + offset, m68ki_cpu.v_flag);
146    offset += sizeof(uint32_t);
147    writeStateValue32(data + offset, m68ki_cpu.c_flag);
148    offset += sizeof(uint32_t);
149    writeStateValue32(data + offset, m68ki_cpu.int_mask);
150    offset += sizeof(uint32_t);
151    writeStateValue32(data + offset, m68ki_cpu.int_level);
152    offset += sizeof(uint32_t);
153    writeStateValue32(data + offset, m68ki_cpu.int_cycles);
154    offset += sizeof(uint32_t);
155    writeStateValue32(data + offset, m68ki_cpu.stopped);
156    offset += sizeof(uint32_t);
157    writeStateValue32(data + offset, m68ki_cpu.pref_addr);
158    offset += sizeof(uint32_t);
159    writeStateValue32(data + offset, m68ki_cpu.pref_data);
160    offset += sizeof(uint32_t);
161    writeStateValue32(data + offset, m68ki_cpu.address_mask);
162    offset += sizeof(uint32_t);
163    writeStateValue32(data + offset, m68ki_cpu.sr_mask);
164    offset += sizeof(uint32_t);
165    writeStateValue32(data + offset, m68ki_cpu.instr_mode);
166    offset += sizeof(uint32_t);
167    writeStateValue32(data + offset, m68ki_cpu.run_mode);
168    offset += sizeof(uint32_t);
169 }
170 
flx68000LoadState(uint8_t * data)171 void flx68000LoadState(uint8_t* data){
172    uint32_t offset = 0;
173    uint8_t index;
174 
175    for(index = 0; index < 16; index++){
176       m68ki_cpu.dar[index] = readStateValue32(data + offset);
177       offset += sizeof(uint32_t);
178    }
179    m68ki_cpu.ppc = readStateValue32(data + offset);
180    offset += sizeof(uint32_t);
181    m68ki_cpu.pc = readStateValue32(data + offset);
182    offset += sizeof(uint32_t);
183    for(index = 0; index < 7; index++){
184       m68ki_cpu.sp[index] = readStateValue32(data + offset);
185       offset += sizeof(uint32_t);
186    }
187    m68ki_cpu.vbr = readStateValue32(data + offset);
188    offset += sizeof(uint32_t);
189    m68ki_cpu.sfc = readStateValue32(data + offset);
190    offset += sizeof(uint32_t);
191    m68ki_cpu.dfc = readStateValue32(data + offset);
192    offset += sizeof(uint32_t);
193    m68ki_cpu.cacr = readStateValue32(data + offset);
194    offset += sizeof(uint32_t);
195    m68ki_cpu.caar = readStateValue32(data + offset);
196    offset += sizeof(uint32_t);
197    m68ki_cpu.ir = readStateValue32(data + offset);
198    offset += sizeof(uint32_t);
199    m68ki_cpu.t1_flag = readStateValue32(data + offset);
200    offset += sizeof(uint32_t);
201    m68ki_cpu.t0_flag = readStateValue32(data + offset);
202    offset += sizeof(uint32_t);
203    m68ki_cpu.s_flag = readStateValue32(data + offset);
204    offset += sizeof(uint32_t);
205    m68ki_cpu.m_flag = readStateValue32(data + offset);
206    offset += sizeof(uint32_t);
207    m68ki_cpu.x_flag = readStateValue32(data + offset);
208    offset += sizeof(uint32_t);
209    m68ki_cpu.n_flag = readStateValue32(data + offset);
210    offset += sizeof(uint32_t);
211    m68ki_cpu.not_z_flag = readStateValue32(data + offset);
212    offset += sizeof(uint32_t);
213    m68ki_cpu.v_flag = readStateValue32(data + offset);
214    offset += sizeof(uint32_t);
215    m68ki_cpu.c_flag = readStateValue32(data + offset);
216    offset += sizeof(uint32_t);
217    m68ki_cpu.int_mask = readStateValue32(data + offset);
218    offset += sizeof(uint32_t);
219    m68ki_cpu.int_level = readStateValue32(data + offset);
220    offset += sizeof(uint32_t);
221    m68ki_cpu.int_cycles = readStateValue32(data + offset);
222    offset += sizeof(uint32_t);
223    m68ki_cpu.stopped = readStateValue32(data + offset);
224    offset += sizeof(uint32_t);
225    m68ki_cpu.pref_addr = readStateValue32(data + offset);
226    offset += sizeof(uint32_t);
227    m68ki_cpu.pref_data = readStateValue32(data + offset);
228    offset += sizeof(uint32_t);
229    m68ki_cpu.address_mask = readStateValue32(data + offset);
230    offset += sizeof(uint32_t);
231    m68ki_cpu.sr_mask = readStateValue32(data + offset);
232    offset += sizeof(uint32_t);
233    m68ki_cpu.instr_mode = readStateValue32(data + offset);
234    offset += sizeof(uint32_t);
235    m68ki_cpu.run_mode = readStateValue32(data + offset);
236    offset += sizeof(uint32_t);
237 }
238 
flx68000LoadStateFinished(void)239 void flx68000LoadStateFinished(void){
240 #if M68K_SEPARATE_READS
241    //set PC accessor to the PC from the state
242    flx68000PcLongJump(m68ki_cpu.pc);
243 #endif
244 }
245 
flx68000Execute(int32_t cycles)246 void flx68000Execute(int32_t cycles){
247    m68k_execute(cycles);
248 }
249 
flx68000SetIrq(uint8_t irqLevel)250 void flx68000SetIrq(uint8_t irqLevel){
251    m68k_set_irq(irqLevel);
252 }
253 
flx68000IsSupervisor(void)254 bool flx68000IsSupervisor(void){
255    return !!(m68k_get_reg(NULL, M68K_REG_SR) & 0x2000);
256 }
257 
flx68000BusError(uint32_t address,bool isWrite)258 void flx68000BusError(uint32_t address, bool isWrite){
259 #if !defined(EMU_NO_SAFETY)
260    if(!palmAllowInvalidBehavior){
261       //never call outsize of a 68K opcode, behavior is undefined due to longjmp
262       m68ki_trigger_bus_error(address, isWrite ? MODE_WRITE : MODE_READ, FLAG_S | m68ki_get_address_space());
263    }
264 #endif
265 }
266 
flx68000GetRegister(uint8_t reg)267 uint32_t flx68000GetRegister(uint8_t reg){
268    return m68k_get_reg(NULL, reg);
269 }
270 
flx68000GetPc(void)271 uint32_t flx68000GetPc(void){
272    return m68k_get_reg(NULL, 16);
273 }
274 
flx68000GetStatusRegister(void)275 uint32_t flx68000GetStatusRegister(void){
276    return m68k_get_reg(NULL, 17);
277 }
278 
flx68000ReadArbitraryMemory(uint32_t address,uint8_t size)279 uint64_t flx68000ReadArbitraryMemory(uint32_t address, uint8_t size){
280    uint64_t data = UINT64_MAX;//invalid access
281 
282    //reading from a hardware register FIFO will corrupt it!
283    if(dbvzBankType[DBVZ_START_BANK(address)] != DBVZ_CHIP_NONE){
284       uint16_t m68kSr = m68k_get_reg(NULL, M68K_REG_SR);
285       m68k_set_reg(M68K_REG_SR, 0x2000);//prevent privilege violations
286       switch(size){
287          case 8:
288             data = m68k_read_memory_8(address);
289             break;
290 
291          case 16:
292             data = m68k_read_memory_16(address);
293             break;
294 
295          case 32:
296             data = m68k_read_memory_32(address);
297             break;
298       }
299       m68k_set_reg(M68K_REG_SR, m68kSr);
300    }
301 
302    return data;
303 }
304