The deed has been accomplished.
authorShamus Hammons <jlhamm@acm.org>
Wed, 7 Aug 2019 23:24:52 +0000 (18:24 -0500)
committerShamus Hammons <jlhamm@acm.org>
Wed, 7 Aug 2019 23:24:52 +0000 (18:24 -0500)
As far as I can tell, there should be no more regressions, but that's
no guarantee of anything.  Assuming no more are found, this should go
out as version 2.0.0.  :-D

20 files changed:
6502.c
direct.c
dsp56k.h
dsp56k_amode.c
error.c
error.h
listing.c
macro.c
object.c
op.c
procln.c
riscasm.c
rmac.c
rmac.h
sect.c
sect.h
symbol.c
symbol.h
token.c
version.h

diff --git a/6502.c b/6502.c
index 27a8e1ac9ac41f153c882c95d1f65c1149931d81..4c188cfb035f8f2faadba13d7d3dccfb48c7a543 100644 (file)
--- a/6502.c
+++ b/6502.c
@@ -645,46 +645,39 @@ badmode:
        if (sloc > 0x10000L)
                fatal("6502 code pointer > 64K");
 
-//Now why use this instead of at_eol()?
-       if (*tok != EOL)
-               error(extra_stuff);
+       ErrorIfNotAtEOL();
 }
 
 
 //
 // Generate 6502 object output file.
+// ggn: Converted to COM/EXE/XEX output format
 //
-// ggn: converted into a com/exe/xex output format
 void m6502obj(int ofd)
 {
-       uint16_t exeheader[3];
-       int headsize = 6;
-       uint16_t * headpoint = exeheader;
+       uint8_t header[4];
 
        CHUNK * ch = sect[M6502].scode;
 
-       // If no 6502 code was generated, forget it
+       // If no 6502 code was generated, bail out
        if ((ch == NULL) || (ch->challoc == 0))
                return;
 
-       exeheader[0] = 0xFFFF;          // Mandatory for first segment
        register uint8_t * p = ch->chptr;
 
+       // Write out mandatory $FFFF header
+       header[0] = header[1] = 0xFF;
+       ssize_t unused = write(ofd, header, 2);
+
        for(uint16_t * l=&orgmap[0][0]; l<currentorg; l+=2)
        {
-/*
-Why are we assuming endianness here? This is retarded
-*/
-               exeheader[1] = l[0];
-               exeheader[2] = l[1] - 1;
-
-               // Write header
-               size_t unused = write(ofd, headpoint, headsize);
-               unused = write(ofd, p + l[0], l[1] - l[0]);
+               SETLE16(header, 0, l[0]);
+               SETLE16(header, 2, l[1] - 1);
 
-               // Skip the $FFFF after first segment, it's not mandatory
-               headpoint = &exeheader[1];
-               headsize = 4;
+               // Write header for segment
+               unused = write(ofd, header, 4);
+               // Write the segment data
+               unused = write(ofd, p + l[0], l[1] - l[0]);
        }
 }
 
index c42d8b8c727f5cd3e5ee938ccc6fc383f03c51a0..32e5dd19233c679bab7845f0f6a41f51bc030452 100644 (file)
--- a/direct.c
+++ b/direct.c
@@ -9,6 +9,7 @@
 #include "direct.h"
 #include "6502.h"
 #include "amode.h"
+#include "dsp56k.h"
 #include "error.h"
 #include "expr.h"
 #include "fltpoint.h"
@@ -222,7 +223,9 @@ int d_org(void)
                return error(".org permitted only in GPU/DSP/OP, 56001 and 6502 sections");
 
        // M56K can leave the expression off the org for some reason :-/
-       if ((abs_expr(&address) == ERROR) && !dsp56001)
+       // (It's because the expression is non-standard, and so we have to look at
+       // it in isolation)
+       if (!dsp56001 && (abs_expr(&address) == ERROR))
        {
                error("cannot determine org'd address");
                return ERROR;
@@ -255,9 +258,94 @@ int d_org(void)
        }
        else if (dsp56001)
        {
+               // Only mark segments we actually wrote something
+               if (chptr != dsp_currentorg->start && dsp_written_data_in_current_org)
+               {
+                       dsp_currentorg->end = chptr;
+                       dsp_currentorg++;
+               }
+
+               // Maybe we switched from a non-DSP section (TEXT, DATA, etc) and
+               // scode isn't initialised yet. Not that it's going to be a valid
+               // scenario, but if we try it anyhow it's going to lead to a crash. So
+               // let's fudge a value of 0 and get on with it.
+               orgaddr = (scode != NULL ? sloc : 0);
+               SaveSection();
+
+               if (tok[1] != ':')
+                       return error(syntax_error);
+
+               int sectionToSwitch = 0;
+
+               switch (tok[0])
+               {
+               case KW_X:
+                       dsp_currentorg->memtype = ORG_X;
+                       sectionToSwitch = M56001X;
+                       break;
+
+               case KW_Y:
+                       dsp_currentorg->memtype = ORG_Y;
+                       sectionToSwitch = M56001Y;
+                       break;
+
+               case KW_P:
+                       dsp_currentorg->memtype = ORG_P;
+                       sectionToSwitch = M56001P;
+                       break;
+
+               case KW_L:
+                       dsp_currentorg->memtype = ORG_L;
+                       sectionToSwitch = M56001L;
+                       break;
+
+               default:
+                       return error("unknown type in ORG");
+               }
+
+               if ((obj_format == LOD) || (obj_format == P56))
+                       SwitchSection(sectionToSwitch);
+
+               tok += 2;
+               chcheck(3); // Ensure we got a valid address to write
+               dsp_currentorg->chunk = scode;  // Mark down which chunk this org starts from (will be needed when outputting)
+
+               if (*tok == EOL)
+               {
+                       // Well, the user didn't specify an address at all so we'll have to
+                       // use the last used address of that section (or 0 if there wasn't one)
+                       address = orgaddr;
+                       dsp_currentorg->start = chptr;
+                       dsp_currentorg->orgadr = orgaddr;
+               }
+               else
+               {
+                       if (abs_expr(&address) == ERROR)
+                       {
+                               error("cannot determine org'd address");
+                               return ERROR;
+                       }
+
+                       dsp_currentorg->start = chptr;
+                       dsp_currentorg->orgadr = (uint32_t)address;
+                       sect[cursect].orgaddr = (uint32_t)address;
+               }
+
+               if (address > DSP_MAX_RAM)
+               {
+                       return error(range_error);
+               }
+
+               dsp_written_data_in_current_org = 0;
+
+               // Copied from 6502 above: kludge `lsloc' so the listing generator
+               // doesn't try to spew out megabytes.
+               lsloc = sloc = (int32_t)address;
+// N.B.: It seems that by enabling this, even though it works elsewhere, will cause symbols to royally fuck up.  Will have to do some digging to figure out why.
+//             orgactive = 1;
        }
 
-       at_eol();
+       ErrorIfNotAtEOL();
        return 0;
 }
 
@@ -830,7 +918,7 @@ int d_assert(void)
                        break;
        }
 
-       at_eol();
+       ErrorIfNotAtEOL();
        return 0;
 }
 
@@ -1011,7 +1099,7 @@ int d_ds(WORD siz)
                dep_block(eval, siz, 0, (WORD)(DEFINED | ABS), NULL);
        }
 
-       at_eol();
+       ErrorIfNotAtEOL();
        return 0;
 }
 
@@ -1029,7 +1117,9 @@ int d_dc(WORD siz)
                return error("illegal initialization of section");
 
        // Do an auto_even if it's not BYTE sized (hmm, should we be doing this???)
-       if (cursect != M6502 && (siz != SIZB) && (sloc & 1))
+       if ((cursect != M6502) && (cursect != M56001P) && (cursect != M56001X)
+               && (cursect != M56001Y) && (cursect != M56001L)
+               && (siz != SIZB) && (sloc & 1))
                auto_even();
 
        // Check to see if we're trying to set LONGS on a non 32-bit aligned
@@ -1086,6 +1176,138 @@ int d_dc(WORD siz)
                uint16_t tdb = eattr & TDB;
                uint16_t defined = eattr & DEFINED;
 
+// N.B.: This is awful.  This needs better handling, rather than just bodging something in that, while works, is basically an ugly wart on the assembler.  !!! FIX !!!
+               if (dsp56001)
+               {
+                       if (cursect != M56001L)
+                       {
+                               if (!defined)
+                               {
+                                       AddFixup(FU_DSPIMM24 | FU_SEXT, sloc, exprbuf);
+                                       D_dsp(0);
+                               }
+                               else
+                               {
+                                       if (eattr & FLOAT)
+                                       {
+                                               double fval = *(double *)&eval;
+
+                                               if (fval >= 1)
+                                               {
+                                                       warn("value clamped to +1.");
+                                                       eval = 0x7fffff;
+                                               }
+                                               else if (fval <= -1)
+                                               {
+                                                       warn("value clamped to -1.");
+                                                       eval = 0x800000;
+                                               }
+                                               else
+                                               {
+                                                       // Convert fraction to 24 bits fixed point with sign and rounding
+                                                       // Yeah, that cast to int32_t has to be there because casting
+                                                       // a float to unsigned int is "undefined" according to the C
+                                                       // standard. Which most compilers seem to do the sensible thing
+                                                       // and just cast the f**king value properly, except gcc 4.x.x
+                                                       // for arm (tested on raspbian).
+                                                       // Thanks, C and gcc! Thanks for making me waste a few hours \o/
+                                                       eval = 0;//!!! FIX !!! (uint32_t)(int32_t)round(fval*(1 << 23));
+                                               }
+                                       }
+                                       else
+                                       {
+                                               if ((uint32_t)eval + 0x1000000 >= 0x2000000)
+                                                       return error(range_error);
+                                       }
+
+                                       // Deposit DSP word (24-bit)
+                                       D_dsp(eval);
+                               }
+                       }
+                       else
+                       {
+                               // In L: we deposit stuff to both X: and Y: instead
+                               // We will be a bit lazy and require that there is a 2nd value in the same source line.
+                               // (Motorola's assembler can parse 12-digit hex values, which we can't do at the moment)
+                               // This of course requires to parse 2 values in one pass.
+                               // If there isn't another value in this line, assume X: value is 0.
+                               int secondword = 0;
+                               uint32_t evaly;
+l_parse_loop:
+
+                               if (!defined)
+                               {
+                                       AddFixup(FU_DSPIMM24 | FU_SEXT, sloc, exprbuf);
+                                       D_dsp(0);
+                               }
+                               else
+                               {
+                                       if (eattr & FLOAT)
+                                       {
+                                               float fval = *(float *)&eval;
+                                               if (fval >= 1)
+                                               {
+                                                       warn("value clamped to +1.");
+                                                       eval = 0x7fffff;
+                                               }
+                                               else if (fval <= -1)
+                                               {
+                                                       warn("value clamped to -1.");
+                                                       eval = 0x800000;
+                                               }
+                                               else
+                                               {
+                                                       // Convert fraction to 24 bits fixed point with sign and rounding
+                                                       // Yeah, that cast to int32_t has to be there because casting
+                                                       // a float to unsigned int is "undefined" according to the C
+                                                       // standard. Which most compilers seem to do the sensible thing
+                                                       // and just cast the f**king value properly, except gcc 4.x.x
+                                                       // for arm (tested on raspbian).
+                                                       // Thanks, C and gcc! Thanks for making me waste a few hours \o/
+                                                       eval = 0;//!!! FIX !!! (uint32_t)(int32_t)round(fval*(1 << 23));
+                                               }
+                                       }
+                                       else
+                                       {
+                                               if (eval + 0x1000000 >= 0x2000000)
+                                                       return error(range_error);
+                                       }
+
+                                       // Parse 2nd value if we didn't do this yet
+                                       if (secondword == 0)
+                                       {
+                                               evaly = (uint32_t)eval;
+                                               secondword = 1;
+
+                                               if (*tok != ':')
+                                               {
+                                                       // If we don't have a : then we're probably at EOL,
+                                                       // which means the X: value will be 0
+                                                       eval = 0;
+                                                       ErrorIfNotAtEOL();
+                                               }
+                                               else
+                                               {
+                                                       tok++; // Eat the comma;
+
+                                                       if (expr(exprbuf, &eval, &eattr, NULL) != OK)
+                                                               return 0;
+
+                                                       defined = (WORD)(eattr & DEFINED);
+                                                       goto l_parse_loop;
+                                               }
+                                       }
+
+                                       // Deposit DSP words (24-bit)
+                                       D_dsp(eval);
+                                       D_dsp(evaly);
+                                       sloc--; // We do write 2 DSP words but as far as L: space is concerned we actually advance our counter by one
+                               }
+
+                       }
+                       goto comma;
+               }
+
                switch (siz)
                {
                case SIZB:
@@ -1252,7 +1474,7 @@ comma:
                        break;
        }
 
-       at_eol();
+       ErrorIfNotAtEOL();
        return 0;
 }
 
@@ -1480,7 +1702,7 @@ int d_comm(void)
                return 0;
 
        sym->svalue = eval;                                     // Install common symbol's size
-       at_eol();
+       ErrorIfNotAtEOL();
        return 0;
 }
 
@@ -1612,7 +1834,7 @@ int d_56001(void)
        rgpu = rdsp = robjproc = 0;
        SaveSection();
 
-       if (obj_format == LOD || obj_format == P56)
+       if ((obj_format == LOD) || (obj_format == P56))
                SwitchSection(M56001P);
 
        return 0;
index 18395fc72f89a95353ef3432f8dd1de26cc6e95c..7b61d63cddddc5a9d2fbf999f1472bdb574a2c8a 100644 (file)
--- a/dsp56k.h
+++ b/dsp56k.h
@@ -6,7 +6,8 @@
 // Source utilised with the kind permission of Landon Dyer
 //
 
-#pragma once
+#ifndef __DSP56K_H__
+#define __DSP56K_H__
 
 #include "rmac.h"
 #include "sect.h"
@@ -36,7 +37,8 @@ extern DSP_ORG dsp_orgmap[1024];              // Mark all 56001 org changes
 extern DSP_ORG * dsp_currentorg;
 extern int dsp_written_data_in_current_org;
 
-#define dprintf(...) p_buf += sprintf(p_buf, __VA_ARGS__)
+#define D_printf(...) chptr += sprintf(chptr, __VA_ARGS__)
 
 // Exported functions
 
+#endif // __DSP56K_H__
index 6c8bc2597348cc32bc59ddfdc459bc34dafd5721..f5f6766fbe854b7a3909613469b1bea20c8e68dc 100644 (file)
@@ -76,73 +76,73 @@ static inline LONG checkea(const uint32_t termchar, const int strings);
 #define P_ERRORS 3
 
 const char *ea_errors[][12] = {
-    // X:
-    {
-        "unrecognised X: parallel move syntax: expected '(' after 'X:-'",                                       // 0
-        "unrecognised X: parallel move syntax: expected ')' after 'X:-(Rn'",                                    // 1
-        "unrecognised X: parallel move syntax: expected R0-R7 after 'X:-('",                                    // 2
-        "unrecognised X: parallel move syntax: expected N0-N7 after 'X:(Rn+'",                                  // 3
-        "unrecognised X: parallel move syntax: expected same register number in Rn and Nn for 'X:(Rn+Nn)'",     // 4
-        "unrecognised X: parallel move syntax: expected ')' after 'X:(Rn+Nn'",                                  // 5
-        "unrecognised X: parallel move syntax: expected same register number in Rn and Nn for 'X:(Rn)+Nn'",     // 6
-        "unrecognised X: parallel move syntax: expected N0-N7 after 'X:(Rn)+'",                                 // 7
-        "unrecognised X: parallel move syntax: expected same register number in Rn and Nn for 'X:(Rn)-Nn'",     // 8
-        "unrecognised X: parallel move syntax: expected N0-N7 after 'X:(Rn)-'",                                 // 9
-        "unrecognised X: parallel move syntax: expected '+', '-' or ',' after 'X:(Rn)'",                        // 10
-        "unrecognised X: parallel move syntax: expected '+' or ')' after 'X:(Rn'",                              // 11
-    },
-    // Y:
-    {
-        "unrecognised Y: parallel move syntax: expected '(' after 'Y:-'",                                       // 0
-        "unrecognised Y: parallel move syntax: expected ')' after 'Y:-(Rn'",                                    // 1
-        "unrecognised Y: parallel move syntax: expected R0-R7 after 'Y:-('",                                    // 2
-        "unrecognised Y: parallel move syntax: expected N0-N7 after 'Y:(Rn+'",                                  // 3
-        "unrecognised Y: parallel move syntax: expected same register number in Rn and Nn for 'Y:(Rn+Nn)'",     // 4
-        "unrecognised Y: parallel move syntax: expected ')' after 'Y:(Rn+Nn'",                                  // 5
-        "unrecognised Y: parallel move syntax: expected same register number in Rn and Nn for 'Y:(Rn)+Nn'",     // 6
-        "unrecognised Y: parallel move syntax: expected N0-N7 after 'Y:(Rn)+'",                                 // 7
-        "unrecognised Y: parallel move syntax: expected same register number in Rn and Nn for 'Y:(Rn)-Nn'",     // 8
-        "unrecognised Y: parallel move syntax: expected N0-N7 after 'Y:(Rn)-'",                                 // 9
-        "unrecognised Y: parallel move syntax: expected '+', '-' or ',' after 'Y:(Rn)'",                        // 10
-        "unrecognised Y: parallel move syntax: expected '+' or ')' after 'Y:(Rn'",                              // 11
-    },
-    // L:
-    {
-        "unrecognised L: parallel move syntax: expected '(' after 'L:-'",                                       // 0
-        "unrecognised L: parallel move syntax: expected ')' after 'L:-(Rn'",                                    // 1
-        "unrecognised L: parallel move syntax: expected R0-R7 after 'L:-('",                                    // 2
-        "unrecognised L: parallel move syntax: expected N0-N7 after 'L:(Rn+'",                                  // 3
-        "unrecognised L: parallel move syntax: expected same register number in Rn and Nn for 'L:(Rn+Nn)'",     // 4
-        "unrecognised L: parallel move syntax: expected ')' after 'L:(Rn+Nn'",                                  // 5
-        "unrecognised L: parallel move syntax: expected same register number in Rn and Nn for 'L:(Rn)+Nn'",     // 6
-        "unrecognised L: parallel move syntax: expected N0-N7 after 'L:(Rn)+'",                                 // 7
-        "unrecognised L: parallel move syntax: expected same register number in Rn and Nn for 'L:(Rn)-Nn'",     // 8
-        "unrecognised L: parallel move syntax: expected N0-N7 after 'L:(Rn)-'",                                 // 9
-        "unrecognised L: parallel move syntax: expected '+', '-' or ',' after 'L:(Rn)'",                        // 10
-        "unrecognised L: parallel move syntax: expected '+' or ')' after 'L:(Rn'",                              // 11
-    },
-    // P:
-    {
-        "unrecognised P: effective address syntax: expected '(' after 'P:-'",                                       // 0
-        "unrecognised P: effective address syntax: expected ')' after 'P:-(Rn'",                                    // 1
-        "unrecognised P: effective address syntax: expected R0-R7 after 'P:-('",                                    // 2
-        "unrecognised P: effective address syntax: expected N0-N7 after 'P:(Rn+'",                                  // 3
-        "unrecognised P: effective address syntax: expected same register number in Rn and Nn for 'P:(Rn+Nn)'",     // 4
-        "unrecognised P: effective address syntax: expected ')' after 'P:(Rn+Nn'",                                  // 5
-        "unrecognised P: effective address syntax: expected same register number in Rn and Nn for 'P:(Rn)+Nn'",     // 6
-        "unrecognised P: effective address syntax: expected N0-N7 after 'P:(Rn)+'",                                 // 7
-        "unrecognised P: effective address syntax: expected same register number in Rn and Nn for 'P:(Rn)-Nn'",     // 8
-        "unrecognised P: effective address syntax: expected N0-N7 after 'P:(Rn)-'",                                 // 9
-        "unrecognised P: effective address syntax: expected '+', '-' or ',' after 'P:(Rn)'",                        // 10
-        "unrecognised P: effective address syntax: expected '+' or ')' after 'P:(Rn'",                              // 11
-    }
+       // X:
+       {
+               "unrecognised X: parallel move syntax: expected '(' after 'X:-'",                                       // 0
+               "unrecognised X: parallel move syntax: expected ')' after 'X:-(Rn'",                                    // 1
+               "unrecognised X: parallel move syntax: expected R0-R7 after 'X:-('",                                    // 2
+               "unrecognised X: parallel move syntax: expected N0-N7 after 'X:(Rn+'",                                  // 3
+               "unrecognised X: parallel move syntax: expected same register number in Rn and Nn for 'X:(Rn+Nn)'",     // 4
+               "unrecognised X: parallel move syntax: expected ')' after 'X:(Rn+Nn'",                                  // 5
+               "unrecognised X: parallel move syntax: expected same register number in Rn and Nn for 'X:(Rn)+Nn'",     // 6
+               "unrecognised X: parallel move syntax: expected N0-N7 after 'X:(Rn)+'",                                 // 7
+               "unrecognised X: parallel move syntax: expected same register number in Rn and Nn for 'X:(Rn)-Nn'",     // 8
+               "unrecognised X: parallel move syntax: expected N0-N7 after 'X:(Rn)-'",                                 // 9
+               "unrecognised X: parallel move syntax: expected '+', '-' or ',' after 'X:(Rn)'",                        // 10
+               "unrecognised X: parallel move syntax: expected '+' or ')' after 'X:(Rn'",                              // 11
+       },
+       // Y:
+       {
+               "unrecognised Y: parallel move syntax: expected '(' after 'Y:-'",                                       // 0
+               "unrecognised Y: parallel move syntax: expected ')' after 'Y:-(Rn'",                                    // 1
+               "unrecognised Y: parallel move syntax: expected R0-R7 after 'Y:-('",                                    // 2
+               "unrecognised Y: parallel move syntax: expected N0-N7 after 'Y:(Rn+'",                                  // 3
+               "unrecognised Y: parallel move syntax: expected same register number in Rn and Nn for 'Y:(Rn+Nn)'",     // 4
+               "unrecognised Y: parallel move syntax: expected ')' after 'Y:(Rn+Nn'",                                  // 5
+               "unrecognised Y: parallel move syntax: expected same register number in Rn and Nn for 'Y:(Rn)+Nn'",     // 6
+               "unrecognised Y: parallel move syntax: expected N0-N7 after 'Y:(Rn)+'",                                 // 7
+               "unrecognised Y: parallel move syntax: expected same register number in Rn and Nn for 'Y:(Rn)-Nn'",     // 8
+               "unrecognised Y: parallel move syntax: expected N0-N7 after 'Y:(Rn)-'",                                 // 9
+               "unrecognised Y: parallel move syntax: expected '+', '-' or ',' after 'Y:(Rn)'",                        // 10
+               "unrecognised Y: parallel move syntax: expected '+' or ')' after 'Y:(Rn'",                              // 11
+       },
+       // L:
+       {
+               "unrecognised L: parallel move syntax: expected '(' after 'L:-'",                                       // 0
+               "unrecognised L: parallel move syntax: expected ')' after 'L:-(Rn'",                                    // 1
+               "unrecognised L: parallel move syntax: expected R0-R7 after 'L:-('",                                    // 2
+               "unrecognised L: parallel move syntax: expected N0-N7 after 'L:(Rn+'",                                  // 3
+               "unrecognised L: parallel move syntax: expected same register number in Rn and Nn for 'L:(Rn+Nn)'",     // 4
+               "unrecognised L: parallel move syntax: expected ')' after 'L:(Rn+Nn'",                                  // 5
+               "unrecognised L: parallel move syntax: expected same register number in Rn and Nn for 'L:(Rn)+Nn'",     // 6
+               "unrecognised L: parallel move syntax: expected N0-N7 after 'L:(Rn)+'",                                 // 7
+               "unrecognised L: parallel move syntax: expected same register number in Rn and Nn for 'L:(Rn)-Nn'",     // 8
+               "unrecognised L: parallel move syntax: expected N0-N7 after 'L:(Rn)-'",                                 // 9
+               "unrecognised L: parallel move syntax: expected '+', '-' or ',' after 'L:(Rn)'",                        // 10
+               "unrecognised L: parallel move syntax: expected '+' or ')' after 'L:(Rn'",                              // 11
+       },
+       // P:
+       {
+               "unrecognised P: effective address syntax: expected '(' after 'P:-'",                                       // 0
+               "unrecognised P: effective address syntax: expected ')' after 'P:-(Rn'",                                    // 1
+               "unrecognised P: effective address syntax: expected R0-R7 after 'P:-('",                                    // 2
+               "unrecognised P: effective address syntax: expected N0-N7 after 'P:(Rn+'",                                  // 3
+               "unrecognised P: effective address syntax: expected same register number in Rn and Nn for 'P:(Rn+Nn)'",     // 4
+               "unrecognised P: effective address syntax: expected ')' after 'P:(Rn+Nn'",                                  // 5
+               "unrecognised P: effective address syntax: expected same register number in Rn and Nn for 'P:(Rn)+Nn'",     // 6
+               "unrecognised P: effective address syntax: expected N0-N7 after 'P:(Rn)+'",                                 // 7
+               "unrecognised P: effective address syntax: expected same register number in Rn and Nn for 'P:(Rn)-Nn'",     // 8
+               "unrecognised P: effective address syntax: expected N0-N7 after 'P:(Rn)-'",                                 // 9
+               "unrecognised P: effective address syntax: expected '+', '-' or ',' after 'P:(Rn)'",                        // 10
+               "unrecognised P: effective address syntax: expected '+' or ')' after 'P:(Rn'",                              // 11
+       }
 };
 
 enum
 {
-    NUM_NORMAL = 0,
-    NUM_FORCE_LONG = 1,
-    NUM_FORCE_SHORT = 2
+       NUM_NORMAL = 0,
+       NUM_FORCE_LONG = 1,
+       NUM_FORCE_SHORT = 2
 };
 
 //
