# HG changeset patch # User Mike Pavone # Date 1368902682 25200 # Node ID 467bfa17004a221d8dbb8133625cdfa4a2d13d03 # Parent 13f994c88c343f39de5d9869b3f702c63599d35c Mostly working runtime generation of memory map read/write functions diff -r 13f994c88c34 -r 467bfa17004a blastem.c --- a/blastem.c Thu May 16 09:37:53 2013 -0700 +++ b/blastem.c Sat May 18 11:44:42 2013 -0700 @@ -235,12 +235,18 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_t value) { + if (vdp_port & 0x2700E0) { + printf("machine freeze due to write to address %X\n", 0xC00000 | vdp_port); + exit(1); + } + vdp_port &= 0x1F; //printf("vdp_port write: %X, value: %X, cycle: %d\n", vdp_port, value, context->current_cycle); sync_components(context, 0); vdp_context * v_context = context->video_context; if (vdp_port < 0x10) { int blocked; if (vdp_port < 4) { + uint32_t before_cycle = v_context->cycles; while (vdp_data_port_write(v_context, value) < 0) { while(v_context->flags & FLAG_DMA_RUN) { vdp_run_dma_done(v_context, mclks_per_frame); @@ -293,25 +299,46 @@ return context; } -m68k_context * vdp_port_read(uint32_t vdp_port, m68k_context * context) +m68k_context * vdp_port_write_b(uint32_t vdp_port, m68k_context * context, uint8_t value) +{ + return vdp_port_write(vdp_port, context, value | value << 8); +} + +uint16_t vdp_port_read(uint32_t vdp_port, m68k_context * context) { + if (vdp_port & 0x2700E0) { + printf("machine freeze due to read from address %X\n", 0xC00000 | vdp_port); + exit(1); + } + vdp_port &= 0x1F; + uint16_t value; sync_components(context, 0); vdp_context * v_context = context->video_context; if (vdp_port < 0x10) { if (vdp_port < 4) { - context->value = vdp_data_port_read(v_context); + value = vdp_data_port_read(v_context); } else if(vdp_port < 8) { - context->value = vdp_control_port_read(v_context); + value = vdp_control_port_read(v_context); } else { - context->value = vdp_hv_counter_read(v_context); - //printf("HV Counter: %X at cycle %d\n", context->value, v_context->cycles); + value = vdp_hv_counter_read(v_context); + //printf("HV Counter: %X at cycle %d\n", value, v_context->cycles); } context->current_cycle = v_context->cycles/MCLKS_PER_68K; } else { printf("Illegal read from PSG or test register port %X\n", vdp_port); exit(1); } - return context; + return value; +} + +uint8_t vdp_port_read_b(uint32_t vdp_port, m68k_context * context) +{ + uint16_t value = vdp_port_read(vdp_port, context); + if (vdp_port & 1) { + return value; + } else { + return value >> 8; + } } #define TH 0x40 @@ -351,7 +378,7 @@ pad->output = value; } -void io_data_read(io_port * pad, m68k_context * context) +uint8_t io_data_read(io_port * pad, m68k_context * context) { uint8_t control = pad->control | 0x80; uint8_t th = control & pad->output; @@ -377,10 +404,11 @@ input = pad->input[GAMEPAD_TH0] | 0xC; } } - context->value = ((~input) & (~control)) | (pad->output & control); + uint8_t value = ((~input) & (~control)) | (pad->output & control); /*if (pad->input[GAMEPAD_TH0] || pad->input[GAMEPAD_TH1]) { - printf ("value: %X\n", context->value); + printf ("value: %X\n", value); }*/ + return value; } uint32_t zram_counter = 0; @@ -596,8 +624,9 @@ #define NO_DISK 0x20 uint8_t version_reg = NO_DISK | USA; -m68k_context * io_read(uint32_t location, m68k_context * context) +uint8_t io_read(uint32_t location, m68k_context * context) { + uint8_t value; genesis_context *gen = context->system; if (location < 0x10000) { if (busack_cycle <= context->current_cycle) { @@ -607,15 +636,83 @@ if (!(busack==Z80_REQ_BUSY || reset)) { location &= 0x7FFF; if (location < 0x4000) { - context->value = z80_ram[location & 0x1FFF]; + value = z80_ram[location & 0x1FFF]; } else if (location < 0x6000) { ym_run(gen->ym, context->current_cycle); - context->value = ym_read_status(gen->ym); + value = ym_read_status(gen->ym); } else { - context->value = 0xFF; + value = 0xFF; + } + } else { + value = 0xFF; + } + } else { + location &= 0x1FFF; + if (location < 0x100) { + switch(location/2) + { + case 0x0: + //version bits should be 0 for now since we're not emulating TMSS + value = version_reg; + break; + case 0x1: + value = io_data_read(&gamepad_1, context); + break; + case 0x2: + value = io_data_read(&gamepad_2, context); + break; + case 0x3://PORT C Data + break; + case 0x4: + value = gamepad_1.control; + break; + case 0x5: + value = gamepad_2.control; + break; + default: + value = 0xFF; } } else { - context->value = 0xFF; + if (location == 0x1100) { + if (busack_cycle <= context->current_cycle) { + busack = new_busack; + busack_cycle = CYCLE_NEVER; + } + value = Z80_RES_BUSACK || busack; + dprintf("Byte read of BUSREQ returned %d @ %d (reset: %d, busack: %d, busack_cycle %d)\n", value, context->current_cycle, reset, busack, busack_cycle); + } else if (location == 0x1200) { + value = !reset; + } else { + value = 0xFF; + printf("Byte read of unknown IO location: %X\n", location); + } + } + } + return value; +} + +uint16_t io_read_w(uint32_t location, m68k_context * context) +{ + uint16_t value; + genesis_context * gen = context->system; + if (location < 0x10000) { + if (busack_cycle <= context->current_cycle) { + busack = new_busack; + busack_cycle = CYCLE_NEVER; + } + if (!(busack==Z80_REQ_BUSY || reset)) { + location &= 0x7FFF; + if (location < 0x4000) { + value = z80_ram[location & 0x1FFE]; + } else if (location < 0x6000) { + ym_run(gen->ym, context->current_cycle); + value = ym_read_status(gen->ym); + } else { + value = 0xFF; + } + value = value | (value << 8); + } else { + value = 0xFFFF; } } else { location &= 0x1FFF; @@ -625,111 +722,47 @@ case 0x0: //version bits should be 0 for now since we're not emulating TMSS //Not sure about the other bits - context->value = version_reg; + value = version_reg; break; case 0x1: - io_data_read(&gamepad_1, context); + value = io_data_read(&gamepad_1, context); break; case 0x2: - io_data_read(&gamepad_2, context); + value = io_data_read(&gamepad_2, context); break; case 0x3://PORT C Data break; case 0x4: - context->value = gamepad_1.control; + value = gamepad_1.control; break; case 0x5: - context->value = gamepad_2.control; + value = gamepad_2.control; + break; + case 0x6: + //PORT C Control + value = 0; break; + default: + value = 0; } + value = value | (value << 8); + //printf("Word read to %X returned %d\n", location, value); } else { if (location == 0x1100) { if (busack_cycle <= context->current_cycle) { busack = new_busack; busack_cycle = CYCLE_NEVER; } - context->value = Z80_RES_BUSACK || busack; - dprintf("Byte read of BUSREQ returned %d @ %d (reset: %d, busack: %d, busack_cycle %d)\n", context->value, context->current_cycle, reset, busack, busack_cycle); + value = (Z80_RES_BUSACK || busack) << 8; + //printf("Word read of BUSREQ returned %d\n", value); } else if (location == 0x1200) { - context->value = !reset; - } else { - printf("Byte read of unknown IO location: %X\n", location); - } - } - } - return context; -} - -m68k_context * io_read_w(uint32_t location, m68k_context * context) -{ - genesis_context * gen = context->system; - if (location < 0x10000) { - if (busack_cycle <= context->current_cycle) { - busack = new_busack; - busack_cycle = CYCLE_NEVER; - } - if (!(busack==Z80_REQ_BUSY || reset)) { - location &= 0x7FFF; - uint16_t value; - if (location < 0x4000) { - value = z80_ram[location & 0x1FFE]; - } else if (location < 0x6000) { - ym_run(gen->ym, context->current_cycle); - value = ym_read_status(gen->ym); - } else { - value = 0xFF; - } - context->value = value | (value << 8); - } else { - context->value = 0xFFFF; - } - } else { - location &= 0x1FFF; - if (location < 0x100) { - switch(location/2) - { - case 0x0: - //version bits should be 0 for now since we're not emulating TMSS - //Not sure about the other bits - context->value = 0; - break; - case 0x1: - io_data_read(&gamepad_1, context); - break; - case 0x2: - io_data_read(&gamepad_2, context); - break; - case 0x3://PORT C Data - break; - case 0x4: - context->value = gamepad_1.control; - break; - case 0x5: - context->value = gamepad_2.control; - break; - case 0x6: - //PORT C Control - context->value = 0; - break; - } - context->value = context->value | (context->value << 8); - //printf("Word read to %X returned %d\n", location, context->value); - } else { - if (location == 0x1100) { - if (busack_cycle <= context->current_cycle) { - busack = new_busack; - busack_cycle = CYCLE_NEVER; - } - context->value = (Z80_RES_BUSACK || busack) << 8; - //printf("Word read of BUSREQ returned %d\n", context->value); - } else if (location == 0x1200) { - context->value = (!reset) << 8; + value = (!reset) << 8; } else { printf("Word read of unknown IO location: %X\n", location); } } } - return context; + return value; } z80_context * z80_write_ym(uint16_t location, z80_context * context, uint8_t value) @@ -1000,7 +1033,19 @@ m68k_context context; x86_68k_options opts; gen->m68k = &context; - init_x86_68k_opts(&opts); + memmap_chunk memmap[] = { + {0, 0x400000, 0xFFFFFF, 0, MMAP_READ | MMAP_WRITE, cart, + NULL, NULL, NULL, NULL}, + {0xE00000, 0x1000000, 0xFFFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, ram, + NULL, NULL, NULL, NULL}, + {0xC00000, 0xE00000, 0x1FFFFF, 0, 0, NULL, + (read_16_fun)vdp_port_read, (write_16_fun)vdp_port_write, + (read_8_fun)vdp_port_read_b, (write_8_fun)vdp_port_write_b}, + {0xA00000, 0xA12000, 0x1FFFF, 0, 0, NULL, + (read_16_fun)io_read_w, (write_16_fun)io_write_w, + (read_8_fun)io_read, (write_8_fun)io_write} + }; + init_x86_68k_opts(&opts, memmap, sizeof(memmap)/sizeof(memmap_chunk)); opts.address_log = address_log; init_68k_context(&context, opts.native_code_map, &opts); @@ -1068,11 +1113,11 @@ void detect_region() { - if (detect_specific_region('U')) { + if (detect_specific_region('U')|| detect_specific_region('B') || detect_specific_region('4')) { version_reg = NO_DISK | USA; } else if (detect_specific_region('J')) { version_reg = NO_DISK | JAP; - } if (detect_specific_region('E') || detect_specific_region('A') || detect_specific_region('B') || detect_specific_region('4')) { + } else if (detect_specific_region('E') || detect_specific_region('A')) { version_reg = NO_DISK | EUR; } } diff -r 13f994c88c34 -r 467bfa17004a gen_x86.c --- a/gen_x86.c Thu May 16 09:37:53 2013 -0700 +++ b/gen_x86.c Sat May 18 11:44:42 2013 -0700 @@ -2,6 +2,7 @@ #include "68kinst.h" #include #include +#include #define REX_RM_FIELD 0x1 #define REX_SIB_FIELD 0x2 @@ -220,6 +221,58 @@ return out; } +uint8_t * x86_rrdisp32_sizedir(uint8_t * out, uint16_t opcode, uint8_t reg, uint8_t base, int32_t disp, uint8_t size, uint8_t dir) +{ + //TODO: Deal with the fact that AH, BH, CH and DH can only be in the R/M param when there's a REX prefix + uint8_t tmp; + if (size == SZ_W) { + *(out++) = PRE_SIZE; + } + if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) { + *out = PRE_REX; + if (reg >= AH && reg <= BH) { + fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); + exit(1); + } + if (size == SZ_Q) { + *out |= REX_QUAD; + } + if (reg >= R8) { + *out |= REX_REG_FIELD; + reg -= (R8 - X86_R8); + } + if (base >= R8) { + *out |= REX_RM_FIELD; + base -= (R8 - X86_R8); + } + out++; + } + if (size == SZ_B) { + if (reg >= AH && reg <= BH) { + reg -= (AH-X86_AH); + } + } else { + opcode |= BIT_SIZE; + } + opcode |= dir; + if (opcode >= 0x100) { + *(out++) = opcode >> 8; + *(out++) = opcode; + } else { + *(out++) = opcode; + } + *(out++) = MODE_REG_DISPLACE32 | base | (reg << 3); + if (base == RSP) { + //add SIB byte, with no index and RSP as base + *(out++) = (RSP << 3) | RSP; + } + *(out++) = disp; + *(out++) = disp >> 8; + *(out++) = disp >> 16; + *(out++) = disp >> 24; + return out; +} + uint8_t * x86_rrind_sizedir(uint8_t * out, uint8_t opcode, uint8_t reg, uint8_t base, uint8_t size, uint8_t dir) { //TODO: Deal with the fact that AH, BH, CH and DH can only be in the R/M param when there's a REX prefix @@ -262,6 +315,54 @@ return out; } +uint8_t * x86_rrindex_sizedir(uint8_t * out, uint8_t opcode, uint8_t reg, uint8_t base, uint8_t index, uint8_t scale, uint8_t size, uint8_t dir) +{ + //TODO: Deal with the fact that AH, BH, CH and DH can only be in the R/M param when there's a REX prefix + uint8_t tmp; + if (size == SZ_W) { + *(out++) = PRE_SIZE; + } + if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) { + *out = PRE_REX; + if (reg >= AH && reg <= BH) { + fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); + exit(1); + } + if (size == SZ_Q) { + *out |= REX_QUAD; + } + if (reg >= R8) { + *out |= REX_REG_FIELD; + reg -= (R8 - X86_R8); + } + if (base >= R8) { + *out |= REX_RM_FIELD; + base -= (R8 - X86_R8); + } + if (index >= R8) { + *out |= REX_SIB_FIELD; + index -= (R8 - X86_R8); + } + out++; + } + if (size == SZ_B) { + if (reg >= AH && reg <= BH) { + reg -= (AH-X86_AH); + } + } else { + opcode |= BIT_SIZE; + } + *(out++) = opcode | dir; + *(out++) = MODE_REG_INDIRECT | base | (RSP << 3); + if (base == RSP) { + if (scale == 4) { + scale = 3; + } + *(out++) = scale << 6 | (index << 3) | base; + } + return out; +} + uint8_t * x86_r_size(uint8_t * out, uint8_t opcode, uint8_t opex, uint8_t dst, uint8_t size) { uint8_t tmp; @@ -949,6 +1050,16 @@ return x86_rrdisp8_sizedir(out, OP_MOV, dst, src_base, disp, size, BIT_DIR); } +uint8_t * mov_rrdisp32(uint8_t * out, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size) +{ + return x86_rrdisp32_sizedir(out, OP_MOV, src, dst_base, disp, size, 0); +} + +uint8_t * mov_rdisp32r(uint8_t * out, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size) +{ + return x86_rrdisp32_sizedir(out, OP_MOV, dst, src_base, disp, size, BIT_DIR); +} + uint8_t * mov_rrind(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size) { return x86_rrind_sizedir(out, OP_MOV, src, dst, size, 0); @@ -959,6 +1070,16 @@ return x86_rrind_sizedir(out, OP_MOV, dst, src, size, BIT_DIR); } +uint8_t * mov_rrindex(uint8_t * out, uint8_t src, uint8_t dst_base, uint8_t dst_index, uint8_t scale, uint8_t size) +{ + return x86_rrindex_sizedir(out, OP_MOV, src, dst_base, dst_index, scale, size, 0); +} + +uint8_t * mov_rindexr(uint8_t * out, uint8_t src_base, uint8_t src_index, uint8_t scale, uint8_t dst, uint8_t size) +{ + return x86_rrindex_sizedir(out, OP_MOV, dst, src_base, src_index, scale, size, BIT_DIR); +} + uint8_t * mov_ir(uint8_t * out, int64_t val, uint8_t dst, uint8_t size) { uint8_t sign_extend = 0; @@ -1370,6 +1491,36 @@ return out; } +uint8_t * bit_rrdisp32(uint8_t * out, uint8_t op2, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size) +{ + if (size == SZ_W) { + *(out++) = PRE_SIZE; + } + if (size == SZ_Q || src >= R8 || dst_base >= R8) { + *out = PRE_REX; + if (size == SZ_Q) { + *out |= REX_QUAD; + } + if (src >= R8) { + *out |= REX_REG_FIELD; + src -= (R8 - X86_R8); + } + if (dst_base >= R8) { + *out |= REX_RM_FIELD; + dst_base -= (R8 - X86_R8); + } + out++; + } + *(out++) = PRE_2BYTE; + *(out++) = op2; + *(out++) = MODE_REG_DISPLACE32 | dst_base | (src << 3); + *(out++) = dst_disp; + *(out++) = dst_disp >> 8; + *(out++) = dst_disp >> 16; + *(out++) = dst_disp >> 24; + return out; +} + uint8_t * bit_ir(uint8_t * out, uint8_t op_ex, uint8_t val, uint8_t dst, uint8_t size) { if (size == SZ_W) { @@ -1427,6 +1578,11 @@ return bit_rrdisp8(out, OP2_BT, src, dst_base, dst_disp, size); } +uint8_t * bt_rrdisp32(uint8_t * out, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size) +{ + return bit_rrdisp32(out, OP2_BT, src, dst_base, dst_disp, size); +} + uint8_t * bt_ir(uint8_t * out, uint8_t val, uint8_t dst, uint8_t size) { return bit_ir(out, OP_EX_BT, val, dst, size); diff -r 13f994c88c34 -r 467bfa17004a gen_x86.h --- a/gen_x86.h Thu May 16 09:37:53 2013 -0700 +++ b/gen_x86.h Sat May 18 11:44:42 2013 -0700 @@ -57,7 +57,7 @@ MODE_REG_INDEXED = 4, MODE_REG_DISPLACE8 = 0x40, MODE_REG_INDEXED_DISPLACE8 = 0x44, - MODE_REG_DIPSLACE32 = 0x80, + MODE_REG_DISPLACE32 = 0x80, MODE_REG_INDEXED_DIPSLACE32 = 0x84, MODE_REG_DIRECT = 0xC0, //"phony" mode @@ -151,6 +151,10 @@ uint8_t * mov_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size); uint8_t * mov_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t disp, uint8_t size); uint8_t * mov_rdisp8r(uint8_t * out, uint8_t src_base, int8_t disp, uint8_t dst, uint8_t size); +uint8_t * mov_rrdisp32(uint8_t * out, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size); +uint8_t * mov_rdisp32r(uint8_t * out, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size); +uint8_t * mov_rrindex(uint8_t * out, uint8_t src, uint8_t dst_base, uint8_t dst_index, uint8_t scale, uint8_t size); +uint8_t * mov_rindexr(uint8_t * out, uint8_t src_base, uint8_t src_index, uint8_t scale, uint8_t dst, uint8_t size); uint8_t * mov_rrind(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size); uint8_t * mov_rindr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size); uint8_t * mov_ir(uint8_t * out, int64_t val, uint8_t dst, uint8_t size); @@ -170,6 +174,7 @@ uint8_t * setcc_rdisp8(uint8_t * out, uint8_t cc, uint8_t dst, int8_t disp); uint8_t * bt_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size); uint8_t * bt_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t dst_disp, uint8_t size); +uint8_t * bt_rrdisp32(uint8_t * out, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size); uint8_t * bt_ir(uint8_t * out, uint8_t val, uint8_t dst, uint8_t size); uint8_t * bt_irdisp8(uint8_t * out, uint8_t val, uint8_t dst_base, int8_t dst_disp, uint8_t size); uint8_t * bts_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size); diff -r 13f994c88c34 -r 467bfa17004a m68k_to_x86.c --- a/m68k_to_x86.c Thu May 16 09:37:53 2013 -0700 +++ b/m68k_to_x86.c Sat May 18 11:44:42 2013 -0700 @@ -24,13 +24,7 @@ char disasm_buf[1024]; void handle_cycle_limit_int(); -void m68k_read_word_scratch1(); -void m68k_read_long_scratch1(); -void m68k_read_byte_scratch1(); -void m68k_write_word(); -void m68k_write_long_lowfirst(); -void m68k_write_long_highfirst(); -void m68k_write_byte(); +void handle_cycle_limit(); void m68k_save_context(); void m68k_load_context(); void m68k_modified_ret_addr(); @@ -65,6 +59,16 @@ return dst; } +uint8_t * check_cycles(uint8_t * dst) +{ + dst = cmp_rr(dst, CYCLES, LIMIT, SZ_D); + uint8_t * jmp_off = dst+1; + dst = jcc(dst, CC_NC, dst + 7); + dst = call(dst, (uint8_t *)handle_cycle_limit); + *jmp_off = dst - (jmp_off+1); + return dst; +} + int8_t native_reg(m68k_op_info * op, x86_68k_options * opts) { if (op->addr_mode == MODE_REG) { @@ -155,13 +159,13 @@ switch (inst->extra.size) { case OPSIZE_BYTE: - out = call(out, (char *)m68k_read_byte_scratch1); + out = call(out, opts->read_8); break; case OPSIZE_WORD: - out = call(out, (char *)m68k_read_word_scratch1); + out = call(out, opts->read_16); break; case OPSIZE_LONG: - out = call(out, (char *)m68k_read_long_scratch1); + out = call(out, opts->read_32); break; } @@ -187,13 +191,13 @@ switch (inst->extra.size) { case OPSIZE_BYTE: - out = call(out, (char *)m68k_read_byte_scratch1); + out = call(out, opts->read_8); break; case OPSIZE_WORD: - out = call(out, (char *)m68k_read_word_scratch1); + out = call(out, opts->read_16); break; case OPSIZE_LONG: - out = call(out, (char *)m68k_read_long_scratch1); + out = call(out, opts->read_32); break; } ea->mode = MODE_REG_DIRECT; @@ -243,13 +247,13 @@ switch (inst->extra.size) { case OPSIZE_BYTE: - out = call(out, (char *)m68k_read_byte_scratch1); + out = call(out, opts->read_8); break; case OPSIZE_WORD: - out = call(out, (char *)m68k_read_word_scratch1); + out = call(out, opts->read_16); break; case OPSIZE_LONG: - out = call(out, (char *)m68k_read_long_scratch1); + out = call(out, opts->read_32); break; } ea->mode = MODE_REG_DIRECT; @@ -261,13 +265,13 @@ switch (inst->extra.size) { case OPSIZE_BYTE: - out = call(out, (char *)m68k_read_byte_scratch1); + out = call(out, opts->read_8); break; case OPSIZE_WORD: - out = call(out, (char *)m68k_read_word_scratch1); + out = call(out, opts->read_16); break; case OPSIZE_LONG: - out = call(out, (char *)m68k_read_long_scratch1); + out = call(out, opts->read_32); break; } ea->mode = MODE_REG_DIRECT; @@ -313,13 +317,13 @@ switch (inst->extra.size) { case OPSIZE_BYTE: - out = call(out, (char *)m68k_read_byte_scratch1); + out = call(out, opts->read_8); break; case OPSIZE_WORD: - out = call(out, (char *)m68k_read_word_scratch1); + out = call(out, opts->read_16); break; case OPSIZE_LONG: - out = call(out, (char *)m68k_read_long_scratch1); + out = call(out, opts->read_32); break; } ea->mode = MODE_REG_DIRECT; @@ -336,13 +340,13 @@ switch (inst->extra.size) { case OPSIZE_BYTE: - out = call(out, (char *)m68k_read_byte_scratch1); + out = call(out, opts->read_8); break; case OPSIZE_WORD: - out = call(out, (char *)m68k_read_word_scratch1); + out = call(out, opts->read_16); break; case OPSIZE_LONG: - out = call(out, (char *)m68k_read_long_scratch1); + out = call(out, opts->read_32); break; } ea->mode = MODE_REG_DIRECT; @@ -416,13 +420,13 @@ switch (inst->extra.size) { case OPSIZE_BYTE: - out = call(out, (char *)m68k_read_byte_scratch1); + out = call(out, opts->read_8); break; case OPSIZE_WORD: - out = call(out, (char *)m68k_read_word_scratch1); + out = call(out, opts->read_16); break; case OPSIZE_LONG: - out = call(out, (char *)m68k_read_long_scratch1); + out = call(out, opts->read_32); break; } } @@ -463,13 +467,13 @@ switch (inst->extra.size) { case OPSIZE_BYTE: - out = call(out, (char *)m68k_read_byte_scratch1); + out = call(out, opts->read_8); break; case OPSIZE_WORD: - out = call(out, (char *)m68k_read_word_scratch1); + out = call(out, opts->read_16); break; case OPSIZE_LONG: - out = call(out, (char *)m68k_read_long_scratch1); + out = call(out, opts->read_32); break; } out = pop_r(out, SCRATCH2); @@ -525,13 +529,13 @@ switch (inst->extra.size) { case OPSIZE_BYTE: - out = call(out, (char *)m68k_read_byte_scratch1); + out = call(out, opts->read_8); break; case OPSIZE_WORD: - out = call(out, (char *)m68k_read_word_scratch1); + out = call(out, opts->read_16); break; case OPSIZE_LONG: - out = call(out, (char *)m68k_read_long_scratch1); + out = call(out, opts->read_32); break; } out = pop_r(out, SCRATCH2); @@ -547,13 +551,13 @@ switch (inst->extra.size) { case OPSIZE_BYTE: - out = call(out, (char *)m68k_read_byte_scratch1); + out = call(out, opts->read_8); break; case OPSIZE_WORD: - out = call(out, (char *)m68k_read_word_scratch1); + out = call(out, opts->read_16); break; case OPSIZE_LONG: - out = call(out, (char *)m68k_read_long_scratch1); + out = call(out, opts->read_32); break; } out = pop_r(out, SCRATCH2); @@ -605,13 +609,13 @@ switch (inst->extra.size) { case OPSIZE_BYTE: - out = call(out, (char *)m68k_read_byte_scratch1); + out = call(out, opts->read_8); break; case OPSIZE_WORD: - out = call(out, (char *)m68k_read_word_scratch1); + out = call(out, opts->read_16); break; case OPSIZE_LONG: - out = call(out, (char *)m68k_read_long_scratch1); + out = call(out, opts->read_32); break; } out = pop_r(out, SCRATCH2); @@ -629,13 +633,13 @@ switch (inst->extra.size) { case OPSIZE_BYTE: - out = call(out, (char *)m68k_read_byte_scratch1); + out = call(out, opts->read_8); break; case OPSIZE_WORD: - out = call(out, (char *)m68k_read_word_scratch1); + out = call(out, opts->read_16); break; case OPSIZE_LONG: - out = call(out, (char *)m68k_read_long_scratch1); + out = call(out, opts->read_32); break; } out = pop_r(out, SCRATCH2); @@ -664,13 +668,13 @@ switch (inst->extra.size) { case OPSIZE_BYTE: - out = call(out, (char *)m68k_write_byte); + out = call(out, opts->write_8); break; case OPSIZE_WORD: - out = call(out, (char *)m68k_write_word); + out = call(out, opts->write_16); break; case OPSIZE_LONG: - out = call(out, (char *)m68k_write_long_lowfirst); + out = call(out, opts->write_32_lowfirst); break; } } @@ -851,13 +855,13 @@ switch (inst->extra.size) { case OPSIZE_BYTE: - dst = call(dst, (char *)m68k_write_byte); + dst = call(dst, opts->write_8); break; case OPSIZE_WORD: - dst = call(dst, (char *)m68k_write_word); + dst = call(dst, opts->write_16); break; case OPSIZE_LONG: - dst = call(dst, (char *)m68k_write_long_highfirst); + dst = call(dst, opts->write_32_highfirst); break; } if (inst->dst.addr_mode == MODE_AREG_POSTINC) { @@ -894,13 +898,13 @@ switch (inst->extra.size) { case OPSIZE_BYTE: - dst = call(dst, (char *)m68k_write_byte); + dst = call(dst, opts->write_8); break; case OPSIZE_WORD: - dst = call(dst, (char *)m68k_write_word); + dst = call(dst, opts->write_16); break; case OPSIZE_LONG: - dst = call(dst, (char *)m68k_write_long_highfirst); + dst = call(dst, opts->write_32_highfirst); break; } break; @@ -968,13 +972,13 @@ switch (inst->extra.size) { case OPSIZE_BYTE: - dst = call(dst, (char *)m68k_write_byte); + dst = call(dst, opts->write_8); break; case OPSIZE_WORD: - dst = call(dst, (char *)m68k_write_word); + dst = call(dst, opts->write_16); break; case OPSIZE_LONG: - dst = call(dst, (char *)m68k_write_long_highfirst); + dst = call(dst, opts->write_32_highfirst); break; } break; @@ -998,13 +1002,13 @@ switch (inst->extra.size) { case OPSIZE_BYTE: - dst = call(dst, (char *)m68k_write_byte); + dst = call(dst, opts->write_8); break; case OPSIZE_WORD: - dst = call(dst, (char *)m68k_write_word); + dst = call(dst, opts->write_16); break; case OPSIZE_LONG: - dst = call(dst, (char *)m68k_write_long_highfirst); + dst = call(dst, opts->write_32_highfirst); break; } break; @@ -1068,13 +1072,13 @@ switch (inst->extra.size) { case OPSIZE_BYTE: - dst = call(dst, (char *)m68k_write_byte); + dst = call(dst, opts->write_8); break; case OPSIZE_WORD: - dst = call(dst, (char *)m68k_write_word); + dst = call(dst, opts->write_16); break; case OPSIZE_LONG: - dst = call(dst, (char *)m68k_write_long_highfirst); + dst = call(dst, opts->write_32_highfirst); break; } break; @@ -1103,13 +1107,13 @@ switch (inst->extra.size) { case OPSIZE_BYTE: - dst = call(dst, (char *)m68k_write_byte); + dst = call(dst, opts->write_8); break; case OPSIZE_WORD: - dst = call(dst, (char *)m68k_write_word); + dst = call(dst, opts->write_16); break; case OPSIZE_LONG: - dst = call(dst, (char *)m68k_write_long_highfirst); + dst = call(dst, opts->write_32_highfirst); break; } break; @@ -1275,9 +1279,9 @@ } } if (inst->extra.size == OPSIZE_LONG) { - dst = call(dst, (uint8_t *)m68k_write_long_lowfirst); + dst = call(dst, opts->write_32_lowfirst); } else { - dst = call(dst, (uint8_t *)m68k_write_word); + dst = call(dst, opts->write_16); } dst = pop_r(dst, SCRATCH2); if (inst->dst.addr_mode != MODE_AREG_PREDEC) { @@ -1415,9 +1419,9 @@ if (inst->dst.params.immed & (1 << reg)) { dst = push_r(dst, SCRATCH1); if (inst->extra.size == OPSIZE_LONG) { - dst = call(dst, (uint8_t *)m68k_read_long_scratch1); + dst = call(dst, opts->read_32); } else { - dst = call(dst, (uint8_t *)m68k_read_word_scratch1); + dst = call(dst, opts->read_16); } if (inst->extra.size == OPSIZE_WORD) { dst = movsx_rr(dst, SCRATCH1, SCRATCH1, SZ_W, SZ_D); @@ -1737,7 +1741,7 @@ } dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); - dst = call(dst, (uint8_t *)m68k_write_long_lowfirst); + dst = call(dst, opts->write_32_lowfirst); return dst; } @@ -1753,7 +1757,7 @@ } dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); - dst = call(dst, (char *)m68k_write_long_highfirst); + dst = call(dst, opts->write_32_highfirst); uint8_t * dest_addr = get_native_address(opts->native_code_map, (inst->address+2) + disp); if (!dest_addr) { opts->deferred = defer_address(opts->deferred, (inst->address+2) + disp, dst + 1); @@ -2077,7 +2081,7 @@ } dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); - dst = call(dst, (char *)m68k_write_long_highfirst); + dst = call(dst, opts->write_32_highfirst); if (opts->aregs[inst->src.params.regs.pri] >= 0) { dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); } else { @@ -2100,7 +2104,7 @@ } dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); - dst = call(dst, (char *)m68k_write_long_highfirst); + dst = call(dst, opts->write_32_highfirst); if (opts->aregs[inst->src.params.regs.pri] >= 0) { dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); } else { @@ -2124,7 +2128,7 @@ } dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); - dst = call(dst, (char *)m68k_write_long_highfirst); + dst = call(dst, opts->write_32_highfirst); if (opts->aregs[inst->src.params.regs.pri] >= 0) { dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); } else { @@ -2182,7 +2186,7 @@ } dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); - dst = call(dst, (char *)m68k_write_long_highfirst); + dst = call(dst, opts->write_32_highfirst); m68k_addr = inst->src.params.regs.displacement + inst->address + 2; if ((m68k_addr & 0xFFFFFF) < 0x400000) { dest_addr = get_native_address(opts->native_code_map, m68k_addr); @@ -2218,7 +2222,7 @@ } dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); - dst = call(dst, (char *)m68k_write_long_highfirst); + dst = call(dst, opts->write_32_highfirst); dst = mov_ir(dst, inst->address+2, SCRATCH1, SZ_D); sec_reg = (inst->src.params.regs.sec >> 1) & 0x7; if (inst->src.params.regs.sec & 1) { @@ -2273,7 +2277,7 @@ } dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); - dst = call(dst, (char *)m68k_write_long_highfirst); + dst = call(dst, opts->write_32_highfirst); m68k_addr = inst->src.params.immed; if ((m68k_addr & 0xFFFFFF) < 0x400000) { dest_addr = get_native_address(opts->native_code_map, m68k_addr); @@ -2314,7 +2318,7 @@ //TODO: Add cycles dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); dst = add_ir(dst, 4, opts->aregs[7], SZ_D); - dst = call(dst, (char *)m68k_read_long_scratch1); + dst = call(dst, opts->read_32); if (opts->flags & OPT_NATIVE_CALL_STACK) { dst = cmp_rdisp8r(dst, RSP, 8, SCRATCH1, SZ_D); dst = jcc(dst, CC_NZ, dst+3); @@ -2420,7 +2424,7 @@ } else { dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_D); } - dst = call(dst, (char *)m68k_write_long_highfirst); + dst = call(dst, opts->write_32_highfirst); if (reg >= 0) { dst = mov_rr(dst, opts->aregs[7], reg, SZ_D); } else { @@ -2451,7 +2455,7 @@ dst = mov_rr(dst, reg, SCRATCH1, SZ_D); dst = shr_ir(dst, 24, SCRATCH1, SZ_D); dst = push_r(dst, SCRATCH2); - dst = call(dst, (uint8_t *)m68k_write_byte); + dst = call(dst, opts->write_8); dst = pop_r(dst, SCRATCH2); dst = mov_rr(dst, reg, SCRATCH1, SZ_D); dst = shr_ir(dst, 16, SCRATCH1, SZ_D); @@ -2459,13 +2463,13 @@ } else { dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src))+3, SCRATCH1, SZ_B); dst = push_r(dst, SCRATCH2); - dst = call(dst, (uint8_t *)m68k_write_byte); + dst = call(dst, opts->write_8); dst = pop_r(dst, SCRATCH2); dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src))+2, SCRATCH1, SZ_B); } dst = add_ir(dst, 2, SCRATCH2, SZ_D); dst = push_r(dst, SCRATCH2); - dst = call(dst, (uint8_t *)m68k_write_byte); + dst = call(dst, opts->write_8); dst = pop_r(dst, SCRATCH2); dst = add_ir(dst, 2, SCRATCH2, SZ_D); } @@ -2473,18 +2477,18 @@ dst = mov_rr(dst, reg, SCRATCH1, SZ_W); dst = shr_ir(dst, 8, SCRATCH1, SZ_W); dst = push_r(dst, SCRATCH2); - dst = call(dst, (uint8_t *)m68k_write_byte); + dst = call(dst, opts->write_8); dst = pop_r(dst, SCRATCH2); dst = mov_rr(dst, reg, SCRATCH1, SZ_W); } else { dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src))+1, SCRATCH1, SZ_B); dst = push_r(dst, SCRATCH2); - dst = call(dst, (uint8_t *)m68k_write_byte); + dst = call(dst, opts->write_8); dst = pop_r(dst, SCRATCH2); dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_B); } dst = add_ir(dst, 2, SCRATCH2, SZ_D); - dst = call(dst, (uint8_t *)m68k_write_byte); + dst = call(dst, opts->write_8); } else { if (opts->aregs[inst->src.params.regs.pri] >= 0) { dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); @@ -2498,43 +2502,43 @@ if (inst->extra.size == OPSIZE_LONG) { if (reg >= 0) { dst = push_r(dst, SCRATCH1); - dst = call(dst, (uint8_t *)m68k_read_byte_scratch1); + dst = call(dst, opts->read_8); dst = shl_ir(dst, 24, SCRATCH1, SZ_D); dst = mov_rr(dst, SCRATCH1, reg, SZ_D); dst = pop_r(dst, SCRATCH1); dst = add_ir(dst, 2, SCRATCH1, SZ_D); dst = push_r(dst, SCRATCH1); - dst = call(dst, (uint8_t *)m68k_read_byte_scratch1); + dst = call(dst, opts->read_8); dst = shl_ir(dst, 16, SCRATCH1, SZ_D); dst = or_rr(dst, SCRATCH1, reg, SZ_D); } else { dst = push_r(dst, SCRATCH1); - dst = call(dst, (uint8_t *)m68k_read_byte_scratch1); + dst = call(dst, opts->read_8); dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, reg_offset(&(inst->dst))+3, SZ_B); dst = pop_r(dst, SCRATCH1); dst = add_ir(dst, 2, SCRATCH1, SZ_D); dst = push_r(dst, SCRATCH1); - dst = call(dst, (uint8_t *)m68k_read_byte_scratch1); + dst = call(dst, opts->read_8); dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, reg_offset(&(inst->dst))+2, SZ_B); } dst = pop_r(dst, SCRATCH1); dst = add_ir(dst, 2, SCRATCH1, SZ_D); } dst = push_r(dst, SCRATCH1); - dst = call(dst, (uint8_t *)m68k_read_byte_scratch1); + dst = call(dst, opts->read_8); if (reg >= 0) { dst = shl_ir(dst, 8, SCRATCH1, SZ_W); dst = mov_rr(dst, SCRATCH1, reg, SZ_W); dst = pop_r(dst, SCRATCH1); dst = add_ir(dst, 2, SCRATCH1, SZ_D); - dst = call(dst, (uint8_t *)m68k_read_byte_scratch1); + dst = call(dst, opts->read_8); dst = mov_rr(dst, SCRATCH1, reg, SZ_B); } else { dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, reg_offset(&(inst->dst))+1, SZ_B); dst = pop_r(dst, SCRATCH1); dst = add_ir(dst, 2, SCRATCH1, SZ_D); - dst = call(dst, (uint8_t *)m68k_read_byte_scratch1); + dst = call(dst, opts->read_8); dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, reg_offset(&(inst->dst)), SZ_B); } } @@ -3711,12 +3715,12 @@ //TODO: Trap if not in system mode //Read saved SR dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); - dst = call(dst, (uint8_t *)m68k_read_word_scratch1); + dst = call(dst, opts->read_16); dst = add_ir(dst, 2, opts->aregs[7], SZ_D); dst = call(dst, (uint8_t *)set_sr); //Read saved PC dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); - dst = call(dst, (uint8_t *)m68k_read_long_scratch1); + dst = call(dst, opts->read_32); dst = add_ir(dst, 4, opts->aregs[7], SZ_D); //Check if we've switched to user mode and swap stack pointers if needed dst = bt_irdisp8(dst, 5, CONTEXT, offsetof(m68k_context, status), SZ_B); @@ -3733,12 +3737,12 @@ case M68K_RTR: //Read saved CCR dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); - dst = call(dst, (uint8_t *)m68k_read_word_scratch1); + dst = call(dst, opts->read_16); dst = add_ir(dst, 2, opts->aregs[7], SZ_D); dst = call(dst, (uint8_t *)set_ccr); //Read saved PC dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); - dst = call(dst, (uint8_t *)m68k_read_long_scratch1); + dst = call(dst, opts->read_32); dst = add_ir(dst, 4, opts->aregs[7], SZ_D); //Get native address and jump to it dst = call(dst, (uint8_t *)m68k_native_addr); @@ -3871,7 +3875,7 @@ dst = mov_rdisp8r(dst, dst_op.base, dst_op.disp, opts->aregs[7], SZ_D); } dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); - dst = call(dst, (uint8_t *)m68k_read_long_scratch1); + dst = call(dst, opts->read_32); if (dst_op.mode == MODE_REG_DIRECT) { dst = mov_rr(dst, SCRATCH1, dst_op.base, SZ_D); } else { @@ -4135,7 +4139,7 @@ start_68k_context(context, address); } -void init_x86_68k_opts(x86_68k_options * opts) +void init_x86_68k_opts(x86_68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks) { opts->flags = 0; for (int i = 0; i < 8; i++) @@ -4154,6 +4158,317 @@ opts->code_end = opts->cur_code + size; opts->ram_inst_sizes = malloc(sizeof(uint8_t *) * 64); memset(opts->ram_inst_sizes, 0, sizeof(uint8_t *) * 64); + uint8_t * dst = opts->read_16 = opts->cur_code; + dst = check_cycles(dst); + dst = cycles(dst, BUS); + dst = and_ir(dst, 0xFFFFFF, SCRATCH1, SZ_D); + uint8_t *lb_jcc = NULL, *ub_jcc = NULL; + for (uint32_t chunk = 0; chunk < num_chunks; chunk++) + { + if (lb_jcc) { + *lb_jcc = dst - (lb_jcc+1); + lb_jcc = NULL; + } + if (ub_jcc) { + *ub_jcc = dst - (ub_jcc+1); + ub_jcc = NULL; + } + if (memmap[chunk].start > 0) { + dst = cmp_ir(dst, memmap[chunk].start, SCRATCH1, SZ_D); + lb_jcc = dst + 1; + dst = jcc(dst, CC_C, dst+2); + } + if (memmap[chunk].end < 0x1000000) { + dst = cmp_ir(dst, memmap[chunk].end, SCRATCH1, SZ_D); + ub_jcc = dst + 1; + dst = jcc(dst, CC_NC, dst+2); + } + + if (memmap[chunk].mask != 0xFFFFFF) { + dst = and_ir(dst, memmap[chunk].mask, SCRATCH1, SZ_D); + } + + if (memmap[chunk].read_16) { + dst = call(dst, (uint8_t *)m68k_save_context); + dst = push_r(dst, CONTEXT); + dst = mov_rr(dst, SCRATCH1, RDI, SZ_D); + dst = call(dst, (uint8_t *)memmap[chunk].read_16); + dst = pop_r(dst, CONTEXT); + dst = mov_rr(dst, RAX, SCRATCH1, SZ_W); + dst = jmp(dst, (uint8_t *)m68k_load_context); + } else if(memmap[chunk].buffer && memmap[chunk].flags & MMAP_READ) { + if ((int64_t)memmap[chunk].buffer <= 0x7FFFFFFF && (int64_t)memmap[chunk].buffer >= -2147483648) { + dst = mov_rdisp32r(dst, SCRATCH1, (int64_t)memmap[chunk].buffer, SCRATCH1, SZ_W); + } else { + dst = mov_ir(dst, (int64_t)memmap[chunk].buffer, SCRATCH2, SZ_Q); + dst = mov_rindexr(dst, SCRATCH2, SCRATCH1, 1, SCRATCH1, SZ_W); + } + dst = retn(dst); + } else { + //Not sure the best course of action here + dst = mov_ir(dst, 0xFFFF, SCRATCH1, SZ_W); + dst = retn(dst); + } + } + if (lb_jcc) { + *lb_jcc = dst - (lb_jcc+1); + lb_jcc = NULL; + } + if (ub_jcc) { + *ub_jcc = dst - (ub_jcc+1); + ub_jcc = NULL; + } + dst = mov_ir(dst, 0xFFFF, SCRATCH1, SZ_W); + dst = retn(dst); + + opts->write_16 = dst; + dst = check_cycles(dst); + dst = cycles(dst, BUS); + dst = and_ir(dst, 0xFFFFFF, SCRATCH2, SZ_D); + for (uint32_t chunk = 0; chunk < num_chunks; chunk++) + { + if (lb_jcc) { + *lb_jcc = dst - (lb_jcc+1); + lb_jcc = NULL; + } + if (ub_jcc) { + *ub_jcc = dst - (ub_jcc+1); + ub_jcc = NULL; + } + if (memmap[chunk].start > 0) { + dst = cmp_ir(dst, memmap[chunk].start, SCRATCH2, SZ_D); + lb_jcc = dst + 1; + dst = jcc(dst, CC_C, dst+2); + } + if (memmap[chunk].end < 0x1000000) { + dst = cmp_ir(dst, memmap[chunk].end, SCRATCH2, SZ_D); + ub_jcc = dst + 1; + dst = jcc(dst, CC_NC, dst+2); + } + + if (memmap[chunk].mask != 0xFFFFFF) { + dst = and_ir(dst, memmap[chunk].mask, SCRATCH2, SZ_D); + } + + if (memmap[chunk].write_16) { + dst = call(dst, (uint8_t *)m68k_save_context); + //SCRATCH2 is RDI, so no need to move it there + dst = mov_rr(dst, SCRATCH1, RDX, SZ_W); + dst = call(dst, (uint8_t *)memmap[chunk].write_16); + dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); + dst = jmp(dst, (uint8_t *)m68k_load_context); + } else if(memmap[chunk].buffer && memmap[chunk].flags & MMAP_WRITE) { + if ((int64_t)memmap[chunk].buffer <= 0x7FFFFFFF && (int64_t)memmap[chunk].buffer >= -2147483648) { + dst = mov_rrdisp32(dst, SCRATCH1, SCRATCH2, (int64_t)memmap[chunk].buffer, SZ_W); + } else { + dst = push_r(dst, SCRATCH1); + dst = mov_ir(dst, (int64_t)memmap[chunk].buffer, SCRATCH1, SZ_Q); + dst = add_rr(dst, SCRATCH1, SCRATCH2, SZ_Q); + dst = pop_r(dst, SCRATCH1); + dst = mov_rrind(dst, SCRATCH1, SCRATCH2, SZ_W); + } + if (memmap[chunk].flags & MMAP_CODE) { + dst = mov_rr(dst, SCRATCH2, SCRATCH1, SZ_D); + dst = shr_ir(dst, 11, SCRATCH1, SZ_D); + dst = bt_rrdisp32(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, ram_code_flags), SZ_D); + uint8_t * not_code = dst+1; + dst = jcc(dst, CC_NC, dst+2); + dst = call(dst, (uint8_t *)m68k_save_context); + dst = call(dst, (uint8_t *)m68k_handle_code_write); + dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); + dst = call(dst, (uint8_t *)m68k_load_context); + *not_code = dst - (not_code+1); + } + dst = retn(dst); + } else { + //Not sure the best course of action here + dst = retn(dst); + } + } + if (lb_jcc) { + *lb_jcc = dst - (lb_jcc+1); + lb_jcc = NULL; + } + if (ub_jcc) { + *ub_jcc = dst - (ub_jcc+1); + ub_jcc = NULL; + } + dst = retn(dst); + + opts->read_8 = dst; + dst = check_cycles(dst); + dst = cycles(dst, BUS); + dst = and_ir(dst, 0xFFFFFF, SCRATCH1, SZ_D); + for (uint32_t chunk = 0; chunk < num_chunks; chunk++) + { + if (lb_jcc) { + *lb_jcc = dst - (lb_jcc+1); + lb_jcc = NULL; + } + if (ub_jcc) { + *ub_jcc = dst - (ub_jcc+1); + ub_jcc = NULL; + } + if (memmap[chunk].start > 0) { + dst = cmp_ir(dst, memmap[chunk].start, SCRATCH1, SZ_D); + lb_jcc = dst + 1; + dst = jcc(dst, CC_C, dst+2); + } + if (memmap[chunk].end < 0x1000000) { + dst = cmp_ir(dst, memmap[chunk].end, SCRATCH1, SZ_D); + ub_jcc = dst + 1; + dst = jcc(dst, CC_NC, dst+2); + } + + if (memmap[chunk].mask != 0xFFFFFF) { + dst = and_ir(dst, memmap[chunk].mask, SCRATCH1, SZ_D); + } + + if (memmap[chunk].read_8) { + dst = call(dst, (uint8_t *)m68k_save_context); + dst = push_r(dst, CONTEXT); + dst = mov_rr(dst, SCRATCH1, RDI, SZ_D); + dst = call(dst, (uint8_t *)memmap[chunk].read_8); + dst = pop_r(dst, CONTEXT); + dst = mov_rr(dst, RAX, SCRATCH1, SZ_B); + dst = jmp(dst, (uint8_t *)m68k_load_context); + } else if(memmap[chunk].buffer && memmap[chunk].flags & MMAP_READ) { + dst = xor_ir(dst, 1, SCRATCH1, SZ_D); + if ((int64_t)memmap[chunk].buffer <= 0x7FFFFFFF && (int64_t)memmap[chunk].buffer >= -2147483648) { + dst = mov_rdisp32r(dst, SCRATCH1, (int64_t)memmap[chunk].buffer, SCRATCH1, SZ_B); + } else { + dst = mov_ir(dst, (int64_t)memmap[chunk].buffer, SCRATCH2, SZ_Q); + dst = mov_rindexr(dst, SCRATCH2, SCRATCH1, 1, SCRATCH1, SZ_B); + } + dst = retn(dst); + } else { + //Not sure the best course of action here + dst = mov_ir(dst, 0xFF, SCRATCH1, SZ_B); + dst = retn(dst); + } + } + if (lb_jcc) { + *lb_jcc = dst - (lb_jcc+1); + lb_jcc = NULL; + } + if (ub_jcc) { + *ub_jcc = dst - (ub_jcc+1); + ub_jcc = NULL; + } + dst = mov_ir(dst, 0xFFFF, SCRATCH1, SZ_W); + dst = retn(dst); + + opts->write_8 = dst; + dst = check_cycles(dst); + dst = cycles(dst, BUS); + dst = and_ir(dst, 0xFFFFFF, SCRATCH2, SZ_D); + for (uint32_t chunk = 0; chunk < num_chunks; chunk++) + { + if (lb_jcc) { + *lb_jcc = dst - (lb_jcc+1); + lb_jcc = NULL; + } + if (ub_jcc) { + *ub_jcc = dst - (ub_jcc+1); + ub_jcc = NULL; + } + if (memmap[chunk].start > 0) { + dst = cmp_ir(dst, memmap[chunk].start, SCRATCH2, SZ_D); + lb_jcc = dst + 1; + dst = jcc(dst, CC_C, dst+2); + } + if (memmap[chunk].end < 0x1000000) { + dst = cmp_ir(dst, memmap[chunk].end, SCRATCH2, SZ_D); + ub_jcc = dst + 1; + dst = jcc(dst, CC_NC, dst+2); + } + + if (memmap[chunk].mask != 0xFFFFFF) { + dst = and_ir(dst, memmap[chunk].mask, SCRATCH2, SZ_D); + } + + if (memmap[chunk].write_8) { + dst = call(dst, (uint8_t *)m68k_save_context); + //SCRATCH2 is RDI, so no need to move it there + dst = mov_rr(dst, SCRATCH1, RDX, SZ_B); + dst = call(dst, (uint8_t *)memmap[chunk].write_8); + dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); + dst = jmp(dst, (uint8_t *)m68k_load_context); + } else if(memmap[chunk].buffer && memmap[chunk].flags & MMAP_WRITE) { + dst = xor_ir(dst, 1, SCRATCH2, SZ_D); + if ((int64_t)memmap[chunk].buffer <= 0x7FFFFFFF && (int64_t)memmap[chunk].buffer >= -2147483648) { + dst = mov_rrdisp32(dst, SCRATCH1, SCRATCH2, (int64_t)memmap[chunk].buffer, SZ_B); + } else { + dst = push_r(dst, SCRATCH1); + dst = mov_ir(dst, (int64_t)memmap[chunk].buffer, SCRATCH1, SZ_Q); + dst = add_rr(dst, SCRATCH1, SCRATCH2, SZ_Q); + dst = pop_r(dst, SCRATCH1); + dst = mov_rrind(dst, SCRATCH1, SCRATCH2, SZ_B); + } + if (memmap[chunk].flags & MMAP_CODE) { + dst = mov_rr(dst, SCRATCH2, SCRATCH1, SZ_D); + dst = shr_ir(dst, 11, SCRATCH1, SZ_D); + dst = bt_rrdisp32(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, ram_code_flags), SZ_D); + uint8_t * not_code = dst+1; + dst = jcc(dst, CC_NC, dst+2); + dst = xor_ir(dst, 1, SCRATCH2, SZ_D); + dst = call(dst, (uint8_t *)m68k_save_context); + dst = call(dst, (uint8_t *)m68k_handle_code_write); + dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); + dst = call(dst, (uint8_t *)m68k_load_context); + *not_code = dst - (not_code+1); + } + dst = retn(dst); + } else { + //Not sure the best course of action here + dst = retn(dst); + } + } + if (lb_jcc) { + *lb_jcc = dst - (lb_jcc+1); + lb_jcc = NULL; + } + if (ub_jcc) { + *ub_jcc = dst - (ub_jcc+1); + ub_jcc = NULL; + } + dst = retn(dst); + + opts->read_32 = dst; + dst = push_r(dst, SCRATCH1); + dst = call(dst, opts->read_16); + dst = mov_rr(dst, SCRATCH1, SCRATCH2, SZ_W); + dst = pop_r(dst, SCRATCH1); + dst = push_r(dst, SCRATCH2); + dst = add_ir(dst, 2, SCRATCH1, SZ_D); + dst = call(dst, opts->read_16); + dst = pop_r(dst, SCRATCH2); + dst = movzx_rr(dst, SCRATCH1, SCRATCH1, SZ_W, SZ_D); + dst = shl_ir(dst, 16, SCRATCH2, SZ_D); + dst = or_rr(dst, SCRATCH2, SCRATCH1, SZ_D); + dst = retn(dst); + + opts->write_32_lowfirst = dst; + dst = push_r(dst, SCRATCH2); + dst = push_r(dst, SCRATCH1); + dst = add_ir(dst, 2, SCRATCH2, SZ_D); + dst = call(dst, opts->write_16); + dst = pop_r(dst, SCRATCH1); + dst = pop_r(dst, SCRATCH2); + dst = shr_ir(dst, 16, SCRATCH1, SZ_D); + dst = jmp(dst, opts->write_16); + + opts->write_32_highfirst = dst; + dst = push_r(dst, SCRATCH1); + dst = push_r(dst, SCRATCH2); + dst = shr_ir(dst, 16, SCRATCH1, SZ_D); + dst = call(dst, opts->write_16); + dst = pop_r(dst, SCRATCH2); + dst = pop_r(dst, SCRATCH1); + dst = add_ir(dst, 2, SCRATCH2, SZ_D); + dst = jmp(dst, opts->write_16); + + opts->cur_code = dst; } void init_68k_context(m68k_context * context, native_map_slot * native_code_map, void * opts) diff -r 13f994c88c34 -r 467bfa17004a m68k_to_x86.h --- a/m68k_to_x86.h Thu May 16 09:37:53 2013 -0700 +++ b/m68k_to_x86.h Sat May 18 11:44:42 2013 -0700 @@ -23,6 +23,13 @@ uint8_t *code_end; uint8_t **ram_inst_sizes; FILE *address_log; + uint8_t *read_16; + uint8_t *write_16; + uint8_t *read_8; + uint8_t *write_8; + uint8_t *read_32; + uint8_t *write_32_lowfirst; + uint8_t *write_32_highfirst; } x86_68k_options; typedef struct { @@ -38,7 +45,7 @@ uint32_t int_num; uint16_t *mem_pointers[NUM_MEM_AREAS]; void *video_context; - uint16_t value; + uint16_t reserved; native_map_slot *native_code_map; void *options; @@ -49,7 +56,7 @@ uint8_t * translate_m68k(uint8_t * dst, struct m68kinst * inst, x86_68k_options * opts); uint8_t * translate_m68k_stream(uint32_t address, m68k_context * context); void start_68k_context(m68k_context * context, uint32_t address); -void init_x86_68k_opts(x86_68k_options * opts); +void init_x86_68k_opts(x86_68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks); void init_68k_context(m68k_context * context, native_map_slot * native_code_map, void * opts); void m68k_reset(m68k_context * context); void insert_breakpoint(m68k_context * context, uint32_t address, uint8_t * bp_handler); diff -r 13f994c88c34 -r 467bfa17004a runtime.S --- a/runtime.S Thu May 16 09:37:53 2013 -0700 +++ b/runtime.S Sat May 18 11:44:42 2013 -0700 @@ -5,12 +5,16 @@ cmp 84(%rsi), %eax jb skip_sync do_sync: + push %rcx + push %rdi call m68k_save_context mov %rsi, %rdi xor %esi, %esi call sync_components mov %rax, %rsi call m68k_load_context + pop %rdi + pop %rcx skip_sync: ret @@ -271,10 +275,11 @@ do_vdp_port_read: mov %ecx, %edi call m68k_save_context + push %rsi call vdp_port_read - mov %rax, %rsi + pop %rsi + mov %ax, %cx call m68k_load_context - mov 136(%rsi), %cx ret do_io_write: @@ -289,10 +294,11 @@ mov %ecx, %edi and $0x1FFFF, %edi call m68k_save_context + push %rsi call io_read - mov %rax, %rsi + pop %rsi + mov %al, %cl call m68k_load_context - mov 136(%rsi), %cl ret do_io_write_w: @@ -307,10 +313,11 @@ mov %ecx, %edi and $0x1FFFF, %edi call m68k_save_context + push %rsi call io_read_w - mov %rax, %rsi + pop %rsi + mov %ax, %cx call m68k_load_context - mov 136(%rsi), %cx ret bad_access_msg: @@ -479,8 +486,7 @@ add $4, %eax ret do_limit: - push %rcx - push %rdi + call handle_cycle_limit pop %rdi pop %rcx diff -r 13f994c88c34 -r 467bfa17004a x86_backend.h --- a/x86_backend.h Thu May 16 09:37:53 2013 -0700 +++ b/x86_backend.h Sat May 18 11:44:42 2013 -0700 @@ -25,6 +25,30 @@ uint32_t address; } deferred_addr; + +#define MMAP_READ 0x1 +#define MMAP_WRITE 0x2 +#define MMAP_CODE 0x4 +#define MMAP_PTR_IDX 0x8 + +typedef uint16_t (*read_16_fun)(uint32_t address, void * context); +typedef uint8_t (*read_8_fun)(uint32_t address, void * context); +typedef void * (*write_16_fun)(uint32_t address, void * context, uint16_t value); +typedef void * (*write_8_fun)(uint32_t address, void * context, uint8_t value); + +typedef struct { + uint32_t start; + uint32_t end; + uint32_t mask; + uint16_t ptr_index; + uint16_t flags; + void * buffer; + read_16_fun read_16; + write_16_fun write_16; + read_8_fun read_8; + write_8_fun write_8; +} memmap_chunk; + typedef uint8_t * (*native_addr_func)(void * context, uint32_t address); deferred_addr * defer_address(deferred_addr * old_head, uint32_t address, uint8_t *dest);