summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--blastem.c131
-rw-r--r--gen_x86.c156
-rw-r--r--gen_x86.h7
-rw-r--r--m68k_to_x86.c509
-rw-r--r--m68k_to_x86.h11
-rw-r--r--runtime.S22
-rw-r--r--x86_backend.h24
7 files changed, 709 insertions, 151 deletions
diff --git a/blastem.c b/blastem.c
index 13afd26..8ea6b01 100644
--- a/blastem.c
+++ b/blastem.c
@@ -235,12 +235,18 @@ m68k_context * sync_components(m68k_context * context, uint32_t address)
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 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_
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 @@ void io_data_write(io_port * pad, m68k_context * context, uint8_t value)
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 @@ void io_data_read(io_port * pad, m68k_context * context)
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 @@ m68k_context * io_write_w(uint32_t location, m68k_context * context, uint16_t va
#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,15 @@ m68k_context * io_read(uint32_t location, m68k_context * context)
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 {
- context->value = 0xFF;
+ value = 0xFF;
}
} else {
location &= 0x1FFF;
@@ -624,23 +653,24 @@ m68k_context * io_read(uint32_t location, m68k_context * context)
{
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;
+ default:
+ value = 0xFF;
}
} else {
if (location == 0x1100) {
@@ -648,20 +678,22 @@ m68k_context * io_read(uint32_t location, m68k_context * context)
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;
+ 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) {
- context->value = !reset;
+ value = !reset;
} else {
+ value = 0xFF;
printf("Byte read of unknown IO location: %X\n", location);
}
}
}
- return context;
+ return value;
}
-m68k_context * io_read_w(uint32_t location, m68k_context * context)
+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) {
@@ -670,7 +702,6 @@ m68k_context * io_read_w(uint32_t location, m68k_context * context)
}
if (!(busack==Z80_REQ_BUSY || reset)) {
location &= 0x7FFF;
- uint16_t value;
if (location < 0x4000) {
value = z80_ram[location & 0x1FFE];
} else if (location < 0x6000) {
@@ -679,9 +710,9 @@ m68k_context * io_read_w(uint32_t location, m68k_context * context)
} else {
value = 0xFF;
}
- context->value = value | (value << 8);
+ value = value | (value << 8);
} else {
- context->value = 0xFFFF;
+ value = 0xFFFF;
}
} else {
location &= 0x1FFF;
@@ -691,45 +722,47 @@ m68k_context * io_read_w(uint32_t location, m68k_context * context)
case 0x0:
//version bits should be 0 for now since we're not emulating TMSS
//Not sure about the other bits
- context->value = 0;
+ 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
- context->value = 0;
+ value = 0;
break;
+ default:
+ value = 0;
}
- context->value = context->value | (context->value << 8);
- //printf("Word read to %X returned %d\n", location, context->value);
+ 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) << 8;
- //printf("Word read of BUSREQ returned %d\n", context->value);
+ value = (Z80_RES_BUSACK || busack) << 8;
+ //printf("Word read of BUSREQ returned %d\n", 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 @@ void init_run_cpu(genesis_context * gen, int debug, FILE * address_log)
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 @@ int detect_specific_region(char region)
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 --git a/gen_x86.c b/gen_x86.c
index 3439a32..4733e73 100644
--- a/gen_x86.c
+++ b/gen_x86.c
@@ -2,6 +2,7 @@
#include "68kinst.h"
#include <stddef.h>
#include <stdio.h>
+#include <stdlib.h>
#define REX_RM_FIELD 0x1
#define REX_SIB_FIELD 0x2
@@ -220,6 +221,58 @@ uint8_t * x86_rrdisp8_sizedir(uint8_t * out, uint16_t opcode, uint8_t reg, uint8
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 @@ uint8_t * x86_rrind_sizedir(uint8_t * out, uint8_t opcode, uint8_t reg, uint8_t
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 @@ uint8_t * mov_rdisp8r(uint8_t * out, uint8_t src_base, int8_t disp, uint8_t dst,
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 @@ uint8_t * mov_rindr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
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 @@ uint8_t * bit_rrdisp8(uint8_t * out, uint8_t op2, uint8_t src, uint8_t dst_base,
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 @@ uint8_t * bt_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t dst_di
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 --git a/gen_x86.h b/gen_x86.h
index bbf085f..74cb4f3 100644
--- a/gen_x86.h
+++ b/gen_x86.h
@@ -57,7 +57,7 @@ enum {
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 * idiv_rdisp8(uint8_t * out, uint8_t dst_base, int8_t disp, uint8_t size
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_rind(uint8_t * out, uint8_t cc, uint8_t dst);
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 --git a/m68k_to_x86.c b/m68k_to_x86.c
index e99f167..3896ba6 100644
--- a/m68k_to_x86.c
+++ b/m68k_to_x86.c
@@ -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 @@ uint8_t * check_cycles_int(uint8_t * dst, uint32_t address)
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 @@ uint8_t * translate_m68k_src(m68kinst * inst, x86_ea * ea, uint8_t * out, x86_68
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 @@ uint8_t * translate_m68k_src(m68kinst * inst, x86_ea * ea, uint8_t * out, x86_68
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 @@ uint8_t * translate_m68k_src(m68kinst * inst, x86_ea * ea, uint8_t * out, x86_68
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 @@ uint8_t * translate_m68k_src(m68kinst * inst, x86_ea * ea, uint8_t * out, x86_68
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 @@ uint8_t * translate_m68k_src(m68kinst * inst, x86_ea * ea, uint8_t * out, x86_68
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 @@ uint8_t * translate_m68k_src(m68kinst * inst, x86_ea * ea, uint8_t * out, x86_68
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 @@ uint8_t * translate_m68k_dst(m68kinst * inst, x86_ea * ea, uint8_t * out, x86_68
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 @@ uint8_t * translate_m68k_dst(m68kinst * inst, x86_ea * ea, uint8_t * out, x86_68
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 @@ uint8_t * translate_m68k_dst(m68kinst * inst, x86_ea * ea, uint8_t * out, x86_68
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 @@ uint8_t * translate_m68k_dst(m68kinst * inst, x86_ea * ea, uint8_t * out, x86_68
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 @@ uint8_t * translate_m68k_dst(m68kinst * inst, x86_ea * ea, uint8_t * out, x86_68
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 @@ uint8_t * translate_m68k_dst(m68kinst * inst, x86_ea * ea, uint8_t * out, x86_68
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 @@ uint8_t * m68k_save_result(m68kinst * inst, uint8_t * out, x86_68k_options * opt
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 @@ uint8_t * translate_m68k_move(uint8_t * dst, m68kinst * inst, x86_68k_options *
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 @@ uint8_t * translate_m68k_move(uint8_t * dst, m68kinst * inst, x86_68k_options *
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 @@ uint8_t * translate_m68k_move(uint8_t * dst, m68kinst * inst, x86_68k_options *
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 @@ uint8_t * translate_m68k_move(uint8_t * dst, m68kinst * inst, x86_68k_options *
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 @@ uint8_t * translate_m68k_move(uint8_t * dst, m68kinst * inst, x86_68k_options *
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 @@ uint8_t * translate_m68k_move(uint8_t * dst, m68kinst * inst, x86_68k_options *
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 @@ uint8_t * translate_m68k_movem(uint8_t * dst, m68kinst * inst, x86_68k_options *
}
}
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 @@ uint8_t * translate_m68k_movem(uint8_t * dst, m68kinst * inst, x86_68k_options *
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 @@ uint8_t * translate_m68k_pea(uint8_t * dst, m68kinst * inst, x86_68k_options * o
}
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 @@ uint8_t * translate_m68k_bsr(uint8_t * dst, m68kinst * inst, x86_68k_options * o
}
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 @@ uint8_t * translate_m68k_jsr(uint8_t * dst, m68kinst * inst, x86_68k_options * o
}
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 @@ uint8_t * translate_m68k_jsr(uint8_t * dst, m68kinst * inst, x86_68k_options * o
}
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 @@ uint8_t * translate_m68k_jsr(uint8_t * dst, m68kinst * inst, x86_68k_options * o
}
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 @@ uint8_t * translate_m68k_jsr(uint8_t * dst, m68kinst * inst, x86_68k_options * o
}
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 @@ uint8_t * translate_m68k_jsr(uint8_t * dst, m68kinst * inst, x86_68k_options * o
}
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 @@ uint8_t * translate_m68k_jsr(uint8_t * dst, m68kinst * inst, x86_68k_options * o
}
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 @@ uint8_t * translate_m68k_rts(uint8_t * dst, m68kinst * inst, x86_68k_options * o
//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 @@ uint8_t * translate_m68k_link(uint8_t * dst, m68kinst * inst, x86_68k_options *
} 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 @@ uint8_t * translate_m68k_movep(uint8_t * dst, m68kinst * inst, x86_68k_options *
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 @@ uint8_t * translate_m68k_movep(uint8_t * dst, m68kinst * inst, x86_68k_options *
} 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 @@ uint8_t * translate_m68k_movep(uint8_t * dst, m68kinst * inst, x86_68k_options *
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 @@ uint8_t * translate_m68k_movep(uint8_t * dst, m68kinst * inst, x86_68k_options *
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 @@ uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
//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 @@ uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
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 @@ uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
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 @@ void m68k_reset(m68k_context * context)
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 @@ void init_x86_68k_opts(x86_68k_options * opts)
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 --git a/m68k_to_x86.h b/m68k_to_x86.h
index 3a8e08d..1dbef16 100644
--- a/m68k_to_x86.h
+++ b/m68k_to_x86.h
@@ -23,6 +23,13 @@ typedef struct {
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 @@ typedef struct {
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 @@ typedef struct {
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 --git a/runtime.S b/runtime.S
index c07b003..2083e0a 100644
--- a/runtime.S
+++ b/runtime.S
@@ -5,12 +5,16 @@ handle_cycle_limit:
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_write:
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 @@ do_io_read:
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 @@ do_io_read_w:
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 @@ inccycles:
add $4, %eax
ret
do_limit:
- push %rcx
- push %rdi
+
call handle_cycle_limit
pop %rdi
pop %rcx
diff --git a/x86_backend.h b/x86_backend.h
index f29200c..35f4494 100644
--- a/x86_backend.h
+++ b/x86_backend.h
@@ -25,6 +25,30 @@ typedef struct deferred_addr {
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);