diff src/insn_rel.c @ 77:a338d496350e

Checkpointing conversion to allow object target
author lost
date Fri, 09 Jan 2009 04:23:00 +0000
parents 89657cb3fdf8
children 964d68cde469
line wrap: on
line diff
--- a/src/insn_rel.c	Thu Jan 08 02:57:24 2009 +0000
+++ b/src/insn_rel.c	Fri Jan 09 04:23:00 2009 +0000
@@ -33,28 +33,81 @@
 OPFUNC(insn_rel8)
 {
 	int v;
+	lwasm_expr_term_t *t;
+	int r;
 	
 	lwasm_emitop(as, l, instab[opnum].ops[0]);
-	
-	if (lwasm_expr_result(as, l, p, EXPR_PASS2CONST, &v) < 0)
+
+	if ((r = lwasm_expr_result2(as, l, p, EXPR_PASS2CONST | EXPR_NOINTERSECT, &v, 0)) != 0)
+		v = 0;
+	else
 	{
-		v = 0;
+		if (as -> passnum == 1)
+		{
+			// need to adjust the expression
+			v -= as -> addr + 1;
+			if (l -> exprs[0])
+			{
+				t = lwasm_expr_term_create_int(as -> addr + 1);
+				lwasm_expr_stack_push(l -> exprs[0], t);
+				lwasm_expr_term_free(t);
+				t = lwasm_expr_term_create_oper(LWASM_OPER_MINUS);
+				lwasm_expr_stack_push(l -> exprs[0], t);
+				lwasm_expr_term_free(t);
+			}
+			else
+			{
+				l -> exprvals[0] -= as -> addr + 1;
+			}
+		}
 	}
-	v -= as -> addr + 1;
+	if (r == 1 && as -> passnum == 2)
+	{
+		register_error(as, l, 2, "Illegal external or intersegment reference");
+	}
 	if (v < -128 || v > 127)
 		register_error(as, l, 2, "Byte overflow");
 	lwasm_emit(as, l, v & 0xff);
 }
 
+/*
+External and intersegment references are adjusted for the relative addressing mode
+by adjusting the expression on pass 1 and then treated as absolute references later
+*/
 OPFUNC(insn_rel16)
 {
 	int v;
+	int r;
+	lwasm_expr_term_t *t;
 	
 	lwasm_emitop(as, l, instab[opnum].ops[0]);
 	
-	if (lwasm_expr_result(as, l, p, EXPR_PASS2CONST, &v) < 0)
+	r = lwasm_expr_result2(as, l, p, EXPR_PASS2CONST, &v, 0);
+	if (r != 0)
 		v = 0;
-	v -= as -> addr + 2;
+	else
+	{
+		if (as -> passnum == 1)
+		{
+			// need to adjust the expression
+			v -= as -> addr + 1;
+			if (l -> exprs[0])
+			{
+				t = lwasm_expr_term_create_int(as -> addr + 1);
+				lwasm_expr_stack_push(l -> exprs[0], t);
+				lwasm_expr_term_free(t);
+				t = lwasm_expr_term_create_oper(LWASM_OPER_MINUS);
+				lwasm_expr_stack_push(l -> exprs[0], t);
+				lwasm_expr_term_free(t);
+			}
+			else
+			{
+				l -> exprvals[0] -= as -> addr + 2;
+			}
+		}
+	}
+	if (as -> passnum == 2 && r == 1)
+		l -> relocoff = as -> addr - l -> codeaddr;
 	lwasm_emit(as, l, (v >> 8) & 0xff);
 	lwasm_emit(as, l, v & 0xff);
 }