Mercurial > repos > blastem
comparison z80_to_x86.c @ 2210:3e591869d135
SP should be set to $FFFF on reset
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 28 Aug 2022 14:32:17 -0700 |
parents | 6fdac0108e47 |
children | c97609fe8315 |
comparison
equal
deleted
inserted
replaced
2209:92dc3e24f309 | 2210:3e591869d135 |
---|---|
1335 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); | 1335 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); |
1336 code_ptr corf_low = code->cur + 1; | 1336 code_ptr corf_low = code->cur + 1; |
1337 jcc(code, CC_NZ, code->cur+2); | 1337 jcc(code, CC_NZ, code->cur+2); |
1338 code_ptr no_corf_low = code->cur + 1; | 1338 code_ptr no_corf_low = code->cur + 1; |
1339 jmp(code, code->cur + 2); | 1339 jmp(code, code->cur + 2); |
1340 | 1340 |
1341 *corf_low_range = code->cur - (corf_low_range + 1); | 1341 *corf_low_range = code->cur - (corf_low_range + 1); |
1342 mov_ir(code, 0x90, opts->gen.scratch1, SZ_B); | 1342 mov_ir(code, 0x90, opts->gen.scratch1, SZ_B); |
1343 *corf_low = code->cur - (corf_low + 1); | 1343 *corf_low = code->cur - (corf_low + 1); |
1344 mov_ir(code, 0x06, opts->gen.scratch2, SZ_B); | 1344 mov_ir(code, 0x06, opts->gen.scratch2, SZ_B); |
1345 | 1345 |
1346 *no_corf_low = code->cur - (no_corf_low + 1); | 1346 *no_corf_low = code->cur - (no_corf_low + 1); |
1347 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); | 1347 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); |
1348 code_ptr corf_high = code->cur+1; | 1348 code_ptr corf_high = code->cur+1; |
1349 jcc(code, CC_NZ, code->cur+2); | 1349 jcc(code, CC_NZ, code->cur+2); |
1350 cmp_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B); | 1350 cmp_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B); |
1352 jcc(code, CC_C, code->cur+2); | 1352 jcc(code, CC_C, code->cur+2); |
1353 *corf_high = code->cur - (corf_high + 1); | 1353 *corf_high = code->cur - (corf_high + 1); |
1354 or_ir(code, 0x60, opts->gen.scratch2, SZ_B); | 1354 or_ir(code, 0x60, opts->gen.scratch2, SZ_B); |
1355 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B); | 1355 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B); |
1356 *no_corf_high = code->cur - (no_corf_high + 1); | 1356 *no_corf_high = code->cur - (no_corf_high + 1); |
1357 | 1357 |
1358 mov_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B); | 1358 mov_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B); |
1359 xor_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_B); | 1359 xor_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_B); |
1360 | 1360 |
1361 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1361 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1362 code_ptr not_sub = code->cur+1; | 1362 code_ptr not_sub = code->cur+1; |
1363 jcc(code, CC_Z, code->cur+2); | 1363 jcc(code, CC_Z, code->cur+2); |
1364 neg_r(code, opts->gen.scratch2, SZ_B); | 1364 neg_r(code, opts->gen.scratch2, SZ_B); |
1365 *not_sub = code->cur - (not_sub + 1); | 1365 *not_sub = code->cur - (not_sub + 1); |
1366 | 1366 |
1367 add_rr(code, opts->gen.scratch2, opts->regs[Z80_A], SZ_B); | 1367 add_rr(code, opts->gen.scratch2, opts->regs[Z80_A], SZ_B); |
1368 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | 1368 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); |
1369 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | 1369 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); |
1370 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); | 1370 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); |
1371 xor_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B); | 1371 xor_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B); |
1894 } | 1894 } |
1895 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | 1895 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); |
1896 } else { | 1896 } else { |
1897 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B); | 1897 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B); |
1898 } | 1898 } |
1899 | 1899 |
1900 if ((inst->addr_mode & 0x1F) == Z80_REG) { | 1900 if ((inst->addr_mode & 0x1F) == Z80_REG) { |
1901 if (src_op.mode == MODE_REG_DIRECT) { | 1901 if (src_op.mode == MODE_REG_DIRECT) { |
1902 if (size == SZ_W) { | 1902 if (size == SZ_W) { |
1903 mov_rr(code, src_op.base, opts->gen.scratch1, SZ_W); | 1903 mov_rr(code, src_op.base, opts->gen.scratch1, SZ_W); |
1904 shr_ir(code, 8, opts->gen.scratch1, SZ_W); | 1904 shr_ir(code, 8, opts->gen.scratch1, SZ_W); |
2351 case Z80_INI: | 2351 case Z80_INI: |
2352 cycles(&opts->gen, num_cycles + 1);//T States: 4, 5 | 2352 cycles(&opts->gen, num_cycles + 1);//T States: 4, 5 |
2353 //read from IO (C) | 2353 //read from IO (C) |
2354 zreg_to_native(opts, Z80_BC, opts->gen.scratch1); | 2354 zreg_to_native(opts, Z80_BC, opts->gen.scratch1); |
2355 call(code, opts->read_io);//T states 3 | 2355 call(code, opts->read_io);//T states 3 |
2356 | 2356 |
2357 //undocumented N flag behavior | 2357 //undocumented N flag behavior |
2358 //flag set on bit 7 of value written | 2358 //flag set on bit 7 of value written |
2359 bt_ir(code, 7, opts->gen.scratch1, SZ_B); | 2359 bt_ir(code, 7, opts->gen.scratch1, SZ_B); |
2360 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N)); | 2360 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N)); |
2361 //save value to be written for flag calculation, as the write func does not | 2361 //save value to be written for flag calculation, as the write func does not |
2362 //guarantee that it's preserved across the call | 2362 //guarantee that it's preserved across the call |
2363 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_B); | 2363 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_B); |
2364 | 2364 |
2365 //write to (HL) | 2365 //write to (HL) |
2366 zreg_to_native(opts, Z80_HL, opts->gen.scratch2); | 2366 zreg_to_native(opts, Z80_HL, opts->gen.scratch2); |
2367 call(code, opts->write_8);//T states 4 | 2367 call(code, opts->write_8);//T states 4 |
2368 cycles(&opts->gen, 1); | 2368 cycles(&opts->gen, 1); |
2369 | 2369 |
2370 //increment HL | 2370 //increment HL |
2371 if (opts->regs[Z80_HL] >= 0) { | 2371 if (opts->regs[Z80_HL] >= 0) { |
2372 add_ir(code, 1, opts->regs[Z80_HL], SZ_W); | 2372 add_ir(code, 1, opts->regs[Z80_HL], SZ_W); |
2373 } else { | 2373 } else { |
2374 add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B); | 2374 add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B); |
2408 case Z80_INIR: { | 2408 case Z80_INIR: { |
2409 cycles(&opts->gen, num_cycles + 1);//T States: 4, 5 | 2409 cycles(&opts->gen, num_cycles + 1);//T States: 4, 5 |
2410 //read from IO (C) | 2410 //read from IO (C) |
2411 zreg_to_native(opts, Z80_BC, opts->gen.scratch1); | 2411 zreg_to_native(opts, Z80_BC, opts->gen.scratch1); |
2412 call(code, opts->read_io);//T states 3 | 2412 call(code, opts->read_io);//T states 3 |
2413 | 2413 |
2414 //undocumented N flag behavior | 2414 //undocumented N flag behavior |
2415 //flag set on bit 7 of value written | 2415 //flag set on bit 7 of value written |
2416 bt_ir(code, 7, opts->gen.scratch1, SZ_B); | 2416 bt_ir(code, 7, opts->gen.scratch1, SZ_B); |
2417 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N)); | 2417 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N)); |
2418 //save value to be written for flag calculation, as the write func does not | 2418 //save value to be written for flag calculation, as the write func does not |
2419 //guarantee that it's preserved across the call | 2419 //guarantee that it's preserved across the call |
2420 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_B); | 2420 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_B); |
2421 | 2421 |
2422 //write to (HL) | 2422 //write to (HL) |
2423 zreg_to_native(opts, Z80_HL, opts->gen.scratch2); | 2423 zreg_to_native(opts, Z80_HL, opts->gen.scratch2); |
2424 call(code, opts->write_8);//T states 4 | 2424 call(code, opts->write_8);//T states 4 |
2425 cycles(&opts->gen, 1); | 2425 cycles(&opts->gen, 1); |
2426 | 2426 |
2427 //increment HL | 2427 //increment HL |
2428 if (opts->regs[Z80_HL] >= 0) { | 2428 if (opts->regs[Z80_HL] >= 0) { |
2429 add_ir(code, 1, opts->regs[Z80_HL], SZ_W); | 2429 add_ir(code, 1, opts->regs[Z80_HL], SZ_W); |
2430 } else { | 2430 } else { |
2431 add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B); | 2431 add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B); |
2476 case Z80_IND: | 2476 case Z80_IND: |
2477 cycles(&opts->gen, num_cycles + 1);//T States: 4, 5 | 2477 cycles(&opts->gen, num_cycles + 1);//T States: 4, 5 |
2478 //read from IO (C) | 2478 //read from IO (C) |
2479 zreg_to_native(opts, Z80_BC, opts->gen.scratch1); | 2479 zreg_to_native(opts, Z80_BC, opts->gen.scratch1); |
2480 call(code, opts->read_io);//T states 3 | 2480 call(code, opts->read_io);//T states 3 |
2481 | 2481 |
2482 //undocumented N flag behavior | 2482 //undocumented N flag behavior |
2483 //flag set on bit 7 of value written | 2483 //flag set on bit 7 of value written |
2484 bt_ir(code, 7, opts->gen.scratch1, SZ_B); | 2484 bt_ir(code, 7, opts->gen.scratch1, SZ_B); |
2485 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N)); | 2485 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N)); |
2486 //save value to be written for flag calculation, as the write func does not | 2486 //save value to be written for flag calculation, as the write func does not |
2487 //guarantee that it's preserved across the call | 2487 //guarantee that it's preserved across the call |
2488 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_B); | 2488 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_B); |
2489 | 2489 |
2490 //write to (HL) | 2490 //write to (HL) |
2491 zreg_to_native(opts, Z80_HL, opts->gen.scratch2); | 2491 zreg_to_native(opts, Z80_HL, opts->gen.scratch2); |
2492 call(code, opts->write_8);//T states 4 | 2492 call(code, opts->write_8);//T states 4 |
2493 cycles(&opts->gen, 1); | 2493 cycles(&opts->gen, 1); |
2494 | 2494 |
2495 //decrement HL | 2495 //decrement HL |
2496 if (opts->regs[Z80_HL] >= 0) { | 2496 if (opts->regs[Z80_HL] >= 0) { |
2497 sub_ir(code, 1, opts->regs[Z80_HL], SZ_W); | 2497 sub_ir(code, 1, opts->regs[Z80_HL], SZ_W); |
2498 } else { | 2498 } else { |
2499 sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B); | 2499 sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B); |
2533 case Z80_INDR: { | 2533 case Z80_INDR: { |
2534 cycles(&opts->gen, num_cycles + 1);//T States: 4, 5 | 2534 cycles(&opts->gen, num_cycles + 1);//T States: 4, 5 |
2535 //read from IO (C) | 2535 //read from IO (C) |
2536 zreg_to_native(opts, Z80_BC, opts->gen.scratch1); | 2536 zreg_to_native(opts, Z80_BC, opts->gen.scratch1); |
2537 call(code, opts->read_io);//T states 3 | 2537 call(code, opts->read_io);//T states 3 |
2538 | 2538 |
2539 //undocumented N flag behavior | 2539 //undocumented N flag behavior |
2540 //flag set on bit 7 of value written | 2540 //flag set on bit 7 of value written |
2541 bt_ir(code, 7, opts->gen.scratch1, SZ_B); | 2541 bt_ir(code, 7, opts->gen.scratch1, SZ_B); |
2542 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N)); | 2542 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N)); |
2543 //save value to be written for flag calculation, as the write func does not | 2543 //save value to be written for flag calculation, as the write func does not |
2544 //guarantee that it's preserved across the call | 2544 //guarantee that it's preserved across the call |
2545 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_B); | 2545 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_B); |
2546 | 2546 |
2547 //write to (HL) | 2547 //write to (HL) |
2548 zreg_to_native(opts, Z80_HL, opts->gen.scratch2); | 2548 zreg_to_native(opts, Z80_HL, opts->gen.scratch2); |
2549 call(code, opts->write_8);//T states 4 | 2549 call(code, opts->write_8);//T states 4 |
2550 cycles(&opts->gen, 1); | 2550 cycles(&opts->gen, 1); |
2551 | 2551 |
2552 //decrement HL | 2552 //decrement HL |
2553 if (opts->regs[Z80_HL] >= 0) { | 2553 if (opts->regs[Z80_HL] >= 0) { |
2554 sub_ir(code, 1, opts->regs[Z80_HL], SZ_W); | 2554 sub_ir(code, 1, opts->regs[Z80_HL], SZ_W); |
2555 } else { | 2555 } else { |
2556 sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B); | 2556 sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B); |
2625 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); | 2625 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); |
2626 call(code, opts->read_8);//T states 3 | 2626 call(code, opts->read_8);//T states 3 |
2627 //undocumented N flag behavior | 2627 //undocumented N flag behavior |
2628 //flag set on bit 7 of value written | 2628 //flag set on bit 7 of value written |
2629 bt_ir(code, 7, opts->gen.scratch1, SZ_B); | 2629 bt_ir(code, 7, opts->gen.scratch1, SZ_B); |
2630 setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_N)); | 2630 setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_N)); |
2631 //write to IO (C) | 2631 //write to IO (C) |
2632 zreg_to_native(opts, Z80_C, opts->gen.scratch2); | 2632 zreg_to_native(opts, Z80_C, opts->gen.scratch2); |
2633 call(code, opts->write_io);//T states 4 | 2633 call(code, opts->write_io);//T states 4 |
2634 //increment HL | 2634 //increment HL |
2635 if (opts->regs[Z80_HL] >= 0) { | 2635 if (opts->regs[Z80_HL] >= 0) { |
2669 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); | 2669 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); |
2670 call(code, opts->read_8);//T states 3 | 2670 call(code, opts->read_8);//T states 3 |
2671 //undocumented N flag behavior | 2671 //undocumented N flag behavior |
2672 //flag set on bit 7 of value written | 2672 //flag set on bit 7 of value written |
2673 bt_ir(code, 7, opts->gen.scratch1, SZ_B); | 2673 bt_ir(code, 7, opts->gen.scratch1, SZ_B); |
2674 setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_N)); | 2674 setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_N)); |
2675 //write to IO (C) | 2675 //write to IO (C) |
2676 zreg_to_native(opts, Z80_C, opts->gen.scratch2); | 2676 zreg_to_native(opts, Z80_C, opts->gen.scratch2); |
2677 call(code, opts->write_io);//T states 4 | 2677 call(code, opts->write_io);//T states 4 |
2678 //increment HL | 2678 //increment HL |
2679 if (opts->regs[Z80_HL] >= 0) { | 2679 if (opts->regs[Z80_HL] >= 0) { |
2724 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); | 2724 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); |
2725 call(code, opts->read_8);//T states 3 | 2725 call(code, opts->read_8);//T states 3 |
2726 //undocumented N flag behavior | 2726 //undocumented N flag behavior |
2727 //flag set on bit 7 of value written | 2727 //flag set on bit 7 of value written |
2728 bt_ir(code, 7, opts->gen.scratch1, SZ_B); | 2728 bt_ir(code, 7, opts->gen.scratch1, SZ_B); |
2729 setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_N)); | 2729 setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_N)); |
2730 //write to IO (C) | 2730 //write to IO (C) |
2731 zreg_to_native(opts, Z80_C, opts->gen.scratch2); | 2731 zreg_to_native(opts, Z80_C, opts->gen.scratch2); |
2732 call(code, opts->write_io);//T states 4 | 2732 call(code, opts->write_io);//T states 4 |
2733 //decrement HL | 2733 //decrement HL |
2734 if (opts->regs[Z80_HL] >= 0) { | 2734 if (opts->regs[Z80_HL] >= 0) { |
2768 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); | 2768 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); |
2769 call(code, opts->read_8);//T states 3 | 2769 call(code, opts->read_8);//T states 3 |
2770 //undocumented N flag behavior | 2770 //undocumented N flag behavior |
2771 //flag set on bit 7 of value written | 2771 //flag set on bit 7 of value written |
2772 bt_ir(code, 7, opts->gen.scratch1, SZ_B); | 2772 bt_ir(code, 7, opts->gen.scratch1, SZ_B); |
2773 setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_N)); | 2773 setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_N)); |
2774 //write to IO (C) | 2774 //write to IO (C) |
2775 zreg_to_native(opts, Z80_C, opts->gen.scratch2); | 2775 zreg_to_native(opts, Z80_C, opts->gen.scratch2); |
2776 call(code, opts->write_io);//T states 4 | 2776 call(code, opts->write_io);//T states 4 |
2777 //increment HL | 2777 //increment HL |
2778 if (opts->regs[Z80_HL] >= 0) { | 2778 if (opts->regs[Z80_HL] >= 0) { |
2885 | 2885 |
2886 uint8_t * z80_get_native_address(z80_context * context, uint32_t address) | 2886 uint8_t * z80_get_native_address(z80_context * context, uint32_t address) |
2887 { | 2887 { |
2888 z80_options *opts = context->options; | 2888 z80_options *opts = context->options; |
2889 native_map_slot * native_code_map = opts->gen.native_code_map; | 2889 native_map_slot * native_code_map = opts->gen.native_code_map; |
2890 | 2890 |
2891 memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, 0, NULL); | 2891 memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, 0, NULL); |
2892 if (mem_chunk) { | 2892 if (mem_chunk) { |
2893 //calculate the lowest alias for this address | 2893 //calculate the lowest alias for this address |
2894 address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask); | 2894 address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask); |
2895 } | 2895 } |
2942 //calculate the lowest alias for this address | 2942 //calculate the lowest alias for this address |
2943 address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask); | 2943 address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask); |
2944 } else { | 2944 } else { |
2945 address &= opts->gen.address_mask; | 2945 address &= opts->gen.address_mask; |
2946 } | 2946 } |
2947 | 2947 |
2948 native_map_slot *map = opts->gen.native_code_map + address / NATIVE_CHUNK_SIZE; | 2948 native_map_slot *map = opts->gen.native_code_map + address / NATIVE_CHUNK_SIZE; |
2949 if (!map->base) { | 2949 if (!map->base) { |
2950 map->base = native_address; | 2950 map->base = native_address; |
2951 map->offsets = malloc(sizeof(int32_t) * NATIVE_CHUNK_SIZE); | 2951 map->offsets = malloc(sizeof(int32_t) * NATIVE_CHUNK_SIZE); |
2952 memset(map->offsets, 0xFF, sizeof(int32_t) * NATIVE_CHUNK_SIZE); | 2952 memset(map->offsets, 0xFF, sizeof(int32_t) * NATIVE_CHUNK_SIZE); |
2958 if (!map->base) { | 2958 if (!map->base) { |
2959 map->base = native_address; | 2959 map->base = native_address; |
2960 map->offsets = malloc(sizeof(int32_t) * NATIVE_CHUNK_SIZE); | 2960 map->offsets = malloc(sizeof(int32_t) * NATIVE_CHUNK_SIZE); |
2961 memset(map->offsets, 0xFF, sizeof(int32_t) * NATIVE_CHUNK_SIZE); | 2961 memset(map->offsets, 0xFF, sizeof(int32_t) * NATIVE_CHUNK_SIZE); |
2962 } | 2962 } |
2963 | 2963 |
2964 if (map->offsets[address % NATIVE_CHUNK_SIZE] == INVALID_OFFSET) { | 2964 if (map->offsets[address % NATIVE_CHUNK_SIZE] == INVALID_OFFSET) { |
2965 //TODO: better handling of potentially overlapping instructions | 2965 //TODO: better handling of potentially overlapping instructions |
2966 map->offsets[address % NATIVE_CHUNK_SIZE] = EXTENSION_WORD; | 2966 map->offsets[address % NATIVE_CHUNK_SIZE] = EXTENSION_WORD; |
2967 } | 2967 } |
2968 } | 2968 } |
2969 } | 2969 } |
2970 | 2970 |
2971 #define INVALID_INSTRUCTION_START 0xFEEDFEED | 2971 #define INVALID_INSTRUCTION_START 0xFEEDFEED |
2972 | 2972 |
2973 uint32_t z80_get_instruction_start(z80_context *context, uint32_t address) | 2973 uint32_t z80_get_instruction_start(z80_context *context, uint32_t address) |
2974 { | 2974 { |
2975 z80_options *opts = context->options; | 2975 z80_options *opts = context->options; |
2976 native_map_slot * native_code_map = opts->gen.native_code_map; | 2976 native_map_slot * native_code_map = opts->gen.native_code_map; |
2977 memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, 0, NULL); | 2977 memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, 0, NULL); |
2978 if (mem_chunk) { | 2978 if (mem_chunk) { |
2979 //calculate the lowest alias for this address | 2979 //calculate the lowest alias for this address |
2980 address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask); | 2980 address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask); |
2981 } | 2981 } |
2982 | 2982 |
2983 uint32_t chunk = address / NATIVE_CHUNK_SIZE; | 2983 uint32_t chunk = address / NATIVE_CHUNK_SIZE; |
2984 if (!native_code_map[chunk].base) { | 2984 if (!native_code_map[chunk].base) { |
2985 return INVALID_INSTRUCTION_START; | 2985 return INVALID_INSTRUCTION_START; |
2986 } | 2986 } |
2987 uint32_t offset = address % NATIVE_CHUNK_SIZE; | 2987 uint32_t offset = address % NATIVE_CHUNK_SIZE; |
3235 options->regs[Z80_A] = RAX; | 3235 options->regs[Z80_A] = RAX; |
3236 options->regs[Z80_R] = AH; | 3236 options->regs[Z80_R] = AH; |
3237 options->regs[Z80_H] = BH; | 3237 options->regs[Z80_H] = BH; |
3238 options->regs[Z80_L] = RBX; | 3238 options->regs[Z80_L] = RBX; |
3239 options->regs[Z80_HL] = RBX; | 3239 options->regs[Z80_HL] = RBX; |
3240 | 3240 |
3241 options->regs[Z80_SP] = RDI; | 3241 options->regs[Z80_SP] = RDI; |
3242 | 3242 |
3243 options->gen.scratch1 = RCX; | 3243 options->gen.scratch1 = RCX; |
3244 options->gen.scratch2 = RDX; | 3244 options->gen.scratch2 = RDX; |
3245 #endif | 3245 #endif |
3340 //calculate call/stack adjust size | 3340 //calculate call/stack adjust size |
3341 sub_ir(code, 16-sizeof(void *), RSP, SZ_PTR); | 3341 sub_ir(code, 16-sizeof(void *), RSP, SZ_PTR); |
3342 call_noalign(code, options->gen.handle_cycle_limit); | 3342 call_noalign(code, options->gen.handle_cycle_limit); |
3343 uint32_t call_adjust_size = code->cur - options->gen.handle_cycle_limit; | 3343 uint32_t call_adjust_size = code->cur - options->gen.handle_cycle_limit; |
3344 code->cur = options->gen.handle_cycle_limit; | 3344 code->cur = options->gen.handle_cycle_limit; |
3345 | 3345 |
3346 neg_r(code, options->gen.cycles, SZ_D); | 3346 neg_r(code, options->gen.cycles, SZ_D); |
3347 add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D); | 3347 add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D); |
3348 cmp_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.cycles, SZ_D); | 3348 cmp_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.cycles, SZ_D); |
3349 code_ptr no_sync = code->cur+1; | 3349 code_ptr no_sync = code->cur+1; |
3350 jcc(code, CC_B, no_sync); | 3350 jcc(code, CC_B, no_sync); |
3361 mov_rrdisp(code, RBX, options->gen.context_reg, offsetof(z80_context, extra_pc), SZ_PTR); | 3361 mov_rrdisp(code, RBX, options->gen.context_reg, offsetof(z80_context, extra_pc), SZ_PTR); |
3362 mov_rrind(code, RAX, options->gen.context_reg, SZ_PTR); | 3362 mov_rrind(code, RAX, options->gen.context_reg, SZ_PTR); |
3363 restore_callee_save_regs(code); | 3363 restore_callee_save_regs(code); |
3364 //return to caller of z80_run | 3364 //return to caller of z80_run |
3365 retn(code); | 3365 retn(code); |
3366 | 3366 |
3367 *no_sync = code->cur - (no_sync + 1); | 3367 *no_sync = code->cur - (no_sync + 1); |
3368 neg_r(code, options->gen.cycles, SZ_D); | 3368 neg_r(code, options->gen.cycles, SZ_D); |
3369 add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D); | 3369 add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D); |
3370 retn(code); | 3370 retn(code); |
3371 code->stack_off = tmp_stack_off; | 3371 code->stack_off = tmp_stack_off; |
3378 code_ptr skip_int = code->cur; | 3378 code_ptr skip_int = code->cur; |
3379 //calculate adjust size | 3379 //calculate adjust size |
3380 add_ir(code, 16-sizeof(void *), RSP, SZ_PTR); | 3380 add_ir(code, 16-sizeof(void *), RSP, SZ_PTR); |
3381 uint32_t adjust_size = code->cur - skip_int; | 3381 uint32_t adjust_size = code->cur - skip_int; |
3382 code->cur = skip_int; | 3382 code->cur = skip_int; |
3383 | 3383 |
3384 cmp_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.cycles, SZ_D); | 3384 cmp_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.cycles, SZ_D); |
3385 code_ptr skip_sync = code->cur + 1; | 3385 code_ptr skip_sync = code->cur + 1; |
3386 jcc(code, CC_B, skip_sync); | 3386 jcc(code, CC_B, skip_sync); |
3387 neg_r(code, options->gen.cycles, SZ_D); | 3387 neg_r(code, options->gen.cycles, SZ_D); |
3388 add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D); | 3388 add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D); |
3395 //pop_rind(code, options->gen.context_reg); | 3395 //pop_rind(code, options->gen.context_reg); |
3396 pop_r(code, RAX); | 3396 pop_r(code, RAX); |
3397 add_ir(code, adjust_size, RAX, SZ_PTR); | 3397 add_ir(code, adjust_size, RAX, SZ_PTR); |
3398 add_ir(code, 16-sizeof(void *), RSP, SZ_PTR); | 3398 add_ir(code, 16-sizeof(void *), RSP, SZ_PTR); |
3399 mov_rrind(code, RAX, options->gen.context_reg, SZ_PTR); | 3399 mov_rrind(code, RAX, options->gen.context_reg, SZ_PTR); |
3400 | 3400 |
3401 //restore callee saved registers | 3401 //restore callee saved registers |
3402 restore_callee_save_regs(code); | 3402 restore_callee_save_regs(code); |
3403 //return to caller of z80_run | 3403 //return to caller of z80_run |
3404 retn(code); | 3404 retn(code); |
3405 *skip_sync = code->cur - (skip_sync+1); | 3405 *skip_sync = code->cur - (skip_sync+1); |
3583 } | 3583 } |
3584 call_noalign(code, options->retrans_stub); | 3584 call_noalign(code, options->retrans_stub); |
3585 uint32_t patch_size = code->cur - options->retrans_stub; | 3585 uint32_t patch_size = code->cur - options->retrans_stub; |
3586 code->cur = options->retrans_stub; | 3586 code->cur = options->retrans_stub; |
3587 code->stack_off = tmp_stack_off; | 3587 code->stack_off = tmp_stack_off; |
3588 | 3588 |
3589 //pop return address | 3589 //pop return address |
3590 pop_r(code, options->gen.scratch2); | 3590 pop_r(code, options->gen.scratch2); |
3591 add_ir(code, 16-sizeof(void*), RSP, SZ_PTR); | 3591 add_ir(code, 16-sizeof(void*), RSP, SZ_PTR); |
3592 code->stack_off = tmp_stack_off; | 3592 code->stack_off = tmp_stack_off; |
3593 call(code, options->gen.save_context); | 3593 call(code, options->gen.save_context); |
3610 #endif | 3610 #endif |
3611 call(code, options->load_context_scratch); | 3611 call(code, options->load_context_scratch); |
3612 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); |
3613 code_ptr no_extra = code->cur+1; | 3613 code_ptr no_extra = code->cur+1; |
3614 jcc(code, CC_Z, no_extra); | 3614 jcc(code, CC_Z, no_extra); |
3615 sub_ir(code, 16-sizeof(void *), RSP, SZ_PTR); | 3615 sub_ir(code, 16-sizeof(void *), RSP, SZ_PTR); |
3616 push_rdisp(code, options->gen.context_reg, offsetof(z80_context, extra_pc)); | 3616 push_rdisp(code, options->gen.context_reg, offsetof(z80_context, extra_pc)); |
3617 mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, extra_pc), SZ_PTR); | 3617 mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, extra_pc), SZ_PTR); |
3618 *no_extra = code->cur - (no_extra + 1); | 3618 *no_extra = code->cur - (no_extra + 1); |
3619 jmp_rind(code, options->gen.context_reg); | 3619 jmp_rind(code, options->gen.context_reg); |
3620 code->stack_off = tmp_stack_off; | 3620 code->stack_off = tmp_stack_off; |
3627 context->options = options; | 3627 context->options = options; |
3628 context->int_cycle = CYCLE_NEVER; | 3628 context->int_cycle = CYCLE_NEVER; |
3629 context->int_pulse_start = CYCLE_NEVER; | 3629 context->int_pulse_start = CYCLE_NEVER; |
3630 context->int_pulse_end = CYCLE_NEVER; | 3630 context->int_pulse_end = CYCLE_NEVER; |
3631 context->nmi_start = CYCLE_NEVER; | 3631 context->nmi_start = CYCLE_NEVER; |
3632 | 3632 context->sp = 0xFFFF; |
3633 | |
3633 return context; | 3634 return context; |
3634 } | 3635 } |
3635 | 3636 |
3636 static void check_nmi(z80_context *context) | 3637 static void check_nmi(z80_context *context) |
3637 { | 3638 { |
3663 context->int_is_nmi = 0; | 3664 context->int_is_nmi = 0; |
3664 } else { | 3665 } else { |
3665 context->int_cycle = CYCLE_NEVER; | 3666 context->int_cycle = CYCLE_NEVER; |
3666 } | 3667 } |
3667 check_nmi(context); | 3668 check_nmi(context); |
3668 | 3669 |
3669 context->target_cycle = context->sync_cycle < context->int_cycle ? context->sync_cycle : context->int_cycle; | 3670 context->target_cycle = context->sync_cycle < context->int_cycle ? context->sync_cycle : context->int_cycle; |
3670 dprintf("Running Z80 from cycle %d to cycle %d. Int cycle: %d (%d - %d)\n", context->current_cycle, context->sync_cycle, context->int_cycle, context->int_pulse_start, context->int_pulse_end); | 3671 dprintf("Running Z80 from cycle %d to cycle %d. Int cycle: %d (%d - %d)\n", context->current_cycle, context->sync_cycle, context->int_cycle, context->int_pulse_start, context->int_pulse_end); |
3671 context->options->run(context); | 3672 context->options->run(context); |
3672 dprintf("Z80 ran to cycle %d\n", context->current_cycle); | 3673 dprintf("Z80 ran to cycle %d\n", context->current_cycle); |
3673 } | 3674 } |
3713 context->iff1 = context->iff2 = 0; | 3714 context->iff1 = context->iff2 = 0; |
3714 context->native_pc = NULL; | 3715 context->native_pc = NULL; |
3715 context->extra_pc = NULL; | 3716 context->extra_pc = NULL; |
3716 context->pc = 0; | 3717 context->pc = 0; |
3717 context->reset = 0; | 3718 context->reset = 0; |
3719 context->sp = 0xFFFF; | |
3718 if (context->busreq) { | 3720 if (context->busreq) { |
3719 //TODO: Figure out appropriate delay | 3721 //TODO: Figure out appropriate delay |
3720 context->busack = 1; | 3722 context->busack = 1; |
3721 } | 3723 } |
3722 } | 3724 } |
3787 } | 3789 } |
3788 | 3790 |
3789 uint32_t zbreakpoint_patch(z80_context * context, uint16_t address, code_ptr dst) | 3791 uint32_t zbreakpoint_patch(z80_context * context, uint16_t address, code_ptr dst) |
3790 { | 3792 { |
3791 code_info code = { | 3793 code_info code = { |
3792 dst, | 3794 dst, |
3793 dst+32, | 3795 dst+32, |
3794 #ifdef X86_64 | 3796 #ifdef X86_64 |
3795 8 | 3797 8 |
3796 #else | 3798 #else |
3797 0 | 3799 0 |