2013-07-03 21:05:00 +00:00
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <algorithm>
|
|
|
|
#include <numeric>
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
2013-07-06 20:38:11 +00:00
|
|
|
#include "debugger.h"
|
2013-07-03 21:05:00 +00:00
|
|
|
#include "parser.h"
|
|
|
|
|
|
|
|
// re2c -b -i
|
|
|
|
|
|
|
|
|
2013-07-05 17:56:24 +00:00
|
|
|
//extern "C" {
|
2013-07-03 21:05:00 +00:00
|
|
|
|
|
|
|
void *ParseAlloc(void *(*mallocProc)(size_t));
|
|
|
|
void ParseFree(void *p, void (*freeProc)(void*));
|
2013-07-06 20:38:11 +00:00
|
|
|
void Parse(void *yyp, int yymajor, uint32_t yyminor, Debug::Command *command);
|
2013-07-03 23:55:09 +00:00
|
|
|
void ParseTrace(FILE *TraceFILE, char *zTracePrompt);
|
2013-07-05 17:56:24 +00:00
|
|
|
//}
|
2013-07-03 21:05:00 +00:00
|
|
|
|
|
|
|
// p / print expression
|
|
|
|
// hd / hexdump expression [:expression]
|
|
|
|
// stack ?
|
|
|
|
// brk expression
|
|
|
|
// tbrk expression
|
|
|
|
namespace {
|
|
|
|
int tox(char c)
|
|
|
|
{
|
|
|
|
c |= 0x20; // lowercase it.
|
|
|
|
if (c >= '0' && c <= '9') return c - '0';
|
|
|
|
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t scan10(const char *begin, const char *end)
|
|
|
|
{
|
|
|
|
return std::accumulate(begin, end, 0,
|
2013-07-03 23:55:09 +00:00
|
|
|
[](uint32_t value, char c){
|
2013-07-03 21:05:00 +00:00
|
|
|
return value * 10 + c - '0';
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t scan16(const char *begin, const char *end)
|
|
|
|
{
|
|
|
|
return std::accumulate(begin, end, 0,
|
2013-07-03 23:55:09 +00:00
|
|
|
[](uint32_t value, char c){
|
2013-07-03 21:05:00 +00:00
|
|
|
return (value << 4) + tox(c);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-06 20:38:11 +00:00
|
|
|
|
|
|
|
namespace Debug {
|
2013-07-03 21:05:00 +00:00
|
|
|
bool ParseLine(const char *iter, Command *command)
|
|
|
|
{
|
|
|
|
void *parser;
|
|
|
|
|
|
|
|
parser = ParseAlloc(malloc);
|
|
|
|
|
2013-07-03 23:55:09 +00:00
|
|
|
//ParseTrace(stdout, "--> ");
|
2013-07-06 20:38:11 +00:00
|
|
|
command->action = cmdNull;
|
2013-07-03 21:05:00 +00:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
const char *begin = iter;
|
|
|
|
const char *marker;
|
|
|
|
|
|
|
|
/*!re2c
|
|
|
|
re2c:define:YYCURSOR = iter;
|
|
|
|
re2c:define:YYMARKER = marker;
|
|
|
|
re2c:define:YYCTYPE = char;
|
|
|
|
re2c:yyfill:enable = 0;
|
|
|
|
|
|
|
|
[ \t\f\r\n]+ {
|
|
|
|
// white space
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-07-03 23:55:09 +00:00
|
|
|
'>=' { Parse(parser, tkGTEQ, 0, command); continue; }
|
|
|
|
'>>' { Parse(parser, tkGTGT, 0, command); continue; }
|
|
|
|
'<=' { Parse(parser, tkLTEQ, 0, command); continue; }
|
|
|
|
'<<' { Parse(parser, tkLTLT, 0, command); continue; }
|
|
|
|
'!=' { Parse(parser, tkBANGEQ, 0, command); continue; }
|
|
|
|
'==' { Parse(parser, tkEQEQ, 0, command); continue; }
|
|
|
|
'||' { Parse(parser, tkPIPEPIPE, 0, command); continue; }
|
|
|
|
'&&' { Parse(parser, tkAMPAMP, 0, command); continue; }
|
|
|
|
|
|
|
|
|
|
|
|
'(' { Parse(parser, tkLPAREN, 0, command); continue; }
|
|
|
|
')' { Parse(parser, tkRPAREN, 0, command); continue; }
|
|
|
|
'=' { Parse(parser, tkEQ, 0, command); continue; }
|
|
|
|
'+' { Parse(parser, tkPLUS, 0, command); continue; }
|
|
|
|
'-' { Parse(parser, tkMINUS, 0, command); continue; }
|
|
|
|
'*' { Parse(parser, tkSTAR, 0, command); continue; }
|
|
|
|
'/' { Parse(parser, tkSLASH, 0, command); continue; }
|
|
|
|
'%' { Parse(parser, tkPERCENT, 0, command); continue; }
|
|
|
|
'~' { Parse(parser, tkTILDE, 0, command); continue; }
|
|
|
|
'!' { Parse(parser, tkBANG, 0, command); continue; }
|
|
|
|
'^' { Parse(parser, tkCARET, 0, command); continue; }
|
|
|
|
'&' { Parse(parser, tkAMP, 0, command); continue; }
|
|
|
|
'|' { Parse(parser, tkPIPE, 0, command); continue; }
|
|
|
|
'<' { Parse(parser, tkLT, 0, command); continue; }
|
|
|
|
'>' { Parse(parser, tkGT, 0, command); continue; }
|
2013-07-03 21:05:00 +00:00
|
|
|
|
2013-07-05 17:56:24 +00:00
|
|
|
':' { Parse(parser, tkCOLON, 0, command); continue; }
|
|
|
|
'@' { Parse(parser, tkAT, 0, command); continue; }
|
|
|
|
|
2013-07-03 21:05:00 +00:00
|
|
|
[0-9]+ {
|
|
|
|
// integer
|
|
|
|
uint32_t data;
|
|
|
|
|
|
|
|
data = std::accumulate(begin, iter, 0,
|
2013-07-03 23:55:09 +00:00
|
|
|
[](uint32_t value, char c){
|
|
|
|
return (value * 10) + c - '0';
|
2013-07-03 21:05:00 +00:00
|
|
|
});
|
|
|
|
|
2013-07-03 23:55:09 +00:00
|
|
|
Parse(parser, tkINTEGER, data, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
'$' [0-9A-Fa-f]+ {
|
|
|
|
// hex number
|
|
|
|
uint32_t data;
|
|
|
|
|
|
|
|
data = std::accumulate(begin + 1, iter, 0,
|
2013-07-03 23:55:09 +00:00
|
|
|
[](uint32_t value, char c){
|
2013-07-03 21:05:00 +00:00
|
|
|
return (value << 4) + tox(c);
|
|
|
|
}
|
|
|
|
);
|
2013-07-03 23:55:09 +00:00
|
|
|
Parse(parser, tkINTEGER, data, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
'0x' [0-9A-Fa-f]+ {
|
|
|
|
// hex number
|
|
|
|
uint32_t data;
|
|
|
|
|
|
|
|
data = std::accumulate(begin + 2, iter, 0,
|
2013-07-03 23:55:09 +00:00
|
|
|
[](uint32_t value, char c){
|
2013-07-03 21:05:00 +00:00
|
|
|
return (value << 4) + tox(c);
|
|
|
|
}
|
|
|
|
);
|
2013-07-03 23:55:09 +00:00
|
|
|
Parse(parser, tkINTEGER, data, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
['] [^']{1,4} ['] {
|
|
|
|
// 4 cc code
|
|
|
|
uint32_t data;
|
|
|
|
|
|
|
|
data = std::accumulate(begin + 1, iter - 1, 0,
|
2013-07-03 23:55:09 +00:00
|
|
|
[](uint32_t value, char c)
|
2013-07-03 21:05:00 +00:00
|
|
|
{
|
|
|
|
return (value << 8) + (unsigned)c;
|
|
|
|
}
|
|
|
|
);
|
2013-07-03 23:55:09 +00:00
|
|
|
Parse(parser, tkINTEGER, data, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
'd' [0-7] {
|
|
|
|
// data register
|
|
|
|
uint32_t data = begin[1] - '0';
|
2013-07-03 23:55:09 +00:00
|
|
|
Parse(parser, tkDREGISTER, data, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
'a' [0-7] {
|
|
|
|
// address register
|
|
|
|
uint32_t data = begin[1] - '0';
|
2013-07-03 23:55:09 +00:00
|
|
|
Parse(parser, tkAREGISTER, data, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
'pc' {
|
|
|
|
// program counter...
|
2013-07-03 23:55:09 +00:00
|
|
|
Parse(parser, tkXREGISTER, 0, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
'csr' {
|
|
|
|
// condition status register.
|
2013-07-03 23:55:09 +00:00
|
|
|
Parse(parser, tkXREGISTER, 1, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
'sp' {
|
|
|
|
// stack pointer aka a7
|
2013-07-03 23:55:09 +00:00
|
|
|
Parse(parser, tkAREGISTER, 7, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
'fp' {
|
|
|
|
// frame pointer aka a6
|
2013-07-03 23:55:09 +00:00
|
|
|
Parse(parser, tkAREGISTER, 6, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
'c' | 'continue' {
|
2013-07-03 23:55:09 +00:00
|
|
|
Parse(parser, tkCONTINUE, 0, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
'hd' | 'dump' {
|
2013-07-03 23:55:09 +00:00
|
|
|
Parse(parser, tkDUMP, 0, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
'h' | 'help' {
|
2013-07-03 23:55:09 +00:00
|
|
|
Parse(parser, tkHELP, 0, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-07-04 04:29:09 +00:00
|
|
|
'l' | 'list' {
|
|
|
|
Parse(parser, tkLIST, 0, command);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-07-03 21:05:00 +00:00
|
|
|
'n' | 'next' {
|
2013-07-03 23:55:09 +00:00
|
|
|
Parse(parser, tkNEXT, 0, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
's' | 'step' {
|
2013-07-03 23:55:09 +00:00
|
|
|
Parse(parser, tkNEXT, 0, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
'b' | 'brk' | 'break' {
|
2013-07-03 23:55:09 +00:00
|
|
|
Parse(parser, tkBREAK, 0, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-07-04 17:24:02 +00:00
|
|
|
'tbrk' | 'tbreak' | 'toolbreak' {
|
2013-07-05 17:56:24 +00:00
|
|
|
Parse(parser, tkTBREAK, 0, command);
|
2013-07-04 17:24:02 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-07-13 17:42:19 +00:00
|
|
|
'mbrk' | 'mbreak' | 'rwbrk' | 'rwbreak' {
|
|
|
|
Parse(parser, tkRWBREAK, 0, command);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
'rbrk' | 'rbreak' {
|
|
|
|
Parse(parser, tkRBREAK, 0, command);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
'wbrk' | 'wbreak' {
|
|
|
|
Parse(parser, tkWBREAK, 0, command);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-03 21:05:00 +00:00
|
|
|
'g' | 'go' {
|
2013-07-03 23:55:09 +00:00
|
|
|
Parse(parser, tkCONTINUE, 0, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-07-03 23:55:09 +00:00
|
|
|
'p' | 'print' {
|
|
|
|
Parse(parser, tkPRINT, 0, command);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-07-03 21:05:00 +00:00
|
|
|
'r' | 'run' {
|
2013-07-03 23:55:09 +00:00
|
|
|
Parse(parser, tkCONTINUE, 0, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-05 17:56:24 +00:00
|
|
|
';h' | ';hd' | ';hexdump' {
|
|
|
|
Parse(parser, tkSEMIH, 0, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-07-05 17:56:24 +00:00
|
|
|
';i' | ';info' {
|
|
|
|
Parse(parser, tkSEMII, 0, command);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
';l' | ';list' {
|
|
|
|
Parse(parser, tkSEMIL, 0, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-07-05 17:56:24 +00:00
|
|
|
|
|
|
|
|
2013-07-03 21:05:00 +00:00
|
|
|
[_A-Za-z][_A-Za-z0-9] + {
|
|
|
|
// identifier. lookup global address, tool number, etc.
|
2013-07-03 23:55:09 +00:00
|
|
|
fprintf(stderr, "illegal identifier: `%.*s`\n", (int)(iter - begin), begin);
|
2013-07-03 21:05:00 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[\x00] {
|
|
|
|
// eol.
|
2013-07-03 23:55:09 +00:00
|
|
|
Parse(parser, tkEOL, 0, command);
|
2013-07-03 21:05:00 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
[^] {
|
|
|
|
fprintf(stderr, "illegal character: `%c`\n", *begin);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-07-03 23:55:09 +00:00
|
|
|
Parse(parser, 0, 0, command);
|
|
|
|
ParseFree(parser, free);
|
2013-07-03 21:05:00 +00:00
|
|
|
|
2013-07-04 04:29:09 +00:00
|
|
|
if (!command->valid)
|
|
|
|
fprintf(stderr,"I don't understand.\n");
|
|
|
|
|
2013-07-03 21:05:00 +00:00
|
|
|
return command->valid;
|
2013-07-06 20:38:11 +00:00
|
|
|
}
|
|
|
|
|
2013-07-08 03:39:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
} // namespace Debugger
|
|
|
|
|