From dac50eca5b26ee6c8e8d3adfb4068655c76e933d Mon Sep 17 00:00:00 2001 From: waltje Date: Sun, 14 May 2023 03:13:06 -0400 Subject: [PATCH] See new changes in CHANGELOG. Added several backends for targets. Fixed many things (and broke a few new ones ;-) Imported the REPEAT..ENDREP from upstream. Most directives can now also be used as pseudo's, because a lot of old source uses that. Added support for the TCC compiler. --- CHANGELOG | 24 +-- src/error.c | 84 ++++++----- src/error.h | 6 +- src/global.h | 27 +++- src/list.c | 51 +++++-- src/main.c | 4 +- src/output.c | 18 ++- src/parse.c | 84 ++++++++--- src/pseudo.c | 264 ++++++++++++++++++++++++--------- src/symbol.c | 19 ++- src/target.c | 49 +++++- src/targets/mos6502.c | 45 +++--- src/unix/Makefile.GCC | 61 +++++++- src/unix/Makefile.TCC | 329 ++++++++++++++++++++++++++++++++++++++++ src/version.h | 4 +- src/win/Makefile.MSVC | 61 +++++++- src/win/Makefile.MinGW | 61 +++++++- src/win/Makefile.TCC | 330 +++++++++++++++++++++++++++++++++++++++++ 18 files changed, 1321 insertions(+), 200 deletions(-) create mode 100644 src/unix/Makefile.TCC create mode 100644 src/win/Makefile.TCC diff --git a/CHANGELOG b/CHANGELOG index 49f9527..52ba966 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,7 +17,7 @@ + add generating .s19 et al (Motorola) files for output + move the processor-specific errors to the backend. + implement multiple source files on command line -+ Reading raw source data. ++ reading raw source data. We currently perform binary-mode reads on the input source files and all included files. Although this works fine on Linux (and, assumedly, on all such systems), it does not seem to behave the same way on Windows systems. @@ -71,13 +71,15 @@ + Implement the .ifn directive. + Implement the [!b] and [!w] (forced cast) modifiers. + Implement the ?: operator for providing a default in case of undef variable. -+ implement loginal AND (&&) and OR (||) operators ++ implement logical AND (&&) and OR (||) operators + parentheses (precedence levels within an expression) ? + documented code in expr.c to clarify operators - ++ The basic infrastructure for multi-CPU support is now in place; we can + start adding more processors and their (sub-)models in the backend files. +- Add C02/RC02/WC02/816, 68xx, 80xx et al support. ++ Added MC6800,MC6805,MC6809,MC6811,CDP1802,SCN2650 targets. - We now support byte, word and doubleword values. However, are we consistent in checking these types within the symbols, labels and expressions? - - Filling, ORG and hex files. We currently allow for filling spaces and auto-filling the .org directive for use with straight-binary output files. This is, however, not necessary @@ -86,14 +88,16 @@ implemented properly, we will have to re-work the "generating output" code to do it as it goes (in pass 2), and not only at the end of that pass. This allows such "jumping" to be handled by those file formats. - - fix the sub-relative include path If one includes a "../foo/bar/bla.inc" file, and then that file also does an include of, say, "xxx.inc", then that file is considered "local" to its parent. So, we should check for that. - - add include search paths using system path and/or -I option? - -- Add C02/RC02/WC02/816, 68xx, 80xx et al support. - The basic infrastructure for multi-CPU support is now in place; we can - start adding more processors and their (sub-)models in the backend files. ++ implement all directives as pseudo's (i.e. make the . optional), many old + sources need this. ++ OOps.. END was not really stopping the parser from processing input! +- implement the '0xxH' notation for hex values. +- implement the H'xx' notation for hex values. ++ implement the 'stitle' and 'subttl' directives. ++ imported the REPEAT and ENDREP directives from upstream. +/ implement the 'width' directive and, maybe, line folding? diff --git a/src/error.c b/src/error.c index 1a34ec5..9435c41 100644 --- a/src/error.c +++ b/src/error.c @@ -8,7 +8,7 @@ * * Handle any errors. * - * Version: @(#)error.c 1.0.1 2023/04/26 + * Version: @(#)error.c 1.0.3 2023/05/13 * * Authors: Fred N. van Kempen, * Bernd B”ckmann, @@ -65,45 +65,49 @@ int errors; jmp_buf error_jmp; char error_hint[128]; const char *err_msgs[ERR_MAXERR] = { - "no error", - "fatal", - "division by zero detected", - "processor type not set", - "unknown processor type", - "out of memory", - "assert failed", - "unknown directive", - "unknown instruction", - "value expected", - "invalid format specifier", - "error in expression", - "incomplete operator", - "unbalanced parentheses", - "identifier expected", - "identifier length exceeded", - "illegal statement", - "end of line expected", - "illegal redefinition", - "IF nesting too deep", - "ELSE without IF", - "ENDIF without IF", - "symbol already defined as label", - "missing closing brace", - "undefined value", - "illegal type", - "string not terminated", - "character constant not terminated", - "value out of range", - "byte value out of range", - "word value out of range", - "illegal redefinition of local label", - "local label definition requires previous global label", - "malformed character constant", - "string too long", - "string expected", - "can not open file", - "maximum number of include files reached", - "file format not enabled" + "no error", + "fatal", + "division by zero detected", + "processor type not set", + "unknown processor type", + "out of memory", + "assert failed", + "unknown directive", + "unknown instruction", + "value expected", + "invalid format specifier", + "error in expression", + "incomplete operator", + "unbalanced parentheses", + "label required", + "identifier expected", + "identifier length exceeded", + "illegal statement", + "end of line expected", + "illegal redefinition", + "IF nesting too deep", + "ELSE without IF", + "ENDIF without IF", + "too many REPEAT levels", + "ENDREP without REPEAT", + "REPEAT without ENDREP", + "symbol already defined as label", + "missing closing brace", + "undefined value", + "illegal type", + "string not terminated", + "character constant not terminated", + "value out of range", + "byte value out of range", + "word value out of range", + "illegal redefinition of local label", + "local label definition requires previous global label", + "malformed character constant", + "string too long", + "string expected", + "can not open file", + "maximum number of include files reached", + "file format not enabled" }; diff --git a/src/error.h b/src/error.h index ad60555..056a2c1 100644 --- a/src/error.h +++ b/src/error.h @@ -8,7 +8,7 @@ * * Define the error codes. * - * Version: @(#)error.h 1.0.1 2023/04/26 + * Version: @(#)error.h 1.0.2 2023/05/13 * * Author: Fred N. van Kempen, * @@ -62,6 +62,7 @@ typedef enum errors_e { ERR_EXPR, // "error in expression" ERR_OPER, // "incomplete operator" ERR_UNBALANCED, // "unbalanced parentheses" + ERR_LABEL, // "label required" ERR_ID, // "identifier expected" ERR_IDLEN, // "identifier length exceeded" ERR_STMT, // "illegal statement" @@ -70,6 +71,9 @@ typedef enum errors_e { ERR_IF, // "IF nesting too deep" ERR_ELSE, // "ELSE without IF" ERR_ENDIF, // "ENDIF without IF" + ERR_MAX_REP, // "too many REPEAT levels" + ERR_REPEAT, // "ENDREP without REPEAT" + ERR_ENDREP, // "REPEAT without ENDREP" ERR_LBLREDEF, // "symbol already defined as label" ERR_CLBR, // "missing closing brace" ERR_UNDEF, // "undefined value" diff --git a/src/global.h b/src/global.h index 24ab4d5..9f5397c 100644 --- a/src/global.h +++ b/src/global.h @@ -8,7 +8,7 @@ * * Definitions for the entire application. * - * Version: @(#)global.h 1.0.8 2023/04/26 + * Version: @(#)global.h 1.0.9 2023/05/13 * * Author: Fred N. van Kempen, * @@ -69,6 +69,7 @@ #define MAX_FILENAMES 256 + 1 // maximum include files #define MAX_IFLEVEL 16 // maximum depth of IF levels +#define MAX_RPTLEVEL 8 // maximum depth of REPEAT levels #define RADIX_DEFAULT 10 // default radix is decimal #define ID_LEN 32 // max #characters in identifiers @@ -127,6 +128,13 @@ typedef struct sym_ { struct pseudo; +typedef struct repeat_info { + int file; + int line; + char *pos; + unsigned count; +} repeat_t; + /* Global variables. */ extern int opt_d, @@ -140,7 +148,8 @@ extern char myname[], extern uint16_t pc; extern int line, - newline; + newline, + found_end; extern symbol_t *current_label; extern int8_t org_done; extern int8_t radix; @@ -148,6 +157,10 @@ extern int iflevel, ifstate, newifstate, ifstack[]; +extern int rptlevel, + rptstate, + newrptstate; +extern repeat_t rptstack[]; extern char *filenames[]; extern int filelines[]; extern int filenames_idx, @@ -191,8 +204,8 @@ extern char sym_type(const symbol_t *); extern symbol_t *sym_lookup(const char *, symbol_t **); extern void sym_free(symbol_t **); extern symbol_t *sym_aquire(const char *, symbol_t **); -extern symbol_t *define_label(const char *, uint16_t, symbol_t *); -extern void define_variable(const char *, value_t); +extern symbol_t *define_label(const char *, uint16_t, symbol_t *, int); +extern void define_variable(const char *, value_t, int); extern value_t expr(char **); extern value_t to_byte(value_t, int); @@ -213,19 +226,21 @@ extern void emit_addr(uint32_t); extern int emit_str(const char *, int, int); extern int emit_byte(uint8_t, int); extern int emit_word(uint16_t, int); +extern int emit_word_be(uint16_t, int); extern int emit_dword(uint32_t, int); extern int save_code(const char *, const uint8_t *, int); extern void list_set_head(const char *); +extern void list_set_head_sub(const char *); extern void list_set_syms(int); extern int list_init(const char *); extern void list_close(void); extern void list_line(const char *); -extern void list_page(const char *); +extern void list_page(const char *, const char *); extern void list_save(uint16_t, uint16_t); extern void list_symbols(void); -extern const struct pseudo *is_pseudo(const char *); +extern const struct pseudo *is_pseudo(const char *, int); extern char *pseudo(const struct pseudo *, char **, int); extern int set_cpu(const char *, int); diff --git a/src/list.c b/src/list.c index 2f4599f..55e8bc9 100644 --- a/src/list.c +++ b/src/list.c @@ -8,7 +8,7 @@ * * Handle the listfile output. * - * Version: @(#)list.c 1.0.4 2023/04/26 + * Version: @(#)list.c 1.0.5 2023/05/13 * * Author: Fred N. van Kempen, * @@ -70,21 +70,35 @@ static int list_lnr, list_pln; static uint16_t list_oc, list_pc; -static char *list_head; +static char *list_title; +static char *list_subttl; static FILE *list_file = NULL; static int list_syms = 0; void -list_set_head(const char *head) +list_set_head(const char *str) { - if (list_head != NULL) - free(list_head); - list_head = NULL; + if (list_title != NULL) + free(list_title); + list_title = NULL; /* .. and set the new one. */ - if (head != NULL) - list_head = strdup(head); + if (str != NULL) + list_title = strdup(str); +} + + +void +list_set_head_sub(const char *str) +{ + if (list_subttl != NULL) + free(list_subttl); + list_subttl = NULL; + + /* .. and set the new one. */ + if (str != NULL) + list_subttl = strdup(str); } @@ -108,7 +122,7 @@ list_set_syms(int syms) * with those default settings, we get to "keep" 60 lines. */ void -list_page(const char *head) +list_page(const char *head, const char *sub) { char buff[1024], page[256], date[64]; char *ptr = buff; @@ -120,7 +134,7 @@ list_page(const char *head) return; if (head == NULL) - head = list_head; + head = list_title; /* Initialize printer to condensed mode if width > 80. */ if (opt_P && list_pnr == 0 && list_pwidth > 80) { @@ -151,11 +165,16 @@ list_page(const char *head) sprintf(page, "File: %s", filenames[filenames_idx]); i = (head != NULL) ? strlen(head) : 0; + i += (sub != NULL) ? strlen(sub) + 3 : 0; skip = list_pwidth - (i + strlen(page)); ptr = buff; if (head != NULL) { sprintf(ptr, "%s", head); ptr += strlen(ptr); + if (sub != NULL) { + sprintf(ptr, " : %s", sub); + ptr += strlen(ptr); + } } while (skip--) *ptr++ = ' '; @@ -166,6 +185,7 @@ list_page(const char *head) list_pln = list_plength - (3 + 3); // margin + header } + /* * Generate one line of listing info. * @@ -184,7 +204,7 @@ list_line(const char *p) if (list_pln == 0) { /* Reset the page. */ - list_page(list_head); + list_page(list_title, list_subttl); } /* Output listing line number. */ @@ -242,7 +262,7 @@ list_symbols(void) /* If we are not using a listing file, dump to stdout. */ if (list_file != NULL) { - list_page("** SYMBOL TABLE **"); // new page + list_page("** SYMBOL TABLE **", NULL); // new page fp = list_file; // use listing file } else fp = stdout; // use stdout @@ -253,7 +273,7 @@ list_symbols(void) for (; sym; sym = sym->next) { if ((list_file != NULL) && (list_pln == 0)) - list_page("** SYMBOL TABLE **"); + list_page("** SYMBOL TABLE **", NULL); fprintf(fp, "%-32s %c ", sym->name, sym_type(sym)); if (DEFINED(sym->value)) { @@ -278,7 +298,7 @@ list_symbols(void) if ((list_syms == 2) && IS_LBL(sym)) { for (loc = sym->locals; loc; loc = loc->next) { if ((list_file != NULL) && (--list_pln == 0)) - list_page("** SYMBOL TABLE **"); + list_page("** SYMBOL TABLE **", NULL); fprintf(fp, " %c%-29s %c ", ALPHA_CHAR, loc->name, sym_type(sym)); @@ -329,7 +349,8 @@ list_init(const char *fn) list_lnr = 1; list_pnr = list_pln = 0; list_oc = list_pc = 0; - list_head = NULL; + list_title = NULL; + list_subttl = NULL; return 1; } diff --git a/src/main.c b/src/main.c index d8771d0..b4359e9 100644 --- a/src/main.c +++ b/src/main.c @@ -10,7 +10,7 @@ * * Usage: vasm [-dCFqsvPV] [-p processor] [-l fn] [-o fn] [-Dsym[=val]] file ... * - * Version: @(#)main.c 1.0.7 2023/04/23 + * Version: @(#)main.c 1.0.8 2023/05/12 * * Authors: Fred N. van Kempen, * Bernd B”ckmann, @@ -104,7 +104,7 @@ nodata: SET_TYPE(v, TYPE_BYTE); } - define_variable(id, v); + define_variable(id, v, 0); } diff --git a/src/output.c b/src/output.c index bafc4c7..3f4a5ec 100644 --- a/src/output.c +++ b/src/output.c @@ -16,7 +16,7 @@ * for the proper use of the ".org" directive, as this then * merely changes the 'load address' of the following bytes. * - * Version: @(#)output.c 1.0.4 2023/04/26 + * Version: @(#)output.c 1.0.5 2023/05/12 * * Authors: Fred N. van Kempen, * Bernd B”ckmann, @@ -128,6 +128,22 @@ emit_word(uint16_t w, int pass) } +/* Copy a single word (BE) to the output. */ +int +emit_word_be(uint16_t w, int pass) +{ + if (pass == 2) { + /* We use big-endian format here. */ + code[oc] = w >> 8; + code[oc + 1] = w & 0xff; + } + + oc += 2; + + return 2; +} + + /* Copy a single double-word to the output. */ int emit_dword(uint32_t w, int pass) diff --git a/src/parse.c b/src/parse.c index 6373931..f17f37b 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.7 2023/04/26 + * Version: @(#)parse.c 1.0.8 2023/05/13 * * Authors: Fred N. van Kempen, * Bernd B”ckmann, @@ -59,20 +59,24 @@ int line, // currently processed line number - newline; // next line to be processed + newline, // next line to be processed + found_end; // END directive was found symbol_t *current_label = NULL; // search scope for local labels int8_t org_done; // has a .org been performed? int8_t radix; // current numerical radix int iflevel, // current level of conditionals ifstate, newifstate, // current conditional state ifstack[MAX_IFLEVEL]; +int rptlevel, + rptstate, newrptstate; +repeat_t rptstack[MAX_RPTLEVEL]; /* program counter and output counter may not be in sync */ /* this happens if an .org directive is used, which modifies the */ /* program counter but not the output counter. */ -uint16_t pc = 0; // addr of currently assembled instr -uint16_t oc = 0; // counter of emitted output bytes -uint16_t sa = 0; // start addr for generated code (.end) +uint16_t pc = 0; // addr of currently assembled instr +uint16_t oc = 0; // counter of emitted output bytes +uint16_t sa = 0; // start addr for generated code (.end) #ifdef _DEBUG @@ -249,19 +253,21 @@ statement(char **p, int pass) ident(p, id); skip_white(p); - if ((**p == EQUAL_CHAR) || !strncmp(*p, "EQU", 3)) { - /* Variable definition. */ - if (**p == EQUAL_CHAR) - (*p)++; - else - (*p) += 3; + if (**p == EQUAL_CHAR) { + (*p)++; v = expr(p); if (ifstate) - define_variable(id, v); + define_variable(id, v, 0); return NULL; } else if ((**p == COLON_CHAR) || !trg_instr_ok(id)) { + if ((ptr = is_pseudo(id, 0)) != NULL) { + /* All good, we're a pseudo-op. */ + newp = pseudo(ptr, p, pass); + return newp; + } + /* * Labels either have a colon at the end, OR are anything * but an valid instruction. To force a label with the same @@ -271,7 +277,7 @@ statement(char **p, int pass) (*p)++; if (ifstate) - current_label = define_label(id, pc, NULL); + current_label = define_label(id, pc, NULL, 1); skip_white_and_comment(p); if (IS_END(**p)) @@ -289,7 +295,7 @@ statement(char **p, int pass) if (current_label == NULL) error(ERR_NO_GLOBAL, NULL); - define_label(id, pc, current_label); + define_label(id, pc, current_label, 0); } skip_white(p); @@ -309,7 +315,7 @@ again: pt = *p; (*p)++; nident_upcase(p, id); - if ((ptr = is_pseudo(id)) != NULL) { + if ((ptr = is_pseudo(id, 1)) != NULL) { /* All good, we're a directive. */ newp = pseudo(ptr, p, pass); @@ -333,7 +339,7 @@ again: strcpy(id, current_label->name); strcat(id, id2); - define_label(id, pc, NULL); + define_label(id, pc, NULL, 0); } skip_white_and_comment(p); @@ -344,6 +350,18 @@ again: goto again; } + /* Check if this is a pseudo (directive without the dot.) */ + pt = *p; + nident_upcase(p, id); + if ((ptr = is_pseudo(id, 0)) != NULL) { + /* All good, we're a directive. */ + skip_white(p); + newp = pseudo(ptr, p, pass); + + return newp; + } + *p = pt; + skip_white_and_comment(p); if (IS_END(**p)) return NULL; @@ -374,6 +392,7 @@ pass(char **p, int pass) int err; errors = 0; + found_end = 0; line = 1; current_label = NULL; org_done = 0; @@ -383,16 +402,22 @@ pass(char **p, int pass) iflevel = 0; ifstate = 1; memset(ifstack, 0x00, sizeof(ifstack)); + rptlevel = 0; + rptstate = 0; + memset(rptstack, 0x00, sizeof(rptstack)); list_set_head(NULL); if ((err = setjmp(error_jmp)) == 0) { - while (**p) { + while (p && **p) { /* Save current line position for the listing. */ list = *p; - newline = line + 1; + if (! rptstate) + newline = line + 1; + newifstate = ifstate; + newrptstate = rptstate; newp = statement(p, pass); @@ -407,23 +432,44 @@ pass(char **p, int pass) skip_eol(p); - if (pass == 2) + if ((pass == 2) && ((rptlevel == 0) || rptstate)) list_line(list); line = newline; ifstate = newifstate; + rptstate = newrptstate; if (**p == EOF_CHAR) { (*p)++; +next_file: filenames_idx++; line = filelines[filenames_idx]; } + if (found_end) { + found_end = 0; + + /* If we are in an included file, go down a level. */ + if (filenames_idx > 0) + goto next_file; + + /* Otherwise, force to be done. */ + p = NULL; + } + if (newp != NULL) text = newp; list_save(pc, oc); } + + /* Make sure we have matched IF..ENDIF at the end. */ + if (iflevel > 0) + error(ERR_ENDIF, "** end of input**"); + + /* Make sure we have matched REPEAT..ENDREP at the end. */ + if (rptlevel > 0) + error(ERR_ENDREP, "** end of input**"); } else { if (err < ERR_MAXERR) msg = err_msgs[err]; diff --git a/src/pseudo.c b/src/pseudo.c index 284e3a1..24c0bdf 100644 --- a/src/pseudo.c +++ b/src/pseudo.c @@ -8,7 +8,7 @@ * * Handle directives and pseudo-ops. * - * Version: @(#)pseudo.c 1.0.4 2023/04/26 + * Version: @(#)pseudo.c 1.0.5 2023/05/12 * * Authors: Fred N. van Kempen, * Bernd B”ckmann, @@ -47,6 +47,7 @@ #include #include #include +#include #include "global.h" #include "error.h" @@ -54,6 +55,7 @@ typedef struct pseudo { const char *name; int always; + int dotted; char *(*func)(char **, int); void *lister; } pseudo_t; @@ -345,7 +347,7 @@ nodata: SET_TYPE(v, TYPE_BYTE); } - define_variable(id, v); + define_variable(id, v, 0); return NULL; } @@ -464,6 +466,19 @@ do_end(char **p, int pass) sa = v.v; } + /* + * Historically, this was to signal an assembler to stop parsing + * input and just read until end of tape (so the tape reel or card + * deck could be removed.) We do similar, we just "eat" any more + * input until we hit the end of this "file". + */ + do { + if (**p) + (*p)++; + } while (**p && **p != EOF_CHAR); + + found_end = 1; + return NULL; } @@ -486,6 +501,27 @@ do_endif(char **p, int pass) } +/* Perform the ".endrep" directive. */ +static char * +do_endrep(char **p, int pass) +{ + if (rptlevel == 0 || rptstack[rptlevel - 1].file != filenames_idx) + error(ERR_REPEAT, NULL); + + if (rptstack[rptlevel - 1].count > 1) { + *p = rptstack[rptlevel - 1].pos; + line = rptstack[rptlevel - 1].line; + rptstack[rptlevel - 1].count--; + } else + rptlevel--; + + rptstate = 0; + newrptstate = (rptstack[rptlevel - 1].count > 0); + + return NULL; +} + + /* The ".error " directive. */ static char * do_error(char **p, int pass) @@ -506,14 +542,15 @@ do_error(char **p, int pass) static char * do_equ(char **p, int pass) { - char id[ID_LEN]; value_t v; - ident(p, id); + if (current_label == NULL) + error(ERR_LABEL, NULL); v = expr(p); - define_variable(id, v); + /* (Re-)define this label as a variable. */ + define_variable(current_label->name, v, 1); return NULL; } @@ -846,7 +883,7 @@ do_page(char **p, int pass) skip_white_and_comment(p); if (IS_END(**p)) { /* This was just a .page to start a new page. */ - list_page(NULL); + list_page(NULL, NULL); return NULL; } @@ -922,6 +959,57 @@ do_radix(char **p, int pass) } +/* Perform the ".repeat expr" directive. */ +static char * +do_repeat(char **p, int pass) +{ + value_t v; + char *pt; + + if (rptlevel == MAX_RPTLEVEL) + error(ERR_MAX_REP, NULL); + + skip_white(p); + v = expr(p); + if ((pass == 2) && UNDEFINED(v)) + error(ERR_UNDEF, NULL); + + /* Find next line to continue by .ENDREP. */ + pt = *p; + skip_white_and_comment(p); + + rptstack[rptlevel].count = v.v; + rptstack[rptlevel].line = line + 1; + rptstack[rptlevel].pos = *p; + rptstack[rptlevel].file = filenames_idx; + rptlevel++; + + newrptstate = (rptstack[rptlevel - 1].count > 0); + rptstate = newrptstate; + + *p = pt; + + return NULL; +} + + +/* The ".subttl " directive. */ +static char * +do_subttl(char **p, int pass) +{ + char buff[STR_LEN]; + + /* Read filename. */ + skip_white(p); + string_lit(p, buff, STR_LEN, 0); + + /* Free any current sub-heading. */ + list_set_head_sub(buff); + + return NULL; +} + + /* The ".syms [off|on|full]" directive. */ static char * do_syms(char **p, int pass) @@ -966,6 +1054,48 @@ do_title(char **p, int pass) } +/* The ".warn " directive. */ +static char * +do_warn(char **p, int pass) +{ + char buff[STR_LEN * 4]; + char *str = *p; + + skip_white(p); + string_lit(p, buff, STR_LEN * 4, 0); + + if (pass == 2) + printf("*** WARNING: "); + + *p = str; + do_echo(p, pass); + + return NULL; +} + + +/* The ".width " directive. */ +static char * +do_width(char **p, int pass) +{ + value_t v; + + skip_white_and_comment(p); + if (IS_EOL(**p)) + error(ERR_EOL, NULL); + + /* Get the number of characters per line. */ + v = expr(p); + if ((pass == 2) && UNDEFINED(v)) + error(ERR_UNDEF, NULL); + + /* Set the new number of characters per line. */ + list_pwidth = (int)v.v; + + return NULL; +} + + /* The ".word [,,...]" directive. */ static char * do_word(char **p, int pass) @@ -994,79 +1124,77 @@ do_word(char **p, int pass) } -/* The ".warn " directive. */ -static char * -do_warn(char **p, int pass) -{ - char buff[STR_LEN * 4]; - char *str = *p; - - skip_white(p); - string_lit(p, buff, STR_LEN * 4, 0); - - if (pass == 2) - printf("*** WARNING: "); - - *p = str; - do_echo(p, pass); - - return NULL; -} - - static const pseudo_t pseudos[] = { - { "ALIGN", 0, do_align, NULL }, - { "ASCII", 0, do_byte, NULL }, - { "ASCIIZ", 0, do_asciz, NULL }, - { "ASCIZ", 0, do_asciz, NULL }, - { "ASSERT", 0, do_assert, NULL }, - { "BINARY", 0, do_blob, NULL }, - { "BLOB", 0, do_blob, NULL }, - { "BYTE", 0, do_byte, NULL }, - { "CPU", 0, do_cpu, NULL }, - { "DATA", 0, do_byte, NULL }, - { "DB", 0, do_byte, NULL }, - { "DEFINE", 0, do_define, NULL }, - { "DL", 0, do_dword, NULL }, - { "DW", 0, do_word, NULL }, - { "DWORD", 0, do_dword, NULL }, - { "ECHO", 0, do_echo, NULL }, - { "ELSE", 1, do_else, NULL }, - { "END", 0, do_end, NULL }, - { "ENDIF", 1, do_endif, NULL }, - { "EQU", 0, do_equ, NULL }, - { "ERROR", 0, do_error, NULL }, - { "FI", 1, do_endif, NULL }, - { "FILL", 0, do_fill, NULL }, - { "IF", 1, do_if, NULL }, - { "IFDEF", 1, do_ifdef, NULL }, - { "IFN", 1, do_ifn, NULL }, - { "IFNDEF", 1, do_ifndef, NULL }, - { "INCLUDE", 0, do_include, NULL }, - { "ORG", 0, do_org, NULL }, - { "PAGE", 0, do_page, NULL }, - { "RADIX", 0, do_radix, NULL }, - { "RADX", 0, do_radix, NULL }, - { "STR", 0, do_byte, NULL }, - { "STRING", 0, do_byte, NULL }, - { "SYM", 0, do_syms, NULL }, - { "SYMS", 0, do_syms, NULL }, - { "TITLE", 0, do_title, NULL }, - { "WARN", 0, do_warn, NULL }, - { "WORD", 0, do_word, NULL }, - { NULL } + { "ALIGN", 0, 0, do_align, NULL }, + { "ASCII", 0, 1, do_byte, NULL }, + { "ASCIIZ", 0, 1, do_asciz, NULL }, + { "ASCIZ", 0, 1, do_asciz, NULL }, + { "ASSERT", 0, 1, do_assert, NULL }, + { "BINARY", 0, 1, do_blob, NULL }, + { "BLOB", 0, 1, do_blob, NULL }, + { "BYTE", 0, 0, do_byte, NULL }, + { "CPU", 0, 1, do_cpu, NULL }, + { "DATA", 0, 1, do_byte, NULL }, + { "DB", 0, 0, do_byte, NULL }, + { "DEFINE", 0, 0, do_define, NULL }, + { "DL", 0, 0, do_dword, NULL }, + { "DW", 0, 0, do_word, NULL }, + { "DWORD", 0, 0, do_dword, NULL }, + { "ECHO", 0, 1, do_echo, NULL }, + { "ELSE", 1, 0, do_else, NULL }, + { "END", 0, 0, do_end, NULL }, + { "ENDIF", 1, 0, do_endif, NULL }, + { "ENDREP", 1, 0, do_endrep, NULL }, + { "EQU", 0, 0, do_equ, NULL }, + { "ERROR", 0, 1, do_error, NULL }, + { "FI", 1, 0, do_endif, NULL }, + { "FILL", 0, 1, do_fill, NULL }, + { "IF", 1, 0, do_if, NULL }, + { "IFDEF", 1, 0, do_ifdef, NULL }, + { "IFN", 1, 0, do_ifn, NULL }, + { "IFNDEF", 1, 0, do_ifndef, NULL }, + { "INCLUDE", 0, 0, do_include, NULL }, + { "ORG", 0, 0, do_org, NULL }, + { "PAGE", 0, 0, do_page, NULL }, + { "RADIX", 0, 0, do_radix, NULL }, + { "RADX", 0, 0, do_radix, NULL }, + { "REPEAT", 0, 0, do_repeat, NULL }, + { "SBTTL", 0, 0, do_subttl, NULL }, + { "STITLE", 0, 0, do_subttl, NULL }, + { "STR", 0, 1, do_byte, NULL }, + { "STRING", 0, 1, do_byte, NULL }, + { "SUBTTL", 0, 0, do_subttl, NULL }, + { "SYM", 0, 0, do_syms, NULL }, + { "SYMS", 0, 0, do_syms, NULL }, + { "TITLE", 0, 0, do_title, NULL }, + { "WARN", 0, 1, do_warn, NULL }, + { "WIDTH", 0, 0, do_width, NULL }, + { "WORD", 0, 0, do_word, NULL }, + { NULL } }; const pseudo_t * -is_pseudo(const char *name) +is_pseudo(const char *name, int dot) { + char id[ID_LEN], *p; const pseudo_t *ptr; int i; + /* Convert the mnemonic to uppercase. */ + p = id; + while (*name != '\0') + *p++ = (char)toupper(*name++); + *p = '\0'; + for (ptr = pseudos; ptr->name != NULL; ptr++) { - if ((i = strcmp(ptr->name, name)) == 0) + if ((i = strcmp(ptr->name, id)) == 0) { + if (ptr->dotted && !dot) + break; + return ptr; + } + if (i > 0) break; } diff --git a/src/symbol.c b/src/symbol.c index 8e68176..03d65b7 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -8,7 +8,7 @@ * * Handle symbols. * - * Version: @(#)symbol.c 1.0.4 2023/04/26 + * Version: @(#)symbol.c 1.0.5 2023/05/12 * * Authors: Fred N. van Kempen, * Bernd B”ckmann, @@ -168,7 +168,7 @@ sym_aquire(const char *name, symbol_t **table) symbol_t * -define_label(const char *id, uint16_t v, symbol_t *parent) +define_label(const char *id, uint16_t v, symbol_t *parent, int force) { char nid[ID_LEN]; symbol_t *sym; @@ -190,8 +190,10 @@ define_label(const char *id, uint16_t v, symbol_t *parent) } else sym = sym_aquire(id, NULL); - if (IS_VAR(sym) || (DEFINED(sym->value) && (sym->value.v != v))) - error(parent ? ERR_LOCAL_REDEF : ERR_REDEF, id); + if (! force) { + if (IS_VAR(sym) || (DEFINED(sym->value) && (sym->value.v != v))) + error(parent ? ERR_LOCAL_REDEF : ERR_REDEF, id); + } sym->kind = KIND_LBL; sym->filenr = filenames_idx; @@ -205,12 +207,12 @@ define_label(const char *id, uint16_t v, symbol_t *parent) void -define_variable(const char *id, value_t v) +define_variable(const char *id, value_t v, int force) { symbol_t *sym; sym = sym_aquire(id, NULL); - if (DEFINED(sym->value) && (sym->value.v != v.v)) + if (!force && DEFINED(sym->value) && (sym->value.v != v.v)) error(ERR_REDEF, id); sym->kind = KIND_VAR; @@ -219,7 +221,7 @@ define_variable(const char *id, value_t v) /* if the type is already set do not change it */ sym->value.v = v.v; - if (TYPE(sym->value)) { + if (!force && TYPE(sym->value)) { #if 0 if (NUM_TYPE(v.v) > TYPE(sym->value)) error(ERR_REDEF, id); #endif @@ -228,9 +230,12 @@ define_variable(const char *id, value_t v) } else sym->value.t = v.t; +#if 0 +//FIXME: we were set to KIND_VAR above..? /* If previously defined as label make it word sized. */ if (IS_LBL(sym)) SET_TYPE(sym->value, TYPE_WORD); +#endif } diff --git a/src/target.c b/src/target.c index 2863098..254b0a5 100644 --- a/src/target.c +++ b/src/target.c @@ -8,7 +8,7 @@ * * Handle selection of a target device. * - * Version: @(#)target.c 1.0.2 2023/04/26 + * Version: @(#)target.c 1.0.3 2023/05/13 * * Author: Fred N. van Kempen, * @@ -59,6 +59,17 @@ extern const target_t t_6502_old, t_csg8500, t_65c02; +extern const target_t t_6800; +extern const target_t t_6805; +extern const target_t t_6809; +extern const target_t t_6811; + +extern const target_t t_1802; + +extern const target_t t_2650, + t_2650a, + t_2650b; + static const target_t *targets[] = { &t_6502_old, // original MOS6502 (NMOS) @@ -68,6 +79,32 @@ static const target_t *targets[] = { &t_65c02, // standard MOS65C02 (CMOS) +#ifdef USE_MC6800 + &t_6800, // MC6800/01/02 +#endif + +#ifdef USE_MC6805 + &t_6805, // MC68(HC)05 +#endif + +#ifdef USE_MC6809 + &t_6809, // MC6809 +#endif + +#ifdef USE_MC6811 + &t_6811, // MC68(HC)11 +#endif + +#ifdef USE_CDP1802 + &t_1802, // CDP1802 +#endif + +#ifdef USE_SCN2650 + &t_2650, // SCN2650 + &t_2650a, // SCN2650A + &t_2650b, // SCN2650B +#endif + NULL }; @@ -125,7 +162,7 @@ trg_symbol(const char *name) SET_DEFINED(v); SET_TYPE(v, TYPE_BYTE); - define_variable(id, v); + define_variable(id, v, 0); } @@ -174,8 +211,10 @@ trg_instr(char **p, int pass) int trg_instr_ok(const char *p) { - if (target == NULL) - error(ERR_NOCPU, NULL); + int ret = 0; - return target->instr_ok(target, p); + if (target != NULL) + ret = target->instr_ok(target, p); + + return ret; } diff --git a/src/targets/mos6502.c b/src/targets/mos6502.c index 1b38917..40ac9ae 100644 --- a/src/targets/mos6502.c +++ b/src/targets/mos6502.c @@ -20,27 +20,36 @@ * Bernd B”ckmann, * * Copyright 2023 Fred N. van Kempen. - * Copyright 2022,2023 Bernd B”ckmann. * - * MIT License Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following - * condition: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include diff --git a/src/unix/Makefile.GCC b/src/unix/Makefile.GCC index 200c97a..279562b 100644 --- a/src/unix/Makefile.GCC +++ b/src/unix/Makefile.GCC @@ -8,7 +8,7 @@ # # Makefile for UNIX-like systems using the GCC environment. # -# Version: @(#)Makefile.GCC 1.1.0 2023/04/26 +# Version: @(#)Makefile.GCC 1.1.0 2023/05/13 # # Author: Fred N. van Kempen, # @@ -67,6 +67,63 @@ IHEX := $(VARCEM)/contrib/Ihex DEFS := -DALLOW_UNDEFINED_IF +ifndef MOS6502 + MOS6502 := y +endif +ifeq ($(MOS6502), y) + DEFS += -DUSE_MOS6502 + TARGETS += mos6502.o +endif + +ifndef MC6800 + MC6800 := n +endif +ifeq ($(MC6800), y) + DEFS += -DUSE_MC6800 + TARGETS += mc6800.o +endif + +ifndef MC6805 + MC6805 := n +endif +ifeq ($(MC6805), y) + DEFS += -DUSE_MC6805 + TARGETS += mc6805.o +endif + +ifndef MC6809 + MC6809 := n +endif +ifeq ($(MC6809), y) + DEFS += -DUSE_MC6809 + TARGETS += mc6809.o +endif + +ifndef MC6811 + MC6811 := n +endif +ifeq ($(MC6811), y) + DEFS += -DUSE_MC6811 + TARGETS += mc6811.o +endif + +ifndef CDP1802 + CDP1802 := n +endif +ifeq ($(CDP1802), y) + DEFS += -DUSE_CDP1802 + TARGETS += cdp1802.o +endif + +ifndef SCN2650 + SCN2650 := n +endif +ifeq ($(SCN2650), y) + DEFS += -DUSE_SCN2650 + TARGETS += scn2650.o +endif + + ######################################################################### # Nothing should need changing from here on.. # ######################################################################### @@ -213,7 +270,7 @@ OBJ := $(SYSOBJ) \ main.o error.o symbol.o expr.o func.o input.o \ output.o list.o parse.o pseudo.o \ target.o \ - mos6502.o + $(TARGETS) all: $(LIBS) $(PROG) diff --git a/src/unix/Makefile.TCC b/src/unix/Makefile.TCC new file mode 100644 index 0000000..6efb803 --- /dev/null +++ b/src/unix/Makefile.TCC @@ -0,0 +1,329 @@ +# +# VASM VARCem Multi-Target Assembler. +# A simple table-driven assembler for several 8-bit target +# devices, like the 6502, 6800, 80x, Z80 et al series. The +# code originated from Bernd B”ckmann's "asm6502" project. +# +# This file is part of the VARCem Project. +# +# Makefile for Windows systems using the TCC environment. +# +# Version: @(#)Makefile.TCC 1.1.0 2023/05/13 +# +# Author: Fred N. van Kempen, +# +# Copyright 2023 Fred N. van Kempen. +# +# Redistribution and use in source and binary forms, with +# or without modification, are permitted provided that the +# following conditions are met: +# +# 1. Redistributions of source code must retain the entire +# above notice, this list of conditions and the following +# disclaimer. +# +# 2. Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the +# following disclaimer in the documentation and/or other +# materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names +# of its contributors may be used to endorse or promote +# products derived from this software without specific +# prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +ifndef ARCH + ARCH := x86 +endif + +ifndef DEBUG + DEBUG := n +endif + + +# Where is the VARCem tree? +VARCEM := ../../../.. + +# Where is our Ihex support library? +IHEX := $(VARCEM)/contrib/Ihex + INCS += -I$(IHEX)/include -DUSE_IHEX=3 + LDIR += -L$(IHEX)/lib/$(ARCH) + LDLIBS += -lihex-tcc_s + + +DEFS := -DALLOW_UNDEFINED_IF + + +ifndef MOS6502 + MOS6502 := y +endif +ifeq ($(MOS6502), y) + DEFS += -DUSE_MOS6502 + TARGETS += mos6502.o +endif + +ifndef MC6800 + MC6800 := n +endif +ifeq ($(MC6800), y) + DEFS += -DUSE_MC6800 + TARGETS += mc6800.o +endif + +ifndef MC6805 + MC6805 := n +endif +ifeq ($(MC6805), y) + DEFS += -DUSE_MC6805 + TARGETS += mc6805.o +endif + +ifndef MC6809 + MC6809 := n +endif +ifeq ($(MC6809), y) + DEFS += -DUSE_MC6809 + TARGETS += mc6809.o +endif + +ifndef MC6811 + MC6811 := n +endif +ifeq ($(MC6811), y) + DEFS += -DUSE_MC6811 + TARGETS += mc6811.o +endif + +ifndef CDP1802 + CDP1802 := n +endif +ifeq ($(CDP1802), y) + DEFS += -DUSE_CDP1802 + TARGETS += cdp1802.o +endif + +ifndef SCN2650 + SCN2650 := n +endif +ifeq ($(SCN2650), y) + DEFS += -DUSE_SCN2650 + TARGETS += scn2650.o +endif + + +######################################################################### +# Nothing should need changing from here on.. # +######################################################################### + +# Definitions for this enivonment. +DEVENV := tcc +DEPS = -MMD -MF $*.d +DEPFILE := .depends-$(DEVENV) + + +# Compilation for X86. +ifeq ($(ARCH), x86) + TARGET := 32 + PREFIX := + RCTARGET := pe-i386 + + AFLAGS := -msse2 -mfpmath=sse + ifeq ($(OPTIM), y) + DFLAGS := -march=native + else + DFLAGS := -march=i686 + endif +endif + +# Compilation for X64. +ifeq ($(ARCH), x64) + TARGET := 64 -D__GNUC__ + PREFIX := + RCTARGET := pe-x86-64 + + ifeq ($(OPTIM), y) + DFLAGS := -march=native + endif +endif + +# Compilation for ARM. +ifeq ($(ARCH), armv7) + error Target ARM7 not supported for Windows ! +endif + +# Compilation for ARM64. +ifeq ($(ARCH), aarch64) + error Target ARM64 not supported for Windows ! +endif + + +# The various toolchain programs. +CC := tcc -m$(TARGET) +CXX := tcc -m$(TARGET) +CPP := cpp -P +LINK := tcc -m$(TARGET) +WINDRES := windres +AR := tcc-ar +RANLIB := echo +STRIP := echo +ifndef CAT + CAT := cat +endif + +# Set up the correct toolchain flags. +OPTS := -DARCH=$(ARCH) \ + -D_CRT_NON_CONFORMING_SWPRINTFS \ + -D__USE_MINGW_ANSI_STDIO_X +ifndef VCRUNTIME + # MinGW does not provide MD/MT yet. + VCRUNTIME := MD +endif +RCOPTS := --input-format=rc -O coff +ifdef RCTARGET + RCOPTS += --target=$(RCTARGET) +endif +RCOPTS += -D RC_INVOKED -o +AOPTS := r +LOPTS := -mconsole + +# General build options. +ifeq ($(DEBUG), y) + VCRUNTIME := $(VCRUNTIME)d + DFLAGS += -ggdb -D_DEBUG + RCOPTS := -D_DEBUG $(RCOPTS) + AOPTIM := + ifndef COPTIM + COPTIM := -Og + endif +else + ifeq ($(OPTIM), y) + AOPTIM := -mtune=native + ifndef COPTIM + COPTIM := -O3 + endif + else + ifndef COPTIM + COPTIM := -O3 + endif + endif +endif +OPTS += #/$(VCRUNTIME) +ifeq ($(PROFILER), y) + LOPTS += -Xlinker -Map=$(PROG).map +endif + + +# Final versions of the toolchain flags. +CFLAGS = $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) \ + $(AFLAGS) $(INCS) $(DEFS) \ + -mstackrealign \ + -fomit-frame-pointer -fno-strict-aliasing \ + -Wall -Wundef #-Wmissing-declarations +LDFLAGS := $(LOPTS) $(DFLAGS) $(LDIR) +ARFLAGS := $(AOPTS) +RCFLAGS = $(RCOPTS) + + +# Build module rules. +.SUFFIXES: .c .cpp .o .rc .res + +ifeq ($(AUTODEP), y) +%.o: %.c + @echo Compiling $< + @$(CC) $(CFLAGS) $(DEPS) -c $< +else +%.o: %.c + @echo Compiling $< + @$(CC) $(CFLAGS) -c $< + +%.d: %.c $(wildcard $*.d) + @echo Compiling $< + @$(CC) $(CFLAGS) $(DEPS) -E $< >NUL +endif + +# For systems that use these, compile a resource file. +.rc.res: $< + @echo Processing $< + @$(WINDRES) $(RCFLAGS) $@ $< + + +######################################################################### +# Nothing should need changing from here on.. # +######################################################################### + +# Final fixups. +INCS += -Iunix + +VPATH := unix targets . + +PROG := vasm +SYSOBJ := +OBJ := $(SYSOBJ) \ + main.o error.o symbol.o expr.o func.o input.o \ + output.o list.o parse.o pseudo.o \ + target.o \ + $(TARGETS) + + +all: $(PROG) + + +vasm: $(SYSOBJ) $(OBJ) + @echo Linking $@ .. + @$(LINK) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(LDLIBS) + $(if $(filter $(DEBUG),y),,@$(STRIP) $@) + + +clean: + @echo Cleaning objects.. + @-rm -f *.o + @-rm -f *.d + @echo Cleaning resources.. + @-rm -f *.res + + +clobber: clean + @echo Removing executables.. + @-rm -f $(PROG) + @echo Cleaning libraries.. + @-rm -f *.so + @-rm -f *.a +# @-rm -f $(DEPFILE) 2>NUL + +depclean: + @-rm -f $(DEPFILE) + @echo Creating dependencies.. + @echo # Run "make depends" to re-create this file. >$(DEPFILE) + +depends: DEPOBJ=$(OBJ:%.o=%.d) +depends: depclean $(DEPOBJ) + @$(CAT) $(DEPOBJ) >>$(DEPFILE) + @-del $(DEPOBJ) + +$(DEPFILE): + + +# Module dependencies. +ifeq ($(AUTODEP), y) +-include *.d +else + ifneq ($(wildcard $(DEPFILE)), ) + include $(wildcard $(DEPFILE)) + endif +endif + + +# End of Makefile.TCC. diff --git a/src/version.h b/src/version.h index 4ef1215..19a4175 100644 --- a/src/version.h +++ b/src/version.h @@ -8,7 +8,7 @@ * * Define application version and build info. * - * Version: @(#)version.h 1.0.4 2023/04/22 + * Version: @(#)version.h 1.0.5 2023/05/13 * * 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 12 +#define APP_VER_REV 13 #define APP_VER_PATCH 0 diff --git a/src/win/Makefile.MSVC b/src/win/Makefile.MSVC index 834a482..5d89e3c 100644 --- a/src/win/Makefile.MSVC +++ b/src/win/Makefile.MSVC @@ -8,7 +8,7 @@ # # Makefile for Windows using Visual Studio 2019. # -# Version: @(#)Makefile.MSVC 1.1.0 2023/04/26 +# Version: @(#)Makefile.MSVC 1.1.0 2023/05/13 # # Author: Fred N. van Kempen, # @@ -67,6 +67,63 @@ IHEX := $(VARCEM)/contrib/Ihex DEFS := -DALLOW_UNDEFINED_IF +ifndef MOS6502 + MOS6502 := y +endif +ifeq ($(MOS6502), y) + DEFS += -DUSE_MOS6502 + TARGETS += mos6502.obj +endif + +ifndef MC6800 + MC6800 := n +endif +ifeq ($(MC6800), y) + DEFS += -DUSE_MC6800 + TARGETS += mc6800.obj +endif + +ifndef MC6805 + MC6805 := n +endif +ifeq ($(MC6805), y) + DEFS += -DUSE_MC6805 + TARGETS += mc6805.obj +endif + +ifndef MC6809 + MC6809 := n +endif +ifeq ($(MC6809), y) + DEFS += -DUSE_MC6809 + TARGETS += mc6809.obj +endif + +ifndef MC6811 + MC6811 := n +endif +ifeq ($(MC6811), y) + DEFS += -DUSE_MC6811 + TARGETS += mc6811.obj +endif + +ifndef CDP1802 + CDP1802 := n +endif +ifeq ($(CDP1802), y) + DEFS += -DUSE_CDP1802 + TARGETS += cdp1802.obj +endif + +ifndef SCN2650 + SCN2650 := n +endif +ifeq ($(SCN2650), y) + DEFS += -DUSE_SCN2650 + TARGETS += scn2650.obj +endif + + ######################################################################### # Nothing should need changing from here on.. # ######################################################################### @@ -238,7 +295,7 @@ OBJ := $(SYSOBJ) \ main.obj error.obj symbol.obj expr.obj func.obj input.obj \ output.obj list.obj parse.obj pseudo.obj \ target.obj \ - mos6502.obj + $(TARGETS) LDLIBS += #advapi32.lib shell32.lib user32.lib kernel32.lib winmm.lib diff --git a/src/win/Makefile.MinGW b/src/win/Makefile.MinGW index fa0644f..eef8aae 100644 --- a/src/win/Makefile.MinGW +++ b/src/win/Makefile.MinGW @@ -8,7 +8,7 @@ # # Makefile for Windows systems using the MinGW-w64 environment. # -# Version: @(#)Makefile.MinGW 1.1.0 2023/04/26 +# Version: @(#)Makefile.MinGW 1.1.0 2023/05/13 # # Author: Fred N. van Kempen, # @@ -67,6 +67,63 @@ IHEX := $(VARCEM)/contrib/Ihex DEFS := -DALLOW_UNDEFINED_IF +ifndef MOS6502 + MOS6502 := y +endif +ifeq ($(MOS6502), y) + DEFS += -DUSE_MOS6502 + TARGETS += mos6502.o +endif + +ifndef MC6800 + MC6800 := n +endif +ifeq ($(MC6800), y) + DEFS += -DUSE_MC6800 + TARGETS += mc6800.o +endif + +ifndef MC6805 + MC6805 := n +endif +ifeq ($(MC6805), y) + DEFS += -DUSE_MC6805 + TARGETS += mc6805.o +endif + +ifndef MC6809 + MC6809 := n +endif +ifeq ($(MC6809), y) + DEFS += -DUSE_MC6809 + TARGETS += mc6809.o +endif + +ifndef MC6811 + MC6811 := n +endif +ifeq ($(MC6811), y) + DEFS += -DUSE_MC6811 + TARGETS += mc6811.o +endif + +ifndef CDP1802 + CDP1802 := n +endif +ifeq ($(CDP1802), y) + DEFS += -DUSE_CDP1802 + TARGETS += cdp1802.o +endif + +ifndef SCN2650 + SCN2650 := n +endif +ifeq ($(SCN2650), y) + DEFS += -DUSE_SCN2650 + TARGETS += scn2650.o +endif + + ######################################################################### # Nothing should need changing from here on.. # ######################################################################### @@ -221,7 +278,7 @@ OBJ := $(SYSOBJ) \ main.o error.o symbol.o expr.o func.o input.o \ output.o list.o parse.o pseudo.o \ target.o \ - mos6502.o + $(TARGETS) all: $(LIBS) $(PROG) diff --git a/src/win/Makefile.TCC b/src/win/Makefile.TCC new file mode 100644 index 0000000..5a9eda0 --- /dev/null +++ b/src/win/Makefile.TCC @@ -0,0 +1,330 @@ +# +# VASM VARCem Multi-Target Assembler. +# A simple table-driven assembler for several 8-bit target +# devices, like the 6502, 6800, 80x, Z80 et al series. The +# code originated from Bernd B”ckmann's "asm6502" project. +# +# This file is part of the VARCem Project. +# +# Makefile for Windows systems using the TCC environment. +# +# Version: @(#)Makefile.TCC 1.1.0 2023/05/13 +# +# Author: Fred N. van Kempen, +# +# Copyright 2023 Fred N. van Kempen. +# +# Redistribution and use in source and binary forms, with +# or without modification, are permitted provided that the +# following conditions are met: +# +# 1. Redistributions of source code must retain the entire +# above notice, this list of conditions and the following +# disclaimer. +# +# 2. Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the +# following disclaimer in the documentation and/or other +# materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names +# of its contributors may be used to endorse or promote +# products derived from this software without specific +# prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +ifndef ARCH + ARCH := x86 +endif + +ifndef DEBUG + DEBUG := n +endif + + +# Where is the VARCem tree? +VARCEM := ../../../.. + +# Where is our Ihex support library? +IHEX := $(VARCEM)/contrib/Ihex + INCS += -I$(IHEX)/include -DUSE_IHEX=3 + LDIR += -L$(IHEX)/lib/$(ARCH) + LDLIBS += -lihex-tcc_s + + +DEFS := -DALLOW_UNDEFINED_IF + + +ifndef MOS6502 + MOS6502 := y +endif +ifeq ($(MOS6502), y) + DEFS += -DUSE_MOS6502 + TARGETS += mos6502.o +endif + +ifndef MC6800 + MC6800 := n +endif +ifeq ($(MC6800), y) + DEFS += -DUSE_MC6800 + TARGETS += mc6800.o +endif + +ifndef MC6805 + MC6805 := n +endif +ifeq ($(MC6805), y) + DEFS += -DUSE_MC6805 + TARGETS += mc6805.o +endif + +ifndef MC6809 + MC6809 := n +endif +ifeq ($(MC6809), y) + DEFS += -DUSE_MC6809 + TARGETS += mc6809.o +endif + +ifndef MC6811 + MC6811 := n +endif +ifeq ($(MC6811), y) + DEFS += -DUSE_MC6811 + TARGETS += mc6811.o +endif + +ifndef CDP1802 + CDP1802 := n +endif +ifeq ($(CDP1802), y) + DEFS += -DUSE_CDP1802 + TARGETS += cdp1802.o +endif + +ifndef SCN2650 + SCN2650 := n +endif +ifeq ($(SCN2650), y) + DEFS += -DUSE_SCN2650 + TARGETS += scn2650.o +endif + + +######################################################################### +# Nothing should need changing from here on.. # +######################################################################### + +# Definitions for this enivonment. +DEVENV := tcc +DEPS = -MMD -MF $*.d +DEPFILE := .depends-$(DEVENV) + + +# Compilation for X86. +ifeq ($(ARCH), x86) + TARGET := 32 + PREFIX := + RCTARGET := pe-i386 + + AFLAGS := -msse2 -mfpmath=sse + ifeq ($(OPTIM), y) + DFLAGS := -march=native + else + DFLAGS := -march=i686 + endif +endif + +# Compilation for X64. +ifeq ($(ARCH), x64) + TARGET := 64 -D__GNUC__ + PREFIX := + RCTARGET := pe-x86-64 + + ifeq ($(OPTIM), y) + DFLAGS := -march=native + endif +endif + +# Compilation for ARM. +ifeq ($(ARCH), armv7) + error Target ARM7 not supported for Windows ! +endif + +# Compilation for ARM64. +ifeq ($(ARCH), aarch64) + error Target ARM64 not supported for Windows ! +endif + + +# The various toolchain programs. +CC := tcc -m$(TARGET) +CXX := tcc -m$(TARGET) +CPP := cpp -P +LINK := tcc -m$(TARGET) +WINDRES := windres +AR := tcc-ar +RANLIB := echo +STRIP := echo +ifndef CAT + CAT := cat +endif + +# Set up the correct toolchain flags. +OPTS := -DARCH=$(ARCH) \ + -D_CRT_NON_CONFORMING_SWPRINTFS \ + -D__USE_MINGW_ANSI_STDIO_X +ifndef VCRUNTIME + # MinGW does not provide MD/MT yet. + VCRUNTIME := MD +endif +RCOPTS := --input-format=rc -O coff +ifdef RCTARGET + RCOPTS += --target=$(RCTARGET) +endif +RCOPTS += -D RC_INVOKED -o +AOPTS := r +LOPTS := -mconsole + +# General build options. +ifeq ($(DEBUG), y) + VCRUNTIME := $(VCRUNTIME)d + DFLAGS += -ggdb -D_DEBUG + RCOPTS := -D_DEBUG $(RCOPTS) + AOPTIM := + ifndef COPTIM + COPTIM := -Og + endif +else + ifeq ($(OPTIM), y) + AOPTIM := -mtune=native + ifndef COPTIM + COPTIM := -O3 + endif + else + ifndef COPTIM + COPTIM := -O3 + endif + endif +endif +OPTS += #/$(VCRUNTIME) +ifeq ($(PROFILER), y) + LOPTS += -Xlinker -Map=$(PROG).map +endif + + +# Final versions of the toolchain flags. +CFLAGS = $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) \ + $(AFLAGS) $(INCS) $(DEFS) \ + -mstackrealign \ + -fomit-frame-pointer -fno-strict-aliasing \ + -Wall -Wundef #-Wmissing-declarations +LDFLAGS := $(LOPTS) $(DFLAGS) $(LDIR) +ARFLAGS := $(AOPTS) +RCFLAGS = $(RCOPTS) + + +# Build module rules. +.SUFFIXES: .c .cpp .o .rc .res + +ifeq ($(AUTODEP), y) +%.o: %.c + @echo Compiling $< + @$(CC) $(CFLAGS) $(DEPS) -c $< +else +%.o: %.c + @echo Compiling $< + @$(CC) $(CFLAGS) -c $< + +%.d: %.c $(wildcard $*.d) + @echo Compiling $< + @$(CC) $(CFLAGS) $(DEPS) -E $< >NUL +endif + +# For systems that use these, compile a resource file. +.rc.res: $< + @echo Processing $< + @$(WINDRES) $(RCFLAGS) $@ $< + + +######################################################################### +# Nothing should need changing from here on.. # +######################################################################### + +# Final fixups. +INCS += -Iwin + +VPATH := win targets . + +PROG := vasm.exe +SYSOBJ := vasm.res getopt.o +OBJ := $(SYSOBJ) \ + main.o error.o symbol.o expr.o func.o input.o \ + output.o list.o parse.o pseudo.o \ + target.o \ + $(TARGETS) + + +all: $(PROG) + + +vasm.exe: $(SYSOBJ) $(OBJ) + @echo Linking $@ .. + @$(LINK) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(LDLIBS) + $(if $(filter $(DEBUG),y),,@$(STRIP) $@) + + +clean: + @echo Cleaning objects.. + @-del *.o 2>NUL + @-del *.d 2>NUL + @echo Cleaning resources.. + @-del *.res 2>NUL + + +clobber: clean + @echo Removing executables.. + @-del *.exe 2>NUL + @echo Cleaning libraries.. + @-del *.dll 2>NUL + @-del *.a 2>NUL + @-del *.manifest 2>NUL +# @-del $(DEPFILE) 2>NUL + +depclean: + @-del $(DEPFILE) + @echo Creating dependencies.. + @echo # Run "make depends" to re-create this file. >$(DEPFILE) + +depends: DEPOBJ=$(OBJ:%.o=%.d) +depends: depclean $(DEPOBJ) + @$(CAT) $(DEPOBJ) >>$(DEPFILE) + @-del $(DEPOBJ) + +$(DEPFILE): + + +# Module dependencies. +ifeq ($(AUTODEP), y) +-include *.d +else + ifneq ($(wildcard $(DEPFILE)), ) + include $(wildcard $(DEPFILE)) + endif +endif + + +# End of Makefile.TCC.