Slight revamp of the optimisation system, featuring: strengthened flag parser, slight...
[rmac] / sect.c
diff --git a/sect.c b/sect.c
index f797300395474822bef6688f02c9fabfd8f9846a..cdf53ffc1ab5e650848211a030931580eb349a11 100644 (file)
--- a/sect.c
+++ b/sect.c
 //
-// RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
+// RMAC - Reboot's Macro Assembler for all Atari computers
 // SECT.C - Code Generation, Fixups and Section Management
-// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends
+// Copyright (C) 199x Landon Dyer, 2011-2020 Reboot and Friends
 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
-// Source Utilised with the Kind Permission of Landon Dyer
+// Source utilised with the kind permission of Landon Dyer
 //
 
 #include "sect.h"
+#include "6502.h"
 #include "direct.h"
+#include "dsp56k.h"
 #include "error.h"
 #include "expr.h"
 #include "listing.h"
 #include "mach.h"
 #include "mark.h"
-#include "risca.h"
+#include "riscasm.h"
 #include "symbol.h"
 #include "token.h"
 
 
+// Function prototypes
+void MakeSection(int, uint16_t);
+void SwitchSection(int);
+
 // Section descriptors
-SECT sect[NSECTS];                             // All sections... 
-int cursect;                                   // Current section number
+SECT sect[NSECTS];             // All sections...
+int cursect;                   // Current section number
 
 // These are copied from the section descriptor, the current code chunk
 // descriptor and the current fixup chunk descriptor when a switch is made into
-// a section.  They are copied back to the descriptors when the section is left.
-WORD scattr;                                   // Section attributes 
-LONG sloc;                                             // Current loc in section 
-
-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 
-
-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
+// a section. They are copied back to the descriptors when the section is left.
+uint16_t scattr;               // Section attributes
+uint32_t sloc;                 // Current loc in section
 
-unsigned fwdjump[MAXFWDJUMPS]; // forward jump check table
-unsigned fwindex = 0;                  // forward jump index
+CHUNK * scode;                 // Current (last) code chunk
+uint32_t challoc;              // # bytes alloc'd to code chunk
+uint32_t ch_size;              // # bytes used in code chunk
+uint8_t * chptr;               // Deposit point in code chunk buffer
+uint8_t * chptr_opcode;        // Backup of chptr, updated before entering code generators
 
 // Return a size (SIZB, SIZW, SIZL) or 0, depending on what kind of fixup is
 // associated with a location.
-static char fusiztab[] = {
-   0,  // FU_QUICK
-   1,  // FU_BYTE
-   2,  // FU_WORD
-   2,  // FU_WBYTE
-   4,  // FU_LONG
-   1,  // FU_BBRA
-   0,  // (unused)
-   1,  // FU_6BRA
+static uint8_t fusiztab[] = {
+       0,      // FU_QUICK
+       1,      // FU_BYTE
+       2,      // FU_WORD
+       2,      // FU_WBYTE
+       4,      // FU_LONG
+       1,      // FU_BBRA
+       0,      // (unused)
+       1,      // FU_6BRA
 };
 
 // Offset to REAL fixup location
-static char fusizoffs[] = {
-   0,  // FU_QUICK
-   0,  // FU_BYTE
-   0,  // FU_WORD
-   1,  // FU_WBYTE
-   0,  // FU_LONG
-   1,  // FU_BBRA
-   0,  // (unused)
-   0,  // FU_6BRA
+static uint8_t fusizoffs[] = {
+       0,      // FU_QUICK
+       0,      // FU_BYTE
+       0,      // FU_WORD
+       1,      // FU_WBYTE
+       0,      // FU_LONG
+       1,      // FU_BBRA
+       0,      // (unused)
+       0,      // FU_6BRA
 };
 
 
 //
-// Make a New (Clean) Section
+// Initialize sections; setup initial ABS, TEXT, DATA and BSS sections
+//
+void InitSection(void)
+{
+       // Initialize all sections
+       for(int i=0; i<NSECTS; i++)
+               MakeSection(i, 0);
+
+       // Construct default sections, make TEXT the current section
+       MakeSection(ABS,     SUSED | SABS | SBSS);      // ABS
+       MakeSection(TEXT,    SUSED | TEXT       );      // TEXT
+       MakeSection(DATA,    SUSED | DATA       );      // DATA
+       MakeSection(BSS,     SUSED | BSS  | SBSS);      // BSS
+       MakeSection(M6502,   SUSED | TEXT       );      // 6502 code section
+       MakeSection(M56001P, SUSED | SABS       );      // DSP 56001 Program RAM
+       MakeSection(M56001X, SUSED | SABS       );      // DSP 56001 X RAM
+       MakeSection(M56001Y, SUSED | SABS       );      // DSP 56001 Y RAM
+
+       // Switch to TEXT for starters
+       SwitchSection(TEXT);
+}
+
+
+//
+// Make a new (clean) section
 //
-void mksect(int sno, WORD attr)
+void MakeSection(int sno, uint16_t attr)
 {
-       SECT * p = &sect[sno];
-       p->scattr = attr;
-       p->sloc = 0;
-       p->scode = p->sfcode = NULL;
-       p->sfix = p->sffix = NULL;
+       SECT * sp = &sect[sno];
+       sp->scattr = attr;
+       sp->sloc = 0;
+       sp->orgaddr = 0;
+       sp->scode = sp->sfcode = NULL;
+       sp->sfix = sp->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)
+void SwitchSection(int sno)
 {
-       CHUNK * cp;                                                             // Chunk pointer
+       CHUNK * cp;
        cursect = sno;
-       SECT * p = &sect[sno];
+       SECT * sp = &sect[sno];
+
+       m6502 = (sno == M6502); // Set 6502-mode flag
 
-       scattr = p->scattr;                                             // Copy section vars
-       sloc = p->sloc;
-       scode = p->scode;
-       sfix = p->sfix;
+       // Copy section vars
+       scattr = sp->scattr;
+       sloc = sp->sloc;
+       scode = sp->scode;
+       orgaddr = sp->orgaddr;
 
        // Copy code chunk vars
        if ((cp = scode) != NULL)
@@ -101,127 +128,89 @@ void switchsect(int sno)
                challoc = cp->challoc;
                ch_size = cp->ch_size;
                chptr = cp->chptr + ch_size;
-       }
-       else
-               challoc = ch_size = 0;
 
-       // Copy fixup chunk vars 
-       if ((cp = sfix) != NULL)
-       {
-               fchalloc = cp->challoc;
-               fchsize = cp->ch_size;
-               fchptr.cp = cp->chptr + fchsize;
-       }
-       else
-               fchalloc = fchsize = 0;
-}
+               // For 6502 mode, add the last org'd address
+// Why?
+/*
+Because the way this is set up it treats the 6502 assembly space as a single 64K space (+ 16 bytes, for some unknown reason) and just bobbles around inside that space and uses a stack of org "pointers" to show where the data ended up.
 
+This is a shitty way to handle things, and we can do better than this!  :-P
 
-//
-// Save Current Section
-//
-void savsect(void)
-{
-       SECT * p = &sect[cursect];
-
-       p->scattr = scattr;                                             // Bailout section vars
-       p->sloc = sloc;
+Really, there's no reason to have the 6502 (or DSP56001 for that matter) have their own private sections for this kind of thing, as there's literally *no* chance that it would be mingled with 68K+ code.  It should be able to use the TEXT, DATA & BSS sections just like the 68K.
 
-       if (scode != NULL)                                              // Bailout code chunk
-               scode->ch_size = ch_size;
-
-       if (sfix != NULL)                                               // Bailout fixup chunk
-               sfix->ch_size = fchsize;
+Or should it?  After looking at the code, maybe it's better to keep the 56001 sections segregated from the rest.  But we can still make the 6502 stuff better.
+*/
+               if (m6502)
+                       chptr = cp->chptr + orgaddr;
+       }
+       else
+               challoc = ch_size = 0;
 }
 
 
 //
