]> Shamusworld >> Repos - rmac/blobdiff - sect.c
Added in DSP fixups to sect.c, misc. fixes for 6502 assembler.
[rmac] / sect.c
diff --git a/sect.c b/sect.c
index 95f9747f7d8d3d3a54556d4db242bf5925583e07..9c1a586b18dbd68d92bf3b06cf9edf72e2432776 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-2019 Reboot and Friends
 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
 // Source utilised with the kind permission of Landon Dyer
 //
@@ -91,12 +91,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 +108,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 +126,12 @@ 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 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 piss poor way to handle things, and for fucks sake, we can do better than this!
+*/
                if (m6502)
                        chptr = cp->chptr + orgaddr;
        }
@@ -139,11 +145,11 @@ 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
                scode->ch_size = ch_size;
@@ -256,6 +262,14 @@ 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;
+               _orgaddr = orgaddr;
+       }
+
        // Allocate space for the fixup + any expression
        FIXUP * fixup = malloc(sizeof(FIXUP) + (sizeof(TOKEN) * exprlen));
 
@@ -290,7 +304,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;
@@ -298,14 +312,10 @@ int AddFixup(uint32_t attr, uint32_t loc, TOKEN * fexpr)
 
 
 //
-// Resolve fixups in a section
+// Resolve fixups in the passed in section
 //
 int ResolveFixups(int sno)
 {
-       uint64_t eval;                  // Expression value
-       int reg2;
-       uint16_t flags;
-
        SECT * sc = &sect[sno];
 
        // "Cache" first chunk
@@ -328,7 +338,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;
@@ -365,13 +375,16 @@ int ResolveFixups(int sno)
                // 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
 
                // Compute expression/symbol value and attributes
 
                // Complex expression
-               if (w & FU_EXPR)
+               if (dw & FU_EXPR)
                {
                        if (evexpr(fup->expr, &eval, &eattr, &esym) != OK)
                                continue;
@@ -404,18 +417,16 @@ int ResolveFixups(int sno)
 
                // 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).
+               // 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).
+               // 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)
+               // 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)
                {
                        if (eattr & DEFINED)
                        {
@@ -451,7 +462,7 @@ int ResolveFixups(int sno)
                                        }
                                }
 
-                               if (sbra_flag && (w & FU_LBRA) && (eval + 0x80 < 0x100))
+                               if (sbra_flag && (dw & FU_LBRA) && (eval + 0x80 < 0x100))
                                        warn("unoptimized short branch");
                        }
                        else if (obj_format == MWC)
@@ -462,7 +473,7 @@ int ResolveFixups(int sno)
                }
 
                // Handle fixup classes
-               switch (w & FUMASK)
+               switch (dw & FUMASK)
                {
                // FU_BBRA fixes up a one-byte branch offset.
                case FU_BBRA:
@@ -515,10 +526,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;
@@ -537,7 +548,7 @@ int ResolveFixups(int sno)
                                continue;
                        }
 
-                       *locp = (uint8_t)((eval >> 8) & 0xFF);
+                       *locp = (uint8_t)(eval >> 8);
                        break;
 
                case FU_BYTEL:
@@ -547,96 +558,102 @@ int ResolveFixups(int sno)
                                continue;
                        }
 
-                       *locp = (uint8_t)(eval & 0xFF);
+                       *locp = (uint8_t)eval;
                        break;
 
-               // Fixup WORD forward references; the word could be unaligned in
-               // the section buffer, so we have to be careful.
+               // 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 ((w & FUMASKRISC) == FU_JR)
+                       if ((dw & FUMASKRISC) == FU_JR)
                        {
+#if 0
+                               int reg;
+
                                if (fup->orgaddr)
-                                       reg2 = (signed)((eval - (fup->orgaddr + 2)) / 2);
+                                       reg = (signed)((eval - (fup->orgaddr + 2)) / 2);
                                else
-                                       reg2 = (signed)((eval - (loc + 2)) / 2);
+                                       reg = (signed)((eval - (loc + 2)) / 2);
+#else
+                               int reg = (signed)((eval - ((fup->orgaddr ? fup->orgaddr : loc) + 2)) / 2);
+#endif
 
-                               if ((reg2 < -16) || (reg2 > 15))
+                               if ((reg < -16) || (reg > 15))
                                {
                                        error("relative jump out of range");
                                        break;
                                }
 
-                               *locp = (uint8_t)(*locp | ((reg2 >> 3) & 0x03));
+                               *locp |= ((uint8_t)reg >> 3) & 0x03;
                                locp++;
-                               *locp = (uint8_t)(*locp | ((reg2 & 0x07) << 5));
+                               *locp |= ((uint8_t)reg & 0x07) << 5;
                                break;
                        }
