ref: b3eaabc77b314248434e707001fd2d0d3087471c
parent: a9d67e014c29b320aeebc0b1e8bdf377cd9f5c0d
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Wed Sep 27 12:28:18 EDT 2017
[as] Add support for registers in expressions
--- a/as/as.h
+++ b/as/as.h
@@ -3,10 +3,12 @@
* type of segment
*/
enum symtype {
+ TUNDEF = 0,
TABS = 1,
TTEXT = 2,
TBSS = 3,
TDATA = 4,
+ TREG = 5,
TMASK = 7,
};
@@ -95,7 +97,7 @@
extern void killtmp(void);
/* main.c */
-extern Symbol *lookup(char *name);
+extern Symbol *lookup(char *name, int type);
extern Symbol *deflabel(char *name);
/* parser.c */
--- a/as/expr.c
+++ b/as/expr.c
@@ -181,7 +181,7 @@
while (isalnum(c = *endp) || c == '_' || c == '.')
++endp;
tok2str();
- yylval.sym = lookup(yytext);
+ yylval.sym = lookup(yytext, TUNDEF);
return IDEN;
}
@@ -238,6 +238,21 @@
}
static int
+reg(void)
+{
+ int c;
+ char *p;
+
+ while (isalnum(c = *endp))
+ ++endp;
+ tok2str();
+ yylval.sym = lookup(yytext, TREG);
+ if (!yylval.sym->argtype)
+ error("incorrect register name");
+ return REG;
+}
+
+static int
next(void)
{
int c;
@@ -246,20 +261,34 @@
++textp;
endp = textp;
- if ((c = *textp) == '\0') {
+
+ switch (c = *textp) {
+ case '\0':
strcpy(yytext, "EOS");
yylen = 3;
c = EOS;
- } else if (isalpha(c) || c == '_' || c == '.') {
- c = iden();
- } else if (isdigit(c)) {
- c = number();
- } else if (c == '\"') {
+ break;
+ case '"':
c = string();
- } else if (c == '\'') {
+ break;
+ case '\'':
c = character();
- } else {
- c = operator();
+ break;
+ case '%':
+ c = reg();
+ break;
+ case '#':
+ case '$':
+ c = number();
+ break;
+ default:
+ if (isdigit(c))
+ c = number();
+ else if (isalpha(c) || c == '_' || c == '.')
+ c = iden();
+ else
+ c = operator();
+ break;
}
return yytoken = c;
@@ -291,6 +320,7 @@
Node *np;
switch (yytoken) {
+ case REG:
case NUMBER:
case IDEN:
case STRING:
--- a/as/symbol.c
+++ b/as/symbol.c
@@ -44,11 +44,11 @@
Symbol *linesym;
Symbol *
-lookup(char *name)
+lookup(char *name, int type)
{
unsigned h;
Symbol *sym, **list;
- int c;
+ int c, symtype;
char *t, *s;
h = 0;
@@ -60,13 +60,17 @@
list = &hashtbl[h];
for (sym = *list; sym; sym = sym->next) {
t = sym->name;
- if (c == toupper(*t) && !casecmp(t, name))
- return sym;
+ if (c != toupper(*t) || casecmp(t, name))
+ continue;
+ symtype = sym->flags & TMASK;
+ if (symtype != TUNDEF && symtype != type)
+ continue;
+ return sym;
}
sym = xmalloc(sizeof(*sym));
sym->name = xstrdup(name);
- sym->flags = (cursec->flags & TMASK) | FLOCAL | FUNDEF;
+ sym->flags = (cursec->flags & TMASK) | FLOCAL | FUNDEF | type;
sym->desc = 0;
sym->value = 0;
sym->next = *list;
@@ -100,7 +104,7 @@
name = label;
}
- sym = lookup(name);
+ sym = lookup(name, TUNDEF);
if (pass == 1 && (sym->flags & FUNDEF) == 0)
error("redefinition of label '%s'", name);
sym->flags &= ~FUNDEF;
--- a/as/target/i386/proc.c
+++ b/as/target/i386/proc.c
@@ -92,7 +92,7 @@
}, *bp;
for (bp = regs; bp->name; ++bp) {
- Symbol *sym = lookup(bp->name);
+ Symbol *sym = lookup(bp->name, TREG);
sym->argtype = bp->type;
}
}
--- a/as/target/z80/proc.c
+++ b/as/target/z80/proc.c
@@ -45,7 +45,7 @@
}, *bp;
for (bp = regs; bp->name; ++bp) {
- Symbol *sym = lookup(bp->name);
+ Symbol *sym = lookup(bp->name, TREG);
sym->argtype = bp->type;
}
}