-// Initialize Sections; Setup initial ABS, TEXT, DATA and BSS sections
+// Save current section
 //
-void init_sect(void)
+void SaveSection(void)
 {
-       int i;
+       SECT * sp = &sect[cursect];
 
-       // Cleanup all sections
-       for(i=0; i<NSECTS; i++)
-               mksect(i, 0);
+       sp->scattr = scattr;                    // Bailout section vars
+       sp->sloc = sloc;
+       sp->orgaddr = orgaddr;
 
-       // 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
+       if (scode != NULL)                              // Bailout code chunk (if any)
+               scode->ch_size = ch_size;
 }
 
 
 //
-// Test to see if a location has a fixup sic'd on it.  This is used by the
+// Test to see if a location has a fixup set 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)
+int fixtest(int sno, uint32_t 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;
+       // Force update to sect[] variables
+       StopMark();
 
-                       if (xloc == loc)
-                               return (int)fusiztab[w & FUMASK];
+       // 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 anyway.
+       for(FIXUP * fp=sect[sno].sffix; fp!=NULL; fp=fp->next)
+       {
+               uint32_t w = fp->attr;
+               uint32_t xloc = fp->loc + (int)fusizoffs[w & FUMASK];
 
-                       if (w & FU_EXPR)
-                       {
-                               w = *fup.wp++;
-                               fup.lp += w;
-                       }
-                       else
-                               ++fup.lp;
-               }
+               if (xloc == loc)
+                       return (int)fusiztab[w & FUMASK];
        }
 
        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).
-// 
-// If `amt' is zero, ensure there are at least CH_THRESHOLD bytes, likewise.
 //
-int chcheck(LONG amt)
+// Check that there are at least 'amt' bytes left in the current chunk. If
+// there are not, allocate another chunk of at least CH_CODE_SIZE bytes or
+// 'amt', whichever is larger.
+//
+// If 'amt' is zero, ensure there are at least CH_THRESHOLD bytes, likewise.
+//
+void chcheck(uint32_t amt)
 {
        DEBUG { printf("chcheck(%u)\n", amt); }
+
        // If in BSS section, no allocation required
        if (scattr & SBSS)
-               return 0;
+               return;
 
-       if (!amt)
+       if (amt == 0)
                amt = CH_THRESHOLD;
 
-       DEBUG { printf("    challoc=%i, ch_size=%i, diff=%i\n", challoc, ch_size, challoc-ch_size); }
-       if ((int)(challoc - ch_size) >= (int)amt) 
-               return 0;
+       DEBUG { printf("    challoc=%i, ch_size=%i, diff=%i\n", challoc, ch_size, challoc - ch_size); }
+
+       if ((int)(challoc - ch_size) >= (int)amt)
+               return;
 
        if (amt < CH_CODE_SIZE)
                amt = CH_CODE_SIZE;
@@ -229,678 +218,789 @@ int chcheck(LONG amt)
        DEBUG { printf("    amt (adjusted)=%u\n", amt); }
        SECT * p = &sect[cursect];
        CHUNK * cp = malloc(sizeof(CHUNK) + amt);
+       int first = 0;
 
-       // First chunk in section
        if (scode == NULL)
        {
+               // First chunk in section
                cp->chprev = NULL;
                p->sfcode = cp;
+               first = 1;
        }
-       // Add chunk to other chunks
        else
        {
+               // Add second and on to previous chunk
                cp->chprev = scode;
                scode->chnext = cp;
-               scode->ch_size = ch_size;                       // Save old chunk's globals 
+               scode->ch_size = ch_size;       // Save old chunk's globals
        }
 
        // Setup chunk and global vars
-       cp->chloc = sloc;
+/*
+So, whenever there's an ORG in a 56K section, it sets sloc TO THE ADDRESS IN THE ORG.  Also, the loc/sloc are incremented by 1s, which means to alias correctly to the byte-oriented memory model we have here, we have to fix that kind of crap.
+*/
+       cp->chloc = sloc; // <-- HERE'S THE PROBLEM FOR 56K  :-/
        cp->chnext = NULL;
        challoc = cp->challoc = amt;
        ch_size = cp->ch_size = 0;
-       chptr = cp->chptr = ((char *)cp) + sizeof(CHUNK);
+       chptr = cp->chptr = ((uint8_t *)cp) + sizeof(CHUNK);
        scode = p->scode = cp;
 
-       return 0;
+       // A quick kludge
+/*
+OK, so this is a bit shite, but at least it gets things working the way they should.  The right way to do this is not rely on sloc & friends for the right fixup address but to have an accurate model of the thing.  That will probably come with v2.0.1  :-P
+
+So the problem is, d_org sets sloc to the address of the ORG statement, and that gives an incorrect base for the fixup.  And so when a second (or later) chunk is allocated, it gets set wrong.  Further complicating things is that the orgaddress *does not* get used in a typical way with the DSP56001 code, and, as such, causes incorrect addresses to be generated.  All that has to be dealt with in order to get this right and do away with this kludge.
+*/
+       if (((cursect == M56001P) || (cursect == M56001X) || (cursect == M56001Y)) && !first)
+               cp->chloc = cp->chprev->chloc + cp->chprev->ch_size;
+
+       return;
 }
 
 
