# HG changeset patch # User lost@l-w.ca # Date 1279168435 21600 # Node ID fbb7bfed80768cd10ade41a57a1f1f4a44c1e15e # Parent 8991eb507d2d46de1d8fe80678b93d273c2f026c Added in structure support and fixed up some warts in the listing code (by adding more warts) diff -r 8991eb507d2d -r fbb7bfed8076 lwasm/Makefile.am --- a/lwasm/Makefile.am Wed Jul 14 20:17:57 2010 -0600 +++ b/lwasm/Makefile.am Wed Jul 14 22:33:55 2010 -0600 @@ -4,6 +4,7 @@ instab.c symbol.c macro.c pass2.c pass3.c pass4.c pass5.c pass6.c \ insn_inh.c insn_rtor.c insn_tfm.c insn_rlist.c insn_rel.c \ insn_bitbit.c insn_indexed.c insn_gen.c insn_logicmem.c \ - pseudo.c section.c os9.c pass7.c debug.c output.c list.c + pseudo.c section.c os9.c pass7.c debug.c output.c list.c \ + struct.c lwasm_LDADD = -L$(top_builddir)/lib -L$(top_srcdir)/lib -L$(top_builddir)/lwlib -L$(top_srcdir)/lwlib -lgnu -llw EXTRA_DIST = lwasm.h input.h instab.h diff -r 8991eb507d2d -r fbb7bfed8076 lwasm/instab.c --- a/lwasm/instab.c Wed Jul 14 20:17:57 2010 -0600 +++ b/lwasm/instab.c Wed Jul 14 22:33:55 2010 -0600 @@ -285,6 +285,14 @@ extern RESOLVEFUNC(pseudo_resolve_align); extern EMITFUNC(pseudo_emit_align); +extern PARSEFUNC(pseudo_parse_struct); +#define pseudo_resolve_struct NULL +#define pseudo_emit_struct NULL + +extern PARSEFUNC(pseudo_parse_endstruct); +#define pseudo_resolve_endstruct NULL +#define pseudo_emit_endstruct NULL + instab_t instab[] = { @@ -555,9 +563,9 @@ { "export", { -1, -1, -1, -1 }, pseudo_parse_export, pseudo_resolve_export, pseudo_emit_export, lwasm_insn_setsym}, { "extdep", { -1, -1, -1, -1 }, pseudo_parse_extdep, pseudo_resolve_extdep, pseudo_emit_extdep, lwasm_insn_setsym}, - { "rmb", { -1, -1, -1, -1 }, pseudo_parse_rmb, pseudo_resolve_rmb, pseudo_emit_rmb, lwasm_insn_normal}, - { "rmd", { -1, -1, -1, -1 }, pseudo_parse_rmd, pseudo_resolve_rmd, pseudo_emit_rmd, lwasm_insn_normal}, - { "rmq", { -1, -1, -1, -1 }, pseudo_parse_rmq, pseudo_resolve_rmq, pseudo_emit_rmq, lwasm_insn_normal}, + { "rmb", { -1, -1, -1, -1 }, pseudo_parse_rmb, pseudo_resolve_rmb, pseudo_emit_rmb, lwasm_insn_struct}, + { "rmd", { -1, -1, -1, -1 }, pseudo_parse_rmd, pseudo_resolve_rmd, pseudo_emit_rmd, lwasm_insn_struct}, + { "rmq", { -1, -1, -1, -1 }, pseudo_parse_rmq, pseudo_resolve_rmq, pseudo_emit_rmq, lwasm_insn_struct}, { "zmb", { -1, -1, -1, -1 }, pseudo_parse_zmb, pseudo_resolve_zmb, pseudo_emit_zmb, lwasm_insn_normal}, { "zmd", { -1, -1, -1, -1 }, pseudo_parse_zmd, pseudo_resolve_zmd, pseudo_emit_zmd, lwasm_insn_normal}, @@ -608,6 +616,9 @@ { "ends", { -1, -1, -1, -1}, pseudo_parse_endsection,pseudo_resolve_endsection, pseudo_emit_endsection, lwasm_insn_normal}, { "endsect", { -1, -1, -1, -1}, pseudo_parse_endsection,pseudo_resolve_endsection, pseudo_emit_endsection, lwasm_insn_normal}, { "endsection", { -1, -1, -1, -1}, pseudo_parse_endsection,pseudo_resolve_endsection, pseudo_emit_endsection, lwasm_insn_normal}, + + { "struct", { -1, -1, -1, -1}, pseudo_parse_struct, pseudo_resolve_struct, pseudo_emit_struct, lwasm_insn_normal}, + { "endstruct", { -1, -1, -1, -1}, pseudo_parse_endstruct, pseudo_resolve_endstruct, pseudo_emit_endstruct, lwasm_insn_struct}, { "pragma", { -1, -1, -1, -1}, pseudo_parse_pragma, pseudo_resolve_pragma, pseudo_emit_pragma, lwasm_insn_normal}, @@ -643,9 +654,9 @@ { ".asciz", { -1, -1, -1, -1}, pseudo_parse_fcn, pseudo_resolve_fcn, pseudo_emit_fcn, lwasm_insn_normal}, { ".strz", { -1, -1, -1, -1}, pseudo_parse_fcn, pseudo_resolve_fcn, pseudo_emit_fcn, lwasm_insn_normal}, - { ".blkb", { -1, -1, -1, -1}, pseudo_parse_rmb, pseudo_resolve_rmb, pseudo_emit_rmb, lwasm_insn_normal}, - { ".ds", { -1, -1, -1, -1}, pseudo_parse_rmb, pseudo_resolve_rmb, pseudo_emit_rmb, lwasm_insn_normal}, - { ".rs", { -1, -1, -1, -1}, pseudo_parse_rmb, pseudo_resolve_rmb, pseudo_emit_rmb, lwasm_insn_normal}, + { ".blkb", { -1, -1, -1, -1}, pseudo_parse_rmb, pseudo_resolve_rmb, pseudo_emit_rmb, lwasm_insn_struct}, + { ".ds", { -1, -1, -1, -1}, pseudo_parse_rmb, pseudo_resolve_rmb, pseudo_emit_rmb, lwasm_insn_struct}, + { ".rs", { -1, -1, -1, -1}, pseudo_parse_rmb, pseudo_resolve_rmb, pseudo_emit_rmb, lwasm_insn_struct}, // for compatibility { ".end", { -1, -1, -1, -1 }, pseudo_parse_end, pseudo_resolve_end, pseudo_emit_end, lwasm_insn_normal}, diff -r 8991eb507d2d -r fbb7bfed8076 lwasm/instab.h --- a/lwasm/instab.h Wed Jul 14 20:17:57 2010 -0600 +++ b/lwasm/instab.h Wed Jul 14 22:33:55 2010 -0600 @@ -38,11 +38,12 @@ enum { - lwasm_insn_normal = 0, lwasm_insn_cond = 1, /* conditional instruction */ lwasm_insn_endm = 2, /* end of macro */ lwasm_insn_setsym = 4, /* insn sets symbol address */ - lwasm_insn_is6309 = 8 /* insn is 6309 only */ + lwasm_insn_is6309 = 8, /* insn is 6309 only */ + lwasm_insn_struct = 16, /* insn allowed in a struct */ + lwasm_insn_normal = 0 }; diff -r 8991eb507d2d -r fbb7bfed8076 lwasm/list.c --- a/lwasm/list.c Wed Jul 14 20:17:57 2010 -0600 +++ b/lwasm/list.c Wed Jul 14 22:33:55 2010 -0600 @@ -55,15 +55,53 @@ { if (cl -> len < 1) { - fprintf(of, " "); + if (cl -> soff >= 0) + { + fprintf(of, "%04X ", cl -> soff & 0xffff); + } + else if (cl -> dshow >= 0) + { + if (cl -> dsize == 1) + { + fprintf(of, " %02X ", cl -> dshow & 0xff); + } + else + { + fprintf(of, " %04X ", cl -> dshow & 0xff); + } + } + else if (cl -> dptr) + { + lw_expr_t te; + te = lw_expr_copy(cl -> dptr -> value); + as -> exportcheck = 1; + as -> csect = cl -> csect; + lwasm_reduce_expr(as, te); + as -> exportcheck = 0; + if (lw_expr_istype(te, lw_expr_type_int)) + { + fprintf(of, " %04X ", lw_expr_intval(te) & 0xffff); + } + else + { + fprintf(of, " ???? "); + } + lw_expr_destroy(te); + } + else + { + fprintf(of, " "); + } } else { lw_expr_t te; te = lw_expr_copy(cl -> addr); as -> exportcheck = 1; + as -> csect = cl -> csect; lwasm_reduce_expr(as, te); as -> exportcheck = 0; +// fprintf(of, "%s\n", lw_expr_print(te)); fprintf(of, "%04X ", lw_expr_intval(te) & 0xffff); lw_expr_destroy(te); for (i = 0; i < cl -> outputl && i < 8; i++) @@ -76,7 +114,7 @@ } fprintf(of, " "); } - fprintf(of, "%15s:%05d %s\n", cl -> linespec, cl -> lineno, cl -> ltext); + fprintf(of, "(%31.31s):%05d %s\n", cl -> linespec, cl -> lineno, cl -> ltext); if (cl -> outputl > 8) { for (i = 8; i < cl -> outputl; i++) diff -r 8991eb507d2d -r fbb7bfed8076 lwasm/lwasm.h --- a/lwasm/lwasm.h Wed Jul 14 20:17:57 2010 -0600 +++ b/lwasm/lwasm.h Wed Jul 14 22:33:55 2010 -0600 @@ -166,11 +166,16 @@ char *ltext; // line number char *linespec; // line spec int lineno; // line number + int soff; // struct offset (for listings) + int dshow; // data value to show (for listings) + int dsize; // set to 1 for 8 bit dshow value + struct symtabe *dptr; // symbol value to display }; enum { symbol_flag_set = 1, // symbol was used with "set" + symbol_flag_nocheck = 2, // do not check symbol characters symbol_flag_none = 0 // no flags }; @@ -198,6 +203,26 @@ int numlines; // number lines in macro macrotab_t *next; // next macro in list }; + +typedef struct structtab_s structtab_t; +typedef struct structtab_field_s structtab_field_t; + +struct structtab_field_s +{ + char *name; // structure field name - NULL for anonymous + int size; // structure field size + structtab_t *substruct; // sub structure if there is one + structtab_field_t *next; // next field entry +}; + +struct structtab_s +{ + char *name; // name of structure + int size; // number of bytes taken by struct + structtab_field_t *fields; // fields in the structure + structtab_t *next; // next structure +}; + struct asmstate_s { int output_format; // output format @@ -208,6 +233,7 @@ int pragmas; // pragmas currently in effect int errorcount; // number of errors encountered int inmacro; // are we in a macro? + int instruct; // are w in a structure? int skipcond; // skipping a condition? int skipcount; // depth of "skipping" int skipmacro; // are we skipping in a macro? @@ -239,6 +265,9 @@ lw_stringlist_t include_list; // include paths lw_stack_t file_dir; // stack of the "current file" dir lw_stack_t includelist; + + structtab_t *structs; // defined structures + structtab_t *cstruct; // current structure int exportcheck; // set if we need to collapse out the section base to 0 }; diff -r 8991eb507d2d -r fbb7bfed8076 lwasm/pass1.c --- a/lwasm/pass1.c Wed Jul 14 20:17:57 2010 -0600 +++ b/lwasm/pass1.c Wed Jul 14 22:33:55 2010 -0600 @@ -31,6 +31,9 @@ #include "instab.h" #include "input.h" +extern int expand_macro(asmstate_t *as, line_t *l, char **p, char *opc); +extern int expand_struct(asmstate_t *as, line_t *l, char **p, char *opc); + /* pass 1: parse the lines @@ -91,6 +94,10 @@ cl -> pragmas = as -> pragmas; cl -> context = as -> context; cl -> ltext = lw_strdup(line); + cl -> soff = -1; + cl -> dshow = -1; + cl -> dsize = 0; + cl -> dptr = NULL; as -> cl = cl; if (!as -> line_tail) { @@ -226,7 +233,7 @@ // do nothing if (as -> skipcond && !(instab[opnum].flags & lwasm_insn_cond)) goto linedone; - + if (instab[opnum].opcode == NULL) { cl -> insn = -1; @@ -236,7 +243,11 @@ if (expand_macro(as, cl, &p1, sym) != 0) { // macro expansion failed - lwasm_register_error(as, cl, "Bad opcode"); + if (expand_struct(as, cl, &p1, sym) != 0) + { + // structure expansion failed + lwasm_register_error(as, cl, "Bad opcode"); + } } } } @@ -246,13 +257,20 @@ // no parse func means operand doesn't matter if (instab[opnum].parse) { - cl -> len = -1; - // call parse function - (instab[opnum].parse)(as, cl, &p1); + if (as -> instruct == 0 || instab[opnum].flags & lwasm_insn_struct) + { + cl -> len = -1; + // call parse function + (instab[opnum].parse)(as, cl, &p1); - if (*p1 && !isspace(*p1)) + if (*p1 && !isspace(*p1)) + { + // flag bad operand error + lwasm_register_error(as, cl, "Bad operand (%s)", p1); + } + } + else if (as -> instruct == 1) { - // flag bad operand error lwasm_register_error(as, cl, "Bad operand (%s)", p1); } } diff -r 8991eb507d2d -r fbb7bfed8076 lwasm/pseudo.c --- a/lwasm/pseudo.c Wed Jul 14 20:17:57 2010 -0600 +++ b/lwasm/pseudo.c Wed Jul 14 22:33:55 2010 -0600 @@ -29,6 +29,8 @@ #include "lw_string.h" +extern void register_struct_entry(asmstate_t *as, line_t *l, int size, structtab_t *ss); + // for "end" PARSEFUNC(pseudo_parse_end) { @@ -302,6 +304,22 @@ { lwasm_register_error(as, l, "Bad expression"); } + + if (as -> instruct) + { + lwasm_reduce_expr(as, expr); + if (!lw_expr_istype(expr, lw_expr_type_int)) + { + lwasm_register_error(as, l, "Expression must be constant at parse time"); + } + else + { + int e; + e = lw_expr_intval(expr); + register_struct_entry(as, l, e, NULL); + l -> len = 0; + } + } lwasm_save_expr(l, 0, expr); } @@ -337,6 +355,21 @@ lwasm_register_error(as, l, "Bad expression"); } + if (as -> instruct) + { + lwasm_reduce_expr(as, expr); + if (!lw_expr_istype(expr, lw_expr_type_int)) + { + lwasm_register_error(as, l, "Expression must be constant at parse time"); + } + else + { + int e; + e = lw_expr_intval(expr) * 2; + register_struct_entry(as, l, e, NULL); + l -> len = 0; + } + } lwasm_save_expr(l, 0, expr); } @@ -371,6 +404,21 @@ { lwasm_register_error(as, l, "Bad expression"); } + if (as -> instruct) + { + lwasm_reduce_expr(as, expr); + if (!lw_expr_istype(expr, lw_expr_type_int)) + { + lwasm_register_error(as, l, "Expression must be constant at parse time"); + } + else + { + int e; + e = lw_expr_intval(expr) * 4; + register_struct_entry(as, l, e, NULL); + l -> len = 0; + } + } lwasm_save_expr(l, 0, expr); } @@ -563,6 +611,7 @@ register_symbol(as, l, l -> sym, e, symbol_flag_none); l -> symset = 1; + l -> dptr = lookup_symbol(as, l, l -> sym); } PARSEFUNC(pseudo_parse_set) @@ -586,6 +635,7 @@ register_symbol(as, l, l -> sym, e, symbol_flag_set); l -> symset = 1; + l -> dptr = lookup_symbol(as, l, l -> sym); } PARSEFUNC(pseudo_parse_setdp) @@ -613,6 +663,8 @@ return; } l -> dpval = lw_expr_intval(e) & 0xff; + l -> dshow = l -> dpval; + l -> dsize = 1; } PARSEFUNC(pseudo_parse_ifp1) diff -r 8991eb507d2d -r fbb7bfed8076 lwasm/struct.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwasm/struct.c Wed Jul 14 22:33:55 2010 -0600 @@ -0,0 +1,218 @@ +/* +struct.c +Copyright © 2010 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 processing +*/ + +#include + +#include + +#include +#include + +#include "lwasm.h" +#include "instab.h" + +PARSEFUNC(pseudo_parse_struct) +{ + structtab_t *s; + + if (as -> instruct) + { + lwasm_register_error(as, l, "Attempt to define a structure inside a structure"); + return; + } + + if (l -> sym == NULL) + { + lwasm_register_error(as, l, "Structure definition with no effect - no symbol"); + return; + } + + for (s = as -> structs; s; s = s -> next) + { + if (!strcmp(s -> name, l -> sym)) + break; + } + + if (s) + { + lwasm_register_error(as, l, "Duplicate structure definition"); + return; + } + + as -> instruct = 1; + + s = lw_alloc(sizeof(structtab_t)); + s -> name = lw_strdup(l -> sym); + s -> next = as -> structs; + s -> fields = NULL; + s -> size = 0; + as -> structs = s; + as -> cstruct = s; + + skip_operand(p); + + l -> len = 0; + l -> symset = 1; +} + +void pseudo_endstruct_aux(asmstate_t *as, line_t *l, structtab_field_t *e, const char *prefix, int *coff) +{ + char *symname = NULL; + lw_expr_t te1, te2; + + while (e) + { + if (e -> name) + 0 == asprintf(&symname, "%s.%s", prefix, e -> name); + else + 0 == asprintf(&symname, "%s.____%d", prefix, *coff); + + // register the symbol + te1 = lw_expr_build(lw_expr_type_int, *coff); + te2 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_plus, te1, l -> addr); + register_symbol(as, l, symname, te2, symbol_flag_nocheck); + lw_expr_destroy(te2); + lw_expr_destroy(te1); + + if (e -> substruct) + { + char *t; + 0 == asprintf(&t, "sizeof{%s}", symname); + te1 = lw_expr_build(lw_expr_type_int, e -> substruct -> size); + register_symbol(as, l, t, te1, symbol_flag_nocheck); + lw_expr_destroy(te1); + lw_free(t); + pseudo_endstruct_aux(as, l, e -> substruct -> fields, symname, coff); + } + else + { + *coff += e -> size; + } + e = e -> next; + } +} + + +PARSEFUNC(pseudo_parse_endstruct) +{ + char *t; + int coff = 0; + lw_expr_t te; + + if (as -> instruct == 0) + { + lwasm_register_warning(as, l, "endstruct without struct"); + skip_operand(p); + return; + } + + 0 == asprintf(&t, "sizeof{%s}", as -> cstruct -> name); + te = lw_expr_build(lw_expr_type_int, as -> cstruct -> size); + register_symbol(as, l, t, te, symbol_flag_nocheck); + lw_expr_destroy(te); + lw_free(t); + + l -> soff = as -> cstruct -> size; + as -> instruct = 0; + + skip_operand(p); + + pseudo_endstruct_aux(as, l, as -> cstruct -> fields, as -> cstruct -> name, &coff); + + l -> len = 0; +} + +void register_struct_entry(asmstate_t *as, line_t *l, int size, structtab_t *ss) +{ + structtab_field_t *e, *e2; + + l -> soff = as -> cstruct -> size; + e = lw_alloc(sizeof(structtab_field_t)); + e -> next = NULL; + e -> size = size; + if (l -> sym) + e -> name = lw_strdup(l -> sym); + else + e -> name = NULL; + e -> substruct = ss; + if (as -> cstruct -> fields) + { + for (e2 = as -> cstruct -> fields; e2 -> next; e2 = e2 -> next) + /* do nothing */ ; + e2 -> next = e; + } + else + { + as -> cstruct -> fields = e; + } + as -> cstruct -> size += size; +} + +int expand_struct(asmstate_t *as, line_t *l, char **p, char *opc) +{ + structtab_t *s; + char *t; + lw_expr_t te; + int addr = 0; + + debug_message(as, 200, "Checking for structure expansion: %s", opc); + + for (s = as -> structs; s; s = s -> next) + { + if (!strcmp(opc, s -> name)) + break; + } + + if (!s) + return -1; + + debug_message(as, 10, "Expanding structure: %s", opc); + + if (!(l -> sym)) + { + lwasm_register_error(as, l, "Cannot declare a structure without a symbol name."); + return; + } + + l -> len = s -> size; + + if (as -> instruct) + 0 == asprintf(&t, "sizeof(%s.%s}", as -> cstruct -> name, l -> sym); + else + 0 == asprintf(&t, "sizeof{%s}", l -> sym); + te = lw_expr_build(lw_expr_type_int, s -> size); + register_symbol(as, l, t, te, symbol_flag_nocheck); + lw_expr_destroy(te); + lw_free(t); + + if (as -> instruct) + 0 == asprintf(&t, "%s.%s", as -> cstruct -> name, l -> sym); + else + t = lw_strdup(l -> sym); + pseudo_endstruct_aux(as, l, s -> fields, t, &addr); + lw_free(t); + l -> symset = 1; + if (as -> instruct) + register_struct_entry(as, l, s -> size, s); + return 0; +} + diff -r 8991eb507d2d -r fbb7bfed8076 lwasm/symbol.c --- a/lwasm/symbol.c Wed Jul 14 20:17:57 2010 -0600 +++ b/lwasm/symbol.c Wed Jul 14 22:33:55 2010 -0600 @@ -38,16 +38,19 @@ int version = -1; char *cp; - if (*sym < 0x80 && !strchr(SSYMCHARS, *sym)) + if (!(flags & symbol_flag_nocheck)) { - lwasm_register_error(as, cl, "Bad symbol (%s)", sym); - return NULL; - } + if (*sym < 0x80 && !strchr(SSYMCHARS, *sym)) + { + lwasm_register_error(as, cl, "Bad symbol (%s)", sym); + return NULL; + } - if ((*sym == '$' || *sym == '@') && (sym[1] >= '0' && sym[1] <= '9')) - { - lwasm_register_error(as, cl, "Bad symbol (%s)", sym); - return NULL; + if ((*sym == '$' || *sym == '@') && (sym[1] >= '0' && sym[1] <= '9')) + { + lwasm_register_error(as, cl, "Bad symbol (%s)", sym); + return NULL; + } } for (cp = sym; *cp; cp++) @@ -58,7 +61,7 @@ islocal = 1; // bad symbol - if (*cp < 0x80 && !strchr(SYMCHARS, *cp)) + if (!(flags & symbol_flag_nocheck) && *cp < 0x80 && !strchr(SYMCHARS, *cp)) { lwasm_register_error(as, cl, "Bad symbol (%s)", sym); return NULL; @@ -84,6 +87,7 @@ break; } } + if (se) { // multiply defined symbol