changeset 381:1624a36f12a3

Properly support 32 bit relocations
author lost@starbug
date Mon, 26 Apr 2010 19:56:10 -0600
parents cc154dc614fe
children eacdae8a1575
files lwasm/lwasm.c
diffstat 1 files changed, 46 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/lwasm/lwasm.c	Mon Apr 26 19:44:44 2010 -0600
+++ b/lwasm/lwasm.c	Mon Apr 26 19:56:10 2010 -0600
@@ -631,17 +631,52 @@
 			reloctab_t *re;
 			lw_expr_t te;
 			
-			// add "expression" record to section table
-			re = lw_alloc(sizeof(reloctab_t));
-			re -> next = l -> csect -> reloctab;
-			l -> csect -> reloctab = re;
-			te = lw_expr_build(lw_expr_type_int, l -> outputl);
-			re -> offset = lw_expr_build(lw_expr_type_oper, lw_expr_oper_plus, l -> addr, te);
-			lw_expr_destroy(te);
-			lwasm_reduce_expr(l -> as, re -> offset);
-			re -> size = size;
-			re -> expr = lw_expr_copy(expr);
-			
+			if (size == 4)
+			{
+				// create a two part reference because lwlink doesn't
+				// support 32 bit references
+				lw_expr_t te2;
+				te = lw_expr_build(lw_expr_type_int, 0x10000);
+				te2 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_divide, expr, te);
+				lw_expr_destroy(te);
+				
+				re = lw_alloc(sizeof(reloctab_t));
+				re -> next = l -> csect -> reloctab;
+				l -> csect -> reloctab = re;
+				te = lw_expr_build(lw_expr_type_int, l -> outputl);
+				re -> offset = lw_expr_build(lw_expr_type_oper, lw_expr_oper_plus, l -> addr, te);
+				lw_expr_destroy(te);
+				lwasm_reduce_expr(l -> as, re -> offset);
+				re -> expr = te2;
+				re -> size = 2;
+
+				te = lw_expr_build(lw_expr_type_int, 0xFFFF);
+				te2 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_bwand, expr, te);
+				lw_expr_destroy(te);
+				
+				re = lw_alloc(sizeof(reloctab_t));
+				re -> next = l -> csect -> reloctab;
+				l -> csect -> reloctab = re;
+				te = lw_expr_build(lw_expr_type_int, l -> outputl + 2);
+				re -> offset = lw_expr_build(lw_expr_type_oper, lw_expr_oper_plus, l -> addr, te);
+				lw_expr_destroy(te);
+				lwasm_reduce_expr(l -> as, re -> offset);
+				re -> expr = te2;
+				re -> size = 2;
+			}
+			else
+			{
+				// add "expression" record to section table
+				re = lw_alloc(sizeof(reloctab_t));
+				re -> next = l -> csect -> reloctab;
+				l -> csect -> reloctab = re;
+				te = lw_expr_build(lw_expr_type_int, l -> outputl);
+				re -> offset = lw_expr_build(lw_expr_type_oper, lw_expr_oper_plus, l -> addr, te);
+				lw_expr_destroy(te);
+				lwasm_reduce_expr(l -> as, re -> offset);
+				re -> size = size;
+				re -> expr = lw_expr_copy(expr);
+			}
 			for (v = 0; v < size; v++)
 				lwasm_emit(l, 0);
 			return 0;