//
-// 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-2018 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"
#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;
}
}
{
if (HandleLabel(label, labtyp) != 0)
goto loop;
+
+ label_defined = label;
}
HandleRept();
registerbank = BANK_0;
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
if (list_flag) // Put value in listing
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 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;
}