X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=procln.c;h=8cdcc6af2501cd5e8b1886cbe76e3813a63a46d9;hp=addff0462d8247e6cdc02632f88939e75f531b3e;hb=ace0b549a94110b69ec61442f825fb421b79799a;hpb=9153334781cd2e23750f4dc002e847606c07a1f0 diff --git a/procln.c b/procln.c index addff04..8cdcc6a 100644 --- a/procln.c +++ b/procln.c @@ -1,7 +1,7 @@ // // RMAC - Reboot's 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-2020 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -10,11 +10,14 @@ #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" @@ -34,6 +37,15 @@ #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 @@ -41,6 +53,7 @@ int disabled; // Assembly conditionally disabled 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"; @@ -174,6 +187,7 @@ DEBUG { printf("Assemble: Found TKEOF flag...\n"); } 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 @@ -221,6 +235,8 @@ as68label: if (HandleLabel(label, labtyp) != 0) goto loop; + label_defined = label; + goto as68label; } } @@ -351,6 +367,8 @@ as68label: { if (HandleLabel(label, labtyp) != 0) goto loop; + + label_defined = label; } HandleRept(); @@ -468,6 +486,11 @@ When checking to see if it's already been equated, issue a warning. 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 @@ -575,7 +598,7 @@ When checking to see if it's already been equated, issue a warning. 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; } @@ -585,6 +608,8 @@ When checking to see if it's already been equated, issue a warning. // Non-zero == error occurred if (HandleLabel(label, labtyp) != 0) goto loop; + + label_defined = label; } // Punt on EOL @@ -659,6 +684,125 @@ When checking to see if it's already been equated, issue a warning. } } + // 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) { @@ -706,8 +850,13 @@ When checking to see if it's already been equated, issue a warning. 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]; @@ -723,16 +872,13 @@ When checking to see if it's already been equated, issue a warning. // 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; }