Mercurial > hg > index.cgi
view lwasm/lwasm.h @ 406:4411a6123716
Add "basic" output format
Add "basic" output format. This outputs the code in the form of a Basic
program that installs the assembled output. If an execution address is
provided to the END pseudo operation, it will transfer control there using
the Basic EXEC command.
Thanks to Tim Lindner <tlindner@macmess.org> for the original patch. I used
it mostly as is except for a couple of minor fixes for coding style and
removing a variable declaration from inside a for() statement for
portability reasons.
author | William Astle <lost@l-w.ca> |
---|---|
date | Thu, 03 Mar 2016 21:04:39 -0700 |
parents | 6153cb49403c |
children | 58cafa61ab40 |
line wrap: on
line source
/* lwasm.h Copyright © 2010 William Astle This file is part of LWTOOLS. LWTOOLS is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef ___lwasm_h_seen___ #define ___lwasm_h_seen___ #ifdef _MSC_VER #include <lw_win.h> // windows build #endif #include <lw_expr.h> #include <lw_stringlist.h> #include <lw_stack.h> #include <lw_version.h> // these are allowed chars BELOW 0x80 for symbols // first is symbol start chars, second is anywhere in symbol #define SSYMCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_@$" #define SYMCHARS SSYMCHARS ".?0123456789" typedef struct asmstate_s asmstate_t; enum { lwasm_expr_linelen = 1, // length of ref'd line lwasm_expr_lineaddr = 2, // addr of ref'd line lwasm_expr_nextbp = 3, // next branch point lwasm_expr_prevbp = 4, // previous branch point lwasm_expr_syment = 5, // symbol table entry lwasm_expr_import = 6, // symbol import entry lwasm_expr_secbase = 7, // section base address lwasm_expr_linedaddr = 8, // data address of the line lwasm_expr_linedlen = 9 // data length of the line }; enum lwasm_output_e { OUTPUT_DECB = 0, // DECB multirecord format OUTPUT_BASIC, // Color BASIC program OUTPUT_RAW, // raw sequence of bytes OUTPUT_OBJ, // proprietary object file format OUTPUT_RAWREL, // raw bytes where ORG causes a SEEK in the file OUTPUT_OS9, // os9 module target OUTPUT_SREC, // motorola SREC format OUTPUT_IHEX, // intel hex format OUTPUT_HEX // generic hexadecimal format }; enum lwasm_flags_e { FLAG_LIST = 0x0001, FLAG_DEPEND = 0x0002, FLAG_SYMBOLS = 0x004, FLAG_DEPENDNOERR = 0x0008, FLAG_UNICORNS = 0x0010, FLAG_MAP = 0x0020, FLAG_SYMBOLS_NOLOCALS = 0x0040, FLAG_NONE = 0 }; enum lwasm_pragmas_e { PRAGMA_NONE = 0, // no pragmas in effect PRAGMA_DOLLARNOTLOCAL = 1 << 0, // dollar sign does not make a symbol local PRAGMA_NOINDEX0TONONE = 1 << 1, // do not change implicit 0,R to ,R PRAGMA_UNDEFEXTERN = 1 << 2, // undefined symbols are considered to be external PRAGMA_CESCAPES = 1 << 3, // allow C style escapes in fcc, fcs, fcn, etc. PRAGMA_IMPORTUNDEFEXPORT = 1 << 4, // imports symbol if undefined upon export PRAGMA_PCASPCR = 1 << 5, // treats ,PC as ,PCR instead of constant offset PRAGMA_SHADOW = 1 << 6, // allow macros to shadow builtin operations PRAGMA_NOLIST = 1 << 7, // don't show line in listing PRAGMA_AUTOBRANCHLENGTH = 1 << 8, // automatically select proper length for relative branches PRAGMA_EXPORT = 1 << 9, // export symbols by default, unless local PRAGMA_SYMBOLNOCASE = 1 << 10, // symbols defined under this pragma are matched case insensitively PRAGMA_CONDUNDEFZERO = 1 << 11, // treat undefined symbols as zero in conditionals during pass 1 PRAGMA_6800COMPAT = 1 << 12, // enable 6800 compatibility opcodes PRAGMA_FORWARDREFMAX = 1 << 13, // force incomplete references on pass 1 to maximum mode PRAGMA_6809 = 1 << 14, // 6809/6309 assembly mode PRAGMA_TESTMODE = 1 << 15, // enable test mode (for internal unit testing) PRAGMA_C = 1 << 16, // enable cycle counts PRAGMA_CD = 1 << 17, // enable detailed cycle count PRAGMA_CT = 1 << 18, // enable cycle count running total PRAGMA_CC = 1 << 19, // clear cycle count running total PRAGMA_QRTS = 1 << 20, // enable BRA ?RTS support PRAGMA_M80EXT = 1 << 21, // enable Macro-80C assembler extensions PRAGMA_6809CONV = 1 << 22, // enable 6809 convenience ops PRAGMA_6309CONV = 1 << 23, // enable 6309 convenience ops PRAGMA_NEWSOURCE = 1 << 24, // don't use compatibility source format PRAGMA_CLEARBIT = 1 << 31 // reserved to indicate negated pragma flag status }; enum { section_flag_bss = 1, // BSS section section_flag_constant = 2, // constants - no base offset section_flag_none = 0 // no flags }; typedef struct reloctab_s reloctab_t; struct reloctab_s { lw_expr_t offset; // offset of relocation int size; // size of relocation lw_expr_t expr; // relocation expression reloctab_t *next; }; typedef struct sectiontab_s sectiontab_t; struct sectiontab_s { char *name; // section name int flags; // section flags; lw_expr_t offset; // offset for next instance int oblen; // size of section output int obsize; // size of output buffer unsigned char *obytes; // output buffer reloctab_t *reloctab; // table of relocations sectiontab_t *next; }; typedef enum { TF_EMIT = 1, TF_ERROR = 2 } lwasm_testflags_t; typedef enum { E_6309_INVALID = 1, E_6809_INVALID = 2, E_ALIGNMENT_INVALID = 3, E_BITNUMBER_UNRESOLVED = 4, E_BITNUMBER_INVALID = 5, E_BYTE_OVERFLOW = 6, E_CONDITION_P1 = 7, E_DIRECTIVE_OS9_ONLY = 8, E_DIV0 = 9, E_EXEC_ADDRESS = 10, E_FILL_INVALID = 11, E_IMMEDIATE_INVALID = 12, E_IMMEDIATE_UNRESOLVED = 13, E_EXPRESSION_BAD = 14, E_EXPRESSION_NOT_CONST = 15, E_EXPRESSION_NOT_RESOLVED = 16, E_FILE_OPEN = 17, E_FILENAME_MISSING = 18, E_INSTRUCTION_FAILED = 19, E_INSTRUCTION_SECTION = 20, E_LINE_ADDRESS = 21, E_LINED_ADDRESS = 22, E_MACRO_DUPE = 23, E_MACRO_ENDM = 24, E_MACRO_NONAME = 25, E_MACRO_RECURSE = 26, E_MODULE_IN = 27, E_MODULE_NOTIN = 28, E_NEGATIVE_BLOCKSIZE = 29, E_NEGATIVE_RESERVATION = 30, E_NW_8 = 31, E_OPCODE_BAD = 32, E_OPERAND_BAD = 33, E_OBJTARGET_ONLY = 34, E_PADDING_BAD = 35, E_PRAGMA_UNRECOGNIZED = 36, E_REGISTER_BAD = 37, E_SECTION_END = 38, E_SECTION_EXTDEP = 39, E_SECTION_FLAG = 40, E_SECTION_NAME = 41, E_SECTION_TARGET = 42, E_SETDP_INVALID = 43, E_SETDP_NOT_CONST = 44, E_STRING_BAD = 45, E_STRUCT_DUPE = 46, E_STRUCT_NONAME = 47, E_STRUCT_NOSYMBOL = 48, E_STRUCT_RECURSE = 49, E_SYMBOL_BAD = 50, E_SYMBOL_DUPE = 51, E_SYMBOL_MISSING = 52, E_SYMBOL_UNDEFINED = 53, E_SYMBOL_UNDEFINED_EXPORT = 54, E_UNKNOWN_OPERATION = 55, E_USER_SPECIFIED = 56, E_ORG_NOT_FOUND = 57, /* warnings must be 1000 or greater */ W_DUPLICATE_SECTION = 1000, W_ENDSTRUCT_WITHOUT = 1001, W_NOT_SUPPORTED = 1002, W_USER_SPECIFIED = 1003 } lwasm_errorcode_t; typedef struct lwasm_error_s lwasm_error_t; struct lwasm_error_s { lwasm_errorcode_t code; // error code char *mess; // actual error message int charpos; // character position on line where parsing stopped lwasm_error_t *next; // ptr to next error }; struct line_expr_s { lw_expr_t expr; int id; struct line_expr_s *next; }; typedef struct line_s line_t; typedef struct exportlist_s exportlist_t; struct exportlist_s { char *symbol; // symbol to export struct symtabe *se; // symbol table entry line_t *line; // line the export is on 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 enum { CYCLE_ADJ = 1, CYCLE_ESTIMATED = 2 } cycle_flags; struct line_s { lw_expr_t addr; // assembly address of the line lw_expr_t daddr; // data address of the line (os9 only) int len; // the "size" this line occupies (address space wise) (-1 if unknown) int dlen; // the data "size" this line occupies (-1 if unknown) int minlen; // minimum length int maxlen; // maximum length int insn; // number of insn in insn table int symset; // set if the line symbol was consumed by the instruction char *sym; // symbol, if any, on the line unsigned char *output; // output bytes int outputl; // size of output int outputbl; // size of output buffer int dpval; // direct page value int cycle_base; // base instruction cycle count int cycle_adj; // cycle adjustment int cycle_flags; // cycle flags int genmode; // generation mode (insn_parse_gen0/8/16) int fcc_extras; // fcc extra bytes lwasm_error_t *err; // list of errors lwasm_error_t *warn; // list of errors lwasm_errorcode_t err_testmode; // error code in testmode line_t *prev; // previous line line_t *next; // next line int inmod; // inside a module? sectiontab_t *csect; // which section are we in? struct line_expr_s *exprs; // expressions used during parsing char *lstr; // string passed forward int pb; // pass forward post byte int lint; // pass forward integer int lint2; // another pass forward integer int conditional_return; // for ?RTS handling (1 if RTS follows) asmstate_t *as; // assembler state data ptr int pragmas; // pragmas in effect for the line int context; // the symbol context number char *ltext; // line number char *linespec; // line spec int lineno; // line number int soff; // struct offset (for listings) int dshow; // data value to show (for listings) int dsize; // set to 1 for 8 bit dshow value int isbrpt; // set to 1 if this line is a branch point struct symtabe *dptr; // symbol value to display int noexpand_start; // start of a no-expand block int noexpand_end; // end of a no-expand block int hideline; // set if we're going to hide this line on output }; enum { symbol_flag_set = 1, // symbol was used with "set" symbol_flag_nocheck = 2, // do not check symbol characters symbol_flag_nolist = 4, // no not show symbol in symbol table symbol_flag_nocase = 8, // do not match case of symbol symbol_flag_none = 0 // no flags }; struct symtabe { char *symbol; // the name of the symbol int context; // symbol context (-1 for global) int version; // version of the symbol (for "set") int flags; // flags for the symbol sectiontab_t *section; // section the symbol is defined in lw_expr_t value; // symbol value struct symtabe *left; // left subtree pointer struct symtabe *right; // right subtree pointer struct symtabe *nextver; // next lower version }; typedef struct { struct symtabe *head; // start of symbol table } symtab_t; typedef struct macrotab_s macrotab_t; struct macrotab_s { char *name; // name of macro char **lines; // macro lines int numlines; // number lines in macro int flags; // flags for the macro macrotab_t *next; // next macro in list line_t *definedat; // the line where the macro definition starts }; enum { macro_noexpand = 1 // set to not expland the macro by default in listing }; typedef struct structtab_s structtab_t; typedef struct structtab_field_s structtab_field_t; struct structtab_field_s { char *name; // structure field name - NULL for anonymous int size; // structure field size structtab_t *substruct; // sub structure if there is one structtab_field_t *next; // next field entry }; struct structtab_s { char *name; // name of structure int size; // number of bytes taken by struct structtab_field_t *fields; // fields in the structure structtab_t *next; // next structure line_t *definedat; // line where structure is defined }; struct asmstate_s { int output_format; // output format int debug_level; // level of debugging requested FILE *debug_file; // FILE * to output debug messages to int flags; // assembly flags int pragmas; // pragmas currently in effect int errorcount; // number of errors encountered int warningcount; // number of warnings issued int testmode_errorcount; // number of errors in testmode int inmacro; // are we in a macro? int instruct; // are w in a structure? int skipcond; // skipping a condition? int skipcount; // depth of "skipping" int skipmacro; // are we skipping in a macro? int endseen; // have we seen an "end" pseudo? int execaddr; // address from "end" int inmod; // inside an os9 module? int undefzero; // used for handling "condundefzero" int pretendmax; // set if we need to pretend the instruction is max length unsigned char crc[3]; // crc accumulator int cycle_total; // cycle count accumulator int badsymerr; // throw error on undef sym if set line_t *line_head; // start of lines list line_t *line_tail; // tail of lines list line_t *cl; // current line pointer sectiontab_t *csect; // current section int context; // the current "context" int nextcontext; // the next available context 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 int tabwidth; // tab width in list file char *map_file; // name of map file char *output_file; // output file name lw_stringlist_t input_files; // files to assemble void *input_data; // opaque data used by the input system lw_stringlist_t include_list; // include paths lw_stack_t file_dir; // stack of the "current file" dir lw_stack_t includelist; structtab_t *structs; // defined structures structtab_t *cstruct; // current structure lw_expr_t savedaddr; // old address counter before struct started int exportcheck; // set if we need to collapse out the section base to 0 int passno; // set to the current pass number int preprocess; // set if we are prepocessing int fileerr; // flags error opening file int exprwidth; // the bit width of the expression being evaluated }; struct symtabe *register_symbol(asmstate_t *as, line_t *cl, char *sym, lw_expr_t value, int flags); struct symtabe *lookup_symbol(asmstate_t *as, line_t *cl, char *sym); int parse_pragma_helper(char *p); int lwasm_cycle_calc_ind(line_t *cl); int lwasm_cycle_calc_rlist(line_t *cl); void lwasm_cycle_update_count(line_t *cl, int opc); void lwasm_parse_testmode_comment(line_t *cl, lwasm_testflags_t *flags, lwasm_errorcode_t *err, int *len, char **buf); void lwasm_error_testmode(line_t *cl, const char* msg, int fatal); void lwasm_register_error(asmstate_t *as, line_t *cl, lwasm_errorcode_t err); void lwasm_register_error2(asmstate_t *as, line_t *cl, lwasm_errorcode_t err, const char* fmt, ...); int lwasm_next_context(asmstate_t *as); void lwasm_emit(line_t *cl, int byte); void lwasm_emitop(line_t *cl, int opc); void lwasm_save_expr(line_t *cl, int id, lw_expr_t expr); lw_expr_t lwasm_fetch_expr(line_t *cl, int id); lw_expr_t lwasm_parse_expr(asmstate_t *as, char **p); int lwasm_emitexpr(line_t *cl, lw_expr_t expr, int s); void skip_operand_real(line_t *l, char **p); /* this macro can only be used where "l" is the current line pointer */ #define skip_operand(p) skip_operand_real(l, p) int lwasm_lookupreg2(const char *rlist, char **p); int lwasm_lookupreg3(const char *rlist, char **p); void lwasm_show_errors(asmstate_t *as); int lwasm_reduce_expr(asmstate_t *as, lw_expr_t expr); lw_expr_t lwasm_parse_cond(asmstate_t *as, char **p); int lwasm_calculate_range(asmstate_t *as, lw_expr_t expr, int *min, int *max); void lwasm_reduce_line_exprs(line_t *cl); #ifdef LWASM_NODEBUG #define debug_message(...) #define dump_state(...) #else void real_debug_message(asmstate_t *as, int level, const char *fmt, ...); void dump_state(asmstate_t *as); #define debug_message(as,level,...) do { asmstate_t *ras = (as); int rlevel = (level); if (ras->debug_level >= rlevel) { real_debug_message(ras, rlevel, __VA_ARGS__); } } while (0) #endif #define OPLEN(op) (((op)>0xFF)?2:1) #define CURPRAGMA(l,p) (((l) && ((l)->pragmas & (p))) ? 1 : 0) /* some functions for parsing */ /* skip to the start of the next token if the current parsing mode allows it */ void lwasm_skip_to_next_token(line_t *cl, char **p); #endif /* ___lwasm_h_seen___ */