shithub: scc

Download patch

ref: c8eab2fc68e164fc11882859499896bbb8e76f3d
parent: b7e1cae8e53b2a4d9cbaf505927d1abdca22f13d
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Thu Jan 25 09:28:25 EST 2018

[as] Remove memory operand from operand()

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

--- a/as/as.h
+++ b/as/as.h
@@ -141,6 +141,12 @@
 	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 *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 Symbol *linesym, *symlist;
 extern char *infile;
 extern int endpass;
+extern int yytoken;
+extern size_t yylen;
+extern union yylval yylval;
--- 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 @@
 
 #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 @@
 
 	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 @@
 	return c;
 }
 
-static int
+int
 next(void)
 {
 	int c;
@@ -337,13 +331,7 @@
 	return yytoken = c;
 }
 
-static void
-unexpected(void)
-{
-	error("unexpected '%s'", yytext);
-}
-
-static void
+void
 expect(int token)
 {
 	if (yytoken != token)
@@ -351,6 +339,13 @@
 	next();
 }
 
+void
+unexpected(void)
+{
+	error("unexpected '%s'", yytext);
+}
+
+
 /*************************************************************************/
 /* grammar functions                                                     */
 /*************************************************************************/
@@ -362,9 +357,6 @@
 	Node *np;
 
 	switch (yytoken) {
-	case REG:
-		addr = AREG;
-		goto basic_atom;
 	case IDEN:
 	case NUMBER:
 		addr = ANUMBER;
@@ -509,35 +501,48 @@
 }
 
 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);
--- a/as/target/x80/ins.c
+++ b/as/target/x80/ins.c
@@ -148,24 +148,53 @@
 	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;
 
-	switch (np->addr) {
-	case AREG:
-		op = AINDIR;
-		break;
-	case AREG_OFF:
-		op = AINDEX;
-		break;
-	case ANUMBER:
+	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(')');
+
+	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;
--- a/as/target/x86/ins.c
+++ b/as/target/x86/ins.c
@@ -38,6 +38,6 @@
 }
 
 Node *
-addrmode(void)
+moperand(void)
 {
 }