From: Shamus Hammons Date: Fri, 14 Apr 2017 20:52:31 +0000 (-0500) Subject: ELF support for RMAC. X-Git-Tag: v2.1.0~146 X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=commitdiff_plain;h=60f204cb9e3905100da0d89f14bb40db764acd9e;hp=1feb728a9eb579b6441daf0124d81483f600365c ELF support for RMAC. ggn deserves most of the credit for this, as my job was going through and tossing out the stuff that wasn't needed. ;-) There might be some ELFish things that still need fixing; time, as usual, will tell. --- diff --git a/68kgen.c b/68kgen.c index c5ea85f..a51b105 100644 --- a/68kgen.c +++ b/68kgen.c @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // 68KGEN.C - Tool to Generate 68000 Opcode Table -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // diff --git a/Vs2015/rmac/rmac.vcxproj b/Vs2015/rmac/rmac.vcxproj index e03e65d..a127bd8 100644 --- a/Vs2015/rmac/rmac.vcxproj +++ b/Vs2015/rmac/rmac.vcxproj @@ -110,7 +110,7 @@ true - $(SolutionDir)\..\ + $(SolutionDir)\.. true diff --git a/amode.c b/amode.c index b09b2da..f0734ea 100644 --- a/amode.c +++ b/amode.c @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // AMODE.C - Addressing Modes -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -78,7 +78,7 @@ int amode(int acount) #define CHK_FOR_DISPn CheckForDisp0 #include "parmode.h" - // If caller wants only one mode, return just one (ignore comma); + // If caller wants only one mode, return just one (ignore comma); // If there is no second addressing mode (no comma), then return just one anyway. nmodes = 1; @@ -146,7 +146,7 @@ int reglist(WORD * a_rmask) if (*tok >= KW_D0 && *tok <= KW_A7) cnt = *tok++ & 15; - else + else return error("register list syntax"); if (cnt < r) @@ -154,7 +154,7 @@ int reglist(WORD * a_rmask) cnt -= r; } - else + else cnt = 0; while (cnt-- >= 0) diff --git a/amode.h b/amode.h index eba0e5f..d0eb770 100644 --- a/amode.h +++ b/amode.h @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // AMODE.H - Addressing Modes -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -39,7 +39,7 @@ #define M_DREG 0x00000001L // Dn #define M_AREG 0x00000002L // An #define M_AIND 0x00000004L // (An) -#define M_APOSTINC 0x00000008L // (An)+ +#define M_APOSTINC 0x00000008L // (An)+ #define M_APREDEC 0x00000010L // -(An) #define M_ADISP 0x00000020L // (d16,An) d16(An) #define M_AINDEXED 0x00000040L // (d8,An,Xn) d8(An,Xn) diff --git a/debug.c b/debug.c index 7e60196..6359cfb 100644 --- a/debug.c +++ b/debug.c @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // DEBUG.C - Debugging Messages -// Copyright (C) 199x Landon Dyer, 2011-2012 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2011-2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -43,8 +43,7 @@ TOKEN * printexpr(TOKEN * tp) switch ((int)*tp++) { case SYMBOL: -// printf("`%s' ", ((SYM *)*tp)->sname); - printf("`%s' ", symbolPtr[*tp]->sname); + printf("'%s' ", symbolPtr[*tp]->sname); tp++; break; case CONST: @@ -61,7 +60,6 @@ TOKEN * printexpr(TOKEN * tp) } } -// printf(";\n"); return tp + 1; } @@ -88,28 +86,24 @@ int chdump(CHUNK * ch, int format) int fudump(CHUNK * ch) { PTR p; - char * ep; - WORD attr, esiz; - WORD line, file; - LONG loc; for(; ch!=NULL;) { p.cp = ch->chptr; - ep = ch->chptr + ch->ch_size; + uint8_t * ep = ch->chptr + ch->ch_size; while (p.cp < ep) { - attr = *p.wp++; - loc = *p.lp++; - file = *p.wp++; - line = *p.wp++; + uint16_t attr = *p.wp++; + uint32_t loc = *p.lp++; + uint16_t file = *p.wp++; + uint16_t line = *p.wp++; printf("$%04X $%08X %d.%d: ", (int)attr, loc, (int)file, (int)line); if (attr & FU_EXPR) { - esiz = *p.wp++; + uint16_t esiz = *p.wp++; printf("(%d long) ", (int)esiz); p.tk = printexpr(p.tk); } @@ -155,7 +149,7 @@ int mudump(void) mch, (mch->mcptr.lw), mch->mcalloc, (mch->mcused)); p = mch->mcptr; - + for(;;) { w = *p.wp++; @@ -192,7 +186,7 @@ int mudump(void) // 0 - bytes // 1 - words // 2 - longwords -// +// // if `base' is not -1, then print it at the start of each line, incremented // accordingly. // @@ -209,7 +203,7 @@ int mdump(char * start, LONG count, int flg, LONG base) { printf(" "); - while(j < i) + while (j < i) visprt(start[j++]); putchar('\n'); @@ -225,7 +219,7 @@ int mdump(char * start, LONG count, int flg, LONG base) { case 0: printf("%02X ", start[i] & 0xff); - ++i; + i++; break; case 1: printf("%02X%02X ", start[i] & 0xff, start[i+1] & 0xff); @@ -250,12 +244,12 @@ int mdump(char * start, LONG count, int flg, LONG base) { k = ((16 - (i - j)) / (1 << (flg & 3))) * siztab[flg & 3]; - while(k--) + while (k--) putchar(' '); printf(" "); - while(j < i) + while (j < i) visprt(start[j++]); putchar('\n'); @@ -291,34 +285,34 @@ int dumptok(TOKEN * tk) case STRING: // STRING
printf("STRING='%s'", string[*tk++]); break; - case SYMBOL: // SYMBOL
+ case SYMBOL: // SYMBOL
printf("SYMBOL='%s'", string[*tk++]); break; - case EOL: // End of line + case EOL: // End of line printf("EOL"); break; case TKEOF: // End of file (or macro) printf("TKEOF"); break; - case DEQUALS: // == + case DEQUALS: // == printf("DEQUALS"); break; - case DCOLON: // :: + case DCOLON: // :: printf("DCOLON"); break; - case GE: // >= + case GE: // >= printf("GE"); break; - case LE: // <= + case LE: // <= printf("LE"); break; - case NE: // <> or != + case NE: // <> or != printf("NE"); break; - case SHR: // >> + case SHR: // >> printf("SHR"); break; - case SHL: // << + case SHL: // << printf("SHL"); break; default: @@ -338,9 +332,7 @@ int dumptok(TOKEN * tk) // int dump_everything(void) { - int i; - - for(i=1; i 0 && buf1[j - 1] != SLASHCHAR) // Append path char if necessary + // Append path char if necessary + if (j > 0 && buf1[j - 1] != SLASHCHAR) strcat(buf1, SLASHSTRING); strcat(buf1, fn); @@ -727,7 +728,7 @@ int globl1(char * p) sy->sattr = GLOBAL; //printf("glob1: Making global symbol: attr=%04X, eattr=%08X, %s\n", sy->sattr, sy->sattre, sy->sname); } - else + else sy->sattr |= GLOBAL; return OK; @@ -846,7 +847,7 @@ int d_ds(WORD siz) if (as68_flag == 0 && (scattr & SBSS) == 0) return error(".ds permitted only in BSS"); - if (siz != SIZB && (sloc & 1)) // Automatic .even + if ((siz != SIZB) && (sloc & 1)) // Automatic .even auto_even(); if (abs_expr(&eval) != OK) @@ -865,7 +866,7 @@ int d_ds(WORD siz) listvalue(eval); eval *= siz; sloc += eval; - just_bss = 1; // No data deposited (8-bit CPU mode) + just_bss = 1; // No data deposited (8-bit CPU mode) } else { @@ -878,17 +879,13 @@ int d_ds(WORD siz) // -// dc.b, dc.w / dc, dc.l +// dc.b, dc.w / dc, dc.l, dc.i // int d_dc(WORD siz) { WORD eattr; VALUE eval; - WORD tdb; - WORD defined; - LONG i; - char * p; - int movei = 0; // movei flag for dc.i + uint8_t * p; if ((scattr & SBSS) != 0) return error("illegal initialization of section"); @@ -904,24 +901,26 @@ int d_dc(WORD siz) || (rdsp && (orgaddr >= 0xF1B000) && (orgaddr <= 0xF1CFFFF)))) warn("depositing LONGs on a non-long address in local RAM"); - for(;; ++tok) + for(;; tok++) { // dc.b 'string' [,] ... if (siz == SIZB && *tok == STRING && (tok[2] == ',' || tok[2] == EOL)) { - i = strlen(string[tok[1]]); + uint32_t i = strlen(string[tok[1]]); - if ((challoc - ch_size) < i) + if ((challoc - ch_size) < i) chcheck(i); - for(p=string[tok[1]]; *p!=EOS; ++p) + for(p=string[tok[1]]; *p!=EOS; p++) D_byte(*p); tok += 2; goto comma; } - if (*tok == 'I') + int movei = 0; // MOVEI flag for dc.i + + if (*tok == DOTI) { movei = 1; tok++; @@ -929,11 +928,13 @@ int d_dc(WORD siz) } // dc.x - if (expr(exprbuf, &eval, &eattr, NULL) != OK) + SYM * esym = 0; + + if (expr(exprbuf, &eval, &eattr, &esym) != OK) return 0; - tdb = (WORD)(eattr & TDB); - defined = (WORD)(eattr & DEFINED); + uint16_t tdb = eattr & TDB; + uint16_t defined = eattr & DEFINED; if ((challoc - ch_size) < 4) chcheck(4); @@ -948,15 +949,15 @@ int d_dc(WORD siz) } else { - if (tdb) - return error("non-absolute byte value"); - if (eval + 0x100 >= 0x200) { sprintf(buffer, "%s (value = $%X)", range_error, eval); return error(buffer); } + if (tdb) + return error("non-absolute byte value"); + D_byte(eval); } @@ -970,13 +971,13 @@ int d_dc(WORD siz) } else { - if (tdb) - rmark(cursect, sloc, tdb, MWORD, NULL); - if (eval + 0x10000 >= 0x20000) return error(range_error); - // Deposit 68000 or 6502 (byte-reversed) word + if (tdb) + MarkRelocatable(cursect, sloc, tdb, MWORD, NULL); + + // Deposit 68000 or 6502 (byte-reversed) word D_word(eval); } @@ -994,16 +995,16 @@ int d_dc(WORD siz) else { if (tdb) - rmark(cursect, sloc, tdb, MLONG, NULL); + MarkRelocatable(cursect, sloc, tdb, MLONG, NULL); - if (movei) - eval = ((eval >> 16) & 0x0000FFFF) | ((eval << 16) & 0xFFFF0000); + if (movei) + eval = WORDSWAP32(eval); D_long(eval); } break; } - + comma: if (*tok != ',') break; @@ -1046,9 +1047,9 @@ int d_dcb(WORD siz) // // Generalized initialization directive -// +// // .init[.siz] [#count,] expression [.size] , ... -// +// // The size suffix on the ".init" directive becomes the default size of the // objects to deposit. If an item is preceeded with a sharp (immediate) sign // and an expression, it specifies a repeat count. The value to be deposited @@ -1092,9 +1093,9 @@ int d_init(WORD def_siz) case DOTB: siz = SIZB; break; case DOTW: siz = SIZB; break; case DOTL: siz = SIZL; break; - default: + default: siz = def_siz; - --tok; + tok--; break; } @@ -1105,7 +1106,7 @@ int d_init(WORD def_siz) case EOL: return 0; case ',': - ++tok; + tok++; continue; default: return error(comma_error); @@ -1160,7 +1161,7 @@ int dep_block(VALUE count, WORD siz, VALUE eval, WORD eattr, TOKEN * exprbuf) else { if (tdb) - rmark(cursect, sloc, tdb, MWORD, NULL); + MarkRelocatable(cursect, sloc, tdb, MWORD, NULL); if (eval + 0x10000 >= 0x20000) return error(range_error); @@ -1179,7 +1180,7 @@ int dep_block(VALUE count, WORD siz, VALUE eval, WORD eattr, TOKEN * exprbuf) else { if (tdb) - rmark(cursect, sloc, tdb, MLONG, NULL); + MarkRelocatable(cursect, sloc, tdb, MLONG, NULL); D_long(eval); } @@ -1263,7 +1264,7 @@ int d_68000(void) { rgpu = rdsp = 0; // Switching from gpu/dsp sections should reset any ORG'd Address - orgactive = 0; + orgactive = 0; orgwarning = 0; SaveSection(); SwitchSection(TEXT); @@ -1325,12 +1326,12 @@ int d_dsp(void) // // .cargs [#offset], symbol[.size], ... -// +// // Lists of registers may also be mentioned; they just take up space. Good for // "documentation" purposes: -// +// // .cargs a6, .arg1, .arg2, .arg3... -// +// // Symbols thus created are ABS and EQUATED. // int d_cargs(void) @@ -1438,12 +1439,12 @@ int d_cargs(void) // // .cstruct [#offset], symbol[.size], ... -// +// // Lists of registers may also be mentioned; they just take up space. Good for // "documentation" purposes: -// +// // .cstruct a6, .arg1, .arg2, .arg3... -// +// // Symbols thus created are ABS and EQUATED. Note that this is for // compatibility with VBCC and the Remover's library. Thanks to GroovyBee for // the suggestion. @@ -1576,7 +1577,6 @@ int undmac1(char * p) SYM * symbol = lookup(p, MACRO, 0); // If the macro symbol exists, cause it to disappear -// if ((sy = lookup(p, MACRO, 0)) != NULL) if (symbol != NULL) symbol->stype = (BYTE)SY_UNDEF; @@ -1626,7 +1626,7 @@ int d_opt(void) if (ParseOptimization(tmpstr) != OK) { char temperr[256]; - sprintf(temperr, "unknown optimisation flag '%s'", tmpstr); + sprintf(temperr, "unknown optimization flag '%s'", tmpstr); return error(temperr); } } diff --git a/direct.h b/direct.h index 2c5ce3a..6ce7d45 100644 --- a/direct.h +++ b/direct.h @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // DIRECT.H - Directive Handling -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -43,7 +43,7 @@ int ExitMacro(void); int d_list(void); int d_nlist(void); int d_title(void); -int d_subttl(void); +int d_subttl(void); int eject(void); int d_error(char *); int d_warn(char *); diff --git a/eagen.c b/eagen.c index d230c1b..e94c21b 100644 --- a/eagen.c +++ b/eagen.c @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // EAGEN.C - Effective Address Code Generation -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -21,6 +21,7 @@ #define aNexpr a0expr #define aNixreg a0ixreg #define aNixsiz a0ixsiz +#define AnESYM a0esym #include "eagen0.c" #define eaNgen ea1gen @@ -30,4 +31,5 @@ #define aNexpr a1expr #define aNixreg a1ixreg #define aNixsiz a1ixsiz +#define AnESYM a1esym #include "eagen0.c" diff --git a/eagen0.c b/eagen0.c index 88ebdb3..1c359b9 100644 --- a/eagen0.c +++ b/eagen0.c @@ -2,20 +2,16 @@ // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // EAGEN0.C - Effective Address Code Generation // Generated Code for eaN (Included twice by "eagen.c") -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // int eaNgen(WORD siz) { - WORD w; - VALUE v; - WORD tdb; - - v = aNexval; - w = (WORD)(aNexattr & DEFINED); - tdb = (WORD)(aNexattr & TDB); + VALUE v = aNexval; + WORD w = (WORD)(aNexattr & DEFINED); + WORD tdb = (WORD)(aNexattr & TDB); switch (amN) { @@ -35,18 +31,16 @@ int eaNgen(WORD siz) // expr(An) if (w) { - // Just deposit it + // Just deposit it if (tdb) - rmark(cursect, sloc, tdb, MWORD, NULL); + MarkRelocatable(cursect, sloc, tdb, MWORD, NULL); if ((v == 0) && optim_flags[OPT_INDIRECT_DISP]) { - // If expr is 0, size optimise the opcode. - // Generally the lower 6 bits of the opcode - // for expr(ax) are 101rrr where rrr=the - // number of the register, then followed by - // a word containing 'expr'. We need to change - // that to 010rrr. + // If expr is 0, size optimise the opcode. Generally the lower + // 6 bits of the opcode for expr(ax) are 101rrr where rrr=the + // number of the register, then followed by a word containing + // 'expr'. We need to change that to 010rrr. if ((siz & 0x8000) == 0) { chptr_opcode[0] &= ((0xFFC7 >> 8) & 255); // mask off bits @@ -56,9 +50,8 @@ int eaNgen(WORD siz) } else { - // Special case for move ea,ea: - // there are two ea fields there and - // we get a signal if it's the second ea field + // Special case for move ea,ea: there are two ea fields + // there and we get a signal if it's the second ea field // from m_ea - siz's 16th bit is set chptr_opcode[0] &= ((0xFE3F >> 8) & 255); // mask off bits chptr_opcode[1] &= 0xFE3F & 255; // mask off bits @@ -79,8 +72,8 @@ int eaNgen(WORD siz) } else { - // Arrange for fixup later on - AddFixup(FU_WORD|FU_SEXT, sloc, aNexpr); + // Arrange for fixup later on + AddFixup(FU_WORD | FU_SEXT, sloc, aNexpr); D_word(0); } @@ -88,7 +81,7 @@ int eaNgen(WORD siz) case PCDISP: if (w) { - // Just deposit it + // Just deposit it if ((aNexattr & TDB) == cursect) v -= (VALUE)sloc; else if ((aNexattr & TDB) != ABS) @@ -101,8 +94,8 @@ int eaNgen(WORD siz) } else { - // Arrange for fixup later on - AddFixup(FU_WORD|FU_SEXT|FU_PCREL, sloc, aNexpr); + // Arrange for fixup later on + AddFixup(FU_WORD | FU_SEXT | FU_PCREL, sloc, aNexpr); D_word(0); } @@ -113,21 +106,21 @@ int eaNgen(WORD siz) if (aNexattr & DEFINED) { - // Deposit a byte... + // Deposit a byte... if (tdb) - // Can't mark bytes + // Can't mark bytes return error(abs_error); if (v + 0x80 >= 0x180) return error(range_error); - w |= v & 0xff; + w |= v & 0xFF; D_word(w); } else { // Fixup the byte later - AddFixup(FU_BYTE|FU_SEXT, sloc+1, aNexpr); + AddFixup(FU_BYTE | FU_SEXT, sloc + 1, aNexpr); D_word(w); } @@ -138,8 +131,8 @@ int eaNgen(WORD siz) if (aNexattr & DEFINED) { - // Deposit a byte... - if ((aNexattr & TDB) == cursect) + // Deposit a byte... + if ((aNexattr & TDB) == cursect) v -= (VALUE)sloc; else if ((aNexattr & TDB) != ABS) error(rel_error); @@ -152,8 +145,8 @@ int eaNgen(WORD siz) } else { - // Fixup the byte later - AddFixup(FU_WBYTE|FU_SEXT|FU_PCREL, sloc, aNexpr); + // Fixup the byte later + AddFixup(FU_WBYTE | FU_SEXT | FU_PCREL, sloc, aNexpr); D_word(w); } @@ -174,7 +167,7 @@ int eaNgen(WORD siz) } else { - AddFixup(FU_BYTE|FU_SEXT, sloc+1, aNexpr); + AddFixup(FU_BYTE | FU_SEXT, sloc + 1, aNexpr); D_word(0); } @@ -183,17 +176,17 @@ int eaNgen(WORD siz) case SIZN: if (w) { - if (tdb) - rmark(cursect, sloc, tdb, MWORD, NULL); - if (v + 0x10000 >= 0x20000) return error(range_error); + if (tdb) + MarkRelocatable(cursect, sloc, tdb, MWORD, NULL); + D_word(v); } else { - AddFixup(FU_WORD|FU_SEXT, sloc, aNexpr); + AddFixup(FU_WORD | FU_SEXT, sloc, aNexpr); D_word(0); } @@ -202,7 +195,7 @@ int eaNgen(WORD siz) if (w) { if (tdb) - rmark(cursect, sloc, tdb, MLONG, NULL); + MarkRelocatable(cursect, sloc, tdb, MLONG, NULL); D_long(v); } @@ -220,10 +213,10 @@ int eaNgen(WORD siz) break; case ABSW: - if (w) + if (w) // Defined { if (tdb) - rmark(cursect, sloc, tdb, MWORD, NULL); + MarkRelocatable(cursect, sloc, tdb, MWORD, NULL); if (v + 0x8000 >= 0x10000) return error(range_error); @@ -232,16 +225,16 @@ int eaNgen(WORD siz) } else { - AddFixup(FU_WORD|FU_SEXT, sloc, aNexpr); + AddFixup(FU_WORD | FU_SEXT, sloc, aNexpr); D_word(0); } break; case ABSL: - if (w) + if (w) // Defined { if (tdb) - rmark(cursect, sloc, tdb, MLONG, NULL); + MarkRelocatable(cursect, sloc, tdb, MLONG, NULL); D_long(v); } @@ -260,7 +253,7 @@ int eaNgen(WORD siz) case PCMPRE: return error("unsupported 68020 addressing mode"); default: - // Bad addressing mode in ea gen + // Bad addressing mode in ea gen interror(3); } @@ -275,4 +268,5 @@ int eaNgen(WORD siz) #undef aNexpr #undef aNixreg #undef aNixsiz +#undef AnESYM diff --git a/error.c b/error.c index 83a6f37..196e4a9 100644 --- a/error.c +++ b/error.c @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // ERROR.C - Error Handling -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // diff --git a/error.h b/error.h index 06d9e46..693fe51 100644 --- a/error.h +++ b/error.h @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // ERROR.H - Error Handling -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // diff --git a/expr.c b/expr.c index 063066e..b7bf4b1 100644 --- a/expr.c +++ b/expr.c @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // EXPR.C - Expression Analyzer -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -17,7 +17,7 @@ #include "symbol.h" #include "token.h" -#define DEF_KW // Declare keyword values +#define DEF_KW // Declare keyword values #include "kwtab.h" // Incl generated keyword tables & defs // N.B.: The size of tokenClass should be identical to the largest value of @@ -29,22 +29,22 @@ static WORD evattr[EVSTACKSIZE]; // Evaluator attribute stack // Token-class initialization list char itokcl[] = { 0, // END - CONST, SYMBOL, 0, // ID + CONST, SYMBOL, 0, // ID '(', '[', '{', 0, // OPAR - ')', ']', '}', 0, // CPAR + ')', ']', '}', 0, // CPAR CR_DEFINED, CR_REFERENCED, // SUNARY (special unary) CR_STREQ, CR_MACDEF, - CR_DATE, CR_TIME, + CR_DATE, CR_TIME, CR_ABSCOUNT, 0, '!', '~', UNMINUS, 0, // UNARY - '*', '/', '%', 0, // MULT - '+', '-', 0, // ADD - SHL, SHR, 0, // SHIFT - LE, GE, '<', '>', NE, '=', 0, // REL - '&', 0, // AND - '^', 0, // XOR - '|', 0, // OR - 1 // (the end) + '*', '/', '%', 0, // MULT + '+', '-', 0, // ADD + SHL, SHR, 0, // SHIFT + LE, GE, '<', '>', NE, '=', 0, // REL + '&', 0, // AND + '^', 0, // XOR + '|', 0, // OR + 1 // (the end) }; const char missym_error[] = "missing symbol"; @@ -55,7 +55,7 @@ static TOKEN * evalTokenBuffer; // Deposit tokens here (this is really a // pointer to exprbuf from direct.c) // (Can also be from others, like // riscasm.c) -static symbolNum; // Pointer to the entry in symbolPtr[] +static int symbolNum; // Pointer to the entry in symbolPtr[] // @@ -88,7 +88,7 @@ void InitExpression(void) { if (*p == 0) i++; - else + else tokenClass[(int)(*p)] = (char)i; } @@ -105,7 +105,7 @@ int expr0(void) if (expr1() != OK) return ERROR; - + while (tokenClass[*tok] >= MULT) { t = *tok++; @@ -211,7 +211,7 @@ getsym: break; } } - else + else return expr2(); return OK; @@ -244,7 +244,7 @@ int expr2(void) // Check register bank usage if (sy->sattre & EQUATEDREG) { - if ((regbank == BANK_0) && (sy->sattre & BANK_1) && !altbankok) + if ((regbank == BANK_0) && (sy->sattre & BANK_1) && !altbankok) warns("equated symbol \'%s\' cannot be used in register bank 0", sy->sname); if ((regbank == BANK_1) && (sy->sattre & BANK_0) && !altbankok) @@ -395,7 +395,7 @@ if (symbol) // Check register bank usage if (symbol->sattre & EQUATEDREG) { - if ((regbank == BANK_0) && (symbol->sattre & BANK_1) && !altbankok) + if ((regbank == BANK_0) && (symbol->sattre & BANK_1) && !altbankok) warns("equated symbol '%s' cannot be used in register bank 0", symbol->sname); if ((regbank == BANK_1) && (symbol->sattre & BANK_0) && !altbankok) @@ -425,7 +425,7 @@ be converted from a linked list into an array). All that extra crap that was put into the svalue when doing the equr stuff is thrown away right here. What the hell is it for? */ - if (symbol->sattre & EQUATEDREG) + if (symbol->sattre & EQUATEDREG) *a_value &= 0x1F; *a_attr = (WORD)(symbol->sattr & ~GLOBAL); @@ -484,7 +484,7 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) case SYMBOL: //printf("evexpr(): SYMBOL\n"); sy = symbolPtr[*tk++]; - sy->sattr |= REFERENCED; // Set "referenced" bit + sy->sattr |= REFERENCED; // Set "referenced" bit if (!(sy->sattr & DEFINED)) { @@ -508,7 +508,7 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) } else { - *++sval = 0; // 0 for undefined symbols + *++sval = 0; // 0 for undefined symbols } *++sattr = (WORD)(sy->sattr & ~GLOBAL); // Push attribs @@ -526,20 +526,20 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) break; // Binary "+" and "-" matrix: - // + // // ABS Sect Other // ---------------------------- // ABS | ABS | Sect | Other | // Sect | Sect | [1] | Error | // Other | Other | Error | [1] | // ---------------------------- - // + // // [1] + : Error // - : ABS case '+': //printf("evexpr(): +\n"); --sval; // Pop value - --sattr; // Pop attrib + --sattr; // Pop attrib //printf("--> N+N: %i + %i = ", *sval, sval[1]); *sval += sval[1]; // Compute value //printf("%i\n", *sval); @@ -553,7 +553,7 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) case '-': //printf("evexpr(): -\n"); --sval; // Pop value - --sattr; // Pop attrib + --sattr; // Pop attrib //printf("--> N-N: %i - %i = ", *sval, sval[1]); *sval -= sval[1]; // Compute value //printf("%i\n", *sval); @@ -599,8 +599,8 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); // are in the same segment, but that's the only requirement. case LE: //printf("evexpr(): LE\n"); - --sattr; - --sval; + sattr--; + sval--; if ((*sattr & TDB) != (sattr[1] & TDB)) error(seg_error); @@ -610,8 +610,8 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case GE: //printf("evexpr(): GE\n"); - --sattr; - --sval; + sattr--; + sval--; if ((*sattr & TDB) != (sattr[1] & TDB)) error(seg_error); @@ -621,8 +621,8 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case '>': //printf("evexpr(): >\n"); - --sattr; - --sval; + sattr--; + sval--; if ((*sattr & TDB) != (sattr[1] & TDB)) error(seg_error); @@ -632,8 +632,8 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case '<': //printf("evexpr(): <\n"); - --sattr; - --sval; + sattr--; + sval--; if ((*sattr & TDB) != (sattr[1] & TDB)) error(seg_error); @@ -643,8 +643,8 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case NE: //printf("evexpr(): NE\n"); - --sattr; - --sval; + sattr--; + sval--; if ((*sattr & TDB) != (sattr[1] & TDB)) error(seg_error); @@ -654,8 +654,8 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); break; case '=': //printf("evexpr(): =\n"); - --sattr; - --sval; + sattr--; + sval--; if ((*sattr & TDB) != (sattr[1] & TDB)) error(seg_error); @@ -675,15 +675,15 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); switch ((int)tk[-1]) { case '*': - --sval; - --sattr; // Pop attrib + sval--; + sattr--; // Pop attrib //printf("--> NxN: %i x %i = ", *sval, sval[1]); *sval *= sval[1]; //printf("%i\n", *sval); break; case '/': - --sval; - --sattr; // Pop attrib + sval--; + sattr--; // Pop attrib if (sval[1] == 0) return error("divide by zero"); @@ -697,8 +697,8 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); //printf("%i\n", *sval); break; case '%': - --sval; - --sattr; // Pop attrib + sval--; + sattr--; // Pop attrib if (sval[1] == 0) return error("mod (%) by zero"); @@ -706,28 +706,28 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); *sval %= sval[1]; break; case SHL: - --sval; - --sattr; // Pop attrib + sval--; + sattr--; // Pop attrib *sval <<= sval[1]; break; case SHR: - --sval; - --sattr; // Pop attrib + sval--; + sattr--; // Pop attrib *sval >>= sval[1]; break; case '&': - --sval; - --sattr; // Pop attrib + sval--; + sattr--; // Pop attrib *sval &= sval[1]; break; case '^': - --sval; - --sattr; // Pop attrib + sval--; + sattr--; // Pop attrib *sval ^= sval[1]; break; case '|': - --sval; - --sattr; // Pop attrib + sval--; + sattr--; // Pop attrib *sval |= sval[1]; break; default: diff --git a/expr.h b/expr.h index 96b8e2a..ebba659 100644 --- a/expr.h +++ b/expr.h @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // EXPR.H - Expression Analyzer -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // diff --git a/kwgen.c b/kwgen.c index b644b10..55bd32a 100644 --- a/kwgen.c +++ b/kwgen.c @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // KWGEN.C - Keyword & Mnemonic Definition and State Machine Creation Tool -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -421,3 +421,4 @@ void panic(char * s) fprintf(stderr, "Panic: %s\n", s); exit(1); } + diff --git a/listing.c b/listing.c index 4fadfef..3d63256 100644 --- a/listing.c +++ b/listing.c @@ -21,21 +21,21 @@ #include "error.h" char * list_fname; // Listing filename -char subttl[TITLESIZ]; // Current subtitle -int listing; // Listing level +uint8_t subttl[TITLESIZ]; // Current subtitle +int listing; // Listing level int pagelen = 61; // Lines on a page int nlines; // #lines on page so far -LONG lsloc; // `sloc' at start of line +LONG lsloc; // `sloc' at start of line // Private static int lcursect; // `cursect' at start of line -static int llineno; // `curlineno' at start of line -static int pageno; // Current page number +static int llineno; // `curlineno' at start of line +static int pageno; // Current page number static int pagewidth; // #columns on a page static int subflag; // 0, don't do .eject on subttl (set 1) static char lnimage[IMAGESIZ]; // Image of output line static char title[TITLESIZ]; // Current title -static char datestr[20]; // Current date dd-mon-yyyy +static char datestr[20]; // Current date dd-mon-yyyy static char timestr[20]; // Current time hh:mm:ss [am|pm] static char buf[IMAGESIZ]; // Buffer for numbers static long unused; // For supressing 'write' warnings @@ -80,7 +80,7 @@ VALUE dos_date(void) } -// +// // Return GEMDOS format time // VALUE dos_time(void) @@ -160,7 +160,7 @@ void lnfill(char * dest, int len, char chr) } -// +// // Create listing file with the appropriate name // void list_setup(void) @@ -176,7 +176,7 @@ void list_setup(void) } list_fname = NULL; - + if ((list_fd = open(fnbuf, _OPEN_FLAGS, _PERM_MODE)) < 0) cantcreat(fnbuf); } @@ -348,13 +348,13 @@ nochunk: strcpy(buf, "xx"); p++; // Advance anyway } - else + else sprintf(buf, "%02x", *p++ & 0xff); strncpy(lnimage + col, buf, 2); } - // Flush partial line + // Flush partial line if (col > DATA_COL) { uc_ln(lnimage); @@ -441,7 +441,7 @@ int d_subttl(void) tok += 2; - // Always eject on pages 2+ + // Always eject on pages 2+ if (ejectok && (subflag || pageno > 1)) eject(); @@ -459,7 +459,7 @@ int d_title(void) { if (*tok != STRING) return error("missing string"); - + // strcpy(title, (char*)tok[1]); strcpy(title, string[tok[1]]); tok += 2; diff --git a/listing.h b/listing.h index 457ff1f..e447f35 100644 --- a/listing.h +++ b/listing.h @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // LISTING.H - Listing Output -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -31,6 +31,7 @@ extern LONG lsloc; // Prototypes void InitListing(void); +int eject(void); void ship_ln(const char *); void taglist(char); void println(const char *); diff --git a/mach.c b/mach.c index 7c91979..69be7ea 100644 --- a/mach.c +++ b/mach.c @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // MACH.C - Code Generation -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -19,7 +19,7 @@ #include "kwtab.h" -// Fucntion prototypes +// Fucntion prototypes int m_unimp(WORD, WORD), m_badmode(WORD, WORD), m_bad6mode(WORD, WORD), m_bad6inst(WORD, WORD); int m_self(WORD, WORD); int m_abcd(WORD, WORD); @@ -59,8 +59,8 @@ extern int ea1gen(WORD); // Include code tables MNTAB machtab[] = { -// { (WORD)-1, (unsigned long)-1L, (unsigned long)-1L, 0x0000, 0, m_badmode }, // 0 - { 0xFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000, 0, m_badmode }, // 0 +// { (WORD)-1, (unsigned long)-1L, (unsigned long)-1L, 0x0000, 0, m_badmode }, // 0 + { 0xFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000, 0, m_badmode }, // 0 #include "68ktab.h" { 0, 0L, 0L, 0x0000, 0, m_unimp } // Last entry }; @@ -72,18 +72,18 @@ WORD reg_9[8] = { // SIZB==>00, SIZW==>01, SIZL==>10, SIZN==>01 << 6 WORD siz_6[] = { - (WORD)-1, // n/a + (WORD)-1, // n/a 0, // SIZB - 1<<6, (WORD)-1, // SIZW, n/a - 2<<6, (WORD)-1, (WORD)-1, (WORD)-1, // SIZL, n/a, n/a, n/a - 1<<6 // SIZN + 1<<6, (WORD)-1, // SIZW, n/a + 2<<6, (WORD)-1, (WORD)-1, (WORD)-1, // SIZL, n/a, n/a, n/a + 1<<6 // SIZN }; // Byte/word/long size for MOVE instrs WORD siz_12[] = { (WORD)-1, - 0x1000, // Byte - 0x3000, (WORD)-1, // Word + 0x1000, // Byte + 0x3000, (WORD)-1, // Word 0x2000, (WORD)-1, (WORD)-1, (WORD)-1, // Long 0x3000 // Word (SIZN) }; @@ -133,59 +133,59 @@ int m_self(WORD inst, WORD usused) // // Do one EA in bits 0..5 -// +// // Bits in `inst' have the following meaning: -// +// // Bit zero specifies which ea (ea0 or ea1) to generate in the lower six bits // of the instr. -// +// // If bit one is set, the OTHER ea (the one that wasn't generated by bit zero) // is generated after the instruction. Regardless of bit 0's value, ea0 is // always deposited in memory before ea1. -// +// // If bit two is set, standard size bits are set in the instr in bits 6 and 7. -// +// // If bit four is set, bit three specifies which eaXreg to place in bits 9..11 // of the instr. // int m_ea(WORD inst, WORD siz) { - WORD flg = inst; // Save flag bits - inst &= ~0x3F; // Clobber flag bits in instr + WORD flg = inst; // Save flag bits + inst &= ~0x3F; // Clobber flag bits in instr - // Install "standard" instr size bits + // Install "standard" instr size bits if (flg & 4) inst |= siz_6[siz]; if (flg & 16) { - // OR-in register number + // OR-in register number if (flg & 8) - inst |= reg_9[a1reg]; // ea1reg in bits 9..11 + inst |= reg_9[a1reg]; // ea1reg in bits 9..11 else - inst |= reg_9[a0reg]; // ea0reg in bits 9..11 + inst |= reg_9[a0reg]; // ea0reg in bits 9..11 } if (flg & 1) { - // Use am1 - inst |= am1 | a1reg; // Get ea1 into instr - D_word(inst); // Deposit instr + // Use am1 + inst |= am1 | a1reg; // Get ea1 into instr + D_word(inst); // Deposit instr - // Generate ea0 if requested + // Generate ea0 if requested if (flg & 2) ea0gen(siz); - ea1gen(siz); // Generate ea1 + ea1gen(siz); // Generate ea1 } else { - // Use am0 - inst |= am0 | a0reg; // Get ea0 into instr - D_word(inst); // Deposit instr - ea0gen(siz); // Generate ea0 + // Use am0 + inst |= am0 | a0reg; // Get ea0 into instr + D_word(inst); // Deposit instr + ea0gen(siz); // Generate ea0 - // Generate ea1 if requested + // Generate ea1 if requested if (flg & 2) ea1gen(siz); } @@ -202,7 +202,7 @@ int m_abcd(WORD inst, WORD siz) { if (inst & 1) { - // Install size bits + // Install size bits inst--; inst |= siz_6[siz]; } @@ -221,7 +221,7 @@ int m_adda(WORD inst, WORD siz) { inst |= am0 | a0reg | lwsiz_8[siz] | reg_9[a1reg]; D_word(inst); - ea0gen(siz); // Generate EA + ea0gen(siz); // Generate EA return 0; } @@ -230,19 +230,19 @@ int m_adda(WORD inst, WORD siz) // // If bit 0 of `inst' is 1, install size bits in bits 6..7 of instr. // If bit 1 of `inst' is 1, install a1reg in bits 9..11 of instr. -// +// int m_reg(WORD inst, WORD siz) { if (inst & 1) - // Install size bits + // Install size bits inst |= siz_6[siz]; if (inst & 2) - // Install other register (9..11) + // Install other register (9..11) inst |= reg_9[a1reg]; - inst &= ~7; // Clear off crufty bits - inst |= a0reg; // Install first register + inst &= ~7; // Clear off crufty bits + inst |= a0reg; // Install first register D_word(inst); return 0; @@ -318,11 +318,11 @@ int m_bitop(WORD inst, WORD siz) { // Enforce instruction sizes if (am1 == DREG) - { // X,Dn must be .n or .l + { // X,Dn must be .n or .l if (siz & (SIZB | SIZW)) return error(siz_error); } - else if (siz & (SIZW | SIZL)) // X,ea must be .n or .b + else if (siz & (SIZW | SIZL)) // X,ea must be .n or .b return error(siz_error); // Construct instr and EAs @@ -331,7 +331,7 @@ int m_bitop(WORD inst, WORD siz) if (am0 == IMMED) { D_word(inst); - ea0gen(SIZB); // Immediate bit number + ea0gen(SIZB); // Immediate bit number } else { @@ -339,7 +339,7 @@ int m_bitop(WORD inst, WORD siz) D_word(inst); } - // ea to bit-munch + // ea to bit-munch ea1gen(SIZB); return 0; @@ -386,14 +386,14 @@ int m_exg(WORD inst, WORD siz) siz = siz; if (am0 == DREG && am1 == DREG) - m = 0x0040; // Dn,Dn + m = 0x0040; // Dn,Dn else if (am0 == AREG && am1 == AREG) - m = 0x0048; // An,An + m = 0x0048; // An,An else { if (am0 == AREG) - { // Dn,An or An,Dn - m = a1reg; // Get AREG into a1reg + { // Dn,An or An,Dn + m = a1reg; // Get AREG into a1reg a1reg = a0reg; a0reg = m; } @@ -425,7 +425,7 @@ int m_link(WORD inst, WORD siz) // // Handle MOVE // MOVE -// +// // Optimize MOVE.L #,D0 to a MOVEQ // int m_move(WORD inst, WORD size) @@ -467,9 +467,9 @@ int m_usp(WORD inst, WORD siz) siz = siz; if (am0 == AM_USP) - inst |= a1reg; // USP, An + inst |= a1reg; // USP, An else - inst |= a0reg; // An, USP + inst |= a0reg; // An, USP D_word(inst); @@ -484,11 +484,11 @@ int m_moveq(WORD inst, WORD siz) { siz = siz; - // Arrange for future fixup + // Arrange for future fixup if (!(a0exattr & DEFINED)) { AddFixup(FU_BYTE | FU_SEXT, sloc + 1, a0expr); - a0exval = 0; + a0exval = 0; } else if (a0exval + 0x100 >= 0x200) return error(range_error); @@ -515,7 +515,7 @@ int m_movep(WORD inst, WORD siz) if (am1 == AIND) D_word(0) - else + else ea1gen(siz); } else @@ -525,7 +525,7 @@ int m_movep(WORD inst, WORD siz) if (am0 == AIND) D_word(0) - else + else ea0gen(siz); } @@ -555,7 +555,7 @@ int m_br(WORD inst, WORD siz) { if (optim_flags[OPT_BSR_BCC_S] && v != 0 && v + 0x80 < 0x100) { - // Fits in .B + // Fits in .B inst |= v & 0xFF; D_word(inst); if (sbra_flag) @@ -564,7 +564,7 @@ int m_br(WORD inst, WORD siz) } else { - // Fits in .W + // Fits in .W if (v + 0x8000 > 0x10000) return error(range_error); @@ -598,14 +598,14 @@ int m_br(WORD inst, WORD siz) if (siz == SIZB) { - // .B + // .B AddFixup(FU_BBRA | FU_PCREL | FU_SEXT, sloc, a0expr); D_word(inst); return 0; } else { - // .W + // .W D_word(inst); AddFixup(FU_WORD | FU_PCREL | FU_LBRA | FU_ISBRA, sloc, a0expr); D_word(0); @@ -624,7 +624,7 @@ int m_addq(WORD inst, WORD siz) if (a0exattr & DEFINED) { - if (a0exval > 8 || a0exval == 0) // Range in 1..8 + if (a0exval > 8 || a0exval == 0) // Range in 1..8 return error(range_error); inst |= (a0exval & 7) << 9; @@ -660,7 +660,7 @@ int m_trap(WORD inst, WORD siz) inst |= a0exval; D_word(inst); } - else + else return error(undef_error); return 0; @@ -685,7 +685,7 @@ int m_movem(WORD inst, WORD siz) if (*tok == '#') { - // Handle #, ea + // Handle #, ea tok++; if (abs_expr(&eval) != OK) @@ -700,7 +700,7 @@ int m_movem(WORD inst, WORD siz) if (*tok >= KW_D0 && *tok <= KW_A7) { - // , ea + // , ea if (reglist(&rmask) < 0) return 0; @@ -728,7 +728,7 @@ immed1: } else { - // ea, + // ea, if (amode(0) < 0) return 0; @@ -742,7 +742,7 @@ immed1: if (*tok == '#') { - // ea, # + // ea, # tok++; if (abs_expr(&eval) != OK) diff --git a/mach.h b/mach.h index f10ff31..46b5db3 100644 --- a/mach.h +++ b/mach.h @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // MACH.H - Code Generation -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -12,7 +12,7 @@ #include "rmac.h" #include "amode.h" -// Globals, Externals etc +// Exported variables extern char seg_error[]; extern char undef_error[]; extern char rel_error[]; @@ -21,3 +21,4 @@ extern char abs_error[]; extern MNTAB machtab[]; #endif // __MACH_H__ + diff --git a/macro.c b/macro.c index 0807e74..2af5997 100644 --- a/macro.c +++ b/macro.c @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // MACRO.C - Macro Definition and Invocation -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -17,20 +17,18 @@ #include "token.h" -LONG curuniq; // Current macro's unique number -//TOKEN ** argp; // Free spot in argptrs[] -int macnum; // Unique number for macro definition -TOKEN * argPtrs[128]; // 128 arguments ought to be enough for anyone +LONG curuniq; // Current macro's unique number +int macnum; // Unique number for macro definition +TOKEN * argPtrs[128]; // 128 arguments ought to be enough for anyone static int argp; -static LONG macuniq; // Unique-per-macro number -static SYM * curmac; // Macro currently being defined -//static char ** curmln; // Previous macro line (or NULL) -static VALUE argno; // Formal argument count +static LONG macuniq; // Unique-per-macro number +static SYM * curmac; // Macro currently being defined +static VALUE argno; // Formal argument count -static LONG * firstrpt; // First .rept line -static LONG * nextrpt; // Last .rept line -static int rptlevel; // .rept nesting level +static LONG * firstrpt; // First .rept line +static LONG * nextrpt; // Last .rept line +static int rptlevel; // .rept nesting level // @@ -150,7 +148,7 @@ features of the language. Seems like we can do better here. *curmln = p.cp; curmln = (char **)p.cp; - return 1; // Keep looking + return 1; // Keep looking #else if (curmac->lineList == NULL) { @@ -239,11 +237,11 @@ int defr1(char * ln, int kwno) switch (kwno) { - case 0: // .endr + case 0: // .endr if (--rptlevel == 0) return(0); goto addln; - case 1: // .rept + case 1: // .rept rptlevel++; default: //MORE stupidity here... @@ -256,7 +254,7 @@ WARNING(!!! Casting (char *) as LONG !!!) *p = 0; strcpy((char *)(p + 1), ln); - + if (nextrpt == NULL) { firstrpt = p; // First line of rept statement @@ -310,14 +308,14 @@ int defrept(void) // Hand off lines of text to the function `lnfunc' until a line containing one // of the directives in `dirlist' is encountered. Return the number of the // keyword encountered (0..n) -// +// // `dirlist' contains null-seperated terminated keywords. A final null // terminates the list. Directives are compared to the keywords without regard // to case. -// +// // If `lnfunc' is NULL, then lines are simply skipped. // If `lnfunc' returns an error, processing is stopped. -// +// // `lnfunc' is called with an argument of -1 for every line but the last one, // when it is called with an argument of the keyword number that caused the // match. @@ -328,7 +326,7 @@ int lncatch(int (* lnfunc)(), char * dirlist) int k; if (lnfunc != NULL) - lnsave++; // Tell tokenizer to keep lines + lnsave++; // Tell tokenizer to keep lines for(;;) { @@ -359,7 +357,7 @@ int lncatch(int (* lnfunc)(), char * dirlist) if (p != NULL) { - if (*p == '.') // ignore leading '.'s + if (*p == '.') // ignore leading '.'s p++; k = kwmatch(p, dirlist); @@ -438,7 +436,7 @@ int InvokeMacro(SYM * mac, WORD siz) // argp = 0; DEBUG printf("InvokeMacro: argp: %d -> ", argp); - INOBJ * inobj = a_inobj(SRC_IMACRO); // Alloc and init IMACRO + INOBJ * inobj = a_inobj(SRC_IMACRO); // Alloc and init IMACRO IMACRO * imacro = inobj->inobj.imacro; imacro->im_siz = siz; WORD nargs = 0; @@ -447,7 +445,6 @@ int InvokeMacro(SYM * mac, WORD siz) TOKEN * dest; int stringNum = 0; int argumentNum = 0; -// int i; for(dry_run=1; ; dry_run--) { @@ -457,7 +454,7 @@ int InvokeMacro(SYM * mac, WORD siz) nargs++; else { -#if 0 +#if 0 *argptr++ = p; #else argPtrs[argp++] = p; @@ -569,7 +566,7 @@ streams, we can alleviate this problem.] // argp += nargs; #endif } - else + else break; } diff --git a/macro.h b/macro.h index bca6d2f..3884ac7 100644 --- a/macro.h +++ b/macro.h @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // MACRO.H - Macro Definition and Invocation -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // diff --git a/makefile b/makefile index cd52ffe..8eef370 100644 --- a/makefile +++ b/makefile @@ -8,7 +8,7 @@ rm = /bin/rm -f CC = $(CROSS)gcc HOSTCC = gcc -CFLAGS = -std=c99 -g -D__GCCUNIX__ -I. -O2 +CFLAGS = -std=c99 -D_DEFAULT_SOURCE -g -D__GCCUNIX__ -I. -O2 SRCS = amode.c debug.c direct.c eagen.c error.c expr.c listing.c mach.c macro.c mark.c object.c procln.c riscasm.c rmac.c sect.c symbol.c token.c diff --git a/mark.c b/mark.c index 81a4d87..6c40c30 100644 --- a/mark.c +++ b/mark.c @@ -10,20 +10,26 @@ #include "error.h" #include "object.h" #include "riscasm.h" +#include "sect.h" +#define MARK_ALLOC_INCR 1024 // # bytes to alloc for more mark space +#define MIN_MARK_MEM (3 * sizeof(uint16_t) + 1 * sizeof(uint32_t) + sizeof(SYM *)) + MCHUNK * firstmch; // First mark chunk MCHUNK * curmch; // Current mark chunk PTR markptr; // Deposit point in current mark chunk -LONG mcalloc; // #bytes alloc'd to current mark chunk -LONG mcused; // #bytes used in current mark chunk +uint32_t mcalloc; // # bytes alloc'd to current mark chunk +uint32_t mcused; // # bytes used in current mark chunk uint16_t curfrom; // Current "from" section -LONG markimg(register char * mp, LONG siz, LONG tsize, int okflag); -// -// Imports -// -extern int prg_flag; // 1, write ".PRG" relocatable executable +// Table to convert from TDB to fixup triad +static uint8_t mark_tr[] = { + 0, // (N/A) + 2, // TEXT relocatable + 1, 0, // DATA relocatable + 3 // BSS relocatable +}; //#define DEBUG_IMAGE_MARKING @@ -36,6 +42,7 @@ void InitMark(void) firstmch = curmch = NULL; mcalloc = mcused = 0; curfrom = 0; + sect[TEXT].relocs = sect[DATA].relocs = sect[BSS].relocs = 0; } @@ -47,37 +54,44 @@ void StopMark(void) if (curmch) { *markptr.wp = MCHEND; // Mark end of block - curmch->mcused = mcused; // Update #used in mark block + curmch->mcused = mcused; // Update # used in mark block } } // -// Mark a word or longword relocatable +// Mark a word or longword as relocatable +// +// Record is either 2, 3, or 4 pieces of data long. A mark is of the form: +// .W section mark is relative to, and flags in upper byte +// .L location of mark in "from" section +// .W [from] new from section (if different from current) +// .L [symbol] symbol involved in external reference (if any) // -int rmark(uint16_t from, uint32_t loc, uint16_t to, uint16_t size, SYM * symbol) +uint32_t MarkRelocatable(uint16_t section, uint32_t loc, uint16_t to, uint16_t flags, SYM * symbol) { #ifdef DEBUG_IMAGE_MARKING -printf("rmark: from=%i, loc=$%X, to=$%X, size=$%x, symbol=$%X\n", from, loc, to, size, symbol); +printf("MarkRelocatable: section=%i, loc=$%X, to=$%X, flags=$%x, symbol=$%X\n", section, loc, to, flags, symbol); if (symbol) printf(" symbol->stype=$%02X, sattr=$%04X, sattre=$%08X, svalue=%i, sname=%s\n", symbol->stype, symbol->sattr, symbol->sattre, symbol->svalue, symbol->sname); #endif if ((mcalloc - mcused) < MIN_MARK_MEM) - amark(); + AllocateMark(); - uint16_t flags = (size | to); + // Set up flags + flags |= to; - if (from != curfrom) + if (section != curfrom) flags |= MCHFROM; if (symbol != NULL) flags |= MSYMBOL; // - // Complain about some things are not allowed in `-p' mode: - // o marks that aren't to LONGs; - // o external references. + // Complain about some things are not allowed in '-p' (PRG) mode: + // o Marks that aren't to LONGs + // o External references // if (prg_flag) { @@ -86,18 +100,19 @@ if (symbol) if (symbol != NULL) errors("illegal external reference (in .PRG mode) to '%s'", - symbol->sname); + symbol->sname); } - mcused += sizeof(WORD) + sizeof(LONG); + // Dump crap into the mark *markptr.wp++ = flags; *markptr.lp++ = loc; + mcused += sizeof(uint16_t) + sizeof(uint32_t); if (flags & MCHFROM) { - curfrom = from; - *markptr.wp++ = from; - mcused += sizeof(WORD); + curfrom = section; + *markptr.wp++ = section; + mcused += sizeof(uint16_t); } if (flags & MSYMBOL) @@ -106,6 +121,11 @@ if (symbol) mcused += sizeof(SYM *); } + // Increment # of relocs in this section + sect[section].relocs++; + + // Not sure what this is about (making sure the next mark is clear until + // it's marked as the end--I think)... *markptr.wp = 0x0000; return 0; @@ -115,29 +135,28 @@ if (symbol) // // Allocate another chunk of mark space // -int amark(void) +uint32_t AllocateMark(void) { -// MCHUNK * p; - // Alloc mark block header (and data) and set it up. -// p = (MCHUNK *)amem((long)(sizeof(MCHUNK)) + MARK_ALLOC_INCR); - MCHUNK * p = (MCHUNK *)malloc(sizeof(MCHUNK) + MARK_ALLOC_INCR); + MCHUNK * p = malloc(sizeof(MCHUNK) + MARK_ALLOC_INCR); p->mcnext = NULL; p->mcalloc = MARK_ALLOC_INCR; - p->mcptr.cp = (char *)(((char *)p) + sizeof(MCHUNK)); + p->mcptr.cp = (uint8_t *)p + sizeof(MCHUNK); + p->mcused = 0; + + if (firstmch == NULL) + firstmch = p; if (curmch) { - // Link onto previous chunk - *markptr.wp++ = MCHEND; // Mark end of block + // Link onto previous chunk + *markptr.wp++ = MCHEND; // Mark end of block curmch->mcused = mcused; curmch->mcnext = p; } - if (!firstmch) - firstmch = p; - - curmch = p; // Setup global vars + // Setup global vars + curmch = p; markptr = p->mcptr; mcalloc = MARK_ALLOC_INCR; mcused = 0; @@ -146,73 +165,48 @@ int amark(void) } -/* - * Table to convert from TDB to fixup triad - * - */ -static char mark_tr[] = { - 0, /* (n/a) */ - 2, /* TEXT relocatable */ - 1, 0, /* DATA relocatable */ - 3 /* BSS relocatable */ -}; - - -/* - * Make mark image for Alcyon .o file - * okflag -- 1, ok to deposit reloc information - */ -LONG markimg(register char * mp, LONG siz, LONG tsize, int okflag) +// +// Make mark image for Alcyon .o file +// okflag: 1, ok to deposit reloc information +// +uint32_t MarkImage(register uint8_t * mp, uint32_t siz, uint32_t tsize, int okflag) { - MCHUNK * mch; /* -> mark chunk */ - register PTR p; /* source point from within mark chunk */ - WORD from; /* section fixups are currently FROM */ - register WORD w; /* a word (temp) */ - LONG loc; /* location (temp) */ - LONG lastloc; /* last location fixed up (RELMOD) */ - SYM * symbol; /* -> symbols (temp) */ - char * wp; /* pointer into raw relocation information */ - register char * dp; /* deposit point for RELMOD information */ - int firstp; /* 1, first relocation (RELMOD) */ - LONG diff; /* difference to relocate (RELMOD) */ + uint16_t from = 0; // Section fixups are currently FROM + uint32_t loc; // Location (temp) + uint32_t lastloc; // Last location fixed up (RELMOD) + uint8_t * wp; // Pointer into raw relocation information + register uint8_t * dp; // Deposit point for RELMOD information if (okflag) - //clear(mp, siz); /* zero relocation buffer */ - memset(mp, 0, siz); /* zero relocation buffer */ - - from = 0; + memset(mp, 0, siz); // zero relocation buffer - for(mch=firstmch; mch!=NULL; mch=mch->mcnext) + for(MCHUNK * mch=firstmch; mch!=NULL; mch=mch->mcnext) { - for(p=mch->mcptr;;) + for(PTR p=mch->mcptr;;) { - w = *p.wp++; /* w = next mark entry */ + uint16_t w = *p.wp++;// w = next mark entry - if (w & MCHEND) /* (end of mark chunk) */ + if (w & MCHEND) // (end of mark chunk) break; - /* - * Get mark record - */ - symbol = NULL; - loc = *p.lp++; /* mark location */ + // Get mark record + SYM * symbol = NULL; + loc = *p.lp++; // mark location - if (w & MCHFROM) /* maybe change "from" section */ + if (w & MCHFROM) // maybe change "from" section from = *p.wp++; - if (w & MSYMBOL) /* maybe includes a symbol */ + if (w & MSYMBOL) // maybe includes a symbol symbol = *p.sy++; - /* - * Compute mark position in relocation information; - * in RELMOD mode, get address of data to fix up. - */ + // Compute mark position in relocation information; in RELMOD mode, + // get address of data to fix up. if (from == DATA) loc += tsize; - wp = (char *)(mp + loc); + wp = (uint8_t *)(mp + loc); - if (okflag && (w & MLONG)) /* indicate first word of long */ + if (okflag && (w & MLONG)) // indicate first word of long { wp[1] = 5; wp += 2; @@ -220,15 +214,13 @@ LONG markimg(register char * mp, LONG siz, LONG tsize, int okflag) if (symbol) { - /* - * Deposit external reference - */ + // Deposit external reference if (okflag) { if (w & MPCREL) - w = 6; /* pc-relative fixup */ + w = 6; // PC-relative fixup else - w = 4; /* absolute fixup */ + w = 4; // Absolute fixup w |= symbol->senv << 3; *wp++ = w >> 8; @@ -237,27 +229,19 @@ LONG markimg(register char * mp, LONG siz, LONG tsize, int okflag) } else { - /* - * Deposit section-relative mark; - * in RELMOD mode, fix it up in the chunk, - * kind of like a sleazoid linker. - * - * In RELMOD mode, marks to words (MWORDs) "cannot happen," - * checks are made when mark() is called, so we don't have - * to check again here. - */ + // Deposit section-relative mark; in RELMOD mode, fix it up in + // the chunk, kind of like a sleazoid linker. + // + // In RELMOD mode, marks to words (MWORDs) "cannot happen," + // checks are made when mark() is called, so we don't have to + // check again here. w &= TDB; if (okflag) wp[1] = mark_tr[w]; else if (prg_flag && (w & (DATA | BSS))) { - dp = wp; - diff = ((LONG)(*dp++ & 0xff)) << 24; - diff |= ((LONG)(*dp++ & 0xff)) << 16; - diff |= ((LONG)(*dp++ & 0xff)) << 8; - diff |= (LONG)(*dp & 0xff); - + uint32_t diff = GETBE32(wp, 0); #ifdef DO_DEBUG DEBUG printf("diff=%lx ==> ", diff); #endif @@ -266,11 +250,7 @@ LONG markimg(register char * mp, LONG siz, LONG tsize, int okflag) if (w == BSS) diff += sect[DATA].sloc; - dp = wp; - *dp++ = (char)(diff >> 24); - *dp++ = (char)(diff >> 16); - *dp++ = (char)(diff >> 8); - *dp = (char)diff; + SETBE32(wp, 0, diff) #ifdef DO_DEBUG DEBUG printf("%lx\n", diff); #endif @@ -279,15 +259,12 @@ LONG markimg(register char * mp, LONG siz, LONG tsize, int okflag) } } - /* - * Generate ".PRG" relocation information in place in - * the relocation words (the ``RELMOD'' operation). - */ + // Generate ".PRG" relocation information in place in the relocation words + // (the "RELMOD" operation). if (okflag && prg_flag) { - firstp = 1; - wp = mp; - dp = mp; + int firstp = 1; + wp = dp = mp; for(loc=0; loc> 24); - *dp++ = (char)(loc >> 16); - *dp++ = (char)(loc >> 8); - *dp++ = (char)loc; + SETBE32(dp, 0, loc); + dp += 4; firstp = 0; } else { - for(diff=loc-lastloc; diff>254; diff-= 254) + uint32_t diff; + + for(diff=loc-lastloc; diff>254; diff-=254) *dp++ = 1; - *dp++ = (char)diff; + *dp++ = (uint8_t)diff; } - wp += 4; lastloc = loc; loc += 4; + wp += 4; } - else + else { loc += 2; wp += 2; } } - /* - * Terminate relocation list with 0L (if there was no - * relocation) or 0.B (if relocation information was - * written). - */ + // Terminate relocation list with 0L (if there was no relocation) or + // 0.B (if relocation information was written). if (!firstp) *dp++ = 0; - else for (firstp = 0; firstp < 4; ++firstp) - *dp++ = 0; + else + for(firstp=0; firstp<4; firstp++) + *dp++ = 0; - /* - * Return size of relocation information - */ + // Return size of relocation information loc = dp - mp; return loc; } @@ -344,211 +317,230 @@ LONG markimg(register char * mp, LONG siz, LONG tsize, int okflag) // // Make mark image for BSD .o file // -uint32_t bsdmarkimg(char * mp, LONG siz, LONG tsize, int reqseg) +// Assumptions about mark records (for BSD): if there is a symbol, the mark is +// for an undefined symbol, otherwise it's just a normal TDB relocation. +// N.B.: tsize is only used if reqseg is DATA +// +uint32_t MarkBSDImage(uint8_t * mp, uint32_t siz, uint32_t tsize, int reqseg) { - MCHUNK * mch; // Mark chunk - PTR p; // Source point from within mark chunk - uint16_t from; // Section fixups are currently FROM - uint16_t w; // A word (temp) - uint32_t loc; // Location (temp) - SYM * symbol; // Symbols (temp) - uint8_t * wp; // Pointer into raw relocation info - uint8_t * dp; // Deposit point for RELMOD info - uint32_t diff; // Difference to relocate (RELMOD) - uint32_t raddr, rflag = 0; // BSD relocation address and flags - uint32_t rsize; // Relocation size - int validsegment = 0; // Valid segment being processed + uint16_t from = 0; // Section fixups are currently FROM + uint32_t rsize = 0; // Relocation table size (written to mp) + int validsegment = 0; // We are not yet in a valid segment... #ifdef DEBUG_IMAGE_MARKING -printf("bsdmarkimg():\n"); +printf("MarkBSDImage():\n"); #endif - // Initialise relocation size - rsize = 0; + // Initialize relocation table point (for D_foo macros) chptr = mp; - from = 0; - for(mch=firstmch; mch!=NULL; mch=mch->mcnext) + // Run through all the relocation mark chunks + for(MCHUNK * mch=firstmch; mch!=NULL; mch=mch->mcnext) { - for(p=mch->mcptr;;) + for(PTR p=mch->mcptr;;) { - w = *p.wp++; // Next mark entry + SYM * symbol = NULL; + uint16_t w = *p.wp++; // Next mark entry + // If we hit the end of a chunk, go get the next one if (w & MCHEND) - break; // End of mark chunk + break; - // Get mark record - symbol = NULL; - loc = *p.lp++; // Mark location + // Get the rest of the mark record + uint32_t loc = *p.lp++; // Mark location + // Maybe change "from" section if (w & MCHFROM) { - // Maybe change "from" section from = *p.wp++; - if (obj_format == BSD) - { - if (reqseg == TEXT) - { - // Requested segment is TEXT - if (from == TEXT) - validsegment = 1; - else - validsegment = 0; - } - else - { - // Requested segment is DATA - if (from == DATA) - validsegment = 1; - else - validsegment = 0; - } - } + if (((reqseg == TEXT) && (from == TEXT)) + || ((reqseg == DATA) && (from == DATA))) + validsegment = 1; + else + validsegment = 0; } - if (w & MSYMBOL) // Maybe includes a symbol + // Maybe includes a symbol + if (w & MSYMBOL) symbol = *p.sy++; - if (obj_format == BSD) - { - raddr = loc; // Set relocation address + if (!validsegment) + continue; - if (validsegment) #ifdef DEBUG_IMAGE_MARKING -{ printf(" validsegment: raddr = $%08X\n", raddr); #endif - D_long(raddr); // Write relocation address -#ifdef DEBUG_IMAGE_MARKING -} -#endif - - if (w & MPCREL) - rflag = 0x000000A0; // PC-relative fixup - else - rflag = 0x00000040; // Absolute fixup - -// This flag tells the linker to WORD swap the LONG when doing the fixup. - if (w & MMOVEI) -//{ -//printf("bsdmarkimg: ORing $01 to rflag (MMOVEI) [symbol=%s]...\n", symbol->sname); - rflag |= 0x00000001; -//} - } + uint32_t rflag = 0x00000040; // Absolute relocation - // Compute mark position in relocation information; - // in RELMOD mode, get address of data to fix up. - if (from == DATA) - loc += tsize; + if (w & MPCREL) + rflag = 0x000000A0; // PC-relative relocation - wp = (uint8_t *)(mp + loc); + // This flag tells the linker to WORD swap the LONG when doing the + // relocation. + if (w & MMOVEI) + rflag |= 0x00000001; - if (symbol) + if (symbol != NULL) { // Deposit external reference - if (obj_format == BSD) - { - rflag |= 0x00000010; // Set external reloc flag bit - rflag |= (symbol->senv << 8); // Put symbol index in flags - -// Looks like this is completely unnecessary (considering it does the wrong thing!) -#if 0 - if (symbol->sattre & RISCSYM) -{ -printf("bsdmarkimg: ORing $01 to rflag (RISCSYM) [symbol=%s]...\n", symbol->sname); - rflag |= 0x00000001; -} -#endif + rflag |= 0x00000010; // Set external reloc flag bit + rflag |= (symbol->senv << 8); // Put symbol index in flags - if (validsegment) - { #ifdef DEBUG_IMAGE_MARKING printf(" validsegment(2): rflag = $%08X\n", rflag); #endif - D_long(rflag); // Write relocation flags - rsize += 8; // Increment relocation size - } - } } else { - if (obj_format == BSD) - { #ifdef DEBUG_IMAGE_MARKING printf(" w = $%04X\n", w); #endif - w &= TDB; // Set reloc flags to segment + w &= TDB; // Set reloc flags to segment - switch (w) - { - case TEXT: rflag |= 0x00000400; break; - case DATA: rflag |= 0x00000600; break; - case BSS: rflag |= 0x00000800; break; - } + switch (w) + { + case TEXT: rflag |= 0x00000400; break; + case DATA: rflag |= 0x00000600; break; + case BSS: rflag |= 0x00000800; break; + } - if (validsegment) - { #ifdef DEBUG_IMAGE_MARKING printf(" validsegment(3): rflag = $%08X\n", rflag); #endif - D_long(rflag); // Write relocation flags - rsize += 8; // Increment relocation size - } - - w &= TDB; - - if (validsegment) - { - if (w & (DATA|BSS)) - { - dp = objImage + BSDHDRSIZE + loc; - diff = ((LONG)(*dp++ & 0xFF)) << 24; - diff |= ((LONG)(*dp++ & 0xFF)) << 16; - diff |= ((LONG)(*dp++ & 0xFF)) << 8; - diff |= (LONG)(*dp & 0xFF); - DEBUG printf("diff=%ux ==> ", diff); + // Fix relocation by adding in start of TEXT segment, since it's + // currently relative to the start of the DATA (or BSS) segment + if (w & (DATA | BSS)) + { + uint8_t * dp = objImage + BSDHDRSIZE + loc; + + // Bump the start of the section if it's DATA (& not TEXT) + if (from == DATA) + dp += tsize; + + uint32_t diff = GETBE32(dp, 0); + DEBUG printf("diff=%uX ==> ", diff); #ifdef DEBUG_IMAGE_MARKING printf(" validsegment(4): diff = $%08X --> ", diff); #endif - - if (rflag & 0x01) - diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000); + if (rflag & 0x01) + diff = WORDSWAP32(diff); - diff += sect[TEXT].sloc; + diff += sect[TEXT].sloc; - if (w == BSS) - diff += sect[DATA].sloc; + if (w == BSS) + diff += sect[DATA].sloc; - if (rflag & 0x01) - diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000); + if (rflag & 0x01) + diff = WORDSWAP32(diff); - dp = objImage + BSDHDRSIZE + loc; - *dp++ = (char)(diff >> 24); - *dp++ = (char)(diff >> 16); - *dp++ = (char)(diff >> 8); - *dp = (char)diff; - DEBUG printf("%ux\n", diff); + SETBE32(dp, 0, diff); + DEBUG printf("%uX\n", diff); #ifdef DEBUG_IMAGE_MARKING printf("$%08X\n", diff); #endif - } - } } } + + D_long(loc); // Write relocation address + D_long(rflag); // Write relocation flags + rsize += 0x08; // Increment relocation size } } - // Return relocation size - if (obj_format == BSD) + // Return relocation table's size #ifdef DEBUG_IMAGE_MARKING -{ printf(" rsize = $%X\n", rsize); #endif - return rsize; -#ifdef DEBUG_IMAGE_MARKING + return rsize; } -#endif - return siz; + +// +// Make relocation record for ELF .o file. +// Returns the size of the relocation record. +// +uint32_t CreateELFRelocationRecord(uint8_t * buf, uint8_t * secBuf, uint16_t section) +{ + uint16_t from = 0; // Section fixups are currently FROM + uint32_t rsize = 0; // Size of the relocation table + + // Setup pointer for D_long/word/byte macros + chptr = buf; + + for(MCHUNK * mch=firstmch; mch!=NULL; mch=mch->mcnext) + { + for(register PTR p=mch->mcptr;;) + { + register uint16_t w = *p.wp++; // w = next mark entry + + if (w & MCHEND) // (end of mark chunk) + break; + + // Get mark record + SYM * symbol = NULL; + uint16_t symFlags = 0; + uint32_t r_offset = *p.lp++; // Mark's location + + if (w & MCHFROM) // Maybe change "from" section + from = *p.wp++; + + if (w & MSYMBOL) // Maybe includes a symbol + { + symbol = *p.sy++; + + if (symbol) + symFlags = symbol->sattr; + } + + // Create relocation record for ELF object, if the mark is in the + // current section. + if (from & section) + { + uint32_t r_sym = 0; + uint32_t r_type = 0; + uint32_t r_addend = 0; + + // Since we're chucking all symbols here for ELF objects by + // default (cf. sect.c), we discriminate here (normally, if + // there is a symbol in the mark record, it means an undefined + // symbol) :-P + if (symbol && !(symFlags & DEFINED) && (symFlags & GLOBAL)) + r_sym = symbol->senv + extraSyms; + else if (w & TEXT) + r_sym = elfHdrNum[ES_TEXT]; // Mark TEXT segment + else if (w & DATA) + r_sym = elfHdrNum[ES_DATA]; // Mark DATA segment + else if (w & BSS) + r_sym = elfHdrNum[ES_BSS]; // Mark BSS segment + + // Set the relocation type next + if (w & MPCREL) + r_type = 5; // R_68K_PC16 + // N.B.: Since we've established that (from & section) is non- + // zero, this condition will *never* be satisfied... :-P + // It might be better to check the symbol's senv; that is, + // if this is a real problem that needs addressing... + else if ((from & section) == 0) + // In the case of a section referring to a label in another + // section (for example text->data) use a R_68K_PC32 mark. + r_type = 4; // R_68K_PC32 + else + r_type = 1; // R_68K_32 + + if (symbol != NULL) + r_addend = symbol->svalue; // Mark offset into section + else + r_addend = GETBE32(secBuf + r_offset, 0); + + // Deposit the relocation record + D_long(r_offset); + D_long((r_sym << 8) | r_type); + D_long(r_addend); + rsize += 0x0C; + } + } + } + + return rsize; } diff --git a/mark.h b/mark.h index e53ae65..2a6dbe9 100644 --- a/mark.h +++ b/mark.h @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // MARK.H - A record of things that are defined relative to any of the sections -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -10,20 +10,40 @@ #define __MARK_H__ #include "rmac.h" -#include "sect.h" -#define MARK_ALLOC_INCR 1024 // # bytes to alloc for more mark space -#define MIN_MARK_MEM (3 * sizeof(WORD) + 2 * sizeof(LONG)) +// A mark is of the form: +// .W section mark is relative to, and flags in upper byte +// .L location of mark in "from" section +// .W [from] new from section +// .L[L] [symbol] symbol involved in external reference (LL for 64-bit pointers) +#define MCHUNK struct _mchunk +MCHUNK { + MCHUNK * mcnext; // Next mark chunk + PTR mcptr; // Vector of marks + uint16_t mcalloc; // # marks allocted to mark block + uint16_t mcused; // # marks used in block +}; -// Globals, externals, etc. +#define MWORD 0x0000 // Marked word +#define MLONG 0x0100 // Marked long +#define MMOVEI 0x0200 // Mark RISC MOVEI instruction +#define MGLOBAL 0x0800 // Mark contains global +#define MPCREL 0x1000 // Mark is PC-relative +#define MCHEND 0x2000 // Indicates end of mark chunk +#define MSYMBOL 0x4000 // Mark includes symbol pointer +#define MCHFROM 0x8000 // Mark includes change-to-from + +// Exported variables extern MCHUNK * firstmch; // Exported functions void InitMark(void); void StopMark(void); -int rmark(uint16_t, uint32_t, uint16_t, uint16_t, SYM *); -int amark(void); -LONG bsdmarkimg(char *, LONG, LONG, int); +uint32_t MarkRelocatable(uint16_t, uint32_t, uint16_t, uint16_t, SYM *); +uint32_t AllocateMark(void); +uint32_t MarkImage(register uint8_t * mp, uint32_t siz, uint32_t tsize, int okflag); +uint32_t MarkBSDImage(uint8_t *, uint32_t, uint32_t, int); +uint32_t CreateELFRelocationRecord(uint8_t *, uint8_t *, uint16_t section); #endif // __MARK_H__ diff --git a/object.c b/object.c index 4614c38..cbedaab 100644 --- a/object.c +++ b/object.c @@ -1,45 +1,142 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // OBJECT.C - Writing Object Files -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // #include "object.h" -#include "sect.h" -#include "symbol.h" -#include "mark.h" #include "error.h" -#include "riscasm.h" #include "mark.h" +#include "riscasm.h" +#include "sect.h" +#include "symbol.h" + + +//#define DEBUG_ELF + +uint32_t symsize = 0; // Size of BSD/ELF symbol table +uint32_t strindx = 0x00000004; // BSD/ELF string table index +uint8_t * strtable; // Pointer to the symbol string table +uint8_t * objImage; // Global object image pointer +int elfHdrNum[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +uint32_t extraSyms; + +static uint16_t tdb_tab[] = { + 0, // absolute + AL_TEXT, // TEXT segment based + AL_DATA, 0, // DATA segment based + AL_BSS // BSS segment based +}; + +uint32_t PRGFLAGS; /* PRGFLAGS as defined in Atari Compendium Chapter 2 +Definition Bit(s) Meaning +--------------- ------- -------------------------------------------------------- +PF_FASTLOAD 0 If set, clear only the BSS area on program load, + otherwise clear the entire heap. +PF_TTRAMLOAD 1 If set, the program may be loaded into alternative RAM, + otherwise it must be loaded into standard RAM. +PF_TTRAMMEM 2 If set, the program's Malloc() requests may be satisfied + from alternative RAM, otherwise they must be satisfied + from standard RAM. +- 3 Currently unused +See left. 4 & 5 If these bits are set to 0 (PF_PRIVATE), the processes' + entire memory space will be considered private + (when memory protection is enabled).If these bits are + set to 1 (PF_GLOBAL), the processes' entire memory space + will be readable and writable by any process (i.e. + global). If these bits are set to 2 (PF_SUPERVISOR), the + processes' entire memory space will only be readable and + writable by itself and any other process in supervisor + mode.If these bits are set to 3 (PF_READABLE), the + processes' entire memory space will be readable by any + application but only writable by itself. +- 6-15 Currently unused +*/ + + +// +// Add entry to symbol table +// If 'globflag' is 1, make the symbol global +// If in .PRG mode, adjust symbol values for fake link +// +uint8_t * AddSymEntry(register uint8_t * buf, SYM * sym, int globflag) +{ + // Copy symbol name to buffer (first 8 chars or less) + register uint8_t * s = sym->sname; + register int i; + + for(i=0; i<8 && *s; i++) + *buf++ = *s++; + + while (i++ < 8) + *buf++ = '\0'; + + // + // Construct and deposit flag word + // + // o all symbols are AL_DEFINED + // o install T/D/B/A base + // o install 'equated' + // o commons (COMMON) are AL_EXTERN, but not BSS + // o exports (DEFINED) are AL_GLOBAL + // o imports (~DEFINED) are AL_EXTERN + // + register uint16_t w1 = sym->sattr; + register uint16_t w = AL_DEFINED | tdb_tab[w1 & TDB]; + + if (w1 & EQUATED) // Equated + w |= AL_EQUATED; + + if (w1 & COMMON) + { + w |= AL_EXTERN | AL_GLOBAL; // Common symbol + w &= ~AL_BSS; // They're not BSS in Alcyon object files + } + else if (w1 & DEFINED) + { + if (globflag) // Export the symbol + w |= AL_GLOBAL; + } + else + w |= AL_EXTERN; // Imported symbol + + SETBE16(buf, 0, w); + buf += 2; + register uint32_t z = sym->svalue; + + if (prg_flag) // Relocate value in .PRG segment + { + w1 &= DATA | BSS; -/* - * Imports - */ -extern int obj_format; // object file format to write -extern int prg_flag; // generate Atari ST direct executable + if (w1) + z += sect[TEXT].sloc; -LONG symsize = 0; // Size of BSD symbol table -LONG strindx = 0x00000004; // BSD string table index -char * strtable; // Pointer to the symbol string table -char * objImage; // Global object image pointer + if (w1 & BSS) + z += sect[DATA].sloc; + } + + SETBE32(buf, 0, z); // Deposit symbol value + buf += 4; + + return buf; +} // // Add an entry to the BSD symbol table // -char * constr_bsdsymtab(char * buf, SYM * sym, int globflag) +uint8_t * AddBSDSymEntry(uint8_t * buf, SYM * sym, int globflag) { - chptr = buf; // Point to buffer for deposit longs + chptr = buf; // Point to buffer for depositing longs D_long(strindx); // Deposit the symbol string index - WORD w1 = sym->sattr; // Obtain symbol attribute - int w2 = sym->sattre; - LONG z = 0; // Initialise resulting symbol flags + uint16_t w1 = sym->sattr; // Obtain symbol attributes + uint32_t z = 0; // Initialize resulting symbol flags if (w1 & EQUATED) - { + { z = 0x02000000; // Set equated flag } else @@ -56,20 +153,16 @@ char * constr_bsdsymtab(char * buf, SYM * sym, int globflag) z |= 0x01000000; // Set global flag if requested D_long(z); // Deposit symbol attribute - z = sym->svalue; // Obtain symbol value - w1 &= DATA | BSS; // Determine DATA or BSS flag - if (w1) + if (w1 & (DATA | BSS)) z += sect[TEXT].sloc; // If DATA or BSS add TEXT segment size - if (w1 & BSS) + if (w1 & BSS) z += sect[DATA].sloc; // If BSS add DATA segment size D_long(z); // Deposit symbol value - strcpy(strtable + strindx, sym->sname); - strindx += strlen(sym->sname) + 1; // Incr string index incl null terminate buf += 12; // Increment buffer to next record symsize += 12; // Increment symbol table size @@ -78,129 +171,104 @@ char * constr_bsdsymtab(char * buf, SYM * sym, int globflag) } -/* - * Alcyon symbol flags - */ -#define AL_DEFINED 0x8000 -#define AL_EQUATED 0x4000 -#define AL_GLOBAL 0x2000 -#define AL_EQUREG 0x1000 -#define AL_EXTERN 0x0800 -#define AL_DATA 0x0400 -#define AL_TEXT 0x0200 -#define AL_BSS 0x0100 -#define AL_FILE 0x0080 - -LONG PRGFLAGS; /* PRGFLAGS as defined in Atari Compendium Chapter 2 */ - /* Definition Bit(s) Meaning */ - /* PF_FASTLOAD 0 If set, clear only the BSS area on program load, */ - /* otherwise clear the entire heap. */ - /* PF_TTRAMLOAD 1 If set, the program may be loaded into alternative RAM, */ - /* otherwise it must be loaded into standard RAM. */ - /* PF_TTRAMMEM 2 If set, the program's Malloc() requests may be satisfied */ - /* from alternative RAM, otherwise they must be satisfied */ - /* from standard RAM. */ - /* - 3 Currently unused. */ - /* See left. 4 & 5 If these bits are set to 0 (PF_PRIVATE), the processes' */ - /* entire memory space will be considered private */ - /* (when memory protection is enabled).If these bits are */ - /* set to 1 (PF_GLOBAL), the processes' entire memory space */ - /* will be readable and writable by any process (i.e. global). */ - /* If these bits are set to 2 (PF_SUPERVISOR), the processes' */ - /* entire memory space will only be readable and writable by */ - /* itself and any other process in supervisor mode.If these */ - /* bits are set to 3 (PF_READABLE), the processes' entire memory */ - /* space will be readable by any application but only */ - /* writable by itself. */ - /* - 6-15 Currently unused. */ - -static WORD tdb_tab[] = { - 0, /* absolute */ - AL_TEXT, /* TEXT segment based */ - AL_DATA, 0, /* DATA segment based */ - AL_BSS /* BSS segment based */ -}; - - -#define HDRSIZE 0x1C /* size of Alcyon header */ - - -/* - * Add entry to symbol table; - * if `globflag' is 1, make the symbol global; - * if in .PRG mode, adjust symbol values for fake link. - * - */ -char * constr_symtab(register char * buf, SYM * sym, int globflag) +// +// Add entry to ELF symbol table; if `globflag' is 1, make the symbol global +// +uint8_t * AddELFSymEntry(uint8_t * buf, SYM * sym, int globflag) { - register int i; - register char * s; - register WORD w; - register LONG z; - register WORD w1; - - /* - * Copy symbol name - */ - s = sym->sname; - - for(i=0; i<8 && *s; i++) - *buf++ = *s++; + chptr = buf; + D_long(strindx); // st_name + D_long(sym->svalue); // st_value + D_long(0); // st_size + uint8_t st_info = 0; - while (i++ < 8) - *buf++ = '\0'; - - /* - * Construct and deposit flag word - * - * o all symbols are AL_DEFINED - * o install T/D/B/A base - * o install 'equated' - * o commons (COMMON) are AL_EXTERN, but not BSS - * o exports (DEFINED) are AL_GLOBAL - * o imports (~DEFINED) are AL_EXTERN - * - */ - w1 = sym->sattr; - w = AL_DEFINED | tdb_tab[w1 & TDB]; - - if (w1 & EQUATED) /* equated */ - w |= AL_EQUATED; + register WORD w1 = sym->sattr; if (w1 & COMMON) { - w |= AL_EXTERN | AL_GLOBAL; /* common symbol */ - w &= ~AL_BSS; /* they're not BSS in Alcyon object files */ + //w |= AL_EXTERN | AL_GLOBAL; // common symbol + //w &= ~AL_BSS; // they're not BSS in Alcyon object files } else if (w1 & DEFINED) { - if (globflag) /* export the symbol */ - w |= AL_GLOBAL; + if (globflag) // Export the symbol + st_info |= 16; //STB_GLOBAL (1<<4) } - else w |= AL_EXTERN; /* imported symbol */ + else if (w1 & (GLOBAL | REFERENCED)) + st_info |= 16; - *buf++ = w >> 8; - *buf++ = (char)w; + D_byte(st_info); + D_byte(0); // st_other - z = sym->svalue; + uint16_t st_shndx = 0xFFF1; // Assume absolute (equated) number - if (prg_flag) /* relocate value in .PRG segment */ - { - w1 &= DATA | BSS; + if (w1 & TEXT) + st_shndx = elfHdrNum[ES_TEXT]; + else if (w1 & DATA) + st_shndx = elfHdrNum[ES_DATA]; + else if (w1 & BSS) + st_shndx = elfHdrNum[ES_BSS]; + else if (globflag) + st_shndx = 0; // Global, not absolute - if (w1) - z += sect[TEXT].sloc; + D_word(st_shndx); - if (w1 & BSS) - z += sect[DATA].sloc; - } + strcpy(strtable + strindx, sym->sname); + strindx += strlen(sym->sname) + 1; // Incr string index incl null terminate + symsize += 0x10; // Increment symbol table size + + return buf + 0x10; +} - *buf++ = z >> 24; /* deposit symbol value */ - *buf++ = z >> 16; - *buf++ = z >> 8; - *buf++ = z; - return buf; +// +// Helper function for ELF output +// +int DepositELFSectionHeader(uint8_t * ptr, uint32_t name, uint32_t type, uint32_t flags, uint32_t addr, uint32_t offset, uint32_t size, uint32_t link, uint32_t info, uint32_t addralign, uint32_t entsize) +{ + chptr = ptr; + D_long(name); + D_long(type); + D_long(flags); + D_long(addr); + D_long(offset); + D_long(size); + D_long(link); + D_long(info); + D_long(addralign); + D_long(entsize); + return 40; +} + + +// +// Deposit an entry in the Section Header string table +// +uint32_t DepositELFSHSTEntry(uint8_t ** pTable, const uint8_t * s) +{ +#ifdef DEBUG_ELF +printf("DepositELFSHSTEntry: s = \"%s\"\n", s); +#endif + uint32_t strSize = strlen(s); + strcpy(*pTable, s); + *pTable += strSize + 1; + return strSize + 1; +} + + +// +// Deposit a symbol table entry in the ELF Symbol Table +// +uint32_t DepositELFSymbol(uint8_t * ptr, uint32_t name, uint32_t addr, uint32_t size, uint8_t info, uint8_t other, uint16_t shndx) +{ + chptr = ptr; + D_long(name); + D_long(addr); + D_long(size); + *chptr++ = info; + *chptr++ = other; + D_word(shndx); + return 16; } @@ -214,8 +282,8 @@ int WriteObject(int fd) LONG tds; // TEXT & DATA segment size int i; // Temporary int CHUNK * cp; // Chunk (for gather) - char * buf; // Scratch area - char * p; // Temporary ptr + uint8_t * buf; // Scratch area + uint8_t * p; // Temporary ptr LONG ssize; // Size of symbols LONG trsize, drsize; // Size of relocations long unused; // For supressing 'write' warnings @@ -230,7 +298,7 @@ int WriteObject(int fd) // Write requested object file... if ((obj_format == BSD) || ((obj_format == ALCYON) && (prg_flag == 0))) { - // Force BSD format from here onwards + // Force BSD format (if it was ALCYON format) obj_format = BSD; if (verb_flag) @@ -238,7 +306,7 @@ int WriteObject(int fd) printf("Total : %d bytes\n", sect[TEXT].sloc + sect[DATA].sloc + sect[BSS].sloc); } - ssize = ((LONG)sy_assign(NULL, NULL)); // Assign index numbers to the symbols + ssize = sy_assign(NULL, NULL); // Assign index numbers to the symbols tds = sect[TEXT].sloc + sect[DATA].sloc; // Get size of TEXT and DATA segment buf = malloc(0x600000); // Allocate 6mb object file image memory @@ -248,9 +316,9 @@ int WriteObject(int fd) return ERROR; } - memset(buf, 0, 0x600000); // Reset allocated memory + memset(buf, 0, 0x600000); // Clear allocated memory objImage = buf; // Set global object image pointer - strtable = malloc(0x200000); // Allocate 2mb scratch buffer + strtable = malloc(0x200000); // Allocate 2MB string table buffer if (strtable == NULL) { @@ -258,23 +326,23 @@ int WriteObject(int fd) return ERROR; } - memset(strtable, 0, 0x200000); // Reset allocated memory + memset(strtable, 0, 0x200000); // Clear allocated memory // Build object file header - chptr = buf; // Base of header + chptr = buf; // Base of header (for D_foo macros) D_long(0x00000107); // Magic number - D_long(sect[TEXT].sloc); // TEXT size - D_long(sect[DATA].sloc); // DATA size - D_long(sect[BSS].sloc); // BSS size + D_long(sect[TEXT].sloc); // TEXT size + D_long(sect[DATA].sloc); // DATA size + D_long(sect[BSS].sloc); // BSS size D_long(0x00000000); // Symbol size D_long(0x00000000); // First entry (0L) D_long(0x00000000); // TEXT relocation size - D_long(0x00000000); // BSD relocation size + D_long(0x00000000); // DATA relocation size // Construct TEXT and DATA segments (without relocation changes) p = buf + BSDHDRSIZE; - for(i=TEXT; i<=DATA; ++i) + for(i=TEXT; i<=DATA; i++) { for(cp=sect[i].sfcode; cp!=NULL; cp=cp->chnext) { @@ -284,40 +352,46 @@ int WriteObject(int fd) } // Do relocation tables (and make changes to segment data) - p = buf + (BSDHDRSIZE + tds); // Move obj image ptr to reloc info - trsize = bsdmarkimg(p, tds, sect[TEXT].sloc, TEXT);// Do TEXT relocation table - chptr = buf + 24; // Point to relocation hdr entry + p = buf + BSDHDRSIZE + tds; // Move obj image ptr to reloc info + trsize = MarkBSDImage(p, tds, sect[TEXT].sloc, TEXT);// Do TEXT relocation table + chptr = buf + 0x18; // Point to relocation hdr entry D_long(trsize); // Write the relocation table size - p = buf + (BSDHDRSIZE + tds + trsize); // Move obj image ptr to reloc info - drsize = bsdmarkimg(p, tds, sect[TEXT].sloc, DATA);// Do DATA relocation table - chptr = buf + 28; // Point to relocation hdr entry + + // Move obj image ptr to reloc info + p = buf + BSDHDRSIZE + tds + trsize; + drsize = MarkBSDImage(p, tds, sect[TEXT].sloc, DATA);// Do DATA relocation table + chptr = buf + 0x1C; // Point to relocation hdr entry D_long(drsize); // Write the relocation table size - p = buf + (BSDHDRSIZE + tds + trsize + drsize);// Point to start of symbol table - sy_assign(p, constr_bsdsymtab); // Build symbol and string tables - chptr = buf + 16; // Point to sym table size hdr entry + // Point to start of symbol table + p = buf + BSDHDRSIZE + tds + trsize + drsize; + sy_assign(p, AddBSDSymEntry); // Build symbol and string tables + chptr = buf + 0x10; // Point to sym table size hdr entry D_long(symsize); // Write the symbol table size // Point to string table - p = buf + (BSDHDRSIZE + tds + trsize + drsize + symsize); - + p = buf + BSDHDRSIZE + tds + trsize + drsize + symsize; memcpy(p, strtable, strindx); // Copy string table to object image - - if (buf) - free(strtable); // Free allocated memory - chptr = p; // Point to string table size long D_long(strindx); // Write string table size // Write the BSD object file from the object image buffer unused = write(fd, buf, BSDHDRSIZE + tds + trsize + drsize + symsize + strindx + 4); + if (verb_flag) + { + printf("TextRel size: %d bytes\n", trsize); + printf("DataRel size: %d bytes\n", drsize); + } + if (buf) + { + free(strtable); // Free allocated memory free(buf); // Free allocated memory - - } - else if (obj_format==ALCYON) - { + } + } + else if (obj_format == ALCYON) + { if (verb_flag) { if (prg_flag) @@ -330,79 +404,353 @@ int WriteObject(int fd) printf("Total : %d bytes\n", sect[TEXT].sloc + sect[DATA].sloc + sect[BSS].sloc); } } - /* - * Compute size of symbol table; - * assign numbers to the symbols... - */ + + // Compute size of symbol table; assign numbers to the symbols... ssize = 0; + // As we grabbed BSD *and* Alcyon in prg_flag == 0 mode, this is *always* + // false... :-P if (prg_flag != 1) - ssize = ((LONG)sy_assign(NULL, NULL)) * 14; + ssize = sy_assign(NULL, NULL) * 14; - /* - * Alloc memory for header+text+data, symbol and - * relocation information construction. - */ + // Alloc memory for header + text + data, symbol and relocation + // information construction. t = tds = sect[TEXT].sloc + sect[DATA].sloc; if (t < ssize) t = ssize; - buf = (char *)((int)malloc(t + HDRSIZE) + HDRSIZE); - - /* - * Build object file header - * just before the text+data image - */ - chptr = buf - HDRSIZE; /* -> base of header */ - D_word(0x601a); /* 00 - magic number */ - t = sect[TEXT].sloc; /* 02 - TEXT size */ - D_long(t); - t = sect[DATA].sloc; /* 06 - DATA size */ - D_long(t); - t = sect[BSS].sloc; /* 0a - BSS size */ - D_long(t); - D_long(ssize); /* 0e - symbol table size */ - D_long(0); /* 12 - stack size (unused) */ - D_long(PRGFLAGS); /* 16 - PRGFLAGS */ - D_word(0); /* 1a - relocation information exists */ - - /* - * Construct text and data segments; - * fixup relocatable longs in .PRG mode; - * finally write the header+text+data - */ + // Is there any reason to do this this way??? + buf = malloc(t + HDRSIZE); + buf += HDRSIZE; + + // Build object file header just before the text+data image + chptr = buf - HDRSIZE; // -> base of header + D_word(0x601A); // 00 - magic number + D_long(sect[TEXT].sloc); // 02 - TEXT size + D_long(sect[DATA].sloc); // 06 - DATA size + D_long(sect[BSS].sloc); // 0A - BSS size + D_long(ssize); // 0E - symbol table size + D_long(0); // 12 - stack size (unused) + D_long(PRGFLAGS); // 16 - PRGFLAGS + D_word(0); // 1A - relocation information exists + + // Construct text and data segments; fixup relocatable longs in .PRG + // mode; finally write the header + text + data p = buf; for(i=TEXT; i<=DATA; i++) { - for (cp=sect[i].sfcode; cp!=NULL; cp=cp->chnext) + for(cp=sect[i].sfcode; cp!=NULL; cp=cp->chnext) { memcpy(p, cp->chptr, cp->ch_size); p += cp->ch_size; } } + // Do a first pass on the Alcyon image, if in PRG mode if (prg_flag) - markimg(buf, tds, sect[TEXT].sloc, 0); + MarkImage(buf, tds, sect[TEXT].sloc, 0); - write(fd, buf - HDRSIZE, tds + HDRSIZE); + unused = write(fd, buf - HDRSIZE, tds + HDRSIZE); - /* - * Construct and write symbol table - */ + // Construct and write symbol table if (prg_flag != 1) { - sy_assign(buf, constr_symtab); - write(fd, buf, ssize); + sy_assign(buf, AddSymEntry); + unused = write(fd, buf, ssize); + } + + // Construct and write relocation information; the size of it changes if + // we're writing a RELMODed executable. + tds = MarkImage(buf, tds, sect[TEXT].sloc, 1); + unused = write(fd, buf, tds); + } + else if (obj_format == ELF) + { + // Allocate 6MB object file image memory + buf = malloc(0x600000); + + if (buf == NULL) + { + error("cannot allocate object file memory (in BSD mode)"); + return ERROR; + } + + memset(buf, 0, 0x600000); + objImage = buf; // Set global object image pointer + strtable = malloc(0x200000); // Allocate 2MB string table buffer + + if (strtable == NULL) + { + error("cannot allocate string table memory (in BSD mode)"); + return ERROR; + } + + memset(strtable, 0, 0x200000); + + // This is pretty much a first pass at this shite, so there's room for + // improvement. :-P + uint8_t headers[4 * 10 * 10]; // (DWORD * 10) = 1 hdr, 10 entries + int headerSize = 0; + uint8_t shstrtab[128]; // The section header string table proper + uint32_t shstTab[9]; // Index into shstrtab for strings + uint8_t * shstPtr = shstrtab; // Temp pointer + uint32_t shstSize = 0; + int numEntries = 4; // There are always at *least* 4 sections + int shstIndex = 1; // The section where the shstrtab lives + int elfSize = 0; // Size of the ELF object + // Clear the header numbers + memset(elfHdrNum, 0, 9 * sizeof(int)); + + // + // First step is to see what sections need to be made; we also + // construct the section header string table here at the same time. + // + shstTab[ES_NULL] = shstSize; + shstSize += DepositELFSHSTEntry(&shstPtr, ""); + shstTab[ES_SHSTRTAB] = shstSize; + shstSize += DepositELFSHSTEntry(&shstPtr, ".shstrtab"); + shstTab[ES_SYMTAB] = shstSize; + shstSize += DepositELFSHSTEntry(&shstPtr, ".symtab"); + shstTab[ES_STRTAB] = shstSize; + shstSize += DepositELFSHSTEntry(&shstPtr, ".strtab"); + + if (sect[TEXT].sloc > 0) + { + elfHdrNum[ES_TEXT] = shstIndex; + shstTab[ES_TEXT] = shstSize; + shstSize += DepositELFSHSTEntry(&shstPtr, "TEXT"); + shstIndex++; + numEntries++; + } + + if (sect[DATA].sloc > 0) + { + elfHdrNum[ES_DATA] = shstIndex; + shstTab[ES_DATA] = shstSize; + shstSize += DepositELFSHSTEntry(&shstPtr, "DATA"); + shstIndex++; + numEntries++; + } + + if (sect[BSS].sloc > 0) + { + elfHdrNum[ES_BSS] = shstIndex; + shstTab[ES_BSS] = shstSize; + shstSize += DepositELFSHSTEntry(&shstPtr, "BSS"); + shstIndex++; + numEntries++; + } + + if (sect[TEXT].relocs > 0) + { + elfHdrNum[ES_RELATEXT] = shstIndex; + shstTab[ES_RELATEXT] = shstSize; + shstSize += DepositELFSHSTEntry(&shstPtr, ".relaTEXT"); + shstIndex++; + numEntries++; + } + + if (sect[DATA].relocs > 0) + { + elfHdrNum[ES_RELADATA] = shstIndex; + shstTab[ES_RELADATA] = shstSize; + shstSize += DepositELFSHSTEntry(&shstPtr, ".relaDATA"); + shstIndex++; + numEntries++; } - /* - * Construct and write relocation information; - * the size of it changes if we're writing a RELMODed executable. - */ - tds = markimg(buf, tds, sect[TEXT].sloc, 1); - write(fd, buf, tds); + elfHdrNum[ES_SHSTRTAB] = shstIndex + 0; + elfHdrNum[ES_SYMTAB] = shstIndex + 1; + elfHdrNum[ES_STRTAB] = shstIndex + 2; + +#ifdef DEBUG_ELF +printf("ELF shstrtab size: %i bytes. Entries:\n", shstSize); +for(int j=0; jELF" Magic Number + D_byte(0x01); // 04 - 32 vs 64 (1 = 32, 2 = 64) + D_byte(0x02); // 05 - Endianness (1 = LE, 2 = BE) + D_byte(0x01); // 06 - Original version of ELF (set to 1) + D_byte(0x00); // 07 - Target OS ABI (0 = System V) + D_byte(0x00); // 08 - ABI Extra (unneeded) + D_byte(0x00); // 09 - Pad bytes + D_word(0x00); + D_long(0x00); + D_word(0x01); // 10 - ELF Type (1 = relocatable) + D_word(0x04); // 12 - Architecture (EM_68K = 4, Motorola M68K family) + D_long(0x01); // 14 - Version (1 = original ELF) + D_long(0x00); // 18 - Entry point virtual address (unneeded) + D_long(0x00); // 1C - Program header table offset (unneeded) + D_long(0x00); // 20 - Section header table offset (to be determined) + + if (0) + { + // Specifically for 68000 CPU + D_long(0x01000000) // 24 - Processor-specific flags - EF_M68K_M68000 + } + else + { + // CPUs other than 68000 (68020...) + D_long(0); // 24 - Processor-specific flags (ISA dependent) + } + + D_word(0x0034); // 28 - ELF header size in bytes + D_word(0); // 2A - Program header table entry size + D_word(0); // 2C - Program header table entry count + D_word(0x0028); // 2E - Section header entry size - 40 bytes for ELF32 + D_word(numEntries); // 30 - Section header table entry count + D_word(shstIndex); // 32 - Section header string table index + + elfSize += 0x34; + + // Deposit section header 0 (NULL) + headerSize += DepositELFSectionHeader(headers + headerSize, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + int textLoc = elfSize; + + // Construct TEXT section, if any + if (sect[TEXT].sloc > 0) + { + headerSize += DepositELFSectionHeader(headers + headerSize, shstTab[ES_TEXT], 1, 6, 0, elfSize, sect[TEXT].sloc, 0, 0, 2, 0); + + for(CHUNK * cp=sect[TEXT].sfcode; cp!=NULL; cp=cp->chnext) + { + memcpy(buf + elfSize, cp->chptr, cp->ch_size); + elfSize += cp->ch_size; + } + + // Pad for next section (LONG boundary) + elfSize = (elfSize + 3) & ~3; + } + + int dataLoc = elfSize; + + // Construct DATA section, if any + if (sect[DATA].sloc > 0) + { + headerSize += DepositELFSectionHeader(headers + headerSize, shstTab[ES_DATA], 1, 3, 0, elfSize, sect[DATA].sloc, 0, 0, 1, 0); + + for(CHUNK * cp=sect[DATA].sfcode; cp!=NULL; cp=cp->chnext) + { + memcpy(buf + elfSize, cp->chptr, cp->ch_size); + elfSize += cp->ch_size; + } + + // Pad for next section (LONG boundary) + elfSize = (elfSize + 3) & ~3; + } + + // Construct BSS section, if any + if (sect[BSS].sloc > 0) + { + headerSize += DepositELFSectionHeader(headers + headerSize, shstTab[ES_BSS], 8, 3, 0, elfSize, sect[BSS].sloc, 0, 0, 2, 0); + } + + int textrelLoc = headerSize; + + // Add headers for relocated sections, if any... + if (sect[TEXT].relocs > 0) + headerSize += DepositELFSectionHeader(headers + headerSize, shstTab[ES_RELATEXT], 4, 0x00, 0, 0, 0, elfHdrNum[ES_SYMTAB], elfHdrNum[ES_TEXT], 4, 0x0C); + + int datarelLoc = headerSize; + + if (sect[DATA].relocs > 0) + headerSize += DepositELFSectionHeader(headers + headerSize, shstTab[ES_RELADATA], 4, 0x40, 0, 0, 0, elfHdrNum[ES_SYMTAB], elfHdrNum[ES_DATA], 4, 0x0C); + + // Add shstrtab + headerSize += DepositELFSectionHeader(headers + headerSize, shstTab[ES_SHSTRTAB], 3, 0, 0, elfSize, shstSize, 0, 0, 1, 0); + memcpy(buf + elfSize, shstrtab, shstSize); + elfSize += shstSize; + // Pad for next section (LONG boundary) + elfSize = (elfSize + 3) & ~3; + + // Add section headers + int headerLoc = elfSize; + chptr = buf + 0x20; // Set section header offset in ELF header + D_long(headerLoc); + elfSize += (4 * 10) * numEntries; + + // Add symbol table & string table + int symtabLoc = elfSize; + strindx = 0; // Make sure we start at the beginning... + elfSize += DepositELFSymbol(buf + elfSize, 0, 0, 0, 0, 0, 0); + *strtable = 0; + strindx++; + extraSyms = 1; + + if (sect[TEXT].sloc > 0) + { + elfSize += DepositELFSymbol(buf + elfSize, 0, 0, 0, 3, 0, elfHdrNum[ES_TEXT]); + extraSyms++; + } + + if (sect[DATA].sloc > 0) + { + elfSize += DepositELFSymbol(buf + elfSize, 0, 0, 0, 3, 0, elfHdrNum[ES_DATA]); + extraSyms++; + } + + if (sect[BSS].sloc > 0) + { + elfSize += DepositELFSymbol(buf + elfSize, 0, 0, 0, 3, 0, elfHdrNum[ES_BSS]); + extraSyms++; + } + + int numSymbols = sy_assign_ELF(buf + elfSize, AddELFSymEntry); + elfSize += numSymbols * 0x10; + + // String table + int strtabLoc = elfSize; + memcpy(buf + elfSize, strtable, strindx); + elfSize += strindx; + // Pad for next section (LONG boundary) + elfSize = (elfSize + 3) & ~3; + + headerSize += DepositELFSectionHeader(headers + headerSize, shstTab[ES_SYMTAB], 2, 0, 0, symtabLoc, (numSymbols + extraSyms) * 0x10, shstIndex + 2, firstglobal + extraSyms, 4, 0x10); + headerSize += DepositELFSectionHeader(headers + headerSize, shstTab[ES_STRTAB], 3, 0, 0, strtabLoc, strindx, 0, 0, 1, 0); + + // Add relocation tables, if any (no need to align after these, they're + // already on DWORD boundaries) + if (sect[TEXT].relocs > 0) + { + uint32_t textrelSize = CreateELFRelocationRecord(buf + elfSize, buf + textLoc, TEXT); + // Deposit offset & size, now that we know them + chptr = headers + textrelLoc + 0x10; + D_long(elfSize); + D_long(textrelSize); + elfSize += textrelSize; + } + + if (sect[DATA].relocs > 0) + { + uint32_t datarelSize = CreateELFRelocationRecord(buf + elfSize, buf + dataLoc, DATA); + // Deposit offset & size, now that we know them + chptr = headers + datarelLoc + 0x10; + D_long(elfSize); + D_long(datarelSize); + elfSize += datarelSize; + } + + // Copy headers into the object + memcpy(buf + headerLoc, headers, headerSize); + + // Finally, write out the object + unused = write(fd, buf, elfSize); + + // Free allocated memory + if (buf) + { + free(buf); + free(strtable); + } } return 0; diff --git a/object.h b/object.h index 26a1960..f3e79d2 100644 --- a/object.h +++ b/object.h @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // OBJECT.H - Writing Object Files -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -9,11 +9,34 @@ #ifndef __OBJECT_H__ #define __OBJECT_H__ -// Size of BSD header -#define BSDHDRSIZE 0x20 +#include -// Globals, externals, etc. -extern char * objImage; +#define BSDHDRSIZE 0x20 // Size of BSD header +#define HDRSIZE 0x1C // Size of Alcyon header + +// +// Alcyon symbol flags +// +#define AL_DEFINED 0x8000 +#define AL_EQUATED 0x4000 +#define AL_GLOBAL 0x2000 +#define AL_EQUREG 0x1000 +#define AL_EXTERN 0x0800 +#define AL_DATA 0x0400 +#define AL_TEXT 0x0200 +#define AL_BSS 0x0100 +#define AL_FILE 0x0080 + +enum ELFSectionNames +{ + ES_NULL, ES_TEXT, ES_DATA, ES_BSS, ES_RELATEXT, ES_RELADATA, ES_SHSTRTAB, + ES_SYMTAB, ES_STRTAB +}; + +// Exported variables. +extern uint8_t * objImage; +extern int elfHdrNum[]; +extern uint32_t extraSyms; // Exported functions int WriteObject(int); diff --git a/parmode.h b/parmode.h index c003523..5518343 100644 --- a/parmode.h +++ b/parmode.h @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // PARMODE.C - Addressing Modes Parser Include -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -75,7 +75,7 @@ goto AMn_IX0; // Handle ",Xn[.siz][*scale])" } else if (*tok == KW_PC) - { // (PC,Xn[.siz][*scale]) + { // (PC,Xn[.siz][*scale]) tok++; AMn = PCINDEXED; @@ -98,7 +98,7 @@ AnIXREG = *tok++ & 15; switch ((int)*tok) - { // Index reg size: | .W | .L + { // Index reg size: | .W | .L case DOTW: tok++; default: @@ -113,7 +113,7 @@ } if (*tok == '*') - { // scale: *1, *2, *4, *8 + { // scale: *1, *2, *4, *8 tok++; if (*tok++ != CONST || *tok > 8) @@ -137,17 +137,17 @@ } } - if (*tok++ != ')') // final ")" + if (*tok++ != ')') // final ")" goto badmode; goto AnOK; } else if (*tok == '[') - { // ([... + { // ([... goto unmode; } else - { // (expr... + { // (expr... if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK) return ERROR; @@ -191,7 +191,7 @@ } else if (*tok == ')') { - AMn = PCDISP; // expr(PC) + AMn = PCDISP; // expr(PC) tok++; goto AnOK; } @@ -241,7 +241,7 @@ CHK_FOR_DISPn: if (*tok == DOTW) { - // expr.W + // expr.W tok++; AMn = ABSW; diff --git a/procln.c b/procln.c index 2cd1bdc..dd89806 100644 --- a/procln.c +++ b/procln.c @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // PROCLN.C - Line Processing -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -18,7 +18,7 @@ #include "symbol.h" #include "riscasm.h" -#define DEF_KW // Declare keyword values +#define DEF_KW // Declare keyword values #include "kwtab.h" // Incl generated keyword tables & defs #define DEF_MN // Incl 68k keyword definitions @@ -34,8 +34,8 @@ IFENT * ifent; // Current ifent static IFENT ifent0; // Root ifent static IFENT * f_ifent; // Freelist of ifents static int disabled; // Assembly conditionally disabled -int just_bss; // 1, ds.b in microprocessor mode -VALUE pcloc; // Value of "PC" at beginning of line +int just_bss; // 1, ds.b in microprocessor mode +VALUE pcloc; // Value of "PC" at beginning of line SYM * lab_sym; // Label on line (or NULL) const char extra_stuff[] = "extra (unexpected) text found after addressing mode"; @@ -76,15 +76,15 @@ LONG amsktab[0112] = { 0L, // 076 0L, // 077 M_ABASE, // 0100 - M_MEMPOST, // 0101 - M_MEMPRE, // 0102 + M_MEMPOST, // 0101 + M_MEMPRE, // 0102 M_PCBASE, // 0103 M_PCMPOST, // 0104 M_PCMPRE, // 0105 M_AM_USP, // 0106 - M_AM_SR, // 0107 + M_AM_SR, // 0107 M_AM_CCR, // 0110 - M_AM_NONE // 0111 + M_AM_NONE // 0111 }; // 0112 length @@ -251,7 +251,7 @@ as68label: // Check for ".b" ".w" ".l" after directive, macro or mnemonic. siz = SIZN; - if (*tok == DOTW) + if (*tok == DOTW) siz = SIZW, tok++; else if (*tok == DOTL) siz = SIZL, tok++; @@ -368,8 +368,8 @@ normal: { if ((equtyp == EQUREG) && (sy->sattre & UNDEF_EQUR)) { -//REALLY? sy->sattre |= ~UNDEF_EQUR; - sy->sattre &= ~UNDEF_EQUR; +//REALLY? sy->sattre |= ~UNDEF_EQUR; + sy->sattre &= ~UNDEF_EQUR; sy->svalue = 0; } else if ((equtyp == CCDEF) && (sy->sattre & UNDEF_CC)) @@ -602,7 +602,7 @@ When checking to see if it's already been equated, issue a warning. // Invoke macro or complain about bad mnemonic if (state < 0) { - if ((sy = lookup(opname, MACRO, 0)) != NULL) + if ((sy = lookup(opname, MACRO, 0)) != NULL) InvokeMacro(sy, siz); else errors("unknown op '%s'", opname); @@ -727,7 +727,7 @@ int HandleLabel(char * label, int labelType) } -// +// // .if, Start conditional assembly // int d_if(void) @@ -762,7 +762,7 @@ int d_if(void) } -// +// // .else, Do alternate case for .if // int d_else(void) diff --git a/procln.h b/procln.h index 4a64dbd..c645722 100644 --- a/procln.h +++ b/procln.h @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // PROCLN.H - Line Processing -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // diff --git a/riscasm.c b/riscasm.c index 9d95bfc..2c291ff 100644 --- a/riscasm.c +++ b/riscasm.c @@ -385,12 +385,13 @@ int GenerateRISCCode(int state) { if (eattr & TDB) //{ -//printf("RISCASM: Doing rmark for RI_MOVEI (tdb=$%X)...\n", eattr & TDB); - rmark(cursect, sloc + 2, (eattr & TDB), (MLONG | MMOVEI), NULL); +//printf("RISCASM: Doing MarkRelocatable for RI_MOVEI (tdb=$%X)...\n", eattr & TDB); + MarkRelocatable(cursect, sloc + 2, (eattr & TDB), (MLONG | MMOVEI), NULL); //} } - val = ((eval >> 16) & 0x0000FFFF) | ((eval << 16) & 0xFFFF0000); +// val = ((eval >> 16) & 0x0000FFFF) | ((eval << 16) & 0xFFFF0000); + val = WORDSWAP32(eval); CHECK_COMMA; reg2 = GetRegister(FU_REGTWO); at_eol(); diff --git a/riscasm.h b/riscasm.h index a91f703..96623e6 100644 --- a/riscasm.h +++ b/riscasm.h @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // RISCA.H - GPU/DSP Assembler -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // diff --git a/rmac.c b/rmac.c index 5745d52..5842792 100644 --- a/rmac.c +++ b/rmac.c @@ -39,11 +39,11 @@ int rgpu, rdsp; // Assembling Jaguar GPU or DSP code int list_fd; // File to write listing to int regbank; // RISC register bank int segpadsize; // Segment padding size -int endian; // Host processor endianess +int endian; // Host processor endianess (0 = LE, 1 = BE) char * objfname; // Object filename pointer char * firstfname; // First source filename char * cmdlnexec; // Executable name, pointer to ARGV[0] -char * searchpath; // Search path for include files +char * searchpath; // Search path for include files char defname[] = "noname.o"; // Default output filename int optim_flags[OPT_COUNT]; // Specific optimisations on/off matrix @@ -128,6 +128,7 @@ void DisplayHelp(void) " -f[format] Output object file format\n" " a: ALCYON (use this for ST)\n" " b: BSD (use this for Jaguar)\n" + " e: ELF\n" " -i[path] Directory to search for include files\n" " -l[filename] Create an output listing file\n" " -n Don't do things behind your back in RISC assembler\n" @@ -209,7 +210,7 @@ int ParseOptimization(char * optstring) } -// +// // Process command line arguments and do an assembly // int Process(int argc, char ** argv) @@ -304,10 +305,14 @@ int Process(int argc, char ** argv) case 'A': obj_format = ALCYON; break; - case 'b': // -fb = BSD (Jaguar Recommended) + case 'b': // -fb = BSD (Jaguar Recommended: 3 out 4 jaguars recommend it!) case 'B': obj_format = BSD; break; + case 'e': // -fe = ELF + case 'E': + obj_format = ELF; + break; default: printf("-f: unknown object format specified\n"); errcnt++; @@ -585,9 +590,9 @@ int main(int argc, char ** argv) // Set legacy optimisation flags to on // and everything else to off memset(optim_flags, 0, OPT_COUNT * sizeof(int)); - optim_flags[OPT_ABS_SHORT] = + optim_flags[OPT_ABS_SHORT] = optim_flags[OPT_MOVEL_MOVEQ] = - optim_flags[OPT_BSR_BCC_S] = 1; + optim_flags[OPT_BSR_BCC_S] = 1; cmdlnexec = argv[0]; // Obtain executable name diff --git a/rmac.h b/rmac.h index 4a4e8b9..f81b9a9 100644 --- a/rmac.h +++ b/rmac.h @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // RMAC.H - Main Application Code -// Copyright (C) 199x Landon Dyer, 2011 Reboot & Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot & Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -26,7 +26,7 @@ #define PLATFORM "Win32" #define _OPEN_FLAGS _O_TRUNC|_O_CREAT|_O_BINARY|_O_RDWR #define _OPEN_INC _O_RDONLY|_O_BINARY - #define _PERM_MODE _S_IREAD|_S_IWRITE + #define _PERM_MODE _S_IREAD|_S_IWRITE #ifdef _MSC_VER #if _MSC_VER > 1000 #pragma warning(disable:4996) @@ -36,6 +36,7 @@ #define STRINGIZE_HELPER(x) #x #define STRINGIZE(x) STRINGIZE_HELPER(x) #define WARNING(desc) __pragma(message(__FILE__ "(" STRINGIZE(__LINE__) ") : Warning: " #desc)) + #define inline __inline // usage: // WARNING(FIXME: Code removed because...) @@ -48,15 +49,20 @@ // for the fireworks! #define DO_PRAGMA(x) _Pragma (#x) #define WARNING(desc) DO_PRAGMA(message (#desc)) - #define inline __inline #endif -#else +#else + #ifdef __GCCUNIX__ + #ifdef __MINGW32__ + #define off64_t long + #define off_t long + #endif + #include #include - // Release platform - mac OS-X or linux + // Release platform - mac OS-X or Linux #define PLATFORM "OSX/Linux" #define _OPEN_FLAGS O_TRUNC|O_CREAT|O_RDWR #define _OPEN_INC O_RDONLY @@ -65,7 +71,7 @@ #define DO_PRAGMA(x) _Pragma (#x) #define WARNING(desc) DO_PRAGMA(message (#desc)) #else - // Release platform - not specified + // Release platform - not specified #include #define PLATFORM "Unknown" #define _OPEN_FLAGS O_TRUNC|O_CREAT|O_RDWR @@ -77,6 +83,49 @@ #endif #endif +// +// Endian related, for safe handling of endian-sensitive data +// USAGE: GETBExx() is *always* an rvalue, a = pointer to a uint8_t, +// r = offset from 0. SETBExx(), v = value to write into 'a' +// +#define GETBE16(a, r) \ + (((uint16_t)(a)[(r + 0)] << 8) | ((uint16_t)(a)[(r + 1)])) + +#define GETBE32(a, r) \ + (((uint32_t)(a)[(r + 0)] << 24) | ((uint32_t)(a)[(r + 1)] << 16) \ + | ((uint32_t)(a)[(r + 2)] << 8) | ((uint32_t)(a)[(r + 3)])) + +#define GETBE64(a, r) \ + (((uint64_t)(a)[(r + 0)] << 56) | ((uint64_t)(a)[(r + 1)] << 48) \ + | ((uint64_t)(a)[(r + 2)] << 40) | ((uint64_t)(a)[(r + 3)] << 32) \ + | ((uint64_t)(a)[(r + 4)] << 24) | ((uint64_t)(a)[(r + 5)] << 16) \ + | ((uint64_t)(a)[(r + 6)] << 8) | ((uint64_t)(a)[(r + 7)])) + +#define SETBE16(a, r, v) \ + { (a)[(r + 0)] = (uint8_t)((v) >> 8); \ + (a)[(r + 1)] = (uint8_t)((v) & 0xFF); } + +#define SETBE32(a, r, v) \ + { (a)[(r + 0)] = (uint8_t)((v) >> 24); \ + (a)[(r + 1)] = (uint8_t)(((v) >> 16) & 0xFF); \ + (a)[(r + 2)] = (uint8_t)(((v) >> 8) & 0xFF); \ + (a)[(r + 3)] = (uint8_t)((v) & 0xFF); } + +#define SETBE64(a, r, v) \ + { (a)[(r + 0)] = (uint8_t)((v) >> 56); \ + (a)[(r + 1)] = (uint8_t)(((v) >> 48) & 0xFF); \ + (a)[(r + 2)] = (uint8_t)(((v) >> 40) & 0xFF); \ + (a)[(r + 3)] = (uint8_t)(((v) >> 32) & 0xFF); \ + (a)[(r + 4)] = (uint8_t)(((v) >> 24) & 0xFF); \ + (a)[(r + 5)] = (uint8_t)(((v) >> 16) & 0xFF); \ + (a)[(r + 6)] = (uint8_t)(((v) >> 8) & 0xFF); \ + (a)[(r + 7)] = (uint8_t)((v) & 0xFF); } + +// Byteswap crap +#define BYTESWAP16(x) ((((x) & 0x00FF) << 8) | (((x) & 0xFF00) >> 8)) +#define BYTESWAP32(x) ((((x) & 0x000000FF) << 24) | (((x) & 0x0000FF00) << 8) | (((x) & 0x00FF0000) >> 8) | (((x) & 0xFF000000) >> 24)) +#define WORDSWAP32(x) ((((x) & 0x0000FFFF) << 16) | (((x) & 0xFFFF0000) >> 16)) + // // Non-target specific stuff // @@ -90,7 +139,7 @@ #define ERROR (-1) // Generic error return #define EOS '\0' // End of string -#define SPACE ' ' // ASCII space +#define SPACE ' ' // ASCII space #define SLASHCHAR '/' #define SLASHSTRING "/" #define VALUE LONG // Assembler value @@ -133,15 +182,16 @@ #define ALCYON 0 // Alcyon/DRI C object format #define MWC 1 // Mark Williams object format #define BSD 2 // BSD object format +#define ELF 3 // ELF object format // Pointer type that can point to (almost) anything #define PTR union _ptr PTR { - char * cp; // Char - WORD * wp; // WORD - LONG * lp; // LONG - LONG lw; // LONG + uint8_t * cp; // Char + uint16_t * wp; // WORD + uint32_t * lp; // LONG + uint32_t lw; // LONG SYM ** sy; // SYM TOKEN * tk; // TOKEN }; @@ -168,10 +218,10 @@ PTR //#define M6502 0x0008 // 6502/microprocessor (absolute) #define TDB (TEXT|DATA|BSS) // Mask for text+data+bss -// Sizes -#define SIZB 0x0001 // .b -#define SIZW 0x0002 // .w -#define SIZL 0x0004 // .l +// Sizes +#define SIZB 0x0001 // .b +#define SIZW 0x0002 // .w +#define SIZL 0x0004 // .l #define SIZN 0x0008 // no .(size) specifier // RISC register bank definitions (used in extended symbol attributes also) @@ -188,10 +238,10 @@ PTR // Optimisation defines enum { - OPT_ABS_SHORT = 0, - OPT_MOVEL_MOVEQ = 1, - OPT_BSR_BCC_S = 2, - OPT_INDIRECT_DISP = 3, + OPT_ABS_SHORT = 0, + OPT_MOVEL_MOVEQ = 1, + OPT_BSR_BCC_S = 2, + OPT_INDIRECT_DISP = 3, OPT_COUNT // Dummy, used to count number of optimisation switches }; @@ -211,6 +261,7 @@ extern int lsym_flag; extern int sbra_flag; extern int obj_format; extern int legacy_flag; +extern int prg_flag; // 1 = write ".PRG" relocatable executable extern LONG PRGFLAGS; extern int optim_flags[OPT_COUNT]; diff --git a/sect.c b/sect.c index 619c163..b58d441 100644 --- a/sect.c +++ b/sect.c @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // SECT.C - Code Generation, Fixups and Section Management -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -19,33 +19,33 @@ // Function prototypes -void MakeSection(int, WORD); +void MakeSection(int, uint16_t); void SwitchSection(int); // Section descriptors -SECT sect[NSECTS]; // All sections... +SECT sect[NSECTS]; // All sections... int cursect; // Current section number // These are copied from the section descriptor, the current code chunk // descriptor and the current fixup chunk descriptor when a switch is made into // a section. They are copied back to the descriptors when the section is left. -WORD scattr; // Section attributes -LONG sloc; // Current loc in section +uint16_t scattr; // Section attributes +uint32_t sloc; // Current loc in section -CHUNK * scode; // Current (last) code chunk -LONG challoc; // # bytes alloc'd to code chunk -LONG ch_size; // # bytes used in code chunk -char * chptr; // Deposit point in code chunk buffer -char * chptr_opcode; // Backup of chptr, updated before entering code generators +CHUNK * scode; // Current (last) code chunk +uint32_t challoc; // # bytes alloc'd to code chunk +uint32_t ch_size; // # bytes used in code chunk +uint8_t * chptr; // Deposit point in code chunk buffer +uint8_t * chptr_opcode; // Backup of chptr, updated before entering code generators CHUNK * sfix; // Current (last) fixup chunk -LONG fchalloc; // # bytes alloc'd to fixup chunk -LONG fchsize; // # bytes used in fixup chunk +uint32_t fchalloc; // # bytes alloc'd to fixup chunk +uint32_t fchsize; // # bytes used in fixup chunk PTR fchptr; // Deposit point in fixup chunk buffer // Return a size (SIZB, SIZW, SIZL) or 0, depending on what kind of fixup is // associated with a location. -static char fusiztab[] = { +static uint8_t fusiztab[] = { 0, // FU_QUICK 1, // FU_BYTE 2, // FU_WORD @@ -57,7 +57,7 @@ static char fusiztab[] = { }; // Offset to REAL fixup location -static char fusizoffs[] = { +static uint8_t fusizoffs[] = { 0, // FU_QUICK 0, // FU_BYTE 0, // FU_WORD @@ -95,7 +95,7 @@ void InitSection(void) // // Make a new (clean) section // -void MakeSection(int sno, WORD attr) +void MakeSection(int sno, uint16_t attr) { SECT * p = §[sno]; p->scattr = attr; @@ -131,7 +131,7 @@ void SwitchSection(int sno) else challoc = ch_size = 0; - // Copy fixup chunk vars + // Copy fixup chunk vars if ((cp = sfix) != NULL) { fchalloc = cp->challoc; @@ -165,13 +165,9 @@ void SaveSection(void) // Test to see if a location has a fixup sic'd on it. This is used by the // listing generator to print 'xx's instead of '00's for forward references // -int fixtest(int sno, LONG loc) +int fixtest(int sno, uint32_t loc) { - CHUNK * ch; PTR fup; - char * fuend; - WORD w; - LONG xloc; // Force update to sect[] variables StopMark(); @@ -179,15 +175,15 @@ int fixtest(int sno, LONG loc) // Hairy, ugly linear search for a mark on our location; the speed doesn't // matter, since this is only done when generating a listing, which is // SLOW. - for(ch=sect[sno].sffix; ch!=NULL; ch=ch->chnext) + for(CHUNK * ch=sect[sno].sffix; ch!=NULL; ch=ch->chnext) { - fup.cp = (char *)ch->chptr; - fuend = fup.cp + ch->ch_size; + fup.cp = (uint8_t *)ch->chptr; + uint8_t * fuend = fup.cp + ch->ch_size; while (fup.cp < fuend) { - w = *fup.wp++; - xloc = *fup.lp++ + (int)fusizoffs[w & FUMASK]; + uint16_t w = *fup.wp++; + uint32_t xloc = *fup.lp++ + (int)fusizoffs[w & FUMASK]; fup.wp += 2; if (xloc == loc) @@ -207,14 +203,14 @@ int fixtest(int sno, LONG loc) } -// +// // 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). -// +// // If 'amt' is zero, ensure there are at least CH_THRESHOLD bytes, likewise. // -int chcheck(LONG amt) +int chcheck(uint32_t amt) { DEBUG { printf("chcheck(%u)\n", amt); } // If in BSS section, no allocation required @@ -225,7 +221,7 @@ int chcheck(LONG amt) amt = CH_THRESHOLD; DEBUG { printf(" challoc=%i, ch_size=%i, diff=%i\n", challoc, ch_size, challoc-ch_size); } - if ((int)(challoc - ch_size) >= (int)amt) + if ((int)(challoc - ch_size) >= (int)amt) return 0; if (amt < CH_CODE_SIZE) @@ -246,7 +242,7 @@ int chcheck(LONG amt) { 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 @@ -254,7 +250,7 @@ int chcheck(LONG amt) cp->chnext = NULL; challoc = cp->challoc = amt; ch_size = cp->ch_size = 0; - chptr = cp->chptr = ((char *)cp) + sizeof(CHUNK); + chptr = cp->chptr = ((uint8_t *)cp) + sizeof(CHUNK); scode = p->scode = cp; return 0; @@ -263,14 +259,14 @@ int chcheck(LONG amt) // This is really wrong. We need to make some proper structures here so we // don't have to count sizes of objects, that's what the compiler's for! :-P -#define FIXUP_BASE_SIZE (sizeof(WORD) + sizeof(LONG) + sizeof(WORD) + sizeof(WORD)) +#define FIXUP_BASE_SIZE (sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t)) // // Arrange for a fixup on a location // -int AddFixup(WORD attr, LONG loc, TOKEN * fexpr) +int AddFixup(uint16_t attr, uint32_t loc, TOKEN * fexpr) { - LONG i; - LONG len = 0; + uint32_t i; + uint32_t len = 0; CHUNK * cp; SECT * p; // Shamus: Expression lengths are voodoo ATM (variable "i"). Need to fix @@ -284,14 +280,14 @@ WARNING(!!! AddFixup() is filled with VOODOO !!!) if (*fexpr == SYMBOL && fexpr[2] == ENDEXPR) { // Just a single symbol - // SCPCD : correct bit mask for attr (else other FU_xxx will match) + // SCPCD : correct bit mask for attr (else other FU_xxx will match) // NYAN ! if ((attr & FUMASKRISC) == FU_JR) { //printf("AddFixup: ((attr & FUMASKRISC) == FU_JR)\n"); // i = 18; -// i = FIXUP_BASE_SIZE + (sizeof(LONG) * 2); - i = FIXUP_BASE_SIZE + sizeof(SYM *) + sizeof(LONG); +// i = FIXUP_BASE_SIZE + (sizeof(uint32_t) * 2); + i = FIXUP_BASE_SIZE + sizeof(SYM *) + sizeof(uint32_t); } else { @@ -311,9 +307,9 @@ WARNING(!!! AddFixup() is filled with VOODOO !!!) len++; } - len++; // Add 1 for ENDEXPR + len++; // Add 1 for ENDEXPR // i = (len << 2) + 12; - i = FIXUP_BASE_SIZE + sizeof(WORD) + (len * sizeof(TOKEN)); + i = FIXUP_BASE_SIZE + sizeof(uint16_t) + (len * sizeof(TOKEN)); } // Alloc another fixup chunk for this one to fit in if necessary @@ -340,7 +336,7 @@ WARNING(!!! AddFixup() is filled with VOODOO !!!) cp->chnext = NULL; fchalloc = cp->challoc = CH_FIXUP_SIZE; fchsize = cp->ch_size = 0; - fchptr.cp = cp->chptr = ((char *)cp) + sizeof(CHUNK); + fchptr.cp = cp->chptr = ((uint8_t *)cp) + sizeof(CHUNK); sfix = p->sfix = cp; } @@ -349,20 +345,19 @@ WARNING(!!! AddFixup() is filled with VOODOO !!!) *fchptr.wp++ = attr; *fchptr.lp++ = loc; *fchptr.wp++ = cfileno; - *fchptr.wp++ = (WORD)curlineno; + *fchptr.wp++ = (uint16_t)curlineno; // Store postfix expression or pointer to a single symbol, or nothing for a // mark. if (attr & FU_EXPR) { - *fchptr.wp++ = (WORD)len; + *fchptr.wp++ = (uint16_t)len; while (len--) - *fchptr.lp++ = (LONG)*fexpr++; + *fchptr.lp++ = (uint32_t)*fexpr++; } else { -// *fchptr.lp++ = (LONG)fexpr[1]; *fchptr.sy++ = symbolPtr[fexpr[1]]; //printf("AddFixup: adding symbol (%s) [%08X]\n", symbolPtr[fexpr[1]]->sname, symbolPtr[fexpr[1]]->sattr); } @@ -387,24 +382,20 @@ WARNING(!!! AddFixup() is filled with VOODOO !!!) int ResolveFixups(int sno) { PTR fup; // Current fixup - WORD * fuend; // End of last fixup (in this chunk) - WORD w; // Fixup word (type+modes+flags) - char * locp; // Location to fix (in cached chunk) - LONG loc; // Location to fixup - VALUE eval; // Expression value - WORD eattr; // Expression attrib + uint16_t * fuend; // End of last fixup (in this chunk) + uint16_t w; // Fixup word (type+modes+flags) + uint8_t * locp; // Location to fix (in cached chunk) + uint32_t loc; // Location to fixup + VALUE eval; // Expression value + uint16_t eattr; // Expression attrib SYM * esym; // External symbol involved in expr SYM * sy; // (Temp) pointer to a symbol - WORD i; // (Temp) word - WORD tdb; // eattr & TDB - LONG oaddr; + uint16_t i; // (Temp) word + uint16_t tdb; // eattr & TDB + uint32_t oaddr; int reg2; - WORD flags; - unsigned page_jump = 0; - unsigned address = 0; - //unsigned j; - //char buf[EBUFSIZ]; - + uint16_t flags; + SECT * sc = §[sno]; CHUNK * ch = sc->sffix; @@ -421,7 +412,7 @@ int ResolveFixups(int sno) do { fup.cp = ch->chptr; // fup -> start of chunk - fuend = (WORD *)(fup.cp + ch->ch_size); // fuend -> end of chunk + fuend = (uint16_t *)(fup.cp + ch->ch_size); // fuend -> end of chunk while (fup.wp < fuend) { @@ -429,16 +420,18 @@ int ResolveFixups(int sno) loc = *fup.lp++; cfileno = *fup.wp++; curlineno = (int)*fup.wp++; -DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); } + DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); } + // This is based on global vars cfileno, curfname :-P - // This approach is kinda meh as well. I think we can do better than this. + // This approach is kinda meh as well. I think we can do better + // than this. SetFilenameForErrorReporting(); esym = NULL; // 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 + // Fixup is in the "cached" chunk, so the linear-search is seldom // executed. if (loc < cch->chloc || loc >= (cch->chloc + cch->ch_size)) { @@ -450,7 +443,7 @@ DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); } if (cch == NULL) { - // Fixup (loc) out of range + // Fixup (loc) out of range interror(7); // NOTREACHED } @@ -460,6 +453,7 @@ DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); } eattr = 0; // Compute expression/symbol value and attribs + // Complex expression if (w & FU_EXPR) { @@ -484,39 +478,31 @@ DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); } else eval = 0; + // If the symbol is not defined, but global, set esym to sy if ((eattr & (GLOBAL | DEFINED)) == GLOBAL) esym = sy; } - tdb = (WORD)(eattr & TDB); + tdb = (uint16_t)(eattr & TDB); // If the expression is undefined and no external symbol is - // involved, then it's an error. + // involved, then that's an error. if (!(eattr & DEFINED) && (esym == NULL)) { error(undef_error); continue; } -// It seems that this is completely unnecessary! -#if 0 - if (((w & FUMASKRISC) == FU_MOVEI) && esym) -//{ -//printf("DoFixups: Setting symbol attre to RISCSYM...\n"); - esym->sattre |= RISCSYM; -//} -#endif - // 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). - // + // // 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). @@ -556,7 +542,7 @@ DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); } eval -= 2; if (eval + 0x80 >= 0x100) - goto range; + goto rangeErr; if (eval == 0) { @@ -564,7 +550,7 @@ DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); } continue; } - *++locp = (char)eval; + *++locp = (uint8_t)eval; break; // Fixup one-byte value at locp + 1. case FU_WBYTE: @@ -585,23 +571,23 @@ DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); } } if ((w & FU_PCREL) && eval + 0x80 >= 0x100) - goto range; + goto rangeErr; if (w & FU_SEXT) { if (eval + 0x100 >= 0x200) - goto range; + goto rangeErr; } else if (eval >= 0x100) - goto range; + goto rangeErr; - *locp = (char)eval; + *locp = (uint8_t)eval; break; - // Fixup WORD forward references; + // 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)// || ((w & 0x0F00) == FU_MJR)) + if ((w & FUMASKRISC) == FU_JR) { oaddr = *fup.lp++; @@ -616,9 +602,9 @@ DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); } break; } - *locp = (char)(*locp | ((reg2 >> 3) & 0x03)); + *locp = (uint8_t)(*locp | ((reg2 >> 3) & 0x03)); locp++; - *locp = (char)(*locp | ((reg2 & 0x07) << 5)); + *locp = (uint8_t)(*locp | ((reg2 & 0x07) << 5)); break; } @@ -630,9 +616,9 @@ DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); } break; } - *locp = (char)(*locp | ((eval >> 3) & 0x03)); + *locp = (uint8_t)(*locp | ((eval >> 3) & 0x03)); locp++; - *locp = (char)(*locp | ((eval & 0x07) << 5)); + *locp = (uint8_t)(*locp | ((eval & 0x07) << 5)); break; } @@ -644,9 +630,9 @@ DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); } break; } - *locp = (char)(*locp | ((eval >> 3) & 0x03)); + *locp = (uint8_t)(*locp | ((eval >> 3) & 0x03)); locp++; - *locp = (char)(*locp | ((eval & 0x07) << 5)); + *locp = (uint8_t)(*locp | ((eval & 0x07) << 5)); break; } @@ -662,9 +648,9 @@ DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); } eval = (32 - eval); eval = (eval == 32) ? 0 : eval; - *locp = (char)(*locp | ((eval >> 3) & 0x03)); + *locp = (uint8_t)(*locp | ((eval >> 3) & 0x03)); locp++; - *locp = (char)(*locp | ((eval & 0x07) << 5)); + *locp = (uint8_t)(*locp | ((eval & 0x07) << 5)); break; } @@ -676,9 +662,9 @@ DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); } break; } - *locp = (char)(*locp | ((eval >> 3) & 0x03)); + *locp = (uint8_t)(*locp | ((eval >> 3) & 0x03)); locp++; - *locp = (char)(*locp | ((eval & 0x07) << 5)); + *locp = (uint8_t)(*locp | ((eval & 0x07) << 5)); break; } @@ -691,28 +677,28 @@ DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); } } locp++; - *locp = (char)(*locp | (eval & 0x1F)); + *locp = (uint8_t)(*locp | (eval & 0x1F)); break; } if (!(eattr & DEFINED)) { + flags = MWORD; + if (w & FU_PCREL) - w = MPCREL | MWORD; - else - w = MWORD; + flags |= MPCREL; - rmark(sno, loc, 0, w, esym); + MarkRelocatable(sno, loc, 0, flags, esym); } else { if (tdb) - rmark(sno, loc, tdb, MWORD, NULL); + MarkRelocatable(sno, loc, tdb, MWORD, NULL); if (w & FU_SEXT) { if (eval + 0x10000 >= 0x20000) - goto range; + goto rangeErr; } else { @@ -720,50 +706,40 @@ DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); } if (w & FU_ISBRA) { if (eval + 0x8000 >= 0x10000) - goto range; + goto rangeErr; } else if (eval >= 0x10000) - goto range; + goto rangeErr; } } - *locp++ = (char)(eval >> 8); - *locp = (char)eval; + SETBE16(locp, 0, eval); break; // 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) { // Long constant in MOVEI # is word-swapped, so fix it here - eval = ((eval >> 16) & 0x0000FFFF) | ((eval << 16) & 0xFFFF0000); - flags = (MLONG | MMOVEI); + eval = WORDSWAP32(eval); + flags |= MMOVEI; } - else - flags = MLONG; + // If the symbol is undefined, make sure to pass the symbol in + // to the MarkRelocatable() function. if (!(eattr & DEFINED)) - { -//printf("Fixup (long): Symbol undefined. loc = $%X, long = $%X, flags = $%x\n", loc, eval, flags); - rmark(sno, loc, 0, flags, esym); - } + MarkRelocatable(sno, loc, 0, flags, esym); else if (tdb) - { -//printf("Fixup (long): TDB = $%X. loc =$%X, long = $%X, flags = $%x\n", tdb, loc, eval, flags); - rmark(sno, loc, tdb, flags, NULL); - } -//else -//printf("Fixup (long): TDB = $%X. loc =$%X, long = $%X, flags = $%x\n", tdb, loc, eval, flags); + MarkRelocatable(sno, loc, tdb, flags, NULL); - *locp++ = (char)(eval >> 24); - *locp++ = (char)(eval >> 16); - *locp++ = (char)(eval >> 8); - *locp = (char)eval; + SETBE32(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. + // (range of 1..8) in a word. Really bits 1..3 in a byte. case FU_QUICK: if (!(eattr & DEFINED)) { @@ -772,7 +748,7 @@ DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); } } if (eval < 1 || eval > 8) - goto range; + goto rangeErr; *locp |= (eval & 7) << 1; break; @@ -782,9 +758,9 @@ DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); } eval -= (loc + 1); if (eval + 0x80 >= 0x100) - goto range; + goto rangeErr; - *locp = (char)eval; + *locp = (uint8_t)eval; break; default: @@ -793,7 +769,7 @@ DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); } // NOTREACHED } continue; -range: +rangeErr: error("expression out of range"); } @@ -809,9 +785,6 @@ range: // int ResolveAllFixups(void) { - //unsigned i; - //char buf[EBUFSIZ]; - // Make undefined symbols GLOBL if (glob_flag) ForceUndefinedSymbolsGlobal(); @@ -824,4 +797,3 @@ int ResolveAllFixups(void) return 0; } - diff --git a/sect.h b/sect.h index ceeb505..b4c3733 100644 --- a/sect.h +++ b/sect.h @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // SECT.H - Code Generation, Fixups and Section Management -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -14,33 +14,37 @@ // Macros to deposit code in the current section // D_rword deposits a "6502" format (low, high) word (01). // D_rlong deposits a MWC "canonical byte order" longword (2301). -#define D_byte(b) {*chptr++=(char)b; ++sloc; ++ch_size; if(orgactive) ++orgaddr;} -#define D_word(w) {chcheck(2);*chptr++=(char)(w>>8); *chptr++=(char)w; \ - sloc+=2; ch_size+=2; if(orgactive) orgaddr += 2;} -#define D_long(lw) {*chptr++=(char)(lw>>24); *chptr++=(char)(lw>>16);\ - *chptr++=(char)(lw>>8); *chptr++=(char)lw; \ - sloc+=4; ch_size += 4; if(orgactive) orgaddr += 4;} -//#define D_rword(w) {*chptr++=(char)w; *chptr++=(char)(w>>8); \ +#define D_byte(b) {*chptr++=(uint8_t)(b); sloc++; ch_size++; \ + if(orgactive) orgaddr++;} +#define D_word(w) {chcheck(2);*chptr++=(uint8_t)((w)>>8); \ + *chptr++=(uint8_t)(w); \ + sloc += 2; ch_size += 2; if(orgactive) orgaddr += 2;} +#define D_long(lw) {*chptr++=(uint8_t)((lw)>>24); \ + *chptr++=(uint8_t)((lw)>>16);\ + *chptr++=(uint8_t)((lw)>>8); \ + *chptr++=(uint8_t)(lw); \ + sloc += 4; ch_size += 4; if(orgactive) orgaddr += 4;} +//#define D_rword(w) {*chptr++=(uint8_t)w; *chptr++=(uint8_t)(w>>8); \ // sloc+=2; ch_size+=2;if(orgactive) orgaddr += 2;} -//#define D_rlong(lw) {*chptr++=(char)(lw>>16);*chptr++=(char)(lw>>24);\ -// *chptr++=(char)lw;*chptr++=(char)(lw>>8); \ +//#define D_rlong(lw) {*chptr++=(uint8_t)(lw>>16);*chptr++=(uint8_t)(lw>>24);\ +// *chptr++=(uint8_t)lw;*chptr++=(uint8_t)(lw>>8); \ // sloc+=4; ch_size += 4;if(orgactive) orgaddr += 4;} // Fill n bytes with zeroes #define D_ZEROFILL(n) {memset(chptr, 0, n); chptr+=n; sloc+=n; ch_size+=n;\ if (orgactive) orgaddr+=n;} -#define NSECTS 16 // Max. number of sections +#define NSECTS 16 // Max. number of sections // Tunable (storage) definitions -#define CH_THRESHOLD 64 // Minimum amount of space in code chunk -#define CH_CODE_SIZE 2048 // Code chunk normal allocation -#define CH_FIXUP_SIZE 1024 // Fixup chunk normal allocation +#define CH_THRESHOLD 64 // Minimum amount of space in code chunk +#define CH_CODE_SIZE 2048 // Code chunk normal allocation +#define CH_FIXUP_SIZE 1024 // Fixup chunk normal allocation // Section attributes (.scattr) -#define SUSED 0x8000 // Section is used (really, valid) -#define SBSS 0x4000 // Section can contain no data -#define SABS 0x2000 // Section is absolute -#define SPIC 0x1000 // Section is position-independent code +#define SUSED 0x8000 // Section is used (really, valid) +#define SBSS 0x4000 // Section can contain no data +#define SABS 0x2000 // Section is absolute +#define SPIC 0x1000 // Section is position-independent code // Fixup record a WORD of these bits, followed by a loc and then a pointer // to a symbol or an ENDEXPR-terminated postfix expression. @@ -55,19 +59,21 @@ // token.L expression list // (etc) // ENDEXPR.L (end of expression) -#define FUMASK 007 // Mask for fixup cases: -#define FU_QUICK 000 // Fixup 3-bit quick instr field -#define FU_BYTE 001 // Fixup byte -#define FU_WORD 002 // Fixup word -#define FU_WBYTE 003 // Fixup byte (at loc+1) -#define FU_LONG 004 // Fixup long -#define FU_BBRA 005 // Fixup byte branch -#define FU_6BRA 007 // Fixup 6502-format branch offset -#define FU_SEXT 010 // Ok to sign extend -#define FU_PCREL 020 // Subtract PC first -#define FU_EXPR 040 // Expression (not symbol) follows - -#define FUMASKRISC 0x0F00 // Mask for RISC fixup cases +#define FUMASK 007 // Mask for fixup cases: +#define FU_QUICK 000 // Fixup 3-bit quick instr field +#define FU_BYTE 001 // Fixup byte +#define FU_WORD 002 // Fixup word +#define FU_WBYTE 003 // Fixup byte (at loc+1) +#define FU_LONG 004 // Fixup long +#define FU_BBRA 005 // Fixup byte branch +#define FU_6BRA 007 // Fixup 6502-format branch offset +#define FU_SEXT 010 // Ok to sign extend +#define FU_PCREL 020 // Subtract PC first +#define FU_EXPR 040 // Expression (not symbol) follows + +#define FU_GLOBAL 0x0080 // Mark global symbol + +#define FUMASKRISC 0x0F00 // Mask for RISC fixup cases #define FU_MOVEI 0x0100 #define FU_JR 0x0200 #define FU_REGONE 0x0400 @@ -77,71 +83,52 @@ #define FU_REGTWO 0x0800 #define FU_SUB32 0x1000 -#define FU_ISBRA 0x2000 // Word forward fixup is a BRA or DBRA -#define FU_LBRA 0x4000 // Long branch, for short branch detect -#define FU_DONE 0x8000 // Fixup has been done +#define FU_ISBRA 0x2000 // Word forward fixup is a BRA or DBRA +#define FU_LBRA 0x4000 // Long branch, for short branch detect +#define FU_DONE 0x8000 // Fixup has been done // Chunks are used to hold generated code and fixup records #define CHUNK struct _chunk CHUNK { - CHUNK * chnext; // Next, previous chunks in section - CHUNK * chprev; - LONG chloc; // Base addr of this chunk - LONG challoc; // # bytes allocated for chunk - LONG ch_size; // # bytes chunk actually uses - char * chptr; // Data for this chunk + CHUNK * chnext; // Next, previous chunks in section + CHUNK * chprev; + uint32_t chloc; // Base addr of this chunk + uint32_t challoc; // # bytes allocated for chunk + uint32_t ch_size; // # bytes chunk actually uses + uint8_t * chptr; // Data for this chunk }; // Section descriptor #define SECT struct _sect SECT { - WORD scattr; // Section attributes - LONG sloc; // Current loc-in / size-of section - CHUNK * sfcode; // First chunk in section - CHUNK * scode; // Last chunk in section - CHUNK * sffix; // First fixup chunk - CHUNK * sfix; // Last fixup chunk + uint16_t scattr; // Section attributes + uint32_t sloc; // Current loc-in / size-of section + uint32_t relocs; // # of relocations for this section + CHUNK * sfcode; // First chunk in section + CHUNK * scode; // Last chunk in section + CHUNK * sffix; // First fixup chunk + CHUNK * sfix; // Last fixup chunk }; -// A mark is of the form: -// .W section mark is relative to, and flags in upper byte -// .L location of mark in "from" section -// .W [from] new from section -// .L [symbol] symbol involved in external reference -#define MCHUNK struct _mchunk -MCHUNK { - MCHUNK * mcnext; // Next mark chunk - PTR mcptr; // Vector of marks - LONG mcalloc; // # marks allocted to mark block - LONG mcused; // # marks used in block -}; - -#define MWORD 0x0000 // Marked word -#define MLONG 0x0100 // Marked long -#define MMOVEI 0x0200 -#define MCHFROM 0x8000 // Mark includes change-to-from -#define MSYMBOL 0x4000 // Mark includes symbol number -#define MCHEND 0x2000 // Indicates end of mark chunk -#define MPCREL 0x1000 // Mark is PC-relative - // Globals, external etc -extern LONG sloc; -extern WORD scattr; -extern char * chptr; -extern char * chptr_opcode; -extern LONG ch_size; +extern uint32_t sloc; +extern uint16_t scattr; +extern uint8_t * chptr; +extern uint8_t * chptr_opcode; +extern uint32_t ch_size; extern int cursect; extern SECT sect[]; -extern LONG challoc; +extern uint32_t challoc; extern CHUNK * scode; // Prototypes void InitSection(void); void SwitchSection(int); void SaveSection(void); -int fixtest(int, LONG); -int chcheck(LONG); -int AddFixup(WORD, LONG, TOKEN *); +int fixtest(int, uint32_t); +int chcheck(uint32_t); +int AddFixup(uint16_t, uint32_t, TOKEN *); int ResolveAllFixups(void); #endif // __SECT_H__ + diff --git a/symbol.c b/symbol.c index 9ba661f..f2f513c 100644 --- a/symbol.c +++ b/symbol.c @@ -7,29 +7,31 @@ // #include "symbol.h" +#include "error.h" #include "listing.h" +#include "object.h" #include "procln.h" -#include "error.h" // Macros -#define NBUCKETS 256 // Number of hash buckets (power of 2) - -static SYM * symbolTable[NBUCKETS]; // User symbol-table header -int curenv; // Current enviroment number -static SYM * sorder; // * -> Symbols, in order of reference -static SYM * sordtail; // * -> Last symbol in sorder list -static SYM * sdecl; // * -> Symbols, in order of declaration -static SYM * sdecltail; // * -> Last symbol in sdecl list -static uint32_t currentUID; // Symbol UID tracking (done by NewSymbol()) - -// Tags for marking symbol spaces +#define NBUCKETS 256 // Number of hash buckets (power of 2) + +static SYM * symbolTable[NBUCKETS]; // User symbol-table header +int curenv; // Current enviroment number +static SYM * sorder; // * -> Symbols, in order of reference +static SYM * sordtail; // * -> Last symbol in sorder list +static SYM * sdecl; // * -> Symbols, in order of declaration +static SYM * sdecltail; // * -> Last symbol in sdecl list +static uint32_t currentUID; // Symbol UID tracking (done by NewSymbol()) +uint32_t firstglobal; // Index of the first global symbol in an ELF object. + +// Tags for marking symbol spaces: // a = absolute // t = text // d = data // ! = "impossible!" // b = BSS -static char tdb_text[8] = { +static uint8_t tdb_text[8] = { 'a', 't', 'd', '!', 'b', SPACE, SPACE, SPACE }; @@ -39,9 +41,7 @@ static char tdb_text[8] = { // void InitSymbolTable(void) { - int i; // Iterator - - for(i=0; isname = strdup(name); - symbol->stype = (BYTE)type; - symbol->senv = (WORD)envno; + symbol->stype = (uint8_t)type; + symbol->senv = (uint16_t)envno; + // We don't set this as DEFINED, as it could be a forward reference! symbol->sattr = 0; - // Don't do this, it could be a forward reference! -// symbol->sattr = DEFINED; // We just defined it... - // This is a bad assumption. Not every symbol 1st seen in a RISC section is - // a RISC symbol! -// symbol->sattre = (rgpu || rdsp ? RISCSYM : 0); + // We don't set RISCSYM here as not every symbol first seen in a RISC + // section is a RISC symbol! symbol->sattre = 0; symbol->svalue = 0; symbol->sorder = NULL; symbol->uid = currentUID++; - // Install symbol in symbol table + // Install symbol in the symbol table int hash = HashSymbol(name, envno); symbol->snext = symbolTable[hash]; symbolTable[hash] = symbol; - // Append symbol to symbol-order list + // Append symbol to the symbol-order list if (sorder == NULL) - sorder = symbol; // Add first symbol + sorder = symbol; // Add first symbol else sordtail->sorder = symbol; // Or append to tail of list @@ -121,7 +119,7 @@ SYM * NewSymbol(char * name, int type, int envno) // Look up the symbol name by its UID and return the pointer to the name. // If it's not found, return NULL. // -char * GetSymbolNameByUID(uint32_t uid) +uint8_t * GetSymbolNameByUID(uint32_t uid) { //problem is with string lookup, that's why we're writing this //so once this is written, we can put the uid in the token stream @@ -143,10 +141,10 @@ char * GetSymbolNameByUID(uint32_t uid) // -// Lookup the symbol `name', of the specified type, with the specified +// Lookup the symbol 'name', of the specified type, with the specified // enviroment level // -SYM * lookup(char * name, int type, int envno) +SYM * lookup(uint8_t * name, int type, int envno) { SYM * symbol = symbolTable[HashSymbol(name, envno)]; @@ -182,7 +180,7 @@ void AddToSymbolDeclarationList(SYM * symbol) if (sdecl == NULL) sdecl = symbol; // First on decl-list - else + else sdecltail->sdecl = symbol; // Add to end of list // Fix up list's tail @@ -200,8 +198,8 @@ void ForceUndefinedSymbolsGlobal(void) DEBUG printf("~ForceUndefinedSymbolsGlobal()\n"); - // Scan through all symbols; - // If a symbol is REFERENCED but not DEFINED, then make it global. + // Scan through all symbols; if a symbol is REFERENCED but not DEFINED, + // then make it global. for(sy=sorder; sy!=NULL; sy=sy->sorder) { if (sy->stype == LABEL && sy->senv == 0 @@ -211,58 +209,43 @@ void ForceUndefinedSymbolsGlobal(void) } -// -// Convert string to uppercase -// -int uc_string(char * s) -{ - for(; *s; s++) - { - if (*s >= 'a' && *s <= 'z') - *s -= 32; - } - - return 0; -} - - // // Assign numbers to symbols that are to be exported or imported. The symbol -// number is put in `.senv'. Return the number of symbols that will be in the +// number is put in 'senv'. Returns the number of symbols that will be in the // symbol table. // -int sy_assign(char * buf, char *(* constr)()) +// N.B.: This is usually called twice; first time with NULL parameters and the +// second time with real ones. The first one is typically done to get a +// count of the # of symbols in the symbol table, and the second is to +// actually create it. +// +uint32_t sy_assign(uint8_t * buf, uint8_t *(* construct)()) { - SYM * sy; - int scount = 0; + uint16_t scount = 0; + // Done only on first pass... if (buf == NULL) { // Append all symbols not appearing on the .sdecl list to the end of // the .sdecl list - for(sy=sorder; sy!=NULL; sy=sy->sorder) + for(SYM * sy=sorder; sy!=NULL; sy=sy->sorder) AddToSymbolDeclarationList(sy); } // Run through all symbols (now on the .sdecl list) and assign numbers to // them. We also pick which symbols should be global or not here. - for(sy=sdecl; sy!=NULL; sy=sy->sdecl) + for(SYM * sy=sdecl; sy!=NULL; sy=sy->sdecl) { - // Don't want register/CC or undefined on our list -//these should already be rejected above... -// if (sy->sattre & (EQUATEDREG | UNDEF_EQUR | EQUATEDCC | UNDEF_CC))) -// continue; - // Export or import external references, and export COMMON blocks. if ((sy->stype == LABEL) && ((sy->sattr & (GLOBAL | DEFINED)) == (GLOBAL | DEFINED) || (sy->sattr & (GLOBAL | REFERENCED)) == (GLOBAL | REFERENCED)) || (sy->sattr & COMMON)) { - sy->senv = (WORD)scount++; + sy->senv = scount++; if (buf != NULL) - buf = (*constr)(buf, sy, 1); + buf = construct(buf, sy, 1); } // Export vanilla labels (but don't make them global). An exception is // made for equates, which are not exported unless they are referenced. @@ -270,49 +253,159 @@ int sy_assign(char * buf, char *(* constr)()) && (sy->sattr & (DEFINED | REFERENCED)) != 0 && (!as68_flag || *sy->sname != 'L')) { - sy->senv = (WORD)scount++; + sy->senv = scount++; if (buf != NULL) - buf = (*constr)(buf, sy, 0); + buf = construct(buf, sy, 0); } } + // For ELF object mode run through all symbols in reference order + // and export all global-referenced labels. Not sure if this is + // required but it's here nonetheless +/* why?? when you have sy_assign_ELF ??? + if (obj_format == ELF) + { + for(sy=sdecl; sy!=NULL; sy=sy->sorder) + { + if ((sy->sattr == (GLOBAL | REFERENCED)) && (buf != NULL)) + { + buf = (*construct)(buf, sy, 0); + scount++; + } + } + }*/ + return scount; } +// +// Custom version of sy_assign for ELF .o files. +// The order that the symbols should be dumped is different. +// (globals must be explicitly at the end of the table) +// +// N.B.: It should be possible to merge this with sy_assign, as there's nothing +// really ELF specific in here, other than the "globals go at the end of +// the queue" thing, which doesn't break the others. :-P +uint32_t sy_assign_ELF(uint8_t * buf, uint8_t *(* construct)()) +{ + uint16_t scount = 0; + +// if (construct == (uint8_t *(*)())constr_elfsymtab) +// if (buf == NULL) + { + // Append all symbols not appearing on the .sdecl list to the end of + // the .sdecl list + for(SYM * sy=sorder; sy!=NULL; sy=sy->sorder) + AddToSymbolDeclarationList(sy); + } + + // Run through all symbols (now on the .sdecl list) and assign numbers to + // them. We also pick which symbols should be global or not here. + for(SYM * sy=sdecl; sy!=NULL; sy=sy->sdecl) + { + // Export or import external references, and export COMMON blocks. + //if ((sy->stype == LABEL) + // && ((sy->sattr & (GLOBAL | DEFINED)) == (GLOBAL | DEFINED) + // || (sy->sattr & (GLOBAL | REFERENCED)) == (GLOBAL | REFERENCED)) + // || (sy->sattr & COMMON)) + //{ + // sy->senv = (WORD)scount++; + // + // if (buf != NULL) + // buf = (*construct)(buf, sy, 1); + //} + // Export vanilla labels (but don't make them global). An exception is + // made for equates, which are not exported unless they are referenced. + if (sy->stype == LABEL && lsym_flag + && (sy->sattr & (DEFINED | REFERENCED)) != 0 + && (*sy->sname != '.') + && (sy->sattr & GLOBAL) == 0) + //if (sy->stype == 0) + // if (lsym_flag) + // if ((sy->sattr & (DEFINED | REFERENCED)) != 0) + // if ((!as68_flag || *sy->sname != 'L')) + { + sy->senv = scount++; + + if (buf != NULL) + buf = construct(buf, sy, 0); + } + } + + firstglobal = scount; + + // For ELF object mode run through all symbols in reference order + // and export all global-referenced labels. Not sure if this is + // required but it's here nonetheless + + //for(sy=sdecl; sy!=NULL; sy=sy->sorder) + for(SYM * sy=sdecl; sy!=NULL; sy=sy->sdecl) + { + if ((sy->stype == LABEL) + && ((sy->sattr & (GLOBAL | DEFINED)) == (GLOBAL | DEFINED) + || (sy->sattr & (GLOBAL | REFERENCED)) == (GLOBAL | REFERENCED)) + || (sy->sattr & COMMON)) + { + sy->senv = scount++; + + if (buf != NULL) + buf = construct(buf, sy, 1); + } + else if ((sy->sattr == (GLOBAL | REFERENCED)) && (buf != NULL)) + { + buf = construct(buf, sy, 0); + scount++; + } + } + + return scount; +} + + +// +// Convert string to uppercase +// +void ToUppercase(uint8_t * s) +{ + for(; *s; s++) + { + if (*s >= 'a' && *s <= 'z') + *s -= 0x20; + } +} + + // // Generate symbol table for listing file // int symtable(void) { + extern int pagelen; int i; int j; SYM * q = NULL; SYM * p; SYM * r; SYM * k; - SYM ** sy; SYM * colptr[4]; - char ln[150]; - char ln1[150]; + char ln[200]; + char ln1[200]; char ln2[20]; char c, c1; WORD w; int ww; - int colhei; - extern int pagelen; + int colhei = pagelen - 5; - colhei = pagelen - 5; + // Allocate storage for list headers and partition all labels. Throw away + // macros and macro arguments. + SYM ** sy = (SYM **)malloc(128 * sizeof(uint32_t)); - // Allocate storage for list headers and partition all labels. - // Throw away macros and macro arguments. - sy = (SYM **)malloc(128 * sizeof(LONG)); - - for(i=0; i<128; ++i) + for(i=0; i<128; i++) sy[i] = NULL; - for(i=0; isvalue); - uc_string(ln2); + ToUppercase(ln2); } sprintf(ln1, " %16s %s %c%c%c", q->sname, ln2, (ww & EQUATEDREG) ? 'e' : SPACE, c1, c); diff --git a/symbol.h b/symbol.h index bd32a5e..9c5c26a 100644 --- a/symbol.h +++ b/symbol.h @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // SYMBOL.H - Symbol Handling -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -15,7 +15,7 @@ struct LineList { struct LineList * next; - char * line; + uint8_t * line; }; // Symbols @@ -25,12 +25,12 @@ SYM SYM * snext; // * -> Next symbol on hash-chain SYM * sorder; // * -> Next sym in order of reference SYM * sdecl; // * -> Next sym in order of declaration - uint8_t stype; // Symbol type + uint8_t stype; // Symbol type uint16_t sattr; // Attribute bits uint32_t sattre; // Extended attribute bits uint16_t senv; // Enviroment number uint32_t svalue; // Symbol value - char * sname; // * -> Symbol's print-name + uint8_t * sname; // * -> Symbol's print-name struct LineList * lineList; // * -> Macro's linked list of lines struct LineList * last; // * -> end of macro linked list uint32_t uid; // Symbol's unique ID @@ -38,18 +38,19 @@ SYM // Globals, externals, etc. extern int curenv; -extern char subttl[]; -extern int eject(void); +extern uint8_t subttl[]; +extern uint32_t firstglobal;// Index of the fist global symbol in an ELF object. // Exported functions -SYM * lookup(char *, int, int); +SYM * lookup(uint8_t *, int, int); void InitSymbolTable(void); -SYM * NewSymbol(char *, int, int); +SYM * NewSymbol(uint8_t *, int, int); void AddToSymbolDeclarationList(SYM *); void ForceUndefinedSymbolsGlobal(void); int symtable(void); -int sy_assign(char *, char *(*)()); -char * GetSymbolNameByUID(uint32_t); +uint32_t sy_assign(uint8_t *, uint8_t *(*)()); +uint32_t sy_assign_ELF(uint8_t *, uint8_t *(*)()); +uint8_t * GetSymbolNameByUID(uint32_t); #endif // __SYMBOL_H__ diff --git a/token.c b/token.c index 30f529d..8726eb4 100644 --- a/token.c +++ b/token.c @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // TOKEN.C - Token Handling -// Copyright (C) 199x Landon Dyer, 2011-2012 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2011-2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -13,7 +13,7 @@ #include "symbol.h" #define DECL_KW // Declare keyword arrays -#define DEF_KW // Declare keyword values +#define DEF_KW // Declare keyword values #include "kwtab.h" // Incl generated keyword tables & defs @@ -23,7 +23,7 @@ int totlines; // Total # of lines int mjump_align = 0; // mjump alignment flag char lntag; // Line tag char * curfname; // Current filename -char tolowertab[128]; // Uppercase ==> lowercase +char tolowertab[128]; // Uppercase ==> lowercase int8_t hextab[128]; // Table of hex values char dotxtab[128]; // Table for ".b", ".s", etc. char irbuf[LNSIZ]; // Text for .rept block line @@ -54,28 +54,28 @@ static IMACRO * f_imacro; // Ptr list of free IMACROs static TOKEN tokbuf[TOKBUFSIZE]; // Token buffer (stack-like, all files) char chrtab[] = { - ILLEG, ILLEG, ILLEG, ILLEG, // NUL SOH STX ETX - ILLEG, ILLEG, ILLEG, ILLEG, // EOT ENQ ACK BEL - ILLEG, WHITE, ILLEG, ILLEG, // BS HT LF VT - WHITE, ILLEG, ILLEG, ILLEG, // FF CR SO SI + ILLEG, ILLEG, ILLEG, ILLEG, // NUL SOH STX ETX + ILLEG, ILLEG, ILLEG, ILLEG, // EOT ENQ ACK BEL + ILLEG, WHITE, ILLEG, ILLEG, // BS HT LF VT + WHITE, ILLEG, ILLEG, ILLEG, // FF CR SO SI - ILLEG, ILLEG, ILLEG, ILLEG, // DLE DC1 DC2 DC3 - ILLEG, ILLEG, ILLEG, ILLEG, // DC4 NAK SYN ETB - ILLEG, ILLEG, ILLEG, ILLEG, // CAN EM SUB ESC - ILLEG, ILLEG, ILLEG, ILLEG, // FS GS RS US + ILLEG, ILLEG, ILLEG, ILLEG, // DLE DC1 DC2 DC3 + ILLEG, ILLEG, ILLEG, ILLEG, // DC4 NAK SYN ETB + ILLEG, ILLEG, ILLEG, ILLEG, // CAN EM SUB ESC + ILLEG, ILLEG, ILLEG, ILLEG, // FS GS RS US WHITE, MULTX, MULTX, SELF, // SP ! " # MULTX+CTSYM, MULTX, SELF, MULTX, // $ % & ' SELF, SELF, SELF, SELF, // ( ) * + SELF, SELF, STSYM, SELF, // , - . / - DIGIT+HDIGIT+CTSYM, DIGIT+HDIGIT+CTSYM, // 0 1 - DIGIT+HDIGIT+CTSYM, DIGIT+HDIGIT+CTSYM, // 2 3 - DIGIT+HDIGIT+CTSYM, DIGIT+HDIGIT+CTSYM, // 4 5 - DIGIT+HDIGIT+CTSYM, DIGIT+HDIGIT+CTSYM, // 6 7 - DIGIT+HDIGIT+CTSYM, DIGIT+HDIGIT+CTSYM, // 8 9 - MULTX, MULTX, // : ; - MULTX, MULTX, MULTX, STSYM+CTSYM, // < = > ? + DIGIT+HDIGIT+CTSYM, DIGIT+HDIGIT+CTSYM, // 0 1 + DIGIT+HDIGIT+CTSYM, DIGIT+HDIGIT+CTSYM, // 2 3 + DIGIT+HDIGIT+CTSYM, DIGIT+HDIGIT+CTSYM, // 4 5 + DIGIT+HDIGIT+CTSYM, DIGIT+HDIGIT+CTSYM, // 6 7 + DIGIT+HDIGIT+CTSYM, DIGIT+HDIGIT+CTSYM, // 8 9 + MULTX, MULTX, // : ; + MULTX, MULTX, MULTX, STSYM+CTSYM, // < = > ? MULTX, STSYM+CTSYM+HDIGIT, // @ A (char)((BYTE)DOT)+STSYM+CTSYM+HDIGIT, STSYM+CTSYM+HDIGIT, // B C @@ -96,10 +96,10 @@ char chrtab[] = { STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, // h i j k (char)((BYTE)DOT)+STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, // l m n o - STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, (char)((BYTE)DOT)+STSYM+CTSYM, // p q r s - STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, (char)((BYTE)DOT)+STSYM+CTSYM, // t u v w - STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, SELF, // x y z { - SELF, SELF, SELF, ILLEG // | } ~ DEL + STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, (char)((BYTE)DOT)+STSYM+CTSYM, // p q r s + STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, (char)((BYTE)DOT)+STSYM+CTSYM, // t u v w + STSYM+CTSYM, STSYM+CTSYM, STSYM+CTSYM, SELF, // x y z { + SELF, SELF, SELF, ILLEG // | } ~ DEL }; // Names of registers @@ -110,7 +110,7 @@ static char * regname[] = { }; static char * riscregname[] = { - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31" @@ -155,15 +155,15 @@ void InitTokenizer(void) tolowertab[i] |= 0x20; // These characters are legal immediately after a period - dotxtab['b'] = DOTB; // .b .B .s .S + dotxtab['b'] = DOTB; // .b .B .s .S dotxtab['B'] = DOTB; dotxtab['s'] = DOTB; dotxtab['S'] = DOTB; - dotxtab['w'] = DOTW; // .w .W + dotxtab['w'] = DOTW; // .w .W dotxtab['W'] = DOTW; - dotxtab['l'] = DOTL; // .l .L + dotxtab['l'] = DOTL; // .l .L dotxtab['L'] = DOTL; - dotxtab['i'] = DOTI; // .i .I (???) + dotxtab['i'] = DOTI; // .i .I (???) dotxtab['I'] = DOTI; } @@ -230,7 +230,7 @@ INOBJ * a_inobj(int typ) inobj->inobj.ifile = ifile; break; - case SRC_IMACRO: // Alloc and init an IMACRO + case SRC_IMACRO: // Alloc and init an IMACRO if (f_imacro == NULL) imacro = malloc(sizeof(IMACRO)); else @@ -288,7 +288,6 @@ int ExpandMacro(char * src, char * dest, int destsiz) IMACRO * imacro = cur_inobj->inobj.imacro; int macnum = (int)(imacro->im_macro->sattr); -// destsiz--; char * dst = dest; // Next dest slot char * edst = dest + destsiz - 1; // End + 1(?) of dest buffer @@ -316,7 +315,7 @@ int ExpandMacro(char * src, char * dest, int destsiz) // Skip comments in case a loose @ or \ is in there // In that case the tokeniser was trying to expand it. - if (*s == '*' || *s == ';' || ((*s == '/') && (*(s + 1) == '/'))) + if ((*s == ';') || ((*s == '/') && (*(s + 1) == '/'))) goto skipcomments; *dst++ = *s++; @@ -335,11 +334,11 @@ int ExpandMacro(char * src, char * dest, int destsiz) *dst++ = *s++; continue; - case '?': // \? set `questmark' flag + case '?': // \? set `questmark' flag ++s; questmark = 1; break; - case '#': // \#, number of arguments + case '#': // \#, number of arguments sprintf(numbuf, "%d", (int)imacro->im_nargs); goto copystr; case '!': // \! size suffix supplied on invocation @@ -352,7 +351,7 @@ int ExpandMacro(char * src, char * dest, int destsiz) } goto copy_d; - case '~': // ==> unique label string Mnnnn... + case '~': // ==> unique label string Mnnnn... sprintf(numbuf, "M%u", curuniq); copystr: d = numbuf; @@ -627,8 +626,6 @@ overflow: // char * GetNextMacroLine(void) { -// unsigned source_addr; - IMACRO * imacro = cur_inobj->inobj.imacro; // LONG * strp = imacro->im_nextln; struct LineList * strp = imacro->im_nextln; @@ -636,7 +633,6 @@ char * GetNextMacroLine(void) if (strp == NULL) // End-of-macro return NULL; -// imacro->im_nextln = (LONG *)*strp; imacro->im_nextln = strp->next; // ExpandMacro((char *)(strp + 1), imacro->im_lnbuf, LNSIZ); ExpandMacro(strp->line, imacro->im_lnbuf, LNSIZ); @@ -682,17 +678,13 @@ char * GetNextRepeatLine(void) // int include(int handle, char * fname) { - IFILE * ifile; - INOBJ * inobj; - FILEREC * fr; - // Debug mode if (debug) printf("[include: %s, cfileno=%u]\n", fname, cfileno); // Alloc and initialize include-descriptors - inobj = a_inobj(SRC_IFILE); - ifile = inobj->inobj.ifile; + INOBJ * inobj = a_inobj(SRC_IFILE); + IFILE * ifile = inobj->inobj.ifile; ifile->ifhandle = handle; // Setup file handle ifile->ifind = ifile->ifcnt = 0; // Setup buffer indices @@ -700,21 +692,20 @@ int include(int handle, char * fname) ifile->ifoldfname = curfname; // Save old filename ifile->ifno = cfileno; // Save old file number -// cfileno = filecount++; // Compute new file number // NB: This *must* be preincrement, we're adding one to the filecount here! cfileno = ++filecount; // Compute NEW file number curfname = strdup(fname); // Set current filename (alloc storage) curlineno = 0; // Start on line zero // Add another file to the file-record - fr = (FILEREC *)malloc(sizeof(FILEREC)); + FILEREC * fr = (FILEREC *)malloc(sizeof(FILEREC)); fr->frec_next = NULL; fr->frec_name = curfname; if (last_fr == NULL) - filerec = fr; // Add first filerec + filerec = fr; // Add first filerec else - last_fr->frec_next = fr; // Append to list of filerecs + last_fr->frec_next = fr; // Append to list of filerecs last_fr = fr; DEBUG printf("[include: curfname: %s, cfileno=%u]\n", curfname, cfileno); @@ -768,7 +759,7 @@ if (debug) printf("[fpop (pre): curfname=%s]\n", curfname); curfname = ifile->ifoldfname; // Set current filename if (debug) printf("[fpop (post): curfname=%s]\n", curfname); if (debug) printf("[fpop: (pre) cfileno=%d ifile->ifno=%d]\n", (int)cfileno, (int)ifile->ifno); - curlineno = ifile->ifoldlineno; // Set current line# + curlineno = ifile->ifoldlineno; // Set current line# DEBUG printf("cfileno=%d ifile->ifno=%d\n", (int)cfileno, (int)ifile->ifno); cfileno = ifile->ifno; // Restore current file number if (debug) printf("[fpop: (post) cfileno=%d ifile->ifno=%d]\n", (int)cfileno, (int)ifile->ifno); @@ -827,7 +818,7 @@ char * GetNextLine(void) if (*p == '\r') { if (i >= j) - break; // Need to read more, then look for '\n' to eat + break; // Need to read more, then look for '\n' to eat else if (p[1] == '\n') i++; } @@ -928,7 +919,7 @@ retry: { if (debug) printf("TokenizeLine: Calling fpop() from SRC_IFILE...\n"); if (fpop() == 0) // Pop input level - goto retry; // Try for more lines + goto retry; // Try for more lines else { ifent->if_prev = (IFENT *) - 1; //Signal Assemble() that we have reached EOF with unbalanced if/endifs @@ -1019,7 +1010,7 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n"); ln++; // Handle EOL, comment with ';' - if (*ln == EOS || *ln == ';'|| ((*ln == '/') && (*(ln + 1) == '/'))) + if (*ln == EOS || *ln == ';'|| ((*ln == '/') && (*(ln + 1) == '/'))) break; // Handle start of symbol. Symbols are null-terminated in place. The @@ -1066,7 +1057,7 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n"); if (*ln == '.') { *ln++ = EOS; // Terminate symbol - stuffnull = 0; // And never try it again + stuffnull = 0; // And never try it again // Character following the `.' must have a DOT attribute, and // the chararacter after THAT one must not have a start-symbol @@ -1171,7 +1162,7 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n"); { switch (*ln++) { - case '!': // ! or != + case '!': // ! or != if (*ln == '=') { *tk++ = NE; @@ -1181,8 +1172,8 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n"); *tk++ = '!'; continue; - case '\'': // 'string' - case '\"': // "string" + case '\'': // 'string' + case '\"': // "string" c1 = ln[-1]; *tk++ = STRING; //#warning @@ -1325,7 +1316,7 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n"); *tk++ = '$'; continue; - case '<': // < or << or <> or <= + case '<': // < or << or <> or <= switch (*ln) { case '<': @@ -1354,7 +1345,7 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n"); *tk++ = ':'; continue; - case '=': // = or == + case '=': // = or == if (*ln == '=') { *tk++ = DEQUALS; @@ -1364,7 +1355,7 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n"); *tk++ = '='; continue; - case '>': // > or >> or >= + case '>': // > or >> or >= switch (*ln) { case '>': @@ -1379,7 +1370,7 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n"); *tk++ = '>'; continue; } - case '%': // % or binary constant + case '%': // % or binary constant if (*ln < '0' || *ln > '1') { *tk++ = '%'; @@ -1414,7 +1405,7 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n"); *tk++ = CONST; *tk++ = v; continue; - case '@': // @ or octal constant + case '@': // @ or octal constant if (*ln < '0' || *ln > '7') { *tk++ = '@'; @@ -1469,7 +1460,7 @@ if (debug) printf("TokenizeLine: Calling fpop() from SRC_IREPT...\n"); for(state=0; state>=0;) { - // Get char, convert to lowercase + // Get char, convert to lowercase j = *p++; if (j >= 'A' && j <= 'Z') @@ -1559,15 +1550,15 @@ goteol: // // .GOTO