@@ -150,106 +150,114 @@ enum
 //
 static inline int dsp_parmode(int *am, int *areg, TOKEN * AnEXPR, uint64_t * AnEXVAL, WORD * AnEXATTR, SYM ** AnESYM, LONG *memspace, LONG *perspace, const int operand)
 {
-    if (*tok == KW_A || *tok == KW_B)
-    {
-        *am = M_ACC56;
-        *areg = *tok++;
-        return OK;
-    }
-    else if (*tok == '#')
-    {
-        tok++;
+       if (*tok == KW_A || *tok == KW_B)
+       {
+               *am = M_ACC56;
+               *areg = *tok++;
+               return OK;
+       }
+       else if (*tok == '#')
+       {
+               tok++;
 
-        if (*tok == '<')
-        {
-            // Immediate Short Addressing Mode Force Operator
-            tok++;
-            if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
-                return ERROR;
-            if (*AnEXVAL > 0xfff && *AnEXVAL<-4096)
-                return error("immediate short addressing mode forced but address is bigger than $fff");
-            if ((int32_t)*AnEXVAL <= 0xff && (int32_t)*AnEXVAL>-0x100)
-            {
-                *am = M_DSPIM8;
-                return OK;
-            }
-            *am = M_DSPIM12;
-            return OK;
-        }
-        else if (*tok == '>')
-        {
-            // Immediate Long Addressing Mode Force Operator
-            tok++;
-            if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
-                return ERROR;
-            if ((int32_t)*AnEXVAL > 0xffffff || (int32_t)*AnEXVAL < -0xffffff)
-                return error("long immediate is bigger than $ffffff");
-            *am = M_DSPIM;
-            return OK;
-        }
+               if (*tok == '<')
+               {
+                       // Immediate Short Addressing Mode Force Operator
+                       tok++;
+                       if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+                               return ERROR;
 
-        if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
-            return ERROR;
+                       if (*AnEXVAL > 0xFFF && *AnEXVAL < -4096)
+                               return error("immediate short addressing mode forced but address is bigger than $FFF");
 
-        if (*AnEXATTR & DEFINED)
-        {
+                       if ((int32_t)*AnEXVAL <= 0xFF && (int32_t)*AnEXVAL > -0x100)
+                       {
+                               *am = M_DSPIM8;
+                               return OK;
+                       }
+
+                       *am = M_DSPIM12;
+                       return OK;
+               }
+               else if (*tok == '>')
+               {
+                       // Immediate Long Addressing Mode Force Operator
+                       tok++;
+
+                       if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+                               return ERROR;
+
+                       if ((int32_t)*AnEXVAL > 0xFFFFFF || (int32_t)*AnEXVAL < -0xFFFFFF)
+                               return error("long immediate is bigger than $FFFFFF");
+
+                       *am = M_DSPIM;
+                       return OK;
+               }
+
+               if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+                       return ERROR;
+
+               if (*AnEXATTR & DEFINED)
+               {
                        if ((int32_t)*AnEXVAL < 0x100 && (int32_t)*AnEXVAL >= -0x100)
                        {
-                               *AnEXVAL &= 0xff;
+                               *AnEXVAL &= 0xFF;
                                *am = M_DSPIM8;
                        }
-            else if (*AnEXVAL < 0x1000)
-                *am = M_DSPIM12;
-            else
-                *am = M_DSPIM;
-        }
-        else
-        {
-            // We have no clue what size our immediate will be
-            // so we have to assume the worst
-            *am = M_DSPIM;
-        }
-        return OK;
-    }
-    else if (*tok >= KW_X0 && *tok <= KW_Y1)
-    {
-        *am = M_ALU24;
-        *areg = *tok++;
-        return OK;
-    }
-    else if (*tok == KW_X && *(tok + 1) == ':')
-    {
-        tok = tok + 2;
-        if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
-        {
-            if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
-                return ERROR;
+                       else if (*AnEXVAL < 0x1000)
+                               *am = M_DSPIM12;
+                       else
+                               *am = M_DSPIM;
+               }
+               else
+               {
+                       // We have no clue what size our immediate will be
+                       // so we have to assume the worst
+                       *am = M_DSPIM;
+               }
+
+               return OK;
+       }
+       else if (*tok >= KW_X0 && *tok <= KW_Y1)
+       {
+               *am = M_ALU24;
+               *areg = *tok++;
+               return OK;
+       }
+       else if (*tok == KW_X && *(tok + 1) == ':')
+       {
+               tok = tok + 2;
+
+               if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
+               {
+                       if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+                               return ERROR;
+
                        if (*AnEXATTR & DEFINED)
                        {
-                               if (*AnEXVAL > 0xffffff)
-                                       return error("long address is bigger than $ffffff");
+                               if (*AnEXVAL > 0xFFFFFF)
+                                       return error("long address is bigger than $FFFFFF");
+
                                *memspace = 0 << 6;     // Mark we're on X memory space
 
-                               // Check if value is between $ffc0 and $ffff, AKA X:pp
-                               {
-                                       uint32_t temp = (LONG)(((int32_t)(((uint32_t)*AnEXVAL) << (32 - 6))) >> (32 - 6));  // Sign extend 6 to 32 bits
-                                       if ((temp >= 0xffffffc0                      /* Check for 32bit sign extended number */
-                                               && ((int32_t)*AnEXVAL<0))                /* Check if 32bit signed number is negative*/
-                                               ||(*AnEXVAL<0xffff && *AnEXVAL>=0x8000)) /* Check if 16bit number is negative*/
-                                       {
-                                               *AnEXVAL = temp;
-                                               *am = M_DSPPP;
-                                               *memspace = 0 << 6;          // Mark we're on X memory space
-                                               *perspace = 0 << 16;         // Mark we're on X peripheral space
-                                               *areg = *AnEXVAL & 0x3f;     // Since this is only going to get used in dsp_ea_imm5...
-                                               return OK;
-                                       }
+                               // Check if value is between $FFC0 and $FFFF, AKA X:pp
+                               uint32_t temp = (LONG)(((int32_t)(((uint32_t)*AnEXVAL) << (32 - 6))) >> (32 - 6));  // Sign extend 6 to 32 bits
 
+                               if ((temp >= 0xFFFFFFC0                      /* Check for 32bit sign extended number */
+                                       && ((int32_t)*AnEXVAL < 0))              /* Check if 32bit signed number is negative*/
+                                       || (*AnEXVAL < 0xFFFF && *AnEXVAL >= 0x8000)) /* Check if 16bit number is negative*/
+                               {
+                                       *AnEXVAL = temp;
+                                       *am = M_DSPPP;
+                                       *memspace = 0 << 6;          // Mark we're on X memory space
+                                       *perspace = 0 << 16;         // Mark we're on X peripheral space
+                                       *areg = *AnEXVAL & 0x3F;     // Since this is only going to get used in dsp_ea_imm5...
+                                       return OK;
                                }
 
                                // If the symbol/expression is defined then check for valid range.
                                // Otherwise the value had better fit or Fixups will bark!
-                               if (*AnEXVAL > 0x3f)
+                               if (*AnEXVAL > 0x3F)
                                {
                                        *am = M_DSPEA;
                                        *areg = DSP_EA_ABS;
@@ -266,33 +274,36 @@ static inline int dsp_parmode(int *am, int *areg, TOKEN * AnEXPR, uint64_t * AnE
                                *am = M_DSPEA;
                                *areg = DSP_EA_ABS;
                        }
-            return OK;
-        }
-        else if (*tok == '<')
-        {
-            // X:aa
-            // Short Addressing Mode Force Operator in the case of '<'
-            tok++;
-            if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
-                return ERROR;
+
+                       return OK;
+               }
+               else if (*tok == '<')
+               {
+                       // X:aa
+                       // Short Addressing Mode Force Operator in the case of '<'
+                       tok++;
+
+                       if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+                               return ERROR;
 
                        // If the symbol/expression is defined then check for valid range.
                        // Otherwise the value had better fit or Fixups will bark!
                        if (*AnEXATTR & DEFINED)
                        {
-                               if (*AnEXVAL > 0x3f)
-                                       return error("short addressing mode forced but address is bigger than $3f");
+                               if (*AnEXVAL > 0x3F)
+                                       return error("short addressing mode forced but address is bigger than $3F");
                        }
-            else
-            {
-                // Mark it as a fixup
-                deposit_extra_ea = DEPOSIT_EXTRA_FIXUP;
-            }
-            *am = M_DSPAA;
-            *memspace = 0 << 6;     // Mark we're on X memory space
-            *areg = (int)*AnEXVAL;     // Since this is only going to get used in dsp_ea_imm5...
-            return OK;
-        }
+                       else
+                       {
+                               // Mark it as a fixup
+                               deposit_extra_ea = DEPOSIT_EXTRA_FIXUP;
+                       }
+
+                       *am = M_DSPAA;
+                       *memspace = 0 << 6;     // Mark we're on X memory space
+                       *areg = (int)*AnEXVAL;     // Since this is only going to get used in dsp_ea_imm5...
+                       return OK;
+               }
                else if (*tok == '>')
                {
                        // Long Addressing Mode Force Operator
@@ -302,12 +313,13 @@ static inline int dsp_parmode(int *am, int *areg, TOKEN * AnEXPR, uint64_t * AnE
                        {
                                if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
                                        return ERROR;
+
                                if (*AnEXATTR&DEFINED)
                                {
-                                       if (*AnEXVAL > 0xffffff)
-                                               return error("long address is bigger than $ffffff");
-                                       *memspace = 0 << 6;     // Mark we're on X memory space
+                                       if (*AnEXVAL > 0xFFFFFF)
+                                               return error("long address is bigger than $FFFFFF");
 
+                                       *memspace = 0 << 6;     // Mark we're on X memory space
                                        *am = M_DSPEA;
                                        *areg = DSP_EA_ABS;
                                }
@@ -321,73 +333,75 @@ static inline int dsp_parmode(int *am, int *areg, TOKEN * AnEXPR, uint64_t * AnE
                                return OK;
                        }
                }
-        else if (*tok == SHL)  // '<<'
-        {
-            // I/O Short Addressing Mode Force Operator
-            // X:pp
-            tok++;
-            if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
-                return ERROR;
+               else if (*tok == SHL)  // '<<'
+               {
+                       // I/O Short Addressing Mode Force Operator
+                       // X:pp
+                       tok++;
+
+                       if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+                               return ERROR;
 
                        // If the symbol/expression is defined then check for valid range.
                        // Otherwise the value had better fit or Fixups will bark!
                        if (*AnEXATTR & DEFINED)
                        {
                                *AnEXVAL = (LONG)(((int32_t)(((uint32_t)*AnEXVAL) << (32 - 6))) >> (32 - 6));  // Sign extend 6 to 32 bits
-                               if (*AnEXVAL < 0xffffffc0)
-                                       return error("I/O Short Addressing Mode addresses must be between $ffc0 and $ffff");
+
+                               if (*AnEXVAL < 0xFFFFFFC0)
+                                       return error("I/O Short Addressing Mode addresses must be between $FFC0 and $FFFF");
                        }
-            *am = M_DSPPP;
-            *memspace = 0 << 6;          // Mark we're on X memory space
-            *perspace = 0 << 16;         // Mark we're on X peripheral space
-            *areg = *AnEXVAL & 0x3f;     // Since this is only going to get used in dsp_ea_imm5...
-            return OK;
-        }
 
-        if ((*areg = checkea(0, X_ERRORS)) != ERROR)
-        {
-            // TODO: what if we need M_DSPAA here????
-            *memspace = 0 << 6;     // Mark we're on X memory space
-            *am = M_DSPEA;
-            return OK;
-        }
-        else
-            return ERROR;
+                       *am = M_DSPPP;
+                       *memspace = 0 << 6;          // Mark we're on X memory space
+                       *perspace = 0 << 16;         // Mark we're on X peripheral space
+                       *areg = *AnEXVAL & 0x3f;     // Since this is only going to get used in dsp_ea_imm5...
+                       return OK;
+               }
 
-    }
-    else if (*tok == KW_Y && *(tok + 1) == ':')
-    {
-        tok = tok + 2;
+               if ((*areg = checkea(0, X_ERRORS)) != ERROR)
+               {
+                       // TODO: what if we need M_DSPAA here????
+                       *memspace = 0 << 6;     // Mark we're on X memory space
+                       *am = M_DSPEA;
+                       return OK;
+               }
+               else
+                       return ERROR;
+       }
+       else if (*tok == KW_Y && *(tok + 1) == ':')
+       {
+               tok = tok + 2;
 
-        if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
-        {
-            if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
-                return ERROR;
-            if (*AnEXVAL > 0xffffff)
-                return error("long address is bigger than $ffffff");
-            *memspace = 1 << 6;     // Mark we're on Y memory space
+               if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
+               {
+                       if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+                               return ERROR;
+
+                       if (*AnEXVAL > 0xFFFFFF)
+                               return error("long address is bigger than $FFFFFF");
+
+                       *memspace = 1 << 6;     // Mark we're on Y memory space
 
                        // Check if value is between $ffc0 and $ffff, AKA Y:pp
-                       {
-                               uint32_t temp = (LONG)(((int32_t)(((uint32_t)*AnEXVAL) << (32 - 6))) >> (32 - 6));  // Sign extend 6 to 32 bits
-                               if ((temp >= 0xffffffc0                         /* Check for 32bit sign extended number */
-                                       && ((int32_t)*AnEXVAL<0))                   /* Check if 32bit signed number is negative*/
-                                       || (*AnEXVAL<0xffff && *AnEXVAL >= 0x8000)) /* Check if 16bit number is negative*/
-                               {
-                                       *AnEXVAL = temp;
-                                       *am = M_DSPPP;
-                                       *perspace = 1 << 16;         // Mark we're on X peripheral space
-                                       *areg = *AnEXVAL & 0x3f;     // Since this is only going to get used in dsp_ea_imm5...
-                                       return OK;
-                               }
+                       uint32_t temp = (LONG)(((int32_t)(((uint32_t)*AnEXVAL) << (32 - 6))) >> (32 - 6));  // Sign extend 6 to 32 bits
 
+                       if ((temp >= 0xFFFFFFC0                         /* Check for 32bit sign extended number */
+                               && ((int32_t)*AnEXVAL < 0))                 /* Check if 32bit signed number is negative*/
+                               || (*AnEXVAL < 0xFFFF && *AnEXVAL >= 0x8000)) /* Check if 16bit number is negative*/
+                       {
+                               *AnEXVAL = temp;
+                               *am = M_DSPPP;
+                               *perspace = 1 << 16;         // Mark we're on X peripheral space
+                               *areg = *AnEXVAL & 0x3F;     // Since this is only going to get used in dsp_ea_imm5...
+                               return OK;
                        }
 
                        // If the symbol/expression is defined then check for valid range.
                        // Otherwise the value had better fit or Fixups will bark!
                        if (*AnEXATTR & DEFINED)
                        {
-                               if (*AnEXVAL > 0x3f)
+                               if (*AnEXVAL > 0x3F)
                                {
                                        *am = M_DSPEA;
                                        *areg = DSP_EA_ABS;
@@ -403,53 +417,56 @@ static inline int dsp_parmode(int *am, int *areg, TOKEN * AnEXPR, uint64_t * AnE
                                *areg = DSP_EA_ABS;
                        }
 
-            return OK;
-        }
-        else if (*tok == '<')
-        {
-            // Y:aa
-            // Short Addressing Mode Force Operator in the case of '<'
-            tok++;
-            if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
-                return ERROR;
+                       return OK;
+               }
+               else if (*tok == '<')
+               {
+                       // Y:aa
+                       // Short Addressing Mode Force Operator in the case of '<'
+                       tok++;
+
+                       if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+                               return ERROR;
 
                        // If the symbol/expression is defined then check for valid range.
                        // Otherwise the value had better fit or Fixups will bark!
                        if (*AnEXATTR & DEFINED)
                        {
-                               if (*AnEXVAL > 0x3f)
+                               if (*AnEXVAL > 0x3F)
                                {
-                                       warn("short addressing mode forced but address is bigger than $3f - switching to long");
+                                       warn("short addressing mode forced but address is bigger than $3F - switching to long");
                                        *am = M_DSPEA;
                                        *memspace = 1 << 6;     // Mark we're on Y memory space
                                        *areg = DSP_EA_ABS;
                                        return OK;
                                }
                        }
-            else
-            {
-                // Mark it as a fixup
-                deposit_extra_ea = DEPOSIT_EXTRA_FIXUP;
-            }
+                       else
+                       {
+                               // Mark it as a fixup
+                               deposit_extra_ea = DEPOSIT_EXTRA_FIXUP;
+                       }
 
-            *am = M_DSPAA;
-            *memspace = 1 << 6;     // Mark we're on Y memory space
-            *areg = (int)*AnEXVAL;      // Since this is only going to get used in dsp_ea_imm5...
-            return OK;
-        }
-        else if (*tok == '>')
-        {
-            // Long Addressing Mode Force Operator
+                       *am = M_DSPAA;
+                       *memspace = 1 << 6;     // Mark we're on Y memory space
+                       *areg = (int)*AnEXVAL;      // Since this is only going to get used in dsp_ea_imm5...
+                       return OK;
+               }
+               else if (*tok == '>')
+               {
+                       // Long Addressing Mode Force Operator
                        tok++;
 
                        if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
                        {
                                if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
                                        return ERROR;
+
                                if (*AnEXATTR&DEFINED)
                                {
-                                       if (*AnEXVAL > 0xffffff)
-                                               return error("long address is bigger than $ffffff");
+                                       if (*AnEXVAL > 0xFFFFFF)
+                                               return error("long address is bigger than $FFFFFF");
+
                                        *memspace = 1 << 6;     // Mark we're on Y memory space
 
                                        *am = M_DSPEA;
@@ -465,364 +482,389 @@ static inline int dsp_parmode(int *am, int *areg, TOKEN * AnEXPR, uint64_t * AnE
                                return OK;
                        }
                }
-        else if (*tok == SHL)  // '<<'
-        {
-            // I/O Short Addressing Mode Force Operator
-            // Y:pp
-            tok++;
-            if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
-                return ERROR;
+               else if (*tok == SHL)  // '<<'
+               {
+                       // I/O Short Addressing Mode Force Operator
+                       // Y:pp
+                       tok++;
+
+                       if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+                               return ERROR;
 
                        // If the symbol/expression is defined then check for valid range.
                        // Otherwise the value had better fit or Fixups will bark!
                        if (*AnEXATTR & DEFINED)
                        {
                                *AnEXVAL = (LONG)(((int32_t)(((uint32_t)*AnEXVAL) << (32 - 6))) >> (32 - 6));  // Sign extend 6 to 32 bits
-                               if (*AnEXVAL < 0xffffffc0)
-                                       return error("I/O Short Addressing Mode addresses must be between $ffe0 and $1f");
+
+                               if (*AnEXVAL < 0xFFFFFFC0)
+                                       return error("I/O Short Addressing Mode addresses must be between $FFE0 and $1F");
                        }
-               *am = M_DSPPP;
-            *memspace = 1 << 6;          // Mark we're on Y memory space
-            *perspace = 1 << 16;         // Mark we're on Y peripheral space
-            *areg = *AnEXVAL & 0x3f;     // Since this is only going to get used in dsp_ea_imm5...
-            return OK;
-        }
 
-        if ((*areg = checkea(0, X_ERRORS)) != ERROR)
-        {
-            *memspace = 1 << 6;     // Mark we're on Y memory space
-            *am = M_DSPEA;
-            return OK;
-        }
-        else
-            return ERROR;
-        // TODO: add absolute address checks
+                       *am = M_DSPPP;
+                       *memspace = 1 << 6;          // Mark we're on Y memory space
+                       *perspace = 1 << 16;         // Mark we're on Y peripheral space
+                       *areg = *AnEXVAL & 0x3F;     // Since this is only going to get used in dsp_ea_imm5...
+                       return OK;
+               }
 
-    }
-    else if (*tok >= KW_X&&*tok <= KW_Y)
-    {
-        *am = M_INP48;
-        *areg = *tok++;
-        return OK;
-    }
-    else if (*tok >= KW_M0 && *tok <= KW_M7)
-    {
-        *am = M_DSPM;
-        *areg = (*tok++) & 7;
-        return OK;
-    }
-    else if (*tok >= KW_R0 && *tok <= KW_R7)
-    {
-        *am = M_DSPR;
-        *areg = (*tok++) - KW_R0;
-        return OK;
-    }
-    else if (*tok >= KW_N0 && *tok <= KW_N7)
-    {
-        *am = M_DSPN;
-        *areg = (*tok++) & 7;
-        return OK;
-    }
-    else if (*tok == KW_A0 || *tok == KW_A1 || *tok == KW_B0 || *tok == KW_B1)
-    {
-        *am = M_ACC24;
-        *areg = *tok++;
-        return OK;
-    }
-    else if (*tok == KW_A2 || *tok == KW_B2)
-    {
-        *am = M_ACC8;
-        *areg = *tok++;
-        return OK;
-    }
-    else if (*tok == '-' && (*(tok + 1) == KW_X0 || *(tok + 1) == KW_X1 || *(tok + 1) == KW_Y0 || *(tok + 1) == KW_Y1))
-    {
-        // '-X0', '-Y0', '-X1' or '-Y1', used in multiplications
-        tok++;
+               if ((*areg = checkea(0, X_ERRORS)) != ERROR)
+               {
+                       *memspace = 1 << 6;     // Mark we're on Y memory space
+                       *am = M_DSPEA;
+                       return OK;
+               }
+               else
+                       return ERROR;
+               // TODO: add absolute address checks
+       }
+       else if ((*tok >= KW_X) && (*tok <= KW_Y))
+       {
+               *am = M_INP48;
+               *areg = *tok++;
+               return OK;
+       }
+       else if ((*tok >= KW_M0) && (*tok <= KW_M7))
+       {
+               *am = M_DSPM;
+               *areg = (*tok++) & 7;
+               return OK;
+       }
+       else if ((*tok >= KW_R0) && (*tok <= KW_R7))
+       {
+               *am = M_DSPR;
+               *areg = (*tok++) - KW_R0;
+               return OK;
+       }
+       else if ((*tok >= KW_N0) && (*tok <= KW_N7))
+       {
+               *am = M_DSPN;
+               *areg = (*tok++) & 7;
+               return OK;
+       }
+       else if ((*tok == KW_A0) || (*tok == KW_A1) || (*tok == KW_B0)
+               || (*tok == KW_B1))
+       {
+               *am = M_ACC24;
+               *areg = *tok++;
+               return OK;
+       }
+       else if ((*tok == KW_A2) || (*tok == KW_B2))
+       {
+               *am = M_ACC8;
+               *areg = *tok++;
+               return OK;
+       }
+       else if ((*tok == '-') && (*(tok + 1) == KW_X0 || *(tok + 1) == KW_X1 || *(tok + 1) == KW_Y0 || *(tok + 1) == KW_Y1))
+       {
+               // '-X0', '-Y0', '-X1' or '-Y1', used in multiplications
+               tok++;
 
-        // Check to see if this is the first operand
-        if (operand != 0)
-            return error("-x0/-x1/-y0/-y1 only allowed in the first operand");
+               // Check to see if this is the first operand
+               if (operand != 0)
+                       return error("-x0/-x1/-y0/-y1 only allowed in the first operand");
+
+               *am = M_ALU24;
+               *areg = *tok++;
+               dsp_k = 1 << 2;
+               return OK;
+       }
+       else if (*tok == '+' && (*(tok + 1) == KW_X0 || *(tok + 1) == KW_X1 || *(tok + 1) == KW_Y0 || *(tok + 1) == KW_Y1))
+       {
+               // '+X0', '+Y0', '+X1' or '+Y1', used in multiplications
+               tok++;
 
-        *am = M_ALU24;
-        *areg = *tok++;
-        dsp_k = 1 << 2;
-        return OK;
-    }
-    else if (*tok == '+' && (*(tok + 1) == KW_X0 || *(tok + 1) == KW_X1 || *(tok + 1) == KW_Y0 || *(tok + 1) == KW_Y1))
-    {
-        // '+X0', '+Y0', '+X1' or '+Y1', used in multiplications
-        tok++;
+               // Check to see if this is the first operand
+               if (operand != 0)
+                       return error("+x0/+x1/+y0/+y1 only allowed in the first operand");
+
+               *am = M_ALU24;
+               *areg = *tok++;
+               dsp_k = 0 << 2;
+               return OK;
+       }
+       else if (*tok == '(' || *tok == '-')
+       {
+               // Could be either an expression or ea mode
+               if (*tok + 1 == SYMBOL)
+               {
+                       tok++;
 
-        // Check to see if this is the first operand
-        if (operand != 0)
-            return error("+x0/+x1/+y0/+y1 only allowed in the first operand");
+                       if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+                               return ERROR;
 
-        *am = M_ALU24;
-        *areg = *tok++;
-        dsp_k = 0 << 2;
-        return OK;
-    }
-    else if (*tok == '(' || *tok == '-')
-    {
-        // Could be either an expression or ea mode
-        if (*tok + 1 == SYMBOL)
-        {
-            tok++;
+                       *am = M_DSPIM;
+                       return OK;
+               }
 
-            if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
-                return ERROR;
+               if ((*areg = checkea(0, P_ERRORS)) != ERROR)
+               {
+                       *am = M_DSPEA;
+                       return OK;
+               }
+               else
+                       return ERROR;
+
+               // TODO: add absolute address checks
+               return error("internal assembler error: parmode checking for '(' and '-' does not have absolute address checks yet!");
+       }
+       else if (*tok == KW_P && *(tok + 1) == ':')
+       {
+               tok = tok + 2;
 
-            *am = M_DSPIM;
-            return OK;
-        }
-        if ((*areg = checkea(0, P_ERRORS)) != ERROR)
-        {
-            *am = M_DSPEA;
-            return OK;
-        }
-        else
-            return ERROR;
-        // TODO: add absolute address checks
-        return error("internal assembler error: parmode checking for '(' and '-' does not have absolute address checks yet!");
-    }
-    else if (*tok == KW_P && *(tok + 1) == ':')
-    {
-        tok = tok + 2;
                if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
-        {
-            // Address
-            if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
-                return ERROR;
-            if (*AnEXVAL > 0xffffff)
-                return error("long address is bigger than $ffffff");
-            if (*AnEXVAL > 0x3f)
-            {
-                *am = M_DSPEA;
-                *areg = DSP_EA_ABS;
-            }
-            else
-            {
-                *areg = (int)*AnEXVAL;     // Lame, but what the hell
-                *am = M_DSPAA;
-            }
-            return OK;
-        }
-        else if (*tok == '<')
-        {
-            // X:aa
-            // Short Addressing Mode Force Operator in the case of '<'
-            tok++;
-            if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
-                return ERROR;
-            if (*AnEXVAL > 0x3f)
-                return error("short addressing mode forced but address is bigger than $3f");
-            *am = M_DSPAA;
-            *areg = (int)*AnEXVAL;     // Since this is only going to get used in dsp_ea_imm5...
-            return OK;
-        }
-        else if (*tok == '>')
-        {
-            // Long Addressing Mode Force Operator
-            tok++;
-            // Immediate Short Addressing Mode Force Operator
-            if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
-                return ERROR;
-            if (*AnEXATTR & DEFINED)
-            {
-                if (*AnEXVAL > 0xffffff)
-                    return error("long address is bigger than $ffffff");
-            }
-            *am = M_DSPEA;
-            *areg = DSP_EA_ABS;
-            return OK;
-        }
+               {
+                       // Address
+                       if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+                               return ERROR;
 
-        if ((*areg = checkea(0, P_ERRORS)) != ERROR)
-        {
-            *am = M_DSPEA;
-            return OK;
-        }
-        else
-            return ERROR;
+                       if (*AnEXVAL > 0xFFFFFF)
+                               return error("long address is bigger than $FFFFFF");
 
-    }
-    else if (*tok == SHL)
-    {
-        // I/O Short Addressing Mode Force Operator
-        tok++;
-        if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
-            return ERROR;
-        if (*AnEXVAL > 0xfff)
-            return error("I/O short addressing mode forced but address is bigger than $fff");
-        *am = M_DSPABS06;
-        return OK;
-    }
-    else if (*tok == '<')
-    {
-        // Short Addressing Mode Force Operator
-        tok++;
-        if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
-            return ERROR;
-        if (*AnEXATTR & DEFINED)
-        {
-            if (*AnEXVAL > 0xfff)
-                return error("short addressing mode forced but address is bigger than $fff");
-        }
-        *am = M_DSPABS12;
-        return OK;
-    }
-    else if (*tok == '>')
-    {
-        // Long Addressing Mode Force Operator
-        tok++;
-        // Immediate Short Addressing Mode Force Operator
-        if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
-            return ERROR;
-        if (*AnEXATTR & DEFINED)
-        {
-            if (*AnEXVAL > 0xffffff)
-                return error("long address is bigger than $ffffff");
-        }
-        *am = M_DSPEA;
-        *areg = DSP_EA_ABS;
-        return OK;
-    }
+                       if (*AnEXVAL > 0x3F)
+                       {
+                               *am = M_DSPEA;
+                               *areg = DSP_EA_ABS;
+                       }
+                       else
+                       {
+                               *areg = (int)*AnEXVAL;     // Lame, but what the hell
+                               *am = M_DSPAA;
+                       }
 
-    else if (*tok == KW_PC || *tok == KW_CCR || *tok == KW_SR || *tok == KW_SP || (*tok >= KW_MR&&*tok <= KW_SS))
-    {
-        *areg = *tok++;
-        *am = M_DSPPCU;
-        return OK;
-    }
-    // expr
-    else
-    {
-        if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
-            return ERROR;
+                       return OK;
+               }
+               else if (*tok == '<')
+               {
+                       // X:aa
+                       // Short Addressing Mode Force Operator in the case of '<'
+                       tok++;
 
-        // We'll store M_DSPEA_ABS in areg and if we have
-        // any extra info, it'll go in am
-        if (*AnEXATTR & DEFINED)
-        {
-            *areg = DSP_EA_ABS;
-            if (*AnEXVAL < 0x1000)
-                *am = M_DSPABS12;
-            else if (*AnEXVAL < 0x10000)
-                *am = M_DSPABS16;
-            else if (*AnEXVAL < 0x1000000)
-                *am = M_DSPABS24;
-            else
-                return error("address must be smaller than $1000000");
-            return OK;
-        }
-        else
-        {
-            // Well, we have no opinion on the expression's size, so let's assume the worst
-            *areg = DSP_EA_ABS;
-            *am = M_DSPABS24;
-            return OK;
-        }
-    }
-    return error("internal assembler error: Please report this error message: 'reached the end of dsp_parmode' with the line of code that caused it. Thanks, and sorry for the inconvenience");   // Something bad happened
-}
+                       if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+                               return ERROR;
 
-//
-// Parse all addressing modes except parallel moves
-//
-int dsp_amode(int maxea)
-{
-    LONG dummy;
-    // Initialize global return values
-    nmodes = dsp_a0reg = dsp_a1reg = 0;
-    dsp_am0 = dsp_am1 = M_AM_NONE;
-    dsp_a0expr[0] = dsp_a1expr[0] = ENDEXPR;
-    dsp_a0exval = 0;
-    dsp_a1exval = 0;
-    dsp_a0exattr = dsp_a1exattr = 0;
-    dsp_a0esym = dsp_a1esym = (SYM *)NULL;
-    dsp_a0memspace = dsp_a1memspace = -1;
-    dsp_a0perspace = dsp_a1perspace = -1;
-    dsp_k = 0;
-
-    // If at EOL, then no addr modes at all
-    if (*tok == EOL)
-        return 0;
-
-    if (dsp_parmode(&dsp_am0, &dsp_a0reg, dsp_a0expr, &dsp_a0exval, &dsp_a0exattr, &dsp_a0esym, &dsp_a0memspace, &dsp_a0perspace, 0) == ERROR)
-        return ERROR;
-
-
-    // If caller wants only one mode, return just one (ignore comma);
-    // If there is no second addressing mode (no comma), then return just one anyway.
-    nmodes = 1;
-
-    if (*tok != ',')
-    {
-        if (dsp_k != 0)
-            return error("-x0/-x1/-y0/-y1 only allowed in multiply operations");
+                       if (*AnEXVAL > 0x3F)
+                               return error("short addressing mode forced but address is bigger than $3F");
 
-        return 1;
-    }
+                       *am = M_DSPAA;
+                       *areg = (int)*AnEXVAL;     // Since this is only going to get used in dsp_ea_imm5...
+                       return OK;
+               }
+               else if (*tok == '>')
+               {
+                       // Long Addressing Mode Force Operator
+                       tok++;
 
-    // Eat the comma
-    tok++;
+                       // Immediate Short Addressing Mode Force Operator
+                       if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+                               return ERROR;
 
-    // Parse second addressing mode
-    if (dsp_parmode(&dsp_am1, &dsp_a1reg, dsp_a1expr, &dsp_a1exval, &dsp_a1exattr, &dsp_a1esym, &dsp_a1memspace, &dsp_a1perspace, 1) == ERROR)
-        return ERROR;
+                       if (*AnEXATTR & DEFINED)
+                       {
+                               if (*AnEXVAL > 0xFFFFFF)
+                                       return error("long address is bigger than $FFFFFF");
+                       }
 
-    if (maxea == 2 || *tok == EOL)
-    {
-        if (dsp_k != 0)
-            return error("-x0/-x1/-y0/-y1 only allowed in multiply operations");
+                       *am = M_DSPEA;
+                       *areg = DSP_EA_ABS;
+                       return OK;
+               }
 
-        nmodes = 2;
-        return 2;
-    }
+               if ((*areg = checkea(0, P_ERRORS)) != ERROR)
+               {
+                       *am = M_DSPEA;
+                       return OK;
+               }
+               else
+                       return ERROR;
+       }
+       else if (*tok == SHL)
+       {
+               // I/O Short Addressing Mode Force Operator
+               tok++;
 
-    if (*tok == ',')
-    {
-        // Only MAC-like or jsset/clr/tst/chg instructions here
-        tok++;
-        if (dsp_parmode(&dsp_am2, &dsp_a2reg, dsp_a2expr, &dsp_a2exval, &dsp_a2exattr, &dsp_a2esym, &dummy, &dummy, 2) == ERROR)
-            return ERROR;
-        if (maxea == 3)
-            return 3;
-        if (*tok != EOL)
-            return error(extra_stuff);
-        nmodes = 3;
-        return 3;
+               if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+                       return ERROR;
 
-    }
+               if (*AnEXVAL > 0xFFF)
+                       return error("I/O short addressing mode forced but address is bigger than $FFF");
 
-    // Only Tcc instructions here, and then only those that accept 4 operands
+               *am = M_DSPABS06;
+               return OK;
+       }
+       else if (*tok == '<')
+       {
+               // Short Addressing Mode Force Operator
+               tok++;
 
-    if (dsp_parmode(&dsp_am2, &dsp_a2reg, dsp_a2expr, &dsp_a2exval, &dsp_a2exattr, &dsp_a2esym, &dummy, &dummy, 2) == ERROR)
-        return ERROR;
+               if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+                       return ERROR;
 
-    if (*tok++ != ',')
-        return error("expected 4 parameters");
+               if (*AnEXATTR & DEFINED)
+               {
+                       if (*AnEXVAL > 0xFFF)
+                               return error("short addressing mode forced but address is bigger than $FFF");
+               }
 
-    if (dsp_parmode(&dsp_am3, &dsp_a3reg, dsp_a3expr, &dsp_a3exval, &dsp_a3exattr, &dsp_a3esym, &dummy, &dummy, 3) == ERROR)
-        return ERROR;
+               *am = M_DSPABS12;
+               return OK;
+       }
+       else if (*tok == '>')
+       {
+               // Long Addressing Mode Force Operator
+               tok++;
 
-    if (*tok == EOL)
-    {
-        if (dsp_k != 0)
-            return error("-x0/-x1/-y0/-y1 only allowed in multiply operations");
+               // Immediate Short Addressing Mode Force Operator
+               if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+                       return ERROR;
 
-        nmodes = 4;
-        return 4;
-    }
-    else
-    {
-        // Tcc instructions do not support parallel moves, so any remaining tokens are garbage
-        return error(extra_stuff);
-    }
+               if (*AnEXATTR & DEFINED)
+               {
+                       if (*AnEXVAL > 0xFFFFFF)
+                               return error("long address is bigger than $FFFFFF");
+               }
+
+               *am = M_DSPEA;
+               *areg = DSP_EA_ABS;
+               return OK;
+       }
+       else if (*tok == KW_PC || *tok == KW_CCR || *tok == KW_SR || *tok == KW_SP || (*tok >= KW_MR&&*tok <= KW_SS))
+       {
+               *areg = *tok++;
+               *am = M_DSPPCU;
+               return OK;
+       }
+       // expr
+       else
+       {
+               if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+                       return ERROR;
+
+               // We'll store M_DSPEA_ABS in areg and if we have
+               // any extra info, it'll go in am
+               if (*AnEXATTR & DEFINED)
+               {
+                       *areg = DSP_EA_ABS;
+
+                       if (*AnEXVAL < 0x1000)
+                               *am = M_DSPABS12;
+                       else if (*AnEXVAL < 0x10000)
+                               *am = M_DSPABS16;
+                       else if (*AnEXVAL < 0x1000000)
+                               *am = M_DSPABS24;
+                       else
+                               return error("address must be smaller than $1000000");
+
+                       return OK;
+               }
+               else
+               {
+                       // Well, we have no opinion on the expression's size, so let's assume the worst
+                       *areg = DSP_EA_ABS;
+                       *am = M_DSPABS24;
+                       return OK;
+               }
+       }
+
+       return error("internal assembler error: Please report this error message: 'reached the end of dsp_parmode' with the line of code that caused it. Thanks, and sorry for the inconvenience");   // Something bad happened
+}
 
-    return error("internal assembler error: Please report this error message: 'reached the end of dsp_amode' with the line of code that caused it. Thanks, and sorry for the inconvenience");   //Something bad happened
 
+//
+// Parse all addressing modes except parallel moves
+//
+int dsp_amode(int maxea)
+{
+       LONG dummy;
+       // Initialize global return values
+       nmodes = dsp_a0reg = dsp_a1reg = 0;
+       dsp_am0 = dsp_am1 = M_AM_NONE;
+       dsp_a0expr[0] = dsp_a1expr[0] = ENDEXPR;
+       dsp_a0exval = 0;
+       dsp_a1exval = 0;
+       dsp_a0exattr = dsp_a1exattr = 0;
+       dsp_a0esym = dsp_a1esym = (SYM *)NULL;
+       dsp_a0memspace = dsp_a1memspace = -1;
+       dsp_a0perspace = dsp_a1perspace = -1;
+       dsp_k = 0;
+
+       // If at EOL, then no addr modes at all
+       if (*tok == EOL)
+               return 0;
+
+       if (dsp_parmode(&dsp_am0, &dsp_a0reg, dsp_a0expr, &dsp_a0exval, &dsp_a0exattr, &dsp_a0esym, &dsp_a0memspace, &dsp_a0perspace, 0) == ERROR)
+               return ERROR;
+
+
+       // If caller wants only one mode, return just one (ignore comma);
+       // If there is no second addressing mode (no comma), then return just one anyway.
+       nmodes = 1;
+
+       if (*tok != ',')
+       {
+               if (dsp_k != 0)
+                       return error("-x0/-x1/-y0/-y1 only allowed in multiply operations");
+
+               return 1;
+       }
+
+       // Eat the comma
+       tok++;
+
+       // Parse second addressing mode
+       if (dsp_parmode(&dsp_am1, &dsp_a1reg, dsp_a1expr, &dsp_a1exval, &dsp_a1exattr, &dsp_a1esym, &dsp_a1memspace, &dsp_a1perspace, 1) == ERROR)
+               return ERROR;
+
+       if (maxea == 2 || *tok == EOL)
+       {
+               if (dsp_k != 0)
+                       return error("-x0/-x1/-y0/-y1 only allowed in multiply operations");
+
+               nmodes = 2;
+               return 2;
+       }
+
+       if (*tok == ',')
+       {
+               // Only MAC-like or jsset/clr/tst/chg instructions here
+               tok++;
+               if (dsp_parmode(&dsp_am2, &dsp_a2reg, dsp_a2expr, &dsp_a2exval, &dsp_a2exattr, &dsp_a2esym, &dummy, &dummy, 2) == ERROR)
+                       return ERROR;
+               if (maxea == 3)
+                       return 3;
+               if (*tok != EOL)
+                       return error(extra_stuff);
+               nmodes = 3;
+               return 3;
+
+       }
+
+       // Only Tcc instructions here, and then only those that accept 4 operands
+
+       if (dsp_parmode(&dsp_am2, &dsp_a2reg, dsp_a2expr, &dsp_a2exval, &dsp_a2exattr, &dsp_a2esym, &dummy, &dummy, 2) == ERROR)
+               return ERROR;
+
+       if (*tok++ != ',')
+               return error("expected 4 parameters");
+
+       if (dsp_parmode(&dsp_am3, &dsp_a3reg, dsp_a3expr, &dsp_a3exval, &dsp_a3exattr, &dsp_a3esym, &dummy, &dummy, 3) == ERROR)
+               return ERROR;
+
+       if (*tok == EOL)
+       {
+               if (dsp_k != 0)
+                       return error("-x0/-x1/-y0/-y1 only allowed in multiply operations");
+
+               nmodes = 4;
+               return 4;
+       }
+       else
+       {
+               // Tcc instructions do not support parallel moves, so any remaining tokens are garbage
+               return error(extra_stuff);
+       }
+
+       return error("internal assembler error: Please report this error message: 'reached the end of dsp_amode' with the line of code that caused it. Thanks, and sorry for the inconvenience");   //Something bad happened
 }
 
 
@@ -831,43 +873,43 @@ int dsp_amode(int maxea)
 //
 static inline int SDreg(int reg)
 {
-    if (reg >= KW_X0 && reg <= KW_N7)
-        return reg & 0xff;
-    else if (reg >= KW_A0&&reg <= KW_A2)
-        return (8 >> (reg & 7)) | 8;
-    else //if (reg>=KW_R0&&reg<=KW_R7)
-        return reg - KW_R0 + 16;
-    // Handy map for the above:
-    // (values are of course taken from keytab)
-    // Register | Value | Return value
-    // x0      | 260   | 4
-    // x1      | 261   | 5
-    // y0      | 262   | 6
-    // y1      | 263   | 7
-    // b0      | 265   | 8
-    // b2      | 267   | 9
-    // b1      | 269   | 10
-    // a       | 270   | 14
-    // b       | 271   | 15
-    // n0      | 280   | 24
-    // n1      | 281   | 25
-    // n2      | 282   | 26
-    // n3      | 283   | 27
-    // n4      | 284   | 28
-    // n5      | 285   | 29
-    // n6      | 286   | 30
-    // n7      | 287   | 31
-    // a0          | 136   | 0
-    // a1          | 137   | 1
-    // a2      | 138   | 2
-    // r0          | 151   | 16
-    // r1          | 152   | 17
-    // r2          | 153   | 18
-    // r3          | 154   | 19
-    // r4          | 155   | 20
-    // r5          | 156   | 21
-    // r6          | 157   | 22
-    // r7          | 158   | 23
+       if (reg >= KW_X0 && reg <= KW_N7)
+               return reg & 0xFF;
+       else if (reg >= KW_A0&&reg <= KW_A2)
+               return (8 >> (reg & 7)) | 8;
+       else //if (reg>=KW_R0&&reg<=KW_R7)
+               return reg - KW_R0 + 16;
+       // Handy map for the above:
+       // (values are of course taken from keytab)
+       // Register | Value | Return value
+       //      x0      | 260   | 4
+       //      x1      | 261   | 5
+       //      y0      | 262   | 6
+       //      y1      | 263   | 7
+       //      b0      | 265   | 8
+       //      b2      | 267   | 9
+       //      b1      | 269   | 10
+       //      a       | 270   | 14
+       //      b       | 271   | 15
+       //      n0      | 280   | 24
+       //      n1      | 281   | 25
+       //      n2      | 282   | 26
+       //      n3      | 283   | 27
+       //      n4      | 284   | 28
+       //      n5      | 285   | 29
+       //      n6      | 286   | 30
+       //      n7      | 287   | 31
+       //      a0          | 136   | 0
+       //      a1          | 137   | 1
+       //      a2      | 138   | 2
+       //      r0          | 151   | 16
+       //      r1          | 152   | 17
+       //      r2          | 153   | 18
+       //      r3          | 154   | 19
+       //      r4          | 155   | 20
+       //      r5          | 156   | 21
+       //      r6          | 157   | 22
+       //      r7          | 158   | 23
 }
 
 
@@ -876,668 +918,714 @@ static inline int SDreg(int reg)
 //
 static inline LONG check_x_y(LONG ea1, LONG S1)
 {
-    LONG inst;
-    LONG eax_temp, eay_temp;
-    LONG D1, D2, S2, ea2;
-    LONG K_D1, K_D2;
-    LONG w = 1 << 7;           // S1=0, D1=1<<14
-    if ((ea1 & 0x38) == DSP_EA_POSTINC || (ea1 & 0x38) == DSP_EA_POSTINC1 ||
-        (ea1 & 0x38) == DSP_EA_POSTDEC1 || (ea1 & 0x38) == DSP_EA_NOUPD)
-    {
-
-        switch (ea1 & 0x38)
-        {
-        case DSP_EA_POSTINC: ea1 = (ea1&(~0x38)) | 0x8;break;
-        case DSP_EA_POSTINC1: ea1 = (ea1&(~0x38)) | 0x18;break;
-        case DSP_EA_POSTDEC1: ea1 = (ea1&(~0x38)) | 0x10;break;
-        case DSP_EA_NOUPD: ea1 = (ea1&(~0x38)) | 0x00;break;
-        }
+       LONG inst;
+       LONG eax_temp, eay_temp;
+       LONG D1, D2, S2, ea2;
+       LONG K_D1, K_D2;
+       LONG w = 1 << 7;                // S1=0, D1=1<<14
+
+       if ((ea1 & 0x38) == DSP_EA_POSTINC || (ea1 & 0x38) == DSP_EA_POSTINC1 ||
+               (ea1 & 0x38) == DSP_EA_POSTDEC1 || (ea1 & 0x38) == DSP_EA_NOUPD)
+       {
+               switch (ea1 & 0x38)
+               {
+               case DSP_EA_POSTINC:  ea1 = (ea1 & (~0x38)) | 0x8; break;
+               case DSP_EA_POSTINC1: ea1 = (ea1 & (~0x38)) | 0x18; break;
+               case DSP_EA_POSTDEC1: ea1 = (ea1 & (~0x38)) | 0x10; break;
+               case DSP_EA_NOUPD:    ea1 = (ea1 & (~0x38)) | 0x00; break;
+               }
 
-        if (S1 == 0)
-        {
-            // 'X:eax,D1 Y:eay,D2', 'X:eax,D1 S2,Y:eay'
-            // Check for D1
-            switch (K_D1 = *tok++)
-            {
-            case KW_X0: D1 = 0 << 10; break;
-            case KW_X1: D1 = 1 << 10; break;
-            case KW_A:  D1 = 2 << 10; break;
-            case KW_B:  D1 = 3 << 10; break;
-            default:    return error("unrecognised X:Y: parallel move syntax: expected x0, x1, a or b after 'X:eax,'");
-            }
-        }
-        else
-        {
-            // 'S1,X:eax Y:eay,D2' 'S1,X:eax S2,Y:eay'
-            w = 0;
-            switch (S1)
-            {
-            case 4:  D1 = 0 << 10; break;
-            case 5:  D1 = 1 << 10; break;
-            case 14: D1 = 2 << 10; break;
-            case 15: D1 = 3 << 10; break;
-            default: return error("unrecognised X:Y: parallel move syntax: S1 can only be x0, x1, a or b in 'S1,X:eax'");
-            }
-        }
+               if (S1 == 0)
+               {
+                       // 'X:eax,D1 Y:eay,D2', 'X:eax,D1 S2,Y:eay'
+                       // Check for D1
+                       switch (K_D1 = *tok++)
+                       {
+                       case KW_X0: D1 = 0 << 10; break;
+                       case KW_X1: D1 = 1 << 10; break;
+                       case KW_A:  D1 = 2 << 10; break;
+                       case KW_B:  D1 = 3 << 10; break;
+                       default:    return error("unrecognised X:Y: parallel move syntax: expected x0, x1, a or b after 'X:eax,'");
+                       }
+               }
+               else
+               {
+                       // 'S1,X:eax Y:eay,D2' 'S1,X:eax S2,Y:eay'
+                       w = 0;
 
-        if (*tok == KW_Y)
-        {
-            tok++;
-            // 'X:eax,D1 Y:eay,D2' 'S1,X:eax Y:eay,D2'
-            if (*tok++ != ':')
-                return error("unrecognised X:Y: parallel move syntax: expected ':' after 'X:ea,D1/S1,X:ea Y'");
-            if (*tok++ == '(')
-            {
-                if (*tok >= KW_R0 && *tok <= KW_R7)
-                {
-                    ea2 = (*tok++ - KW_R0);
-                    if (((ea1 & 7) < 4 && ea2 < 4) || ((ea1 & 7) >= 4 && ea2 > 4))
-                        return error("unrecognised X:Y: parallel move syntax: eax and eay register banks must be different in 'X:ea,D1/S1,X:ea Y:eay,D2'");
-                }
-                else
-                    return error("unrecognised X:Y: parallel move syntax: expected 'Rn' after 'X:ea,D1/S1,X:ea Y:('");
-                // If eax register is r0-r3 then eay register is r4-r7.
-                // Encode that to 2 bits (i.e. eay value is 0-3)
-                eax_temp = (ea2 & 3) << 5;  // Store register temporarily
-                if (*tok++ != ')')
-                    return error("unrecognised X:Y: parallel move syntax: expected ')' after 'X:ea,D1/S1,X:ea Y:(Rn'");
-                if (*tok == '+')
-                {
-                    tok++;
-                    if (*tok == ',')
-                    {
-                        // (Rn)+
-                        ea2 = 3 << 12;
-                        tok++;
-                    }
-                    else if (*tok >= KW_N0 && *tok <= KW_N7)
-                    {
-                        // (Rn)+Nn
-                        if ((*tok++ & 7) != ea2)
-                            return error("unrecognised X:Y: parallel move syntax(Same register number expected for Rn, Nn in 'X:ea,D1/S1,X:ea Y:(Rn)+Nn,D')");
-                        ea2 = 1 << 12;
-                        if (*tok++ != ',')
-                            return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea Y:(Rn)+Nn'");
-                    }
-                    else
-                        return error("unrecognised X:Y: parallel move syntax: expected ',' or 'Nn' after 'X:ea,D1/S1,X:ea Y:(Rn)+'");
+                       switch (S1)
+                       {
+                       case 4:  D1 = 0 << 10; break;
+                       case 5:  D1 = 1 << 10; break;
+                       case 14: D1 = 2 << 10; break;
+                       case 15: D1 = 3 << 10; break;
+                       default: return error("unrecognised X:Y: parallel move syntax: S1 can only be x0, x1, a or b in 'S1,X:eax'");
+                       }
+               }
 
-                }
-                else if (*tok == '-')
-                {
-                    // (Rn)-
-                    ea2 = 2 << 12;
-                    tok++;
-                    if (*tok++ != ',')
-                        return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea Y:(Rn)-'");
-                }
-                else if (*tok++ == ',')
-                {
-                    // (Rn)
-                    ea2 = 0 << 12;
-                }
-                else
-                    return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea Y:eay'");
+               if (*tok == KW_Y)
+               {
+                       tok++;
+                       // 'X:eax,D1 Y:eay,D2' 'S1,X:eax Y:eay,D2'
+                       if (*tok++ != ':')
+                               return error("unrecognised X:Y: parallel move syntax: expected ':' after 'X:ea,D1/S1,X:ea Y'");
 
-                ea2 |= eax_temp; // OR eay back from temp
+                       if (*tok++ == '(')
+                       {
+                               if (*tok >= KW_R0 && *tok <= KW_R7)
+                               {
+                                       ea2 = (*tok++ - KW_R0);
 
-                switch (K_D2 = *tok++)
-                {
-                case KW_Y0: D2 = 0 << 8; break;
-                case KW_Y1: D2 = 1 << 8; break;
-                case KW_A:  D2 = 2 << 8; break;
-                case KW_B:  D2 = 3 << 8; break;
-                default:    return error("unrecognised X:Y: parallel move syntax: expected y0, y1, a or b after 'X:ea,D1/S1,X:ea Y:eay,'");
-                }
+                                       if (((ea1 & 7) < 4 && ea2 < 4) || ((ea1 & 7) >= 4 && ea2 > 4))
+                                               return error("unrecognised X:Y: parallel move syntax: eax and eay register banks must be different in 'X:ea,D1/S1,X:ea Y:eay,D2'");
+                               }
+                               else
+                                       return error("unrecognised X:Y: parallel move syntax: expected 'Rn' after 'X:ea,D1/S1,X:ea Y:('");
 
-                if (*tok != EOL)
-                    return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea Y:eay,D'");
+                               // If eax register is r0-r3 then eay register is r4-r7.
+                               // Encode that to 2 bits (i.e. eay value is 0-3)
+                               eax_temp = (ea2 & 3) << 5;  // Store register temporarily
 
-                if (S1 == 0)
-                    if (K_D1 == K_D2)
-                        return error("unrecognised X:Y: parallel move syntax: D1 and D2 cannot be the same in 'X:ea,D1 Y:eay,D2'");
+                               if (*tok++ != ')')
+                                       return error("unrecognised X:Y: parallel move syntax: expected ')' after 'X:ea,D1/S1,X:ea Y:(Rn'");
 
-                inst = B16(11000000, 00000000) | w;
-                inst |= ea1 | D1 | ea2 | D2;
-                return inst;
-            }
-            else
-                return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' after 'X:ea,D1/S1,X:ea Y:'");
-        }
-        else if (*tok == KW_Y0 || *tok == KW_Y1 || *tok == KW_A || *tok == KW_B)
-        {
-            // 'X:eax,D1 S2,Y:eay' 'S1,X:eax1 S2,Y:eay'
-            switch (*tok++)
-            {
-            case KW_Y0: S2 = 0 << 8; break;
-            case KW_Y1: S2 = 1 << 8; break;
-            case KW_A:  S2 = 2 << 8; break;
-            case KW_B:  S2 = 3 << 8; break;
-            default: return error("unrecognised X:Y: parallel move syntax: expected y0, y1, a or b after 'X:ea,D1/S1,X:ea Y:eay,'");
-            }
+                               if (*tok == '+')
+                               {
+                                       tok++;
 
-            if (*tok++ != ',')
-                return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea S2'");
+                                       if (*tok == ',')
+                                       {
+                                               // (Rn)+
+                                               ea2 = 3 << 12;
+                                               tok++;
+                                       }
+                                       else if (*tok >= KW_N0 && *tok <= KW_N7)
+                                       {
+                                               // (Rn)+Nn
+                                               if ((*tok++ & 7) != ea2)
+                                                       return error("unrecognised X:Y: parallel move syntax(Same register number expected for Rn, Nn in 'X:ea,D1/S1,X:ea Y:(Rn)+Nn,D')");
 
-            if (*tok++ == KW_Y)
-            {
-                // 'X:eax,D1 Y:eay,D2' 'S1,X:eax Y:eay,D2'
-                if (*tok++ != ':')
-                    return error("unrecognised X:Y: parallel move syntax: expected ':' after 'X:ea,D1/S1,X:ea Y'");
-                if (*tok++ == '(')
-                {
-                    if (*tok >= KW_R0 && *tok <= KW_R7)
-                    {
-                        ea2 = (*tok++ - KW_R0);
-                        if (((ea1 & 7) < 4 && ea2 < 4) || ((ea1 & 7) >= 4 && ea2 > 4))
-                            return error("unrecognised X:Y: parallel move syntax: eax and eay register banks must be different in 'X:ea,D1/S1,X:ea S2,Y:eay'");
-                    }
-                    else
-                        return error("unrecognised X:Y: parallel move syntax: expected 'Rn' after 'X:ea,D1/S1,X:ea S2,Y:('");
-                    // If eax register is r0-r3 then eay register is r4-r7.
-                    // Encode that to 2 bits (i.e. eay value is 0-3)
-                    eay_temp = (ea2 & 3) << 5; //Store register temporarily
-                    if (*tok++ != ')')
-                        return error("unrecognised X:Y: parallel move syntax: expected ')' after 'X:ea,D1/S1,X:ea S2,Y:(Rn'");
-                    if (*tok == '+')
-                    {
-                        tok++;
-                        if (*tok == EOL)
-                            // (Rn)+
-                            ea2 = 3 << 12;
-                        else if (*tok >= KW_N0 && *tok <= KW_N7)
-                        {
-                            // (Rn)+Nn
-                            if ((*tok++ & 7) != ea2)
-                                return error("unrecognised X:Y: parallel move syntax(Same register number expected for Rn, Nn in 'X:ea,D1/S1,X:ea S2,Y:(Rn)+Nn')");
-                            ea2 = 1 << 12;
-                            if (*tok != EOL)
-                                return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea S2,Y:(Rn)+Nn'");
-                        }
-                        else
-                            return error("unrecognised X:Y: parallel move syntax: expected ',' or 'Nn' after 'X:ea,D1/S1,X:ea S2,Y:(Rn)+'");
+                                               ea2 = 1 << 12;
 
-                    }
-                    else if (*tok == '-')
-                    {
-                        // (Rn)-
-                        ea2 = 2 << 12;
-                        tok++;
-                        if (*tok != EOL)
-                            return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea S2,Y:(Rn)-'");
-                    }
-                    else if (*tok == EOL)
-                    {
-                        // (Rn)
-                        ea2 = 0 << 12;
-                    }
-                    else
-                        return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea S2,Y:eay'");
+                                               if (*tok++ != ',')
+                                                       return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea Y:(Rn)+Nn'");
+                                       }
+                                       else
+                                               return error("unrecognised X:Y: parallel move syntax: expected ',' or 'Nn' after 'X:ea,D1/S1,X:ea Y:(Rn)+'");
 
-                    ea2 |= eay_temp; //OR eay back from temp
+                               }
+                               else if (*tok == '-')
+                               {
+                                       // (Rn)-
+                                       ea2 = 2 << 12;
+                                       tok++;
 
-                    inst = B16(10000000, 00000000) | w;
-                    inst |= (ea1 & 0x1f) | D1 | S2 | ea2;
-                    return inst;
-                }
-                else
-                    return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' after 'X:ea,D1/S1,X:ea Y:'");
+                                       if (*tok++ != ',')
+                                               return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea Y:(Rn)-'");
+                               }
+                               else if (*tok++ == ',')
+                               {
+                                       // (Rn)
+                                       ea2 = 0 << 12;
+                               }
+                               else
+                                       return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea Y:eay'");
 
-            }
-            else
-                return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' in 'X:ea,D1/S1,X:ea'");
-        }
-        else
-            return error("unrecognised X:Y: or X:R parallel move syntax: expected Y:, A or B after 'X:ea,D1/S1,X:ea S2,'");
+                               ea2 |= eax_temp; // OR eay back from temp
 
+                               switch (K_D2 = *tok++)
+                               {
+                               case KW_Y0: D2 = 0 << 8; break;
+                               case KW_Y1: D2 = 1 << 8; break;
+                               case KW_A:  D2 = 2 << 8; break;
+                               case KW_B:  D2 = 3 << 8; break;
+                               default:    return error("unrecognised X:Y: parallel move syntax: expected y0, y1, a or b after 'X:ea,D1/S1,X:ea Y:eay,'");
+                               }
 
-    }
-    return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' in 'X:ea,D1/S1,X:ea'");
-}
+                               if (*tok != EOL)
+                                       return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea Y:eay,D'");
 
-//
-// Parse X: addressing space parallel moves
-//
-static inline LONG parse_x(const int W, LONG inst, const LONG S1, const int check_for_x_y)
-{
-    int immreg;                                        // Immediate register destination
-    LONG S2, D1, D2;                   // Source and Destinations
-    LONG ea1;                                  // ea bitfields
-    uint32_t termchar = ',';   // Termination character for ea checks
-    int force_imm = NUM_NORMAL;        // Holds forced immediate value (i.e. '<' or '>')
-    ea1 = -1;                                  // initialise e1 (useful for some code paths)
-    if (W == 0)
-        termchar = EOL;
-    if (*tok == '-')
-    {
-        if (tok[1] == CONST || tok[1] == FCONST)
-        {
-            tok++;
-            dspImmedEXVAL = *tok++;
-            goto x_check_immed;
-        }
-        // This could be either -(Rn), -aa or -ea. Check for immediate first
-        if (tok[1] == SYMBOL)
-        {
-            if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) == OK)
-            {
-                if (S1 != 0)
-                {
-                x_checkea_right:
+                               if (S1 == 0)
+                                       if (K_D1 == K_D2)
+                                               return error("unrecognised X:Y: parallel move syntax: D1 and D2 cannot be the same in 'X:ea,D1 Y:eay,D2'");
 
-                    // 'S1,X:ea S2,D2', 'A,X:ea X0,A', 'B,X:ea X0,B', 'S1,X:eax Y:eay,D2', 'S1,X:eax S2,Y:eay'
-                    if (*tok == KW_X0 && tok[1] == ',' && tok[2] == KW_A)
-                    {
-                        // 'A,X:ea X0,A'
-                        if (ea1 == DSP_EA_ABS)
-                            deposit_extra_ea = DEPOSIT_EXTRA_WORD;
-                        if (S1 != 14)
-                            return error("unrecognised X:R parallel move syntax: S1 can only be a in 'a,X:ea x0,a'");
-                        if (ea1 == -1)
-                            return error("unrecognised X:R parallel move syntax: absolute address not allowed in 'a,X:ea x0,a'");
-                        if (ea1 == B8(00110100))
-                            return error("unrecognised X:R parallel move syntax: immediate data not allowed in 'a,X:ea x0,a'");
-                        inst = B16(00001000, 00000000) | ea1 | (0 << 8);
-                        return inst;
-                    }
-                    else if (*tok == KW_X0 && tok[1] == ',' && tok[2] == KW_B)
-                    {
-                        // 'B,X:ea X0,B'
-                        if (ea1 == DSP_EA_ABS)
-                            deposit_extra_ea = DEPOSIT_EXTRA_WORD;
-                        if (S1 != 15)
-                            return error("unrecognised X:R parallel move syntax: S1 can only be b in 'b,X:ea x0,b'");
-                        if (ea1 == -1)
-                            return error("unrecognised X:R parallel move syntax: absolute address not allowed in 'b,X:ea x0,b'");
-                        if (ea1 == B8(00110100))
-                            return error("unrecognised X:R parallel move syntax: immediate data not allowed in 'b,X:ea x0,b'");
-                        inst = B16(00001001, 00000000) | ea1 | (1 << 8);
-                        return inst;
-                    }
-                    else if (*tok == KW_A || *tok == KW_B)
-                    {
-                        // 'S1,X:ea S2,D2', 'S1,X:eax S2,Y:eay'
+                               inst = B16(11000000, 00000000) | w;
+                               inst |= ea1 | D1 | ea2 | D2;
+                               return inst;
+                       }
+                       else
+                               return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' after 'X:ea,D1/S1,X:ea Y:'");
+               }
+               else if (*tok == KW_Y0 || *tok == KW_Y1 || *tok == KW_A || *tok == KW_B)
+               {
+                       // 'X:eax,D1 S2,Y:eay' 'S1,X:eax1 S2,Y:eay'
+                       switch (*tok++)
+                       {
+                       case KW_Y0: S2 = 0 << 8; break;
+                       case KW_Y1: S2 = 1 << 8; break;
+                       case KW_A:  S2 = 2 << 8; break;
+                       case KW_B:  S2 = 3 << 8; break;
+                       default: return error("unrecognised X:Y: parallel move syntax: expected y0, y1, a or b after 'X:ea,D1/S1,X:ea Y:eay,'");
+                       }
 
-                        switch (S1)
-                        {
-                        case 4:  D1 = 0 << 10; break;
-                        case 5:  D1 = 1 << 10; break;
-                        case 14: D1 = 2 << 10; break;
-                        case 15: D1 = 3 << 10; break;
-                        default: return error("unrecognised X:R parallel move syntax: S1 can only be x0, x1, a or b in 'S1,X:ea S2,D2'");
-                        }
+                       if (*tok++ != ',')
+                               return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea S2'");
 
-                        if (tok[1] == ',' && tok[2] == KW_Y)
-                        {
-                            // 'S1,X:eax S2,Y:eay'
-                            return check_x_y(ea1, S1);
-                        }
+                       if (*tok++ == KW_Y)
+                       {
+                               // 'X:eax,D1 Y:eay,D2' 'S1,X:eax Y:eay,D2'
+                               if (*tok++ != ':')
+                                       return error("unrecognised X:Y: parallel move syntax: expected ':' after 'X:ea,D1/S1,X:ea Y'");
 
-                        // 'S1,X:ea S2,D2'
-                        if (ea1 == DSP_EA_ABS)
-                            deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+                               if (*tok++ == '(')
+                               {
+                                       if (*tok >= KW_R0 && *tok <= KW_R7)
+                                       {
+                                               ea2 = (*tok++ - KW_R0);
 
-                        switch (*tok++)
-                        {
-                        case KW_A: S2 = 0 << 9; break;
-                        case KW_B: S2 = 1 << 9; break;
-                        default:   return error("unrecognised X:R parallel move syntax: expected a or b after 'S1,X:eax'");
-                        }
-                        if (*tok++ != ',')
-                            return error("unrecognised X:R parallel move syntax: expected ',' after 'S1,X:eax S2'");
+                                               if (((ea1 & 7) < 4 && ea2 < 4) || ((ea1 & 7) >= 4 && ea2 > 4))
+                                                       return error("unrecognised X:Y: parallel move syntax: eax and eay register banks must be different in 'X:ea,D1/S1,X:ea S2,Y:eay'");
+                                       }
+                                       else
+                                               return error("unrecognised X:Y: parallel move syntax: expected 'Rn' after 'X:ea,D1/S1,X:ea S2,Y:('");
+                                       // If eax register is r0-r3 then eay register is r4-r7.
+                                       // Encode that to 2 bits (i.e. eay value is 0-3)
+                                       eay_temp = (ea2 & 3) << 5; //Store register temporarily
 
-                        if (*tok == KW_Y0 || *tok == KW_Y1)
-                        {
-                            if (*tok++ == KW_Y0)
-                                D2 = 0 << 8;
-                            else
-                                D2 = 1 << 8;
+                                       if (*tok++ != ')')
+                                               return error("unrecognised X:Y: parallel move syntax: expected ')' after 'X:ea,D1/S1,X:ea S2,Y:(Rn'");
 
-                            if (*tok != EOL)
-                                return error("unrecognised X:R parallel move syntax: unexpected text after 'X:eax,D1 S2,S2'");
+                                       if (*tok == '+')
+                                       {
+                                               tok++;
 
-                            inst = B16(00010000, 00000000) | (0 << 7);
-                            inst |= ea1 | D1 | S2 | D2;
-                            return inst;
-                        }
-                        else
-                            return error("unrecognised X:R parallel move syntax: expected y0 or y1 after 'X:eax,D1 S2,'");
+                                               if (*tok == EOL)
+                                                       // (Rn)+
+                                                       ea2 = 3 << 12;
+                                               else if (*tok >= KW_N0 && *tok <= KW_N7)
+                                               {
+                                                       // (Rn)+Nn
+                                                       if ((*tok++ & 7) != ea2)
+                                                               return error("unrecognised X:Y: parallel move syntax(Same register number expected for Rn, Nn in 'X:ea,D1/S1,X:ea S2,Y:(Rn)+Nn')");
 
-                    }
-                    else if (*tok == KW_Y)
-                    {
-                        // 'S1,X:eax Y:eay,D2'
-                        return check_x_y(ea1, S1);
-                    }
-                    else if (*tok == KW_Y0 || *tok == KW_Y1)
-                    {
-                        // 'S1,X:eax S2,Y:eay'
-                        return check_x_y(ea1, S1);
-                    }
-                    else
-                        return error("unrecognised X:Y or X:R parallel move syntax: expected y0 or y1 after 'X:eax,D1/X:ea,D1");
-                }
-                else
-                {
-                    // Only check for aa if we have a defined number in our hands or we've
-                    // been asked to use a short number format. The former case we'll just test
-                    // it to see if it's small enough. The later - it's the programmer's call
-                    // so he'd better have a small address or the fixups will bite him/her in the arse!
-                    if (dspImmedEXATTR&DEFINED || force_imm == NUM_FORCE_SHORT)
-                    {
+                                                       ea2 = 1 << 12;
 
-                        // It's an immediate, so ea or eax is probably an absolute address
-                        // (unless it's aa if the immediate is small enough)
-                        // 'X:ea,D' or 'X:aa,D' or 'X:ea,D1 S2,D2' or 'X:eax,D1 Y:eay,D2' or 'X:eax,D1 S2,Y:eay'
-                    x_check_immed:
-                        // Check for aa (which is 6 bits zero extended)
-                        if (dspImmedEXVAL < 0x40 && force_imm != NUM_FORCE_LONG)
-                        {
-                            if (W == 1)
-                            {
-                                // It might be X:aa but we're not 100% sure yet.
-                                // If it is, the only possible syntax here is 'X:aa,D'.
-                                // So check ahead to see if EOL follows D, then we're good to go.
-                                if (*tok == ',' && ((*(tok + 1) >= KW_X0 && *(tok + 1) <= KW_N7) || (*(tok + 1) >= KW_R0 && *(tok + 1) <= KW_R7) || (*(tok + 1) >= KW_A0 && *(tok + 1) <= KW_A2)) && *(tok + 2) == EOL)
-                                {
-                                    // Yup, we're good to go - 'X:aa,D' it is
-                                    tok++;
-                                    immreg = SDreg(*tok++);
-                                    inst = inst | (uint32_t)dspImmedEXVAL;
-                                    inst |= ((immreg & 0x18) << (12 - 3)) + ((immreg & 7) << 8);
-                                    inst |= 1 << 7; // W
-                                    return inst;
-                                }
-                            }
-                            else
-                            {
-                                if (*tok == EOL)
-                                {
-                                    // 'S,X:aa'
-                                    inst = inst | (uint32_t)dspImmedEXVAL;
-                                    inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8);
-                                    return inst;
-                                }
-                                else
-                                {
-                                    // 'S1,X:ea S2,D2', 'A,X:ea X0,A', 'B,X:ea X0,B',
-                                    // 'S1,X:eax Y:eay,D2', 'S1,X:eax S2,Y:eay'
-                                    ea1 = DSP_EA_ABS;
-                                    deposit_extra_ea = DEPOSIT_EXTRA_WORD;
-                                    goto x_checkea_right;
-                                }
-                            }
-                        }
-                    }
+                                                       if (*tok != EOL)
+                                                               return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea S2,Y:(Rn)+Nn'");
+                                               }
+                                               else
+                                                       return error("unrecognised X:Y: parallel move syntax: expected ',' or 'Nn' after 'X:ea,D1/S1,X:ea S2,Y:(Rn)+'");
 
-                    // Well, that settles it - we do have an ea in our hands
-                    if (W == 1)
-                    {
-                        // 'X:ea,D' [... S2,d2]
-                        if (*tok++ != ',')
-                            return error("unrecognised X: parallel move syntax: expected ',' after 'X:ea'");
-                        if ((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2))
-                        {
-                            D1 = SDreg(*tok++);
-                            if (*tok == EOL)
-                            {
-                                // 'X:ea,D'
-                                inst = inst | B8(01000000) | (1 << 7);
-                                inst |= ((D1 & 0x18) << (12 - 3)) + ((D1 & 7) << 8);
-                                inst |= ea1;
-                                if (ea1 == DSP_EA_ABS)
-                                    deposit_extra_ea = DEPOSIT_EXTRA_WORD;
-                                return inst;
-                            }
-                            else
-                            {
-                                // 'X:ea,D1 S2,D2'
-                                if (*tok == KW_A || *tok == KW_B)
-                                {
-                                    S2 = SDreg(*tok++);
-                                    if (*tok++ != ',')
-                                        return error("unrecognised X:R parallel move syntax: expected comma after X:ea,D1 S2");
-                                    if (*tok == KW_Y0 || *tok == KW_Y1)
-                                    {
-                                        D2 = SDreg(*tok++);
-                                        if (*tok != EOL)
-                                            return error("unrecognised X:R parallel move syntax: expected EOL after X:ea,D1 S2,D2");
-                                        inst = B16(00010000, 00000000) | (1 << 7);
-                                        inst |= ((D1 & 0x8) << (12 - 4)) + ((D1 & 1) << 10);
-                                        inst |= (S2 & 1) << 9;
-                                        inst |= (D2 & 1) << 8;
-                                        inst |= ea1;
-                                        return inst;
-                                    }
-                                    else
-                                        return error("unrecognised X:R parallel move syntax: expected y0,y1 after X:ea,D1 S2,");
-                                }
-                                else
-                                    return error("unrecognised X:R parallel move syntax: expected a,b after X:ea,D1");
-                            }
-                        }
-                        else
-                            return error("unrecognised X: parallel move syntax: expected x0,x1,y0,y1,a0,b0,a2,b2,a1,b1,a,b,r0-r7,n0-n7 after 'X:ea,'");
-                    }
-                    else
-                    {
-                        if (*tok == EOL)
-                        {
-                            // 'S,X:ea'
-                            inst = inst | B8(01000000) | (0 << 7);
-                            inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8);
-                            inst |= ea1;
-                            if (ea1 == DSP_EA_ABS)
-                                deposit_extra_ea = DEPOSIT_EXTRA_WORD;
-                            return inst;
-                        }
-                        else
-                        {
-                            // 'S1,X:ea S2,D2', 'A,X:ea X0,A', 'B,X:ea X0,B',
-                            // 'S1,X:eax Y:eay,D2', 'S1,X:eax S2,Y:eay'
-                            goto x_checkea_right;
-                        }
-                    }
+                                       }
+                                       else if (*tok == '-')
+                                       {
+                                               // (Rn)-
+                                               ea2 = 2 << 12;
+                                               tok++;
+                                               if (*tok != EOL)
+                                                       return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea S2,Y:(Rn)-'");
+                                       }
+                                       else if (*tok == EOL)
+                                       {
+                                               // (Rn)
+                                               ea2 = 0 << 12;
+                                       }
+                                       else
+                                               return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea S2,Y:eay'");
 
-                }
-            }
-        }
-        else
-        {
-            // It's not an immediate, check for '-(Rn)'
-            ea1 = checkea(termchar, X_ERRORS);
+                                       ea2 |= eay_temp; //OR eay back from temp
 
-            if (ea1 == ERROR)
-                return ERROR;
+                                       inst = B16(10000000, 00000000) | w;
+                                       inst |= (ea1 & 0x1f) | D1 | S2 | ea2;
+                                       return inst;
+                               }
+                               else
+                                       return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' after 'X:ea,D1/S1,X:ea Y:'");
+                       }
+                       else
+                               return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' in 'X:ea,D1/S1,X:ea'");
+               }
+               else
+                       return error("unrecognised X:Y: or X:R parallel move syntax: expected Y:, A or B after 'X:ea,D1/S1,X:ea S2,'");
+       }
 
-            goto x_gotea1;
+       return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' in 'X:ea,D1/S1,X:ea'");
+}
 
-        }
-    }
-    else if (*tok == '#')
-    {
-        tok++;
-        if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
-            return ERROR;
-        // Okay so we have immediate data - mark it down
-        ea1 = DSP_EA_IMM;
-        // Now, proceed to the main code for this branch
-        goto x_gotea1;
-    }
-    else if (*tok == '(')
-    {
-        // Maybe we got an expression here, check for it
-        if (tok[1] == CONST || tok[1] == FCONST || tok[1] == SUNARY || tok[1] == SYMBOL || tok[1] == STRING)
-        {
-            // Evaluate the expression and go to immediate code path
-            expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM);
-            goto x_check_immed;
-        }
+//
+// Parse X: addressing space parallel moves
+//
+static inline LONG parse_x(const int W, LONG inst, const LONG S1, const int check_for_x_y)
+{
+       int immreg;                                     // Immediate register destination
+       LONG S2, D1, D2;                        // Source and Destinations
+       LONG ea1;                                       // ea bitfields
+       uint32_t termchar = ',';        // Termination character for ea checks
+       int force_imm = NUM_NORMAL;     // Holds forced immediate value (i.e. '<' or '>')
+       ea1 = -1;                                       // initialise e1 (useful for some code paths)
+
+       if (W == 0)
+               termchar = EOL;
+
+       if (*tok == '-')
+       {
+               if (tok[1] == CONST || tok[1] == FCONST)
+               {
+                       tok++;
+                       dspImmedEXVAL = *tok++;
+                       goto x_check_immed;
+               }
 
-        // Nope, let's check for ea then
-        ea1 = checkea(termchar, X_ERRORS);
-        if (ea1 == ERROR)
-            return ERROR;
+               // This could be either -(Rn), -aa or -ea. Check for immediate first
+               if (tok[1] == SYMBOL)
+               {
+                       if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) == OK)
+                       {
+                               if (S1 != 0)
+                               {
+x_checkea_right:
+                                       // 'S1,X:ea S2,D2', 'A,X:ea X0,A', 'B,X:ea X0,B', 'S1,X:eax Y:eay,D2', 'S1,X:eax S2,Y:eay'
+                                       if (*tok == KW_X0 && tok[1] == ',' && tok[2] == KW_A)
+                                       {
+                                               // 'A,X:ea X0,A'
+                                               if (ea1 == DSP_EA_ABS)
+                                                       deposit_extra_ea = DEPOSIT_EXTRA_WORD;
 
-    x_gotea1:
-        if (W == 1)
-        {
-            if (*tok++ != ',')
-                return error("Comma expected after 'X:(Rn)')");
+                                               if (S1 != 14)
+                                                       return error("unrecognised X:R parallel move syntax: S1 can only be a in 'a,X:ea x0,a'");
 
-            // It might be 'X:(Rn..)..,D' but we're not 100% sure yet.
-            // If it is, the only possible syntax here is 'X:ea,D'.
-            // So check ahead to see if EOL follows D, then we're good to go.
-            if (((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2)) && *(tok + 1) == EOL)
-            {
-                //'X:ea,D'
-                D1 = SDreg(*tok++);
+                                               if (ea1 == -1)
+                                                       return error("unrecognised X:R parallel move syntax: absolute address not allowed in 'a,X:ea x0,a'");
 
-                inst = inst | B8(01000000) | (1 << 7);
-                inst |= ea1;
-                inst |= ((D1 & 0x18) << (12 - 3)) + ((D1 & 7) << 8);
-                return inst;
-            }
-        }
-        else
-        {
-            if (*tok == EOL)
-            {
-                //'S,X:ea'
-                inst = inst | B8(01000000) | (0 << 7);
-                inst |= ea1;
-                inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8);
-                return inst;
-            }
-            else
-            {
-                goto x_checkea_right;
-            }
-        }
-        // 'X:eax,D1 Y:eay,D2', 'X:eax,D1 S2,Y:eay' or 'X:ea,D1 S2,D2'
-        // Check ahead for S2,D2 - if that's true then we have 'X:ea,D1 S2,D2'
-        if ((*tok == KW_X0 || *tok == KW_X1 || *tok == KW_A || *tok == KW_B) && (*(tok + 1) == KW_A || *(tok + 1) == KW_B) && (*(tok + 2) == ',') && (*(tok + 3) == KW_Y0 || (*(tok + 3) == KW_Y1)))
-        {
-            // 'X:ea,D1 S2,D2'
-            // Check if D1 is x0, x1, a or b
-            switch (*tok++)
-            {
-            case KW_X0: D1 = 0 << 10; break;
-            case KW_X1: D1 = 1 << 10; break;
-            case KW_A:  D1 = 2 << 10; break;
-            case KW_B:  D1 = 3 << 10; break;
-            default:    return error("unrecognised X:R parallel move syntax: expected x0, x1, a or b after 'X:eax,'");
-            }
+                                               if (ea1 == B8(00110100))
+                                                       return error("unrecognised X:R parallel move syntax: immediate data not allowed in 'a,X:ea x0,a'");
 
-            switch (*tok++)
-            {
-            case KW_A: S2 = 0 << 9; break;
-            case KW_B: S2 = 1 << 9; break;
-            default:   return error("unrecognised X:R parallel move syntax: expected a or b after 'X:eax,D1 '");
-            }
+                                               inst = B16(00001000, 00000000) | ea1 | (0 << 8);
+                                               return inst;
+                                       }
+                                       else if (*tok == KW_X0 && tok[1] == ',' && tok[2] == KW_B)
+                                       {
+                                               // 'B,X:ea X0,B'
+                                               if (ea1 == DSP_EA_ABS)
+                                                       deposit_extra_ea = DEPOSIT_EXTRA_WORD;
 
-            if (*tok++ != ',')
-                return error("unrecognised X:R parallel move syntax: expected ',' after 'X:eax,D1 S2'");
+                                               if (S1 != 15)
+                                                       return error("unrecognised X:R parallel move syntax: S1 can only be b in 'b,X:ea x0,b'");
 
-            if (*tok == KW_Y0 || *tok == KW_Y1)
-            {
-                if (*tok++ == KW_Y0)
-                    D2 = 0 << 8;
-                else
-                    D2 = 1 << 8;
+                                               if (ea1 == -1)
+                                                       return error("unrecognised X:R parallel move syntax: absolute address not allowed in 'b,X:ea x0,b'");
 
-                if (*tok != EOL)
-                    return error("unrecognised X:R parallel move syntax: unexpected text after 'X:eax,D1 S2,S2'");
+                                               if (ea1 == B8(00110100))
+                                                       return error("unrecognised X:R parallel move syntax: immediate data not allowed in 'b,X:ea x0,b'");
 
-                inst = B16(00010000, 00000000) | (W << 7);
-                inst |= ea1 | D1 | S2 | D2;
-                return inst;
-            }
-            else
-                return error("unrecognised X:R parallel move syntax: expected y0 or y1 after 'X:eax,D1 S2,'");
+                                               inst = B16(00001001, 00000000) | ea1 | (1 << 8);
+                                               return inst;
+                                       }
+                                       else if (*tok == KW_A || *tok == KW_B)
+                                       {
+                                               // 'S1,X:ea S2,D2', 'S1,X:eax S2,Y:eay'
+                                               switch (S1)
+                                               {
+                                               case 4:  D1 = 0 << 10; break;
+                                               case 5:  D1 = 1 << 10; break;
+                                               case 14: D1 = 2 << 10; break;
+                                               case 15: D1 = 3 << 10; break;
+                                               default: return error("unrecognised X:R parallel move syntax: S1 can only be x0, x1, a or b in 'S1,X:ea S2,D2'");
+                                               }
 
-        }
+                                               if (tok[1] == ',' && tok[2] == KW_Y)
+                                               {
+                                                       // 'S1,X:eax S2,Y:eay'
+                                                       return check_x_y(ea1, S1);
+                                               }
 
-        // Check to see if we got eax (which is a subset of ea)
-        if (check_for_x_y)
-        {
-            if ((inst = check_x_y(ea1, 0)) != 0)
-                return inst;
-            else
-            {
-                // Rewind pointer as it might be an expression and check for it
-                tok--;
-                if (expr(dspaaEXPR, &dspaaEXVAL, &dspaaEXATTR, &dspaaESYM) != OK)
-                    return ERROR;
-                // Yes, we have an expression, so we now check for
-                // 'X:ea,D' or 'X:aa,D' or 'X:ea,D1 S2,D2' or 'X:eax,D1 Y:eay,D2' or 'X:eax,D1 S2,Y:eay'
-                goto x_check_immed;
-            }
-        }
-    }
-    else if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
-    {
-        // Check for immediate address
-        if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
-            return ERROR;
+                                               // 'S1,X:ea S2,D2'
+                                               if (ea1 == DSP_EA_ABS)
+                                                       deposit_extra_ea = DEPOSIT_EXTRA_WORD;
 
-        // We set ea1 here - if it's aa instead of ea
-        // then it won't be used anyway
-        ea1 = DSP_EA_ABS;
-        if (!(dspImmedEXATTR&DEFINED))
-        {
-            force_imm = NUM_FORCE_LONG;
-            deposit_extra_ea = DEPOSIT_EXTRA_WORD;
-        }
+                                               switch (*tok++)
+                                               {
+                                               case KW_A: S2 = 0 << 9; break;
+                                               case KW_B: S2 = 1 << 9; break;
+                                               default:   return error("unrecognised X:R parallel move syntax: expected a or b after 'S1,X:eax'");
+                                               }
 
-        goto x_check_immed;
-    }
-    else if (*tok == '>')
-    {
-        // Check for immediate address forced long
-        tok++;
-        if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
-            return ERROR;
-        if (dspImmedEXATTR & DEFINED)
-            if (dspImmedEXVAL > 0xffffff)
-                return error("long address is bigger than $ffffff");
+                                               if (*tok++ != ',')
+                                                       return error("unrecognised X:R parallel move syntax: expected ',' after 'S1,X:eax S2'");
 
-        deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+                                               if (*tok == KW_Y0 || *tok == KW_Y1)
+                                               {
+                                                       if (*tok++ == KW_Y0)
+                                                               D2 = 0 << 8;
+                                                       else
+                                                               D2 = 1 << 8;
 
-        force_imm = NUM_FORCE_LONG;
-        ea1 = DSP_EA_ABS;
-        goto x_check_immed;
-    }
-    else if (*tok == '<')
-    {
-        // Check for immediate address forced short
-        tok++;
-        if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
-            return ERROR;
-        force_imm = NUM_FORCE_SHORT;
-        if (dspImmedEXATTR & DEFINED)
-        {
-            if (dspImmedEXVAL > 0x3f)
-            {
-                warn("short addressing mode forced but address is bigger than $3f - switching to long");
-                force_imm = NUM_FORCE_LONG;
-                deposit_extra_ea = DEPOSIT_EXTRA_WORD;
-                ea1 = DSP_EA_ABS;
-            }
-        }
-        else
-        {
-            // This might end up as something like 'move Y:<adr,register'
-            // so let's mark it as an extra aa fixup here.
-            // Note: we are branching to x_check_immed without a
-            // defined dspImmed so it's going to be 0. It probably
-            // doesn't harm anything.
-            deposit_extra_ea = DEPOSIT_EXTRA_FIXUP;
-        }
+                                                       if (*tok != EOL)
+                                                               return error("unrecognised X:R parallel move syntax: unexpected text after 'X:eax,D1 S2,S2'");
 
-        goto x_check_immed;
-    }
-    return error("unknown x: addressing mode");
+                                                       inst = B16(00010000, 00000000) | (0 << 7);
+                                                       inst |= ea1 | D1 | S2 | D2;
+                                                       return inst;
+                                               }
+                                               else
+                                                       return error("unrecognised X:R parallel move syntax: expected y0 or y1 after 'X:eax,D1 S2,'");
+                                       }
+                                       else if (*tok == KW_Y)
+                                       {
+                                               // 'S1,X:eax Y:eay,D2'
+                                               return check_x_y(ea1, S1);
+                                       }
+                                       else if (*tok == KW_Y0 || *tok == KW_Y1)
+                                       {
+                                               // 'S1,X:eax S2,Y:eay'
+                                               return check_x_y(ea1, S1);
+                                       }
+                                       else
+                                               return error("unrecognised X:Y or X:R parallel move syntax: expected y0 or y1 after 'X:eax,D1/X:ea,D1");
+                               }
+                               else
+                               {
+                                       // Only check for aa if we have a defined number in our hands or we've
+                                       // been asked to use a short number format. The former case we'll just test
+                                       // it to see if it's small enough. The later - it's the programmer's call
+                                       // so he'd better have a small address or the fixups will bite him/her in the arse!
+                                       if (dspImmedEXATTR&DEFINED || force_imm == NUM_FORCE_SHORT)
+                                       {
+
+                                               // It's an immediate, so ea or eax is probably an absolute address
+                                               // (unless it's aa if the immediate is small enough)
+                                               // 'X:ea,D' or 'X:aa,D' or 'X:ea,D1 S2,D2' or 'X:eax,D1 Y:eay,D2' or 'X:eax,D1 S2,Y:eay'
+x_check_immed:
+                                               // Check for aa (which is 6 bits zero extended)
+                                               if (dspImmedEXVAL < 0x40 && force_imm != NUM_FORCE_LONG)
+                                               {
+                                                       if (W == 1)
+                                                       {
+                                                               // It might be X:aa but we're not 100% sure yet.
+                                                               // If it is, the only possible syntax here is 'X:aa,D'.
+                                                               // So check ahead to see if EOL follows D, then we're good to go.
+                                                               if (*tok == ',' && ((*(tok + 1) >= KW_X0 && *(tok + 1) <= KW_N7) || (*(tok + 1) >= KW_R0 && *(tok + 1) <= KW_R7) || (*(tok + 1) >= KW_A0 && *(tok + 1) <= KW_A2)) && *(tok + 2) == EOL)
+                                                               {
+                                                                       // Yup, we're good to go - 'X:aa,D' it is
+                                                                       tok++;
+                                                                       immreg = SDreg(*tok++);
+                                                                       inst = inst | (uint32_t)dspImmedEXVAL;
+                                                                       inst |= ((immreg & 0x18) << (12 - 3)) + ((immreg & 7) << 8);
+                                                                       inst |= 1 << 7; // W
+                                                                       return inst;
+                                                               }
+                                                       }
+                                                       else
+                                                       {
+                                                               if (*tok == EOL)
+                                                               {
+                                                                       // 'S,X:aa'
+                                                                       inst = inst | (uint32_t)dspImmedEXVAL;
+                                                                       inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8);
+                                                                       return inst;
+                                                               }
+                                                               else
+                                                               {
+                                                                       // 'S1,X:ea S2,D2', 'A,X:ea X0,A', 'B,X:ea X0,B',
+                                                                       // 'S1,X:eax Y:eay,D2', 'S1,X:eax S2,Y:eay'
+                                                                       ea1 = DSP_EA_ABS;
+                                                                       deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+                                                                       goto x_checkea_right;
+                                                               }
+                                                       }
+                                               }
+                                       }
+
+                                       // Well, that settles it - we do have an ea in our hands
+                                       if (W == 1)
+                                       {
+                                               // 'X:ea,D' [... S2,d2]
+                                               if (*tok++ != ',')
+                                                       return error("unrecognised X: parallel move syntax: expected ',' after 'X:ea'");
+
+                                               if ((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2))
+                                               {
+                                                       D1 = SDreg(*tok++);
+
+                                                       if (*tok == EOL)
+                                                       {
+                                                               // 'X:ea,D'
+                                                               inst = inst | B8(01000000) | (1 << 7);
+                                                               inst |= ((D1 & 0x18) << (12 - 3)) + ((D1 & 7) << 8);
+                                                               inst |= ea1;
+
+                                                               if (ea1 == DSP_EA_ABS)
+                                                                       deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+
+                                                               return inst;
+                                                       }
+                                                       else
+                                                       {
+                                                               // 'X:ea,D1 S2,D2'
+                                                               if (*tok == KW_A || *tok == KW_B)
+                                                               {
+                                                                       S2 = SDreg(*tok++);
+
+                                                                       if (*tok++ != ',')
+                                                                               return error("unrecognised X:R parallel move syntax: expected comma after X:ea,D1 S2");
+
+                                                                       if (*tok == KW_Y0 || *tok == KW_Y1)
+                                                                       {
+                                                                               D2 = SDreg(*tok++);
+
+                                                                               if (*tok != EOL)
+                                                                                       return error("unrecognised X:R parallel move syntax: expected EOL after X:ea,D1 S2,D2");
+
+                                                                               inst = B16(00010000, 00000000) | (1 << 7);
+                                                                               inst |= ((D1 & 0x8) << (12 - 4)) + ((D1 & 1) << 10);
+                                                                               inst |= (S2 & 1) << 9;
+                                                                               inst |= (D2 & 1) << 8;
+                                                                               inst |= ea1;
+                                                                               return inst;
+                                                                       }
+                                                                       else
+                                                                               return error("unrecognised X:R parallel move syntax: expected y0,y1 after X:ea,D1 S2,");
+                                                               }
+                                                               else
+                                                                       return error("unrecognised X:R parallel move syntax: expected a,b after X:ea,D1");
+                                                       }
+                                               }
+                                               else
+                                                       return error("unrecognised X: parallel move syntax: expected x0,x1,y0,y1,a0,b0,a2,b2,a1,b1,a,b,r0-r7,n0-n7 after 'X:ea,'");
+                                       }
+                                       else
+                                       {
+                                               if (*tok == EOL)
+                                               {
+                                                       // 'S,X:ea'
+                                                       inst = inst | B8(01000000) | (0 << 7);
+                                                       inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8);
+                                                       inst |= ea1;
+
+                                                       if (ea1 == DSP_EA_ABS)
+                                                               deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+
+                                                       return inst;
+                                               }
+                                               else
+                                               {
+                                                       // 'S1,X:ea S2,D2', 'A,X:ea X0,A', 'B,X:ea X0,B',
+                                                       // 'S1,X:eax Y:eay,D2', 'S1,X:eax S2,Y:eay'
+                                                       goto x_checkea_right;
+                                               }
+                                       }
+
+                               }
+                       }
+               }
+               else
+               {
+                       // It's not an immediate, check for '-(Rn)'
+                       ea1 = checkea(termchar, X_ERRORS);
+
+                       if (ea1 == ERROR)
+                               return ERROR;
+
+                       goto x_gotea1;
+
+               }
+       }
+       else if (*tok == '#')
+       {
+               tok++;
+
+               if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+                       return ERROR;
+
+               // Okay so we have immediate data - mark it down
+               ea1 = DSP_EA_IMM;
+               // Now, proceed to the main code for this branch
+               goto x_gotea1;
+       }
+       else if (*tok == '(')
+       {
+               // Maybe we got an expression here, check for it
+               if (tok[1] == CONST || tok[1] == FCONST || tok[1] == SUNARY || tok[1] == SYMBOL || tok[1] == STRING)
+               {
+                       // Evaluate the expression and go to immediate code path
+                       expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM);
+                       goto x_check_immed;
+               }
+
+               // Nope, let's check for ea then
+               ea1 = checkea(termchar, X_ERRORS);
+
+               if (ea1 == ERROR)
+                       return ERROR;
+
+x_gotea1:
+               if (W == 1)
+               {
+                       if (*tok++ != ',')
+                               return error("Comma expected after 'X:(Rn)')");
+
+                       // It might be 'X:(Rn..)..,D' but we're not 100% sure yet.
+                       // If it is, the only possible syntax here is 'X:ea,D'.
+                       // So check ahead to see if EOL follows D, then we're good to go.
+                       if (((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2)) && *(tok + 1) == EOL)
+                       {
+                               //'X:ea,D'
+                               D1 = SDreg(*tok++);
+
+                               inst = inst | B8(01000000) | (1 << 7);
+                               inst |= ea1;
+                               inst |= ((D1 & 0x18) << (12 - 3)) + ((D1 & 7) << 8);
+                               return inst;
+                       }
+               }
+               else
+               {
+                       if (*tok == EOL)
+                       {
+                               //'S,X:ea'
+                               inst = inst | B8(01000000) | (0 << 7);
+                               inst |= ea1;
+                               inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8);
+                               return inst;
+                       }
+                       else
+                       {
+                               goto x_checkea_right;
+                       }
+               }
+
+               // 'X:eax,D1 Y:eay,D2', 'X:eax,D1 S2,Y:eay' or 'X:ea,D1 S2,D2'
+               // Check ahead for S2,D2 - if that's true then we have 'X:ea,D1 S2,D2'
+               if ((*tok == KW_X0 || *tok == KW_X1 || *tok == KW_A || *tok == KW_B) && (*(tok + 1) == KW_A || *(tok + 1) == KW_B) && (*(tok + 2) == ',') && (*(tok + 3) == KW_Y0 || (*(tok + 3) == KW_Y1)))
+               {
+                       // 'X:ea,D1 S2,D2'
+                       // Check if D1 is x0, x1, a or b
+                       switch (*tok++)
+                       {
+                       case KW_X0: D1 = 0 << 10; break;
+                       case KW_X1: D1 = 1 << 10; break;
+                       case KW_A:  D1 = 2 << 10; break;
+                       case KW_B:  D1 = 3 << 10; break;
+                       default:    return error("unrecognised X:R parallel move syntax: expected x0, x1, a or b after 'X:eax,'");
+                       }
+
+                       switch (*tok++)
+                       {
+                       case KW_A: S2 = 0 << 9; break;
+                       case KW_B: S2 = 1 << 9; break;
+                       default:   return error("unrecognised X:R parallel move syntax: expected a or b after 'X:eax,D1 '");
+                       }
+
+                       if (*tok++ != ',')
+                               return error("unrecognised X:R parallel move syntax: expected ',' after 'X:eax,D1 S2'");
+
+                       if (*tok == KW_Y0 || *tok == KW_Y1)
+                       {
+                               if (*tok++ == KW_Y0)
+                                       D2 = 0 << 8;
+                               else
+                                       D2 = 1 << 8;
+
+                               if (*tok != EOL)
+                                       return error("unrecognised X:R parallel move syntax: unexpected text after 'X:eax,D1 S2,S2'");
+
+                               inst = B16(00010000, 00000000) | (W << 7);
+                               inst |= ea1 | D1 | S2 | D2;
+                               return inst;
+                       }
+                       else
+                               return error("unrecognised X:R parallel move syntax: expected y0 or y1 after 'X:eax,D1 S2,'");
+               }
+
+               // Check to see if we got eax (which is a subset of ea)
+               if (check_for_x_y)
+               {
+                       if ((inst = check_x_y(ea1, 0)) != 0)
+                               return inst;
+                       else
+                       {
+                               // Rewind pointer as it might be an expression and check for it
+                               tok--;
+
+                               if (expr(dspaaEXPR, &dspaaEXVAL, &dspaaEXATTR, &dspaaESYM) != OK)
+                                       return ERROR;
+
+                               // Yes, we have an expression, so we now check for
+                               // 'X:ea,D' or 'X:aa,D' or 'X:ea,D1 S2,D2' or 'X:eax,D1 Y:eay,D2' or 'X:eax,D1 S2,Y:eay'
+                               goto x_check_immed;
+                       }
+               }
+       }
+       else if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
+       {
+               // Check for immediate address
+               if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+                       return ERROR;
+
+               // We set ea1 here - if it's aa instead of ea
+               // then it won't be used anyway
+               ea1 = DSP_EA_ABS;
+
+               if (!(dspImmedEXATTR&DEFINED))
+               {
+                       force_imm = NUM_FORCE_LONG;
+                       deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+               }
+
+               goto x_check_immed;
+       }
+       else if (*tok == '>')
+       {
+               // Check for immediate address forced long
+               tok++;
+
+               if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+                       return ERROR;
+
+               if (dspImmedEXATTR & DEFINED)
+                       if (dspImmedEXVAL > 0xffffff)
+                               return error("long address is bigger than $ffffff");
+
+               deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+
+               force_imm = NUM_FORCE_LONG;
+               ea1 = DSP_EA_ABS;
+               goto x_check_immed;
+       }
+       else if (*tok == '<')
+       {
+               // Check for immediate address forced short
+               tok++;
+
+               if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+                       return ERROR;
+
+               force_imm = NUM_FORCE_SHORT;
+
+               if (dspImmedEXATTR & DEFINED)
+               {
+                       if (dspImmedEXVAL > 0x3F)
+                       {
+                               warn("short addressing mode forced but address is bigger than $3F - switching to long");
+                               force_imm = NUM_FORCE_LONG;
+                               deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+                               ea1 = DSP_EA_ABS;
+                       }
+               }
+               else
+               {
+                       // This might end up as something like 'move Y:<adr,register'
+                       // so let's mark it as an extra aa fixup here.
+                       // Note: we are branching to x_check_immed without a
+                       // defined dspImmed so it's going to be 0. It probably
+                       // doesn't harm anything.
+                       deposit_extra_ea = DEPOSIT_EXTRA_FIXUP;
+               }
+
+               goto x_check_immed;
+       }
+
+       return error("unknown x: addressing mode");
 }
 
 
