Mercurial > repos > blastem
comparison z80_to_x86.c @ 1769:8fe162bdb038 mame_interp
Merge from default
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 01 Mar 2019 14:17:29 -0800 |
parents | 8a29c250f352 |
children | 37afb9cf58be |
comparison
equal
deleted
inserted
replaced
1768:63256371046f | 1769:8fe162bdb038 |
---|---|
353 if (size != SZ_B) { | 353 if (size != SZ_B) { |
354 num_cycles += 2; | 354 num_cycles += 2; |
355 } | 355 } |
356 if (inst->reg == Z80_I || inst->ea_reg == Z80_I || inst->reg == Z80_R || inst->ea_reg == Z80_R) { | 356 if (inst->reg == Z80_I || inst->ea_reg == Z80_I || inst->reg == Z80_R || inst->ea_reg == Z80_R) { |
357 num_cycles += 1; | 357 num_cycles += 1; |
358 } else if (inst->reg == Z80_USE_IMMED) { | |
359 num_cycles += 3; | |
358 } | 360 } |
359 break; | 361 break; |
360 case Z80_IMMED: | 362 case Z80_IMMED: |
361 num_cycles += size == SZ_B ? 3 : 6; | 363 num_cycles += size == SZ_B ? 3 : 6; |
362 break; | 364 break; |
872 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { | 874 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { |
873 num_cycles += 8; | 875 num_cycles += 8; |
874 } else if(inst->addr_mode == Z80_IMMED) { | 876 } else if(inst->addr_mode == Z80_IMMED) { |
875 num_cycles += 3; | 877 num_cycles += 3; |
876 } else if(z80_size(inst) == SZ_W) { | 878 } else if(z80_size(inst) == SZ_W) { |
877 num_cycles += 4; | 879 num_cycles += 7; |
878 } | 880 } |
879 cycles(&opts->gen, num_cycles); | 881 cycles(&opts->gen, num_cycles); |
880 translate_z80_reg(inst, &dst_op, opts); | 882 translate_z80_reg(inst, &dst_op, opts); |
881 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); | 883 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); |
882 if (dst_op.mode == MODE_REG_DIRECT) { | 884 if (dst_op.mode == MODE_REG_DIRECT) { |
940 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { | 942 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { |
941 num_cycles += 8; | 943 num_cycles += 8; |
942 } else if(inst->addr_mode == Z80_IMMED) { | 944 } else if(inst->addr_mode == Z80_IMMED) { |
943 num_cycles += 3; | 945 num_cycles += 3; |
944 } else if(z80_size(inst) == SZ_W) { | 946 } else if(z80_size(inst) == SZ_W) { |
945 num_cycles += 4; | 947 num_cycles += 7; |
946 } | 948 } |
947 cycles(&opts->gen, num_cycles); | 949 cycles(&opts->gen, num_cycles); |
948 translate_z80_reg(inst, &dst_op, opts); | 950 translate_z80_reg(inst, &dst_op, opts); |
949 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); | 951 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); |
950 if (dst_op.mode == MODE_REG_DIRECT) { | 952 if (dst_op.mode == MODE_REG_DIRECT) { |
1071 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { | 1073 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { |
1072 num_cycles += 8; | 1074 num_cycles += 8; |
1073 } else if(inst->addr_mode == Z80_IMMED) { | 1075 } else if(inst->addr_mode == Z80_IMMED) { |
1074 num_cycles += 3; | 1076 num_cycles += 3; |
1075 } else if(z80_size(inst) == SZ_W) { | 1077 } else if(z80_size(inst) == SZ_W) { |
1076 num_cycles += 4; | 1078 num_cycles += 7; |
1077 } | 1079 } |
1078 cycles(&opts->gen, num_cycles); | 1080 cycles(&opts->gen, num_cycles); |
1079 translate_z80_reg(inst, &dst_op, opts); | 1081 translate_z80_reg(inst, &dst_op, opts); |
1080 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); | 1082 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); |
1081 if (dst_op.mode == MODE_REG_DIRECT) { | 1083 if (dst_op.mode == MODE_REG_DIRECT) { |
1259 break; | 1261 break; |
1260 case Z80_INC: | 1262 case Z80_INC: |
1261 case Z80_DEC: | 1263 case Z80_DEC: |
1262 if(z80_size(inst) == SZ_W) { | 1264 if(z80_size(inst) == SZ_W) { |
1263 num_cycles += 2; | 1265 num_cycles += 2; |
1266 } else if (inst->addr_mode == Z80_REG_INDIRECT) { | |
1267 num_cycles += 1; | |
1268 } else if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { | |
1269 num_cycles += 9; | |
1264 } | 1270 } |
1265 cycles(&opts->gen, num_cycles); | 1271 cycles(&opts->gen, num_cycles); |
1266 translate_z80_reg(inst, &dst_op, opts); | 1272 translate_z80_reg(inst, &dst_op, opts); |
1267 if (dst_op.mode == MODE_UNUSED) { | 1273 if (dst_op.mode == MODE_UNUSED) { |
1268 translate_z80_ea(inst, &dst_op, opts, READ, MODIFY); | 1274 translate_z80_ea(inst, &dst_op, opts, READ, MODIFY); |
1851 ror_ir(code, 8, opts->gen.scratch1, SZ_W); | 1857 ror_ir(code, 8, opts->gen.scratch1, SZ_W); |
1852 call(code, opts->write_8); | 1858 call(code, opts->write_8); |
1853 break; | 1859 break; |
1854 case Z80_BIT: { | 1860 case Z80_BIT: { |
1855 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { | 1861 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { |
1856 num_cycles += 8; | 1862 num_cycles += 4; |
1857 } | 1863 } |
1858 cycles(&opts->gen, num_cycles); | 1864 cycles(&opts->gen, num_cycles); |
1859 uint8_t bit; | 1865 uint8_t bit; |
1860 if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) { | 1866 if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) { |
1861 src_op.base = opts->regs[z80_word_reg(inst->ea_reg)]; | 1867 src_op.base = opts->regs[z80_word_reg(inst->ea_reg)]; |
1912 } | 1918 } |
1913 break; | 1919 break; |
1914 } | 1920 } |
1915 case Z80_SET: { | 1921 case Z80_SET: { |
1916 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { | 1922 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { |
1917 num_cycles += 8; | 1923 num_cycles += 4; |
1918 } | 1924 } |
1919 cycles(&opts->gen, num_cycles); | 1925 cycles(&opts->gen, num_cycles); |
1920 uint8_t bit; | 1926 uint8_t bit; |
1921 if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) { | 1927 if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) { |
1922 src_op.base = opts->regs[z80_word_reg(inst->ea_reg)]; | 1928 src_op.base = opts->regs[z80_word_reg(inst->ea_reg)]; |
1981 } | 1987 } |
1982 break; | 1988 break; |
1983 } | 1989 } |
1984 case Z80_RES: { | 1990 case Z80_RES: { |
1985 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { | 1991 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { |
1986 num_cycles += 8; | 1992 num_cycles += 4; |
1987 } | 1993 } |
1988 cycles(&opts->gen, num_cycles); | 1994 cycles(&opts->gen, num_cycles); |
1989 uint8_t bit; | 1995 uint8_t bit; |
1990 if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) { | 1996 if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) { |
1991 src_op.base = opts->regs[z80_word_reg(inst->ea_reg)]; | 1997 src_op.base = opts->regs[z80_word_reg(inst->ea_reg)]; |
2591 jmp(code, start); | 2597 jmp(code, start); |
2592 *done = code->cur - (done + 1); | 2598 *done = code->cur - (done + 1); |
2593 break; | 2599 break; |
2594 } | 2600 } |
2595 case Z80_OUT: | 2601 case Z80_OUT: |
2596 if (inst->reg == Z80_A) { | 2602 if (inst->addr_mode == Z80_IMMED_INDIRECT) { |
2597 num_cycles += 3; | 2603 num_cycles += 3; |
2598 } | 2604 } |
2599 cycles(&opts->gen, num_cycles);//T States: 4 3/4 | 2605 cycles(&opts->gen, num_cycles);//T States: 4 3/4 |
2600 if ((inst->addr_mode & 0x1F) == Z80_IMMED_INDIRECT) { | 2606 if ((inst->addr_mode & 0x1F) == Z80_IMMED_INDIRECT) { |
2601 mov_ir(code, inst->immed, opts->gen.scratch2, SZ_B); | 2607 mov_ir(code, inst->immed, opts->gen.scratch2, SZ_B); |
2656 xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B); | 2662 xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B); |
2657 } | 2663 } |
2658 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); | 2664 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); |
2659 break; | 2665 break; |
2660 case Z80_OTIR: { | 2666 case Z80_OTIR: { |
2661 code_ptr start = code->cur; | |
2662 cycles(&opts->gen, num_cycles + 1);//T States: 4, 5 | 2667 cycles(&opts->gen, num_cycles + 1);//T States: 4, 5 |
2663 //read from (HL) | 2668 //read from (HL) |
2664 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); | 2669 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); |
2665 call(code, opts->read_8);//T states 3 | 2670 call(code, opts->read_8);//T states 3 |
2666 //undocumented N flag behavior | 2671 //undocumented N flag behavior |
2756 xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B); | 2761 xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B); |
2757 } | 2762 } |
2758 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); | 2763 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); |
2759 break; | 2764 break; |
2760 case Z80_OTDR: { | 2765 case Z80_OTDR: { |
2761 code_ptr start = code->cur; | |
2762 cycles(&opts->gen, num_cycles + 1);//T States: 4, 5 | 2766 cycles(&opts->gen, num_cycles + 1);//T States: 4, 5 |
2763 //read from (HL) | 2767 //read from (HL) |
2764 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); | 2768 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); |
2765 call(code, opts->read_8);//T states 3 | 2769 call(code, opts->read_8);//T states 3 |
2766 //undocumented N flag behavior | 2770 //undocumented N flag behavior |
3418 cmp_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, int_is_nmi), SZ_B); | 3422 cmp_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, int_is_nmi), SZ_B); |
3419 code_ptr is_nmi = code->cur + 1; | 3423 code_ptr is_nmi = code->cur + 1; |
3420 jcc(code, CC_NZ, is_nmi); | 3424 jcc(code, CC_NZ, is_nmi); |
3421 mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff1), SZ_B); | 3425 mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff1), SZ_B); |
3422 mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff2), SZ_B); | 3426 mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff2), SZ_B); |
3427 cycles(&options->gen, 6); //interupt ack cycle | |
3423 code_ptr after_int_disable = code->cur + 1; | 3428 code_ptr after_int_disable = code->cur + 1; |
3424 jmp(code, after_int_disable); | 3429 jmp(code, after_int_disable); |
3425 *is_nmi = code->cur - (is_nmi + 1); | 3430 *is_nmi = code->cur - (is_nmi + 1); |
3426 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, iff1), options->gen.scratch2, SZ_B); | 3431 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, iff1), options->gen.scratch2, SZ_B); |
3427 mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff1), SZ_B); | 3432 mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff1), SZ_B); |
3428 mov_rrdisp(code, options->gen.scratch2, options->gen.context_reg, offsetof(z80_context, iff2), SZ_B); | 3433 mov_rrdisp(code, options->gen.scratch2, options->gen.context_reg, offsetof(z80_context, iff2), SZ_B); |
3434 cycles(&options->gen, 5); //NMI processing cycles | |
3429 *after_int_disable = code->cur - (after_int_disable + 1); | 3435 *after_int_disable = code->cur - (after_int_disable + 1); |
3430 cycles(&options->gen, 7); | |
3431 //save return address (in scratch1) to Z80 stack | 3436 //save return address (in scratch1) to Z80 stack |
3432 sub_ir(code, 2, options->regs[Z80_SP], SZ_W); | 3437 sub_ir(code, 2, options->regs[Z80_SP], SZ_W); |
3433 mov_rr(code, options->regs[Z80_SP], options->gen.scratch2, SZ_W); | 3438 mov_rr(code, options->regs[Z80_SP], options->gen.scratch2, SZ_W); |
3434 //we need to do check_cycles and cycles outside of the write_8 call | 3439 //we need to do check_cycles and cycles outside of the write_8 call |
3435 //so that the stack has the correct depth if we need to return to C | 3440 //so that the stack has the correct depth if we need to return to C |
3451 //dispose of return address as we'll be jumping somewhere else | 3456 //dispose of return address as we'll be jumping somewhere else |
3452 add_ir(code, 16, RSP, SZ_PTR); | 3457 add_ir(code, 16, RSP, SZ_PTR); |
3453 cmp_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, int_is_nmi), SZ_B); | 3458 cmp_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, int_is_nmi), SZ_B); |
3454 is_nmi = code->cur + 1; | 3459 is_nmi = code->cur + 1; |
3455 jcc(code, CC_NZ, is_nmi); | 3460 jcc(code, CC_NZ, is_nmi); |
3456 cycles(&options->gen, 6); //interupt ack cycle | |
3457 //TODO: Support interrupt mode 0, not needed for Genesis sit it seems to read $FF during intack | 3461 //TODO: Support interrupt mode 0, not needed for Genesis sit it seems to read $FF during intack |
3458 //which is conveniently rst $38, i.e. the same thing that im 1 does | 3462 //which is conveniently rst $38, i.e. the same thing that im 1 does |
3459 //check interrupt mode | 3463 //check interrupt mode |
3460 cmp_irdisp(code, 2, options->gen.context_reg, offsetof(z80_context, im), SZ_B); | 3464 cmp_irdisp(code, 2, options->gen.context_reg, offsetof(z80_context, im), SZ_B); |
3461 code_ptr im2 = code->cur + 1; | 3465 code_ptr im2 = code->cur + 1; |
3462 jcc(code, CC_Z, im2); | 3466 jcc(code, CC_Z, im2); |
3463 mov_ir(code, 0x38, options->gen.scratch1, SZ_W); | 3467 mov_ir(code, 0x38, options->gen.scratch1, SZ_W); |
3468 cycles(&options->gen, 1); //total time for mode 0/1 is 13 t-states | |
3464 code_ptr after_int_dest = code->cur + 1; | 3469 code_ptr after_int_dest = code->cur + 1; |
3465 jmp(code, after_int_dest); | 3470 jmp(code, after_int_dest); |
3466 *im2 = code->cur - (im2 + 1); | 3471 *im2 = code->cur - (im2 + 1); |
3467 //read vector address from I << 8 | vector | 3472 //read vector address from I << 8 | vector |
3468 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, regs) + Z80_I, options->gen.scratch1, SZ_B); | 3473 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, regs) + Z80_I, options->gen.scratch1, SZ_B); |
3499 code->stack_off = tmp_stack_off; | 3504 code->stack_off = tmp_stack_off; |
3500 | 3505 |
3501 //HACK | 3506 //HACK |
3502 options->gen.address_size = SZ_D; | 3507 options->gen.address_size = SZ_D; |
3503 options->gen.address_mask = io_address_mask; | 3508 options->gen.address_mask = io_address_mask; |
3509 options->gen.bus_cycles = 4; | |
3504 options->read_io = gen_mem_fun(&options->gen, io_chunks, num_io_chunks, READ_8, NULL); | 3510 options->read_io = gen_mem_fun(&options->gen, io_chunks, num_io_chunks, READ_8, NULL); |
3505 options->write_io = gen_mem_fun(&options->gen, io_chunks, num_io_chunks, WRITE_8, NULL); | 3511 options->write_io = gen_mem_fun(&options->gen, io_chunks, num_io_chunks, WRITE_8, NULL); |
3506 options->gen.address_size = SZ_W; | 3512 options->gen.address_size = SZ_W; |
3507 options->gen.address_mask = 0xFFFF; | 3513 options->gen.address_mask = 0xFFFF; |
3514 options->gen.bus_cycles = 3; | |
3508 | 3515 |
3509 options->read_16 = code->cur; | 3516 options->read_16 = code->cur; |
3510 cycles(&options->gen, 3); | 3517 cycles(&options->gen, 3); |
3511 check_cycles(&options->gen); | 3518 check_cycles(&options->gen); |
3512 //TODO: figure out how to handle the extra wait state for word reads to bank area | 3519 //TODO: figure out how to handle the extra wait state for word reads to bank area |