Slight revamp of the optimisation system, featuring: strengthened flag parser, slight...
[rmac] / sect.c
diff --git a/sect.c b/sect.c
index 2269403e2b68e3426e843a9cb0569d5aa3b58637..cdf53ffc1ab5e650848211a030931580eb349a11 100644 (file)
--- a/sect.c
+++ b/sect.c
@@ -1,7 +1,7 @@
 //
 // RMAC - Reboot's Macro Assembler for all Atari computers
 // SECT.C - Code Generation, Fixups and Section Management
-// Copyright (C) 199x Landon Dyer, 2011-2018 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
 //
@@ -9,6 +9,7 @@
 #include "sect.h"
 #include "6502.h"
 #include "direct.h"
+#include "dsp56k.h"
 #include "error.h"
 #include "expr.h"
 #include "listing.h"
@@ -75,11 +76,14 @@ void InitSection(void)
                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(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);
@@ -91,12 +95,12 @@ void InitSection(void)
 //
 void MakeSection(int sno, uint16_t attr)
 {
-       SECT * p = &sect[sno];
-       p->scattr = attr;
-       p->sloc = 0;
-       p->orgaddr = 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;
 }
 
 
@@ -108,15 +112,15 @@ void SwitchSection(int sno)
 {
        CHUNK * cp;
        cursect = sno;
-       SECT * p = &sect[sno];
+       SECT * sp = &sect[sno];
 
        m6502 = (sno == M6502); // Set 6502-mode flag
 
        // Copy section vars
-       scattr = p->scattr;
-       sloc = p->sloc;
-       scode = p->scode;
-       orgaddr = p->orgaddr;
+       scattr = sp->scattr;
+       sloc = sp->sloc;
+       scode = sp->scode;
+       orgaddr = sp->orgaddr;
 
        // Copy code chunk vars
        if ((cp = scode) != NULL)
@@ -126,6 +130,16 @@ void SwitchSection(int sno)
                chptr = cp->chptr + ch_size;
 
                // 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
+
+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.
+
+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;
        }
@@ -139,13 +153,13 @@ void SwitchSection(int sno)
 //
 void SaveSection(void)
 {
-       SECT * p = &sect[cursect];
+       SECT * sp = &sect[cursect];
 
-       p->scattr = scattr;                             // Bailout section vars
-       p->sloc = sloc;
-       p->orgaddr = orgaddr;
+       sp->scattr = scattr;                    // Bailout section vars
+       sp->sloc = sloc;
+       sp->orgaddr = orgaddr;
 
-       if (scode != NULL)                              // Bailout code chunk
+       if (scode != NULL)                              // Bailout code chunk (if any)
                scode->ch_size = ch_size;
 }
 
@@ -204,29 +218,43 @@ void chcheck(uint32_t 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
        }
 
        // 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 = ((uint8_t *)cp) + sizeof(CHUNK);
        scode = p->scode = cp;
 
+       // 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;
 }
 
@@ -256,6 +284,15 @@ int AddFixup(uint32_t attr, uint32_t loc, TOKEN * fexpr)
                exprlen = ExpressionLength(fexpr);
        }
 
+       // 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)
+       {
+               attr |= FU_56001;
+               // Save the exact spot in this chunk where the fixup should go
+               _orgaddr = chptr - scode->chptr + scode->chloc;
+       }
+
        // Allocate space for the fixup + any expression
        FIXUP * fixup = malloc(sizeof(FIXUP) + (sizeof(TOKEN) * exprlen));
 
@@ -290,7 +327,7 @@ int AddFixup(uint32_t attr, uint32_t loc, TOKEN * fexpr)
 
        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);
+                       printf("          name: %s, value: $%lX\n", symbol->sname, symbol->svalue);
        }
 
        return 0;
@@ -324,7 +361,7 @@ int ResolveFixups(int sno)
                FIXUP * fup = fixup;
                fixup = fixup->next;
 