-// This is really wrong. We need to make some proper structures here so we don't
-// have to count sizes of objects, that's what the compiler's for! :-P
-#define FIXUP_BASE_SIZE (sizeof(WORD) + sizeof(LONG) + sizeof(WORD) + sizeof(WORD))
 //
 // Arrange for a fixup on a location
 //
-int fixup(WORD attr, LONG loc, TOKEN * fexpr)
+int AddFixup(uint32_t attr, uint32_t loc, TOKEN * fexpr)
 {
-       LONG i;
-       LONG len = 0;
-       CHUNK * cp;
-       SECT * p;
-       // Shamus: Expression lengths are voodoo ATM (varibale "i"). Need to fix this.
-       DEBUG printf("FIXUP@$%X: $%X\n", loc, attr);
-
-       // 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)
+       uint16_t exprlen = 0;
+       SYM * symbol = NULL;
+       uint32_t _orgaddr = 0;
+
+       // First, check to see if the expression is a bare label, otherwise, force
+       // the FU_EXPR flag into the attributes and count the tokens.
+       if ((fexpr[0] == SYMBOL) && (fexpr[2] == ENDEXPR))
        {
-               // Just a single symbol
-               // SCPCD : correct bit mask for attr (else other FU_xxx will match) NYAN !
-               if ((attr & 0x0F00) == FU_JR)
-               {
-//                     i = 18;
-//                     i = FIXUP_BASE_SIZE + (sizeof(LONG) * 2);
-                       i = FIXUP_BASE_SIZE + sizeof(SYM *) + sizeof(LONG);
-               }
-               else
-               {
-//                     i = 14;
-                       i = FIXUP_BASE_SIZE + sizeof(SYM *);
-               }
+               symbol = symbolPtr[fexpr[1]];
+
+               // Save the org address for JR RISC instruction
+               if ((attr & FUMASKRISC) == FU_JR)
+                       _orgaddr = orgaddr;
        }
        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;
-               i = FIXUP_BASE_SIZE + sizeof(WORD) + (len * sizeof(TOKEN));
+               exprlen = ExpressionLength(fexpr);
        }
 
