# HG changeset patch
# User lost@starbug
# Date 1270087940 21600
# Node ID 0cf4948d53b47ce741bdc2d00fc63d17c0b8d056
# Parent 7166254491ed4d95a7469697a20d1dedad8b4bfb
Checkpoint - adding actual cpu instructions
diff -r 7166254491ed -r 0cf4948d53b4 lwasm/Makefile.am
--- a/lwasm/Makefile.am Wed Mar 31 18:46:32 2010 -0600
+++ b/lwasm/Makefile.am Wed Mar 31 20:12:20 2010 -0600
@@ -2,7 +2,7 @@
bin_PROGRAMS = lwasm
lwasm_SOURCES = main.c pragma.c input.c pass1.c lwasm.c \
instab.c symbol.c macro.c \
- insn_inh.c \
+ insn_inh.c insn_rtor.c insn_tfm.c insn_rlist.c insn_rel.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 7166254491ed -r 0cf4948d53b4 lwasm/insn_rel.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/insn_rel.c Wed Mar 31 20:12:20 2010 -0600
@@ -0,0 +1,117 @@
+/*
+insn_rel.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 .
+*/
+
+/*
+for handling relative mode instructions
+*/
+
+#include
+#include
+
+#include
+
+#include "lwasm.h"
+#include "instab.h"
+
+PARSEFUNC(insn_parse_rel8)
+{
+ int v;
+ lw_expr_t t, e1, e2;
+ int r;
+
+ // sometimes there is a "#", ignore if there
+ if (**p == '#')
+ (*p)++;
+
+ t = lwasm_parse_expr(as, p);
+ if (!t)
+ {
+ lwasm_register_error(as, l, "Bad operand");
+ return;
+ }
+ l -> len = OPLEN(instab[l -> insn].ops[0]) + 1;
+
+ e1 = lw_expr_build(lw_expr_type_special, lwasm_expr_linelen, l);
+ e2 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_plus, e1, l -> addr);
+ lw_expr_destroy(e1);
+ e1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_minus, t, e2);
+ lw_expr_destroy(e2);
+ lwasm_save_expr(l, 0, e2);
+}
+
+EMITFUNC(insn_emit_rel8)
+{
+ lw_expr_t e;
+ int offs;
+
+ e = lwasm_fetch_expr(l, 0);
+ if (!lw_expr_istype(e, lw_expr_type_int))
+ {
+ lwasm_register_error(as, l, "Illegal non-constant expression");
+ return;
+ }
+
+ offs = lw_expr_intval(e);
+ if (offs < -128 || offs > 127)
+ {
+ lwasm_register_error(as, l, "Byte overflow");
+ return;
+ }
+
+ lwasm_emitop(l, instab[l -> insn].ops[0]);
+ lwasm_emit(l, offs);
+}
+
+PARSEFUNC(insn_parse_rel16)
+{
+ int v;
+ lw_expr_t t, e1, e2;
+ int r;
+
+ // sometimes there is a "#", ignore if there
+ if (**p == '#')
+ (*p)++;
+
+ t = lwasm_parse_expr(as, p);
+ if (!t)
+ {
+ lwasm_register_error(as, l, "Bad operand");
+ return;
+ }
+ l -> len = OPLEN(instab[l -> insn].ops[0]) + 2;
+
+ e1 = lw_expr_build(lw_expr_type_special, lwasm_expr_linelen, l);
+ e2 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_plus, e1, l -> addr);
+ lw_expr_destroy(e1);
+ e1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_minus, t, e2);
+ lw_expr_destroy(e2);
+ lwasm_save_expr(l, 0, e2);
+}
+
+EMITFUNC(insn_emit_rel16)
+{
+ lw_expr_t e;
+ int offs;
+
+ e = lwasm_fetch_expr(l, 0);
+
+ lwasm_emitop(l, instab[l -> insn].ops[0]);
+ lwasm_emitexpr(l, e, 2);
+}
diff -r 7166254491ed -r 0cf4948d53b4 lwasm/insn_rlist.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/insn_rlist.c Wed Mar 31 20:12:20 2010 -0600
@@ -0,0 +1,65 @@
+/*
+insn_rlist.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 .
+*/
+
+/*
+for handling inherent mode instructions
+*/
+
+#include
+#include "lwasm.h"
+#include "instab.h"
+
+PARSEFUNC(insn_parse_rlist)
+{
+ int rb = 0;
+ int rn;
+ static const char *regs = "CCA B DPX Y U PCD S ";
+
+ while (**p && !isspace(**p))
+ {
+ rn = lwasm_lookupreg2(regs, p);
+ if (rn < 0)
+ {
+ lwasm_register_error(as, l, "Bad register '%s'", *p);
+ return;
+ }
+ if (**p && **p != ',' && !isspace(**p))
+ {
+ lwasm_register_error(as, l, "Bad operand");
+ }
+ if (**p == ',')
+ (*p)++;
+ if (rn == 8)
+ rn = 6;
+ else if (rn == 9)
+ rn = 0x40;
+ else
+ rn = 1 << rn;
+ rb |= rn;
+ }
+ l -> len = OPLEN(instab[l -> insn].ops[0]) + 1;
+ l -> pb = rb;
+}
+
+EMITFUNC(insn_emit_rlist)
+{
+ lwasm_emitop(l, instab[l -> insn].ops[0]);
+ lwasm_emit(l, l -> pb);
+}
diff -r 7166254491ed -r 0cf4948d53b4 lwasm/insn_rtor.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/insn_rtor.c Wed Mar 31 20:12:20 2010 -0600
@@ -0,0 +1,62 @@
+/*
+insn_rtor.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 .
+
+*/
+
+#include
+
+#include "lwasm.h"
+#include "instab.h"
+
+PARSEFUNC(insn_parse_rtor)
+{
+ int r0, r1;
+
+ static const char *regs = "D X Y U S PCW V A B CCDP0 0 E F ";
+ static const char *regs9 = "D X Y U S PC A B CCDP ";
+
+ // register to register (r0,r1)
+ // registers are in order:
+ // D,X,Y,U,S,PC,W,V
+ // A,B,CC,DP,0,0,E,F
+
+ r0 = lwasm_lookupreg2((as -> target == TARGET_6309) ? regs9 : regs, p);
+ if (r0 < 0 || *(*p)++ != ',')
+ {
+ lwasm_register_error(as, l, "Bad operand");
+ r0 = r1 = 0;
+ }
+ else
+ {
+ r1 = lwasm_lookupreg2((as -> target = TARGET_6309) ? regs9 : regs, p);
+ if (r1 < 0)
+ {
+ lwasm_register_error(as, l, "Bad operand");
+ r0 = r1 = 0;
+ }
+ }
+ l -> pb = (r0 << 4) | r1;
+ l -> len = OPLEN(instab[l -> insn].ops[0]) + 1;
+}
+
+EMITFUNC(insn_emit_rtor)
+{
+ lwasm_emitop(l, instab[l -> insn].ops[0]);
+ lwasm_emit(l, l -> pb);
+}
diff -r 7166254491ed -r 0cf4948d53b4 lwasm/insn_tfm.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/insn_tfm.c Wed Mar 31 20:12:20 2010 -0600
@@ -0,0 +1,151 @@
+/*
+insn_tfm.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 .
+*/
+
+#include
+#include
+#include
+
+#include "lwasm.h"
+#include "instab.h"
+
+PARSEFUNC(insn_parse_tfm)
+{
+ static const char *reglist = "DXYUS AB 00EF";
+ int r0, r1;
+ char *c;
+ int tfm = 0;
+
+ c = strchr(reglist, toupper(*(*p)++));
+ if (!c)
+ {
+ lwasm_register_error(as, l, "Unknown operation");
+ return;
+ }
+ r0 = c - reglist;
+ if (**p == '+')
+ {
+ (*p)++;
+ tfm = 1;
+ }
+ else if (**p == '-')
+ {
+ (*p)++;
+ tfm = 2;
+ }
+ if (*(*p)++ != ',')
+ {
+ lwasm_register_error(as, l, "Unknown operation");
+ return;
+ }
+ c = strchr(reglist, toupper(*(*p)++));
+ if (!c)
+ {
+ lwasm_register_error(as, l, "Unknown operation");
+ return;
+ }
+ r1 = c - reglist;
+
+ if (**p == '+')
+ {
+ (*p)++;
+ tfm |= 4;
+ }
+ else if (**p == '-')
+ {
+ (*p)++;
+ tfm |= 8;
+ }
+
+ if (**p && !isspace(**p))
+ {
+ lwasm_register_error(as, l, "Bad operand");
+ return;
+ }
+
+ // valid values of tfm here are:
+ // 1: r0+,r1 (2)
+ // 4: r0,r1+ (3)
+ // 5: r0+,r1+ (0)
+ // 10: r0-,r1- (1)
+ switch (tfm)
+ {
+ case 5: //r0+,r1+
+ l -> lint = instab[l -> insn].ops[0];
+ break;
+
+ case 10: //r0-,r1-
+ l -> lint = instab[l -> insn].ops[1];
+ break;
+
+ case 1: // r0+,r1
+ l -> lint = instab[l -> insn].ops[2];
+ break;
+
+ case 4: // r0,r1+
+ l -> lint = instab[l -> insn].ops[3];
+ break;
+
+ default:
+ lwasm_register_error(as, l, "Unknown operation");
+ return;
+ }
+ l -> pb = (r0 << 4) | r1;
+ l -> len = OPLEN(l -> lint);
+}
+
+EMITFUNC(insn_emit_tfm)
+{
+ lwasm_emitop(l, l -> lint);
+ lwasm_emit(l, l -> pb);
+}
+
+PARSEFUNC(insn_parse_tfmrtor)
+{
+ int r0, r1;
+ static const char *regs = "D X Y U S A B 0 0 E F ";
+
+ // register to register (r0,r1)
+ // registers are in order:
+ // D,X,Y,U,S,PC,W,V
+ // A,B,CC,DP,0,0,E,F
+ r0 = lwasm_lookupreg2(regs, p);
+ if (r0 < 0 || *(*p)++ != ',')
+ {
+ lwasm_register_error(as, l, "Bad operand");
+ r0 = r1 = 0;
+ }
+ else
+ {
+ r1 = lwasm_lookupreg2(regs, p);
+ if (r1 < 0)
+ {
+ lwasm_register_error(as, l, "Bad operand");
+ r0 = r1 = 0;
+ }
+ }
+ l -> len = instab[l -> insn].ops[0] + 1;
+ l -> pb = (r0 << 4) | r1;
+}
+
+EMITFUNC(insn_emit_tfmrtor)
+{
+ lwasm_emitop(l, instab[l -> insn].ops[0]);
+ lwasm_emit(l, l -> pb);
+}
diff -r 7166254491ed -r 0cf4948d53b4 lwasm/instab.c
--- a/lwasm/instab.c Wed Mar 31 18:46:32 2010 -0600
+++ b/lwasm/instab.c Wed Mar 31 20:12:20 2010 -0600
@@ -31,6 +31,74 @@
#define insn_resolve_inh NULL
extern EMITFUNC(insn_emit_inh);
+// register to register
+extern PARSEFUNC(insn_parse_rtor);
+#define insn_resolve_rtor NULL
+extern EMITFUNC(insn_emit_rtor);
+
+// TFM and variants
+extern PARSEFUNC(insn_parse_tfmrtor);
+#define insn_resolve_tfmrtor NULL
+extern EMITFUNC(insn_emit_tfmrtor);
+extern PARSEFUNC(insn_parse_tfm);
+#define insn_resolve_tfm NULL
+extern EMITFUNC(insn_emit_tfm);
+
+// register list
+extern PARSEFUNC(insn_parse_rlist);
+#define insn_resolve_rlist NULL
+extern EMITFUNC(insn_emit_rlist);
+
+// indexed
+extern PARSEFUNC(insn_parse_indexed);
+extern RESOLVEFUNC(insn_resolve_indexed);
+extern EMITFUNC(insn_emit_indexed);
+
+// generic 32 bit immediate
+extern PARSEFUNC(insn_parse_gen32);
+extern RESOLVEFUNC(insn_resolve_gen32);
+extern EMITFUNC(insn_emit_gen32);
+
+// generic 16 bit immediate
+extern PARSEFUNC(insn_parse_gen16);
+extern RESOLVEFUNC(insn_resolve_gen16);
+extern EMITFUNC(insn_emit_gen16);
+
+// generic 8 bit immediate
+extern PARSEFUNC(insn_parse_gen8);
+extern RESOLVEFUNC(insn_resolve_gen8);
+extern EMITFUNC(insn_emit_gen8);
+
+// generic no immediate
+extern PARSEFUNC(insn_parse_gen0);
+extern RESOLVEFUNC(insn_resolve_gen0);
+extern EMITFUNC(insn_emit_gen0);
+
+// logic memory
+extern PARSEFUNC(insn_parse_logicmem);
+extern RESOLVEFUNC(insn_resolve_logicmem);
+extern EMITFUNC(insn_emit_logicmem);
+
+// logic memory
+extern PARSEFUNC(insn_parse_imm8);
+#define insn_resolve_imm8 NULL
+extern EMITFUNC(insn_emit_imm8);
+
+// bit to bit ops
+extern PARSEFUNC(insn_parse_bitbit);
+#define insn_resolve_bitbit NULL
+extern EMITFUNC(insn_emit_bitbit);
+
+// 8 bit relative
+extern PARSEFUNC(insn_parse_rel8);
+#define insn_resolve_rel8 NULL
+extern EMITFUNC(insn_emit_rel8);
+
+// 16 bit relative
+extern PARSEFUNC(insn_parse_rel16);
+#define insn_resolve_rel16 NULL
+extern EMITFUNC(insn_emit_rel16);
+
// MACRO pseudo op
extern PARSEFUNC(pseudo_parse_macro);
#define pseudo_resolve_macro NULL
@@ -215,8 +283,8 @@
instab_t instab[] =
{
-/*
- { "abx", { 0x3a, -1, -1, -1 }, insn_parse_inh, insn_resolve_inh, lwasm_emit_inh, lwasm_insn_normal},
+
+ { "abx", { 0x3a, -1, -1, -1 }, insn_parse_inh, insn_resolve_inh, insn_emit_inh, lwasm_insn_normal},
{ "adca", { 0x99, 0xa9, 0xb9, 0x89}, insn_parse_gen8, insn_resolve_gen8, insn_emit_gen8, lwasm_insn_normal},
{ "adcb", { 0xd9, 0xe9, 0xf9, 0xc9}, insn_parse_gen8, insn_resolve_gen8, insn_emit_gen8, lwasm_insn_normal},
{ "adcd", { 0x1099, 0x10a9, 0x10b9, 0x1089},insn_parse_gen16, insn_resolve_gen16, insn_emit_gen16, lwasm_insn_is6309},
@@ -382,9 +450,9 @@
{ "nega", { 0x40, -1, -1, -1 }, insn_parse_inh, insn_resolve_inh, insn_emit_inh, lwasm_insn_normal},
{ "negb", { 0x50, -1, -1, -1 }, insn_parse_inh, insn_resolve_inh, insn_emit_inh, lwasm_insn_normal},
{ "negd", { 0x1040, -1, -1, -1 }, insn_parse_inh, insn_resolve_inh, insn_emit_inh, lwasm_insn_is6309},
-*/
+
{ "nop", { 0x12, -1, -1, -1 }, insn_parse_inh, insn_resolve_inh, insn_emit_inh, lwasm_insn_normal},
-/*
+
{ "oim", { 0x01, 0x61, 0x71, -1 }, insn_parse_logicmem, insn_resolve_logicmem, insn_emit_logicmem, lwasm_insn_is6309},
{ "ora", { 0x9a, 0xaa, 0xba, 0x8a}, insn_parse_gen8, insn_resolve_gen8, insn_emit_gen8, lwasm_insn_normal},
{ "orb", { 0xda, 0xea, 0xfa, 0xca}, insn_parse_gen8, insn_resolve_gen8, insn_emit_gen8, lwasm_insn_normal},
@@ -472,7 +540,7 @@
{ "tste", { 0x114d, -1, -1, -1 }, insn_parse_inh, insn_resolve_inh, insn_emit_inh, lwasm_insn_is6309},
{ "tstf", { 0x115d, -1, -1, -1 }, insn_parse_inh, insn_resolve_inh, insn_emit_inh, lwasm_insn_is6309},
{ "tstw", { 0x105d, -1, -1, -1 }, insn_parse_inh, insn_resolve_inh, insn_emit_inh, lwasm_insn_is6309},
-*/
+
{ "org", { -1, -1, -1, -1 }, pseudo_parse_org, pseudo_resolve_org, pseudo_emit_org, lwasm_insn_normal},
{ "equ", { -1, -1, -1, -1 }, pseudo_parse_equ, pseudo_resolve_equ, pseudo_emit_equ, lwasm_insn_setsym},
{ "=", { -1, -1, -1, -1 }, pseudo_parse_equ, pseudo_resolve_equ, pseudo_emit_equ, lwasm_insn_setsym},
diff -r 7166254491ed -r 0cf4948d53b4 lwasm/lwasm.c
--- a/lwasm/lwasm.c Wed Mar 31 18:46:32 2010 -0600
+++ b/lwasm/lwasm.c Wed Mar 31 20:12:20 2010 -0600
@@ -555,3 +555,28 @@
return 0;
}
+
+int lwasm_lookupreg2(const char *regs, char **p)
+{
+ int rval = 0;
+
+ while (*regs)
+ {
+ if (toupper(**p) == *regs)
+ {
+ if (regs[1] == ' ' && !isalpha(*(*p + 1)))
+ break;
+ if (toupper(*(*p + 1)) == regs[1])
+ break;
+ }
+ regs += 2;
+ rval++;
+ }
+ if (!*regs)
+ return -1;
+ if (regs[1] == ' ')
+ (*p)++;
+ else
+ (*p) += 2;
+ return rval;
+}
diff -r 7166254491ed -r 0cf4948d53b4 lwasm/lwasm.h
--- a/lwasm/lwasm.h Wed Mar 31 18:46:32 2010 -0600
+++ b/lwasm/lwasm.h Wed Mar 31 20:12:20 2010 -0600
@@ -138,6 +138,8 @@
sectiontab_t *csect; // which section are we in?
struct line_expr_s *exprs; // expressions used during parsing
char *lstr; // string passed forward
+ int pb; // pass forward post byte
+ int lint; // pass forward integer
asmstate_t *as; // assembler state data ptr
};
@@ -232,6 +234,8 @@
extern void skip_operand(char **p);
+extern int lwasm_lookupreg2(const char *rlist, char **p);
+
#endif
#define OPLEN(op) (((op)>0xFF)?2:1)