-               uint32_t w = fup->attr;         // Fixup long (type + modes + flags)
+               uint32_t dw = fup->attr;        // Fixup long (type + modes + flags)
                uint32_t loc = fup->loc;        // Location to fixup
                cfileno = fup->fileno;
                curlineno = fup->lineno;
@@ -335,6 +372,9 @@ int ResolveFixups(int sno)
                // 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
@@ -370,10 +410,20 @@ int ResolveFixups(int sno)
                // Compute expression/symbol value and attributes
 
                // Complex expression
-               if (w & FU_EXPR)
+               if (dw & FU_EXPR)
                {
+                       // evexpr presumably issues the errors/warnings here
                        if (evexpr(fup->expr, &eval, &eattr, &esym) != OK)
                                continue;
+
+                       if (CHECK_OPTS(OPT_PC_RELATIVE))
+                               if (eattr & REFERENCED)
+                                       if (eattr & DEFINED)
+                                               if (!(eattr & EQUATED))
+                                               {
+                                                       error("relocation not allowed");
+                                                       continue;
+                                               }
                }
                // Simple symbol
                else
@@ -381,6 +431,15 @@ int ResolveFixups(int sno)
                        SYM * sy = fup->symbol;
                        eattr = sy->sattr;
 
+                       if (CHECK_OPTS(OPT_PC_RELATIVE))
+                               if (eattr & REFERENCED)
+                                       if (eattr & DEFINED)
+                                               if (!(eattr & EQUATED))
+                                               {
+                                                       error("relocation not allowed");
+                                                       continue;
+                                               }
+
                        if (eattr & DEFINED)
                                eval = sy->svalue;
                        else
@@ -389,6 +448,8 @@ int ResolveFixups(int sno)
                        // If the symbol is not defined, but global, set esym to sy
                        if ((eattr & (GLOBAL | DEFINED)) == GLOBAL)
                                esym = sy;
+
+                       DEBUG { printf("               name: %s, value: $%" PRIX64 "\n", sy->sname, sy->svalue); }
                }
 
                uint16_t tdb = eattr & TDB;
@@ -407,21 +468,24 @@ int ResolveFixups(int sno)
                // 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 ((dw & FU_PCREL) || (dw & FU_PCRELX))
                {
                        if (eattr & DEFINED)
                        {
                                if (tdb == sno)
+                               {
                                        eval -= loc;
+
+                                       // In this instruction the PC is located a DWORD away
+                                       if (dw & FU_PCRELX)
+                                               eval += 2;
+                               }
                                else if (tdb)
                                {
                                        // Allow cross-section PCREL fixups in Alcyon mode
-                                       if (prg_flag)
+                                       if (prg_flag || (obj_format == RAW))
                                        {
                                                switch (tdb)
                                                {
@@ -440,6 +504,10 @@ int ResolveFixups(int sno)
                                                }
 
                                                eval -= loc;
+
+                                               // In this instruction the PC is located a DWORD away
+                                               if (dw & FU_PCRELX)
+                                                       eval += 2;
                                        }
                                        else
                                        {
@@ -448,18 +516,17 @@ int ResolveFixups(int sno)
                                        }
                                }
 
-                               if (sbra_flag && (w & FU_LBRA) && (eval + 0x80 < 0x100))
+                               if (optim_warn_flag && (dw & FU_LBRA) && (eval + 0x80 < 0x100))
                                        warn("unoptimized short branch");
                        }
-                       else if (obj_format == MWC)
-                               eval -= loc;
 
+                       // Be sure to clear any TDB flags, since we handled it just now
                        tdb = 0;
                        eattr &= ~TDB;
                }
 
                // Handle fixup classes
