Debugger: Added ":" operator to return an address' offset in prg/sram/wram/etc.

This commit is contained in:
Sour 2019-11-04 20:16:20 -05:00
parent fafb52df0d
commit bc335e104d
3 changed files with 37 additions and 12 deletions

View file

@ -11,9 +11,9 @@
const vector<string> ExpressionEvaluator::_binaryOperators = { { "*", "/", "%", "+", "-", "<<", ">>", "<", "<=", ">", ">=", "==", "!=", "&", "^", "|", "&&", "||" } }; const vector<string> ExpressionEvaluator::_binaryOperators = { { "*", "/", "%", "+", "-", "<<", ">>", "<", "<=", ">", ">=", "==", "!=", "&", "^", "|", "&&", "||" } };
const vector<int> ExpressionEvaluator::_binaryPrecedence = { { 10, 10, 10, 9, 9, 8, 8, 7, 7, 7, 7, 6, 6, 5, 4, 3, 2, 1 } }; const vector<int> ExpressionEvaluator::_binaryPrecedence = { { 10, 10, 10, 9, 9, 8, 8, 7, 7, 7, 7, 6, 6, 5, 4, 3, 2, 1 } };
const vector<string> ExpressionEvaluator::_unaryOperators = { { "+", "-", "~", "!" } }; const vector<string> ExpressionEvaluator::_unaryOperators = { { "+", "-", "~", "!", ":" } };
const vector<int> ExpressionEvaluator::_unaryPrecedence = { { 11, 11, 11, 11 } }; const vector<int> ExpressionEvaluator::_unaryPrecedence = { { 11, 11, 11, 11, 11 } };
const std::unordered_set<string> ExpressionEvaluator::_operators = { { "*", "/", "%", "+", "-", "<<", ">>", "<", "<=", ">", ">=", "==", "!=", "&", "^", "|", "&&", "||", "~", "!", "(", ")", "{", "}", "[", "]" } }; const std::unordered_set<string> ExpressionEvaluator::_operators = { { "*", "/", "%", "+", "-", "<<", ">>", "<", "<=", ">", ">=", "==", "!=", "&", "^", "|", "&&", "||", "~", "!", "(", ")", "{", "}", "[", "]", ":" } };
bool ExpressionEvaluator::IsOperator(string token, int &precedence, bool unaryOperator) 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); output += std::to_string((int64_t)EvalValues::Value);
} else if(token == "address") { } else if(token == "address") {
output += std::to_string((int64_t)EvalValues::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") { } else if(token == "iswrite") {
output += std::to_string((int64_t)EvalValues::IsWrite); output += std::to_string((int64_t)EvalValues::IsWrite);
} else if(token == "isread") { } 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::Irq: token = state.CPU.IRQFlag; resultType = EvalResultType::Boolean; break;
case EvalValues::Value: token = operationInfo.Value; break; case EvalValues::Value: token = operationInfo.Value; break;
case EvalValues::Address: token = operationInfo.Address; 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::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::IsRead: token = operationInfo.OperationType == MemoryOperationType::Read || operationInfo.OperationType == MemoryOperationType::DummyRead; break;
case EvalValues::PreviousOpPC: token = state.CPU.PreviousDebugPC; 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::Minus: token = -right; break;
case EvalOperators::BinaryNot: token = ~right; break; case EvalOperators::BinaryNot: token = ~right; break;
case EvalOperators::LogicalNot: 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::Bracket: token = _debugger->GetMemoryDumper()->GetMemoryValue(DebugMemoryType::CpuMemory, (uint32_t)right); break;
case EvalOperators::Braces: token = _debugger->GetMemoryDumper()->GetMemoryValueWord(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"); default: throw std::runtime_error("Invalid operator");
@ -591,5 +598,12 @@ void ExpressionEvaluator::RunTests()
test("%011", EvalResultType::Numeric, 3); test("%011", EvalResultType::Numeric, 3);
test("%1011", EvalResultType::Numeric, 11); test("%1011", EvalResultType::Numeric, 11);
test("%12", EvalResultType::Invalid, 0); 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 #endif

View file

@ -36,10 +36,11 @@ enum EvalOperators : int64_t
Minus = 20000000051, Minus = 20000000051,
BinaryNot = 20000000052, BinaryNot = 20000000052,
LogicalNot = 20000000053, LogicalNot = 20000000053,
AbsoluteAddress = 20000000054,
//Used to read ram address //Used to read ram address
Bracket = 20000000054, //Read byte Bracket = 20000000060, //Read byte
Braces = 20000000055, //Read word Braces = 20000000061, //Read word
//Special value, not used as an operator //Special value, not used as an operator
Parenthesis = 20000000100, Parenthesis = 20000000100,
@ -61,7 +62,6 @@ enum EvalValues : int64_t
Irq = 20000000111, Irq = 20000000111,
Value = 20000000112, Value = 20000000112,
Address = 20000000113, Address = 20000000113,
AbsoluteAddress = 20000000114,
IsWrite = 20000000115, IsWrite = 20000000115,
IsRead = 20000000116, IsRead = 20000000116,
PreviousOpPC = 20000000117, PreviousOpPC = 20000000117,

View file

@ -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`) Use the $ prefix to denote hexadecimal values (e.g: `$FF`) or the % prefix for binary values (e.g: `%1101`)
{{% /notice %}} {{% /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 #### #### 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. 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) * **Frame**: PPU frame number (since power on/reset)
* **Value**: Current value being read/written from/to memory * **Value**: Current value being read/written from/to memory
* **Address**: Current CPU memory address being read/written * **Address**: Current CPU memory address being read/written
* **RomAddress**: Current ROM address being read/written
* **[&lt;address&gt;]**: (Byte) Memory value at &lt;address&gt; (CPU)
* **{&lt;address&gt;}**: (Word) Memory value at &lt;address&gt; (CPU)
**Flags** **Flags**