@@ -2309,228 +2397,235 @@ LONG checkea_full(const uint32_t termchar, const int strings)
 
 }
 
+
 //
 // Main routine to check parallel move modes.
-// It's quite complex so it's split into a few procedures (in fact most of the above ones).
-// A big effort was made so this can be managable and not too hacky, however one look at
-// the 56001 manual regarding parallel moves and you'll know that this is not an easy
-// problem to deal with!
-// dest=destination register from the main opcode. This must not be the same as D1 or D2
-// and that even goes for stuff like dest=A, D1=A0/1/2!!!
+// It's quite complex so it's split into a few procedures (in fact most of the
+// above ones). A big effort was made so this can be managable and not too
+// hacky, however one look at the 56001 manual regarding parallel moves and
+// you'll know that this is not an easy // problem to deal with!
+// dest=destination register from the main opcode. This must not be the same
+// as D1 or D2 and that even goes for stuff like dest=A, D1=A0/1/2!!!
 //
 LONG parmoves(WORD dest)
 {
-    int force_imm;          // Addressing mode force operator
-    int immreg;             // Immediate register destination
-    LONG inst;              // 16 bit bitfield that has the parallel move opcode
-    LONG S1, S2, D1, D2;    // Source and Destinations
-    LONG ea1;                          // ea bitfields
+       int force_imm;          // Addressing mode force operator
+       int immreg;             // Immediate register destination
+       LONG inst;              // 16 bit bitfield that has the parallel move opcode
+       LONG S1, S2, D1, D2;    // Source and Destinations
+       LONG ea1;                               // ea bitfields
+
+       if (*tok == EOL)
+       {
+               // No parallel move
+               return B16(00100000, 00000000);
+       }
+
+       if (*tok == '#')
+       {
+               // '#xxxxxx,D', '#xx,D'
+               tok++;
+               force_imm = NUM_NORMAL;
 
-    if (*tok == EOL)
-    {
-        // No parallel move
-        return B16(00100000, 00000000);
-    }
-    if (*tok == '#')
-    {
-        // '#xxxxxx,D', '#xx,D'
-        tok++;
-        force_imm = NUM_NORMAL;
-        if (*tok == '>')
-        {
-            force_imm = NUM_FORCE_LONG;
-            tok++;
-        }
-        else if (*tok == '<')
-        {
-            force_imm = NUM_FORCE_SHORT;
-            tok++;
-        }
+               if (*tok == '>')
+               {
+                       force_imm = NUM_FORCE_LONG;
+                       tok++;
+               }
+               else if (*tok == '<')
+               {
+                       force_imm = NUM_FORCE_SHORT;
+                       tok++;
+               }
 
-        if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
-            return ERROR;
+               if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+                       return ERROR;
 
-        if (*tok++ != ',')
-            return error("expected comma");
+               if (*tok++ != ',')
+                       return error("expected comma");
 
-        if (!((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2)))
-            return error("expected x0,x1,y0,y1,a0,b0,a2,b2,a1,b1,a,b,r0-r7,n0-n7 after immediate");
-        immreg = SDreg(*tok++);
+               if (!((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2)))
+                       return error("expected x0,x1,y0,y1,a0,b0,a2,b2,a1,b1,a,b,r0-r7,n0-n7 after immediate");
 
-        if (*tok == EOL)
-        {
-            if (!(dspImmedEXATTR & FLOAT))
-            {
-                if (dspImmedEXATTR & DEFINED)
-                {
-                    // From I parallel move:
-                    // "If the destination register D is X0, X1, Y0, Y1, A, or B, the 8-bit immediate short operand
-                    // is interpreted as a signed fraction and is stored in the specified destination register.
-                    // That is, the 8 - bit data is stored in the eight MS bits of the destination operand, and the
-                    // remaining bits of the destination operand D are zeroed."
-                    // The funny bit is that Motorola assembler can parse something like 'move #$FF0000,b' into an
-                    // I (immediate short move) - so let's do that as well then...
-                    if (((immreg >= 4 && immreg <= 7) || immreg == 14 || immreg == 15) && force_imm != NUM_FORCE_LONG)
-                    {
-                        if ((dspImmedEXVAL & 0xffff) == 0)
-                        {
-                            dspImmedEXVAL >>= 16;
-                        }
-                    }
-                    if (force_imm == NUM_FORCE_SHORT)
-                    {
-                        if (dspImmedEXVAL<0xff && (int32_t)dspImmedEXVAL>-0x100)
-                        {
-                            // '#xx,D'
-                            // value fits in 8 bits - immediate move
-                            inst = B16(00100000, 00000000) + (immreg << 8) + (uint32_t)dspImmedEXVAL;
-                            return inst;
-                        }
-                        else
-                        {
-                            warn("forced short immediate value doesn't fit in 8 bits - switching to long");
-                            force_imm = NUM_FORCE_LONG;
-                        }
-                    }
-                    if (force_imm == NUM_FORCE_LONG)
-                    {
-                        // '#xxxxxx,D'
-                        // it can either be
-                        // X or Y Data move. I don't think it matters much
-                        // which of the two it will be, so let's use X.
-                    deposit_immediate_long_with_register:
-                        inst = B16(01000000, 11110100);
-                        inst |= ((immreg & 0x18) << (12 - 3)) + ((immreg & 7) << 8);
-                        deposit_extra_ea = DEPOSIT_EXTRA_WORD;
-                        return inst;
-                    }
-                    if (((int32_t)dspImmedEXVAL < 0x100) && ((int32_t)dspImmedEXVAL >= -0x100))
-                    {
-                        // value fits in 8 bits - immediate move
-                    deposit_immediate_short_with_register:
-                        inst = B16(00100000, 00000000) + (immreg << 8) + (uint32_t)dspImmedEXVAL;
-                        return inst;
-                    }
-                    else
-                    {
-                        // value doesn't fit in 8 bits, so it can either be
-                        // X or Y Data move. I don't think it matters much
-                        // which of the two it will be, so let's use X:.
-                        // TODO: if we're just goto'ing perhaps the logic can be simplified
-                        goto deposit_immediate_long_with_register;
-                    }
-                }
-                else
-                {
-                    if (force_imm != NUM_FORCE_SHORT)
-                    {
-                        // '#xxxxxx,D'
-                        // TODO: if we're just goto'ing perhaps the logic can be simplified
-                        goto deposit_immediate_long_with_register;
-                    }
-                    else
-                    {
-                        // '#xx,D' - I mode
-                        // No visibility of the number so let's add a fixup for this
-                        AddFixup(FU_DSPIMM8, sloc, dspImmedEXPR);
-                        inst = B16(00100000, 00000000);
-                        inst |= ((immreg & 0x18) << (11 - 3)) + ((immreg & 7) << 8);
-                        return inst;
-                    }
+               immreg = SDreg(*tok++);
 
-                }
-            }
-            else
-            {
-                // Float constant
-                if (dspImmedEXATTR & DEFINED)
-                {
+               if (*tok == EOL)
+               {
+                       if (!(dspImmedEXATTR & FLOAT))
+                       {
+                               if (dspImmedEXATTR & DEFINED)
+                               {
+                                       // From I parallel move:
+                                       // "If the destination register D is X0, X1, Y0, Y1, A, or B, the 8-bit immediate short operand
+                                       // is interpreted as a signed fraction and is stored in the specified destination register.
+                                       // That is, the 8 - bit data is stored in the eight MS bits of the destination operand, and the
+                                       // remaining bits of the destination operand D are zeroed."
+                                       // The funny bit is that Motorola assembler can parse something like 'move #$FF0000,b' into an
+                                       // I (immediate short move) - so let's do that as well then...
+                                       if (((immreg >= 4 && immreg <= 7) || immreg == 14 || immreg == 15) && force_imm != NUM_FORCE_LONG)
+                                       {
+                                               if ((dspImmedEXVAL & 0xffff) == 0)
+                                               {
+                                                       dspImmedEXVAL >>= 16;
+                                               }
+                                       }
+
+                                       if (force_imm == NUM_FORCE_SHORT)
+                                       {
+                                               if (dspImmedEXVAL < 0xFF && (int32_t)dspImmedEXVAL > -0x100)
+                                               {
+                                                       // '#xx,D'
+                                                       // value fits in 8 bits - immediate move
+                                                       inst = B16(00100000, 00000000) + (immreg << 8) + (uint32_t)dspImmedEXVAL;
+                                                       return inst;
+                                               }
+                                               else
+                                               {
+                                                       warn("forced short immediate value doesn't fit in 8 bits - switching to long");
+                                                       force_imm = NUM_FORCE_LONG;
+                                               }
+                                       }
+
+                                       if (force_imm == NUM_FORCE_LONG)
+                                       {
+                                               // '#xxxxxx,D'
+                                               // it can either be
+                                               // X or Y Data move. I don't think it matters much
+                                               // which of the two it will be, so let's use X.
+deposit_immediate_long_with_register:
+                                               inst = B16(01000000, 11110100);
+                                               inst |= ((immreg & 0x18) << (12 - 3)) + ((immreg & 7) << 8);
+                                               deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+                                               return inst;
+                                       }
+
+                                       if (((int32_t)dspImmedEXVAL < 0x100) && ((int32_t)dspImmedEXVAL >= -0x100))
+                                       {
+                                               // value fits in 8 bits - immediate move
+deposit_immediate_short_with_register:
+                                               inst = B16(00100000, 00000000) + (immreg << 8) + (uint32_t)dspImmedEXVAL;
+                                               return inst;
+                                       }
+                                       else
+                                       {
+                                               // value doesn't fit in 8 bits, so it can either be
+                                               // X or Y Data move. I don't think it matters much
+                                               // which of the two it will be, so let's use X:.
+                                               // TODO: if we're just goto'ing perhaps the logic can be simplified
+                                               goto deposit_immediate_long_with_register;
+                                       }
+                               }
+                               else
+                               {
+                                       if (force_imm != NUM_FORCE_SHORT)
+                                       {
+                                               // '#xxxxxx,D'
+                                               // TODO: if we're just goto'ing perhaps the logic can be simplified
+                                               goto deposit_immediate_long_with_register;
+                                       }
+                                       else
+                                       {
+                                               // '#xx,D' - I mode
+                                               // No visibility of the number so let's add a fixup for this
+                                               AddFixup(FU_DSPIMM8, sloc, dspImmedEXPR);
+                                               inst = B16(00100000, 00000000);
+                                               inst |= ((immreg & 0x18) << (11 - 3)) + ((immreg & 7) << 8);
+                                               return inst;
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               // Float constant
+                               if (dspImmedEXATTR & DEFINED)
+                               {
+                                       double f = *(double *)&dspImmedEXVAL;
+                                       // Check direct.c for ossom comments regarding conversion!
+//N.B.: This is bogus, we need to fix this so it does this the right way... !!! FIX !!!
+                                       dspImmedEXVAL = ((uint32_t)(int32_t)round(f * (1 << 23))) & 0xFFFFFF;
+                                       double g;
+                                       g = f * (1 << 23);
+                                       g = round(g);
+
+                                       if ((dspImmedEXVAL & 0xFFFF) == 0)
+                                       {
+                                               // Value's 16 lower bits are not set so the value can fit in a single byte
+                                               // (check parallel I move quoted above)
+                                               warn("Immediate value fits inside 8 bits, so using instruction short format");
+                                               dspImmedEXVAL >>= 16;
+                                               goto deposit_immediate_short_with_register;
+                                       }
 
-                    double f = *(double *)&dspImmedEXVAL;
-                    // Check direct.c for ossom comments regarding conversion!
-                    dspImmedEXVAL = ((uint32_t)(int32_t)round(f*(1 << 23))) & 0xffffff;
-                    double g;
-                    g = f*(1 << 23);
-                    g = round(g);
+                                       if (force_imm == NUM_FORCE_SHORT)
+                                       {
+                                               if ((dspImmedEXVAL & 0xFFFF) != 0)
+                                               {
+                                                       warn("Immediate value short format forced but value does not fit inside 8 bits - switching to long format");
+                                                       goto deposit_immediate_long_with_register;
+                                               }
 
-                    if ((dspImmedEXVAL & 0xffff) == 0)
-                    {
-                        // Value's 16 lower bits are not set so the value can fit in a single byte
-                        // (check parallel I move quoted above)
-                        warn("Immediate value fits inside 8 bits, so using instruction short format");
-                        dspImmedEXVAL >>= 16;
-                        goto deposit_immediate_short_with_register;
-                    }
+                                               return error("internal assembler error: we haven't implemented floating point constants in parallel mode parser yet!");
+                                       }
 
-                    if (force_imm == NUM_FORCE_SHORT)
-                    {
-                        if ((dspImmedEXVAL & 0xffff) != 0)
-                        {
-                            warn("Immediate value short format forced but value does not fit inside 8 bits - switching to long format");
-                            goto deposit_immediate_long_with_register;
-                        }
-                        return error("internal assembler error: we haven't implemented floating point constants in parallel mode parser yet!");
-                    }
-                    // If we reach here we either have NUM_FORCE_LONG or nothing, so we might as well store a long.
-                    goto deposit_immediate_long_with_register;
-                }
-                else
-                {
-                    if (force_imm == NUM_FORCE_SHORT)
-                    {
+                                       // If we reach here we either have NUM_FORCE_LONG or nothing, so we might as well store a long.
+                                       goto deposit_immediate_long_with_register;
+                               }
+                               else
+                               {
+                                       if (force_imm == NUM_FORCE_SHORT)
+                                       {
                                                goto deposit_immediate_short_with_register;
-                    }
-                    else
-                    {
-                        // Just deposit a float fixup
-                        AddFixup(FU_DSPIMMFL8, sloc, dspImmedEXPR);
-                        inst = B16(00100000, 00000000);
-                        inst |= ((immreg & 0x18) << (12 - 3)) + ((immreg & 7) << 8);
-                        return inst;
-                    }
-                }
-            }
-        }
-        else
-        {
-            // At this point we can only have '#xxxxxx,D1 S2,D2' (X:R Class I)
-
-            switch (immreg)
-            {
-            case 4: D1 = 0 << 10;break;  // X0
-            case 5: D1 = 1 << 10;break;  // X1
-            case 14: D1 = 2 << 10;break; // A
-            case 15: D1 = 3 << 10;break; // B
-            default: return error("unrecognised X:R parallel move syntax: D1 can only be x0,x1,a,b in '#xxxxxx,D1 S2,D2'"); break;
-            }
+                                       }
+                                       else
+                                       {
+                                               // Just deposit a float fixup
+                                               AddFixup(FU_DSPIMMFL8, sloc, dspImmedEXPR);
+                                               inst = B16(00100000, 00000000);
+                                               inst |= ((immreg & 0x18) << (12 - 3)) + ((immreg & 7) << 8);
+                                               return inst;
+                                       }
+                               }
+                       }
+               }
+               else
+               {
+                       // At this point we can only have '#xxxxxx,D1 S2,D2' (X:R Class I)
+                       switch (immreg)
+                       {
+                       case 4: D1 = 0 << 10;break;  // X0
+                       case 5: D1 = 1 << 10;break;  // X1
+                       case 14: D1 = 2 << 10;break; // A
+                       case 15: D1 = 3 << 10;break; // B
+                       default: return error("unrecognised X:R parallel move syntax: D1 can only be x0,x1,a,b in '#xxxxxx,D1 S2,D2'"); break;
+                       }
 
-            switch (*tok++)
-            {
-            case KW_A: S2 = 0 << 9; break;
-            case KW_B: S2 = 1 << 9; break;
-            default: return error("unrecognised X:R parallel move syntax: S2 can only be A or B in '#xxxxxx,D1 S2,D2'"); break;
-            }
+                       switch (*tok++)
+                       {
+                       case KW_A: S2 = 0 << 9; break;
+                       case KW_B: S2 = 1 << 9; break;
+                       default: return error("unrecognised X:R parallel move syntax: S2 can only be A or B in '#xxxxxx,D1 S2,D2'"); break;
+                       }
 
-            if (*tok++ != ',')
-                return error("unrecognised X:R parallel move syntax: expected comma after '#xxxxxx,D1 S2'");
+                       if (*tok++ != ',')
+                               return error("unrecognised X:R parallel move syntax: expected comma after '#xxxxxx,D1 S2'");
 
-            switch (*tok++)
-            {
-            case KW_Y0: D2 = 0 << 8; break;
-            case KW_Y1: D2 = 1 << 8; break;
-            default: return error("unrecognised X:R parallel move syntax: D2 can only be Y0 or Y1 in '#xxxxxx,D1 S2,D2'"); break;
-            }
+                       switch (*tok++)
+                       {
+                       case KW_Y0: D2 = 0 << 8; break;
+                       case KW_Y1: D2 = 1 << 8; break;
+                       default: return error("unrecognised X:R parallel move syntax: D2 can only be Y0 or Y1 in '#xxxxxx,D1 S2,D2'"); break;
+                       }
 
-            if (*tok != EOL)
-                return error("unrecognised X:R parallel move syntax: expected end-of-line after '#xxxxxx,D1 S2,D2'");
+                       if (*tok != EOL)
+                               return error("unrecognised X:R parallel move syntax: expected end-of-line after '#xxxxxx,D1 S2,D2'");
 
-            inst = B16(00010000, 10110100) | D1 | S2 | D2;
-            deposit_extra_ea = DEPOSIT_EXTRA_WORD;
-            return inst;
-        }
-    }
-    else if (*tok == KW_X)
-    {
+                       inst = B16(00010000, 10110100) | D1 | S2 | D2;
+                       deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+                       return inst;
+               }
+       }
+       else if (*tok == KW_X)
+       {
                if (tok[1] == ',')
                        // Hey look, it's just the register X and not the addressing mode - fall through to general case
                        goto parse_everything_else;
@@ -2538,269 +2633,307 @@ LONG parmoves(WORD dest)
                tok++;
 
                if (*tok++ != ':')
-            return error("expected ':' after 'X' in parallel move (i.e. X:)");
+                       return error("expected ':' after 'X' in parallel move (i.e. X:)");
 
                // 'X:ea,D' or 'X:aa,D' or 'X:ea,D1 S2,D2' or 'X:eax,D1 Y:eay,D2' or 'X:eax,D1 S2,Y:eay'
                return parse_x(1, B16(01000000, 00000000), 0, 1);
-    }
-    else if (*tok == KW_Y)
-    {
+       }
+       else if (*tok == KW_Y)
+       {
                if (tok[1] == ',')
                        // Hey look, it's just the register y and not the addressing mode - fall through to general case
                        goto parse_everything_else;
 
                tok++;
+
                if (*tok++ != ':')
-            return error("expected ':' after 'Y' in parallel move (i.e. Y:)");
+                       return error("expected ':' after 'Y' in parallel move (i.e. Y:)");
 
                // 'Y:ea,D' or 'Y:aa,D'
-        return parse_y(B16(01001000, 10000000), 0, 0, 0);
-    }
-    else if (*tok == KW_L)
-    {
-        // 'L:ea,D' or 'L:aa,D'
-        tok++;
-        if (*tok++ != ':')
-            return error("expected ':' after 'L' in parallel move (i.e. L:)");
-
-        return parse_l(1, B16(01000000, 11000000), 0);
-    }
-    else if ((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2) || (*tok >= KW_A10 && *tok <= KW_BA))
-    {
-        // Everything else - brace for impact!
-        // R:   'S,D'
-        // X:   'S,X:ea' 'S,X:aa'
-        // X:R  'S,X:ea S2,D2' 'A,X:ea X0,A' 'B,X:ea X0,B'
-        // Y:   'S,Y:ea' 'S,Y:aa'
-        // R:Y: 'S1,D1 Y:ea,D2' 'S1,D1 S2,Y:ea' 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' 'S1,D1 #xxxxxx,D2' 'Y0,A A,Y:ea' 'Y0,B B,Y:ea'
-        // L:   'S,L:ea' 'S,L:aa'
+               return parse_y(B16(01001000, 10000000), 0, 0, 0);
+       }
+       else if (*tok == KW_L)
+       {
+               // 'L:ea,D' or 'L:aa,D'
+               tok++;
+               if (*tok++ != ':')
+                       return error("expected ':' after 'L' in parallel move (i.e. L:)");
+
+               return parse_l(1, B16(01000000, 11000000), 0);
+       }
+       else if ((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2) || (*tok >= KW_A10 && *tok <= KW_BA))
+       {
+               // Everything else - brace for impact!
+               // R:   'S,D'
+               // X:   'S,X:ea' 'S,X:aa'
+               // X:R  'S,X:ea S2,D2' 'A,X:ea X0,A' 'B,X:ea X0,B'
+               // Y:   'S,Y:ea' 'S,Y:aa'
+               // R:Y: 'S1,D1 Y:ea,D2' 'S1,D1 S2,Y:ea' 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' 'S1,D1 #xxxxxx,D2' 'Y0,A A,Y:ea' 'Y0,B B,Y:ea'
+               // L:   'S,L:ea' 'S,L:aa'
                LONG L_S1;
 parse_everything_else:
                L_S1 = *tok++;
                S1 = SDreg(L_S1);
 
-        if (*tok++ != ',')
-            return error("Comma expected after 'S')");
+               if (*tok++ != ',')
+                       return error("Comma expected after 'S')");
 
-        if (*tok == KW_X)
-        {
-            // 'S,X:ea' 'S,X:aa' 'S,X:ea S2,D2' 'S1,X:eax Y:eay,D2' 'S1,X:eax S2,Y:eay'
-            // 'A,X:ea X0,A' 'B,X:ea X0,B'
-            tok++;
-            if (*tok++ != ':')
-                return error("unrecognised X: parallel move syntax: expected ':' after 'S,X'");
-            return parse_x(0, B16(01000000, 00000000), S1, 1);
-        }
-        else if (*tok == KW_Y)
-        {
-            // 'S,Y:ea' 'S,Y:aa'
-            tok++;
-            if (*tok++ != ':')
-                return error("unrecognised Y: parallel move syntax: expected ':' after 'S,Y'");
-            return parse_y(B16(0000000, 00000000), S1, 0, 0);
-        }
-        else if (*tok == KW_L)
-        {
-            // 'S,L:ea' 'S,L:aa'
-            tok++;
-            if (*tok++ != ':')
-                return error("unrecognised L: parallel move syntax: expected ':' after 'S,L'");
-            return parse_l(1, B16(00000000, 00000000), L_S1);
-        }
-        else if ((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2))
-        {
-            // 'S,D'
-            // 'S1,D1 Y:ea,D2' 'S1,D1 S2,Y:ea' 'S1,D1 #xxxxxx,D2'
-            // 'Y0,A A,Y:ea' 'Y0,B B,Y:ea'
-            D1 = SDreg(*tok++);
-            if (*tok == EOL)
-            {
-                // R 'S,D'
-                inst = B16(00100000, 00000000);
-                inst |= (S1 << 5) | (D1);
-                return inst;
-            }
-            else if (*tok == KW_Y)
-            {
-                // 'S1,D1 Y:ea,D2'
-                tok++;
-                if (*tok++ != ':')
-                    return error("expected ':' after 'Y' in parallel move (i.e. Y:)");
-                return parse_y(B16(00010000, 01000000), S1, D1, 0);
+               if (*tok == KW_X)
+               {
+                       // 'S,X:ea' 'S,X:aa' 'S,X:ea S2,D2' 'S1,X:eax Y:eay,D2' 'S1,X:eax S2,Y:eay'
+                       // 'A,X:ea X0,A' 'B,X:ea X0,B'
+                       tok++;
 
-            }
-            else if (*tok == KW_A || *tok == KW_B || *tok == KW_Y0 || *tok == KW_Y1)
-            {
-                // 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' 'S1,D1 S2,Y:ea'
-                S2 = SDreg(*tok++);
-                if (S1 == 6 && D1 == 14 && S2 == 14)
-                {
-                    // 'Y0,A A,Y:ea'
-                    if (*tok++ != ',')
-                        return error("unrecognised Y: parallel move syntax: expected ',' after Y0,A A");
-                    if (*tok++ != KW_Y)
-                        return error("unrecognised Y: parallel move syntax: expected 'Y' after Y0,A A,");
-                    if (*tok++ != ':')
-                        return error("unrecognised Y: parallel move syntax: expected ':' after Y0,A A,Y");
-                    ea1 = checkea_full(EOL, Y_ERRORS);
-                    if (ea1 == ERROR)
-                        return ERROR;
-                    inst = B16(00001000, 10000000);
-                    inst |= 0 << 8;
-                    inst |= ea1;
-                    return inst;
-                }
-                else if (S1 == 6 && D1 == 15 && S2 == 15)
-                {
-                    // 'Y0,B B,Y:ea'
-                    if (*tok++ != ',')
-                        return error("unrecognised Y: parallel move syntax: expected ',' after Y0,B B");
-                    if (*tok++ != KW_Y)
-                        return error("unrecognised Y: parallel move syntax: expected 'Y' after Y0,B B,");
-                    if (*tok++ != ':')
-                        return error("unrecognised Y: parallel move syntax: expected ':' after Y0,B B,Y");
-                    ea1 = checkea_full(EOL, Y_ERRORS);
-                    if (ea1 == ERROR)
-                        return ERROR;
-                    inst = B16(00001000, 10000000);
-                    inst |= 1 << 8;
-                    inst |= ea1;
-                    return inst;
-                }
-                else if ((S1 == 14 || S1 == 15) && (D1 == 4 || D1 == 5) && (S2 == 6 || S2 == 7 || S2 == 14 || S2 == 15))
-                {
-                    //'S1,D1 S2,Y:ea'
-                    if (*tok++ != ',')
-                        return error("unrecognised Y: parallel move syntax: expected ',' after S1,D1 S2");
-                    if (*tok++ != KW_Y)
-                        return error("unrecognised Y: parallel move syntax: expected 'Y' after S1,D1 S2,");
-                    if (*tok++ != ':')
-                        return error("unrecognised Y: parallel move syntax: expected ':' after S1,D1 S2,Y");
-                    ea1 = checkea_full(EOL, Y_ERRORS);
-                    if (ea1 == ERROR)
-                        return ERROR;
-                    inst = B16(00010000, 01000000);
-                    inst |= (S1 & 1) << 11;
-                    inst |= (D1 & 1) << 10;
-                    inst |= ((S2 & 8) << (10 - 4)) | ((S2 & 1) << 8);
-                    inst |= ea1;
-                    return inst;
-                }
-                else
-                    return error("unrecognised Y: parallel move syntax: only 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' allowed'");
-                // Check for Y:
-            }
-            else if (*tok == '#')
-            {
-                // R:Y: 'S1,D1 #xxxxxx,D2'
-                tok++;
-                if (*tok == '>')
-                {
-                    // Well, forcing an immediate to be 24 bits is legal here
-                    // but then it's the only available option so my guess is that this
-                    // is simply superfluous. So let's just eat the character
-                    tok++;
-                }
-                if (expr(dspaaEXPR, &dspaaEXVAL, &dspaaEXATTR, &dspaaESYM) != OK)
-                    return ERROR;
-                if (dspImmedEXATTR & DEFINED)
-                    if (dspImmedEXVAL > 0xffffff)
-                        return error("immediate is bigger than $ffffff");
-                deposit_extra_ea = DEPOSIT_EXTRA_WORD;
-                if (*tok++ != ',')
-                    return error("Comma expected after 'S1,D1 #xxxxxx')");
-                // S1 is a or b, D1 is x0 or x1 and d2 is y0, y1, a or b
-                switch (*tok++)
-                {
-                case KW_Y0: D2 = 0 << 8; break;
-                case KW_Y1: D2 = 1 << 8; break;
-                case KW_A:  D2 = 2 << 8; break;
-                case KW_B:  D2 = 3 << 8; break;
-                default:    return error("unrecognised R:Y: parallel move syntax: D2 must be y0, y1, a or b in 'S1,D1 #xxxxxx,D2'");
-                }
+                       if (*tok++ != ':')
+                               return error("unrecognised X: parallel move syntax: expected ':' after 'S,X'");
 
-                if (S1 == 14 || S1 == 15)
-                {
-                    if (D1 == 4 || D1 == 5)
-                    {
-                        inst = B16(00010000, 11110100);
-                        inst |= (S1 & 1) << 11;
-                        inst |= (D1 & 1) << 10;
-                        inst |= D2;
-                        dspImmedEXVAL = dspaaEXVAL;
-                        return inst;
-                    }
-                    else
-                        return error("unrecognised R:Y: parallel move syntax: D1 must be x0 or x1 in 'S1,D1 #xxxxxx,D2'");
-                }
-                else
-                    return error("unrecognised R:Y: parallel move syntax: S1 must be a or b in 'S1,D1 #xxxxxx,D2'");
-            }
-            else
-                return error("unrecognised R:Y: parallel move syntax: Unexpected text after S,D in 'S1,D1 #xxxxxx,D2'");
-        }
-        else
-            return error("unrecognised R:Y: parallel move syntax: Unexpected text after 'S,'");
-    }
-    else if (*tok == '(')
-    {
-        // U: 'ea'
-        // U 'ea' can only be '(Rn)-Nn', '(Rn)+Nn', '(Rn)-' or '(Rn)+'
-        tok++;
-        if (*tok >= KW_R0 && *tok <= KW_R7)
-        {
-            ea1 = (*tok++ - KW_R0);
-        }
-        else
-            return error("unrecognised U parallel move syntax: expected 'Rn' after '('");
-        if (*tok++ != ')')
-            return error("unrecognised U parallel move syntax: expected ')' after '(Rn'");
-        if (*tok == '+')
-        {
-            tok++;
-            if (*tok == EOL)
-                // (Rn)+
-                ea1 |= 3 << 3;
-            else if (*tok >= KW_N0 && *tok <= KW_N7)
-            {
-                // (Rn)+Nn
-                if ((*tok++ & 7) != ea1)
-                    return error("unrecognised U parallel move syntax: Same register number expected for Rn, Nn in '(Rn)+Nn')");
-                ea1 |= 1 << 3;
-                if (*tok != EOL)
-                    return error("unrecognised U parallel move syntax: expected End-Of-Line after '(Rn)+Nn'");
-            }
-            else
-                return error("unrecognised U parallel move syntax: expected End-Of-Line or 'Nn' after '(Rn)+'");
+                       return parse_x(0, B16(01000000, 00000000), S1, 1);
+               }
+               else if (*tok == KW_Y)
+               {
+                       // 'S,Y:ea' 'S,Y:aa'
+                       tok++;
 
-        }
-        else if (*tok == '-')
-        {
-            tok++;
-            if (*tok == EOL)
-            {
-                // (Rn)-
-                ea1 |= 2 << 3;
-                tok++;
-            }
-            else if (*tok >= KW_N0 && *tok <= KW_N7)
-            {
-                // (Rn)-Nn
-                if ((*tok++ & 7) != ea1)
-                    return error("unrecognised U parallel move syntax: Same register number expected for Rn, Nn in '(Rn)-Nn')");
-                ea1 |= 0 << 3;
-                if (*tok != EOL)
-                    return error("unrecognised U parallel move syntax: expected End-Of-Line after '(Rn)-Nn'");
-            }
-        }
+                       if (*tok++ != ':')
+                               return error("unrecognised Y: parallel move syntax: expected ':' after 'S,Y'");
 
-        inst = B16(00100000, 01000000);
-        inst |= ea1;
-        return inst;
-    }
-    else
-        return error("extra (unexpected) text found");
+                       return parse_y(B16(0000000, 00000000), S1, 0, 0);
+               }
+               else if (*tok == KW_L)
+               {
+                       // 'S,L:ea' 'S,L:aa'
+                       tok++;
+
+                       if (*tok++ != ':')
+                               return error("unrecognised L: parallel move syntax: expected ':' after 'S,L'");
+
+                       return parse_l(1, B16(00000000, 00000000), L_S1);
+               }
+               else if ((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2))
+               {
+                       // 'S,D'
+                       // 'S1,D1 Y:ea,D2' 'S1,D1 S2,Y:ea' 'S1,D1 #xxxxxx,D2'
+                       // 'Y0,A A,Y:ea' 'Y0,B B,Y:ea'
+                       D1 = SDreg(*tok++);
+
+                       if (*tok == EOL)
+                       {
+                               // R 'S,D'
+                               inst = B16(00100000, 00000000);
+                               inst |= (S1 << 5) | (D1);
+                               return inst;
+                       }
+                       else if (*tok == KW_Y)
+                       {
+                               // 'S1,D1 Y:ea,D2'
+                               tok++;
+                               if (*tok++ != ':')
+                                       return error("expected ':' after 'Y' in parallel move (i.e. Y:)");
+                               return parse_y(B16(00010000, 01000000), S1, D1, 0);
+
+                       }
+                       else if (*tok == KW_A || *tok == KW_B || *tok == KW_Y0 || *tok == KW_Y1)
+                       {
+                               // 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' 'S1,D1 S2,Y:ea'
+                               S2 = SDreg(*tok++);
+
+                               if (S1 == 6 && D1 == 14 && S2 == 14)
+                               {
+                                       // 'Y0,A A,Y:ea'
+                                       if (*tok++ != ',')
+                                               return error("unrecognised Y: parallel move syntax: expected ',' after Y0,A A");
+
+                                       if (*tok++ != KW_Y)
+                                               return error("unrecognised Y: parallel move syntax: expected 'Y' after Y0,A A,");
+
+                                       if (*tok++ != ':')
+                                               return error("unrecognised Y: parallel move syntax: expected ':' after Y0,A A,Y");
+
+                                       ea1 = checkea_full(EOL, Y_ERRORS);
+
+                                       if (ea1 == ERROR)
+                                               return ERROR;
+
+                                       inst = B16(00001000, 10000000);
+                                       inst |= 0 << 8;
+                                       inst |= ea1;
+                                       return inst;
+                               }
+                               else if (S1 == 6 && D1 == 15 && S2 == 15)
+                               {
+                                       // 'Y0,B B,Y:ea'
+                                       if (*tok++ != ',')
+                                               return error("unrecognised Y: parallel move syntax: expected ',' after Y0,B B");
+
+                                       if (*tok++ != KW_Y)
+                                               return error("unrecognised Y: parallel move syntax: expected 'Y' after Y0,B B,");
+
+                                       if (*tok++ != ':')
+                                               return error("unrecognised Y: parallel move syntax: expected ':' after Y0,B B,Y");
+
+                                       ea1 = checkea_full(EOL, Y_ERRORS);
+
+                                       if (ea1 == ERROR)
+                                               return ERROR;
+
+                                       inst = B16(00001000, 10000000);
+                                       inst |= 1 << 8;
+                                       inst |= ea1;
+                                       return inst;
+                               }
+                               else if ((S1 == 14 || S1 == 15) && (D1 == 4 || D1 == 5) && (S2 == 6 || S2 == 7 || S2 == 14 || S2 == 15))
+                               {
+                                       //'S1,D1 S2,Y:ea'
+                                       if (*tok++ != ',')
+                                               return error("unrecognised Y: parallel move syntax: expected ',' after S1,D1 S2");
+
+                                       if (*tok++ != KW_Y)
+                                               return error("unrecognised Y: parallel move syntax: expected 'Y' after S1,D1 S2,");
+
+                                       if (*tok++ != ':')
+                                               return error("unrecognised Y: parallel move syntax: expected ':' after S1,D1 S2,Y");
+
+                                       ea1 = checkea_full(EOL, Y_ERRORS);
+
+                                       if (ea1 == ERROR)
+                                               return ERROR;
+
+                                       inst = B16(00010000, 01000000);
+                                       inst |= (S1 & 1) << 11;
+                                       inst |= (D1 & 1) << 10;
+                                       inst |= ((S2 & 8) << (10 - 4)) | ((S2 & 1) << 8);
+                                       inst |= ea1;
+                                       return inst;
+                               }
+                               else
+                                       return error("unrecognised Y: parallel move syntax: only 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' allowed'");
+                               // Check for Y:
+                       }
+                       else if (*tok == '#')
+                       {
+                               // R:Y: 'S1,D1 #xxxxxx,D2'
+                               tok++;
+
+                               if (*tok == '>')
+                               {
+                                       // Well, forcing an immediate to be 24 bits is legal here
+                                       // but then it's the only available option so my guess is that this
+                                       // is simply superfluous. So let's just eat the character
+                                       tok++;
+                               }
+
+                               if (expr(dspaaEXPR, &dspaaEXVAL, &dspaaEXATTR, &dspaaESYM) != OK)
+                                       return ERROR;
+
+                               if (dspImmedEXATTR & DEFINED)
+                                       if (dspImmedEXVAL > 0xffffff)
+                                               return error("immediate is bigger than $ffffff");
+
+                               deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+
+                               if (*tok++ != ',')
+                                       return error("Comma expected after 'S1,D1 #xxxxxx')");
+
+                               // S1 is a or b, D1 is x0 or x1 and d2 is y0, y1, a or b
+                               switch (*tok++)
+                               {
+                               case KW_Y0: D2 = 0 << 8; break;
+                               case KW_Y1: D2 = 1 << 8; break;
+                               case KW_A:  D2 = 2 << 8; break;
+                               case KW_B:  D2 = 3 << 8; break;
+                               default:    return error("unrecognised R:Y: parallel move syntax: D2 must be y0, y1, a or b in 'S1,D1 #xxxxxx,D2'");
+                               }
+
+                               if (S1 == 14 || S1 == 15)
+                               {
+                                       if (D1 == 4 || D1 == 5)
+                                       {
+                                               inst = B16(00010000, 11110100);
+                                               inst |= (S1 & 1) << 11;
+                                               inst |= (D1 & 1) << 10;
+                                               inst |= D2;
+                                               dspImmedEXVAL = dspaaEXVAL;
+                                               return inst;
+                                       }
+                                       else
+                                               return error("unrecognised R:Y: parallel move syntax: D1 must be x0 or x1 in 'S1,D1 #xxxxxx,D2'");
+                               }
+                               else
+                                       return error("unrecognised R:Y: parallel move syntax: S1 must be a or b in 'S1,D1 #xxxxxx,D2'");
+                       }
+                       else
+                               return error("unrecognised R:Y: parallel move syntax: Unexpected text after S,D in 'S1,D1 #xxxxxx,D2'");
+               }
+               else
+                       return error("unrecognised R:Y: parallel move syntax: Unexpected text after 'S,'");
+       }
+       else if (*tok == '(')
+       {
+               // U: 'ea'
+               // U 'ea' can only be '(Rn)-Nn', '(Rn)+Nn', '(Rn)-' or '(Rn)+'
+               tok++;
+
+               if (*tok >= KW_R0 && *tok <= KW_R7)
+               {
+                       ea1 = (*tok++ - KW_R0);
+               }
+               else
+                       return error("unrecognised U parallel move syntax: expected 'Rn' after '('");
+
+               if (*tok++ != ')')
+                       return error("unrecognised U parallel move syntax: expected ')' after '(Rn'");
+
+               if (*tok == '+')
+               {
+                       tok++;
+
+                       if (*tok == EOL)
+                               // (Rn)+
+                               ea1 |= 3 << 3;
+                       else if (*tok >= KW_N0 && *tok <= KW_N7)
+                       {
+                               // (Rn)+Nn
+                               if ((*tok++ & 7) != ea1)
+                                       return error("unrecognised U parallel move syntax: Same register number expected for Rn, Nn in '(Rn)+Nn')");
+
+                               ea1 |= 1 << 3;
+
+                               if (*tok != EOL)
+                                       return error("unrecognised U parallel move syntax: expected End-Of-Line after '(Rn)+Nn'");
+                       }
+                       else
+                               return error("unrecognised U parallel move syntax: expected End-Of-Line or 'Nn' after '(Rn)+'");
+               }
+               else if (*tok == '-')
+               {
+                       tok++;
+
+                       if (*tok == EOL)
+                       {
+                               // (Rn)-
+                               ea1 |= 2 << 3;
+                               tok++;
+                       }
+                       else if (*tok >= KW_N0 && *tok <= KW_N7)
+                       {
+                               // (Rn)-Nn
+                               if ((*tok++ & 7) != ea1)
+                                       return error("unrecognised U parallel move syntax: Same register number expected for Rn, Nn in '(Rn)-Nn')");
+
+                               ea1 |= 0 << 3;
+
+                               if (*tok != EOL)
+                                       return error("unrecognised U parallel move syntax: expected End-Of-Line after '(Rn)-Nn'");
+                       }
+               }
+
+               inst = B16(00100000, 01000000);
+               inst |= ea1;
+               return inst;
+       }
+       else
+               return error("extra (unexpected) text found");
 
-    return OK;
+       return OK;
 }
 
diff --git a/error.c b/error.c
index 6db7ad0f29c29d3d7261fafcd9f15dad2888222d..81983b14afecc912d844c54385619cf0758f2153 100644 (file)
--- a/error.c
+++ b/error.c
 #include "listing.h"
 #include "token.h"
 
+// Exported variables
 int errcnt;                                            // Error count
 char * err_fname;                              // Name of error message file
 
+// Internal variables
 static long unused;                            // For supressing 'write' warnings
 
 
 //
 // Report error if not at EOL
+//
 // N.B.: Since this should *never* happen, we can feel free to add whatever
 //       diagnostics that will help in tracking down a problem to this function.
 //
-int at_eol(void)
+int ErrorIfNotAtEOL(void)
 {
        if (*tok != EOL)
        {
@@ -40,9 +43,9 @@ int at_eol(void)
 //
 // Cannot create a file
 //
-void cantcreat(const char * fn)
+void CantCreateFile(const char * fn)
 {
-       printf("cannot create: '%s'\n", fn);
+       printf("Cannot create file: '%s'\n", fn);
        exit(1);
 }
 
@@ -66,7 +69,7 @@ void err_setup(void)
                err_fname = NULL;
 
                if ((err_fd = open(fnbuf, _OPEN_FLAGS, _PERM_MODE)) < 0)
-                       cantcreat(fnbuf);
+                       CantCreateFile(fnbuf);
 
                err_flag = 1;
        }
diff --git a/error.h b/error.h
index be072d56cf3d3b604d7fdd110245197e51b07c5d..5dec21e061acac989ea5bd025d419f6a5e576def 100644 (file)
--- a/error.h
+++ b/error.h
@@ -22,9 +22,9 @@ int error(const char *, ...);
 int warn(const char *, ...);
 int fatal(const char *);
 int interror(int);
-void cantcreat(const char *);
+void CantCreateFile(const char *);
 void err_setup(void);
-int at_eol(void);
+int ErrorIfNotAtEOL(void);
 
 #endif // __ERROR_H__
 
index 87956af889aba508e531149fc16b7dcce20ebce7..3e89ad514022a8d62a5ace76b59deb687b29db06 100644 (file)
--- a/listing.c
+++ b/listing.c
@@ -178,7 +178,7 @@ void list_setup(void)
        list_fname = NULL;
 
        if ((list_fd = open(fnbuf, _OPEN_FLAGS, _PERM_MODE)) < 0)
-               cantcreat(fnbuf);
+               CantCreateFile(fnbuf);
 }
 
 
diff --git a/macro.c b/macro.c
index 8d5d88e9b4f0ffe9ad1d8fdadb270181810aa8eb..4d63f2fa5cc58d61c4e125660ff8ed3d772574f1 100644 (file)
--- a/macro.c
+++ b/macro.c
@@ -172,7 +172,7 @@ int DefineMacro(void)
        {
                argno = 0;
                symlist(defmac2);
-               at_eol();
+               ErrorIfNotAtEOL();
        }
 
        // Suck in the macro definition; we're looking for an ENDM symbol on a line
index bee4fd60febb432fb79f91465a13b3e6fe6494af..29fd8f3ce0d672e42757eed92131ccfd47b6461d 100644 (file)
--- a/object.c
+++ b/object.c
@@ -9,11 +9,13 @@
 #include "object.h"
 #include "6502.h"
 #include "direct.h"
+#include "dsp56k.h"
 #include "error.h"
 #include "mark.h"
 #include "riscasm.h"
 #include "sect.h"
 #include "symbol.h"
+#include "version.h"
 
 //#define DEBUG_ELF
 
@@ -56,6 +58,10 @@ See left.            4 & 5   If these bits are set to 0 (PF_PRIVATE), the processes'
 -                              6-15    Currently unused
 */
 
+// Internal function prototypes
+static void WriteLOD(void);
+static void WriteP56(void);
+
 
 //
 // Add entry to symbol table (in ALCYON mode)
@@ -351,6 +357,7 @@ int WriteObject(int fd)
 
                if (strtable == NULL)
                {
+                       free(buf);
                        error("cannot allocate string table memory (in BSD mode)");
                        return ERROR;
                }
@@ -359,6 +366,8 @@ int WriteObject(int fd)
 
                // Build object file header
                chptr = buf;                                    // Base of header (for D_foo macros)
+               ch_size = 0;
+               challoc = 0x800000;
                D_long(0x00000107);                             // Magic number
                D_long(sect[TEXT].sloc);                // TEXT size
                D_long(sect[DATA].sloc);                // DATA size
@@ -440,6 +449,8 @@ int WriteObject(int fd)
 
                // Build object file header just before the text+data image
                chptr = buf;                            // -> base of header
+               ch_size = 0;
+               challoc = HDRSIZE + tds + symbolMaxSize;
                D_word(0x601A);                         // 00 - magic number
                D_long(sect[TEXT].sloc);        // 02 - TEXT size
                D_long(sect[DATA].sloc);        // 06 - DATA size
@@ -592,6 +603,8 @@ for(int j=0; j<i; j++)
                // If you want to make any sense out of this you'd better take a look
                // at Executable and Linkable Format on Wikipedia.
                chptr = buf;
+               ch_size = 0;
+               challoc = 0x600000;
                D_long(0x7F454C46); // 00 - "<7F>ELF" Magic Number
                D_byte(0x01); // 04 - 32 vs 64 (1 = 32, 2 = 64)
                D_byte(0x02); // 05 - Endianness (1 = LE, 2 = BE)
@@ -774,7 +787,174 @@ for(int j=0; j<i; j++)
                // Just write the object file
                m6502obj(fd);
        }
+       else if (obj_format == P56 || obj_format == LOD)
+       {
+               // Allocate 6MB object file image memory
+               uint8_t * buf = malloc(0x600000);
+
+               if (buf == NULL)
+                       return error("cannot allocate object file memory (in P56/LOD mode)");
+
+//             objImage = buf;                                 // Set global object image pointer
+
+               memset(buf, 0, 0x600000);               // Clear allocated memory
+
+               // Iterate through DSP ram buffers
+               chptr = buf;                                    // -> base of header
+               ch_size = 0;
+               challoc = 0x600000;
+
+               if (obj_format == LOD)
+                       WriteLOD();
+               else
+                       WriteP56();
+
+               // Write all the things |o/
+               ssize_t unused = write(fd, buf, chptr - buf);
+
+               if (buf)
+                       free(buf);
+       }
 
        return 0;
 }
 
