//
-// RMAC - Reboot's Macro Assembler for all Atari computers
+// RMAC - Renamed Macro Assembler for all Atari computers
// PROCLN.C - Line Processing
-// Copyright (C) 199x Landon Dyer, 2011-2017 Reboot and Friends
+// Copyright (C) 199x Landon Dyer, 2011-2021 Reboot and Friends
// RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
// Source utilised with the kind permission of Landon Dyer
//
#include "6502.h"
#include "amode.h"
#include "direct.h"
+#include "dsp56k_amode.h"
+#include "dsp56k_mach.h"
#include "error.h"
#include "expr.h"
#include "listing.h"
#include "mach.h"
#include "macro.h"
+#include "op.h"
#include "riscasm.h"
#include "sect.h"
#include "symbol.h"
#define DECL_MP // Include 6502 keyword state machine tables
#include "6502kw.h"
+#define DEF_MO // Include OP keyword definitions
+#define DECL_MO // Include OP keyword state machine tables
+#include "opkw.h"
+
+#define DEF_DSP // Include DSP56K keywords definitions
+#define DECL_DSP // Include DSP56K keyword state machine tables
+#include "dsp56kkw.h"
+
+
IFENT * ifent; // Current ifent
static IFENT ifent0; // Root ifent
IFENT * f_ifent; // Freelist of ifents
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;
}
}
case DOTX: siz = SIZX, tok++; break;
}
-
// Do special directives (500..999) (These must be handled in "real time")
if (state >= 500 && state < 1000)
{
{
if (HandleLabel(label, labtyp) != 0)
goto loop;
+
+ label_defined = label;
}
HandleRept();
{
if ((equtyp == EQUREG) && (sy->sattre & UNDEF_EQUR))
{
-//REALLY? sy->sattre |= ~UNDEF_EQUR;
sy->sattre &= ~UNDEF_EQUR;
sy->svalue = 0;
}
else if ((equtyp == CCDEF) && (sy->sattre & UNDEF_CC))
{
-//REALLY? sy->sattre |= ~UNDEF_CC;
sy->sattre &= ~UNDEF_CC;
sy->svalue = 0;
}
{
// Advance token pointer to the constant
tok += 3;
- tok++; // Skip the hi LONG, so pointing at lo LONG
// Anything other than a 0 or a 1 will result in "No Bank"
- if (*tok == 0)
+ if (*(uint64_t *)tok == 0)
registerbank = BANK_0;
- else if (*tok == 1)
+ else if (*(uint64_t *)tok == 1)
registerbank = BANK_1;
+
+ // Advance half-way through the 64-bit const.
+ // The code below, expecting a regular token,
+ // will advance past the second half.
+ tok++;
}
#ifdef DEBODGE_REGBANK
sy->sattre |= regbank; // Store register bank
#endif
eattr = ABS | DEFINED | GLOBAL;
-// & what does this $80000080 constant mean???
-// eval = 0x80000080 + (riscreg) + (registerbank << 8);
eval = riscreg;
tok++;
}
else if (expr(exprbuf, &eval, &eattr, &esym) != OK)
goto loop;
}
- //equ a equr
+ // equ an equr
else if (*tok == SYMBOL)
{
sy2 = lookup(string[tok[1]], LABEL, j);
sy->stype = sy2->stype;
sy->sattr = sy2->sattr;
sy->sattre = sy2->sattre;
-//ICK sy->svalue = (sy2->svalue & 0xFFFFF0FF);
sy->svalue = sy2->svalue;
goto loop;
}
sy->svalue = eval;
if (list_flag) // Put value in listing
- listvalue(eval);
+ listvalue((uint32_t)eval);
- at_eol(); // Must be at EOL now
+ ErrorIfNotAtEOL(); // Must be at EOL now
goto loop;
}
// Non-zero == error occurred
if (HandleLabel(label, labtyp) != 0)
goto loop;
+
+ label_defined = label;
}
// Punt on EOL
}
}
+ // If we are in OP mode and still in need of a mnemonic then search for one
+ if (robjproc && ((state < 0) || (state >= 1000)))
+ {
+ for(state=0, p=opname; state>=0;)
+ {
+ j = mobase[state] + (int)tolowertab[*p];
+
+ // Reject, character doesn't match
+ if (mocheck[j] != state)
+ {
+ state = -1; // No match
+ break;
+ }
+
+ // Must accept or reject at EOS
+ if (!*++p)
+ {
+ state = moaccept[j]; // (-1 on no terminal match)
+ break;
+ }
+
+ state = motab[j];
+ }
+
+ // Call OP code generator if we found a mnemonic
+ if (state >= 3100)
+ {
+ GenerateOPCode(state);
+ goto loop;
+ }
+ }
+
+ // If we are in 56K mode and still in need of a mnemonic then search for one
+ if (dsp56001 && ((state < 0) || (state >= 1000)))
+ {
+ for(state=0, p=opname; state>=0;)
+ {
+ j = dspbase[state] + (int)tolowertab[*p];
+
+ // Reject, character doesn't match
+ if (dspcheck[j] != state)
+ {
+ state = -1; // No match
+ break;
+ }
+
+ // Must accept or reject at EOS
+ if (!*++p)
+ {
+ state = dspaccept[j]; // (-1 on no terminal match)
+ break;
+ }
+
+ state = dsptab[j];
+ }
+
+ // Call DSP code generator if we found a mnemonic
+ if (state >= 2000)
+ {
+ LONG parcode;
+ int operands;
+ MNTABDSP * md = &dsp56k_machtab[state - 2000];
+ deposit_extra_ea = 0; // Assume no extra word needed
+
+ if (md->mnfunc == dsp_mult)
+ {
+ // Special case for multiplication instructions: they require
+ // 3 operands
+ if ((operands = dsp_amode(3)) == ERROR)
+ goto loop;
+ }
+ else if ((md->mnattr & PARMOVE) && md->mn0 != M_AM_NONE)
+ {
+ if (dsp_amode(2) == ERROR)
+ goto loop;
+ }
+ else if ((md->mnattr & PARMOVE) && md->mn0 == M_AM_NONE)
+ {
+ // Instructions that have parallel moves but use no operands
+ // (probably only move). In this case, don't parse addressing
+ // modes--just go straight to parallel parse
+ dsp_am0 = dsp_am1 = M_AM_NONE;
+ }
+ else
+ {
+ // Non parallel move instructions can have up to 4 parameters
+ // (well, only tcc instructions really)
+ if ((operands = dsp_amode(4)) == ERROR)
+ goto loop;
+
+ if (operands == 4)
+ {
+ dsp_tcc4(md->mninst);
+ goto loop;
+ }
+ }
+
+ if (md->mnattr & PARMOVE)
+ {
+ // Check for parallel moves
+ if ((parcode = parmoves(dsp_a1reg)) == ERROR)
+ goto loop;
+ }
+ else
+ {
+ if (*tok != EOL)
+ error("parallel moves not allowed with this instruction");
+
+ parcode = 0;
+ }
+
+ while ((dsp_am0 & md->mn0) == 0 || (dsp_am1 & md->mn1) == 0)
+ md = &dsp56k_machtab[md->mncont];
+
+ (*md->mnfunc)(md->mninst | (parcode << 8));
+ goto loop;
+ }
+ }
+
// Invoke macro or complain about bad mnemonic
if (state < 0)
{
if (amode(1) < 0) // Parse 0, 1 or 2 addr modes
goto loop;
- if (*tok != EOL)
- error(extra_stuff);
+ // Check that we're at EOL
+ // The only exception is ptestr/ptestw instructions
+ // that have 3 or 4 operands and are not handled by
+ // amode(). (yes, we're taking a performance hit here sadly)
+ if (m->mnfunc != m_ptestr && m->mnfunc != m_ptestw)
+ if (*tok != EOL)
+ error(extra_stuff);
amsk0 = amsktab[am0];
amsk1 = amsktab[am1];
// Keep a backup of chptr (used for optimisations during codegen)
chptr_opcode = chptr;
- for(;;)
- {
- if ((m->mnattr & siz) && (amsk0 & m->mn0) != 0 && (amsk1 & m->mn1) != 0)
- {
- (*m->mnfunc)(m->mninst, siz);
- goto loop;
- }
-
+ while (!(m->mnattr & siz) || (amsk0 & m->mn0) == 0 || (amsk1 & m->mn1) == 0)
m = &machtab[m->mncont];
- }
+
+ DEBUG { printf(" 68K: mninst=$%X, siz=$%X, mnattr=$%X, amsk0=$%X, mn0=$%X, amsk1=$%X, mn1=$%X\n", m->mninst, siz, m->mnattr, amsk0, m->mn0, amsk1, m->mn1); }
+
+ (*m->mnfunc)(m->mninst, siz);
+ goto loop;
}
{
symbol = NewSymbol(label, LABEL, environment);
symbol->sattr = 0;
-// symbol->sattre = RISCSYM;
symbol->sattre = 0;
}
else if (symbol->sattr & DEFINED)