summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Pavone <pavone@retrodev.com>2015-01-01 14:36:55 -0800
committerMichael Pavone <pavone@retrodev.com>2015-01-01 14:36:55 -0800
commitec4eed4f35910aa27ca353fceea38155806ef188 (patch)
tree584f2856096548fca66984e84649ee5db2ea7500
parentfd85c8d7a74d44f169db4a51a600295042682ee8 (diff)
Remove some of the hard coded assumptions about the memory map from the CPU cores
-rw-r--r--backend.c21
-rw-r--r--backend.h56
-rw-r--r--m68k_core.c39
-rw-r--r--m68k_core.h2
-rw-r--r--m68k_core_x86.c6
-rw-r--r--z80_to_x86.c157
6 files changed, 119 insertions, 162 deletions
diff --git a/backend.c b/backend.c
index eaae9d7..86bc4b5 100644
--- a/backend.c
+++ b/backend.c
@@ -51,3 +51,24 @@ void process_deferred(deferred_addr ** head_ptr, void * context, native_addr_fun
}
}
+void * get_native_pointer(uint32_t address, void ** mem_pointers, cpu_options * opts)
+{
+ memmap_chunk * memmap = opts->memmap;
+ address &= opts->address_mask;
+ for (uint32_t chunk = 0; chunk < opts->memmap_chunks; chunk++)
+ {
+ if (address >= memmap[chunk].start && address < memmap[chunk].end) {
+ if (!(memmap[chunk].flags & MMAP_READ)) {
+ return NULL;
+ }
+ uint8_t * base = memmap[chunk].flags & MMAP_PTR_IDX
+ ? mem_pointers[memmap[chunk].ptr_index]
+ : memmap[chunk].buffer;
+ if (!base) {
+ return NULL;
+ }
+ return base + (address & memmap[chunk].mask);
+ }
+ }
+ return NULL;
+}
diff --git a/backend.h b/backend.h
index 18c3752..c3e0c76 100644
--- a/backend.h
+++ b/backend.h
@@ -46,33 +46,6 @@ typedef enum {
WRITE_8
} ftype;
-typedef struct {
- uint32_t flags;
- native_map_slot *native_code_map;
- deferred_addr *deferred;
- code_info code;
- uint8_t **ram_inst_sizes;
- code_ptr save_context;
- code_ptr load_context;
- code_ptr handle_cycle_limit;
- code_ptr handle_cycle_limit_int;
- code_ptr handle_code_write;
- uint32_t address_mask;
- uint32_t max_address;
- uint32_t bus_cycles;
- int32_t mem_ptr_off;
- int32_t ram_flags_off;
- uint8_t ram_flags_shift;
- uint8_t address_size;
- uint8_t byte_swap;
- uint8_t context_reg;
- uint8_t cycles;
- uint8_t limit;
- uint8_t scratch1;
- uint8_t scratch2;
-} cpu_options;
-
-
#define MMAP_READ 0x01
#define MMAP_WRITE 0x02
#define MMAP_CODE 0x04
@@ -100,6 +73,34 @@ typedef struct {
write_8_fun write_8;
} memmap_chunk;
+typedef struct {
+ uint32_t flags;
+ native_map_slot *native_code_map;
+ deferred_addr *deferred;
+ code_info code;
+ uint8_t **ram_inst_sizes;
+ memmap_chunk const *memmap;
+ code_ptr save_context;
+ code_ptr load_context;
+ code_ptr handle_cycle_limit;
+ code_ptr handle_cycle_limit_int;
+ code_ptr handle_code_write;
+ uint32_t memmap_chunks;
+ uint32_t address_mask;
+ uint32_t max_address;
+ uint32_t bus_cycles;
+ int32_t mem_ptr_off;
+ int32_t ram_flags_off;
+ uint8_t ram_flags_shift;
+ uint8_t address_size;
+ uint8_t byte_swap;
+ uint8_t context_reg;
+ uint8_t cycles;
+ uint8_t limit;
+ uint8_t scratch1;
+ uint8_t scratch2;
+} cpu_options;
+
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);
@@ -112,6 +113,7 @@ void check_cycles(cpu_options * opts);
void check_code_prologue(code_info *code);
code_ptr gen_mem_fun(cpu_options * opts, memmap_chunk const * memmap, uint32_t num_chunks, ftype fun_type, code_ptr *after_inc);
+void * get_native_pointer(uint32_t address, void ** mem_pointers, cpu_options * opts);
#endif //BACKEND_H_
diff --git a/m68k_core.c b/m68k_core.c
index 7fc31e3..1c0e65d 100644
--- a/m68k_core.c
+++ b/m68k_core.c
@@ -754,26 +754,17 @@ void translate_m68k_stream(uint32_t address, m68k_context * context)
m68kinst instbuf;
m68k_options * opts = context->options;
code_info *code = &opts->gen.code;
- address &= 0xFFFFFF;
if(get_native_address(opts->gen.native_code_map, address)) {
return;
}
- char disbuf[1024];
uint16_t *encoded, *next;
- if ((address & 0xFFFFFF) < 0x400000) {
- encoded = context->mem_pointers[0] + (address & 0xFFFFFF)/2;
- } else if ((address & 0xFFFFFF) > 0xE00000) {
- encoded = context->mem_pointers[1] + (address & 0xFFFF)/2;
- } else {
- printf("attempt to translate non-memory address: %X\n", address);
- exit(1);
- }
do {
if (opts->address_log) {
fprintf(opts->address_log, "%X\n", address);
}
do {
- if (address >= 0x400000 && address < 0xE00000) {
+ encoded = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen);
+ if (!encoded) {
translate_out_of_bounds(code);
break;
}
@@ -788,7 +779,7 @@ void translate_m68k_stream(uint32_t address, m68k_context * context)
}
uint16_t m68k_size = (next-encoded)*2;
address += m68k_size;
- encoded = next;
+ //char disbuf[1024];
//m68k_disasm(&instbuf, disbuf);
//printf("%X: %s\n", instbuf.address, disbuf);
@@ -802,18 +793,8 @@ void translate_m68k_stream(uint32_t address, m68k_context * context)
process_deferred(&opts->gen.deferred, context, (native_addr_func)get_native_from_context);
if (opts->gen.deferred) {
address = opts->gen.deferred->address;
- if ((address & 0xFFFFFF) < 0x400000) {
- encoded = context->mem_pointers[0] + (address & 0xFFFFFF)/2;
- } else if ((address & 0xFFFFFF) > 0xE00000) {
- encoded = context->mem_pointers[1] + (address & 0xFFFF)/2;
- } else {
- printf("attempt to translate non-memory address: %X\n", address);
- exit(1);
- }
- } else {
- encoded = NULL;
}
- } while(encoded != NULL);
+ } while(opts->gen.deferred);
}
void * m68k_retranslate_inst(uint32_t address, m68k_context * context)
@@ -826,8 +807,7 @@ void * m68k_retranslate_inst(uint32_t address, m68k_context * context)
code_info orig_code;
orig_code.cur = orig_start;
orig_code.last = orig_start + orig_size + 5;
- address &= 0xFFFF;
- uint16_t *after, *inst = context->mem_pointers[1] + address/2;
+ uint16_t *after, *inst = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen);
m68kinst instbuf;
after = m68k_decode(inst, &instbuf, orig);
if (orig_size != MAX_NATIVE_SIZE) {
@@ -910,7 +890,7 @@ code_ptr get_native_address_trans(m68k_context * context, uint32_t address)
void remove_breakpoint(m68k_context * context, uint32_t address)
{
code_ptr native = get_native_address(context->native_code_map, address);
- check_cycles_int(context->options, address);
+ check_cycles_int(&context->options->gen, address);
}
void start_68k_context(m68k_context * context, uint32_t address)
@@ -922,9 +902,10 @@ void start_68k_context(m68k_context * context, uint32_t address)
void m68k_reset(m68k_context * context)
{
- //TODO: Make this actually use the normal read functions
- context->aregs[7] = context->mem_pointers[0][0] << 16 | context->mem_pointers[0][1];
- uint32_t address = context->mem_pointers[0][2] << 16 | context->mem_pointers[0][3];
+ //TODO: Actually execute the M68K reset vector rather than simulating some of its behavior
+ uint16_t *reset_vec = get_native_pointer(0, (void **)context->mem_pointers, &context->options->gen);
+ context->aregs[7] = reset_vec[0] << 16 | reset_vec[1];
+ uint32_t address = reset_vec[2] << 16 | reset_vec[3];
start_68k_context(context, address);
}
diff --git a/m68k_core.h b/m68k_core.h
index 370aa1e..31ca320 100644
--- a/m68k_core.h
+++ b/m68k_core.h
@@ -59,7 +59,7 @@ typedef struct {
uint16_t reserved;
native_map_slot *native_code_map;
- void *options;
+ m68k_options *options;
uint8_t ram_code_flags[32/8];
void *system;
} m68k_context;
diff --git a/m68k_core_x86.c b/m68k_core_x86.c
index 7e97886..c0964bd 100644
--- a/m68k_core_x86.c
+++ b/m68k_core_x86.c
@@ -1464,7 +1464,7 @@ void translate_m68k_abcd_sbcd(m68k_options *opts, m68kinst *inst, host_ea *src_o
set_flag_cond(opts, CC_O, FLAG_V);
*no_adjust = code->cur - (no_adjust+1);
flag_to_flag(opts, FLAG_C, FLAG_X);
-
+
cmp_ir(code, 0, opts->gen.scratch1, SZ_B);
set_flag_cond(opts, CC_S, FLAG_N);
jcc(code, CC_Z, code->cur + 4);
@@ -1664,7 +1664,7 @@ void translate_m68k_div(m68k_options *opts, m68kinst *inst, host_ea *src_op, hos
case MODE_ABSOLUTE_SHORT:
case MODE_PC_INDEX_DISP8:
case MODE_IMMEDIATE:
- isize = 4;
+ isize = 4;
break;
case MODE_ABSOLUTE:
isize = 6;
@@ -2230,6 +2230,8 @@ void insert_breakpoint(m68k_context * context, uint32_t address, code_ptr bp_han
void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks)
{
memset(opts, 0, sizeof(*opts));
+ opts->gen.memmap = memmap;
+ opts->gen.memmap_chunks = num_chunks;
opts->gen.address_size = SZ_D;
opts->gen.address_mask = 0xFFFFFF;
opts->gen.byte_swap = 1;
diff --git a/z80_to_x86.c b/z80_to_x86.c
index 6da2321..dc38cae 100644
--- a/z80_to_x86.c
+++ b/z80_to_x86.c
@@ -1331,7 +1331,7 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
num_cycles += 4;
}
cycles(&opts->gen, num_cycles);
- if (inst->addr_mode != Z80_REG_INDIRECT && inst->immed < 0x4000) {
+ if (inst->addr_mode != Z80_REG_INDIRECT) {
code_ptr call_dst = z80_get_native_address(context, inst->immed);
if (!call_dst) {
opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
@@ -1380,38 +1380,26 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
jcc(code, cond, code->cur+2);
cycles(&opts->gen, 5);//T States: 5
uint16_t dest_addr = inst->immed;
- if (dest_addr < 0x4000) {
- code_ptr call_dst = z80_get_native_address(context, dest_addr);
- if (!call_dst) {
- opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
- //fake address to force large displacement
- call_dst = code->cur + 256;
- }
- jmp(code, call_dst);
- } else {
- mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W);
- call(code, opts->native_addr);
- jmp_r(code, opts->gen.scratch1);
+ code_ptr call_dst = z80_get_native_address(context, dest_addr);
+ if (!call_dst) {
+ opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
+ //fake address to force large displacement
+ call_dst = code->cur + 256;
}
+ jmp(code, call_dst);
*no_jump_off = code->cur - (no_jump_off+1);
break;
}
case Z80_JR: {
cycles(&opts->gen, 12);//T States: 4,3,5
uint16_t dest_addr = address + inst->immed + 2;
- if (dest_addr < 0x4000) {
- code_ptr call_dst = z80_get_native_address(context, dest_addr);
- if (!call_dst) {
- opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
- //fake address to force large displacement
- call_dst = code->cur + 256;
- }
- jmp(code, call_dst);
- } else {
- mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W);
- call(code, opts->native_addr);
- jmp_r(code, opts->gen.scratch1);
+ code_ptr call_dst = z80_get_native_address(context, dest_addr);
+ if (!call_dst) {
+ opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
+ //fake address to force large displacement
+ call_dst = code->cur + 256;
}
+ jmp(code, call_dst);
break;
}
case Z80_JRCC: {
@@ -1434,66 +1422,49 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
jcc(code, cond, code->cur+2);
cycles(&opts->gen, 5);//T States: 5
uint16_t dest_addr = address + inst->immed + 2;
- if (dest_addr < 0x4000) {
- code_ptr call_dst = z80_get_native_address(context, dest_addr);
- if (!call_dst) {
- opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
- //fake address to force large displacement
- call_dst = code->cur + 256;
- }
- jmp(code, call_dst);
- } else {
- mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W);
- call(code, opts->native_addr);
- jmp_r(code, opts->gen.scratch1);
+ code_ptr call_dst = z80_get_native_address(context, dest_addr);
+ if (!call_dst) {
+ opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
+ //fake address to force large displacement
+ call_dst = code->cur + 256;
}
+ jmp(code, call_dst);
*no_jump_off = code->cur - (no_jump_off+1);
break;
}
- case Z80_DJNZ:
+ case Z80_DJNZ: {
cycles(&opts->gen, 8);//T States: 5,3
sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
uint8_t *no_jump_off = code->cur+1;
jcc(code, CC_Z, code->cur+2);
cycles(&opts->gen, 5);//T States: 5
uint16_t dest_addr = address + inst->immed + 2;
- if (dest_addr < 0x4000) {
- code_ptr call_dst = z80_get_native_address(context, dest_addr);
- if (!call_dst) {
- opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
- //fake address to force large displacement
- call_dst = code->cur + 256;
- }
- jmp(code, call_dst);
- } else {
- mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W);
- call(code, opts->native_addr);
- jmp_r(code, opts->gen.scratch1);
+ code_ptr call_dst = z80_get_native_address(context, dest_addr);
+ if (!call_dst) {
+ opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
+ //fake address to force large displacement
+ call_dst = code->cur + 256;
}
+ jmp(code, call_dst);
*no_jump_off = code->cur - (no_jump_off+1);
break;
+ }
case Z80_CALL: {
cycles(&opts->gen, 11);//T States: 4,3,4
sub_ir(code, 2, opts->regs[Z80_SP], SZ_W);
mov_ir(code, address + 3, opts->gen.scratch1, SZ_W);
mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
call(code, opts->write_16_highfirst);//T States: 3, 3
- if (inst->immed < 0x4000) {
- code_ptr call_dst = z80_get_native_address(context, inst->immed);
- if (!call_dst) {
- opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
- //fake address to force large displacement
- call_dst = code->cur + 256;
- }
- jmp(code, call_dst);
- } else {
- mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W);
- call(code, opts->native_addr);
- jmp_r(code, opts->gen.scratch1);
+ code_ptr call_dst = z80_get_native_address(context, inst->immed);
+ if (!call_dst) {
+ opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
+ //fake address to force large displacement
+ call_dst = code->cur + 256;
}
+ jmp(code, call_dst);
break;
}
- case Z80_CALLCC:
+ case Z80_CALLCC: {
cycles(&opts->gen, 10);//T States: 4,3,3 (false case)
uint8_t cond = CC_Z;
switch (inst->reg)
@@ -1526,21 +1497,16 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
mov_ir(code, address + 3, opts->gen.scratch1, SZ_W);
mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
call(code, opts->write_16_highfirst);//T States: 3, 3
- if (inst->immed < 0x4000) {
- code_ptr call_dst = z80_get_native_address(context, inst->immed);
- if (!call_dst) {
- opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
- //fake address to force large displacement
- call_dst = code->cur + 256;
- }
- jmp(code, call_dst);
- } else {
- mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W);
- call(code, opts->native_addr);
- jmp_r(code, opts->gen.scratch1);
+ code_ptr call_dst = z80_get_native_address(context, inst->immed);
+ if (!call_dst) {
+ opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
+ //fake address to force large displacement
+ call_dst = code->cur + 256;
}
+ jmp(code, call_dst);
*no_call_off = code->cur - (no_call_off+1);
break;
+ }
case Z80_RET:
cycles(&opts->gen, 4);//T States: 4
mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
@@ -1850,10 +1816,8 @@ void * z80_retranslate_inst(uint32_t address, z80_context * context, uint8_t * o
char disbuf[80];
z80_options * opts = context->options;
uint8_t orig_size = z80_get_native_inst_size(opts, address);
- uint32_t orig = address;
- address &= 0x1FFF;
code_info *code = &opts->gen.code;
- uint8_t *after, *inst = context->mem_pointers[0] + address;
+ uint8_t *after, *inst = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen);
z80inst instbuf;
dprintf("Retranslating code at Z80 address %X, native address %p\n", address, orig_start);
after = z80_decode(inst, &instbuf);
@@ -1921,26 +1885,24 @@ void translate_z80_stream(z80_context * context, uint32_t address)
}
z80_options * opts = context->options;
uint32_t start_address = address;
- uint8_t * encoded = NULL, *next;
- if (address < 0x4000) {
- encoded = context->mem_pointers[0] + (address & 0x1FFF);
- }
- while (encoded != NULL || address >= 0x4000)
+ do
{
z80inst inst;
dprintf("translating Z80 code at address %X\n", address);
do {
- if (address >= 0x4000) {
- code_info stub = z80_make_interp_stub(context, address);
- z80_map_native_address(context, address, stub.cur, 1, stub.last - stub.cur);
- break;
- }
uint8_t * existing = z80_get_native_address(context, address);
if (existing) {
jmp(&opts->gen.code, existing);
break;
}
+ uint8_t * encoded, *next;
+ encoded = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen);
+ if (!encoded) {
+ code_info stub = z80_make_interp_stub(context, address);
+ z80_map_native_address(context, address, stub.cur, 1, stub.last - stub.cur);
+ break;
+ }
//make sure prologue is in a contiguous chunk of code
check_code_prologue(&opts->gen.code);
next = z80_decode(encoded, &inst);
@@ -1956,33 +1918,22 @@ void translate_z80_stream(z80_context * context, uint32_t address)
translate_z80inst(&inst, context, address, 0);
z80_map_native_address(context, address, start, next-encoded, opts->gen.code.cur - start);
address += next-encoded;
- if (address > 0xFFFF) {
- address &= 0xFFFF;
-
- } else {
- encoded = next;
- }
+ address &= 0xFFFF;
} while (!z80_is_terminal(&inst));
process_deferred(&opts->gen.deferred, context, (native_addr_func)z80_get_native_address);
if (opts->gen.deferred) {
address = opts->gen.deferred->address;
dprintf("defferred address: %X\n", address);
- if (address < 0x4000) {
- encoded = context->mem_pointers[0] + (address & 0x1FFF);
- } else {
- encoded = NULL;
- }
- } else {
- encoded = NULL;
- address = 0;
}
- }
+ } while (opts->gen.deferred);
}
void init_x86_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t num_chunks)
{
memset(options, 0, sizeof(*options));
+ options->gen.memmap = chunks;
+ options->gen.memmap_chunks = num_chunks;
options->gen.address_size = SZ_W;
options->gen.address_mask = 0xFFFF;
options->gen.max_address = 0x10000;