+
+static void WriteLOD(void)
+{
+       D_printf("_START %s 0000 0000 0000 RMAC %01i.%01i.%01i\n\n", firstfname, MAJOR, MINOR, PATCH);
+
+       for(DSP_ORG * l=&dsp_orgmap[0]; l<dsp_currentorg; l++)
+       {
+               if (l->end != l->start)
+               {
+                       switch (l->memtype)
+                       {
+                       case ORG_P: D_printf("_DATA P %.4X\n", l->orgadr); break;
+                       case ORG_X: D_printf("_DATA X %.4X\n", l->orgadr); break;
+                       case ORG_Y: D_printf("_DATA Y %.4X\n", l->orgadr); break;
+                       case ORG_L: D_printf("_DATA L %.4X\n", l->orgadr); break;
+                       default:
+                               error("Internal error: unknown DSP56001 org'd section");
+                               return;
+                       }
+
+                       CHUNK * cp = l->chunk;
+                       uint8_t * p_chunk = l->start;
+                       uint8_t * p_chunk_end = p_chunk;
+                       uint32_t j = 0;
+
+                       while (p_chunk_end != l->end)
+                       {
+                               if (l->end < (cp->chptr + cp->ch_size) && l->end > cp->chptr)
+                               {
+                                       // If the end of the section is inside the current chunk, just dump everything and stop
+                                       p_chunk_end = l->end;
+                               }
+                               else
+                               {
+                                       // If the end of the section is not inside the current chunk, just dump everything from the current chunk and move on to the next
+                                       p_chunk_end = cp->chptr + cp->ch_size;
+                               }
+
+                               uint32_t count = (uint32_t)(p_chunk_end - p_chunk);
+
+                               for(uint32_t i=0; i<count; i+=3)
+                               {
+                                       if ((j & 7) != 7)
+                                       {
+                                               D_printf("%.6X ", (((p_chunk[0] << 8) | p_chunk[1]) << 8) | p_chunk[2]);
+                                       }
+                                       else
+                                       {
+                                               D_printf("%.6X\n", (((p_chunk[0] << 8) | p_chunk[1]) << 8) | p_chunk[2]);
+                                       }
+
+                                       p_chunk += 3;
+                                       j++;
+                               }
+
+                               cp = cp->chnext;        // Advance chunk
+
+                               if (cp != NULL)
+                                       p_chunk = cp->chptr;    // Set dump pointer to start of this chunk
+                       }
+
+                       if ((j & 7) != 0)
+                               D_printf("\n");
+               }
+       }
+
+       // Dump the symbol table into the buf
+       DumpLODSymbols();
+
+       D_printf("\n_END %.4X\n", dsp_orgmap[0].orgadr);
+}
+
+
+static void WriteP56(void)
+{
+       for(DSP_ORG * l=&dsp_orgmap[0]; l<dsp_currentorg; l++)
+       {
+               if (l->end == l->start)
+                       continue;
+
+               if ((l->memtype < ORG_P) || (l->memtype > ORG_L))
+               {
+                       error("Internal error: unknown DSP56001 org'd section");
+                       return;
+               }
+
+               CHUNK * cp = l->chunk;
+               uint8_t * p_chunk = l->start;
+               uint8_t * p_chunk_end = p_chunk;
+
+               // Memory type (P, X, Y or L)
+               D_dsp(l->memtype);
+
+               // Chunk start address (in DSP words)
+               D_dsp(l->orgadr);
+
+               // Chunk length (in DSP words)
+               // We'll fill this field after we write the chunk so we can calculate
+               // how long it is (so if the chunk is split into different CHUNKs we
+               // can deal with this during copy)
+               uint8_t * p_buf_len = chptr;
+               chptr += 3;
+
+               // The chunk itself
+               uint32_t chunk_size = 0;
+
+               while (p_chunk_end != l->end)
+               {
+                       if (l->end < (cp->chptr + cp->ch_size) && l->end > cp->chptr)
+                       {
+                               // If the end of the section is inside the current chunk, just
+                               // dump everything and stop
+                               p_chunk_end = l->end;
+                       }
+                       else
+                       {
+                               // If the end of the section is not inside the current chunk,
+                               // just dump everything from the current chunk and move on to
+                               // the next
+                               p_chunk_end = cp->chptr + cp->ch_size;
+                       }
+
+                       uint32_t current_chunk_size = p_chunk_end - p_chunk;
+                       chunk_size += current_chunk_size;
+                       memcpy(chptr, p_chunk, current_chunk_size);
+                       chptr += current_chunk_size;
+
+                       cp = cp->chnext;        // Advance chunk
+
+                       if (cp != NULL)
+                               p_chunk = cp->chptr;    // Set dump pointer to start of this chunk
+               }
+
+               // Now we can mark the chunk's length (DSP word size is 24-bits, so
+               // the byte count needs to be divided by 3)
+               SETBE24(p_buf_len, chunk_size / 3);
+       }
+}
+
diff --git a/op.c b/op.c
index 6a78fbc01f6898a7b5ab05e39b7fab4caf1c1c48..836f4de173b01add2b452414574c98b9c5c13953 100644 (file)
--- a/op.c
+++ b/op.c
@@ -177,7 +177,7 @@ static int HandleBitmap(void)
                }
        }
 