-                       else if ((w & FUMASKRISC) == FU_NUM15)
+                       else if ((dw & FUMASKRISC) == FU_NUM15)
                        {
-                               if (eval < -16 || eval > 15)
+                               if (((int)eval < -16) || ((int)eval > 15))
                                {
-                                       error("constant out of range");
+                                       error("constant out of range (-16 - +15)");
                                        break;
                                }
 
-                               *locp = (uint8_t)(*locp | ((eval >> 3) & 0x03));
+                               *locp |= ((uint8_t)eval >> 3) & 0x03;
                                locp++;
-                               *locp = (uint8_t)(*locp | ((eval & 0x07) << 5));
+                               *locp |= ((uint8_t)eval & 0x07) << 5;
                                break;
                        }
-                       else if ((w & FUMASKRISC) == FU_NUM31)
+                       else if ((dw & FUMASKRISC) == FU_NUM31)
                        {
                                if (eval > 31)
                                {
-                                       error("constant out of range");
+                                       error("constant out of range (0-31)");
                                        break;
                                }
 
-                               *locp = (uint8_t)(*locp | ((eval >> 3) & 0x03));
+                               *locp |= ((uint8_t)eval >> 3) & 0x03;
                                locp++;
-                               *locp = (uint8_t)(*locp | ((eval & 0x07) << 5));
+                               *locp |= ((uint8_t)eval & 0x07) << 5;
                                break;
                        }
-                       else if ((w & FUMASKRISC) == FU_NUM32)
+                       else if ((dw & FUMASKRISC) == FU_NUM32)
                        {
-                               if (eval < 1 || eval > 32)
+                               if ((eval < 1) || (eval > 32))
                                {
-                                       error("constant out of range");
+                                       error("constant out of range (1-32)");
                                        break;
                                }
 
-                               if (w & FU_SUB32)
+                               if (dw & FU_SUB32)
                                        eval = (32 - eval);
 
                                eval = (eval == 32) ? 0 : eval;
-                               *locp = (uint8_t)(*locp | ((eval >> 3) & 0x03));
+                               *locp |= ((uint8_t)eval >> 3) & 0x03;
                                locp++;
-                               *locp = (uint8_t)(*locp | ((eval & 0x07) << 5));
+                               *locp |= ((uint8_t)eval & 0x07) << 5;
                                break;
                        }
-                       else if ((w & FUMASKRISC) == FU_REGONE)
+                       else if ((dw & FUMASKRISC) == FU_REGONE)
                        {
                                if (eval > 31)
                                {
-                                       error("register value out of range");
+                                       error("register one value out of range");
                                        break;
                                }
 
-                               *locp = (uint8_t)(*locp | ((eval >> 3) & 0x03));
+                               *locp |= ((uint8_t)eval >> 3) & 0x03;
                                locp++;
-                               *locp = (uint8_t)(*locp | ((eval & 0x07) << 5));
+                               *locp |= ((uint8_t)eval & 0x07) << 5;
                                break;
                        }
-                       else if ((w & FUMASKRISC) == FU_REGTWO)
+                       else if ((dw & FUMASKRISC) == FU_REGTWO)
                        {
                                if (eval > 31)
                                {
-                                       error("register value out of range");
+                                       error("register two value out of range");
                                        break;
                                }
 
                                locp++;
-                               *locp = (uint8_t)(*locp | (eval & 0x1F));
+                               *locp |= (uint8_t)eval & 0x1F;
                                break;
                        }
 
@@ -644,7 +661,7 @@ int ResolveFixups(int sno)
                        {
                                flags = MWORD;
 
-                               if (w & FU_PCREL)
+                               if (dw & FU_PCREL)
                                        flags |= MPCREL;
 
                                MarkRelocatable(sno, loc, 0, flags, esym);
@@ -654,7 +671,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;
@@ -662,7 +679,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;
@@ -680,13 +697,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);
@@ -703,6 +719,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:
@@ -728,6 +777,146 @@ 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 ($000-$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 >= 0x100000)
+                               {
+                                       error("value out of range ($000-$FFFFFF)");
+                                       break;
+                               }
+
+                               *locp++ = (uint32_t)eval >> 16;
+                               *locp++ = ((uint32_t)eval >> 8) & 0xFF;
+                               *locp++ = (uint32_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 ($0000-$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 ($000-$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 ($00-$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?\"");
+                       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