# HG changeset patch # User lost # Date 1261204723 0 # Node ID c7a41b4c89b3c1927420f2614b7317be65d32a97 # Parent c537a3a723fc16d423e50d520433e368ec811d28 Added struct support to LWASM diff -r c537a3a723fc -r c7a41b4c89b3 ChangeLog --- a/ChangeLog Wed Dec 09 03:59:26 2009 +0000 +++ b/ChangeLog Sat Dec 19 06:38:43 2009 +0000 @@ -16,6 +16,7 @@ [!] Fixed symbol resolution so all externally referenced objects, including within library archives, are properly included [LWLINK] [!] Fixed bug that prevented setting non-default stack size for LWEX [LWLINK] +[+] Added structure support (struct, endstruct) [LWASM] [+] Added "EXTDEP" pseudo op to force a dependency on an external symbol without an actual external reference - a zero-width external reference so to speak [LWASM,LWLINK] diff -r c537a3a723fc -r c7a41b4c89b3 lwasm/Makefile.am --- a/lwasm/Makefile.am Wed Dec 09 03:59:26 2009 +0000 +++ b/lwasm/Makefile.am Sat Dec 19 06:38:43 2009 +0000 @@ -1,5 +1,5 @@ AM_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib bin_PROGRAMS = lwasm -lwasm_SOURCES = main.c expr.c pass1.c pass2.c util.c instab.c parse.c lwasm.c insn_inh.c insn_rtor.c insn_rlist.c insn_rel.c insn_tfm.c insn_bitbit.c insn_indexed.c insn_gen.c insn_logicmem.c list.c symbol.c output.c pseudo.c macro.c pragma.c os9.c +lwasm_SOURCES = main.c expr.c pass1.c pass2.c util.c instab.c parse.c lwasm.c insn_inh.c insn_rtor.c insn_rlist.c insn_rel.c insn_tfm.c insn_bitbit.c insn_indexed.c insn_gen.c insn_logicmem.c list.c symbol.c output.c pseudo.c macro.c pragma.c os9.c struct.c lwasm_LDADD = -L$(top_builddir)/lib -L$(top_srcdir)/lib -lgnu EXTRA_DIST = instab.h lwasm.h expr.h util.h diff -r c537a3a723fc -r c7a41b4c89b3 lwasm/instab.c --- a/lwasm/instab.c Wed Dec 09 03:59:26 2009 +0000 +++ b/lwasm/instab.c Sat Dec 19 06:38:43 2009 +0000 @@ -86,6 +86,9 @@ extern OPFUNC(pseudo_includebin); extern OPFUNC(pseudo_extdep); +extern OPFUNC(pseudo_struct); +extern OPFUNC(pseudo_endstruct); + extern OPFUNC(pseudo_os9); extern OPFUNC(pseudo_mod); extern OPFUNC(pseudo_emod); @@ -359,9 +362,9 @@ { "extdep", { -1, -1, -1, -1 }, pseudo_extdep, 0, 0, 1 }, - { "rmb", { -1, -1, -1, -1 }, pseudo_rmb }, - { "rmd", { -1, -1, -1, -1 }, pseudo_rmd }, - { "rmq", { -1, -1, -1, -1 }, pseudo_rmq }, + { "rmb", { -1, -1, -1, -1 }, pseudo_rmb, 0, 0, 0, 0, 1 }, + { "rmd", { -1, -1, -1, -1 }, pseudo_rmd, 0, 0, 0, 0, 1 }, + { "rmq", { -1, -1, -1, -1 }, pseudo_rmq, 0, 0, 0, 0, 1 }, { "zmb", { -1, -1, -1, -1 }, pseudo_zmb }, { "zmd", { -1, -1, -1, -1 }, pseudo_zmd }, @@ -404,6 +407,10 @@ { "macro", { -1, -1, -1, -1}, pseudo_macro, 1, 0, 1 }, { "endm", { -1, -1, -1, -1}, pseudo_endm, 1, 1, 1 }, + { "struct", { -1, -1, -1, -1}, pseudo_struct, 0, 0, 0 }, + { "ends", { -1, -1, -1, -1}, pseudo_endstruct, 0, 0, 0, 0, 1}, + { "endstruct", { -1, -1, -1, -1}, pseudo_endstruct, 0, 0, 0, 0, 1 }, + { "setdp", { -1, -1, -1, -1}, pseudo_setdp }, { "set", { -1, -1, -1, -1}, pseudo_set, 0, 0, 1 }, @@ -444,9 +451,9 @@ { ".asciz", { -1, -1, -1, -1}, pseudo_fcn }, { ".strz", { -1, -1, -1, -1}, pseudo_fcn }, - { ".blkb", { -1, -1, -1, -1}, pseudo_rmb }, - { ".ds", { -1, -1, -1, -1}, pseudo_rmb }, - { ".rs", { -1, -1, -1, -1}, pseudo_rmb }, + { ".blkb", { -1, -1, -1, -1}, pseudo_rmb, 0, 0, 0, 0, 1 }, + { ".ds", { -1, -1, -1, -1}, pseudo_rmb, 0, 0, 0, 0, 1 }, + { ".rs", { -1, -1, -1, -1}, pseudo_rmb, 0, 0, 0, 0, 1 }, // needs to handle C escapes maybe? // { ".ascii", { -1, -1, -1, -1}, pseudo_ascii }, diff -r c537a3a723fc -r c7a41b4c89b3 lwasm/instab.h --- a/lwasm/instab.h Wed Dec 09 03:59:26 2009 +0000 +++ b/lwasm/instab.h Sat Dec 19 06:38:43 2009 +0000 @@ -35,6 +35,7 @@ int endm; /* end of macro? */ int setsym; /* does this set a symbol address? EQU, SET */ int is6309; /* is this 6309 only? */ + int isreserve; /* reserves space but does not output anything */ } instab_t; #define OPFUNC(fn) void (fn)(asmstate_t *as, lwasm_line_t *l, char **p, int opnum) diff -r c537a3a723fc -r c7a41b4c89b3 lwasm/lwasm.h --- a/lwasm/lwasm.h Wed Dec 09 03:59:26 2009 +0000 +++ b/lwasm/lwasm.h Sat Dec 19 06:38:43 2009 +0000 @@ -78,6 +78,26 @@ macrotab_t *next; }; +// structure for tracking structs +struct struct_sym_e; + +typedef struct structtab_s structtab_t; +struct structtab_s +{ + char *name; + int size; + struct struct_sym_e *fields; + structtab_t *next; +}; + +struct struct_sym_e +{ + char *name; + int size; + structtab_t *substruct; + struct struct_sym_e *next; +}; + // structure for tracking errors typedef struct lwasm_error_s lwasm_error_t; struct lwasm_error_s @@ -131,6 +151,7 @@ #define SYMBOL_NORM 0 // no flags #define SYMBOL_EXTERN 8 // the symbol is an external reference #define SYMBOL_GLOBAL 16 // force global if non-complex symbol +#define SYMBOL_NOCHECK 32 // don't check characters for validity typedef struct lwasm_symbol_ent_s lwasm_symbol_ent_t; struct lwasm_symbol_ent_s { @@ -162,6 +183,8 @@ lwasm_symbol_ent_t *symtail; // last entry in symbol table macrotab_t *macros; // macro table + structtab_t *structs; // structure table + structtab_t *cstruct; // address within the current structure def const char *infile; // input file const char *outfile; // output file @@ -178,6 +201,7 @@ int macroex; // current depth of macro expansion int nextcontext; // next context number int skiplines; // number of lines to skip + int instruct; // are we currently in a structure def? // items used only for the "object" target sectiontab_t *sections; // pointer to section table diff -r c537a3a723fc -r c7a41b4c89b3 lwasm/parse.c --- a/lwasm/parse.c Wed Dec 09 03:59:26 2009 +0000 +++ b/lwasm/parse.c Sat Dec 19 06:38:43 2009 +0000 @@ -188,6 +188,62 @@ if (as -> skipcond && instab[opnum].iscond == 0) goto done_line; + if (as -> instruct && as -> passnum == 1) + { + structtab_t *s = NULL; + struct struct_sym_e *e, *e2; + + // look for a structure if not an acceptable opcode + if (!instab[opnum].opcode) + { + for (s = as -> structs; s; s = s -> next) + { + if (s == as -> cstruct) + continue; + if (!strcmp(opc, s -> name)) + goto isok; + } + } + // check for a "reservation opcode" + if (instab[opnum].opcode && instab[opnum].isreserve) + { + (instab[opnum].fn)(as, l, &p2, opnum); + + // if we didn't end on a "space" character or EOL, throw error + if (p2 && *p2 && !isspace(*p2) && !(l -> err) && as -> passnum == 1) + register_error(as, l, 1, "Bad operand: %s (%d)", p2, as -> passnum); + + if (as -> instruct == 0) + goto done_line; + + goto isok; + } + // carp if not valid + register_error(as, l, 1, "Only other structs and rmb allowed in struct"); + l -> badop = 1; + goto done_line; + + isok: + for (e2 = as -> cstruct -> fields; e2 && e2 -> next; e2 = e2 -> next) + /* do nothing */ ; + e = lwasm_alloc(sizeof(struct struct_sym_e)); + e -> next = NULL; + e -> substruct = s; + if (sym) + e -> name = lwasm_strdup(sym); + else + e -> name = NULL; + if (s) + e -> size = s -> size; + else + e -> size = l -> nocodelen; + if (e2) + e2 -> next = e; + else + as -> cstruct -> fields = e; + as -> cstruct -> size += e -> size; + } + // we've registered the symbol as needed // now we need to check for a macro call IFF we don't collide with // an operation code; otherwise, call the operation function @@ -215,6 +271,9 @@ if (expand_macro(as, l, &p2, opc) == 0) goto done_line; + if (expand_struct(as, l, &p2, opc) == 0) + goto done_line; + // carp about an unknown operation code and note that fact for // pass 2 in case a macro appears later with the same name! register_error(as, l, 1, "Uknown operation code: %s", opc); @@ -225,7 +284,7 @@ if (!(as -> skipcond || as -> inmacro)) { // register symbol if the operation didn't - if (sym && instab[opnum].setsym == 0) + if (sym && instab[opnum].setsym == 0 && as -> instruct == 0) { if (as -> passnum == 1) { diff -r c537a3a723fc -r c7a41b4c89b3 lwasm/pass1.c --- a/lwasm/pass1.c Wed Dec 09 03:59:26 2009 +0000 +++ b/lwasm/pass1.c Sat Dec 19 06:38:43 2009 +0000 @@ -166,6 +166,8 @@ as -> nextcontext = 1; as -> inmod = 0; + + as -> instruct = 0; as -> extdeps = NULL; as -> nextdeps = 0; diff -r c537a3a723fc -r c7a41b4c89b3 lwasm/pass2.c --- a/lwasm/pass2.c Wed Dec 09 03:59:26 2009 +0000 +++ b/lwasm/pass2.c Sat Dec 19 06:38:43 2009 +0000 @@ -44,6 +44,7 @@ as -> skiplines = 0; as -> dpval = 0; as -> inmod = 0; + as -> instruct = 0; for (st = as -> sections; st; st = st -> next) st -> offset = 0; diff -r c537a3a723fc -r c7a41b4c89b3 lwasm/pseudo.c --- a/lwasm/pseudo.c Wed Dec 09 03:59:26 2009 +0000 +++ b/lwasm/pseudo.c Sat Dec 19 06:38:43 2009 +0000 @@ -222,6 +222,8 @@ if (r != 0) return; l -> nocodelen = v; + if (as -> instruct) + return; as -> addr += v; } @@ -240,6 +242,8 @@ return; v *= 2; l -> nocodelen = v; + if (as -> instruct) + return; as -> addr += v; } @@ -258,6 +262,8 @@ return; v *= 4; l -> nocodelen = v; + if (as -> instruct) + return; as -> addr += v; } diff -r c537a3a723fc -r c7a41b4c89b3 lwasm/struct.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwasm/struct.c Sat Dec 19 06:38:43 2009 +0000 @@ -0,0 +1,174 @@ +/* +struct.c +Copyright © 2009 William Astle + +This file is part of LWASM. + +LWASM is free software: you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see . + +Contains stuff associated with structure definition. + +Structures have their own name space. Macros will shadow structures so it's +a good idea to make sure no structures are name the same as macros. +*/ + +#include + +#include +#include +#include +#include "lwasm.h" +#include "instab.h" +#include "util.h" + +OPFUNC(pseudo_struct) +{ + structtab_t *m; + + // actually define a structure + if (as -> instruct) + { + register_error(as, l, 1, "Attempt to define a structure inside a structure"); + return; + } + + as -> instruct = 1; + + // don't actually do anything if not pass 1 + if (as -> passnum != 1) + return; + + + if (!l -> sym) + { + register_error(as, l, 1, "Structure definition with no effect - no symbol"); + return; + } + + // search for macro by same name... + for (m = as -> structs; m; m = m -> next) + { + if (!strcmp(m -> name, l -> sym)) + break; + } + if (m) + { + register_error(as, l, 1, "Duplicate structure definition"); + return; + } + + m = lwasm_alloc(sizeof(structtab_t)); + m -> name = lwasm_strdup(l -> sym); + m -> next = as -> structs; + m -> fields = NULL; + m -> size = 0; + as -> structs = m; + as -> cstruct = m; + + while (**p && !isspace(**p)) + (*p)++; +} + + + +pseudo_endstruct_aux(asmstate_t *as, lwasm_line_t *l, struct struct_sym_e *e, const char *prefix, int *coff) +{ + char *symname = NULL; + + while (e) + { + if (e -> name) + 0 == asprintf(&symname, "%s.%s", prefix, e -> name); + else + 0 == asprintf(&symname, "%s.___%d", prefix, *coff); + + // register symbol "symname" as global at coff + lwasm_register_symbol(as, l, symname, *coff, SYMBOL_NOCHECK); + + if (e -> substruct) + { + char * t; + 0 == asprintf(&t, "sizeof{%s}", symname); + lwasm_register_symbol(as, l, t, e -> substruct -> size, SYMBOL_NOCHECK); + lwasm_free(t); + pseudo_endstruct_aux(as, l, e -> substruct -> fields, symname, coff); + } + else + { + *coff += e -> size; + } + + lwasm_free(symname); + e = e -> next; + } +} + +OPFUNC(pseudo_endstruct) +{ + int coff = 0; + char *t; + + as -> instruct = 0; + + if (as -> passnum != 1) + return; + + // now register the global symbols for the structure + // this is a recursive process + 0 == asprintf(&t, "sizeof{%s}", as -> cstruct -> name); + lwasm_register_symbol(as, l, t, as -> cstruct -> size, SYMBOL_NOCHECK); + lwasm_free(t); + + pseudo_endstruct_aux(as, l, as -> cstruct -> fields, as -> cstruct -> name, &coff); +} + + +int expand_struct(asmstate_t *as, lwasm_line_t *l, char **p, char *opc) +{ + structtab_t *s; + int addr; + char *t; + + if (as -> passnum != 1) + return 0; + + for (s = as -> structs; s; s = s -> next) + { + if (!strcmp(opc, s -> name)) + break; + } + if (!s) + return -1; + + if (!(l -> sym)) + { + register_error(as, l, 1, "Cannot declare a structure without a symbol name."); + return; + } + + l -> nocodelen = s -> size; + + addr = as -> addr; + as -> addr += s -> size; + + // now register the global symbols for the structure + // this is a recursive process + 0 == asprintf(&t, "sizeof{%s}", l -> sym); + lwasm_register_symbol(as, l, t, s -> size, SYMBOL_NOCHECK); + lwasm_free(t); + + pseudo_endstruct_aux(as, l, s -> fields, l -> sym, &addr); + + return 0; +} diff -r c537a3a723fc -r c7a41b4c89b3 lwasm/symbol.c --- a/lwasm/symbol.c Wed Dec 09 03:59:26 2009 +0000 +++ b/lwasm/symbol.c Sat Dec 19 06:38:43 2009 +0000 @@ -62,7 +62,7 @@ // [a-zA-Z0-9._$?@] and any byte value larger than 0x7F // although symbols should be restricted to the 7 bit range // symbols must start with [a-zA-Z._] - if (!strchr(sym, '$')) + if ((flags & SYMBOL_NOCHECK) == 0 && !strchr(sym, '$')) { if (!strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._@?", *sym)) { @@ -79,7 +79,7 @@ for (p = sym; *p; p++) { - if (!strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._$?@0123456789", *sym)) + if ((flags & SYMBOL_NOCHECK == 0) && !strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._$?@0123456789", *sym)) { register_error(as, l, 1, "Bad symbol: %s", sym); return -1; diff -r c537a3a723fc -r c7a41b4c89b3 m4/gnulib-cache.m4 --- a/m4/gnulib-cache.m4 Wed Dec 09 03:59:26 2009 +0000 +++ b/m4/gnulib-cache.m4 Sat Dec 19 06:38:43 2009 +0000 @@ -1,4 +1,4 @@ -# Copyright (C) 2002-2008 Free Software Foundation, Inc. +# Copyright (C) 2002-2009 Free Software Foundation, Inc. # # This file is free software, distributed under the terms of the GNU # General Public License. As a special exception to the GNU General