diff m68k_to_x86.c @ 124:da95566514f3

Some fixes for translating code in located in RAM
author Mike Pavone <pavone@retrodev.com>
date Sat, 29 Dec 2012 21:55:42 -0800
parents bd3858121ab0
children dc5fc3adf705
line wrap: on
line diff
--- a/m68k_to_x86.c	Sat Dec 29 21:10:07 2012 -0800
+++ b/m68k_to_x86.c	Sat Dec 29 21:55:42 2012 -0800
@@ -1517,6 +1517,7 @@
 uint8_t * translate_m68k_jmp(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
 {
 	uint8_t * dest_addr;
+	uint32_t m68k_addr;
 	switch(inst->src.addr_mode)
 	{
 	case MODE_AREG_INDIRECT:
@@ -1531,24 +1532,38 @@
 		break;
 	case MODE_PC_DISPLACE:
 		dst = cycles(dst, 10);
-		dest_addr = get_native_address(opts->native_code_map, inst->src.params.regs.displacement + inst->address + 2);
-		if (!dest_addr) {
-			opts->deferred = defer_address(opts->deferred, inst->src.params.regs.displacement + inst->address + 2, dst + 1);
-			//dummy address to be replaced later, make sure it generates a 4-byte displacement
-			dest_addr = dst + 256;
+		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);
+			if (!dest_addr) {
+				opts->deferred = defer_address(opts->deferred, m68k_addr, dst + 1);
+				//dummy address to be replaced later, make sure it generates a 4-byte displacement
+				dest_addr = dst + 256;
+			}
+			dst = jmp(dst, dest_addr);
+		} else {
+			dst = mov_ir(dst, m68k_addr, SCRATCH1, SZ_D);
+			dst = call(dst, (uint8_t *)m68k_native_addr);
+			dst = jmp_r(dst, SCRATCH1);
 		}
-		dst = jmp(dst, dest_addr);
 		break;
 	case MODE_ABSOLUTE:
 	case MODE_ABSOLUTE_SHORT:
 		dst = cycles(dst, inst->src.addr_mode == MODE_ABSOLUTE ? 12 : 10);
-		dest_addr = get_native_address(opts->native_code_map, inst->src.params.immed);
-		if (!dest_addr) {
-			opts->deferred = defer_address(opts->deferred, inst->src.params.immed, dst + 1);
-			//dummy address to be replaced later, make sure it generates a 4-byte displacement
-			dest_addr = dst + 256;
+		m68k_addr = inst->src.params.immed;
+		if ((m68k_addr & 0xFFFFFF) < 0x400000) {
+			dest_addr = get_native_address(opts->native_code_map, m68k_addr);
+			if (!dest_addr) {
+				opts->deferred = defer_address(opts->deferred, m68k_addr, dst + 1);
+				//dummy address to be replaced later, make sure it generates a 4-byte displacement
+				dest_addr = dst + 256;
+			}
+			dst = jmp(dst, dest_addr);
+		} else {
+			dst = mov_ir(dst, m68k_addr, SCRATCH1, SZ_D);
+			dst = call(dst, (uint8_t *)m68k_native_addr);
+			dst = jmp_r(dst, SCRATCH1);
 		}
-		dst = jmp(dst, dest_addr);
 		break;
 	default:
 		printf("address mode %d not yet supported (jmp)\n", inst->src.addr_mode);
@@ -1561,6 +1576,7 @@
 {
 	uint8_t * dest_addr, sec_reg;
 	uint32_t after;
+	uint32_t m68k_addr;
 	switch(inst->src.addr_mode)
 	{
 	case MODE_AREG_INDIRECT:
@@ -1639,13 +1655,20 @@
 		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);
-		dest_addr = get_native_address(opts->native_code_map, inst->src.params.regs.displacement + inst->address + 2);
-		if (!dest_addr) {
-			opts->deferred = defer_address(opts->deferred, inst->src.params.regs.displacement + inst->address + 2, dst + 1);
-			//dummy address to be replaced later, make sure it generates a 4-byte displacement
-			dest_addr = dst + 5;
+		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);
+			if (!dest_addr) {
+				opts->deferred = defer_address(opts->deferred, m68k_addr, dst + 1);
+				//dummy address to be replaced later, make sure it generates a 4-byte displacement
+				dest_addr = dst + 5;
+			}
+			dst = call(dst, (char *)dest_addr);
+		} else {
+			dst = mov_ir(dst, m68k_addr, SCRATCH1, SZ_D);
+			dst = call(dst, (uint8_t *)m68k_native_addr);
+			dst = call_r(dst, SCRATCH1);
 		}
-		dst = call(dst, (char *)dest_addr);
 		//would add_ir(dst, 8, RSP, SZ_Q) be faster here?
 		dst = pop_r(dst, SCRATCH1);
 		break;
@@ -1705,13 +1728,20 @@
 		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);
-		dest_addr = get_native_address(opts->native_code_map, inst->src.params.immed);
-		if (!dest_addr) {
-			opts->deferred = defer_address(opts->deferred, inst->src.params.immed, dst + 1);
-			//dummy address to be replaced later, make sure it generates a 4-byte displacement
-			dest_addr = dst + 5;
+		m68k_addr = inst->src.params.immed;
+		if ((m68k_addr & 0xFFFFFF) < 0x400000) {
+			dest_addr = get_native_address(opts->native_code_map, m68k_addr);
+			if (!dest_addr) {
+				opts->deferred = defer_address(opts->deferred, m68k_addr, dst + 1);
+				//dummy address to be replaced later, make sure it generates a 4-byte displacement
+				dest_addr = dst + 5;
+			}
+			dst = call(dst, (char *)dest_addr);
+		} else {
+			dst = mov_ir(dst, m68k_addr, SCRATCH1, SZ_D);
+			dst = call(dst, (uint8_t *)m68k_native_addr);
+			dst = call_r(dst, SCRATCH1);
 		}
-		dst = call(dst, (char *)dest_addr);
 		//would add_ir(dst, 8, RSP, SZ_Q) be faster here?
 		dst = pop_r(dst, SCRATCH1);
 		break;
@@ -2622,7 +2652,14 @@
 		process_deferred(opts);
 		if (opts->deferred) {
 			address = opts->deferred->address;
-			encoded = context->mem_pointers[0] + address/2;
+			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;
 		}