-       // Maybe alloc another fixup chunk for this one to fit in
-       if ((fchalloc - fchsize) < i)
+       // Second, check to see if it's a DSP56001 fixup, and force the FU_56001
+       // flag into the attributes if so; also save the current org address.
+       if (attr & FUMASKDSP)
        {
-               p = &sect[cursect];
-               cp = (CHUNK *)malloc(sizeof(CHUNK) + CH_FIXUP_SIZE);
-
-               // First fixup chunk in section
-               if (sfix == NULL)
-               {
-                       cp->chprev = NULL;
-                       p->sffix = cp;
-               }
-               // Add to other chunks
-               else
-               {
-                       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;
+               attr |= FU_56001;
+               // Save the exact spot in this chunk where the fixup should go
+               _orgaddr = chptr - scode->chptr + scode->chloc;
        }
 
-       // 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)
+       // Allocate space for the fixup + any expression
+       FIXUP * fixup = malloc(sizeof(FIXUP) + (sizeof(TOKEN) * exprlen));
+
+       // Store the relevant fixup information in the FIXUP
+       fixup->next = NULL;
+       fixup->attr = attr;
+       fixup->loc = loc;
+       fixup->fileno = cfileno;
+       fixup->lineno = curlineno;
+       fixup->expr = NULL;
+       fixup->symbol = symbol;
+       fixup->orgaddr = _orgaddr;
+
+       // Copy the passed in expression to the FIXUP, if any
+       if (exprlen > 0)
        {
-               *fchptr.wp++ = (WORD)len;
+               fixup->expr = (TOKEN *)((uint8_t *)fixup + sizeof(FIXUP));
+               memcpy(fixup->expr, fexpr, sizeof(TOKEN) * exprlen);
+       }
 
-               while (len--)
-                       *fchptr.lp++ = (LONG)*fexpr++;
+       // Finally, put the FIXUP in the current section's linked list
+       if (sect[cursect].sffix == NULL)
+       {
+               sect[cursect].sffix = fixup;
+               sect[cursect].sfix = fixup;
        }
        else
        {
-//             *fchptr.lp++ = (LONG)fexpr[1];
-               *fchptr.sy++ = symbolPtr[fexpr[1]];
+               sect[cursect].sfix->next = fixup;
+               sect[cursect].sfix = fixup;
        }
 
-       // SCPCD : correct bit mask for attr (else other FU_xxx will match) NYAN !
-       if ((attr & 0x0F00) == FU_JR)
-       {
-               if (orgactive)
-                       *fchptr.lp++ = orgaddr;
-               else
-                       *fchptr.lp++ = 0x00000000;
+       DEBUG { printf("AddFixup: sno=%u, l#=%u, attr=$%X, loc=$%X, expr=%p, sym=%p, org=$%X\n", cursect, fixup->lineno, fixup->attr, fixup->loc, (void *)fixup->expr, (void *)fixup->symbol, fixup->orgaddr);
+               if (symbol != NULL)
+                       printf("          name: %s, value: $%lX\n", symbol->sname, symbol->svalue);
        }
 
-       fchsize += i;
        return 0;
 }
 
 
 //
-// Resolve all Fixups
+// Resolve fixups in the passed in section
 //
-int ResolveAllFixups(void)
+int ResolveFixups(int sno)
 {
-       unsigned i;
-       char buf[EBUFSIZ];
+       SECT * sc = &sect[sno];
 
-       // Make undefined symbols GLOBL
-       if (glob_flag)
-               syg_fix();
+       // "Cache" first chunk
+       CHUNK * cch = sc->sfcode;
 
-       DEBUG printf("Resolving TEXT sections...\n");
-       ResolveFixups(TEXT);
-       DEBUG printf("Resolving DATA sections...\n");
-       ResolveFixups(DATA);
-       
-       // We need to do a final check of forward 'jump' destination addresses that
-       // are external
-       for(i=0; i<MAXFWDJUMPS; i++)
+       // Can't fixup a section with nothing in it
+       if (cch == NULL)
+               return 0;
+
+       // Wire the 6502 segment's size to its allocated size (64K)
+       if (sno == M6502)
+               cch->ch_size = cch->challoc;
+
+       // Get first fixup for the passed in section
+       FIXUP * fixup = sect[sno].sffix;
+
+       while (fixup != NULL)
        {
-               if (fwdjump[i])
+               // We do it this way because we have continues everywhere... :-P
+               FIXUP * fup = fixup;
+               fixup = fixup->next;
+
+               uint32_t dw = fup->attr;        // Fixup long (type + modes + flags)
+               uint32_t loc = fup->loc;        // Location to fixup
+               cfileno = fup->fileno;
+               curlineno = fup->lineno;
+               DEBUG { printf("ResolveFixups: sect#=%u, l#=%u, attr=$%X, loc=$%X, expr=%p, sym=%p, org=$%X\n", sno, fup->lineno, fup->attr, fup->loc, (void *)fup->expr, (void *)fup->symbol, fup->orgaddr); }
+
+               // This is based on global vars cfileno, curfname :-P
+               // This approach is kinda meh as well. I think we can do better
+               // than this.
+               SetFilenameForErrorReporting();
+
+               if ((sno == M56001P) || (sno == M56001X) || (sno == M56001Y) || (sno == M56001L))
+                       loc = fup->orgaddr;
+
+               // 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))
                {
-                       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);
+                       for(cch=sc->sfcode; cch!=NULL; cch=cch->chnext)
+                       {
+                               if (loc >= cch->chloc && loc < (cch->chloc + cch->ch_size))
+                                       break;
+                       }
 
-                       if (err_flag)
-                               write(err_fd, buf, (LONG)strlen(buf));
-                       else
-                               printf("%s\n", buf);
+                       if (cch == NULL)
+                       {
+                               // Fixup (loc) is out of range--this should never happen!
+                               // Once we call this function, it winds down immediately; it
+                               // doesn't return.
+                               interror(7);
+                       }
                }
-       }
 
-       return 0;
-}
+               // Location to fix (in current chunk)
+               // We use the address of the chunk that loc is actually in, then
+               // subtract the chunk's starting location from loc to get the offset
+               // into the current chunk.
+               uint8_t * locp = cch->chptr + (loc - cch->chloc);
 
+               uint16_t eattr = 0;                     // Expression attrib
+               SYM * esym = NULL;                      // External symbol involved in expr
+               uint64_t eval;                          // Expression value
+               uint16_t flags;                         // Mark flags
 
-//
-// Resolve Fixups in a Section
-//
-int ResolveFixups(int sno)
-{
-       PTR fup;                                        // Current fixup
-       WORD * fuend;                           // End of last fixup (in this chunk)
-       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];
-       
-       SECT * sc = &sect[sno];
-       CHUNK * ch = sc->sffix;
+               // Compute expression/symbol value and attributes
 
