scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | README | LICENSE

commit bf5f923ad705e6e2c275b3415c7b18d3b4a000b9
parent 8130fb4222269cbe669a68372c1d2a28d1c34f9d
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sat, 16 Dec 2017 16:47:49 +0100

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

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

Diffstat:
Mas/as.h | 23++++++++++++++---------
Mas/expr.c | 2+-
Mas/ins.c | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Mas/myro.c | 9++++++---
Mas/symbol.c | 8+++++---
Mas/target/x80/x80.dat | 6++++++
Mobjdump/main.c | 18++++++++++--------
7 files changed, 100 insertions(+), 28 deletions(-)

diff --git 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 reloc { struct op { unsigned char flags; - char size; + unsigned char size; void (*format)(Op *, Node **); unsigned char *bytes; unsigned char *args; @@ -121,6 +125,7 @@ struct symbol { unsigned char pass; unsigned char argtype; TUINT value; + TUINT size; Section *section; struct symbol *next; struct symbol *hash; diff --git a/as/expr.c b/as/expr.c @@ -275,7 +275,7 @@ reg(void) ++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; } diff --git a/as/ins.c b/as/ins.c @@ -5,6 +5,12 @@ static char sccsid[] = "@(#) ./as/ins.c"; extern Section *sabs, *sbss, *sdata, *stext; +enum { + EQU, + COMMON, + SIZE, +}; + char * tobytes(TUINT v, int nbytes, int inc) { @@ -67,13 +73,61 @@ defq(Op *op, Node **args) 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 diff --git a/as/myro.c b/as/myro.c @@ -16,6 +16,7 @@ static size_t relcap, relsiz; static size_t writestrings(FILE *fp) { + int type; size_t off = 0; size_t len; Symbol *sym; @@ -26,7 +27,7 @@ writestrings(FILE *fp) 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,19 +102,21 @@ getsymflags(Symbol *sym) 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; symbol.section = sym->section->id; symbol.flags = getsymflags(sym); symbol.offset = sym->value; - symbol.len = 0; + symbol.len = sym->size; off += wrmyrosym(fp, &symbol); } diff --git a/as/symbol.c b/as/symbol.c @@ -65,7 +65,7 @@ lookup(char *name) 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 @@ setsec(char *name, char *attr) { 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 @@ tmpsym(TUINT val) sym = new(tmpalloc); sym->value = val; sym->section = NULL; + sym->flags = FABS; return sym; } diff --git 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 diff --git a/objdump/main.c b/objdump/main.c @@ -93,18 +93,18 @@ sectflags(struct myrosect *sec) 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) *--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 @@ printsymbols(struct obj_info *obj) 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;