changeset 470:2c1c5dd84024

Add << prefix to force 5 bit offsets in indexed modes Rounding out the compliment of operand size prefixes, we now have "<<" to mean "force 5 bits". According to Steve Bjork, this was the "official" way to do this since 1980. However, I have no official Motorola source for that. It does suggest that the choice of "<<" is consistent with other (historical) assemblers, though. Either way, it seems the most logical choice while avoiding any conflicts with legal source code, so "<<" it is.
author William Astle <lost@l-w.ca>
date Mon, 23 Jul 2018 17:45:18 -0600
parents 9393a6b8886c
children ad0efd5835c3
files lwasm/insn_gen.c lwasm/insn_indexed.c lwasm/lwasm.c lwasm/lwasm.h
diffstat 4 files changed, 112 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/lwasm/insn_gen.c	Sun Mar 04 10:24:58 2018 -0700
+++ b/lwasm/insn_gen.c	Mon Jul 23 17:45:18 2018 -0600
@@ -65,6 +65,11 @@
 	{
 		(*p)++;
 		l -> lint2 = 0;
+		if (**p == '<')
+		{
+			*p = optr2;
+			goto indexed;
+		}
 	}
 	// for compatibility with asxxxx
 	// * followed by a digit, alpha, or _, or ., or ?, or another * is "f8"
@@ -175,7 +180,10 @@
 		}
 		else if (l -> lint2 == 1 && l -> lint != -1)
 		{
-			l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1 + elen;
+			if (l -> lint == 3)
+				l -> len = OPLEN(instab[l -> insn].ops[1]) + 1 + elen;
+			else
+				l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1 + elen;
 		}
 	}
 }
@@ -261,7 +269,10 @@
 		}
 		else if (l -> lint2 == 1 && l -> lint != -1)
 		{
-			l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1 + elen;
+			if (l -> lint == 3)
+				l -> len = OPLEN(instab[l -> insn].ops[1]) + 1 + elen;
+			else
+				l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1 + elen;
 		}
 	}
 }
@@ -278,6 +289,27 @@
 	
 	if (l -> lint2 == 1)
 	{
+		if (l -> lint == 3)
+		{
+			int offs;
+			if (lw_expr_istype(e, lw_expr_type_int))
+			{
+				offs = lw_expr_intval(e);
+				if ((offs >= -16 && offs <= 15) || offs >= 0xFFF0)
+				{
+					l -> pb |= offs & 0x1f;
+					l -> lint = 0;
+				}
+				else
+				{
+					lwasm_register_error(as, l, E_BYTE_OVERFLOW);
+				}
+			}
+			else
+			{
+				lwasm_register_error(as, l, E_EXPRESSION_NOT_RESOLVED);
+			}
+		}
 		lwasm_emit(l, l -> pb);
 		if (l -> lint > 0)
 		{
@@ -375,7 +407,10 @@
 		}
 		else if (l -> lint2 == 1 && l -> lint != -1)
 		{
-			l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1;
+			if (l -> lint == 3)
+				l -> len = OPLEN(instab[l -> insn].ops[1]) + 1;
+			else
+				l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1;
 		}
 	}
 }
@@ -447,7 +482,10 @@
 		}
 		else if (l -> lint2 == 1 && l -> lint != -1)
 		{
-			l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1;
+			if (l -> lint == 3)
+				l -> len = OPLEN(instab[l -> insn].ops[1]) + 1;
+			else
+				l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1;
 		}
 	}
 }
@@ -509,7 +547,10 @@
 		}
 		else if (l -> lint2 == 1 && l -> lint != -1)
 		{
-			l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1;
+			if (l -> lint == 3)
+				l -> len = OPLEN(instab[l -> insn].ops[1]) + 1;
+			else
+				l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1;
 		}
 	}
 }
--- a/lwasm/insn_indexed.c	Sun Mar 04 10:24:58 2018 -0700
+++ b/lwasm/insn_indexed.c	Mon Jul 23 17:45:18 2018 -0600
@@ -286,6 +286,16 @@
 	{
 		l -> lint = 1;
 		(*p)++;
+		if (**p == '<')
+		{
+			l -> lint = 3;
+			(*p)++;
+			if (indir)
+			{
+				lwasm_register_error(as, l, E_ILL5);
+				return;
+			}
+		}
 	}
 	else if (**p == '>')
 	{
@@ -359,6 +369,10 @@
 			l -> pb = 0x89 | (rn << 5) | (indir ? 0x10 : 0);
 			return;
 		}
+		else if (l -> lint == 3)
+		{
+			l -> pb = (rn << 5);
+		}
 	}
 
 	// nnnn,W is only 16 bit (or 0 bit)
@@ -369,6 +383,11 @@
 			lwasm_register_error(as, l, E_NW_8);
 			return;
 		}
