Mercurial > repos > blastem
comparison z80_to_x86.c @ 735:539d12fa6a4d
Add a define in both the source and Makefile for enabling logging of z80 instruction address/cycle counts. Fix Z80 in/out instructions to eliminate assumptions about which registers are stored in native regs. Fix read_16 to not corrupt the low byte when the read has to call into a C function.
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 25 May 2015 18:56:22 -0700 |
parents | e21c274a008e |
children | 043393b79e28 |
comparison
equal
deleted
inserted
replaced
734:e21c274a008e | 735:539d12fa6a4d |
---|---|
340 if (!interp) { | 340 if (!interp) { |
341 check_cycles_int(&opts->gen, address); | 341 check_cycles_int(&opts->gen, address); |
342 if (context->breakpoint_flags[address / sizeof(uint8_t)] & (1 << (address % sizeof(uint8_t)))) { | 342 if (context->breakpoint_flags[address / sizeof(uint8_t)] & (1 << (address % sizeof(uint8_t)))) { |
343 zbreakpoint_patch(context, address, start); | 343 zbreakpoint_patch(context, address, start); |
344 } | 344 } |
345 //log_address(&opts->gen, address, "Z80: %X @ %d\n"); | 345 #ifdef Z80_LOG_ADDRESS |
346 log_address(&opts->gen, address, "Z80: %X @ %d\n"); | |
347 #endif | |
346 } | 348 } |
347 switch(inst->op) | 349 switch(inst->op) |
348 { | 350 { |
349 case Z80_LD: | 351 case Z80_LD: |
350 size = z80_size(inst); | 352 size = z80_size(inst); |
1895 } else { | 1897 } else { |
1896 mov_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B); | 1898 mov_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B); |
1897 } | 1899 } |
1898 call(code, opts->read_io); | 1900 call(code, opts->read_io); |
1899 translate_z80_reg(inst, &dst_op, opts); | 1901 translate_z80_reg(inst, &dst_op, opts); |
1900 mov_rr(code, opts->gen.scratch1, dst_op.base, SZ_B); | 1902 if (dst_op.mode == MODE_REG_DIRECT) { |
1903 mov_rr(code, opts->gen.scratch1, dst_op.base, SZ_B); | |
1904 } else { | |
1905 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_B); | |
1906 } | |
1901 z80_save_reg(inst, opts); | 1907 z80_save_reg(inst, opts); |
1902 break; | 1908 break; |
1903 /*case Z80_INI: | 1909 /*case Z80_INI: |
1904 case Z80_INIR: | 1910 case Z80_INIR: |
1905 case Z80_IND: | 1911 case Z80_IND: |
1907 case Z80_OUT: | 1913 case Z80_OUT: |
1908 cycles(&opts->gen, inst->reg == Z80_A ? 7 : 8);//T States: 4 3/4 | 1914 cycles(&opts->gen, inst->reg == Z80_A ? 7 : 8);//T States: 4 3/4 |
1909 if ((inst->addr_mode & 0x1F) == Z80_IMMED_INDIRECT) { | 1915 if ((inst->addr_mode & 0x1F) == Z80_IMMED_INDIRECT) { |
1910 mov_ir(code, inst->immed, opts->gen.scratch2, SZ_B); | 1916 mov_ir(code, inst->immed, opts->gen.scratch2, SZ_B); |
1911 } else { | 1917 } else { |
1918 zreg_to_native(opts, Z80_C, opts->gen.scratch2); | |
1912 mov_rr(code, opts->regs[Z80_C], opts->gen.scratch2, SZ_B); | 1919 mov_rr(code, opts->regs[Z80_C], opts->gen.scratch2, SZ_B); |
1913 } | 1920 } |
1914 translate_z80_reg(inst, &src_op, opts); | 1921 translate_z80_reg(inst, &src_op, opts); |
1915 mov_rr(code, dst_op.base, opts->gen.scratch1, SZ_B); | 1922 if (src_op.mode == MODE_REG_DIRECT) { |
1923 mov_rr(code, src_op.base, opts->gen.scratch1, SZ_B); | |
1924 } else if (src_op.mode == MODE_IMMED) { | |
1925 mov_ir(code, src_op.disp, opts->gen.scratch1, SZ_B); | |
1926 } else { | |
1927 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B); | |
1928 } | |
1916 call(code, opts->write_io); | 1929 call(code, opts->write_io); |
1917 z80_save_reg(inst, opts); | 1930 z80_save_reg(inst, opts); |
1918 break; | 1931 break; |
1919 /*case Z80_OUTI: | 1932 /*case Z80_OUTI: |
1920 case Z80_OTIR: | 1933 case Z80_OTIR: |
2457 //TODO: figure out how to handle the extra wait state for word reads to bank area | 2470 //TODO: figure out how to handle the extra wait state for word reads to bank area |
2458 //may also need special handling to avoid too much stack depth when access is blocked | 2471 //may also need special handling to avoid too much stack depth when access is blocked |
2459 push_r(code, options->gen.scratch1); | 2472 push_r(code, options->gen.scratch1); |
2460 call(code, options->read_8_noinc); | 2473 call(code, options->read_8_noinc); |
2461 mov_rr(code, options->gen.scratch1, options->gen.scratch2, SZ_B); | 2474 mov_rr(code, options->gen.scratch1, options->gen.scratch2, SZ_B); |
2475 #ifndef X86_64 | |
2476 //scratch 2 is a caller save register in 32-bit builds and may be clobbered by something called from the read8 fun | |
2477 mov_rrdisp(code, options->gen.scratch1, options->gen.context_reg, offsetof(z80_context, scratch2), SZ_B); | |
2478 #endif | |
2462 pop_r(code, options->gen.scratch1); | 2479 pop_r(code, options->gen.scratch1); |
2463 add_ir(code, 1, options->gen.scratch1, SZ_W); | 2480 add_ir(code, 1, options->gen.scratch1, SZ_W); |
2464 cycles(&options->gen, 3); | 2481 cycles(&options->gen, 3); |
2465 check_cycles(&options->gen); | 2482 check_cycles(&options->gen); |
2466 call(code, options->read_8_noinc); | 2483 call(code, options->read_8_noinc); |
2467 shl_ir(code, 8, options->gen.scratch1, SZ_W); | 2484 shl_ir(code, 8, options->gen.scratch1, SZ_W); |
2485 #ifdef X86_64 | |
2468 mov_rr(code, options->gen.scratch2, options->gen.scratch1, SZ_B); | 2486 mov_rr(code, options->gen.scratch2, options->gen.scratch1, SZ_B); |
2487 #else | |
2488 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, scratch2), options->gen.scratch1, SZ_B); | |
2489 #endif | |
2469 retn(code); | 2490 retn(code); |
2470 | 2491 |
2471 options->write_16_highfirst = code->cur; | 2492 options->write_16_highfirst = code->cur; |
2472 cycles(&options->gen, 3); | 2493 cycles(&options->gen, 3); |
2473 check_cycles(&options->gen); | 2494 check_cycles(&options->gen); |