shithub: scc

Download patch

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;
 	}
 }