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;