-       at_eol();
+       ErrorIfNotAtEOL();
 
        uint64_t p1 = 0x00 | ((ypos * 2) << 3) | (iheight << 14) | (linkAddr << 21) | (dataAddr << 40);
        uint64_t p2 = xpos | (bpp << 12) | (pitch << 15) | (dwidth << 18) | (iwidth << 28) | (index << 38) | (flags << 45) | (firstpix << 49);
@@ -302,7 +302,7 @@ static int HandleScaledBitmap(void)
                }
        }
 
-       at_eol();
+       ErrorIfNotAtEOL();
 
        uint64_t p1 = 0x01 | ((ypos * 2) << 3) | (iheight << 14) | (linkAddr << 21) | (dataAddr << 40);
        uint64_t p2 = xpos | (bpp << 12) | (pitch << 15) | (dwidth << 18) | (iwidth << 28) | (index << 38) | (flags << 45) | (firstpix << 49);
@@ -345,7 +345,7 @@ static int HandleGPUObject(void)
        if (!(eattr & DEFINED))
                return error("bad expression in data");
 
-       at_eol();
+       ErrorIfNotAtEOL();
 
        uint64_t p1 = 0x02 | ((ypos * 2) << 3) | (eval << 14);
 
@@ -410,7 +410,7 @@ static int HandleBranch(void)
        if (!(eattr & DEFINED))
                AddFixup(FU_QUAD | FU_OBJLINK, sloc, exprbuf);
 
-       at_eol();
+       ErrorIfNotAtEOL();
 
        uint64_t p1 = 0x03 | (cc << 14) | ((ypos * 2) << 3) | ((eval & 0x3FFFF8) << 21);
 
@@ -468,7 +468,7 @@ static int HandleJump(void)
        if (!(eattr & DEFINED))
                AddFixup(FU_QUAD | FU_OBJLINK, sloc, exprbuf);
 
-       at_eol();
+       ErrorIfNotAtEOL();
 
        // This is "branch if VC < 2047", which pretty much guarantees the branch.
        uint64_t p1 = 0x03 | (1 << 14) | (0x7FF << 3) | ((eval & 0x3FFFF8) << 21);
index fe13aa760a822f649fd054805273c5ed3931cfc7..8917004b258d4cc6e74b7f2f6ecb751723486222 100644 (file)
--- a/procln.c
+++ b/procln.c
@@ -587,7 +587,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;
        }
 
@@ -782,11 +782,24 @@ When checking to see if it's already been equated, issue a warning.
                                parcode = 0;
                        }
 
+#if 1
                        while ((dsp_am0 & md->mn0) == 0 || (dsp_am1 & md->mn1) == 0)
                                md = &dsp56k_machtab[md->mncont];
 
                        (*md->mnfunc)(md->mninst | (parcode << 8));
                        goto loop;
