changeset 2170:ada3130b1396

Add memory indirection syntax to debugger parser/evaluator
author Michael Pavone <pavone@retrodev.com>
date Sat, 06 Aug 2022 14:50:41 -0700
parents cb9572145f8e
children 4b47155965c8
files debug.c
diffstat 1 files changed, 130 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/debug.c	Sat Aug 06 14:14:15 2022 -0700
+++ b/debug.c	Sat Aug 06 14:50:41 2022 -0700
@@ -69,7 +69,9 @@
 	TOKEN_NUM,
 	TOKEN_NAME,
 	TOKEN_OPER,
-	TOKEN_SIZE
+	TOKEN_SIZE,
+	TOKEN_LBRACKET,
+	TOKEN_RBRACKET,
 } token_type;
 
 static const char *token_type_names[] = {
@@ -77,7 +79,9 @@
 	"TOKEN_NUM",
 	"TOKEN_NAME",
 	"TOKEN_OPER",
-	"TOKEN_SIZE"
+	"TOKEN_SIZE",
+	"TOKEN_LBRACKET",
+	"TOKEN_RBRACKET"
 };
 
 typedef struct {
@@ -153,6 +157,16 @@
 				.op = {start[1], 0}
 			}
 		};
+	case '[':
+		*end = start + 1;
+		return (token) {
+			.type = TOKEN_LBRACKET
+		};
+	case ']':
+		*end = start + 1;
+		return (token) {
+			.type = TOKEN_RBRACKET
+		};
 	}
 	*end = start + 1;
 	while (**end && !isblank(**end) && **end != '.')
@@ -175,7 +189,8 @@
 	EXPR_SCALAR,
 	EXPR_UNARY,
 	EXPR_BINARY,
-	EXPR_SIZE
+	EXPR_SIZE,
+	EXPR_MEM
 } expr_type;
 
 typedef struct expr expr;
@@ -200,6 +215,9 @@
 	free(e);
 }
 
+static expr *parse_scalar_or_muldiv(char *start, char **end);
+static expr *parse_expression(char *start, char **end);
+
 static expr *parse_scalar(char *start, char **end)
 {
 	char *after_first;
@@ -224,6 +242,29 @@
 		*end = after_first;
 		return ret;
 	}
+	if (first.type == TOKEN_LBRACKET) {
+		expr *ret = calloc(1, sizeof(expr));
+		ret->type = EXPR_MEM;
+		ret->left = parse_expression(after_first, end);
+		if (!ret->left) {
+			fprintf(stderr, "Expression expected after `[`\n");
+			free(ret);
+			return NULL;
+		}
+		token rbrack = parse_token(*end, end);
+		if (rbrack.type != TOKEN_RBRACKET) {
+			fprintf(stderr, "Missing closing `]`");
+			free_expr(ret);
+			return NULL;
+		}
+		char *after_size;
+		token size = parse_token(*end, &after_size);
+		if (size.type == TOKEN_SIZE) {
+			*end = after_size;
+			ret->op = size;
+		}
+		return ret;
+	}
 	token second = parse_token(after_first, end);
 	if (second.type != TOKEN_SIZE) {
 		expr *ret = calloc(1, sizeof(expr));
@@ -241,9 +282,6 @@
 	return ret;
 }
 
-static expr *parse_scalar_or_muldiv(char *start, char **end);
-static expr *parse_expression(char *start, char **end);
-
 static expr *maybe_binary(expr *left, char *start, char **end)
 {
 	char *after_first;
@@ -331,15 +369,31 @@
 		ret->left = target;
 		return ret;
 	}
+	if (first.type == TOKEN_LBRACKET) {
+		expr *ret = calloc(1, sizeof(expr));
+		ret->type = EXPR_MEM;
+		ret->left = parse_expression(after_first, end);
+		if (!ret->left) {
+			fprintf(stderr, "Expression expected after `[`\n");
+			free(ret);
+			return NULL;
+		}
+		token rbrack = parse_token(*end, end);
+		if (rbrack.type != TOKEN_RBRACKET) {
+			fprintf(stderr, "Missing closing `]`");
+			free_expr(ret);
+			return NULL;
+		}
+		char *after_size;
+		token size = parse_token(*end, &after_size);
+		if (size.type == TOKEN_SIZE) {
+			*end = after_size;
+			ret->op = size;
+		}
+		return ret;
+	}
 	char *after_second;
 	token second = parse_token(after_first, &after_second);
-	if (!second.type) {
-		expr *ret = calloc(1, sizeof(expr));
-		ret->type = EXPR_SCALAR;
-		ret->op = first;
-		*end = after_first;
-		return ret;
-	}
 	if (second.type == TOKEN_OPER) {
 		expr *ret;
 		expr *bin = calloc(1, sizeof(expr));
@@ -380,8 +434,11 @@
 		value->left->op = first;
 		return maybe_muldiv(value, after_second, end);
 	} else {
-		fprintf(stderr, "Unexpected %s after scalar\n", token_type_names[second.type]);
-		return NULL;
+		expr *ret = calloc(1, sizeof(expr));
+		ret->type = EXPR_SCALAR;
+		ret->op = first;
+		*end = after_first;
+		return ret;
 	}
 }
 
