# HG changeset patch # User lost@starbug # Date 1270012201 21600 # Node ID 60568b123281d33db0fc60bb8be200d1e5921dfc # Parent faa97115952e0e90df09d260b8b3ff92a43e54e5 Added os9 opcodes and ERROR diff -r faa97115952e -r 60568b123281 lwasm/Makefile.am --- a/lwasm/Makefile.am Tue Mar 30 21:48:49 2010 -0600 +++ b/lwasm/Makefile.am Tue Mar 30 23:10:01 2010 -0600 @@ -3,6 +3,6 @@ lwasm_SOURCES = main.c pragma.c input.c pass1.c lwasm.c \ instab.c symbol.c macro.c \ insn_inh.c \ - pseudo.c section.c + pseudo.c section.c os9.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 faa97115952e -r 60568b123281 lwasm/instab.c --- a/lwasm/instab.c Tue Mar 30 21:48:49 2010 -0600 +++ b/lwasm/instab.c Tue Mar 30 23:10:01 2010 -0600 @@ -177,6 +177,10 @@ #define pseudo_resolve_endsection NULL #define pseudo_emit_endsection NULL +extern PARSEFUNC(pseudo_parse_error); +#define pseudo_resolve_error NULL +#define pseudo_emit_error NULL + instab_t instab[] = { /* @@ -470,9 +474,9 @@ { "align", { -1, -1, -1, -1 }, pseudo_parse_align, pseudo_resolve_align, pseudo_emit_align, lwasm_insn_normal}, +*/ { "error", { -1, -1, -1, -1}, pseudo_parse_error, pseudo_resolve_error, pseudo_emit_error, lwasm_insn_normal}, -*/ // these are *dangerous* { "ifp1", { -1, -1, -1, -1}, pseudo_parse_ifp1, pseudo_resolve_ifp1, pseudo_emit_ifp1, lwasm_insn_cond}, { "ifp2", { -1, -1, -1, -1}, pseudo_parse_ifp2, pseudo_resolve_ifp2, pseudo_emit_ifp2, lwasm_insn_cond}, diff -r faa97115952e -r 60568b123281 lwasm/lwasm.c --- a/lwasm/lwasm.c Tue Mar 30 21:48:49 2010 -0600 +++ b/lwasm/lwasm.c Tue Mar 30 23:10:01 2010 -0600 @@ -129,6 +129,31 @@ cl -> outputbl += 8; } cl -> output[cl -> outputl++] = byte & 0xff; + + if (cl -> inmod) + { + asmstate_t *as = cl -> as; + // update module CRC + // this is a direct transliteration from the nitros9 asm source + // to C; it can, no doubt, be optimized for 32 bit processing + byte &= 0xff; + + byte ^= (as -> crc)[0]; + (as -> crc)[0] = (as -> crc)[1]; + (as -> crc)[1] = (as -> crc)[2]; + (as -> crc)[1] ^= (byte >> 7); + (as -> crc)[2] = (byte << 1); + (as -> crc)[1] ^= (byte >> 2); + (as -> crc)[2] ^= (byte << 6); + byte ^= (byte << 1); + byte ^= (byte << 2); + byte ^= (byte << 4); + if (byte & 0x80) + { + (as -> crc)[0] ^= 0x80; + (as -> crc)[2] ^= 0x21; + } + } } void lwasm_emitop(line_t *cl, int opc) diff -r faa97115952e -r 60568b123281 lwasm/lwasm.h --- a/lwasm/lwasm.h Tue Mar 30 21:48:49 2010 -0600 +++ b/lwasm/lwasm.h Tue Mar 30 23:10:01 2010 -0600 @@ -74,6 +74,22 @@ PRAGMA_IMPORTUNDEFEXPORT = 0x0010 // imports symbol if undefined upon export }; + +enum +{ + section_flag_bss = 1, // BSS section + section_flag_none = 0 // no flags +}; + +typedef struct sectiontab_s sectiontab_t; +struct sectiontab_s +{ + char *name; // section name + int flags; // section flags; + lw_expr_t offset; // offset for next instance + sectiontab_t *next; +}; + typedef struct lwasm_error_s lwasm_error_t; struct lwasm_error_s { @@ -104,7 +120,8 @@ lwasm_error_t *warn; // list of errors line_t *prev; // previous line line_t *next; // next line - + int inmod; // inside a module? + sectiontab_t *csect; // which section are we in? struct line_expr_s *exprs; // expressions used during parsing char *lstr; // string passed forward asmstate_t *as; // assembler state data ptr @@ -139,22 +156,6 @@ int numlines; // number lines in macro macrotab_t *next; // next macro in list }; - -enum -{ - section_flag_bss = 1, // BSS section - section_flag_none = 0 // no flags -}; - -typedef struct sectiontab_s sectiontab_t; -struct sectiontab_s -{ - char *name; // section name - int flags; // section flags; - lw_expr_t offset; // offset for next instance - sectiontab_t *next; -}; - struct asmstate_s { int output_format; // output format @@ -169,6 +170,8 @@ int skipmacro; // are we skipping in a macro? int endseen; // have we seen an "end" pseudo? int execaddr; // address from "end" + int inmod; // inside an os9 module? + unsigned char crc[3]; // crc accumulator line_t *line_head; // start of lines list line_t *line_tail; // tail of lines list diff -r faa97115952e -r 60568b123281 lwasm/os9.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwasm/os9.c Tue Mar 30 23:10:01 2010 -0600 @@ -0,0 +1,192 @@ +/* +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 + +#include "lwasm.h" +#include "instab.h" + + +// OS9 syscall +PARSEFUNC(pseudo_parse_os9) +{ + lw_expr_t e; + + if (as -> output_format != OUTPUT_OS9) + { + lwasm_register_error(as, l, "os9 directive only valid for OS9 target"); + return; + } + + // fetch immediate value + e = lwasm_parse_expr(as, p); + if (!e) + { + lwasm_register_error(as, l, "Bad operand"); + return; + } + lwasm_save_expr(l, 0, e); + l -> len = 3; +} + +EMITFUNC(pseudo_emit_os9) +{ + lw_expr_t e; + + e = lwasm_fetch_expr(l, 0); + + lwasm_emitop(l, 0x103f); + lwasm_emitexpr(l, e, 1); +} + +PARSEFUNC(pseudo_parse_mod) +{ + lw_expr_t e; + int i; + + if (as -> output_format != OUTPUT_OS9) + { + lwasm_register_error(as, l, "mod directive only valid for OS9 target"); + return; + } + + if (as -> inmod) + { + lwasm_register_error(as, l, "Already in a module!"); + return; + } + + // parse 6 expressions... + for (i = 0; i < 5; i++) + { + e = lwasm_parse_expr(as, p); + if (!e) + { + lwasm_register_error(as, l, "Bad operand"); + return; + } + + lwasm_save_expr(l, i, e); + + if (**p != ',') + { + lwasm_register_error(as, l, "Bad operand"); + return; + } + (*p)++; + } + + e = lwasm_parse_expr(as, p); + if (!e) + { + lwasm_register_error(as, l, "Bad operand"); + return; + } + lwasm_save_expr(l, 5, e); + + l -> inmod = 1; + + // we have an implicit ORG 0 with "mod" + lw_expr_destroy(l -> addr); + l -> addr = lw_expr_build(lw_expr_type_int, 0); + + // init crc + as -> inmod = 1; +} + +EMITFUNC(pseudo_emit_mod) +{ + lw_expr_t e1, e2, e3, e4; + int csum; + + as -> crc[0] = 0xff; + as -> crc[1] = 0xff; + as -> crc[2] = 0xff; + + // sync bytes + lwasm_emit(l, 0x87); + lwasm_emit(l, 0xcd); + + // mod length + lwasm_emitexpr(l, e1 = lwasm_fetch_expr(l, 0), 2); + + // name offset + lwasm_emitexpr(l, e2 = lwasm_fetch_expr(l, 1), 2); + + // type + lwasm_emitexpr(l, e3 = lwasm_fetch_expr(l, 2), 1); + + // flags/rev + lwasm_emitexpr(l, e4 = lwasm_fetch_expr(l, 3), 1); + + // header check + csum = ~(0x87 ^ 0xCD ^(lw_expr_intval(e1) >> 8) ^ (lw_expr_intval(e1) & 0xff) + ^ (lw_expr_intval(e2) >> 8) ^ (lw_expr_intval(e2) & 0xff) + ^ lw_expr_intval(e3) ^ lw_expr_intval(e4)); + lwasm_emit(l, csum); + + // 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_emitexpr(l, lwasm_fetch_expr(l, 4), 2); + + // data size or drvr name offset + lwasm_emitexpr(l, lwasm_fetch_expr(l, 5), 2); +} + +PARSEFUNC(pseudo_parse_emod) +{ + if (as -> output_format != OUTPUT_OS9) + { + lwasm_register_error(as, l, "emod directive only valid for OS9 target"); + return; + } + + if (!(as -> inmod)) + { + lwasm_register_error(as, l, "not in a module!"); + return; + } + + as -> inmod = 0; +} + +EMITFUNC(pseudo_emit_emod) +{ + unsigned char tcrc[3]; + + // don't mess with CRC! + tcrc[0] = as -> crc[0] ^ 0xff; + tcrc[1] = as -> crc[1] ^ 0xff; + tcrc[2] = as -> crc[2] ^ 0xff; + lwasm_emit(l, tcrc[0]); + lwasm_emit(l, tcrc[1]); + lwasm_emit(l, tcrc[2]); +} diff -r faa97115952e -r 60568b123281 lwasm/pass1.c --- a/lwasm/pass1.c Tue Mar 30 21:48:49 2010 -0600 +++ b/lwasm/pass1.c Tue Mar 30 23:10:01 2010 -0600 @@ -83,6 +83,8 @@ cl -> prev = as -> line_tail; cl -> insn = -1; cl -> as = as; + cl -> inmod = as -> inmod; + cl -> csect = as -> csect; if (!as -> line_tail) { as -> line_head = cl; diff -r faa97115952e -r 60568b123281 lwasm/pseudo.c --- a/lwasm/pseudo.c Tue Mar 30 21:48:49 2010 -0600 +++ b/lwasm/pseudo.c Tue Mar 30 23:10:01 2010 -0600 @@ -907,3 +907,8 @@ } } +PARSEFUNC(pseudo_parse_error) +{ + lwasm_register_error(as, l, "User error: %s", *p); + skip_operand(p); +}