X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=sect.c;h=49806a02b9d4e8d7570b19b5d27f35ca89b6dc86;hp=59f7977160b11dee3d3057e050f166f426bc74ea;hb=29fa5dcf504b966803063a1c2891f58f97126d04;hpb=b93a2e2f8ade36a09709b4a72b10f3e8228bed2b diff --git a/sect.c b/sect.c index 59f7977..49806a0 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 // @@ -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 = §[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 +112,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 +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,11 +153,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 +270,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; + } + // Allocate space for the fixup + any expression FIXUP * fixup = malloc(sizeof(FIXUP) + (sizeof(TOKEN) * exprlen)); @@ -324,7 +347,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 +358,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,7 +396,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 +438,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 +474,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 +485,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 +538,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 +574,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 +591,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 +604,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 +617,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 +625,7 @@ int ResolveFixups(int sno) break; } - if (w & FU_SUB32) + if (dw & FU_SUB32) eval = (32 - eval); eval = (eval == 32) ? 0 : eval; @@ -613,7 +634,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 +647,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 +664,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 +674,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 +682,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; @@ -684,7 +705,7 @@ int ResolveFixups(int sno) 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,18 +724,18 @@ int ResolveFixups(int sno) // Fixup QUAD forward references (mainly used by the OP assembler) case FU_QUAD: - if (w & FU_OBJLINK) + if (dw & FU_OBJLINK) { uint64_t quad = GETBE64(locp, 0); uint64_t addr = eval; - if (fup->orgaddr) - addr = fup->orgaddr; - +//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 (w & FU_OBJDATA) + else if (dw & FU_OBJDATA) { // If it's in a TEXT or DATA section, be sure to mark for a // fixup later @@ -724,8 +745,9 @@ int ResolveFixups(int sno) uint64_t quad = GETBE64(locp, 0); uint64_t addr = eval; - if (fup->orgaddr) - addr = fup->orgaddr; +//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); } @@ -758,6 +780,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?\""); @@ -804,6 +951,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; }