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