int namcnt;
char ln[256];
- if (argc == 2)
- if ((kfp = fopen(argv[1], "w")) == NULL)
- error("Cannot create: %s", argv[1]);
+ if ((argc == 2) && ((kfp = fopen(argv[1], "w")) == NULL))
+ error("Cannot create: %s", argv[1]);
-// while (gets(ln) != NULL)
while (fgets(ln, 256, stdin) != NULL)
{
-
++lineno; /* bump line# */
+
if (*ln == '#') /* ignore comments */
continue;
if (namcnt)
procln(namcnt, namv);
}
+
return 0;
}
printf("CGSPECIAL");
else for (s = namv[1], i=0; *s; ++s)
printf("%sSIZ%c", (i++ ? "|" : ""), *s);
+
printf(", %s, %s, ", namv[2], namv[3]);
if (*namv[4] == '%') /* enforce little fascist percent signs */
++kwnum;
}
+
void error(char * s, char * s1)
{
fprintf(stderr, s, s1);
extern TOKEN a0oexpr[], a1oexpr[];
extern VALUE a0oexval, a1oexval;
extern WORD a0oexattr, a1oexattr;
-extern SYM *a0esym, *a1esym;
+extern SYM * a0esym, * a1esym;
// Mnemonic table structure
#define MNTAB struct _mntab
static int siztab[4] = {3, 5, 9, 9};
+
//
-// --- Print 'c' Visibly ---------------------------------------------------------------------------
+// Print 'c' Visibly
//
-
int visprt(char c)
{
- if (c < 0x20 || c >= 0x7f)
- putchar('.');
- else
- putchar(c);
+ if (c < 0x20 || c >= 0x7F)
+ putchar('.');
+ else
+ putchar(c);
- return 0;
+ return 0;
}
+
//
-// --- Print expression, return ptr to just past the ENDEXPR ---------------------------------------
+// Print expression, return ptr to just past the ENDEXPR
//
-
TOKEN * printexpr(TOKEN * tp)
{
- if (tp != NULL)
- {
- while (*tp != ENDEXPR)
- {
- switch ((int)*tp++)
- {
- case SYMBOL:
- printf("`%s' ", ((SYM *)*tp)->sname);
- ++tp;
- break;
- case CONST:
- printf("$%ux ", *tp++);
- break;
- case ACONST:
- printf("ACONST=($%ux,$%ux) ", *tp, tp[1]);
- tp += 2;
- break;
- default:
- printf("%c ", (char)tp[-1]);
- break;
- }
- }
- }
-
- printf(";\n");
- return tp + 1;
+ if (tp != NULL)
+ {
+ while (*tp != ENDEXPR)
+ {
+ switch ((int)*tp++)
+ {
+ case SYMBOL:
+ printf("`%s' ", ((SYM *)*tp)->sname);
+ ++tp;
+ break;
+ case CONST:
+ printf("$%ux ", *tp++);
+ break;
+ case ACONST:
+ printf("ACONST=($%ux,$%ux) ", *tp, tp[1]);
+ tp += 2;
+ break;
+ default:
+ printf("%c ", (char)tp[-1]);
+ break;
+ }
+ }
+ }
+
+ printf(";\n");
+ return tp + 1;
}
+
//
-// --- Dump data in a chunk (and maybe others) in the appropriate format ---------------------------
+// Dump data in a chunk (and maybe others) in the appropriate format
//
-
int chdump(CHUNK * ch, int format)
{
- while (ch != NULL)
- {
- printf("chloc=$%08ux, chsize=$%ux\n", ch->chloc, ch->ch_size);
- mdump(ch->chptr, ch->ch_size, format, ch->chloc);
- ch = ch->chnext;
- }
-
- return 0;
+ while (ch != NULL)
+ {
+ printf("chloc=$%08ux, chsize=$%ux\n", ch->chloc, ch->ch_size);
+ mdump(ch->chptr, ch->ch_size, format, ch->chloc);
+ ch = ch->chnext;
+ }
+
+ return 0;
}
+
//
-// --- Dump fixup records in printable format ------------------------------------------------------
+// Dump fixup records in printable format
//
-
int fudump(CHUNK * ch)
{
- PTR p;
- char * ep;
- WORD attr, esiz;
- WORD line, file;
- LONG loc;
-
- for(; ch!=NULL;)
- {
- p.cp = ch->chptr;
- ep = ch->chptr + ch->ch_size;
-
- while(p.cp < ep)
- {
- attr = *p.wp++;
- loc = *p.lp++;
- file = *p.wp++;
- line = *p.wp++;
-
- printf("$%04x $%08ux %d.%d: ", (int)attr, loc, (int)file, (int)line);
-
- if (attr & FU_EXPR)
- {
- esiz = *p.wp++;
- printf("(%d long) ", (int)esiz);
- p.tk = printexpr(p.tk);
- }
- else
- {
- printf("`%s' ;\n", (*p.sy)->sname);
- ++p.lp;
- }
- }
-
- ch = ch->chnext;
- }
-
- return 0;
+ PTR p;
+ char * ep;
+ WORD attr, esiz;
+ WORD line, file;
+ LONG loc;
+
+ for(; ch!=NULL;)
+ {
+ p.cp = ch->chptr;
+ ep = ch->chptr + ch->ch_size;
+
+ while(p.cp < ep)
+ {
+ attr = *p.wp++;
+ loc = *p.lp++;
+ file = *p.wp++;
+ line = *p.wp++;
+
+ printf("$%04x $%08ux %d.%d: ", (int)attr, loc, (int)file, (int)line);
+
+ if (attr & FU_EXPR)
+ {
+ esiz = *p.wp++;
+ printf("(%d long) ", (int)esiz);
+ p.tk = printexpr(p.tk);
+ }
+ else
+ {
+ printf("`%s' ;\n", (*p.sy)->sname);
+ ++p.lp;
+ }
+ }
+
+ ch = ch->chnext;
+ }
+
+ return 0;
}
+
//
-// --- Dump marks ----------------------------------------------------------------------------------
+// Dump marks
//
-
int mudump(void)
{
- MCHUNK * mch;
- PTR p;
- WORD from;
- WORD w;
- LONG loc;
- SYM * symbol;
+ MCHUNK * mch;
+ PTR p;
+ WORD from;
+ WORD w;
+ LONG loc;
+ SYM * symbol;
- from = 0;
+ from = 0;
- for(mch=firstmch; mch!=NULL; mch=mch->mcnext)
- {
- printf("mch=$%08ux mcptr=$%08ux mcalloc=$%ux mcused=$%x\n",
- (uint32_t)mch,
- (mch->mcptr.lw),
- mch->mcalloc,
- (mch->mcused));
+ for(mch=firstmch; mch!=NULL; mch=mch->mcnext)
+ {
+ printf("mch=$%08ux mcptr=$%08ux mcalloc=$%ux mcused=$%x\n",
+ (uint32_t)mch,
+ (mch->mcptr.lw),
+ mch->mcalloc,
+ (mch->mcused));
- p = mch->mcptr;
-
- for(;;)
- {
- w = *p.wp++;
+ p = mch->mcptr;
+
+ for(;;)
+ {
+ w = *p.wp++;
- if (w & MCHEND)
- break;
+ if (w & MCHEND)
+ break;
- symbol = NULL;
- loc = *p.lp++;
+ symbol = NULL;
+ loc = *p.lp++;
- if (w & MCHFROM)
- from = *p.wp++;
+ if (w & MCHFROM)
+ from = *p.wp++;
- if (w & MSYMBOL)
- symbol = *p.sy++;
+ if (w & MSYMBOL)
+ symbol = *p.sy++;
- printf("m=$%04x to=%d loc=$%ux from=%d siz=%s",
- w, w & 0x00ff, loc, from, (w & MLONG) ? "long" : "word");
+ printf("m=$%04x to=%d loc=$%ux from=%d siz=%s",
+ w, w & 0x00ff, loc, from, (w & MLONG) ? "long" : "word");
- if (symbol != NULL)
- printf(" sym=`%s'", symbol->sname);
+ if (symbol != NULL)
+ printf(" sym=`%s'", symbol->sname);
- printf("\n");
- }
- }
+ printf("\n");
+ }
+ }
- return 0;
+ return 0;
}
+
//
-// -------------------------------------------------------------------------------------------------
// Dump memory from 'start' for 'count' bytes; `flg' is the following ORed together:
// 0 - bytes
// 1 - words
// 2 - longwords
//
// if `base' is not -1, then print it at the start of each line, incremented accordingly.
-// -------------------------------------------------------------------------------------------------
//
-
-int mdump(char *start, LONG count, int flg, LONG base) {
- int i, j, k;
-
- j = 0;
- for(i = 0; i < (int)count;) {
- if((i & 15) == 0) {
- if(j < i) {
- printf(" ");
- while(j < i)
- visprt(start[j++]);
- putchar('\n');
- }
- j = i;
- if(base != -1)
- printf("%08ux ", base);
- }
-
- switch(flg & 3) {
- case 0:
- printf("%02x ", start[i] & 0xff);
- ++i;
- break;
- case 1:
- printf("%02x%02x ", start[i] & 0xff, start[i+1] & 0xff);
- i += 2;
- break;
- case 2:
- printf("%02x%02x%02x%02x ", start[i] & 0xff, start[i+1] & 0xff,
- start[i+2] & 0xff, start[i+3] & 0xff);
- i += 4;
- break;
- case 3:
- break;
- }
-
- if(base != -1)
- base += 1 << (flg & 3);
- }
-
- // Print remaining bit of ascii; the hairy expression computes the number of
- // spaces to print to make the ascii line up nicely.
- if(j != i) {
- k = ((16 - (i - j)) / (1 << (flg & 3))) * siztab[flg & 3];
- while(k--)
- putchar(' ');
- printf(" ");
- while(j < i)
- visprt(start[j++]);
- putchar('\n');
- }
-
- return(0);
+int mdump(char * start, LONG count, int flg, LONG base)
+{
+ int i, j, k;
+ j = 0;
+
+ for(i=0; i<(int)count;)
+ {
+ if ((i & 15) == 0)
+ {
+ if (j < i)
+ {
+ printf(" ");
+
+ while(j < i)
+ visprt(start[j++]);
+
+ putchar('\n');
+ }
+
+ j = i;
+
+ if (base != -1)
+ printf("%08ux ", base);
+ }
+
+ switch (flg & 3)
+ {
+ case 0:
+ printf("%02x ", start[i] & 0xff);
+ ++i;
+ break;
+ case 1:
+ printf("%02x%02x ", start[i] & 0xff, start[i+1] & 0xff);
+ i += 2;
+ break;
+ case 2:
+ printf("%02x%02x%02x%02x ", start[i] & 0xff, start[i+1] & 0xff,
+ start[i+2] & 0xff, start[i+3] & 0xff);
+ i += 4;
+ break;
+ case 3:
+ break;
+ }
+
+ if (base != -1)
+ base += 1 << (flg & 3);
+ }
+
+ // Print remaining bit of ascii; the hairy expression computes the number of
+ // spaces to print to make the ascii line up nicely.
+ if (j != i)
+ {
+ k = ((16 - (i - j)) / (1 << (flg & 3))) * siztab[flg & 3];
+
+ while(k--)
+ putchar(' ');
+
+ printf(" ");
+
+ while(j < i)
+ visprt(start[j++]);
+
+ putchar('\n');
+ }
+
+ return 0;
}
+
//
-// --- Dump list of tokens on stdout in printable form ---------------------------------------------
+// Dump list of tokens on stdout in printable form
//
-
int dumptok(TOKEN * tk)
{
- int flg = 0;
-
- while (*tk != EOL)
- {
- if (flg++)
- printf(" ");
-
- if (*tk >= 128)
- {
- printf("REG=%ud", *tk++ - 128);
- continue;
- }
-
- switch ((int)*tk++)
- {
- case CONST: // CONST <value>
- printf("CONST=%ud", *tk++);
- break;
- case STRING: // STRING <address>
- printf("STRING='%s'", (char *)*tk++);
- break;
- case SYMBOL: // SYMBOL <address>
- printf("SYMBOL='%s'", (char *)*tk++);
- break;
- case EOL: // End of line
- printf("EOL");
- break;
- case TKEOF: // End of file (or macro)
- printf("TKEOF");
- break;
- case DEQUALS: // ==
- printf("DEQUALS");
- break;
- case DCOLON: // ::
- printf("DCOLON");
- break;
- case GE: // >=
- printf("GE");
- break;
- case LE: // <=
- printf("LE");
- break;
- case NE: // <> or !=
- printf("NE");
- break;
- case SHR: // >>
- printf("SHR");
- break;
- case SHL: // <<
- printf("SHL");
- break;
- default:
- printf("%c", (int)tk[-1]);
- break;
- }
- }
-
- printf("\n");
-
- return 0;
+ int flg = 0;
+
+ while (*tk != EOL)
+ {
+ if (flg++)
+ printf(" ");
+
+ if (*tk >= 128)
+ {
+ printf("REG=%ud", *tk++ - 128);
+ continue;
+ }
+
+ switch ((int)*tk++)
+ {
+ case CONST: // CONST <value>
+ printf("CONST=%ud", *tk++);
+ break;
+ case STRING: // STRING <address>
+ printf("STRING='%s'", (char *)*tk++);
+ break;
+ case SYMBOL: // SYMBOL <address>
+ printf("SYMBOL='%s'", (char *)*tk++);
+ break;
+ case EOL: // End of line
+ printf("EOL");
+ break;
+ case TKEOF: // End of file (or macro)
+ printf("TKEOF");
+ break;
+ case DEQUALS: // ==
+ printf("DEQUALS");
+ break;
+ case DCOLON: // ::
+ printf("DCOLON");
+ break;
+ case GE: // >=
+ printf("GE");
+ break;
+ case LE: // <=
+ printf("LE");
+ break;
+ case NE: // <> or !=
+ printf("NE");
+ break;
+ case SHR: // >>
+ printf("SHR");
+ break;
+ case SHL: // <<
+ printf("SHL");
+ break;
+ default:
+ printf("%c", (int)tk[-1]);
+ break;
+ }
+ }
+
+ printf("\n");
+
+ return 0;
}
+
//
-// --- Dump Everything -----------------------------------------------------------------------------
+// Dump Everything
//
+int dump_everything(void)
+{
+ int i;
-int dump_everything(void) {
- int i;
-
- for(i = 1; i < NSECTS; ++i)
- if(sect[i].scattr & SUSED) {
- printf("Section %d sloc=$%ux\n", i, sect[i].sloc);
- printf("Code:\n");
- chdump(sect[i].sfcode, 1);
+ for(i = 1; i < NSECTS; ++i)
+ {
+ if (sect[i].scattr & SUSED)
+ {
+ printf("Section %d sloc=$%ux\n", i, sect[i].sloc);
+ printf("Code:\n");
+ chdump(sect[i].sfcode, 1);
- printf("Fixup:\n");
- fudump(sect[i].sffix);
+ printf("Fixup:\n");
+ fudump(sect[i].sffix);
- printf("\n");
- }
+ printf("\n");
+ }
+ }
- printf("\nMarks:\n");
- mudump(); // Dump marks
- printf("Total memory allocated=$%ux\n", amemtot);
+ printf("\nMarks:\n");
+ mudump(); // Dump marks
+ printf("Total memory allocated=$%ux\n", amemtot);
- return(0);
+ return 0;
}
#include "object.h"
#include "risca.h"
-MCHUNK *firstmch; // First mark chunk
-MCHUNK *curmch; // Current mark chunk
-PTR markptr; // Deposit point in current mark chunk
-LONG mcalloc; // #bytes alloc'd to current mark chunk
-LONG mcused; // #bytes used in current mark chunk
-WORD curfrom; // Current "from" section
+MCHUNK * firstmch; // First mark chunk
+MCHUNK * curmch; // Current mark chunk
+PTR markptr; // Deposit point in current mark chunk
+LONG mcalloc; // #bytes alloc'd to current mark chunk
+LONG mcused; // #bytes used in current mark chunk
+WORD curfrom; // Current "from" section
+
//
-// --- Initialize Marker ---------------------------------------------------------------------------
+// Initialize Marker
//
-
-void init_mark(void) {
- firstmch = curmch = NULL;
- mcalloc = mcused = 0;
- curfrom = 0;
+void init_mark(void)
+{
+ firstmch = curmch = NULL;
+ mcalloc = mcused = 0;
+ curfrom = 0;
}
+
//
-// --- Wrap up marker (called after final mark is made) --------------------------------------------
+// Wrap up marker (called after final mark is made)
//
-
-void stopmark(void) {
- if(curmch) {
- *markptr.wp = MCHEND; // Mark end of block
- curmch->mcused = mcused; // Update #used in mark block
- }
+void stopmark(void)
+{
+ if (curmch)
+ {
+ *markptr.wp = MCHEND; // Mark end of block
+ curmch->mcused = mcused; // Update #used in mark block
+ }
}
+
//
-// --- Mark a word or longword relocatable ---------------------------------------------------------
+// Mark a word or longword relocatable
//
+int rmark(int from, LONG loc, int to, int size, SYM * symbol)
+{
+ WORD w;
-int rmark(int from, LONG loc, int to, int size, SYM *symbol) {
- WORD w;
+ if ((mcalloc - mcused) < MIN_MARK_MEM)
+ amark();
- if((mcalloc - mcused) < MIN_MARK_MEM)
- amark();
+ w = (WORD)(size | to);
- w = (WORD)(size | to);
- if(from != curfrom)
- w |= MCHFROM;
- if(symbol != NULL)
- w |= MSYMBOL;
+ if (from != curfrom)
+ w |= MCHFROM;
- mcused += sizeof(WORD) + sizeof(LONG);
- *markptr.wp++ = w;
- *markptr.lp++ = loc;
+ if (symbol != NULL)
+ w |= MSYMBOL;
- if(w & MCHFROM) {
- *markptr.wp++ = (WORD)from;
- curfrom = (WORD)from;
- mcused += sizeof(WORD);
- }
+ mcused += sizeof(WORD) + sizeof(LONG);
+ *markptr.wp++ = w;
+ *markptr.lp++ = loc;
- if(w & MSYMBOL) {
- *markptr.sy++ = symbol;
- mcused += sizeof(LONG);
- }
+ if (w & MCHFROM)
+ {
+ *markptr.wp++ = (WORD)from;
+ curfrom = (WORD)from;
+ mcused += sizeof(WORD);
+ }
- *markptr.wp = 0x0000;
+ if (w & MSYMBOL)
+ {
+ *markptr.sy++ = symbol;
+ mcused += sizeof(LONG);
+ }
- return(0);
+ *markptr.wp = 0x0000;
+
+ return 0;
}
+
//
-// --- Allocate another chunk of mark space --------------------------------------------------------
+// Allocate another chunk of mark space
//
-
-int amark(void) {
- MCHUNK *p;
-
- // Alloc mark block header (and data) and set it up.
- p = (MCHUNK *)amem((long)(sizeof(MCHUNK)) + MARK_ALLOC_INCR);
- p->mcnext = NULL;
- p->mcalloc = MARK_ALLOC_INCR;
- p->mcptr.cp = (char *)(((char *)p) + sizeof(MCHUNK));
-
- if(curmch) { // Link onto previous chunk
- *markptr.wp++ = MCHEND; // Mark end of block
- curmch->mcused = mcused;
- curmch->mcnext = p;
- }
- if(!firstmch)
- firstmch = p;
-
- curmch = p; // Setup global vars
- markptr = p->mcptr;
- mcalloc = MARK_ALLOC_INCR;
- mcused = 0;
-
- return(0);
+int amark(void)
+{
+ MCHUNK * p;
+
+ // Alloc mark block header (and data) and set it up.
+ p = (MCHUNK *)amem((long)(sizeof(MCHUNK)) + MARK_ALLOC_INCR);
+ p->mcnext = NULL;
+ p->mcalloc = MARK_ALLOC_INCR;
+ p->mcptr.cp = (char *)(((char *)p) + sizeof(MCHUNK));
+
+ if (curmch)
+ { // Link onto previous chunk
+ *markptr.wp++ = MCHEND; // Mark end of block
+ curmch->mcused = mcused;
+ curmch->mcnext = p;
+ }
+
+ if (!firstmch)
+ firstmch = p;
+
+ curmch = p; // Setup global vars
+ markptr = p->mcptr;
+ mcalloc = MARK_ALLOC_INCR;
+ mcused = 0;
+
+ return 0;
}
+
//
-// --- Make mark image for BSD .o file -------------------------------------------------------------
+// Make mark image for BSD .o file
//
-
-LONG bsdmarkimg(char *mp, LONG siz, LONG tsize, int reqseg) {
- MCHUNK *mch; // Mark chunk
- PTR p; // Source point from within mark chunk
- WORD from; // Section fixups are currently FROM
- WORD w; // A word (temp)
- LONG loc; // Location (temp)
- SYM *symbol; // Symbols (temp)
- char *wp; // Pointer into raw relocation info
- char *dp; // Deposit point for RELMOD info
- LONG diff; // Difference to relocate (RELMOD)
- LONG raddr, rflag = 0; // BSD relocation address and flags
- LONG rsize; // Relocation size
- int validsegment = 0; // Valid segment being processed
-
- rsize = 0; // Initialise relocation size
- chptr = mp;
-
- from = 0;
- for(mch = firstmch; mch != NULL; mch = mch->mcnext)
- for(p = mch->mcptr;;) {
- w = *p.wp++; // Next mark entry
-
- if(w & MCHEND) break; // End of mark chunk
-
- // Get mark record
- symbol = NULL;
- loc = *p.lp++; // Mark location
- if(w & MCHFROM) { // Maybe change "from" section
- from = *p.wp++;
- if(obj_format == BSD) {
- if(reqseg == TEXT) { // Requested segment is TEXT
- if(from == TEXT) validsegment = 1;
- else validsegment = 0;
- } else { // Requested segment is DATA
- if(from == DATA) validsegment = 1;
- else validsegment = 0;
- }
- }
- }
-
- if(w & MSYMBOL) // Maybe includes a symbol
- symbol = *p.sy++;
-
- if(obj_format == BSD) {
- raddr = loc; // Set relocation address
- if(validsegment)
- D_long(raddr); // Write relocation address
- if(w & MPCREL)
- rflag = 0x000000A0; // PC-relative fixup
- else
- rflag = 0x00000040; // Absolute fixup
- if(w & MMOVEI)
- rflag |= 0x00000001;
- }
-
- // Compute mark position in relocation information;
- // in RELMOD mode, get address of data to fix up.
- if(from == DATA)
- loc += tsize;
- wp = (char *)(mp + loc);
-
- if(symbol) {
- // Deposit external reference
- if(obj_format == BSD) {
- rflag |= 0x00000010; // Set external reloc flag bit
- rflag |= (symbol->senv << 8); // Put symbol index in flags
- if(symbol->sattre & RISCSYM) rflag |= 0x00000001;
- if(validsegment) {
- D_long(rflag); // Write relocation flags
- rsize += 8; // Increment relocation size
- }
- }
-
- } else {
-
- if(obj_format == BSD) {
- w &= TDB; // Set reloc flags to segment
- switch(w) {
- case TEXT: rflag |= 0x00000400; break;
- case DATA: rflag |= 0x00000600; break;
- case BSS: rflag |= 0x00000800; break;
- }
- if(validsegment) {
- D_long(rflag); // Write relocation flags
- rsize += 8; // Increment relocation size
- }
- w &= TDB;
- if(validsegment) {
- if(w & (DATA|BSS)) {
- dp = objimage + BSDHDRSIZE + loc;
- diff = ((LONG)(*dp++ & 0xff)) << 24;
- diff |= ((LONG)(*dp++ & 0xff)) << 16;
- diff |= ((LONG)(*dp++ & 0xff)) << 8;
- diff |= (LONG)(*dp & 0xff);
- DEBUG printf("diff=%ux ==> ", diff);
- if(rflag & 0x01)
- diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000);
- diff += sect[TEXT].sloc;
- if(w == BSS)
- diff += sect[DATA].sloc;
- if(rflag & 0x01)
- diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000);
- dp = objimage + BSDHDRSIZE + loc;
- *dp++ = (char)(diff >> 24);
- *dp++ = (char)(diff >> 16);
- *dp++ = (char)(diff >> 8);
- *dp = (char)diff;
- DEBUG printf("%ux\n", diff);
- }
- }
- }
- }
- }
-
- if(obj_format == BSD) // Return relocation size
- return(rsize);
- else
- return(siz);
+LONG bsdmarkimg(char * mp, LONG siz, LONG tsize, int reqseg)
+{
+ MCHUNK * mch; // Mark chunk
+ PTR p; // Source point from within mark chunk
+ WORD from; // Section fixups are currently FROM
+ WORD w; // A word (temp)
+ LONG loc; // Location (temp)
+ SYM * symbol; // Symbols (temp)
+ char * wp; // Pointer into raw relocation info
+ char * dp; // Deposit point for RELMOD info
+ LONG diff; // Difference to relocate (RELMOD)
+ LONG raddr, rflag = 0; // BSD relocation address and flags
+ LONG rsize; // Relocation size
+ int validsegment = 0; // Valid segment being processed
+
+ rsize = 0; // Initialise relocation size
+ chptr = mp;
+
+ from = 0;
+ for(mch = firstmch; mch != NULL; mch = mch->mcnext)
+ {
+ for(p=mch->mcptr;;)
+ {
+ w = *p.wp++; // Next mark entry
+
+ if (w & MCHEND)
+ break; // End of mark chunk
+
+ // Get mark record
+ symbol = NULL;
+ loc = *p.lp++; // Mark location
+
+ if (w & MCHFROM)
+ { // Maybe change "from" section
+ from = *p.wp++;
+
+ if (obj_format == BSD)
+ {
+ if (reqseg == TEXT)
+ { // Requested segment is TEXT
+ if (from == TEXT)
+ validsegment = 1;
+ else
+ validsegment = 0;
+ }
+ else
+ { // Requested segment is DATA
+ if (from == DATA)
+ validsegment = 1;
+ else
+ validsegment = 0;
+ }
+ }
+ }
+
+ if (w & MSYMBOL) // Maybe includes a symbol
+ symbol = *p.sy++;
+
+ if (obj_format == BSD)
+ {
+ raddr = loc; // Set relocation address
+
+ if (validsegment)
+ D_long(raddr); // Write relocation address
+
+ if (w & MPCREL)
+ rflag = 0x000000A0; // PC-relative fixup
+ else
+ rflag = 0x00000040; // Absolute fixup
+
+ if (w & MMOVEI)
+ rflag |= 0x00000001;
+ }
+
+ // Compute mark position in relocation information;
+ // in RELMOD mode, get address of data to fix up.
+ if (from == DATA)
+ loc += tsize;
+
+ wp = (char *)(mp + loc);
+
+ if (symbol)
+ {
+ // Deposit external reference
+ if (obj_format == BSD)
+ {
+ rflag |= 0x00000010; // Set external reloc flag bit
+ rflag |= (symbol->senv << 8); // Put symbol index in flags
+
+ if (symbol->sattre & RISCSYM)
+ rflag |= 0x00000001;
+
+ if (validsegment)
+ {
+ D_long(rflag); // Write relocation flags
+ rsize += 8; // Increment relocation size
+ }
+ }
+ }
+ else
+ {
+ if (obj_format == BSD)
+ {
+ w &= TDB; // Set reloc flags to segment
+
+ switch (w)
+ {
+ case TEXT: rflag |= 0x00000400; break;
+ case DATA: rflag |= 0x00000600; break;
+ case BSS: rflag |= 0x00000800; break;
+ }
+
+ if (validsegment)
+ {
+ D_long(rflag); // Write relocation flags
+ rsize += 8; // Increment relocation size
+ }
+
+ w &= TDB;
+
+ if (validsegment)
+ {
+ if (w & (DATA|BSS))
+ {
+ dp = objimage + BSDHDRSIZE + loc;
+ diff = ((LONG)(*dp++ & 0xFF)) << 24;
+ diff |= ((LONG)(*dp++ & 0xFF)) << 16;
+ diff |= ((LONG)(*dp++ & 0xFF)) << 8;
+ diff |= (LONG)(*dp & 0xFF);
+ DEBUG printf("diff=%ux ==> ", diff);
+
+ if (rflag & 0x01)
+ diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000);
+
+ diff += sect[TEXT].sloc;
+
+ if (w == BSS)
+ diff += sect[DATA].sloc;
+
+ if (rflag & 0x01)
+ diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000);
+
+ dp = objimage + BSDHDRSIZE + loc;
+ *dp++ = (char)(diff >> 24);
+ *dp++ = (char)(diff >> 16);
+ *dp++ = (char)(diff >> 8);
+ *dp = (char)diff;
+ DEBUG printf("%ux\n", diff);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Return relocation size
+ if (obj_format == BSD)
+ return rsize;
+
+ return siz;
}
#include "rmac.h"
#include "sect.h"
-#define MARK_ALLOC_INCR 1024 // #bytes to alloc for more mark space
+#define MARK_ALLOC_INCR 1024 // #bytes to alloc for more mark space
#define MIN_MARK_MEM (3*sizeof(WORD)+2*sizeof(LONG))
// Globals, Externals etc
// 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)
#define BSDHDRSIZE 0x20 // Size of BSD header
// Globals, externals etc
-extern char *objimage;
+extern char * objimage;
// Prototypes
int object(WORD);
// Source Utilised with the Kind Permission of Landon Dyer
//
-// This file is included (twice) to parse two addressing modes, into slightly different var names
+// This file is included (twice) to parse two addressing modes, into slightly
+// different var names
{
- // Dn
- // An
- // # expression
- if((*tok >= KW_D0) && (*tok <= KW_D7)) {
- AMn = DREG;
- AnREG = *tok++ & 7;
- } else if((*tok >= KW_A0) && (*tok <= KW_A7)) {
- AMn = AREG;
- AnREG = *tok++ & 7;
- } else if(*tok == '#') {
- ++tok;
- if(expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
- return(ERROR);
- AMn = IMMED;
- }
- // (An)
- // (An)+
- // (An,Xn[.siz][*scale])
- // (PC,Xn[.siz][*scale])
- // (d16,An)
- // (d8,An,Xn[.siz][*scale])
- // (d16,PC)
- // (d8,PC,Xn[.siz][*scale])
- // ([bd,An],Xn,od)
- // ([bd,An,Xn],od)
- // ([bd,PC],Xn,od)
- // ([bd,PC,Xn],od)
- else if(*tok == '(') {
- ++tok;
- if((*tok >= KW_A0) && (*tok <= KW_A7)) {
- AnREG = *tok++ & 7;
- if(*tok == ')') {
- ++tok;
- if(*tok == '+') {
- ++tok;
- AMn = APOSTINC;
- } else AMn = AIND;
- goto AnOK;
- }
- AMn = AINDEXED;
- goto AMn_IX0; // Handle ",Xn[.siz][*scale])"
- } else if(*tok == KW_PC) { // (PC,Xn[.siz][*scale])
- ++tok;
- AMn = PCINDEXED;
-
- // Common index handler; enter here with `tok' pointing at the comma.
-
- AMn_IX0: // Handle indexed with missing expr
-
- AnEXVAL = 0;
- AnEXATTR = ABS | DEFINED;
-
- AMn_IXN: // Handle any indexed (tok -> a comma)
-
- if(*tok++ != ',')
- goto badmode;
- if(*tok < KW_D0 || *tok > KW_A7)
- goto badmode;
- AnIXREG = *tok++ & 15;
-
- switch((int)*tok) { // Index reg size: <empty> | .W | .L
- case DOTW:
- ++tok;
- default:
- AnIXSIZ = 0;
- break;
- case DOTL:
- AnIXSIZ = 0x0800;
- ++tok;
- break;
- case DOTB: // .B not allowed here...
- goto badmode;
- }
-
- if(*tok == '*') { // scale: *1, *2, *4, *8
- ++tok;
- if(*tok++ != CONST || *tok > 8)
- goto badmode;
-
- switch((int)*tok++) {
- case 1:
- break;
- case 2:
- AnIXSIZ |= TIMES2;
- break;
- case 4:
- AnIXSIZ |= TIMES4;
- break;
- case 8:
- AnIXSIZ |= TIMES8;
- break;
- default:
- goto badmode;
- }
- }
-
- if(*tok++ != ')') // final ")"
- goto badmode;
- goto AnOK;
- } else if(*tok == '[') { // ([...
- goto unmode;
- } else { // (expr...
- if(expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
- return ERROR;
- if(*tok++ != ',')
- goto badmode;
-
- if((*tok >= KW_A0) && (*tok <= KW_A7)) {
- AnREG = *tok & 7;
- ++tok;
- if(*tok == ',') {
- AMn = AINDEXED;
- goto AMn_IXN;
- } else if(*tok == ')') {
- AMn = ADISP;
- ++tok;
- goto AnOK;
- } else goto badmode;
- } else if(*tok == KW_PC) {
- if(*++tok == ',') { // expr(PC,Xn...)
- AMn = PCINDEXED;
- goto AMn_IXN;
- } else if(*tok == ')') {
- AMn = PCDISP; // expr(PC)
- ++tok;
- goto AnOK;
- } else goto badmode;
- } else goto badmode;
- }
- } else if(*tok=='-' && tok[1]=='(' && ((tok[2]>=KW_A0) && (tok[2]<=KW_A7)) && tok[3]==')') {
- AMn = APREDEC;
- AnREG = tok[2] & 7;
- tok += 4;
- } else if(*tok == KW_CCR) {
- AMn = AM_CCR;
- ++tok;
- goto AnOK;
- } else if(*tok == KW_SR) {
- AMn = AM_SR;
- ++tok;
- goto AnOK;
- } else if(*tok == KW_USP) {
- AMn = AM_USP;
- ++tok;
- goto AnOK;
- }
- // expr
- // expr.w
- // expr.l
- // d16(An)
- // d8(An,Xn[.siz])
- // d16(PC)
- // d8(PC,Xn[.siz])
- else {
- if(expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
- return ERROR;
-
- if(*tok == DOTW) { // expr.W
- ++tok;
- AMn = ABSW;
- goto AnOK;
- } else if(*tok != '(') { // expr[.L]
- AMn = ABSL;
- // Defined, absolute values from $FFFF8000..$00007FFF get optimized to absolute short
- if((AnEXATTR & (TDB|DEFINED)) == DEFINED && (AnEXVAL + 0x8000) < 0x10000)
- AMn = ABSW;
-
- if(*tok == DOTL) { // force .L
- ++tok;
- AMn = ABSL;
- }
- goto AnOK;
- }
-
- ++tok;
- if((*tok >= KW_A0) && (*tok <= KW_A7)) {
- AnREG = *tok++ & 7;
- if(*tok == ')') {
- AMn = ADISP;
- ++tok;
- goto AnOK;
- }
- AMn = AINDEXED;
- goto AMn_IXN;
- } else if(*tok == KW_PC) {
- if(*++tok == ')') {
- AMn = PCDISP;
- ++tok;
- goto AnOK;
- }
- AMn = PCINDEXED;
- goto AMn_IXN;
- }
- goto badmode;
- }
-
- // Addressing mode OK
-
- AnOK:
- ;
+ // Dn
+ // An
+ // # expression
+ if ((*tok >= KW_D0) && (*tok <= KW_D7))
+ {
+ AMn = DREG;
+ AnREG = *tok++ & 7;
+ }
+ else if ((*tok >= KW_A0) && (*tok <= KW_A7))
+ {
+ AMn = AREG;
+ AnREG = *tok++ & 7;
+ }
+ else if (*tok == '#')
+ {
+ ++tok;
+ if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
+ return ERROR;
+
+ AMn = IMMED;
+ }
+ // (An)
+ // (An)+
+ // (An,Xn[.siz][*scale])
+ // (PC,Xn[.siz][*scale])
+ // (d16,An)
+ // (d8,An,Xn[.siz][*scale])
+ // (d16,PC)
+ // (d8,PC,Xn[.siz][*scale])
+ // ([bd,An],Xn,od)
+ // ([bd,An,Xn],od)
+ // ([bd,PC],Xn,od)
+ // ([bd,PC,Xn],od)
+ else if (*tok == '(')
+ {
+ ++tok;
+
+ if ((*tok >= KW_A0) && (*tok <= KW_A7))
+ {
+ AnREG = *tok++ & 7;
+
+ if (*tok == ')')
+ {
+ ++tok;
+
+ if (*tok == '+')
+ {
+ ++tok;
+ AMn = APOSTINC;
+ }
+ else
+ AMn = AIND;
+
+ goto AnOK;
+ }
+
+ AMn = AINDEXED;
+ goto AMn_IX0; // Handle ",Xn[.siz][*scale])"
+ }
+ else if (*tok == KW_PC)
+ { // (PC,Xn[.siz][*scale])
+ ++tok;
+ AMn = PCINDEXED;
+
+ // Common index handler; enter here with `tok' pointing at the comma.
+
+ AMn_IX0: // Handle indexed with missing expr
+
+ AnEXVAL = 0;
+ AnEXATTR = ABS | DEFINED;
+
+ AMn_IXN: // Handle any indexed (tok -> a comma)
+
+ if (*tok++ != ',')
+ goto badmode;
+
+ if (*tok < KW_D0 || *tok > KW_A7)
+ goto badmode;
+
+ AnIXREG = *tok++ & 15;
+
+ switch ((int)*tok)
+ { // Index reg size: <empty> | .W | .L
+ case DOTW:
+ ++tok;
+ default:
+ AnIXSIZ = 0;
+ break;
+ case DOTL:
+ AnIXSIZ = 0x0800;
+ ++tok;
+ break;
+ case DOTB: // .B not allowed here...
+ goto badmode;
+ }
+
+ if (*tok == '*')
+ { // scale: *1, *2, *4, *8
+ ++tok;
+ if (*tok++ != CONST || *tok > 8)
+ goto badmode;
+
+ switch ((int)*tok++)
+ {
+ case 1:
+ break;
+ case 2:
+ AnIXSIZ |= TIMES2;
+ break;
+ case 4:
+ AnIXSIZ |= TIMES4;
+ break;
+ case 8:
+ AnIXSIZ |= TIMES8;
+ break;
+ default:
+ goto badmode;
+ }
+ }
+
+ if (*tok++ != ')') // final ")"
+ goto badmode;
+
+ goto AnOK;
+ }
+ else if (*tok == '[')
+ { // ([...
+ goto unmode;
+ }
+ else
+ { // (expr...
+ if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
+ return ERROR;
+
+ if (*tok++ != ',')
+ goto badmode;
+
+ if ((*tok >= KW_A0) && (*tok <= KW_A7))
+ {
+ AnREG = *tok & 7;
+ ++tok;
+
+ if (*tok == ',')
+ {
+ AMn = AINDEXED;
+ goto AMn_IXN;
+ }
+ else if (*tok == ')')
+ {
+ AMn = ADISP;
+ ++tok;
+ goto AnOK;
+ }
+ else
+ goto badmode;
+ }
+ else if (*tok == KW_PC)
+ {
+ if (*++tok == ',')
+ { // expr(PC,Xn...)
+ AMn = PCINDEXED;
+ goto AMn_IXN;
+ }
+ else if (*tok == ')')
+ {
+ AMn = PCDISP; // expr(PC)
+ ++tok;
+ goto AnOK;
+ }
+ else
+ goto badmode;
+ }
+ else
+ goto badmode;
+ }
+ }
+ else if (*tok=='-' && tok[1]=='(' && ((tok[2]>=KW_A0) && (tok[2]<=KW_A7)) && tok[3]==')')
+ {
+ AMn = APREDEC;
+ AnREG = tok[2] & 7;
+ tok += 4;
+ }
+ else if (*tok == KW_CCR)
+ {
+ AMn = AM_CCR;
+ ++tok;
+ goto AnOK;
+ }
+ else if (*tok == KW_SR)
+ {
+ AMn = AM_SR;
+ ++tok;
+ goto AnOK;
+ }
+ else if (*tok == KW_USP)
+ {
+ AMn = AM_USP;
+ ++tok;
+ goto AnOK;
+ }
+ // expr
+ // expr.w
+ // expr.l
+ // d16(An)
+ // d8(An,Xn[.siz])
+ // d16(PC)
+ // d8(PC,Xn[.siz])
+ else
+ {
+ if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
+ return ERROR;
+
+ if (*tok == DOTW)
+ { // expr.W
+ ++tok;
+ AMn = ABSW;
+ goto AnOK;
+ }
+ else if (*tok != '(')
+ { // expr[.L]
+ AMn = ABSL;
+ // Defined, absolute values from $FFFF8000..$00007FFF get optimized to absolute short
+
+ if ((AnEXATTR & (TDB|DEFINED)) == DEFINED && (AnEXVAL + 0x8000) < 0x10000)
+ AMn = ABSW;
+
+ if (*tok == DOTL)
+ { // force .L
+ ++tok;
+ AMn = ABSL;
+ }
+
+ goto AnOK;
+ }
+
+ ++tok;
+
+ if ((*tok >= KW_A0) && (*tok <= KW_A7))
+ {
+ AnREG = *tok++ & 7;
+
+ if (*tok == ')')
+ {
+ AMn = ADISP;
+ ++tok;
+ goto AnOK;
+ }
+
+ AMn = AINDEXED;
+ goto AMn_IXN;
+ }
+ else if (*tok == KW_PC)
+ {
+ if (*++tok == ')')
+ {
+ AMn = PCDISP;
+ ++tok;
+ goto AnOK;
+ }
+
+ AMn = PCINDEXED;
+ goto AMn_IXN;
+ }
+ goto badmode;
+ }
+
+ // Addressing mode OK
+
+ AnOK:
+ ;
}
// Cleanup dirty little macros
#define DECL_MR
#include "risckw.h"
-IFENT *ifent; // Current ifent
+IFENT * ifent; // Current ifent
static IFENT ifent0; // Root ifent
-static IFENT *f_ifent; // Freelist of ifents
+static IFENT * f_ifent; // Freelist of ifents
static int disabled; // Assembly conditionally disabled
int just_bss; // 1, ds.b in microprocessor mode
VALUE pcloc; // Value of "PC" at beginning of line
-IFENT *ifent; // Current ifent
-SYM *lab_sym; // Label on line (or NULL)
+IFENT * ifent; // Current ifent
+SYM * lab_sym; // Label on line (or NULL)
char extra_stuff[] = "extra (unexpected) text found after addressing mode";
-char *comma_error = "missing comma";
-char *syntax_error = "syntax error";
-char *locgl_error = "cannot GLOBL local symbol";
-char *lab_ignored = "label ignored";
+char * comma_error = "missing comma";
+char * syntax_error = "syntax error";
+char * locgl_error = "cannot GLOBL local symbol";
+char * lab_ignored = "label ignored";
// Table to convert an addressing-mode number to a bitmask.
LONG amsktab[0112] = {
- M_DREG, M_DREG, M_DREG, M_DREG,
- M_DREG, M_DREG, M_DREG, M_DREG,
-
- M_AREG, M_AREG, M_AREG, M_AREG,
- M_AREG, M_AREG, M_AREG, M_AREG,
-
- M_AIND, M_AIND, M_AIND, M_AIND,
- M_AIND, M_AIND, M_AIND, M_AIND,
-
- M_APOSTINC, M_APOSTINC, M_APOSTINC, M_APOSTINC,
- M_APOSTINC, M_APOSTINC, M_APOSTINC, M_APOSTINC,
-
- M_APREDEC, M_APREDEC, M_APREDEC, M_APREDEC,
- M_APREDEC, M_APREDEC, M_APREDEC, M_APREDEC,
-
- M_ADISP, M_ADISP, M_ADISP, M_ADISP,
- M_ADISP, M_ADISP, M_ADISP, M_ADISP,
-
- M_AINDEXED, M_AINDEXED, M_AINDEXED, M_AINDEXED,
- M_AINDEXED, M_AINDEXED, M_AINDEXED, M_AINDEXED,
-
- M_ABSW, // 070
- M_ABSL, // 071
- M_PCDISP, // 072
- M_PCINDEXED, // 073
- M_IMMED, // 074
- 0L, // 075
- 0L, // 076
- 0L, // 077
- M_ABASE, // 0100
- M_MEMPOST, // 0101
- M_MEMPRE, // 0102
- M_PCBASE, // 0103
- M_PCMPOST, // 0104
- M_PCMPRE, // 0105
- M_AM_USP, // 0106
- M_AM_SR, // 0107
- M_AM_CCR, // 0110
- M_AM_NONE // 0111
+ M_DREG, M_DREG, M_DREG, M_DREG,
+ M_DREG, M_DREG, M_DREG, M_DREG,
+
+ M_AREG, M_AREG, M_AREG, M_AREG,
+ M_AREG, M_AREG, M_AREG, M_AREG,
+
+ M_AIND, M_AIND, M_AIND, M_AIND,
+ M_AIND, M_AIND, M_AIND, M_AIND,
+
+ M_APOSTINC, M_APOSTINC, M_APOSTINC, M_APOSTINC,
+ M_APOSTINC, M_APOSTINC, M_APOSTINC, M_APOSTINC,
+
+ M_APREDEC, M_APREDEC, M_APREDEC, M_APREDEC,
+ M_APREDEC, M_APREDEC, M_APREDEC, M_APREDEC,
+
+ M_ADISP, M_ADISP, M_ADISP, M_ADISP,
+ M_ADISP, M_ADISP, M_ADISP, M_ADISP,
+
+ M_AINDEXED, M_AINDEXED, M_AINDEXED, M_AINDEXED,
+ M_AINDEXED, M_AINDEXED, M_AINDEXED, M_AINDEXED,
+
+ M_ABSW, // 070
+ M_ABSL, // 071
+ M_PCDISP, // 072
+ M_PCINDEXED, // 073
+ M_IMMED, // 074
+ 0L, // 075
+ 0L, // 076
+ 0L, // 077
+ M_ABASE, // 0100
+ M_MEMPOST, // 0101
+ M_MEMPRE, // 0102
+ M_PCBASE, // 0103
+ M_PCMPOST, // 0104
+ M_PCMPRE, // 0105
+ M_AM_USP, // 0106
+ M_AM_SR, // 0107
+ M_AM_CCR, // 0110
+ M_AM_NONE // 0111
}; // 0112 length
+
//
-// --- Initialize Line Processor -------------------------------------------------------------------
+// Initialize Line Processor
//
-
-void init_procln(void) {
- disabled = 0;
- ifent = &ifent0;
- f_ifent = ifent0.if_prev = NULL;
- ifent0.if_state = 0;
+void init_procln(void)
+{
+ disabled = 0;
+ ifent = &ifent0;
+ f_ifent = ifent0.if_prev = NULL;
+ ifent0.if_state = 0;
}
+
//
-// --- Line Processor ------------------------------------------------------------------------------
+// Line Processor
//
-
-void assemble(void) {
- int state; // Keyword machine state (output)
- int j; // Random int, must be fast
- char *p; // Random char ptr, must be fast
- TOKEN *tk; // First token in line
- char *label; // Symbol (or NULL)
- char *equate; // Symbol (or NULL)
- int labtyp = 0; // Label type (':', DCOLON)
- int equtyp = 0; // Equ type ('=', DEQUALS)
- VALUE eval; // Expression value
- WORD eattr; // Expression attributes
- SYM *esym; // External symbol involved in expr.
- WORD siz = 0; // Size suffix to mnem/diretve/macro
- LONG amsk0, amsk1; // Address-type masks for ea0, ea1
- MNTAB *m; // Code generation table pointer
- SYM *sy, *sy2; // Symbol (temp usage)
- char *opname = NULL; // Name of dirctve/mnemonic/macro
- int listflag; // 0: Don't call listeol()
- int as68mode = 0; // 1: Handle multiple labels
- WORD rmask; // Register list, for REG
- int registerbank; // RISC register bank
- int riscreg; // RISC register
-
- listflag = 0; // Initialise listing flag
-
- loop: // Line processing loop label
-
- if(tokln() == TKEOF) { // Get another line of tokens
- if(list_flag && listflag) // Flush last line of source
- listeol();
- if(ifent->if_prev != NULL) // Check conditional token
- error("hit EOF without finding matching .endif");
- return;
- }
-
- if(list_flag) {
- if(listflag && listing > 0) listeol(); // Tell listing generator about EOL
- lstout((char)(disabled ? '-' : lntag)); // Prepare new line for listing
- listflag = 1; // OK to call `listeol' now
- just_bss = 0; // Reset just_bss mode
- }
-
- state = -3; // No keyword (just EOL)
- label = NULL; // No label
- lab_sym = NULL; // No (exported) label
- equate = NULL; // No equate
- tk = tok; // Save first token in line
- pcloc = (VALUE)sloc; // Set beginning-of-line PC
-
- loop1: // Internal line processing loop
-
- if(*tok == EOL) // Restart loop if end-of-line
- goto loop;
-
- if(*tok != SYMBOL) { // First token MUST be a symbol
- error(syntax_error);
- goto loop;
- }
-
- j = (int)tok[2]; // Skip equates (normal statements)
- if(j == '=' || j == DEQUALS || j == SET || j == REG || j == EQUREG || j == CCDEF) {
- equate = (char *)tok[1];
- equtyp = j;
- tok += 3;
- goto normal;
- }
-
- if(j == ':' || j == DCOLON) { // Skip past label (but record it)
-
- as68label:
-
- label = (char *)tok[1]; // Get label name
- labtyp = tok[2]; // Get label type
- tok += 3; // Go to next line token
-
- // Handle multiple labels; if there's another label, go process it,
- // and come back at `as68label' above.
- if(as68_flag) {
- as68mode = 0;
- if(*tok == SYMBOL && tok[2] == ':') {
- as68mode = 1;
- goto do_label;
- }
- }
- }
-
- if(*tok == EOL) // EOL is legal here...
- goto normal;
-
- if(*tok++ != SYMBOL) { // Next token MUST be a symbol
- error(syntax_error);
- goto loop;
- }
- opname = p = (char *)*tok++; // Store opcode name here
-
- // Check to see if the SYMBOL is a keyword (a mnemonic or directive).
- // On output, `state' will have one of the values:
- // -3 there was no symbol (EOL)
- // -2..-1 the symbol didn't match any keyword
- // 0..499 vanilla directives (dc, ds, etc.)
- // 500..999 electric directives (macro, rept, etc.)
- // 1000..+ mnemonics (move, lsr, etc.)
- for(state = 0; state >= 0;) {
- j = mnbase[state] + (int)tolowertab[*p];
- if(mncheck[j] != state) { // Reject, character doesn't match
- state = -1; // No match
- break;
- }
- if(!*++p) { // Must accept or reject at EOS
- state = mnaccept[j]; // (-1 on no terminal match)
- break;
- }
- state = mntab[j];
- }
-
- // Check for ".b" ".w" ".l" after directive, macro or mnemonic.
- siz = SIZN;
- if(*tok == DOTW)
- siz = SIZW, ++tok;
- else if(*tok == DOTL)
- siz = SIZL, ++tok;
- else if(*tok == DOTB)
- siz = SIZB, ++tok;
-
- // Do special directives (500..999) (These must be handled in "real time")
- if(state >= 500 && state < 1000)
- switch(state) {
- case MN_IF:
- d_if();
- goto loop;
- case MN_ELSE:
- d_else();
- goto loop;
- case MN_ENDIF:
- d_endif();
- goto loop;
- case MN_IIF: // .iif --- immediate if
- if(disabled || expr(exprbuf, &eval, &eattr, &esym) != OK)
- goto loop;
- if(!(eattr & DEFINED)) {
- error(undef_error);
- goto loop;
- }
- if(*tok++ != ',') {
- error(comma_error);
- goto loop;
- }
- if(eval == 0)
- goto loop;
- goto loop1;
- case MN_MACRO: // .macro --- macro definition
- if(!disabled) {
- if(label != NULL)
- warn(lab_ignored);
- defmac();
- }
- goto loop;
- case MN_EXITM: // .exitm --- exit macro
- case MN_ENDM: // .endm --- same as .exitm
- if(!disabled) {
- if(label != NULL)
- warn(lab_ignored);
- exitmac();
- }
- goto loop;
- case MN_REPT:
- if(!disabled) {
- if(label != NULL)
- warn(lab_ignored);
- defrept();
- }
- goto loop;
- case MN_ENDR:
- if(!disabled)
- error("mis-nested .endr");
- goto loop;
- }
-
- normal:
-
- if(disabled) // Conditionally disabled code
- goto loop;
-
- // Do equates
- if(equate != NULL) {
- j = 0; // Pick global or local sym enviroment
- if(*equate == '.')
- j = curenv;
-
- sy = lookup(equate, LABEL, j);
- if(sy == NULL) {
- sy = newsym(equate, LABEL, j);
- sy->sattr = 0;
- if(equtyp == DEQUALS) {
- if(j) { // Can't GLOBAL a local symbol
- error(locgl_error);
- goto loop;
- }
- sy->sattr = GLOBAL;
- }
- } else if((sy->sattr & DEFINED) && equtyp != SET) {
- if((equtyp == EQUREG) && (sy->sattre & UNDEF_EQUR)) {
- sy->sattre |= ~UNDEF_EQUR;
- sy->svalue = 0;
- } else if((equtyp == CCDEF) && (sy->sattre & UNDEF_CC)) {
- sy->sattre |= ~UNDEF_CC;
- sy->svalue = 0;
- } else {
- errors("multiple equate to '%s'", sy->sname);
- goto loop;
- }
- }
-
- // Put symbol in "order of definition" list
- if(!(sy->sattr & SDECLLIST)) sym_decl(sy);
-
- // Parse value to equate symbol to;
- // o .equr
- // o .reg
- // o everything else
- if(equtyp == EQUREG) {
- if(!rgpu && !rdsp) { // Check that we are in a RISC section
- error(".equr/.regequ must be defined in .gpu/.dsp section");
- goto loop;
- }
- if((*tok >= KW_R0) && (*tok <= KW_R31)) { // Check for register to equate to
- sy->sattre = EQUATEDREG | RISCSYM; // Mark as equated register
- riscreg = (*tok - KW_R0);
- sy->sattre |= (riscreg << 8); // Store register number
- if((tok[1] == ',') && (tok[2] == CONST)) {
- tok += 3;
- if(*tok == 0) registerbank = BANK_0;
- else if(*tok == 1) registerbank = BANK_1;
- else registerbank = BANK_N;
- } else {
- registerbank = BANK_N;
- }
- sy->sattre |= regbank; // Store register bank
- eattr = ABS | DEFINED | GLOBAL;
- eval = 0x80000080 + (riscreg) + (registerbank << 8);
- tok++;
- } else if(tok[0] == SYMBOL) { // Checking for a register symbol
- sy2 = lookup((char *)tok[1], LABEL, j);
- if(!sy2 || !(sy2->sattre & EQUATEDREG)) { // Make sure symbol is a valid equreg
- error("invalid GPU/DSP .equr/.regequ definition");
- goto loop;
- } else {
- eattr = ABS | DEFINED | GLOBAL; // Copy symbols attributes
- sy->sattre = sy2->sattre;
- eval = (sy2->svalue & 0xFFFFF0FF);
- tok += 2;
- }
- } else {
- error("invalid GPU/DSP .equr/.regequ definition");
- goto loop;
- }
- } else if(equtyp == REG) {
- if(reglist(&rmask) < 0)
- goto loop;
- eval = (VALUE)rmask;
- eattr = ABS | DEFINED;
- } else if(equtyp == CCDEF) {
- sy->sattre |= EQUATEDCC;
- eattr = ABS | DEFINED | GLOBAL;
- if(tok[0] == SYMBOL) {
- sy2 = lookup((char *)tok[1], LABEL, j);
- if(!sy2 || !(sy2->sattre & EQUATEDCC)) {
- error("invalid gpu/dsp .ccdef definition");
- goto loop;
- } else {
- eattr = ABS | DEFINED | GLOBAL;
- sy->sattre = sy2->sattre;
- eval = sy2->svalue;
- tok += 2;
- }
- } else
- if(expr(exprbuf, &eval, &eattr, &esym) != OK)
- goto loop;
- } else if(*tok == SYMBOL) { //equ a equr
- sy2 = lookup((char *)tok[1], LABEL, j);
- if(sy2 && (sy2->sattre & EQUATEDREG)) {
- sy->stype = sy2->stype;
- sy->sattr = sy2->sattr;
- sy->sattre = sy2->sattre;
- sy->svalue = (sy2->svalue & 0xFFFFF0FF);
- goto loop;
- } else
- if(expr(exprbuf, &eval, &eattr, &esym) != OK)
- goto loop;
- } else
- if(expr(exprbuf, &eval, &eattr, &esym) != OK)
- goto loop;
-
- if(!(eattr & DEFINED)) {
- error(undef_error);
- goto loop;
- }
-
-
- sy->sattr |= eattr | EQUATED; // Symbol inherits value and attributes
- sy->svalue = eval;
- if(list_flag) // Put value in listing
- listvalue(eval);
-
- at_eol(); // Must be at EOL now
- goto loop;
- }
-
- // Do labels
- if(label != NULL) {
-
- do_label:
-
- j = 0;
- if(*label == '.')
- j = curenv;
- sy = lookup(label, LABEL, j);
-
- if(sy == NULL) {
- sy = newsym(label, LABEL, j);
- sy->sattr = 0;
- sy->sattre = RISCSYM;
- } else if(sy->sattr & DEFINED) {
- errors("multiply-defined label '%s'", label);
- goto loop;
- }
-
- // Put symbol in "order of definition" list
- if(!(sy->sattr & SDECLLIST)) sym_decl(sy);
-
- if(orgactive) {
- sy->svalue = orgaddr;
- sy->sattr |= ABS | DEFINED | EQUATED;
- } else {
- sy->svalue = sloc;
- sy->sattr |= DEFINED | cursect;
- }
-
- lab_sym = sy;
- if(!j)
- ++curenv;
-
- if(labtyp == DCOLON) { // Make label global
- if(j) {
- error(locgl_error);
- goto loop;
- }
- sy->sattr |= GLOBAL;
- }
-
- // If we're in as68 mode, and there's another label, go back and handle it
- if(as68_flag && as68mode)
- goto as68label;
- }
-
- // Punt on EOL
- if(state == -3)
- goto loop;
-
- // If we are in GPU or DSP mode and still in need of a mnemonic then search for one
- if((rgpu || rdsp) && (state < 0 || state >= 1000)) {
- for(state = 0, p = opname; state >= 0;) {
- j = mrbase[state] + (int)tolowertab[*p];
- if(mrcheck[j] != state) { // Reject, character doesn't match
- state = -1; // No match
- break;
- }
-
- if(!*++p) { // Must accept or reject at EOS
- state = mraccept[j]; // (-1 on no terminal match)
- break;
- }
- state = mrtab[j];
- }
-
- // Call RISC code generator if we found a mnemonic
- if(state >= 3000) {
- risccg(state);
- goto loop;
- }
- }
-
- // Invoke macro or complain about bad mnemonic
- if(state < 0) {
- if((sy = lookup(opname, MACRO, 0)) != NULL)
- invokemac(sy, siz);
- else errors("unknown op '%s'", opname);
- goto loop;
- }
-
- // Call directive handlers
- if(state < 500) {
- (*dirtab[state])(siz);
- goto loop;
- }
-
- // Do mnemonics
- // o can't deposit instrs in BSS or ABS
- // o do automatic .EVEN for instrs
- // o allocate space for largest possible instr
- // o can't do ".b" operations with an address register
- if(scattr & SBSS) {
- error("cannot initialize non-storage (BSS) section");
- goto loop;
- }
-
- if(sloc & 1) // Automatic .even
- auto_even();
-
- if(challoc - ch_size < 18) // Make sure have space in current chunk
- chcheck(0L);
-
- m = &machtab[state - 1000];
- if(m->mnattr & CGSPECIAL) { // Call special-mode handler
- (*m->mnfunc)(m->mninst, siz);
- goto loop;
- }
-
- if(amode(1) < 0) // Parse 0, 1 or 2 addr modes
- goto loop;
-
- if(*tok != EOL)
- error(extra_stuff);
-
- amsk0 = amsktab[am0];
- amsk1 = amsktab[am1];
-
- // Catch attempts to use ".B" with an address register (yes, this check does work at this level)
- if(siz == SIZB && (am0 == AREG || am1 == AREG)) {
- error("cannot use '.b' with an address register");
- goto loop;
- }
-
- for(;;) {
- if((m->mnattr & siz) && (amsk0 & m->mn0) != 0 && (amsk1 & m->mn1) != 0) {
- (*m->mnfunc)(m->mninst, siz);
- goto loop;
- }
- m = &machtab[m->mncont];
- }
+void assemble(void)
+{
+ int state; // Keyword machine state (output)
+ int j; // Random int, must be fast
+ char * p; // Random char ptr, must be fast
+ TOKEN * tk; // First token in line
+ char * label; // Symbol (or NULL)
+ char * equate; // Symbol (or NULL)
+ int labtyp = 0; // Label type (':', DCOLON)
+ int equtyp = 0; // Equ type ('=', DEQUALS)
+ VALUE eval; // Expression value
+ WORD eattr; // Expression attributes
+ SYM * esym; // External symbol involved in expr.
+ WORD siz = 0; // Size suffix to mnem/diretve/macro
+ LONG amsk0, amsk1; // Address-type masks for ea0, ea1
+ MNTAB * m; // Code generation table pointer
+ SYM * sy, * sy2; // Symbol (temp usage)
+ char * opname = NULL; // Name of dirctve/mnemonic/macro
+ int listflag; // 0: Don't call listeol()
+ int as68mode = 0; // 1: Handle multiple labels
+ WORD rmask; // Register list, for REG
+ int registerbank; // RISC register bank
+ int riscreg; // RISC register
+
+ listflag = 0; // Initialise listing flag
+
+loop: // Line processing loop label
+
+ if (tokln() == TKEOF)
+ { // Get another line of tokens
+ if (list_flag && listflag) // Flush last line of source
+ listeol();
+
+ if (ifent->if_prev != NULL) // Check conditional token
+ error("hit EOF without finding matching .endif");
+
+ return;
+ }
+
+ if (list_flag)
+ {
+ if (listflag && listing > 0)
+ listeol(); // Tell listing generator about EOL
+
+ lstout((char)(disabled ? '-' : lntag)); // Prepare new line for listing
+ listflag = 1; // OK to call `listeol' now
+ just_bss = 0; // Reset just_bss mode
+ }
+
+ state = -3; // No keyword (just EOL)
+ label = NULL; // No label
+ lab_sym = NULL; // No (exported) label
+ equate = NULL; // No equate
+ tk = tok; // Save first token in line
+ pcloc = (VALUE)sloc; // Set beginning-of-line PC
+
+ loop1: // Internal line processing loop
+
+ if (*tok == EOL) // Restart loop if end-of-line
+ goto loop;
+
+ if (*tok != SYMBOL)
+ { // First token MUST be a symbol
+ error(syntax_error);
+ goto loop;
+ }
+
+ j = (int)tok[2]; // Skip equates (normal statements)
+
+ if (j == '=' || j == DEQUALS || j == SET || j == REG || j == EQUREG || j == CCDEF)
+ {
+ equate = (char *)tok[1];
+ equtyp = j;
+ tok += 3;
+ goto normal;
+ }
+
+ if (j == ':' || j == DCOLON)
+ { // Skip past label (but record it)
+as68label:
+ label = (char *)tok[1]; // Get label name
+ labtyp = tok[2]; // Get label type
+ tok += 3; // Go to next line token
+
+ // Handle multiple labels; if there's another label, go process it,
+ // and come back at `as68label' above.
+ if (as68_flag)
+ {
+ as68mode = 0;
+
+ if (*tok == SYMBOL && tok[2] == ':')
+ {
+ as68mode = 1;
+ goto do_label;
+ }
+ }
+ }
+
+ if (*tok == EOL) // EOL is legal here...
+ goto normal;
+
+ if (*tok++ != SYMBOL)
+ { // Next token MUST be a symbol
+ error(syntax_error);
+ goto loop;
+ }
+
+ opname = p = (char *)*tok++; // Store opcode name here
+
+ // Check to see if the SYMBOL is a keyword (a mnemonic or directive).
+ // On output, `state' will have one of the values:
+ // -3 there was no symbol (EOL)
+ // -2..-1 the symbol didn't match any keyword
+ // 0..499 vanilla directives (dc, ds, etc.)
+ // 500..999 electric directives (macro, rept, etc.)
+ // 1000..+ mnemonics (move, lsr, etc.)
+ for(state=0; state>=0;)
+ {
+ j = mnbase[state] + (int)tolowertab[*p];
+
+ if (mncheck[j] != state)
+ { // Reject, character doesn't match
+ state = -1; // No match
+ break;
+ }
+
+ if (!*++p)
+ { // Must accept or reject at EOS
+ state = mnaccept[j]; // (-1 on no terminal match)
+ break;
+ }
+
+ state = mntab[j];
+ }
+
+ // Check for ".b" ".w" ".l" after directive, macro or mnemonic.
+ siz = SIZN;
+
+ if (*tok == DOTW)
+ siz = SIZW, ++tok;
+ else if (*tok == DOTL)
+ siz = SIZL, ++tok;
+ else if (*tok == DOTB)
+ siz = SIZB, ++tok;
+
+ // Do special directives (500..999) (These must be handled in "real time")
+ if (state >= 500 && state < 1000)
+ {
+ switch (state)
+ {
+ case MN_IF:
+ d_if ();
+ goto loop;
+ case MN_ELSE:
+ d_else();
+ goto loop;
+ case MN_ENDIF:
+ d_endif ();
+ goto loop;
+ case MN_IIF: // .iif --- immediate if
+ if (disabled || expr(exprbuf, &eval, &eattr, &esym) != OK)
+ goto loop;
+
+ if (!(eattr & DEFINED))
+ {
+ error(undef_error);
+ goto loop;
+ }
+
+ if (*tok++ != ',')
+ {
+ error(comma_error);
+ goto loop;
+ }
+
+ if (eval == 0)
+ goto loop;
+
+ goto loop1;
+ case MN_MACRO: // .macro --- macro definition
+ if (!disabled)
+ {
+ if (label != NULL)
+ warn(lab_ignored);
+
+ defmac();
+ }
+
+ goto loop;
+ case MN_EXITM: // .exitm --- exit macro
+ case MN_ENDM: // .endm --- same as .exitm
+ if (!disabled)
+ {
+ if (label != NULL)
+ warn(lab_ignored);
+
+ exitmac();
+ }
+
+ goto loop;
+ case MN_REPT:
+ if (!disabled)
+ {
+ if (label != NULL)
+ warn(lab_ignored);
+
+ defrept();
+ }
+
+ goto loop;
+ case MN_ENDR:
+ if (!disabled)
+ error("mis-nested .endr");
+
+ goto loop;
+ }
+ }
+
+normal:
+ if (disabled) // Conditionally disabled code
+ goto loop;
+
+ // Do equates
+ if (equate != NULL)
+ {
+ j = 0; // Pick global or local sym enviroment
+
+ if (*equate == '.')
+ j = curenv;
+
+ sy = lookup(equate, LABEL, j);
+
+ if (sy == NULL)
+ {
+ sy = newsym(equate, LABEL, j);
+ sy->sattr = 0;
+
+ if (equtyp == DEQUALS)
+ {
+ if (j)
+ { // Can't GLOBAL a local symbol
+ error(locgl_error);
+ goto loop;
+ }
+
+ sy->sattr = GLOBAL;
+ }
+ }
+ else if ((sy->sattr & DEFINED) && equtyp != SET)
+ {
+ if ((equtyp == EQUREG) && (sy->sattre & UNDEF_EQUR))
+ {
+ sy->sattre |= ~UNDEF_EQUR;
+ sy->svalue = 0;
+ }
+ else if ((equtyp == CCDEF) && (sy->sattre & UNDEF_CC))
+ {
+ sy->sattre |= ~UNDEF_CC;
+ sy->svalue = 0;
+ }
+ else
+ {
+ errors("multiple equate to '%s'", sy->sname);
+ goto loop;
+ }
+ }
+
+ // Put symbol in "order of definition" list
+ if (!(sy->sattr & SDECLLIST))
+ sym_decl(sy);
+
+ // Parse value to equate symbol to;
+ // o .equr
+ // o .reg
+ // o everything else
+ if (equtyp == EQUREG)
+ {
+ if (!rgpu && !rdsp)
+ { // Check that we are in a RISC section
+ error(".equr/.regequ must be defined in .gpu/.dsp section");
+ goto loop;
+ }
+
+ if ((*tok >= KW_R0) && (*tok <= KW_R31))
+ { // Check for register to equate to
+ sy->sattre = EQUATEDREG | RISCSYM; // Mark as equated register
+ riscreg = (*tok - KW_R0);
+ sy->sattre |= (riscreg << 8); // Store register number
+
+ if ((tok[1] == ',') && (tok[2] == CONST))
+ {
+ tok += 3;
+
+ if (*tok == 0)
+ registerbank = BANK_0;
+ else if (*tok == 1)
+ registerbank = BANK_1;
+ else
+ registerbank = BANK_N;
+ }
+ else
+ {
+ registerbank = BANK_N;
+ }
+
+ sy->sattre |= regbank; // Store register bank
+ eattr = ABS | DEFINED | GLOBAL;
+ eval = 0x80000080 + (riscreg) + (registerbank << 8);
+ tok++;
+ }
+ else if (tok[0] == SYMBOL)
+ { // Checking for a register symbol
+ sy2 = lookup((char *)tok[1], LABEL, j);
+
+ if (!sy2 || !(sy2->sattre & EQUATEDREG))
+ { // Make sure symbol is a valid equreg
+ error("invalid GPU/DSP .equr/.regequ definition");
+ goto loop;
+ }
+ else
+ {
+ eattr = ABS | DEFINED | GLOBAL; // Copy symbols attributes
+ sy->sattre = sy2->sattre;
+ eval = (sy2->svalue & 0xFFFFF0FF);
+ tok += 2;
+ }
+ }
+ else
+ {
+ error("invalid GPU/DSP .equr/.regequ definition");
+ goto loop;
+ }
+ }
+ else if (equtyp == REG)
+ {
+ if (reglist(&rmask) < 0)
+ goto loop;
+
+ eval = (VALUE)rmask;
+ eattr = ABS | DEFINED;
+ }
+ else if (equtyp == CCDEF)
+ {
+ sy->sattre |= EQUATEDCC;
+ eattr = ABS | DEFINED | GLOBAL;
+
+ if (tok[0] == SYMBOL)
+ {
+ sy2 = lookup((char *)tok[1], LABEL, j);
+
+ if (!sy2 || !(sy2->sattre & EQUATEDCC))
+ {
+ error("invalid gpu/dsp .ccdef definition");
+ goto loop;
+ }
+ else
+ {
+ eattr = ABS | DEFINED | GLOBAL;
+ sy->sattre = sy2->sattre;
+ eval = sy2->svalue;
+ tok += 2;
+ }
+ }
+ else if (expr(exprbuf, &eval, &eattr, &esym) != OK)
+ goto loop;
+ }
+ else if (*tok == SYMBOL)
+ { //equ a equr
+ sy2 = lookup((char *)tok[1], LABEL, j);
+
+ if (sy2 && (sy2->sattre & EQUATEDREG))
+ {
+ sy->stype = sy2->stype;
+ sy->sattr = sy2->sattr;
+ sy->sattre = sy2->sattre;
+ sy->svalue = (sy2->svalue & 0xFFFFF0FF);
+ goto loop;
+ }
+ else if (expr(exprbuf, &eval, &eattr, &esym) != OK)
+ goto loop;
+ }
+ else if (expr(exprbuf, &eval, &eattr, &esym) != OK)
+ goto loop;
+
+ if (!(eattr & DEFINED))
+ {
+ error(undef_error);
+ goto loop;
+ }
+
+
+ sy->sattr |= eattr | EQUATED; // Symbol inherits value and attributes
+ sy->svalue = eval;
+ if (list_flag) // Put value in listing
+ listvalue(eval);
+
+ at_eol(); // Must be at EOL now
+ goto loop;
+ }
+
+ // Do labels
+ if (label != NULL)
+ {
+do_label:
+ j = 0;
+
+ if (*label == '.')
+ j = curenv;
+
+ sy = lookup(label, LABEL, j);
+
+ if (sy == NULL)
+ {
+ sy = newsym(label, LABEL, j);
+ sy->sattr = 0;
+ sy->sattre = RISCSYM;
+ }
+ else if (sy->sattr & DEFINED)
+ {
+ errors("multiply-defined label '%s'", label);
+ goto loop;
+ }
+
+ // Put symbol in "order of definition" list
+ if (!(sy->sattr & SDECLLIST))
+ sym_decl(sy);
+
+ if (orgactive)
+ {
+ sy->svalue = orgaddr;
+ sy->sattr |= ABS | DEFINED | EQUATED;
+ }
+ else
+ {
+ sy->svalue = sloc;
+ sy->sattr |= DEFINED | cursect;
+ }
+
+ lab_sym = sy;
+
+ if (!j)
+ ++curenv;
+
+ if (labtyp == DCOLON)
+ { // Make label global
+ if (j)
+ {
+ error(locgl_error);
+ goto loop;
+ }
+
+ sy->sattr |= GLOBAL;
+ }
+
+ // If we're in as68 mode, and there's another label, go back and handle it
+ if (as68_flag && as68mode)
+ goto as68label;
+ }
+
+ // Punt on EOL
+ if (state == -3)
+ goto loop;
+
+ // If we are in GPU or DSP mode and still in need of a mnemonic then search for one
+ if ((rgpu || rdsp) && (state < 0 || state >= 1000))
+ {
+ for(state=0, p=opname; state>=0;)
+ {
+ j = mrbase[state] + (int)tolowertab[*p];
+
+ if (mrcheck[j] != state)
+ { // Reject, character doesn't match
+ state = -1; // No match
+ break;
+ }
+
+ if (!*++p)
+ { // Must accept or reject at EOS
+ state = mraccept[j]; // (-1 on no terminal match)
+ break;
+ }
+
+ state = mrtab[j];
+ }
+
+ // Call RISC code generator if we found a mnemonic
+ if (state >= 3000)
+ {
+ risccg(state);
+ goto loop;
+ }
+ }
+
+ // Invoke macro or complain about bad mnemonic
+ if (state < 0)
+ {
+ if ((sy = lookup(opname, MACRO, 0)) != NULL)
+ invokemac(sy, siz);
+ else
+ errors("unknown op '%s'", opname);
+
+ goto loop;
+ }
+
+ // Call directive handlers
+ if (state < 500)
+ {
+ (*dirtab[state])(siz);
+ goto loop;
+ }
+
+ // Do mnemonics
+ // o can't deposit instrs in BSS or ABS
+ // o do automatic .EVEN for instrs
+ // o allocate space for largest possible instr
+ // o can't do ".b" operations with an address register
+ if (scattr & SBSS)
+ {
+ error("cannot initialize non-storage (BSS) section");
+ goto loop;
+ }
+
+ if (sloc & 1) // Automatic .even
+ auto_even();
+
+ if (challoc - ch_size < 18) // Make sure have space in current chunk
+ chcheck(0L);
+
+ m = &machtab[state - 1000];
+
+ if (m->mnattr & CGSPECIAL)
+ { // Call special-mode handler
+ (*m->mnfunc)(m->mninst, siz);
+ goto loop;
+ }
+
+ if (amode(1) < 0) // Parse 0, 1 or 2 addr modes
+ goto loop;
+
+ if (*tok != EOL)
+ error(extra_stuff);
+
+ amsk0 = amsktab[am0];
+ amsk1 = amsktab[am1];
+
+ // Catch attempts to use ".B" with an address register (yes, this check does work at this level)
+ if (siz == SIZB && (am0 == AREG || am1 == AREG))
+ {
+ error("cannot use '.b' with an address register");
+ goto loop;
+ }
+
+ for(;;)
+ {
+ if ((m->mnattr & siz) && (amsk0 & m->mn0) != 0 && (amsk1 & m->mn1) != 0)
+ {
+ (*m->mnfunc)(m->mninst, siz);
+ goto loop;
+ }
+
+ m = &machtab[m->mncont];
+ }
}
+
//
-// --- .if, Start Conditional Assembly -------------------------------------------------------------
+// .if, Start Conditional Assembly
//
-
-int d_if(void) {
- IFENT *rif;
- WORD eattr;
- VALUE eval;
- SYM *esym;
-
- // Alloc an IFENTRY
- if((rif = f_ifent) == NULL) rif = (IFENT *)amem((LONG)sizeof(IFENT));
- else f_ifent = rif->if_prev;
-
- rif->if_prev = ifent;
- ifent = rif;
-
- if(!disabled) {
- if(expr(exprbuf, &eval, &eattr, &esym) != OK) return(0);
- if((eattr & DEFINED) == 0) return(error(undef_error));
- disabled = !eval;
- }
- rif->if_state = (WORD)disabled;
- return(0);
+int d_if (void)
+{
+ IFENT * rif;
+ WORD eattr;
+ VALUE eval;
+ SYM * esym;
+
+ // Alloc an IFENTRY
+ if ((rif = f_ifent) == NULL)
+ rif = (IFENT *)amem((LONG)sizeof(IFENT));
+ else
+ f_ifent = rif->if_prev;
+
+ rif->if_prev = ifent;
+ ifent = rif;
+
+ if (!disabled)
+ {
+ if (expr(exprbuf, &eval, &eattr, &esym) != OK) return 0;
+
+ if ((eattr & DEFINED) == 0)
+ return error(undef_error);
+
+ disabled = !eval;
+ }
+
+ rif->if_state = (WORD)disabled;
+ return 0;
}
+
//
-// --- .else, Do Alternate Case For .if ------------------------------------------------------------
+// .else, Do Alternate Case For .if
//
+int d_else(void)
+{
+ IFENT * rif = ifent;
-int d_else(void) {
- IFENT *rif;
+ if (rif->if_prev == NULL)
+ return error("mismatched .else");
- rif = ifent;
+ if (disabled)
+ disabled = rif->if_prev->if_state;
+ else
+ disabled = 1;
- if(rif->if_prev == NULL) return(error("mismatched .else"));
-
- if(disabled) disabled = rif->if_prev->if_state;
- else disabled = 1;
-
- rif->if_state = (WORD)disabled;
- return(0);
+ rif->if_state = (WORD)disabled;
+ return 0;
}
+
//
-// -------------------------------------------------------------------------------------------------
// .endif, End of conditional assembly block
-// This is also called by fpop() to pop levels of IFENTs in case a macro or include file exits
-// early with `exitm' or `end'.
-// -------------------------------------------------------------------------------------------------
+// This is also called by fpop() to pop levels of IFENTs in case a macro or
+// include file exits early with `exitm' or `end'.
//
-
-int d_endif(void) {
- IFENT *rif;
-
- rif = ifent;
- if(rif->if_prev == NULL) return(error("mismatched .endif"));
-
- ifent = rif->if_prev;
- disabled = rif->if_prev->if_state;
- rif->if_prev = f_ifent;
- f_ifent = rif;
- return(0);
+int d_endif (void)
+{
+ IFENT * rif = ifent;
+
+ if (rif->if_prev == NULL)
+ return error("mismatched .endif");
+
+ ifent = rif->if_prev;
+ disabled = rif->if_prev->if_state;
+ rif->if_prev = f_ifent;
+ f_ifent = rif;
+ return 0;
}
-
#include "token.h"
// Globals, externals etc
-extern IFENT *ifent;
-extern char *comma_error;
-extern char *locgl_error;
-extern char *syntax_error;
+extern IFENT * ifent;
+extern char * comma_error;
+extern char * locgl_error;
+extern char * syntax_error;
extern int just_bss;
extern VALUE pcloc;
-extern IFENT *ifent;
-extern SYM *lab_sym;
+extern IFENT * ifent;
+extern SYM * lab_sym;
extern char extra_stuff[];
extern LONG amsktab[];
// Jaguar Jump Condition Names
char condname[MAXINTERNCC][5] = {
- "NZ", "Z", "NC", "NCNZ", "NCZ", "C", "CNZ", "CZ", "NN", "NNNZ", "NNZ", "N", "N_NZ", "N_Z ",
- "T", "A", "NE", "EQ", "CC", "HS", "HI", "CS", "LO", "PL", "MI", "F"
+ "NZ", "Z", "NC", "NCNZ", "NCZ", "C", "CNZ", "CZ", "NN", "NNNZ", "NNZ",
+ "N", "N_NZ", "N_Z ", "T", "A", "NE", "EQ", "CC", "HS", "HI", "CS", "LO",
+ "PL", "MI", "F"
};
// Jaguar Jump Condition Numbers
0, 0, 1, 2, 4, 4, 5, 8, 8, 20, 24, 31};
struct opcoderecord roptbl[] = {
- { MR_ADD, RI_TWO, 0 },
- { MR_ADDC, RI_TWO, 1 },
- { MR_ADDQ, RI_NUM_32, 2 },
- { MR_ADDQT, RI_NUM_32, 3 },
- { MR_SUB, RI_TWO, 4 },
- { MR_SUBC, RI_TWO, 5 },
- { MR_SUBQ, RI_NUM_32, 6 },
- { MR_SUBQT, RI_NUM_32, 7 },
- { MR_NEG, RI_ONE, 8 },
- { MR_AND, RI_TWO, 9 },
- { MR_OR, RI_TWO, 10 },
- { MR_XOR, RI_TWO, 11 },
- { MR_NOT, RI_ONE, 12 },
- { MR_BTST, RI_NUM_31, 13 },
- { MR_BSET, RI_NUM_31, 14 },
- { MR_BCLR, RI_NUM_31, 15 },
- { MR_MULT, RI_TWO, 16 },
- { MR_IMULT, RI_TWO, 17 },
- { MR_IMULTN, RI_TWO, 18 },
- { MR_RESMAC, RI_ONE, 19 },
- { MR_IMACN, RI_TWO, 20 },
- { MR_DIV, RI_TWO, 21 },
- { MR_ABS, RI_ONE, 22 },
- { MR_SH, RI_TWO, 23 },
- { MR_SHLQ, RI_NUM_32, 24 + SUB32 },
- { MR_SHRQ, RI_NUM_32, 25 },
- { MR_SHA, RI_TWO, 26 },
- { MR_SHARQ, RI_NUM_32, 27 },
- { MR_ROR, RI_TWO, 28 },
- { MR_RORQ, RI_NUM_32, 29 },
- { MR_ROLQ, RI_NUM_32, 29 + SUB32 },
- { MR_CMP, RI_TWO, 30 },
- { MR_CMPQ, RI_NUM_15, 31 },
- { MR_SAT8, RI_ONE, 32 + GPUONLY },
- { MR_SUBQMOD, RI_NUM_32, 32 + DSPONLY },
- { MR_SAT16, RI_ONE, 33 + GPUONLY },
- { MR_SAT16S, RI_ONE, 33 + DSPONLY },
- { MR_MOVEQ, RI_NUM_31, 35 },
- { MR_MOVETA, RI_TWO, 36 },
- { MR_MOVEFA, RI_TWO, 37 },
- { MR_MOVEI, RI_MOVEI, 38 },
- { MR_LOADB, RI_LOADN, 39 },
- { MR_LOADW, RI_LOADN, 40 },
- { MR_LOADP, RI_LOADN, 42 + GPUONLY },
- { MR_SAT32S, RI_ONE, 42 + DSPONLY },
- { MR_STOREB, RI_STOREN, 45 },
- { MR_STOREW, RI_STOREN, 46 },
- { MR_STOREP, RI_STOREN, 48 + GPUONLY },
- { MR_MIRROR, RI_ONE, 48 + DSPONLY },
- { MR_JUMP, RI_JUMP, 52 },
- { MR_JR, RI_JR, 53 },
- { MR_MMULT, RI_TWO, 54 },
- { MR_MTOI, RI_TWO, 55 },
- { MR_NORMI, RI_TWO, 56 },
- { MR_NOP, RI_NONE, 57 },
- { MR_SAT24, RI_ONE, 62 },
- { MR_UNPACK, RI_ONE, 63 + GPUONLY },
- { MR_PACK, RI_ONE, 63 + GPUONLY },
- { MR_ADDQMOD, RI_NUM_32, 63 + DSPONLY },
- { MR_MOVE, RI_MOVE, 0 },
- { MR_LOAD, RI_LOAD, 0 },
- { MR_STORE, RI_STORE, 0 }
+ { MR_ADD, RI_TWO, 0 },
+ { MR_ADDC, RI_TWO, 1 },
+ { MR_ADDQ, RI_NUM_32, 2 },
+ { MR_ADDQT, RI_NUM_32, 3 },
+ { MR_SUB, RI_TWO, 4 },
+ { MR_SUBC, RI_TWO, 5 },
+ { MR_SUBQ, RI_NUM_32, 6 },
+ { MR_SUBQT, RI_NUM_32, 7 },
+ { MR_NEG, RI_ONE, 8 },
+ { MR_AND, RI_TWO, 9 },
+ { MR_OR, RI_TWO, 10 },
+ { MR_XOR, RI_TWO, 11 },
+ { MR_NOT, RI_ONE, 12 },
+ { MR_BTST, RI_NUM_31, 13 },
+ { MR_BSET, RI_NUM_31, 14 },
+ { MR_BCLR, RI_NUM_31, 15 },
+ { MR_MULT, RI_TWO, 16 },
+ { MR_IMULT, RI_TWO, 17 },
+ { MR_IMULTN, RI_TWO, 18 },
+ { MR_RESMAC, RI_ONE, 19 },
+ { MR_IMACN, RI_TWO, 20 },
+ { MR_DIV, RI_TWO, 21 },
+ { MR_ABS, RI_ONE, 22 },
+ { MR_SH, RI_TWO, 23 },
+ { MR_SHLQ, RI_NUM_32, 24 + SUB32 },
+ { MR_SHRQ, RI_NUM_32, 25 },
+ { MR_SHA, RI_TWO, 26 },
+ { MR_SHARQ, RI_NUM_32, 27 },
+ { MR_ROR, RI_TWO, 28 },
+ { MR_RORQ, RI_NUM_32, 29 },
+ { MR_ROLQ, RI_NUM_32, 29 + SUB32 },
+ { MR_CMP, RI_TWO, 30 },
+ { MR_CMPQ, RI_NUM_15, 31 },
+ { MR_SAT8, RI_ONE, 32 + GPUONLY },
+ { MR_SUBQMOD, RI_NUM_32, 32 + DSPONLY },
+ { MR_SAT16, RI_ONE, 33 + GPUONLY },
+ { MR_SAT16S, RI_ONE, 33 + DSPONLY },
+ { MR_MOVEQ, RI_NUM_31, 35 },
+ { MR_MOVETA, RI_TWO, 36 },
+ { MR_MOVEFA, RI_TWO, 37 },
+ { MR_MOVEI, RI_MOVEI, 38 },
+ { MR_LOADB, RI_LOADN, 39 },
+ { MR_LOADW, RI_LOADN, 40 },
+ { MR_LOADP, RI_LOADN, 42 + GPUONLY },
+ { MR_SAT32S, RI_ONE, 42 + DSPONLY },
+ { MR_STOREB, RI_STOREN, 45 },
+ { MR_STOREW, RI_STOREN, 46 },
+ { MR_STOREP, RI_STOREN, 48 + GPUONLY },
+ { MR_MIRROR, RI_ONE, 48 + DSPONLY },
+ { MR_JUMP, RI_JUMP, 52 },
+ { MR_JR, RI_JR, 53 },
+ { MR_MMULT, RI_TWO, 54 },
+ { MR_MTOI, RI_TWO, 55 },
+ { MR_NORMI, RI_TWO, 56 },
+ { MR_NOP, RI_NONE, 57 },
+ { MR_SAT24, RI_ONE, 62 },
+ { MR_UNPACK, RI_ONE, 63 + GPUONLY },
+ { MR_PACK, RI_ONE, 63 + GPUONLY },
+ { MR_ADDQMOD, RI_NUM_32, 63 + DSPONLY },
+ { MR_MOVE, RI_MOVE, 0 },
+ { MR_LOAD, RI_LOAD, 0 },
+ { MR_STORE, RI_STORE, 0 }
};
+
//
-// --- Convert a String to Uppercase ---------------------------------------------------------------
+// Convert a String to Uppercase
//
-
-void strtoupper(char *s) {
- while(*s) {
- *s = (char)(toupper(*s));
- s++;
- }
+void strtoupper(char * s)
+{
+ while (*s)
+ {
+ *s = (char)(toupper(*s));
+ s++;
+ }
}
+
//
-// --- Build RISC Instruction Word -----------------------------------------------------------------
+// Build RISC Instruction Word
//
+void risc_instruction_word(unsigned short parm, int reg1, int reg2)
+{
+ int value = 0xE400;
+
+ previousop = currentop; // Opcode tracking for nop padding
+ currentop = parm;
+
+ if (!orgwarning)
+ { // Check for absolute address setting
+ if (!orgactive && !in_main)
+ {
+ warn("GPU/DSP code outside of absolute section");
+ orgwarning = 1;
+ }
+ }
+
+ if (jpad)
+ { // JPAD directive
+ // JUMP JR NOP
+ if (((previousop == 52) || (previousop == 53)) && (currentop != 57))
+ D_word(value); // Insert NOP
+ }
+ else
+ {
+ // JUMP JR
+ if ((previousop == 52) || (previousop == 53))
+ {
+ switch (currentop)
+ {
+ case 38:
+ warn("NOP inserted before MOVEI instruction.");
+ D_word(value);
+ break;
+ case 53:
+ warn("NOP inserted before JR instruction.");
+ D_word(value);
+ break;
+ case 52:
+ warn("NOP inserted before JUMP instruction.");
+ D_word(value);
+ break;
+ case 51:
+ warn("NOP inserted before MOVE PC instruction.");
+ D_word(value);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (currentop == 20)
+ { // IMACN checks
+ if ((previousop != 18) && (previousop != 20))
+ {
+ error("IMULTN/IMACN instruction must preceed IMACN instruction");
+ }
+ }
-void risc_instruction_word(unsigned short parm, int reg1, int reg2) {
- int value = 0xE400;
-
- previousop = currentop; // Opcode tracking for nop padding
- currentop = parm;
-
- if(!orgwarning) { // Check for absolute address setting
- if(!orgactive && !in_main) {
- warn("GPU/DSP code outside of absolute section");
- orgwarning = 1;
- }
- }
-
- if(jpad) { // JPAD directive
- // JUMP JR NOP
- if(((previousop == 52) || (previousop == 53)) && (currentop != 57))
- D_word(value); // Insert NOP
- } else {
- // JUMP JR
- if((previousop == 52) || (previousop == 53)) {
- switch(currentop) {
- case 38: warn("NOP inserted before MOVEI instruction."); D_word(value); break;
- case 53: warn("NOP inserted before JR instruction."); D_word(value); break;
- case 52: warn("NOP inserted before JUMP instruction."); D_word(value); break;
- case 51: warn("NOP inserted before MOVE PC instruction."); D_word(value); break;
- default:
- break;
- }
- }
- }
-
- if(currentop == 20) { // IMACN checks
- if((previousop != 18) && (previousop != 20)) {
- error("IMULTN/IMACN instruction must preceed IMACN instruction");
- }
- }
-
- if(currentop == 19) { // RESMAC checks
- if(previousop != 20) {
- error("IMACN instruction must preceed RESMAC instruction");
- }
- }
-
- value =((parm & 0x3F) << 10) + ((reg1 & 0x1F) << 5) + (reg2 & 0x1F);
- D_word(value);
+ if (currentop == 19)
+ { // RESMAC checks
+ if (previousop != 20)
+ {
+ error("IMACN instruction must preceed RESMAC instruction");
+ }
+ }
+
+ value =((parm & 0x3F) << 10) + ((reg1 & 0x1F) << 5) + (reg2 & 0x1F);
+ D_word(value);
}
+
//
-// --- Get a RISC Register -------------------------------------------------------------------------
+// Get a RISC Register
//
+int getregister(WORD rattr)
+{
+ VALUE eval; // Expression value
+ WORD eattr; // Expression attributes
+ SYM * esym; // External symbol involved in expr.
+ TOKEN r_expr[EXPRSIZE]; // Expression token list
+ WORD defined; // Symbol defined flag
+
+ if (expr(r_expr, &eval, &eattr, &esym) != OK)
+ {
+ error("malformed opcode");
+ return ERROR;
+ }
+ else
+ {
+ defined = (WORD)(eattr & DEFINED);
-int getregister(WORD rattr) {
- VALUE eval; // Expression value
- WORD eattr; // Expression attributes
- SYM *esym; // External symbol involved in expr.
- TOKEN r_expr[EXPRSIZE]; // Expression token list
- WORD defined; // Symbol defined flag
-
- if(expr(r_expr, &eval, &eattr, &esym) != OK) {
- error("malformed opcode");
- return(ERROR);
- } else {
- defined = (WORD)(eattr & DEFINED);
- if((challoc - ch_size) < 4)
- chcheck(4L);
- if(!defined) {
- fixup((WORD)(FU_WORD|rattr), sloc, r_expr);
- return(0);
- } else {
- if((eval >= 0) && (eval <= 31)) { // Check for specified register, r0->r31
- return(eval);
- } else {
- error(reg_err);
- return(ERROR);
- }
- }
- }
-
- return(ERROR);
+ if ((challoc - ch_size) < 4)
+ chcheck(4L);
+
+ if (!defined)
+ {
+ fixup((WORD)(FU_WORD|rattr), sloc, r_expr);
+ return 0;
+ }
+ else
+ {
+ // Check for specified register, r0->r31
+ if ((eval >= 0) && (eval <= 31))
+ {
+ return eval;
+ }
+ else
+ {
+ error(reg_err);
+ return ERROR;
+ }
+ }
+ }
+
+ return ERROR;
}
+
//
-// --- Do RISC Code Generation ---------------------------------------------------------------------
+// Do RISC Code Generation
//
+int risccg(int state)
+{
+ unsigned short parm; // Opcode parameters
+ unsigned type; // Opcode type
+ int reg1; // Register 1
+ int reg2; // Register 2
+ int val = 0; // Constructed value
+ char scratch[80];
+ SYM * ccsym;
+ SYM * sy;
+ int i; // Iterator
+ int t, c;
+ WORD tdb;
+ unsigned locptr = 0; // Address location pointer
+ unsigned page_jump = 0; // Memory page jump flag
+ VALUE eval; // Expression value
+ WORD eattr; // Expression attributes
+ SYM * esym; // External symbol involved in expr.
+ TOKEN r_expr[EXPRSIZE]; // Expression token list
+ WORD defined; // Symbol defined flag
+ WORD attrflg;
+ int indexed; // Indexed register flag
-int risccg(int state) {
- unsigned short parm; // Opcode parameters
- unsigned type; // Opcode type
- int reg1; // Register 1
- int reg2; // Register 2
- int val = 0; // Constructed value
- char scratch[80];
- SYM *ccsym;
- SYM *sy;
- int i; // Iterator
- int t, c;
- WORD tdb;
- unsigned locptr = 0; // Address location pointer
- unsigned page_jump = 0; // Memory page jump flag
- VALUE eval; // Expression value
- WORD eattr; // Expression attributes
- SYM *esym; // External symbol involved in expr.
- TOKEN r_expr[EXPRSIZE]; // Expression token list
- WORD defined; // Symbol defined flag
- WORD attrflg;
- int indexed; // Indexed register flag
-
- parm = (WORD)(roptbl[state-3000].parm); // Get opcode parameter and type
- type = roptbl[state-3000].typ;
-
- // Detect whether the opcode parmeter passed determines that the opcode is specific to only one
- // of the RISC processors and ensure it is legal in the current code section.
- // If not then error and return.
- if(((parm & GPUONLY) && rdsp) || ((parm & DSPONLY) && rgpu) ) {
- error("opcode is not valid in this code section");
- return(ERROR);
- }
-
- // Process RISC opcode
- switch(type) {
- // No operand instructions
- // NOP
- case RI_NONE:
- risc_instruction_word(parm, 0, 0);
- break;
- // Single operand instructions (Rd)
- // ABS, MIRROR, NEG, NOT, PACK, RESMAC, SAT8, SAT16, SAT16S, SAT24, SAT32S, UNPACK
- case RI_ONE:
- reg2 = getregister(FU_REGTWO);
- at_eol();
- risc_instruction_word(parm, parm >> 6, reg2);
- break;
- // Two operand instructions (Rs,Rd)
- // ADD, ADDC, AND, CMP, DIV, IMACN, IMULT, IMULTN, MOVEFA, MOVETA, MULT, MMULT,
- // MTOI, NORMI, OR, ROR, SH, SHA, SUB, SUBC, XOR
- case RI_TWO:
- if(parm == 37) altbankok = 1; // MOVEFA
- reg1 = getregister(FU_REGONE);
- CHECK_COMMA;
- if(parm == 36) altbankok = 1; // MOVETA
- reg2 = getregister(FU_REGTWO);
- at_eol();
- risc_instruction_word(parm, reg1, reg2);
- break;
- // Numeric operand (n,Rd) where n = -16..+15
- // CMPQ
- case RI_NUM_15:
- // Numeric operand (n,Rd) where n = 0..31
- // BCLR, BSET, BTST, MOVEQ
- case RI_NUM_31:
- // Numeric operand (n,Rd) where n = 1..32
- // ADDQ, ADDQMOD, ADDQT, SHARQ, SHLQ, SHRQ, SUBQ, SUBQMOD, SUBQT, ROLQ, RORQ
- case RI_NUM_32:
- switch(type) {
- case RI_NUM_15: reg1 = -16; reg2 = 15; attrflg = FU_NUM15; break;
- default:
- case RI_NUM_31: reg1 = 0; reg2 = 31; attrflg = FU_NUM31; break;
- case RI_NUM_32: reg1 = 1; reg2 = 32; attrflg = FU_NUM32; break;
- }
- if(parm & SUB32) attrflg |= FU_SUB32;
- if(*tok == '#') {
- ++tok;
- if(expr(r_expr, &eval, &eattr, &esym) != OK)
- goto malformed;
- else {
- defined = (WORD)(eattr & DEFINED);
- if((challoc - ch_size) < 4)
- chcheck(4L);
- if(!defined) {
- fixup((WORD)(FU_WORD|attrflg), sloc, r_expr);
- reg1 = 0;
- } else {
- if((int)eval < reg1 || (int)eval > reg2) {
- error("constant out of range");
- return(ERROR);
- }
- if(parm & SUB32)
- reg1 = 32 - eval;
- else if(type == RI_NUM_32)
- reg1 = (reg1 == 32) ? 0 : eval;
- else
- reg1 = eval;
- }
- }
- } else goto malformed;
- CHECK_COMMA;
- reg2 = getregister(FU_REGTWO);
- at_eol();
- risc_instruction_word(parm, reg1, reg2);
- break;
- // Move Immediate - n,Rn - n in Second Word
- case RI_MOVEI:
- if(*tok == '#') {
- ++tok;
- if(expr(r_expr, &eval, &eattr, &esym) != OK) {
- malformed:
- error("malformed opcode");
- return(ERROR);
- } else {
- // Opcode tracking for nop padding
- previousop = currentop;
- currentop = parm;
- // JUMP or JR
- if((previousop == 52) || (previousop == 53) && !jpad) {
- warn("NOP inserted before MOVEI instruction.");
- D_word(0xE400);
- }
- tdb = (WORD)(eattr & TDB);
- defined = (WORD)(eattr & DEFINED);
- if((challoc - ch_size) < 4)
- chcheck(4L);
- if(!defined) {
- fixup(FU_LONG|FU_MOVEI, sloc + 2, r_expr);
- eval = 0;
- } else {
- if(tdb) {
- rmark(cursect, sloc + 2, tdb, MLONG|MMOVEI, NULL);
- }
- }
- val = eval;
- // Store the defined flags and value of the movei when used in mjump
- if(mjump_align) {
- mjump_defined = defined;
- mjump_dest = val;
- }
- }
- } else goto malformed;
- ++tok;
- reg2 = getregister(FU_REGTWO);
- at_eol();
- D_word((((parm & 0x3F) << 10) + reg2));
- val = ((val >> 16) & 0x0000FFFF) | ((val << 16) & 0xFFFF0000);
- D_long(val);
- break;
- case RI_MOVE: // PC,Rd or Rs,Rd
- if(*tok == KW_PC) {
- parm = 51;
- reg1 = 0;
- ++tok;
- } else {
- parm = 34;
- reg1 = getregister(FU_REGONE);
- }
- CHECK_COMMA;
- reg2 = getregister(FU_REGTWO);
- at_eol();
- risc_instruction_word(parm, reg1, reg2);
- break;
- // (Rn),Rn = 41 / (R14/R15+n),Rn = 43/44 / (R14/R15+Rn),Rn = 58/59
- case RI_LOAD:
- indexed = 0;
- parm = 41;
- if(*tok != '(') goto malformed;
- ++tok;
- if((*tok == KW_R14 || *tok == KW_R15) && (*(tok+1) != ')'))
- indexed = (*tok - KW_R0);
- if(*tok == SYMBOL) {
- sy = lookup((char *)tok[1], LABEL, 0);
- if(!sy) {
- error(reg_err);
- return(ERROR);
- }
- if(sy->sattre & EQUATEDREG)
- if(((sy->svalue & 0x1F) == 14 || (sy->svalue & 0x1F) == 15) && (*(tok+2) != ')')) {
- indexed = (sy->svalue & 0x1F);
- ++tok;
- }
- }
- if(!indexed) {
- reg1 = getregister(FU_REGONE);
- } else {
- reg1 = indexed;
- indexed = 0;
- ++tok;
- if(*tok == '+') {
- parm = (WORD)(reg1 - 14 + 58);
- tok++;
- if(*tok >= KW_R0 && *tok <= KW_R31) {
- indexed = 1;
- }
- if(*tok == SYMBOL) {
- sy = lookup((char *)tok[1], LABEL, 0);
- if(!sy) {
- error(reg_err);
- return(ERROR);
- }
- if(sy->sattre & EQUATEDREG) {
- indexed = 1;
- }
- }
- if(indexed) {
- reg1 = getregister(FU_REGONE);
- } else {
- if(expr(r_expr, &eval, &eattr, &esym) != OK) {
- goto malformed;
- } else {
- tdb = (WORD)(eattr & TDB);
- defined = (WORD)(eattr & DEFINED);
- if((challoc - ch_size) < 4)
- chcheck(4L);
- if(!defined) {
- error("constant expected");
- return(ERROR);
- //fixup(FU_WORD|FU_REGONE, sloc, r_expr);
- reg1 = 0;
- } else {
- reg1 = eval;
- if(reg1 == 0) {
- reg1 = 14+(parm-58);
- parm = 41;
- warn("NULL offset removed");
- } else {
- if(reg1 < 1 || reg1 > 32) {
- error("constant out of range");
- return(ERROR);
- }
- if(reg1 == 32) reg1 = 0;
- parm = (WORD)(parm - 58 + 43);
- }
- }
- }
- }
- } else {
- reg1 = getregister(FU_REGONE);
- }
- }
- if(*tok != ')') goto malformed;
- ++tok;
- CHECK_COMMA;
- reg2 = getregister(FU_REGTWO);
- at_eol();
- risc_instruction_word(parm, reg1, reg2);
- break;
- // Rn,(Rn) = 47 / Rn,(R14/R15+n) = 49/50 / Rn,(R14/R15+Rn) = 60/61
- case RI_STORE:
- parm = 47;
- reg1 = getregister(FU_REGONE);
- CHECK_COMMA;
- if(*tok != '(') goto malformed;
- ++tok;
- indexed = 0;
- if((*tok == KW_R14 || *tok == KW_R15) && (*(tok+1) != ')'))
- indexed = (*tok - KW_R0);
- if(*tok == SYMBOL) {
- sy = lookup((char *)tok[1], LABEL, 0);
- if(!sy) {
- error(reg_err);
- return(ERROR);
- }
- if(sy->sattre & EQUATEDREG)
- if(((sy->svalue & 0x1F) == 14 || (sy->svalue & 0x1F) == 15) && (*(tok+2) != ')')) {
- indexed = (sy->svalue & 0x1F);
- ++tok;
- }
- }
- if(!indexed) {
- reg2 = getregister(FU_REGTWO);
- } else {
- reg2 = indexed;
- indexed = 0;
- ++tok;
- if(*tok == '+') {
- parm = (WORD)(reg2 - 14 + 60);
- tok++;
- if(*tok >= KW_R0 && *tok <= KW_R31) {
- indexed = 1;
- }
- if(*tok == SYMBOL) {
- sy = lookup((char *)tok[1], LABEL, 0);
- if(!sy) {
- error(reg_err);
- return(ERROR);
- }
- if(sy->sattre & EQUATEDREG) {
- indexed = 1;
- }
- }
- if(indexed) {
- reg2 = getregister(FU_REGTWO);
- } else {
- if(expr(r_expr, &eval, &eattr, &esym) != OK) {
- goto malformed;
- } else {
- tdb = (WORD)(eattr & TDB);
- defined = (WORD)(eattr & DEFINED);
- if((challoc - ch_size) < 4)
- chcheck(4L);
- if(!defined) {
- fixup(FU_WORD|FU_REGTWO, sloc, r_expr);
- reg2 = 0;
- } else {
- reg2 = eval;
- if(reg2 == 0 ) {
- reg2 = 14+(parm-60);
- parm = 47;
- warn("NULL offset removed");
- } else {
- if(reg2 < 1 || reg2 > 32) {
- error("constant out of range");
- return(ERROR);
- }
- if(reg2 == 32) reg2 = 0;
- parm = (WORD)(parm - 60 + 49);
- }
- }
- }
- }
- } else {
- reg2 = getregister(FU_REGTWO);
- }
- }
- if(*tok != ')') goto malformed;
- ++tok;
- at_eol();
- risc_instruction_word(parm, reg2, reg1);
- break;
- // LOADB/LOADP/LOADW (Rn),Rn
- case RI_LOADN:
- if(*tok != '(') goto malformed;
- ++tok;
- reg1 = getregister(FU_REGONE);
- if(*tok != ')') goto malformed;
- ++tok;
- CHECK_COMMA;
- reg2 = getregister(FU_REGTWO);
- at_eol();
- risc_instruction_word(parm, reg1, reg2);
- break;
- // STOREB/STOREP/STOREW Rn,(Rn)
- case RI_STOREN:
- reg1 = getregister(FU_REGONE);
- CHECK_COMMA;
- if(*tok != '(') goto malformed;
- ++tok;
- reg2 = getregister(FU_REGTWO);
- if(*tok != ')') goto malformed;
- ++tok;
- at_eol();
- risc_instruction_word(parm, reg2, reg1);
- break;
- case RI_JR: // Jump Relative - cc,n - n=-16..+15 words, reg2=cc
- case RI_JUMP: // Jump Absolute - cc,(Rs) - reg2=cc
- // Check to see if there is a comma in the token string. If not then the JR or JUMP should
- // default to 0, Jump Always
- t = i = c = 0;
- while(t != EOL) {
- t = *(tok + i);
- if(t == ',') c = 1;
- i++;
- }
- if(c) { // Comma present in token string
- if(*tok == CONST) { // CC using a constant number
- ++tok;
- val = *tok;
- ++tok;
- CHECK_COMMA;
- } else if(*tok == SYMBOL) {
- val = 99;
- for(i = 0; i < MAXINTERNCC; i++) {
- strcpy(scratch, (char *)tok[1]);
- strtoupper(scratch);
- if(!strcmp(condname[i], scratch))
- val = condnumber[i];
- }
- if(val == 99) {
- ccsym = lookup((char *)tok[1], LABEL, 0);
- if(ccsym && (ccsym->sattre & EQUATEDCC) && !(ccsym->sattre & UNDEF_CC)) {
- val = ccsym->svalue;
- } else {
- error("unknown condition code");
- return(ERROR);
- }
- }
- tok += 2;
- CHECK_COMMA;
- } else if(*tok == '(') {
- val = 0; // Jump always
- }
- } else {
- val = 0; // Jump always
- }
-
- if(val < 0 || val > 31) {
- error("condition constant out of range");
- return(ERROR);
- } else {
- reg1 = val; // Store condition code
- }
- if(type == RI_JR) { // JR cc,n
- if(expr(r_expr, &eval, &eattr, &esym) != OK)
- goto malformed;
- else {
- tdb = (WORD)(eattr & TDB);
- defined = (WORD)(eattr & DEFINED);
- if((challoc - ch_size) < 4)
- chcheck(4L);
- if(!defined) {
- if(in_main) {
- fixup(FU_WORD|FU_MJR, sloc, r_expr);
- } else {
- fixup(FU_WORD|FU_JR, sloc, r_expr);
- }
- reg2 = 0;
- } else {
- val = eval;
- if(orgactive) {
- reg2 = ((int)(val - (orgaddr + 2))) / 2;
- if((reg2 < -16) || (reg2 > 15))
- error("PC relative overflow");
- locptr = orgaddr;
- } else {
- reg2 = ((int)(val - (sloc + 2))) / 2;
- if((reg2 < -16) || (reg2 > 15))
- error("PC relative overflow");
- locptr = sloc;
- }
- }
- if(in_main) {
- if(defined) {
- if(((locptr >= 0xF03000) && (locptr < 0xF04000) && (val < 0xF03000)) ||
- ((val >= 0xF03000) && (val < 0xF04000) && (locptr < 0xF03000)) ) {
- warn("* cannot jump relative between main memory and local gpu ram");
- } else {
- page_jump = (locptr & 0xFFFFFF00) - (val & 0xFFFFFF00);
- if(page_jump) {
- if(val % 4) {
- warn("* destination address not aligned for long page jump relative, "
- "insert a \'nop\' before the destination label/address");
- }
- } else {
- if((val - 2) % 4) {
- warn("* destination address not aligned for short page jump relative, "
- "insert a \'nop\' before the destination label/address");
- }
- }
- }
- }
- }
- }
- risc_instruction_word(parm, reg2, reg1);
- } else { // JUMP cc, (Rn)
- if(*tok != '(') goto malformed;
- ++tok;
- reg2 = getregister(FU_REGTWO);
- if(*tok != ')') goto malformed;
- ++tok;
- at_eol();
- if(in_main) {
- if(!mjump_align) {
- warn("* \'jump\' is not recommended for .gpumain as destination addresses "
- "cannot be validated for alignment, use \'mjump\'");
- locptr = (orgactive) ? orgaddr : sloc;
- if(locptr % 4) {
- warn("* source address not aligned for long or short jump, "
- "insert a \'nop\' before the \'jump\'");
- }
- } else {
- if(mjump_defined) {
- locptr = (orgactive) ? orgaddr : sloc;
- page_jump = (locptr & 0xFFFFFF00) - (mjump_dest & 0xFFFFFF00);
- if(page_jump) {
- if(mjump_dest % 4) {
- warn("* destination address not aligned for long page jump, "
- "insert a \'nop\' before the destination label/address");
- }
- } else {
- if(!(mjump_dest & 0x0000000F) || ((mjump_dest - 2) % 4)) {
- warn("* destination address not aligned for short page jump, "
- "insert a \'nop\' before the destination label/address");
- }
- }
- } else {
- locptr = (orgactive) ? orgaddr : sloc;
- fwdjump[fwindex++] = locptr;
- }
- }
-
- }
- risc_instruction_word(parm, reg2, reg1);
- }
- break;
- // Should never get here :D
- default:
- error("unknown risc opcode type");
- return(ERROR);
- break;
-
- }
-
- return(0);
-}
+ parm = (WORD)(roptbl[state-3000].parm); // Get opcode parameter and type
+ type = roptbl[state-3000].typ;
+
+ // Detect whether the opcode parmeter passed determines that the opcode is specific to only one
+ // of the RISC processors and ensure it is legal in the current code section.
+ // If not then error and return.
+ if (((parm & GPUONLY) && rdsp) || ((parm & DSPONLY) && rgpu))
+ {
+ error("opcode is not valid in this code section");
+ return ERROR;
+ }
+
+ // Process RISC opcode
+ switch (type)
+ {
+ // No operand instructions
+ // NOP
+ case RI_NONE:
+ risc_instruction_word(parm, 0, 0);
+ break;
+ // Single operand instructions (Rd)
+ // ABS, MIRROR, NEG, NOT, PACK, RESMAC, SAT8, SAT16, SAT16S, SAT24, SAT32S, UNPACK
+ case RI_ONE:
+ reg2 = getregister(FU_REGTWO);
+ at_eol();
+ risc_instruction_word(parm, parm >> 6, reg2);
+ break;
+ // Two operand instructions (Rs,Rd)
+ // ADD, ADDC, AND, CMP, DIV, IMACN, IMULT, IMULTN, MOVEFA, MOVETA, MULT, MMULT,
+ // MTOI, NORMI, OR, ROR, SH, SHA, SUB, SUBC, XOR
+ case RI_TWO:
+ if (parm == 37)
+ altbankok = 1; // MOVEFA
+
+ reg1 = getregister(FU_REGONE);
+ CHECK_COMMA;
+
+ if (parm == 36)
+ altbankok = 1; // MOVETA
+
+ reg2 = getregister(FU_REGTWO);
+ at_eol();
+ risc_instruction_word(parm, reg1, reg2);
+ break;
+ // Numeric operand (n,Rd) where n = -16..+15
+ // CMPQ
+ case RI_NUM_15:
+ // Numeric operand (n,Rd) where n = 0..31
+ // BCLR, BSET, BTST, MOVEQ
+ case RI_NUM_31:
+ // Numeric operand (n,Rd) where n = 1..32
+ // ADDQ, ADDQMOD, ADDQT, SHARQ, SHLQ, SHRQ, SUBQ, SUBQMOD, SUBQT, ROLQ, RORQ
+ case RI_NUM_32:
+ switch (type)
+ {
+ case RI_NUM_15:
+ reg1 = -16; reg2 = 15; attrflg = FU_NUM15;
+ break;
+ default:
+ case RI_NUM_31:
+ reg1 = 0; reg2 = 31; attrflg = FU_NUM31;
+ break;
+ case RI_NUM_32:
+ reg1 = 1; reg2 = 32; attrflg = FU_NUM32;
+ break;
+ }
+
+ if (parm & SUB32) attrflg |= FU_SUB32;
+ {
+ if (*tok == '#')
+ {
+ ++tok;
+
+ if (expr(r_expr, &eval, &eattr, &esym) != OK)
+ goto malformed;
+ else
+ {
+ defined = (WORD)(eattr & DEFINED);
+
+ if ((challoc - ch_size) < 4)
+ chcheck(4L);
+
+ if (!defined)
+ {
+ fixup((WORD)(FU_WORD|attrflg), sloc, r_expr);
+ reg1 = 0;
+ }
+ else
+ {
+ if ((int)eval < reg1 || (int)eval > reg2)
+ {
+ error("constant out of range");
+ return ERROR;
+ }
+
+ if (parm & SUB32)
+ reg1 = 32 - eval;
+ else if (type == RI_NUM_32)
+ reg1 = (reg1 == 32) ? 0 : eval;
+ else
+ reg1 = eval;
+ }
+ }
+ }
+ else
+ goto malformed;
+ }
+
+ CHECK_COMMA;
+ reg2 = getregister(FU_REGTWO);
+ at_eol();
+ risc_instruction_word(parm, reg1, reg2);
+ break;
+ // Move Immediate - n,Rn - n in Second Word
+ case RI_MOVEI:
+ if (*tok == '#')
+ {
+ ++tok;
+ if (expr(r_expr, &eval, &eattr, &esym) != OK)
+ {
+ malformed:
+ error("malformed opcode");
+ return ERROR;
+ }
+ else
+ {
+ // Opcode tracking for nop padding
+ previousop = currentop;
+ currentop = parm;
+
+ // JUMP or JR
+ if ((previousop == 52) || (previousop == 53) && !jpad)
+ {
+ warn("NOP inserted before MOVEI instruction.");
+ D_word(0xE400);
+ }
+
+ tdb = (WORD)(eattr & TDB);
+ defined = (WORD)(eattr & DEFINED);
+
+ if ((challoc - ch_size) < 4)
+ chcheck(4L);
+
+ if (!defined)
+ {
+ fixup(FU_LONG|FU_MOVEI, sloc + 2, r_expr);
+ eval = 0;
+ }
+ else
+ {
+ if (tdb)
+ {
+ rmark(cursect, sloc + 2, tdb, MLONG|MMOVEI, NULL);
+ }
+ }
+
+ val = eval;
+
+ // Store the defined flags and value of the movei when used in mjump
+ if (mjump_align)
+ {
+ mjump_defined = defined;
+ mjump_dest = val;
+ }
+ }
+ }
+ else
+ goto malformed;
+
+ ++tok;
+ reg2 = getregister(FU_REGTWO);
+ at_eol();
+ D_word((((parm & 0x3F) << 10) + reg2));
+ val = ((val >> 16) & 0x0000FFFF) | ((val << 16) & 0xFFFF0000);
+ D_long(val);
+ break;
+ case RI_MOVE: // PC,Rd or Rs,Rd
+ if (*tok == KW_PC)
+ {
+ parm = 51;
+ reg1 = 0;
+ ++tok;
+ }
+ else
+ {
+ parm = 34;
+ reg1 = getregister(FU_REGONE);
+ }
+
+ CHECK_COMMA;
+ reg2 = getregister(FU_REGTWO);
+ at_eol();
+ risc_instruction_word(parm, reg1, reg2);
+ break;
+ // (Rn),Rn = 41 / (R14/R15+n),Rn = 43/44 / (R14/R15+Rn),Rn = 58/59
+ case RI_LOAD:
+ indexed = 0;
+ parm = 41;
+
+ if (*tok != '(')
+ goto malformed;
+
+ ++tok;
+ if ((*tok == KW_R14 || *tok == KW_R15) && (*(tok+1) != ')'))
+ indexed = (*tok - KW_R0);
+
+ if (*tok == SYMBOL)
+ {
+ sy = lookup((char *)tok[1], LABEL, 0);
+ if (!sy)
+ {
+ error(reg_err);
+ return ERROR;
+ }
+
+ if (sy->sattre & EQUATEDREG)
+ {
+ if (((sy->svalue & 0x1F) == 14 || (sy->svalue & 0x1F) == 15)
+ && (*(tok+2) != ')'))
+ {
+ indexed = (sy->svalue & 0x1F);
+ ++tok;
+ }
+ }
+ }
+
+ if (!indexed)
+ {
+ reg1 = getregister(FU_REGONE);
+ }
+ else
+ {
+ reg1 = indexed;
+ indexed = 0;
+ ++tok;
+
+ if (*tok == '+')
+ {
+ parm = (WORD)(reg1 - 14 + 58);
+ tok++;
+
+ if (*tok >= KW_R0 && *tok <= KW_R31)
+ {
+ indexed = 1;
+ }
+
+ if (*tok == SYMBOL)
+ {
+ sy = lookup((char *)tok[1], LABEL, 0);
+
+ if (!sy)
+ {
+ error(reg_err);
+ return ERROR;
+ }
+
+ if (sy->sattre & EQUATEDREG)
+ {
+ indexed = 1;
+ }
+ }
+
+ if (indexed)
+ {
+ reg1 = getregister(FU_REGONE);
+ }
+ else
+ {
+ if (expr(r_expr, &eval, &eattr, &esym) != OK)
+ {
+ goto malformed;
+ }
+ else
+ {
+ tdb = (WORD)(eattr & TDB);
+ defined = (WORD)(eattr & DEFINED);
+
+ if ((challoc - ch_size) < 4)
+ chcheck(4L);
+
+ if (!defined)
+ {
+ error("constant expected");
+ return ERROR;
+ //fixup(FU_WORD|FU_REGONE, sloc, r_expr);
+ reg1 = 0;
+ }
+ else
+ {
+ reg1 = eval;
+
+ if (reg1 == 0)
+ {
+ reg1 = 14 + (parm - 58);
+ parm = 41;
+ warn("NULL offset removed");
+ }
+ else
+ {
+ if (reg1 < 1 || reg1 > 32)
+ {
+ error("constant out of range");
+ return ERROR;
+ }
+
+ if (reg1 == 32)
+ reg1 = 0;
+
+ parm = (WORD)(parm - 58 + 43);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ reg1 = getregister(FU_REGONE);
+ }
+ }
+
+ if (*tok != ')')
+ goto malformed;
+
+ ++tok;
+ CHECK_COMMA;
+ reg2 = getregister(FU_REGTWO);
+ at_eol();
+ risc_instruction_word(parm, reg1, reg2);
+ break;
+ // Rn,(Rn) = 47 / Rn,(R14/R15+n) = 49/50 / Rn,(R14/R15+Rn) = 60/61
+ case RI_STORE:
+ parm = 47;
+ reg1 = getregister(FU_REGONE);
+ CHECK_COMMA;
+ if (*tok != '(') goto malformed;
+
+ ++tok;
+ indexed = 0;
+
+ if ((*tok == KW_R14 || *tok == KW_R15) && (*(tok+1) != ')'))
+ indexed = (*tok - KW_R0);
+
+ if (*tok == SYMBOL)
+ {
+ sy = lookup((char *)tok[1], LABEL, 0);
+
+ if (!sy)
+ {
+ error(reg_err);
+ return ERROR;
+ }
+
+ if (sy->sattre & EQUATEDREG)
+ {
+ if (((sy->svalue & 0x1F) == 14 || (sy->svalue & 0x1F) == 15)
+ && (*(tok+2) != ')'))
+ {
+ indexed = (sy->svalue & 0x1F);
+ ++tok;
+ }
+ }
+ }
+
+ if (!indexed)
+ {
+ reg2 = getregister(FU_REGTWO);
+ }
+ else
+ {
+ reg2 = indexed;
+ indexed = 0;
+ ++tok;
+
+ if (*tok == '+')
+ {
+ parm = (WORD)(reg2 - 14 + 60);
+ tok++;
+
+ if (*tok >= KW_R0 && *tok <= KW_R31)
+ {
+ indexed = 1;
+ }
+
+ if (*tok == SYMBOL)
+ {
+ sy = lookup((char *)tok[1], LABEL, 0);
+
+ if (!sy)
+ {
+ error(reg_err);
+ return ERROR;
+ }
+
+ if (sy->sattre & EQUATEDREG)
+ {
+ indexed = 1;
+ }
+ }
+
+ if (indexed)
+ {
+ reg2 = getregister(FU_REGTWO);
+ }
+ else
+ {
+ if (expr(r_expr, &eval, &eattr, &esym) != OK)
+ {
+ goto malformed;
+ }
+ else
+ {
+ tdb = (WORD)(eattr & TDB);
+ defined = (WORD)(eattr & DEFINED);
+
+ if ((challoc - ch_size) < 4)
+ chcheck(4L);
+
+ if (!defined)
+ {
+ fixup(FU_WORD|FU_REGTWO, sloc, r_expr);
+ reg2 = 0;
+ }
+ else
+ {
+ reg2 = eval;
+
+ if (reg2 == 0 )
+ {
+ reg2 = 14 + (parm - 60);
+ parm = 47;
+ warn("NULL offset removed");
+ }
+ else
+ {
+ if (reg2 < 1 || reg2 > 32)
+ {
+ error("constant out of range");
+ return ERROR;
+ }
+
+ if (reg2 == 32)
+ reg2 = 0;
+
+ parm = (WORD)(parm - 60 + 49);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ reg2 = getregister(FU_REGTWO);
+ }
+ }
+
+ if (*tok != ')')
+ goto malformed;
+
+ ++tok;
+ at_eol();
+ risc_instruction_word(parm, reg2, reg1);
+ break;
+ // LOADB/LOADP/LOADW (Rn),Rn
+ case RI_LOADN:
+ if (*tok != '(')
+ goto malformed;
+
+ ++tok;
+ reg1 = getregister(FU_REGONE);
+
+ if (*tok != ')')
+ goto malformed;
+
+ ++tok;
+ CHECK_COMMA;
+ reg2 = getregister(FU_REGTWO);
+ at_eol();
+ risc_instruction_word(parm, reg1, reg2);
+ break;
+ // STOREB/STOREP/STOREW Rn,(Rn)
+ case RI_STOREN:
+ reg1 = getregister(FU_REGONE);
+ CHECK_COMMA;
+
+ if (*tok != '(')
+ goto malformed;
+
+ ++tok;
+ reg2 = getregister(FU_REGTWO);
+
+ if (*tok != ')')
+ goto malformed;
+
+ ++tok;
+ at_eol();
+ risc_instruction_word(parm, reg2, reg1);
+ break;
+ case RI_JR: // Jump Relative - cc,n - n=-16..+15 words, reg2=cc
+ case RI_JUMP: // Jump Absolute - cc,(Rs) - reg2=cc
+ // Check to see if there is a comma in the token string. If not then the JR or JUMP should
+ // default to 0, Jump Always
+ t = i = c = 0;
+ while (t != EOL)
+ {
+ t = *(tok + i);
+ if (t == ',') c = 1;
+ i++;
+ }
+
+ if (c)
+ { // Comma present in token string
+ if (*tok == CONST)
+ { // CC using a constant number
+ ++tok;
+ val = *tok;
+ ++tok;
+ CHECK_COMMA;
+ }
+ else if (*tok == SYMBOL)
+ {
+ val = 99;
+
+ for(i=0; i<MAXINTERNCC; i++)
+ {
+ strcpy(scratch, (char *)tok[1]);
+ strtoupper(scratch);
+
+ if (!strcmp(condname[i], scratch))
+ val = condnumber[i];
+ }
+
+ if (val == 99)
+ {
+ ccsym = lookup((char *)tok[1], LABEL, 0);
+
+ if (ccsym && (ccsym->sattre & EQUATEDCC) && !(ccsym->sattre & UNDEF_CC))
+ {
+ val = ccsym->svalue;
+ }
+ else
+ {
+ error("unknown condition code");
+ return ERROR;
+ }
+ }
+
+ tok += 2;
+ CHECK_COMMA;
+ }
+ else if (*tok == '(')
+ {
+ val = 0; // Jump always
+ }
+ }
+ else
+ {
+ val = 0; // Jump always
+ }
+
+ if (val < 0 || val > 31)
+ {
+ error("condition constant out of range");
+ return ERROR;
+ }
+ else
+ {
+ reg1 = val; // Store condition code
+ }
+
+ if (type == RI_JR)
+ { // JR cc,n
+ if (expr(r_expr, &eval, &eattr, &esym) != OK)
+ goto malformed;
+ else
+ {
+ tdb = (WORD)(eattr & TDB);
+ defined = (WORD)(eattr & DEFINED);
+
+ if ((challoc - ch_size) < 4)
+ chcheck(4L);
+
+ if (!defined)
+ {
+ if (in_main)
+ {
+ fixup(FU_WORD|FU_MJR, sloc, r_expr);
+ }
+ else
+ {
+ fixup(FU_WORD|FU_JR, sloc, r_expr);
+ }
+
+ reg2 = 0;
+ }
+ else
+ {
+ val = eval;
+
+ if (orgactive)
+ {
+ reg2 = ((int)(val - (orgaddr + 2))) / 2;
+ if ((reg2 < -16) || (reg2 > 15))
+ error("PC relative overflow");
+ locptr = orgaddr;
+ }
+ else
+ {
+ reg2 = ((int)(val - (sloc + 2))) / 2;
+ if ((reg2 < -16) || (reg2 > 15))
+ error("PC relative overflow");
+ locptr = sloc;
+ }
+ }
+
+ if (in_main)
+ {
+ if (defined)
+ {
+ if (((locptr >= 0xF03000) && (locptr < 0xF04000)
+ && (val < 0xF03000)) || ((val >= 0xF03000)
+ && (val < 0xF04000) && (locptr < 0xF03000)))
+ {
+ warn("* cannot jump relative between main memory and local gpu ram");
+ }
+ else
+ {
+ page_jump = (locptr & 0xFFFFFF00) - (val & 0xFFFFFF00);
+
+ if (page_jump)
+ {
+ if (val % 4)
+ {
+ warn("* destination address not aligned for long page jump relative, "
+ "insert a \'nop\' before the destination label/address");
+ }
+ }
+ else
+ {
+ if ((val - 2) % 4)
+ {
+ warn("* destination address not aligned for short page jump relative, "
+ "insert a \'nop\' before the destination label/address");
+ }
+ }
+ }
+ }
+ }
+ }
+
+ risc_instruction_word(parm, reg2, reg1);
+ }
+ else
+ { // JUMP cc, (Rn)
+ if (*tok != '(')
+ goto malformed;
+
+ ++tok;
+ reg2 = getregister(FU_REGTWO);
+
+ if (*tok != ')')
+ goto malformed;
+
+ ++tok;
+ at_eol();
+
+ if (in_main)
+ {
+ if (!mjump_align)
+ {
+ warn("* \'jump\' is not recommended for .gpumain as destination addresses "
+ "cannot be validated for alignment, use \'mjump\'");
+ locptr = (orgactive) ? orgaddr : sloc;
+
+ if (locptr % 4)
+ {
+ warn("* source address not aligned for long or short jump, "
+ "insert a \'nop\' before the \'jump\'");
+ }
+ }
+ else
+ {
+ if (mjump_defined)
+ {
+ locptr = (orgactive) ? orgaddr : sloc;
+ page_jump = (locptr & 0xFFFFFF00) - (mjump_dest & 0xFFFFFF00);
+
+ if (page_jump)
+ {
+ if (mjump_dest % 4)
+ {
+ warn("* destination address not aligned for long page jump, "
+ "insert a \'nop\' before the destination label/address");
+ }
+ }
+ else
+ {
+ if (!(mjump_dest & 0x0000000F) || ((mjump_dest - 2) % 4))
+ {
+ warn("* destination address not aligned for short page jump, "
+ "insert a \'nop\' before the destination label/address");
+ }
+ }
+ }
+ else
+ {
+ locptr = (orgactive) ? orgaddr : sloc;
+ fwdjump[fwindex++] = locptr;
+ }
+ }
+ }
+
+ risc_instruction_word(parm, reg2, reg1);
+ }
+
+ break;
+ // Should never get here :D
+ default:
+ error("unknown risc opcode type");
+ return ERROR;
+ break;
+ }
+
+ return 0;
+}
//
-// 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
-// partitioning/swapping, followed by moving the discriminator into the right place. Then,
-// figure out the sizes of the two partions, do the smaller one recursively and the larger one
-// via a repeat of this code. Stopping when there are less than THRESH elements in a partition
-// 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).
+// 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 partitioning/swapping, followed by
+// moving the discriminator into the right place. Then, figure out the sizes of
+// the two partions, do the smaller one recursively and the larger one via a
+// repeat of this code. Stopping when there are less than THRESH elements in a
+// partition 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)
{
/*
* At the top here, lo is the number of characters of elements in the
- * current partition. (Which should be max - base).
+ * current partition. (Which should be max - base).
* Find the median of the first, last, and middle element and make
- * that the middle element. Set j to largest of first and middle.
+ * that the middle element. Set j to largest of first and middle.
* If max is larger than that guy, then it's that guy, else compare
- * max with loser of first and take larger. Things are set up to
+ * max with loser of first and take larger. Things are set up to
* prefer the middle, then the first in case of ties.
*/
lo = max - base; /* number of elements as chars */
- do {
+
+ do
+ {
mid = i = base + qsz * ((lo / qsz) >> 1);
- if (lo >= mthresh) {
+
+ if (lo >= mthresh)
+ {
j = (qcmp((jj = base), i) > 0 ? jj : i);
- if (qcmp(j, (tmp = max - qsz)) > 0) {
+
+ if (qcmp(j, (tmp = max - qsz)) > 0)
+ {
/* switch to first loser */
j = (j == jj ? i : jj);
+
if (qcmp(j, tmp) < 0)
j = tmp;
}
- if (j != i) {
+
+ if (j != i)
+ {
ii = qsz;
- do {
+
+ do
+ {
c = *i;
*i++ = *j;
*j++ = c;
- } while (--ii);
+ }
+ while (--ii);
}
}
+
/*
* Semi-standard quicksort partitioning/swapping
*/
- for (i = base, j = max - qsz; ; ) {
+ for(i=base, j=max-qsz; ;)
+ {
while (i < mid && qcmp(i, mid) <= 0)
i += qsz;
- while (j > mid) {
- if (qcmp(mid, j) <= 0) {
+
+ while (j > mid)
+ {
+ if (qcmp(mid, j) <= 0)
+ {
j -= qsz;
continue;
}
+
tmp = i + qsz; /* value of i after swap */
- if (i == mid) {
+
+ if (i == mid)
+ {
/* j <-> mid, new mid is j */
mid = jj = j;
- } else {
+ }
+ else
+ {
/* i <-> j */
jj = j;
j -= qsz;
}
+
goto swap;
}
- if (i == mid) {
+
+ if (i == mid)
+ {
break;
- } else {
+ }
+ else
+ {
/* i <-> mid, new mid is i */
jj = mid;
tmp = mid = i; /* value of i after swap */
}
swap:
ii = qsz;
- do {
+
+ do
+ {
c = *i;
*i++ = *jj;
*jj++ = c;
- } while (--ii);
+ }
+ while (--ii);
+
i = tmp;
}
+
/*
* Look at sizes of the two partitions, do the smaller
* one first by recursion, then do the larger one by
* of at least size THRESH.
*/
i = (j = mid) + qsz;
- if ((lo = j - base) <= (hi = max - i)) {
+
+ if ((lo = j - base) <= (hi = max - i))
+ {
if (lo >= thresh)
qst(base, j);
+
base = i;
lo = hi;
- } else {
+ }
+ else
+ {
if (hi >= thresh)
qst(i, max);
+
max = j;
}
- } while (lo >= thresh);
+ }
+ while (lo >= thresh);
- return(0);
+ return 0;
}
* 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)())
+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);
+ return 0;
qsz = size;
qcmp = compar;
* the first THRESH elements (or the first n if n < THRESH), finding
* the min, and swapping it into the first position.
*/
- for (j = lo = base; (lo += qsz) < hi; )
+ for(j=lo=base; (lo+=qsz)<hi;)
+ {
if (qcmp(j, lo) > 0)
j = lo;
+ }
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;
}
}
+
/*
* With our sentinel in place, we now run the following hyper-fast
* insertion sort. For each remaining element, min, from [1] to [n-1],
* Then, do the standard insertion sort shift on a character at a time
* basis for each element in the frob.
*/
- for (min = base; (hi = min += qsz) < max; ) {
+ for(min=base; (hi=min+=qsz)<max;)
+ {
while (qcmp(hi -= qsz, min) > 0)
/* void */;
- if ((hi += qsz) != min) {
- for (lo = min + qsz; --lo >= min; ) {
+
+ if ((hi += qsz) != min)
+ {
+ for(lo=min+qsz; --lo>=min;)
+ {
c = *lo;
- for (i = j = lo; (j -= qsz) >= hi; i = j)
+
+ for(i=j=lo; (j-=qsz)>=hi; i=j)
*i = *j;
+
*i = c;
}
}
}
- return(0);
+
+ return 0;
}
//
int process(int argc, char ** argv)
{
- int argno; // Argument number
- SYM * sy; // Pointer to a symbol record
- char * s; // String pointer
- int fd; // File descriptor
- char fnbuf[FNSIZ]; // Filename buffer
- int i; // Iterator
-
- errcnt = 0; // Initialise error count
- listing = 0; // Initialise listing level
- list_flag = 0; // Initialise listing flag
- verb_flag = perm_verb_flag; // Initialise verbose flag
- as68_flag = 0; // Initialise as68 kludge mode
- glob_flag = 0; // Initialise .globl flag
- sbra_flag = 0; // Initialise short branch flag
- debug = 0; // Initialise debug flag
- searchpath = NULL; // Initialise search path
- objfname = NULL; // Initialise object filename
- list_fname = NULL; // Initialise listing filename
- err_fname = NULL; // Initialise error filename
- obj_format = BSD; // Initialise object format
- firstfname = NULL; // Initialise first filename
- err_fd = ERROUT; // Initialise error file descriptor
- err_flag = 0; // Initialise error flag
- rgpu = 0; // Initialise GPU assembly flag
- rdsp = 0; // Initialise DSP assembly flag
- lsym_flag = 1; // Include local symbols in object file
- regbank = BANK_N; // No RISC register bank specified
- orgactive = 0; // Not in RISC org section
- orgwarning = 0; // No ORG warning issued
- a_amount = 0;
- segpadsize = 2; // Initialise segment padding size
- in_main = 0;
-
- // Initialise modules
- init_sym(); // Symbol table
- init_token(); // Tokenizer
- init_procln(); // Line processor
- init_expr(); // Expression analyzer
- init_sect(); // Section manager / code generator
- init_mark(); // Mark tape-recorder
- init_macro(); // Macro processor
- init_list(); // Listing generator
-
- // Process command line arguments and assemble source files
- for(argno = 0; argno < argc; ++argno) {
- if (*argv[argno] == '-') {
- switch(argv[argno][1]) {
- case 'd': // Define symbol
- case 'D':
- for(s = argv[argno] + 2; *s != EOS;) {
- if (*s++ == '=') {
- s[-1] = EOS;
- break;
- }
- }
- if (argv[argno][2] == EOS) {
- printf("-d: empty symbol\n");
- ++errcnt;
- return(errcnt);
- }
- sy = lookup(argv[argno] + 2, 0, 0);
- if (sy == NULL) {
- sy = newsym(argv[argno] + 2, LABEL, 0);
- sy->svalue = 0;
- }
- sy->sattr = DEFINED | EQUATED | ABS;
- if (*s)
- sy->svalue = (VALUE)atoi(s);
- else
- sy->svalue = 0;
- break;
- case 'e': // Redirect error message output
- case 'E':
- err_fname = argv[argno] + 2;
- break;
- case 'f': // -f<format>
- case 'F':
- switch(argv[argno][2]) {
- case EOS:
- case 'b': // -fb = BSD (Jaguar Recommended)
- case 'B':
- obj_format = BSD;
- break;
- default:
- printf("-f: unknown object format specified\n");
- ++errcnt;
- return(errcnt);
- }
- break;
- case 'g': // Debugging flag
- case 'G':
- printf("Debugging flag (-g) not yet implemented\n");
- break;
- case 'i': // Set directory search path
- case 'I':
- searchpath = argv[argno] + 2;
- break;
- case 'l': // Produce listing file
- case 'L':
- list_fname = argv[argno] + 2;
- listing = 1;
- list_flag = 1;
- ++lnsave;
- break;
- case 'o': // Direct object file output
- case 'O':
- if (argv[argno][2] != EOS) objfname = argv[argno] + 2;
- else {
- if (++argno >= argc) {
- printf("Missing argument to -o");
- ++errcnt;
- return(errcnt);
- }
- objfname = argv[argno];
- }
- break;
- case 'r': // Pad seg to requested boundary size
- case 'R':
- switch(argv[argno][2]) {
- case 'w': case 'W': segpadsize = 2; break;
- case 'l': case 'L': segpadsize = 4; break;
- case 'p': case 'P': segpadsize = 8; break;
- case 'd': case 'D': segpadsize = 16; break;
- case 'q': case 'Q': segpadsize = 32; break;
- default: segpadsize = 2; break; // Effective autoeven();
- }
- break;
- case 's': // Warn about possible short branches
- case 'S':
- sbra_flag = 1;
- break;
- case 'u': // Make undefined symbols .globl
- case 'U':
- glob_flag = 1;
- break;
- case 'v': // Verbose flag
- case 'V':
- verb_flag++;
- if (verb_flag > 1) display_version();
- break;
- case 'x': // Turn on debugging
- case 'X':
- debug = 1;
- printf("~ Debugging ON\n");
- break;
- case 'y': // -y<pagelen>
- case 'Y':
- pagelen = atoi(argv[argno] + 2);
- if (pagelen < 10) {
- printf("-y: bad page length\n");
- ++errcnt;
- return(errcnt);
- }
- break;
- case EOS: // Input is stdin
- if (firstfname == NULL) // Kludge first filename
- firstfname = defname;
- include(0, "(stdin)");
- assemble();
- break;
- case 'h': // Display command line usage
- case 'H':
- case '?':
- display_version();
- display_help();
- ++errcnt;
- break;
- default:
- display_version();
- printf("Unknown switch: %s\n\n", argv[argno]);
- display_help();
- ++errcnt;
- break;
- }
- } else {
- // Record first filename.
- if (firstfname == NULL)
- firstfname = argv[argno];
- strcpy(fnbuf, argv[argno]);
- fext(fnbuf, ".s", 0);
- fd = open(fnbuf, 0);
- if (fd < 0) {
- printf("Cannot open: %s\n", fnbuf);
- ++errcnt;
- continue;
- }
- include(fd, fnbuf);
- assemble();
- }
- }
-
- // Wind-up processing;
- // o save current section (no more code generation)
- // o do auto-even of all sections (or boundary alignment as requested through '-r')
- // o determine name of object file:
- // - "foo.o" for linkable output;
- // - "foo.prg" for GEMDOS executable (-p flag).
- savsect();
- for(i = TEXT; i <= BSS; i <<= 1) {
- switchsect(i);
- switch(segpadsize) {
- case 2: d_even(); break;
- case 4: d_long(); break;
- case 8: d_phrase(); break;
- case 16: d_dphrase(); break;
- case 32: d_qphrase(); break;
- }
- savsect();
- }
-
- if (objfname == NULL) {
- if (firstfname == NULL)
- firstfname = defname;
- strcpy(fnbuf, firstfname);
- //fext(fnbuf, prg_flag ? ".prg" : ".o", 1);
- fext(fnbuf, ".o", 1);
- objfname = fnbuf;
- }
-
- // With one pass finished, go back and:
- // (1) run through all the fixups and resolve forward references;
- // (1.5) ensure that remaining fixups can be handled by the linker
- // (`lo68' format, extended (postfix) format....)
- // (2) generate the output file image and symbol table;
- // (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)
- cantcreat(objfname);
- if (verb_flag) {
- s = "object";
- printf("[Writing %s file: %s]\n", s, objfname);
- }
- object((WORD)fd);
- close(fd);
- if (errcnt != 0)
- unlink(objfname);
- }
-
- if (list_flag) {
- if (verb_flag) printf("[Wrapping-up listing file]\n");
- listing = 1;
- symtable();
- close(list_fd);
- }
-
- if (err_flag)
- close(err_fd);
-
- DEBUG dump_everything();
-
- return(errcnt);
-}
+ int argno; // Argument number
+ SYM * sy; // Pointer to a symbol record
+ char * s; // String pointer
+ int fd; // File descriptor
+ char fnbuf[FNSIZ]; // Filename buffer
+ int i; // Iterator
+
+ errcnt = 0; // Initialise error count
+ listing = 0; // Initialise listing level
+ list_flag = 0; // Initialise listing flag
+ verb_flag = perm_verb_flag; // Initialise verbose flag
+ as68_flag = 0; // Initialise as68 kludge mode
+ glob_flag = 0; // Initialise .globl flag
+ sbra_flag = 0; // Initialise short branch flag
+ debug = 0; // Initialise debug flag
+ searchpath = NULL; // Initialise search path
+ objfname = NULL; // Initialise object filename
+ list_fname = NULL; // Initialise listing filename
+ err_fname = NULL; // Initialise error filename
+ obj_format = BSD; // Initialise object format
+ firstfname = NULL; // Initialise first filename
+ err_fd = ERROUT; // Initialise error file descriptor
+ err_flag = 0; // Initialise error flag
+ rgpu = 0; // Initialise GPU assembly flag
+ rdsp = 0; // Initialise DSP assembly flag
+ lsym_flag = 1; // Include local symbols in object file
+ regbank = BANK_N; // No RISC register bank specified
+ orgactive = 0; // Not in RISC org section
+ orgwarning = 0; // No ORG warning issued
+ a_amount = 0;
+ segpadsize = 2; // Initialise segment padding size
+ in_main = 0;
+
+ // Initialise modules
+ init_sym(); // Symbol table
+ init_token(); // Tokenizer
+ init_procln(); // Line processor
+ init_expr(); // Expression analyzer
+ init_sect(); // Section manager / code generator
+ init_mark(); // Mark tape-recorder
+ init_macro(); // Macro processor
+ init_list(); // Listing generator
+
+ // Process command line arguments and assemble source files
+ for(argno = 0; argno < argc; ++argno)
+ {
+ if (*argv[argno] == '-')
+ {
+ switch (argv[argno][1])
+ {
+ case 'd': // Define symbol
+ case 'D':
+ for(s=argv[argno]+2; *s!=EOS;)
+ {
+ if (*s++ == '=')
+ {
+ s[-1] = EOS;
+ break;
+ }
+ }
+ if (argv[argno][2] == EOS)
+ {
+ printf("-d: empty symbol\n");
+ ++errcnt;
+ return errcnt;
+ }
-#if 0
-//
-// Interactive Mode
-//
-void interactive(void)
-{
- char * s; // String pointer for banner
- char ln[LNSIZ]; // Input line
- char * argv[MAXARGV]; // Argument values
- int argcnt; // Argument count
-
- // As there is no command line, print a copyright message and prompt for command line
- s = "*****************************************************\n";
- printf("\n%s* RMAC - Reboot's Macro Assembler for Atari Jaguar *\n", s);
- printf("* Copyright (C) 199x Landon Dyer, 2011 Reboot *\n");
- printf("* Version %01i.%01i.%01i Platform: %-9s *\n",MAJOR,MINOR,PATCH,PLATFORM);
- printf("* ------------------------------------------------- *\n");
- printf("* INTERACTIVE MODE (press ENTER by itself to quit) *\n%s\n", s);
-
- perm_verb_flag = 1; // Enter permanent verbose mode
-
- // Handle commandlines until EOF or we get an empty one
- for(;;)
- {
- loop:
- printf("* ");
- fflush(stdout); // Make prompt visible
+ sy = lookup(argv[argno] + 2, 0, 0);
-// if (gets(ln) == NULL || !*ln) // Get input line
- if (fgets(ln, LNSIZ, stdin) == NULL || !*ln) // Get input line
- break;
+ if (sy == NULL)
+ {
+ sy = newsym(argv[argno] + 2, LABEL, 0);
+ sy->svalue = 0;
+ }
- argcnt = 0; // Process input line
- s = ln;
+ sy->sattr = DEFINED | EQUATED | ABS;
- while (*s)
- {
- if (isspace(*s))
- { // Skip whitespace
- ++s;
- }
- else
- {
- if (argcnt >= MAXARGV)
+ if (*s)
+ sy->svalue = (VALUE)atoi(s);
+ else
+ sy->svalue = 0;
+
+ break;
+ case 'e': // Redirect error message output
+ case 'E':
+ err_fname = argv[argno] + 2;
+ break;
+ case 'f': // -f<format>
+ case 'F':
+ switch (argv[argno][2])
{
- printf("Too many arguments\n");
- goto loop;
+ case EOS:
+ case 'b': // -fb = BSD (Jaguar Recommended)
+ case 'B':
+ obj_format = BSD;
+ break;
+ default:
+ printf("-f: unknown object format specified\n");
+ ++errcnt;
+ return errcnt;
+ }
+ break;
+ case 'g': // Debugging flag
+ case 'G':
+ printf("Debugging flag (-g) not yet implemented\n");
+ break;
+ case 'i': // Set directory search path
+ case 'I':
+ searchpath = argv[argno] + 2;
+ break;
+ case 'l': // Produce listing file
+ case 'L':
+ list_fname = argv[argno] + 2;
+ listing = 1;
+ list_flag = 1;
+ ++lnsave;
+ break;
+ case 'o': // Direct object file output
+ case 'O':
+ if (argv[argno][2] != EOS)
+ objfname = argv[argno] + 2;
+ else
+ {
+ if (++argno >= argc)
+ {
+ printf("Missing argument to -o");
+ ++errcnt;
+ return errcnt;
+ }
+ objfname = argv[argno];
}
- argv[argcnt++] = s;
+ break;
+ case 'r': // Pad seg to requested boundary size
+ case 'R':
+ switch(argv[argno][2])
+ {
+ case 'w': case 'W': segpadsize = 2; break;
+ case 'l': case 'L': segpadsize = 4; break;
+ case 'p': case 'P': segpadsize = 8; break;
+ case 'd': case 'D': segpadsize = 16; break;
+ case 'q': case 'Q': segpadsize = 32; break;
+ default: segpadsize = 2; break; // Effective autoeven();
+ }
+ break;
+ case 's': // Warn about possible short branches
+ case 'S':
+ sbra_flag = 1;
+ break;
+ case 'u': // Make undefined symbols .globl
+ case 'U':
+ glob_flag = 1;
+ break;
+ case 'v': // Verbose flag
+ case 'V':
+ verb_flag++;
+
+ if (verb_flag > 1)
+ display_version();
+
+ break;
+ case 'x': // Turn on debugging
+ case 'X':
+ debug = 1;
+ printf("~ Debugging ON\n");
+ break;
+ case 'y': // -y<pagelen>
+ case 'Y':
+ pagelen = atoi(argv[argno] + 2);
+
+ if (pagelen < 10)
+ {
+ printf("-y: bad page length\n");
+ ++errcnt;
+ return errcnt;
+ }
- while (*s && !isspace(*s))
- ++s;
+ break;
+ case EOS: // Input is stdin
+ if (firstfname == NULL) // Kludge first filename
+ firstfname = defname;
- if (isspace(*s))
- *s++ = EOS;
+ include(0, "(stdin)");
+ assemble();
+ break;
+ case 'h': // Display command line usage
+ case 'H':
+ case '?':
+ display_version();
+ display_help();
+ ++errcnt;
+ break;
+ default:
+ display_version();
+ printf("Unknown switch: %s\n\n", argv[argno]);
+ display_help();
+ ++errcnt;
+ break;
}
}
+ else
+ {
+ // Record first filename.
+ if (firstfname == NULL)
+ firstfname = argv[argno];
- if (argcnt == 0) // Exit if no arguments
- break;
+ strcpy(fnbuf, argv[argno]);
+ fext(fnbuf, ".s", 0);
+ fd = open(fnbuf, 0);
- process(argcnt, argv); // Process arguments
+ if (fd < 0)
+ {
+ printf("Cannot open: %s\n", fnbuf);
+ ++errcnt;
+ continue;
+ }
+
+ include(fd, fnbuf);
+ assemble();
+ }
+ }
+
+ // Wind-up processing;
+ // o save current section (no more code generation)
+ // o do auto-even of all sections (or boundary alignment as requested through '-r')
+ // o determine name of object file:
+ // - "foo.o" for linkable output;
+ // - "foo.prg" for GEMDOS executable (-p flag).
+ savsect();
+
+ for(i=TEXT; i<=BSS; i<<=1)
+ {
+ switchsect(i);
+
+ switch(segpadsize)
+ {
+ case 2: d_even(); break;
+ case 4: d_long(); break;
+ case 8: d_phrase(); break;
+ case 16: d_dphrase(); break;
+ case 32: d_qphrase(); break;
+ }
+
+ savsect();
+ }
+
+ if (objfname == NULL)
+ {
+ if (firstfname == NULL)
+ firstfname = defname;
+
+ strcpy(fnbuf, firstfname);
+ //fext(fnbuf, prg_flag ? ".prg" : ".o", 1);
+ fext(fnbuf, ".o", 1);
+ objfname = fnbuf;
+ }
+
+ // With one pass finished, go back and:
+ // (1) run through all the fixups and resolve forward references;
+ // (1.5) ensure that remaining fixups can be handled by the linker
+ // (`lo68' format, extended (postfix) format....)
+ // (2) generate the output file image and symbol table;
+ // (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)
+ cantcreat(objfname);
+
+ if (verb_flag)
+ {
+ s = "object";
+ printf("[Writing %s file: %s]\n", s, objfname);
+ }
+
+ object((WORD)fd);
+ close(fd);
- if (errcnt)
- printf("%d assembly error%s\n", errcnt, (errcnt > 1) ? "s" : "");
+ if (errcnt != 0)
+ unlink(objfname);
}
+
+ if (list_flag)
+ {
+ if (verb_flag)
+ printf("[Wrapping-up listing file]\n");
+
+ listing = 1;
+ symtable();
+ close(list_fd);
+ }
+
+ if (err_flag)
+ close(err_fd);
+
+ DEBUG dump_everything();
+
+ return errcnt;
}
-#endif
//
//
int main(int argc, char ** argv)
{
- int status; // Status flag
+ int status;
int i;
- perm_verb_flag = 0; // Clobber "permanent" verbose flag
- cmdlnexec = argv[0]; // Obtain executable name
+ perm_verb_flag = 0; // Clobber "permanent" verbose flag
+ cmdlnexec = argv[0]; // Obtain executable name
- endian = get_endianess(); // Get processor endianess
+ endian = get_endianess(); // Get processor endianess
for(i=0; i<MAXFWDJUMPS; i++)
fwdjump[i] = 0;
+ // Full command line passed
if (argc > 1)
- { // Full command line passed
+ {
status = process(argc - 1, argv + 1);
}
- // Interactive mode
else
{
-// Sorry Landon, this is the year 20xx and we haz plenty of resources now ;-)
-// status = 0;
-// interactive();
- // Instead, we show a nice banner and switches :-)
display_version();
display_help();
}
WORD scattr; // Section attributes
LONG sloc; // Current loc in section
-CHUNK *scode; // Current (last) code chunk
+CHUNK * scode; // Current (last) code chunk
LONG challoc; // #bytes alloc'd to code chunk
LONG ch_size; // #bytes used in code chunk
-char *chptr; // Deposit point in code chunk buffer
+char * chptr; // Deposit point in code chunk buffer
-CHUNK *sfix; // Current (last) fixup chunk
+CHUNK * sfix; // Current (last) fixup chunk
LONG fchalloc; // #bytes alloc'd to fixup chunk
LONG fchsize; // #bytes used in fixup chunk
PTR fchptr; // Deposit point in fixup chunk buffer
0, // FU_6BRA
};
+
//
-// --- Make a New (Clean) Section ------------------------------------------------------------------
+// Make a New (Clean) Section
//
-
-void mksect(int sno, WORD attr) {
- SECT *p; // Section pointer
-
- p = §[sno];
- p->scattr = attr;
- p->sloc = 0;
- p->scode = p->sfcode = NULL;
- p->sfix = p->sffix = NULL;
+void mksect(int sno, WORD attr)
+{
+ SECT * p; // Section pointer
+
+ p = §[sno];
+ p->scattr = attr;
+ p->sloc = 0;
+ p->scode = p->sfcode = NULL;
+ p->sfix = p->sffix = NULL;
}
+
//
-// --- Switch to Another Section (Copy Section & Chunk Descriptors to Global Vars for Fast Access) -
+// Switch to Another Section (Copy Section & Chunk Descriptors to Global Vars
+// for Fast Access)
//
-
-void switchsect(int sno) {
- SECT *p; // Section pointer
- CHUNK *cp; // Chunk pointer
-
- cursect = sno;
- p = §[sno];
-
- scattr = p->scattr; // Copy section vars
- sloc = p->sloc;
- scode = p->scode;
- sfix = p->sfix;
-
- if((cp = scode) != NULL) { // Copy code chunk vars
- challoc = cp->challoc;
- ch_size = cp->ch_size;
- chptr = cp->chptr + ch_size;
- } else challoc = ch_size = 0;
-
- if((cp = sfix) != NULL) { // Copy fixup chunk vars
- fchalloc = cp->challoc;
- fchsize = cp->ch_size;
- fchptr.cp = cp->chptr + fchsize;
- } else fchalloc = fchsize = 0;
+void switchsect(int sno)
+{
+ SECT * p; // Section pointer
+ CHUNK * cp; // Chunk pointer
+
+ cursect = sno;
+ p = §[sno];
+
+ scattr = p->scattr; // Copy section vars
+ sloc = p->sloc;
+ scode = p->scode;
+ sfix = p->sfix;
+
+ if ((cp = scode) != NULL)
+ { // Copy code chunk vars
+ challoc = cp->challoc;
+ ch_size = cp->ch_size;
+ chptr = cp->chptr + ch_size;
+ }
+ else
+ challoc = ch_size = 0;
+
+ if ((cp = sfix) != NULL)
+ { // Copy fixup chunk vars
+ fchalloc = cp->challoc;
+ fchsize = cp->ch_size;
+ fchptr.cp = cp->chptr + fchsize;
+ }
+ else
+ fchalloc = fchsize = 0;
}
+
//
-// --- Save Current Section ------------------------------------------------------------------------
+// Save Current Section
//
+void savsect(void)
+{
+ SECT * p = §[cursect];
-void savsect(void) {
- SECT *p;
+ p->scattr = scattr; // Bailout section vars
+ p->sloc = sloc;
- p = §[cursect];
+ if (scode != NULL) // Bailout code chunk
+ scode->ch_size = ch_size;
- p->scattr = scattr; // Bailout section vars
- p->sloc = sloc;
-
- if(scode != NULL) // Bailout code chunk
- scode->ch_size = ch_size;
-
- if(sfix != NULL) // Bailout fixup chunk
- sfix->ch_size = fchsize;
+ if (sfix != NULL) // Bailout fixup chunk
+ sfix->ch_size = fchsize;
}
+
//
-// --- Initialize Sections; Setup initial ABS, TEXT, DATA and BSS sections -------------------------
+// Initialize Sections; Setup initial ABS, TEXT, DATA and BSS sections
//
-
-void init_sect(void) {
- int i; // Iterator
-
- // Cleanup all sections
- for(i = 0; i < NSECTS; ++i)
- mksect(i, 0);
-
- // Construct default sections, make TEXT the current section
- mksect(ABS, SUSED|SABS|SBSS); // ABS
- mksect(TEXT, SUSED|TEXT ); // TEXT
- mksect(DATA, SUSED|DATA ); // DATA
- mksect(BSS, SUSED|BSS |SBSS); // BSS
-// mksect(M6502, SUSED|TEXT ); // 6502 code section
-
- switchsect(TEXT); // Switch to TEXT for starters
+void init_sect(void)
+{
+ int i; // Iterator
+
+ // Cleanup all sections
+ for(i=0; i<NSECTS; ++i)
+ mksect(i, 0);
+
+ // Construct default sections, make TEXT the current section
+ mksect(ABS, SUSED|SABS|SBSS); // ABS
+ mksect(TEXT, SUSED|TEXT ); // TEXT
+ mksect(DATA, SUSED|DATA ); // DATA
+ mksect(BSS, SUSED|BSS |SBSS); // BSS
+// mksect(M6502, SUSED|TEXT ); // 6502 code section
+
+ switchsect(TEXT); // Switch to TEXT for starters
}
+
//
-// -------------------------------------------------------------------------------------------------
-// Test to see if a location has a fixup sic'd on it. This is used by the listing
-// generator to print 'xx's instead of '00's for forward references
-// -------------------------------------------------------------------------------------------------
+// Test to see if a location has a fixup sic'd on it. This is used by the
+// listing generator to print 'xx's instead of '00's for forward references
//
-
-int fixtest(int sno, LONG loc) {
- CHUNK *ch;
- PTR fup;
- char *fuend;
- WORD w;
- LONG xloc;
-
- stopmark(); // Force update to sect[] variables
-
- // Hairy, ugly linear search for a mark on our location;
- // the speed doesn't matter, since this is only done when generating a listing, which is SLOW.
- for(ch = sect[sno].sffix; ch != NULL; ch = ch->chnext) {
- fup.cp = (char *)ch->chptr;
- fuend = fup.cp + ch->ch_size;
-
- while(fup.cp < fuend) {
- w = *fup.wp++;
- xloc = *fup.lp++ + (int)fusizoffs[w & FUMASK];
- fup.wp += 2;
-
- if(xloc == loc)
- return((int)fusiztab[w & FUMASK]);
-
- if(w & FU_EXPR) {
- w = *fup.wp++;
- fup.lp += w;
- } else ++fup.lp;
- }
- }
-
- return(0);
+int fixtest(int sno, LONG loc)
+{
+ CHUNK * ch;
+ PTR fup;
+ char * fuend;
+ WORD w;
+ LONG xloc;
+
+ stopmark(); // Force update to sect[] variables
+
+ // Hairy, ugly linear search for a mark on our location;
+ // the speed doesn't matter, since this is only done when generating a listing, which is SLOW.
+ for(ch=sect[sno].sffix; ch!=NULL; ch=ch->chnext)
+ {
+ fup.cp = (char *)ch->chptr;
+ fuend = fup.cp + ch->ch_size;
+
+ while (fup.cp < fuend)
+ {
+ w = *fup.wp++;
+ xloc = *fup.lp++ + (int)fusizoffs[w & FUMASK];
+ fup.wp += 2;
+
+ if (xloc == loc)
+ return (int)fusiztab[w & FUMASK];
+
+ if (w & FU_EXPR)
+ {
+ w = *fup.wp++;
+ fup.lp += w;
+ }
+ else
+ ++fup.lp;
+ }
+ }
+
+ return 0;
}
+
//
-// -------------------------------------------------------------------------------------------------
-// Check that there are at least `amt' bytes left in the current chunk. If there are not,
-// allocate another chunk of at least `amt' bytes (and probably more).
+// Check that there are at least `amt' bytes left in the current chunk. If
+// there are not, allocate another chunk of at least `amt' bytes (and probably
+// more).
//
// If `amt' is zero, ensure there are at least CH_THRESHOLD bytes, likewise.
-// -------------------------------------------------------------------------------------------------
//
-
-int chcheck(LONG amt) {
- CHUNK *cp;
- SECT *p;
-
- if(scattr & SBSS) return(0); // If in BSS section, forget it
-
- if(!amt) amt = CH_THRESHOLD;
-
- if((int)(challoc - ch_size) >= (int)amt)
- return(0);
-
- if(amt < CH_CODE_SIZE) amt = CH_CODE_SIZE;
- p = §[cursect];
- cp = (CHUNK *)amem((long)(sizeof(CHUNK) + amt));
- if(scode == NULL) { // First chunk in section
- cp->chprev = NULL;
- p->sfcode = cp;
- } else { // Add chunk to other chunks
- cp->chprev = scode;
- scode->chnext = cp;
- scode->ch_size = ch_size; // Save old chunk's globals
- }
-
- // Setup chunk and global vars
- cp->chloc = sloc;
- cp->chnext = NULL;
- challoc = cp->challoc = amt;
- ch_size = cp->ch_size = 0;
- chptr = cp->chptr = ((char *)cp) + sizeof(CHUNK);
- scode = p->scode = cp;
-
- return(0);
+int chcheck(LONG amt)
+{
+ CHUNK * cp;
+ SECT * p;
+
+ if (scattr & SBSS)
+ return 0; // If in BSS section, forget it
+
+ if (!amt)
+ amt = CH_THRESHOLD;
+
+ if ((int)(challoc - ch_size) >= (int)amt)
+ return 0;
+
+ if (amt < CH_CODE_SIZE)
+ amt = CH_CODE_SIZE;
+
+ p = §[cursect];
+ cp = (CHUNK *)amem((long)(sizeof(CHUNK) + amt));
+
+ if (scode == NULL)
+ { // First chunk in section
+ cp->chprev = NULL;
+ p->sfcode = cp;
+ }
+ else
+ { // Add chunk to other chunks
+ cp->chprev = scode;
+ scode->chnext = cp;
+ scode->ch_size = ch_size; // Save old chunk's globals
+ }
+
+ // Setup chunk and global vars
+ cp->chloc = sloc;
+ cp->chnext = NULL;
+ challoc = cp->challoc = amt;
+ ch_size = cp->ch_size = 0;
+ chptr = cp->chptr = ((char *)cp) + sizeof(CHUNK);
+ scode = p->scode = cp;
+
+ return 0;
}
+
//
-// --- Arrange for a fixup on a location -----------------------------------------------------------
+// Arrange for a fixup on a location
//
-
-int fixup(WORD attr, LONG loc, TOKEN *fexpr) {
- LONG i;
- LONG len = 0;
- CHUNK *cp;
- SECT *p;
-
- // Compute length of expression (could be faster); determine if it's the single-symbol case;
- // no expression if it's just a mark. This code assumes 16 bit WORDs and 32 bit LONGs
- if(*fexpr == SYMBOL && fexpr[2] == ENDEXPR)
- //if((attr & 0x0F00) == FU_JR) {
- if((attr & 0x0200) == FU_JR) {
- i = 18; // Just a single symbol
- } else {
- i = 14;
- }
- else {
- attr |= FU_EXPR;
- for(len = 0; fexpr[len] != ENDEXPR; ++len)
- if(fexpr[len] == CONST || fexpr[len] == SYMBOL)
- ++len;
- ++len; // Add 1 for ENDEXPR
- i = (len << 2) + 12;
- }
-
- // Maybe alloc another fixup chunk for this one to fit in
- if((fchalloc - fchsize) < i) {
- p = §[cursect];
- cp = (CHUNK *)amem((long)(sizeof(CHUNK) + CH_FIXUP_SIZE));
- if(sfix == NULL) { // First fixup chunk in section
- cp->chprev = NULL;
- p->sffix = cp;
- } else { // Add to other chunks
- cp->chprev = sfix;
- sfix->chnext = cp;
- sfix->ch_size = fchsize;
- }
-
- // Setup fixup chunk and its global vars
- cp->chnext = NULL;
- fchalloc = cp->challoc = CH_FIXUP_SIZE;
- fchsize = cp->ch_size = 0;
- fchptr.cp = cp->chptr = ((char *)cp) + sizeof(CHUNK);
- sfix = p->sfix = cp;
- }
-
- // Record fixup type, fixup location, and the file number and line number the fixup is
- // located at.
- *fchptr.wp++ = attr;
- *fchptr.lp++ = loc;
- *fchptr.wp++ = cfileno;
- *fchptr.wp++ = (WORD)curlineno;
- // Store postfix expression or pointer to a single symbol, or nothing for a mark.
- if(attr & FU_EXPR) {
- *fchptr.wp++ = (WORD)len;
- while(len--)
- *fchptr.lp++ = (LONG)*fexpr++;
- } else {
- *fchptr.lp++ = (LONG)fexpr[1];
- }
-
- //if((attr & 0x0F00) == FU_JR) {
- if((attr & 0x0200) == FU_JR) {
- if(orgactive) *fchptr.lp++ = orgaddr;
- else *fchptr.lp++ = 0x00000000;
- }
-
- fchsize += i;
-
- return(0);
+int fixup(WORD attr, LONG loc, TOKEN * fexpr)
+{
+ LONG i;
+ LONG len = 0;
+ CHUNK * cp;
+ SECT * p;
+
+ // Compute length of expression (could be faster); determine if it's the single-symbol case;
+ // no expression if it's just a mark. This code assumes 16 bit WORDs and 32 bit LONGs
+ if (*fexpr == SYMBOL && fexpr[2] == ENDEXPR)
+ {
+ //if ((attr & 0x0F00) == FU_JR) {
+ if ((attr & 0x0200) == FU_JR)
+ {
+ i = 18; // Just a single symbol
+ }
+ else
+ {
+ i = 14;
+ }
+ }
+ else
+ {
+ attr |= FU_EXPR;
+
+ for(len=0; fexpr[len]!=ENDEXPR; ++len)
+ {
+ if (fexpr[len] == CONST || fexpr[len] == SYMBOL)
+ ++len;
+ }
+
+ ++len; // Add 1 for ENDEXPR
+ i = (len << 2) + 12;
+ }
+
+ // Maybe alloc another fixup chunk for this one to fit in
+ if ((fchalloc - fchsize) < i)
+ {
+ p = §[cursect];
+ cp = (CHUNK *)amem((long)(sizeof(CHUNK) + CH_FIXUP_SIZE));
+
+ if (sfix == NULL)
+ { // First fixup chunk in section
+ cp->chprev = NULL;
+ p->sffix = cp;
+ }
+ else
+ { // Add to other chunks
+ cp->chprev = sfix;
+ sfix->chnext = cp;
+ sfix->ch_size = fchsize;
+ }
+
+ // Setup fixup chunk and its global vars
+ cp->chnext = NULL;
+ fchalloc = cp->challoc = CH_FIXUP_SIZE;
+ fchsize = cp->ch_size = 0;
+ fchptr.cp = cp->chptr = ((char *)cp) + sizeof(CHUNK);
+ sfix = p->sfix = cp;
+ }
+
+ // Record fixup type, fixup location, and the file number and line number the fixup is
+ // located at.
+ *fchptr.wp++ = attr;
+ *fchptr.lp++ = loc;
+ *fchptr.wp++ = cfileno;
+ *fchptr.wp++ = (WORD)curlineno;
+
+ // Store postfix expression or pointer to a single symbol, or nothing for a mark.
+ if (attr & FU_EXPR)
+ {
+ *fchptr.wp++ = (WORD)len;
+
+ while (len--)
+ *fchptr.lp++ = (LONG)*fexpr++;
+ }
+ else
+ {
+ *fchptr.lp++ = (LONG)fexpr[1];
+ }
+
+ //if ((attr & 0x0F00) == FU_JR) {
+ if ((attr & 0x0200) == FU_JR)
+ {
+ if (orgactive)
+ *fchptr.lp++ = orgaddr;
+ else
+ *fchptr.lp++ = 0x00000000;
+ }
+
+ fchsize += i;
+
+ return 0;
}
+
//
-// --- Resolve all Fixups --------------------------------------------------------------------------
+// Resolve all Fixups
//
-
-int fixups(void) {
- unsigned i; // Iterator
- char buf[EBUFSIZ];
-
- if(glob_flag) // Make undefined symbols GLOBL
- syg_fix();
- resfix(TEXT);
- resfix(DATA);
-
- // We need to do a final check of forward 'jump' destination addresses that are external
- for(i = 0; i < MAXFWDJUMPS; i++) {
- if(fwdjump[i]) {
- err_setup();
- sprintf(buf, "* \'jump\' at $%08X - destination address is external to this source file and "
- "cannot have its aligment validated", fwdjump[i]);
- if(listing > 0) ship_ln(buf);
- if(err_flag) write(err_fd, buf, (LONG)strlen(buf));
- else printf("%s\n", buf);
- }
- }
-
- return(0);
+int fixups(void)
+{
+ unsigned i;
+ char buf[EBUFSIZ];
+
+ // Make undefined symbols GLOBL
+ if (glob_flag)
+ syg_fix();
+
+ resfix(TEXT);
+ resfix(DATA);
+
+ // We need to do a final check of forward 'jump' destination addresses that are external
+ for(i=0; i<MAXFWDJUMPS; i++)
+ {
+ if (fwdjump[i])
+ {
+ err_setup();
+ sprintf(buf, "* \'jump\' at $%08X - destination address is external to this source file and cannot have its aligment validated", fwdjump[i]);
+
+ if (listing > 0)
+ ship_ln(buf);
+
+ if (err_flag)
+ write(err_fd, buf, (LONG)strlen(buf));
+ else
+ printf("%s\n", buf);
+ }
+ }
+
+ return 0;
}
+
//
-// --- Resolve Fixups in a Section -----------------------------------------------------------------
+// Resolve Fixups in a Section
//
-
-int resfix(int sno) {
- SECT *sc; // Section
- CHUNK *ch;
- PTR fup; // Current fixup
- WORD *fuend; // End of last fixup (in this chunk)
- CHUNK *cch; // Cached chunk for target
- WORD w; // Fixup word (type+modes+flags)
- char *locp; // Location to fix (in cached chunk)
- LONG loc; // Location to fixup
- VALUE eval; // Expression value
- WORD eattr; // Expression attrib
- SYM *esym; // External symbol involved in expr
- SYM *sy; // (Temp) pointer to a symbol
- WORD i; // (Temp) word
- WORD tdb; // eattr & TDB
- LONG oaddr;
- int reg2;
- WORD flags;
- unsigned page_jump = 0;
- unsigned address = 0;
- unsigned j; // iterator
- char buf[EBUFSIZ];
-
- sc = §[sno];
- ch = sc->sffix;
-
- if(ch == NULL)
- return(0);
-
- cch = sc->sfcode; // "cache" first chunk
- if(cch == NULL) // Can't fixup a sect with nothing in it
- return(0);
-
- do {
- fup.cp = ch->chptr; // fup -> start of chunk
- fuend = (WORD *)(fup.cp + ch->ch_size); // fuend -> end of chunk
- while(fup.wp < fuend) {
- w = *fup.wp++;
- loc = *fup.lp++;
- cfileno = *fup.wp++;
- curlineno = (int)*fup.wp++;
-
- esym = NULL;
- // Search for chunk containing location to fix up; compute a pointer to the location
- // (in the chunk). Often we will find the fixup is in the "cached" chunk, so the
- // linear-search is seldom executed.
- if(loc < cch->chloc || loc >= (cch->chloc + cch->ch_size)) {
- for(cch = sc->sfcode; cch != NULL; cch = cch->chnext)
- if(loc >= cch->chloc && loc < (cch->chloc + cch->ch_size))
- break;
- if(cch == NULL) {
- interror(7); // Fixup (loc) out of range
+int resfix(int sno)
+{
+ SECT * sc; // Section
+ CHUNK * ch;
+ PTR fup; // Current fixup
+ WORD * fuend; // End of last fixup (in this chunk)
+ CHUNK * cch; // Cached chunk for target
+ WORD w; // Fixup word (type+modes+flags)
+ char * locp; // Location to fix (in cached chunk)
+ LONG loc; // Location to fixup
+ VALUE eval; // Expression value
+ WORD eattr; // Expression attrib
+ SYM * esym; // External symbol involved in expr
+ SYM * sy; // (Temp) pointer to a symbol
+ WORD i; // (Temp) word
+ WORD tdb; // eattr & TDB
+ LONG oaddr;
+ int reg2;
+ WORD flags;
+ unsigned page_jump = 0;
+ unsigned address = 0;
+ unsigned j;
+ char buf[EBUFSIZ];
+
+ sc = §[sno];
+ ch = sc->sffix;
+
+ if (ch == NULL)
+ return 0;
+
+ cch = sc->sfcode; // "cache" first chunk
+
+ if (cch == NULL) // Can't fixup a sect with nothing in it
+ return 0;
+
+ do
+ {
+ fup.cp = ch->chptr; // fup -> start of chunk
+ fuend = (WORD *)(fup.cp + ch->ch_size); // fuend -> end of chunk
+
+ while (fup.wp < fuend)
+ {
+ w = *fup.wp++;
+ loc = *fup.lp++;
+ cfileno = *fup.wp++;
+ curlineno = (int)*fup.wp++;
+
+ esym = NULL;
+
+ // Search for chunk containing location to fix up; compute a pointer to the location
+ // (in the chunk). Often we will find the fixup is in the "cached" chunk, so the
+ // linear-search is seldom executed.
+ if (loc < cch->chloc || loc >= (cch->chloc + cch->ch_size))
+ {
+ for(cch=sc->sfcode; cch!=NULL; cch=cch->chnext)
+ {
+ if (loc >= cch->chloc && loc < (cch->chloc + cch->ch_size))
+ break;
+ }
+
+ if (cch == NULL)
+ {
+ interror(7); // Fixup (loc) out of range
// NOTREACHED
- }
- }
- locp = cch->chptr + (loc - cch->chloc);
-
- eattr = 0;
-
- // Compute expression/symbol value and attribs
- if(w & FU_EXPR) { // Complex expression
- i = *fup.wp++;
- if(evexpr(fup.tk, &eval, &eattr, &esym) != OK) {
- fup.lp += i;
- continue;
- }
- fup.lp += i;
- } else { // Simple symbol
- sy = *fup.sy++;
- eattr = sy->sattr;
- if(eattr & DEFINED)
- eval = sy->svalue;
- else eval = 0;
-
- if((eattr & (GLOBAL|DEFINED)) == GLOBAL)
- esym = sy;
- }
- tdb = (WORD)(eattr & TDB);
- // If the expression is undefined and no external symbol is involved, then it's an error.
- if(!(eattr & DEFINED) && esym == NULL) {
- error(undef_error);
- continue;
- }
-
-
- if(((w & 0x0F00) == FU_MOVEI) && esym)
- esym->sattre |= RISCSYM;
-
- // Do the fixup
- //
- // If a PC-relative fixup is undefined, its value is *not* subtracted from the location
- // (that will happen in the linker when the external reference is resolved).
- //
- // MWC expects PC-relative things to have the LOC subtracted from the value, if the
- // value is external (that is, undefined at this point).
- //
- // PC-relative fixups must be DEFINED and either in the same section (whereupon the
- // subtraction takes place) or ABS (with no subtract).
- if(w & FU_PCREL) {
- if(eattr & DEFINED) {
- if(tdb == sno) eval -= (VALUE)loc;
- else if(tdb) {
- error("PC-relative expr across sections");
- continue;
- }
-
- if(sbra_flag && (w & FU_LBRA) && (eval + 0x80 < 0x100))
- warn("unoptimized short branch");
- } else
- if(obj_format == MWC) eval -= (VALUE)loc;
-
- tdb = 0;
- eattr &= ~TDB;
- }
-
- // Do fixup classes
- switch((int)(w & FUMASK)) {
- // FU_BBRA fixes up a one-byte branch offset.
- case FU_BBRA:
- if(!(eattr & DEFINED)) {
- error("external short branch");
- continue;
- }
- eval -= 2;
- if(eval + 0x80 >= 0x100)
- goto range;
- if(eval == 0) {
- error("illegal bra.s with zero offset");
- continue;
- }
- *++locp = (char)eval;
- break;
- // Fixup one-byte value at locp + 1.
- case FU_WBYTE:
- ++locp;
- // FALLTHROUGH
- // Fixup one-byte forward references
- case FU_BYTE:
- if(!(eattr & DEFINED)) {
- error("external byte reference");
- continue;
- }
- if(tdb) {
- error("non-absolute byte reference");
- continue;
- }
- if((w & FU_PCREL) && eval + 0x80 >= 0x100) goto range;
- if(w & FU_SEXT) {
- if(eval + 0x100 >= 0x200) goto range;
- } else
- if(eval >= 0x100) goto range;
-
- *locp = (char)eval;
- break;
- // Fixup WORD forward references;
- // the word could be unaligned in the section buffer, so we have to be careful.
- case FU_WORD:
- if(((w & 0x0F00) == FU_JR) || ((w & 0x0F00) == FU_MJR)) {
- oaddr = *fup.lp++;
- if(oaddr) {
- reg2 = (signed)((eval - (oaddr + 2)) / 2);// & 0x1F;
- } else {
- reg2 = (signed)((eval - (loc + 2)) / 2);// & 0x1F;
- }
- if((w & 0x0F00) == FU_MJR) {
- // Main code destination alignment checking here for forward declared labels
- address = (oaddr) ? oaddr : loc;
- if(((address >= 0xF03000) && (address < 0xF04000) && (eval < 0xF03000)) ||
- ((eval >= 0xF03000) && (eval < 0xF04000) && (address < 0xF03000)) ) {
- warni("* \'jr\' at $%08X - cannot jump relative between "
- "main memory and local gpu ram", address);
- } else {
- page_jump = (address & 0xFFFFFF00) - (eval & 0xFFFFFF00);
- if(page_jump) {
- // This jump is to a page outside of the current 256 byte page
- if(eval % 4) {
- warni("* \'jr\' at $%08X - destination address not aligned for long page jump, "
- "insert a \'nop\' before the destination address", address);
- }
- } else {
- // This jump is in the current 256 byte page
- if((eval - 2) % 4) {
- warni("* \'jr\' at $%08X - destination address not aligned for short page jump, "
- "insert a \'nop\' before the destination address", address);
- }
- }
- }
- }
- if((reg2 < -16) || (reg2 > 15)) {
- error("relative jump out of range");
- break;
- }
- *locp = (char)(*locp | ((reg2 >> 3) & 0x03));
- locp++;
- *locp = (char)(*locp | ((reg2 & 0x07) << 5));
- break;
- }
- if((w & 0x0F00) == FU_NUM15) {
- if(eval < -16 || eval > 15) {
- error("constant out of range");
- break;
- }
- *locp = (char)(*locp | ((eval >> 3) & 0x03));
- locp++;
- *locp = (char)(*locp | ((eval & 0x07) << 5));
- break;
- }
- if((w & 0x0F00) == FU_NUM31) {
- if(eval < 0 || eval > 31) {
- error("constant out of range");
- break;
- }
- *locp = (char)(*locp | ((eval >> 3) & 0x03));
- locp++;
- *locp = (char)(*locp | ((eval & 0x07) << 5));
- break;
- }
- if((w & 0x0F00) == FU_NUM32) {
- if(eval < 1 || eval > 32) {
- error("constant out of range");
- break;
- }
- if(w & FU_SUB32)
- eval = (32 - eval);
- eval = (eval == 32) ? 0 : eval;
- *locp = (char)(*locp | ((eval >> 3) & 0x03));
- locp++;
- *locp = (char)(*locp | ((eval & 0x07) << 5));
- break;
- }
- if((w & 0x0F00) == FU_REGONE) {
- if(eval < 0 || eval > 31) {
- error("register value out of range");
- break;
- }
- *locp = (char)(*locp | ((eval >> 3) & 0x03));
- locp++;
- *locp = (char)(*locp | ((eval & 0x07) << 5));
- break;
- }
- if((w & 0x0F00) == FU_REGTWO) {
- if(eval < 0 || eval > 31) {
- error("register value out of range");
- break;
- }
- locp++;
- *locp = (char)(*locp | (eval & 0x1F));
- break;
- }
-
- if(!(eattr & DEFINED)) {
- if(w & FU_PCREL)
- w = MPCREL | MWORD;
- else w = MWORD;
- rmark(sno, loc, 0, w, esym);
- } else {
- if(tdb)
- rmark(sno, loc, tdb, MWORD, NULL);
- if(w & FU_SEXT) {
- if(eval + 0x10000 >= 0x20000)
- goto range;
- } else
- if(w & FU_ISBRA) { // Range-check BRA and DBRA
- if(eval + 0x8000 >= 0x10000)
- goto range;
- } else
- if(eval >= 0x10000)
- goto range;
- }
-
- *locp++ = (char)(eval >> 8);
- *locp = (char)eval;
- break;
- // Fixup LONG forward references;
- // the long could be unaligned in the section buffer, so be careful (again).
- case FU_LONG:
- if((w & 0x0F00) == FU_MOVEI) {
- address = loc + 4;
- if(eattr & DEFINED) {
- for(j = 0; j < fwindex; j++) {
- if(fwdjump[j] == address) {
- page_jump = (address & 0xFFFFFF00) - (eval & 0xFFFFFF00);
- if(page_jump) {
- if(eval % 4) {
- err_setup();
- sprintf(buf, "* \'jump\' at $%08X - destination address not aligned for long page jump, "
- "insert a \'nop\' before the destination address", address);
- if(listing > 0) ship_ln(buf);
- if(err_flag) write(err_fd, buf, (LONG)strlen(buf));
- else printf("%s\n", buf);
- }
- } else {
- if(!(eval & 0x0000000F) || ((eval - 2) % 4)) {
- err_setup();
- sprintf(buf, "* \'jump\' at $%08X - destination address not aligned for short page jump, "
- "insert a \'nop\' before the destination address", address);
- if(listing > 0) ship_ln(buf);
- if(err_flag) write(err_fd, buf, (LONG)strlen(buf));
- else printf("%s\n", buf);
- }
- }
- // Clear this jump as it has been checked
- fwdjump[j] = 0;
- j = fwindex;
- }
- }
- }
- eval = ((eval >> 16) & 0x0000FFFF) | ((eval << 16) & 0xFFFF0000);
- flags = (MLONG|MMOVEI);
- } else flags = MLONG;
- if(!(eattr & DEFINED)) {
- rmark(sno, loc, 0, flags, esym);
- }
- else if(tdb) {
- rmark(sno, loc, tdb, flags, NULL);
- }
- *locp++ = (char)(eval >> 24);
- *locp++ = (char)(eval >> 16);
- *locp++ = (char)(eval >> 8);
- *locp = (char)eval;
- break;
- // Fixup a 3-bit "QUICK" reference in bits 9..1
- // (range of 1..8) in a word. Really bits 1..3 in a byte.
- case FU_QUICK:
- if(!(eattr & DEFINED)) {
- error("External quick reference");
- continue;
- }
-
- if(eval < 1 || eval > 8)
- goto range;
- *locp |= (eval & 7) << 1;
- break;
- // Fix up 6502 funny branch
- case FU_6BRA:
- eval -= (loc + 1);
- if(eval + 0x80 >= 0x100)
- goto range;
- *locp = (char)eval;
- break;
- default:
- interror(4); // Bad fixup type
- // NOTREACHED
- }
- continue;
-
- range:
-
- error("expression out of range");
- }
-
- ch = ch->chnext;
- } while(ch != NULL);
-
- return(0);
+ }
+ }
+
+ locp = cch->chptr + (loc - cch->chloc);
+
+ eattr = 0;
+
+ // Compute expression/symbol value and attribs
+ if (w & FU_EXPR)
+ { // Complex expression
+ i = *fup.wp++;
+
+ if (evexpr(fup.tk, &eval, &eattr, &esym) != OK)
+ {
+ fup.lp += i;
+ continue;
+ }
+
+ fup.lp += i;
+ }
+ else
+ { // Simple symbol
+ sy = *fup.sy++;
+ eattr = sy->sattr;
+
+ if (eattr & DEFINED)
+ eval = sy->svalue;
+ else
+ eval = 0;
+
+ if ((eattr & (GLOBAL|DEFINED)) == GLOBAL)
+ esym = sy;
+ }
+
+ tdb = (WORD)(eattr & TDB);
+
+ // If the expression is undefined and no external symbol is
+ // involved, then it's an error.
+ if (!(eattr & DEFINED) && esym == NULL)
+ {
+ error(undef_error);
+ continue;
+ }
+
+ if (((w & 0x0F00) == FU_MOVEI) && esym)
+ esym->sattre |= RISCSYM;
+
+ // Do the fixup
+ //
+ // If a PC-relative fixup is undefined, its value is *not* subtracted from the location
+ // (that will happen in the linker when the external reference is resolved).
+ //
+ // MWC expects PC-relative things to have the LOC subtracted from the value, if the
+ // value is external (that is, undefined at this point).
+ //
+ // PC-relative fixups must be DEFINED and either in the same section (whereupon the
+ // subtraction takes place) or ABS (with no subtract).
+ if (w & FU_PCREL)
+ {
+ if (eattr & DEFINED)
+ {
+ if (tdb == sno)
+ eval -= (VALUE)loc;
+ else if (tdb)
+ {
+ error("PC-relative expr across sections");
+ continue;
+ }
+
+ if (sbra_flag && (w & FU_LBRA) && (eval + 0x80 < 0x100))
+ warn("unoptimized short branch");
+ }
+ else if (obj_format == MWC)
+ eval -= (VALUE)loc;
+
+ tdb = 0;
+ eattr &= ~TDB;
+ }
+
+ // Do fixup classes
+ switch ((int)(w & FUMASK))
+ {
+ // FU_BBRA fixes up a one-byte branch offset.
+ case FU_BBRA:
+ if (!(eattr & DEFINED))
+ {
+ error("external short branch");
+ continue;
+ }
+
+ eval -= 2;
+
+ if (eval + 0x80 >= 0x100)
+ goto range;
+
+ if (eval == 0)
+ {
+ error("illegal bra.s with zero offset");
+ continue;
+ }
+
+ *++locp = (char)eval;
+ break;
+ // Fixup one-byte value at locp + 1.
+ case FU_WBYTE:
+ ++locp;
+ // FALLTHROUGH
+ // Fixup one-byte forward references
+ case FU_BYTE:
+ if (!(eattr & DEFINED))
+ {
+ error("external byte reference");
+ continue;
+ }
+
+ if (tdb)
+ {
+ error("non-absolute byte reference");
+ continue;
+ }
+
+ if ((w & FU_PCREL) && eval + 0x80 >= 0x100)
+ goto range;
+
+ if (w & FU_SEXT)
+ {
+ if (eval + 0x100 >= 0x200)
+ goto range;
+ }
+ else if (eval >= 0x100)
+ goto range;
+
+ *locp = (char)eval;
+ break;
+ // Fixup WORD forward references;
+ // the word could be unaligned in the section buffer, so we have to be careful.
+ case FU_WORD:
+ if (((w & 0x0F00) == FU_JR) || ((w & 0x0F00) == FU_MJR))
+ {
+ oaddr = *fup.lp++;
+
+ if (oaddr)
+ {
+ reg2 = (signed)((eval - (oaddr + 2)) / 2);// & 0x1F;
+ }
+ else
+ {
+ reg2 = (signed)((eval - (loc + 2)) / 2);// & 0x1F;
+ }
+
+ if ((w & 0x0F00) == FU_MJR)
+ {
+ // Main code destination alignment checking here for forward declared labels
+ address = (oaddr) ? oaddr : loc;
+
+ if (((address >= 0xF03000) && (address < 0xF04000)
+ && (eval < 0xF03000)) || ((eval >= 0xF03000)
+ && (eval < 0xF04000) && (address < 0xF03000)))
+ {
+ warni("* \'jr\' at $%08X - cannot jump relative between "
+ "main memory and local gpu ram", address);
+ }
+ else
+ {
+ page_jump = (address & 0xFFFFFF00) - (eval & 0xFFFFFF00);
+
+ if (page_jump)
+ {
+ // This jump is to a page outside of the current 256 byte page
+ if (eval % 4)
+ {
+ warni("* \'jr\' at $%08X - destination address not aligned for long page jump, insert a \'nop\' before the destination address", address);
+ }
+ }
+ else
+ {
+ // This jump is in the current 256 byte page
+ if ((eval - 2) % 4)
+ {
+ warni("* \'jr\' at $%08X - destination address not aligned for short page jump, insert a \'nop\' before the destination address", address);
+ }
+ }
+ }
+ }
+
+ if ((reg2 < -16) || (reg2 > 15))
+ {
+ error("relative jump out of range");
+ break;
+ }
+
+ *locp = (char)(*locp | ((reg2 >> 3) & 0x03));
+ locp++;
+ *locp = (char)(*locp | ((reg2 & 0x07) << 5));
+ break;
+ }
+
+ if ((w & 0x0F00) == FU_NUM15)
+ {
+ if (eval < -16 || eval > 15)
+ {
+ error("constant out of range");
+ break;
+ }
+
+ *locp = (char)(*locp | ((eval >> 3) & 0x03));
+ locp++;
+ *locp = (char)(*locp | ((eval & 0x07) << 5));
+ break;
+ }
+
+ if ((w & 0x0F00) == FU_NUM31)
+ {
+ if (eval < 0 || eval > 31)
+ {
+ error("constant out of range");
+ break;
+ }
+
+ *locp = (char)(*locp | ((eval >> 3) & 0x03));
+ locp++;
+ *locp = (char)(*locp | ((eval & 0x07) << 5));
+ break;
+ }
+
+ if ((w & 0x0F00) == FU_NUM32)
+ {
+ if (eval < 1 || eval > 32)
+ {
+ error("constant out of range");
+ break;
+ }
+
+ if (w & FU_SUB32)
+ eval = (32 - eval);
+
+ eval = (eval == 32) ? 0 : eval;
+ *locp = (char)(*locp | ((eval >> 3) & 0x03));
+ locp++;
+ *locp = (char)(*locp | ((eval & 0x07) << 5));
+ break;
+ }
+
+ if ((w & 0x0F00) == FU_REGONE)
+ {
+ if (eval < 0 || eval > 31)
+ {
+ error("register value out of range");
+ break;
+ }
+
+ *locp = (char)(*locp | ((eval >> 3) & 0x03));
+ locp++;
+ *locp = (char)(*locp | ((eval & 0x07) << 5));
+ break;
+ }
+
+ if ((w & 0x0F00) == FU_REGTWO)
+ {
+ if (eval < 0 || eval > 31)
+ {
+ error("register value out of range");
+ break;
+ }
+
+ locp++;
+ *locp = (char)(*locp | (eval & 0x1F));
+ break;
+ }
+
+ if (!(eattr & DEFINED))
+ {
+ if (w & FU_PCREL)
+ w = MPCREL | MWORD;
+ else
+ w = MWORD;
+
+ rmark(sno, loc, 0, w, esym);
+ }
+ else
+ {
+ if (tdb)
+ rmark(sno, loc, tdb, MWORD, NULL);
+
+ if (w & FU_SEXT)
+ {
+ if (eval + 0x10000 >= 0x20000)
+ goto range;
+ }
+ else
+ {
+ // Range-check BRA and DBRA
+ if (w & FU_ISBRA)
+ {
+ if (eval + 0x8000 >= 0x10000)
+ goto range;
+ }
+ else if (eval >= 0x10000)
+ goto range;
+ }
+ }
+
+ *locp++ = (char)(eval >> 8);
+ *locp = (char)eval;
+ break;
+ // Fixup LONG forward references;
+ // the long could be unaligned in the section buffer, so be careful (again).
+ case FU_LONG:
+ if ((w & 0x0F00) == FU_MOVEI)
+ {
+ address = loc + 4;
+
+ if (eattr & DEFINED)
+ {
+ for(j=0; j<fwindex; j++)
+ {
+ if (fwdjump[j] == address)
+ {
+ page_jump = (address & 0xFFFFFF00) - (eval & 0xFFFFFF00);
+
+ if (page_jump)
+ {
+ if (eval % 4)
+ {
+ err_setup();
+ sprintf(buf, "* \'jump\' at $%08X - destination address not aligned for long page jump, insert a \'nop\' before the destination address", address);
+
+ if (listing > 0)
+ ship_ln(buf);
+
+ if (err_flag)
+ write(err_fd, buf, (LONG)strlen(buf));
+ else
+ printf("%s\n", buf);
+ }
+ }
+ else
+ {
+ if (!(eval & 0x0000000F) || ((eval - 2) % 4))
+ {
+ err_setup();
+ sprintf(buf, "* \'jump\' at $%08X - destination address not aligned for short page jump, insert a \'nop\' before the destination address", address);
+
+ if (listing > 0)
+ ship_ln(buf);
+
+ if (err_flag)
+ write(err_fd, buf, (LONG)strlen(buf));
+ else
+ printf("%s\n", buf);
+ }
+ }
+
+ // Clear this jump as it has been checked
+ fwdjump[j] = 0;
+ j = fwindex;
+ }
+ }
+ }
+
+ eval = ((eval >> 16) & 0x0000FFFF) | ((eval << 16) & 0xFFFF0000);
+ flags = (MLONG|MMOVEI);
+ }
+ else
+ flags = MLONG;
+
+ if (!(eattr & DEFINED))
+ {
+ rmark(sno, loc, 0, flags, esym);
+ }
+ else if (tdb)
+ {
+ rmark(sno, loc, tdb, flags, NULL);
+ }
+
+ *locp++ = (char)(eval >> 24);
+ *locp++ = (char)(eval >> 16);
+ *locp++ = (char)(eval >> 8);
+ *locp = (char)eval;
+ break;
+ // Fixup a 3-bit "QUICK" reference in bits 9..1
+ // (range of 1..8) in a word. Really bits 1..3 in a byte.
+ case FU_QUICK:
+ if (!(eattr & DEFINED))
+ {
+ error("External quick reference");
+ continue;
+ }
+
+ if (eval < 1 || eval > 8)
+ goto range;
+
+ *locp |= (eval & 7) << 1;
+ break;
+ // Fix up 6502 funny branch
+ case FU_6BRA:
+ eval -= (loc + 1);
+
+ if (eval + 0x80 >= 0x100)
+ goto range;
+
+ *locp = (char)eval;
+ break;
+ default:
+ interror(4); // Bad fixup type
+ // NOTREACHED
+ }
+ continue;
+range:
+ error("expression out of range");
+ }
+
+ ch = ch->chnext;
+ }
+ while (ch != NULL);
+
+ return 0;
}
// Chunks are used to hold generated code and fixup records
#define CHUNK struct _chunk
CHUNK {
- CHUNK *chnext; // Next, previous chunks in section
- CHUNK *chprev;
+ CHUNK * chnext; // Next, previous chunks in section
+ CHUNK * chprev;
LONG chloc; // Base addr of this chunk
LONG challoc; // #bytes allocated for chunk
LONG ch_size; // #bytes chunk actually uses
- char *chptr; // Data for this chunk
+ char * chptr; // Data for this chunk
};
// Section descriptor
SECT {
WORD scattr; // Section attributes
LONG sloc; // Current loc-in / size-of section
- CHUNK *sfcode; // First chunk in section
- CHUNK *scode; // Last chunk in section
- CHUNK *sffix; // First fixup chunk
- CHUNK *sfix; // Last fixup chunk
+ CHUNK * sfcode; // First chunk in section
+ CHUNK * scode; // Last chunk in section
+ CHUNK * sffix; // First fixup chunk
+ CHUNK * sfix; // Last fixup chunk
};
// A mark is of the form:
// .L [symbol] symbol involved in external reference
#define MCHUNK struct _mchunk
MCHUNK {
- MCHUNK *mcnext; // Next mark chunk
+ MCHUNK * mcnext; // Next mark chunk
PTR mcptr; // Vector of marks
LONG mcalloc; // #marks allocted to mark block
LONG mcused; // #marks used in block
// Globals, external etc
extern LONG sloc;
extern WORD scattr;
-extern char *chptr;
+extern char * chptr;
extern LONG ch_size;
extern int cursect;
extern SECT sect[];
extern LONG challoc;
-extern CHUNK *scode;
+extern CHUNK * scode;
// Prototypes
void init_sect(void);
#include "procln.h"
#include "error.h"
-static SYM *sytab[NBUCKETS]; // User symbol-table header
+static SYM * sytab[NBUCKETS]; // User symbol-table header
int curenv; // Current enviroment number
-SYM *sorder; // * -> Symbols, in order of reference
-SYM *sordtail; // * -> Last symbol in sorder list
-SYM *sdecl; // * -> Symbols, in order of declaration
-SYM *sdecltail; // * -> Last symbol in sdecl list
+SYM * sorder; // * -> Symbols, in order of reference
+SYM * sordtail; // * -> Last symbol in sorder list
+SYM * sdecl; // * -> Symbols, in order of declaration
+SYM * sdecltail; // * -> Last symbol in sdecl list
// Tags for marking symbol spaces
// a = absolute
'a', 't', 'd', '!', 'b', SPACE, SPACE, SPACE
};
+
//
-// --- Initialize Symbol Table ---------------------------------------------------------------------
+// Initialize Symbol Table
//
-
-void init_sym(void) {
- int i; // Iterator
-
- for(i = 0; i < NBUCKETS; ++i) // Initialise symbol hash table
- sytab[i] = NULL;
-
- curenv = 1; // Init local symbol enviroment
- sorder = NULL; // Init symbol-reference list
- sordtail = NULL;
- sdecl = NULL; // Init symbol-decl list
- sdecltail = NULL;
+void init_sym(void)
+{
+ int i; // Iterator
+
+ for(i=0; i<NBUCKETS; ++i) // Initialise symbol hash table
+ sytab[i] = NULL;
+
+ curenv = 1; // Init local symbol enviroment
+ sorder = NULL; // Init symbol-reference list
+ sordtail = NULL;
+ sdecl = NULL; // Init symbol-decl list
+ sdecltail = NULL;
}
+
//
-// --- Allocate and Return Pointer to a Copy of a String -------------------------------------------
+// Allocate and Return Pointer to a Copy of a String
//
+char * nstring(char * str)
+{
+ long i;
+ char * s, * d;
-char *nstring(char *str) {
- long i;
- char *s, *d;
-
- for(i = 0; str[i]; ++i)
- ;
- s = d = amem(i + 1);
- while(*str)
- *d++ = *str++;
- *d++ = '\0';
-
- return(s);
+ for(i=0; str[i]; ++i)
+ ;
+
+ s = d = amem(i + 1);
+
+ while (*str)
+ *d++ = *str++;
+
+ *d++ = '\0';
+
+ return s;
}
+
//
-// --- Hash the Print Name and Enviroment Number ---------------------------------------------------
+// Hash the Print Name and Enviroment Number
//
-int syhash(char *name, int envno) {
- int sum, k; // Hash calculation
-
- k = 0;
- for(sum = envno; *name; ++name) {
- if(k++ == 1)
- sum += *name << 2;
- else
- sum += *name;
- }
-
- return(sum & (NBUCKETS - 1));
+int syhash(char * name, int envno)
+{
+ int sum, k; // Hash calculation
+ k = 0;
+
+ for(sum=envno; *name; ++name)
+ {
+ if (k++ == 1)
+ sum += *name << 2;
+ else
+ sum += *name;
+ }
+
+ return sum & (NBUCKETS - 1);
}
+
//
-// --- Make a new symbol of type `type' in enviroment `envno' --------------------------------------
+// Make a new symbol of type `type' in enviroment `envno'
//
+SYM * newsym(char * name, int type, int envno)
+{
+ int hash; // Symbol hash value
+ SYM * sy; // Pointer to symbol
+
+ // Allocate the symbol
+ sy = (SYM *)amem((long)(sizeof(SYM)));
+
+ if (sy == NULL)
+ {
+ printf("SYMALLOC ERROR (%s)\n", name);
+ return NULL;
+ }
+
+ sy->sname = nstring(name);
+
+ // Fill-in the symbol
+ sy->stype = (BYTE)type;
+ sy->senv = (WORD)envno;
+ sy->sattr = 0;
+
+ if (rgpu || rdsp)
+ sy->sattre = RISCSYM;
+ else
+ sy->sattre = 0;
+
+ sy->svalue = 0;
+
+ // Install symbol in symbol table
+ hash = syhash(name, envno);
+ sy->snext = sytab[hash];
+ sytab[hash] = sy;
-SYM *newsym(char *name, int type, int envno) {
- int hash; // Symbol hash value
- SYM *sy; // Pointer to symbol
-
-
- // Allocate the symbol
- sy = (SYM *)amem((long)(sizeof(SYM)));
- if(sy == NULL) {
- printf("SYMALLOC ERROR (%s)\n", name);
- return(NULL);
- }
-
- sy->sname = nstring(name);
-
- // Fill-in the symbol
- sy->stype = (BYTE)type;
- sy->senv = (WORD)envno;
- sy->sattr = 0;
- if(rgpu || rdsp) sy->sattre = RISCSYM;
- else sy->sattre = 0;
- sy->svalue = 0;
-
- // Install symbol in symbol table
- hash = syhash(name, envno);
- sy->snext = sytab[hash];
- sytab[hash] = sy;
-
- // Append symbol to symbol-order list
- if(sorder == NULL)
- sorder = sy; // Add first symbol
- else
- sordtail->sorder = sy; // Or append to tail of list
-
- sy->sorder = NULL;
- sordtail = sy;
-
- return(sy); // Return pointer to symbol
+ // Append symbol to symbol-order list
+ if (sorder == NULL)
+ sorder = sy; // Add first symbol
+ else
+ sordtail->sorder = sy; // Or append to tail of list
+
+ sy->sorder = NULL;
+ sordtail = sy;
+
+ return sy; // Return pointer to symbol
}
+
//
-// --- Lookup the symbol `name', of the specified type, with the specified enviroment level --------
+// Lookup the symbol `name', of the specified type, with the specified
+// enviroment level
//
-
-SYM *lookup(char *name, int type, int envno) {
- SYM *sy; // Symbol record pointer
- int k, sum; // Hash bucket calculation
- char *s; // String pointer
-
- // Pick a hash-bucket (SAME algorithm as syhash())
- k = 0;
- s = name;
- for(sum = envno; *s;) {
- if(k++ == 1)
- sum += *s++ << 2;
- else sum += *s++;
- }
-
- sy = sytab[sum & (NBUCKETS-1)];
-
- // Do linear-search for symbol in bucket
- while(sy != NULL) {
- if(sy->stype == type && // Type, envno and name must match
- sy->senv == envno &&
- *name == *sy->sname && // Fast check for first character
+SYM * lookup(char * name, int type, int envno)
+{
+ SYM * sy; // Symbol record pointer
+ int k, sum; // Hash bucket calculation
+ char * s; // String pointer
+
+ // Pick a hash-bucket (SAME algorithm as syhash())
+ k = 0;
+ s = name;
+
+ for(sum=envno; *s;)
+ {
+ if (k++ == 1)
+ sum += *s++ << 2;
+ else
+ sum += *s++;
+ }
+
+ sy = sytab[sum & (NBUCKETS-1)];
+
+ // Do linear-search for symbol in bucket
+ while (sy != NULL)
+ {
+ if (sy->stype == type && // Type, envno and name must match
+ sy->senv == envno &&
+ *name == *sy->sname && // Fast check for first character
!strcmp(name, sy->sname))
- break;
- else sy = sy->snext;
- }
+ break;
+ else
+ sy = sy->snext;
+ }
- return(sy); // Return NULL or matching symbol
+ return sy; // Return NULL or matching symbol
}
+
//
-// --- Put symbol on "order-of-declaration" list of symbols ----------------------------------------
+// Put symbol on "order-of-declaration" list of symbols
//
+void sym_decl(SYM * sym)
+{
+ if (sym->sattr & SDECLLIST)
+ return; // Already on list
-void sym_decl(SYM *sym) {
- if(sym->sattr & SDECLLIST) return; // Already on list
- sym->sattr |= SDECLLIST; // Mark "already on list"
+ sym->sattr |= SDECLLIST; // Mark "already on list"
- if(sdecl == NULL)
- sdecl = sym; // First on decl-list
- else
- sdecltail->sdecl = sym; // Add to end of list
+ if (sdecl == NULL)
+ sdecl = sym; // First on decl-list
+ else
+ sdecltail->sdecl = sym; // Add to end of list
- sym->sdecl = NULL; // Fix up list's tail
- sdecltail = sym;
+ sym->sdecl = NULL; // Fix up list's tail
+ sdecltail = sym;
}
+
//
-// --- Make all referenced, undefined symbols global -----------------------------------------------
+// Make all referenced, undefined symbols global
//
-
-int syg_fix(void) {
- SYM *sy;
-
- DEBUG printf("~syg_fix()\n");
-
- // Scan through all symbols;
- // If a symbol is REFERENCED but not DEFINED, then make it global.
- for(sy = sorder; sy != NULL; sy = sy->sorder)
- if(sy->stype == LABEL && sy->senv == 0 &&
- ((sy->sattr & (REFERENCED|DEFINED)) == REFERENCED))
- sy->sattr |= GLOBAL;
-
- return(0);
+int syg_fix(void)
+{
+ SYM * sy;
+
+ DEBUG printf("~syg_fix()\n");
+
+ // Scan through all symbols;
+ // If a symbol is REFERENCED but not DEFINED, then make it global.
+ for(sy = sorder; sy != NULL; sy = sy->sorder)
+ {
+ if (sy->stype == LABEL && sy->senv == 0
+ && ((sy->sattr & (REFERENCED|DEFINED)) == REFERENCED))
+ sy->sattr |= GLOBAL;
+ }
+
+ return 0;
}
+
//
-// --- Convert string to uppercase -----------------------------------------------------------------
+// Convert string to uppercase
//
-
-int uc_string(char *s) {
- for(; *s; ++s)
- if(*s >= 'a' && *s <= 'z')
- *s -= 32;
- return(0);
+int uc_string(char * s)
+{
+ for(; *s; ++s)
+ {
+ if (*s >= 'a' && *s <= 'z')
+ *s -= 32;
+ }
+
+ return 0;
}
+
//
-// -------------------------------------------------------------------------------------------------
-// Assign numbers to symbols that are to be exported or imported. The symbol number is put in
-// `.senv'. Return the number of symbols that will be in the symbol table.
-// -------------------------------------------------------------------------------------------------
+// Assign numbers to symbols that are to be exported or imported. The symbol
+// number is put in `.senv'. Return the number of symbols that will be in the
+// symbol table.
//
-
-int sy_assign(char *buf, char *(*constr)()) {
- SYM *sy;
- int scount;
- //int i;
-
- scount = 0;
-
- if(buf == NULL)
- // Append all symbols not appearing on the .sdecl list to the end of the .sdecl list
- for(sy = sorder; sy != NULL; sy = sy->sorder) {
-
- // Essentially the same as 'sym_decl()' above:
- if(sy->sattr & SDECLLIST) continue; // Already on list
- sy->sattr |= SDECLLIST; // Mark "on the list"
-
- if(sdecl == NULL) sdecl = sy; // First on decl-list
- else sdecltail->sdecl = sy; // Add to end of list
-
- sy->sdecl = NULL; // Fix up list's tail
- sdecltail = sy;
- }
-
- // Run through all symbols (now on the .sdecl list) and assign numbers to them. We also pick
- // which symbols should be global or not here.
- for(sy = sdecl; sy != NULL; sy = sy->sdecl) {
-
- if(sy->sattre & UNDEF_EQUR) continue; // Don't want undefined on our list
- if(sy->sattre & UNDEF_CC) continue;
-
- // Export or import external references, and export COMMON blocks.
- if((sy->stype == LABEL) &&
- ((sy->sattr & (GLOBAL|DEFINED)) == (GLOBAL|DEFINED) ||
- (sy->sattr & (GLOBAL|REFERENCED)) == (GLOBAL|REFERENCED)) ||
- (sy->sattr & COMMON)) {
- sy->senv = (WORD)scount++;
- if(buf != NULL) buf = (*constr)(buf, sy, 1);
- } else
- // Export vanilla labels (but don't make them global). An exception is made for equates,
- // which are not exported unless they are referenced.
- if(sy->stype == LABEL && lsym_flag &&
- (sy->sattr & (DEFINED|REFERENCED)) != 0 &&
- (!as68_flag || *sy->sname != 'L') ) {
- sy->senv = (WORD)scount++;
- if(buf != NULL) buf = (*constr)(buf, sy, 0);
- }
- }
-
- return(scount);
+int sy_assign(char * buf, char *(*constr)())
+{
+ SYM * sy;
+ int scount;
+ //int i;
+
+ scount = 0;
+
+ if (buf == NULL)
+ {
+ // Append all symbols not appearing on the .sdecl list to the end of
+ // the .sdecl list
+ for(sy=sorder; sy!=NULL; sy=sy->sorder)
+ {
+ // Essentially the same as 'sym_decl()' above:
+ if (sy->sattr & SDECLLIST)
+ continue; // Already on list
+
+ sy->sattr |= SDECLLIST; // Mark "on the list"
+
+ if (sdecl == NULL)
+ sdecl = sy; // First on decl-list
+ else
+ sdecltail->sdecl = sy; // Add to end of list
+
+ sy->sdecl = NULL; // Fix up list's tail
+ sdecltail = sy;
+ }
+ }
+
+ // Run through all symbols (now on the .sdecl list) and assign numbers to
+ // them. We also pick which symbols should be global or not here.
+ for(sy=sdecl; sy!=NULL; sy=sy->sdecl)
+ {
+ if (sy->sattre & UNDEF_EQUR)
+ continue; // Don't want undefined on our list
+
+ if (sy->sattre & UNDEF_CC)
+ continue;
+
+ // Export or import external references, and export COMMON blocks.
+ if ((sy->stype == LABEL)
+ && ((sy->sattr & (GLOBAL|DEFINED)) == (GLOBAL|DEFINED)
+ || (sy->sattr & (GLOBAL|REFERENCED)) == (GLOBAL|REFERENCED))
+ || (sy->sattr & COMMON))
+ {
+ sy->senv = (WORD)scount++;
+
+ if (buf != NULL)
+ buf = (*constr)(buf, sy, 1);
+ }
+ // Export vanilla labels (but don't make them global). An exception is
+ // made for equates, which are not exported unless they are referenced.
+ else if (sy->stype == LABEL && lsym_flag
+ && (sy->sattr & (DEFINED|REFERENCED)) != 0
+ && (!as68_flag || *sy->sname != 'L'))
+ {
+ sy->senv = (WORD)scount++;
+ if (buf != NULL) buf = (*constr)(buf, sy, 0);
+ }
+ }
+
+ return scount;
}
+
//
-// --- Generate symbol table for listing file ------------------------------------------------------
+// Generate symbol table for listing file
//
-
-int symtable(void) {
- int i;
- int j;
- SYM *q = NULL;
- SYM *p;
- SYM *r;
- SYM *k;
- SYM **sy;
- SYM *colptr[4];
- char ln[150];
- char ln1[150];
- char ln2[20];
- char c, c1;
- WORD w;
- int ww;
- int colhei;
- extern int pagelen;
-
- colhei = pagelen - 5;
-
- // Allocate storage for list headers and partition all labels.
- // Throw away macros and macro arguments.
- sy = (SYM **)amem((LONG)(128 * sizeof(LONG)));
- for(i = 0; i < 128; ++i) sy[i] = NULL;
-
- for(i = 0; i < NBUCKETS; ++i)
- for(p = sytab[i]; p != NULL; p = k) {
- k = p->snext;
- j = *p->sname;
- r = NULL;
- if(p->stype != LABEL) continue; // Ignore non-labels
- if(p->sattre & UNDEF_EQUR) continue;
-
- for(q = sy[j]; q != NULL; q = q->snext)
- if(strcmp(p->sname, q->sname) < 0)
- break;
- else r = q;
-
- if(r == NULL) { // Insert at front of list
- p->snext = sy[j];
- sy[j] = p;
- } else { // Insert in middle or append to list
- p->snext = r->snext;
- r->snext = p;
- }
- }
-
- // Link all symbols onto one list again
- p = NULL;
- for(i = 0; i < 128; ++i)
- if((r = sy[i]) != NULL) {
- if(p == NULL)
- q = r;
- else q->snext = r;
-
- while(q->snext != NULL)
- q = q->snext;
-
- if(p == NULL)
- p = r;
- }
-
- eject();
- strcpy(subttl, "Symbol Table");
-
- while(p != NULL) {
- for (i = 0; i < 4; ++i) {
- colptr[i] = p;
- for(j = 0; j < colhei; ++j)
- if(p == NULL)
- break;
- else p = p->snext;
- }
-
- for(i = 0; i < colhei; ++i) {
- *ln = EOS;
- if(colptr[0] == NULL)
- break;
-
- for(j = 0; j < 4; ++j) {
- if((q = colptr[j]) == NULL)
- break;
- colptr[j] = q->snext;
- w = q->sattr;
- ww = q->sattre;
- // Pick a tag:
- // c common
- // x external reference
- // g global (export)
- // space nothing special
- c1 = SPACE;
- c = SPACE;
-
- if(w & COMMON) c = 'c';
- else if((w & (DEFINED|GLOBAL)) == GLOBAL) c = 'x';
- else if(w & GLOBAL) c = 'g';
-
- c1 = tdb_text[w & TDB];
- if(c == 'x') strcpy(ln2, "external");
- else {
- sprintf(ln2, "%08ux", q->svalue);
- uc_string(ln2);
- }
-
- sprintf(ln1, " %16s %s %c%c%c", q->sname, ln2, (ww & EQUATEDREG) ? 'e' : SPACE, c1, c);
-
- strcat(ln, ln1);
- }
- ship_ln(ln);
- }
- eject();
- }
-
- return(0);
+int symtable(void)
+{
+ int i;
+ int j;
+ SYM * q = NULL;
+ SYM * p;
+ SYM * r;
+ SYM * k;
+ SYM ** sy;
+ SYM * colptr[4];
+ char ln[150];
+ char ln1[150];
+ char ln2[20];
+ char c, c1;
+ WORD w;
+ int ww;
+ int colhei;
+ extern int pagelen;
+
+ colhei = pagelen - 5;
+
+ // Allocate storage for list headers and partition all labels.
+ // Throw away macros and macro arguments.
+ sy = (SYM **)amem((LONG)(128 * sizeof(LONG)));
+
+ for(i=0; i<128; ++i)
+ sy[i] = NULL;
+
+ for(i=0; i<NBUCKETS; ++i)
+ {
+ for(p=sytab[i]; p!=NULL; p=k)
+ {
+ k = p->snext;
+ j = *p->sname;
+ r = NULL;
+
+ if (p->stype != LABEL)
+ continue; // Ignore non-labels
+
+ if (p->sattre & UNDEF_EQUR)
+ continue;
+
+ for(q=sy[j]; q!=NULL; q=q->snext)
+ {
+ if (strcmp(p->sname, q->sname) < 0)
+ break;
+ else
+ r = q;
+ }
+
+ if (r == NULL)
+ { // Insert at front of list
+ p->snext = sy[j];
+ sy[j] = p;
+ }
+ else
+ { // Insert in middle or append to list
+ p->snext = r->snext;
+ r->snext = p;
+ }
+ }
+ }
+
+ // Link all symbols onto one list again
+ p = NULL;
+
+ for(i=0; i<128; ++i)
+ {
+ if ((r = sy[i]) != NULL)
+ {
+ if (p == NULL)
+ q = r;
+ else
+ q->snext = r;
+
+ while (q->snext != NULL)
+ q = q->snext;
+
+ if (p == NULL)
+ p = r;
+ }
+ }
+
+ eject();
+ strcpy(subttl, "Symbol Table");
+
+ while (p != NULL)
+ {
+ for(i=0; i<4; ++i)
+ {
+ colptr[i] = p;
+
+ for(j=0; j<colhei; ++j)
+ {
+ if (p == NULL)
+ break;
+ else
+ p = p->snext;
+ }
+ }
+
+ for(i=0; i<colhei; ++i)
+ {
+ *ln = EOS;
+
+ if (colptr[0] == NULL)
+ break;
+
+ for(j=0; j<4; ++j)
+ {
+ if ((q = colptr[j]) == NULL)
+ break;
+
+ colptr[j] = q->snext;
+ w = q->sattr;
+ ww = q->sattre;
+ // Pick a tag:
+ // c common
+ // x external reference
+ // g global (export)
+ // space nothing special
+ c1 = SPACE;
+ c = SPACE;
+
+ if (w & COMMON)
+ c = 'c';
+ else if ((w & (DEFINED|GLOBAL)) == GLOBAL)
+ c = 'x';
+ else if (w & GLOBAL)
+ c = 'g';
+
+ c1 = tdb_text[w & TDB];
+
+ if (c == 'x')
+ strcpy(ln2, "external");
+ else
+ {
+ sprintf(ln2, "%08ux", q->svalue);
+ uc_string(ln2);
+ }
+
+ sprintf(ln1, " %16s %s %c%c%c", q->sname, ln2, (ww & EQUATEDREG) ? 'e' : SPACE, c1, c);
+ strcat(ln, ln1);
+ }
+
+ ship_ln(ln);
+ }
+
+ eject();
+ }
+
+ return 0;
}
#include "rmac.h"
// Macros
-#define NBUCKETS 256 // Number of hash buckets (power of 2)
+#define NBUCKETS 256 // Number of hash buckets (power of 2)
// Globals, externals etc
extern int curenv;
{
char * s;
char * d = NULL;
- char * dst; // Next dest slot
- char * edst; // End+1 of dest buffer
+ char * dst; // Next dest slot
+ char * edst; // End+1 of dest buffer
int i;
- int questmark; // \? for testing argument existence
+ int questmark; // \? for testing argument existence
TOKEN * tk;
- char mname[128]; // Assume max size of a formal arg name
+ char mname[128]; // Assume max size of a formal arg name
int macnum;
SYM * arg;
IMACRO * imacro;
- char numbuf[20]; // Buffer for text of CONSTs
+ char numbuf[20]; // Buffer for text of CONSTs
imacro = cur_inobj->inobj.imacro;
macnum = (int)(imacro->im_macro->sattr);
//#include "risca.h"
// Include Files and Macros
-#define SRC_IFILE 0 // Input source is IFILE
-#define SRC_IMACRO 1 // Input source is IMACRO
-#define SRC_IREPT 2 // Input source is IREPT
+#define SRC_IFILE 0 // Input source is IFILE
+#define SRC_IMACRO 1 // Input source is IMACRO
+#define SRC_IREPT 2 // Input source is IREPT
// Macros
#define INOBJ struct _inobj
#define IFENT struct _ifent
// Tunable definitions
-#define LNSIZ 256 // Maximum size of a line of text
-#define TOKBUFSIZE 400 // Size of token-line buffer
-#define QUANTUM 4096L // #bytes to eat at a time from a file
-#define LNBUFSIZ (QUANTUM*2) // Size of file's buffer
-#define KWSIZE 7 // Maximum size of keyword in kwtab.h
+#define LNSIZ 256 // Maximum size of a line of text
+#define TOKBUFSIZE 400 // Size of token-line buffer
+#define QUANTUM 4096L // #bytes to eat at a time from a file
+#define LNBUFSIZ (QUANTUM*2) // Size of file's buffer
+#define KWSIZE 7 // Maximum size of keyword in kwtab.h
// (Normally) non-printable tokens
-#define COLON ':' // : (grumble: GNUmacs hates ':')
-#define CONST 'a' // CONST <value>
-#define ACONST 'A' // ACONST <value> <attrib>
-#define STRING 'b' // STRING <address>
-#define SYMBOL 'c' // SYMBOL <address>
-#define EOL 'e' // End of line
-#define TKEOF 'f' // End of file (or macro)
-#define DEQUALS 'g' // ==
-#define SET 149 // Set
-#define REG 'R' // Reg
-#define DCOLON 'h' // ::
-#define GE 'i' // >=
-#define LE 'j' // <=
-#define NE 'k' // <> or !=
-#define SHR 'l' // >>
-#define SHL 'm' // <<
-#define UNMINUS 'n' // Unary '-'
-#define DOTB 'B' // .b or .B or .s or .S
-#define DOTW 'W' // .w or .W
-#define DOTL 'L' // .l or .L
-#define DOTI 'I' // .l or .L
-#define ENDEXPR 'E' // End of expression
+#define COLON ':' // : (grumble: GNUmacs hates ':')
+#define CONST 'a' // CONST <value>
+#define ACONST 'A' // ACONST <value> <attrib>
+#define STRING 'b' // STRING <address>
+#define SYMBOL 'c' // SYMBOL <address>
+#define EOL 'e' // End of line
+#define TKEOF 'f' // End of file (or macro)
+#define DEQUALS 'g' // ==
+#define SET 149 // Set
+#define REG 'R' // Reg
+#define DCOLON 'h' // ::
+#define GE 'i' // >=
+#define LE 'j' // <=
+#define NE 'k' // <> or !=
+#define SHR 'l' // >>
+#define SHL 'm' // <<
+#define UNMINUS 'n' // Unary '-'
+#define DOTB 'B' // .b or .B or .s or .S
+#define DOTW 'W' // .w or .W
+#define DOTL 'L' // .l or .L
+#define DOTI 'I' // .l or .L
+#define ENDEXPR 'E' // End of expression
// ^^ operators
-#define CR_DEFINED 'p' // ^^defined - is symbol defined?
-#define CR_REFERENCED 'q' // ^^referenced - was symbol referenced?
-#define CR_STREQ 'v' // ^^streq - compare two strings
-#define CR_MACDEF 'w' // ^^macdef - is macro defined?
-#define CR_TIME 'x' // ^^time - DOS format time
-#define CR_DATE 'y' // ^^date - DOS format date
+#define CR_DEFINED 'p' // ^^defined - is symbol defined?
+#define CR_REFERENCED 'q' // ^^referenced - was symbol referenced?
+#define CR_STREQ 'v' // ^^streq - compare two strings
+#define CR_MACDEF 'w' // ^^macdef - is macro defined?
+#define CR_TIME 'x' // ^^time - DOS format time
+#define CR_DATE 'y' // ^^date - DOS format date
// Character Attributes
-#define ILLEG 0 // Illegal character (unused)
-#define DIGIT 1 // 0-9
-#define HDIGIT 2 // A-F, a-f
-#define STSYM 4 // A-Z, a-z, _~.
-#define CTSYM 8 // A-Z, a-z, 0-9, _~$?
-#define SELF 16 // Single-character tokens: ( ) [ ] etc
-#define WHITE 32 // Whitespace (space, tab, etc.)
-#define MULTX 64 // Multiple-character tokens
-#define DOT 128 // [bwlsBWSL] for what follows a `.'
+#define ILLEG 0 // Illegal character (unused)
+#define DIGIT 1 // 0-9
+#define HDIGIT 2 // A-F, a-f
+#define STSYM 4 // A-Z, a-z, _~.
+#define CTSYM 8 // A-Z, a-z, 0-9, _~$?
+#define SELF 16 // Single-character tokens: ( ) [ ] etc
+#define WHITE 32 // Whitespace (space, tab, etc.)
+#define MULTX 64 // Multiple-character tokens
+#define DOT 128 // [bwlsBWSL] for what follows a `.'
// Conditional assembly structures
IFENT {
- IFENT *if_prev; // Ptr prev .if state block (or NULL)
- WORD if_state; // 0:enabled, 1:disabled
+ IFENT * if_prev; // Ptr prev .if state block (or NULL)
+ WORD if_state; // 0:enabled, 1:disabled
};
// Pointer to IFILE or IMACRO
IUNION {
- IFILE *ifile;
- IMACRO *imacro;
- IREPT *irept;
+ IFILE * ifile;
+ IMACRO * imacro;
+ IREPT * irept;
};
// Ptr to IFILEs, IMACROs, and so on; back-ptr to previous input objects
INOBJ {
- WORD in_type; // 0=IFILE, 1=IMACRO ...
- IFENT *in_ifent; // Pointer to .if context on entry
- INOBJ *in_link; // Pointer to previous INOBJ
- TOKEN *in_otok; // Old `tok' value
- TOKEN *in_etok; // Old `etok' value
- IUNION inobj; // IFILE or IMACRO ...
+ WORD in_type; // 0=IFILE, 1=IMACRO ...
+ IFENT * in_ifent; // Pointer to .if context on entry
+ INOBJ * in_link; // Pointer to previous INOBJ
+ TOKEN * in_otok; // Old `tok' value
+ TOKEN * in_etok; // Old `etok' value
+ IUNION inobj; // IFILE or IMACRO ...
};
// Information about a file
IFILE {
- IFILE *if_link; // Pointer to ancient IFILEs
- char *ifoldfname; // Old file's name
- int ifoldlineno; // Old line number
- int ifind; // Position in file buffer
- int ifcnt; // #chars left in file buffer
- int ifhandle; // File's descriptor
- WORD ifno; // File number
- char ifbuf[LNBUFSIZ]; // Line buffer
+ IFILE * if_link; // Pointer to ancient IFILEs
+ char * ifoldfname; // Old file's name
+ int ifoldlineno; // Old line number
+ int ifind; // Position in file buffer
+ int ifcnt; // #chars left in file buffer
+ int ifhandle; // File's descriptor
+ WORD ifno; // File number
+ char ifbuf[LNBUFSIZ]; // Line buffer
};
// Information about a macro invocation
IMACRO {
- IMACRO *im_link; // Pointer to ancient IMACROs
- LONG *im_nextln; // Next line to include
- WORD im_nargs; // # of arguments supplied on invocation
- WORD im_siz; // Size suffix supplied on invocation
- LONG im_olduniq; // Old value of 'macuniq'
- SYM *im_macro; // Pointer to macro we're in
- char im_lnbuf[LNSIZ]; // Line buffer
+ IMACRO * im_link; // Pointer to ancient IMACROs
+ LONG * im_nextln; // Next line to include
+ WORD im_nargs; // # of arguments supplied on invocation
+ WORD im_siz; // Size suffix supplied on invocation
+ LONG im_olduniq; // Old value of 'macuniq'
+ SYM * im_macro; // Pointer to macro we're in
+ char im_lnbuf[LNSIZ]; // Line buffer
};
// Information about a .rept invocation
IREPT {
- LONG *ir_firstln; // Pointer to first line
- LONG *ir_nextln; // Pointer to next line
- VALUE ir_count; // Repeat count (decrements)
+ LONG * ir_firstln; // Pointer to first line
+ LONG * ir_nextln; // Pointer to next line
+ VALUE ir_count; // Repeat count (decrements)
};
// Globals, externals etc
extern int lnsave;
extern int curlineno;
-extern char *curfname;
+extern char * curfname;
extern WORD cfileno;
-extern TOKEN *tok;
+extern TOKEN * tok;
extern char lnbuf[];
extern char lntag;
extern char tolowertab[];
-extern INOBJ *cur_inobj;
+extern INOBJ * cur_inobj;
extern unsigned orgactive;
extern unsigned orgaddr;
extern LONG sloc;
int fpop(void);
//int d_goto(WORD);
int d_goto(void);
-INOBJ *a_inobj(int);
+INOBJ * a_inobj(int);
#endif // __TOKEN_H__