# HG changeset patch # User lost@starbug # Date 1270082792 21600 # Node ID 7166254491ed4d95a7469697a20d1dedad8b4bfb # Parent 981e34165e977237e1276642d1c9f796dd7f5661 Finished pseudo ops diff -r 981e34165e97 -r 7166254491ed lwasm/input.c --- 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; diff -r 981e34165e97 -r 7166254491ed lwasm/input.h --- 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 diff -r 981e34165e97 -r 7166254491ed lwasm/instab.c --- 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}, diff -r 981e34165e97 -r 7166254491ed lwasm/lwasm.h --- 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 diff -r 981e34165e97 -r 7166254491ed lwasm/pseudo.c --- 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 +#include + #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); + } +} diff -r 981e34165e97 -r 7166254491ed lwasm/section.c --- 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; + } +}