Debugger: Add unary operators and memory dereferencing
Vicki Pfau vi@endrift.com
Mon, 04 Mar 2019 18:27:13 -0800
5 files changed,
83 insertions(+),
9 deletions(-)
M
CHANGES
→
CHANGES
@@ -3,6 +3,7 @@ Features:
- Improved logging configuration - One-Player BattleChip/Progress/Beast Link Gate support - Add Game Boy Color palettes for original Game Boy games + - Debugger: Add unary operators and memory dereferencing Emulation fixes: - GBA: All IRQs have 7 cycle delay (fixes mgba.io/i/539, mgba.io/i/1208) - GBA: Reset now reloads multiboot ROMs
M
include/mgba/internal/debugger/parser.h
→
include/mgba/internal/debugger/parser.h
@@ -38,6 +38,7 @@ OP_FLIP,
OP_NOT, OP_SHIFT_L, OP_SHIFT_R, + OP_DEREFERENCE, }; struct Token {
M
src/debugger/parser.c
→
src/debugger/parser.c
@@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include <mgba/internal/debugger/parser.h> +#include <mgba/core/core.h> #include <mgba/debugger/debugger.h> #include <mgba-util/string.h>@@ -89,6 +90,29 @@ default:
break; } *state = LEX_ERROR; + } + if (*state == LEX_ROOT || *state == LEX_ERROR) { + struct Token* lvNext = LexVectorAppend(lv); + lvNext->type = TOKEN_OPERATOR_TYPE; + *state = LEX_ROOT; + switch (operator) { + case '-': + lvNext->operatorValue = OP_NEGATE; + break; + case '~': + lvNext->operatorValue = OP_FLIP; + break; + case '!': + lvNext->operatorValue = OP_NOT; + break; + case '*': + lvNext->operatorValue = OP_DEREFERENCE; + break; + default: + lvNext->type = TOKEN_ERROR_TYPE; + *state = LEX_ERROR; + break; + } return; } struct Token* lvNext = LexVectorAppend(lv);@@ -247,6 +271,12 @@ state = LEX_ROOT;
lvNext = LexVectorAppend(lv); lvNext->type = TOKEN_OPEN_PAREN_TYPE; break; + case '!': + case '-': + case '~': + case '*': + _lexOperator(lv, token, &state); + break; case ' ': case '\t': break;@@ -499,6 +529,7 @@ [OP_FLIP] = 2,
[OP_NOT] = 2, [OP_SHIFT_L] = 5, [OP_SHIFT_R] = 5, + [OP_DEREFERENCE] = 2, }; static struct ParseTree* _parseTreeCreate() {@@ -622,7 +653,7 @@ free(tree->token.identifierValue);
} } -static bool _performOperation(enum Operation operation, int32_t current, int32_t next, int32_t* value) { +static bool _performOperation(struct mDebugger* debugger, enum Operation operation, int32_t current, int32_t next, int32_t* value, int* segment) { switch (operation) { case OP_ASSIGN: current = next;@@ -683,12 +714,29 @@ break;
case OP_GE: current = current >= next; break; + case OP_NEGATE: + current = -next; + break; + case OP_FLIP: + current = ~next; + break; + case OP_NOT: + current = !next; + break; case OP_SHIFT_L: current <<= next; break; case OP_SHIFT_R: current >>= next; break; + case OP_DEREFERENCE: + if (*segment < 0) { + current = debugger->core->busRead8(debugger->core, next); + } else { + current = debugger->core->rawRead8(debugger->core, next, *segment); + } + *segment = -1; + break; default: return false; }@@ -714,13 +762,37 @@ return false;
} return mDebuggerEvaluateParseTree(debugger, tree->lhs, segment, NULL); case TOKEN_OPERATOR_TYPE: - if (!mDebuggerEvaluateParseTree(debugger, tree->lhs, &lhs, segment)) { - return false; - } - if (!mDebuggerEvaluateParseTree(debugger, tree->rhs, &rhs, segment)) { - return false; + switch (tree->token.operatorValue) { + case OP_ASSIGN: + case OP_ADD: + case OP_SUBTRACT: + case OP_MULTIPLY: + case OP_DIVIDE: + case OP_MODULO: + case OP_AND: + case OP_OR: + case OP_XOR: + case OP_LESS: + case OP_GREATER: + case OP_EQUAL: + case OP_NOT_EQUAL: + case OP_LOGICAL_AND: + case OP_LOGICAL_OR: + case OP_LE: + case OP_GE: + case OP_SHIFT_L: + case OP_SHIFT_R: + if (!mDebuggerEvaluateParseTree(debugger, tree->lhs, &lhs, segment)) { + return false; + } + // Fall through + default: + if (!mDebuggerEvaluateParseTree(debugger, tree->rhs, &rhs, segment)) { + return false; + } + break; } - return _performOperation(tree->token.operatorValue, lhs, rhs, value); + return _performOperation(debugger, tree->token.operatorValue, lhs, rhs, value, segment); case TOKEN_IDENTIFIER_TYPE: return mDebuggerLookupIdentifier(debugger, tree->token.identifierValue, value, segment); case TOKEN_ERROR_TYPE:
M
src/lr35902/debugger/cli-debugger.c
→
src/lr35902/debugger/cli-debugger.c
@@ -74,7 +74,7 @@ bytesRemaining += LR35902Decode(instruction, &info);
}; disPtr[0] = '\t'; ++disPtr; - LR35902Disassemble(&info, disPtr, sizeof(disassembly) - (disPtr - disassembly)); + LR35902Disassemble(&info, address, disPtr, sizeof(disassembly) - (disPtr - disassembly)); be->printf(be, "%s\n", disassembly); return address; }
M
src/lr35902/debugger/debugger.c
→
src/lr35902/debugger/debugger.c
@@ -215,7 +215,7 @@ };
disPtr[0] = ':'; disPtr[1] = ' '; disPtr += 2; - LR35902Disassemble(&info, disPtr, sizeof(disassembly) - (disPtr - disassembly)); + LR35902Disassemble(&info, address, disPtr, sizeof(disassembly) - (disPtr - disassembly)); *length = snprintf(out, *length, "A: %02X F: %02X B: %02X C: %02X D: %02X E: %02X H: %02X L: %02X SP: %04X PC: %02X:%04X | %s", cpu->a, cpu->f.packed, cpu->b, cpu->c,