# 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);
+}