diff src/insn_misc.c @ 0:57495da01900

Initial checking of LWASM
author lost
date Fri, 03 Oct 2008 02:44:20 +0000
parents
children 34568fab6058
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/insn_misc.c	Fri Oct 03 02:44:20 2008 +0000
@@ -0,0 +1,315 @@
+/*
+ * insn_misc.c
+ *
+ * parsing miscelaneous addressing modes
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include "lwasm.h"
+#include "instab.h"
+
+extern void insn_gen_aux(asmstate_t *as, sourceline_t *cl, char **optr, int *b1, int *b2, int *b3, int *op);
+
+void insn_inh(asmstate_t *as, sourceline_t *cl, char **optr)
+{
+	cl -> addrmode = OPER_INH;
+	emitop(instab[cl -> opcode].ops[0]);
+}
+
+void insn_rtor(asmstate_t *as, sourceline_t *cl, char **optr)
+{
+	int r0, r1;
+	static const char *regs = "D X Y U S PCW V A B CCDP0 0 E F ";
+	
+	cl -> addrmode = OPER_RTOR;
+	emitop(instab[cl -> opcode].ops[0]);
+	// 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 = lookupreg(regs, optr);
+	if (r0 < 0 || *(*optr)++ != ',')
+	{
+		errorp1(ERR_BADOPER);
+		r0 = r1 = 0;
+	}
+	else
+	{
+		r1 = lookupreg(regs, optr);
+		if (r1 < 0)
+		{
+			errorp1(ERR_BADOPER);
+			r0=r1=0;
+		}
+	}
+	emit((r0 << 4) | r1);
+}
+
+void insn_rlist(asmstate_t *as, sourceline_t *cl, char **optr)
+{
+	int rb = 0;
+	int rn;
+	static const char *regs = "CCA B DPX Y U PCD S ";
+
+	emitop(instab[cl -> opcode].ops[0]);
+	cl -> addrmode = OPER_RLIST;
+	while (**optr && !isspace(**optr))
+	{
+		rn = lookupreg(regs, optr);
+		if (rn < 0)
+		{
+			printf("Bad reg (%s)\n", *optr);
+			errorp1(ERR_BADOPER);
+			emit(0);
+			return;
+		}
+		if (**optr && **optr != ',' && !isspace(**optr))
+		{
+			printf("Bad char (%c)\n", **optr);
+			errorp1(ERR_BADOPER);
+			emit(0);
+			return;
+		}
+		if (**optr == ',')
+			(*optr)++;
+		if (rn == 8)
+			rn = 6;
+		else if (rn == 9)
+			rn = 0x40;
+		else
+			rn = 1 << rn;
+		rb |= rn;
+	}
+	emit(rb);
+}
+
+// for aim, oim, eim, tim
+void insn_logicmem(asmstate_t *as, sourceline_t *cl, char **optr)
+{
+	int rval, v1;
+	int b1, b2, b3, op;
+	
+	if (**optr == '#')
+		(*optr)++;
+	
+	rval = eval_expr(as, cl, optr, &v1);
+	if (rval < 0)
+		return;
+	
+	if (v1 < -128 || v1 > 255)
+	{
+		errorp2(ERR_OVERFLOW);
+		v1 = 0;
+	}
+	
+	if (**optr != ',' && **optr != ';')
+	{
+		errorp1(ERR_BADOPER);
+		return;
+	}
+	
+	(*optr)++;
+
+	// now we have a general addressing mode - call for it
+	insn_gen_aux(as, cl, optr, &b1, &b2, &b3, &op);
+	
+	emitop(op);
+	emit(v1 & 0xff);
+	if (b1 != -1)
+	{
+		emit(b1);
+	}
+	if (b2 != -1)
+	{
+		emit(b2);
+	}
+	if (b3 != -1)
+	{
+		emit(b3);
+	}
+}
+
+void insn_tfm(asmstate_t *as, sourceline_t *cl, char **optr)
+{
+	static const char *reglist = "DXYUS   AB  00EF";
+	int r0, r1;
+	char *c;
+	int tfm = 0;
+			
+	cl -> addrmode = OPER_TFM;
+			
+	c = strchr(reglist, toupper(*(*optr)++));
+	if (!c)
+	{
+		errorp1(ERR_BADOPER);
+		return;
+	}
+	r0 = c - reglist;
+	if (**optr == '+')
+	{
+		(*optr)++;
+		tfm = 1;
+	}
+	else if (**optr == '-')
+	{
+		(*optr)++;
+		tfm = 2;
+	}
+	if (*(*optr)++ != ',')
+	{
+		errorp1(ERR_BADOPER);
+		return;
+	}
+	c = strchr(reglist, toupper(*(*optr)++));
+	if (!c)
+	{
+		errorp1(ERR_BADOPER);
+		return;
+	}
+	r1 = c - reglist;
+
+	if (**optr == '+')
+	{
+		(*optr)++;
+		tfm |= 4;
+	}
+	else if (**optr == '-')
+	{
+		(*optr)++;
+		tfm |= 8;
+	}
+	
+	if (**optr && !isspace(**optr))
+	{
+		errorp1(ERR_BADOPER);
+		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+
+		emitop(instab[cl -> opcode].ops[0]);
+		break;
+	case 10: //r0-,r1-
+		emitop(instab[cl -> opcode].ops[1]);
+		break;
+	case 1: // r0+,r1
+		emitop(instab[cl -> opcode].ops[2]);
+		break;
+	case 4: // r0,r1+
+		emitop(instab[cl -> opcode].ops[3]);
+		break;
+	default:
+		errorp1(ERR_BADOPER);
+		return;
+	}
+	emit((r0 << 4) | r1);
+}
+
+void insn_bitbit(asmstate_t *as, sourceline_t *cl, char **optr)
+{
+	int r;
+	int rval;
+	int v1;
+	int tv;
+		
+	emitop(instab[cl -> opcode].ops[0]);
+	
+	cl -> addrmode = OPER_BITBIT;
+
+	r = toupper(*(*optr)++);
+	if (r == 'A')
+		r = 1;
+	else if (r == 'B')
+		r = 2;
+	else if (r == 'C' && toupper(**optr) == 'C')
+	{
+		r = 0;
+		(*optr)++;
+	}
+	else
+	{
+		errorp1(ERR_BADREG);
+		return;
+	}
+	if (*(*optr)++ != ',')
+	{
+		errorp1(ERR_BADOPER);
+		return;
+	}
+	rval = eval_expr(as, cl, optr, &v1);
+	if (v1 < 0 || v1 > 7)
+	{
+		errorp2(ERR_OVERFLOW3);
+		v1 = 0;
+	}
+	if (*(*optr)++ != ',')
+	{
+		errorp1(ERR_BADOPER);
+		return;
+	}
+	r = (r << 6) | (v1 << 3);
+	rval = eval_expr(as, cl, optr, &v1);
+	if (v1 < 0 || v1 > 7)
+	{
+		errorp2(ERR_OVERFLOW3);
+		v1 = 0;
+	}
+	if (*(*optr)++ != ',')
+	{
+		errorp1(ERR_BADOPER);
+		return;
+	}
+	r |= v1;
+	
+	emit(r);
+			
+	// ignore base page address modifier
+	if (**optr == '<')
+		optr++;
+			
+	rval = eval_expr(as, cl, optr, &v1);
+	v1 &= 0xFFFF;
+	tv = v1 - ((cl -> dpval) << 8);
+	if (tv > 0xFF || tv < 0)
+		errorp2(ERR_OVERFLOW);
+	emit(tv & 0xff);
+}
+
+void insn_rel8(asmstate_t *as, sourceline_t *cl, char **optr)
+{
+	int v1, rval;
+	
+	emitop(instab[cl -> opcode].ops[0]);
+	cl -> addrmode = OPER_REL8;
+	rval = eval_expr(as, cl, optr, &v1);
+	v1 &= 0xFFFF;
+	v1 -= cl -> addr + 2;
+	if (v1 < -128 || v1 > 127)
+		errorp2(ERR_OVERFLOW);
+	v1 &= 0xFFFF;
+	emit(v1 & 0xff);
+}
+
+void insn_rel16(asmstate_t *as, sourceline_t *cl, char **optr)
+{
+	int v1, rval;
+
+	emitop(instab[cl -> opcode].ops[0]);
+	cl -> addrmode = OPER_REL16;
+	rval = eval_expr(as, cl, optr, &v1);
+	v1 &= 0xFFFF;
+	v1 -= cl -> addr + 3;
+	if (instab[cl -> opcode].ops[0] > 0xff)
+		v1 -= 1;
+	v1 &= 0xFFFF;
+	emit(v1 >> 8);
+	emit(v1 & 0xff);
+}