scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | README | LICENSE

commit ce6c64b4ef06cc210573c019a6255abbc0b024d2
parent 48a6fc29693471ca6a56e6691fed7ffb154a1b58
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Thu, 25 Jan 2018 14:28:25 +0100

[as] Remove memory operand from operand()

This patchs moves all the logic to the arch and implements the
test for z80.

Diffstat:
Mas/as.h | 16+++++++++++++++-
Mas/expr.c | 75++++++++++++++++++++++++++++++++++++++++-----------------------------------
Mas/target/x80/ins.c | 55++++++++++++++++++++++++++++++++++++++++++-------------
Mas/target/x86/ins.c | 2+-
4 files changed, 98 insertions(+), 50 deletions(-)

diff --git a/as/as.h b/as/as.h @@ -141,6 +141,12 @@ struct node { struct node *right; }; +union yylval { + TUINT val; + Symbol *sym; +}; + + /* symbol.c */ extern void cleansecs(void); extern void isecs(void); @@ -169,11 +175,16 @@ extern Node *operand(char **s); extern Node *expr(void); extern void deltree(Node *np); extern Node *node(int op, Node *l, Node *r); +extern Node *getreg(void); +extern void regctx(void); +extern void unexpected(void); +extern void expect(int token); +int next(void); /* proc.c */ extern void iarch(void); extern int match(Op *op, Node **args); -extern Node *addrmode(void); +extern Node *moperand(void); /* ins.c */ extern char *tobytes(TUINT v, int n, int inc); @@ -200,3 +211,6 @@ extern int endian; extern Symbol *linesym, *symlist; extern char *infile; extern int endpass; +extern int yytoken; +extern size_t yylen; +extern union yylval yylval; diff --git a/as/expr.c b/as/expr.c @@ -1,4 +1,4 @@ -static char sccsid[] = "@(#) ./as/node.c"; +static char sccsid[] = "@(#) ./as/expr.c"; #include <ctype.h> #include <limits.h> @@ -11,16 +11,12 @@ static char sccsid[] = "@(#) ./as/node.c"; #define NNODES 10 -union yylval { - TUINT val; - Symbol *sym; -}; +int yytoken; +size_t yylen; +union yylval yylval; static Alloc *arena; -static int yytoken; static char yytext[INTIDENTSIZ+1], *textp, *endp; -static size_t yylen; -static union yylval yylval; static int regmode; #define accept(t) (yytoken == (t) ? next() : 0) @@ -133,10 +129,8 @@ binary(int op, Node *l, Node *r) if (l->op == NUMBER && r->op == NUMBER) return fold(op, l, r); - else if (l->addr == AREG && r->addr == ANUMBER) - addr = AREG_OFF; - else if (l->addr == AREG && l->addr != ANUMBER) - error("incorrect operand"); + else + abort(); np = node(op, l, r); np->addr = addr; @@ -297,7 +291,7 @@ operator(void) return c; } -static int +int next(void) { int c; @@ -337,13 +331,7 @@ next(void) return yytoken = c; } -static void -unexpected(void) -{ - error("unexpected '%s'", yytext); -} - -static void +void expect(int token) { if (yytoken != token) @@ -351,6 +339,13 @@ expect(int token) next(); } +void +unexpected(void) +{ + error("unexpected '%s'", yytext); +} + + /*************************************************************************/ /* grammar functions */ /*************************************************************************/ @@ -362,9 +357,6 @@ primary(void) Node *np; switch (yytoken) { - case REG: - addr = AREG; - goto basic_atom; case IDEN: case NUMBER: addr = ANUMBER; @@ -509,35 +501,48 @@ expr(void) } Node * +getreg(void) +{ + Node *np; + + np = node(REG, NULL, NULL); + np->sym = yylval.sym; + np->addr = AREG; + expect(REG); + return np; +} + +void +regctx(void) +{ + regmode = 1; +} + +Node * operand(char **strp) { int imm = 0; Node *np; - regmode = 1; textp = *strp; + regctx(); switch (next()) { case EOS: np = NULL; break; - case '(': - next(); - np = addrmode(); - expect(')'); - break; case REG: - np = node(yytoken, NULL, NULL); - np->sym = yylval.sym; - np->addr = AREG; - next(); + np = getreg(); break; case '$': next(); imm = 1; default: - np = expr(); - if (imm) + if (!imm) { + np = moperand(); + } else { + np = expr(); np->addr = AIMM; + } } if (yytoken != ',' && yytoken != EOS) error("trailing characters in expression '%s'", textp); diff --git a/as/target/x80/ins.c b/as/target/x80/ins.c @@ -148,24 +148,53 @@ match(Op *op, Node **args) return *args == NULL; } +/* + * (expr) -> ADIRECT + * (REG) -> AINDIR + * (REG + expr) -> AINDEX + * (REG - expr) -> AINDEX + * expr (REG) -> AINDEX + */ Node * -addrmode(void) +moperand(void) { int op; - Node *np = expr(); + Node *np, *dir, *off, *reg; + + dir = off = reg = NULL; + if (yytoken == '(') { + regctx(); + if (next() != REG) { + dir = expr(); + } else { + reg = getreg(); + switch (yytoken) { + case '+': + case '-': + off = expr(); + case ')': + break; + default: + unexpected(); + } + } + } else { + off = expr(); + regctx(); + expect('('); + reg = getreg(); + } + expect(')'); - switch (np->addr) { - case AREG: - op = AINDIR; - break; - case AREG_OFF: - op = AINDEX; - break; - case ANUMBER: + if (dir) { op = ADIRECT; - break; - default: - abort(); + np = dir; + } else if (off) { + np = node(AREG_OFF, reg, off); + op = AINDEX; + } else { + np = reg; + op = AINDIR; } np = node(op, np, NULL); np->addr = op; diff --git a/as/target/x86/ins.c b/as/target/x86/ins.c @@ -38,6 +38,6 @@ match(Op *op, Node **args) } Node * -addrmode(void) +moperand(void) { }