Mercurial > repos > blastem
comparison z80_to_x86.c @ 241:2586d49ddd46
Implement EX, EXX and RST in Z80 core
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 28 Apr 2013 13:45:17 -0700 |
parents | a5bea9711a46 |
children | d3b84b2a4397 |
comparison
equal
deleted
inserted
replaced
240:ed540dd4cf2b | 241:2586d49ddd46 |
---|---|
31 if (reg != Z80_UNUSED && reg != Z80_USE_IMMED) { | 31 if (reg != Z80_UNUSED && reg != Z80_USE_IMMED) { |
32 return reg < Z80_BC ? SZ_B : SZ_W; | 32 return reg < Z80_BC ? SZ_B : SZ_W; |
33 } | 33 } |
34 //TODO: Handle any necessary special cases | 34 //TODO: Handle any necessary special cases |
35 return SZ_B; | 35 return SZ_B; |
36 } | |
37 | |
38 uint8_t z80_high_reg(uint8_t reg) | |
39 { | |
40 switch(reg) | |
41 { | |
42 case Z80_C: | |
43 case Z80_BC: | |
44 return Z80_B; | |
45 case Z80_E: | |
46 case Z80_DE: | |
47 return Z80_D; | |
48 case Z80_L: | |
49 case Z80_HL: | |
50 return Z80_H; | |
51 case Z80_IXL: | |
52 case Z80_IX: | |
53 return Z80_IXH; | |
54 case Z80_IYL: | |
55 case Z80_IY: | |
56 return Z80_IYH; | |
57 default: | |
58 return Z80_UNUSED; | |
59 } | |
36 } | 60 } |
37 | 61 |
38 uint8_t * zcycles(uint8_t * dst, uint32_t num_cycles) | 62 uint8_t * zcycles(uint8_t * dst, uint32_t num_cycles) |
39 { | 63 { |
40 return add_ir(dst, num_cycles, ZCYCLES, SZ_D); | 64 return add_ir(dst, num_cycles, ZCYCLES, SZ_D); |
183 uint8_t zf_off(uint8_t flag) | 207 uint8_t zf_off(uint8_t flag) |
184 { | 208 { |
185 return offsetof(z80_context, flags) + flag; | 209 return offsetof(z80_context, flags) + flag; |
186 } | 210 } |
187 | 211 |
212 uint8_t zaf_off(uint8_t flag) | |
213 { | |
214 return offsetof(z80_context, alt_flags) + flag; | |
215 } | |
216 | |
217 uint8_t zar_off(uint8_t reg) | |
218 { | |
219 return offsetof(z80_context, alt_regs) + reg; | |
220 } | |
221 | |
188 void z80_print_regs_exit(z80_context * context) | 222 void z80_print_regs_exit(z80_context * context) |
189 { | 223 { |
190 printf("A: %X\nB: %X\nC: %X\nD: %X\nE: %X\nHL: %X\nIX: %X\nIY: %X\nSP: %X\n", | 224 printf("A: %X\nB: %X\nC: %X\nD: %X\nE: %X\nHL: %X\nIX: %X\nIY: %X\nSP: %X\n", |
191 context->regs[Z80_A], context->regs[Z80_B], context->regs[Z80_C], | 225 context->regs[Z80_A], context->regs[Z80_B], context->regs[Z80_C], |
192 context->regs[Z80_D], context->regs[Z80_E], | 226 context->regs[Z80_D], context->regs[Z80_E], |
193 (context->regs[Z80_H] << 8) | context->regs[Z80_L], | 227 (context->regs[Z80_H] << 8) | context->regs[Z80_L], |
194 (context->regs[Z80_IXH] << 8) | context->regs[Z80_IXL], | 228 (context->regs[Z80_IXH] << 8) | context->regs[Z80_IXL], |
195 (context->regs[Z80_IYH] << 8) | context->regs[Z80_IYL], | 229 (context->regs[Z80_IYH] << 8) | context->regs[Z80_IYL], |
196 context->sp); | 230 context->sp); |
231 puts("--Alternate Regs--"); | |
232 printf("A: %X\nB: %X\nC: %X\nD: %X\nE: %X\nHL: %X\nIX: %X\nIY: %X\n", | |
233 context->alt_regs[Z80_A], context->alt_regs[Z80_B], context->alt_regs[Z80_C], | |
234 context->alt_regs[Z80_D], context->alt_regs[Z80_E], | |
235 (context->alt_regs[Z80_H] << 8) | context->alt_regs[Z80_L], | |
236 (context->alt_regs[Z80_IXH] << 8) | context->alt_regs[Z80_IXL], | |
237 (context->alt_regs[Z80_IYH] << 8) | context->alt_regs[Z80_IYL]); | |
197 exit(0); | 238 exit(0); |
198 } | 239 } |
199 | 240 |
200 uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context, uint16_t address) | 241 uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context, uint16_t address) |
201 { | 242 { |
299 dst = mov_rr(dst, SCRATCH1, src_op.base, SZ_W); | 340 dst = mov_rr(dst, SCRATCH1, src_op.base, SZ_W); |
300 } | 341 } |
301 //no call to save_z80_reg needed since there's no chance we'll use the only | 342 //no call to save_z80_reg needed since there's no chance we'll use the only |
302 //the upper half of a register pair | 343 //the upper half of a register pair |
303 break; | 344 break; |
304 /*case Z80_EX: | 345 case Z80_EX: |
346 if (inst->addr_mode == Z80_REG || inst->reg == Z80_HL) { | |
347 cycles = 4; | |
348 } else { | |
349 cycles = 8; | |
350 } | |
351 dst = zcycles(dst, cycles); | |
352 if (inst->addr_mode == Z80_REG) { | |
353 if(inst->reg == Z80_AF) { | |
354 dst = mov_rr(dst, opts->regs[Z80_A], SCRATCH1, SZ_B); | |
355 dst = mov_rdisp8r(dst, CONTEXT, zar_off(Z80_A), opts->regs[Z80_A], SZ_B); | |
356 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, zar_off(Z80_A), SZ_B); | |
357 | |
358 //Flags are currently word aligned, so we can move | |
359 //them efficiently a word at a time | |
360 for (int f = ZF_C; f < ZF_NUM; f+=2) { | |
361 dst = mov_rdisp8r(dst, CONTEXT, zf_off(f), SCRATCH1, SZ_W); | |
362 dst = mov_rdisp8r(dst, CONTEXT, zaf_off(f), SCRATCH2, SZ_W); | |
363 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, zaf_off(f), SZ_W); | |
364 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, zf_off(f), SZ_W); | |
365 } | |
366 } else { | |
367 dst = xchg_rr(dst, opts->regs[Z80_DE], opts->regs[Z80_HL], SZ_W); | |
368 } | |
369 } else { | |
370 dst = mov_rr(dst, opts->regs[Z80_SP], SCRATCH1, SZ_W); | |
371 dst = call(dst, (uint8_t *)z80_read_byte); | |
372 dst = mov_rr(dst, opts->regs[inst->reg], SCRATCH2, SZ_B); | |
373 dst = mov_rr(dst, SCRATCH1, opts->regs[inst->reg], SZ_B); | |
374 dst = mov_rr(dst, opts->regs[Z80_SP], SCRATCH1, SZ_W); | |
375 dst = call(dst, (uint8_t *)z80_write_byte); | |
376 dst = zcycles(dst, 1); | |
377 uint8_t high_reg = z80_high_reg(inst->reg); | |
378 uint8_t use_reg; | |
379 //even though some of the upper halves can be used directly | |
380 //the limitations on mixing *H regs with the REX prefix | |
381 //prevent us from taking advantage of it | |
382 use_reg = opts->regs[inst->reg]; | |
383 dst = ror_ir(dst, 8, use_reg, SZ_W); | |
384 dst = mov_rr(dst, opts->regs[Z80_SP], SCRATCH1, SZ_W); | |
385 dst = add_ir(dst, 1, SCRATCH1, SZ_W); | |
386 dst = call(dst, (uint8_t *)z80_read_byte); | |
387 dst = mov_rr(dst, use_reg, SCRATCH2, SZ_B); | |
388 dst = mov_rr(dst, SCRATCH1, use_reg, SZ_B); | |
389 dst = mov_rr(dst, opts->regs[Z80_SP], SCRATCH1, SZ_W); | |
390 dst = add_ir(dst, 1, SCRATCH1, SZ_W); | |
391 dst = call(dst, (uint8_t *)z80_write_byte); | |
392 //restore reg to normal rotation | |
393 dst = ror_ir(dst, 8, use_reg, SZ_W); | |
394 dst = zcycles(dst, 2); | |
395 } | |
396 break; | |
305 case Z80_EXX: | 397 case Z80_EXX: |
306 case Z80_LDI: | 398 dst = zcycles(dst, 4); |
399 dst = mov_rr(dst, opts->regs[Z80_BC], SCRATCH1, SZ_W); | |
400 dst = mov_rr(dst, opts->regs[Z80_HL], SCRATCH2, SZ_W); | |
401 dst = mov_rdisp8r(dst, CONTEXT, zar_off(Z80_C), opts->regs[Z80_BC], SZ_W); | |
402 dst = mov_rdisp8r(dst, CONTEXT, zar_off(Z80_L), opts->regs[Z80_HL], SZ_W); | |
403 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, zar_off(Z80_C), SZ_W); | |
404 dst = mov_rrdisp8(dst, SCRATCH2, CONTEXT, zar_off(Z80_L), SZ_W); | |
405 dst = mov_rr(dst, opts->regs[Z80_DE], SCRATCH1, SZ_W); | |
406 dst = mov_rdisp8r(dst, CONTEXT, zar_off(Z80_E), opts->regs[Z80_DE], SZ_W); | |
407 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, zar_off(Z80_E), SZ_W); | |
408 break; | |
409 /*case Z80_LDI: | |
307 case Z80_LDIR: | 410 case Z80_LDIR: |
308 case Z80_LDD: | 411 case Z80_LDD: |
309 case Z80_LDDR: | 412 case Z80_LDDR: |
310 case Z80_CPI: | 413 case Z80_CPI: |
311 case Z80_CPIR: | 414 case Z80_CPIR: |
768 dst = call(dst, (uint8_t *)z80_native_addr); | 871 dst = call(dst, (uint8_t *)z80_native_addr); |
769 dst = jmp_r(dst, SCRATCH1); | 872 dst = jmp_r(dst, SCRATCH1); |
770 break; | 873 break; |
771 /*case Z80_RETCC: | 874 /*case Z80_RETCC: |
772 case Z80_RETI: | 875 case Z80_RETI: |
773 case Z80_RETN: | 876 case Z80_RETN:*/ |
774 case Z80_RST: | 877 case Z80_RST: { |
775 case Z80_IN: | 878 //RST is basically CALL to an address in page 0 |
879 dst = zcycles(dst, 5);//T States: 5 | |
880 dst = sub_ir(dst, 2, opts->regs[Z80_SP], SZ_W); | |
881 dst = mov_ir(dst, address + 3, SCRATCH2, SZ_W); | |
882 dst = mov_rr(dst, opts->regs[Z80_SP], SCRATCH1, SZ_W); | |
883 dst = call(dst, (uint8_t *)z80_write_word_highfirst);//T States: 3, 3 | |
884 uint8_t * call_dst = z80_get_native_address(context, inst->immed); | |
885 if (!call_dst) { | |
886 opts->deferred = defer_address(opts->deferred, inst->immed, dst + 1); | |
887 //fake address to force large displacement | |
888 call_dst = dst + 256; | |
889 } | |
890 dst = jmp(dst, call_dst); | |
891 break; | |
892 } | |
893 /*case Z80_IN: | |
776 case Z80_INI: | 894 case Z80_INI: |
777 case Z80_INIR: | 895 case Z80_INIR: |
778 case Z80_IND: | 896 case Z80_IND: |
779 case Z80_INDR: | 897 case Z80_INDR: |
780 case Z80_OUT: | 898 case Z80_OUT: |