changeset 160:b061350c17e4

Added cescapes pragma and a few other compatibility pseudo ops
author lost
date Sat, 31 Jan 2009 06:33:03 +0000
parents 71561c12b20b
children 56d60169fc4d
files lwasm/instab.c lwasm/lwasm.h lwasm/pragma.c lwasm/pseudo.c
diffstat 4 files changed, 175 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/lwasm/instab.c	Sat Jan 31 06:32:27 2009 +0000
+++ b/lwasm/instab.c	Sat Jan 31 06:33:03 2009 +0000
@@ -389,10 +389,27 @@
 	{ ".globl",	{ -1, -1, -1, -1}, 	pseudo_export },
 	{ ".module",	{ -1, -1, -1, -1},	pseudo_noop },
 	
+	{ ".4byte",	{ -1, -1, -1, -1},	pseudo_fqb },
+	{ ".quad",	{ -1, -1, -1, -1},	pseudo_fqb },
+	
 	{ ".word",	{ -1, -1, -1, -1},	pseudo_fdb },
+	{ ".dw",	{ -1, -1, -1, -1},	pseudo_fdb },
+
 	{ ".byte",	{ -1, -1, -1, -1},	pseudo_fcb },
+	{ ".db",	{ -1, -1, -1, -1},	pseudo_fcb },
+
+	{ ".ascii",	{ -1, -1, -1, -1},	pseudo_fcc },
+	{ ".str",	{ -1, -1, -1, -1},	pseudo_fcc },
+	
+	{ ".ascis",	{ -1, -1, -1, -1},	pseudo_fcs },
+	{ ".strs",	{ -1, -1, -1, -1},	pseudo_fcs },
+	
+	{ ".asciz",	{ -1, -1, -1, -1},	pseudo_fcn },
+	{ ".strz",	{ -1, -1, -1, -1},	pseudo_fcn },
 	
 	{ ".blkb",	{ -1, -1, -1, -1},	pseudo_rmb },
+	{ ".ds",	{ -1, -1, -1, -1},	pseudo_rmb },
+	{ ".rs",	{ -1, -1, -1, -1},	pseudo_rmb },
 
 // needs to handle C escapes maybe?
 //	{ ".ascii",	{ -1, -1, -1, -1},	pseudo_ascii },
--- a/lwasm/lwasm.h	Sat Jan 31 06:32:27 2009 +0000
+++ b/lwasm/lwasm.h	Sat Jan 31 06:33:03 2009 +0000
@@ -181,7 +181,9 @@
 // do not rewrite XXX,r to ,r if XXX evaluates to 0
 #define PRAGMA_NOINDEX0TONONE	1
 // any undefined symbols are considered external
-#define PRAGMA_UNDEFEXTERN	2
+#define PRAGMA_UNDEFEXTERN		2
+// allow C-style escapes in fcc, fcs, and fcn directives
+#define PRAGMA_CESCAPES			4
 
 #ifndef __lwasm_c_seen__
 #define __lwasm_E__ extern
--- a/lwasm/pragma.c	Sat Jan 31 06:32:27 2009 +0000
+++ b/lwasm/pragma.c	Sat Jan 31 06:33:03 2009 +0000
@@ -99,6 +99,14 @@
 	{
 		as -> pragmas &= ~PRAGMA_UNDEFEXTERN;
 	}
+	else if (!strcasecmp(pragma, "cescapes"))
+	{
+		as -> pragmas |= PRAGMA_CESCAPES;
+	}
+	else if (!strcasecmp(pragma, "nocescapes"))
+	{
+		as -> pragmas &= ~PRAGMA_CESCAPES;
+	}
 	else
 	{
 		if (error)
--- a/lwasm/pseudo.c	Sat Jan 31 06:32:27 2009 +0000
+++ b/lwasm/pseudo.c	Sat Jan 31 06:33:03 2009 +0000
@@ -346,9 +346,120 @@
 	as -> dpval = v & 0xFF;
 }
 
