shithub: scc

Download patch

ref: 64fa51cfd8c6099b14a3de110f1b620d6f12f242
parent: 5477869521457e8c088f7480104316b68914ce88
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Sat Dec 16 11:47:49 EST 2017

[as/objdump] Add .size and .comm pseudo instructions

These instructions allow to define the size and the type
of storage for memory objects.

--- a/as/as.h
+++ b/as/as.h
@@ -3,14 +3,18 @@
  * type of segment
  */
 enum symflags {
-	FREG    = 1 << 0,
-	FCOMMON = 1 << 1,
-	FEXTERN = 1 << 2,
-	FUNDEF  = 1 << 3,
-	FDEDUP  = 1 << 4,
-	FRELOC  = 1 << 5,
-	FSECT   = 1 << 6,
-	FNTYPE  = 1 << 7, 
+	FTMASK   = 0x3,
+	FNTYPE  = 0,
+	FREG    = 1,
+	FSECT   = 2,
+	FSYM    = 3,
+
+	FCOMMON = 1 << 2,
+	FEXTERN = 1 << 3,
+	FUNDEF  = 1 << 4,
+	FDEDUP  = 1 << 5,
+	FRELOC  = 1 << 6,
+	FABS    = 1 << 7,
 };
 
 enum secflags {
@@ -95,7 +99,7 @@
 
 struct op {
 	unsigned char flags;
-	char size;
+	unsigned char size;
 	void (*format)(Op *, Node **);
 	unsigned char *bytes;
 	unsigned char *args;
@@ -121,6 +125,7 @@
 	unsigned char pass;
 	unsigned char argtype;
 	TUINT value;
+	TUINT size;
 	Section *section;
 	struct symbol *next;
 	struct symbol *hash;
--- a/as/expr.c
+++ b/as/expr.c
@@ -275,7 +275,7 @@
 		++endp;
 	tok2str();
 	yylval.sym = lookup(yytext);
-	if ((yylval.sym->flags & FREG) == 0)
+	if ((yylval.sym->flags & FTMASK) != FREG)
 		error("incorrect register name '%s'", yytext);
 	return REG;
 }
--- a/as/ins.c
+++ b/as/ins.c
@@ -5,6 +5,12 @@
 
 extern Section *sabs, *sbss, *sdata, *stext;
 
+enum {
+	EQU,
+	COMMON,
+	SIZE,
+};
+
 char *
 tobytes(TUINT v, int nbytes, int inc)
 {
@@ -67,13 +73,61 @@
 	def(args, 8);
 }
 
+static void
+symexp(int which, Op *op, Node **args)
+{
+	Symbol *sym, *exp;
+	static char *cmds[] = {
+		[EQU] = "equ",
+		[COMMON] = "common",
+		[SIZE] = "size",
+	};
+	char *cmd = cmds[which];
+
+	if (args[1]) {
+		sym = args[0]->sym;
+		exp = args[1]->sym;
+	} else if (linesym) {
+		sym = linesym;
+		exp = args[0];
+	} else {
+		error("%s pseudo instruction lacks a label", cmd);
+	}
+
+	if ((exp->flags & FABS) == 0)
+		error("%s expression is not an absolute expression", cmd);
+
+	switch (which) {
+	case EQU:
+		if (pass == 1 && (sym->flags & FUNDEF) == 0)
+			error("redefinition of symbol '%s'", sym->name.buf);
+		sym->value = exp->value;
+		sym->flags &= ~FUNDEF;
+		break;
+	case COMMON:
+		sym->flags |= FCOMMON;
+	case SIZE:
+		sym->size = exp->value;
+		break;
+	}
+}
+
 void
 equ(Op *op, Node **args)
 {
-	if (!linesym)
-		error("label definition lacks a label");
-	else
-		linesym->value = (*args)->sym->value;
+	symexp(EQU, op, args);
+}
+
+void
+common(Op *op, Node **args)
+{
+	symexp(COMMON, op, args);
+}
+
+void
+size(Op *op, Node **args)
+{
+	symexp(SIZE, op, args);
 }
 
 void
--- a/as/myro.c
+++ b/as/myro.c
@@ -16,6 +16,7 @@
 static size_t
 writestrings(FILE *fp)
 {
+	int type;
 	size_t off = 0;
 	size_t len;
 	Symbol *sym;
@@ -26,7 +27,7 @@
 	off = sizeof(FORMAT);
 
 	for (sym = symlist; sym; sym = sym->next) {
-		if (sym->flags & FREG)
+		if ((sym->flags & FTMASK) == FREG)
 			continue;
 		str = &sym->name;
 		len = strlen(str->buf) + 1;
@@ -101,12 +102,14 @@
 static size_t
 writesymbols(FILE *fp)
 {
+	int type;
 	Symbol *sym;
 	size_t off = 0;
 	struct myrosym symbol;
 
 	for (sym = symlist; sym; sym = sym->next) {
-		if (sym->flags & (FREG|FSECT))
+		type = sym->flags & FTMASK;
+		if (type == FREG || type == FSECT)
 			continue;
 		symbol.name = sym->name.offset;
 		symbol.type = -1;
@@ -113,7 +116,7 @@
 		symbol.section = sym->section->id;
 		symbol.flags = getsymflags(sym);
 		symbol.offset = sym->value;
-		symbol.len = 0;
+		symbol.len = sym->size;
 		off += wrmyrosym(fp, &symbol);
 	}
 
--- a/as/symbol.c
+++ b/as/symbol.c
@@ -65,7 +65,7 @@
 	sym = xmalloc(sizeof(*sym));
 	sym->name = newstring(name);
 	sym->flags = FRELOC | FUNDEF | FNTYPE;
-	sym->value = 0;
+	sym->size = sym->value = 0;
 	sym->section = cursec;
 	sym->hash = *list;
 	sym->next = NULL;
@@ -190,11 +190,12 @@
 {
 	Section *sec;
 	Symbol *sym;
-	int flags;
+	int flags, type;
 
 	cursec = NULL;
 	sym = lookup(name);
-	if ((sym->flags & (FNTYPE | FSECT)) == 0)
+	type = sym->flags & FTMASK;
+	if (type != FNTYPE && type != FSECT)
 		error("invalid section name '%s'", name);
 
 	if ((sec = sym->section) == NULL) {
@@ -264,6 +265,7 @@
 	sym = new(tmpalloc);
 	sym->value = val;
 	sym->section = NULL;
+	sym->flags = FABS;
 
 	return sym;
 }
--- a/as/target/x80/x80.dat
+++ b/as/target/x80/x80.dat
@@ -17,8 +17,14 @@
 .INT	imm16+	0	none	defd	Z80,R800,GB80
 .DQ	imm64+	0	none	defq	Z80,R800,GB80
 .DEFQ	imm64+	0	none	defq	Z80,R800,GB80
+.EQU	sym,imm16	0	none	equ	Z80,R800,GB80
 .EQU	imm16	0	none	equ	Z80,R800,GB80
 =	imm16	0	none	equ	Z80,R800,GB80
+.SIZE	sym,imm16	0	none	size	Z80,R800,GB80
+.SIZE	imm16	0	none	size	Z80,R800,GB80
+.COMM	sym,imm16	0	none	common	Z80,R800,GB80
+.COMM	imm16	0	none	common	Z80,R800,GB80
+
 NOP	none	1	0x00	noargs	Z80,R800,GB80
 EI	none	1	0xfb	noargs	Z80,R800,GB80
 DI	none	1	0xf3	noargs	Z80,R800,GB80
--- a/objdump/main.c
+++ b/objdump/main.c
@@ -93,12 +93,6 @@
 	static char flags[10];
 	char *s = flags + sizeof(flags);
 
-	if (sec->flags & MYROSEC_READ)
-		*--s = 'R';
-	if (sec->flags & MYROSEC_WRITE)
-		*--s = 'W';
-	if (sec->flags & MYROSEC_EXEC)
-		*--s = 'X';
 	if (sec->flags & MYROSEC_LOAD)
 		*--s = 'L';
 	if (sec->flags & MYROSEC_FILE)
@@ -105,6 +99,12 @@
 		*--s = 'F';
 	if (sec->flags & MYROSEC_ABS)
 		*--s = 'A';
+	if (sec->flags & MYROSEC_EXEC)
+		*--s = 'X';
+	if (sec->flags & MYROSEC_WRITE)
+		*--s = 'W';
+	if (sec->flags & MYROSEC_READ)
+		*--s = 'R';
 	return s;
 }
 
@@ -165,22 +165,24 @@
 	struct myrohdr *hdr = &obj->hdr;
 
 	printf("symbols:\n"
-	       " [Nr]\t%s\t%-16s\t%s\t%s\t%s\n",
+	       " [Nr]\t%s\t%-16s\t%s\t%s\t%s\t%s\n",
 	       "Name",
 	       "Value",
 	       "Section",
 	       "Flags",
+	       "Size",
 	       "Type");
 	n = hdr->symsize / MYROSYM_SIZ;
 	for (i = 0; i < n; ++i) {
 		if (rdmyrosym(obj->fp, &sym) < 0)
 			return -1;
-		printf(" [%2llu]\t%s\t%016llX\t%u\t%s\t%s\n",
+		printf(" [%2llu]\t%s\t%016llX\t%u\t%s\t%llu\t%s\n",
 		       i,
 		       getstring(sym.name),
 		       sym.offset,
 		       sym.section,
 		       symflags(&sym),
+		       sym.len,
 		       getstring(sym.type));
 	}
 	return 0;