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: