From d09274f3e3d4dca122c308a621ea8edc100b7d99 Mon Sep 17 00:00:00 2001 From: James Hammons Date: Wed, 18 Jan 2012 02:06:46 +0000 Subject: [PATCH] Code cleanups. --- amode.c | 219 +++--- direct.c | 2010 +++++++++++++++++++++++++++++------------------------ eagen0.c | 359 ++++++---- error.c | 10 +- error.h | 2 +- expr.c | 1112 ++++++++++++++++------------- kwgen.c | 116 ++-- listing.c | 594 +++++++++------- mach.c | 930 ++++++++++++++----------- object.c | 282 ++++---- rmac.c | 254 +++---- 11 files changed, 3278 insertions(+), 2610 deletions(-) diff --git a/amode.c b/amode.c index 2693467..b721491 100644 --- a/amode.c +++ b/amode.c @@ -29,7 +29,7 @@ int a0ixsiz; // Index register si TOKEN a0oexpr[EXPRSIZE]; // Outer displacement expression VALUE a0oexval; // Outer displacement value WORD a0oexattr; // Outer displacement attribute -SYM *a0esym; // External symbol involved in expr +SYM * a0esym; // External symbol involved in expr int am1; // Addressing mode int a1reg; // Register @@ -41,121 +41,130 @@ int a1ixsiz; // Index register si TOKEN a1oexpr[EXPRSIZE]; // Outer displacement expression VALUE a1oexval; // Outer displacement value WORD a1oexattr; // Outer displacement attribute -SYM *a1esym; // External symbol involved in expr +SYM * a1esym; // External symbol involved in expr + // -// --- Parse Addressing Mode ----------------------------------------------------------------------- +// Parse Addressing Mode // - -int amode(int acount) { - // Initialize global return values +int amode(int acount) +{ + // Initialize global return values nmodes = a0reg = a1reg = 0; am0 = am1 = AM_NONE; a0expr[0] = a0oexpr[0] = a1expr[0] = a1oexpr[0] = ENDEXPR; a0exattr = a0oexattr = a1exattr = a1oexattr = 0; a0esym = a1esym = (SYM *)NULL; - // If at EOL, then no addr modes at all - if(*tok == EOL) - return(0); - - // Parse first addressing mode - #define AnOK a0ok - #define AMn am0 - #define AnREG a0reg - #define AnIXREG a0ixreg - #define AnIXSIZ a0ixsiz - #define AnEXPR a0expr - #define AnEXVAL a0exval - #define AnEXATTR a0exattr - #define AnOEXPR a0oexpr - #define AnOEXVAL a0oexval - #define AnOEXATTR a0oexattr - #define AnESYM a0esym - #define AMn_IX0 am0_ix0 - #define AMn_IXN am0_ixn - #include "parmode.h" - - // If caller wants only one mode, return just one (ignore comma); - // If there is no second addressing mode (no comma), then return just one anyway. - nmodes = 1; - if(acount == 0 || *tok != ',') - return(1); - ++tok; // Eat comma - - // Parse second addressing mode - #define AnOK a1ok - #define AMn am1 - #define AnREG a1reg - #define AnIXREG a1ixreg - #define AnIXSIZ a1ixsiz - #define AnEXPR a1expr - #define AnEXVAL a1exval - #define AnEXATTR a1exattr - #define AnOEXPR a1oexpr - #define AnOEXVAL a1oexval - #define AnOEXATTR a1oexattr - #define AnESYM a1esym - #define AMn_IX0 am1_ix0 - #define AMn_IXN am1_ixn - #include "parmode.h" - - nmodes = 2; - return(2); - - // Error messages: - badmode: - - return(error("addressing mode syntax")); - - unmode: - - return(error("unimplemented addressing mode")); + // If at EOL, then no addr modes at all + if (*tok == EOL) + return 0; + + // Parse first addressing mode + #define AnOK a0ok + #define AMn am0 + #define AnREG a0reg + #define AnIXREG a0ixreg + #define AnIXSIZ a0ixsiz + #define AnEXPR a0expr + #define AnEXVAL a0exval + #define AnEXATTR a0exattr + #define AnOEXPR a0oexpr + #define AnOEXVAL a0oexval + #define AnOEXATTR a0oexattr + #define AnESYM a0esym + #define AMn_IX0 am0_ix0 + #define AMn_IXN am0_ixn + #include "parmode.h" + + // If caller wants only one mode, return just one (ignore comma); + // If there is no second addressing mode (no comma), then return just one anyway. + nmodes = 1; + + if (acount == 0 || *tok != ',') + return 1; + + ++tok; // Eat comma + + // Parse second addressing mode + #define AnOK a1ok + #define AMn am1 + #define AnREG a1reg + #define AnIXREG a1ixreg + #define AnIXSIZ a1ixsiz + #define AnEXPR a1expr + #define AnEXVAL a1exval + #define AnEXATTR a1exattr + #define AnOEXPR a1oexpr + #define AnOEXVAL a1oexval + #define AnOEXATTR a1oexattr + #define AnESYM a1esym + #define AMn_IX0 am1_ix0 + #define AMn_IXN am1_ixn + #include "parmode.h" + + nmodes = 2; + return 2; + + // Error messages: + badmode: + return error("addressing mode syntax"); + + unmode: + return error("unimplemented addressing mode"); } + // -// --- Parse Register List ------------------------------------------------------------------------- +// Parse Register List // - -int reglist(WORD *a_rmask) { - static WORD msktab[] = { - 0x0001, 0x0002, 0x0004, 0x0008, - 0x0010, 0x0020, 0x0040, 0x0080, - 0x0100, 0x0200, 0x0400, 0x0800, - 0x1000, 0x2000, 0x4000, 0x8000 - }; - WORD rmask; - int r, cnt; - - rmask = 0; - for(;;) { - if(*tok >= KW_D0 && *tok <= KW_A7) - r = *tok++ & 15; - else break; - - if(*tok == '-') { - ++tok; - if(*tok >= KW_D0 && *tok <= KW_A7) - cnt = *tok++ & 15; - else - return(error("register list syntax")); - - if(cnt < r) - return(error("register list order")); - cnt -= r; - } else - cnt = 0; - - while(cnt-- >= 0) - rmask |= msktab[r++]; - if(*tok != '/') - break; - ++tok; - } - - *a_rmask = rmask; - - return(OK); +int reglist(WORD * a_rmask) +{ + static WORD msktab[] = { + 0x0001, 0x0002, 0x0004, 0x0008, + 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, + 0x1000, 0x2000, 0x4000, 0x8000 + }; + WORD rmask; + int r, cnt; + + rmask = 0; + + for(;;) + { + if (*tok >= KW_D0 && *tok <= KW_A7) + r = *tok++ & 15; + else + break; + + if (*tok == '-') + { + ++tok; + + if (*tok >= KW_D0 && *tok <= KW_A7) + cnt = *tok++ & 15; + else + return error("register list syntax"); + + if (cnt < r) + return error("register list order"); + + cnt -= r; + } + else + cnt = 0; + + while (cnt-- >= 0) + rmask |= msktab[r++]; + + if (*tok != '/') + break; + + ++tok; + } + + *a_rmask = rmask; + + return OK; } - - diff --git a/direct.c b/direct.c index 3b20a21..95fd51b 100644 --- a/direct.c +++ b/direct.c @@ -84,1139 +84,1347 @@ int (*dirtab[])() = { d_fail, // 56 .fail }; + // -// --- .org - Set origin --------------------------------------------------------------------------- +// .org - Set origin // - int d_fail(void) { - fatal("user abort"); - return(0); + fatal("user abort"); + return 0; } - + + // -// --- .org - Set origin --------------------------------------------------------------------------- +// .org - Set origin // - int d_org(void) { - VALUE address; + VALUE address; - if (!rgpu && !rdsp) - return(error(".org permitted only in gpu/dsp section")); + if (!rgpu && !rdsp) + return error(".org permitted only in gpu/dsp section"); - orgaddr = 0; + orgaddr = 0; - if (abs_expr(&address) == ERROR) - { - error("cannot determine org'd address"); - return(ERROR); - } + if (abs_expr(&address) == ERROR) + { + error("cannot determine org'd address"); + return ERROR; + } - orgaddr = address; - orgactive = 1; + orgaddr = address; + orgactive = 1; - return(0); + return 0; } + // -// --- NOP Padding Directive ----------------------------------------------------------------------- +// NOP Padding Directive // - int d_jpad(void) { - jpad = 1; - return(0); + jpad = 1; + return 0; } + int d_nojpad(void) { - jpad = 0; - return(0); + jpad = 0; + return 0; } + // -// --- Print Directive ----------------------------------------------------------------------------- +// Print Directive // - int d_print(void) { - char prntstr[LNSIZ]; // String for PRINT directive - char format[LNSIZ]; // Format for PRINT directive - int formatting = 0; // Formatting on/off - int wordlong = 0; // WORD = 0, LONG = 1 - int outtype = 0; // 0:hex, 1:decimal, 2:unsigned - - VALUE eval; // Expression value - WORD eattr; // Expression attributes - SYM *esym; // External symbol involved in expr. - TOKEN r_expr[EXPRSIZE]; - - while(*tok != EOL) { - switch(*tok) { - case STRING: - sprintf(prntstr, "%s", (char*)tok[1]); - printf("%s", prntstr); - if(list_fd) - write(list_fd, prntstr, (LONG)strlen(prntstr)); - tok+=2; - break; - case '/': - formatting = 1; - if(tok[1] != SYMBOL) goto token_err; - strcpy(prntstr, (char*)tok[2]); - switch(prntstr[0]) { - case 'l': case 'L': wordlong = 1; break; - case 'w': case 'W': wordlong = 0; break; - case 'x': case 'X': outtype = 0; break; - case 'd': case 'D': outtype = 1; break; - case 'u': case 'U': outtype = 2; break; - default: - error("unknown print format flag"); - return(ERROR); - } - tok += 3; - break; - case ',': - tok++; - break; - default: - if(expr(r_expr, &eval, &eattr, &esym) != OK) - goto token_err; - else { - switch(outtype) { - case 0: strcpy(format, "%X"); break; - case 1: strcpy(format, "%d" ); break; - case 2: strcpy(format, "%u" ); break; - } - if(wordlong) sprintf(prntstr, format, eval); - else sprintf(prntstr, format, eval & 0xFFFF); - printf("%s", prntstr); - if(list_fd) - write(list_fd, prntstr, (LONG)strlen(prntstr)); - formatting = 0; - wordlong = 0; - outtype = 0; - } - break; - } - } - - printf("\n"); - println("\n"); - - return(0); - - token_err: - error("illegal print token"); - return(ERROR); -} + char prntstr[LNSIZ]; // String for PRINT directive + char format[LNSIZ]; // Format for PRINT directive + int formatting = 0; // Formatting on/off + int wordlong = 0; // WORD = 0, LONG = 1 + int outtype = 0; // 0:hex, 1:decimal, 2:unsigned + + VALUE eval; // Expression value + WORD eattr; // Expression attributes + SYM * esym; // External symbol involved in expr. + TOKEN r_expr[EXPRSIZE]; + + while (*tok != EOL) + { + switch(*tok) + { + case STRING: + sprintf(prntstr, "%s", (char *)tok[1]); + printf("%s", prntstr); + + if (list_fd) + write(list_fd, prntstr, (LONG)strlen(prntstr)); + + tok += 2; + break; + case '/': + formatting = 1; + + if (tok[1] != SYMBOL) + goto token_err; + + strcpy(prntstr, (char *)tok[2]); + + switch(prntstr[0]) + { + case 'l': case 'L': wordlong = 1; break; + case 'w': case 'W': wordlong = 0; break; + case 'x': case 'X': outtype = 0; break; + case 'd': case 'D': outtype = 1; break; + case 'u': case 'U': outtype = 2; break; + default: + error("unknown print format flag"); + return ERROR; + } + + tok += 3; + break; + case ',': + tok++; + break; + default: + if (expr(r_expr, &eval, &eattr, &esym) != OK) + goto token_err; + else + { + switch(outtype) + { + case 0: strcpy(format, "%X"); break; + case 1: strcpy(format, "%d" ); break; + case 2: strcpy(format, "%u" ); break; + } -// -// --- Undefine an Equated Condition Code ---------------------------------------------------------- -// + if (wordlong) + sprintf(prntstr, format, eval); + else + sprintf(prntstr, format, eval & 0xFFFF); + + printf("%s", prntstr); + + if (list_fd) + write(list_fd, prntstr, (LONG)strlen(prntstr)); -int d_ccundef(void) { - SYM *ccname; + formatting = 0; + wordlong = 0; + outtype = 0; + } - if(!rgpu && !rdsp) { // Check that we are in a RISC section - error(".ccundef must be defined in .gpu/.dsp section"); - return(ERROR); - } - if(*tok != SYMBOL) { - error(syntax_error); - return(ERROR); - } - ccname = lookup((char *)tok[1], LABEL, 0); - if(!ccname || !(ccname->sattre & EQUATEDCC)) { // Make sure symbol is a valid ccdef - error("invalid equated condition name specified"); - return(ERROR); - } + break; + } + } - ccname->sattre |= UNDEF_CC; + printf("\n"); + println("\n"); - return(0); + return 0; + +token_err: + error("illegal print token"); + return ERROR; } + // -// --- Undefine an Equated Register ---------------------------------------------------------------- +// Undefine an Equated Condition Code // +int d_ccundef(void) +{ + SYM * ccname; -int d_equrundef(void) { - SYM *regname; - - if(!rgpu && !rdsp) { // Check that we are in a RISC section - error(".equrundef/.regundef must be defined in .gpu/.dsp section"); - return(ERROR); - } + // Check that we are in a RISC section + if (!rgpu && !rdsp) + { + error(".ccundef must be defined in .gpu/.dsp section"); + return ERROR; + } - while(*tok != EOL) { - if(*tok == ',') tok++; // Skip preceeding or seperating commas + if (*tok != SYMBOL) + { + error(syntax_error); + return ERROR; + } - if(*tok != SYMBOL) { // Check we are dealing with a symbol - error(syntax_error); - return(ERROR); - } + ccname = lookup((char *)tok[1], LABEL, 0); - regname = lookup((char *)tok[1], LABEL, 0); // Lookup and undef if equated register - if(regname && (regname->sattre & EQUATEDREG)) - regname->sattre |= UNDEF_EQUR; + // Make sure symbol is a valid ccdef + if (!ccname || !(ccname->sattre & EQUATEDCC)) + { + error("invalid equated condition name specified"); + return ERROR; + } - tok += 2; // Skip over symbol token and address - } + ccname->sattre |= UNDEF_CC; - return(0); + return 0; } + // -// --- Do Not Allow the Use of the CLR.L Opcode ---------------------------------------------------- +// Undefine an Equated Register // +int d_equrundef(void) +{ + SYM * regname; + + // Check that we are in a RISC section + if (!rgpu && !rdsp) + { + error(".equrundef/.regundef must be defined in .gpu/.dsp section"); + return ERROR; + } + + while (*tok != EOL) + { + // Skip preceeding or seperating commas + if (*tok == ',') + tok++; + + // Check we are dealing with a symbol + if (*tok != SYMBOL) + { + error(syntax_error); + return ERROR; + } + + // Lookup and undef if equated register + regname = lookup((char *)tok[1], LABEL, 0); + + if (regname && (regname->sattre & EQUATEDREG)) + regname->sattre |= UNDEF_EQUR; + + // Skip over symbol token and address + tok += 2; + } + + return 0; +} + -int d_noclear(void) { - return(0); +// +// Do Not Allow the Use of the CLR.L Opcode +// +int d_noclear(void) +{ + return 0; } + // -// --- Include Binary File ------------------------------------------------------------------------- -// - -int d_incbin(void) { - int i, j; - int bytes = 0; - long pos, size; - char buf; - - if(*tok != STRING) { - error(syntax_error); - return(ERROR); - } - - if((j = open((char *)tok[1], _OPEN_INC)) >= 0) { - size = lseek(j, 0L, SEEK_END); - chcheck(size); - pos = lseek(j, 0L, SEEK_SET); - - for(i = 0; i < size; i++) { - buf = '\0'; - bytes = read(j, &buf, 1); - D_byte(buf); - } - - } else { - errors("cannot open include binary file (%s)", (char*)tok[1]); - return(ERROR); - } - - close(j); - return(0); +// Include Binary File +// +int d_incbin(void) +{ + int i, j; + int bytes = 0; + long pos, size; + char buf; + + if (*tok != STRING) + { + error(syntax_error); + return ERROR; + } + + if ((j = open((char *)tok[1], _OPEN_INC)) >= 0) + { + size = lseek(j, 0L, SEEK_END); + chcheck(size); + pos = lseek(j, 0L, SEEK_SET); + + for(i=0; isvalue; + if (lab_sym != NULL) // Bump label if we have to + ++lab_sym->svalue; } + // -// --- Unimplemened Directive Error ---------------------------------------------------------------- +// Unimplemened Directive Error // - -int d_unimpl(void) { - return(error("unimplemented directive")); +int d_unimpl(void) +{ + return error("unimplemented directive"); } + // -// --- Return absolute (not TDB) and defined expression or return an error ------------------------- +// Return absolute (not TDB) and defined expression or return an error // +int abs_expr(VALUE * a_eval) +{ + WORD eattr; + + if (expr(exprbuf, a_eval, &eattr, NULL) < 0) + return ERROR; -int abs_expr(VALUE *a_eval) { - WORD eattr; + if (!(eattr & DEFINED)) + return error(undef_error); - if(expr(exprbuf, a_eval, &eattr, NULL) < 0) - return(ERROR); - if(!(eattr & DEFINED)) - return(error(undef_error)); - if(eattr & TDB) - return(error(rel_error)); + if (eattr & TDB) + return error(rel_error); - return(OK); + return OK; } + // -// --- Hand symbols in a symbol-list to a function (kind of like mapcar...) ------------------------ +// Hand symbols in a symbol-list to a function (kind of like mapcar...) // +int symlist(int(* func)()) +{ + char * em = "symbol list syntax"; + + for(;;) + { + if (*tok != SYMBOL) + return error(em); + + if ((*func)(tok[1]) != OK) + break; + + tok += 2; + + if (*tok == EOL) + break; -int symlist(int(*func)()) { - char *em = "symbol list syntax"; + if (*tok != ',') + return error(em); - for(;;) { - if(*tok != SYMBOL) return(error(em)); - if((*func)(tok[1]) != OK) break; - tok += 2; - if(*tok == EOL) break; - if(*tok != ',') return(error(em)); - ++tok; - } + ++tok; + } - return(0); + return 0; } + +// +// .include "filename" // -// --- .include "filename" ------------------------------------------------------------------------- -// - -int d_include(void) { - int j; - int i; - char *fn; - char buf[128]; - char buf1[128]; - - if(*tok == STRING) // Leave strings ALONE - fn = (char *)*++tok; - else if(*tok == SYMBOL) { // Try to append ".s" to symbols - strcpy(buf, (char *)*++tok); - fext(buf, ".s", 0); - fn = &buf[0]; - } else // Punt if no STRING or SYMBOL - return(error("missing filename")); - - // Make sure the user didn't try anything like: - // .include equates.s - if(*++tok != EOL) return(error("extra stuff after filename -- enclose it in quotes")); - - // Attempt to open the include file in the current directory, then (if that failed) try list - // of include files passed in the enviroment string or by the "-d" option. - if((j = open(fn, 0)) < 0) { - for(i = 0; nthpath("RMACPATH", i, buf1) != 0; ++i) { - j = strlen(buf1); - if(j > 0 && buf1[j-1] != SLASHCHAR) // Append path char if necessary - strcat(buf1, SLASHSTRING); - strcat(buf1, fn); - if((j = open(buf1, 0)) >= 0) - goto allright; - } - - return(errors("cannot open: \"%s\"", fn)); - } - - allright: - - include(j, fn); - return(0); +int d_include(void) +{ + int j; + int i; + char * fn; + char buf[128]; + char buf1[128]; + + if (*tok == STRING) // Leave strings ALONE + fn = (char *)*++tok; + else if (*tok == SYMBOL) // Try to append ".s" to symbols + { + strcpy(buf, (char *)*++tok); + fext(buf, ".s", 0); + fn = &buf[0]; + } + else // Punt if no STRING or SYMBOL + return error("missing filename"); + + // Make sure the user didn't try anything like: + // .include equates.s + if (*++tok != EOL) + return error("extra stuff after filename -- enclose it in quotes"); + + // Attempt to open the include file in the current directory, then (if that failed) try list + // of include files passed in the enviroment string or by the "-d" option. + if ((j = open(fn, 0)) < 0) + { + for(i=0; nthpath("RMACPATH", i, buf1)!=0; ++i) + { + j = strlen(buf1); + + if (j > 0 && buf1[j-1] != SLASHCHAR) // Append path char if necessary + strcat(buf1, SLASHSTRING); + + strcat(buf1, fn); + + if ((j = open(buf1, 0)) >= 0) + goto allright; + } + + return errors("cannot open: \"%s\"", fn); + } + +allright: + include(j, fn); + return 0; } + // -// --- .assert expression [, expression...] -------------------------------------------------------- +// .assert expression [, expression...] // +int d_assert(void) +{ + WORD eattr; + VALUE eval; -int d_assert(void) { - WORD eattr; - VALUE eval; + for(; expr(exprbuf, &eval, &eattr, NULL)==OK; ++tok) + { + if (!(eattr & DEFINED)) + return error("forward or undefined .assert"); - for(; expr(exprbuf, &eval, &eattr, NULL) == OK; ++tok) { - if(!(eattr & DEFINED)) - return(error("forward or undefined .assert")); - if(!eval) - return(error("assert failure")); - if(*tok != ',') - break; - } - at_eol(); - return(0); + if (!eval) + return error("assert failure"); + + if (*tok != ',') + break; + } + + at_eol(); + return 0; } + // -// --- .globl symbol [, symbol] <<>> ----------------------------- +// .globl symbol [, symbol] <<>> // +int globl1(char * p) +{ + SYM *sy; -int globl1(char *p) { - SYM *sy; + if (*p == '.') + return error("cannot .globl local symbol"); - if(*p == '.') - return(error("cannot .globl local symbol")); - if((sy = lookup(p, LABEL, 0)) == NULL) { - sy = newsym(p, LABEL, 0); - sy->svalue = 0; - sy->sattr = GLOBAL; - } else - sy->sattr |= GLOBAL; + if ((sy = lookup(p, LABEL, 0)) == NULL) + { + sy = newsym(p, LABEL, 0); + sy->svalue = 0; + sy->sattr = GLOBAL; + } + else + sy->sattr |= GLOBAL; - return(OK); + return OK; } -int d_globl(void) { - symlist(globl1); - return(0); + +int d_globl(void) +{ + symlist(globl1); + return 0; } + // -// --- .abs [expression] --------------------------------------------------------------------------- +// .abs [expression] // +int d_abs(void) +{ + VALUE eval; -int d_abs(void) { - VALUE eval; + savsect(); - savsect(); - if(*tok == EOL) - eval = 0; - else - if(abs_expr(&eval) != OK) - return(0); + if (*tok == EOL) + eval = 0; + else if (abs_expr(&eval) != OK) + return 0; - switchsect(ABS); - sloc = eval; - return(0); + switchsect(ABS); + sloc = eval; + return 0; } + // -// --- Switch Segments ----------------------------------------------------------------------------- +// Switch Segments // -int d_text(void) { - if(rgpu || rdsp) - return(error("directive forbidden in gpu/dsp mode")); +int d_text(void) +{ + if (rgpu || rdsp) + return error("directive forbidden in gpu/dsp mode"); + + if (cursect != TEXT) + { + savsect(); + switchsect(TEXT); + } - if(cursect != TEXT) { - savsect(); - switchsect(TEXT); - } - return(0); + return 0; } -int d_data(void) { - if(rgpu || rdsp) - return(error("directive forbidden in gpu/dsp mode")); - if(cursect != DATA) { - savsect(); - switchsect(DATA); - } - return(0); +int d_data(void) +{ + if (rgpu || rdsp) + return error("directive forbidden in gpu/dsp mode"); + + if (cursect != DATA) + { + savsect(); + switchsect(DATA); + } + + return 0; } -int d_bss(void) { - if(rgpu || rdsp) - return(error("directive forbidden in gpu/dsp mode")); - if(cursect != BSS) { - savsect(); - switchsect(BSS); - } - return(0); +int d_bss(void) +{ + if (rgpu || rdsp) + return error("directive forbidden in gpu/dsp mode"); + + if (cursect != BSS) + { + savsect(); + switchsect(BSS); + } + + return 0; } + // -// --- .ds[.size] expression ----------------------------------------------------------------------- +// .ds[.size] expression // - int d_ds(WORD siz) { - VALUE eval; - - // This gets kind of stupid. This directive is disallowed in normal 68000 mode ("for your own - // good!"), but is permitted for 6502 and Alcyon-compatibility modes. - // For obvious reasons, no auto-even is done in 8-bit processor modes. - if (as68_flag == 0 && (scattr & SBSS) == 0) - return(error(".ds permitted only in BSS")); - - if (siz != SIZB && (sloc & 1)) // Automatic .even - auto_even(); - - if (abs_expr(&eval) != OK) - return(0); - - // In non-TDB section (BSS, ABS and M6502) just advance the location counter appropriately. - // In TDB sections, deposit (possibly large) chunks of zeroed memory.... - if ((scattr & SBSS)) - { - listvalue(eval); - eval *= siz; - sloc += eval; - just_bss = 1; // No data deposited (8-bit CPU mode) - } - else - { - dep_block(eval, siz, (VALUE)0, (WORD)(DEFINED|ABS), NULL); - } - - at_eol(); - return(0); + VALUE eval; + + // This gets kind of stupid. This directive is disallowed in normal 68000 + // mode ("for your own good!"), but is permitted for 6502 and Alcyon- + // compatibility modes. For obvious reasons, no auto-even is done in 8-bit + // processor modes. + if (as68_flag == 0 && (scattr & SBSS) == 0) + return error(".ds permitted only in BSS"); + + if (siz != SIZB && (sloc & 1)) // Automatic .even + auto_even(); + + if (abs_expr(&eval) != OK) + return 0; + + // In non-TDB section (BSS, ABS and M6502) just advance the location + // counter appropriately. In TDB sections, deposit (possibly large) chunks + //of zeroed memory.... + if ((scattr & SBSS)) + { + listvalue(eval); + eval *= siz; + sloc += eval; + just_bss = 1; // No data deposited (8-bit CPU mode) + } + else + { + dep_block(eval, siz, (VALUE)0, (WORD)(DEFINED|ABS), NULL); + } + + at_eol(); + return 0; } + // -// --- dc.b, dc.w / dc, dc.l ----------------------------------------------------------------------- +// dc.b, dc.w / dc, dc.l // - int d_dc(WORD siz) { - WORD eattr; - VALUE eval; - WORD tdb; - WORD defined; - LONG i; - char * p; - int movei = 0; // movei flag for dc.i - - if ((scattr & SBSS) != 0) - return(error("illegal initialization of section")); - - if ((siz != SIZB) && (sloc & 1)) - auto_even(); - - for(;; ++tok) - { - // dc.b 'string' [,] ... - if (siz == SIZB && *tok == STRING && (tok[2] == ',' || tok[2] == EOL)) - { - i = strlen((const char*)tok[1]); - - if ((challoc - ch_size) < i) - chcheck(i); - - for(p=(char *)tok[1]; *p!=EOS; ++p) - D_byte(*p); - - tok += 2; - goto comma; - } - - if (*tok == 'I') - { - movei = 1; - tok++; - siz = SIZL; - } - - // dc.x - if (expr(exprbuf, &eval, &eattr, NULL) != OK) - return(0); - - tdb = (WORD)(eattr & TDB); - defined = (WORD)(eattr & DEFINED); - - if ((challoc - ch_size) < 4) - chcheck(4L); - - switch (siz) - { - case SIZB: - if (!defined) + WORD eattr; + VALUE eval; + WORD tdb; + WORD defined; + LONG i; + char * p; + int movei = 0; // movei flag for dc.i + + if ((scattr & SBSS) != 0) + return error("illegal initialization of section"); + + if ((siz != SIZB) && (sloc & 1)) + auto_even(); + + for(;; ++tok) + { + // dc.b 'string' [,] ... + if (siz == SIZB && *tok == STRING && (tok[2] == ',' || tok[2] == EOL)) + { + i = strlen((const char*)tok[1]); + + if ((challoc - ch_size) < i) + chcheck(i); + + for(p=(char *)tok[1]; *p!=EOS; ++p) + D_byte(*p); + + tok += 2; + goto comma; + } + + if (*tok == 'I') + { + movei = 1; + tok++; + siz = SIZL; + } + + // dc.x + if (expr(exprbuf, &eval, &eattr, NULL) != OK) + return 0; + + tdb = (WORD)(eattr & TDB); + defined = (WORD)(eattr & DEFINED); + + if ((challoc - ch_size) < 4) + chcheck(4L); + + switch (siz) + { + case SIZB: + if (!defined) { - fixup(FU_BYTE|FU_SEXT, sloc, exprbuf); - D_byte(0); - } - else + fixup(FU_BYTE|FU_SEXT, sloc, exprbuf); + D_byte(0); + } + else { - if (tdb) - return(error("non-absolute byte value")); - - if (eval + 0x100 >= 0x200) - return(error(range_error)); - - D_byte(eval); - } - break; - case SIZW: - case SIZN: - if (!defined) - { - fixup(FU_WORD|FU_SEXT, sloc, exprbuf); - D_word(0); - } - else - { - if (tdb) - rmark(cursect, sloc, tdb, MWORD, NULL); - - if (eval + 0x10000 >= 0x20000) - return(error(range_error)); - - // Deposit 68000 or 6502 (byte-reversed) word - D_word(eval); - } - break; - case SIZL: - if (!defined) + if (tdb) + return error("non-absolute byte value"); + + if (eval + 0x100 >= 0x200) + return error(range_error); + + D_byte(eval); + } + + break; + case SIZW: + case SIZN: + if (!defined) { - if (movei) - fixup(FU_LONG|FU_MOVEI, sloc, exprbuf); - else - fixup(FU_LONG, sloc, exprbuf); - - D_long(0); - } - else + fixup(FU_WORD|FU_SEXT, sloc, exprbuf); + D_word(0); + } + else { - if (tdb) - rmark(cursect, sloc, tdb, MLONG, NULL); + if (tdb) + rmark(cursect, sloc, tdb, MWORD, NULL); - if (movei) - eval = ((eval >> 16) & 0x0000FFFF) | ((eval << 16) & 0xFFFF0000); + if (eval + 0x10000 >= 0x20000) + return error(range_error); - D_long(eval); - } - break; - } - - comma: + // Deposit 68000 or 6502 (byte-reversed) word + D_word(eval); + } - if (*tok != ',') - break; - } - - at_eol(); - return(0); + break; + case SIZL: + if (!defined) + { + if (movei) + fixup(FU_LONG|FU_MOVEI, sloc, exprbuf); + else + fixup(FU_LONG, sloc, exprbuf); + + D_long(0); + } + else + { + if (tdb) + rmark(cursect, sloc, tdb, MLONG, NULL); + + if (movei) + eval = ((eval >> 16) & 0x0000FFFF) | ((eval << 16) & 0xFFFF0000); + + D_long(eval); + } + break; + } + +comma: + if (*tok != ',') + break; + } + + at_eol(); + return 0; } + // -// --- dcb[.siz] expr1,expr2 - Make 'expr1' copies of 'expr2' -------------------------------------- +// dcb[.siz] expr1,expr2 - Make 'expr1' copies of 'expr2' // - int d_dcb(WORD siz) { - VALUE evalc, eval; - WORD eattr; + VALUE evalc, eval; + WORD eattr; - if ((scattr & SBSS) != 0) - return(error("illegal initialization of section")); + if ((scattr & SBSS) != 0) + return error("illegal initialization of section"); - if (abs_expr(&evalc) != OK) - return(0); + if (abs_expr(&evalc) != OK) + return 0; - if (*tok++ != ',') - return(error("missing comma")); + if (*tok++ != ',') + return error("missing comma"); - if (expr(exprbuf, &eval, &eattr, NULL) < 0) - return(0); + if (expr(exprbuf, &eval, &eattr, NULL) < 0) + return 0; - if ((siz != SIZB) && (sloc & 1)) - auto_even(); + if ((siz != SIZB) && (sloc & 1)) + auto_even(); - dep_block(evalc, siz, eval, eattr, exprbuf); - return(0); + dep_block(evalc, siz, eval, eattr, exprbuf); + return 0; } + // -// ------------------------------------------------------------------------------------------------- // Generalized initialization directive // // .init[.siz] [#count,] expression [.size] , ... // -// The size suffix on the ".init" directive becomes the default size of the objects to deposit. -// If an item is preceeded with a sharp (immediate) sign and an expression, it specifies a repeat -// count. The value to be deposited may be followed by a size suffix, which overrides the -// default size. -// ------------------------------------------------------------------------------------------------- +// The size suffix on the ".init" directive becomes the default size of the +// objects to deposit. If an item is preceeded with a sharp (immediate) sign +// and an expression, it specifies a repeat count. The value to be deposited +// may be followed by a size suffix, which overrides the default size. // - int d_init(WORD def_siz) { - VALUE count; - VALUE eval; - WORD eattr; - WORD siz; - - if ((scattr & SBSS) != 0) - return(error(".init not permitted in BSS or ABS")); - - if (rgpu || rdsp) - return(error("directive forbidden in gpu/dsp mode")); - - for(;;) - { - // Get repeat count (defaults to 1) - if (*tok == '#') - { - ++tok; - - if (abs_expr(&count) != OK) - return(0); - - if (*tok++ != ',') - return(error(comma_error)); - } - else - count = 1; - - // Evaluate expression to deposit - if (expr(exprbuf, &eval, &eattr, NULL) < 0) - return(0); - - switch ((int)*tok++) - { // Determine size of object to deposit - case DOTB: siz = SIZB; break; - case DOTW: siz = SIZB; break; - case DOTL: siz = SIZL; break; - default: - siz = def_siz; - --tok; - break; - } - - dep_block(count, siz, eval, eattr, exprbuf); - - switch ((int)*tok) - { - case EOL: - return(0); - case ',': - ++tok; - continue; - default: - return(error(comma_error)); - } - } + VALUE count; + VALUE eval; + WORD eattr; + WORD siz; + + if ((scattr & SBSS) != 0) + return error(".init not permitted in BSS or ABS"); + + if (rgpu || rdsp) + return error("directive forbidden in gpu/dsp mode"); + + for(;;) + { + // Get repeat count (defaults to 1) + if (*tok == '#') + { + ++tok; + + if (abs_expr(&count) != OK) + return 0; + + if (*tok++ != ',') + return error(comma_error); + } + else + count = 1; + + // Evaluate expression to deposit + if (expr(exprbuf, &eval, &eattr, NULL) < 0) + return 0; + + switch ((int)*tok++) + { // Determine size of object to deposit + case DOTB: siz = SIZB; break; + case DOTW: siz = SIZB; break; + case DOTL: siz = SIZL; break; + default: + siz = def_siz; + --tok; + break; + } + + dep_block(count, siz, eval, eattr, exprbuf); + + switch ((int)*tok) + { + case EOL: + return 0; + case ',': + ++tok; + continue; + default: + return error(comma_error); + } + } } + +// +// Deposit 'count' values of size 'siz' in the current (non-BSS) segment // -// --- Deposit 'count' values of size 'siz' in the current (non-BSS) segment ----------------------- -// - -int dep_block(VALUE count, WORD siz, VALUE eval, WORD eattr, TOKEN *exprbuf) { - WORD tdb; - WORD defined; - - tdb = (WORD)(eattr & TDB); - defined = (WORD)(eattr & DEFINED); - - while(count--) { - if((challoc - ch_size) < 4) - chcheck(4L); - - switch(siz) { - case SIZB: - if(!defined) { - fixup(FU_BYTE|FU_SEXT, sloc, exprbuf); - D_byte(0); - } else { - if(tdb) - return(error("non-absolute byte value")); - if(eval + 0x100 >= 0x200) - return(error(range_error)); - D_byte(eval); - } - break; - case SIZW: - case SIZN: - if(!defined) { - fixup(FU_WORD|FU_SEXT, sloc, exprbuf); - D_word(0); - } else { - if(tdb) - rmark(cursect, sloc, tdb, MWORD, NULL); - if(eval + 0x10000 >= 0x20000) - return(error(range_error)); - - // Deposit 68000 or 6502 (byte-reversed) word - D_word(eval); - } - break; - case SIZL: - if(!defined) { - fixup(FU_LONG, sloc, exprbuf); - D_long(0); - } else { - if(tdb) - rmark(cursect, sloc, tdb, MLONG, NULL); - D_long(eval); - } - break; - } - } - return(0); +int dep_block(VALUE count, WORD siz, VALUE eval, WORD eattr, TOKEN * exprbuf) +{ + WORD tdb; + WORD defined; + + tdb = (WORD)(eattr & TDB); + defined = (WORD)(eattr & DEFINED); + + while (count--) + { + if ((challoc - ch_size) < 4) + chcheck(4L); + + switch(siz) + { + case SIZB: + if (!defined) + { + fixup(FU_BYTE|FU_SEXT, sloc, exprbuf); + D_byte(0); + } + else + { + if (tdb) + return error("non-absolute byte value"); + + if (eval + 0x100 >= 0x200) + return error(range_error); + + D_byte(eval); + } + + break; + case SIZW: + case SIZN: + if (!defined) + { + fixup(FU_WORD|FU_SEXT, sloc, exprbuf); + D_word(0); + } + else + { + if (tdb) + rmark(cursect, sloc, tdb, MWORD, NULL); + + if (eval + 0x10000 >= 0x20000) + return error(range_error); + + // Deposit 68000 or 6502 (byte-reversed) word + D_word(eval); + } + + break; + case SIZL: + if (!defined) + { + fixup(FU_LONG, sloc, exprbuf); + D_long(0); + } + else + { + if (tdb) + rmark(cursect, sloc, tdb, MLONG, NULL); + + D_long(eval); + } + + break; + } + } + + return 0; } + // -// --- .comm symbol, size -------------------------------------------------------------------------- +// .comm symbol, size // +int d_comm(void) +{ + SYM * sym; + char * p; + VALUE eval; + + if (*tok != SYMBOL) + return error("missing symbol"); + + p = (char *)tok[1]; + tok += 2; -int d_comm(void) { - SYM *sym; - char *p; - VALUE eval; + if (*p == '.') // Cannot .comm a local symbol + return error(locgl_error); - if(*tok != SYMBOL) - return(error("missing symbol")); - p = (char *)tok[1]; - tok += 2; + if ((sym = lookup(p, LABEL, 0)) == NULL) + sym = newsym(p, LABEL, 0); + else + { + if (sym->sattr & DEFINED) + return error(".comm symbol already defined"); + } - if(*p == '.') // Cannot .comm a local symbol - return(error(locgl_error)); + sym->sattr = GLOBAL|COMMON|BSS; - if((sym = lookup(p, LABEL, 0)) == NULL) - sym = newsym(p, LABEL, 0); - else { - if(sym->sattr & DEFINED) - return(error(".comm symbol already defined")); - } + if (*tok++ != ',') + return error(comma_error); - sym->sattr = GLOBAL|COMMON|BSS; - if(*tok++ != ',') - return(error(comma_error)); + if (abs_expr(&eval) != OK) // Parse size of common region + return 0; - if(abs_expr(&eval) != OK) // Parse size of common region - return(0); - sym->svalue = eval; // Install common symbol's size - at_eol(); - return(0); + sym->svalue = eval; // Install common symbol's size + at_eol(); + return 0; } + // -// --- .list - Turn listing on -------------------------------------------------------------------- +// .list - Turn listing on // +int d_list(void) +{ + if (list_flag) + ++listing; -int d_list(void) { - if(list_flag) - ++listing; - return(0); + return 0; } + // -// --- .nlist - Turn listing off ------------------------------------------------------------------- +// .nlist - Turn listing off // +int d_nlist(void) +{ + if (list_flag) + --listing; -int d_nlist(void) { - if(list_flag) - --listing; - return(0); + return 0; } + // -// --- .68000 - Back to 68000 TEXT segment --------------------------------------------------------- +// .68000 - Back to 68000 TEXT segment // - -int d_68000(void) { - rgpu = rdsp = 0; - in_main = 0; - // Switching from gpu/dsp sections should reset any ORG'd Address - orgactive = 0; - orgwarning = 0; - savsect(); - switchsect(TEXT); - return(0); +int d_68000(void) +{ + rgpu = rdsp = 0; + in_main = 0; + // Switching from gpu/dsp sections should reset any ORG'd Address + orgactive = 0; + orgwarning = 0; + savsect(); + switchsect(TEXT); + return 0; } + // -// --- .gpu - Switch to GPU Assembler -------------------------------------------------------------- -// - -int d_gpu(void) { - if((cursect != TEXT) && (cursect != DATA)) { - error(".gpu can only be used in the TEXT or DATA segments"); - return(ERROR); - } - // If previous section was dsp or 68000 then we need to reset ORG'd Addresses - if(!rgpu) { - orgactive = 0; - orgwarning = 0; - } - rgpu = 1; // Set GPU assembly - rdsp = 0; // Unset DSP assembly - regbank = BANK_N; // Set no default register bank - in_main = 0; - jpad = 0; - return(0); +// .gpu - Switch to GPU Assembler +// +int d_gpu(void) +{ + if ((cursect != TEXT) && (cursect != DATA)) + { + error(".gpu can only be used in the TEXT or DATA segments"); + return ERROR; + } + + // If previous section was dsp or 68000 then we need to reset ORG'd Addresses + if (!rgpu) + { + orgactive = 0; + orgwarning = 0; + } + + rgpu = 1; // Set GPU assembly + rdsp = 0; // Unset DSP assembly + regbank = BANK_N; // Set no default register bank + in_main = 0; + jpad = 0; + return 0; } + +// +// GPU Main Code Directive // -// --- GPU Main Code Directive --------------------------------------------------------------------- -// - -int d_gpumain(void) { - if((cursect != TEXT) && (cursect != DATA)) { - error(".gpumain can only be used in the TEXT or DATA segments"); - return(ERROR); - } - // If previous section was dsp or 68000 then we need to reset ORG'd Addresses - if(!rgpu) { - orgactive = 0; - orgwarning = 0; - } - rgpu = 1; // Set GPU assembly - rdsp = 0; // Unset DSP assembly - regbank = BANK_N; // Set no default register bank - in_main = 1; // Enable main code execution rules - jpad = 0; - return(0); + +int d_gpumain(void) +{ + if ((cursect != TEXT) && (cursect != DATA)) + { + error(".gpumain can only be used in the TEXT or DATA segments"); + return ERROR; + } + + // If previous section was dsp or 68000 then we need to reset ORG'd Addresses + if (!rgpu) + { + orgactive = 0; + orgwarning = 0; + } + + rgpu = 1; // Set GPU assembly + rdsp = 0; // Unset DSP assembly + regbank = BANK_N; // Set no default register bank + in_main = 1; // Enable main code execution rules + jpad = 0; + return 0; } + +// +// .dsp - Switch to DSP Assembler // -// --- .dsp - Switch to DSP Assembler -------------------------------------------------------------- -// - -int d_dsp(void) { - if((cursect != TEXT) && (cursect != DATA)) { - error(".dsp can only be used in the TEXT or DATA segments"); - return(ERROR); - } - // If previous section was gpu or 68000 then we need to reset ORG'd Addresses - if(!rdsp) { - orgactive = 0; - orgwarning = 0; - } - rdsp = 1; // Set DSP assembly - rgpu = 0; // Unset GPU assembly - regbank = BANK_N; // Set no default register bank - in_main = 0; - jpad = 0; - return(0); +int d_dsp(void) +{ + if ((cursect != TEXT) && (cursect != DATA)) + { + error(".dsp can only be used in the TEXT or DATA segments"); + return ERROR; + } + + // If previous section was gpu or 68000 then we need to reset ORG'd Addresses + if (!rdsp) + { + orgactive = 0; + orgwarning = 0; + } + + rdsp = 1; // Set DSP assembly + rgpu = 0; // Unset GPU assembly + regbank = BANK_N; // Set no default register bank + in_main = 0; + jpad = 0; + return 0; } + // -// ------------------------------------------------------------------------------------------------- // .cargs [#offset], symbol[.size], ... // -// Lists of registers may also be mentioned; they just take up space. Good for "documentation" -// purposes. +// Lists of registers may also be mentioned; they just take up space. Good for +// "documentation" purposes. // // .cargs a6,.arg1, .arg2, .arg3... // // The symbols are ABS and EQUATED. -// ------------------------------------------------------------------------------------------------- -// - -int d_cargs(void) { - VALUE eval; - WORD rlist; - SYM *sy; - char *p; - int env; - int i; - - if(rgpu || rdsp) - return(error("directive forbidden in gpu/dsp mode")); - - if(*tok == '#') { - ++tok; - if(abs_expr(&eval) != OK) - return(0); - if(*tok == ',') // Eat comma if it's there - ++tok; - } else - eval = 4; - - for(;;) { - if(*tok == SYMBOL) { - p = (char *)tok[1]; - if(*p == '.') - env = curenv; - else - env = 0; - - sy = lookup(p, LABEL, env); - if(sy == NULL) { - sy = newsym(p, LABEL, env); - sy->sattr = 0; - } else - if(sy->sattr & DEFINED) - return(errors("multiply-defined label '%s'", p)); - - // Put symbol in "order of definition" list - if(!(sy->sattr & SDECLLIST)) sym_decl(sy); - - sy->sattr |= ABS|DEFINED|EQUATED; - sy->svalue = eval; - tok += 2; - - switch((int)*tok) { - case DOTL: - eval += 2; - case DOTB: - case DOTW: - ++tok; - } - eval += 2; - } else - if(*tok >= KW_D0 && *tok <= KW_A7) { - if(reglist(&rlist) < 0) - return(0); - for(i = 0; i++ < 16; rlist >>= 1) - if(rlist & 1) - eval += 4; - } else - switch((int)*tok) { - case KW_USP: - case KW_SSP: - case KW_PC: - eval += 2; - // FALLTHROUGH - case KW_SR: - case KW_CCR: - eval += 2; - ++tok; - break; - case EOL: - return(0); - default: - return(error(".cargs syntax")); - } - - if(*tok == ',') - ++tok; - } +// +int d_cargs(void) +{ + VALUE eval; + WORD rlist; + SYM * sy; + char * p; + int env; + int i; + + if (rgpu || rdsp) + return error("directive forbidden in gpu/dsp mode"); + + if (*tok == '#') + { + ++tok; + + if (abs_expr(&eval) != OK) + return 0; + + if (*tok == ',') // Eat comma if it's there + ++tok; + } + else + eval = 4; + + for(;;) + { + if (*tok == SYMBOL) + { + p = (char *)tok[1]; + + if (*p == '.') + env = curenv; + else + env = 0; + + sy = lookup(p, LABEL, env); + + if (sy == NULL) + { + sy = newsym(p, LABEL, env); + sy->sattr = 0; + } + else if (sy->sattr & DEFINED) + return errors("multiply-defined label '%s'", p); + + // Put symbol in "order of definition" list + if (!(sy->sattr & SDECLLIST)) + sym_decl(sy); + + sy->sattr |= ABS|DEFINED|EQUATED; + sy->svalue = eval; + tok += 2; + + switch((int)*tok) + { + case DOTL: + eval += 2; + case DOTB: + case DOTW: + ++tok; + } + + eval += 2; + } + else + { + if (*tok >= KW_D0 && *tok <= KW_A7) + { + if (reglist(&rlist) < 0) + return 0; + + for(i=0; i++<16; rlist>>=1) + if (rlist & 1) + eval += 4; + } + else + { + switch((int)*tok) + { + case KW_USP: + case KW_SSP: + case KW_PC: + eval += 2; + // FALLTHROUGH + case KW_SR: + case KW_CCR: + eval += 2; + ++tok; + break; + case EOL: + return 0; + default: + return error(".cargs syntax"); + } + } + + if (*tok == ',') + ++tok; + } + } } + // -// --- Undefine a macro - .undefmac macname [, macname...] ----------------------------------------- +// Undefine a macro - .undefmac macname [, macname...] // +int undmac1(char * p) +{ + SYM * sy; -int undmac1(char *p) { - SYM *sy; + // If the macro symbol exists, cause it to dissappear + if ((sy = lookup(p, MACRO, 0)) != NULL) + sy->stype = (BYTE)SY_UNDEF; - // If the macro symbol exists, cause it to dissappear - if((sy = lookup(p, MACRO, 0)) != NULL) sy->stype = (BYTE)SY_UNDEF; - return(OK); + return OK; } -int d_undmac(void) { - symlist(undmac1); - return(0); + +int d_undmac(void) +{ + symlist(undmac1); + return 0; } diff --git a/eagen0.c b/eagen0.c index de4f409..c69ac88 100644 --- a/eagen0.c +++ b/eagen0.c @@ -9,158 +9,213 @@ int eaNgen(WORD siz) { - WORD w; - VALUE v; - WORD tdb; - - v = aNexval; - w = (WORD)(aNexattr & DEFINED); - tdb = (WORD)(aNexattr & TDB); - - switch(amN) { - case DREG: // "Do nothing" - they're in the opword - case AREG: - case AIND: - case APOSTINC: - case APREDEC: - case AM_USP: - case AM_CCR: - case AM_SR: - case AM_NONE: - break; // This is a performance hit, though - case ADISP: // expr(An) - if(w) { // Just deposit it - if(tdb) - rmark(cursect, sloc, tdb, MWORD, NULL); - if(v + 0x8000 >= 0x18000) - return(error(range_error)); - D_word(v); - } else { // Arrange for fixup later on - fixup(FU_WORD|FU_SEXT, sloc, aNexpr); - D_word(0); - } - break; - case PCDISP: - if(w) { // Just deposit it - if((aNexattr & TDB) == cursect) - v -= (VALUE)sloc; - else if((aNexattr & TDB) != ABS) - error(rel_error); - - if(v + 0x8000 >= 0x10000) - return(error(range_error)); - D_word(v); - } else { // Arrange for fixup later on - fixup(FU_WORD|FU_SEXT|FU_PCREL, sloc, aNexpr); - D_word(0); - } - break; - case AINDEXED: - w = (WORD)((aNixreg << 12) | aNixsiz); // Compute ixreg and size+scale - if(aNexattr & DEFINED) { // Deposit a byte... - if(tdb) - return(error(abs_error)); // Can't mark bytes - if(v + 0x80 >= 0x180) - return(error(range_error)); - w |= v & 0xff; - D_word(w); - } else { // Fixup the byte later - fixup(FU_BYTE|FU_SEXT, sloc+1, aNexpr); - D_word(w); - } - break; - case PCINDEXED: - w = (WORD)((aNixreg << 12) | aNixsiz); // Compute ixreg and size+scale - if(aNexattr & DEFINED) { // Deposit a byte... - if((aNexattr & TDB) == cursect) - v -= (VALUE)sloc; - else if((aNexattr & TDB) != ABS) - error(rel_error); - - if(v + 0x80 >= 0x100) - return(error(range_error)); - w |= v & 0xff; - D_word(w); - } else { // Fixup the byte later - fixup(FU_WBYTE|FU_SEXT|FU_PCREL, sloc, aNexpr); - D_word(w); - } - break; - case IMMED: - switch(siz) { - case SIZB: - if(w) { - if(tdb) - return(error("illegal byte-sized relative reference")); - if(v + 0x100 >= 0x200) - return(error(range_error)); - D_word(v); - } else { - fixup(FU_BYTE|FU_SEXT, sloc+1, aNexpr); - D_word(0); - } - break; - case SIZW: - case SIZN: - if(w) { - if(tdb) - rmark(cursect, sloc, tdb, MWORD, NULL); - if(v + 0x10000 >= 0x20000) - return(error(range_error)); - D_word(v); - } else { - fixup(FU_WORD|FU_SEXT, sloc, aNexpr); - D_word(0); - } - break; - case SIZL: - if(w) { - if(tdb) - rmark(cursect, sloc, tdb, MLONG, NULL); - D_long(v); - } else { - fixup(FU_LONG, sloc, aNexpr); - D_long(0); - } - break; - default: - interror(1); // IMMED size problem - } - break; - case ABSW: - if(w) { - if(tdb) - rmark(cursect, sloc, tdb, MWORD, NULL); - if(v + 0x8000 >= 0x10000) - return(error(range_error)); - D_word(v); - } else { - fixup(FU_WORD|FU_SEXT, sloc, aNexpr); - D_word(0); - } - break; - case ABSL: - if(w) { - if(tdb) - rmark(cursect, sloc, tdb, MLONG, NULL); - D_long(v); - } else { - fixup(FU_LONG, sloc, aNexpr); - D_long(0); - } - break; - case ABASE: - case MEMPOST: - case MEMPRE: - case PCBASE: - case PCMPOST: - case PCMPRE: - return(error("unsupported 68020 addressing mode")); - default: - interror(3); // Bad addressing mode in ea gen - } - - return(OK); + WORD w; + VALUE v; + WORD tdb; + + v = aNexval; + w = (WORD)(aNexattr & DEFINED); + tdb = (WORD)(aNexattr & TDB); + + switch (amN) + { + case DREG: // "Do nothing" - they're in the opword + case AREG: + case AIND: + case APOSTINC: + case APREDEC: + case AM_USP: + case AM_CCR: + case AM_SR: + case AM_NONE: + break; // This is a performance hit, though + case ADISP: // expr(An) + if (w) + { // Just deposit it + if (tdb) + rmark(cursect, sloc, tdb, MWORD, NULL); + + if (v + 0x8000 >= 0x18000) + return error(range_error); + + D_word(v); + } + else + { // Arrange for fixup later on + fixup(FU_WORD|FU_SEXT, sloc, aNexpr); + D_word(0); + } + + break; + case PCDISP: + if (w) + { // Just deposit it + if ((aNexattr & TDB) == cursect) + v -= (VALUE)sloc; + else if ((aNexattr & TDB) != ABS) + error(rel_error); + + if (v + 0x8000 >= 0x10000) + return error(range_error); + + D_word(v); + } + else + { // Arrange for fixup later on + fixup(FU_WORD|FU_SEXT|FU_PCREL, sloc, aNexpr); + D_word(0); + } + + break; + case AINDEXED: + w = (WORD)((aNixreg << 12) | aNixsiz); // Compute ixreg and size+scale + + if (aNexattr & DEFINED) + { // Deposit a byte... + if (tdb) + return error(abs_error); // Can't mark bytes + + if (v + 0x80 >= 0x180) + return error(range_error); + + w |= v & 0xff; + D_word(w); + } + else + { // Fixup the byte later + fixup(FU_BYTE|FU_SEXT, sloc+1, aNexpr); + D_word(w); + } + + break; + case PCINDEXED: + w = (WORD)((aNixreg << 12) | aNixsiz); // Compute ixreg and size+scale + + if (aNexattr & DEFINED) + { // Deposit a byte... + if ((aNexattr & TDB) == cursect) + v -= (VALUE)sloc; + else if ((aNexattr & TDB) != ABS) + error(rel_error); + + if (v + 0x80 >= 0x100) + return error(range_error); + + w |= v & 0xff; + D_word(w); + } + else + { // Fixup the byte later + fixup(FU_WBYTE|FU_SEXT|FU_PCREL, sloc, aNexpr); + D_word(w); + } + + break; + case IMMED: + switch (siz) + { + case SIZB: + if (w) + { + if (tdb) + return error("illegal byte-sized relative reference"); + + if (v + 0x100 >= 0x200) + return error(range_error); + + D_word(v); + } + else + { + fixup(FU_BYTE|FU_SEXT, sloc+1, aNexpr); + D_word(0); + } + + break; + case SIZW: + case SIZN: + if (w) + { + if (tdb) + rmark(cursect, sloc, tdb, MWORD, NULL); + + if (v + 0x10000 >= 0x20000) + return error(range_error); + + D_word(v); + } + else + { + fixup(FU_WORD|FU_SEXT, sloc, aNexpr); + D_word(0); + } + + break; + case SIZL: + if (w) + { + if (tdb) + rmark(cursect, sloc, tdb, MLONG, NULL); + + D_long(v); + } + else + { + fixup(FU_LONG, sloc, aNexpr); + D_long(0); + } + + break; + default: + interror(1); // IMMED size problem + } + + break; + case ABSW: + if (w) + { + if (tdb) + rmark(cursect, sloc, tdb, MWORD, NULL); + + if (v + 0x8000 >= 0x10000) + return error(range_error); + + D_word(v); + } + else + { + fixup(FU_WORD|FU_SEXT, sloc, aNexpr); + D_word(0); + } + + break; + case ABSL: + if (w) + { + if (tdb) + rmark(cursect, sloc, tdb, MLONG, NULL); + + D_long(v); + } + else + { + fixup(FU_LONG, sloc, aNexpr); + D_long(0); + } + + break; + case ABASE: + case MEMPOST: + case MEMPRE: + case PCBASE: + case PCMPOST: + case PCMPRE: + return error("unsupported 68020 addressing mode"); + default: + interror(3); // Bad addressing mode in ea gen + } + + return OK; } // Undefine dirty macros diff --git a/error.c b/error.c index c831d73..c73cec5 100644 --- a/error.c +++ b/error.c @@ -90,7 +90,7 @@ int error(char * s) taglist('E'); ++errcnt; - return(ERROR); + return ERROR; } int errors(char * s, char * s1) @@ -114,7 +114,7 @@ int errors(char * s, char * s1) taglist('E'); ++errcnt; - return(ERROR); + return ERROR; } int warn(char * s) @@ -135,7 +135,7 @@ int warn(char * s) taglist('W'); - return(OK); + return OK; } int warns(char * s, char * s1) @@ -158,7 +158,7 @@ int warns(char * s, char * s1) taglist('W'); - return(OK); + return OK; } int warni(char * s, unsigned i) @@ -181,7 +181,7 @@ int warni(char * s, unsigned i) taglist('W'); - return(OK); + return OK; } int fatal(char * s) diff --git a/error.h b/error.h index 2e67284..7754792 100644 --- a/error.h +++ b/error.h @@ -15,7 +15,7 @@ // Globals, externals etc extern int errcnt; -extern char *err_fname; +extern char * err_fname; // Prototypes int error(char *); diff --git a/expr.c b/expr.c index 5438ff6..e7a5062 100644 --- a/expr.c +++ b/expr.c @@ -25,541 +25,655 @@ static WORD evattr[EVSTACKSIZE]; // Evaluator attribu // Token-class initialization list char itokcl[] = { - 0, // END - CONST, SYMBOL, 0, // ID - '(', '[', '{', 0, // OPAR - ')', ']', '}', 0, // CPAR - CR_DEFINED, CR_REFERENCED, // SUNARY (special unary) - CR_STREQ, CR_MACDEF, - CR_DATE, CR_TIME, 0, - '!', '~', UNMINUS, 0, // UNARY - '*', '/', '%', 0, // MULT - '+', '-', 0, // ADD - SHL, SHR, 0, // SHIFT - LE, GE, '<', '>', NE, '=', 0, // REL - '&', 0, // AND - '^', 0, // XOR - '|', 0, // OR - 1 // (the end) + 0, // END + CONST, SYMBOL, 0, // ID + '(', '[', '{', 0, // OPAR + ')', ']', '}', 0, // CPAR + CR_DEFINED, CR_REFERENCED, // SUNARY (special unary) + CR_STREQ, CR_MACDEF, + CR_DATE, CR_TIME, 0, + '!', '~', UNMINUS, 0, // UNARY + '*', '/', '%', 0, // MULT + '+', '-', 0, // ADD + SHL, SHR, 0, // SHIFT + LE, GE, '<', '>', NE, '=', 0, // REL + '&', 0, // AND + '^', 0, // XOR + '|', 0, // OR + 1 // (the end) }; char missym_error[] = "missing symbol"; -char *str_error = "missing symbol or string"; +char * str_error = "missing symbol or string"; // Convert expression to postfix -static TOKEN *tk; // Deposit tokens here -SYM *lookup(); -SYM *newsym(); +static TOKEN * tk; // Deposit tokens here +SYM * lookup(); +SYM * newsym(); + // -// --- Obtain a String Value ----------------------------------------------------------------------- +// Obtain a String Value // +static VALUE str_value(char * p) +{ + VALUE v; -static VALUE str_value(char *p) { - VALUE v; + for(v=0; *p; ++p) + v = (v << 8) | (*p & 0xFF); - for(v = 0; *p; ++p) - v = (v << 8) | (*p & 0xff); - return(v); + return v; } + // -// --- Initialize Expression Analyzer -------------------------------------------------------------- +// Initialize Expression Analyzer // - -void init_expr(void) { - int i; // Iterator - char *p; // Token pointer - - // Initialize token-class table - for(i = 0; i < 128; ++i) // Mark all entries END - tokcl[i] = END; - - for(i = 0, p = itokcl; *p != 1; ++p) - if(*p == 0) - ++i; - else - tokcl[(int)(*p)] = (char)i; +void init_expr(void) +{ + int i; // Iterator + char * p; // Token pointer + + // Initialize token-class table + for(i=0; i<128; ++i) // Mark all entries END + tokcl[i] = END; + + for(i=0, p=itokcl; *p!=1; ++p) + { + if (*p == 0) + ++i; + else + tokcl[(int)(*p)] = (char)i; + } } + // -// --- Binary operators (all the same precedence) -------------------------------------------------- +// Binary operators (all the same precedence) // +int expr0(void) +{ + TOKEN t; -int expr0(void) { - TOKEN t; - - if(expr1() != OK) - return(ERROR); - while(tokcl[*tok] >= MULT) { - t = *tok++; - if(expr1() != OK) - return(ERROR); - *tk++ = t; - } - return(OK); -} + if (expr1() != OK) + return ERROR; + + while (tokcl[*tok] >= MULT) + { + t = *tok++; -// -// --- Unary operators (detect unary '-') ---------------------------------------------------------- -// + if (expr1() != OK) + return ERROR; -int expr1(void) { - int class; - TOKEN t; - SYM *sy; - char *p, *p2; - WORD w; - int j; - - class = tokcl[*tok]; - - if(*tok == '-' || class == UNARY) { - t = *tok++; - if(expr2() != OK) - return(ERROR); - if(t == '-') - t = UNMINUS; - *tk++ = t; - } else if(class == SUNARY) - switch((int)*tok++) { - case CR_TIME: - *tk++ = CONST; - *tk++ = dos_time(); - break; - case CR_DATE: - *tk++ = CONST; - *tk++ = dos_date(); - break; - case CR_MACDEF: // ^^macdef - if(*tok++ != SYMBOL) return(error(missym_error)); - p = (char *)*tok++; - if(lookup(p, MACRO, 0) == NULL) w = 0; - else w = 1; - - *tk++ = CONST; - *tk++ = (TOKEN)w; - break; - case CR_DEFINED: - w = DEFINED; - goto getsym; - case CR_REFERENCED: - w = REFERENCED; - - getsym: - - if(*tok++ != SYMBOL) return(error(missym_error)); - p = (char *)*tok++; - j = 0; - if(*p == '.') j = curenv; - if((sy = lookup(p, LABEL, j)) != NULL && (sy->sattr & w)) w = 1; - else w = 0; - - *tk++ = CONST; - *tk++ = (TOKEN)w; - break; - case CR_STREQ: - if(*tok != SYMBOL && *tok != STRING) return(error(str_error)); - p = (char *)tok[1]; - tok +=2; - - if(*tok++ != ',') return(error(comma_error)); - - if(*tok != SYMBOL && *tok != STRING) return(error(str_error)); - p2 = (char *)tok[1]; - tok += 2; - - w = (WORD)(!strcmp(p, p2)); - *tk++ = CONST; - *tk++ = (TOKEN)w; - break; - } - else - return(expr2()); + *tk++ = t; + } - return(OK); + return OK; } + // -// --- Terminals (CONSTs) and parenthesis grouping ------------------------------------------------- +// Unary operators (detect unary '-') // +int expr1(void) +{ + int class; + TOKEN t; + SYM * sy; + char * p, * p2; + WORD w; + int j; + + class = tokcl[*tok]; + + if (*tok == '-' || class == UNARY) + { + t = *tok++; + + if (expr2() != OK) + return ERROR; + + if (t == '-') + t = UNMINUS; + + *tk++ = t; + } + else if (class == SUNARY) + { + switch ((int)*tok++) + { + case CR_TIME: + *tk++ = CONST; + *tk++ = dos_time(); + break; + case CR_DATE: + *tk++ = CONST; + *tk++ = dos_date(); + break; + case CR_MACDEF: // ^^macdef + if (*tok++ != SYMBOL) + return error(missym_error); + + p = (char *)*tok++; + + if (lookup(p, MACRO, 0) == NULL) + w = 0; + else + w = 1; + + *tk++ = CONST; + *tk++ = (TOKEN)w; + break; + case CR_DEFINED: + w = DEFINED; + goto getsym; + case CR_REFERENCED: + w = REFERENCED; +getsym: + if (*tok++ != SYMBOL) + return error(missym_error); + + p = (char *)*tok++; + j = 0; + + if (*p == '.') + j = curenv; + + if ((sy = lookup(p, LABEL, j)) != NULL && (sy->sattr & w)) + w = 1; + else + w = 0; + + *tk++ = CONST; + *tk++ = (TOKEN)w; + break; + case CR_STREQ: + if (*tok != SYMBOL && *tok != STRING) + return error(str_error); + + p = (char *)tok[1]; + tok +=2; + + if (*tok++ != ',') + return error(comma_error); + + if (*tok != SYMBOL && *tok != STRING) + return error(str_error); + + p2 = (char *)tok[1]; + tok += 2; + + w = (WORD)(!strcmp(p, p2)); + *tk++ = CONST; + *tk++ = (TOKEN)w; + break; + } + } + else + return expr2(); -int expr2(void) { - char *p; - SYM *sy; - int j; - - switch((int)*tok++) { - case CONST: - *tk++ = CONST; - *tk++ = *tok++; - break; - case SYMBOL: - p = (char *)*tok++; - j = 0; - if(*p == '.') - j = curenv; - sy = lookup(p, LABEL, j); - if(sy == NULL) - sy = newsym(p, LABEL, j); - - if(sy->sattre & EQUATEDREG) { // Check register bank usage - if((regbank == BANK_0) && (sy->sattre & BANK_1) && !altbankok) - warns("equated symbol \'%s\' cannot be used in register bank 0", sy->sname); - if((regbank == BANK_1) && (sy->sattre & BANK_0) && !altbankok) - warns("equated symbol \'%s\' cannot be used in register bank 1", sy->sname); - } - - *tk++ = SYMBOL; - *tk++ = (TOKEN)sy; - break; - case STRING: - *tk++ = CONST; - *tk++ = str_value((char *)*tok++); - break; - case '(': - if(expr0() != OK) - return(ERROR); - if(*tok++ != ')') - return(error("missing close parenthesis ')'")); - break; - case '[': - if(expr0() != OK) - return(ERROR); - if(*tok++ != ']') - return(error("missing close parenthesis ']'")); - break; - case '$': - *tk++ = ACONST; // Attributed const - *tk++ = sloc; // Current location - *tk++ = cursect | DEFINED; // Store attribs - break; - case '*': - *tk++ = ACONST; // Attributed const - if(orgactive) - *tk++ = orgaddr; - else - *tk++ = pcloc; // Location at start of line - *tk++ = ABS | DEFINED; // Store attribs - break; - default: - return(error("bad expression")); - } - return(OK); + return OK; } + // -// --- Recursive-descent expression analyzer (with some simple speed hacks) ------------------------ +// Terminals (CONSTs) and parenthesis grouping // +int expr2(void) +{ + char * p; + SYM * sy; + int j; + + switch ((int)*tok++) + { + case CONST: + *tk++ = CONST; + *tk++ = *tok++; + break; + case SYMBOL: + p = (char *)*tok++; + j = 0; + + if (*p == '.') + j = curenv; + + sy = lookup(p, LABEL, j); + + if (sy == NULL) + sy = newsym(p, LABEL, j); + + // Check register bank usage + if (sy->sattre & EQUATEDREG) + { + if ((regbank == BANK_0) && (sy->sattre & BANK_1) && !altbankok) + warns("equated symbol \'%s\' cannot be used in register bank 0", sy->sname); + + if ((regbank == BANK_1) && (sy->sattre & BANK_0) && !altbankok) + warns("equated symbol \'%s\' cannot be used in register bank 1", sy->sname); + } + + *tk++ = SYMBOL; + *tk++ = (TOKEN)sy; + break; + case STRING: + *tk++ = CONST; + *tk++ = str_value((char *)*tok++); + break; + case '(': + if (expr0() != OK) + return ERROR; + + if (*tok++ != ')') + return error("missing close parenthesis ')'"); + + break; + case '[': + if (expr0() != OK) + return ERROR; + + if (*tok++ != ']') + return error("missing close parenthesis ']'"); + + break; + case '$': + *tk++ = ACONST; // Attributed const + *tk++ = sloc; // Current location + *tk++ = cursect | DEFINED; // Store attribs + break; + case '*': + *tk++ = ACONST; // Attributed const + + if (orgactive) + *tk++ = orgaddr; + else + *tk++ = pcloc; // Location at start of line + + *tk++ = ABS | DEFINED; // Store attribs + break; + default: + return error("bad expression"); + } + + return OK; +} -int expr(TOKEN *otk, VALUE *a_value, WORD *a_attr, SYM **a_esym) { - SYM *sy; - char *p; - int j; - tk = otk; - - // Optimize for single constant or single symbol. - if((tok[1] == EOL) || - (((*tok == CONST || *tok == SYMBOL) || (*tok >= KW_R0 && *tok <= KW_R31)) && - (tokcl[tok[2]] < UNARY))) { - - if(*tok >= KW_R0 && *tok <= KW_R31) { - *tk++ = CONST; - *tk++ = *a_value = (*tok - KW_R0); - *a_attr = ABS | DEFINED; - if(a_esym != NULL) - *a_esym = NULL; - tok++; - *tk++ = ENDEXPR; - return(OK); - } else if(*tok == CONST) { - *tk++ = CONST; - *tk++ = *a_value = tok[1]; - *a_attr = ABS | DEFINED; - if(a_esym != NULL) - *a_esym = NULL; - } else if(*tok == '*') { - *tk++ = CONST; - if(orgactive) - *tk++ = *a_value = orgaddr; - else - *tk++ = *a_value = pcloc; - *a_attr = ABS | DEFINED; - //*tk++ = - if(a_esym != NULL) - *a_esym = NULL; - tok--; - } else { - p = (char *)tok[1]; - j = 0; - if(*p == '.') - j = curenv; - sy = lookup(p, LABEL, j); - - if(sy == NULL) - sy = newsym(p, LABEL, j); - sy->sattr |= REFERENCED; - - if(sy->sattre & EQUATEDREG) { // Check register bank usage - if((regbank == BANK_0) && (sy->sattre & BANK_1) && !altbankok) - warns("equated symbol \'%s\' cannot be used in register bank 0", sy->sname); - if((regbank == BANK_1) && (sy->sattre & BANK_0) && !altbankok) - warns("equated symbol \'%s\' cannot be used in register bank 1", sy->sname); - } - - *tk++ = SYMBOL; - *tk++ = (TOKEN)sy; - - if(sy->sattr & DEFINED) - *a_value = sy->svalue; - else *a_value = 0; - - if(sy->sattre & EQUATEDREG) - *a_value &= 0x1F; - - *a_attr = (WORD)(sy->sattr & ~GLOBAL); - - if((sy->sattr & (GLOBAL|DEFINED)) == GLOBAL && a_esym != NULL) { - *a_esym = sy; - } - } - tok += 2; - *tk++ = ENDEXPR; - return(OK); - } - - if(expr0() != OK) - return(ERROR); - *tk++ = ENDEXPR; - return(evexpr(otk, a_value, a_attr, a_esym)); +// +// Recursive-descent expression analyzer (with some simple speed hacks) +// +int expr(TOKEN * otk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) +{ + SYM * sy; + char * p; + int j; + + tk = otk; + + // Optimize for single constant or single symbol. + if ((tok[1] == EOL) + || (((*tok == CONST || *tok == SYMBOL) || (*tok >= KW_R0 && *tok <= KW_R31)) + && (tokcl[tok[2]] < UNARY))) + { + if (*tok >= KW_R0 && *tok <= KW_R31) + { + *tk++ = CONST; + *tk++ = *a_value = (*tok - KW_R0); + *a_attr = ABS | DEFINED; + + if (a_esym != NULL) + *a_esym = NULL; + + tok++; + *tk++ = ENDEXPR; + return OK; + } + else if (*tok == CONST) + { + *tk++ = CONST; + *tk++ = *a_value = tok[1]; + *a_attr = ABS | DEFINED; + + if (a_esym != NULL) + *a_esym = NULL; + } + else if (*tok == '*') + { + *tk++ = CONST; + + if (orgactive) + *tk++ = *a_value = orgaddr; + else + *tk++ = *a_value = pcloc; + + *a_attr = ABS | DEFINED; + //*tk++ = + + if (a_esym != NULL) + *a_esym = NULL; + + tok--; + } + else + { + p = (char *)tok[1]; + j = 0; + + if (*p == '.') + j = curenv; + + sy = lookup(p, LABEL, j); + + if (sy == NULL) + sy = newsym(p, LABEL, j); + + sy->sattr |= REFERENCED; + + // Check register bank usage + if (sy->sattre & EQUATEDREG) + { + if ((regbank == BANK_0) && (sy->sattre & BANK_1) && !altbankok) + warns("equated symbol \'%s\' cannot be used in register bank 0", sy->sname); + + if ((regbank == BANK_1) && (sy->sattre & BANK_0) && !altbankok) + warns("equated symbol \'%s\' cannot be used in register bank 1", sy->sname); + } + + *tk++ = SYMBOL; + *tk++ = (TOKEN)sy; + + if (sy->sattr & DEFINED) + *a_value = sy->svalue; + else + *a_value = 0; + + if (sy->sattre & EQUATEDREG) + *a_value &= 0x1F; + + *a_attr = (WORD)(sy->sattr & ~GLOBAL); + + if ((sy->sattr & (GLOBAL|DEFINED)) == GLOBAL && a_esym != NULL) + *a_esym = sy; + } + + tok += 2; + *tk++ = ENDEXPR; + return OK; + } + + if (expr0() != OK) + return ERROR; + + *tk++ = ENDEXPR; + return evexpr(otk, a_value, a_attr, a_esym); } + // -// ------------------------------------------------------------------------------------------------- // Evaluate expression. -// If the expression involves only ONE external symbol, the expression is UNDEFINED, but it's value -// includes everything but the symbol value, and `a_esym' is set to the external symbol. -// ------------------------------------------------------------------------------------------------- +// If the expression involves only ONE external symbol, the expression is +// UNDEFINED, but it's value includes everything but the symbol value, and +// `a_esym' is set to the external symbol. // - -int evexpr(TOKEN *tk, VALUE *a_value, WORD *a_attr, SYM **a_esym) { - WORD *sattr; - VALUE *sval; - WORD attr; - SYM *sy; - SYM *esym; - WORD sym_seg; - - sval = evstk; // (Empty) initial stack - sattr = evattr; - esym = NULL; // No external symbol involved - sym_seg = 0; - - while(*tk != ENDEXPR) - switch((int)*tk++) { - case SYMBOL: - sy = (SYM *)*tk++; - sy->sattr |= REFERENCED; // Set "referenced" bit - - if(!(sy->sattr & DEFINED)) { - if(!(sy->sattr & GLOBAL)) { // Reference to undefined symbol - *a_attr = 0; - *a_value = 0; - return(OK); - } - if(esym != NULL) // Check for multiple externals - return(error(seg_error)); - esym = sy; - } - - if(sy->sattr & DEFINED) { - *++sval = sy->svalue; // Push symbol's value - } else { - *++sval = 0; // 0 for undefined symbols - } - - *++sattr = (WORD)(sy->sattr & ~GLOBAL); // Push attribs - sym_seg = (WORD)(sy->sattr & (TEXT|DATA|BSS)); - break; - case CONST: - *++sval = *tk++; // Push value - *++sattr = ABS|DEFINED; // Push simple attribs - break; - case ACONST: - *++sval = *tk++; // Push value - *++sattr = (WORD)*tk++; // Push attribs - break; - - // Binary "+" and "-" matrix: - // - // ABS Sect Other - // ---------------------------- - // ABS | ABS | Sect | Other | - // Sect | Sect | [1] | Error | - // Other | Other | Error | [1] | - // ---------------------------- - // - // [1] + : Error - // - : ABS - case '+': - --sval; // Pop value - --sattr; // Pop attrib - *sval += sval[1]; // Compute value - - if(!(*sattr & (TEXT|DATA|BSS))) - *sattr = sattr[1]; - else if(sattr[1] & (TEXT|DATA|BSS)) - return(error(seg_error)); - break; - case '-': - --sval; // Pop value - --sattr; // Pop attrib - *sval -= sval[1]; // Compute value - - attr = (WORD)(*sattr & (TEXT|DATA|BSS)); - if(!attr) - *sattr = sattr[1]; - else if(sattr[1] & (TEXT|DATA|BSS)) { - if(!(attr & sattr[1])) { - return(error(seg_error)); - } else { - *sattr &= ~(TEXT|DATA|BSS); - } - } - break; - // Unary operators only work on ABS items - case UNMINUS: - if(*sattr & (TEXT|DATA|BSS)) - error(seg_error); - *sval = -(int)*sval; - *sattr = ABS|DEFINED; // Expr becomes absolute - break; - case '!': - if(*sattr & (TEXT|DATA|BSS)) - error(seg_error); - *sval = !*sval; - *sattr = ABS|DEFINED; // Expr becomes absolute - break; - case '~': - if(*sattr & (TEXT|DATA|BSS)) - error(seg_error); - *sval = ~*sval; - *sattr = ABS|DEFINED; // Expr becomes absolute - break; - // Comparison operators must have two values that - // are in the same segment, but that's the only requirement. - case LE: - --sattr; - --sval; - if((*sattr & TDB) != (sattr[1] & TDB)) error(seg_error); - *sattr = ABS|DEFINED; - *sval = *sval <= sval[1]; - break; - case GE: - --sattr; - --sval; - if((*sattr & TDB) != (sattr[1] & TDB)) error(seg_error); - *sattr = ABS|DEFINED; - *sval = *sval >= sval[1]; - break; - case '>': - --sattr; - --sval; - if((*sattr & TDB) != (sattr[1] & TDB)) error(seg_error); - *sattr = ABS|DEFINED; - *sval = *sval > sval[1]; - break; - case '<': - --sattr; - --sval; - if((*sattr & TDB) != (sattr[1] & TDB)) error(seg_error); - *sattr = ABS|DEFINED; - *sval = *sval < sval[1]; - break; - case NE: - --sattr; - --sval; - if((*sattr & TDB) != (sattr[1] & TDB)) error(seg_error); - *sattr = ABS|DEFINED; - *sval = *sval != sval[1]; - break; - case '=': - --sattr; - --sval; - if((*sattr & TDB) != (sattr[1] & TDB)) error(seg_error); - *sattr = ABS|DEFINED; - *sval = *sval == sval[1]; - break; - // All other binary operators must have two ABS items - // to work with. They all produce an ABS value. - default: - // GH - Removed for v1.0.15 as part of the fix for indexed loads. - //if((*sattr & (TEXT|DATA|BSS)) || (*--sattr & (TEXT|DATA|BSS))) - //error(seg_error); - - *sattr = ABS|DEFINED; // Expr becomes absolute - switch((int)tk[-1]) { - case '*': - --sval; - --sattr; // Pop attrib - *sval *= sval[1]; - break; - case '/': - --sval; - --sattr; // Pop attrib - if(sval[1] == 0) - return(error("divide by zero")); - *sval /= sval[1]; - break; - case '%': - --sval; - --sattr; // Pop attrib - if(sval[1] == 0) - return(error("mod (%) by zero")); - *sval %= sval[1]; - break; - case SHL: - --sval; - --sattr; // Pop attrib - *sval <<= sval[1]; - break; - case SHR: - --sval; - --sattr; // Pop attrib - *sval >>= sval[1]; - break; - case '&': - --sval; - --sattr; // Pop attrib - *sval &= sval[1]; - break; - case '^': - --sval; - --sattr; // Pop attrib - *sval ^= sval[1]; - break; - case '|': - --sval; - --sattr; // Pop attrib - *sval |= sval[1]; - break; - default: - interror(5); // Bad operator in expression stream - } - } - - if(esym != NULL) *sattr &= ~DEFINED; - if(a_esym != NULL) *a_esym = esym; - - // sym_seg added in 1.0.16 to solve a problem with forward symbols in expressions where absolute - // values also existed. The absolutes were overiding the symbol segments and not being included :( - //*a_attr = *sattr | sym_seg; // Copy value + attrib - - *a_attr = *sattr; // Copy value + attrib - *a_value = *sval; - - return(OK); +int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) +{ + WORD * sattr; + VALUE * sval; + WORD attr; + SYM * sy; + SYM * esym; + WORD sym_seg; + + sval = evstk; // (Empty) initial stack + sattr = evattr; + esym = NULL; // No external symbol involved + sym_seg = 0; + + while (*tk != ENDEXPR) + { + switch ((int)*tk++) + { + case SYMBOL: + sy = (SYM *)*tk++; + sy->sattr |= REFERENCED; // Set "referenced" bit + + if (!(sy->sattr & DEFINED)) + { + if (!(sy->sattr & GLOBAL)) + { // Reference to undefined symbol + *a_attr = 0; + *a_value = 0; + return OK; + } + + if (esym != NULL) // Check for multiple externals + return error(seg_error); + + esym = sy; + } + + if (sy->sattr & DEFINED) + { + *++sval = sy->svalue; // Push symbol's value + } + else + { + *++sval = 0; // 0 for undefined symbols + } + + *++sattr = (WORD)(sy->sattr & ~GLOBAL); // Push attribs + sym_seg = (WORD)(sy->sattr & (TEXT|DATA|BSS)); + break; + case CONST: + *++sval = *tk++; // Push value + *++sattr = ABS|DEFINED; // Push simple attribs + break; + case ACONST: + *++sval = *tk++; // Push value + *++sattr = (WORD)*tk++; // Push attribs + break; + + // Binary "+" and "-" matrix: + // + // ABS Sect Other + // ---------------------------- + // ABS | ABS | Sect | Other | + // Sect | Sect | [1] | Error | + // Other | Other | Error | [1] | + // ---------------------------- + // + // [1] + : Error + // - : ABS + case '+': + --sval; // Pop value + --sattr; // Pop attrib + *sval += sval[1]; // Compute value + + if (!(*sattr & (TEXT|DATA|BSS))) + *sattr = sattr[1]; + else if (sattr[1] & (TEXT|DATA|BSS)) + return error(seg_error); + + break; + case '-': + --sval; // Pop value + --sattr; // Pop attrib + *sval -= sval[1]; // Compute value + + attr = (WORD)(*sattr & (TEXT|DATA|BSS)); + + if (!attr) + *sattr = sattr[1]; + else if (sattr[1] & (TEXT|DATA|BSS)) + { + if (!(attr & sattr[1])) + return error(seg_error); + else + *sattr &= ~(TEXT|DATA|BSS); + } + + break; + // Unary operators only work on ABS items + case UNMINUS: + if (*sattr & (TEXT|DATA|BSS)) + error(seg_error); + + *sval = -(int)*sval; + *sattr = ABS|DEFINED; // Expr becomes absolute + break; + case '!': + if (*sattr & (TEXT|DATA|BSS)) + error(seg_error); + + *sval = !*sval; + *sattr = ABS|DEFINED; // Expr becomes absolute + break; + case '~': + if (*sattr & (TEXT|DATA|BSS)) + error(seg_error); + + *sval = ~*sval; + *sattr = ABS|DEFINED; // Expr becomes absolute + break; + // Comparison operators must have two values that + // are in the same segment, but that's the only requirement. + case LE: + --sattr; + --sval; + + if ((*sattr & TDB) != (sattr[1] & TDB)) + error(seg_error); + + *sattr = ABS|DEFINED; + *sval = *sval <= sval[1]; + break; + case GE: + --sattr; + --sval; + + if ((*sattr & TDB) != (sattr[1] & TDB)) + error(seg_error); + + *sattr = ABS|DEFINED; + *sval = *sval >= sval[1]; + break; + case '>': + --sattr; + --sval; + + if ((*sattr & TDB) != (sattr[1] & TDB)) + error(seg_error); + + *sattr = ABS|DEFINED; + *sval = *sval > sval[1]; + break; + case '<': + --sattr; + --sval; + + if ((*sattr & TDB) != (sattr[1] & TDB)) + error(seg_error); + + *sattr = ABS|DEFINED; + *sval = *sval < sval[1]; + break; + case NE: + --sattr; + --sval; + + if ((*sattr & TDB) != (sattr[1] & TDB)) + error(seg_error); + + *sattr = ABS|DEFINED; + *sval = *sval != sval[1]; + break; + case '=': + --sattr; + --sval; + + if ((*sattr & TDB) != (sattr[1] & TDB)) + error(seg_error); + + *sattr = ABS|DEFINED; + *sval = *sval == sval[1]; + break; + // All other binary operators must have two ABS items + // to work with. They all produce an ABS value. + default: + // GH - Removed for v1.0.15 as part of the fix for indexed loads. + //if ((*sattr & (TEXT|DATA|BSS)) || (*--sattr & (TEXT|DATA|BSS))) + //error(seg_error); + *sattr = ABS|DEFINED; // Expr becomes absolute + + switch ((int)tk[-1]) + { + case '*': + --sval; + --sattr; // Pop attrib + *sval *= sval[1]; + break; + case '/': + --sval; + --sattr; // Pop attrib + + if (sval[1] == 0) + return error("divide by zero"); + + *sval /= sval[1]; + break; + case '%': + --sval; + --sattr; // Pop attrib + + if (sval[1] == 0) + return error("mod (%) by zero"); + + *sval %= sval[1]; + break; + case SHL: + --sval; + --sattr; // Pop attrib + *sval <<= sval[1]; + break; + case SHR: + --sval; + --sattr; // Pop attrib + *sval >>= sval[1]; + break; + case '&': + --sval; + --sattr; // Pop attrib + *sval &= sval[1]; + break; + case '^': + --sval; + --sattr; // Pop attrib + *sval ^= sval[1]; + break; + case '|': + --sval; + --sattr; // Pop attrib + *sval |= sval[1]; + break; + default: + interror(5); // Bad operator in expression stream + } + } + } + + if (esym != NULL) + *sattr &= ~DEFINED; + + if (a_esym != NULL) + *a_esym = esym; + + // sym_seg added in 1.0.16 to solve a problem with forward symbols in + // expressions where absolute values also existed. The absolutes were + // overiding the symbol segments and not being included :( + //*a_attr = *sattr | sym_seg; // Copy value + attrib + + *a_attr = *sattr; // Copy value + attrib + *a_value = *sval; + + return OK; } - - diff --git a/kwgen.c b/kwgen.c index b7682a5..8404d67 100644 --- a/kwgen.c +++ b/kwgen.c @@ -88,7 +88,9 @@ void print_tables(void); void dumptab(char *, char *, int *, int); void traverse(int); -int main(int argc, char **argv) { + +int main(int argc, char ** argv) +{ register int i, /*j,*/ k, w; char *s, *s1; int found1; @@ -102,19 +104,22 @@ int main(int argc, char **argv) { } basename = argv[1]; - for (s = basename, s1 = uppername; *s; ++s, ++s1) + + for(s=basename, s1=uppername; *s; ++s, ++s1) *s1 = (char)toupper(*s); + *s1 = EOS; /* * init tables */ - for (i = 0; i < TABSIZE; ++i) + for(i=0; i= NSTRINGS) panic("name table overflow"); + if (s >= &strpool[STRPOOLSIZ-100]) panic("string table overflow"); } @@ -183,39 +194,39 @@ empty: /* use previous entry + 1 */ */ found1 = 1; - for (k = 1; found1; ++k) + for(k=1; found1; ++k) { found1 = 0; - for (w = 0; w <= nnames; ++w) + for(w=0; w<=nnames; ++w) { - if (w == 0 || - w == nnames || - !nmatch(k-1, namtab[w].nstr, namtab[w-1].nstr)) + if (w == 0 || w == nnames + || !nmatch(k-1, namtab[w].nstr, namtab[w-1].nstr)) { - if (w != 0 && - valid != 0) + if (w != 0 && valid != 0) { wiredown(); if (k > 1) { state = 0; - for (i = 0; i < k-2; ++i) + + for(i=0; i= nnames || - (int)strlen(namtab[w].nstr) < k) + if (w >= nnames || (int)strlen(namtab[w].nstr) < k) { continue; } tab[*(namtab[w].nstr + k-1)] = MARKED; + if (*(namtab[w].nstr + k) == '\0') { accept[*(namtab[w].nstr + k-1)] = namtab[w].nval; } + valid = 1; } } @@ -250,16 +262,17 @@ empty: /* use previous entry + 1 */ * find position for set of characters; * */ -void wiredown(void) { +void wiredown(void) +{ register int base; register int i; - for (base = 0; base < TABSIZE-128; ++base) + for(base=0; base= 128) break; } @@ -267,13 +280,16 @@ void wiredown(void) { if (base >= TABSIZE-128) panic("Cannot build table (won't fit in tables)\n"); - for (i = 0; i < 128; ++i) + for(i=0; i<128; ++i) + { if (tab[i] == MARKED) { ktab[base + i] = MARKED; kaccept[base + i] = accept[i]; kcheck[base + i] = nstates; } + } + kbase[nstates] = base; if (kmax < base) @@ -281,7 +297,8 @@ void wiredown(void) { } -void print_tables(void) { +void print_tables(void) +{ // int i; printf("\n#ifdef DECL_%s\n", uppername); @@ -294,48 +311,58 @@ void print_tables(void) { } -void dumptab(char *tabname, char *tabprefix, int *table, int tabsize) { +void dumptab(char * tabname, char * tabprefix, int * table, int tabsize) +{ int i, j; - printf("\nint %s%s[%d] = {\n", - tabprefix, tabname, tabsize); + printf("\nint %s%s[%d] = {\n", tabprefix, tabname, tabsize); - for (i = j = 0; i < tabsize; ++i) + for(i=j=0; instr, ent2->nstr); } -int nmatch(int len, char *s1, char *s2) { +int nmatch(int len, char * s1, char * s2) +{ while (len--) + { if (*s1++ != *s2++) return 0; + } + return 1; } char nam[128]; -char *pnam; +char * pnam; -void traverse(int state) { +void traverse(int state) +{ register int base, i;//, j; - char *s, c; + char * s, c; if (state == 0) { @@ -346,42 +373,51 @@ void traverse(int state) { } base = kbase[state]; - for (i = 0; i < 128; ++i) + + for(i=0; i<128; ++i) + { if (kcheck[base + i] == state) { *pnam++ = (char)i; *pnam = '\0'; - for (s = nam; *s; ++s) + for(s=nam; *s; ++s) + { if (isupper(*s)) break; + } - if (kaccept[base + i] >= 0 && - !isupper(*s)) + if (kaccept[base + i] >= 0 && !isupper(*s)) { printf("#define\t%s_", uppername); - for (s = nam; (c = *s); ++s) + + for(s=nam; (c=*s); ++s) { if (c == '.') c = '_'; else if ((c >= 'a') && (c <= 'z')) c -= 32; + printf("%c", c); } + printf("\t%d\n", kaccept[base + i]); } if (ktab[base + i] >= 0) traverse(ktab[base + i]); + *--pnam = '\0'; } + } if (state == 0) printf("#endif\n"); } -void panic(char *s) { +void panic(char * s) +{ fprintf(stderr, "Panic: %s\n", s); exit(1); } diff --git a/listing.c b/listing.c index 265f47c..cea150b 100644 --- a/listing.c +++ b/listing.c @@ -4,7 +4,8 @@ // Copyright (C) 199x Landon Dyer, 2011-2012 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source Utilised with the Kind Permission of Landon Dyer -// ------------------------------------------------------------------------------------------------- +// +// -------------------------------------------------------------------------- // 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 // 012345678901234567890123456789012345678901234567890123456789012345678901234567 // filename.... Reboot's Macro Assembler N.N.NN (Unknown) @@ -19,7 +20,7 @@ #include "sect.h" #include "error.h" -char *list_fname; // Listing filename +char * list_fname; // Listing filename char subttl[TITLESIZ]; // Current subtitle int listing; // Listing level int pagelen = 61; // Lines on a page @@ -38,333 +39,387 @@ static char datestr[20]; // Current date dd-m static char timestr[20]; // Current time hh:mm:ss [am|pm] static char buf[IMAGESIZ]; // Buffer for numbers -static char *month[16] = { "", "Jan", "Feb", "Mar", +static char * month[16] = { "", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "", "", "" }; // -// --- Eject the Page (Print Empty Lines), Reset the Line Count and Bump the Page Number ----------- +// Eject the Page (Print Empty Lines), Reset the Line Count and Bump the Page Number // +int eject(void) +{ + if (listing > 0) + { + println("\f"); + nlines = 0; + } -int eject(void) { - if(listing > 0) { - println("\f"); - nlines = 0; - } - return(0); + return 0; } + // -// --- Return GEMDOS Format Date ------------------------------------------------------------------- +// Return GEMDOS Format Date // +VALUE dos_date(void) +{ + VALUE v; + struct tm * tm; + time_t tloc; -VALUE dos_date(void) { - VALUE v; - struct tm *tm; - time_t tloc; - - time(&tloc); - tm = localtime(&tloc); - v = ((tm->tm_year - 80) << 9) | ((tm->tm_mon+1) << 5) | tm->tm_mday; + time(&tloc); + tm = localtime(&tloc); + v = ((tm->tm_year - 80) << 9) | ((tm->tm_mon+1) << 5) | tm->tm_mday; - return(v); + return v; } + // -// --- Return GEMDOS Format Time ------------------------------------------------------------------- +// Return GEMDOS Format Time // - -VALUE dos_time(void) { - VALUE v; - struct tm *tm; - time_t tloc; +VALUE dos_time(void) +{ + VALUE v; + struct tm * tm; + time_t tloc; time(&tloc); tm = localtime(&tloc); v = (tm->tm_hour << 11) | (tm->tm_min) << 5 | tm->tm_sec; - return(v); + return v; } + // -// --- Generate a Time String ---------------------------------------------------------------------- +// Generate a Time String // +void time_string(char * buf, VALUE time) +{ + int hour; + char *ampm; -void time_string(char *buf, VALUE time) { - int hour; - char *ampm; + hour = (time >> 11); - hour = (time >> 11); - if(hour > 12) { - hour -= 12; - ampm = "pm"; - } else ampm = "am"; + if (hour > 12) + { + hour -= 12; + ampm = "pm"; + } + else + ampm = "am"; - sprintf(buf, "%d:%02d:%02d %s", - hour, (int)((time >> 5) & 0x3f), (int)((time & 0x1f) << 1), ampm); + sprintf(buf, "%d:%02d:%02d %s", + hour, (int)((time >> 5) & 0x3F), (int)((time & 0x1F) << 1), ampm); } + // -// --- Generate a Date String ---------------------------------------------------------------------- +// Generate a Date String // - -void date_string(char *buf, VALUE date) { - sprintf(buf, "%d-%s-%d", - (int)(date & 0x1f), month[(date >> 5) & 0xf], (int)((date >> 9) + 1980)); +void date_string(char * buf, VALUE date) +{ + sprintf(buf, "%d-%s-%d", + (int)(date & 0x1F), month[(date >> 5) & 0xF], (int)((date >> 9) + 1980)); } + // -// ------------------------------------------------------------------------------------------------- // Copy `n' Characters from `src' to `dest' (also stops on EOS in src). // Does not null-terminate dest. -// ------------------------------------------------------------------------------------------------- // +void scopy(char *dest, char *src, int len) +{ + if (len < 0) + len = 1000; // Some large number -void scopy(char *dest, char *src, int len) { - if(len < 0) - len = 1000; // Some large number - while(len-- && *src) - *dest++ = *src++; + while (len-- && *src) + *dest++ = *src++; } + // -// ------------------------------------------------------------------------------------------------- -// Transform letters a-f in the address and data columns of the listing to uppercase. (People seem -// to like uppercase hex better in assembly-language listings....) -// ------------------------------------------------------------------------------------------------- +// Transform letters a-f in the address and data columns of the listing to +// uppercase. (People seem to like uppercase hex better in assembly-language +// listings....) // +void uc_ln(char * ln) +{ + int i; + char j; -void uc_ln(char *ln) { - int i; - char j; - - for(i = LOC_COL; i < SRC_COL; ++i) - if((j = ln[i]) >= 'a' && j <= 'f') - ln[i] = (char)(j - 0x20); + for(i=LOC_COL; i= 'a' && j <= 'f') + ln[i] = (char)(j - 0x20); + } } + // -// --- Fill Region `dest' with `len' Characters `c' and Null Terminate the Region ------------------ +// Fill Region `dest' with `len' Characters `c' and Null Terminate the Region // +void lnfill(char * dest, int len, char chr) +{ + while (len--) + *dest++ = chr; -void lnfill(char *dest, int len, char chr) { - while(len--) - *dest++ = chr; - *dest = EOS; + *dest = EOS; } + // -// --- Create Listing File with the Appropriate Name ----------------------------------------------- +// Create Listing File with the Appropriate Name // +void list_setup(void) +{ + char fnbuf[FNSIZ]; + + strcpy(fnbuf, list_fname); -void list_setup(void) { - char fnbuf[FNSIZ]; + if (*fnbuf == EOS) + { + strcpy(fnbuf, firstfname); + fext(fnbuf, ".prn", 1); + } - strcpy(fnbuf, list_fname); - if(*fnbuf == EOS) { - strcpy(fnbuf, firstfname); - fext(fnbuf, ".prn", 1); - } - list_fname = NULL; - - if((list_fd = open(fnbuf, _OPEN_FLAGS, _PERM_MODE)) < 0) - cantcreat(fnbuf); + list_fname = NULL; + + if ((list_fd = open(fnbuf, _OPEN_FLAGS, _PERM_MODE)) < 0) + cantcreat(fnbuf); } + +// +// Tag Listing with a Character, Typically for Errors or Warnings // -// --- Tag Listing with a Character, Typically for Errors or Warnings ------------------------------ - -void taglist(char chr) { - lnimage[TAG_COL+1] = chr; +void taglist(char chr) +{ + lnimage[TAG_COL+1] = chr; } + // -// --- Print a Line to the Listing File ------------------------------------------------------------ +// Print a Line to the Listing File // +void println(char * ln) +{ + unsigned int length; -void println(char *ln) { - unsigned int length; - - if(list_fname != NULL) // Create listing file, if necessary - list_setup(); + if (list_fname != NULL) // Create listing file, if necessary + list_setup(); - length = strlen(ln); - write(list_fd, ln, length); - write(list_fd, "\n", 1L); + length = strlen(ln); + write(list_fd, ln, length); + write(list_fd, "\n", 1L); } + // -// --- Ship Line `ln' Out; Do Page Breaks and Title Stuff ------------------------------------------ -// - -void ship_ln(char *ln) { - // If listing level is <= 0, then don't print anything - if(listing <= 0) - return; - - // Notice bottom of page - if(nlines >= pagelen - BOT_MAR) - eject(); - - // Print title, boilerplate, and subtitle at top of page - if(nlines == 0) { - ++pageno; - println(""); - date_string(datestr, dos_date()); - time_string(timestr, dos_time()); - sprintf(buf, - "%-40s%-20s Page %-4d %s %s RMAC %01i.%01i.%02i (%s)", - title, curfname, pageno, timestr, datestr, MAJOR, MINOR, PATCH, PLATFORM); - println(buf); - sprintf(buf, "%s", subttl); - println(buf); - println(""); - nlines = 4; - } - - println(ln); - ++nlines; +// Ship Line `ln' Out; Do Page Breaks and Title Stuff +// +void ship_ln(char * ln) +{ + // If listing level is <= 0, then don't print anything + if (listing <= 0) + return; + + // Notice bottom of page + if (nlines >= pagelen - BOT_MAR) + eject(); + + // Print title, boilerplate, and subtitle at top of page + if (nlines == 0) + { + ++pageno; + println(""); + date_string(datestr, dos_date()); + time_string(timestr, dos_time()); + sprintf(buf, + "%-40s%-20s Page %-4d %s %s RMAC %01i.%01i.%02i (%s)", + title, curfname, pageno, timestr, datestr, MAJOR, MINOR, PATCH, PLATFORM); + println(buf); + sprintf(buf, "%s", subttl); + println(buf); + println(""); + nlines = 4; + } + + println(ln); + ++nlines; } + // -// --- Initialize Listing Generator ---------------------------------------------------------------- +// Initialize Listing Generator // - -void init_list(void) { +void init_list(void) +{ extern VALUE dos_date(), dos_time(); - subflag = 0; - pageno = 0; - nlines = 0; - pagelen = 61; - pagewidth = 132; - strcpy(title, ""); - strcpy(subttl, ""); - date_string(datestr, dos_date()); - time_string(timestr, dos_time()); + subflag = 0; + pageno = 0; + nlines = 0; + pagelen = 61; + pagewidth = 132; + strcpy(title, ""); + strcpy(subttl, ""); + date_string(datestr, dos_date()); + time_string(timestr, dos_time()); } + // -// --- Listing EOL --------------------------------------------------------------------------------- -// - -void listeol(void) { - CHUNK *ch; - char *p; - int col; - LONG count; - int fixcount; - - DEBUG printf("~list: lsloc=$%ux sloc=$%ux\n", lsloc, sloc); - - if(lsloc != sloc) { - sprintf(buf, "%08ux", lsloc); - scopy(lnimage+LOC_COL, buf, 8); - } - - if(llineno != curlineno) { - sprintf(buf, "%5d", llineno); - scopy(lnimage+LN_COL, buf, 5); - } - - // List bytes only when section stayed the same and the section is not a "no-data" (SBSS) - // section. An extra annoyance is caused by "ds.b" in a microprocessor mode, which prints - // out bytes of zero as if they had been deposited with dcb. The fix (kludge) is an extra - // variable which records the fact that a 'ds.x' directive generated all the data, and it - // shouldn't be listed - savsect(); // Update section variables - if(lcursect == cursect && (sect[lcursect].scattr & SBSS) == 0 && lsloc != sloc && just_bss==0) { - ch = sect[lcursect].sfcode; - for(; ch != NULL; ch = ch->chnext) - if(lsloc >= ch->chloc && lsloc < (ch->chloc + ch->ch_size)) - break; - - if(ch == NULL) { // Fatal: Can't find chunk holding code - - nochunk: - - interror(6); // Can't find generated code in section - } - - p = ch->chptr + (lsloc - ch->chloc); - col = DATA_COL; - fixcount = 0; - for(count = sloc - lsloc; count--; col += 2, ++lsloc) { - if(col >= DATA_END) { // Ship the line - col = DATA_COL; - uc_ln(lnimage); - ship_ln(lnimage); - lnfill(lnimage, SRC_COL, SPACE); // Fill with spaces - sprintf(buf, "%08ux", lsloc); - scopy(lnimage+LOC_COL, buf, 8); - } - - if(lsloc >= (ch->chloc + ch->ch_size)) { - if((ch = ch->chnext) == NULL) - goto nochunk; - p = ch->chptr; - } - - if(!fixcount) - fixcount = fixtest(lcursect, lsloc); - - if(fixcount) { - --fixcount; - strcpy(buf, "xx"); - ++p; // Advance anyway - } else - sprintf(buf, "%02x", *p++ & 0xff); - scopy(lnimage+col, buf, 2); - } - - if(col > DATA_COL) { // Flush partial line - uc_ln(lnimage); - ship_ln(lnimage); - } - } else { - uc_ln(lnimage); - ship_ln(lnimage); - } +// Listing EOL +// +void listeol(void) +{ + CHUNK * ch; + char * p; + int col; + LONG count; + int fixcount; + + DEBUG printf("~list: lsloc=$%ux sloc=$%ux\n", lsloc, sloc); + + if (lsloc != sloc) + { + sprintf(buf, "%08ux", lsloc); + scopy(lnimage+LOC_COL, buf, 8); + } + + if (llineno != curlineno) + { + sprintf(buf, "%5d", llineno); + scopy(lnimage+LN_COL, buf, 5); + } + + // List bytes only when section stayed the same and the section is not a + // "no-data" (SBSS) section. An extra annoyance is caused by "ds.b" in a + // microprocessor mode, which prints out bytes of zero as if they had been + // deposited with dcb. The fix (kludge) is an extra variable which records + // the fact that a 'ds.x' directive generated all the data, and it + // shouldn't be listed + savsect(); // Update section variables + + if (lcursect == cursect && (sect[lcursect].scattr & SBSS) == 0 + && lsloc != sloc && just_bss == 0) + { + ch = sect[lcursect].sfcode; + + for(; ch!=NULL; ch=ch->chnext) + { + if (lsloc >= ch->chloc && lsloc < (ch->chloc + ch->ch_size)) + break; + } + + // Fatal: Can't find chunk holding code + if (ch == NULL) + { +nochunk: + interror(6); // Can't find generated code in section + } + + p = ch->chptr + (lsloc - ch->chloc); + col = DATA_COL; + fixcount = 0; + + for(count=sloc-lsloc; count--; col+=2, ++lsloc) + { + if (col >= DATA_END) + { // Ship the line + col = DATA_COL; + uc_ln(lnimage); + ship_ln(lnimage); + lnfill(lnimage, SRC_COL, SPACE); // Fill with spaces + sprintf(buf, "%08ux", lsloc); + scopy(lnimage+LOC_COL, buf, 8); + } + + if (lsloc >= (ch->chloc + ch->ch_size)) + { + if ((ch = ch->chnext) == NULL) + goto nochunk; + + p = ch->chptr; + } + + if (!fixcount) + fixcount = fixtest(lcursect, lsloc); + + if (fixcount) + { + --fixcount; + strcpy(buf, "xx"); + ++p; // Advance anyway + } + else + sprintf(buf, "%02x", *p++ & 0xff); + + scopy(lnimage+col, buf, 2); + } + + // Flush partial line + if (col > DATA_COL) + { + uc_ln(lnimage); + ship_ln(lnimage); + } + } + else + { + uc_ln(lnimage); + ship_ln(lnimage); + } } + // -// --- Copy Current (Saved) Line to Output Buffer and Tag it with a Character ---------------------- +// Copy Current (Saved) Line to Output Buffer and Tag it with a Character // +void lstout(char tag) +{ + char * s; + char * d; -void lstout(char tag) { - char *s; - char *d; + lsloc = sloc; + lcursect = cursect; + llineno = curlineno; - lsloc = sloc; - lcursect = cursect; - llineno = curlineno; + lnfill(lnimage, SRC_COL, SPACE); // Fill with spaces + lnimage[TAG_COL] = tag; - lnfill(lnimage, SRC_COL, SPACE); // Fill with spaces - lnimage[TAG_COL] = tag; + // Copy line image and handle control characters + d = lnimage + SRC_COL; - // Copy line image and handle control characters - d = lnimage + SRC_COL; - for(s = lnbuf; *s; ++s) - if(*s >= 0x20 || *s == '\t') - *d++ = *s; - else { - *d++ = '^'; - *d++ = (char)(*s + 0x40); - } - *d++ = EOS; + for(s=lnbuf; *s; ++s) + { + if (*s >= 0x20 || *s == '\t') + *d++ = *s; + else + { + *d++ = '^'; + *d++ = (char)(*s + 0x40); + } + } + + *d++ = EOS; } + // -// --- Output a Value to Listing ------------------------------------------------------------------- +// Output a Value to Listing // - -int listvalue(VALUE v) { - sprintf(buf, "=%08ux", v); - scopy(lnimage+DATA_COL-1, buf, 9); - return(0); +int listvalue(VALUE v) +{ + sprintf(buf, "=%08ux", v); + scopy(lnimage + DATA_COL - 1, buf, 9); + return 0; } + /* * .subttl [-] "string" * @@ -374,42 +429,49 @@ int listvalue(VALUE v) { * o arrange not to print the .subttl directive * */ -int d_subttl(void) { - int ejectok; +int d_subttl(void) +{ + int ejectok; + ejectok = 1; + + if (*tok == '-') + { + ejectok = 0; + ++tok; + } + + if (*tok != STRING) + return error("missing string"); - ejectok = 1; - if(*tok == '-') { - ejectok = 0; - ++tok; - } + strcpy(subttl, (char *)tok[1]); - if(*tok != STRING) - return(error("missing string")); - strcpy(subttl, (char*)tok[1]); + tok += 2; - tok += 2; - if(ejectok && (subflag || pageno > 1)) // Always eject on pages 2+ - eject(); - subflag = 1; + if (ejectok && (subflag || pageno > 1)) // Always eject on pages 2+ + eject(); - return(0); + subflag = 1; + + return 0; } + // -// --- Set title on titles not on the first page, do an eject and clobber the subtitle ------------- +// Set title on titles not on the first page, do an eject and clobber the subtitle // +int d_title(void) +{ + if (*tok != STRING) + return error("missing string"); + + strcpy(title, (char*)tok[1]); + tok += 2; -int d_title(void) { - if(*tok != STRING) - return(error("missing string")); - strcpy(title, (char*)tok[1]); - tok += 2; + if (pageno > 1) + { + strcpy(subttl, ""); + eject(); + } - if(pageno > 1) { - strcpy(subttl, ""); - eject(); - } - - return(0); + return 0; } - diff --git a/mach.c b/mach.c index 90f0471..fac29e3 100644 --- a/mach.c +++ b/mach.c @@ -81,511 +81,653 @@ WORD am_6[] = { 00700, 01700, 02700, 03700, 04700, 05700, 06700, 07700 }; + // Error messages -int m_unimp(void) { return((int)error("unimplemented mnemonic")); } -int m_badmode(void) { return((int)error("inappropriate addressing mode")); } +int m_unimp(void) +{ + return (int)error("unimplemented mnemonic"); +} + + +int m_badmode(void) +{ + return (int)error("inappropriate addressing mode"); +} + + +int m_self(WORD inst) +{ + D_word(inst); + return 0; +} -int m_self(WORD inst) { D_word(inst); return(0);} // -// ------------------------------------------------------------------------------------------------- // Do one EA in bits 0..5 // // Bits in `inst' have the following meaning: // -// Bit zero specifies which ea (ea0 or ea1) to generate in the lower six bits of the instr. +// Bit zero specifies which ea (ea0 or ea1) to generate in the lower six bits +// of the instr. // -// If bit one is set, the OTHER ea (the one that wasn't generated by bit zero) is generated after -// the instruction. Regardless of bit 0's value, ea0 is always deposited in memory before ea1. +// If bit one is set, the OTHER ea (the one that wasn't generated by bit zero) +// is generated after the instruction. Regardless of bit 0's value, ea0 is +// always deposited in memory before ea1. // // If bit two is set, standard size bits are set in the instr in bits 6 and 7. // -// If bit four is set, bit three specifies which eaXreg to place in bits 9..11 of the instr. -// ------------------------------------------------------------------------------------------------- -// - -int m_ea(WORD inst, WORD siz) { - WORD flg; - - flg = inst; // Save flag bits - inst &= ~0x3f; // Clobber flag bits in instr - - if(flg & 4) // Install "standard" instr size bits - inst |= siz_6[siz]; - - if(flg & 16) { // OR-in register number - if(flg & 8) { - inst |= reg_9[a1reg]; // ea1reg in bits 9..11 - } else { - inst |= reg_9[a0reg]; // ea0reg in bits 9..11 - } - } - - if(flg & 1) { // Use am1 - inst |= am1 | a1reg; // Get ea1 into instr - D_word(inst); // Deposit instr - if(flg & 2) // Generate ea0 if requested - ea0gen(siz); - ea1gen(siz); // Generate ea1 - } else { // Use am0 - inst |= am0 | a0reg; // Get ea0 into instr - D_word(inst); // Deposit instr - ea0gen(siz); // Generate ea0 - if(flg & 2) // Generate ea1 if requested - ea1gen(siz); - } - - return(0); +// If bit four is set, bit three specifies which eaXreg to place in bits 9..11 +// of the instr. +// +int m_ea(WORD inst, WORD siz) +{ + WORD flg; + + flg = inst; // Save flag bits + inst &= ~0x3f; // Clobber flag bits in instr + + if (flg & 4) // Install "standard" instr size bits + inst |= siz_6[siz]; + + if (flg & 16) + { // OR-in register number + if (flg & 8) + { + inst |= reg_9[a1reg]; // ea1reg in bits 9..11 + } + else + { + inst |= reg_9[a0reg]; // ea0reg in bits 9..11 + } + } + + if (flg & 1) + { // Use am1 + inst |= am1 | a1reg; // Get ea1 into instr + D_word(inst); // Deposit instr + + if (flg & 2) // Generate ea0 if requested + ea0gen(siz); + + ea1gen(siz); // Generate ea1 + } + else + { // Use am0 + inst |= am0 | a0reg; // Get ea0 into instr + D_word(inst); // Deposit instr + ea0gen(siz); // Generate ea0 + + if (flg & 2) // Generate ea1 if requested + ea1gen(siz); + } + + return 0; } + // -// --- Dx,Dy nnnnXXXnssnnnYYY If bit 0 of `inst' is set, install size bits in bits 6..7 ------------ +// Dx,Dy nnnnXXXnssnnnYYY If bit 0 of `inst' is set, install size bits in bits +// 6..7 // - -int m_abcd(WORD inst, WORD siz) { - if(inst & 1) { // Install size bits - --inst; - inst |= siz_6[siz]; - } +int m_abcd(WORD inst, WORD siz) +{ + if (inst & 1) + { // Install size bits + --inst; + inst |= siz_6[siz]; + } - inst |= a0reg | reg_9[a1reg]; - D_word(inst); + inst |= a0reg | reg_9[a1reg]; + D_word(inst); - return(0); + return 0; } + // -// --- {adda} ea,AREG ------------------------------------------------------------------------------ +// {adda} ea,AREG // - -int m_adda(WORD inst, WORD siz) { - inst |= am0 | a0reg | lwsiz_8[siz] | reg_9[a1reg]; - D_word(inst); - ea0gen(siz); // Gen EA +int m_adda(WORD inst, WORD siz) +{ + inst |= am0 | a0reg | lwsiz_8[siz] | reg_9[a1reg]; + D_word(inst); + ea0gen(siz); // Gen EA - return(0); + return 0; } + // -// ------------------------------------------------------------------------------------------------- // If bit 0 of `inst' is 1, install size bits in bits 6..7 of instr. // If bit 1 of `inst' is 1, install a1reg in bits 9..11 of instr. -// ------------------------------------------------------------------------------------------------- // +int m_reg(WORD inst, WORD siz) +{ + if (inst & 1) // Install size bits + inst |= siz_6[siz]; -int m_reg(WORD inst, WORD siz) { - if(inst & 1) // Install size bits - inst |= siz_6[siz]; - if(inst & 2) // Install other register (9..11) - inst |= reg_9[a1reg]; + if (inst & 2) // Install other register (9..11) + inst |= reg_9[a1reg]; - inst &= ~7; // Clear off crufty bits - inst |= a0reg; // Install first register - D_word(inst); + inst &= ~7; // Clear off crufty bits + inst |= a0reg; // Install first register + D_word(inst); - return(0); + return 0; } + // -// --- #expr ---------------------------------------------------------------------------------- +// #expr // - -int m_imm(WORD inst, WORD siz) { - D_word(inst); - ea0gen(siz); +int m_imm(WORD inst, WORD siz) +{ + D_word(inst); + ea0gen(siz); - return(0); + return 0; } + // -// --- .b #expr -------------------------------------------------------------------------------- +// .b #expr // - -int m_imm8(WORD inst, WORD siz) { - siz = siz; - D_word(inst); - ea0gen(SIZB); +int m_imm8(WORD inst, WORD siz) +{ + siz = siz; + D_word(inst); + ea0gen(SIZB); - return(0); + return 0; } + // -// --- Dn,Dn ------------------------------------------------------------------------------- +// Dn,Dn // - -int m_shr(WORD inst, WORD siz) { - inst |= reg_9[a0reg] | a1reg | siz_6[siz]; - D_word(inst); +int m_shr(WORD inst, WORD siz) +{ + inst |= reg_9[a0reg] | a1reg | siz_6[siz]; + D_word(inst); - return(0); + return 0; } + // -// --- #n,Dn ------------------------------------------------------------------------------- +// #n,Dn // - -int m_shi(WORD inst, WORD siz) { - inst |= a1reg | siz_6[siz]; +int m_shi(WORD inst, WORD siz) +{ + inst |= a1reg | siz_6[siz]; + + if (a0exattr & DEFINED) + { + if (a0exval > 8) + return error(range_error); - if(a0exattr & DEFINED) { - if(a0exval > 8) - return(error(range_error)); - inst |= (a0exval & 7) << 9; - D_word(inst); - } else { - fixup(FU_QUICK, sloc, a0expr); - D_word(inst); - } + inst |= (a0exval & 7) << 9; + D_word(inst); + } + else + { + fixup(FU_QUICK, sloc, a0expr); + D_word(inst); + } - return(0); + return 0; } + // -// --- {bset, btst, bchg, bclr} -- #immed,ea -- Dn,ea ---------------------------------------------- +// {bset, btst, bchg, bclr} -- #immed,ea -- Dn,ea // - -int m_bitop(WORD inst, WORD siz) { - // Enforce instruction sizes - if(am1 == DREG) { // X,Dn must be .n or .l - if(siz & (SIZB|SIZW)) - return(error(siz_error)); - } else - if(siz & (SIZW|SIZL)) // X,ea must be .n or .b - return error(siz_error); +int m_bitop(WORD inst, WORD siz) +{ + // Enforce instruction sizes + if (am1 == DREG) + { // X,Dn must be .n or .l + if (siz & (SIZB|SIZW)) + return error(siz_error); + } + else if (siz & (SIZW|SIZL)) // X,ea must be .n or .b + return error(siz_error); - // Construct instr and EAs - inst |= am1 | a1reg; - if(am0 == IMMED) { - D_word(inst); - ea0gen(SIZB); // Immediate bit number - } else { - inst |= reg_9[a0reg]; - D_word(inst); - } + // Construct instr and EAs + inst |= am1 | a1reg; - ea1gen(SIZB); // ea to bit-munch + if (am0 == IMMED) + { + D_word(inst); + ea0gen(SIZB); // Immediate bit number + } + else + { + inst |= reg_9[a0reg]; + D_word(inst); + } - return(0); + ea1gen(SIZB); // ea to bit-munch + + return 0; } -int m_dbra(WORD inst, WORD siz) { - VALUE v; - - siz = siz; - inst |= a0reg; - D_word(inst); - if(a1exattr & DEFINED) { - if((a1exattr & TDB) != cursect) - return(error(rel_error)); - v = a1exval - sloc; - - if(v + 0x8000 > 0x10000) - return(error(range_error)); - D_word(v); - } else { - fixup(FU_WORD|FU_PCREL|FU_ISBRA, sloc, a1expr); - D_word(0); - } - - return(0); + +int m_dbra(WORD inst, WORD siz) +{ + VALUE v; + + siz = siz; + inst |= a0reg; + D_word(inst); + + if (a1exattr & DEFINED) + { + if ((a1exattr & TDB) != cursect) + return error(rel_error); + + v = a1exval - sloc; + + if (v + 0x8000 > 0x10000) + return error(range_error); + + D_word(v); + } + else + { + fixup(FU_WORD|FU_PCREL|FU_ISBRA, sloc, a1expr); + D_word(0); + } + + return 0; } + +// +// EXG // -// --- EXG ----------------------------------------------------------------------------------------- -// - -int m_exg(WORD inst, WORD siz) { - int m; - - siz = siz; - if(am0 == DREG && am1 == DREG) - m = 0x0040; // Dn,Dn - else if(am0 == AREG && am1 == AREG) - m = 0x0048; // An,An - else { - if(am0 == AREG) { // Dn,An or An,Dn - m = a1reg; // Get AREG into a1reg - a1reg = a0reg; - a0reg = m; - } - m = 0x0088; - } - inst |= m | reg_9[a0reg] | a1reg; - D_word(inst); - - return(0); +int m_exg(WORD inst, WORD siz) +{ + int m; + + siz = siz; + + if (am0 == DREG && am1 == DREG) + m = 0x0040; // Dn,Dn + else if (am0 == AREG && am1 == AREG) + m = 0x0048; // An,An + else + { + if (am0 == AREG) + { // Dn,An or An,Dn + m = a1reg; // Get AREG into a1reg + a1reg = a0reg; + a0reg = m; + } + + m = 0x0088; + } + + inst |= m | reg_9[a0reg] | a1reg; + D_word(inst); + + return 0; } + // -// --- LINK ---------------------------------------------------------------------------------------- +// LINK // - -int m_link(WORD inst, WORD siz) { - siz = siz; - inst |= a0reg; - D_word(inst); - ea1gen(SIZW); +int m_link(WORD inst, WORD siz) +{ + siz = siz; + inst |= a0reg; + D_word(inst); + ea1gen(SIZW); - return(0); + return 0; } + // -// ------------------------------------------------------------------------------------------------- // Handle MOVE // MOVE // // Optimize MOVE.L #,D0 to a MOVEQ -// ------------------------------------------------------------------------------------------------- -// - -int m_move(WORD inst, int siz) { - // Try to optimize to MOVEQ - if(siz == SIZL && am0 == IMMED && am1 == DREG && (a0exattr & (TDB|DEFINED)) == DEFINED && - a0exval + 0x80 < 0x100) { - m_moveq((WORD)0x7000, (WORD)0); - } else { - inst |= siz_12[siz] | am_6[am1] | reg_9[a1reg] | am0 | a0reg; - - D_word(inst); - if(am0 >= ADISP) ea0gen((WORD)siz); - if(am1 >= ADISP) ea1gen((WORD)siz); - } - - return(0); +// +int m_move(WORD inst, int siz) +{ + // Try to optimize to MOVEQ + if (siz == SIZL && am0 == IMMED && am1 == DREG + && (a0exattr & (TDB|DEFINED)) == DEFINED && a0exval + 0x80 < 0x100) + { + m_moveq((WORD)0x7000, (WORD)0); + } + else + { + inst |= siz_12[siz] | am_6[am1] | reg_9[a1reg] | am0 | a0reg; + + D_word(inst); + + if (am0 >= ADISP) + ea0gen((WORD)siz); + + if (am1 >= ADISP) + ea1gen((WORD)siz); + } + + return 0; } + // -// --- move USP,An -- move An,USP ------------------------------------------------------------------ +// move USP,An -- move An,USP // - -int m_usp(WORD inst, WORD siz) { - siz = siz; - if(am0 == AM_USP) inst |= a1reg; // USP,An - else inst |= a0reg; // An,USP - D_word(inst); +int m_usp(WORD inst, WORD siz) +{ + siz = siz; + + if (am0 == AM_USP) + inst |= a1reg; // USP,An + else + inst |= a0reg; // An,USP - return(0); + D_word(inst); + + return 0; } + // -// --- moveq --------------------------------------------------------------------------------------- +// moveq // - -int m_moveq(WORD inst, WORD siz) { - siz = siz; - if(!(a0exattr & DEFINED)) { // Arrange for future fixup - fixup(FU_BYTE|FU_SEXT, sloc+1, a0expr); - a0exval = 0; - } else - if(a0exval + 0x100 >= 0x200) - return(error(range_error)); +int m_moveq(WORD inst, WORD siz) +{ + siz = siz; - inst |= reg_9[a1reg] | (a0exval & 0xff); - D_word(inst); + if (!(a0exattr & DEFINED)) + { // Arrange for future fixup + fixup(FU_BYTE|FU_SEXT, sloc+1, a0expr); + a0exval = 0; + } + else if (a0exval + 0x100 >= 0x200) + return error(range_error); - return(0); + inst |= reg_9[a1reg] | (a0exval & 0xff); + D_word(inst); + + return 0; } + +// +// movep Dn,disp(An) -- movep disp(An),Dn // -// --- movep Dn,disp(An) -- movep disp(An),Dn ------------------------------------------------------ -// - -int m_movep(WORD inst, WORD siz) { - //WORD k; - - if(siz == SIZL) - inst |= 0x0040; - - if(am0 == DREG) { - inst |= reg_9[a0reg] | a1reg; - D_word(inst); - if(am1 == AIND) { - D_word(0); - } else - ea1gen(siz); - } else { - inst |= reg_9[a1reg] | a0reg; - D_word(inst); - if(am0 == AIND) { - D_word(0); - } else - ea0gen(siz); - } - - return(0); +int m_movep(WORD inst, WORD siz) +{ + //WORD k; + + if (siz == SIZL) + inst |= 0x0040; + + if (am0 == DREG) + { + inst |= reg_9[a0reg] | a1reg; + D_word(inst); + + if (am1 == AIND) + { + D_word(0); + } + else + ea1gen(siz); + } + else + { + inst |= reg_9[a1reg] | a0reg; + D_word(inst); + + if (am0 == AIND) + { + D_word(0); + } + else + ea0gen(siz); + } + + return 0; } + // -// --- Bcc -- BSR ---------------------------------------------------------------------------------- -// - -int m_br(WORD inst, WORD siz) { - VALUE v; - - if(a0exattr & DEFINED) { - if((a0exattr & TDB) != cursect) - return(error(rel_error)); - - v = a0exval - (sloc + 2); - - // Optimize branch instr. size - if(siz == SIZN) { - if(v != 0 && v + 0x80 < 0x100) { // Fits in .B - inst |= v & 0xff; - D_word(inst); - return(0); - } else { // Fits in .W - if(v + 0x8000 > 0x10000) - return(error(range_error)); - D_word(inst); - D_word(v); - return(0); - } - } - - if(siz == SIZB) { - if(v + 0x80 >= 0x100) - return(error(range_error)); - inst |= v & 0xff; - D_word(inst); - } else { - if(v + 0x8000 >= 0x10000) - return(error(range_error)); - D_word(inst); - D_word(v); - } - return(0); - } else - if(siz == SIZN) - siz = SIZW; - - if(siz == SIZB) { // .B - fixup(FU_BBRA|FU_PCREL|FU_SEXT, sloc, a0expr); - D_word(inst); - return(0); - } else { // .W - D_word(inst); - fixup(FU_WORD|FU_PCREL|FU_LBRA|FU_ISBRA, sloc, a0expr); - D_word(0); - } - - return(0); +// Bcc -- BSR +// +int m_br(WORD inst, WORD siz) +{ + VALUE v; + + if (a0exattr & DEFINED) + { + if ((a0exattr & TDB) != cursect) + return error(rel_error); + + v = a0exval - (sloc + 2); + + // Optimize branch instr. size + if (siz == SIZN) + { + if (v != 0 && v + 0x80 < 0x100) + { // Fits in .B + inst |= v & 0xff; + D_word(inst); + return 0; + } + else + { // Fits in .W + if (v + 0x8000 > 0x10000) + return error(range_error); + + D_word(inst); + D_word(v); + return 0; + } + } + + if (siz == SIZB) + { + if (v + 0x80 >= 0x100) + return error(range_error); + + inst |= v & 0xff; + D_word(inst); + } + else + { + if (v + 0x8000 >= 0x10000) + return error(range_error); + + D_word(inst); + D_word(v); + } + + return 0; + } + else if (siz == SIZN) + siz = SIZW; + + if (siz == SIZB) + { // .B + fixup(FU_BBRA|FU_PCREL|FU_SEXT, sloc, a0expr); + D_word(inst); + return 0; + } + else + { // .W + D_word(inst); + fixup(FU_WORD|FU_PCREL|FU_LBRA|FU_ISBRA, sloc, a0expr); + D_word(0); + } + + return 0; } + // -// --- ADDQ -- SUBQ -------------------------------------------------------------------------------- +// ADDQ -- SUBQ // - -int m_addq(WORD inst, WORD siz) { - inst |= siz_6[siz] | am1 | a1reg; +int m_addq(WORD inst, WORD siz) +{ + inst |= siz_6[siz] | am1 | a1reg; + + if (a0exattr & DEFINED) + { + if (a0exval > 8 || a0exval == 0) // Range in 1..8 + return error(range_error); - if(a0exattr & DEFINED) { - if(a0exval > 8 || a0exval == 0) // Range in 1..8 - return(error(range_error)); - inst |= (a0exval & 7) << 9; - D_word(inst); - } else { - fixup(FU_QUICK, sloc, a0expr); - D_word(inst); - } - ea1gen(siz); + inst |= (a0exval & 7) << 9; + D_word(inst); + } + else + { + fixup(FU_QUICK, sloc, a0expr); + D_word(inst); + } - return(0); + ea1gen(siz); + + return 0; } + // -// --- trap #n ------------------------------------------------------------------------------------- +// trap #n // - -int m_trap(WORD inst, WORD siz) { - siz = siz; - if(a0exattr & DEFINED) { - if(a0exattr & TDB) - return(error(abs_error)); - if(a0exval >= 16) - return(error(range_error)); - inst |= a0exval; - D_word(inst); - } else - return(error(undef_error)); +int m_trap(WORD inst, WORD siz) +{ + siz = siz; + + if (a0exattr & DEFINED) + { + if (a0exattr & TDB) + return error(abs_error); - return(0); + if (a0exval >= 16) + return error(range_error); + + inst |= a0exval; + D_word(inst); + } + else + return error(undef_error); + + return 0; } + // -// --- movem ,ea -- movem ea, -------------------------------------------------------- -// - -int m_movem(WORD inst, WORD siz) { - VALUE eval; - WORD i; - WORD w; - WORD rmask; - - if(siz & SIZB) return(error("bad size suffix")); - - if(siz == SIZL) inst |= 0x0040; - - if(*tok == '#') { // Handle #,ea - ++tok; - if(abs_expr(&eval) != OK) return(0); - if(eval >= 0x10000L) return(error(range_error)); - rmask = (WORD)eval; - goto immed1; - } - - if(*tok >= KW_D0 && *tok <= KW_A7) { // ,ea - if(reglist(&rmask) < 0) return(0); - - immed1: - - if(*tok++ != ',') return(error("missing comma")); - if(amode(0) < 0) return(0); - inst |= am0 | a0reg; - - if(!(amsktab[am0] & (C_ALTCTRL|M_APREDEC))) - return(error("invalid addressing mode")); - - // If APREDEC, reverse register mask - if(am0 == APREDEC) { - w = rmask; - rmask = 0; - for(i = 0x8000; i; i >>= 1, w >>= 1) - rmask = (WORD)((rmask << 1) | w & 1); - } - } else { // ea, - if(amode(0) < 0) return(0); - inst |= 0x0400 | am0 | a0reg; - if(*tok++ != ',') return(error("missing comma")); - if(*tok == EOL) return(error("missing register list")); - - if(*tok == '#') { // ea,# - ++tok; - if(abs_expr(&eval) != OK) return(0); - if(eval >= 0x10000) return(error(range_error)); - rmask = (WORD)eval; - } else - if(reglist(&rmask) < 0) return(0); - - if(!(amsktab[am0] & (C_CTRL|M_APOSTINC))) - return(error("invalid addressing mode")); - } - - D_word(inst); - D_word(rmask); - ea0gen(siz); - - return(0); +// movem ,ea -- movem ea, +// +int m_movem(WORD inst, WORD siz) +{ + VALUE eval; + WORD i; + WORD w; + WORD rmask; + + if (siz & SIZB) + return error("bad size suffix"); + + if (siz == SIZL) + inst |= 0x0040; + + if (*tok == '#') + { // Handle #,ea + ++tok; + + if (abs_expr(&eval) != OK) + return 0; + + if (eval >= 0x10000L) + return error(range_error); + + rmask = (WORD)eval; + goto immed1; + } + + if (*tok >= KW_D0 && *tok <= KW_A7) + { // ,ea + if (reglist(&rmask) < 0) + return 0; + +immed1: + if (*tok++ != ',') + return error("missing comma"); + + if (amode(0) < 0) + return 0; + + inst |= am0 | a0reg; + + if (!(amsktab[am0] & (C_ALTCTRL|M_APREDEC))) + return error("invalid addressing mode"); + + // If APREDEC, reverse register mask + if (am0 == APREDEC) + { + w = rmask; + rmask = 0; + + for(i=0x8000; i; i>>=1, w>>=1) + rmask = (WORD)((rmask << 1) | w & 1); + } + } + else + { // ea, + if (amode(0) < 0) + return 0; + + inst |= 0x0400 | am0 | a0reg; + + if (*tok++ != ',') + return error("missing comma"); + + if (*tok == EOL) + return error("missing register list"); + + if (*tok == '#') + { // ea,# + ++tok; + + if (abs_expr(&eval) != OK) + return 0; + + if (eval >= 0x10000) + return error(range_error); + + rmask = (WORD)eval; + } + else if (reglist(&rmask) < 0) + return 0; + + if (!(amsktab[am0] & (C_CTRL|M_APOSTINC))) + return error("invalid addressing mode"); + } + + D_word(inst); + D_word(rmask); + ea0gen(siz); + + return 0; } + // -// --- CLR.x An ==> SUBA.x An,An ------------------------------------------------------------------- +// CLR.x An ==> SUBA.x An,An // - -int m_clra(WORD inst, WORD siz) { - inst |= a0reg | reg_9[a0reg] | lwsiz_8[siz]; - D_word(inst); +int m_clra(WORD inst, WORD siz) +{ + inst |= a0reg | reg_9[a0reg] | lwsiz_8[siz]; + D_word(inst); - return(0); + return 0; } - diff --git a/object.c b/object.c index 1608ede..9a750dd 100644 --- a/object.c +++ b/object.c @@ -15,145 +15,167 @@ LONG symsize = 0; // Size of BSD symbol table LONG strindx = 0x00000004; // BSD string table index -char *strtable; // Pointer to the symbol string table -char *objimage; // Global object image pointer +char * strtable; // Pointer to the symbol string table +char * objimage; // Global object image pointer + // -// --- Add an entry to the BSD symbol table -------------------------------------------------------- +// Add an entry to the BSD symbol table // +char * constr_bsdsymtab(char * buf, SYM * sym, int globflag) +{ + LONG z; // Scratch long + WORD w1; // Scratch word + int w2; // Scratch long -char *constr_bsdsymtab(char *buf, SYM *sym, int globflag) { - LONG z; // Scratch long - WORD w1; // Scratch word - int w2; // Scratch long - - chptr = buf; // Point to buffer for deposit longs - D_long(strindx); // Deposit the symbol string index - - w1 = sym->sattr; // Obtain symbol attribute - w2 = sym->sattre; - z = 0; // Initialise resulting symbol flags - if(w1 & EQUATED) { - z = 0x02000000; // Set equated flag - } else { - switch(w1 & TDB) { - case TEXT: z = 0x04000000; break; // Set TEXT segment flag - case DATA: z = 0x06000000; break; // Set DATA segment flag - case BSS : z = 0x08000000; break; // Set BSS segment flag - } - } - if(globflag) z |= 0x01000000; // Set global flag if requested - D_long(z); // Deposit symbol attribute - - z = sym->svalue; // Obtain symbol value - w1 &= DATA|BSS; // Determine DATA or BSS flag - if(w1) - z += sect[TEXT].sloc; // If DATA or BSS add TEXT segment size - if(w1 & BSS) - z += sect[DATA].sloc; // If BSS add DATA segment size - D_long(z); // Deposit symbol value - - strcpy(strtable + strindx, sym->sname); - - strindx += strlen(sym->sname) + 1; // Incr string index incl null terminate - buf += 12; // Increment buffer to next record - symsize += 12; // Increment symbol table size - - return(buf); -} + chptr = buf; // Point to buffer for deposit longs + D_long(strindx); // Deposit the symbol string index -// -// --- Generate object file ------------------------------------------------------------------------ -// + w1 = sym->sattr; // Obtain symbol attribute + w2 = sym->sattre; + z = 0; // Initialise resulting symbol flags -int object(WORD fd) { - LONG t; // Scratch long - LONG tds; // TEXT & DATA segment size - int i; // Temporary int - CHUNK *cp; // Chunk (for gather) - char *buf; // Scratch area - char *p; // Temporary ptr - LONG ssize; // Size of symbols - LONG trsize, drsize; // Size of relocations - - // Write requested object file... - switch(obj_format) { - case BSD: - ssize = ((LONG)sy_assign(NULL, NULL)); // Assign index numbers to the symbols - tds = sect[TEXT].sloc + sect[DATA].sloc; // Get size of TEXT and DATA segment - buf = malloc(0x400000); // Allocate 4mb object file image memory - if(buf == NULL) { - error("cannot allocate object file memory (in BSD mode)"); - return(ERROR); - } - memset(buf, 0, 0x400000); // Reset allocated memory - objimage = buf; // Set global object image pointer - strtable = malloc(0x200000); // Allocate 2mb scratch buffer - if(strtable == NULL) { - error("cannot allocate string table memory (in BSD mode)"); - return(ERROR); - } - memset(strtable, 0, 0x200000); // Reset allocated memory - - // Build object file header - chptr = buf; // Base of header - t = 0x00000107; - D_long(t); // Magic number - t = sect[TEXT].sloc; // TEXT size - D_long(t); - t = sect[DATA].sloc; // DATA size - D_long(t); - t = sect[BSS].sloc; // BSS size - D_long(t); - t = 0x00000000; - D_long(t); // Symbol size - D_long(t); // First entry (0L) - D_long(t); // TEXT relocation size - D_long(t); // BSD relocation size - - // Construct TEXT and DATA segments (without relocation changes) - p = buf + BSDHDRSIZE; - for(i = TEXT; i <= DATA; ++i) - for(cp = sect[i].sfcode; cp != NULL; cp = cp->chnext) { - copy(p, cp->chptr, cp->ch_size); - p += cp->ch_size; - } - - // Do relocation tables (and make changes to segment data) - p = buf + (BSDHDRSIZE + tds); // Move obj image ptr to reloc info - trsize = bsdmarkimg(p, tds, sect[TEXT].sloc, TEXT);// Do TEXT relocation table - chptr = buf + 24; // Point to relocation hdr entry - D_long(trsize); // Write the relocation table size - p = buf + (BSDHDRSIZE + tds + trsize); // Move obj image ptr to reloc info - drsize = bsdmarkimg(p, tds, sect[TEXT].sloc, DATA);// Do DATA relocation table - chptr = buf + 28; // Point to relocation hdr entry - D_long(drsize); // Write the relocation table size - - p = buf + (BSDHDRSIZE + tds + trsize + drsize); // Point to start of symbol table - sy_assign(p, constr_bsdsymtab); // Build symbol and string tables - chptr = buf + 16; // Point to sym table size hdr entry - D_long(symsize); // Write the symbol table size - - // Point to string table - p = buf + (BSDHDRSIZE + tds + trsize + drsize + symsize); - - memcpy(p, strtable, strindx); // Copy string table to object image - if(buf) free(strtable); // Free allocated memory - chptr = p; // Point to string table size long - D_long(strindx); // Write string table size - - // Write the BSD object file from the object image buffer - write(fd, buf, BSDHDRSIZE + tds + trsize + drsize + symsize + strindx + 4); - - if(buf) free(buf); // Free allocated memory - break; - } - - return(0); -} + if (w1 & EQUATED) + { + z = 0x02000000; // Set equated flag + } + else + { + switch (w1 & TDB) + { + case TEXT: z = 0x04000000; break; // Set TEXT segment flag + case DATA: z = 0x06000000; break; // Set DATA segment flag + case BSS : z = 0x08000000; break; // Set BSS segment flag + } + } + + if (globflag) + z |= 0x01000000; // Set global flag if requested + + D_long(z); // Deposit symbol attribute + z = sym->svalue; // Obtain symbol value + w1 &= DATA|BSS; // Determine DATA or BSS flag + if (w1) + z += sect[TEXT].sloc; // If DATA or BSS add TEXT segment size + if (w1 & BSS) + z += sect[DATA].sloc; // If BSS add DATA segment size + D_long(z); // Deposit symbol value + strcpy(strtable + strindx, sym->sname); + strindx += strlen(sym->sname) + 1; // Incr string index incl null terminate + buf += 12; // Increment buffer to next record + symsize += 12; // Increment symbol table size + + return buf; +} + + +// +// Generate object file +// +int object(WORD fd) +{ + LONG t; // Scratch long + LONG tds; // TEXT & DATA segment size + int i; // Temporary int + CHUNK * cp; // Chunk (for gather) + char * buf; // Scratch area + char * p; // Temporary ptr + LONG ssize; // Size of symbols + LONG trsize, drsize; // Size of relocations + + // Write requested object file... + switch (obj_format) + { + case BSD: + ssize = ((LONG)sy_assign(NULL, NULL)); // Assign index numbers to the symbols + tds = sect[TEXT].sloc + sect[DATA].sloc; // Get size of TEXT and DATA segment + buf = malloc(0x400000); // Allocate 4mb object file image memory + + if (buf == NULL) + { + error("cannot allocate object file memory (in BSD mode)"); + return ERROR; + } + + memset(buf, 0, 0x400000); // Reset allocated memory + objimage = buf; // Set global object image pointer + strtable = malloc(0x200000); // Allocate 2mb scratch buffer + + if (strtable == NULL) + { + error("cannot allocate string table memory (in BSD mode)"); + return ERROR; + } + + memset(strtable, 0, 0x200000); // Reset allocated memory + + // Build object file header + chptr = buf; // Base of header + t = 0x00000107; + D_long(t); // Magic number + t = sect[TEXT].sloc; // TEXT size + D_long(t); + t = sect[DATA].sloc; // DATA size + D_long(t); + t = sect[BSS].sloc; // BSS size + D_long(t); + t = 0x00000000; + D_long(t); // Symbol size + D_long(t); // First entry (0L) + D_long(t); // TEXT relocation size + D_long(t); // BSD relocation size + + // Construct TEXT and DATA segments (without relocation changes) + p = buf + BSDHDRSIZE; + for(i=TEXT; i<=DATA; ++i) + { + for(cp=sect[i].sfcode; cp!=NULL; cp=cp->chnext) + { + copy(p, cp->chptr, cp->ch_size); + p += cp->ch_size; + } + } + + // Do relocation tables (and make changes to segment data) + p = buf + (BSDHDRSIZE + tds); // Move obj image ptr to reloc info + trsize = bsdmarkimg(p, tds, sect[TEXT].sloc, TEXT);// Do TEXT relocation table + chptr = buf + 24; // Point to relocation hdr entry + D_long(trsize); // Write the relocation table size + p = buf + (BSDHDRSIZE + tds + trsize); // Move obj image ptr to reloc info + drsize = bsdmarkimg(p, tds, sect[TEXT].sloc, DATA);// Do DATA relocation table + chptr = buf + 28; // Point to relocation hdr entry + D_long(drsize); // Write the relocation table size + + p = buf + (BSDHDRSIZE + tds + trsize + drsize); // Point to start of symbol table + sy_assign(p, constr_bsdsymtab); // Build symbol and string tables + chptr = buf + 16; // Point to sym table size hdr entry + D_long(symsize); // Write the symbol table size + + // Point to string table + p = buf + (BSDHDRSIZE + tds + trsize + drsize + symsize); + + memcpy(p, strtable, strindx); // Copy string table to object image + + if (buf) + free(strtable); // Free allocated memory + + chptr = p; // Point to string table size long + D_long(strindx); // Write string table size + + // Write the BSD object file from the object image buffer + write(fd, buf, BSDHDRSIZE + tds + trsize + drsize + symsize + strindx + 4); + + if (buf) + free(buf); // Free allocated memory + + break; + } + + return 0; +} diff --git a/rmac.c b/rmac.c index dd7add1..f0b7efb 100644 --- a/rmac.c +++ b/rmac.c @@ -22,37 +22,37 @@ #include "symbol.h" #include "object.h" -int perm_verb_flag; // Permanently verbose, interactive mode -int list_flag; // "-l" Listing flag on command line -int verb_flag; // Be verbose about what's going on -int as68_flag; // as68 kludge mode -int glob_flag; // Assume undefined symbols are global -int lsym_flag; // Include local symbols in object file -int sbra_flag; // Warn about possible short branches -int obj_format; // Object format flag -int debug; // [1..9] Enable debugging levels -int err_flag; // '-e' specified -int err_fd; // File to write error messages to -int rgpu, rdsp; // Assembling Jaguar GPU or DSP code -int list_fd; // File to write listing to -int regbank; // RISC register bank -int segpadsize; // Segment padding size -int in_main; // In main memory flag for GPUMAIN -int endian; // Processor endianess -char *objfname; // Object filename pointer -char *firstfname; // First source filename -char *cmdlnexec; // Executable name, pointer to ARGV[0] -char *searchpath; // Search path for include files -char defname[] = "noname.o"; // Default output filename - -// Under Windows and UNIX malloc() is an expensive call, so for small amounts of memory we allocate -// from a previously allocated buffer. +int perm_verb_flag; // Permanently verbose, interactive mode +int list_flag; // "-l" Listing flag on command line +int verb_flag; // Be verbose about what's going on +int as68_flag; // as68 kludge mode +int glob_flag; // Assume undefined symbols are global +int lsym_flag; // Include local symbols in object file +int sbra_flag; // Warn about possible short branches +int obj_format; // Object format flag +int debug; // [1..9] Enable debugging levels +int err_flag; // '-e' specified +int err_fd; // File to write error messages to +int rgpu, rdsp; // Assembling Jaguar GPU or DSP code +int list_fd; // File to write listing to +int regbank; // RISC register bank +int segpadsize; // Segment padding size +int in_main; // In main memory flag for GPUMAIN +int endian; // Host processor endianess +char * objfname; // Object filename pointer +char * firstfname; // First source filename +char * cmdlnexec; // Executable name, pointer to ARGV[0] +char * searchpath; // Search path for include files +char defname[] = "noname.o"; // Default output filename + +// Under Windows and UNIX malloc() is an expensive call, so for small amounts +// of memory we allocate from a previously allocated buffer. #define A_AMOUNT 4096 // Amount to malloc() at a time #define A_THRESH 64 // Use malloc() for amounts >= A_THRESH static LONG a_amount; // Amount left at a_ptr -static char *a_ptr; // Next free chunk +static char * a_ptr; // Next free chunk LONG amemtot; // amem() total of requests // Qsort; The THRESHold below is the insertion sort threshold, and has been adjusted @@ -66,6 +66,8 @@ static int qsz; // Size of each reco static int thresh; // THRESHold in chars static int mthresh; // MTHRESHold in chars + +// // qst: Do a quicksort. First, find the median element, and put that one in the first place as // the discriminator. (This "median" is just the median of the first, last and middle elements). // (Using this median instead of the first element is a big win). Then, the usual @@ -75,11 +77,12 @@ static int mthresh; // MTHRESHold in cha // and cleaning up with an insertion sort (in our caller) is a huge win. All data swaps are done // in-line, which is space-losing but time-saving. (And there are only three places where // this is done). - -static int qst(char *base, char *max) { - char c, *i, *j, *jj; +// +static int qst(char * base, char * max) +{ + char c, * i, * j, * jj; int ii; - char *mid, *tmp; + char * mid, * tmp; long lo, hi; /* @@ -174,30 +177,37 @@ swap: return(0); } + /* * qsort: * First, set up some global parameters for qst to share. Then, quicksort * with qst(), and then a cleanup insertion sort ourselves. Sound simple? * It's not... */ - -int rmac_qsort(char *base, int n, int size, int (*compar)()) { - register char c, *i, *j, *lo, *hi; - char *min, *max; +int rmac_qsort(char * base, int n, int size, int (*compar)()) +{ + register char c, * i, * j, * lo, * hi; + char * min, * max; if (n <= 1) return(0); + qsz = size; qcmp = compar; thresh = qsz * THRESH; mthresh = qsz * MTHRESH; max = base + n * qsz; - if (n >= THRESH) { + + if (n >= THRESH) + { qst(base, max); hi = base + thresh; - } else { + } + else + { hi = max; } + /* * First put smallest element, which must be in the first THRESH, in * the first position as a sentinel. This is done just by searching @@ -207,9 +217,12 @@ int rmac_qsort(char *base, int n, int size, int (*compar)()) { for (j = lo = base; (lo += qsz) < hi; ) if (qcmp(j, lo) > 0) j = lo; - if (j != base) { + + if (j != base) + { /* swap j into place */ - for (i = base, hi = base + qsz; i < hi; ) { + for (i = base, hi = base + qsz; i < hi; ) + { c = *j; *j++ = *i; *i++ = c; @@ -237,10 +250,10 @@ int rmac_qsort(char *base, int n, int size, int (*compar)()) { return(0); } + // -// --- Allocate memory; Panic and Quit if we Run Out ----------------------------------------------- +// Allocate memory; Panic and Quit if we Run Out // - char * amem(LONG amount) { char * p; @@ -274,32 +287,33 @@ char * amem(LONG amount) return p; } + // -// --- Copy stuff around, return pointer to dest+count+1 (doesn't handle overlap) ------------------ +// Copy stuff around, return pointer to dest+count+1 (doesn't handle overlap) // - char * copy(char * dest, char * src, LONG count) { - while (count--) - *dest++ = *src++; + while (count--) + *dest++ = *src++; - return dest; + return dest; } + // -// --- Clear a region of memory -------------------------------------------------------------------- +// Clear a region of memory // - -void clear(char *dest, LONG count) +void clear(char * dest, LONG count) { while(count--) *dest++ = 0; } + // -// --- Check to see if the string is a keyword. Returns -1, or a value from the 'accept[]' table --- +// Check to see if the string is a keyword. Returns -1, or a value from the +// 'accept[]' table // - int kmatch(char * p, int * base, int * check, int * tab, int * accept) { int state; @@ -327,10 +341,10 @@ int kmatch(char * p, int * base, int * check, int * tab, int * accept) return state; } + // -// --- Auto-even a section ------------------------------------------------------------------------- +// Auto-even a section // - void autoeven(int sect) { switchsect(sect); @@ -338,53 +352,58 @@ void autoeven(int sect) savsect(); } + // -// ------------------------------------------------------------------------------------------------- // Manipulate file extension. // `name' must be large enough to hold any possible filename. // If `stripp' is nonzero, any old extension is removed. // Then, if the file does not already have an extension, // `extension' is appended to the filename. -// ------------------------------------------------------------------------------------------------- // +char * fext(char * name, char * extension, int stripp) +{ + char * s, * beg; // String pointers -char *fext(char *name, char *extension, int stripp) { - char *s, *beg; // String pointers + // Find beginning of "real" name + beg = name + strlen(name) - 1; - // Find beginning of "real" name - beg = name + strlen(name) - 1; - for(; beg > name; --beg) { - if(*beg == SLASHCHAR) { - ++beg; - break; - } - } + for(; beg>name; --beg) + { + if (*beg == SLASHCHAR) + { + ++beg; + break; + } + } - if(stripp) { // Clobber any old extension - for(s = beg; *s && *s != '.'; ++s) - ; - *s = '\0'; - } + if (stripp) + { // Clobber any old extension + for(s=beg; *s && *s!='.'; ++s) + ; - for(s = beg; *s != '.'; ++s) { - if(!*s) { // Append the new extension - strcat(beg, extension); - break; - } - } + *s = '\0'; + } + + for(s=beg; *s!='.'; ++s) + { + if (!*s) + { // Append the new extension + strcat(beg, extension); + break; + } + } - return(name); + return name; } + // -// ------------------------------------------------------------------------------------------------- -// Return `item'nth element of semicolon-seperated pathnames specified in the enviroment string `s'. -// Copy the pathname to `buf'. Return 0 if the `item'nth path doesn't exist. +// Return `item'nth element of semicolon-seperated pathnames specified in the +// enviroment string `s'. Copy the pathname to `buf'. Return 0 if the `item' +// nth path doesn't exist. // // [`item' ranges from 0 to N-1, where N = #elements in search path] -// ------------------------------------------------------------------------------------------------- // - int nthpath(char * env_var, int itemno, char * buf) { char * s = searchpath; @@ -410,10 +429,10 @@ int nthpath(char * env_var, int itemno, char * buf) return 1; } + // -// --- Display Command Line Help ----------------------------------------------- +// Display Command Line Help // - void display_help(void) { printf("Usage:\n"); @@ -441,10 +460,10 @@ void display_help(void) printf("\n"); } + // -// --- Display Version Information --------------------------------------------- +// Display Version Information // - void display_version(void) { printf("\nReboot's Macro Assembler for Atari Jaguar\n"); @@ -452,14 +471,15 @@ void display_version(void) printf("V%01i.%01i.%01i %s (%s)\n\n", MAJOR, MINOR, PATCH, __DATE__, PLATFORM); } + // -// --- Process Command Line Arguments and do an Assembly ------------------------------------------- +// Process Command Line Arguments and do an Assembly // - -int process(int argc, char **argv) { +int process(int argc, char ** argv) +{ int argno; // Argument number - SYM *sy; // Pointer to a symbol record - char *s; // String pointer + SYM * sy; // Pointer to a symbol record + char * s; // String pointer int fd; // File descriptor char fnbuf[FNSIZ]; // Filename buffer int i; // Iterator @@ -502,28 +522,28 @@ int process(int argc, char **argv) { // Process command line arguments and assemble source files for(argno = 0; argno < argc; ++argno) { - if(*argv[argno] == '-') { + if (*argv[argno] == '-') { switch(argv[argno][1]) { case 'd': // Define symbol case 'D': for(s = argv[argno] + 2; *s != EOS;) { - if(*s++ == '=') { + if (*s++ == '=') { s[-1] = EOS; break; } } - if(argv[argno][2] == EOS) { + if (argv[argno][2] == EOS) { printf("-d: empty symbol\n"); ++errcnt; return(errcnt); } sy = lookup(argv[argno] + 2, 0, 0); - if(sy == NULL) { + if (sy == NULL) { sy = newsym(argv[argno] + 2, LABEL, 0); sy->svalue = 0; } sy->sattr = DEFINED | EQUATED | ABS; - if(*s) + if (*s) sy->svalue = (VALUE)atoi(s); else sy->svalue = 0; @@ -563,9 +583,9 @@ int process(int argc, char **argv) { break; case 'o': // Direct object file output case 'O': - if(argv[argno][2] != EOS) objfname = argv[argno] + 2; + if (argv[argno][2] != EOS) objfname = argv[argno] + 2; else { - if(++argno >= argc) { + if (++argno >= argc) { printf("Missing argument to -o"); ++errcnt; return(errcnt); @@ -595,7 +615,7 @@ int process(int argc, char **argv) { case 'v': // Verbose flag case 'V': verb_flag++; - if(verb_flag > 1) display_version(); + if (verb_flag > 1) display_version(); break; case 'x': // Turn on debugging case 'X': @@ -605,14 +625,14 @@ int process(int argc, char **argv) { case 'y': // -y case 'Y': pagelen = atoi(argv[argno] + 2); - if(pagelen < 10) { + if (pagelen < 10) { printf("-y: bad page length\n"); ++errcnt; return(errcnt); } break; case EOS: // Input is stdin - if(firstfname == NULL) // Kludge first filename + if (firstfname == NULL) // Kludge first filename firstfname = defname; include(0, "(stdin)"); assemble(); @@ -633,12 +653,12 @@ int process(int argc, char **argv) { } } else { // Record first filename. - if(firstfname == NULL) + if (firstfname == NULL) firstfname = argv[argno]; strcpy(fnbuf, argv[argno]); fext(fnbuf, ".s", 0); fd = open(fnbuf, 0); - if(fd < 0) { + if (fd < 0) { printf("Cannot open: %s\n", fnbuf); ++errcnt; continue; @@ -667,8 +687,8 @@ int process(int argc, char **argv) { savsect(); } - if(objfname == NULL) { - if(firstfname == NULL) + if (objfname == NULL) { + if (firstfname == NULL) firstfname = defname; strcpy(fnbuf, firstfname); //fext(fnbuf, prg_flag ? ".prg" : ".o", 1); @@ -684,27 +704,27 @@ int process(int argc, char **argv) { // (3) generate relocation information from left-over fixups. fixups(); // Do all fixups stopmark(); // Stop mark tape-recorder - if(errcnt == 0) { - if((fd = open(objfname, _OPEN_FLAGS, _PERM_MODE)) < 0) + if (errcnt == 0) { + if ((fd = open(objfname, _OPEN_FLAGS, _PERM_MODE)) < 0) cantcreat(objfname); - if(verb_flag) { + if (verb_flag) { s = "object"; printf("[Writing %s file: %s]\n", s, objfname); } object((WORD)fd); close(fd); - if(errcnt != 0) + if (errcnt != 0) unlink(objfname); } - if(list_flag) { - if(verb_flag) printf("[Wrapping-up listing file]\n"); + if (list_flag) { + if (verb_flag) printf("[Wrapping-up listing file]\n"); listing = 1; symtable(); close(list_fd); } - if(err_flag) + if (err_flag) close(err_fd); DEBUG dump_everything(); @@ -712,11 +732,11 @@ int process(int argc, char **argv) { return(errcnt); } + #if 0 // -// --- Interactive Mode ---------------------------------------------------------------------------- +// Interactive Mode // - void interactive(void) { char * s; // String pointer for banner @@ -783,10 +803,10 @@ void interactive(void) } #endif + // -// --- Determine Processor Endianess --------------------------------------------------------------- +// Determine Processor Endianess // - int get_endianess(void) { int i = 1; @@ -798,10 +818,10 @@ int get_endianess(void) return 1; } + // -// --- Application Entry Point; Handle the Command Line -------------------------------------------- +// Application Entry Point; Handle the Command Line // - int main(int argc, char ** argv) { int status; // Status flag -- 2.37.2