int d_comm(void);
int d_dc(WORD);
int d_ds(WORD);
+int d_dsm(WORD);
int d_dcb(WORD);
int d_globl(void);
int d_gpu(void);
d_nofpu, // 65 nofpu
d_opt, // 66 .opt
d_objproc, // 67 .objproc
+ d_dsm, // 68 .dsm
};
}
+//
+// dsm[.siz] expression
+// Define modulo storage
+// Quoting the Motorola assembler manual:
+// "The DSM directive reserves a block of memory the length of which in words is equal to
+// the value of <expression>.If the runtime location counter is not zero, this directive first
+// advances the runtime location counter to a base address that is a multiple of 2k, where
+// 2k >= <expression>."
+// The kicker of course is written a few sentences after:
+// "<label>, if present, will be assigned the value of the runtime location counter after a valid
+// base address has been established."
+//
+int d_dsm(WORD siz)
+{
+ TOKEN * tok_current = tok; // Keep track of where tok was when we entered this procedure
+ uint64_t eval;
+
+ if (abs_expr(&eval) != OK)
+ return 0;
+
+ // Round up to the next highest power of 2
+ // Nicked from https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
+ eval--;
+ eval |= eval >> 1;
+ eval |= eval >> 2;
+ eval |= eval >> 4;
+ eval |= eval >> 8;
+ eval |= eval >> 16;
+
+ int units_to_skip;
+ units_to_skip = eval + 1 - sloc;
+ sloc += units_to_skip; // Bump up sloc - TODO: check if this goes over the RAM limits?
+
+ // If a label has been defined in the same line as dsm, its value also needs to be adjusted
+ if (label_defined)
+ {
+ SYM * label = lookup(label_defined, LABEL, 0);
+ label->svalue += units_to_skip;
+ }
+
+ tok = tok_current; // Rewind tok back to where it was
+ return d_ds(siz); // And let d_ds take over from here
+}
+
+
//
// dc.b, dc.w / dc, dc.l, dc.i, dc.q, dc.d, dc.s, dc.x
//
#include "rmac.h"
#include "token.h"
+// Imported variables
+
+extern char * label_defined;
+
// Exported variables
extern TOKEN exprbuf[];
extern SYM * symbolPtr[];
`6: Convert null short branches to NOP`
`7: Convert clr.l Dn to moveq #0,Dn`
+
+ `8: Convert adda.w/l #x,Dy to addq.w/l #x,Dy`
+
+ `9: Convert adda.w/l #x,Dy to lea x(Dy),Dy`
-p Produce an executable (**.prg**) output file.
-ps Produce an executable (**.prg**) output file with symbols.
-px Produce an executable (**.prg**) output file with extended symbols.
`Differences from Motorola's assembler`_
''''''''''''''''''''''''''''''''''''''''
-- and #xxx,reg alias with andi
-- move/movec/movep/movem alias
-- local labels
-- macros
-- macros + local labels
-- x: x:r r:y x:y rigidness
-- no dsm support - it sucks
-- in l: dc cannot be 12 digits, split them in two and in the same line, separated by :
-- Rigid syntax - no reordering allowed
+- Motorola's assembler aliases **and #xxx,reg** with **andi #xxx,reg** and can
+ distinguish between the two. rmac needs the user to be explicit and will
+ generate an error if the programmer tries to use syntax from one instruction
+ to the other.
+- Similarly Motorola's assembler can alias **move** with **movec**, **movep**
+ and **movem**. rmac also not accept such aliasing and generate an error.
+- Motorola's assembler uses the underscore character (*_*) to define local
+ labels. In order for rmac to maintain a uniform syntax across all platforms,
+ such labels will not be treated as local.
+- Macros syntax is different from Motorola's assembler. This includes local
+ labels inside macros. The user is encouraged to study the `Macros`_ section
+ and compare syntactical differences.
+- 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.
+ Instead, the value needs to be split into two parts separated by **:**.
`6502 Support`_
===============
//
int WriteObject(int fd)
{
- LONG t; // Scratch long
LONG tds; // TEXT & DATA segment size
int i; // Temporary int
CHUNK * cp; // Chunk (for gather)
sy_assign(buf + HDRSIZE + tds, AddSymEntry);
chptr = buf + 0x0E; // Point to symbol table size entry
D_long(symsize);
+
+ if (verb_flag)
+ printf("Symbol table: %d bytes\n", symsize);
}
// Write out the header + text & data + symbol table (if any)
int just_bss; // 1, ds.b in microprocessor mode
uint32_t pcloc; // Value of "PC" at beginning of line
SYM * lab_sym; // Label on line (or NULL)
+char * label_defined; // The name of the last label defined in current line (if any)
const char extra_stuff[] = "extra (unexpected) text found after addressing mode";
const char comma_error[] = "missing comma";
state = -3; // No keyword (just EOL)
label = NULL; // No label
+ label_defined = NULL; // No label defined yet
lab_sym = NULL; // No (exported) label
equate = NULL; // No equate
tk = tok; // Save first token in line
if (HandleLabel(label, labtyp) != 0)
goto loop;
+ label_defined = label;
+
goto as68label;
}
}
{
if (HandleLabel(label, labtyp) != 0)
goto loop;
+
+ label_defined = label;
}
HandleRept();
// Non-zero == error occurred
if (HandleLabel(label, labtyp) != 0)
goto loop;
+
+ label_defined = label;
}
// Punt on EOL
" -l[filename] Create an output listing file\n"
" -l*[filename] Create an output listing file without pagination\n"
" -m[cpu] Select default CPU. Available options:\n"
- " 68000\n"
- " 68020\n"
- " 68030\n"
- " 68040\n"
- " 68060\n"
- " 6502\n"
- " tom\n"
- " jerry\n"
- " 56001\n"
+ " 68000, 68020, 68030, 68040, 68060, 6502, tom, jerry, 56001\n"
" -n Don't do things behind your back in RISC assembler\n"
" -o file Output file name\n"
" +o[value] Turn a specific optimisation on\n"