//
// 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
//
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
- <OutDir>$(SolutionDir)\..\</OutDir>
+ <OutDir>$(SolutionDir)\..</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
//
// 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
//
#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;
if (*tok >= KW_D0 && *tok <= KW_A7)
cnt = *tok++ & 15;
- else
+ else
return error("register list syntax");
if (cnt < r)
cnt -= r;
}
- else
+ else
cnt = 0;
while (cnt-- >= 0)
//
// 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
//
#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)
//
// 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
//
switch ((int)*tp++)
{
case SYMBOL:
-// printf("`%s' ", ((SYM *)*tp)->sname);
- printf("`%s' ", symbolPtr[*tp]->sname);
+ printf("'%s' ", symbolPtr[*tp]->sname);
tp++;
break;
case CONST:
}
}
-// printf(";\n");
return tp + 1;
}
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);
}
mch, (mch->mcptr.lw), mch->mcalloc, (mch->mcused));
p = mch->mcptr;
-
+
for(;;)
{
w = *p.wp++;
// 0 - bytes
// 1 - words
// 2 - longwords
-//
+//
// if `base' is not -1, then print it at the start of each line, incremented
// accordingly.
//
{
printf(" ");
- while(j < i)
+ while (j < i)
visprt(start[j++]);
putchar('\n');
{
case 0:
printf("%02X ", start[i] & 0xff);
- ++i;
+ i++;
break;
case 1:
printf("%02X%02X ", start[i] & 0xff, start[i+1] & 0xff);
{
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');
case STRING: // STRING <address>
printf("STRING='%s'", string[*tk++]);
break;
- case SYMBOL: // SYMBOL <address>
+ case SYMBOL: // SYMBOL <address>
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:
//
int dump_everything(void)
{
- int i;
-
- for(i=1; i<NSECTS; i++)
+ for(int i=1; i<NSECTS; i++)
{
if (sect[i].scattr & SUSED)
{
printf("\nMarks:\n");
mudump(); // Dump marks
-// printf("Total memory allocated=$%X\n", amemtot);
return 0;
}
+
//
// RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
// DEBUG.H - Debugging Messages
-// 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
//
//
// RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
// DIRECT.C - 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
//
d_title, // 44 title
d_subttl, // 45 subttl
eject, // 46 eject
- d_error, // 47 error
- d_warn, // 48 warn
+ d_error, // 47 error
+ d_warn, // 48 warn
d_noclear, // 49 .noclear
d_equrundef, // 50 .equrundef/.regundef
d_ccundef, // 51 .ccundef
{
VALUE address;
- if (!rgpu && !rdsp)
+ if (!rgpu && !rdsp)
return error(".org permitted only in gpu/dsp section");
orgaddr = 0;
sprintf(prntstr, "%s", string[tok[1]]);
printf("%s", prntstr);
- if (list_fd)
+ if (list_fd)
unused = write(list_fd, prntstr, (LONG)strlen(prntstr));
tok += 2;
{
switch(outtype)
{
- case 0: strcpy(format, "%X"); break;
- case 1: strcpy(format, "%d" ); break;
- case 2: strcpy(format, "%u" ); break;
+ case 0: strcpy(format, "%X"); break;
+ case 1: strcpy(format, "%d" ); break;
+ case 2: strcpy(format, "%u" ); break;
}
if (wordlong)
printf("%s", prntstr);
- if (list_fd)
+ if (list_fd)
unused = write(list_fd, prntstr, (LONG)strlen(prntstr));
formatting = 0;
}
-//
+//
// Include binary file
//
int d_incbin(void)
}
-//
+//
// Set RISC register banks
//
int d_regbank0(void)
int d_even(void)
{
unsigned skip = (rgpu || rdsp ? orgaddr : sloc) & 0x01;
-
+
if (skip)
{
if ((scattr & SBSS) == 0)
}
-//
+//
// Return absolute (not TDB) and defined expression or return an error
//
int abs_expr(VALUE * a_eval)
char buf[128];
char buf1[128];
- if (*tok == STRING) // Leave strings ALONE
+ if (*tok == STRING) // Leave strings ALONE
fn = string[*++tok];
else if (*tok == SYMBOL) // Try to append ".s" to symbols
{
fext(buf, ".s", 0);
fn = &buf[0];
}
- else // Punt if no STRING or SYMBOL
+ else // Punt if no STRING or SYMBOL
return error("missing filename");
// Make sure the user didn't try anything like:
// Attempt to open the include file in the current directory, then (if that
// failed) try list of include files passed in the enviroment string or by
- // the "-d" option.
+ // the "-i" option.
if ((j = open(fn, 0)) < 0)
{
for(i=0; nthpath("RMACPATH", i, buf1)!=0; i++)
{
j = strlen(buf1);
- if (j > 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);
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;
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)
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
{
//
-// 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");
|| (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++;
}
// dc.x <expression>
- 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);
}
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);
}
}
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);
}
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;
//
// 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
case DOTB: siz = SIZB; break;
case DOTW: siz = SIZB; break;
case DOTL: siz = SIZL; break;
- default:
+ default:
siz = def_siz;
- --tok;
+ tok--;
break;
}
case EOL:
return 0;
case ',':
- ++tok;
+ tok++;
continue;
default:
return error(comma_error);
else
{
if (tdb)
- rmark(cursect, sloc, tdb, MWORD, NULL);
+ MarkRelocatable(cursect, sloc, tdb, MWORD, NULL);
if (eval + 0x10000 >= 0x20000)
return error(range_error);
else
{
if (tdb)
- rmark(cursect, sloc, tdb, MLONG, NULL);
+ MarkRelocatable(cursect, sloc, tdb, MLONG, NULL);
D_long(eval);
}
{
rgpu = rdsp = 0;
// Switching from gpu/dsp sections should reset any ORG'd Address
- orgactive = 0;
+ orgactive = 0;
orgwarning = 0;
SaveSection();
SwitchSection(TEXT);
//
// .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)
//
// .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.
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;
if (ParseOptimization(tmpstr) != OK)
{
char temperr[256];
- sprintf(temperr, "unknown optimisation flag '%s'", tmpstr);
+ sprintf(temperr, "unknown optimization flag '%s'", tmpstr);
return error(temperr);
}
}
//
// 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
//
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 *);
//
// 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
//
#define aNexpr a0expr
#define aNixreg a0ixreg
#define aNixsiz a0ixsiz
+#define AnESYM a0esym
#include "eagen0.c"
#define eaNgen ea1gen
#define aNexpr a1expr
#define aNixreg a1ixreg
#define aNixsiz a1ixsiz
+#define AnESYM a1esym
#include "eagen0.c"
// 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)
{
// 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
}
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
}
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);
}
case PCDISP:
if (w)
{
- // Just deposit it
+ // Just deposit it
if ((aNexattr & TDB) == cursect)
v -= (VALUE)sloc;
else if ((aNexattr & TDB) != ABS)
}
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);
}
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);
}
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);
}
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);
}
}
else
{
- AddFixup(FU_BYTE|FU_SEXT, sloc+1, aNexpr);
+ AddFixup(FU_BYTE | FU_SEXT, sloc + 1, aNexpr);
D_word(0);
}
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);
}
if (w)
{
if (tdb)
- rmark(cursect, sloc, tdb, MLONG, NULL);
+ MarkRelocatable(cursect, sloc, tdb, MLONG, NULL);
D_long(v);
}
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);
}
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);
}
case PCMPRE:
return error("unsupported 68020 addressing mode");
default:
- // Bad addressing mode in ea gen
+ // Bad addressing mode in ea gen
interror(3);
}
#undef aNexpr
#undef aNixreg
#undef aNixsiz
+#undef AnESYM
//
// 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
//
//
// 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
//
//
// 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
//
#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
// 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";
// 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[]
//
{
if (*p == 0)
i++;
- else
+ else
tokenClass[(int)(*p)] = (char)i;
}
if (expr1() != OK)
return ERROR;
-
+
while (tokenClass[*tok] >= MULT)
{
t = *tok++;
break;
}
}
- else
+ else
return expr2();
return OK;
// 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)
// 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)
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);
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))
{
}
else
{
- *++sval = 0; // 0 for undefined symbols
+ *++sval = 0; // 0 for undefined symbols
}
*++sattr = (WORD)(sy->sattr & ~GLOBAL); // Push attribs
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);
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);
// 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);
break;
case GE:
//printf("evexpr(): GE\n");
- --sattr;
- --sval;
+ sattr--;
+ sval--;
if ((*sattr & TDB) != (sattr[1] & TDB))
error(seg_error);
break;
case '>':
//printf("evexpr(): >\n");
- --sattr;
- --sval;
+ sattr--;
+ sval--;
if ((*sattr & TDB) != (sattr[1] & TDB))
error(seg_error);
break;
case '<':
//printf("evexpr(): <\n");
- --sattr;
- --sval;
+ sattr--;
+ sval--;
if ((*sattr & TDB) != (sattr[1] & TDB))
error(seg_error);
break;
case NE:
//printf("evexpr(): NE\n");
- --sattr;
- --sval;
+ sattr--;
+ sval--;
if ((*sattr & TDB) != (sattr[1] & TDB))
error(seg_error);
break;
case '=':
//printf("evexpr(): =\n");
- --sattr;
- --sval;
+ sattr--;
+ sval--;
if ((*sattr & TDB) != (sattr[1] & TDB))
error(seg_error);
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");
//printf("%i\n", *sval);
break;
case '%':
- --sval;
- --sattr; // Pop attrib
+ sval--;
+ sattr--; // Pop attrib
if (sval[1] == 0)
return error("mod (%) by zero");
*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:
//
// 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
//
//
// 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
//
fprintf(stderr, "Panic: %s\n", s);
exit(1);
}
+
#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
}
-//
+//
// Return GEMDOS format time
//
VALUE dos_time(void)
}
-//
+//
// Create listing file with the appropriate name
//
void list_setup(void)
}
list_fname = NULL;
-
+
if ((list_fd = open(fnbuf, _OPEN_FLAGS, _PERM_MODE)) < 0)
cantcreat(fnbuf);
}
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);
tok += 2;
- // Always eject on pages 2+
+ // Always eject on pages 2+
if (ejectok && (subflag || pageno > 1))
eject();
{
if (*tok != STRING)
return error("missing string");
-
+
// strcpy(title, (char*)tok[1]);
strcpy(title, string[tok[1]]);
tok += 2;
//
// 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
//
// Prototypes
void InitListing(void);
+int eject(void);
void ship_ln(const char *);
void taglist(char);
void println(const char *);
//
// 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
//
#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);
// 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
};
// 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)
};
//
// 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);
}
{
if (inst & 1)
{
- // Install size bits
+ // Install size bits
inst--;
inst |= siz_6[siz];
}
{
inst |= am0 | a0reg | lwsiz_8[siz] | reg_9[a1reg];
D_word(inst);
- ea0gen(siz); // Generate EA
+ ea0gen(siz); // Generate EA
return 0;
}
//
// 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;
{
// 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
if (am0 == IMMED)
{
D_word(inst);
- ea0gen(SIZB); // Immediate bit number
+ ea0gen(SIZB); // Immediate bit number
}
else
{
D_word(inst);
}
- // ea to bit-munch
+ // ea to bit-munch
ea1gen(SIZB);
return 0;
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;
}
//
// Handle MOVE <C_ALL> <C_ALTDATA>
// MOVE <C_ALL> <M_AREG>
-//
+//
// Optimize MOVE.L #<smalldata>,D0 to a MOVEQ
//
int m_move(WORD inst, WORD size)
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);
{
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);
if (am1 == AIND)
D_word(0)
- else
+ else
ea1gen(siz);
}
else
if (am0 == AIND)
D_word(0)
- else
+ else
ea0gen(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)
}
else
{
- // Fits in .W
+ // Fits in .W
if (v + 0x8000 > 0x10000)
return error(range_error);
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);
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;
inst |= a0exval;
D_word(inst);
}
- else
+ else
return error(undef_error);
return 0;
if (*tok == '#')
{
- // Handle #<expr>, ea
+ // Handle #<expr>, ea
tok++;
if (abs_expr(&eval) != OK)
if (*tok >= KW_D0 && *tok <= KW_A7)
{
- // <rlist>, ea
+ // <rlist>, ea
if (reglist(&rmask) < 0)
return 0;
}
else
{
- // ea, <rlist>
+ // ea, <rlist>
if (amode(0) < 0)
return 0;
if (*tok == '#')
{
- // ea, #<expr>
+ // ea, #<expr>
tok++;
if (abs_expr(&eval) != OK)
//
// 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
//
#include "rmac.h"
#include "amode.h"
-// Globals, Externals etc
+// Exported variables
extern char seg_error[];
extern char undef_error[];
extern char rel_error[];
extern MNTAB machtab[];
#endif // __MACH_H__
+
//
// 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
//
#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
//
*curmln = p.cp;
curmln = (char **)p.cp;
- return 1; // Keep looking
+ return 1; // Keep looking
#else
if (curmac->lineList == NULL)
{
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...
*p = 0;
strcpy((char *)(p + 1), ln);
-
+
if (nextrpt == NULL)
{
firstrpt = p; // First line of rept statement
// 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.
int k;
if (lnfunc != NULL)
- lnsave++; // Tell tokenizer to keep lines
+ lnsave++; // Tell tokenizer to keep lines
for(;;)
{
if (p != NULL)
{
- if (*p == '.') // ignore leading '.'s
+ if (*p == '.') // ignore leading '.'s
p++;
k = kwmatch(p, dirlist);
// 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;
TOKEN * dest;
int stringNum = 0;
int argumentNum = 0;
-// int i;
for(dry_run=1; ; dry_run--)
{
nargs++;
else
{
-#if 0
+#if 0
*argptr++ = p;
#else
argPtrs[argp++] = p;
// argp += nargs;
#endif
}
- else
+ else
break;
}
//
// 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
//
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
#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
firstmch = curmch = NULL;
mcalloc = mcused = 0;
curfrom = 0;
+ sect[TEXT].relocs = sect[DATA].relocs = sect[BSS].relocs = 0;
}
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 <to+flags> section mark is relative to, and flags in upper byte
+// .L <loc> 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)
{
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)
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;
//
// 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;
}
-/*
- * 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;
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;
}
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
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
}
}
- /*
- * 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<siz;)
{
{
if (firstp)
{
- *dp++ = (char)(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;
}
//
// 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;
}
//
// 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
//
#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 <to+flags> section mark is relative to, and flags in upper byte
+// .L <loc> 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__
//
// 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
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
}
-/*
- * 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;
}
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
// 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)
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
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)
{
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)
{
}
// 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)
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; j<i; j++)
+ printf("\"%s\"\n", shstrtab + shstTab[j]);
+#endif
+
+ // Construct ELF header
+ // If you want to make any sense out of this you'd better take a look
+ // at Executable and Linkable Format on Wikipedia.
+ chptr = buf;
+ D_long(0x7F454C46); // 00 - "<7F>ELF" 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;
//
// 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
//
#ifndef __OBJECT_H__
#define __OBJECT_H__
-// Size of BSD header
-#define BSDHDRSIZE 0x20
+#include <rmac.h>
-// 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);
//
// 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
//
goto AMn_IX0; // Handle ",Xn[.siz][*scale])"
}
else if (*tok == KW_PC)
- { // (PC,Xn[.siz][*scale])
+ { // (PC,Xn[.siz][*scale])
tok++;
AMn = PCINDEXED;
AnIXREG = *tok++ & 15;
switch ((int)*tok)
- { // Index reg size: <empty> | .W | .L
+ { // Index reg size: <empty> | .W | .L
case DOTW:
tok++;
default:
}
if (*tok == '*')
- { // scale: *1, *2, *4, *8
+ { // scale: *1, *2, *4, *8
tok++;
if (*tok++ != CONST || *tok > 8)
}
}
- 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;
}
else if (*tok == ')')
{
- AMn = PCDISP; // expr(PC)
+ AMn = PCDISP; // expr(PC)
tok++;
goto AnOK;
}
CHK_FOR_DISPn:
if (*tok == DOTW)
{
- // expr.W
+ // expr.W
tok++;
AMn = ABSW;
//
// 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
//
#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
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";
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
// 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++;
{
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))
// 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);
}
-//
+//
// .if, Start conditional assembly
//
int d_if(void)
}
-//
+//
// .else, Do alternate case for .if
//
int d_else(void)
//
// 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
//
{
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();
//
// 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
//
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
" -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"
}
-//
+//
// Process command line arguments and do an assembly
//
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++;
// 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
//
// 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
//
#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)
#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...)
// 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 <sys/fcntl.h>
#include <unistd.h>
- // 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
#define DO_PRAGMA(x) _Pragma (#x)
#define WARNING(desc) DO_PRAGMA(message (#desc))
#else
- // Release platform - not specified
+ // Release platform - not specified
#include <sys/fcntl.h>
#define PLATFORM "Unknown"
#define _OPEN_FLAGS O_TRUNC|O_CREAT|O_RDWR
#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
//
#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
#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
};
//#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)
// 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
};
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];
//
// 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
//
// 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
};
// Offset to REAL fixup location
-static char fusizoffs[] = {
+static uint8_t fusizoffs[] = {
0, // FU_QUICK
0, // FU_BYTE
0, // FU_WORD
//
// Make a new (clean) section
//
-void MakeSection(int sno, WORD attr)
+void MakeSection(int sno, uint16_t attr)
{
SECT * p = §[sno];
p->scattr = attr;
else
challoc = ch_size = 0;
- // Copy fixup chunk vars
+ // Copy fixup chunk vars
if ((cp = sfix) != NULL)
{
fchalloc = cp->challoc;
// 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();
// 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)
}
-//
+//
// 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
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)
{
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
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;
// 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
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
{
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
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;
}
*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);
}
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;
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)
{
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))
{
if (cch == NULL)
{
- // Fixup (loc) out of range
+ // Fixup (loc) out of range
interror(7);
// NOTREACHED
}
eattr = 0;
// Compute expression/symbol value and attribs
+
// Complex expression
if (w & FU_EXPR)
{
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).
eval -= 2;
if (eval + 0x80 >= 0x100)
- goto range;
+ goto rangeErr;
if (eval == 0)
{
continue;
}
- *++locp = (char)eval;
+ *++locp = (uint8_t)eval;
break;
// Fixup one-byte value at locp + 1.
case FU_WBYTE:
}
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++;
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;
}
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;
}
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;
}
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;
}
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;
}
}
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
{
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))
{
}
if (eval < 1 || eval > 8)
- goto range;
+ goto rangeErr;
*locp |= (eval & 7) << 1;
break;
eval -= (loc + 1);
if (eval + 0x80 >= 0x100)
- goto range;
+ goto rangeErr;
- *locp = (char)eval;
+ *locp = (uint8_t)eval;
break;
default:
// NOTREACHED
}
continue;
-range:
+rangeErr:
error("expression out of range");
}
//
int ResolveAllFixups(void)
{
- //unsigned i;
- //char buf[EBUFSIZ];
-
// Make undefined symbols GLOBL
if (glob_flag)
ForceUndefinedSymbolsGlobal();
return 0;
}
-
//
// 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
//
// 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.
// 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
#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 <to+flags> section mark is relative to, and flags in upper byte
-// .L <loc> 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__
+
//
#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
};
//
void InitSymbolTable(void)
{
- int i; // Iterator
-
- for(i=0; i<NBUCKETS; i++) // Initialise symbol hash table
+ for(int i=0; i<NBUCKETS; i++) // Initialise symbol hash table
symbolTable[i] = NULL;
curenv = 1; // Init local symbol enviroment
//
-// Hash the print name and enviroment number
+// Hash the ASCII name and enviroment number
//
-int HashSymbol(char * name, int envno)
+int HashSymbol(uint8_t * name, int envno)
{
- int sum, k = 0; // Hash calculation
+ int sum = envno, k = 0;
- for(sum=envno; *name; name++)
+ for(; *name; name++)
{
if (k++ == 1)
sum += *name << 2;
//
-// Make a new symbol of type `type' in enviroment `envno'
+// Make a new symbol of type 'type' in enviroment 'envno'
//
-SYM * NewSymbol(char * name, int type, int envno)
+SYM * NewSymbol(uint8_t * name, int type, int envno)
{
// Allocate the symbol
SYM * symbol = malloc(sizeof(SYM));
// Fill-in the symbol
symbol->sname = 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
// 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
//
-// 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)];
if (sdecl == NULL)
sdecl = symbol; // First on decl-list
- else
+ else
sdecltail->sdecl = symbol; // Add to end of list
// Fix up list's tail
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
}
-//
-// 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.
&& (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; i<NBUCKETS; ++i)
+ for(i=0; i<NBUCKETS; i++)
{
for(p=symbolTable[i]; p!=NULL; p=k)
{
while (p != NULL)
{
- for(i=0; i<4; ++i)
+ for(i=0; i<4; i++)
{
colptr[i] = p;
- for(j=0; j<colhei; ++j)
+ for(j=0; j<colhei; j++)
{
if (p == NULL)
break;
}
}
- for(i=0; i<colhei; ++i)
+ for(i=0; i<colhei; i++)
{
*ln = EOS;
if (colptr[0] == NULL)
break;
- for(j=0; j<4; ++j)
+ for(j=0; j<4; j++)
{
if ((q = colptr[j]) == NULL)
break;
if (w & COMMON)
c = 'c';
- else if ((w & (DEFINED|GLOBAL)) == GLOBAL)
+ else if ((w & (DEFINED | GLOBAL)) == GLOBAL)
c = 'x';
else if (w & GLOBAL)
c = 'g';
else
{
sprintf(ln2, "%08X", q->svalue);
- uc_string(ln2);
+ ToUppercase(ln2);
}
sprintf(ln1, " %16s %s %c%c%c", q->sname, ln2, (ww & EQUATEDREG) ? 'e' : SPACE, c1, c);
//
// 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
//
struct LineList
{
struct LineList * next;
- char * line;
+ uint8_t * line;
};
// Symbols
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
// 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__
//
// 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
//
#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
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
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
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
};
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"
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;
}
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
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
// 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++;
*dst++ = *s++;
continue;
- case '?': // \? <macro> set `questmark' flag
+ case '?': // \? <macro> 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
}
goto copy_d;
- case '~': // ==> unique label string Mnnnn...
+ case '~': // ==> unique label string Mnnnn...
sprintf(numbuf, "M%u", curuniq);
copystr:
d = numbuf;
//
char * GetNextMacroLine(void)
{
-// unsigned source_addr;
-
IMACRO * imacro = cur_inobj->inobj.imacro;
// LONG * strp = imacro->im_nextln;
struct LineList * strp = imacro->im_nextln;
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);
//
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
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);
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);
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++;
}
{
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
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
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
{
switch (*ln++)
{
- case '!': // ! or !=
+ case '!': // ! or !=
if (*ln == '=')
{
*tk++ = NE;
*tk++ = '!';
continue;
- case '\'': // 'string'
- case '\"': // "string"
+ case '\'': // 'string'
+ case '\"': // "string"
c1 = ln[-1];
*tk++ = STRING;
//#warning
*tk++ = '$';
continue;
- case '<': // < or << or <> or <=
+ case '<': // < or << or <> or <=
switch (*ln)
{
case '<':
*tk++ = ':';
continue;
- case '=': // = or ==
+ case '=': // = or ==
if (*ln == '=')
{
*tk++ = DEQUALS;
*tk++ = '=';
continue;
- case '>': // > or >> or >=
+ case '>': // > or >> or >=
switch (*ln)
{
case '>':
*tk++ = '>';
continue;
}
- case '%': // % or binary constant
+ case '%': // % or binary constant
if (*ln < '0' || *ln > '1')
{
*tk++ = '%';
*tk++ = CONST;
*tk++ = v;
continue;
- case '@': // @ or octal constant
+ case '@': // @ or octal constant
if (*ln < '0' || *ln > '7')
{
*tk++ = '@';
for(state=0; state>=0;)
{
- // Get char, convert to lowercase
+ // Get char, convert to lowercase
j = *p++;
if (j >= 'A' && j <= 'Z')
//
// .GOTO <label> goto directive
-//
+//
// The label is searched for starting from the first line of the current,
// enclosing macro definition. If no enclosing macro exists, an error is
// generated.
-//
+//
// A label is of the form:
-//
+//
// :<name><whitespace>
-//
+//
// The colon must appear in column 1. The label is stripped prior to macro
// expansion, and is NOT subject to macro expansion. The whitespace may also
// be EOL.
struct LineList * defln = imacro->im_macro->lineList;
// Find the label, starting with the first line.
-// for(; defln!=NULL; defln=(LONG *)*defln)
for(; defln!=NULL; defln=defln->next)
{
// if (*(char *)(defln + 1) == ':')
//
// RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
// TOKEN.H - Token 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
//
#define SET 149 // Set
#define REG 'R' // Reg
#define DCOLON 'h' // ::
-#define GE 'i' // >=
-#define LE 'j' // <=
-#define NE 'k' // <> or !=
-#define SHR 'l' // >>
-#define SHL 'm' // <<
-#define UNMINUS 'n' // Unary '-'
-#define DOTB 'B' // .b or .B or .s or .S
-#define DOTW 'W' // .w or .W
-#define DOTL 'L' // .l or .L
-#define DOTI 'I' // .l or .L
-#define ENDEXPR 'E' // End of expression
+#define GE 'i' // >=
+#define LE 'j' // <=
+#define NE 'k' // <> or !=
+#define SHR 'l' // >>
+#define SHL 'm' // <<
+#define UNMINUS 'n' // Unary '-'
+#define DOTB 'B' // .b or .B or .s or .S
+#define DOTW 'W' // .w or .W
+#define DOTL 'L' // .l or .L
+#define DOTI 'I' // .l or .L
+#define ENDEXPR 'E' // End of expression
// ^^ operators
#define CR_DEFINED 'p' // ^^defined - is symbol defined?
char * ifoldfname; // Old file's name
int ifoldlineno; // Old line number
int ifind; // Position in file buffer
- int ifcnt; // #chars left in file buffer
+ int ifcnt; // #chars left in file buffer
int ifhandle; // File's descriptor
WORD ifno; // File number
char ifbuf[LNBUFSIZ]; // Line buffer
VALUE ir_count; // Repeat count (decrements)
};
-// Globals, externals etc
+// Exported variables
extern int lnsave;
extern int curlineno;
extern char * curfname;
extern int mjump_align;
extern char * string[];
-// Prototypes
+// Exported functions
int include(int, char *);
void InitTokenizer(void);
void SetFilenameForErrorReporting(void);
//
// RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
// VERSION.H - Version Information
-// Copyright (C) 199x Landon Dyer, 2011 - 2017 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
//
+// Contributors: James Hammons, George Nakos, Graeme Hinchliffe, SCPCD
+//
#ifndef __VERSION_H__
#define __VERSION_H__
// Release Information
#define MAJOR 1 // Major version number
-#define MINOR 4 // Minor version number
-#define PATCH 21 // Patch release number
+#define MINOR 5 // Minor version number
+#define PATCH 0 // Patch release number
#endif // __VERSION_H__
+