+#else
+                       for(;;)
+                       {
+                               if ((dsp_am0 & md->mn0) != 0 && (dsp_am1 & md->mn1) != 0)
+                               {
+                                       (*md->mnfunc)(md->mninst|(parcode << 8));
+                                       goto loop;
+                               }
+
+                               md = &dsp56k_machtab[md->mncont];
+                       }
+#endif
                }
        }
 
index fea5153a9f1bb54dd45aa6b52da55562b47621e7..50fecf4e8e412b5a44f3f2b0684e2b9355f7b35a 100644 (file)
--- a/riscasm.c
+++ b/riscasm.c
@@ -258,7 +258,7 @@ int GenerateRISCCode(int state)
        // UNPACK
        case RI_ONE:
                reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
-               at_eol();
+               ErrorIfNotAtEOL();
                DepositRISCInstructionWord(parm, parm >> 6, reg2);
                break;
 
@@ -276,7 +276,7 @@ int GenerateRISCCode(int state)
                        altbankok = 1;                      // MOVETA
 
                reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
-               at_eol();
+               ErrorIfNotAtEOL();
                DepositRISCInstructionWord(parm, reg1, reg2);
                break;
 
@@ -338,7 +338,7 @@ int GenerateRISCCode(int state)
 
                CHECK_COMMA;
                reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