-       if (ch == NULL)
-               return 0;
+               // Complex expression
+               if (dw & FU_EXPR)
+               {
+                       // evexpr presumably issues the errors/warnings here
+                       if (evexpr(fup->expr, &eval, &eattr, &esym) != OK)
+                               continue;
 
-       CHUNK * cch = sc->sfcode;                               // "cache" first chunk
+                       if (CHECK_OPTS(OPT_PC_RELATIVE))
+                               if (eattr & REFERENCED)
+                                       if (eattr & DEFINED)
+                                               if (!(eattr & EQUATED))
+                                               {
+                                                       error("relocation not allowed");
+                                                       continue;
+                                               }
+               }
+               // Simple symbol
+               else
+               {
+                       SYM * sy = fup->symbol;
+                       eattr = sy->sattr;
 
-       if (cch == NULL)                                                // Can't fixup a sect with nothing in it
-               return 0;
+                       if (CHECK_OPTS(OPT_PC_RELATIVE))
+                               if (eattr & REFERENCED)
+                                       if (eattr & DEFINED)
+                                               if (!(eattr & EQUATED))
+                                               {
+                                                       error("relocation not allowed");
+                                                       continue;
+                                               }
 
-       do
-       {
-               fup.cp = ch->chptr;                                     // fup -> start of chunk
-               fuend = (WORD *)(fup.cp + ch->ch_size); // fuend -> end of chunk
+                       if (eattr & DEFINED)
+                               eval = sy->svalue;
+                       else
+                               eval = 0;
+
+                       // If the symbol is not defined, but global, set esym to sy
+                       if ((eattr & (GLOBAL | DEFINED)) == GLOBAL)
+                               esym = sy;
 
-               while (fup.wp < fuend)
+                       DEBUG { printf("               name: %s, value: $%" PRIX64 "\n", sy->sname, sy->svalue); }
+               }
+
+               uint16_t tdb = eattr & TDB;
+
+               // If the expression/symbol is undefined and no external symbol is
+               // involved, then that's an error.
+               if (!(eattr & DEFINED) && (esym == NULL))
+               {
+                       error(undef_error);
+                       continue;
+               }
+
+               // 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).
+               //
+               // PC-relative fixups must be DEFINED and either in the same section
+               // (whereupon the subtraction takes place) or ABS (with no subtract).
+               if ((dw & FU_PCREL) || (dw & FU_PCRELX))
                {
-                       w = *fup.wp++;
-                       loc = *fup.lp++;
-                       cfileno = *fup.wp++;
-                       curlineno = (int)*fup.wp++;
-DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); }
-                       // This is based on global vars cfileno, curfname :-P
-                       // This approach is kinda meh as well. I think we can do better than this.
-                       SetFilenameForErrorReporting();
-
-                       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))
+                       if (eattr & DEFINED)
                        {
-                               for(cch=sc->sfcode; cch!=NULL; cch=cch->chnext)
+                               if (tdb == sno)
                                {
-                                       if (loc >= cch->chloc && loc < (cch->chloc + cch->ch_size))
-                                               break;
-                               }
+                                       eval -= loc;
 
-                               if (cch == NULL)
+                                       // In this instruction the PC is located a DWORD away
+                                       if (dw & FU_PCRELX)
+                                               eval += 2;
+                               }
+                               else if (tdb)
                                {
-                                       interror(7);                    // Fixup (loc) out of range 
-                                       // NOTREACHED
+                                       // Allow cross-section PCREL fixups in Alcyon mode
+                                       if (prg_flag || (obj_format == RAW))
+                                       {
+                                               switch (tdb)
+                                               {
+                                               case TEXT:
+// Shouldn't there be a break here, since otherwise, it will point to the DATA section?
+//                                                     break;
+                                               case DATA:
+                                                       eval += sect[TEXT].sloc;
+                                                       break;
+                                               case BSS:
+                                                       eval += sect[TEXT].sloc + sect[DATA].sloc;
+                                                       break;
+                                               default:
+                                                       error("invalid section");
+                                               break;
+                                               }
+
+                                               eval -= loc;
+
+                                               // In this instruction the PC is located a DWORD away
+                                               if (dw & FU_PCRELX)
+                                                       eval += 2;
+                                       }
+                                       else
+                                       {
+                                               error("PC-relative expr across sections");
+                                               continue;
+                                       }
                                }
+
+                               if (optim_warn_flag && (dw & FU_LBRA) && (eval + 0x80 < 0x100))
+                                       warn("unoptimized short branch");
                        }
 
-                       locp = cch->chptr + (loc - cch->chloc);
-                       eattr = 0;
+                       // Be sure to clear any TDB flags, since we handled it just now
+                       tdb = 0;
+                       eattr &= ~TDB;
+               }
 
-                       // Compute expression/symbol value and attribs
-                       // Complex expression
-                       if (w & FU_EXPR)
+               // Handle fixup classes
+               switch (dw & FUMASK)
+               {
+               // FU_BBRA fixes up a one-byte branch offset.
+               case FU_BBRA:
+                       if (!(eattr & DEFINED))
                        {
-                               i = *fup.wp++;
+                               error("external short branch");
+                               continue;
+                       }
+
+                       eval -= 2;
 
-                               if (evexpr(fup.tk, &eval, &eattr, &esym) != OK)
+                       if (eval + 0x80 >= 0x100)
+                               goto rangeErr;
+
+                       if (eval == 0)
+                       {
+                               if (*locp) // optim_flags[OPT_NULL_BRA] is stored there, check the comment in mach.s under m_br
                                {
-                                       fup.lp += i;
+                                       // Just output a NOP
+                                       *locp++ = 0x4E;
+                                       *locp = 0x71;
+                                       if (optim_warn_flag)
+                                               warn("bra.s with zero offset converted to NOP");
                                        continue;
                                }
+                               else
+                               {
+                                       error("illegal bra.s with zero offset");
+                                       continue;
+                               }
+                       }
 
-                               fup.lp += i;
+                       *++locp = (uint8_t)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;
                        }
-                       // Simple symbol
-                       else
+
+                       if (tdb)
                        {
-                               sy = *fup.sy++;
-                               eattr = sy->sattr;
+                               error("non-absolute byte reference");
+                               continue;
+                       }
 
-                               if (eattr & DEFINED)
-                                       eval = sy->svalue;
-                               else
-                                       eval = 0;
+                       if ((dw & FU_PCREL) && ((eval + 0x80) >= 0x100))
+                               goto rangeErr;
 
-                               if ((eattr & (GLOBAL | DEFINED)) == GLOBAL)
-                                       esym = sy;
+                       if (dw & FU_SEXT)
+                       {
+                               if ((eval + 0x100) >= 0x200)
+                                       goto rangeErr;
                        }
+                       else if (eval >= 0x100)
+                               goto rangeErr;
 
-                       tdb = (WORD)(eattr & TDB);
+                       *locp = (uint8_t)eval;
+                       break;
 
