changeset 211:6f2e18f1fe67

Improve autobranchlength pragma Improve detection of 8 bit relative offsets when autobranchlength is in effect. This should eliminate all but the most obscure corner cases where the 16 bit mode is selected when 8 bit mode will do.
author William Astle <lost@l-w.ca>
date Sat, 09 Jun 2012 17:23:04 -0600
parents 5d969517db74
children b0d53e2f3f53
files lwasm/insn_rel.c lwasm/lwasm.c lwasm/lwasm.h
diffstat 3 files changed, 32 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/lwasm/insn_rel.c	Sat Jun 09 16:25:19 2012 -0600
+++ b/lwasm/insn_rel.c	Sat Jun 09 17:23:04 2012 -0600
@@ -50,6 +50,7 @@
 	lw_expr_t t, e1, e2;
 	
 	l -> lint = -1;
+	l -> maxlen = OPLEN(instab[l -> insn].ops[3]) + 2;
 	if (CURPRAGMA(l, PRAGMA_AUTOBRANCHLENGTH) == 0)
 	{
 		l -> lint = instab[l -> insn].ops[1];
@@ -163,6 +164,23 @@
 					l -> lint = 16;
 				}
 			}
+			// size of 8-bit opcode + 8 bit offset
+			l -> len = OPLEN(instab[l -> insn].ops[2]) + 1;
+			as -> pretendmax = 1;
+			lwasm_reduce_expr(as, e2);
+			as -> pretendmax = 0;
+			l -> len = -1;
+			if (lw_expr_istype(e2, lw_expr_type_int))
+			{
+				// it reduced to an integer; is it in 8 bit range?
+				offs = lw_expr_intval(e2);
+				if (offs >= -128 && offs <= 127)
+				{
+					// fits in 8 bits with a worst case scenario
+					l -> len = OPLEN(instab[l -> insn].ops[2]) + 1;
+					l -> lint = 8;
+				}
+			}
 			lw_expr_destroy(e2);
 		}
 		if (lw_expr_istype(e, lw_expr_type_int))
--- a/lwasm/lwasm.c	Sat Jun 09 16:25:19 2012 -0600
+++ b/lwasm/lwasm.c	Sat Jun 09 17:23:04 2012 -0600
@@ -125,9 +125,18 @@
 	case lwasm_expr_linelen:
 		{
 			line_t *cl = ptr;
-			if (cl -> len == -1)
-				return NULL;
-			return lw_expr_build(lw_expr_type_int, cl -> len);
+			if (cl -> len != -1)
+				return lw_expr_build(lw_expr_type_int, cl -> len);
+				
+			if (cl -> as -> pretendmax)
+			{
+				if (cl -> maxlen != 0)
+				{
+					fprintf(stderr, "Pretending max, len = %d\n", cl -> maxlen);
+					return lw_expr_build(lw_expr_type_int, cl -> maxlen);
+				}
+			}
+			return NULL;
 		}
 		break;
 		
--- a/lwasm/lwasm.h	Sat Jun 09 16:25:19 2012 -0600
+++ b/lwasm/lwasm.h	Sat Jun 09 17:23:04 2012 -0600
@@ -156,6 +156,7 @@
 	lw_expr_t daddr;					// data address of the line (os9 only)
 	int len;							// the "size" this line occupies (address space wise) (-1 if unknown)
 	int dlen;							// the data "size" this line occupies (-1 if unknown)
+	int maxlen;							// maximum length; will be zero if not relevant
 	int insn;							// number of insn in insn table
 	int symset;							// set if the line symbol was consumed by the instruction
 	char *sym;							// symbol, if any, on the line
@@ -271,6 +272,7 @@
 	int execaddr;						// address from "end"
 	int inmod;							// inside an os9 module?
 	int undefzero;						// used for handling "condundefzero"
+	int pretendmax;						// set if we need to pretend the instruction is max length
 	unsigned char crc[3];				// crc accumulator
 	int badsymerr;						// throw error on undef sym if set