# 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)