-                       // If the expression is undefined and no external symbol is
-                       // involved, then it's an error.
-                       if (!(eattr & DEFINED) && esym == NULL)
+               // Fixup high/low byte off word for 6502
+               case FU_BYTEH:
+                       if (!(eattr & DEFINED))
                        {
-                               error(undef_error);
+                               error("external byte reference");
                                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;
+                       *locp = (uint8_t)(eval >> 8);
+                       break;
 
-                               tdb = 0;
-                               eattr &= ~TDB;
+               case FU_BYTEL:
+                       if (!(eattr & DEFINED))
+                       {
+                               error("external byte reference");
+                               continue;
                        }
 
-                       // Do fixup classes
-                       switch ((int)(w & FUMASK))
+                       *locp = (uint8_t)eval;
+                       break;
+
+               // Fixup WORD forward references; the word could be unaligned in the
+               // section buffer, so we have to be careful. (? careful about what?)
+               case FU_WORD:
+                       if ((dw & FUMASKRISC) == FU_JR)
                        {
-                       // FU_BBRA fixes up a one-byte branch offset.
-                       case FU_BBRA:
-                               if (!(eattr & DEFINED))
+                               int reg = (signed)((eval - ((fup->orgaddr ? fup->orgaddr : loc) + 2)) / 2);
+
+                               if ((reg < -16) || (reg > 15))
                                {
-                                       error("external short branch");
-                                       continue;
+                                       error("relative jump out of range");
+                                       break;
                                }
 
-                               eval -= 2;
-
-                               if (eval + 0x80 >= 0x100)
-                                       goto range;
-
-                               if (eval == 0)
+                               *locp |= ((uint8_t)reg >> 3) & 0x03;
+                               locp++;
+                               *locp |= ((uint8_t)reg & 0x07) << 5;
+                               break;
+                       }
+                       else if ((dw & FUMASKRISC) == FU_NUM15)
+                       {
+                               if (((int)eval < -16) || ((int)eval > 15))
                                {
-                                       error("illegal bra.s with zero offset");
-                                       continue;
+                                       error("constant out of range (-16 - +15)");
+                                       break;
                                }
 
-                               *++locp = (char)eval;
+                               *locp |= ((uint8_t)eval >> 3) & 0x03;
+                               locp++;
+                               *locp |= ((uint8_t)eval & 0x07) << 5;
                                break;
-                       // Fixup one-byte value at locp + 1.
-                       case FU_WBYTE:
-                               ++locp;
-                               // FALLTHROUGH
-                       // Fixup one-byte forward references
-                       case FU_BYTE:
-                               if (!(eattr & DEFINED))
+                       }
+                       else if ((dw & FUMASKRISC) == FU_NUM31)
+                       {
+                               if (eval > 31)
                                {
-                                       error("external byte reference");
-                                       continue;
+                                       error("constant out of range (0-31)");
+                                       break;
                                }
 
-                               if (tdb)
+                               *locp |= ((uint8_t)eval >> 3) & 0x03;
+                               locp++;
+                               *locp |= ((uint8_t)eval & 0x07) << 5;
+                               break;
+                       }
+                       else if ((dw & FUMASKRISC) == FU_NUM32)
+                       {
+                               if ((eval < 1) || (eval > 32))
                                {
-                                       error("non-absolute byte reference");
-                                       continue;
+                                       error("constant out of range (1-32)");
+                                       break;
                                }
 
-                               if ((w & FU_PCREL) && eval + 0x80 >= 0x100)
-                                       goto range;
+                               if (dw & FU_SUB32)
+                                       eval = (32 - eval);
 
-                               if (w & FU_SEXT)
+                               eval = (eval == 32) ? 0 : eval;
+                               *locp |= ((uint8_t)eval >> 3) & 0x03;
+                               locp++;
+                               *locp |= ((uint8_t)eval & 0x07) << 5;
+                               break;
+                       }
+                       else if ((dw & FUMASKRISC) == FU_REGONE)
+                       {
+                               if (eval > 31)
                                {
-                                       if (eval + 0x100 >= 0x200)
-                                               goto range;
+                                       error("register one value out of range");
+                                       break;
                                }
-                               else if (eval >= 0x100)
-                                       goto range;
 
-                               *locp = (char)eval;
+                               *locp |= ((uint8_t)eval >> 3) & 0x03;
+                               locp++;
+                               *locp |= ((uint8_t)eval & 0x07) << 5;
                                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))
+                       }
+                       else if ((dw & FUMASKRISC) == FU_REGTWO)
+                       {
+                               if (eval > 31)
                                {
-                                       oaddr = *fup.lp++;
+                                       error("register two value out of range");
+                                       break;
+                               }
 
-                                       if (oaddr)
-                                       {
-                                               reg2 = (signed)((eval - (oaddr + 2)) / 2);// & 0x1F;
-                                       }
-                                       else
-                                       {
-                                               reg2 = (signed)((eval - (loc + 2)) / 2);// & 0x1F;
-                                       }
+                               locp++;
+                               *locp |= (uint8_t)eval & 0x1F;
+                               break;
+                       }
 