-               switch (w & FUMASK)
+               switch (dw & FUMASK)
                {
                // FU_BBRA fixes up a one-byte branch offset.
                case FU_BBRA:
@@ -476,11 +543,13 @@ int ResolveFixups(int sno)
 
                        if (eval == 0)
                        {
-                               if (CHECK_OPTS(OPT_NULL_BRA))
+                               if (*locp) // optim_flags[OPT_NULL_BRA] is stored there, check the comment in mach.s under m_br
                                {
                                        // Just output a NOP
                                        *locp++ = 0x4E;
                                        *locp = 0x71;
+                                       if (optim_warn_flag)
+                                               warn("bra.s with zero offset converted to NOP");
                                        continue;
                                }
                                else
@@ -512,10 +581,10 @@ int ResolveFixups(int sno)
                                continue;
                        }
 
-                       if ((w & FU_PCREL) && ((eval + 0x80) >= 0x100))
+                       if ((dw & FU_PCREL) && ((eval + 0x80) >= 0x100))
                                goto rangeErr;
 
-                       if (w & FU_SEXT)
+                       if (dw & FU_SEXT)
                        {
                                if ((eval + 0x100) >= 0x200)
                                        goto rangeErr;
@@ -548,16 +617,11 @@ int ResolveFixups(int sno)
                        break;
 
                // Fixup WORD forward references; the word could be unaligned in the
-               // section buffer, so we have to be careful.
+               // section buffer, so we have to be careful. (? careful about what?)
                case FU_WORD:
-                       if ((w & FUMASKRISC) == FU_JR)
+                       if ((dw & FUMASKRISC) == FU_JR)
                        {
-                               int reg;
-
-                               if (fup->orgaddr)
-                                       reg = (signed)((eval - (fup->orgaddr + 2)) / 2);
-                               else
-                                       reg = (signed)((eval - (loc + 2)) / 2);
+                               int reg = (signed)((eval - ((fup->orgaddr ? fup->orgaddr : loc) + 2)) / 2);
 
                                if ((reg < -16) || (reg > 15))
                                {
@@ -570,7 +634,7 @@ int ResolveFixups(int sno)
                                *locp |= ((uint8_t)reg & 0x07) << 5;
                                break;
                        }
-                       else if ((w & FUMASKRISC) == FU_NUM15)
+                       else if ((dw & FUMASKRISC) == FU_NUM15)
                        {
                                if (((int)eval < -16) || ((int)eval > 15))
                                {
@@ -583,7 +647,7 @@ int ResolveFixups(int sno)
                                *locp |= ((uint8_t)eval & 0x07) << 5;
                                break;
                        }
-                       else if ((w & FUMASKRISC) == FU_NUM31)
+                       else if ((dw & FUMASKRISC) == FU_NUM31)
                        {
                                if (eval > 31)
                                {
@@ -596,7 +660,7 @@ int ResolveFixups(int sno)
                                *locp |= ((uint8_t)eval & 0x07) << 5;
                                break;
                        }
-                       else if ((w & FUMASKRISC) == FU_NUM32)
+                       else if ((dw & FUMASKRISC) == FU_NUM32)
                        {
                                if ((eval < 1) || (eval > 32))
                                {
@@ -604,7 +668,7 @@ int ResolveFixups(int sno)
                                        break;
                                }
 
-                               if (w & FU_SUB32)
+                               if (dw & FU_SUB32)
                                        eval = (32 - eval);
 
                                eval = (eval == 32) ? 0 : eval;
@@ -613,7 +677,7 @@ int ResolveFixups(int sno)
                                *locp |= ((uint8_t)eval & 0x07) << 5;
                                break;
                        }
-                       else if ((w & FUMASKRISC) == FU_REGONE)
+                       else if ((dw & FUMASKRISC) == FU_REGONE)
                        {
                                if (eval > 31)
                                {
@@ -626,7 +690,7 @@ int ResolveFixups(int sno)
                                *locp |= ((uint8_t)eval & 0x07) << 5;
                                break;
                        }
-                       else if ((w & FUMASKRISC) == FU_REGTWO)
+                       else if ((dw & FUMASKRISC) == FU_REGTWO)
                        {
                                if (eval > 31)
                                {
@@ -643,7 +707,7 @@ int ResolveFixups(int sno)
                        {
                                flags = MWORD;
 
-                               if (w & FU_PCREL)
+                               if (dw & FU_PCREL)
                                        flags |= MPCREL;
 
                                MarkRelocatable(sno, loc, 0, flags, esym);
@@ -653,7 +717,7 @@ int ResolveFixups(int sno)
                                if (tdb)
                                        MarkRelocatable(sno, loc, tdb, MWORD, NULL);
 
-                               if (w & FU_SEXT)
+                               if (dw & FU_SEXT)
                                {
                                        if (eval + 0x10000 >= 0x20000)
                                                goto rangeErr;
@@ -661,7 +725,7 @@ int ResolveFixups(int sno)
                                else
                                {
                                        // Range-check BRA and DBRA
-                                       if (w & FU_ISBRA)
+                                       if (dw & FU_ISBRA)
                                        {
                                                if (eval + 0x8000 >= 0x10000)
                                                        goto rangeErr;
@@ -679,13 +743,12 @@ int ResolveFixups(int sno)
 
                        break;
 
-               // Fixup LONG forward references;
-               // the long could be unaligned in the section buffer, so be careful
-               // (again).
+               // Fixup LONG forward references; the long could be unaligned in the
+               // section buffer, so be careful (again).
                case FU_LONG:
                        flags = MLONG;
 
-                       if ((w & FUMASKRISC) == FU_MOVEI)
+                       if ((dw & FUMASKRISC) == FU_MOVEI)
                        {
                                // Long constant in MOVEI # is word-swapped, so fix it here
                                eval = WORDSWAP32(eval);
@@ -702,6 +765,39 @@ int ResolveFixups(int sno)
                        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;
+
+//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:
@@ -727,6 +823,131 @@ int ResolveFixups(int sno)
                        *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;
+                               }
+
+                               locp[2] |= eval;
+                               break;
+
+                       // 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;
+                               }
+
+                               locp[1] |= eval >> 8;
+                               locp[2] = eval & 0xFF;
+                               break;
+
+                       // This is a full DSP word containing Effective Address Extension
+                       case FU_DSPADR24:
+                       case FU_DSPIMM24:
+                               if (eval >= 0x1000000)
+                               {
+                                       error("value out of range ($0-$FFFFFF)");
+                                       break;
+                               }
+
+                               locp[0] = (uint8_t)((eval >> 16) & 0xFF);
+                               locp[1] = (uint8_t)((eval >> 8) & 0xFF);
+                               locp[2] = (uint8_t)(eval & 0xFF);
+                               break;
+
+                       // This is a 16bit absolute address into a 24bit field
+                       case FU_DSPADR16:
+                               if (eval >= 0x10000)
+                               {
+                                       error("address out of range ($0-$FFFF)");
+                                       break;
+                               }
+
+                               locp[1] = (uint8_t)(eval >> 8);
+                               locp[2] = (uint8_t)eval;
+                               break;
+
+                       // 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;
+                               }
+
+                               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)
+                               {
+                                       error("immediate out of range ($0-$FF)");
+                                       break;
+                               }
+
+                               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)
+                               {
+                                       error("address must be between 0 and 63");
+                                       break;
+                               }
+
+                               locp[1] |= 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_DSPPP06:
+                               if (eval < 0xFFFFFFC0)
+                               {
+                                       error("address must be between $FFC0 and $FFFF");
+                                       break;
+                               }
+
+                               locp[1] |= eval & 0x3F;
+                               break;
+
+                       // 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;
+
+                       case FU_DSPIMMFL16:
+                               warn("FU_DSPIMMFL16 missing implementation\n%s", "And you may ask yourself, \"Self, how did I get here?\"");
+                               break;
+
+                       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);
+                               // NOTREACHED
+                       }
+                       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?\"");
@@ -773,6 +994,12 @@ int ResolveAllFixups(void)
        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;
 }