Mercurial > repos > blastem
comparison z80_to_x86.c @ 505:b7b7a1cab44a
The local clone on my laptop got messed up and some changes had not been pushed. This commit represents the status of the working copy from that clone. It unfortunately contains some changes that I did not intend to commit yet, but this seems like the best option at the moment.
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 06 Jan 2014 22:54:05 -0800 |
parents | 140af5509ce7 |
children | a3b48a57e847 |
comparison
equal
deleted
inserted
replaced
504:7b0df1aaf384 | 505:b7b7a1cab44a |
---|---|
1 /* | 1 /* |
2 Copyright 2013 Michael Pavone | 2 Copyright 2013 Michael Pavone |
3 This file is part of BlastEm. | 3 This file is part of BlastEm. |
4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. | 4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. |
5 */ | 5 */ |
6 #include "z80inst.h" | 6 #include "z80inst.h" |
7 #include "z80_to_x86.h" | 7 #include "z80_to_x86.h" |
8 #include "gen_x86.h" | 8 #include "gen_x86.h" |
307 return offsetof(z80_context, alt_regs) + reg; | 307 return offsetof(z80_context, alt_regs) + reg; |
308 } | 308 } |
309 | 309 |
310 void z80_print_regs_exit(z80_context * context) | 310 void z80_print_regs_exit(z80_context * context) |
311 { | 311 { |
312 printf("A: %X\nB: %X\nC: %X\nD: %X\nE: %X\nHL: %X\nIX: %X\nIY: %X\nSP: %X\n\nIM: %d, IFF1: %d, IFF2: %d\n", | 312 printf("A: %X\nB: %X\nC: %X\nD: %X\nE: %X\nHL: %X\nIX: %X\nIY: %X\nSP: %X\n\nIM: %d, IFF1: %d, IFF2: %d\n", |
313 context->regs[Z80_A], context->regs[Z80_B], context->regs[Z80_C], | 313 context->regs[Z80_A], context->regs[Z80_B], context->regs[Z80_C], |
314 context->regs[Z80_D], context->regs[Z80_E], | 314 context->regs[Z80_D], context->regs[Z80_E], |
315 (context->regs[Z80_H] << 8) | context->regs[Z80_L], | 315 (context->regs[Z80_H] << 8) | context->regs[Z80_L], |
316 (context->regs[Z80_IXH] << 8) | context->regs[Z80_IXL], | 316 (context->regs[Z80_IXH] << 8) | context->regs[Z80_IXL], |
317 (context->regs[Z80_IYH] << 8) | context->regs[Z80_IYL], | 317 (context->regs[Z80_IYH] << 8) | context->regs[Z80_IYL], |
318 context->sp, context->im, context->iff1, context->iff2); | 318 context->sp, context->im, context->iff1, context->iff2); |
319 puts("--Alternate Regs--"); | 319 puts("--Alternate Regs--"); |
320 printf("A: %X\nB: %X\nC: %X\nD: %X\nE: %X\nHL: %X\nIX: %X\nIY: %X\n", | 320 printf("A: %X\nB: %X\nC: %X\nD: %X\nE: %X\nHL: %X\nIX: %X\nIY: %X\n", |
321 context->alt_regs[Z80_A], context->alt_regs[Z80_B], context->alt_regs[Z80_C], | 321 context->alt_regs[Z80_A], context->alt_regs[Z80_B], context->alt_regs[Z80_C], |
322 context->alt_regs[Z80_D], context->alt_regs[Z80_E], | 322 context->alt_regs[Z80_D], context->alt_regs[Z80_E], |
323 (context->alt_regs[Z80_H] << 8) | context->alt_regs[Z80_L], | 323 (context->alt_regs[Z80_H] << 8) | context->alt_regs[Z80_L], |
324 (context->alt_regs[Z80_IXH] << 8) | context->alt_regs[Z80_IXL], | 324 (context->alt_regs[Z80_IXH] << 8) | context->alt_regs[Z80_IXL], |
325 (context->alt_regs[Z80_IYH] << 8) | context->alt_regs[Z80_IYL]); | 325 (context->alt_regs[Z80_IYH] << 8) | context->alt_regs[Z80_IYL]); |
326 exit(0); | 326 exit(0); |
327 } | 327 } |
328 | 328 |
329 uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context, uint16_t address) | 329 uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context, uint16_t address) |
361 if ((inst->reg >= Z80_IXL && inst->reg <= Z80_IYH) || inst->reg == Z80_IX || inst->reg == Z80_IY) { | 361 if ((inst->reg >= Z80_IXL && inst->reg <= Z80_IYH) || inst->reg == Z80_IX || inst->reg == Z80_IY) { |
362 cycles += 4; | 362 cycles += 4; |
363 } | 363 } |
364 dst = zcycles(dst, cycles); | 364 dst = zcycles(dst, cycles); |
365 if (inst->addr_mode & Z80_DIR) { | 365 if (inst->addr_mode & Z80_DIR) { |
366 dst = translate_z80_ea(inst, &dst_op, dst, opts, DONT_READ, MODIFY); | |
366 dst = translate_z80_reg(inst, &src_op, dst, opts); | 367 dst = translate_z80_reg(inst, &src_op, dst, opts); |
367 dst = translate_z80_ea(inst, &dst_op, dst, opts, DONT_READ, MODIFY); | |
368 } else { | 368 } else { |
369 dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); | 369 dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); |
370 dst = translate_z80_reg(inst, &dst_op, dst, opts); | 370 dst = translate_z80_reg(inst, &dst_op, dst, opts); |
371 } | 371 } |
372 if (src_op.mode == MODE_REG_DIRECT) { | 372 if (src_op.mode == MODE_REG_DIRECT) { |
416 dst = zcycles(dst, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 8 : 4); | 416 dst = zcycles(dst, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 8 : 4); |
417 dst = mov_rr(dst, opts->regs[Z80_SP], SCRATCH1, SZ_W); | 417 dst = mov_rr(dst, opts->regs[Z80_SP], SCRATCH1, SZ_W); |
418 dst = call(dst, (uint8_t *)z80_read_word); | 418 dst = call(dst, (uint8_t *)z80_read_word); |
419 dst = add_ir(dst, 2, opts->regs[Z80_SP], SZ_W); | 419 dst = add_ir(dst, 2, opts->regs[Z80_SP], SZ_W); |
420 if (inst->reg == Z80_AF) { | 420 if (inst->reg == Z80_AF) { |
421 | 421 |
422 dst = bt_ir(dst, 0, SCRATCH1, SZ_W); | 422 dst = bt_ir(dst, 0, SCRATCH1, SZ_W); |
423 dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C)); | 423 dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C)); |
424 dst = bt_ir(dst, 1, SCRATCH1, SZ_W); | 424 dst = bt_ir(dst, 1, SCRATCH1, SZ_W); |
425 dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_N)); | 425 dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_N)); |
426 dst = bt_ir(dst, 2, SCRATCH1, SZ_W); | 426 dst = bt_ir(dst, 2, SCRATCH1, SZ_W); |
450 if (inst->addr_mode == Z80_REG) { | 450 if (inst->addr_mode == Z80_REG) { |
451 if(inst->reg == Z80_AF) { | 451 if(inst->reg == Z80_AF) { |
452 dst = mov_rr(dst, opts->regs[Z80_A], SCRATCH1, SZ_B); | 452 dst = mov_rr(dst, opts->regs[Z80_A], SCRATCH1, SZ_B); |
453 dst = mov_rdisp8r(dst, CONTEXT, zar_off(Z80_A), opts->regs[Z80_A], SZ_B); | 453 dst = mov_rdisp8r(dst, CONTEXT, zar_off(Z80_A), opts->regs[Z80_A], SZ_B); |
454 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, zar_off(Z80_A), SZ_B); | 454 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, zar_off(Z80_A), SZ_B); |
455 | 455 |
456 //Flags are currently word aligned, so we can move | 456 //Flags are currently word aligned, so we can move |
457 //them efficiently a word at a time | 457 //them efficiently a word at a time |
458 for (int f = ZF_C; f < ZF_NUM; f+=2) { | 458 for (int f = ZF_C; f < ZF_NUM; f+=2) { |
459 dst = mov_rdisp8r(dst, CONTEXT, zf_off(f), SCRATCH1, SZ_W); | 459 dst = mov_rdisp8r(dst, CONTEXT, zf_off(f), SCRATCH1, SZ_W); |
460 dst = mov_rdisp8r(dst, CONTEXT, zaf_off(f), SCRATCH2, SZ_W); | 460 dst = mov_rdisp8r(dst, CONTEXT, zaf_off(f), SCRATCH2, SZ_W); |
523 dst = call(dst, (uint8_t *)z80_read_byte); | 523 dst = call(dst, (uint8_t *)z80_read_byte); |
524 dst = mov_rr(dst, opts->regs[Z80_DE], SCRATCH2, SZ_W); | 524 dst = mov_rr(dst, opts->regs[Z80_DE], SCRATCH2, SZ_W); |
525 dst = call(dst, (uint8_t *)z80_write_byte); | 525 dst = call(dst, (uint8_t *)z80_write_byte); |
526 dst = add_ir(dst, 1, opts->regs[Z80_DE], SZ_W); | 526 dst = add_ir(dst, 1, opts->regs[Z80_DE], SZ_W); |
527 dst = add_ir(dst, 1, opts->regs[Z80_HL], SZ_W); | 527 dst = add_ir(dst, 1, opts->regs[Z80_HL], SZ_W); |
528 | 528 |
529 dst = sub_ir(dst, 1, opts->regs[Z80_BC], SZ_W); | 529 dst = sub_ir(dst, 1, opts->regs[Z80_BC], SZ_W); |
530 uint8_t * cont = dst+1; | 530 uint8_t * cont = dst+1; |
531 dst = jcc(dst, CC_Z, dst+2); | 531 dst = jcc(dst, CC_Z, dst+2); |
532 dst = zcycles(dst, 7); | 532 dst = zcycles(dst, 7); |
533 //TODO: Figure out what the flag state should be here | 533 //TODO: Figure out what the flag state should be here |
561 dst = call(dst, (uint8_t *)z80_read_byte); | 561 dst = call(dst, (uint8_t *)z80_read_byte); |
562 dst = mov_rr(dst, opts->regs[Z80_DE], SCRATCH2, SZ_W); | 562 dst = mov_rr(dst, opts->regs[Z80_DE], SCRATCH2, SZ_W); |
563 dst = call(dst, (uint8_t *)z80_write_byte); | 563 dst = call(dst, (uint8_t *)z80_write_byte); |
564 dst = sub_ir(dst, 1, opts->regs[Z80_DE], SZ_W); | 564 dst = sub_ir(dst, 1, opts->regs[Z80_DE], SZ_W); |
565 dst = sub_ir(dst, 1, opts->regs[Z80_HL], SZ_W); | 565 dst = sub_ir(dst, 1, opts->regs[Z80_HL], SZ_W); |
566 | 566 |
567 dst = sub_ir(dst, 1, opts->regs[Z80_BC], SZ_W); | 567 dst = sub_ir(dst, 1, opts->regs[Z80_BC], SZ_W); |
568 uint8_t * cont = dst+1; | 568 uint8_t * cont = dst+1; |
569 dst = jcc(dst, CC_Z, dst+2); | 569 dst = jcc(dst, CC_Z, dst+2); |
570 dst = zcycles(dst, 7); | 570 dst = zcycles(dst, 7); |
571 //TODO: Figure out what the flag state should be here | 571 //TODO: Figure out what the flag state should be here |
1160 //TODO: Implement half-carry flag | 1160 //TODO: Implement half-carry flag |
1161 dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B); | 1161 dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B); |
1162 dst = setcc_rdisp8(dst, CC_P, CONTEXT, zf_off(ZF_PV)); | 1162 dst = setcc_rdisp8(dst, CC_P, CONTEXT, zf_off(ZF_PV)); |
1163 dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z)); | 1163 dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z)); |
1164 dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S)); | 1164 dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S)); |
1165 | 1165 |
1166 dst = mov_rr(dst, opts->regs[Z80_HL], SCRATCH2, SZ_W); | 1166 dst = mov_rr(dst, opts->regs[Z80_HL], SCRATCH2, SZ_W); |
1167 dst = ror_ir(dst, 8, SCRATCH1, SZ_W); | 1167 dst = ror_ir(dst, 8, SCRATCH1, SZ_W); |
1168 dst = call(dst, (uint8_t *)z80_write_byte); | 1168 dst = call(dst, (uint8_t *)z80_write_byte); |
1169 break; | 1169 break; |
1170 case Z80_RRD: | 1170 case Z80_RRD: |
1190 //TODO: Implement half-carry flag | 1190 //TODO: Implement half-carry flag |
1191 dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B); | 1191 dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B); |
1192 dst = setcc_rdisp8(dst, CC_P, CONTEXT, zf_off(ZF_PV)); | 1192 dst = setcc_rdisp8(dst, CC_P, CONTEXT, zf_off(ZF_PV)); |
1193 dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z)); | 1193 dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z)); |
1194 dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S)); | 1194 dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S)); |
1195 | 1195 |
1196 dst = mov_rr(dst, opts->regs[Z80_HL], SCRATCH2, SZ_W); | 1196 dst = mov_rr(dst, opts->regs[Z80_HL], SCRATCH2, SZ_W); |
1197 dst = ror_ir(dst, 8, SCRATCH1, SZ_W); | 1197 dst = ror_ir(dst, 8, SCRATCH1, SZ_W); |
1198 dst = call(dst, (uint8_t *)z80_write_byte); | 1198 dst = call(dst, (uint8_t *)z80_write_byte); |
1199 break; | 1199 break; |
1200 case Z80_BIT: { | 1200 case Z80_BIT: { |
1253 dst = ror_ir(dst, 8, src_op.base, SZ_W); | 1253 dst = ror_ir(dst, 8, src_op.base, SZ_W); |
1254 dst = mov_rr(dst, opts->regs[z80_low_reg(inst->ea_reg)], dst_op.base, SZ_B); | 1254 dst = mov_rr(dst, opts->regs[z80_low_reg(inst->ea_reg)], dst_op.base, SZ_B); |
1255 dst = ror_ir(dst, 8, src_op.base, SZ_W); | 1255 dst = ror_ir(dst, 8, src_op.base, SZ_W); |
1256 } else { | 1256 } else { |
1257 dst = mov_rr(dst, opts->regs[inst->ea_reg], dst_op.base, SZ_B); | 1257 dst = mov_rr(dst, opts->regs[inst->ea_reg], dst_op.base, SZ_B); |
1258 } | 1258 } |
1259 } else { | 1259 } else { |
1260 dst = mov_rr(dst, src_op.base, dst_op.base, SZ_B); | 1260 dst = mov_rr(dst, src_op.base, dst_op.base, SZ_B); |
1261 } | 1261 } |
1262 } | 1262 } |
1263 if ((inst->addr_mode & 0x1F) != Z80_REG) { | 1263 if ((inst->addr_mode & 0x1F) != Z80_REG) { |
1295 dst = ror_ir(dst, 8, src_op.base, SZ_W); | 1295 dst = ror_ir(dst, 8, src_op.base, SZ_W); |
1296 dst = mov_rr(dst, opts->regs[z80_low_reg(inst->ea_reg)], dst_op.base, SZ_B); | 1296 dst = mov_rr(dst, opts->regs[z80_low_reg(inst->ea_reg)], dst_op.base, SZ_B); |
1297 dst = ror_ir(dst, 8, src_op.base, SZ_W); | 1297 dst = ror_ir(dst, 8, src_op.base, SZ_W); |
1298 } else { | 1298 } else { |
1299 dst = mov_rr(dst, opts->regs[inst->ea_reg], dst_op.base, SZ_B); | 1299 dst = mov_rr(dst, opts->regs[inst->ea_reg], dst_op.base, SZ_B); |
1300 } | 1300 } |
1301 } else { | 1301 } else { |
1302 dst = mov_rr(dst, src_op.base, dst_op.base, SZ_B); | 1302 dst = mov_rr(dst, src_op.base, dst_op.base, SZ_B); |
1303 } | 1303 } |
1304 } | 1304 } |
1305 if (inst->addr_mode != Z80_REG) { | 1305 if (inst->addr_mode != Z80_REG) { |
1846 char disbuf[80]; | 1846 char disbuf[80]; |
1847 if (z80_get_native_address(context, address)) { | 1847 if (z80_get_native_address(context, address)) { |
1848 return; | 1848 return; |
1849 } | 1849 } |
1850 x86_z80_options * opts = context->options; | 1850 x86_z80_options * opts = context->options; |
1851 uint32_t start_address = address; | |
1851 uint8_t * encoded = NULL, *next; | 1852 uint8_t * encoded = NULL, *next; |
1852 if (address < 0x4000) { | 1853 if (address < 0x4000) { |
1853 encoded = context->mem_pointers[0] + (address & 0x1FFF); | 1854 encoded = context->mem_pointers[0] + (address & 0x1FFF); |
1854 } else if(address >= 0x8000 && context->mem_pointers[1]) { | 1855 } else if(address >= 0x8000 && context->mem_pointers[1]) { |
1855 printf("attempt to translate Z80 code from banked area at address %X\n", address); | 1856 printf("attempt to translate Z80 code from banked area at address %X\n", address); |
1894 z80_map_native_address(context, address, opts->cur_code, next-encoded, after - opts->cur_code); | 1895 z80_map_native_address(context, address, opts->cur_code, next-encoded, after - opts->cur_code); |
1895 opts->cur_code = after; | 1896 opts->cur_code = after; |
1896 address += next-encoded; | 1897 address += next-encoded; |
1897 if (address > 0xFFFF) { | 1898 if (address > 0xFFFF) { |
1898 address &= 0xFFFF; | 1899 address &= 0xFFFF; |
1899 | 1900 |
1900 } else { | 1901 } else { |
1901 encoded = next; | 1902 encoded = next; |
1902 } | 1903 } |
1903 } while (!z80_is_terminal(&inst)); | 1904 } while (!z80_is_terminal(&inst)); |
1904 process_deferred(&opts->deferred, context, (native_addr_func)z80_get_native_address); | 1905 process_deferred(&opts->deferred, context, (native_addr_func)z80_get_native_address); |
1985 dst = alloc_code(&size); | 1986 dst = alloc_code(&size); |
1986 opts->code_end = dst_end = dst + size; | 1987 opts->code_end = dst_end = dst + size; |
1987 } | 1988 } |
1988 bp_stub = dst; | 1989 bp_stub = dst; |
1989 native = call(native, bp_stub); | 1990 native = call(native, bp_stub); |
1990 | 1991 |
1991 //Calculate length of prologue | 1992 //Calculate length of prologue |
1992 dst = z80_check_cycles_int(dst, address); | 1993 dst = z80_check_cycles_int(dst, address); |
1993 int check_int_size = dst-bp_stub; | 1994 int check_int_size = dst-bp_stub; |
1994 dst = bp_stub; | 1995 dst = bp_stub; |
1995 | 1996 |
1996 //Save context and call breakpoint handler | 1997 //Save context and call breakpoint handler |
1997 dst = call(dst, (uint8_t *)z80_save_context); | 1998 dst = call(dst, (uint8_t *)z80_save_context); |
1998 dst = push_r(dst, SCRATCH1); | 1999 dst = push_r(dst, SCRATCH1); |
1999 dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); | 2000 dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); |
2000 dst = mov_rr(dst, SCRATCH1, RSI, SZ_W); | 2001 dst = mov_rr(dst, SCRATCH1, RSI, SZ_W); |