Mercurial > repos > blastem
comparison z80_to_x86.c @ 1062:779acbfb74d0
Implemented IND and INDR
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 01 Aug 2016 19:24:51 -0700 |
parents | 9b5bb50098d2 |
children | d1eed3b1121c |
comparison
equal
deleted
inserted
replaced
1061:9b5bb50098d2 | 1062:779acbfb74d0 |
---|---|
2459 cycles(&opts->gen, 5); | 2459 cycles(&opts->gen, 5); |
2460 jmp(code, start); | 2460 jmp(code, start); |
2461 *done = code->cur - (done + 1); | 2461 *done = code->cur - (done + 1); |
2462 break; | 2462 break; |
2463 } | 2463 } |
2464 /* | |
2465 case Z80_IND: | 2464 case Z80_IND: |
2466 case Z80_INDR:*/ | 2465 cycles(&opts->gen, num_cycles + 1);//T States: 4, 5 |
2466 //read from IO (C) | |
2467 zreg_to_native(opts, Z80_BC, opts->gen.scratch1); | |
2468 call(code, opts->read_io);//T states 3 | |
2469 | |
2470 //undocumented N flag behavior | |
2471 //flag set on bit 7 of value written | |
2472 bt_ir(code, 7, opts->gen.scratch1, SZ_B); | |
2473 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N)); | |
2474 //save value to be written for flag calculation, as the write func does not | |
2475 //guarantee that it's preserved across the call | |
2476 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_B); | |
2477 | |
2478 //write to (HL) | |
2479 zreg_to_native(opts, Z80_HL, opts->gen.scratch2); | |
2480 call(code, opts->write_8);//T states 4 | |
2481 cycles(&opts->gen, 1); | |
2482 | |
2483 //decrement HL | |
2484 if (opts->regs[Z80_HL] >= 0) { | |
2485 sub_ir(code, 1, opts->regs[Z80_HL], SZ_W); | |
2486 } else { | |
2487 sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B); | |
2488 } | |
2489 mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch1, SZ_B); | |
2490 if (opts->regs[Z80_C] >= 0) { | |
2491 add_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B); | |
2492 } else { | |
2493 add_rdispr(code, opts->gen.context_reg, zr_off(Z80_C), opts->gen.scratch1, SZ_B); | |
2494 } | |
2495 add_ir(code, 1, opts->gen.scratch1, SZ_B); | |
2496 //undocumented C and H flag behavior | |
2497 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | |
2498 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H)); | |
2499 //decrement B | |
2500 if (opts->regs[Z80_B] >= 0) { | |
2501 sub_ir(code, 1, opts->regs[Z80_B], SZ_B); | |
2502 mov_rrdisp(code, opts->regs[Z80_B], opts->gen.context_reg, zf_off(ZF_XY), SZ_B); | |
2503 } else { | |
2504 sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B); | |
2505 } | |
2506 //undocumented Z and S flag behavior, set based on decrement of B | |
2507 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | |
2508 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | |
2509 //crazy undocumented P/V flag behavior | |
2510 and_ir(code, 7, opts->gen.scratch1, SZ_B); | |
2511 if (opts->regs[Z80_B] >= 0) { | |
2512 //deal with silly x86-64 restrictions on *H registers | |
2513 ror_ir(code, 8, opts->regs[Z80_BC], SZ_W); | |
2514 xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B); | |
2515 ror_ir(code, 8, opts->regs[Z80_BC], SZ_W); | |
2516 } else { | |
2517 xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B); | |
2518 } | |
2519 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); | |
2520 break; | |
2521 case Z80_INDR: { | |
2522 cycles(&opts->gen, num_cycles + 1);//T States: 4, 5 | |
2523 //read from IO (C) | |
2524 zreg_to_native(opts, Z80_BC, opts->gen.scratch1); | |
2525 call(code, opts->read_io);//T states 3 | |
2526 | |
2527 //undocumented N flag behavior | |
2528 //flag set on bit 7 of value written | |
2529 bt_ir(code, 7, opts->gen.scratch1, SZ_B); | |
2530 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N)); | |
2531 //save value to be written for flag calculation, as the write func does not | |
2532 //guarantee that it's preserved across the call | |
2533 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_B); | |
2534 | |
2535 //write to (HL) | |
2536 zreg_to_native(opts, Z80_HL, opts->gen.scratch2); | |
2537 call(code, opts->write_8);//T states 4 | |
2538 cycles(&opts->gen, 1); | |
2539 | |
2540 //decrement HL | |
2541 if (opts->regs[Z80_HL] >= 0) { | |
2542 sub_ir(code, 1, opts->regs[Z80_HL], SZ_W); | |
2543 } else { | |
2544 sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B); | |
2545 } | |
2546 mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch1, SZ_B); | |
2547 if (opts->regs[Z80_C] >= 0) { | |
2548 add_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B); | |
2549 } else { | |
2550 add_rdispr(code, opts->gen.context_reg, zr_off(Z80_C), opts->gen.scratch1, SZ_B); | |
2551 } | |
2552 add_ir(code, 1, opts->gen.scratch1, SZ_B); | |
2553 //undocumented C and H flag behavior | |
2554 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | |
2555 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H)); | |
2556 //decrement B | |
2557 if (opts->regs[Z80_B] >= 0) { | |
2558 sub_ir(code, 1, opts->regs[Z80_B], SZ_B); | |
2559 mov_rrdisp(code, opts->regs[Z80_B], opts->gen.context_reg, zf_off(ZF_XY), SZ_B); | |
2560 } else { | |
2561 sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B); | |
2562 } | |
2563 //undocumented Z and S flag behavior, set based on decrement of B | |
2564 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | |
2565 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | |
2566 //crazy undocumented P/V flag behavior | |
2567 and_ir(code, 7, opts->gen.scratch1, SZ_B); | |
2568 if (opts->regs[Z80_B] >= 0) { | |
2569 //deal with silly x86-64 restrictions on *H registers | |
2570 ror_ir(code, 8, opts->regs[Z80_BC], SZ_W); | |
2571 xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B); | |
2572 ror_ir(code, 8, opts->regs[Z80_BC], SZ_W); | |
2573 } else { | |
2574 xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B); | |
2575 } | |
2576 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); | |
2577 if (opts->regs[Z80_B] >= 0) { | |
2578 cmp_ir(code, 0, opts->regs[Z80_B], SZ_B); | |
2579 } else { | |
2580 cmp_irdisp(code, 0, opts->gen.context_reg, zr_off(Z80_B), SZ_B); | |
2581 } | |
2582 code_ptr done = code->cur+1; | |
2583 jcc(code, CC_Z, code->cur+2); | |
2584 cycles(&opts->gen, 5); | |
2585 jmp(code, start); | |
2586 *done = code->cur - (done + 1); | |
2587 break; | |
2588 } | |
2467 case Z80_OUT: | 2589 case Z80_OUT: |
2468 if (inst->reg == Z80_A) { | 2590 if (inst->reg == Z80_A) { |
2469 num_cycles += 3; | 2591 num_cycles += 3; |
2470 } | 2592 } |
2471 cycles(&opts->gen, num_cycles);//T States: 4 3/4 | 2593 cycles(&opts->gen, num_cycles);//T States: 4 3/4 |