d_nofpu, // 65 nofpu
d_opt, // 66 .opt
d_objproc, // 67 .objproc
- d_dsm, // 68 .dsm
+ (void *)d_dsm, // 68 .dsm
};
{
uint64_t address;
- if (!rgpu && !rdsp && !robjproc && !m6502 && !dsp56001)
- return error(".org permitted only in GPU/DSP/OP, 56001 and 6502 sections");
+ if (!rgpu && !rdsp && !robjproc && !m6502 && !dsp56001 && !(obj_format == RAW))
+ return error(".org permitted only in GPU/DSP/OP, 56001, 6502 and 68k (with -fr switch) sections");
// M56K can leave the expression off the org for some reason :-/
// (It's because the expression is non-standard, and so we have to look at
// N.B.: It seems that by enabling this, even though it works elsewhere, will cause symbols to royally fuck up. Will have to do some digging to figure out why.
// orgactive = 1;
}
+ else
+ {
+ // If we get here we assume it's 68k with RAW output, so this is allowed
+ if (orgactive)
+ {
+ return error("In 68k mode only one .org statement is allowed");
+ }
+
+ org68k_address = address;
+ org68k_active = 1;
+ }
ErrorIfNotAtEOL();
return 0;
=====================
Reference Manual
================
-version 2.0.4
+version 2.0.8
=============
© and notes
-fa ALCYON output object file format (implied when **-ps** is enabled).
-fb BSD COFF output object file format.
-fe ELF output object file format.
+-fr Absolute address. Source code is required to have one .org statement.
-fx Atari 800 com/exe/xex output object file format.
-i\ *path* Set include-file directory search path.
-l\ *[file[prn]]* Construct and direct assembly listing to the specified file.
-o\ *file[.o]* Direct object code output to the specified file.
+/~oall Turn all optimisations on/off
-+o\ *0-7* Enable specific optimisation
-~o\ *0-7* Disable specific optimisation
++o\ *0-9* Enable specific optimisation
+~o\ *0-9* Disable specific optimisation
`0: Absolute long adddresses to word`
r0 r1 r2 r3 r4 r5 r6 r7
r8 r9 r10 r11 r12 rl3 r14 ri5
6502:
- **TODO**
+ x y a
DSP56001:
- **TODO**
+ x x0 x1 x2 y y0 y1 y2
+ a a0 a1 a2 b b0 b1 b2 ab ba
+ mr omr la lc ssh ssl ss
+ n0 n1 n2 n3 n4 n5 n6 n7
+ m0 m1 m2 m3 m4 m5 m6 m7
+ r0 r1 r2 r3 r4 r5 r6 r7
+
`Constants`_
''''''''''''
Switch to Motorola DSP56001 mode.
+**.org** *location* [*X:*/*Y:*/*P:*/*L:*]
+ This directive sets the value of the location counter (or **pc**) to location, an
+ expression that must be defined and absolute. It is legal to use the directive in
+ the following modes: 6502, Tom, Jerry, OP, 56001 and 680x0 (only with -fr switch).
+ Especially for the 56001 mode the *location* field **must** be prefixed with the
+ intended section (*X:*, *Y:*, *P:* or *L:*).
+
**.abs** [*location*]
Start an absolute section, beginning with the specified location (or zero, if
- Motorola's assembler allows reordering of addressing modes **x:**, **x:r**,
**r:y**, **x:y**. rmac will only accept syntax as is defined on the reference
manual.
-- In **l:** section a dc value cannot be 12 hex digits like Motorola's assmebler.
+- In **L:** section a dc value cannot be 12 hex digits like Motorola's assmebler.
Instead, the value needs to be split into two parts separated by **:**.
`6502 Support`_
This directive leaves the 6502 segment and returns to the 68000's text segment.
68000 instructions may be assembled as normal.
**.org** *location*
- This directive is only legal in the 6502 section. It sets the value of the location
+ This directive sets the value of the location
counter (or **pc**) to location, an expression that must be defined, absolute, and
less than $10000.
You tried to use ``.init`` in the BSS or ABS section.
-**.org permitted only in .6502 section**
-
- You tried to use ``.org`` in a 68000 section.
-
**Cannot create:** *filename*
The assembler could not create the indicated filename.
}
+//
+// Make mark image for RAW file
+//
+uint32_t MarkABSImage(uint8_t * mp, uint32_t siz, uint32_t tsize, int reqseg)
+{
+ 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...
+
+ // Initialize relocation table point (for D_foo macros)
+ chptr = mp;
+
+ // Run through all the relocation mark chunks
+ for(MCHUNK * mch=firstmch; mch!=NULL; mch=mch->mcnext)
+ {
+ for (PTR p = mch->mcptr;;)
+ {
+ 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;
+
+ // Get the rest of the mark record
+ uint32_t loc = *p.lp++; // Mark location
+
+ // Maybe change "from" section
+ if (w & MCHFROM)
+ {
+ from = *p.wp++;
+
+ if (((reqseg == TEXT) && (from == TEXT))
+ || ((reqseg == DATA) && (from == DATA)))
+ validsegment = 1;
+ else
+ validsegment = 0;
+ }
+
+ // Maybe includes a symbol
+ if (w & MSYMBOL)
+ symbol = *p.sy++;
+
+ if (!validsegment)
+ continue;
+
+ uint32_t rflag = 0x00000040; // Absolute relocation
+
+ if (w & MPCREL)
+ rflag = 0x000000A0; // PC-relative relocation
+
+ // This flag tells the linker to WORD swap the LONG when doing the
+ // relocation.
+ if (w & MMOVEI)
+ rflag |= 0x00000001;
+
+ // This tells the linker to do a WORD relocation (otherwise it
+ // defaults to doing a LONG, throwing things off for WORD sized
+ // fixups)
+ if (!(w & (MLONG | MQUAD)))
+ rflag |= 0x00000002;
+
+ // Tell the linker that the fixup is an OL QUAD data address
+ if (w & MQUAD)
+ rflag |= 0x00000004;
+
+ if (symbol != NULL)
+ {
+ return error("Unresolved symbol when outputting raw image");
+ }
+ else
+ {
+ w &= TDB; // Set reloc flags to segment
+
+ switch (w)
+ {
+ case TEXT: rflag |= 0x00000400; break;
+ case DATA: rflag |= 0x00000600; break;
+ case BSS: rflag |= 0x00000800; break;
+ }
+
+ // Fix relocation by adding in start of TEXT segment, since it's
+ // currently relative to the start of the DATA (or BSS) segment
+ uint8_t * dp = objImage + loc;
+ uint32_t olBitsSave = 0;
+
+ // Bump the start of the section if it's DATA (& not TEXT)
+ if (from == DATA)
+ dp += tsize;
+
+ uint32_t diff = (rflag & 0x02 ? GETBE16(dp, 0) : GETBE32(dp, 0));
+
+ if (w & (DATA | BSS))
+ {
+ // Special handling for OP (data addr) relocation...
+ if (rflag & 0x04)
+ {
+ olBitsSave = diff & 0x7FF;
+ diff = (diff & 0xFFFFF800) >> 8;
+ }
+
+ if (rflag & 0x01)
+ diff = WORDSWAP32(diff);
+
+ diff += sect[TEXT].sloc;
+
+ if (w == BSS)
+ diff += sect[DATA].sloc;
+ }
+ if ((rflag & 0x02) == 0)
+ {
+ diff += org68k_address;
+ }
+
+ if (rflag & 0x01)
+ diff = WORDSWAP32(diff);
+
+ // Make sure to deposit the correct size payload
+ // Check comments in MarkBSDImage for more candid moments
+ if (rflag & 0x02) // WORD relocation
+ {
+ SETBE16(dp, 0, diff);
+ }
+ else if (rflag & 0x04) // OP data address relocation
+ {
+ // We do it this way because we might have an offset
+ // that is not a multiple of 8 and thus we need this in
+ // place to prevent a bad address at link time. :-P As
+ // a consequence of this, the highest address we can
+ // have here is $1FFFF8.
+ uint32_t diffsave = diff;
+ diff = ((diff & 0x001FFFFF) << 11) | olBitsSave;
+ SETBE32(dp, 0, diff);
+ // But we need those 3 bits, otherwise we can get in
+ // trouble with things like OL data that is in the cart
+ // space, and BOOM! So the 2nd phrase of the fixup (it
+ // will *always* have a 2nd phrase) has a few spare
+ // bits, we chuck them in there.
+ uint32_t p2 = GETBE32(dp, 8);
+ p2 &= 0x1FFFFFFF;
+ p2 |= (diffsave & 0x00E00000) << 8;
+ SETBE32(dp, 8, p2);
+ }
+ else // LONG relocation
+ {
+ SETBE32(dp, 0, diff);
+ }
+ }
+ }
+ }
+
+ return OK;
+}
+
+
//
// Make relocation record for ELF .o file.
// Returns the size of the relocation record.
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);
+uint32_t MarkABSImage(uint8_t * mp, uint32_t siz, uint32_t tsize, int reqseg);
#endif // __MARK_H__
// Write requested object file...
if ((obj_format == BSD) || ((obj_format == ALCYON) && (prg_flag == 0)))
- {
+ {
+ ch_size = 0;
+
// Force BSD format (if it was ALCYON format)
obj_format = BSD;
}
else if (obj_format == ALCYON)
{
+ ch_size = 0;
+
if (verb_flag)
{
if (prg_flag)
// Assign index numbers to the symbols, get # of symbols (we assume
// that all symbols can potentially be extended, hence the x28)
+ // (To clarify: 28 bytes is the size of an extended symbol)
uint32_t symbolMaxSize = sy_assign(NULL, NULL) * 28;
// Alloc memory for header + text + data, symbol and relocation
else
WriteP56();
- // Write all the things |o/
+ // Write all the things \o/
unused = write(fd, buf, chptr - buf);
if (buf)
free(buf);
}
+ else if (obj_format == RAW)
+ {
+ if (!org68k_active)
+ {
+ return error("cannot output absolute binary without a starting address (.org or command line)");
+ }
+
+ // Alloc memory for text + data construction.
+ tds = sect[TEXT].sloc + sect[DATA].sloc;
+ buf = malloc(tds);
+ chptr = buf;
+
+ // Construct text and data segments; fixup relocatable longs;
+ // finally write the text + data
+
+ p = buf;
+ objImage = buf; // Set global object image pointer
+
+ for (i = TEXT; i <= DATA; i++)
+ {
+ for (cp = sect[i].sfcode; cp != NULL; cp = cp->chnext)
+ {
+ memcpy(p, cp->chptr, cp->ch_size);
+ p += cp->ch_size;
+ }
+ }
+
+ if (MarkABSImage(buf, tds, sect[TEXT].sloc, TEXT) != OK) // Do TEXT relocation table
+ {
+ return ERROR;
+ }
+ if (MarkABSImage(buf, tds, sect[TEXT].sloc, DATA) != OK) // Do DATA relocation table
+ {
+ return ERROR;
+ }
+ // Write out the header + text & data + symbol table (if any)
+ unused = write(fd, buf, tds);
+
+ }
return 0;
}
int optim_flags[OPT_COUNT]; // Specific optimisations on/off matrix
int activecpu = CPU_68000; // Active 68k CPU (68000 by default)
int activefpu = FPU_NONE; // Active FPU (none by default)
-
+int org68k_active = 0; // .org switch for 68k (only with RAW output format)
+uint32_t org68k_address; // .org for 68k
//
// Convert a string to uppercase
" p: P56 (use this for DSP56001 only)\n"
" l: LOD (use this for DSP56001 only)\n"
" x: com/exe/xex (Atari 800)\n"
+ " r: absolute address"
" -i[path] Directory to search for include files\n"
" -l[filename] Create an output listing file\n"
" -l*[filename] Create an output listing file without pagination\n"
" ~o[value] Turn a specific optimisation off\n"
" +oall Turn all optimisations on\n"
" ~oall Turn all optimisations off\n"
- " -p Create an ST .prg (without symbols)\n"
- " -ps Create an ST .prg (with symbols)\n"
- " -px Create an ST .prg (with exsymbols)\n"
- " Forces -fa\n"
+ " -p Create an ST .prg (without symbols). Forces -fa\n"
+ " -ps Create an ST .prg (with symbols). Forces -fa\n"
+ " -px Create an ST .prg (with exsymbols). Forces -fa\n"
" -r[size] Pad segments to boundary size specified\n"
" w: word (2 bytes, default alignment)\n"
" l: long (4 bytes)\n"
case 'X':
obj_format = XEX;
break;
+ case 'r': // -fr = Absolute address
+ case 'R':
+ obj_format = RAW;
+ break;
default:
printf("-f: unknown object format specified\n");
errcnt++;
enum
{
ALCYON, // Alcyon/DRI C object format
-MWC, // Mark Williams object format
BSD, // BSD object format
ELF, // ELF object format
LOD, // DSP 56001 object format
P56, // DSP 56001 object format
XEX, // COM/EXE/XEX/whatever a8 object format
+RAW, // Output at absolute address
};
// Assembler token
extern int optim_flags[OPT_COUNT];
extern int activecpu;
extern int activefpu;
+extern uint32_t org68k_address;
+extern int org68k_active;
// Exported functions
void strtoupper(char * s);
// 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).
if ((dw & FU_PCREL) || (dw & FU_PCRELX))
else if (tdb)
{
// Allow cross-section PCREL fixups in Alcyon mode
- if (prg_flag)
+ if (prg_flag || (obj_format == RAW))
{
switch (tdb)
{
if (sbra_flag && (dw & FU_LBRA) && (eval + 0x80 < 0x100))
warn("unoptimized short branch");
}
- else if (obj_format == MWC)
- {
- eval -= loc;
-
- // In this instruction the PC is located a DWORD away
- if (dw & FU_PCRELX)
- eval += 2;
- }
// Be sure to clear any TDB flags, since we handled it just now
tdb = 0;