mirror of
https://git.planet-casio.com/Lephenixnoir/fxsdk.git
synced 2024-12-29 13:03:37 +01:00
25db504c22
Almost-complete implementation of fxos, the disassembler in particular is now able to detect syscalls and register addresses on the fly, plus support for SH4-only instructions.
117 lines
2 KiB
Text
117 lines
2 KiB
Text
%{
|
|
#include <fxos.h>
|
|
#include <errors.h>
|
|
#include <util.h>
|
|
|
|
/* Values for tokens generated by the lexer */
|
|
static union {
|
|
char *text;
|
|
long long integer;
|
|
} yylval;
|
|
|
|
/* Token list */
|
|
#define NUMBER 0
|
|
#define SYMBOL 1
|
|
|
|
%}
|
|
|
|
%option prefix="reg"
|
|
%option noyywrap
|
|
%option nounput
|
|
|
|
decimal 0|[1-9][0-9]*
|
|
octal 0[0-7]+
|
|
hexa 0x[0-9a-fA-F]+
|
|
number {decimal}|{octal}|{hexa}
|
|
|
|
symbol [^0-9 \t\n][^\n]*
|
|
|
|
space [ \t]+
|
|
|
|
%%
|
|
|
|
^#[^\n]* ;
|
|
{space} ;
|
|
[\n] yylineno++;
|
|
|
|
{number} { yylval.integer = integer(yytext, NULL); return NUMBER; }
|
|
{symbol} { yylval.text = strdup(yytext); return SYMBOL; }
|
|
|
|
<<EOF>> return -1;
|
|
|
|
%%
|
|
|
|
#include <stdio.h>
|
|
|
|
/* lex_reg(): Peripheral register table lexer and parser */
|
|
struct reg_address *lex_reg(void *data, size_t len, int *count)
|
|
{
|
|
/* Count number of register descriptions (upper bound) */
|
|
|
|
YY_BUFFER_STATE buf = yy_scan_bytes(data, len);
|
|
yylineno = 1;
|
|
|
|
int total = 0, t;
|
|
while((t = yylex()) != -1)
|
|
{
|
|
total += (t == NUMBER);
|
|
if(t == SYMBOL) free(yylval.text);
|
|
}
|
|
|
|
yy_delete_buffer(buf);
|
|
|
|
/* Allocate a large enough register array */
|
|
|
|
struct reg_address *table = calloc(total, sizeof *table);
|
|
if(!table)
|
|
{
|
|
errf(ERR_ERRNO, "cannot allocate memory for database");
|
|
return 0;
|
|
}
|
|
|
|
/* Lex all instructions and fill in the array */
|
|
|
|
buf = yy_scan_bytes(data, len);
|
|
yylineno = 1;
|
|
|
|
struct reg_address *reg = table - 1;
|
|
int line = -1;
|
|
|
|
while(1)
|
|
{
|
|
t = yylex();
|
|
|
|
if(t == NUMBER || t == -1)
|
|
{
|
|
/* Finalize current instruction */
|
|
if(reg >= table && !reg->name)
|
|
err("%d: unnamed register", line);
|
|
else reg++;
|
|
}
|
|
if(t == -1) break;
|
|
|
|
if(t == NUMBER)
|
|
{
|
|
reg->address = yylval.integer;
|
|
line = yylineno;
|
|
}
|
|
else if(t == SYMBOL && reg < table)
|
|
{
|
|
err("%d: expected register address", yylineno);
|
|
free(yylval.text);
|
|
}
|
|
else if(t == SYMBOL && !reg->name)
|
|
{
|
|
reg->name = yylval.text;
|
|
}
|
|
else if(t == SYMBOL)
|
|
{
|
|
err("%d: excess names for 0x%08x\n", reg->address);
|
|
free(yylval.text);
|
|
}
|
|
}
|
|
|
|
yy_delete_buffer(buf);
|
|
if(count) *count = reg - table;
|
|
return table;
|
|
}
|