# HG changeset patch
# User lost@starbug
# Date 1270094265 21600
# Node ID f50a54d0293af1f52a7c9f3d2673402dfa6ffe01
# Parent be0f9f8d799f06abfee683cb5de6ddb5574d730d
Indexed part 1
diff -r be0f9f8d799f -r f50a54d0293a lwasm/Makefile.am
--- a/lwasm/Makefile.am Wed Mar 31 20:37:59 2010 -0600
+++ b/lwasm/Makefile.am Wed Mar 31 21:57:45 2010 -0600
@@ -3,7 +3,7 @@
lwasm_SOURCES = main.c pragma.c input.c pass1.c lwasm.c \
instab.c symbol.c macro.c \
insn_inh.c insn_rtor.c insn_tfm.c insn_rlist.c insn_rel.c \
- insn_bitbit.c \
+ insn_bitbit.c insn_indexed.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 be0f9f8d799f -r f50a54d0293a lwasm/insn_indexed.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/insn_indexed.c Wed Mar 31 21:57:45 2010 -0600
@@ -0,0 +1,319 @@
+/*
+insn_indexed.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 indexed mode instructions
+*/
+
+#include
+
+#include
+#include
+
+#include
+
+#include "lwasm.h"
+#include "instab.h"
+
+/*
+l -> lint: size of operand (0, 1, 2, -1 if not determined)
+l -> pb: actual post byte (from "resolve" stage) or info passed
+ forward to the resolve stage (if l -> line is -1); 0x80 is indir
+ bits 0-2 are register number
+*/
+void insn_parse_indexed_aux(asmstate_t *as, line_t *l, char **p)
+{
+ struct opvals { char *opstr; int pb; };
+
+ static const char *regs = "X Y U S W PCRPC ";
+ static const struct opvals simpleindex[] =
+ {
+ {",x", 0x84}, {",y", 0xa4}, {",u", 0xc4}, {",s", 0xe4},
+ {",x+", 0x80}, {",y+", 0xa0}, {",u+", 0xc0}, {",s+", 0xe0},
+ {",x++", 0x81}, {",y++", 0xa1}, {",u++", 0xc1}, {",s++", 0xe1},
+ {",-x", 0x82}, {",-y", 0xa2}, {",-u", 0xc2}, {",-s", 0xe2},
+ {",--x", 0x83}, {",--y", 0xa3}, {",--u", 0xc3}, {",--s", 0xe3},
+ {"a,x", 0x86}, {"a,y", 0xa6}, {"a,u", 0xc6}, {"a,s", 0xe6},
+ {"b,x", 0x85}, {"b,y", 0xa5}, {"b,u", 0xc5}, {"b,s", 0xe5},
+ {"e,x", 0x87}, {"e,y", 0xa7}, {"e,u", 0xc7}, {"e,s", 0xe7},
+ {"f,x", 0x8a}, {"f,y", 0xaa}, {"f,u", 0xca}, {"f,s", 0xea},
+ {"d,x", 0x8b}, {"d,y", 0xab}, {"d,u", 0xcb}, {"d,s", 0xed},
+ {"w,x", 0x8e}, {"w,y", 0xae}, {"w,u", 0xce}, {"w,s", 0xee},
+ {",w", 0x8f}, {",w++", 0xcf}, {",--w", 0xef},
+
+ {"[,x]", 0x94}, {"[,y]", 0xb4}, {"[,u", 0xd4}, {"[,s]", 0xf4},
+ {"[,x++]", 0x91}, {"[,y++]", 0xb1}, {"[,u++]", 0xd1}, {"[,s++]", 0xf1},
+ {"[,--x]", 0x93}, {"[,--y]", 0xb3}, {"[,--u]", 0xd3}, {"[,--s]", 0xf3},
+ {"[a,x]", 0x96}, {"[a,y]", 0xb6}, {"[a,u]", 0xd6}, {"[a,s]", 0xf6},
+ {"[b,x]", 0x95}, {"[b,y]", 0xb5}, {"[b,u]", 0xd5}, {"[b,s]", 0xf5},
+ {"[e,x]", 0x97}, {"[e,y]", 0xb7}, {"[e,u]", 0xd7}, {"[e,s]", 0xf7},
+ {"[f,x]", 0x9a}, {"[f,y]", 0xba}, {"[f,u]", 0xda}, {"[f,s]", 0xfa},
+ {"[d,x]", 0x9b}, {"[d,y]", 0xbb}, {"[d,u]", 0xdb}, {"[d,s]", 0xfd},
+ {"[w,x]", 0x9e}, {"[w,y]", 0xbe}, {"[w,u]", 0xde}, {"[w,s]", 0xfe},
+ {"[,w]", 0x90}, {"[,w++]", 0xd0}, {"[,--w]", 0xf0},
+
+ { "", -1 }
+ };
+
+ static const char *regs9 = "X Y U S PCRPC ";
+ static const struct opvals simpleindex9[] =
+ {
+ {",x", 0x84}, {",y", 0xa4}, {",u", 0xc4}, {",s", 0xe4},
+ {",x+", 0x80}, {",y+", 0xa0}, {",u+", 0xc0}, {",s+", 0xe0},
+ {",x++", 0x81}, {",y++", 0xa1}, {",u++", 0xc1}, {",s++", 0xe1},
+ {",-x", 0x82}, {",-y", 0xa2}, {",-u", 0xc2}, {",-s", 0xe2},
+ {",--x", 0x83}, {",--y", 0xa3}, {",--u", 0xc3}, {",--s", 0xe3},
+ {"a,x", 0x86}, {"a,y", 0xa6}, {"a,u", 0xc6}, {"a,s", 0xe6},
+ {"b,x", 0x85}, {"b,y", 0xa5}, {"b,u", 0xc5}, {"b,s", 0xe5},
+ {"d,x", 0x8b}, {"d,y", 0xab}, {"d,u", 0xcb}, {"d,s", 0xed},
+
+ {"[,x]", 0x94}, {"[,y]", 0xb4}, {"[,u", 0xd4}, {"[,s]", 0xf4},
+ {"[,x++]", 0x91}, {"[,y++]", 0xb1}, {"[,u++]", 0xd1}, {"[,s++]", 0xf1},
+ {"[,--x]", 0x93}, {"[,--y]", 0xb3}, {"[,--u]", 0xd3}, {"[,--s]", 0xf3},
+ {"[a,x]", 0x96}, {"[a,y]", 0xb6}, {"[a,u]", 0xd6}, {"[a,s]", 0xf6},
+ {"[b,x]", 0x95}, {"[b,y]", 0xb5}, {"[b,u]", 0xd5}, {"[b,s]", 0xf5},
+ {"[d,x]", 0x9b}, {"[d,y]", 0xbb}, {"[d,u]", 0xdb}, {"[d,s]", 0xfd},
+
+ { "", -1 }
+ };
+ char stbuf[25];
+ int i, j, rn;
+ int indir = 0;
+ int f0 = 1;
+ const struct opvals *simples;
+ const char *reglist;
+ lw_expr_t e;
+
+ if (as -> target == TARGET_6809)
+ {
+ simples = simpleindex9;
+ reglist = regs9;
+ }
+ else
+ {
+ simples = simpleindex;
+ reglist = regs;
+ }
+
+ // fetch out operand for lookup
+ for (i = 0; i < 24; i++)
+ {
+ if (*((*p) + i) && !isspace(*((*p) + i)))
+ stbuf[i] = *((*p) + i);
+ else
+ break;
+ }
+ stbuf[i] = '\0';
+
+ // now look up operand in "simple" table
+ if (!*((*p) + i) || isspace(*((*p) + i)))
+ {
+ // do simple lookup
+ for (j = 0; simples[j].opstr[0]; j++)
+ {
+ if (!strcasecmp(stbuf, simples[j].opstr))
+ break;
+ }
+ if (simples[j].opstr[0])
+ {
+ l -> pb = simples[j].pb;
+ l -> lint = 0;
+ (*p) += i;
+ return;
+ }
+ }
+
+ // now do the "hard" ones
+
+ // is it indirect?
+ if (**p == '[')
+ {
+ indir = 1;
+ (*p)++;
+ }
+
+ // look for a "," - all indexed modes have a "," except extended indir
+ rn = 0;
+ for (i = 0; (*p)[i] && !isspace((*p)[i]); i++)
+ {
+ if ((*p)[i] == ',')
+ {
+ rn = 1;
+ break;
+ }
+ }
+
+ // if no "," and indirect, do extended indir
+ if (!rn && indir)
+ {
+ // extended indir
+ l -> pb = 0x9f;
+ e = lwasm_parse_expr(as, p);
+ if (!e || **p != ']')
+ {
+ lwasm_register_error(as, l, "Bad operand");
+ return;
+ }
+
+ (*p)++;
+ l -> lint = 2;
+ return;
+ }
+
+ if (**p == '<')
+ {
+ l -> lint = 1;
+ (*p)++;
+ }
+ else if (**p == '>')
+ {
+ l -> lint = 2;
+ (*p)++;
+ }
+
+ if (**p == '0' && *(*p+1) == ',')
+ {
+ f0 = 1;
+ }
+
+ // now we have to evaluate the expression
+ e = lwasm_parse_expr(as, p);
+ if (!e)
+ {
+ lwasm_register_error(as, l, "Bad operand");
+ return;
+ }
+ lwasm_save_expr(l, 0, e);
+
+ // now look for a comma; if not present, explode
+ if (*(*p)++ != ',')
+ {
+ lwasm_register_error(as, l, "Bad operand");
+ return;
+ }
+
+ // now get the register
+ rn = lwasm_lookupreg3(reglist, p);
+ if (rn < 0)
+ {
+ lwasm_register_error(as, l, "Bad register");
+ return;
+ }
+
+ if (indir)
+ {
+ if (**p != ']')
+ {
+ lwasm_register_error(as, l, "Bad operand");
+ return;
+ }
+ else
+ (*p)++;
+ }
+
+ // nnnn,W is only 16 bit (or 0 bit)
+ if (rn == 4)
+ {
+ if (l -> lint == 1)
+ {
+ lwasm_register_error(as, l, "n,W cannot be 8 bit");
+ return;
+ }
+
+ if (l -> lint == 2)
+ {
+ l -> pb = indir ? 0xb0 : 0xcf;
+ l -> lint = 2;
+ return;
+ }
+
+ l -> pb = (0x80 * indir) | rn;
+
+/* [,w] and ,w
+ if (indir)
+ *b1 = 0x90;
+ else
+ *b1 = 0x8f;
+*/
+ return;
+ }
+
+ // PCR? then we have PC relative addressing (like B??, LB??)
+ if (rn == 5)
+ {
+ lw_expr_t e1, e2;
+ // external references are handled exactly the same as for
+ // relative addressing modes
+ // on pass 1, adjust the expression for a subtraction of the
+ // current address
+
+ e1 = lw_expr_build(lw_expr_type_special, lwasm_expr_linelen, l);
+ e2 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_plus, l -> addr, e1);
+ lw_expr_destroy(e1);
+ e1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_minus, e, l -> addr);
+ lwasm_save_expr(l, 0, e1);
+ lw_expr_destroy(e2);
+ }
+
+ l -> pb = (indir * 0x80) | rn | (f0 * 0x40);
+}
+
+PARSEFUNC(insn_parse_indexed)
+{
+ l -> lint = -1;
+ insn_parse_indexed_aux(as, l, p);
+
+ if (l -> lint != -1)
+ {
+ l -> len = OPLEN(instab[l -> insn].ops[0]) + l -> lint + 1;
+ }
+}
+
+void insn_resolve_indexed_aux(asmstate_t *as, line_t *l)
+{
+}
+
+RESOLVEFUNC(insn_resolve_indexed)
+{
+ insn_resolve_indexed_aux(as, l);
+
+ if (l -> lint != -1 && l -> pb != -1)
+ {
+ l -> len = OPLEN(instab[l -> insn].ops[0]) + l -> lint + 1;
+ }
+}
+
+void insn_emit_indexed_aux(asmstate_t *as, line_t *l)
+{
+ lw_expr_t e;
+
+ lwasm_emitop(l, instab[l -> insn].ops[0]);
+ lwasm_emitop(l, l -> pb);
+ if (l -> lint > 0)
+ {
+ e = lwasm_fetch_expr(l, 0);
+ lwasm_emitexpr(l, e, l -> lint);
+ }
+}
+
+EMITFUNC(insn_emit_indexed)
+{
+ insn_emit_indexed_aux(as, l);
+}
diff -r be0f9f8d799f -r f50a54d0293a lwasm/lwasm.c
--- a/lwasm/lwasm.c Wed Mar 31 20:37:59 2010 -0600
+++ b/lwasm/lwasm.c Wed Mar 31 21:57:45 2010 -0600
@@ -580,3 +580,35 @@
(*p) += 2;
return rval;
}
+
+int lwasm_lookupreg3(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])
+ {
+ if (regs[2] == ' ' && !isalpha(*(*p + 2)))
+ break;
+ if (toupper(*(*p + 2)) == regs[2])
+ break;
+ }
+ }
+ regs += 3;
+ rval++;
+ }
+ if (!*regs)
+ return -1;
+ if (regs[1] == ' ')
+ (*p)++;
+ else if (regs[2] == ' ')
+ (*p) += 2;
+ else
+ (*p) += 3;
+ return rval;
+}
diff -r be0f9f8d799f -r f50a54d0293a lwasm/lwasm.h
--- a/lwasm/lwasm.h Wed Mar 31 20:37:59 2010 -0600
+++ b/lwasm/lwasm.h Wed Mar 31 21:57:45 2010 -0600
@@ -235,6 +235,7 @@
extern void skip_operand(char **p);
extern int lwasm_lookupreg2(const char *rlist, char **p);
+extern int lwasm_lookupreg3(const char *rlist, char **p);
#endif