X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=sect.c;h=9c1a586b18dbd68d92bf3b06cf9edf72e2432776;hp=26fe2f95f304a84e9139de36bfb0c196ffced331;hb=bdbf34766f4d074a5933eb1326fe4ce03d249e10;hpb=fe673c9fe1498448453f74d753e7dd4c8655e1b1 diff --git a/sect.c b/sect.c index 26fe2f9..9c1a586 100644 --- 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 = §[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; } @@ -108,15 +108,15 @@ void SwitchSection(int sno) { 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) @@ -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 = §[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; @@ -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; @@ -324,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; @@ -370,7 +384,7 @@ int ResolveFixups(int sno) // 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; @@ -412,7 +426,7 @@ int ResolveFixups(int sno) // // 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) { @@ -448,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) @@ -459,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: @@ -512,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; @@ -548,16 +562,20 @@ 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) { +#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)) { @@ -570,7 +588,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 +601,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 +614,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 +622,7 @@ int ResolveFixups(int sno) break; } - if (w & FU_SUB32) + if (dw & FU_SUB32) eval = (32 - eval); eval = (eval == 32) ? 0 : eval; @@ -613,7 +631,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 +644,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 +661,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 +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; @@ -661,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; @@ -679,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); @@ -702,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: @@ -727,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