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