From bc335e104d3cea1b5150bc081e8812baf3436263 Mon Sep 17 00:00:00 2001 From: Sour Date: Mon, 4 Nov 2019 20:16:20 -0500 Subject: [PATCH] Debugger: Added ":" operator to return an address' offset in prg/sram/wram/etc. --- Core/ExpressionEvaluator.cpp | 26 ++++++++++++++++++++------ Core/ExpressionEvaluator.h | 6 +++--- Docs/content/debugging/Debugger.md | 17 ++++++++++++++--- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/Core/ExpressionEvaluator.cpp b/Core/ExpressionEvaluator.cpp index 76f358a8..61c1b9f0 100644 --- a/Core/ExpressionEvaluator.cpp +++ b/Core/ExpressionEvaluator.cpp @@ -11,9 +11,9 @@ const vector ExpressionEvaluator::_binaryOperators = { { "*", "/", "%", "+", "-", "<<", ">>", "<", "<=", ">", ">=", "==", "!=", "&", "^", "|", "&&", "||" } }; const vector ExpressionEvaluator::_binaryPrecedence = { { 10, 10, 10, 9, 9, 8, 8, 7, 7, 7, 7, 6, 6, 5, 4, 3, 2, 1 } }; -const vector ExpressionEvaluator::_unaryOperators = { { "+", "-", "~", "!" } }; -const vector ExpressionEvaluator::_unaryPrecedence = { { 11, 11, 11, 11 } }; -const std::unordered_set ExpressionEvaluator::_operators = { { "*", "/", "%", "+", "-", "<<", ">>", "<", "<=", ">", ">=", "==", "!=", "&", "^", "|", "&&", "||", "~", "!", "(", ")", "{", "}", "[", "]" } }; +const vector ExpressionEvaluator::_unaryOperators = { { "+", "-", "~", "!", ":" } }; +const vector ExpressionEvaluator::_unaryPrecedence = { { 11, 11, 11, 11, 11 } }; +const std::unordered_set ExpressionEvaluator::_operators = { { "*", "/", "%", "+", "-", "<<", ">>", "<", "<=", ">", ">=", "==", "!=", "&", "^", "|", "&&", "||", "~", "!", "(", ")", "{", "}", "[", "]", ":" } }; bool ExpressionEvaluator::IsOperator(string token, int &precedence, bool unaryOperator) { @@ -105,8 +105,6 @@ bool ExpressionEvaluator::CheckSpecialTokens(string expression, size_t &pos, str output += std::to_string((int64_t)EvalValues::Value); } else if(token == "address") { output += std::to_string((int64_t)EvalValues::Address); - } else if(token == "romaddress") { - output += std::to_string((int64_t)EvalValues::AbsoluteAddress); } else if(token == "iswrite") { output += std::to_string((int64_t)EvalValues::IsWrite); } else if(token == "isread") { @@ -388,7 +386,6 @@ int32_t ExpressionEvaluator::Evaluate(ExpressionData &data, DebugState &state, E case EvalValues::Irq: token = state.CPU.IRQFlag; resultType = EvalResultType::Boolean; break; case EvalValues::Value: token = operationInfo.Value; break; case EvalValues::Address: token = operationInfo.Address; break; - case EvalValues::AbsoluteAddress: token = _debugger->GetAbsoluteAddress(operationInfo.Address); break; case EvalValues::IsWrite: token = operationInfo.OperationType == MemoryOperationType::Write || operationInfo.OperationType == MemoryOperationType::DummyWrite; break; case EvalValues::IsRead: token = operationInfo.OperationType == MemoryOperationType::Read || operationInfo.OperationType == MemoryOperationType::DummyRead; break; case EvalValues::PreviousOpPC: token = state.CPU.PreviousDebugPC; break; @@ -442,6 +439,16 @@ int32_t ExpressionEvaluator::Evaluate(ExpressionData &data, DebugState &state, E case EvalOperators::Minus: token = -right; break; case EvalOperators::BinaryNot: token = ~right; break; case EvalOperators::LogicalNot: token = !right; break; + case EvalOperators::AbsoluteAddress: { + if(right >= 0) { + AddressTypeInfo addressInfo; + _debugger->GetAbsoluteAddressAndType((uint32_t)right, &addressInfo); + token = addressInfo.Address; + } else { + token = -1; + } + break; + } case EvalOperators::Bracket: token = _debugger->GetMemoryDumper()->GetMemoryValue(DebugMemoryType::CpuMemory, (uint32_t)right); break; case EvalOperators::Braces: token = _debugger->GetMemoryDumper()->GetMemoryValueWord(DebugMemoryType::CpuMemory, (uint32_t)right); break; default: throw std::runtime_error("Invalid operator"); @@ -591,5 +598,12 @@ void ExpressionEvaluator::RunTests() test("%011", EvalResultType::Numeric, 3); test("%1011", EvalResultType::Numeric, 11); test("%12", EvalResultType::Invalid, 0); + + test(":$00", EvalResultType::Numeric, 0); + test(":50", EvalResultType::Numeric, 50); + test(":$50", EvalResultType::Numeric, 0x50); + test(":($1FFF+1)", EvalResultType::Numeric, -1); + test(":$1FFF+1", EvalResultType::Numeric, 0x2000); + test("1+:$100", EvalResultType::Numeric, 0x101); } #endif \ No newline at end of file diff --git a/Core/ExpressionEvaluator.h b/Core/ExpressionEvaluator.h index 9471130f..effcdc82 100644 --- a/Core/ExpressionEvaluator.h +++ b/Core/ExpressionEvaluator.h @@ -36,10 +36,11 @@ enum EvalOperators : int64_t Minus = 20000000051, BinaryNot = 20000000052, LogicalNot = 20000000053, + AbsoluteAddress = 20000000054, //Used to read ram address - Bracket = 20000000054, //Read byte - Braces = 20000000055, //Read word + Bracket = 20000000060, //Read byte + Braces = 20000000061, //Read word //Special value, not used as an operator Parenthesis = 20000000100, @@ -61,7 +62,6 @@ enum EvalValues : int64_t Irq = 20000000111, Value = 20000000112, Address = 20000000113, - AbsoluteAddress = 20000000114, IsWrite = 20000000115, IsRead = 20000000116, PreviousOpPC = 20000000117, diff --git a/Docs/content/debugging/Debugger.md b/Docs/content/debugging/Debugger.md index f5c98f5d..85c5449d 100644 --- a/Docs/content/debugging/Debugger.md +++ b/Docs/content/debugging/Debugger.md @@ -133,6 +133,20 @@ The syntax is identical to C/C++ (e.g `&&` for AND, `||` for OR) and uses the sa Use the $ prefix to denote hexadecimal values (e.g: `$FF`) or the % prefix for binary values (e.g: `%1101`) {{% /notice %}} +#### Operators #### + +The following operators are supported (same usage/precedence as C): +`*`, `/`, `%`, `+`, `-`, `<<`, `>>`, `<`, `<=`, `>`, `>=`, `==`, `!=`, `&`, `^`, `|`, `&&`, `||`, `~`, `!`, `(`, `)` + +Additionally, the following special operators exist: + +* **[*address/label*]**: Surrounding a value/expression with brackets will read the corresponding memory address and return its value (1 byte). + * e.g: `[$8000]` will read the value at address $8000 and return it. +* **{*address/label*}**: Surrounding a value/expression with curly brackets will read the corresponding memory address and return its value (2 byte). + * e.g: `{myLabel}` will read 2 bytes of memory at the address represented by the `myLabel` label and return its value +* **:*address/label***: Prepending a `:` before an address/label will return the offset of the corresponding address within that memory type. If an address is not mapped to any type of memory, `-1` will be returned. + * e.g: `:$8000` will return the offset in PRG ROM of the byte currently mapped at the CPU address $8000. + #### Special values #### The following "variables" can be used in both the watch window and contional breakpoints to check the state of specific portions of the emulation core. @@ -147,9 +161,6 @@ The following "variables" can be used in both the watch window and contional bre * **Frame**: PPU frame number (since power on/reset) * **Value**: Current value being read/written from/to memory * **Address**: Current CPU memory address being read/written -* **RomAddress**: Current ROM address being read/written -* **[<address>]**: (Byte) Memory value at <address> (CPU) -* **{<address>}**: (Word) Memory value at <address> (CPU) **Flags**