diff --git a/CHANGELOG b/CHANGELOG index 52ba966..72dccf6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -101,3 +101,16 @@ + implement the 'stitle' and 'subttl' directives. + imported the REPEAT and ENDREP directives from upstream. / implement the 'width' directive and, maybe, line folding? ++ fixed some if..else..endif issues. ++ finalized (I hope..) the SCN2650 backend so it can be committed soon. ++ reworked the way we handle pseudo's and directives. ++ added commandline 'T' option, to show all supported devices. ++ added builtin macros __VASM__ (set to 1) and __VASM_VER__ (set to the + binary version number, so 0x01000E00 for this commit.) ++ target-device macros (P6502 etc) now start with a _ (underscore), so + be sure to update your files! ++ reworked some small issues in the listing output ++ added option that page-length of 255 lines *disables* paging. ++ added the DS directive (alias for FILL, really.) +- make option to allow for case-insensitivity of symbol names +- add symbol-table listing in numeric order diff --git a/README.md b/README.md index 91f53ed..496ba43 100644 --- a/README.md +++ b/README.md @@ -57,4 +57,4 @@ can work on it, and/or talk to us on the IRC channel. We cannot promise a fix, but will try the best we can ! -Last Updated: 2023/04/11 +Last Updated: 2023/05/14 diff --git a/src/error.c b/src/error.c index 9435c41..5d3176a 100644 --- a/src/error.c +++ b/src/error.c @@ -74,6 +74,7 @@ const char *err_msgs[ERR_MAXERR] = { "assert failed", "unknown directive", "unknown instruction", + "comma expected", "value expected", "invalid format specifier", "error in expression", diff --git a/src/error.h b/src/error.h index 056a2c1..8ae8deb 100644 --- a/src/error.h +++ b/src/error.h @@ -57,6 +57,7 @@ typedef enum errors_e { ERR_ASSERT, // "assert failed" ERR_NODIRECTIVE, // "unknown directive" ERR_INSTR, // "unknown instruction" + ERR_COMMA, // "comma expected" ERR_NUM, // "value expected" ERR_FMT, // "invalid format specifier" ERR_EXPR, // "error in expression" diff --git a/src/list.c b/src/list.c index 55e8bc9..c11fd0d 100644 --- a/src/list.c +++ b/src/list.c @@ -8,7 +8,7 @@ * * Handle the listfile output. * - * Version: @(#)list.c 1.0.5 2023/05/13 + * Version: @(#)list.c 1.0.6 2023/05/14 * * Author: Fred N. van Kempen, * @@ -242,7 +242,8 @@ list_line(const char *p) } fputs("\n", list_file); - list_pln--; + if (list_plength != 255) + list_pln--; if (list_oc < oc) list_line(NULL); @@ -277,32 +278,34 @@ list_symbols(void) fprintf(fp, "%-32s %c ", sym->name, sym_type(sym)); if (DEFINED(sym->value)) { - fprintf(fp, "%5s ", value_print(sym->value)); + fprintf(fp, "%9s ", value_print(sym->value)); if (IS_VAR(sym)) fprintf(fp, "%c", value_type(sym->value)); else fprintf(fp, " "); fprintf(fp, " "); - if (sym->filenr != -1) + if (sym->linenr < 0) + fprintf(fp, "-builtin-"); + else if (sym->filenr != -1 && sym->linenr != 0) fprintf(fp, "%s:%i", filenames[sym->filenr], sym->linenr); else fprintf(fp, "-command line-"); } else - fprintf(fp, "%5s", "??"); + fprintf(fp, "%9s", "??"); fprintf(fp, "\n"); - if (list_file != NULL) + if (list_file != NULL && list_plength != 255) list_pln--; if ((list_syms == 2) && IS_LBL(sym)) { for (loc = sym->locals; loc; loc = loc->next) { - if ((list_file != NULL) && (--list_pln == 0)) + if ((list_file != NULL && (list_plength != 255)) && (--list_pln == 0)) list_page("** SYMBOL TABLE **", NULL); fprintf(fp, " %c%-29s %c ", ALPHA_CHAR, loc->name, sym_type(sym)); - fprintf(fp, "%5s %s:%i\n", + fprintf(fp, "%9s %s:%i\n", value_print(loc->value), filenames[loc->filenr], loc->linenr); } diff --git a/src/main.c b/src/main.c index b4359e9..ac4e6c0 100644 --- a/src/main.c +++ b/src/main.c @@ -8,9 +8,9 @@ * * A simple but reasonably useful assembler for the 6502. * - * Usage: vasm [-dCFqsvPV] [-p processor] [-l fn] [-o fn] [-Dsym[=val]] file ... + * Usage: vasm [-dCFqsTvPV] [-p processor] [-l fn] [-o fn] [-Dsym[=val]] file ... * - * Version: @(#)main.c 1.0.8 2023/05/12 + * Version: @(#)main.c 1.0.9 2023/05/14 * * Authors: Fred N. van Kempen, * Bernd B”ckmann, @@ -58,6 +58,7 @@ # include #endif #include "global.h" +#include "target.h" #include "version.h" @@ -108,10 +109,30 @@ nodata: } +static void +init_symbols(void) +{ + char temp[128]; + uint32_t i; + + /* Indicate "builtin" symbol. */ + line = -1; + + do_define("__VASM__"); + i = ((APP_VER_MAJOR << 24) | (APP_VER_MINOR << 16) | \ + (APP_VER_REV << 8) | APP_VER_PATCH); + sprintf(temp, "__VASM_VER__=%i", i); + do_define(temp); + + /* Set for "commandline" symbols. */ + line = 0; +} + + static void usage(const char *prog) { - printf("Usage: %s [-dCFPqsvV] [-p processor] [-l fn] [-o fn] [-Dsym[=val]] file ...\n", prog); + printf("Usage: %s [-dCFPqsTvV] [-p processor] [-l fn] [-o fn] [-Dsym[=val]] file ...\n", prog); exit(1); /*NOTREACHED*/ @@ -152,6 +173,9 @@ main(int argc, char *argv[]) filenames_idx = -1; // this indicates "command line" radix = RADIX_DEFAULT; + /* Create any pre-defined symbols. */ + init_symbols(); + /* Create a version string. */ sprintf(myname, "%s", APP_NAME); sprintf(version, "version %s (%s, %s)", @@ -164,7 +188,7 @@ main(int argc, char *argv[]) STR(ARCH)); opterr = 0; - while ((c = getopt(argc, argv, "dCD:Fl:o:Pp:qsvV")) != EOF) switch(c) { + while ((c = getopt(argc, argv, "dCD:Fl:o:Pp:qsTvV")) != EOF) switch(c) { case 'C': // toggle list-offset display (disabled) opt_C ^= 1; break; @@ -209,6 +233,13 @@ main(int argc, char *argv[]) list_set_syms(opt_s << 1); // FULL or OFF break; + case 'T': // list all supported targets + banner(); + printf("These are the supported target devices:\n\n"); + trg_list(); + exit(EXIT_SUCCESS); + /*NOTREACHED*/ + case 'v': // level of verbosity (lowest) opt_v++; break; diff --git a/src/parse.c b/src/parse.c index f17f37b..1d833dd 100644 --- a/src/parse.c +++ b/src/parse.c @@ -8,7 +8,7 @@ * * Parse the source input, process it, and generate output. * - * Version: @(#)parse.c 1.0.8 2023/05/13 + * Version: @(#)parse.c 1.0.8 2023/05/14 * * Authors: Fred N. van Kempen, * Bernd B”ckmann, @@ -371,6 +371,11 @@ again: if (isalpha(**p)) { /* Execute instruction and update program counter. */ pc += trg_instr(p, pass); + + /* We should have nothing left now.. */ + skip_white_and_comment(p); + if (! IS_EOL(**p)) + error(ERR_EOL, NULL); } else error(ERR_STMT, NULL); } else { diff --git a/src/pseudo.c b/src/pseudo.c index 24c0bdf..4742eac 100644 --- a/src/pseudo.c +++ b/src/pseudo.c @@ -8,7 +8,7 @@ * * Handle directives and pseudo-ops. * - * Version: @(#)pseudo.c 1.0.5 2023/05/12 + * Version: @(#)pseudo.c 1.0.6 2023/05/14 * * Authors: Fred N. van Kempen, * Bernd B”ckmann, @@ -391,7 +391,7 @@ do_echo(char **p, int pass) int fmt, next; value_t v; - if (pass == 1) { + if (pass == 2) { while (! IS_END(**p)) (*p)++; return NULL; @@ -439,12 +439,15 @@ do_else(char **p, int pass) if (! IS_END(**p)) error(ERR_EOL, NULL); - if (iflevel > 0) { + if (iflevel > 0) newifstate = !ifstate; - ifstate = ifstack[iflevel - 1]; - } else + else error(ERR_ELSE, NULL); + /* If we are skipping, keep skipping! */ +// if (! ifstate) +// newifstate = ifstate; + return NULL; } @@ -526,10 +529,42 @@ do_endrep(char **p, int pass) static char * do_error(char **p, int pass) { - char buff[STR_LEN * 4]; + char buff[4*STR_LEN], *s; + char temp[STR_LEN]; + int fmt, next; + value_t v; - skip_white(p); - string_lit(p, buff, STR_LEN * 4, 0); + s = buff; + + do { + next = 0; + + skip_white(p); + if (**p == '"') { + string_lit(p, temp, STR_LEN, 1); + sprintf(s, "%s", temp); + s += strlen(s); + } else { + fmt = value_format(p); + if (fmt == 0) + fmt = FMT_DEC_CHAR; + else if (fmt < 0) + error(-fmt, NULL); + + v = expr(p); + if (DEFINED(v)) + sprintf(s, "%s", value_print_format(v, fmt)); + else + sprintf(s, "??"); + s += strlen(s); + } + + skip_white(p); + if (**p == ',') { + skip_curr_and_white(p); + next = 1; + } + } while (next); error(ERR_USER, buff); /*NOTREACHED*/ @@ -624,6 +659,10 @@ do_if(char **p, int pass) } else error(ERR_IF, NULL); + /* If we are skipping, keep skipping! */ + if (! ifstate) + newifstate = ifstate; + return NULL; } @@ -648,6 +687,10 @@ do_ifdef(char **p, int pass) } else error(ERR_IF, NULL); + /* If we are skipping, keep skipping! */ + if (! ifstate) + newifstate = ifstate; + return NULL; } @@ -681,6 +724,10 @@ do_ifn(char **p, int pass) } else error(ERR_IF, NULL); + /* If we are skipping, keep skipping! */ + if (! ifstate) + newifstate = ifstate; + return NULL; } @@ -748,6 +795,10 @@ do_ifndef(char **p, int pass) } else error(ERR_IF, NULL); + /* If we are skipping, keep skipping! */ + if (! ifstate) + newifstate = ifstate; + return NULL; } @@ -1058,17 +1109,46 @@ do_title(char **p, int pass) static char * do_warn(char **p, int pass) { - char buff[STR_LEN * 4]; - char *str = *p; + char buff[4*STR_LEN], *s; + char temp[STR_LEN]; + int fmt, next; + value_t v; - skip_white(p); - string_lit(p, buff, STR_LEN * 4, 0); + s = buff; + sprintf(s, "*** WARNING: "); + s += strlen(s); - if (pass == 2) - printf("*** WARNING: "); + do { + next = 0; - *p = str; - do_echo(p, pass); + skip_white(p); + if (**p == '"') { + string_lit(p, temp, STR_LEN, 1); + sprintf(s, "%s", temp); + s += strlen(s); + } else { + fmt = value_format(p); + if (fmt == 0) + fmt = FMT_DEC_CHAR; + else if (fmt < 0) + error(-fmt, NULL); + + v = expr(p); + if (DEFINED(v)) + sprintf(s, "%s", value_print_format(v, fmt)); + else + sprintf(s, "??"); + s += strlen(s); + } + + skip_white(p); + if (**p == ',') { + skip_curr_and_white(p); + next = 1; + } + } while (next); + + printf("%s\n", buff); return NULL; } @@ -1138,6 +1218,7 @@ static const pseudo_t pseudos[] = { { "DB", 0, 0, do_byte, NULL }, { "DEFINE", 0, 0, do_define, NULL }, { "DL", 0, 0, do_dword, NULL }, + { "DS", 0, 0, do_fill, NULL }, { "DW", 0, 0, do_word, NULL }, { "DWORD", 0, 0, do_dword, NULL }, { "ECHO", 0, 1, do_echo, NULL }, @@ -1168,6 +1249,7 @@ static const pseudo_t pseudos[] = { { "SYMS", 0, 0, do_syms, NULL }, { "TITLE", 0, 0, do_title, NULL }, { "WARN", 0, 1, do_warn, NULL }, + { "WARNING", 0, 1, do_warn, NULL }, { "WIDTH", 0, 0, do_width, NULL }, { "WORD", 0, 0, do_word, NULL }, { NULL } diff --git a/src/target.c b/src/target.c index 254b0a5..847aeb6 100644 --- a/src/target.c +++ b/src/target.c @@ -8,7 +8,7 @@ * * Handle selection of a target device. * - * Version: @(#)target.c 1.0.3 2023/05/13 + * Version: @(#)target.c 1.0.4 2023/05/14 * * Author: Fred N. van Kempen, * @@ -57,7 +57,8 @@ extern const target_t t_6502_old, t_6502_nmos, t_csg6510, t_csg8500, - t_65c02; + t_r65c02, + t_w65c02; extern const target_t t_6800; extern const target_t t_6805; @@ -77,7 +78,9 @@ static const target_t *targets[] = { &t_csg6510, // CSG 6510 (NMOS) &t_csg8500, // CSG 8500 (NMOS) - &t_65c02, // standard MOS65C02 (CMOS) +// &t_65c02, // MOS 65C02 (CMOS) + &t_r65c02, // Rockwell 65C02 (CMOS) + &t_w65c02, // WDC 65C02 (CMOS) #ifdef USE_MC6800 &t_6800, // MC6800/01/02 @@ -142,6 +145,17 @@ set_cpu(const char *p, int pass) } +/* List all supported targets. */ +void +trg_list(void) +{ + const target_t **t; + + for (t = targets; *t != NULL; t++) + printf("%-10s %s\n", (*t)->name, (*t)->descr); +} + + /* Create a target-specific symbol. */ void trg_symbol(const char *name) @@ -150,6 +164,7 @@ trg_symbol(const char *name) value_t v = { 0 }; int i = 0; + id[i++] = '_'; id[i++] = 'P'; do { id[i++] = (char)toupper(*name++); diff --git a/src/target.h b/src/target.h index 7a7901c..ce6e156 100644 --- a/src/target.h +++ b/src/target.h @@ -8,7 +8,7 @@ * * Definitions for the target backends. * - * Version: @(#)target.h 1.0.1 2023/04/20 + * Version: @(#)target.h 1.0.2 2023/05/14 * * Author: Fred N. van Kempen, * @@ -50,8 +50,8 @@ typedef struct target { const char *name; - uint32_t flags; + const char *descr; const void *priv; int priv2; @@ -64,6 +64,7 @@ typedef struct target { extern int trg_set_cpu(const char *); +extern void trg_list(void); extern void trg_symbol(const char *); extern const char *trg_error(int); extern int trg_instr(char **, int); diff --git a/src/targets/mos6502.c b/src/targets/mos6502.c index 40ac9ae..42ba81a 100644 --- a/src/targets/mos6502.c +++ b/src/targets/mos6502.c @@ -14,7 +14,7 @@ * version produced later. The CMOS version also has variants * from Rockwell and WDC, with even more changes. * - * Version: @(#)mos6502.c 1.0.5 2023/04/26 + * Version: @(#)mos6502.c 1.0.7 2023/05/14 * * Authors: Fred N. van Kempen, * Bernd B”ckmann, @@ -98,8 +98,8 @@ typedef enum { #define CPU_NMOS_0 0x00 // first NMOS processor, ROR bug #define CPU_NMOS_1 0x01 // regular NMOS core #define CPU_CMOS 0x02 // standard CMOS core -#define CPU_CMOS_1 0x04 // Rockwell CMOS -#define CPU_CMOS_2 0x08 // WDC CMOS +#define CPU_RW 0x04 // Rockwell CMOS +#define CPU_WDC 0x08 // WDC CMOS typedef struct opcode { @@ -339,7 +339,7 @@ static const opcode_t opc_cmos[] = { {INV ,INV ,INV ,INV ,INV ,INV ,0x87,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV }}, { "STA", CPU_CMOS, {INV ,INV ,INV ,INV ,0x85,0x92,INV ,0x95,INV ,0x8d,0x9d,0x99,INV ,0x81,0x91}}, - { "STP", CPU_CMOS|CPU_CMOS_2, + { "STP", CPU_CMOS|CPU_WDC, {INV ,0xdb,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV }}, { "STX", CPU_CMOS, {INV ,INV ,INV ,INV ,0x86,INV ,INV ,INV ,0x96,0x8e,INV ,INV ,INV ,INV ,INV }}, @@ -363,7 +363,7 @@ static const opcode_t opc_cmos[] = { {INV ,0x9a,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV }}, { "TYA", CPU_CMOS, {INV ,0x98,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV }}, - { "WAI", CPU_CMOS|CPU_CMOS_2, + { "WAI", CPU_CMOS|CPU_WDC, {INV ,0xcb,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV ,INV }} }; @@ -371,7 +371,7 @@ static const opcode_t opc_cmos[] = { static const uint16_t am_size[AM_NUM] = { 1,1,2,2,2,2,2,2,2,3,3,3,3,2,2 }; -static const char *err_msg[] = { +static const char *err_msg[ERR_MAXTRG - ERR_MAXERR] = { "invalid addressing mode", "invalid register", "malformed indirect X addressing", @@ -719,7 +719,7 @@ t_instr_ok(const target_t *trg, const char *p) *ptr++ = (char)toupper(*p++); *ptr = '\0'; - /* First get instruction for given mnemonic. */ + /* Get instruction for given mnemonic. */ op = get_mnemonic((const opcode_t *)trg->priv, trg->priv2, id); if (op != NULL) return 1; @@ -728,9 +728,7 @@ t_instr_ok(const target_t *trg, const char *p) } -/* - * Return a local error message. - */ +/* Return a local error message. */ static const char * t_error(int err) { @@ -743,30 +741,42 @@ t_error(int err) const target_t t_6502_old = { "6502_old", CPU_CMOS, + "MOS6502 (old)", opc_nmos, (sizeof(opc_nmos) / sizeof(opcode_t)), t_error, t_instr, t_instr_ok }; const target_t t_6502_nmos = { "6502", CPU_NMOS_1, + "MOS6502", opc_nmos, (sizeof(opc_nmos) / sizeof(opcode_t)), t_error, t_instr, t_instr_ok }; const target_t t_csg6510 = { "6510", CPU_NMOS_1, + "CSG6510", opc_nmos, (sizeof(opc_nmos) / sizeof(opcode_t)), t_error, t_instr, t_instr_ok }; const target_t t_csg8500 = { "8500", CPU_NMOS_1, + "CSG8500", opc_nmos, (sizeof(opc_nmos) / sizeof(opcode_t)), t_error, t_instr, t_instr_ok }; -const target_t t_65c02 = { +const target_t t_r65c02 = { "65c02", CPU_CMOS, + "Rockwell 65C02", + opc_cmos, (sizeof(opc_cmos) / sizeof(opcode_t)), + t_error, t_instr, t_instr_ok +}; + +const target_t t_w65c02 = { + "w65c02", CPU_CMOS | CPU_WDC, + "WDC 65C02", opc_cmos, (sizeof(opc_cmos) / sizeof(opcode_t)), t_error, t_instr, t_instr_ok }; diff --git a/src/version.h b/src/version.h index 19a4175..8365753 100644 --- a/src/version.h +++ b/src/version.h @@ -8,7 +8,7 @@ * * Define application version and build info. * - * Version: @(#)version.h 1.0.5 2023/05/13 + * Version: @(#)version.h 1.0.5 2023/05/14 * * Author: Fred N. van Kempen, * @@ -55,7 +55,7 @@ /* Version info. */ #define APP_VER_MAJOR 1 #define APP_VER_MINOR 0 -#define APP_VER_REV 13 +#define APP_VER_REV 14 #define APP_VER_PATCH 0 diff --git a/src/win/varcem.ico b/src/win/varcem.ico index 97f7f17..db2916e 100644 Binary files a/src/win/varcem.ico and b/src/win/varcem.ico differ