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
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;
}
-
-
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; 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;
}
-
+
+
//
-// --- Set RISC Register Banks ---------------------------------------------------------------------
+// Set RISC Register Banks
//
-
-int d_regbank0(void) {
- regbank = BANK_0; // Set active register bank zero
- return(0);
+int d_regbank0(void)
+{
+ regbank = BANK_0; // Set active register bank zero
+ return 0;
}
-int d_regbank1(void) {
- regbank = BANK_1; // Set active register bank one
- return(0);
+
+int d_regbank1(void)
+{
+ regbank = BANK_1; // Set active register bank one
+ return 0;
}
+
//
-// --- Adjust Location to an EVEN Value ------------------------------------------------------------
+// Adjust Location to an EVEN Value
//
-
-int d_even(void) {
- if(sloc & 1) {
- if((scattr & SBSS) == 0) {
- chcheck(1);
- D_byte(0);
- } else {
- ++sloc;
- }
- }
-
- return(0);
+int d_even(void)
+{
+ if (sloc & 1)
+ {
+ if ((scattr & SBSS) == 0)
+ {
+ chcheck(1);
+ D_byte(0);
+ }
+ else
+ {
+ ++sloc;
+ }
+ }
+
+ return 0;
}
+
//
-// --- Adjust Location to an LONG Value ------------------------------------------------------------
+// Adjust Location to an LONG Value
//
-
-int d_long(void) {
- unsigned i;
- unsigned val = 4;
-
- i = sloc & ~(val - 1);
- if(i != sloc) val = val - (sloc - i);
- else val = 0;
-
- if(val) {
- if((scattr & SBSS) == 0) {
- chcheck(val);
- for(i = 0; i < val; i++)
- D_byte(0);
- } else {
- sloc += val;
- }
- }
-
- return(0);
+int d_long(void)
+{
+ unsigned i;
+ unsigned val = 4;
+
+ i = sloc & ~(val - 1);
+
+ if (i != sloc)
+ val = val - (sloc - i);
+ else
+ val = 0;
+
+ if (val)
+ {
+ if ((scattr & SBSS) == 0)
+ {
+ chcheck(val);
+
+ for(i=0; i<val; i++)
+ D_byte(0);
+ }
+ else
+ {
+ sloc += val;
+ }
+ }
+
+ return 0;
}
+
//
-// --- Adjust Location to an PHRASE Value ----------------------------------------------------------
+// Adjust Location to an PHRASE Value
//
-
-int d_phrase(void) {
- unsigned i;
- unsigned val = 8;
-
- i = sloc & ~(val - 1);
- if(i != sloc) val = val - (sloc - i);
- else val = 0;
-
- if(val) {
- if((scattr & SBSS) == 0) {
- chcheck(val);
- for(i = 0; i < val; i++)
- D_byte(0);
- } else {
- sloc += val;
- }
- }
-
- return(0);
+int d_phrase(void)
+{
+ unsigned i;
+ unsigned val = 8;
+
+ i = sloc & ~(val - 1);
+
+ if (i != sloc)
+ val = val - (sloc - i);
+ else
+ val = 0;
+
+ if (val)
+ {
+ if ((scattr & SBSS) == 0)
+ {
+ chcheck(val);
+
+ for(i=0; i<val; i++)
+ D_byte(0);
+ }
+ else
+ {
+ sloc += val;
+ }
+ }
+
+ return 0;
}
+
//
-// --- Adjust Location to an DPHRASE Value ---------------------------------------------------------
+// Adjust Location to an DPHRASE Value
//
-
-int d_dphrase(void) {
- unsigned i;
- unsigned val = 16;
-
- i = sloc & ~(val - 1);
- if(i != sloc) val = val - (sloc - i);
- else val = 0;
-
- if(val) {
- if((scattr & SBSS) == 0) {
- chcheck(val);
- for(i = 0; i < val; i++)
- D_byte(0);
- } else {
- sloc += val;
- }
- }
-
- return(0);
+int d_dphrase(void)
+{
+ unsigned i;
+ unsigned val = 16;
+
+ i = sloc & ~(val - 1);
+
+ if (i != sloc)
+ val = val - (sloc - i);
+ else
+ val = 0;
+
+ if (val)
+ {
+ if ((scattr & SBSS) == 0)
+ {
+ chcheck(val);
+
+ for(i=0; i<val; i++)
+ D_byte(0);
+ }
+ else
+ {
+ sloc += val;
+ }
+ }
+
+ return 0;
}
+
//
-// --- Adjust Location to an QPHRASE Value ---------------------------------------------------------
+// Adjust Location to an QPHRASE Value
//
-
-int d_qphrase(void) {
- unsigned i;
- unsigned val = 32;
-
- i = sloc & ~(val - 1);
- if(i != sloc) val = val - (sloc - i);
- else val = 0;
-
- if(val) {
- if((scattr & SBSS) == 0) {
- savsect();
- chcheck(val);
- for(i = 0; i < val; i++)
- D_byte(0);
- } else {
- sloc += val;
- }
- }
-
- return(0);
+int d_qphrase(void)
+{
+ unsigned i;
+ unsigned val = 32;
+
+ i = sloc & ~(val - 1);
+
+ if (i != sloc)
+ val = val - (sloc - i);
+ else
+ val = 0;
+
+ if (val)
+ {
+ if ((scattr & SBSS) == 0)
+ {
+ savsect();
+ chcheck(val);
+
+ for(i=0; i<val; i++)
+ D_byte(0);
+ }
+ else
+ {
+ sloc += val;
+ }
+ }
+
+ return 0;
}
+
//
-// -------------------------------------------------------------------------------------------------
// Do auto-even. This must be called ONLY if 'sloc' is odd.
//
-// This is made hairy because, if there was a label on the line, we also have to adjust its value.
-// This won't work with more than one label on the line, which is OK since multiple labels are only
-// allowed in AS68 kludge mode, and the C compiler is VERY paranoid and uses ".even" whenever it can
-// -------------------------------------------------------------------------------------------------
+// This is made hairy because, if there was a label on the line, we also have
+// to adjust its value. This won't work with more than one label on the line,
+// which is OK since multiple labels are only allowed in AS68 kludge mode, and
+// the C compiler is VERY paranoid and uses ".even" whenever it can
//
+void auto_even(void)
+{
+ if (scattr & SBSS)
+ ++sloc; // Bump BSS section
+ else
+ D_byte(0) // Deposit 0.b in non-BSS
-void auto_even(void) {
- if(scattr & SBSS)
- ++sloc; // Bump BSS section
- else {
- D_byte(0) // Deposit 0.b in non-BSS
- }
-
- if(lab_sym != NULL) // Bump label if we have to
- ++lab_sym->svalue;
+ 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] <<<cannot make local symbols global>>> -----------------------------
+// .globl symbol [, symbol] <<<cannot make local symbols global>>>
//
+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 <expression>
- 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 <expression>
+ 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;
}
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
taglist('E');
++errcnt;
- return(ERROR);
+ return ERROR;
}
int errors(char * s, char * s1)
taglist('E');
++errcnt;
- return(ERROR);
+ return ERROR;
}
int warn(char * s)
taglist('W');
- return(OK);
+ return OK;
}
int warns(char * s, char * s1)
taglist('W');
- return(OK);
+ return OK;
}
int warni(char * s, unsigned i)
taglist('W');
- return(OK);
+ return OK;
}
int fatal(char * s)
// Globals, externals etc
extern int errcnt;
-extern char *err_fname;
+extern char * err_fname;
// Prototypes
int error(char *);
// 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 <macro-name>
- 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 <macro-name>
+ 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;
}
-
-
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;
}
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<TABSIZE; ++i)
{
ktab[i] = -1;
kcheck[i] = -1;
kaccept[i] = -1;
}
+
nstates = 0;
/*
continue;
namtab[nnames].nstr = s;
+
while (*s && !isspace(*s))
++s;
*s++ = '\0';
s1 = s;
+
while (*s1 && isspace(*s1))
++s1;
empty: /* use previous entry + 1 */
if (!nnames) /* complain if no previous entry */
namtab[nnames].nval = 0;
- else namtab[nnames].nval = namtab[nnames-1].nval + 1;
+ else
+ namtab[nnames].nval = namtab[nnames-1].nval + 1;
}
else if (isdigit(*s1))
namtab[nnames].nval = atoi(s1);
{ /* same as previous entry */
if (!nnames) /* zero for first entry */
namtab[nnames].nval = 0;
- else namtab[nnames].nval = namtab[nnames-1].nval;
+ else
+ namtab[nnames].nval = namtab[nnames-1].nval;
}
else
{
}
++nnames;
+
if (nnames >= NSTRINGS)
panic("name table overflow");
+
if (s >= &strpool[STRPOOLSIZ-100])
panic("string table overflow");
}
*/
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<k-2; ++i)
{
if (ktab[kbase[state] + *(namtab[w-1].nstr + i)] < 0)
panic("table build error");
- else state = ktab[kbase[state] +
- *(namtab[w-1].nstr + i)];
+ else
+ state = ktab[kbase[state] + *(namtab[w-1].nstr + i)];
}
ktab[kbase[state] + *(namtab[w-1].nstr + k-2)] = nstates;
}
+
++nstates;
found1 = 1;
}
- for (i = 0; i < 128; ++i)
+ for(i=0; i<128; ++i)
{
tab[i] = UNUSED;
accept[i] = -1;
valid = 0;
}
- if ( w >= 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;
}
}
* 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<TABSIZE-128; ++base)
{
- for (i = 0; i < 128; ++i)
- if (ktab[base+i] != UNUSED &&
- tab[i] == MARKED)
+ for(i=0; i<128; ++i)
+ if (ktab[base+i] != UNUSED && tab[i] == MARKED)
break;
+
if (i >= 128)
break;
}
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)
}
-void print_tables(void) {
+void print_tables(void)
+{
// int i;
printf("\n#ifdef DECL_%s\n", uppername);
}
-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; i<tabsize; ++i)
{
printf(" %d", table[i]);
+
if (i != tabsize-1)
putchar(',');
+
if (++j == 8)
{
j = 0;
putchar('\n');
}
}
+
if (j)
putchar('\n');
+
printf("};\n");
}
-int comp_entry(struct name_entry *ent1, struct name_entry *ent2) {
+int comp_entry(struct name_entry * ent1, struct name_entry * ent2)
+{
return strcmp(ent1->nstr, 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)
{
}
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);
}
// 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)
#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
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<SRC_COL; ++i)
+ {
+ if ((j = ln[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"
*
* 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;
}
-
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;
}
+
//
-// --- <op> #expr ----------------------------------------------------------------------------------
+// <op> #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;
}
+
//
-// --- <op>.b #expr --------------------------------------------------------------------------------
+// <op>.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;
}
+
//
-// --- <shift> Dn,Dn -------------------------------------------------------------------------------
+// <shift> 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;
}
+
//
-// --- <shift> #n,Dn -------------------------------------------------------------------------------
+// <shift> #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 <C_ALL> <C_ALTDATA>
// MOVE <C_ALL> <M_AREG>
//
// Optimize MOVE.L #<smalldata>,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 <rlist>,ea -- movem ea,<rlist> --------------------------------------------------------
-//
-
-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 #<expr>,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) { // <rlist>,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,<rlist>
- 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,#<expr>
- ++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 <rlist>,ea -- movem ea,<rlist>
+//
+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 #<expr>,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)
+ { // <rlist>,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,<rlist>
+ 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,#<expr>
+ ++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;
}
-
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;
+}
#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
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
// 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;
/*
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
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;
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;
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;
return state;
}
+
//
-// --- Auto-even a section -------------------------------------------------------------------------
+// Auto-even a section
//
-
void autoeven(int sect)
{
switchsect(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;
return 1;
}
+
//
-// --- Display Command Line Help -----------------------------------------------
+// Display Command Line Help
//
-
void display_help(void)
{
printf("Usage:\n");
printf("\n");
}
+
//
-// --- Display Version Information ---------------------------------------------
+// Display Version Information
//
-
void display_version(void)
{
printf("\nReboot's Macro Assembler for Atari Jaguar\n");
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
// 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;
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);
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':
case 'y': // -y<pagelen>
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();
}
} 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;
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);
// (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();
return(errcnt);
}
+
#if 0
//
-// --- Interactive Mode ----------------------------------------------------------------------------
+// Interactive Mode
//
-
void interactive(void)
{
char * s; // String pointer for banner
}
#endif
+
//
-// --- Determine Processor Endianess ---------------------------------------------------------------
+// Determine Processor Endianess
//
-
int get_endianess(void)
{
int i = 1;
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