diff lwasm/insn_indexed.c @ 382:eacdae8a1575

Various bugfixes
author lost@starbug
date Sat, 15 May 2010 13:39:21 -0600
parents 8f9d72cfb897
children 2d7255509130
line wrap: on
line diff
--- a/lwasm/insn_indexed.c	Mon Apr 26 19:56:10 2010 -0600
+++ b/lwasm/insn_indexed.c	Sat May 15 13:39:21 2010 -0600
@@ -171,6 +171,7 @@
 			lwasm_register_error(as, l, "Bad operand");
 			return;
 		}
+		lwasm_save_expr(l, 0, e);
 		
 		(*p)++;
 		l -> lint = 2;
@@ -287,14 +288,118 @@
 	}
 }
 
-void insn_resolve_indexed_aux(asmstate_t *as, line_t *l, int force)
+void insn_resolve_indexed_aux(asmstate_t *as, line_t *l, int force, int elen)
 {
 	// here, we have an expression which needs to be
 	// resolved; the post byte is determined here as well
-	lw_expr_t e;
+	lw_expr_t e, e2, e3;
 	int pb = -1;
 	int v;
+	
+	if (l -> len != -1)
+		return;
+	
 	e = lwasm_fetch_expr(l, 0);
+	if (!lw_expr_istype(e, lw_expr_type_int))
+	{
+		// temporarily set the instruction length to see if we get a
+		// constant for our expression; if so, we can select an instruction
+		// size
+		e2 = lw_expr_copy(e);
+		// magic 2 for 8 bit (post byte + offset)
+		l -> len = OPLEN(instab[l -> insn].ops[0]) + elen + 2;
+		lwasm_reduce_expr(as, e2);
+//		l -> len += 1;
+//		e3 = lw_expr_copy(e);
+//		lwasm_reduce_expr(as, e3);
+		l -> len = -1;
+		if (lw_expr_istype(e2, lw_expr_type_int))
+		{
+			v = lw_expr_intval(e2);
+			// we have a reducible expression here which depends on
+			// the size of this instruction
+			if (v < -128 || v > 127)
+			{
+				l -> lint = 2;
+				switch (l -> pb & 0x07)
+				{
+				case 0:
+				case 1:
+				case 2:
+				case 3:
+					pb = 0x89 | (l -> pb & 0x03) | (0x10 * (l -> pb & 0x80));
+					break;
+			
+				case 4: // W
+					pb = (l -> pb & 0x80) ? 0xD0 : 0xCF;
+					break;
+				
+				case 5: // PCR
+				case 6: // PC
+					pb = (l -> pb & 0x80) ? 0x9D : 0x8D;
+					break;
+				}
+				
+				l -> pb = pb;
+				lw_expr_destroy(e2);
+//				lw_expr_destroy(e3);
+				return;
+			}
+			else if ((l -> pb & 0x80) || ((l -> pb & 0x07) > 3) || v < -16 || v > 15)
+			{
+				// if not a 5 bit value, is indirect, or is not X,Y,U,S
+				l -> lint = 1;
+				switch (l -> pb & 0x07)
+				{
+				case 0:
+				case 1:
+				case 2:
+				case 3:
+					pb = 0x88 | (l -> pb & 0x03) | (0x10 * (l -> pb & 0x80));
+					break;
+			
+				case 4: // W
+					// use 16 bit because W doesn't have 8 bit, unless 0
+					if (v == 0 && !(CURPRAGMA(l, PRAGMA_NOINDEX0TONONE) || l -> pb & 0x40))
+					{
+						pb = (l -> pb & 0x80) ? 0x90 : 0x8F;
+						l -> lint = 0;
+					}
+					else
+					{
+						pb = (l -> pb & 0x80) ? 0xD0 : 0xCF;
+						l -> lint = 2;
+					}
+					break;
+				
+				case 5: // PCR
+				case 6: // PC
+					pb = (l -> pb & 0x80) ? 0x9C : 0x8C;
+					break;
+				}
+			
+				l -> pb = pb;
+				return;
+			}
+			else
+			{
+				// we have X,Y,U,S and a possible 16 bit here
+				l -> lint = 0;
+				
+				if (v == 0 && !(CURPRAGMA(l, PRAGMA_NOINDEX0TONONE) || l -> pb & 0x40))
+				{
+					pb = (l -> pb & 0x03) << 5 | 0x84;
+				}	
+				else
+				{
+					pb = (l -> pb & 0x03) << 5 | v & 0x1F;
+				}
+				l -> pb = pb;
+				return;
+			}
+		}
+	}
+		
 	if (lw_expr_istype(e, lw_expr_type_int))
 	{
 		// we know how big it is
@@ -363,15 +468,17 @@
 		}
 		else
 		{
-			// we have X,Y,U,S and a possible 15 bit here
+			// we have X,Y,U,S and a possible 16 bit here
 			l -> lint = 0;
 			
 			if (v == 0 && !(CURPRAGMA(l, PRAGMA_NOINDEX0TONONE) || l -> pb & 0x40))
 			{
+				pb = (l -> pb & 0x03) << 5 | 0x84;
+			}
+			else
+			{
 				pb = (l -> pb & 0x03) << 5 | v & 0x1F;
 			}
-			else
-				pb = (l -> pb & 0x03) << 5 | 0x84;
 			l -> pb = pb;
 			return;
 		}
@@ -390,7 +497,7 @@
 RESOLVEFUNC(insn_resolve_indexed)
 {
 	if (l -> lint == -1)
-		insn_resolve_indexed_aux(as, l, force);
+		insn_resolve_indexed_aux(as, l, force, 0);
 	
 	if (l -> lint != -1 && l -> pb != -1)
 	{