diff lwasm/output.c @ 376:91c0fe026940

Output incomplete references in object target
author lost@starbug
date Mon, 26 Apr 2010 17:59:30 -0600
parents 3498b2d88376
children 55ed7d06b136
line wrap: on
line diff
--- a/lwasm/output.c	Mon Apr 26 17:14:04 2010 -0600
+++ b/lwasm/output.c	Mon Apr 26 17:59:30 2010 -0600
@@ -230,6 +230,134 @@
 	s -> oblen += 1;
 }
 
+
+int write_code_obj_expraux(lw_expr_t e, void *of)
+{
+	int tt;
+	int v;
+	unsigned char buf[16];
+	
+	tt = lw_expr_type(e);
+
+	switch (tt)
+	{
+	case lw_expr_type_oper:
+		buf[0] =  0x04;
+		switch (lw_expr_intval(e))
+		{
+		case lw_expr_oper_plus:
+			buf[1] = 0x01;
+			break;
+		
+		case lw_expr_oper_minus:
+			buf[1] = 0x02;
+			break;
+		
+		case lw_expr_oper_times:
+			buf[1] = 0x03;
+			break;
+		
+		case lw_expr_oper_divide:
+			buf[1] = 0x04;
+			break;
+		
+		case lw_expr_oper_mod:
+			buf[1] = 0x05;
+			break;
+		
+		case lw_expr_oper_intdiv:
+			buf[1] = 0x06;
+			break;
+		
+		case lw_expr_oper_bwand:
+			buf[1] = 0x07;
+			break;
+		
+		case lw_expr_oper_bwor:
+			buf[1] = 0x08;
+			break;
+		
+		case lw_expr_oper_bwxor:
+			buf[1] = 0x09;
+			break;
+		
+		case lw_expr_oper_and:
+			buf[1] = 0x0A;
+			break;
+		
+		case lw_expr_oper_or:
+			buf[1] = 0x0B;
+			break;
+		
+		case lw_expr_oper_neg:
+			buf[1] = 0x0C;
+			break;
+		
+		case lw_expr_oper_com:
+			buf[1] = 0x0D;
+			break;
+
+		default:
+			buf[1] = 0xff;
+		}
+		writebytes(buf, 2, 1, of);
+		break;
+
+	case lw_expr_type_int:
+		v = lw_expr_intval(e);
+		buf[0] = 0x01;
+		buf[1] = (v >> 8) & 0xff;
+		buf[2] = v & 0xff;
+		writebytes(buf, 3, 1, of);
+		break;
+		
+	case lw_expr_type_special:
+		v = lw_expr_specint(e);
+		switch (v)
+		{
+		case lwasm_expr_secbase:
+			writebytes("\x05", 1, 1, of);
+			break;
+		
+		case lwasm_expr_import:
+			{
+				importlist_t *ie;
+				ie = lw_expr_specptr(e);
+				buf[0] = 0x02;
+				writebytes(buf, 1, 1, of);
+				writebytes(ie -> symbol, strlen(ie -> symbol) + 1, 1, of);
+				break;
+			}
+		case lwasm_expr_syment:
+			{
+				struct symtabe *se;
+				se = lw_expr_specptr(e);
+				buf[0] = 0x03;
+				writebytes(buf, 1, 1, of);
+				writebytes(se -> symbol, strlen(se -> symbol), 1, of);
+				if (se -> context != -1)
+				{
+					sprintf(buf, "\x01%d", se -> context);
+					writebytes(buf, strlen(buf), 1, of);
+				}
+				writebytes("", 1, 1, of);
+				break;
+			}
+			break;
+		}
+			
+	default:
+		// unrecognized term type - replace with integer 0
+		buf[0] = 0x01;
+		buf[1] = 0x00;
+		buf[2] = 0x00;
+		writebytes(buf, 3, 1, of);
+		break;
+	}
+	return 0;
+}
+
+
 void write_code_obj(asmstate_t *as, FILE *of)
 {
 	line_t *l;
@@ -359,8 +487,17 @@
 		writebytes("", 1, 1, of);
 		
 		// FIXME - relocation table
-/*		for (re = s -> rl; re; re = re -> next)
+		for (re = s -> reloctab; re; re = re -> next)
 		{
+			int offset;
+			lw_expr_t te;
+			line_t tl;
+			
+			tl.as = as;
+			as -> cl = &tl;
+			as -> csect = s;
+			as -> exportcheck = 1;
+			
 			if (re -> expr == NULL)
 			{
 				// this is an error but we'll simply ignore it
@@ -370,80 +507,36 @@
 			
 			// work through each term in the expression and output
 			// the proper equivalent to the object file
-			if (re -> relocsize == 1)
+			if (re -> size == 1)
 			{
 				// flag an 8 bit relocation (low 8 bits will be used)
 				buf[0] = 0xFF;
 				buf[1] = 0x01;
 				writebytes(buf, 2, 1, of);
 			}
-			for (sn = re -> expr -> head; sn; sn = sn -> next)
+			
+			te = lw_expr_copy(ex -> se -> value);
+			lwasm_reduce_expr(as, te);
+			if (!lw_expr_istype(te, lw_expr_type_int))
 			{
-				switch (sn -> term -> term_type)
-				{
-				case LWASM_TERM_OPER:
-					buf[0] =  0x04;
-					buf[1] = sn -> term -> value;
-					writebytes(buf, 2, 1, of);
-					break;
-					
-				case LWASM_TERM_INT:
-					buf[0] = 0x01;
-					buf[1] = (sn -> term -> value >> 8) & 0xff;
-					buf[2] = sn -> term -> value & 0xff;
-					writebytes(buf, 3, 1, of);
-					break;
-				
-				case LWASM_TERM_SECBASE:
-					writebytes("\x05", 1, 1, of);
-					break;
-
-				case LWASM_TERM_SYM:
-					// now for the ugly part - resolve a symbol reference
-					// and determine whether it's internal, external, or
-					// a section base
-					se = lwasm_find_symbol(as, sn -> term -> symbol, re -> context);
-					if (!se)
-						se = lwasm_find_symbol(as, sn -> term -> symbol, -1);
-					if (!se || se -> flags & SYMBOL_EXTERN)
-					{
-						// not found - assume external reference
-						// found but flagged external - handle it
-						writebytes("\x02", 1, 1, of);
-						writebytes(se -> sym, strlen(se -> sym) + 1, 1, of);
-						break;
-					}
-					// a local symbol reference here
-					writebytes("\x03", 1, 1, of);
-					writebytes(se -> sym, strlen(se -> sym), 1, of);
-					if (se -> context >= 0)
-					{
-						writebytes("\x01", 1, 1, of);
-						sprintf(buf, "%d", se -> context);
-						writebytes(buf, strlen(buf), 1, of);
-					}
-					writebytes("", 1, 1, of);
-					break;
-
-				default:
-					// unrecognized term type - replace with integer 0
-					buf[0] = 0x01;
-					buf[1] = 0x00;
-					buf[2] = 0x00;
-					writebytes(buf, 3, 1, of);
-					break;
-				}
+				lw_expr_destroy(te);
+				continue;
 			}
+			offset = lw_expr_intval(te);
+			lw_expr_destroy(te);
+			
+			// output expression
+			lw_expr_testterms(re -> expr, write_code_obj_expraux, of);
 			
 			// flag end of expressions
 			writebytes("", 1, 1, of);
 			
 			// write the offset
-			buf[0] = (re -> offset >> 8) & 0xff;
-			buf[1] = re -> offset & 0xff;
+			buf[0] = (offset >> 8) & 0xff;
+			buf[1] = offset & 0xff;
 			writebytes(buf, 2, 1, of);
 		}
-*/
+
 		// flag end of incomplete references list
 		writebytes("", 1, 1, of);