changeset 2668:b0b6c6042103

Fix some bugs in memory access functions used in interpreter mode
author Michael Pavone <pavone@retrodev.com>
date Sat, 08 Mar 2025 11:45:25 -0800
parents 1f6503bcb1d5
children c6bc66b16392
files backend.c
diffstat 1 files changed, 72 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- a/backend.c	Fri Mar 07 23:41:42 2025 -0800
+++ b/backend.c	Sat Mar 08 11:45:25 2025 -0800
@@ -162,6 +162,11 @@
 		return 0xFFFF;
 	}
 	uint32_t offset = address & chunk->mask;
+	if (chunk->shift > 0) {
+		offset <<= chunk->shift;
+	} else if (chunk->shift < 0){
+		offset >>= -chunk->shift;
+	}
 	if (chunk->flags & MMAP_READ) {
 		uint8_t *base;
 		if (chunk->flags & MMAP_PTR_IDX) {
@@ -171,11 +176,6 @@
 		}
 		if (base) {
 			uint16_t val;
-			if (chunk->shift > 0) {
-				offset <<= chunk->shift;
-			} else if (chunk->shift < 0){
-				offset >>= chunk->shift;
-			}
 			if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) {
 				offset /= 2;
 				val = base[offset];
@@ -203,6 +203,11 @@
 		return;
 	}
 	uint32_t offset = address & chunk->mask;
+	if (chunk->shift > 0) {
+		offset <<= chunk->shift;
+	} else if (chunk->shift < 0){
+		offset >>= -chunk->shift;
+	}
 	if (chunk->flags & MMAP_WRITE) {
 		uint8_t *base;
 		if (chunk->flags & MMAP_PTR_IDX) {
@@ -211,11 +216,6 @@
 			base = chunk->buffer;
 		}
 		if (base) {
-			if (chunk->shift > 0) {
-				offset <<= chunk->shift;
-			} else if (chunk->shift < 0){
-				offset >>= chunk->shift;
-			}
 			if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) {
 				offset /= 2;
 				if (chunk->flags & MMAP_ONLY_EVEN) {
@@ -240,6 +240,16 @@
 		return 0xFF;
 	}
 	uint32_t offset = address & chunk->mask;
+	if (offset) {
+		uint32_t low_bit = offset & 1;
+		offset &= ~1;
+		if (chunk->shift > 0) {
+			offset <<= chunk->shift;
+		} else {
+			offset >>= -chunk->shift;
+		}
+		offset |= low_bit;
+	}
 	if (chunk->flags & MMAP_READ) {
 		uint8_t *base;
 		if (chunk->flags & MMAP_PTR_IDX) {
@@ -248,11 +258,6 @@
 			base = chunk->buffer;
 		}
 		if (base) {
-			if (chunk->shift > 0) {
-				offset <<= chunk->shift;
-			} else if (chunk->shift < 0){
-				offset >>= chunk->shift;
-			}
 			if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) {
 				if (address & 1) {
 					if (chunk->flags & MMAP_ONLY_EVEN) {
@@ -281,6 +286,16 @@
 		return;
 	}
 	uint32_t offset = address & chunk->mask;
+	if (chunk->shift) {
+		uint32_t low_bit = offset & 1;
+		offset &= ~1;
+		if (chunk->shift > 0) {
+			offset <<= chunk->shift;
+		} else {
+			offset >>= -chunk->shift;
+		}
+		offset |= low_bit;
+	}
 	if (chunk->flags & MMAP_WRITE) {
 		uint8_t *base;
 		if (chunk->flags & MMAP_PTR_IDX) {
@@ -289,11 +304,6 @@
 			base = chunk->buffer;
 		}
 		if (base) {
-			if (chunk->shift > 0) {
-				offset <<= chunk->shift;
-			} else if (chunk->shift < 0){
-				offset >>= chunk->shift;
-			}
 			if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) {
 				if (address & 1) {
 					if (chunk->flags & MMAP_ONLY_EVEN) {
@@ -421,6 +431,11 @@
 		}
 	}
 	uint32_t offset = address & chunk->mask;
+	if (chunk->shift > 0) {
+		offset <<= chunk->shift;
+	} else if (chunk->shift < 0){
+		offset >>= -chunk->shift;
+	}
 	if (chunk->flags & MMAP_READ) {
 		uint8_t *base;
 		if (chunk->flags & MMAP_PTR_IDX) {
@@ -431,11 +446,6 @@
 		}
 		if (base) {
 			uint16_t val;
-			if (chunk->shift > 0) {
-				offset <<= chunk->shift;
-			} else if (chunk->shift < 0){
-				offset >>= chunk->shift;
-			}
 			if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) {
 				offset /= 2;
 				val = base[offset];
@@ -475,6 +485,16 @@
 		}
 	}
 	uint32_t offset = address & chunk->mask;
+	if (chunk->shift) {
+		uint32_t low_bit = offset & 1;
+		offset &= ~1;
+		if (chunk->shift > 0) {
+			offset <<= chunk->shift;
+		} else {
+			offset >>= -chunk->shift;
+		}
+		offset |= low_bit;
+	}
 	if (chunk->flags & MMAP_READ) {
 		uint8_t *base;
 		if (chunk->flags & MMAP_PTR_IDX) {
@@ -484,11 +504,6 @@
 			base = chunk->buffer;
 		}
 		if (base) {
-			if (chunk->shift > 0) {
-				offset <<= chunk->shift;
-			} else if (chunk->shift < 0){
-				offset >>= chunk->shift;
-			}
 			if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) {
 				if (address & 1) {
 					if (chunk->flags & MMAP_ONLY_EVEN) {
@@ -527,7 +542,12 @@
 			return;
 		}
 	}
-	uint32_t offset = address & chunk->mask;
+	uint32_t offset = address & chunk->mask;	
+	if (chunk->shift > 0) {
+		offset <<= chunk->shift;
+	} else if (chunk->shift < 0){
+		offset >>= -chunk->shift;
+	}
 	if (chunk->flags & MMAP_WRITE) {
 		uint8_t *base;
 		if (chunk->flags & MMAP_PTR_IDX) {
@@ -537,11 +557,6 @@
 			base = chunk->buffer;
 		}
 		if (base) {
-			if (chunk->shift > 0) {
-				offset <<= chunk->shift;
-			} else if (chunk->shift < 0){
-				offset >>= chunk->shift;
-			}
 			if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) {
 				offset /= 2;
 				if (chunk->flags & MMAP_ONLY_EVEN) {
@@ -577,6 +592,16 @@
 		}
 	}
 	uint32_t offset = address & chunk->mask;
+	if (chunk->shift) {
+		uint32_t low_bit = offset & 1;
+		offset &= ~1;
+		if (chunk->shift > 0) {
+			offset <<= chunk->shift;
+		} else {
+			offset >>= -chunk->shift;
+		}
+		offset |= low_bit;
+	}
 	if (chunk->flags & MMAP_WRITE) {
 		uint8_t *base;
 		if (chunk->flags & MMAP_PTR_IDX) {
@@ -586,11 +611,6 @@
 			base = chunk->buffer;
 		}
 		if (base) {
-			if (chunk->shift > 0) {
-				offset <<= chunk->shift;
-			} else if (chunk->shift < 0){
-				offset >>= chunk->shift;
-			}
 			if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) {
 				if (address & 1) {
 					if (chunk->flags & MMAP_ONLY_EVEN) {
@@ -624,11 +644,11 @@
 		*data_out = (void *)(uintptr_t)0xFFFF;
 		return interp_read_fixed_16;
 	}
-	if (chunk->end < end || chunk->start > start) {
+	if (chunk->end < end || chunk->start > start || chunk->shift) {
 		goto use_map;
 	}
 	if (chunk->flags & MMAP_READ) {
-		if ((chunk->flags & (MMAP_ONLY_ODD|MMAP_ONLY_EVEN|MMAP_FUNC_NULL)) || chunk->shift) {
+		if ((chunk->flags & (MMAP_ONLY_ODD|MMAP_ONLY_EVEN|MMAP_FUNC_NULL))) {
 			goto use_map;
 		}
 		if (!chunk->mask && !(chunk->flags & ~MMAP_READ)) {
@@ -674,11 +694,11 @@
 		*data_out = (void *)(uintptr_t)0xFFFF;
 		return interp_read_fixed_8;
 	}
-	if (chunk->end != end || chunk->start != start) {
+	if (chunk->end != end || chunk->start != start || chunk->shift) {
 		goto use_map;
 	}
 	if (chunk->flags & MMAP_READ) {
-		if ((chunk->flags & (MMAP_ONLY_ODD|MMAP_ONLY_EVEN|MMAP_FUNC_NULL)) || chunk->shift) {
+		if ((chunk->flags & (MMAP_ONLY_ODD|MMAP_ONLY_EVEN|MMAP_FUNC_NULL)) || !opts->byte_swap) {
 			goto use_map;
 		}
 		if (!chunk->mask && !(chunk->flags & ~MMAP_READ)) {
@@ -724,11 +744,11 @@
 		*data_out = NULL;
 		return interp_write_ignored_16;
 	}
-	if (chunk->end != end || chunk->start != start) {
+	if (chunk->end != end || chunk->start != start || chunk->shift) {
 		goto use_map;
 	}
-	if (chunk->flags & MMAP_READ) {
-		if ((chunk->flags & (MMAP_ONLY_ODD|MMAP_ONLY_EVEN|MMAP_FUNC_NULL)) || chunk->shift || (chunk->mask & 0xFFFF) != 0xFFFF) {
+	if (chunk->flags & MMAP_WRITE) {
+		if ((chunk->flags & (MMAP_ONLY_ODD|MMAP_ONLY_EVEN|MMAP_FUNC_NULL)) || (chunk->mask & 0xFFFF) != 0xFFFF) {
 			goto use_map;
 		}
 		if (chunk->flags & MMAP_PTR_IDX) {
@@ -766,11 +786,11 @@
 		*data_out = NULL;
 		return interp_write_ignored_8;
 	}
-	if (chunk->end != end || chunk->start != start) {
+	if (chunk->end != end || chunk->start != start || chunk->shift) {
 		goto use_map;
 	}
-	if (chunk->flags & MMAP_READ) {
-		if ((chunk->flags & (MMAP_ONLY_ODD|MMAP_ONLY_EVEN|MMAP_FUNC_NULL)) || chunk->shift
+	if (chunk->flags & MMAP_WRITE) {
+		if ((chunk->flags & (MMAP_ONLY_ODD|MMAP_ONLY_EVEN|MMAP_FUNC_NULL))
 			|| (chunk->mask & 0xFFFF) != 0xFFFF || !opts->byte_swap
 		) {
 			goto use_map;
@@ -786,7 +806,7 @@
 			return interp_write_direct_8;
 		}
 	}
-	if (chunk->write_16 && chunk->mask == opts->address_mask) {
+	if (chunk->write_8 && chunk->mask == opts->address_mask) {
 		*data_out = NULL;
 		//This is not safe for all calling conventions due to the extra param
 		//but should work for the ones we actually care about