//
// 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).
+// 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.
//
-int chcheck(uint32_t amt)
+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); }
+ 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;
+ return;
if (amt < CH_CODE_SIZE)
amt = CH_CODE_SIZE;
{
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
chptr = cp->chptr = ((uint8_t *)cp) + sizeof(CHUNK);
scode = p->scode = cp;
- return 0;
+ return;
}
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;
//
-// 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 = §[sno];
// "Cache" first chunk
FIXUP * fup = fixup;
fixup = fixup->next;
- uint32_t w = fup->attr; // Fixup long (type+modes+flags)
+ uint32_t w = fup->attr; // Fixup long (type + modes + flags)
uint32_t loc = fup->loc; // Location to fixup
cfileno = fup->fileno;
curlineno = fup->lineno;
// 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
// 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).
+ // 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)
continue;
}
- *locp = (uint8_t)((eval >> 8) & 0xFF);
+ *locp = (uint8_t)(eval >> 8);
break;
case FU_BYTEL:
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.
case FU_WORD:
if ((w & FUMASKRISC) == FU_JR)
{
+ 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);
- 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)
{
- 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)
{
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)
{
- if (eval < 1 || eval > 32)
+ if ((eval < 1) || (eval > 32))
{
- error("constant out of range");
+ error("constant out of range (1-32)");
break;
}
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)
{
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)
{
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;
}
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;
SETBE32(locp, 0, eval);
break;
+ // Fixup QUAD forward references (mainly used by the OP assembler)
+ case FU_QUAD:
+ if (w & FU_OBJLINK)
+ {
+ uint64_t quad = GETBE64(locp, 0);
+ uint64_t addr = eval;
+
+ if (fup->orgaddr)
+ addr = fup->orgaddr;
+
+
+ eval = (quad & 0xFFFFFC0000FFFFFFLL) | ((addr & 0x3FFFF8) << 21);
+ }
+ else if (w & 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;
+
+ 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 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