-                                       if ((w & 0x0F00) == FU_MJR)
-                                       {
-                                               // Main code destination alignment checking here for
-                                               // forward declared labels
-                                               address = (oaddr) ? oaddr : loc;
+                       if (!(eattr & DEFINED))
+                       {
+                               flags = MWORD;
 
-                                               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 (dw & FU_PCREL)
+                                       flags |= MPCREL;
 
-                                       if ((reg2 < -16) || (reg2 > 15))
-                                       {
-                                               error("relative jump out of range");
-                                               break;
-                                       }
+                               MarkRelocatable(sno, loc, 0, flags, esym);
+                       }
+                       else
+                       {
+                               if (tdb)
+                                       MarkRelocatable(sno, loc, tdb, MWORD, NULL);
 
-                                       *locp = (char)(*locp | ((reg2 >> 3) & 0x03));
-                                       locp++;
-                                       *locp = (char)(*locp | ((reg2 & 0x07) << 5));
-                                       break;
+                               if (dw & FU_SEXT)
+                               {
+                                       if (eval + 0x10000 >= 0x20000)
+                                               goto rangeErr;
                                }
-
-                               if ((w & 0x0F00) == FU_NUM15)
+                               else
                                {
-                                       if (eval < -16 || eval > 15)
+                                       // Range-check BRA and DBRA
+                                       if (dw & FU_ISBRA)
                                        {
-                                               error("constant out of range");
-                                               break;
+                                               if (eval + 0x8000 >= 0x10000)
+                                                       goto rangeErr;
                                        }
-
-                                       *locp = (char)(*locp | ((eval >> 3) & 0x03));
-                                       locp++;
-                                       *locp = (char)(*locp | ((eval & 0x07) << 5));
-                                       break;
+                                       else if (eval >= 0x10000)
+                                               goto rangeErr;
                                }
+                       }
 
-                               if ((w & 0x0F00) == FU_NUM31)
-                               {
-                                       if (eval < 0 || eval > 31)
-                                       {
-                                               error("constant out of range");
-                                               break;
-                                       }
+                       // 6502 words are little endian, so handle that here
+                       if (sno == M6502)
+                               SETLE16(locp, 0, eval)
+                       else
+                               SETBE16(locp, 0, eval)
 
-                                       *locp = (char)(*locp | ((eval >> 3) & 0x03));
-                                       locp++;
-                                       *locp = (char)(*locp | ((eval & 0x07) << 5));
-                                       break;
-                               }
+                       break;
 
-                               if ((w & 0x0F00) == FU_NUM32)
-                               {
-                                       if (eval < 1 || eval > 32)
-                                       {
-                                               error("constant out of range");
-                                               break;
-                                       }
+               // Fixup LONG forward references; the long could be unaligned in the
+               // section buffer, so be careful (again).
+               case FU_LONG:
+                       flags = MLONG;
 
-                                       if (w & FU_SUB32)
-                                               eval = (32 - eval);
+                       if ((dw & FUMASKRISC) == FU_MOVEI)
+                       {
+                               // Long constant in MOVEI # is word-swapped, so fix it here
+                               eval = WORDSWAP32(eval);
+                               flags |= MMOVEI;
+                       }
 
-                                       eval = (eval == 32) ? 0 : eval;
-                                       *locp = (char)(*locp | ((eval >> 3) & 0x03));
-                                       locp++;
-                                       *locp = (char)(*locp | ((eval & 0x07) << 5));
-                                       break;
-                               }
+                       // If the symbol is undefined, make sure to pass the symbol in
+                       // to the MarkRelocatable() function.
+                       if (!(eattr & DEFINED))
+                               MarkRelocatable(sno, loc, 0, flags, esym);
+                       else if (tdb)
+                               MarkRelocatable(sno, loc, tdb, flags, NULL);
 
-                               if ((w & 0x0F00) == FU_REGONE)
-                               {
-                                       if (eval < 0 || eval > 31)
-                                       {
-                                               error("register value out of range");
-                                               break;
-                                       }
+                       SETBE32(locp, 0, eval);
+                       break;
+
+               // Fixup QUAD forward references (mainly used by the OP assembler)
+               case FU_QUAD:
+                       if (dw & FU_OBJLINK)
+                       {
+                               uint64_t quad = GETBE64(locp, 0);
+                               uint64_t addr = eval;
 
-                                       *locp = (char)(*locp | ((eval >> 3) & 0x03));
-                                       locp++;
-                                       *locp = (char)(*locp | ((eval & 0x07) << 5));
+//Hmm, not sure how this can be set, since it's only set if it's a DSP56001 fixup or a FU_JR...  :-/
+//                             if (fup->orgaddr)
+//                                     addr = fup->orgaddr;
+
+                               eval = (quad & 0xFFFFFC0000FFFFFFLL) | ((addr & 0x3FFFF8) << 21);
+                       }
+                       else if (dw & FU_OBJDATA)
+                       {
+                               // If it's in a TEXT or DATA section, be sure to mark for a
+                               // fixup later
+                               if (tdb)
+                                       MarkRelocatable(sno, loc, tdb, MQUAD, NULL);
+
+                               uint64_t quad = GETBE64(locp, 0);
+                               uint64_t addr = eval;
+
+//Hmm, not sure how this can be set, since it's only set if it's a DSP56001 fixup or a FU_JR...  :-/
+//                             if (fup->orgaddr)
+//                                     addr = fup->orgaddr;
+
+                               eval = (quad & 0x000007FFFFFFFFFFLL) | ((addr & 0xFFFFF8) << 40);
+                       }
+
+                       SETBE64(locp, 0, 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 rangeErr;
+
+                       *locp |= (eval & 7) << 1;
+                       break;
+
+               // Fix up 6502 funny branch
+               case FU_6BRA:
+                       eval -= (loc + 1);
+
+                       if (eval + 0x80 >= 0x100)
+                               goto rangeErr;
+
+                       *locp = (uint8_t)eval;
+                       break;
+
+               // Fixup DSP56001 addresses
+               case FU_56001:
+                       switch (dw & FUMASKDSP)
+                       {
+                       // DSPIMM5 actually is clamped from 0 to 23 for our purposes
+                       // and does not use the full 5 bit range.
+                       case FU_DSPIMM5:
+                               if (eval > 23)
+                               {
+                                       error("immediate value must be between 0 and 23");
                                        break;
                                }
 
-                               if ((w & 0x0F00) == FU_REGTWO)
-                               {
-                                       if (eval < 0 || eval > 31)
-                                       {
-                                               error("register value out of range");
-                                               break;
-                                       }
+                               locp[2] |= eval;
+                               break;
 
-                                       locp++;
-                                       *locp = (char)(*locp | (eval & 0x1F));
+                       // This is a 12-bit address encoded into the lower 12
+                       // bits of a DSP word
+                       case FU_DSPADR12:
+                               if (eval >= 0x1000)
+                               {
+                                       error("address out of range ($0-$FFF)");
                                        break;
                                }
 
-                               if (!(eattr & DEFINED))
-                               {
-                                       if (w & FU_PCREL)
-                                               w = MPCREL | MWORD;
-                                       else
-                                               w = MWORD;
+                               locp[1] |= eval >> 8;
+                               locp[2] = eval & 0xFF;
+                               break;
 
-                                       rmark(sno, loc, 0, w, esym);
-                               }
-                               else
+                       // This is a full DSP word containing Effective Address Extension
+                       case FU_DSPADR24:
+                       case FU_DSPIMM24:
+                               if (eval >= 0x1000000)
                                {
-                                       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;
-                                       }
+                                       error("value out of range ($0-$FFFFFF)");
+                                       break;
                                }
 
-                               *locp++ = (char)(eval >> 8);
-                               *locp = (char)eval;
+                               locp[0] = (uint8_t)((eval >> 16) & 0xFF);
+                               locp[1] = (uint8_t)((eval >> 8) & 0xFF);
+                               locp[2] = (uint8_t)(eval & 0xFF);
                                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)
+
+                       // This is a 16bit absolute address into a 24bit field
+                       case FU_DSPADR16:
+                               if (eval >= 0x10000)
                                {
-                                       address = loc + 4;
+                                       error("address out of range ($0-$FFFF)");
+                                       break;
+                               }
 
-                                       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;
-                                                       }
-                                               }
-                                       }
+                               locp[1] = (uint8_t)(eval >> 8);
+                               locp[2] = (uint8_t)eval;
+                               break;
 
