%extra_argument { Debug::Command *command } %token_prefix tk %token_type { Token } %include { #include #include #include #include #include "debugger.h" #include using Debug::Token; #ifdef __cplusplus extern "C" { #endif uint32_t cpuGetSR(); uint32_t cpuGetPC(); uint32_t cpuGetAReg(unsigned); uint32_t cpuGetDReg(unsigned); #ifdef __cplusplus } #endif #undef NDEBUG } %parse_failure { //fprintf(stderr,"I don't understand.\n"); command->valid = false; } %parse_accept { command->valid = true; } %left PIPEPIPE. %left AMPAMP. %left PIPE. %left CARET. %left AMP. %left EQEQ BANGEQ. %left LT LTEQ GT GTEQ. %left LTLT GTGT. %left PLUS MINUS. %left STAR SLASH PERCENT. %right BANG TILDE. stmt ::= expr(a) EOL. { Debug::Print(a.intValue); } stmt ::= STAR EOL. { Debug::PrintRegisters(); } stmt ::= PRINT expr(a) EOL. { Debug::Print(a.intValue); } stmt ::= BREAK EOL. { Debug::Break(); } stmt ::= BREAK expr(a) EOL. { Debug::Break(a.intValue); } stmt ::= BACKTRACE EOL. { Debug::PrintBackTrace(); } stmt ::= CONTINUE EOL. { command->action = Debug::cmdContinue; command->argc = 0; } stmt ::= TBREAK EOL. { Debug::ToolBreak(); } stmt ::= TBREAK expr(a) EOL. { Debug::ToolBreak(a.intValue); } stmt ::= RBREAK EOL . { Debug::ReadBreak(); } stmt ::= RBREAK expr(a) EOL. { Debug::ReadBreak(a.intValue); } stmt ::= WBREAK EOL. { Debug::WriteBreak(); } stmt ::= WBREAK expr(a) EOL. { Debug::WriteBreak(a.intValue); } stmt ::= RWBREAK expr(a) EOL . { Debug::ReadWriteBreak(a.intValue); } stmt ::= NEXT EOL. { command->action = Debug::cmdStep; command->argc = 0; } stmt ::= NEXT expr(a) EOL. { command->action = Debug::cmdStep; command->argc = 1; command->argv[0] = a.intValue; } stmt ::= DUMP expr(a) EOL. { Debug::Dump(a.intValue); } stmt ::= DUMP expr(a) COLON expr(b) EOL. { Debug::Dump(a.intValue, b.intValue - a.intValue); } stmt ::= DUMP expr(a) AT expr(b) EOL. { Debug::Dump(a.intValue, b.intValue); } stmt ::= LIST expr(a) EOL. { Debug::List(a.intValue); } stmt ::= expr(a) SEMI SEMIH EOL. { Debug::Dump(a.intValue); } stmt ::= expr(a) COLON expr(b) SEMI SEMIH EOL. { Debug::Dump(a.intValue, b.intValue - a.intValue); } stmt ::= expr(a) AT expr(b) SEMI SEMIH EOL. { Debug::Dump(a.intValue, b.intValue); } stmt ::= expr(a) SEMI SEMII EOL. { Debug::Info(a.intValue); } stmt ::= expr(a) SEMI SEMIL EOL. { Debug::List(a.intValue); } stmt ::= expr(a) AT expr(b) SEMI SEMIL EOL. { Debug::List(a.intValue, (int)b.intValue); } stmt ::= expr(a) COLON expr(b) SEMI SEMIL EOL. { Debug::List(a.intValue, b.intValue); } stmt ::= expr(a) SEMI SEMIDATE EOL. { Debug::PrintDate(a.intValue); } stmt ::= expr(a) SEMI SEMIERROR EOL. { Debug::PrintError(a.intValue); } stmt ::= expr(a) SEMI SEMIT IDENTIFIER(b) EOL. { Debug::ApplyTemplate(a.intValue, *b.stringValue); } stmt ::= DREGISTER(a) EQ expr(b) EOL. { Debug::SetDRegister(a.intValue, b.intValue); } stmt ::= AREGISTER(a) EQ expr(b) EOL. { Debug::SetARegister(a.intValue, b.intValue); } stmt ::= XREGISTER(a) EQ expr(b) EOL. { Debug::SetXRegister(a.intValue, b.intValue); } stmt ::= HELP EOL. { Debug::Help(); } stmt ::= IDENTIFIER(a) EQ expr(b) EOL. { Debug::VariableSet(*a.stringValue, b.intValue); } expr(rhs) ::= unary(a). { rhs = a; } expr(rhs) ::= expr(a) PLUS expr(b). { rhs = Token::Make(a.intValue + b.intValue); } expr(rhs) ::= expr(a) MINUS expr(b). { rhs = Token::Make(a.intValue - b.intValue); } expr(rhs) ::= expr(a) STAR expr(b). { rhs = Token::Make(a.intValue * b.intValue); } expr(rhs) ::= expr(a) SLASH expr(b). { rhs = Token::Make(a.intValue / b.intValue); } expr(rhs) ::= expr(a) PERCENT expr(b). { rhs = Token::Make(a.intValue % b.intValue); } expr(rhs) ::= expr(a) LTLT expr(b). { rhs = Token::Make(a.intValue << b.intValue); } expr(rhs) ::= expr(a) GTGT expr(b). { rhs = Token::Make(a.intValue >> b.intValue); } expr(rhs) ::= expr(a) LT expr(b). { rhs = Token::Make(a.intValue < b.intValue); } expr(rhs) ::= expr(a) LTEQ expr(b). { rhs = Token::Make(a.intValue <= b.intValue); } expr(rhs) ::= expr(a) GT expr(b). { rhs = Token::Make(a.intValue > b.intValue); } expr(rhs) ::= expr(a) GTEQ expr(b). { rhs = Token::Make(a.intValue >= b.intValue); } expr(rhs) ::= expr(a) EQEQ expr(b). { rhs = Token::Make(a.intValue == b.intValue); } expr(rhs) ::= expr(a) BANGEQ expr(b). { rhs = Token::Make(a.intValue != b.intValue); } expr(rhs) ::= expr(a) AMP expr(b). { rhs = Token::Make(a.intValue & b.intValue); } expr(rhs) ::= expr(a) CARET expr(b). { rhs = Token::Make(a.intValue ^ b.intValue); } expr(rhs) ::= expr(a) PIPE expr(b). { rhs = Token::Make(a.intValue | b.intValue); } expr(rhs) ::= expr(a) AMPAMP expr(b). { rhs = Token::Make(a.intValue && b.intValue); } expr(rhs) ::= expr(a) PIPEPIPE expr(b). { rhs = Token::Make(a.intValue || b.intValue); } // 68k assembly - offset(register) // offset is a 16-bit quantity... this will // handle 32-bit values or 16-bit. expr(rhs) ::= unary(a) LPAREN register(b) RPAREN. { uint32_t offset = a.intValue; uint32_t value = b.intValue; // offset is 16-bits. if (offset <= 0xffff) { if (offset & 0x8000) offset |= 0xffff0000; } rhs = Token::Make(value + offset); } unary(rhs) ::= term(a). { rhs = a; } unary(rhs) ::= PLUS unary(a). [BANG] { rhs = a; } unary(rhs) ::= MINUS unary(a). [BANG] { rhs = Token::Make(-a.intValue); } unary(rhs) ::= TILDE unary(a). { rhs = Token::Make(~a.intValue); } unary(rhs) ::= BANG unary(a). { rhs = Token::Make(!a.intValue); } unary(rhs) ::= STAR unary(a). [BANG] { rhs = Token::Make(Debug::ReadLong(a)); } term(rhs) ::= LPAREN expr(a) RPAREN. { rhs = a; } term(rhs) ::= INTEGER(a). { rhs = a; } term(rhs) ::= register(a). { rhs = a; } term(rhs) ::= IDENTIFIER(a). { // should throw/barf if undefined? rhs = Token::Make(Debug::VariableGet(*a.stringValue)); } register(rhs) ::= DREGISTER(a). { rhs = Token::Make(cpuGetDReg(a)); } register(rhs) ::= AREGISTER(a). { rhs = Token::Make(cpuGetAReg(a)); } register(rhs) ::= XREGISTER(a). { switch(a) { case 0: rhs = Token::Make(cpuGetPC()); break; case 1: rhs = Token::Make(cpuGetSR()); break; default: rhs = Token::Make(0); } }