diff src/insn_gen.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_gen.c	Fri Oct 03 02:44:20 2008 +0000
@@ -0,0 +1,154 @@
+/*
+ * insn_gen.c
+ *
+ * parsing general addressing modes (IMM+DIR+EXT+IND)
+ */
+
+#include <ctype.h>
+#include "lwasm.h"
+#include "instab.h"
+
+extern void insn_indexed_aux(asmstate_t *as, sourceline_t *cl, char **optr, int *b1, int *b2, int *b3);
+
+void insn_gen_aux(asmstate_t *as, sourceline_t *cl, char **optr, int *b1, int *b2, int *b3, int *op)
+{
+	*b1 = *b2 = *b3 = -1;
+	char *optr2;
+	int v1, tv, rval;
+	
+	optr2 = *optr;
+	while (*optr2 && !isspace(*optr2) && *optr2 != ',') optr2++
+		;
+	if (*optr2 != ',' && **optr != '[')
+	{
+		// not indexed
+		if (**optr == '<')
+		{
+			(*optr)++;
+			rval = eval_expr(as, cl, optr, &v1);
+			v1 = v1 & 0xffff;
+			tv = v1 - ((cl -> dpval) << 8);
+			if (tv < 0 || tv > 0xff)
+			{
+				errorp2(ERR_OVERFLOW);
+			}
+			v1 = v1 & 0xff;
+			goto ins_gen_dir;
+		}
+		else if (**optr == '>')
+		{
+			// extended mode
+			(*optr)++;
+			rval = eval_expr(as, cl, optr, &v1);
+			goto ins_gen_ext;
+		}
+		else
+		{
+			// eval expr and see how big it is
+			rval = eval_expr(as, cl, optr, &v1);
+			v1 = v1 & 0xFFFF;
+			
+			if (cl -> undef && as -> passnum == 1)
+			{
+				cl -> p1f16 = 1;
+				goto ins_gen_ext;
+			}
+			
+			tv = v1 - (cl -> dpval << 8);
+
+			if (tv < 0 || tv > 0xff || cl -> p1f16)
+				goto ins_gen_ext;
+			else
+			{
+				v1 = v1 & 0xff;
+				goto ins_gen_dir;
+			}
+		}
+		return;
+	}	
+
+	*op = instab[cl -> opcode].ops[1];
+	insn_indexed_aux(as, cl, optr, b1, b2, b3);
+	return;
+
+ins_gen_dir:
+	*op = instab[cl -> opcode].ops[0];
+//	cl -> code_operlen = 1;
+	cl -> addrmode = OPER_DIR;
+	if ((v1 & 0xFFFF) > 0xff)
+		errorp2(ERR_OVERFLOW);
+	*b1 = (v1);
+	return;
+
+ins_gen_ext:
+	*op = instab[cl -> opcode].ops[2];
+//	cl -> code_operlen = 2;
+	cl -> addrmode = OPER_EXT;
+	*b1 = (v1 >> 8);
+	*b2 = (v1 & 0xff);
+	return;
+}
+
+void insn_gen(asmstate_t *as, sourceline_t *cl, char **optr)
+{
+	int rval;
+	int v1;
+	int b1, b2, b3, op;
+		
+	if (**optr == '#')
+	{
+		// immediate mode has perterbations on instruction size
+		(*optr)++;
+		emitop(instab[cl -> opcode].ops[3]);
+		rval = eval_expr(as, cl, optr, &v1);
+
+		switch (instab[cl -> opcode].instype)
+		{
+		case INSTYPE_GEN8:
+		case INSTYPE_IMM8:
+			cl -> addrmode = OPER_IMM8;
+//			cl -> code_operlen = 1;
+			emit(v1 & 0xff);
+			if (v1 < -128 || v1 > 255)
+				errorp2(ERR_OVERFLOW);
+			return;
+			
+		case INSTYPE_GEN:
+			cl -> addrmode = OPER_IMM16;
+//			cl -> code_operlen = 2;
+			emit(v1 >> 8);
+			emit(v1 & 0xff);
+			return;
+			
+		case INSTYPE_GEN32:
+			cl -> addrmode = OPER_IMM32;
+//			cl -> code_operlen = 4;
+			emit(v1 >> 24);
+			emit((v1 >> 16) & 0xff);
+			emit((v1 >> 8) & 0xff);
+			emit(v1 & 0xff);
+			return;
+			
+		default:
+			errorp1(ERR_BADOPER);
+			return;
+		
+		}
+
+		return;
+	}
+	if (instab[cl -> opcode].instype == INSTYPE_IMM8)
+	{
+		errorp1(ERR_BADOPER);
+		return;
+	}
+
+	insn_gen_aux(as, cl, optr, &b1, &b2, &b3, &op);
+	emitop(op);
+	if (b1 != -1)
+		emit(b1);
+	if (b2 != -1)
+		emit(b2);
+	if (b3 != -1)
+		emit(b3);
+}