changeset 356:7166254491ed

Finished pseudo ops
author lost@starbug
date Wed, 31 Mar 2010 18:46:32 -0600
parents 981e34165e97
children 0cf4948d53b4
files lwasm/input.c lwasm/input.h lwasm/instab.c lwasm/lwasm.h lwasm/pseudo.c lwasm/section.c
diffstat 6 files changed, 383 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/lwasm/input.c	Tue Mar 30 23:12:41 2010 -0600
+++ b/lwasm/input.c	Wed Mar 31 18:46:32 2010 -0600
@@ -213,6 +213,53 @@
 	lw_error("Cannot figure out how to open '%s'.", t -> filespec);
 }
 
+FILE *input_open_standalone(asmstate_t *as, char *s)
+{
+	char *s2;
+	FILE *fp;
+	char *p, *p2;
+
+	/* first check for absolute path and if so, skip path */
+	if (*s == '/')
+	{
+		/* absolute path */
+		fp = fopen(s, "rb");
+		if (!fp)
+		{
+			return NULL;
+		}
+		return fp;
+	}
+
+	/* relative path, check relative to "current file" directory */
+	p = lw_stack_top(as -> file_dir);
+	0 == asprintf(&p2, "%s/%s", p, s);
+	fp = fopen(p2, "rb");
+	if (fp)
+	{
+		lw_free(p2);
+		return fp;
+	}
+	lw_free(p2);
+
+	/* now check relative to entries in the search path */
+	lw_stringlist_reset(as -> include_list);
+	while (p = lw_stringlist_current(as -> include_list))
+	{
+		0 == asprintf(&p2, "%s/%s", p, s);
+		fp = fopen(p2, "rb");
+		if (fp)
+		{
+			lw_free(p2);
+			return fp;
+		}
+		lw_free(p2);
+		lw_stringlist_next(as -> include_list);
+	}
+	
+	return NULL;
+}
+
 char *input_readline(asmstate_t *as)
 {
 	char *s;
--- a/lwasm/input.h	Tue Mar 30 23:12:41 2010 -0600
+++ b/lwasm/input.h	Wed Mar 31 18:46:32 2010 -0600
@@ -29,5 +29,6 @@
 extern void input_open(asmstate_t *as, char *s);
 extern char *input_readline(asmstate_t *as);
 extern char *input_curspec(asmstate_t *as);
+extern FILE *input_open_standalone(asmstate_t *as, char *s);
 
 #endif
--- a/lwasm/instab.c	Tue Mar 30 23:12:41 2010 -0600
+++ b/lwasm/instab.c	Wed Mar 31 18:46:32 2010 -0600
@@ -193,6 +193,25 @@
 #define pseudo_resolve_emod NULL
 extern EMITFUNC(pseudo_emit_emod);
 
+extern PARSEFUNC(pseudo_parse_extern);
+#define pseudo_resolve_extern NULL
+#define pseudo_emit_extern NULL
+
+extern PARSEFUNC(pseudo_parse_export);
+#define pseudo_resolve_export NULL
+#define pseudo_emit_export NULL
+
+extern PARSEFUNC(pseudo_parse_includebin);
+#define pseudo_resolve_includebin NULL
+extern EMITFUNC(pseudo_emit_includebin);
+
+extern PARSEFUNC(pseudo_parse_include);
+#define pseudo_resolve_include NULL
+#define pseudo_emit_include NULL
+
+extern PARSEFUNC(pseudo_parse_align);
+extern RESOLVEFUNC(pseudo_resolve_align);
+extern EMITFUNC(pseudo_emit_align);
 
 instab_t instab[] =
 {
@@ -457,13 +476,12 @@
 	{ "org",		{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_org,		pseudo_resolve_org,				pseudo_emit_org,			lwasm_insn_normal},
 	{ "equ",		{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_equ,		pseudo_resolve_equ,				pseudo_emit_equ,			lwasm_insn_setsym},
 	{ "=",			{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_equ,		pseudo_resolve_equ,				pseudo_emit_equ,			lwasm_insn_setsym},
-/*
+
 	{ "extern",		{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_extern,	pseudo_resolve_extern,			pseudo_emit_extern,			lwasm_insn_setsym},
 	{ "external",	{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_extern,	pseudo_resolve_extern,			pseudo_emit_extern,			lwasm_insn_setsym},
 	{ "import",		{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_extern,	pseudo_resolve_extern,			pseudo_emit_extern,			lwasm_insn_setsym},
 	{ "export",		{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_export,	pseudo_resolve_export,			pseudo_emit_export,			lwasm_insn_setsym},
 
-*/
 	{ "rmb", 		{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_rmb,		pseudo_resolve_rmb,				pseudo_emit_rmb,			lwasm_insn_normal},
 	{ "rmd", 		{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_rmd,		pseudo_resolve_rmd,				pseudo_emit_rmd,			lwasm_insn_normal},
 	{ "rmq", 		{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_rmq,		pseudo_resolve_rmq,				pseudo_emit_rmq,			lwasm_insn_normal},
@@ -480,14 +498,13 @@
 	{ "fdb",		{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_fdb,		pseudo_resolve_fdb,				pseudo_emit_fdb,			lwasm_insn_normal},
 	{ "fqb",		{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_fqb,		pseudo_resolve_fqb,				pseudo_emit_fqb,			lwasm_insn_normal},
 	{ "end", 		{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_end,		pseudo_resolve_end,				pseudo_emit_end,			lwasm_insn_normal},
-/*
+
 	{ "includebin", {	-1, 	-1, 	-1, 	-1},	pseudo_parse_includebin,pseudo_resolve_includebin,		pseudo_emit_includebin,		lwasm_insn_normal},
 	{ "include",	{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_include,	pseudo_resolve_include,			pseudo_emit_include,		lwasm_insn_normal},
 	{ "use",		{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_include,	pseudo_resolve_include,			pseudo_emit_include,		lwasm_insn_normal},
 	
 	{ "align", 		{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_align,		pseudo_resolve_align,			pseudo_emit_align,			lwasm_insn_normal},
 
-*/
 	{ "error",		{	-1, 	-1, 	-1, 	-1},	pseudo_parse_error,		pseudo_resolve_error,			pseudo_emit_error,			lwasm_insn_normal},
 
 	// these are *dangerous*
@@ -529,10 +546,10 @@
 	{ "emod",		{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_emod,		pseudo_resolve_emod,			pseudo_emit_emod,			lwasm_insn_normal},
 
 	// for compatibility with gcc6809 output...
-/*
+
 	{ ".area",		{	-1, 	-1, 	-1, 	-1},	pseudo_parse_section,	pseudo_resolve_section,			pseudo_emit_section,		lwasm_insn_normal},
 	{ ".globl",		{	-1, 	-1, 	-1, 	-1}, 	pseudo_parse_export,	pseudo_resolve_export,			pseudo_emit_export,			lwasm_insn_normal},
-*/
+
 	{ ".module",	{	-1, 	-1, 	-1, 	-1},	pseudo_parse_noop,		pseudo_resolve_noop,			pseudo_emit_noop,			lwasm_insn_normal},
 	
 	{ ".4byte",		{	-1, 	-1, 	-1, 	-1},	pseudo_parse_fqb,		pseudo_resolve_fqb,				pseudo_emit_fqb,			lwasm_insn_normal},
--- a/lwasm/lwasm.h	Tue Mar 30 23:12:41 2010 -0600
+++ b/lwasm/lwasm.h	Wed Mar 31 18:46:32 2010 -0600
@@ -104,6 +104,20 @@
 	struct line_expr_s *next;
 };
 
+typedef struct exportlist_s exportlist_t;
+struct exportlist_s
+{
+	char *symbol;						// symbol to export
+	exportlist_t *next;					// next in the export list
+};
+
+typedef struct importlist_s importlist_t;
+struct importlist_s
+{
+	char *symbol;						// symbol to import
+	importlist_t *next;					// next in the import list
+};
+
 typedef struct line_s line_t;
 struct line_s
 {
@@ -186,7 +200,8 @@
 	symtab_t symtab;					// meta data for the symbol table
 	macrotab_t *macros;					// macro table
 	sectiontab_t *sections;				// section table
-
+	exportlist_t *exportlist;			// list of exported symbols
+	importlist_t *importlist;			// list of imported symbols
 	char *list_file;					// name of file to list to
 	char *output_file;					// output file name	
 	lw_stringlist_t input_files;		// files to assemble
--- a/lwasm/pseudo.c	Tue Mar 30 23:12:41 2010 -0600
+++ b/lwasm/pseudo.c	Wed Mar 31 18:46:32 2010 -0600
@@ -21,8 +21,11 @@
 
 #include <config.h>
 
+#include <stdio.h>
+
 #include "lwasm.h"
 #include "instab.h"
+#include "input.h"
 
 #include "lw_string.h"
 
@@ -912,3 +915,188 @@
 	lwasm_register_error(as, l, "User error: %s", *p);
 	skip_operand(p);
 }
+
+PARSEFUNC(pseudo_parse_includebin)
+{
+	char *fn, *p2;
+	int delim = 0;
+	FILE *fp;
+	long flen;
+	
+	if (!**p)
+	{
+		lwasm_register_error(as, l, "Missing filename");
+		return;
+	}
+	
+	if (**p == '"' || **p == '\'')
+	{
+		delim = **p;
+		(*p)++;
+
+		for (p2 = *p; *p2 && *p2 != delim; p2++)
+			/* do nothing */ ;
+	}
+	else
+	{
+		for (p2 = *p; *p2 && !isspace(*p2); p2++)
+			/* do nothing */ ;
+	}
+	fn = lw_strndup(*p, p2 - *p);
+	
+	if (delim && **p)
+		(*p)++;
+	
+	fp = input_open_standalone(as, fn);
+	if (!fp)
+	{
+		lwasm_register_error(as, l, "Cannot open file");
+		lw_free(fn);
+		return;
+	}
+	
+	l -> lstr = fn;
+	
+	fseek(fp, 0, SEEK_END);
+	flen = ftell(fp);
+	fclose(fp);
+
+	l -> len = flen;
+}
+
+EMITFUNC(pseudo_emit_includebin)
+{
+	FILE *fp;
+	int c;
+	
+	fp = input_open_standalone(as, l -> lstr);
+	if (!fp)
+	{
+		lwasm_register_error(as, l, "Cannot open file (emit)!");
+		return;
+	}
+	
+	for (;;)
+	{
+		c = fgetc(fp);
+		if (c == EOF)
+		{
+			fclose(fp);
+			return;
+		}
+		lwasm_emit(l, c);
+	}
+}
+
+PARSEFUNC(pseudo_parse_include)
+{
+	char *fn, *p2;
+	int delim = 0;
+	
+	if (!**p)
+	{
+		lwasm_register_error(as, l, "Missing filename");
+		return;
+	}
+	
+	if (**p == '"' || **p == '\'')
+	{
+		delim = **p;
+		(*p)++;
+
+		for (p2 = *p; *p2 && *p2 != delim; p2++)
+			/* do nothing */ ;
+	}
+	else
+	{
+		for (p2 = *p; *p2 && !isspace(*p2); p2++)
+			/* do nothing */ ;
+	}
+	fn = lw_strndup(*p, p2 - *p);
+	
+	if (delim && **p)
+		(*p)++;
+	
+	input_open(as, fn);
+
+	l -> len = 0;
+}
+
+PARSEFUNC(pseudo_parse_align)
+{
+	lw_expr_t e;
+	
+	if (!**p)
+	{
+		lwasm_register_error(as, l, "Bad operand");
+		return;
+	}
+	
+	e = lwasm_parse_expr(as, p);
+	if (!e)
+	{
+		lwasm_register_error(as, l, "Bad operand");
+		return;
+	}
+	
+	lwasm_save_expr(l, 0, e);
+	
+	if (**p == ',')
+	{
+		e = lwasm_parse_expr(as, p);
+	}
+	else
+	{
+		e = lw_expr_build(lw_expr_type_int, 0);
+	}
+	if (!e)
+	{
+		lwasm_register_error(as, l, "Bad padding");
+		return;
+	}
+	
+	lwasm_save_expr(l, 1, e);
+}
+
+RESOLVEFUNC(pseudo_resolve_align)
+{
+	lw_expr_t e;
+	int align;
+
+	e = lwasm_fetch_expr(l, 0);
+	
+	if (lw_expr_istype(e, lw_expr_type_int))
+	{
+		align = lw_expr_intval(e);
+		if (align < 1)
+		{
+			lwasm_register_error(as, l, "Invalid alignment");
+			return;
+		}
+	}
+	
+	if (lw_expr_istype(l -> addr, lw_expr_type_int))
+	{
+		int a;
+		a = lw_expr_intval(l -> addr);
+		if (a % align == 0)
+		{
+			l -> len = 0;
+			return;
+		}
+		l -> len = align - (a % align);
+		return;
+	}
+}
+
+EMITFUNC(pseudo_emit_align)
+{
+	lw_expr_t e;
+	int i;
+	
+	e = lwasm_fetch_expr(l, 1);
+	for (i = 0; i < l -> len; i++)
+	{
+		lwasm_emitexpr(l, e, 1);
+	}
+}
--- a/lwasm/section.c	Tue Mar 30 23:12:41 2010 -0600
+++ b/lwasm/section.c	Wed Mar 31 18:46:32 2010 -0600
@@ -159,3 +159,111 @@
 
 	skip_operand(p);
 }
+
+PARSEFUNC(pseudo_parse_export)
+{
+	int after = 0;
+	char *sym = NULL;
+	exportlist_t *e;
+	
+	if (as -> output_format != OUTPUT_OBJ)
+	{
+		lwasm_register_error(as, l, "EXPORT only supported for object target");
+		return;
+	}
+	
+	if (l -> sym)
+		sym = lw_strdup(l -> sym);
+	
+	if (l -> sym)
+	{
+		skip_operand(p);
+	}
+
+again:
+	if (after || !sym)
+	{
+		char *p2;
+		
+		after = 1;
+		for (p2 = *p; *p2 && *p2 != ',' && !isspace(*p2); p2++)
+			/* do nothing */ ;
+		
+		sym = lw_strndup(*p, p2 - *p);
+	}
+	if (!sym)
+	{
+		lwasm_register_error(as, l, "No symbol for EXPORT");
+		return;
+	}
+	
+	// add the symbol to the "export" list (which will be resolved
+	// after the parse pass is complete
+	e = lw_alloc(sizeof(exportlist_t));
+	e -> next = as -> exportlist;
+	e -> symbol = lw_strdup(sym);
+	as -> exportlist = e;
+	lw_free(sym);
+	
+	if (after && **p == ',')
+	{
+		(*p)++;
+		for (; **p && isspace(**p); (*p)++)
+			/* do nothing */ ;
+		goto again;
+	}
+}
+
+PARSEFUNC(pseudo_parse_extern)
+{
+	int after = 0;
+	char *sym = NULL;
+	importlist_t *e;
+	
+	if (as -> output_format != OUTPUT_OBJ)
+	{
+		lwasm_register_error(as, l, "IMPORT only supported for object target");
+		return;
+	}
+	
+	if (l -> sym)
+		sym = lw_strdup(l -> sym);
+	
+	if (l -> sym)
+	{
+		skip_operand(p);
+	}
+
+again:
+	if (after || !sym)
+	{
+		char *p2;
+		
+		after = 1;
+		for (p2 = *p; *p2 && *p2 != ',' && !isspace(*p2); p2++)
+			/* do nothing */ ;
+		
+		sym = lw_strndup(*p, p2 - *p);
+	}
+	if (!sym)
+	{
+		lwasm_register_error(as, l, "No symbol for IMPORT");
+		return;
+	}
+	
+	// add the symbol to the "export" list (which will be resolved
+	// after the parse pass is complete
+	e = lw_alloc(sizeof(importlist_t));
+	e -> next = as -> importlist;
+	e -> symbol = lw_strdup(sym);
+	as -> importlist = e;
+	lw_free(sym);
+	
+	if (after && **p == ',')
+	{
+		(*p)++;
+		for (; **p && isspace(**p); (*p)++)
+			/* do nothing */ ;
+		goto again;
+	}
+}