comparison z80_to_x86.c @ 2053:3414a4423de1 segacd

Merge from default
author Michael Pavone <pavone@retrodev.com>
date Sat, 15 Jan 2022 13:15:21 -0800
parents 6fdac0108e47
children 3e591869d135
comparison
equal deleted inserted replaced
1692:5dacaef602a7 2053:3414a4423de1
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)];
2319 } 2325 }
2320 cycles(&opts->gen, num_cycles);//T States: 4 3/4 2326 cycles(&opts->gen, num_cycles);//T States: 4 3/4
2321 if (inst->addr_mode == Z80_IMMED_INDIRECT) { 2327 if (inst->addr_mode == Z80_IMMED_INDIRECT) {
2322 mov_ir(code, inst->immed, opts->gen.scratch1, SZ_B); 2328 mov_ir(code, inst->immed, opts->gen.scratch1, SZ_B);
2323 } else { 2329 } else {
2324 zreg_to_native(opts, Z80_C, opts->gen.scratch2); 2330 zreg_to_native(opts, Z80_C, opts->gen.scratch1);
2325 } 2331 }
2326 call(code, opts->read_io); 2332 call(code, opts->read_io);
2327 if (inst->addr_mode != Z80_IMMED_INDIRECT) { 2333 if (inst->addr_mode != Z80_IMMED_INDIRECT) {
2328 or_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_B); 2334 or_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_B);
2329 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); 2335 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
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
3407 options->gen.handle_cycle_limit_int = code->cur; 3411 options->gen.handle_cycle_limit_int = code->cur;
3408 neg_r(code, options->gen.cycles, SZ_D); 3412 neg_r(code, options->gen.cycles, SZ_D);
3409 add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D); 3413 add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D);
3410 cmp_rdispr(code, options->gen.context_reg, offsetof(z80_context, int_cycle), options->gen.cycles, SZ_D); 3414 cmp_rdispr(code, options->gen.context_reg, offsetof(z80_context, int_cycle), options->gen.cycles, SZ_D);
3411 jcc(code, CC_B, skip_int); 3415 jcc(code, CC_B, skip_int);
3416 //check that we are not past the end of interrupt pulse
3417 cmp_rrdisp(code, options->gen.cycles, options->gen.context_reg, offsetof(z80_context, int_pulse_end), SZ_D);
3418 jcc(code, CC_B, skip_int);
3412 //set limit to the cycle limit 3419 //set limit to the cycle limit
3413 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.scratch2, SZ_D); 3420 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.scratch2, SZ_D);
3414 mov_rrdisp(code, options->gen.scratch2, options->gen.context_reg, offsetof(z80_context, target_cycle), SZ_D); 3421 mov_rrdisp(code, options->gen.scratch2, options->gen.context_reg, offsetof(z80_context, target_cycle), SZ_D);
3415 neg_r(code, options->gen.cycles, SZ_D); 3422 neg_r(code, options->gen.cycles, SZ_D);
3416 add_rr(code, options->gen.scratch2, options->gen.cycles, SZ_D); 3423 add_rr(code, options->gen.scratch2, options->gen.cycles, SZ_D);
3418 cmp_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, int_is_nmi), SZ_B); 3425 cmp_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, int_is_nmi), SZ_B);
3419 code_ptr is_nmi = code->cur + 1; 3426 code_ptr is_nmi = code->cur + 1;
3420 jcc(code, CC_NZ, is_nmi); 3427 jcc(code, CC_NZ, is_nmi);
3421 mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff1), SZ_B); 3428 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); 3429 mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff2), SZ_B);
3430 cycles(&options->gen, 6); //interupt ack cycle
3423 code_ptr after_int_disable = code->cur + 1; 3431 code_ptr after_int_disable = code->cur + 1;
3424 jmp(code, after_int_disable); 3432 jmp(code, after_int_disable);
3425 *is_nmi = code->cur - (is_nmi + 1); 3433 *is_nmi = code->cur - (is_nmi + 1);
3426 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, iff1), options->gen.scratch2, SZ_B); 3434 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); 3435 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); 3436 mov_rrdisp(code, options->gen.scratch2, options->gen.context_reg, offsetof(z80_context, iff2), SZ_B);
3437 cycles(&options->gen, 5); //NMI processing cycles
3429 *after_int_disable = code->cur - (after_int_disable + 1); 3438 *after_int_disable = code->cur - (after_int_disable + 1);
3430 cycles(&options->gen, 7);
3431 //save return address (in scratch1) to Z80 stack 3439 //save return address (in scratch1) to Z80 stack
3432 sub_ir(code, 2, options->regs[Z80_SP], SZ_W); 3440 sub_ir(code, 2, options->regs[Z80_SP], SZ_W);
3433 mov_rr(code, options->regs[Z80_SP], options->gen.scratch2, SZ_W); 3441 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 3442 //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 3443 //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 3459 //dispose of return address as we'll be jumping somewhere else
3452 add_ir(code, 16, RSP, SZ_PTR); 3460 add_ir(code, 16, RSP, SZ_PTR);
3453 cmp_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, int_is_nmi), SZ_B); 3461 cmp_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, int_is_nmi), SZ_B);
3454 is_nmi = code->cur + 1; 3462 is_nmi = code->cur + 1;
3455 jcc(code, CC_NZ, is_nmi); 3463 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 3464 //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 3465 //which is conveniently rst $38, i.e. the same thing that im 1 does
3459 //check interrupt mode 3466 //check interrupt mode
3460 cmp_irdisp(code, 2, options->gen.context_reg, offsetof(z80_context, im), SZ_B); 3467 cmp_irdisp(code, 2, options->gen.context_reg, offsetof(z80_context, im), SZ_B);
3461 code_ptr im2 = code->cur + 1; 3468 code_ptr im2 = code->cur + 1;
3462 jcc(code, CC_Z, im2); 3469 jcc(code, CC_Z, im2);
3463 mov_ir(code, 0x38, options->gen.scratch1, SZ_W); 3470 mov_ir(code, 0x38, options->gen.scratch1, SZ_W);
3471 cycles(&options->gen, 1); //total time for mode 0/1 is 13 t-states
3464 code_ptr after_int_dest = code->cur + 1; 3472 code_ptr after_int_dest = code->cur + 1;
3465 jmp(code, after_int_dest); 3473 jmp(code, after_int_dest);
3466 *im2 = code->cur - (im2 + 1); 3474 *im2 = code->cur - (im2 + 1);
3467 //read vector address from I << 8 | vector 3475 //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); 3476 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; 3507 code->stack_off = tmp_stack_off;
3500 3508
3501 //HACK 3509 //HACK
3502 options->gen.address_size = SZ_D; 3510 options->gen.address_size = SZ_D;
3503 options->gen.address_mask = io_address_mask; 3511 options->gen.address_mask = io_address_mask;
3512 options->gen.bus_cycles = 4;
3504 options->read_io = gen_mem_fun(&options->gen, io_chunks, num_io_chunks, READ_8, NULL); 3513 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); 3514 options->write_io = gen_mem_fun(&options->gen, io_chunks, num_io_chunks, WRITE_8, NULL);
3506 options->gen.address_size = SZ_W; 3515 options->gen.address_size = SZ_W;
3507 options->gen.address_mask = 0xFFFF; 3516 options->gen.address_mask = 0xFFFF;
3517 options->gen.bus_cycles = 3;
3508 3518
3509 options->read_16 = code->cur; 3519 options->read_16 = code->cur;
3510 cycles(&options->gen, 3); 3520 cycles(&options->gen, 3);
3511 check_cycles(&options->gen); 3521 check_cycles(&options->gen);
3512 //TODO: figure out how to handle the extra wait state for word reads to bank area 3522 //TODO: figure out how to handle the extra wait state for word reads to bank area
3592 3602
3593 options->run = (z80_ctx_fun)code->cur; 3603 options->run = (z80_ctx_fun)code->cur;
3594 tmp_stack_off = code->stack_off; 3604 tmp_stack_off = code->stack_off;
3595 save_callee_save_regs(code); 3605 save_callee_save_regs(code);
3596 #ifdef X86_64 3606 #ifdef X86_64
3597 mov_rr(code, RDI, options->gen.context_reg, SZ_PTR); 3607 mov_rr(code, FIRST_ARG_REG, options->gen.context_reg, SZ_PTR);
3598 #else 3608 #else
3599 mov_rdispr(code, RSP, 5 * sizeof(int32_t), options->gen.context_reg, SZ_PTR); 3609 mov_rdispr(code, RSP, 5 * sizeof(int32_t), options->gen.context_reg, SZ_PTR);
3600 #endif 3610 #endif
3601 call(code, options->load_context_scratch); 3611 call(code, options->load_context_scratch);
3602 cmp_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, extra_pc), SZ_PTR); 3612 cmp_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, extra_pc), SZ_PTR);