+		else if (l -> lint == 3)
+		{
+			lwasm_register_error(as, l, E_ILL5);
+			return;
+		}
 
 		if (l -> lint == 2)
 		{
@@ -409,11 +428,16 @@
 			l -> pb = indir ? 0x9C : 0x8C;
 			return;
 		}
-		if (l -> lint == 2)
+		else if (l -> lint == 2)
 		{
 			l -> pb = indir ? 0x9D : 0x8D;
 			return;
 		}
+		else if (l -> lint == 3)
+		{
+			lwasm_register_error(as, l, E_ILL5);
+			return;
+		}
 	}
 	
 	if (rn == 6)
@@ -423,14 +447,20 @@
 			l -> pb = indir ? 0x9C : 0x8C;
 			return;
 		}
-		if (l -> lint == 2)
+		else if (l -> lint == 2)
 		{
 			l -> pb = indir ? 0x9D : 0x8D;
 			return;
 		}
+		else if (l -> lint == 3)
+		{
+			lwasm_register_error(as, l, E_ILL5);
+			return;
+		}
 	}
 
-	l -> pb = (indir * 0x80) | rn | (f0 * 0x40);
+	if (l -> lint != 3)
+		l -> pb = (indir * 0x80) | rn | (f0 * 0x40);
 }
 
 PARSEFUNC(insn_parse_indexed)
@@ -440,7 +470,10 @@
 
 	if (l -> lint != -1)
 	{
-		l -> len = OPLEN(instab[l -> insn].ops[0]) + l -> lint + 1;
+		if (l -> lint == 3)
+			l -> len = OPLEN(instab[l -> insn].ops[0]) + 1;
+		else
+			l -> len = OPLEN(instab[l -> insn].ops[0]) + l -> lint + 1;
 	}
 }
 
@@ -722,7 +755,10 @@
 	
 	if (l -> lint != -1 && l -> pb != -1)
 	{
-		l -> len = OPLEN(instab[l -> insn].ops[0]) + l -> lint + 1;
+		if (l -> lint == 3)
+			l -> len = OPLEN(instab[l -> insn].ops[0]) + 1;
+		else
+			l -> len = OPLEN(instab[l -> insn].ops[0]) + l -> lint + 1;
 	}
 }
 
@@ -742,7 +778,29 @@
 	}
 	
 	// exclude expr,W since that can only be 16 bits
-	if (l -> lint == 2 && CURPRAGMA(l, PRAGMA_OPERANDSIZE) && (l -> pb != 0xAF && l -> pb != 0xB0))
+	if (l -> lint == 3)
+	{
+		int offs;
+		e = lwasm_fetch_expr(l, 0);
+		if (lw_expr_istype(e, lw_expr_type_int))
+		{
+			offs = lw_expr_intval(e);
+			if ((offs >= -16 && offs <= 15) || offs >= 0xFFF0)
+			{
+				l -> pb |= offs & 0x1f;
+				l -> lint = 0;
+			}
+			else
+			{
+				lwasm_register_error(as, l, E_BYTE_OVERFLOW);
+			}
+		}
+		else
+		{
+			lwasm_register_error(as, l, E_EXPRESSION_NOT_RESOLVED);
+		}
+	}
+	else if (l -> lint == 2 && CURPRAGMA(l, PRAGMA_OPERANDSIZE) && (l -> pb != 0xAF && l -> pb != 0xB0))
 	{
 		int offs;
 		e = lwasm_fetch_expr(l, 0);
--- a/lwasm/lwasm.c	Sun Mar 04 10:24:58 2018 -0700
+++ b/lwasm/lwasm.c	Mon Jul 23 17:45:18 2018 -0600
@@ -283,6 +283,7 @@
 		case E_ORG_NOT_FOUND:			return "Previous ORG not found";
 		case E_COMPLEX_INCOMPLETE:      return "Incomplete expression too complex";
 		case E_USER_SPECIFIED:			return "User Specified:";
+		case E_ILL5:					return "Illegal 5 bit offset";
 
 		case W_ENDSTRUCT_WITHOUT:		return "ENDSTRUCT without STRUCT";
 		case W_DUPLICATE_SECTION:		return "Section flags can only be specified the first time; ignoring duplicate definition";
--- a/lwasm/lwasm.h	Sun Mar 04 10:24:58 2018 -0700
+++ b/lwasm/lwasm.h	Mon Jul 23 17:45:18 2018 -0600
@@ -206,6 +206,7 @@
 	E_USER_SPECIFIED			= 56,
 	E_ORG_NOT_FOUND				= 57,
 	E_COMPLEX_INCOMPLETE        = 58,
+	E_ILL5						= 59,
 	
 	/* warnings must be 1000 or greater */