// DIRECT.C - Directive Handling
// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends
// RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
-// Source Utilised with the Kind Permission of Landon Dyer
+// Source utilised with the kind permission of Landon Dyer
//
#include "direct.h"
#include "kwtab.h"
-TOKEN exprbuf[128]; // Expression buffer
+TOKEN exprbuf[128]; // Expression buffer
SYM * symbolPtr[1000000]; // Symbol pointers table
static long unused; // For supressing 'write' warnings
+char buffer[256]; // Scratch buffer for messages
// Directive handler table
d_org, // 0 org
d_even, // 1 even
d_unimpl, // 2 .6502
- d_68000, // 3 .68000
+ d_68000, // 3 .68000
d_bss, // 4 bss
- d_data, // 5 data
- d_text, // 6 text
- d_abs, // 7 abs
- d_comm, // 8 comm
- d_init, // 9 init
- d_cargs, // 10 cargs
- d_goto, // 11 goto
- d_dc, // 12 dc
- d_ds, // 13 ds
- d_undmac, // 14 undefmac
+ d_data, // 5 data
+ d_text, // 6 text
+ d_abs, // 7 abs
+ d_comm, // 8 comm
+ (void *)d_init, // 9 init
+ d_cargs, // 10 cargs
+ (void *)d_goto, // 11 goto
+ (void *)d_dc, // 12 dc
+ (void *)d_ds, // 13 ds
+ d_undmac, // 14 undefmac
d_gpu, // 15 .gpu
d_dsp, // 16 .dsp
- d_dcb, // 17 dcb
- d_unimpl, // 18* set
- d_unimpl, // 19* reg
- d_unimpl, // 20 dump
- d_incbin, // 21 .incbin //load
- d_unimpl, // 22 disable
- d_unimpl, // 23 enable
- d_globl, // 24 globl
+ (void *)d_dcb, // 17 dcb
+ d_unimpl, // 18* set
+ d_unimpl, // 19* reg
+ d_unimpl, // 20 dump
+ d_incbin, // 21 .incbin //load
+ d_unimpl, // 22 disable
+ d_unimpl, // 23 enable
+ d_globl, // 24 globl
d_regbank0, // 25 .regbank0
d_regbank1, // 26 .regbank1
- d_unimpl, // 27 xdef
- d_assert, // 28 assert
- d_unimpl, // 29* if
- d_unimpl, // 30* endif
- d_unimpl, // 31* endc
- d_unimpl, // 32* iif
- d_include, // 33 include
- fpop, // 34 end
- d_unimpl, // 35* macro
- ExitMacro, // 36* exitm
- d_unimpl, // 37* endm
- d_list, // 38 list
- d_nlist, // 39 nlist
- d_long, // 40* rept
- d_phrase, // 41* endr
- d_dphrase, // 42 struct
- d_qphrase, // 43 ends
- d_title, // 44 title
- d_subttl, // 45 subttl
- eject, // 46 eject
- d_unimpl, // 47 error
- d_unimpl, // 48 warn
+ d_unimpl, // 27 xdef
+ d_assert, // 28 assert
+ d_unimpl, // 29* if
+ d_unimpl, // 30* endif
+ d_unimpl, // 31* endc
+ d_unimpl, // 32* iif
+ d_include, // 33 include
+ fpop, // 34 end
+ d_unimpl, // 35* macro
+ ExitMacro, // 36* exitm
+ d_unimpl, // 37* endm
+ d_list, // 38 list
+ d_nlist, // 39 nlist
+ d_long, // 40* rept
+ d_phrase, // 41* endr
+ d_dphrase, // 42 struct
+ d_qphrase, // 43 ends
+ d_title, // 44 title
+ d_subttl, // 45 subttl
+ eject, // 46 eject
+ d_error, // 47 error
+ d_warn, // 48 warn
d_noclear, // 49 .noclear
d_equrundef, // 50 .equrundef/.regundef
d_ccundef, // 51 .ccundef
d_cstruct, // 53 .cstruct
d_jpad, // 54 .jpad (deprecated)
d_nojpad, // 55 .nojpad (deprecated)
+ d_gpumain, // 56 .gpumain (deprecated)
+ d_prgflags, // 57 .prgflags
};
+//
+// .error - Abort compilation, printing an error message
+//
+int d_error(char *str)
+{
+ if (*tok == EOL)
+ return error("error directive encountered - aborting assembling");
+ else
+ {
+ switch(*tok)
+ {
+ case STRING:
+ return error(string[tok[1]]);
+ break;
+ default:
+ return error("error directive encountered - aborting assembling");
+ }
+ }
+}
+
+
+//
+// .warn - Just display a warning on screen
+//
+int d_warn(char *str)
+{
+ if (*tok == EOL)
+ return warn("WARNING WARNING WARNING");
+ else
+ {
+ switch(*tok)
+ {
+ case STRING:
+ return warn(string[tok[1]]);
+ break;
+ default:
+ return warn("WARNING WARNING WARNING");
+ }
+ }
+}
+
+
//
// .org - Set origin
//
}
orgaddr = address;
- orgactive = 1;
+ orgactive = 1;
+//printf("ORG: address = $%08X...\n", orgaddr);
return 0;
}
//
-// Print Directive
+// Print directive
//
int d_print(void)
{
- char prntstr[LNSIZ]; // String for PRINT directive
- char format[LNSIZ]; // Format for PRINT directive
- int formatting = 0; // Formatting on/off
- int wordlong = 0; // WORD = 0, LONG = 1
- int outtype = 0; // 0:hex, 1:decimal, 2:unsigned
-
- VALUE eval; // Expression value
- WORD eattr; // Expression attributes
- SYM * esym; // External symbol involved in expr.
+ char prntstr[LNSIZ]; // String for PRINT directive
+ char format[LNSIZ]; // Format for PRINT directive
+ int formatting = 0; // Formatting on/off
+ int wordlong = 0; // WORD = 0, LONG = 1
+ int outtype = 0; // 0:hex, 1:decimal, 2:unsigned
+
+ VALUE eval; // Expression value
+ WORD eattr; // Expression attributes
+ SYM * esym; // External symbol involved in expr.
TOKEN r_expr[EXPRSIZE];
while (*tok != EOL)
switch(*tok)
{
case STRING:
-// sprintf(prntstr, "%s", (char *)tok[1]);
sprintf(prntstr, "%s", string[tok[1]]);
printf("%s", prntstr);
}
printf("\n");
- println("\n");
return 0;
//
-// Undefine an Equated Condition Code
+// Undefine an equated condition code
//
int d_ccundef(void)
{
if (*tok != SYMBOL)
{
- error(syntax_error);
+ error("syntax error; expected symbol");
return ERROR;
}
-// ccname = lookup((char *)tok[1], LABEL, 0);
ccname = lookup(string[tok[1]], LABEL, 0);
// Make sure symbol is a valid ccdef
//
-// Undefine an Equated Register
+// Undefine an equated register
//
int d_equrundef(void)
{
// Check that we are in a RISC section
if (!rgpu && !rdsp)
- {
- error(".equrundef/.regundef must be defined in .gpu/.dsp section");
- return ERROR;
- }
+ return error(".equrundef/.regundef must be defined in .gpu/.dsp section");
while (*tok != EOL)
{
// Check we are dealing with a symbol
if (*tok != SYMBOL)
- {
- error(syntax_error);
- return ERROR;
- }
+ return error("syntax error; expected symbol");
// Lookup and undef if equated register
-// regname = lookup((char *)tok[1], LABEL, 0);
regname = lookup(string[tok[1]], LABEL, 0);
if (regname && (regname->sattre & EQUATEDREG))
+ {
+ // Reset the attributes of this symbol...
+ regname->sattr = 0;
+ regname->sattre &= ~(EQUATEDREG | BANK_0 | BANK_1);
regname->sattre |= UNDEF_EQUR;
+ }
// Skip over symbol token and address
tok += 2;
//
-// Do Not Allow the Use of the CLR.L Opcode
+// Do not allow use of the CLR.L opcode
//
int d_noclear(void)
{
+ warn("CLR.L opcode ignored...");
return 0;
}
//
-// Include Binary File
+// Include binary file
//
int d_incbin(void)
{
if (*tok != STRING)
{
- error(syntax_error);
+ error("syntax error; string missing");
return ERROR;
}
return ERROR;
}
-//#define D_byte(b) {*chptr++=(char)b; ++sloc; ++ch_size; if(orgactive) ++orgaddr;}
memcpy(chptr, fileBuffer, size);
chptr += size;
sloc += size;
//
-// Set RISC Register Banks
+// Set RISC register banks
//
int d_regbank0(void)
{
//
-// Adjust Location to an EVEN Value
+// Helper function, to cut down on mistakes & typing
+//
+static inline void SkipBytes(unsigned bytesToSkip)
+{
+ if (!bytesToSkip)
+ return;
+
+ if ((scattr & SBSS) == 0)
+ {
+ chcheck(bytesToSkip);
+ D_ZEROFILL(bytesToSkip);
+ }
+ else
+ {
+ sloc += bytesToSkip;
+
+ if (orgactive)
+ orgaddr += bytesToSkip;
+ }
+}
+
+
+//
+// Adjust location to an EVEN value
//
int d_even(void)
{
- if (sloc & 1)
+ unsigned skip = (rgpu || rdsp ? orgaddr : sloc) & 0x01;
+
+ if (skip)
{
if ((scattr & SBSS) == 0)
{
}
else
{
- ++sloc;
+ sloc++;
+
+ if (orgactive)
+ orgaddr++;
}
}
//
-// Adjust Location to an LONG Value
+// Adjust location to a LONG value
//
int d_long(void)
{
- unsigned i;
- unsigned val = 4;
-
- i = sloc & ~(val - 1);
-
- if (i != sloc)
- val = val - (sloc - i);
- else
- val = 0;
-
- if (val)
- {
- if ((scattr & SBSS) == 0)
- {
- chcheck(val);
-
- for(i=0; i<val; i++)
- D_byte(0);
- }
- else
- {
- sloc += val;
- }
- }
+ unsigned lower2Bits = (rgpu || rdsp ? orgaddr : sloc) & 0x03;
+ unsigned bytesToSkip = (0x04 - lower2Bits) & 0x03;
+ SkipBytes(bytesToSkip);
return 0;
}
//
-// Adjust Location to an PHRASE Value
+// Adjust location to a PHRASE value
+//
+// N.B.: We have to handle the GPU/DSP cases separately because you can embed
+// RISC code in the middle of a regular 68K section. Also note that all
+// of the alignment pseudo-ops will have to be fixed this way.
+//
+// This *must* behave differently when in a RISC section, as following sloc
+// (instead of orgaddr) will fuck things up royally. Note that we do it this
+// way because you can embed RISC code in a 68K section, and have the origin
+// pointing to a different alignment in the RISC section than the 68K section.
//
int d_phrase(void)
{
- unsigned i;
- unsigned val = 8;
-
- i = sloc & ~(val - 1);
-
- if (i != sloc)
- val = val - (sloc - i);
- else
- val = 0;
-
- if (val)
- {
- if ((scattr & SBSS) == 0)
- {
- chcheck(val);
-
- for(i=0; i<val; i++)
- D_byte(0);
- }
- else
- {
- sloc += val;
- }
- }
+ unsigned lower3Bits = (rgpu || rdsp ? orgaddr : sloc) & 0x07;
+ unsigned bytesToSkip = (0x08 - lower3Bits) & 0x07;
+ SkipBytes(bytesToSkip);
return 0;
}
//
-// Adjust Location to an DPHRASE Value
+// Adjust location to a DPHRASE value
//
int d_dphrase(void)
{
- unsigned i;
- unsigned val = 16;
-
- i = sloc & ~(val - 1);
-
- if (i != sloc)
- val = val - (sloc - i);
- else
- val = 0;
-
- if (val)
- {
- if ((scattr & SBSS) == 0)
- {
- chcheck(val);
-
- for(i=0; i<val; i++)
- D_byte(0);
- }
- else
- {
- sloc += val;
- }
- }
+ unsigned lower4Bits = (rgpu || rdsp ? orgaddr : sloc) & 0x0F;
+ unsigned bytesToSkip = (0x10 - lower4Bits) & 0x0F;
+ SkipBytes(bytesToSkip);
return 0;
}
//
-// Adjust Location to an QPHRASE Value
+// Adjust location to a QPHRASE value
//
int d_qphrase(void)
{
- unsigned i;
- unsigned val = 32;
-
- i = sloc & ~(val - 1);
-
- if (i != sloc)
- val = val - (sloc - i);
- else
- val = 0;
-
- if (val)
- {
- if ((scattr & SBSS) == 0)
- {
- savsect();
- chcheck(val);
-
- for(i=0; i<val; i++)
- D_byte(0);
- }
- else
- {
- sloc += val;
- }
- }
+ unsigned lower5Bits = (rgpu || rdsp ? orgaddr : sloc) & 0x1F;
+ unsigned bytesToSkip = (0x20 - lower5Bits) & 0x1F;
+ SkipBytes(bytesToSkip);
return 0;
}
// which is OK since multiple labels are only allowed in AS68 kludge mode, and
// the C compiler is VERY paranoid and uses ".even" whenever it can
//
+// N.B.: This probably needs the same fixes as above...
+//
void auto_even(void)
{
if (scattr & SBSS)
- ++sloc; // Bump BSS section
+ sloc++; // Bump BSS section
else
- D_byte(0) // Deposit 0.b in non-BSS
+ D_byte(0); // Deposit 0.b in non-BSS
- if (lab_sym != NULL) // Bump label if we have to
- ++lab_sym->svalue;
+ if (lab_sym != NULL) // Bump label if we have to
+ lab_sym->svalue++;
}
//
-// Unimplemened Directive Error
+// Unimplemened directive error
//
int d_unimpl(void)
{
//
int symlist(int(* func)())
{
- char * em = "symbol list syntax";
+ const char * em = "symbol list syntax";
for(;;)
{
if (*tok != SYMBOL)
return error(em);
-#if 0
- if ((*func)(tok[1]) != OK)
-#else
if ((*func)(string[tok[1]]) != OK)
-#endif
break;
tok += 2;
if (*tok != ',')
return error(em);
- ++tok;
+ tok++;
}
return 0;
char buf[128];
char buf1[128];
- if (*tok == STRING) // Leave strings ALONE
-#if 0
- fn = (char *)*++tok;
-#else
+ if (*tok == STRING) // Leave strings ALONE
fn = string[*++tok];
-#endif
- else if (*tok == SYMBOL) // Try to append ".s" to symbols
+ else if (*tok == SYMBOL) // Try to append ".s" to symbols
{
-#if 0
- strcpy(buf, (char *)*++tok);
-#else
strcpy(buf, string[*++tok]);
-#endif
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:
//
int globl1(char * p)
{
- SYM *sy;
+ SYM * sy;
if (*p == '.')
return error("cannot .globl local symbol");
sy = NewSymbol(p, LABEL, 0);
sy->svalue = 0;
sy->sattr = GLOBAL;
+//printf("glob1: Making global symbol: attr=%04X, eattr=%08X, %s\n", sy->sattr, sy->sattre, sy->sname);
}
else
sy->sattr |= GLOBAL;
}
+//
+// .prgflags expression
+//
+int d_prgflags(void)
+{
+ VALUE eval;
+
+ if (*tok == EOL)
+ return error("PRGFLAGS requires value");
+ else if (abs_expr(&eval) == OK)
+ {
+ PRGFLAGS=eval;
+ return 0;
+ }
+ else
+ {
+ return error("PRGFLAGS requires value");
+ }
+}
+
+
//
// .abs [expression]
//
{
VALUE eval;
- savsect();
+ SaveSection();
if (*tok == EOL)
eval = 0;
else if (abs_expr(&eval) != OK)
return 0;
- switchsect(ABS);
+ SwitchSection(ABS);
sloc = eval;
return 0;
}
//
-// Switch Segments
+// Switch segments
//
-
int d_text(void)
{
if (rgpu || rdsp)
if (cursect != TEXT)
{
- savsect();
- switchsect(TEXT);
+ SaveSection();
+ SwitchSection(TEXT);
}
return 0;
if (cursect != DATA)
{
- savsect();
- switchsect(DATA);
+ SaveSection();
+ SwitchSection(DATA);
}
return 0;
if (cursect != BSS)
{
- savsect();
- switchsect(BSS);
+ SaveSection();
+ SwitchSection(BSS);
}
return 0;
//
int d_ds(WORD siz)
{
-if (verb_flag)
+if (debug)
printf("Directive: .ds.[size] = %u, sloc = $%X\n", siz, sloc);
VALUE eval;
if ((scattr & SBSS) != 0)
return error("illegal initialization of section");
+ // Do an auto_even if it's not BYTE sized (hmm, should we be doing this???)
if ((siz != SIZB) && (sloc & 1))
auto_even();
+ // Check to see if we're trying to set LONGS on a non 32-bit aligned
+ // address in a GPU or DSP section, in their local RAM
+ if ((siz == SIZL) && (orgaddr & 0x03)
+ && ((rgpu && (orgaddr >= 0xF03000) && (orgaddr <= 0xF03FFFF))
+ || (rdsp && (orgaddr >= 0xF1B000) && (orgaddr <= 0xF1CFFFF))))
+ warn("depositing LONGs on a non-long address in local RAM");
+
for(;; ++tok)
{
// dc.b 'string' [,] ...
if (siz == SIZB && *tok == STRING && (tok[2] == ',' || tok[2] == EOL))
{
-// i = strlen((const char*)tok[1]);
i = strlen(string[tok[1]]);
if ((challoc - ch_size) < i)
case SIZB:
if (!defined)
{
- fixup(FU_BYTE | FU_SEXT, sloc, exprbuf);
+ AddFixup(FU_BYTE | FU_SEXT, sloc, exprbuf);
D_byte(0);
}
else
return error("non-absolute byte value");
if (eval + 0x100 >= 0x200)
- return error(range_error);
+ {
+ sprintf(buffer, "%s (value = $%X)", range_error, eval);
+ return error(buffer);
+ }
D_byte(eval);
}
case SIZN:
if (!defined)
{
- fixup(FU_WORD | FU_SEXT, sloc, exprbuf);
+ AddFixup(FU_WORD | FU_SEXT, sloc, exprbuf);
D_word(0);
}
else
if (!defined)
{
if (movei)
- fixup(FU_LONG | FU_MOVEI, sloc, exprbuf);
+ AddFixup(FU_LONG | FU_MOVEI, sloc, exprbuf);
else
- fixup(FU_LONG, sloc, exprbuf);
+ AddFixup(FU_LONG, sloc, exprbuf);
D_long(0);
}
VALUE evalc, eval;
WORD eattr;
+printf("dcb: section is %s%s%s (scattr=$%X)\n", (cursect & TEXT ? "TEXT" : ""), (cursect & DATA ? " DATA" : ""), (cursect & BSS ? "BSS" : ""), scattr);
if ((scattr & SBSS) != 0)
return error("illegal initialization of section");
case SIZB:
if (!defined)
{
- fixup(FU_BYTE | FU_SEXT, sloc, exprbuf);
+ AddFixup(FU_BYTE | FU_SEXT, sloc, exprbuf);
D_byte(0);
}
else
case SIZN:
if (!defined)
{
- fixup(FU_WORD | FU_SEXT, sloc, exprbuf);
+ AddFixup(FU_WORD | FU_SEXT, sloc, exprbuf);
D_word(0);
}
else
case SIZL:
if (!defined)
{
- fixup(FU_LONG, sloc, exprbuf);
+ AddFixup(FU_LONG, sloc, exprbuf);
D_long(0);
}
else
if (*tok != SYMBOL)
return error("missing symbol");
-// p = (char *)tok[1];
p = string[tok[1]];
tok += 2;
// Switching from gpu/dsp sections should reset any ORG'd Address
orgactive = 0;
orgwarning = 0;
- savsect();
- switchsect(TEXT);
+ SaveSection();
+ SwitchSection(TEXT);
return 0;
}
//
-// .gpu - Switch to GPU Assembler
+// .gpu - Switch to GPU assembler
//
int d_gpu(void)
{
// If previous section was dsp or 68000 then we need to reset ORG'd Addresses
if (!rgpu)
{
+//printf("Resetting ORG...\n");
orgactive = 0;
orgwarning = 0;
}
+//else printf("NOT resetting ORG!\n");
rgpu = 1; // Set GPU assembly
rdsp = 0; // Unset DSP assembly
//
-// .dsp - Switch to DSP Assembler
+// .dsp - Switch to DSP assembler
//
int d_dsp(void)
{
{
if (*tok == SYMBOL)
{
-// p = (char *)tok[1];
p = string[tok[1]];
-#if 0
- if (*p == '.')
- env = curenv; // Label is local
- else
- env = 0; // Label is global
-#else
// Set env to either local (dot prefixed) or global scope
env = (*p == '.' ? curenv : 0);
-#endif
symbol = lookup(p, LABEL, env);
if (symbol == NULL)
return errors("multiply-defined label '%s'", p);
// Put symbol in "order of definition" list
- if (!(symbol->sattr & SDECLLIST))
- sym_decl(symbol);
+ AddToSymbolDeclarationList(symbol);
symbol->sattr |= (ABS | DEFINED | EQUATED);
symbol->svalue = eval;
if (reglist(&rlist) < 0)
return 0;
-// for(i=0; i++<16; rlist>>=1)
for(i=0; i<16; i++, rlist>>=1)
{
if (rlist & 1)
return errors("multiply-defined label '%s'", symbolName);
// Put symbol in "order of definition" list
- if (!(symbol->sattr & SDECLLIST))
- sym_decl(symbol);
+ AddToSymbolDeclarationList(symbol);
tok += 2;
return OK;
}
+
+int d_gpumain(void)
+{
+ return error("What the hell? Do you think we adhere to the Goof standard?");
+}
+