-                                       eval = ((eval >> 16) & 0x0000FFFF) | ((eval << 16) & 0xFFFF0000);
-                                       flags = (MLONG|MMOVEI);
+                       // This is 12-bit immediate short data
+                       // The upper nibble goes into the last byte's low nibble
+                       // while the remainder 8 bits go into the 2nd byte.
+                       case FU_DSPIMM12:
+                               if (eval >= 0x1000)
+                               {
+                                       error("immediate out of range ($0-$FFF)");
+                                       break;
                                }
-                               else
-                                       flags = MLONG;
 
-                               if (!(eattr & DEFINED))
+                               locp[1] = (uint8_t)eval;
+                               locp[2] |= (uint8_t)(eval >> 8);
+                               break;
+
+                       // This is 8-bit immediate short data
+                       // which goes into the middle byte of a DSP word.
+                       case FU_DSPIMM8:
+                               if (eval >= 0x100)
                                {
-                                       rmark(sno, loc, 0, flags, esym);
+                                       error("immediate out of range ($0-$FF)");
+                                       break;
                                }
-                               else if (tdb)
+
+                               locp[1] = (uint8_t)eval;
+                               break;
+
+                       // This is a 6 bit absoulte short address. It occupies
+                       // the low 6 bits of the middle byte of a DSP word.
+                       case FU_DSPADR06:
+                               if (eval > 63)
                                {
-                                       rmark(sno, loc, tdb, flags, NULL);
+                                       error("address must be between 0 and 63");
+                                       break;
                                }
 
-                               *locp++ = (char)(eval >> 24);
-                               *locp++ = (char)(eval >> 16);
-                               *locp++ = (char)(eval >> 8);
-                               *locp = (char)eval;
+                               locp[1] |= 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))
+
+                       // This is a 6 bit absoulte short address. It occupies
+                       // the low 6 bits of the middle byte of a DSP word.
+                       case FU_DSPPP06:
+                               if (eval < 0xFFFFFFC0)
                                {
-                                       error("External quick reference");
-                                       continue;
+                                       error("address must be between $FFC0 and $FFFF");
+                                       break;
                                }
 
-                               if (eval < 1 || eval > 8)
-                                       goto range;
+                               locp[1] |= eval & 0x3F;
+                               break;
 
-                               *locp |= (eval & 7) << 1;
+                       // Shamus: I'm pretty sure these don't make any sense...
+                       case FU_DSPIMMFL8:
+                               warn("FU_DSPIMMFL8 missing implementation\n%s", "And you may ask yourself, \"Self, how did I get here?\"");
                                break;
-                       // Fix up 6502 funny branch
-                       case FU_6BRA:
-                               eval -= (loc + 1);
 
-                               if (eval + 0x80 >= 0x100)
-                                       goto range;
+                       case FU_DSPIMMFL16:
+                               warn("FU_DSPIMMFL16 missing implementation\n%s", "And you may ask yourself, \"Self, how did I get here?\"");
+                               break;
 
-                               *locp = (char)eval;
+                       case FU_DSPIMMFL24:
+                               warn("FU_DSPIMMFL24 missing implementation\n%s", "And you may ask yourself, \"Self, how did I get here?\"");
                                break;
+
+                       // Bad fixup type--this should *never* happen!
                        default:
-                               interror(4);                                 // Bad fixup type
+                               interror(4);
                                // NOTREACHED
                        }
-                       continue;
-range:
-                       error("expression out of range");
+                       break;
+
+               // Fixup a 4-byte float
+               case FU_FLOATSING:
+                       warn("FU_FLOATSING missing implementation\n%s", "And you may ask yourself, \"Self, how did I get here?\"");
+                       break;
+
+               // Fixup a 8-byte float
+               case FU_FLOATDOUB:
+                       warn("FU_FLOATDOUB missing implementation\n%s", "And you may ask yourself, \"Self, how did I get here?\"");
+                       break;
+
+               // Fixup a 12-byte float
+               case FU_FLOATEXT:
+                       warn("FU_FLOATEXT missing implementation\n%s", "And you may ask yourself, \"Self, how did I get here?\"");
+                       break;
+
+               default:
+                       // Bad fixup type--this should *never* happen!
+                       // Once we call this function, it winds down immediately; it
+                       // doesn't return.
+                       interror(4);
                }
 
-               ch = ch->chnext;
+               continue;
+rangeErr:
+               error("expression out of range");
        }
-       while (ch != NULL);
 
        return 0;
 }
+
+
+//
+// Resolve all fixups
+//
+int ResolveAllFixups(void)
+{
+       // Make undefined symbols GLOBL
+       if (glob_flag)
+               ForceUndefinedSymbolsGlobal();
+
+       DEBUG printf("Resolving TEXT sections...\n");
+       ResolveFixups(TEXT);
+       DEBUG printf("Resolving DATA sections...\n");
+       ResolveFixups(DATA);
+       DEBUG printf("Resolving 6502 sections...\n");
+       ResolveFixups(M6502);           // Fixup 6502 section (if any)
+       DEBUG printf("Resolving DSP56001 P: sections...\n");
+       ResolveFixups(M56001P);         // Fixup 56001 P: section (if any)
+       DEBUG printf("Resolving DSP56001 X: sections...\n");
+       ResolveFixups(M56001X);         // Fixup 56001 X: section (if any)
+       DEBUG printf("Resolving DSP56001 Y: sections...\n");
+       ResolveFixups(M56001Y);         // Fixup 56001 Y: section (if any)
+
+       return 0;
+}
+