//
// 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
//
//
void MakeSection(int sno, uint16_t attr)
{
- SECT * p = §[sno];
- p->scattr = attr;
- p->sloc = 0;
- p->orgaddr = 0;
- p->scode = p->sfcode = NULL;
- p->sfix = p->sffix = NULL;
+ SECT * sp = §[sno];
+ sp->scattr = attr;
+ sp->sloc = 0;
+ sp->orgaddr = 0;
+ sp->scode = sp->sfcode = NULL;
+ sp->sfix = sp->sffix = NULL;
}
{
CHUNK * cp;
cursect = sno;
- SECT * p = §[sno];
+ SECT * sp = §[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)
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;
}
//
void SaveSection(void)
{
- SECT * p = §[cursect];
+ SECT * sp = §[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;
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));
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;
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;
// 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;
//
// 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)
{
if (eattr & DEFINED)
{
}
}
- 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)
}
// Handle fixup classes
- switch (w & FUMASK)
+ switch (dw & FUMASK)
{
// FU_BBRA fixes up a one-byte branch offset.
case FU_BBRA:
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;
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)
{
+#if 0
int reg;
if (fup->orgaddr)
reg = (signed)((eval - (fup->orgaddr + 2)) / 2);
else
reg = (signed)((eval - (loc + 2)) / 2);
+#else
+ int reg = (signed)((eval - ((fup->orgaddr ? fup->orgaddr : loc) + 2)) / 2);
+#endif
if ((reg < -16) || (reg > 15))
{
*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))
{
*locp |= ((uint8_t)eval & 0x07) << 5;
break;
}
- else if ((w & FUMASKRISC) == FU_NUM31)
+ else if ((dw & FUMASKRISC) == FU_NUM31)
{
if (eval > 31)
{
*locp |= ((uint8_t)eval & 0x07) << 5;
break;
}
- else if ((w & FUMASKRISC) == FU_NUM32)
+ else if ((dw & FUMASKRISC) == FU_NUM32)
{
if ((eval < 1) || (eval > 32))
{
break;
}
- if (w & FU_SUB32)
+ if (dw & FU_SUB32)
eval = (32 - eval);
eval = (eval == 32) ? 0 : eval;
*locp |= ((uint8_t)eval & 0x07) << 5;
break;
}
- else if ((w & FUMASKRISC) == FU_REGONE)
+ else if ((dw & FUMASKRISC) == FU_REGONE)
{
if (eval > 31)
{
*locp |= ((uint8_t)eval & 0x07) << 5;
break;
}
- else if ((w & FUMASKRISC) == FU_REGTWO)
+ else if ((dw & FUMASKRISC) == FU_REGTWO)
{
if (eval > 31)
{
{
flags = MWORD;
- if (w & FU_PCREL)
+ if (dw & FU_PCREL)
flags |= MPCREL;
MarkRelocatable(sno, loc, 0, flags, esym);
if (tdb)
MarkRelocatable(sno, loc, tdb, MWORD, NULL);
- if (w & FU_SEXT)
+ if (dw & FU_SEXT)
{
if (eval + 0x10000 >= 0x20000)
goto rangeErr;
else
{
// Range-check BRA and DBRA
- if (w & FU_ISBRA)
+ if (dw & FU_ISBRA)
{
if (eval + 0x8000 >= 0x10000)
goto rangeErr;
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);
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:
*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