# HG changeset patch # User lost # Date 1250220146 0 # Node ID a58f49a77441450e1586582b1cc612c003cb1b67 # Parent aa0056ca7319567f963d95f8810ed18bb9ed15e8 Added os9 target, pragma to control whether $ localizes a symbol, and fixed some condition nesting bugs diff -r aa0056ca7319 -r a58f49a77441 ChangeLog --- a/ChangeLog Fri Jun 12 05:25:41 2009 +0000 +++ b/ChangeLog Fri Aug 14 03:22:26 2009 +0000 @@ -16,6 +16,7 @@ [!] Fixed error in the fix for invalid operands included in 2.4 [LWASM] [b] Fixed bug with "include" directive operand parsing [LWASM] [b] Fixed additional parsing errors with pseudo ops [LWASM] +[b] Fixed parsing error with various conditional nesting situations [LWASM] [+] Added includebin directive to include the literal contents of a binary file at the current assembly address. [LWASM] [+] Added || and && as boolean or and boolean and respectively [LWASM] @@ -27,6 +28,10 @@ [LWASM] [+] ALIGN now takes an optional padding value (ALIGN align,pad) to specify the byte value that will be used for padding if needed [LWASM] +[+] Added OS9 module target along with the OS9, MOD, and EMOD pseudo ops + to allow building OS9 modules [LWASM] +[+] Added pragma "dollarlocal"/"nodollarlocal" and "dollarnotlocal"/ + "nodollarnotlocal" to control whether $ localizes a symbol [LWASM] [ ] Fixed a few cosmetic issues with error reporting Version 2.4 diff -r aa0056ca7319 -r a58f49a77441 lwasm/Makefile.am --- a/lwasm/Makefile.am Fri Jun 12 05:25:41 2009 +0000 +++ b/lwasm/Makefile.am Fri Aug 14 03:22:26 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 +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_LDADD = -L$(top_builddir)/lib -L$(top_srcdir)/lib -lgnu EXTRA_DIST = instab.h lwasm.h expr.h util.h diff -r aa0056ca7319 -r a58f49a77441 lwasm/instab.c --- a/lwasm/instab.c Fri Jun 12 05:25:41 2009 +0000 +++ b/lwasm/instab.c Fri Aug 14 03:22:26 2009 +0000 @@ -66,6 +66,8 @@ extern OPFUNC(pseudo_ifge); extern OPFUNC(pseudo_iflt); extern OPFUNC(pseudo_ifle); +extern OPFUNC(pseudo_ifp1); +extern OPFUNC(pseudo_ifp2); extern OPFUNC(pseudo_else); extern OPFUNC(pseudo_endc); extern OPFUNC(pseudo_macro); @@ -83,6 +85,10 @@ extern OPFUNC(pseudo_noop); extern OPFUNC(pseudo_includebin); +extern OPFUNC(pseudo_os9); +extern OPFUNC(pseudo_mod); +extern OPFUNC(pseudo_emod); + instab_t instab[] = { { "abx", { 0x3a, -0x1, -0x1, -0x1 }, insn_inh }, @@ -371,11 +377,16 @@ { "includebin", { -1, -1, -1, -1}, pseudo_includebin }, { "include", { -1, -1, -1, -1 }, pseudo_include }, + { "use", { -1, -1, -1, -1 }, pseudo_include }, { "align", { -1, -1, -1, -1 }, pseudo_align }, { "error", { -1, -1, -1, -1}, pseudo_error }, + // these are *dangerous* + { "ifp1", { -1, -1, -1, -1}, pseudo_ifp1, 1 }, + { "ifp2", { -1, -1, -1, -1}, pseudo_ifp2, 1 }, + { "ifeq", { -1, -1, -1, -1}, pseudo_ifeq, 1 }, { "ifne", { -1, -1, -1, -1}, pseudo_ifne, 1 }, { "if", { -1, -1, -1, -1}, pseudo_ifne, 1 }, @@ -402,6 +413,11 @@ { "pragma", { -1, -1, -1, -1}, pseudo_pragma }, { "*pragma", { -1, -1, -1, -1}, pseudo_starpragma }, + + // for os9 target + { "os9", { -1, -1, -1, -1 }, pseudo_os9 }, + { "mod", { -1, -1, -1, -1 }, pseudo_mod }, + { "emod", { -1, -1, -1, -1 }, pseudo_emod }, /* for compatibility with gcc6809 output... */ { ".area", { -1, -1, -1, -1}, pseudo_section }, @@ -435,6 +451,12 @@ // for compatibility { ".end", { -1, -1, -1, -1 }, pseudo_end }, + + // extra ops that are ignored because they are generally only for + // pretty printing the listing + { "nam", { -1, -1, -1, -1 }, pseudo_noop }, + { "pag", { -1, -1, -1, -1 }, pseudo_noop }, + { "ttl", { -1, -1, -1, -1 }, pseudo_noop }, /* flag end of table */ { NULL, { -0x1, -0x1, -0x1, -0x1 }, insn_inh } diff -r aa0056ca7319 -r a58f49a77441 lwasm/lwasm.c --- a/lwasm/lwasm.c Fri Jun 12 05:25:41 2009 +0000 +++ b/lwasm/lwasm.c Fri Aug 14 03:22:26 2009 +0000 @@ -79,6 +79,13 @@ register_error(as, l, 1, "Output not allowed inside BSS sections"); return; } + + if (as -> outformat == OUTPUT_OS9 && as -> inmod == 0) + { + register_error(as, l, 1, "Output not allowed outside of module in OS9 mode"); + return; + } + if (as -> passnum == 1) return; @@ -90,6 +97,23 @@ } l -> bytes[l -> codelen] = b & 0xff; l -> codelen += 1; + + if (as -> outformat == OUTPUT_OS9 && as -> inmod) + { + // calc the CRC + b &= 0xff; + + b ^= (as -> crc) >> 16; + as -> crc <<= 8; + as -> crc ^= b << 1; + as -> crc ^= b << 6; + b ^= b << 1; + b ^= b << 2; + b ^= b << 4; + if (b & 0x80) + as -> crc ^= 0x800021; + as -> crc &= 0xffffff; + } } void lwasm_emitop(asmstate_t *as, lwasm_line_t *l, int o) diff -r aa0056ca7319 -r a58f49a77441 lwasm/lwasm.h --- a/lwasm/lwasm.h Fri Jun 12 05:25:41 2009 +0000 +++ b/lwasm/lwasm.h Fri Aug 14 03:22:26 2009 +0000 @@ -31,6 +31,7 @@ #define OUTPUT_RAW 1 // raw sequence of bytes #define OUTPUT_OBJ 2 // proprietary object file format #define OUTPUT_RAWREL 3 // raw bytes where ORG causes a SEEK in the file +#define OUTPUT_OS9 4 // os9 module target // structure for tracking sections typedef struct section_reloc_list_s section_reloc_list_t; @@ -118,6 +119,7 @@ lwasm_expr_stack_t *exprs[4]; // non-constant expression values int exprvals[4]; // constant expression values char *exprends[4]; // pointer to character after end of expression + int inmod; // in an os9 module sectiontab_t *sect; // which section is the line in? }; @@ -182,7 +184,11 @@ sectiontab_t *csect; // current section - NULL if not in one // only 6809 ops? - int no6309; + int no6309; + + // for os9 mode + int inmod; // in a module? + unsigned long crc; // running crc count } asmstate_t; // do not rewrite XXX,r to ,r if XXX evaluates to 0 @@ -191,9 +197,10 @@ #define PRAGMA_UNDEFEXTERN 2 // allow C-style escapes in fcc, fcs, and fcn directives #define PRAGMA_CESCAPES 4 - // allow "export " to import the symbol #define PRAGMA_IMPORTUNDEFEXPORT 8 +// don't have $ as a local symbol +#define PRAGMA_DOLLARNOTLOCAL 16 #ifndef __lwasm_c_seen__ #define __lwasm_E__ extern diff -r aa0056ca7319 -r a58f49a77441 lwasm/main.c --- a/lwasm/main.c Fri Jun 12 05:25:41 2009 +0000 +++ b/lwasm/main.c Fri Aug 14 03:22:26 2009 +0000 @@ -94,6 +94,11 @@ as -> outformat = OUTPUT_RAW; else if (!strcasecmp(arg, "obj")) as -> outformat = OUTPUT_OBJ; + else if (!strcasecmp(arg, "os9")) + { + as -> pragmas |= PRAGMA_DOLLARNOTLOCAL; + as -> outformat = OUTPUT_OS9; + } else { fprintf(stderr, "Invalid output format: %s\n", arg); @@ -146,7 +151,7 @@ { "debug", 'd', 0, 0, "Set debug mode"}, { "format", 'f', "TYPE", 0, - "Select output format: decb, raw, obj"}, + "Select output format: decb, raw, obj, os9"}, { "list", 'l', "FILE", OPTION_ARG_OPTIONAL, "Generate list [to FILE]"}, { "decb", 'b', 0, 0, diff -r aa0056ca7319 -r a58f49a77441 lwasm/os9.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwasm/os9.c Fri Aug 14 03:22:26 2009 +0000 @@ -0,0 +1,177 @@ +/* +os9.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 . + + +This file implements the various pseudo operations related to OS9 target +*/ +#include +#include +#include +#include +#include +#include "lwasm.h" +#include "instab.h" +#include "expr.h" +#include "util.h" + +OPFUNC(pseudo_os9) +{ + int r, rval; + + if (as -> outformat != OUTPUT_OS9) + { + register_error(as, l, 1, "os9 directive only valid for OS9 target"); + return; + } + + // fetch immediate value + r = lwasm_expr_result2(as, l, p, 0, &rval, 0); + if (r != 0) + rval = 0; + if (r == 1 && as -> passnum == 2) + register_error(as, l, 2, "Illegal external or intersegment reference"); + + // SWI2; FCB ... + lwasm_emit(as, l, 0x10); + lwasm_emit(as, l, 0x3f); + lwasm_emit(as, l, rval); +} + +OPFUNC(pseudo_mod) +{ + int modvals[6]; + int r, v, i; + + if (as -> outformat != OUTPUT_OS9) + { + register_error(as, l, 1, "mod directive only valid for OS9 target"); + return; + } + + if (as -> inmod) + { + register_error(as, l, 1, "Already in a module!"); + return; + } + + // parse 6 expressions... + for (i = 0; i < 5; i++) + { + r = lwasm_expr_result2(as, l, p, 0, &v, -1); + if (r < 0) + return; + if (r > 0) + { + register_error(as, l, 2, "Illegal external or inter-segment reference (only 1 per FDB line)"); + v = 0; + } + else + { + modvals[i] = v; + } + if (**p != ',') + { + register_error(as, l, 1, "Bad operand"); + return; + } + (*p)++; + } + r = lwasm_expr_result2(as, l, p, 0, &v, -1); + if (r < 0) + return; + if (r > 0) + { + register_error(as, l, 2, "Illegal external or inter-segment reference (only 1 per FDB line)"); + v = 0; + } + else + { + modvals[5] = v; + } + + l -> inmod = 1; + + // we have an implicit ORG 0 with "mod" + l -> codeaddr = 0; + l -> addrset = 1; + as -> addr = 0; + + // init crc + as -> crc = 0xffffff; + as -> inmod = 1; + + // sync bytes + lwasm_emit(as, l, 0x87); + lwasm_emit(as, l, 0xcd); + + // mod length + lwasm_emit(as, l, modvals[0] >> 8); + lwasm_emit(as, l, modvals[0] & 0xff); + + // name offset + lwasm_emit(as, l, modvals[1] >> 8); + lwasm_emit(as, l, modvals[1] & 0xff); + + // type + lwasm_emit(as, l, modvals[2]); + + // flags/rev + lwasm_emit(as, l, modvals[3]); + + // header check + lwasm_emit(as, l, ~(0x87 ^ 0xCD ^ (modvals[0] >> 8) ^ (modvals[0] & 0xff) + ^ (modvals[1] >> 8) ^ (modvals[1] & 0xff) + ^ modvals[2] ^ modvals[3])); + + // module type specific output + // note that these are handled the same for all so + // there need not be any special casing + + // exec offset or fmgr name offset + lwasm_emit(as, l, modvals[4] >> 8); + lwasm_emit(as, l, modvals[4] & 0xff); + + // data size or drvr name offset + lwasm_emit(as, l, modvals[5] >> 8); + lwasm_emit(as, l, modvals[5] & 0xff); +} + +OPFUNC(pseudo_emod) +{ + unsigned long tcrc; + + if (as -> outformat != OUTPUT_OS9) + { + register_error(as, l, 1, "emod directive only valid for OS9 target"); + return; + } + + if (!(as -> inmod)) + { + register_error(as, l, 1, "not in a module!"); + return; + } + + // don't mess with CRC! + tcrc = as -> crc; + lwasm_emit(as, l, tcrc >> 16); + lwasm_emit(as, l, tcrc >> 8); + lwasm_emit(as, l, tcrc); + as -> inmod = 0; +} diff -r aa0056ca7319 -r a58f49a77441 lwasm/output.c --- a/lwasm/output.c Fri Jun 12 05:25:41 2009 +0000 +++ b/lwasm/output.c Fri Aug 14 03:22:26 2009 +0000 @@ -36,6 +36,7 @@ void write_code_decb(asmstate_t *as, FILE *of); void write_code_rawrel(asmstate_t *as, FILE *of); void write_code_obj(asmstate_t *as, FILE *of); +void write_code_os9(asmstate_t *as, FILE *of); // this prevents warnings about not using the return value of fwrite() #define writebytes(s, l, c, f) do { int r; r = fwrite((s), (l), (c), (f)); } while (0) @@ -76,6 +77,10 @@ write_code_obj(as, of); break; + case OUTPUT_OS9: + write_code_os9(as, of); + break; + default: fprintf(stderr, "BUG: unrecognized output format when generating output file\n"); fclose(of); @@ -131,6 +136,30 @@ } } + +/* +OS9 target also just writes all the bytes in order. No need for anything +else. +*/ +void write_code_os9(asmstate_t *as, FILE *of) +{ + lwasm_line_t *cl; + + for (cl = as -> lineshead; cl; cl = cl -> next) + { + if (cl -> inmod == 0) + continue; + if (cl -> nocodelen) + { + int i; + for (i = 0; i < cl -> nocodelen; i++) + writebytes("\0", 1, 1, of); + continue; + } + writebytes(cl -> bytes, cl -> codelen, 1, of); + } +} + void write_code_decb(asmstate_t *as, FILE *of) { long preambloc; diff -r aa0056ca7319 -r a58f49a77441 lwasm/parse.c --- a/lwasm/parse.c Fri Jun 12 05:25:41 2009 +0000 +++ b/lwasm/parse.c Fri Aug 14 03:22:26 2009 +0000 @@ -47,6 +47,7 @@ p = l -> text; l -> sect = as -> csect; + l -> inmod = as -> inmod; // blank lines are a no brainer if (!*p) @@ -186,8 +187,8 @@ (instab[opnum].fn)(as, l, &p2, opnum); // if we didn't end on a "space" character or EOL, throw error - if (*p2 && !isspace(*p2) && !(l -> err)) - register_error(as, l, 1, "Bad operand"); + if (*p2 && !isspace(*p2) && !(l -> err) && as -> passnum == 1) + register_error(as, l, 1, "Bad operand: %s (%d)", p2, as -> passnum); } else { diff -r aa0056ca7319 -r a58f49a77441 lwasm/pass1.c --- a/lwasm/pass1.c Fri Jun 12 05:25:41 2009 +0000 +++ b/lwasm/pass1.c Fri Aug 14 03:22:26 2009 +0000 @@ -164,6 +164,8 @@ as -> passnum = 1; as -> addr = 0; as -> nextcontext = 1; + + as -> inmod = 0; debug_message(1, "Entering pass 1"); if (lwasm_read_file(as, as -> infile) < 0) diff -r aa0056ca7319 -r a58f49a77441 lwasm/pass2.c --- a/lwasm/pass2.c Fri Jun 12 05:25:41 2009 +0000 +++ b/lwasm/pass2.c Fri Aug 14 03:22:26 2009 +0000 @@ -43,6 +43,7 @@ as -> nextcontext = 1; as -> skiplines = 0; as -> dpval = 0; + as -> inmod = 0; for (st = as -> sections; st; st = st -> next) st -> offset = 0; diff -r aa0056ca7319 -r a58f49a77441 lwasm/pragma.c --- a/lwasm/pragma.c Fri Jun 12 05:25:41 2009 +0000 +++ b/lwasm/pragma.c Fri Aug 14 03:22:26 2009 +0000 @@ -117,6 +117,14 @@ { as -> pragmas &= ~PRAGMA_IMPORTUNDEFEXPORT; } + else if (!strcasecmp(pragma, "dollarnotlocal") || !strcasecmp(pragma, "nodollarlocal")) + { + as -> pragmas |= PRAGMA_DOLLARNOTLOCAL; + } + else if (!strcasecmp(pragma, "dollarlocal") || !strcasecmp(pragma, "nodollarnotlocal")) + { + as -> pragmas &= ~PRAGMA_DOLLARNOTLOCAL; + } else { if (error) diff -r aa0056ca7319 -r a58f49a77441 lwasm/pseudo.c --- a/lwasm/pseudo.c Fri Jun 12 05:25:41 2009 +0000 +++ b/lwasm/pseudo.c Fri Aug 14 03:22:26 2009 +0000 @@ -757,6 +757,7 @@ if (as -> skipcond && !(as -> skipmacro)) { as -> skipcount++; + skip_operand(p); return; } @@ -779,6 +780,7 @@ if (as -> skipcond && !(as -> skipmacro)) { as -> skipcount++; + skip_operand(p); return; } @@ -799,15 +801,14 @@ return; } - for (p2 = *p; *p2 && !isspace(*p2); p2++) + for (p2 = *p; **p && !isspace(**p); (*p)++) /* do nothing */ ; - sym = lwasm_alloc(p2 - *p + 1); - memcpy(sym, *p, p2 - *p); - sym[p2 - *p] = '\0'; - - *p = p2; + sym = lwasm_alloc(*p - p2 + 1); + memcpy(sym, p2, *p - p2); + sym[*p - p2] = '\0'; +// fprintf(stderr, "STUFF: %s; '%s'; '%s' (%d)\n", p2, *p, sym, as -> passnum); se = lwasm_find_symbol(as, sym, l -> context); if (!se) se = lwasm_find_symbol(as, sym, -1); @@ -831,10 +832,11 @@ lwasm_symbol_ent_t *se; char *sym; char *p2; - + if (as -> skipcond && !(as -> skipmacro)) { as -> skipcount++; + skip_operand(p); return; } @@ -864,6 +866,7 @@ *p = p2; +// fprintf(stderr, "STUFF2: %s; '%s'; '%s' (%d)\n", *p, p2, sym, as -> passnum); se = lwasm_find_symbol(as, sym, l -> context); if (!se) se = lwasm_find_symbol(as, sym, -1); @@ -882,6 +885,38 @@ } } +OPFUNC(pseudo_ifp1) +{ + if (as -> skipcond && !(as -> skipmacro)) + { + as -> skipcount++; + skip_operand(p); + return; + } + + if (as -> passnum != 1) + { + as -> skipcond = 1; + as -> skipcount = 1; + } +} + +OPFUNC(pseudo_ifp2) +{ + if (as -> skipcond && !(as -> skipmacro)) + { + as -> skipcount++; + skip_operand(p); + return; + } + + if (as -> passnum != 2) + { + as -> skipcond = 1; + as -> skipcount = 1; + } +} + OPFUNC(pseudo_ifeq) { int v1; @@ -890,6 +925,7 @@ if (as -> skipcond && !(as -> skipmacro)) { as -> skipcount++; + skip_operand(p); return; } @@ -911,6 +947,7 @@ if (as -> skipcond && !(as -> skipmacro)) { as -> skipcount++; + skip_operand(p); return; } @@ -932,6 +969,7 @@ if (as -> skipcond && !(as -> skipmacro)) { as -> skipcount++; + skip_operand(p); return; } @@ -953,6 +991,7 @@ if (as -> skipcond && !(as -> skipmacro)) { as -> skipcount++; + skip_operand(p); return; } @@ -974,6 +1013,7 @@ if (as -> skipcond && !(as -> skipmacro)) { as -> skipcount++; + skip_operand(p); return; } diff -r aa0056ca7319 -r a58f49a77441 lwasm/symbol.c --- a/lwasm/symbol.c Fri Jun 12 05:25:41 2009 +0000 +++ b/lwasm/symbol.c Fri Aug 14 03:22:26 2009 +0000 @@ -85,7 +85,7 @@ return -1; } // flag local symbols while we're at it... - if (*p == '?' || *p == '@' || *p == '$') + if (*p == '?' || *p == '@' || (*p == '$' && !(as -> pragmas & PRAGMA_DOLLARNOTLOCAL))) scontext = as -> context; }