-               at_eol();
+               ErrorIfNotAtEOL();
                DepositRISCInstructionWord(parm, reg1, reg2);
                break;
 
@@ -387,7 +387,7 @@ int GenerateRISCCode(int state)
 
                CHECK_COMMA;
                reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
-               at_eol();
+               ErrorIfNotAtEOL();
 
                DepositRISCInstructionWord(parm, 0, reg2);
                val = WORDSWAP32(eval);
@@ -410,7 +410,7 @@ int GenerateRISCCode(int state)
 
                CHECK_COMMA;
                reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
-               at_eol();
+               ErrorIfNotAtEOL();
                DepositRISCInstructionWord(parm, reg1, reg2);
                break;
 
@@ -533,7 +533,7 @@ int GenerateRISCCode(int state)
                tok++;
                CHECK_COMMA;
                reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
-               at_eol();
+               ErrorIfNotAtEOL();
                DepositRISCInstructionWord(parm, reg1, reg2);
                break;
 
@@ -652,7 +652,7 @@ int GenerateRISCCode(int state)
                        return MalformedOpcode(MALF_RPAREN);
 
                tok++;
-               at_eol();
+               ErrorIfNotAtEOL();
                DepositRISCInstructionWord(parm, reg2, reg1);
                break;
 
@@ -670,7 +670,7 @@ int GenerateRISCCode(int state)
                tok++;
                CHECK_COMMA;
                reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO);
-               at_eol();
+               ErrorIfNotAtEOL();
                DepositRISCInstructionWord(parm, reg1, reg2);
                break;
 
@@ -689,7 +689,7 @@ int GenerateRISCCode(int state)
                        return MalformedOpcode(MALF_RPAREN);
 
                tok++;
-               at_eol();
+               ErrorIfNotAtEOL();
                DepositRISCInstructionWord(parm, reg2, reg1);
                break;
 
@@ -802,7 +802,7 @@ int GenerateRISCCode(int state)
                                return MalformedOpcode(MALF_RPAREN);
 
                        tok++;
-                       at_eol();
+                       ErrorIfNotAtEOL();
                }
 
                DepositRISCInstructionWord(parm, reg2, reg1);
diff --git a/rmac.c b/rmac.c
index ecc3adcdb51294eab38b80859044f2f68c117bed..3f021e7c495713f187d4193fd25a18bc5d191d7d 100644 (file)
--- a/rmac.c
+++ b/rmac.c
@@ -10,6 +10,7 @@
 #include "6502.h"
 #include "debug.h"
 #include "direct.h"
+#include "dsp56k.h"
 #include "error.h"
 #include "expr.h"
 #include "listing.h"
@@ -148,6 +149,8 @@ void DisplayHelp(void)
                "                    a: ALCYON (use this for ST)\n"
                "                    b: BSD (use this for Jaguar)\n"
                "                    e: ELF\n"
+               "                    p: P56 (use this for DSP56001 only)\n"
+               "                    l: LOD (use this for DSP56001 only)\n"
                "                    x: com/exe/xex (Atari 800)\n"
                "  -i[path]          Directory to search for include files\n"
                "  -l[filename]      Create an output listing file\n"
@@ -161,6 +164,7 @@ void DisplayHelp(void)
                "                    6502\n"
                "                    tom\n"
                "                    jerry\n"
+               "                    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"
@@ -358,6 +362,14 @@ int Process(int argc, char ** argv)
                                case 'E':
                                        obj_format = ELF;
                                        break;
+                case 'l':           // -fl = LOD
+                case 'L':
+                    obj_format = LOD;
+                    break;
+                case 'p':           // -fp = P56
+                case 'P':
+                    obj_format = P56;
+                                       break;
                                case 'x':                       // -fx = COM/EXE/XEX
                                case 'X':
                                        obj_format = XEX;
@@ -588,6 +600,7 @@ int Process(int argc, char ** argv)
        //    -  "foo.o" for linkable output;
        //    -  "foo.prg" for GEMDOS executable (-p flag).
        SaveSection();
+       int temp_section = cursect;
 
        for(i=TEXT; i<=BSS; i<<=1)
        {
@@ -613,6 +626,20 @@ int Process(int argc, char ** argv)
                currentorg += 2;
        }
 
+       // This looks like an awful kludge...  !!! FIX !!!
+       if (temp_section & (M56001P | M56001X | M56001Y))
+       {
+               SwitchSection(temp_section);
+
+               if (chptr != dsp_currentorg->start)
+               {
+                       dsp_currentorg->end = chptr;
+                       dsp_currentorg++;
+               }
+       }
+
+       SwitchSection(TEXT);
+
        if (objfname == NULL)
        {
                if (firstfname == NULL)
@@ -635,7 +662,7 @@ int Process(int argc, char ** argv)
        if (errcnt == 0)
        {
                if ((fd = open(objfname, _OPEN_FLAGS, _PERM_MODE)) < 0)
-                       cantcreat(objfname);
+                       CantCreateFile(objfname);
 
                if (verb_flag)
                {
diff --git a/rmac.h b/rmac.h
index 10e7e59aae29fc6bfddcbb0db31ceccaaaabc6f8..cd7d671f01a9201774e428a0a7a0af0aa5ed2853 100644 (file)
--- a/rmac.h
+++ b/rmac.h
        { (a)[(r + 0)] = (uint8_t)((v) & 0xFF); \
        (a)[(r + 1)] = (uint8_t)((v) >> 8); }
 
+// In DSP56001 mode, this is useful:
+#define SETBE24(a, v) \
+       { (a)[0] = (uint8_t)(((v) >> 16) & 0xFF); \
+       (a)[1] = (uint8_t)(((v) >> 8) & 0xFF); \
+       (a)[2] = (uint8_t)((v) & 0xFF); }
+
 // Byteswap crap
 #define BYTESWAP16(x) ((((x) & 0x00FF) << 8) | (((x) & 0xFF00) >> 8))
 #define BYTESWAP32(x) ((((x) & 0x000000FF) << 24) | (((x) & 0x0000FF00) << 8) | (((x) & 0x00FF0000) >> 8) | (((x) & 0xFF000000) >> 24))
@@ -218,12 +224,13 @@ PTR
 #define TEXT         0x0001            // Relative to text
 #define DATA         0x0002            // Relative to data
 #define BSS          0x0004            // Relative to BSS
+//OK, this is bad, mmkay? These are treated as indices into an array which means that this was never meant to be defined this way--at least if it was, it was a compromise that has come home to bite us all in the ass.  !!! FIX !!!
 #define M6502        0x0008            // 6502/microprocessor (absolute)
 #define M56001P      0x0010            // DSP 56001 Program RAM
 #define M56001X      0x0020            // DSP 56001 X RAM
 #define M56001Y      0x0040            // DSP 56001 Y RAM
 #define M56001L      0x0080            // DSP 56001 L RAM
-#define TDB          (TEXT|DATA|BSS)   // Mask for text+data+bss
+#define TDB          (TEXT|DATA|BSS)   // Mask for TEXT+DATA+BSS
 #define M56KPXYL     (M56001P|M56001X|M56001Y|M56001L) // Mask for 56K stuff
 
 // Sizes
diff --git a/sect.c b/sect.c
index 9c1a586b18dbd68d92bf3b06cf9edf72e2432776..49806a02b9d4e8d7570b19b5d27f35ca89b6dc86 100644 (file)
--- a/sect.c
+++ b/sect.c
@@ -9,6 +9,7 @@
 #include "sect.h"
 #include "6502.h"
 #include "direct.h"
+#include "dsp56k.h"
 #include "error.h"
 #include "expr.h"
 #include "listing.h"
@@ -75,11 +76,14 @@ void InitSection(void)
                MakeSection(i, 0);
 
        // Construct default sections, make TEXT the current section
-       MakeSection(ABS,   SUSED | SABS | SBSS);        // ABS
-       MakeSection(TEXT,  SUSED | TEXT       );        // TEXT
-       MakeSection(DATA,  SUSED | DATA       );        // DATA
-       MakeSection(BSS,   SUSED | BSS  | SBSS);        // BSS
-       MakeSection(M6502, SUSED | TEXT       );        // 6502 code section
+       MakeSection(ABS,     SUSED | SABS | SBSS);      // ABS
+       MakeSection(TEXT,    SUSED | TEXT       );      // TEXT
+       MakeSection(DATA,    SUSED | DATA       );      // DATA
+       MakeSection(BSS,     SUSED | BSS  | SBSS);      // BSS
+       MakeSection(M6502,   SUSED | TEXT       );      // 6502 code section
+       MakeSection(M56001P, SUSED | SABS       );      // DSP 56001 Program RAM
+       MakeSection(M56001X, SUSED | SABS       );      // DSP 56001 X RAM
+       MakeSection(M56001Y, SUSED | SABS       );      // DSP 56001 Y RAM
 
        // Switch to TEXT for starters
        SwitchSection(TEXT);
@@ -128,9 +132,13 @@ void SwitchSection(int sno)
                // For 6502 mode, add the last org'd address
 // Why?
 /*
-Because the way this is set up it treats the 6502 assembly space as a single 64K space (+ 16 bytes, for some reason) and just bobbles around inside that space and uses a stack of org "pointers" to show where the data ended up.
+Because the way this is set up it treats the 6502 assembly space as a single 64K space (+ 16 bytes, for some unknown reason) and just bobbles around inside that space and uses a stack of org "pointers" to show where the data ended up.
 
-This is a piss poor way to handle things, and for fucks sake, we can do better than this!
+This is a shitty way to handle things, and we can do better than this!  :-P
+
+Really, there's no reason to have the 6502 (or DSP56001 for that matter) have their own private sections for this kind of thing, as there's literally *no* chance that it would be mingled with 68K+ code.  It should be able to use the TEXT, DATA & BSS sections just like the 68K.
+
+Or should it?  After looking at the code, maybe it's better to keep the 56001 sections segregated from the rest.  But we can still make the 6502 stuff better.
 */
                if (m6502)
                        chptr = cp->chptr + orgaddr;
@@ -267,7 +275,8 @@ int AddFixup(uint32_t attr, uint32_t loc, TOKEN * fexpr)
        if (attr & FUMASKDSP)
        {
                attr |= FU_56001;
-               _orgaddr = orgaddr;
+               // Save the exact spot in this chunk where the fixup should go
+               _orgaddr = chptr - scode->chptr;
        }
 
        // Allocate space for the fixup + any expression
@@ -349,6 +358,9 @@ int ResolveFixups(int sno)
                // than this.
                SetFilenameForErrorReporting();
 
+               if ((sno == M56001P) || (sno == M56001X) || (sno == M56001Y) || (sno == M56001L))
+                       loc = fup->orgaddr;
+
                // Search for chunk containing location to fix up; compute a
                // pointer to the location (in the chunk). Often we will find the
                // Fixup is in the "cached" chunk, so the linear-search is seldom
@@ -566,16 +578,7 @@ int ResolveFixups(int sno)
                case FU_WORD:
                        if ((dw & FUMASKRISC) == FU_JR)
                        {
-#if 0
-                               int reg;
-
-                               if (fup->orgaddr)
-                                       reg = (signed)((eval - (fup->orgaddr + 2)) / 2);
-                               else
-                                       reg = (signed)((eval - (loc + 2)) / 2);
-#else
                                int reg = (signed)((eval - ((fup->orgaddr ? fup->orgaddr : loc) + 2)) / 2);
-#endif
 
                                if ((reg < -16) || (reg > 15))
                                {
@@ -727,8 +730,8 @@ int ResolveFixups(int sno)
                                uint64_t addr = eval;
 
 //Hmm, not sure how this can be set, since it's only set if it's a DSP56001 fixup or a FU_JR...  :-/
-                               if (fup->orgaddr)
-                                       addr = fup->orgaddr;
+//                             if (fup->orgaddr)
+//                                     addr = fup->orgaddr;
 
                                eval = (quad & 0xFFFFFC0000FFFFFFLL) | ((addr & 0x3FFFF8) << 21);
                        }
@@ -743,8 +746,8 @@ int ResolveFixups(int sno)
                                uint64_t addr = eval;
 
 //Hmm, not sure how this can be set, since it's only set if it's a DSP56001 fixup or a FU_JR...  :-/
-                               if (fup->orgaddr)
-                                       addr = fup->orgaddr;
+//                             if (fup->orgaddr)
+//                                     addr = fup->orgaddr;
 
                                eval = (quad & 0x000007FFFFFFFFFFLL) | ((addr & 0xFFFFF8) << 40);
                        }
@@ -798,7 +801,7 @@ int ResolveFixups(int sno)
                        case FU_DSPADR12:
                                if (eval >= 0x1000)
                                {
-                                       error("address out of range ($000-$FFF)");
+                                       error("address out of range ($0-$FFF)");
                                        break;
                                }
 
@@ -809,22 +812,22 @@ int ResolveFixups(int sno)
                        // This is a full DSP word containing Effective Address Extension
                        case FU_DSPADR24:
                        case FU_DSPIMM24:
-                               if (eval >= 0x100000)
+                               if (eval >= 0x1000000)
                                {
-                                       error("value out of range ($000-$FFFFFF)");
+                                       error("value out of range ($0-$FFFFFF)");
                                        break;
                                }
 
-                               *locp++ = (uint32_t)eval >> 16;
-                               *locp++ = ((uint32_t)eval >> 8) & 0xFF;
-                               *locp++ = (uint32_t)eval & 0xFF;
+                               locp[0] = (uint8_t)((eval >> 16) & 0xFF);
+                               locp[1] = (uint8_t)((eval >> 8) & 0xFF);
+                               locp[2] = (uint8_t)(eval & 0xFF);
                                break;
 
                        // This is a 16bit absolute address into a 24bit field
                        case FU_DSPADR16:
                                if (eval >= 0x10000)
                                {
-                                       error("address out of range ($0000-$FFFF)");
+                                       error("address out of range ($0-$FFFF)");
                                        break;
                                }
 
@@ -838,7 +841,7 @@ int ResolveFixups(int sno)
                        case FU_DSPIMM12:
                                if (eval >= 0x1000)
                                {
-                                       error("immediate out of range ($000-$FFF)");
+                                       error("immediate out of range ($0-$FFF)");
                                        break;
                                }
 
@@ -851,7 +854,7 @@ int ResolveFixups(int sno)
                        case FU_DSPIMM8:
                                if (eval >= 0x100)
                                {
-                                       error("immediate out of range ($00-$FF)");
+                                       error("immediate out of range ($0-$FF)");
                                        break;
                                }
 
@@ -948,6 +951,12 @@ int ResolveAllFixups(void)
        ResolveFixups(DATA);
        DEBUG printf("Resolving 6502 sections...\n");
        ResolveFixups(M6502);           // Fixup 6502 section (if any)
+       DEBUG printf("Resolving DSP56001 P: sections...\n");
+       ResolveFixups(M56001P);         // Fixup 56001 P: section (if any)
+       DEBUG printf("Resolving DSP56001 X: sections...\n");
+       ResolveFixups(M56001X);         // Fixup 56001 X: section (if any)
+       DEBUG printf("Resolving DSP56001 Y: sections...\n");
+       ResolveFixups(M56001Y);         // Fixup 56001 Y: section (if any)
 
        return 0;
 }
diff --git a/sect.h b/sect.h
index 84ad789c9456c931e14573cbff248b477c3ce136..fb1db431438e5c43ae28f8ab8e41364ce066ebbf 100644 (file)
--- a/sect.h
+++ b/sect.h
@@ -54,7 +54,9 @@
 #define D_ZEROFILL(n)  {chcheck(n); memset(chptr, 0, n); chptr+=n; sloc+=n; \
        ch_size+=n; if (orgactive) orgaddr+=n;}
 
-#define NSECTS       16                        // Max. number of sections
+//OK, this is bad, mmkay? The constants defined in rmac.h are used as indices into an array which means that this was never meant to be defined this way--at least if it was, it was a compromise that has come home to bite us all in the ass.  !!! FIX !!!
+//#define NSECTS       16                      // Max. number of sections
+#define NSECTS       256                       // Max. number of sections
 
 // Tunable (storage) definitions
 #define CH_THRESHOLD    32             // Minimum amount of space in code chunk
index 84d5e16cc56beaa579067ecd7049aec4869ba827..c1abfab58693aa0427abb641a9451c6929c6db4d 100644 (file)
--- a/symbol.c
+++ b/symbol.c
@@ -7,6 +7,7 @@
 //
 
 #include "symbol.h"
+#include "dsp56k.h"
 #include "error.h"
 #include "listing.h"
 #include "object.h"
@@ -35,6 +36,9 @@ static uint8_t tdb_text[8] = {
    'a', 't', 'd', '!', 'b', SPACE, SPACE, SPACE
 };
 
+// Internal function prototypes
+static uint16_t WriteLODSection(int, uint16_t);
+
 
 //
 // Initialize symbol table
@@ -332,6 +336,53 @@ uint32_t sy_assign_ELF(uint8_t * buf, uint8_t *(* construct)())
 }
 
 
+//
+// Helper function for dsp_lod_symbols
+//
+static uint16_t WriteLODSection(int section, uint16_t symbolCount)
+{
+       for(SYM * sy=sdecl; sy!=NULL; sy=sy->sdecl)
+       {
+               // Export vanilla labels (but don't make them global). An exception is
+               // made for equates, which are not exported unless they are referenced.
+               if (sy->stype == LABEL && lsym_flag
+                       && (sy->sattr & (DEFINED | REFERENCED)) != 0
+                       && (*sy->sname != '.')
+                       && (sy->sattr & GLOBAL) == 0
+                       && (sy->sattr & (section)))
+               {
+                       sy->senv = symbolCount++;
+                       D_printf("%-19s   I %.6" PRIX64 "\n", sy->sname, sy->svalue);
+               }
+       }
+
+       return symbolCount;
+}
+
+
+//
+// Dump LOD style symbols into the passed in buffer
+//
+void DumpLODSymbols(void)
+{
+       D_printf("_SYMBOL P\n");
+       uint16_t count = WriteLODSection(M56001P, 0);
+
+       D_printf("_SYMBOL X\n");
+       count = WriteLODSection(M56001X, count);
+
+       D_printf("_SYMBOL Y\n");
+       count = WriteLODSection(M56001Y, count);
+
+       D_printf("_SYMBOL L\n");
+       count = WriteLODSection(M56001L, count);
+
+       // TODO: I've seen _SYMBOL N in there but no idea what symbols it needs...
+       //D_printf("_SYMBOL N\n");
+       //WriteLODSection(M56001?, count);
+}
+
+
 //
 // Convert string to uppercase
 //
index 47ea3cd3298e0c543d2f6d8ac9c4f790b9b04e20..f8391a02fa78a6f31cd34ac504088ef22b666985 100644 (file)
--- a/symbol.h
+++ b/symbol.h
@@ -51,6 +51,7 @@ void ForceUndefinedSymbolsGlobal(void);
 int symtable(void);
 uint32_t sy_assign(uint8_t *, uint8_t *(*)());
 uint32_t sy_assign_ELF(uint8_t *, uint8_t *(*)());
+void DumpLODSymbols(void);
 uint8_t * GetSymbolNameByUID(uint32_t);
 
 #endif // __SYMBOL_H__
diff --git a/token.c b/token.c
index 564ff0cc895d9349644776c69021687927f7dd83..cd6b9c61269442bc1ce14692a15aed04881890e4 100644 (file)
--- a/token.c
+++ b/token.c
@@ -1171,7 +1171,7 @@ DEBUG { printf("TokenizeLine: Calling fpop() from SRC_IFILE...\n"); }
                        }
 
                        // Make j = -1 if user tries to use a RISC register while in 68K mode
-                       if (!(rgpu || rdsp) && ((TOKEN)j >= KW_R0 && (TOKEN)j <= KW_R31))
+                       if (!(rgpu || rdsp || dsp56001) && ((TOKEN)j >= KW_R0 && (TOKEN)j <= KW_R31))
                        {
                                j = -1;
                        }
index 1be65d89aa8c2ea77c1d2a2e7687be7b00de82a9..a6184b5af37a7a8470715513d1e0b82f85902257 100644 (file)
--- a/version.h
+++ b/version.h
@@ -13,9 +13,9 @@
 
 // Release Information
 
-#define MAJOR   1              // Major version number
-#define MINOR   13             // Minor version number
-#define PATCH   5              // Patch release number
+#define MAJOR   2              // Major version number
+#define MINOR                // Minor version number
+#define PATCH   0              // Patch release number
 
 #endif // __VERSION_H__