diff backend_x86.c @ 2054:8ee7ecbf3f21 segacd

Implement enough of Sega CD gate array and Sub CPU to pass Sik's Mode 1 test ROM
author Michael Pavone <pavone@retrodev.com>
date Tue, 18 Jan 2022 00:03:50 -0800
parents 45c4b74e7676
children afc54649ebed
line wrap: on
line diff
--- a/backend_x86.c	Sat Jan 15 13:15:21 2022 -0800
+++ b/backend_x86.c	Tue Jan 18 00:03:50 2022 -0800
@@ -116,7 +116,7 @@
 	if (after_inc) {
 		*after_inc = code->cur;
 	}
-	
+
 	if (opts->address_size == SZ_D && opts->address_mask != 0xFFFFFFFF) {
 		and_ir(code, opts->address_mask, adr_reg, SZ_D);
 	} else if (opts->address_size == SZ_W && opts->address_mask != 0xFFFF) {
@@ -127,19 +127,31 @@
 	uint32_t ram_flags_off = opts->ram_flags_off;
 	uint32_t min_address = 0;
 	uint32_t max_address = opts->max_address;
+	uint8_t need_wide_jcc = 0;
 	for (uint32_t chunk = 0; chunk < num_chunks; chunk++)
 	{
+		code_info chunk_start = *code;
 		if (memmap[chunk].start > min_address) {
 			cmp_ir(code, memmap[chunk].start, adr_reg, opts->address_size);
 			lb_jcc = code->cur + 1;
-			jcc(code, CC_C, code->cur + 2);
+			if (need_wide_jcc) {
+				jcc(code, CC_C, code->cur + 130);
+				lb_jcc++;
+			} else {
+				jcc(code, CC_C, code->cur + 2);
+			}
 		} else {
 			min_address = memmap[chunk].end;
 		}
 		if (memmap[chunk].end < max_address) {
 			cmp_ir(code, memmap[chunk].end, adr_reg, opts->address_size);
 			ub_jcc = code->cur + 1;
-			jcc(code, CC_NC, code->cur + 2);
+			if (need_wide_jcc) {
+				jcc(code, CC_NC, code->cur + 130);
+				ub_jcc++;
+			} else {
+				jcc(code, CC_NC, code->cur + 2);
+			}
 		} else {
 			max_address = memmap[chunk].start;
 		}
@@ -312,13 +324,35 @@
 			}
 		}
 		if (lb_jcc) {
-			*lb_jcc = code->cur - (lb_jcc+1);
+			if (need_wide_jcc) {
+				*((int32_t*)lb_jcc) = code->cur - (lb_jcc+4);
+			} else if (code->cur - (lb_jcc+1) > 0x7f) {
+				need_wide_jcc = 1;
+				chunk--;
+				*code = chunk_start;
+				continue;
+			} else {
+				*lb_jcc = code->cur - (lb_jcc+1);
+			}
 			lb_jcc = NULL;
 		}
 		if (ub_jcc) {
-			*ub_jcc = code->cur - (ub_jcc+1);
+			if (need_wide_jcc) {
+				*((int32_t*)ub_jcc) = code->cur - (ub_jcc+4);
+			} else if (code->cur - (ub_jcc+1) > 0x7f) {
+				need_wide_jcc = 1;
+				chunk--;
+				*code = chunk_start;
+				continue;
+			} else {
+				*ub_jcc = code->cur - (ub_jcc+1);
+			}
+
 			ub_jcc = NULL;
 		}
+		if (need_wide_jcc) {
+			need_wide_jcc = 0;
+		}
 	}
 	if (!is_write) {
 		mov_ir(code, size == SZ_B ? 0xFF : 0xFFFF, opts->scratch1, size);