@@ -408,15 +465,31 @@
 		ret->left = target;
 		return ret;
 	}
+	if (first.type == TOKEN_LBRACKET) {
+		expr *ret = calloc(1, sizeof(expr));
+		ret->type = EXPR_MEM;
+		ret->left = parse_expression(after_first, end);
+		if (!ret->left) {
+			fprintf(stderr, "Expression expected after `[`\n");
+			free(ret);
+			return NULL;
+		}
+		token rbrack = parse_token(*end, end);
+		if (rbrack.type != TOKEN_RBRACKET) {
+			fprintf(stderr, "Missing closing `]`");
+			free_expr(ret);
+			return NULL;
+		}
+		char *after_size;
+		token size = parse_token(*end, &after_size);
+		if (size.type == TOKEN_SIZE) {
+			*end = after_size;
+			ret->op = size;
+		}
+		return ret;
+	}
 	char *after_second;
 	token second = parse_token(after_first, &after_second);
-	if (!second.type) {
-		expr *ret = calloc(1, sizeof(expr));
-		ret->type = EXPR_SCALAR;
-		ret->op = first;
-		*end = after_first;
-		return ret;
-	}
 	if (second.type == TOKEN_OPER) {
 		expr *bin = calloc(1, sizeof(expr));
 		bin->type = EXPR_BINARY;
@@ -456,16 +529,21 @@
 		value->left->op = first;
 		return maybe_binary(value, after_second, end);
 	} else {
-		fprintf(stderr, "Unexpected %s after scalar\n", token_type_names[second.type]);
-		return NULL;
+		expr *ret = calloc(1, sizeof(expr));
+		ret->type = EXPR_SCALAR;
+		ret->op = first;
+		*end = after_first;
+		return ret;
 	}
 }
 
 typedef struct debug_context debug_context;
 typedef uint8_t (*resolver)(debug_context *context, const char *name, uint32_t *out);
+typedef uint8_t (*reader)(debug_context *context, uint32_t *out, char size);
 
 struct debug_context {
 	resolver resolve;
+	reader   read_mem;
 	void     *system;
 };
 
@@ -551,6 +629,11 @@
 			break;
 		}
 		return 1;
+	case EXPR_MEM:
+		if (!eval_expr(context, e->left, out)) {
+			return 0;
+		}
+		return context->read_mem(context, out, e->op.v.op[0]);
 	default:
 		return 0;
 	}
@@ -608,17 +691,35 @@
 	return read_byte(address, (void **)context->mem_pointers, &context->options->gen, context);
 }
 
-uint16_t m68k_read_word(uint32_t address, m68k_context *context)
+static uint16_t m68k_read_word(uint32_t address, m68k_context *context)
 {
 	return read_word(address, (void **)context->mem_pointers, &context->options->gen, context);
 }
 
-uint32_t m68k_read_long(uint32_t address, m68k_context *context)
+static uint32_t m68k_read_long(uint32_t address, m68k_context *context)
 {
 	return m68k_read_word(address, context) << 16 | m68k_read_word(address + 2, context);
 }
 
-uint8_t resolve_m68k(m68k_context *context, const char *name, uint32_t *out)
+static uint8_t read_m68k(m68k_context *context, uint32_t *out, char size)
+{
+	if (size == 'b') {
+		*out = m68k_read_byte(*out, context);
+	} else if (size == 'l') {
+		*out = m68k_read_long(*out, context);
+	} else {
+		*out = m68k_read_word(*out, context);
+	}
+	return 1;
+}
+
+static uint8_t read_genesis(debug_context *context, uint32_t *out, char size)
+{
+	genesis_context *gen = context->system;
+	return read_m68k(gen->m68k, out, size);
+}
+
+static uint8_t resolve_m68k(m68k_context *context, const char *name, uint32_t *out)
 {
 	if (name[0] == 'd' && name[1] >= '0' && name[1] <= '7') {
 		*out = context->dregs[name[1]-'0'];
@@ -640,7 +741,7 @@
 	return 1;
 }
 
-uint8_t resolve_genesis(debug_context *context, const char *name, uint32_t *out)
+static uint8_t resolve_genesis(debug_context *context, const char *name, uint32_t *out)
 {
 	genesis_context *gen = context->system;
 	if (resolve_m68k(gen->m68k, name, out)) {
@@ -674,6 +775,7 @@
 	}
 	debug_context c = {
 		.resolve = resolve_genesis,
+		.read_mem = read_genesis,
 		.system = context->system
 	};
 	char *after;