#pragma once #include "stdafx.h" #include #include #include #include #include "DebugTypes.h" #include "../Utilities/SimpleLock.h" class Debugger; class LabelManager; enum EvalOperators : int64_t { //Binary operators Multiplication = 20000000000, Division = 20000000001, Modulo = 20000000002, Addition = 20000000003, Substration = 20000000004, ShiftLeft = 20000000005, ShiftRight = 20000000006, SmallerThan = 20000000007, SmallerOrEqual = 20000000008, GreaterThan = 20000000009, GreaterOrEqual = 20000000010, Equal = 20000000011, NotEqual = 20000000012, BinaryAnd = 20000000013, BinaryXor = 20000000014, BinaryOr = 20000000015, LogicalAnd = 20000000016, LogicalOr = 20000000017, //Unary operators Plus = 20000000050, Minus = 20000000051, BinaryNot = 20000000052, LogicalNot = 20000000053, //Used to read ram address Bracket = 20000000054, //Read byte Braces = 20000000055, //Read word //Special value, not used as an operator Parenthesis = 20000000100, }; enum EvalValues : int64_t { RegA = 20000000100, RegX = 20000000101, RegY = 20000000102, RegSP = 20000000103, RegPS = 20000000104, RegPC = 20000000105, RegOpPC = 20000000106, PpuFrameCount = 20000000107, PpuCycle = 20000000108, PpuScanline = 20000000109, Nmi = 20000000110, Irq = 20000000111, Value = 20000000112, Address = 20000000113, AbsoluteAddress = 20000000114, IsWrite = 20000000115, IsRead = 20000000116, PreviousOpPC = 20000000117, R0 = 20000000120, R1 = 20000000121, R2 = 20000000122, R3 = 20000000123, R4 = 20000000124, R5 = 20000000125, R6 = 20000000126, R7 = 20000000127, R8 = 20000000128, R9 = 20000000129, R10 = 20000000130, R11 = 20000000131, R12 = 20000000132, R13 = 20000000133, R14 = 20000000134, R15 = 20000000135, SrcReg = 20000000137, DstReg = 20000000138, SFR = 20000000139, PBR = 20000000140, RomBR = 20000000141, RamBR = 20000000142, RegPS_Carry = 20000000150, RegPS_Zero = 20000000151, RegPS_Interrupt = 20000000152, RegPS_Decimal = 20000000153, RegPS_8bitIndex = 20000000154, RegPS_8bit = 20000000155, RegPS_Overflow = 20000000156, RegPS_Negative = 20000000157, RegPS_16bitIndex = 20000000158, RegPS_16bit = 20000000159, // SPC flags RegPS_HalfCarry = 20000000153, RegPS_Break = 20000000154, RegPS_StackZeropage = 20000000155, RegB = 20000000160, RegC = 20000000161, RegD = 20000000162, RegE = 20000000163, RegF = 20000000164, RegH = 20000000165, RegL = 20000000166, RegAF = 20000000167, RegBC = 20000000168, RegDE = 20000000169, RegHL = 20000000170, FirstLabelIndex = 20000002000, }; enum class EvalResultType : int32_t { Numeric = 0, Boolean = 1, Invalid = 2, DivideBy0 = 3, OutOfScope = 4 }; class StringHasher { public: size_t operator()(const std::string& t) const { //Quick hash for expressions - most are likely to have different lengths, and not expecting dozens of breakpoints, either, so this should be fine. return t.size(); } }; struct ExpressionData { std::vector RpnQueue; std::vector Labels; }; class ExpressionEvaluator { private: static const vector _binaryOperators; static const vector _binaryPrecedence; static const vector _unaryOperators; static const vector _unaryPrecedence; static const std::unordered_set _operators; std::unordered_map _cache; SimpleLock _cacheLock; int64_t operandStack[1000]; Debugger* _debugger; LabelManager* _labelManager; CpuType _cpuType; SnesMemoryType _cpuMemory; bool IsOperator(string token, int &precedence, bool unaryOperator); EvalOperators GetOperator(string token, bool unaryOperator); bool CheckSpecialTokens(string expression, size_t &pos, string &output, ExpressionData &data); int64_t ProcessCpuSpcTokens(string token, bool spc); int64_t ProcessSharedTokens(string token); int64_t ProcessGsuTokens(string token); int64_t ProcessGameboyTokens(string token); string GetNextToken(string expression, size_t &pos, ExpressionData &data, bool &success, bool previousTokenIsOp); bool ProcessSpecialOperator(EvalOperators evalOp, std::stack &opStack, std::stack &precedenceStack, vector &outputQueue); bool ToRpn(string expression, ExpressionData &data); int32_t PrivateEvaluate(string expression, DebugState &state, EvalResultType &resultType, MemoryOperationInfo &operationInfo, bool &success); ExpressionData* PrivateGetRpnList(string expression, bool& success); public: ExpressionEvaluator(Debugger* debugger, CpuType cpuType); int32_t Evaluate(ExpressionData &data, DebugState &state, EvalResultType &resultType, MemoryOperationInfo &operationInfo); int32_t Evaluate(string expression, DebugState &state, EvalResultType &resultType, MemoryOperationInfo &operationInfo); ExpressionData GetRpnList(string expression, bool &success); bool Validate(string expression); #if _DEBUG void RunTests(); #endif };