+// used to get a byte from a string
+// -1 is end of line
+int pseudo_fcc_fetchchar(asmstate_t *as, char **p)
+{
+	int c;
+	
+	// -
+	if (!**p)
+		return -1;
+	
+	c = (unsigned char)(**p);
+	(*p)++;
+	
+	if (as -> pragmas & PRAGMA_CESCAPES && c == '\\')
+	{
+		// decode escapes if needed
+		if (!**p)
+			return c;
+		
+		c = **p;
+		(*p)++;
+		
+		switch (c)
+		{
+		// octal value
+		// 1, 2, or 3 digits
+		// NOTE: \0 for NUL is included in this...
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+			c -= '0';
+			if (**p < '0' || **p > '9')
+				return c;
+			c = c << 3;
+			c |= **p - '0';
+			(*p)++;
+			if (**p < '0' || **p > '9')
+				return c;
+			c = c << 3;
+			c |= **p - '0';
+			(*p)++;
+			return c;
+
+		// LF
+		case 'n':
+			return 10;
+		
+		// CR
+		case 'r':
+			return 13;
+		
+		// TAB
+		case 't':
+			return 9;
+		
+		// VT
+		case 'v':
+			return 11;
+		
+		// BS
+		case 'b':
+			return 8;
+		
+		// FF
+		case 'f':
+			return 12;
+		
+		// BEL
+		case 'a':
+			return 7;
+		
+		// hex char code (2 chars)
+		case 'x':
+		{
+			int c2;
+			if (!**p)
+				return 'x';
+			c = toupper(**p);
+			(*p)++;
+			if (c < '0' || (c > '9' && c < 'A') || c > 'F')
+				return 0;
+			c -= '0';
+			if (c > 9)
+				c -= 7;
+			c2 = c << 4;
+			if (!**p)
+				return 0;
+			c = toupper(**p);
+			(*p)++;
+			if (c < '0' || (c > '9' && c < 'A') || c > 'F')
+				return 0;
+			c -= '0';
+			if (c > 9)
+				c -= 7;
+			c2 |= c;
+			return c2;
+		}
+		// everything else stands for itself as a fall back or legit		
+		default:
+			return c;
+		}
+	}
+	return c;
+}
+
 OPFUNC(pseudo_fcc)
 {
 	int delim = 0;
+	int c;
 				
 	delim = **p;
 	if (!delim)
@@ -357,20 +468,22 @@
 		return;
 	}
 	*p += 1;
-	while (**p && **p != delim)
+	for (;;)
 	{
-		lwasm_emit(as, l, **p);
-		(*p)++;
+		c = pseudo_fcc_fetchchar(as, p);
+		if (c == delim || c < 0)
+			break;
+
+		lwasm_emit(as, l, c);
 	}
-	if (**p)
-		(*p)++;
 }
 		
 
 OPFUNC(pseudo_fcs)
 {
 	int delim = 0;
-
+	int c, lc = -1;
+	
 	delim = **p;
 	if (!delim)
 	{
@@ -378,22 +491,26 @@
 		return;
 	}
 	*p += 1;
-	while (**p && **p != delim)
+	for (;;)
 	{
-		if (!*((*p) + 1) || *((*p) + 1) == delim)
-			lwasm_emit(as, l, **p | 0x80);
-		else
-			lwasm_emit(as, l, **p);
-		(*p)++;
+		c = pseudo_fcc_fetchchar(as, p);
+		if (c == delim || c < 0)
+		{
+			if (lc >= 0)
+				lwasm_emit(as, l, lc | 0x80);
+			break;
+		}
+		if (lc >= 0)
+			lwasm_emit(as, l, lc);
+		lc = c;
 	}
-	if (**p)
-		(*p)++;
 }
 
 OPFUNC(pseudo_fcn)
 {		
 	int delim = 0;
-				
+	int c;
+	
 	delim = **p;
 	if (!delim)
 	{
@@ -401,17 +518,17 @@
 		return;
 	}
 	*p += 1;
-	while (**p && **p != delim)
+	for (;;)
 	{
-		lwasm_emit(as, l, **p);
-		(*p)++;
+		c = pseudo_fcc_fetchchar(as, p);
+		if (c == delim || c < 0)
+			break;
+
+		lwasm_emit(as, l, c);
 	}
-	if (**p)
-		(*p)++;
 	lwasm_emit(as, l, 0);
 }
 
-// FIXME: handle external, etc., references in a useful manner
 OPFUNC(pseudo_fcb)
 {
 	int r, v;
@@ -845,12 +962,20 @@
 		s -> obsize = 0;
 		s -> rl = NULL;
 		s -> exports = NULL;
+		// if name of section is "bss" or ".bss", assume bss flag
+		// which can be overridden with !bss flag
+		if (!strcasecmp(sn, "bss") || !strcasecmp(sn, ".bss"))
+			s -> flags = SECTION_BSS;
 		// parse options; only one "bss"
 		if (opts && as -> passnum == 1)
 		{
 			if (!strcasecmp(opts, "bss"))
 			{
-				s -> flags = SECTION_BSS;
+				s -> flags |= SECTION_BSS;
+			}
+			else if (!strcasecmp(opts, "!bss"))
+			{
+				s -> flags &= ~SECTION_BSS;
 			}
 			else
 			{