]> Shamusworld >> Repos - rmac/blob - dsp56k_amode.c
Version bump + cleanup for last commit; now at v2.0.19.
[rmac] / dsp56k_amode.c
1 //
2 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
3 // AMODE.C - DSP 56001 Addressing Modes
4 // Copyright (C) 199x Landon Dyer, 2011-2020 Reboot and Friends
5 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
6 // Source utilised with the kind permission of Landon Dyer
7 //
8
9 #include "dsp56k_amode.h"
10 #include "error.h"
11 #include "token.h"
12 #include "expr.h"
13 #include "rmac.h"
14 #include "procln.h"
15 #include "sect.h"
16 #include "math.h"
17
18 #define DEF_KW
19 #include "kwtab.h"
20 #define DEF_MN
21 #include "mntab.h"
22
23 // Address-mode information
24 //int nmodes;                                           // Number of addr'ing modes found
25 int dsp_am0;                                    // Addressing mode
26 int dsp_a0reg;                                  // Register
27 TOKEN dsp_a0expr[EXPRSIZE];             // Expression
28 uint64_t dsp_a0exval;                   // Expression's value
29 WORD dsp_a0exattr;                              // Expression's attribute
30 LONG dsp_a0memspace;                    // Addressing mode's memory space (P, X, Y)
31 SYM * dsp_a0esym;                               // External symbol involved in expr
32
33 int dsp_am1;                                    // Addressing mode
34 int dsp_a1reg;                                  // Register
35 TOKEN dsp_a1expr[EXPRSIZE];             // Expression
36 uint64_t dsp_a1exval;                   // Expression's value
37 WORD dsp_a1exattr;                              // Expression's attribute
38 LONG dsp_a1memspace;                    // Addressing mode's memory space (P, X, Y)
39 SYM * dsp_a1esym;                               // External symbol involved in expr
40
41 int dsp_am2;                                    // Addressing mode
42 int dsp_a2reg;                                  // Register
43 TOKEN dsp_a2expr[EXPRSIZE];             // Expression
44 uint64_t dsp_a2exval;                   // Expression's value
45 WORD dsp_a2exattr;                              // Expression's attribute
46 SYM * dsp_a2esym;                               // External symbol involved in expr
47
48 int dsp_am3;                                    // Addressing mode
49 int dsp_a3reg;                                  // Register
50 TOKEN dsp_a3expr[EXPRSIZE];             // Expression
51 uint64_t dsp_a3exval;                   // Expression's value
52 WORD dsp_a3exattr;                              // Expression's attribute
53 SYM * dsp_a3esym;                               // External symbol involved in expr
54
55 TOKEN dspImmedEXPR[EXPRSIZE];   // Expression
56 uint64_t dspImmedEXVAL;                 // Expression's value
57 WORD  dspImmedEXATTR;                   // Expression's attribute
58 SYM * dspImmedESYM;                             // External symbol involved in expr
59 int  deposit_extra_ea;                  // Optional effective address extension
60 TOKEN dspaaEXPR[EXPRSIZE];              // Expression
61 uint64_t dspaaEXVAL;                    // Expression's value
62 WORD  dspaaEXATTR;                              // Expression's attribute
63 SYM * dspaaESYM;                                // External symbol involved in expr
64
65 LONG dsp_a0perspace;                    // Peripheral space (X, Y - used in movep)
66 LONG dsp_a1perspace;                    // Peripheral space (X, Y - used in movep)
67
68 int dsp_k;                                              // Multiplications sign
69
70 static inline LONG checkea(const uint32_t termchar, const int strings);
71
72 // ea checking error strings put into a table because I'm not sure there's an
73 // easy way to do otherwise (the messages start getting differerent in many
74 // places so it will get awkward to code those in) (I'd rather burn some RAM
75 // in order to have more helpful error messages than the other way round)
76
77 #define X_ERRORS 0
78 #define Y_ERRORS 1
79 #define L_ERRORS 2
80 #define P_ERRORS 3
81
82 const char *ea_errors[][12] = {
83         // X:
84         {
85                 "unrecognised X: parallel move syntax: expected '(' after 'X:-'",                                       // 0
86                 "unrecognised X: parallel move syntax: expected ')' after 'X:-(Rn'",                                    // 1
87                 "unrecognised X: parallel move syntax: expected R0-R7 after 'X:-('",                                    // 2
88                 "unrecognised X: parallel move syntax: expected N0-N7 after 'X:(Rn+'",                                  // 3
89                 "unrecognised X: parallel move syntax: expected same register number in Rn and Nn for 'X:(Rn+Nn)'",     // 4
90                 "unrecognised X: parallel move syntax: expected ')' after 'X:(Rn+Nn'",                                  // 5
91                 "unrecognised X: parallel move syntax: expected same register number in Rn and Nn for 'X:(Rn)+Nn'",     // 6
92                 "unrecognised X: parallel move syntax: expected N0-N7 after 'X:(Rn)+'",                                 // 7
93                 "unrecognised X: parallel move syntax: expected same register number in Rn and Nn for 'X:(Rn)-Nn'",     // 8
94                 "unrecognised X: parallel move syntax: expected N0-N7 after 'X:(Rn)-'",                                 // 9
95                 "unrecognised X: parallel move syntax: expected '+', '-' or ',' after 'X:(Rn)'",                        // 10
96                 "unrecognised X: parallel move syntax: expected '+' or ')' after 'X:(Rn'",                              // 11
97         },
98         // Y:
99         {
100                 "unrecognised Y: parallel move syntax: expected '(' after 'Y:-'",                                       // 0
101                 "unrecognised Y: parallel move syntax: expected ')' after 'Y:-(Rn'",                                    // 1
102                 "unrecognised Y: parallel move syntax: expected R0-R7 after 'Y:-('",                                    // 2
103                 "unrecognised Y: parallel move syntax: expected N0-N7 after 'Y:(Rn+'",                                  // 3
104                 "unrecognised Y: parallel move syntax: expected same register number in Rn and Nn for 'Y:(Rn+Nn)'",     // 4
105                 "unrecognised Y: parallel move syntax: expected ')' after 'Y:(Rn+Nn'",                                  // 5
106                 "unrecognised Y: parallel move syntax: expected same register number in Rn and Nn for 'Y:(Rn)+Nn'",     // 6
107                 "unrecognised Y: parallel move syntax: expected N0-N7 after 'Y:(Rn)+'",                                 // 7
108                 "unrecognised Y: parallel move syntax: expected same register number in Rn and Nn for 'Y:(Rn)-Nn'",     // 8
109                 "unrecognised Y: parallel move syntax: expected N0-N7 after 'Y:(Rn)-'",                                 // 9
110                 "unrecognised Y: parallel move syntax: expected '+', '-' or ',' after 'Y:(Rn)'",                        // 10
111                 "unrecognised Y: parallel move syntax: expected '+' or ')' after 'Y:(Rn'",                              // 11
112         },
113         // L:
114         {
115                 "unrecognised L: parallel move syntax: expected '(' after 'L:-'",                                       // 0
116                 "unrecognised L: parallel move syntax: expected ')' after 'L:-(Rn'",                                    // 1
117                 "unrecognised L: parallel move syntax: expected R0-R7 after 'L:-('",                                    // 2
118                 "unrecognised L: parallel move syntax: expected N0-N7 after 'L:(Rn+'",                                  // 3
119                 "unrecognised L: parallel move syntax: expected same register number in Rn and Nn for 'L:(Rn+Nn)'",     // 4
120                 "unrecognised L: parallel move syntax: expected ')' after 'L:(Rn+Nn'",                                  // 5
121                 "unrecognised L: parallel move syntax: expected same register number in Rn and Nn for 'L:(Rn)+Nn'",     // 6
122                 "unrecognised L: parallel move syntax: expected N0-N7 after 'L:(Rn)+'",                                 // 7
123                 "unrecognised L: parallel move syntax: expected same register number in Rn and Nn for 'L:(Rn)-Nn'",     // 8
124                 "unrecognised L: parallel move syntax: expected N0-N7 after 'L:(Rn)-'",                                 // 9
125                 "unrecognised L: parallel move syntax: expected '+', '-' or ',' after 'L:(Rn)'",                        // 10
126                 "unrecognised L: parallel move syntax: expected '+' or ')' after 'L:(Rn'",                              // 11
127         },
128         // P:
129         {
130                 "unrecognised P: effective address syntax: expected '(' after 'P:-'",                                       // 0
131                 "unrecognised P: effective address syntax: expected ')' after 'P:-(Rn'",                                    // 1
132                 "unrecognised P: effective address syntax: expected R0-R7 after 'P:-('",                                    // 2
133                 "unrecognised P: effective address syntax: expected N0-N7 after 'P:(Rn+'",                                  // 3
134                 "unrecognised P: effective address syntax: expected same register number in Rn and Nn for 'P:(Rn+Nn)'",     // 4
135                 "unrecognised P: effective address syntax: expected ')' after 'P:(Rn+Nn'",                                  // 5
136                 "unrecognised P: effective address syntax: expected same register number in Rn and Nn for 'P:(Rn)+Nn'",     // 6
137                 "unrecognised P: effective address syntax: expected N0-N7 after 'P:(Rn)+'",                                 // 7
138                 "unrecognised P: effective address syntax: expected same register number in Rn and Nn for 'P:(Rn)-Nn'",     // 8
139                 "unrecognised P: effective address syntax: expected N0-N7 after 'P:(Rn)-'",                                 // 9
140                 "unrecognised P: effective address syntax: expected '+', '-' or ',' after 'P:(Rn)'",                        // 10
141                 "unrecognised P: effective address syntax: expected '+' or ')' after 'P:(Rn'",                              // 11
142         }
143 };
144
145 enum
146 {
147         NUM_NORMAL = 0,
148         NUM_FORCE_LONG = 1,
149         NUM_FORCE_SHORT = 2
150 };
151
152
153 //
154 // Parse a single addressing mode
155 //
156 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)
157 {
158         if (*tok == KW_A || *tok == KW_B)
159         {
160                 *am = M_ACC56;
161                 *areg = *tok++;
162                 return OK;
163         }
164         else if (*tok == '#')
165         {
166                 tok++;
167
168                 if (*tok == '<')
169                 {
170                         // Immediate Short Addressing Mode Force Operator
171                         tok++;
172                         if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
173                                 return ERROR;
174
175                         if (*AnEXVAL > 0xFFF && *AnEXVAL < -4096)
176                                 return error("immediate short addressing mode forced but address is bigger than $FFF");
177
178                         if ((int32_t)*AnEXVAL <= 0xFF && (int32_t)*AnEXVAL > -0x100)
179                         {
180                                 *am = M_DSPIM8;
181                                 return OK;
182                         }
183
184                         *am = M_DSPIM12;
185                         return OK;
186                 }
187                 else if (*tok == '>')
188                 {
189                         // Immediate Long Addressing Mode Force Operator
190                         tok++;
191
192                         if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
193                                 return ERROR;
194
195                         if ((int32_t)*AnEXVAL > 0xFFFFFF || (int32_t)*AnEXVAL < -0xFFFFFF)
196                                 return error("long immediate is bigger than $FFFFFF");
197
198                         *am = M_DSPIM;
199                         return OK;
200                 }
201
202                 if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
203                         return ERROR;
204
205                 if (*AnEXATTR & DEFINED)
206                 {
207                         if ((int32_t)*AnEXVAL < 0x100 && (int32_t)*AnEXVAL >= -0x100)
208                         {
209                                 *AnEXVAL &= 0xFF;
210                                 *am = M_DSPIM8;
211                         }
212                         else if (*AnEXVAL < 0x1000)
213                                 *am = M_DSPIM12;
214                         else
215                                 *am = M_DSPIM;
216                 }
217                 else
218                 {
219                         // We have no clue what size our immediate will be
220                         // so we have to assume the worst
221                         *am = M_DSPIM;
222                 }
223
224                 return OK;
225         }
226         else if (*tok >= KW_X0 && *tok <= KW_Y1)
227         {
228                 *am = M_ALU24;
229                 *areg = *tok++;
230                 return OK;
231         }
232         else if (*tok == KW_X && *(tok + 1) == ':')
233         {
234                 tok = tok + 2;
235
236                 if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
237                 {
238                         if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
239                                 return ERROR;
240
241                         if (*AnEXATTR & DEFINED)
242                         {
243                                 if (*AnEXVAL > 0xFFFFFF)
244                                         return error("long address is bigger than $FFFFFF");
245
246                                 *memspace = 0 << 6;     // Mark we're on X memory space
247
248                                 // Check if value is between $FFC0 and $FFFF, AKA X:pp
249                                 uint32_t temp = (LONG)(((int32_t)(((uint32_t)*AnEXVAL) << (32 - 6))) >> (32 - 6));  // Sign extend 6 to 32 bits
250
251                                 if ((temp >= 0xFFFFFFC0                      /* Check for 32bit sign extended number */
252                                         && ((int32_t)*AnEXVAL < 0))              /* Check if 32bit signed number is negative*/
253                                         || (*AnEXVAL < 0xFFFF && *AnEXVAL >= 0x8000)) /* Check if 16bit number is negative*/
254                                 {
255                                         *AnEXVAL = temp;
256                                         *am = M_DSPPP;
257                                         *memspace = 0 << 6;          // Mark we're on X memory space
258                                         *perspace = 0 << 16;         // Mark we're on X peripheral space
259                                         *areg = *AnEXVAL & 0x3F;     // Since this is only going to get used in dsp_ea_imm5...
260                                         return OK;
261                                 }
262
263                                 // If the symbol/expression is defined then check for valid range.
264                                 // Otherwise the value had better fit or Fixups will bark!
265                                 if (*AnEXVAL > 0x3F)
266                                 {
267                                         *am = M_DSPEA;
268                                         *areg = DSP_EA_ABS;
269                                 }
270                                 else
271                                 {
272                                         *am = M_DSPAA;
273                                 }
274                         }
275                         else
276                         {
277                                 // Assume the worst
278                                 *memspace = 0 << 6;     // Mark we're on X memory space
279                                 *am = M_DSPEA;
280                                 *areg = DSP_EA_ABS;
281                         }
282
283                         return OK;
284                 }
285                 else if (*tok == '<')
286                 {
287                         // X:aa
288                         // Short Addressing Mode Force Operator in the case of '<'
289                         tok++;
290
291                         if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
292                                 return ERROR;
293
294                         // If the symbol/expression is defined then check for valid range.
295                         // Otherwise the value had better fit or Fixups will bark!
296                         if (*AnEXATTR & DEFINED)
297                         {
298                                 if (*AnEXVAL > 0x3F)
299                                         return error("short addressing mode forced but address is bigger than $3F");
300                         }
301                         else
302                         {
303                                 // Mark it as a fixup
304                                 deposit_extra_ea = DEPOSIT_EXTRA_FIXUP;
305                         }
306
307                         *am = M_DSPAA;
308                         *memspace = 0 << 6;     // Mark we're on X memory space
309                         *areg = (int)*AnEXVAL;     // Since this is only going to get used in dsp_ea_imm5...
310                         return OK;
311                 }
312                 else if (*tok == '>')
313                 {
314                         // Long Addressing Mode Force Operator
315                         tok++;
316
317                         if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
318                         {
319                                 if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
320                                         return ERROR;
321
322                                 if (*AnEXATTR&DEFINED)
323                                 {
324                                         if (*AnEXVAL > 0xFFFFFF)
325                                                 return error("long address is bigger than $FFFFFF");
326
327                                         *memspace = 0 << 6;     // Mark we're on X memory space
328                                         *am = M_DSPEA;
329                                         *areg = DSP_EA_ABS;
330                                 }
331                                 else
332                                 {
333                                         // Assume the worst
334                                         *memspace = 0 << 6;     // Mark we're on X memory space
335                                         *am = M_DSPEA;
336                                         *areg = DSP_EA_ABS;
337                                 }
338                                 return OK;
339                         }
340                 }
341                 else if (*tok == SHL)  // '<<'
342                 {
343                         // I/O Short Addressing Mode Force Operator
344                         // X:pp
345                         tok++;
346
347                         if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
348                                 return ERROR;
349
350                         // If the symbol/expression is defined then check for valid range.
351                         // Otherwise the value had better fit or Fixups will bark!
352                         if (*AnEXATTR & DEFINED)
353                         {
354                                 *AnEXVAL = (LONG)(((int32_t)(((uint32_t)*AnEXVAL) << (32 - 6))) >> (32 - 6));  // Sign extend 6 to 32 bits
355
356                                 if (*AnEXVAL < 0xFFFFFFC0)
357                                         return error("I/O Short Addressing Mode addresses must be between $FFC0 and $FFFF");
358                         }
359
360                         *am = M_DSPPP;
361                         *memspace = 0 << 6;          // Mark we're on X memory space
362                         *perspace = 0 << 16;         // Mark we're on X peripheral space
363                         *areg = *AnEXVAL & 0x3F;     // Since this is only going to get used in dsp_ea_imm5...
364                         return OK;
365                 }
366
367                 if ((*areg = checkea(0, X_ERRORS)) != ERROR)
368                 {
369                         // TODO: what if we need M_DSPAA here????
370                         *memspace = 0 << 6;     // Mark we're on X memory space
371                         *am = M_DSPEA;
372                         return OK;
373                 }
374                 else
375                         return ERROR;
376         }
377         else if (*tok == KW_Y && *(tok + 1) == ':')
378         {
379                 tok = tok + 2;
380
381                 if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
382                 {
383                         if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
384                                 return ERROR;
385
386                         if (*AnEXVAL > 0xFFFFFF)
387                                 return error("long address is bigger than $FFFFFF");
388
389                         *memspace = 1 << 6;     // Mark we're on Y memory space
390
391                         // Check if value is between $ffc0 and $ffff, AKA Y:pp
392                         uint32_t temp = (LONG)(((int32_t)(((uint32_t)*AnEXVAL) << (32 - 6))) >> (32 - 6));  // Sign extend 6 to 32 bits
393
394                         if ((temp >= 0xFFFFFFC0                         /* Check for 32bit sign extended number */
395                                 && ((int32_t)*AnEXVAL < 0))                 /* Check if 32bit signed number is negative*/
396                                 || (*AnEXVAL < 0xFFFF && *AnEXVAL >= 0x8000)) /* Check if 16bit number is negative*/
397                         {
398                                 *AnEXVAL = temp;
399                                 *am = M_DSPPP;
400                                 *perspace = 1 << 16;         // Mark we're on X peripheral space
401                                 *areg = *AnEXVAL & 0x3F;     // Since this is only going to get used in dsp_ea_imm5...
402                                 return OK;
403                         }
404
405                         // If the symbol/expression is defined then check for valid range.
406                         // Otherwise the value had better fit or Fixups will bark!
407                         if (*AnEXATTR & DEFINED)
408                         {
409                                 if (*AnEXVAL > 0x3F)
410                                 {
411                                         *am = M_DSPEA;
412                                         *areg = DSP_EA_ABS;
413                                 }
414                                 else
415                                 {
416                                         *am = M_DSPAA;
417                                 }
418                         }
419                         else
420                         {
421                                 *am = M_DSPEA;
422                                 *areg = DSP_EA_ABS;
423                         }
424
425                         return OK;
426                 }
427                 else if (*tok == '<')
428                 {
429                         // Y:aa
430                         // Short Addressing Mode Force Operator in the case of '<'
431                         tok++;
432
433                         if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
434                                 return ERROR;
435
436                         // If the symbol/expression is defined then check for valid range.
437                         // Otherwise the value had better fit or Fixups will bark!
438                         if (*AnEXATTR & DEFINED)
439                         {
440                                 if (*AnEXVAL > 0x3F)
441                                 {
442                                         if (optim_warn_flag)
443                                                 warn("short addressing mode forced but address is bigger than $3F - switching to long");
444
445                                         *am = M_DSPEA;
446                                         *memspace = 1 << 6;     // Mark we're on Y memory space
447                                         *areg = DSP_EA_ABS;
448                                         return OK;
449                                 }
450                         }
451                         else
452                         {
453                                 // Mark it as a fixup
454                                 deposit_extra_ea = DEPOSIT_EXTRA_FIXUP;
455                         }
456
457                         *am = M_DSPAA;
458                         *memspace = 1 << 6;     // Mark we're on Y memory space
459                         *areg = (int)*AnEXVAL;      // Since this is only going to get used in dsp_ea_imm5...
460                         return OK;
461                 }
462                 else if (*tok == '>')
463                 {
464                         // Long Addressing Mode Force Operator
465                         tok++;
466
467                         if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
468                         {
469                                 if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
470                                         return ERROR;
471
472                                 if (*AnEXATTR&DEFINED)
473                                 {
474                                         if (*AnEXVAL > 0xFFFFFF)
475                                                 return error("long address is bigger than $FFFFFF");
476
477                                         *memspace = 1 << 6;     // Mark we're on Y memory space
478
479                                         *am = M_DSPEA;
480                                         *areg = DSP_EA_ABS;
481                                 }
482                                 else
483                                 {
484                                         // Assume the worst
485                                         *memspace = 1 << 6;     // Mark we're on Y memory space
486                                         *am = M_DSPEA;
487                                         *areg = DSP_EA_ABS;
488                                 }
489                                 return OK;
490                         }
491                 }
492                 else if (*tok == SHL)  // '<<'
493                 {
494                         // I/O Short Addressing Mode Force Operator
495                         // Y:pp
496                         tok++;
497
498                         if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
499                                 return ERROR;
500
501                         // If the symbol/expression is defined then check for valid range.
502                         // Otherwise the value had better fit or Fixups will bark!
503                         if (*AnEXATTR & DEFINED)
504                         {
505                                 *AnEXVAL = (LONG)(((int32_t)(((uint32_t)*AnEXVAL) << (32 - 6))) >> (32 - 6));  // Sign extend 6 to 32 bits
506
507                                 if (*AnEXVAL < 0xFFFFFFC0)
508                                         return error("I/O Short Addressing Mode addresses must be between $FFE0 and $1F");
509                         }
510
511                         *am = M_DSPPP;
512                         *memspace = 1 << 6;          // Mark we're on Y memory space
513                         *perspace = 1 << 16;         // Mark we're on Y peripheral space
514                         *areg = *AnEXVAL & 0x3F;     // Since this is only going to get used in dsp_ea_imm5...
515                         return OK;
516                 }
517
518                 if ((*areg = checkea(0, X_ERRORS)) != ERROR)
519                 {
520                         *memspace = 1 << 6;     // Mark we're on Y memory space
521                         *am = M_DSPEA;
522                         return OK;
523                 }
524                 else
525                         return ERROR;
526                 // TODO: add absolute address checks
527         }
528         else if ((*tok >= KW_X) && (*tok <= KW_Y))
529         {
530                 *am = M_INP48;
531                 *areg = *tok++;
532                 return OK;
533         }
534         else if ((*tok >= KW_M0) && (*tok <= KW_M7))
535         {
536                 *am = M_DSPM;
537                 *areg = (*tok++) & 7;
538                 return OK;
539         }
540         else if ((*tok >= KW_R0) && (*tok <= KW_R7))
541         {
542                 *am = M_DSPR;
543                 *areg = (*tok++) - KW_R0;
544                 return OK;
545         }
546         else if ((*tok >= KW_N0) && (*tok <= KW_N7))
547         {
548                 *am = M_DSPN;
549                 *areg = (*tok++) & 7;
550                 return OK;
551         }
552         else if ((*tok == KW_A0) || (*tok == KW_A1) || (*tok == KW_B0)
553                 || (*tok == KW_B1))
554         {
555                 *am = M_ACC24;
556                 *areg = *tok++;
557                 return OK;
558         }
559         else if ((*tok == KW_A2) || (*tok == KW_B2))
560         {
561                 *am = M_ACC8;
562                 *areg = *tok++;
563                 return OK;
564         }
565         else if ((*tok == '-') && (*(tok + 1) == KW_X0 || *(tok + 1) == KW_X1 || *(tok + 1) == KW_Y0 || *(tok + 1) == KW_Y1))
566         {
567                 // '-X0', '-Y0', '-X1' or '-Y1', used in multiplications
568                 tok++;
569
570                 // Check to see if this is the first operand
571                 if (operand != 0)
572                         return error("-x0/-x1/-y0/-y1 only allowed in the first operand");
573
574                 *am = M_ALU24;
575                 *areg = *tok++;
576                 dsp_k = 1 << 2;
577                 return OK;
578         }
579         else if (*tok == '+' && (*(tok + 1) == KW_X0 || *(tok + 1) == KW_X1 || *(tok + 1) == KW_Y0 || *(tok + 1) == KW_Y1))
580         {
581                 // '+X0', '+Y0', '+X1' or '+Y1', used in multiplications
582                 tok++;
583
584                 // Check to see if this is the first operand
585                 if (operand != 0)
586                         return error("+x0/+x1/+y0/+y1 only allowed in the first operand");
587
588                 *am = M_ALU24;
589                 *areg = *tok++;
590                 dsp_k = 0 << 2;
591                 return OK;
592         }
593         else if (*tok == '(' || *tok == '-')
594         {
595                 // Could be either an expression or ea mode
596                 if (*tok + 1 == SYMBOL)
597                 {
598                         tok++;
599
600                         if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
601                                 return ERROR;
602
603                         *am = M_DSPIM;
604                         return OK;
605                 }
606
607                 if ((*areg = checkea(0, P_ERRORS)) != ERROR)
608                 {
609                         *am = M_DSPEA;
610                         return OK;
611                 }
612                 else
613                         return ERROR;
614
615                 // TODO: add absolute address checks
616                 return error("internal assembler error: parmode checking for '(' and '-' does not have absolute address checks yet!");
617         }
618         else if (*tok == KW_P && *(tok + 1) == ':')
619         {
620                 tok = tok + 2;
621
622                 if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
623                 {
624                         // Address
625                         if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
626                                 return ERROR;
627
628                         if (*AnEXVAL > 0xFFFFFF)
629                                 return error("long address is bigger than $FFFFFF");
630
631                         if (*AnEXVAL > 0x3F)
632                         {
633                                 *am = M_DSPEA;
634                                 *areg = DSP_EA_ABS;
635                         }
636                         else
637                         {
638                                 *areg = (int)*AnEXVAL;     // Lame, but what the hell
639                                 *am = M_DSPAA;
640                         }
641
642                         return OK;
643                 }
644                 else if (*tok == '<')
645                 {
646                         // X:aa
647                         // Short Addressing Mode Force Operator in the case of '<'
648                         tok++;
649
650                         if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
651                                 return ERROR;
652
653                         if (*AnEXVAL > 0x3F)
654                                 return error("short addressing mode forced but address is bigger than $3F");
655
656                         *am = M_DSPAA;
657                         *areg = (int)*AnEXVAL;     // Since this is only going to get used in dsp_ea_imm5...
658                         return OK;
659                 }
660                 else if (*tok == '>')
661                 {
662                         // Long Addressing Mode Force Operator
663                         tok++;
664
665                         // Immediate Short Addressing Mode Force Operator
666                         if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
667                                 return ERROR;
668
669                         if (*AnEXATTR & DEFINED)
670                         {
671                                 if (*AnEXVAL > 0xFFFFFF)
672                                         return error("long address is bigger than $FFFFFF");
673                         }
674
675                         *am = M_DSPEA;
676                         *areg = DSP_EA_ABS;
677                         return OK;
678                 }
679
680                 if ((*areg = checkea(0, P_ERRORS)) != ERROR)
681                 {
682                         *am = M_DSPEA;
683                         return OK;
684                 }
685                 else
686                         return ERROR;
687         }
688         else if (*tok == SHL)
689         {
690                 // I/O Short Addressing Mode Force Operator
691                 tok++;
692
693                 if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
694                         return ERROR;
695
696                 if (*AnEXVAL > 0xFFF)
697                         return error("I/O short addressing mode forced but address is bigger than $FFF");
698
699                 *am = M_DSPABS06;
700                 return OK;
701         }
702         else if (*tok == '<')
703         {
704                 // Short Addressing Mode Force Operator
705                 tok++;
706
707                 if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
708                         return ERROR;
709
710                 if (*AnEXATTR & DEFINED)
711                 {
712                         if (*AnEXVAL > 0xFFF)
713                                 return error("short addressing mode forced but address is bigger than $FFF");
714                 }
715
716                 *am = M_DSPABS12;
717                 return OK;
718         }
719         else if (*tok == '>')
720         {
721                 // Long Addressing Mode Force Operator
722                 tok++;
723
724                 // Immediate Short Addressing Mode Force Operator
725                 if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
726                         return ERROR;
727
728                 if (*AnEXATTR & DEFINED)
729                 {
730                         if (*AnEXVAL > 0xFFFFFF)
731                                 return error("long address is bigger than $FFFFFF");
732                 }
733
734                 *am = M_DSPEA;
735                 *areg = DSP_EA_ABS;
736                 return OK;
737         }
738         else if (*tok == KW_PC || *tok == KW_CCR || *tok == KW_SR || *tok == KW_SP || (*tok >= KW_MR&&*tok <= KW_SS))
739         {
740                 *areg = *tok++;
741                 *am = M_DSPPCU;
742                 return OK;
743         }
744         // expr
745         else
746         {
747                 if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
748                         return ERROR;
749
750                 // We'll store M_DSPEA_ABS in areg and if we have
751                 // any extra info, it'll go in am
752                 if (*AnEXATTR & DEFINED)
753                 {
754                         *areg = DSP_EA_ABS;
755
756                         if (*AnEXVAL < 0x1000)
757                                 *am = M_DSPABS12;
758                         else if (*AnEXVAL < 0x10000)
759                                 *am = M_DSPABS16;
760                         else if (*AnEXVAL < 0x1000000)
761                                 *am = M_DSPABS24;
762                         else
763                                 return error("address must be smaller than $1000000");
764
765                         return OK;
766                 }
767                 else
768                 {
769                         // Well, we have no opinion on the expression's size, so let's assume the worst
770                         *areg = DSP_EA_ABS;
771                         *am = M_DSPABS24;
772                         return OK;
773                 }
774         }
775
776         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
777 }
778
779
780 //
781 // Parse all addressing modes except parallel moves
782 //
783 int dsp_amode(int maxea)
784 {
785         LONG dummy;
786         // Initialize global return values
787         nmodes = dsp_a0reg = dsp_a1reg = 0;
788         dsp_am0 = dsp_am1 = M_AM_NONE;
789         dsp_a0expr[0] = dsp_a1expr[0] = ENDEXPR;
790         dsp_a0exval = 0;
791         dsp_a1exval = 0;
792         dsp_a0exattr = dsp_a1exattr = 0;
793         dsp_a0esym = dsp_a1esym = (SYM *)NULL;
794         dsp_a0memspace = dsp_a1memspace = -1;
795         dsp_a0perspace = dsp_a1perspace = -1;
796         dsp_k = 0;
797
798         // If at EOL, then no addr modes at all
799         if (*tok == EOL)
800                 return 0;
801
802         if (dsp_parmode(&dsp_am0, &dsp_a0reg, dsp_a0expr, &dsp_a0exval, &dsp_a0exattr, &dsp_a0esym, &dsp_a0memspace, &dsp_a0perspace, 0) == ERROR)
803                 return ERROR;
804
805
806         // If caller wants only one mode, return just one (ignore comma);
807         // If there is no second addressing mode (no comma), then return just one anyway.
808         nmodes = 1;
809
810         if (*tok != ',')
811         {
812                 if (dsp_k != 0)
813                         return error("-x0/-x1/-y0/-y1 only allowed in multiply operations");
814
815                 return 1;
816         }
817
818         // Eat the comma
819         tok++;
820
821         // Parse second addressing mode
822         if (dsp_parmode(&dsp_am1, &dsp_a1reg, dsp_a1expr, &dsp_a1exval, &dsp_a1exattr, &dsp_a1esym, &dsp_a1memspace, &dsp_a1perspace, 1) == ERROR)
823                 return ERROR;
824
825         if (maxea == 2 || *tok == EOL)
826         {
827                 if (dsp_k != 0)
828                         return error("-x0/-x1/-y0/-y1 only allowed in multiply operations");
829
830                 nmodes = 2;
831                 return 2;
832         }
833
834         if (*tok == ',')
835         {
836                 // Only MAC-like or jsset/clr/tst/chg instructions here
837                 tok++;
838                 if (dsp_parmode(&dsp_am2, &dsp_a2reg, dsp_a2expr, &dsp_a2exval, &dsp_a2exattr, &dsp_a2esym, &dummy, &dummy, 2) == ERROR)
839                         return ERROR;
840                 if (maxea == 3)
841                         return 3;
842                 if (*tok != EOL)
843                         return error(extra_stuff);
844                 nmodes = 3;
845                 return 3;
846
847         }
848
849         // Only Tcc instructions here, and then only those that accept 4 operands
850
851         if (dsp_parmode(&dsp_am2, &dsp_a2reg, dsp_a2expr, &dsp_a2exval, &dsp_a2exattr, &dsp_a2esym, &dummy, &dummy, 2) == ERROR)
852                 return ERROR;
853
854         if (*tok++ != ',')
855                 return error("expected 4 parameters");
856
857         if (dsp_parmode(&dsp_am3, &dsp_a3reg, dsp_a3expr, &dsp_a3exval, &dsp_a3exattr, &dsp_a3esym, &dummy, &dummy, 3) == ERROR)
858                 return ERROR;
859
860         if (*tok == EOL)
861         {
862                 if (dsp_k != 0)
863                         return error("-x0/-x1/-y0/-y1 only allowed in multiply operations");
864
865                 nmodes = 4;
866                 return 4;
867         }
868         else
869         {
870                 // Tcc instructions do not support parallel moves, so any remaining tokens are garbage
871                 return error(extra_stuff);
872         }
873
874         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
875 }
876
877
878 //
879 // Helper function which gives us the encoding of a DSP register
880 //
881 static inline int SDreg(int reg)
882 {
883         if (reg >= KW_X0 && reg <= KW_N7)
884                 return reg & 0xFF;
885         else if (reg >= KW_A0&&reg <= KW_A2)
886                 return (8 >> (reg & 7)) | 8;
887         else //if (reg>=KW_R0&&reg<=KW_R7)
888                 return reg - KW_R0 + 16;
889         // Handy map for the above:
890         // (values are of course taken from keytab)
891         // Register | Value | Return value
892         //      x0      | 260   | 4
893         //      x1      | 261   | 5
894         //      y0      | 262   | 6
895         //      y1      | 263   | 7
896         //      b0      | 265   | 8
897         //      b2      | 267   | 9
898         //      b1      | 269   | 10
899         //      a       | 270   | 14
900         //      b       | 271   | 15
901         //      n0      | 280   | 24
902         //      n1      | 281   | 25
903         //      n2      | 282   | 26
904         //      n3      | 283   | 27
905         //      n4      | 284   | 28
906         //      n5      | 285   | 29
907         //      n6      | 286   | 30
908         //      n7      | 287   | 31
909         //      a0          | 136   | 0
910         //      a1          | 137   | 1
911         //      a2      | 138   | 2
912         //      r0          | 151   | 16
913         //      r1          | 152   | 17
914         //      r2          | 153   | 18
915         //      r3          | 154   | 19
916         //      r4          | 155   | 20
917         //      r5          | 156   | 21
918         //      r6          | 157   | 22
919         //      r7          | 158   | 23
920 }
921
922
923 //
924 // Check for X:Y: parallel mode syntax
925 //
926 static inline LONG check_x_y(LONG ea1, LONG S1)
927 {
928         LONG inst;
929         LONG eax_temp, eay_temp;
930         LONG D1, D2, S2, ea2;
931         LONG K_D1, K_D2;
932         LONG w = 1 << 7;                // S1=0, D1=1<<14
933
934         if ((ea1 & 0x38) == DSP_EA_POSTINC || (ea1 & 0x38) == DSP_EA_POSTINC1 ||
935                 (ea1 & 0x38) == DSP_EA_POSTDEC1 || (ea1 & 0x38) == DSP_EA_NOUPD)
936         {
937                 switch (ea1 & 0x38)
938                 {
939                 case DSP_EA_POSTINC:  ea1 = (ea1 & (~0x38)) | 0x8; break;
940                 case DSP_EA_POSTINC1: ea1 = (ea1 & (~0x38)) | 0x18; break;
941                 case DSP_EA_POSTDEC1: ea1 = (ea1 & (~0x38)) | 0x10; break;
942                 case DSP_EA_NOUPD:    ea1 = (ea1 & (~0x38)) | 0x00; break;
943                 }
944
945                 if (S1 == 0)
946                 {
947                         // 'X:eax,D1 Y:eay,D2', 'X:eax,D1 S2,Y:eay'
948                         // Check for D1
949                         switch (K_D1 = *tok++)
950                         {
951                         case KW_X0: D1 = 0 << 10; break;
952                         case KW_X1: D1 = 1 << 10; break;
953                         case KW_A:  D1 = 2 << 10; break;
954                         case KW_B:  D1 = 3 << 10; break;
955                         default:    return error("unrecognised X:Y: parallel move syntax: expected x0, x1, a or b after 'X:eax,'");
956                         }
957                 }
958                 else
959                 {
960                         // 'S1,X:eax Y:eay,D2' 'S1,X:eax S2,Y:eay'
961                         w = 0;
962
963                         switch (S1)
964                         {
965                         case 4:  D1 = 0 << 10; break;
966                         case 5:  D1 = 1 << 10; break;
967                         case 14: D1 = 2 << 10; break;
968                         case 15: D1 = 3 << 10; break;
969                         default: return error("unrecognised X:Y: parallel move syntax: S1 can only be x0, x1, a or b in 'S1,X:eax'");
970                         }
971                 }
972
973                 if (*tok == KW_Y)
974                 {
975                         tok++;
976                         // 'X:eax,D1 Y:eay,D2' 'S1,X:eax Y:eay,D2'
977                         if (*tok++ != ':')
978                                 return error("unrecognised X:Y: parallel move syntax: expected ':' after 'X:ea,D1/S1,X:ea Y'");
979
980                         if (*tok++ == '(')
981                         {
982                                 if (*tok >= KW_R0 && *tok <= KW_R7)
983                                 {
984                                         ea2 = (*tok++ - KW_R0);
985
986                                         if (((ea1 & 7) < 4 && ea2 < 4) || ((ea1 & 7) >= 4 && ea2 > 4))
987                                                 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'");
988                                 }
989                                 else
990                                         return error("unrecognised X:Y: parallel move syntax: expected 'Rn' after 'X:ea,D1/S1,X:ea Y:('");
991
992                                 // If eax register is r0-r3 then eay register is r4-r7.
993                                 // Encode that to 2 bits (i.e. eay value is 0-3)
994                                 eax_temp = (ea2 & 3) << 5;  // Store register temporarily
995
996                                 if (*tok++ != ')')
997                                         return error("unrecognised X:Y: parallel move syntax: expected ')' after 'X:ea,D1/S1,X:ea Y:(Rn'");
998
999                                 if (*tok == '+')
1000                                 {
1001                                         tok++;
1002
1003                                         if (*tok == ',')
1004                                         {
1005                                                 // (Rn)+
1006                                                 ea2 = 3 << 12;
1007                                                 tok++;
1008                                         }
1009                                         else if (*tok >= KW_N0 && *tok <= KW_N7)
1010                                         {
1011                                                 // (Rn)+Nn
1012                                                 if ((*tok++ & 7) != ea2)
1013                                                         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')");
1014
1015                                                 ea2 = 1 << 12;
1016
1017                                                 if (*tok++ != ',')
1018                                                         return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea Y:(Rn)+Nn'");
1019                                         }
1020                                         else
1021                                                 return error("unrecognised X:Y: parallel move syntax: expected ',' or 'Nn' after 'X:ea,D1/S1,X:ea Y:(Rn)+'");
1022
1023                                 }
1024                                 else if (*tok == '-')
1025                                 {
1026                                         // (Rn)-
1027                                         ea2 = 2 << 12;
1028                                         tok++;
1029
1030                                         if (*tok++ != ',')
1031                                                 return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea Y:(Rn)-'");
1032                                 }
1033                                 else if (*tok++ == ',')
1034                                 {
1035                                         // (Rn)
1036                                         ea2 = 0 << 12;
1037                                 }
1038                                 else
1039                                         return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea Y:eay'");
1040
1041                                 ea2 |= eax_temp; // OR eay back from temp
1042
1043                                 switch (K_D2 = *tok++)
1044                                 {
1045                                 case KW_Y0: D2 = 0 << 8; break;
1046                                 case KW_Y1: D2 = 1 << 8; break;
1047                                 case KW_A:  D2 = 2 << 8; break;
1048                                 case KW_B:  D2 = 3 << 8; break;
1049                                 default:    return error("unrecognised X:Y: parallel move syntax: expected y0, y1, a or b after 'X:ea,D1/S1,X:ea Y:eay,'");
1050                                 }
1051
1052                                 if (*tok != EOL)
1053                                         return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea Y:eay,D'");
1054
1055                                 if (S1 == 0)
1056                                         if (K_D1 == K_D2)
1057                                                 return error("unrecognised X:Y: parallel move syntax: D1 and D2 cannot be the same in 'X:ea,D1 Y:eay,D2'");
1058
1059                                 inst = B16(11000000, 00000000) | w;
1060                                 inst |= ea1 | D1 | ea2 | D2;
1061                                 return inst;
1062                         }
1063                         else
1064                                 return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' after 'X:ea,D1/S1,X:ea Y:'");
1065                 }
1066                 else if (*tok == KW_Y0 || *tok == KW_Y1 || *tok == KW_A || *tok == KW_B)
1067                 {
1068                         // 'X:eax,D1 S2,Y:eay' 'S1,X:eax1 S2,Y:eay'
1069                         switch (*tok++)
1070                         {
1071                         case KW_Y0: S2 = 0 << 8; break;
1072                         case KW_Y1: S2 = 1 << 8; break;
1073                         case KW_A:  S2 = 2 << 8; break;
1074                         case KW_B:  S2 = 3 << 8; break;
1075                         default: return error("unrecognised X:Y: parallel move syntax: expected y0, y1, a or b after 'X:ea,D1/S1,X:ea Y:eay,'");
1076                         }
1077
1078                         if (*tok++ != ',')
1079                                 return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea S2'");
1080
1081                         if (*tok++ == KW_Y)
1082                         {
1083                                 // 'X:eax,D1 Y:eay,D2' 'S1,X:eax Y:eay,D2'
1084                                 if (*tok++ != ':')
1085                                         return error("unrecognised X:Y: parallel move syntax: expected ':' after 'X:ea,D1/S1,X:ea Y'");
1086
1087                                 if (*tok++ == '(')
1088                                 {
1089                                         if (*tok >= KW_R0 && *tok <= KW_R7)
1090                                         {
1091                                                 ea2 = (*tok++ - KW_R0);
1092
1093                                                 if (((ea1 & 7) < 4 && ea2 < 4) || ((ea1 & 7) >= 4 && ea2 > 4))
1094                                                         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'");
1095                                         }
1096                                         else
1097                                                 return error("unrecognised X:Y: parallel move syntax: expected 'Rn' after 'X:ea,D1/S1,X:ea S2,Y:('");
1098                                         // If eax register is r0-r3 then eay register is r4-r7.
1099                                         // Encode that to 2 bits (i.e. eay value is 0-3)
1100                                         eay_temp = (ea2 & 3) << 5; //Store register temporarily
1101
1102                                         if (*tok++ != ')')
1103                                                 return error("unrecognised X:Y: parallel move syntax: expected ')' after 'X:ea,D1/S1,X:ea S2,Y:(Rn'");
1104
1105                                         if (*tok == '+')
1106                                         {
1107                                                 tok++;
1108
1109                                                 if (*tok == EOL)
1110                                                         // (Rn)+
1111                                                         ea2 = 3 << 12;
1112                                                 else if (*tok >= KW_N0 && *tok <= KW_N7)
1113                                                 {
1114                                                         // (Rn)+Nn
1115                                                         if ((*tok++ & 7) != ea2)
1116                                                                 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')");
1117
1118                                                         ea2 = 1 << 12;
1119
1120                                                         if (*tok != EOL)
1121                                                                 return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea S2,Y:(Rn)+Nn'");
1122                                                 }
1123                                                 else
1124                                                         return error("unrecognised X:Y: parallel move syntax: expected ',' or 'Nn' after 'X:ea,D1/S1,X:ea S2,Y:(Rn)+'");
1125
1126                                         }
1127                                         else if (*tok == '-')
1128                                         {
1129                                                 // (Rn)-
1130                                                 ea2 = 2 << 12;
1131                                                 tok++;
1132                                                 if (*tok != EOL)
1133                                                         return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea S2,Y:(Rn)-'");
1134                                         }
1135                                         else if (*tok == EOL)
1136                                         {
1137                                                 // (Rn)
1138                                                 ea2 = 0 << 12;
1139                                         }
1140                                         else
1141                                                 return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea S2,Y:eay'");
1142
1143                                         ea2 |= eay_temp; //OR eay back from temp
1144
1145                                         inst = B16(10000000, 00000000) | w;
1146                                         inst |= (ea1 & 0x1f) | D1 | S2 | ea2;
1147                                         return inst;
1148                                 }
1149                                 else
1150                                         return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' after 'X:ea,D1/S1,X:ea Y:'");
1151                         }
1152                         else
1153                                 return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' in 'X:ea,D1/S1,X:ea'");
1154                 }
1155                 else
1156                         return error("unrecognised X:Y: or X:R parallel move syntax: expected Y:, A or B after 'X:ea,D1/S1,X:ea S2,'");
1157         }
1158
1159         return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' in 'X:ea,D1/S1,X:ea'");
1160 }
1161
1162 //
1163 // Parse X: addressing space parallel moves
1164 //
1165 static inline LONG parse_x(const int W, LONG inst, const LONG S1, const int check_for_x_y)
1166 {
1167         int immreg;                                     // Immediate register destination
1168         LONG S2, D1, D2;                        // Source and Destinations
1169         LONG ea1;                                       // ea bitfields
1170         uint32_t termchar = ',';        // Termination character for ea checks
1171         int force_imm = NUM_NORMAL;     // Holds forced immediate value (i.e. '<' or '>')
1172         ea1 = -1;                                       // initialise e1 (useful for some code paths)
1173
1174         if (W == 0)
1175                 termchar = EOL;
1176
1177         if (*tok == '-')
1178         {
1179                 if (tok[1] == CONST || tok[1] == FCONST)
1180                 {
1181                         tok++;
1182                         dspImmedEXVAL = *tok++;
1183                         goto x_check_immed;
1184                 }
1185
1186                 // This could be either -(Rn), -aa or -ea. Check for immediate first
1187                 if (tok[1] == SYMBOL)
1188                 {
1189                         if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) == OK)
1190                         {
1191                                 if (S1 != 0)
1192                                 {
1193 x_checkea_right:
1194                                         // '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'
1195                                         if (*tok == KW_X0 && tok[1] == ',' && tok[2] == KW_A)
1196                                         {
1197                                                 // 'A,X:ea X0,A'
1198                                                 if (ea1 == DSP_EA_ABS)
1199                                                         deposit_extra_ea = DEPOSIT_EXTRA_WORD;
1200
1201                                                 if (S1 != 14)
1202                                                         return error("unrecognised X:R parallel move syntax: S1 can only be a in 'a,X:ea x0,a'");
1203
1204                                                 if (ea1 == -1)
1205                                                         return error("unrecognised X:R parallel move syntax: absolute address not allowed in 'a,X:ea x0,a'");
1206
1207                                                 if (ea1 == B8(00110100))
1208                                                         return error("unrecognised X:R parallel move syntax: immediate data not allowed in 'a,X:ea x0,a'");
1209
1210                                                 inst = B16(00001000, 00000000) | ea1 | (0 << 8);
1211                                                 return inst;
1212                                         }
1213                                         else if (*tok == KW_X0 && tok[1] == ',' && tok[2] == KW_B)
1214                                         {
1215                                                 // 'B,X:ea X0,B'
1216                                                 if (ea1 == DSP_EA_ABS)
1217                                                         deposit_extra_ea = DEPOSIT_EXTRA_WORD;
1218
1219                                                 if (S1 != 15)
1220                                                         return error("unrecognised X:R parallel move syntax: S1 can only be b in 'b,X:ea x0,b'");
1221
1222                                                 if (ea1 == -1)
1223                                                         return error("unrecognised X:R parallel move syntax: absolute address not allowed in 'b,X:ea x0,b'");
1224
1225                                                 if (ea1 == B8(00110100))
1226                                                         return error("unrecognised X:R parallel move syntax: immediate data not allowed in 'b,X:ea x0,b'");
1227
1228                                                 inst = B16(00001001, 00000000) | ea1 | (1 << 8);
1229                                                 return inst;
1230                                         }
1231                                         else if (*tok == KW_A || *tok == KW_B)
1232                                         {
1233                                                 // 'S1,X:ea S2,D2', 'S1,X:eax S2,Y:eay'
1234                                                 switch (S1)
1235                                                 {
1236                                                 case 4:  D1 = 0 << 10; break;
1237                                                 case 5:  D1 = 1 << 10; break;
1238                                                 case 14: D1 = 2 << 10; break;
1239                                                 case 15: D1 = 3 << 10; break;
1240                                                 default: return error("unrecognised X:R parallel move syntax: S1 can only be x0, x1, a or b in 'S1,X:ea S2,D2'");
1241                                                 }
1242
1243                                                 if (tok[1] == ',' && tok[2] == KW_Y)
1244                                                 {
1245                                                         // 'S1,X:eax S2,Y:eay'
1246                                                         return check_x_y(ea1, S1);
1247                                                 }
1248
1249                                                 // 'S1,X:ea S2,D2'
1250                                                 if (ea1 == DSP_EA_ABS)
1251                                                         deposit_extra_ea = DEPOSIT_EXTRA_WORD;
1252
1253                                                 switch (*tok++)
1254                                                 {
1255                                                 case KW_A: S2 = 0 << 9; break;
1256                                                 case KW_B: S2 = 1 << 9; break;
1257                                                 default:   return error("unrecognised X:R parallel move syntax: expected a or b after 'S1,X:eax'");
1258                                                 }
1259
1260                                                 if (*tok++ != ',')
1261                                                         return error("unrecognised X:R parallel move syntax: expected ',' after 'S1,X:eax S2'");
1262
1263                                                 if (*tok == KW_Y0 || *tok == KW_Y1)
1264                                                 {
1265                                                         if (*tok++ == KW_Y0)
1266                                                                 D2 = 0 << 8;
1267                                                         else
1268                                                                 D2 = 1 << 8;
1269
1270                                                         if (*tok != EOL)
1271                                                                 return error("unrecognised X:R parallel move syntax: unexpected text after 'X:eax,D1 S2,S2'");
1272
1273                                                         inst = B16(00010000, 00000000) | (0 << 7);
1274                                                         inst |= ea1 | D1 | S2 | D2;
1275                                                         return inst;
1276                                                 }
1277                                                 else
1278                                                         return error("unrecognised X:R parallel move syntax: expected y0 or y1 after 'X:eax,D1 S2,'");
1279                                         }
1280                                         else if (*tok == KW_Y)
1281                                         {
1282                                                 // 'S1,X:eax Y:eay,D2'
1283                                                 return check_x_y(ea1, S1);
1284                                         }
1285                                         else if (*tok == KW_Y0 || *tok == KW_Y1)
1286                                         {
1287                                                 // 'S1,X:eax S2,Y:eay'
1288                                                 return check_x_y(ea1, S1);
1289                                         }
1290                                         else
1291                                                 return error("unrecognised X:Y or X:R parallel move syntax: expected y0 or y1 after 'X:eax,D1/X:ea,D1");
1292                                 }
1293                                 else
1294                                 {
1295                                         // Only check for aa if we have a defined number in our hands or we've
1296                                         // been asked to use a short number format. The former case we'll just test
1297                                         // it to see if it's small enough. The later - it's the programmer's call
1298                                         // so he'd better have a small address or the fixups will bite him/her in the arse!
1299                                         if (dspImmedEXATTR&DEFINED || force_imm == NUM_FORCE_SHORT)
1300                                         {
1301
1302                                                 // It's an immediate, so ea or eax is probably an absolute address
1303                                                 // (unless it's aa if the immediate is small enough)
1304                                                 // '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'
1305 x_check_immed:
1306                                                 // Check for aa (which is 6 bits zero extended)
1307                                                 if (dspImmedEXVAL < 0x40 && force_imm != NUM_FORCE_LONG)
1308                                                 {
1309                                                         if (W == 1)
1310                                                         {
1311                                                                 // It might be X:aa but we're not 100% sure yet.
1312                                                                 // If it is, the only possible syntax here is 'X:aa,D'.
1313                                                                 // So check ahead to see if EOL follows D, then we're good to go.
1314                                                                 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)
1315                                                                 {
1316                                                                         // Yup, we're good to go - 'X:aa,D' it is
1317                                                                         tok++;
1318                                                                         immreg = SDreg(*tok++);
1319                                                                         inst = inst | (uint32_t)dspImmedEXVAL;
1320                                                                         inst |= ((immreg & 0x18) << (12 - 3)) + ((immreg & 7) << 8);
1321                                                                         inst |= 1 << 7; // W
1322                                                                         return inst;
1323                                                                 }
1324                                                         }
1325                                                         else
1326                                                         {
1327                                                                 if (*tok == EOL)
1328                                                                 {
1329                                                                         // 'S,X:aa'
1330                                                                         inst = inst | (uint32_t)dspImmedEXVAL;
1331                                                                         inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8);
1332                                                                         return inst;
1333                                                                 }
1334                                                                 else
1335                                                                 {
1336                                                                         // 'S1,X:ea S2,D2', 'A,X:ea X0,A', 'B,X:ea X0,B',
1337                                                                         // 'S1,X:eax Y:eay,D2', 'S1,X:eax S2,Y:eay'
1338                                                                         ea1 = DSP_EA_ABS;
1339                                                                         deposit_extra_ea = DEPOSIT_EXTRA_WORD;
1340                                                                         goto x_checkea_right;
1341                                                                 }
1342                                                         }
1343                                                 }
1344                                         }
1345
1346                                         // Well, that settles it - we do have an ea in our hands
1347                                         if (W == 1)
1348                                         {
1349                                                 // 'X:ea,D' [... S2,d2]
1350                                                 if (*tok++ != ',')
1351                                                         return error("unrecognised X: parallel move syntax: expected ',' after 'X:ea'");
1352
1353                                                 if ((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2))
1354                                                 {
1355                                                         D1 = SDreg(*tok++);
1356
1357                                                         if (*tok == EOL)
1358                                                         {
1359                                                                 // 'X:ea,D'
1360                                                                 inst = inst | B8(01000000) | (1 << 7);
1361                                                                 inst |= ((D1 & 0x18) << (12 - 3)) + ((D1 & 7) << 8);
1362                                                                 inst |= ea1;
1363
1364                                                                 if (ea1 == DSP_EA_ABS)
1365                                                                         deposit_extra_ea = DEPOSIT_EXTRA_WORD;
1366
1367                                                                 return inst;
1368                                                         }
1369                                                         else
1370                                                         {
1371                                                                 // 'X:ea,D1 S2,D2'
1372                                                                 if (*tok == KW_A || *tok == KW_B)
1373                                                                 {
1374                                                                         S2 = SDreg(*tok++);
1375
1376                                                                         if (*tok++ != ',')
1377                                                                                 return error("unrecognised X:R parallel move syntax: expected comma after X:ea,D1 S2");
1378
1379                                                                         if (*tok == KW_Y0 || *tok == KW_Y1)
1380                                                                         {
1381                                                                                 D2 = SDreg(*tok++);
1382
1383                                                                                 if (*tok != EOL)
1384                                                                                         return error("unrecognised X:R parallel move syntax: expected EOL after X:ea,D1 S2,D2");
1385
1386                                                                                 inst = B16(00010000, 00000000) | (1 << 7);
1387                                                                                 inst |= ((D1 & 0x8) << (12 - 4)) + ((D1 & 1) << 10);
1388                                                                                 inst |= (S2 & 1) << 9;
1389                                                                                 inst |= (D2 & 1) << 8;
1390                                                                                 inst |= ea1;
1391                                                                                 return inst;
1392                                                                         }
1393                                                                         else
1394                                                                                 return error("unrecognised X:R parallel move syntax: expected y0,y1 after X:ea,D1 S2,");
1395                                                                 }
1396                                                                 else
1397                                                                         return error("unrecognised X:R parallel move syntax: expected a,b after X:ea,D1");
1398                                                         }
1399                                                 }
1400                                                 else
1401                                                         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,'");
1402                                         }
1403                                         else
1404                                         {
1405                                                 if (*tok == EOL)
1406                                                 {
1407                                                         // 'S,X:ea'
1408                                                         inst = inst | B8(01000000) | (0 << 7);
1409                                                         inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8);
1410                                                         inst |= ea1;
1411
1412                                                         if (ea1 == DSP_EA_ABS)
1413                                                                 deposit_extra_ea = DEPOSIT_EXTRA_WORD;
1414
1415                                                         return inst;
1416                                                 }
1417                                                 else
1418                                                 {
1419                                                         // 'S1,X:ea S2,D2', 'A,X:ea X0,A', 'B,X:ea X0,B',
1420                                                         // 'S1,X:eax Y:eay,D2', 'S1,X:eax S2,Y:eay'
1421                                                         goto x_checkea_right;
1422                                                 }
1423                                         }
1424
1425                                 }
1426                         }
1427                 }
1428                 else
1429                 {
1430                         // It's not an immediate, check for '-(Rn)'
1431                         ea1 = checkea(termchar, X_ERRORS);
1432
1433                         if (ea1 == ERROR)
1434                                 return ERROR;
1435
1436                         goto x_gotea1;
1437
1438                 }
1439         }
1440         else if (*tok == '#')
1441         {
1442                 tok++;
1443
1444                 if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
1445                         return ERROR;
1446
1447                 // Okay so we have immediate data - mark it down
1448                 ea1 = DSP_EA_IMM;
1449                 // Now, proceed to the main code for this branch
1450                 goto x_gotea1;
1451         }
1452         else if (*tok == '(')
1453         {
1454                 // Maybe we got an expression here, check for it
1455                 if (tok[1] == CONST || tok[1] == FCONST || tok[1] == SUNARY || tok[1] == SYMBOL || tok[1] == STRING)
1456                 {
1457                         // Evaluate the expression and go to immediate code path
1458                         expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM);
1459                         goto x_check_immed;
1460                 }
1461
1462                 // Nope, let's check for ea then
1463                 ea1 = checkea(termchar, X_ERRORS);
1464
1465                 if (ea1 == ERROR)
1466                         return ERROR;
1467
1468 x_gotea1:
1469                 if (W == 1)
1470                 {
1471                         if (*tok++ != ',')
1472                                 return error("Comma expected after 'X:(Rn)')");
1473
1474                         // It might be 'X:(Rn..)..,D' but we're not 100% sure yet.
1475                         // If it is, the only possible syntax here is 'X:ea,D'.
1476                         // So check ahead to see if EOL follows D, then we're good to go.
1477                         if (((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2)) && *(tok + 1) == EOL)
1478                         {
1479                                 //'X:ea,D'
1480                                 D1 = SDreg(*tok++);
1481
1482                                 inst = inst | B8(01000000) | (1 << 7);
1483                                 inst |= ea1;
1484                                 inst |= ((D1 & 0x18) << (12 - 3)) + ((D1 & 7) << 8);
1485                                 return inst;
1486                         }
1487                 }
1488                 else
1489                 {
1490                         if (*tok == EOL)
1491                         {
1492                                 //'S,X:ea'
1493                                 inst = inst | B8(01000000) | (0 << 7);
1494                                 inst |= ea1;
1495                                 inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8);
1496                                 return inst;
1497                         }
1498                         else
1499                         {
1500                                 goto x_checkea_right;
1501                         }
1502                 }
1503
1504                 // 'X:eax,D1 Y:eay,D2', 'X:eax,D1 S2,Y:eay' or 'X:ea,D1 S2,D2'
1505                 // Check ahead for S2,D2 - if that's true then we have 'X:ea,D1 S2,D2'
1506                 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)))
1507                 {
1508                         // 'X:ea,D1 S2,D2'
1509                         // Check if D1 is x0, x1, a or b
1510                         switch (*tok++)
1511                         {
1512                         case KW_X0: D1 = 0 << 10; break;
1513                         case KW_X1: D1 = 1 << 10; break;
1514                         case KW_A:  D1 = 2 << 10; break;
1515                         case KW_B:  D1 = 3 << 10; break;
1516                         default:    return error("unrecognised X:R parallel move syntax: expected x0, x1, a or b after 'X:eax,'");
1517                         }
1518
1519                         switch (*tok++)
1520                         {
1521                         case KW_A: S2 = 0 << 9; break;
1522                         case KW_B: S2 = 1 << 9; break;
1523                         default:   return error("unrecognised X:R parallel move syntax: expected a or b after 'X:eax,D1 '");
1524                         }
1525
1526                         if (*tok++ != ',')
1527                                 return error("unrecognised X:R parallel move syntax: expected ',' after 'X:eax,D1 S2'");
1528
1529                         if (*tok == KW_Y0 || *tok == KW_Y1)
1530                         {
1531                                 if (*tok++ == KW_Y0)
1532                                         D2 = 0 << 8;
1533                                 else
1534                                         D2 = 1 << 8;
1535
1536                                 if (*tok != EOL)
1537                                         return error("unrecognised X:R parallel move syntax: unexpected text after 'X:eax,D1 S2,S2'");
1538
1539                                 inst = B16(00010000, 00000000) | (W << 7);
1540                                 inst |= ea1 | D1 | S2 | D2;
1541                                 return inst;
1542                         }
1543                         else
1544                                 return error("unrecognised X:R parallel move syntax: expected y0 or y1 after 'X:eax,D1 S2,'");
1545                 }
1546
1547                 // Check to see if we got eax (which is a subset of ea)
1548                 if (check_for_x_y)
1549                 {
1550                         if ((inst = check_x_y(ea1, 0)) != 0)
1551                                 return inst;
1552                         else
1553                         {
1554                                 // Rewind pointer as it might be an expression and check for it
1555                                 tok--;
1556
1557                                 if (expr(dspaaEXPR, &dspaaEXVAL, &dspaaEXATTR, &dspaaESYM) != OK)
1558                                         return ERROR;
1559
1560                                 // Yes, we have an expression, so we now check for
1561                                 // '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'
1562                                 goto x_check_immed;
1563                         }
1564                 }
1565         }
1566         else if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
1567         {
1568                 // Check for immediate address
1569                 if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
1570                         return ERROR;
1571
1572                 // We set ea1 here - if it's aa instead of ea
1573                 // then it won't be used anyway
1574                 ea1 = DSP_EA_ABS;
1575
1576                 if (!(dspImmedEXATTR&DEFINED))
1577                 {
1578                         force_imm = NUM_FORCE_LONG;
1579                         deposit_extra_ea = DEPOSIT_EXTRA_WORD;
1580                 }
1581
1582                 goto x_check_immed;
1583         }
1584         else if (*tok == '>')
1585         {
1586                 // Check for immediate address forced long
1587                 tok++;
1588
1589                 if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
1590                         return ERROR;
1591
1592                 if ((dspImmedEXATTR & DEFINED) && (dspImmedEXVAL > 0xFFFFFF))
1593                         return error("long address is bigger than $FFFFFF");
1594
1595                 deposit_extra_ea = DEPOSIT_EXTRA_WORD;
1596
1597                 force_imm = NUM_FORCE_LONG;
1598                 ea1 = DSP_EA_ABS;
1599                 goto x_check_immed;
1600         }
1601         else if (*tok == '<')
1602         {
1603                 // Check for immediate address forced short
1604                 tok++;
1605
1606                 if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
1607                         return ERROR;
1608
1609                 force_imm = NUM_FORCE_SHORT;
1610
1611                 if (dspImmedEXATTR & DEFINED)
1612                 {
1613                         if (dspImmedEXVAL > 0x3F)
1614                         {
1615                                 if (optim_warn_flag)
1616                                         warn("short addressing mode forced but address is bigger than $3F - switching to long");
1617
1618                                 force_imm = NUM_FORCE_LONG;
1619                                 deposit_extra_ea = DEPOSIT_EXTRA_WORD;
1620                                 ea1 = DSP_EA_ABS;
1621                         }
1622                 }
1623                 else
1624                 {
1625                         // This might end up as something like 'move Y:<adr,register'
1626                         // so let's mark it as an extra aa fixup here.
1627                         // Note: we are branching to x_check_immed without a
1628                         // defined dspImmed so it's going to be 0. It probably
1629                         // doesn't harm anything.
1630                         deposit_extra_ea = DEPOSIT_EXTRA_FIXUP;
1631                 }
1632
1633                 goto x_check_immed;
1634         }
1635
1636         return error("unknown x: addressing mode");
1637 }
1638
1639
1640 //
1641 // Parse Y: addressing space parallel moves
1642 //
1643 static inline LONG parse_y(LONG inst, LONG S1, LONG D1, LONG S2)
1644 {
1645     int immreg;                                 // Immediate register destination
1646     LONG D2;                                    // Destination
1647     LONG ea1;                                   // ea bitfields
1648     int force_imm = NUM_NORMAL; // Holds forced immediate value (i.e. '<' or '>')
1649     if (*tok == '-')
1650     {
1651         if (tok[1] == CONST || tok[1] == FCONST)
1652         {
1653             tok++;
1654             dspImmedEXVAL = *tok++;
1655             goto y_check_immed;
1656         }
1657         // This could be either -(Rn), -aa or -ea. Check for immediate first
1658                 if (*tok == SYMBOL || tok[1] == SYMBOL)
1659                 {
1660                         if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) == OK)
1661                         {
1662                                 // Only check for aa if we have a defined number in our hands or we've
1663                                 // been asked to use a short number format. The former case we'll just test
1664                                 // it to see if it's small enough. The later - it's the programmer's call
1665                                 // so he'd better have a small address or the fixups will bite him/her in the arse!
1666                                 if (dspImmedEXATTR&DEFINED || force_imm == NUM_FORCE_SHORT)
1667                                 {
1668                                         // It's an immediate, so ea is probably an absolute address
1669                                         // (unless it's aa if the immediate is small enough)
1670                                         // 'Y:ea,D', 'Y:aa,D', 'S,Y:ea' or 'S,Y:aa'
1671                                 y_check_immed:
1672                                         // Check for aa (which is 6 bits zero extended)
1673                                         if (dspImmedEXVAL < 0x40 && force_imm != NUM_FORCE_LONG)
1674                                         {
1675                                                 // It might be Y:aa but we're not 100% sure yet.
1676                                                 // If it is, the only possible syntax here is 'Y:aa,D'/'S,Y:aa'.
1677                                                 // So check ahead to see if EOL follows D, then we're good to go.
1678                                                 if (*tok == EOL && S1 != 0)
1679                                                 {
1680                                                         // 'S,Y:aa'
1681                                                         inst = B16(01001000, 00000000);
1682                                                         inst |= dspImmedEXVAL;
1683                                                         inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8);
1684                                                         return inst;
1685                                                 }
1686
1687                                                 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)
1688                                                 {
1689                                                         // Yup, we're good to go - 'Y:aa,D' it is
1690                                                         tok++;
1691                                                         immreg = SDreg(*tok++);
1692                                                         inst |= dspImmedEXVAL;
1693                                                         inst |= ((immreg & 0x18) << (12 - 3)) + ((immreg & 7) << 8);
1694                                                         return inst;
1695                                                 }
1696                                         }
1697                                 }
1698                                 // Well, that settles it - we do have a ea in our hands
1699                                 if (*tok == EOL && S1 != 0)
1700                                 {
1701                                         // 'S,Y:ea'
1702                                         inst = B16(01001000, 01110000);
1703                                         inst |= ea1;
1704                                         inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8);
1705                                         if (ea1 == DSP_EA_ABS)
1706                                                 deposit_extra_ea = DEPOSIT_EXTRA_WORD;
1707                                         return inst;
1708                                 }
1709
1710                                 if (*tok++ != ',')
1711                                         return error("unrecognised Y: parallel move syntax: expected ',' after 'Y:ea'");
1712
1713                                 if (D1 == 0 && S1 == 0)
1714                                 {
1715                                         // 'Y:ea,D'
1716                                         if ((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2))
1717                                         {
1718                                                 D1 = SDreg(*tok++);
1719
1720                                                 if (*tok != EOL)
1721                                                         return error("unrecognised Y: parallel move syntax: expected EOL after 'Y:ea,D'");
1722
1723                                                 inst |= B16(00000000, 01110000);
1724                                                 inst |= ea1;
1725                                                 inst |= ((D1 & 0x18) << (12 - 3)) + ((D1 & 7) << 8);
1726                                                 if (ea1 == DSP_EA_ABS)
1727                                                         deposit_extra_ea = DEPOSIT_EXTRA_WORD;
1728                                                 return inst;
1729                                         }
1730                                         else
1731                                                 return error("unrecognised Y: parallel move syntax: expected x0,x1,y0,y1,a0,b0,a2,b2,a1,b1,a,b,r0-r7,n0-n7 after 'Y:ea,'");
1732                                 }
1733                                 else
1734                                 {
1735                                         // 'S1,D1 Y:ea,D2'
1736                                         if (*tok == KW_A || *tok == KW_B || *tok == KW_Y0 || *tok == KW_Y1)
1737                                         {
1738                                                 D2 = SDreg(*tok++);
1739                                                 inst |= ea1;
1740                                                 inst |= 1 << 7;
1741                                                 inst |= (S1 & 1) << 11;
1742                                                 inst |= (D1 & 1) << 10;
1743                                                 inst |= (D2 & 8) << (9 - 3);
1744                                                 inst |= (D2 & 1) << 8;
1745                                                 return inst;
1746                                         }
1747                                         else
1748                                                 return error("unrecognised R:Y: parallel move syntax: expected a,b after 'S1,D1 Y:ea,'");
1749                                 }
1750                         }
1751                         else
1752                                 return ERROR;
1753                 }
1754                 else
1755                 {
1756                         // It's not an immediate, check for '-(Rn)'
1757                         ea1 = checkea(',', Y_ERRORS);
1758
1759                         if (ea1 == ERROR)
1760                                 return ERROR;
1761
1762                         goto y_gotea1;
1763
1764                 }
1765         }
1766         else if (*tok == '#')
1767         {
1768                 tok++;
1769
1770                 if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
1771                         return ERROR;
1772
1773                 // Okay so we have immediate data - mark it down
1774                 ea1 = DSP_EA_IMM;
1775                 // Now, proceed to the main code for this branch
1776                 goto y_gotea1;
1777         }
1778         else if (*tok == '(')
1779         {
1780                 // Maybe we got an expression here, check for it
1781                 if (tok[1] == CONST || tok[1] == FCONST || tok[1] == SUNARY || tok[1] == SYMBOL || tok[1] == STRING)
1782                 {
1783                         // Evaluate the expression and go to immediate code path
1784                         expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM);
1785                         goto y_check_immed;
1786                 }
1787
1788                 // Nope, let's check for ea then
1789                 if (S1 == 0 || (S1 != 0 && D1 != 0))
1790                         ea1 = checkea(',', Y_ERRORS);
1791                 else
1792                         ea1 = checkea(EOL, Y_ERRORS);
1793
1794                 if (ea1 == ERROR)
1795                         return ERROR;
1796
1797         y_gotea1:
1798                 if (S1 != 0 && *tok == EOL)
1799                 {
1800                         // 'S,Y:ea'
1801                         inst = B16(01001000, 01000000);
1802                         inst |= ea1;
1803                         inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8);
1804                         return inst;
1805                 }
1806                 else if (S1 != 0 && D1 != 0 && S2 == 0)
1807                 {
1808                         // 'S1,D1 Y:ea,D2'
1809                         switch (S1)
1810                         {
1811                         case 14: S1 = 0 << 11; break; // A
1812                         case 15: S1 = 1 << 11; break; // B
1813                         default: return error("unrecognised R:Y parallel move syntax: S1 can only be A or B in 'S1,D1 Y:ea,D2'"); break;
1814                         }
1815
1816                         switch (D1)
1817                         {
1818                         case 4: D1 = 0 << 10; break; // X0
1819                         case 5: D1 = 1 << 10; break; // X1
1820                         default: return error("unrecognised R:Y parallel move syntax: D1 can only be x0 or x1 in 'S1,D1 Y:ea,D2'");break;
1821                         }
1822
1823                         if (*tok++ != ',')
1824                                 return error("unrecognised R:Y parallel move syntax: expected ',' after 'S1,D1 Y:ea'");
1825
1826                         switch (*tok++)
1827                         {
1828                         case KW_Y0: D2 = 0 << 8; break;
1829                         case KW_Y1: D2 = 1 << 8; break;
1830                         case KW_A:  D2 = 2 << 8; break;
1831                         case KW_B:  D2 = 3 << 8; break;
1832                         default: return error("unrecognised R:Y parallel move syntax: D2 can only be y0, y1, a or b after 'S1,D1 Y:ea'");
1833                         }
1834
1835                         inst = B16(00010000, 11000000);
1836                         inst |= S1 | D1 | D2;
1837                         inst |= ea1;
1838                         return inst;
1839                 }
1840
1841                 if (*tok++ != ',')
1842             return error("Comma expected after 'Y:(Rn)')");
1843
1844                 // It might be 'Y:(Rn..)..,D' but we're not 100% sure yet.
1845                 // If it is, the only possible syntax here is 'Y:ea,D'.
1846                 // So check ahead to see if EOL follows D, then we're good to go.
1847                 if (((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2)) && *(tok + 1) == EOL)
1848                 {
1849                         //'Y:ea,D'
1850                         D1 = SDreg(*tok++);
1851                         inst |= B16(00000000, 01000000);
1852                         inst |= ea1;
1853                         inst |= ((D1 & 0x18) << (12 - 3)) + ((D1 & 7) << 8);
1854                         return inst;
1855                 }
1856         }
1857         else if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
1858         {
1859                 // Check for immediate address
1860                 if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
1861                         return ERROR;
1862
1863                 // Yes, we have an expression, so we now check for
1864                 // 'Y:ea,D' or 'Y:aa,D'
1865                 ea1 = DSP_EA_ABS; // Reluctant - but it's probably correct
1866
1867                 if (!(dspImmedEXATTR&DEFINED))
1868                 {
1869                         force_imm = NUM_FORCE_LONG;
1870                         deposit_extra_ea = DEPOSIT_EXTRA_WORD;
1871                 }
1872
1873                 goto y_check_immed;
1874         }
1875         else if (*tok == '>')
1876         {
1877                 // Check for immediate address forced long
1878                 tok++;
1879
1880                 if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
1881                         return ERROR;
1882
1883                 if ((dspImmedEXATTR & DEFINED) && (dspImmedEXVAL > 0xFFFFFF))
1884                         return error("long address is bigger than $FFFFFF");
1885
1886                 deposit_extra_ea = DEPOSIT_EXTRA_WORD;
1887
1888                 force_imm = NUM_FORCE_LONG;
1889                 ea1 = DSP_EA_ABS;
1890                 goto y_check_immed;
1891         }
1892         else if (*tok == '<')
1893         {
1894                 tok++;
1895
1896                 if (S1 != 0 && D1 != 0)
1897                 {
1898                         // We're in 'S1,D1 Y:ea,D2' or 'S1,D1 S1,Y:ea'
1899                         // there's no Y:aa mode here, so we'll force long
1900                         if (optim_warn_flag)
1901                                 warn("forced short addressing in R:Y mode is not allowed - switching to long");
1902
1903                         if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
1904                                 return ERROR;
1905
1906                         ea1 = DSP_EA_ABS;
1907
1908                         force_imm = NUM_FORCE_LONG;
1909                         deposit_extra_ea = DEPOSIT_EXTRA_WORD;
1910                         goto y_check_immed;
1911                 }
1912                 else
1913                 {
1914                         // Check for immediate address forced short
1915                         ea1 = DSP_EA_ABS; // Reluctant - but it's probably correct
1916
1917                         if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
1918                                 return ERROR;
1919
1920                         force_imm = NUM_FORCE_SHORT;
1921
1922                         if (dspImmedEXATTR & DEFINED)
1923                         {
1924                                 if (dspImmedEXVAL > 0xFFF)
1925                                 {
1926                                         if (optim_warn_flag)
1927                                                 warn("short addressing mode forced but address is bigger than $FFF - switching to long");
1928
1929                                         ea1 = DSP_EA_ABS;
1930                                         force_imm = NUM_FORCE_LONG;
1931                                         deposit_extra_ea = DEPOSIT_EXTRA_WORD;
1932                                 }
1933                         }
1934                         else
1935                         {
1936                                 // This might end up as something like 'move Y:<adr,register'
1937                                 // so let's mark it as an extra aa fixup here.
1938                                 // Note: we are branching to y_check_immed without a
1939                                 // defined dspImmed so it's going to be 0. It probably
1940                                 // doesn't harm anything.
1941                                 deposit_extra_ea = DEPOSIT_EXTRA_FIXUP;
1942                         }
1943
1944                         goto y_check_immed;
1945                 }
1946         }
1947
1948         return error("unrecognised Y: parallel move syntax");
1949 }
1950
1951
1952 //
1953 // Parse L: addressing space parallel moves
1954 //
1955 static inline LONG parse_l(const int W, LONG inst, LONG S1)
1956 {
1957         int immreg;                                     // Immediate register destination
1958         LONG D1;                                        // Source and Destinations
1959         LONG ea1;                                       // ea bitfields
1960         int force_imm = NUM_NORMAL;     // Holds forced immediate value (i.e. '<' or '>')
1961
1962         if (*tok == '-')
1963         {
1964                 if (*tok == CONST || tok[1] == FCONST)
1965                 {
1966                         tok++;
1967                         dspImmedEXVAL = *tok++;
1968                         goto l_check_immed;
1969                 }
1970
1971                 // This could be either -(Rn), -aa or -ea. Check for immediate first
1972                 // Maybe we got an expression here, check for it
1973                 if (*tok == SYMBOL || tok[1] == SYMBOL)
1974                 {
1975                         // Evaluate the expression and go to immediate code path
1976                         if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) == OK)
1977                         {
1978                                 // Only check for aa if we have a defined number in our hands
1979                                 // or we've been asked to use a short number format. The
1980                                 // former case we'll just test it to see if it's small enough.
1981                                 // The later - it's the programmer's call so he'd better have
1982                                 // a small address or the fixups will bite him/her in the arse!
1983                                 if (dspImmedEXATTR&DEFINED || force_imm == NUM_FORCE_SHORT)
1984                                 {
1985                                         // It's an immediate, so ea is probably an absolute address
1986                                         // (unless it's aa if the immediate is small enough)
1987                                         // 'L:ea,D' or 'L:aa,D'
1988                                 l_check_immed:
1989                                         // Check for aa (which is 6 bits zero extended)
1990                                         if (*tok == EOL)
1991                                         {
1992                                                 // 'S,L:aa'
1993                                                 if (dspImmedEXVAL < 0x40 && force_imm != NUM_FORCE_LONG)
1994                                                 {
1995                                                         // 'S,L:aa'
1996                                                         if (S1 == KW_A)
1997                                                                 S1 = 4;
1998                                                         else if (S1 == KW_B)
1999                                                                 S1 = 5;
2000                                                         else
2001                                                                 S1 &= 7;
2002
2003                                                         inst = B16(01000000, 00000000);
2004                                                         inst |= dspImmedEXVAL;
2005                                                         inst |= ((S1 & 0x4) << (11 - 2)) + ((S1 & 3) << 8);
2006                                                         return inst;
2007                                                 }
2008                                                 else
2009                                                 {
2010                                                         // 'S,L:ea'
2011                                                         if (S1 == KW_A)
2012                                                                 S1 = 4;
2013                                                         else if (S1 == KW_B)
2014                                                                 S1 = 5;
2015                                                         else
2016                                                                 S1 &= 7;
2017
2018                                                         if (ea1 == DSP_EA_ABS)
2019                                                                 deposit_extra_ea = DEPOSIT_EXTRA_WORD;
2020
2021                                                         inst |= B16(01000000, 01110000);
2022                                                         inst |= ((S1 & 0x4) << (11 - 2)) + ((S1 & 3) << 8);
2023                                                         inst |= ea1;
2024                                                         return inst;
2025                                                 }
2026
2027                                         }
2028
2029                                         if (*tok++ != ',')
2030                                                 return error("unrecognised L: parallel move syntax: expected ',' after 'L:ea/L:aa'");
2031
2032                                         // Check for allowed registers for D (a0, b0, x, y, a, b, ab or ba)
2033                                         if (!((*tok >= KW_A10 && *(tok + 1) <= KW_BA) || (*tok >= KW_A && *tok <= KW_B)))
2034                                                 return error("unrecognised L: parallel move syntax: expected a0, b0, x, y, a, b, ab or ba after 'L:ea/L:aa'");
2035
2036                                         if (dspImmedEXVAL < (1 << 6) && (dspImmedEXATTR&DEFINED))
2037                                         {
2038                                                 // 'L:aa,D'
2039                                                 l_aa:
2040                                                 immreg = *tok++;
2041
2042                                                 if (immreg == KW_A)
2043                                                         immreg = 4;
2044                                                 else if (immreg == KW_B)
2045                                                         immreg = 5;
2046                                                 else
2047                                                         immreg &= 7;
2048
2049                                                 if (*tok != EOL)
2050                                                         return error("unrecognised L: parallel move syntax: expected End-Of-Line after L:aa,D");
2051
2052                                                 inst &= B16(11111111, 10111111);
2053                                                 inst |= dspImmedEXVAL;
2054                                                 inst |= ((immreg & 0x4) << (11 - 2)) + ((immreg & 3) << 8);
2055                                                 return inst;
2056                                         }
2057                                 }
2058
2059                                 if (deposit_extra_ea == DEPOSIT_EXTRA_FIXUP)
2060                                 {
2061                                         // Hang on, we've got a L:<aa here, let's do that instead
2062                                         goto l_aa;
2063                                 }
2064
2065                                 // Well, that settles it - we do have a ea in our hands
2066                                 // 'L:ea,D'
2067                                 D1 = *tok++;
2068
2069                                 if (D1 == KW_A)
2070                                         D1 = 4;
2071                                 else if (D1 == KW_B)
2072                                         D1 = 5;
2073                                 else
2074                                         D1 &= 7;
2075
2076                                 if (*tok != EOL)
2077                                         return error("unrecognised L: parallel move syntax: expected End-Of-Line after L:ea,D");
2078
2079                                 inst |= B16(00000000, 00110000);
2080                                 inst |= ((D1 & 0x4) << (11 - 2)) + ((D1 & 3) << 8);
2081                                 return inst;
2082                         }
2083                 }
2084                 else
2085                 {
2086                         //It's not an immediate, check for '-(Rn)'
2087                         ea1 = checkea(',', L_ERRORS);
2088
2089                         if (ea1 == ERROR)
2090                                 return ERROR;
2091
2092                         goto l_gotea1;
2093
2094                 }
2095         }
2096         else if (*tok == '(')
2097         {
2098                 // Maybe we got an expression here, check for it
2099                 if (tok[1] == CONST || tok[1] == FCONST || tok[1] == SUNARY || tok[1] == SYMBOL || tok[1] == STRING)
2100                 {
2101                         // Evaluate the expression and go to immediate code path
2102                         expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM);
2103                         goto l_check_immed;
2104                 }
2105
2106                 //Nope, let's check for ea then
2107                 if (S1 == 0)
2108                         ea1 = checkea(',', L_ERRORS);
2109                 else
2110                         ea1 = checkea(EOL, L_ERRORS);
2111
2112                 if (ea1 == ERROR)
2113                         return ERROR;
2114
2115         l_gotea1:
2116                 if (*tok == EOL)
2117                 {
2118                         // 'S,L:ea'
2119                         inst = B16(01000000, 01000000);
2120
2121                         if (S1 == KW_A)
2122                                 S1 = 4;
2123                         else if (S1 == KW_B)
2124                                 S1 = 5;
2125                         else
2126                                 S1 &= 7;
2127
2128                         inst |= ea1;
2129                         inst |= ((S1 & 0x4) << (11 - 2)) + ((S1 & 3) << 8);
2130                         return inst;
2131                 }
2132                 else if (*tok++ != ',')
2133                         return error("Comma expected after 'L:(Rn)')");
2134
2135                 // It might be 'L:(Rn..)..,D' but we're not 100% sure yet.
2136                 // If it is, the only possible syntax here is 'L:ea,D'.
2137                 // So check ahead to see if EOL follows D, then we're good to go.
2138                 if (((*tok >= KW_A10 && *tok <= KW_BA) || (*tok >= KW_A && *tok <= KW_B)) && *(tok + 1) == EOL)
2139                 {
2140                         //'L:ea,D'
2141                         D1 = *tok++;
2142
2143                         if (D1 == KW_A)
2144                                 D1 = 4;
2145                         else if (D1 == KW_B)
2146                                 D1 = 5;
2147                         else
2148                                 D1 &= 7;
2149
2150                         inst |= ea1;
2151                         inst |= ((D1 & 0x4) << (11 - 2)) + ((D1 & 3) << 8);
2152                         return inst;
2153                 }
2154         }
2155         else if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
2156         {
2157                 // Check for immediate address
2158                 if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
2159                         return ERROR;
2160
2161                 // We set ea1 here - if it's aa instead of ea
2162                 // then it won't be used anyway
2163                 ea1 = DSP_EA_ABS;
2164
2165                 if (!(dspImmedEXATTR & DEFINED))
2166                 {
2167                         force_imm = NUM_FORCE_LONG;
2168                         deposit_extra_ea = DEPOSIT_EXTRA_WORD;
2169                 }
2170                 else if (dspImmedEXVAL > 0x3f)
2171                 {
2172                         // Definitely no aa material, so it's going to be a long
2173                         // Mark that we need to deposit an extra word
2174                         deposit_extra_ea = DEPOSIT_EXTRA_WORD;
2175                 }
2176
2177                 // Yes, we have an expression, so we now check for
2178                 // 'L:ea,D' or 'L:aa,D'
2179                 goto l_check_immed;
2180         }
2181         else if (*tok == '>')
2182         {
2183                 // Check for immediate address forced long
2184                 tok++;
2185
2186                 if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
2187                         return ERROR;
2188
2189                 if ((dspImmedEXATTR & DEFINED) && (dspImmedEXVAL > 0xFFFFFF))
2190                         return error("long address is bigger than $FFFFFF");
2191
2192                 deposit_extra_ea = DEPOSIT_EXTRA_WORD;
2193
2194                 force_imm = NUM_FORCE_LONG;
2195                 goto l_check_immed;
2196         }
2197         else if (*tok == '<')
2198         {
2199                 // Check for immediate address forced short
2200                 tok++;
2201
2202                 if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
2203                         return ERROR;
2204
2205                 if (dspImmedEXATTR & DEFINED)
2206                 {
2207                         if (dspImmedEXVAL > 0xFFF)
2208                                 return error("short addressing mode forced but address is bigger than $FFF");
2209                 }
2210                 else
2211                 {
2212                         // This might end up as something like 'move Y:<adr,register'
2213                         // so let's mark it as an extra aa fixup here.
2214                         // Note: we are branching to l_check_immed without a
2215                         // defined dspImmed so it's going to be 0. It probably
2216                         // doesn't harm anything.
2217                         deposit_extra_ea = DEPOSIT_EXTRA_FIXUP;
2218                 }
2219
2220                 force_imm = NUM_FORCE_SHORT;
2221                 goto l_check_immed;
2222         }
2223
2224         return error("internal assembler error: Please report this error message: 'reached the end of parse_l' with the line of code that caused it. Thanks, and sorry for the inconvenience");
2225 }
2226
2227
2228 //
2229 // Checks for all ea cases where indexed addressing is concenred
2230 //
2231 static inline LONG checkea(const uint32_t termchar, const int strings)
2232 {
2233         LONG ea;
2234
2235         if (*tok == '-')
2236         {
2237                 // -(Rn)
2238                 tok++;
2239
2240                 if (*tok++ != '(')
2241                         return error(ea_errors[strings][0]);
2242
2243                 if (*tok >= KW_R0 && *tok <= KW_R7)
2244                 {
2245                         // We got '-(Rn' so mark it down
2246                         ea = DSP_EA_PREDEC1 | (*tok++ - KW_R0);
2247
2248                         if (*tok++ != ')')
2249                                 return error(ea_errors[strings][1]);
2250
2251                         // Now, proceed to the main code for this branch
2252                         return ea;
2253                 }
2254                 else
2255                         return error(ea_errors[strings][2]);
2256         }
2257         else if (*tok == '(')
2258         {
2259                 // Checking for ea of type (Rn)
2260                 tok++;
2261
2262                 if (*tok >= KW_R0 && *tok <= KW_R7)
2263                 {
2264                         // We're in 'X:(Rn..)..,D', 'X:(Rn..)..,D1 Y:eay,D2', 'X:(Rn..)..,D1 S2,Y:eay'
2265                         ea = *tok++ - KW_R0;
2266
2267                         if (*tok == '+')
2268                         {
2269                                 // '(Rn+Nn)'
2270                                 tok++;
2271
2272                                 if (*tok < KW_N0 || *tok > KW_N7)
2273                                         return error(ea_errors[strings][3]);
2274
2275                                 if ((*tok++ & 7) != ea)
2276                                         return error(ea_errors[strings][4]);
2277
2278                                 ea |= DSP_EA_INDEX;
2279
2280                                 if (*tok++ != ')')
2281                                         return error(ea_errors[strings][5]);
2282
2283                                 return ea;
2284                         }
2285                         else if (*tok == ')')
2286                         {
2287                                 // Check to see if we have '(Rn)+', '(Rn)-', '(Rn)-Nn', '(Rn)+Nn' or '(Rn)'
2288                                 tok++;
2289
2290                                 if (*tok == '+')
2291                                 {
2292                                         tok++;
2293
2294                                         if (termchar == ',')
2295                                         {
2296                                                 if (*tok == ',')
2297                                                 {
2298                                                         // (Rn)+
2299                                                         ea |= DSP_EA_POSTINC1;
2300                                                         return ea;
2301                                                 }
2302                                                 else if (*tok >= KW_N0 && *tok <= KW_N7)
2303                                                 {
2304                                                         // (Rn)+Nn
2305                                                         if ((*tok++ & 7) != ea)
2306                                                                 return error(ea_errors[strings][6]);
2307
2308                                                         ea |= DSP_EA_POSTINC;
2309                                                         return ea;
2310                                                 }
2311                                                 else
2312                                                         return error(ea_errors[strings][7]);
2313                                         }
2314                                         else
2315                                         {
2316                                                 if (*tok >= KW_N0 && *tok <= KW_N7)
2317                                                 {
2318                                                         // (Rn)+Nn
2319                                                         if ((*tok++ & 7) != ea)
2320                                                                 return error(ea_errors[strings][6]);
2321
2322                                                         ea |= DSP_EA_POSTINC;
2323                                                         return ea;
2324                                                 }
2325                                                 else
2326                                                 {
2327                                                         // (Rn)+
2328                                                         ea |= DSP_EA_POSTINC1;
2329                                                         return ea;
2330                                                 }
2331                                         }
2332                                 }
2333                                 else if (*tok == '-')
2334                                 {
2335                                         tok++;
2336
2337                                         if (termchar == ',')
2338                                         {
2339                                                 if (*tok == ',')
2340                                                 {
2341                                                         // (Rn)-
2342                                                         ea |= DSP_EA_POSTDEC1;
2343                                                         return ea;
2344                                                 }
2345                                                 else if (*tok >= KW_N0 && *tok <= KW_N7)
2346                                                 {
2347                                                         // (Rn)-Nn
2348                                                         if ((*tok++ & 7) != ea)
2349                                                                 return error(ea_errors[strings][8]);
2350
2351                                                         ea |= DSP_EA_POSTDEC;
2352                                                         return ea;
2353                                                 }
2354                                                 else
2355                                                         return error(ea_errors[strings][9]);
2356                                         }
2357                                         else
2358                                         {
2359                                                 if (*tok >= KW_N0 && *tok <= KW_N7)
2360                                                 {
2361                                                         // (Rn)-Nn
2362                                                         if ((*tok++ & 7) != ea)
2363                                                                 return error(ea_errors[strings][8]);
2364
2365                                                         ea |= DSP_EA_POSTDEC;
2366                                                         return ea;
2367                                                 }
2368                                                 else
2369                                                 {
2370                                                         // (Rn)-
2371                                                         ea |= DSP_EA_POSTDEC1;
2372                                                         return ea;
2373                                                 }
2374                                         }
2375                                 }
2376                                 else if (termchar == ',')
2377                                 {
2378                                         if (*tok == ',')
2379                                         {
2380                                                 // (Rn)
2381                                                 ea |= DSP_EA_NOUPD;
2382                                                 return ea;
2383                                         }
2384                                         else
2385                                                 return error(ea_errors[strings][10]);
2386                                 }
2387                                 else
2388                                 {
2389                                         // (Rn)
2390                                         ea |= DSP_EA_NOUPD;
2391                                         return ea;
2392                                 }
2393                         }
2394                         else
2395                                 return error(ea_errors[strings][11]);
2396                 }
2397         }
2398
2399         return error("internal assembler error: Please report this error message: 'reached the end of checkea' with the line of code that caused it. Thanks, and sorry for the inconvenience");
2400 }
2401
2402
2403 //
2404 // Checks for all ea cases, i.e. all addressing modes that checkea handles
2405 // plus immediate addresses included forced short/long ones.
2406 // In other words this is a superset of checkea (and in fact calls checkea).
2407 //
2408 LONG checkea_full(const uint32_t termchar, const int strings)
2409 {
2410         LONG ea1;
2411
2412         if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
2413         {
2414                 // Check for immediate address
2415                 if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
2416                         return ERROR;
2417
2418                 deposit_extra_ea = DEPOSIT_EXTRA_WORD;
2419
2420                 // Yes, we have an expression
2421                 return DSP_EA_ABS;
2422         }
2423         else if (*tok == '>')
2424         {
2425                 // Check for immediate address forced long
2426                 tok++;
2427
2428                 if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
2429                         return ERROR;
2430
2431                 if ((dspImmedEXATTR & DEFINED) && (dspImmedEXVAL > 0xFFFFFF))
2432                         return error("long address is bigger than $FFFFFF");
2433
2434                 deposit_extra_ea = DEPOSIT_EXTRA_WORD;
2435
2436                 // Yes, we have an expression
2437                 return DSP_EA_ABS;
2438         }
2439         else if (*tok == '<')
2440         {
2441                 // Check for immediate address forced short
2442                 tok++;
2443
2444                 if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
2445                         return ERROR;
2446
2447                 if ((dspImmedEXATTR & DEFINED) && (dspImmedEXVAL > 0xFFF))
2448                         return error("short addressing mode forced but address is bigger than $FFF");
2449
2450                 // Yes, we have an expression
2451                 return DSP_EA_ABS;
2452         }
2453         else
2454         {
2455                 ea1 = checkea(termchar, strings);
2456
2457                 if (ea1 == ERROR)
2458                         return ERROR;
2459                 else
2460                         return ea1;
2461         }
2462
2463 }
2464
2465
2466 //
2467 // Main routine to check parallel move modes.
2468 // It's quite complex so it's split into a few procedures (in fact most of the
2469 // above ones). A big effort was made so this can be managable and not too
2470 // hacky, however one look at the 56001 manual regarding parallel moves and
2471 // you'll know that this is not an easy // problem to deal with!
2472 // dest=destination register from the main opcode. This must not be the same
2473 // as D1 or D2 and that even goes for stuff like dest=A, D1=A0/1/2!!!
2474 //
2475 LONG parmoves(WORD dest)
2476 {
2477         int force_imm;          // Addressing mode force operator
2478         int immreg;             // Immediate register destination
2479         LONG inst;              // 16 bit bitfield that has the parallel move opcode
2480         LONG S1, S2, D1, D2;    // Source and Destinations
2481         LONG ea1;                               // ea bitfields
2482
2483         if (*tok == EOL)
2484         {
2485                 // No parallel move
2486                 return B16(00100000, 00000000);
2487         }
2488
2489         if (*tok == '#')
2490         {
2491                 // '#xxxxxx,D', '#xx,D'
2492                 tok++;
2493                 force_imm = NUM_NORMAL;
2494
2495                 if (*tok == '>')
2496                 {
2497                         force_imm = NUM_FORCE_LONG;
2498                         tok++;
2499                 }
2500                 else if (*tok == '<')
2501                 {
2502                         force_imm = NUM_FORCE_SHORT;
2503                         tok++;
2504                 }
2505
2506                 if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
2507                         return ERROR;
2508
2509                 if (*tok++ != ',')
2510                         return error("expected comma");
2511
2512                 if (!((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2)))
2513                         return error("expected x0,x1,y0,y1,a0,b0,a2,b2,a1,b1,a,b,r0-r7,n0-n7 after immediate");
2514
2515                 immreg = SDreg(*tok++);
2516
2517                 if (*tok == EOL)
2518                 {
2519                         if (!(dspImmedEXATTR & FLOAT))
2520                         {
2521                                 if (dspImmedEXATTR & DEFINED)
2522                                 {
2523                                         // From I parallel move:
2524                                         // "If the destination register D is X0, X1, Y0, Y1, A, or
2525                                         // B, the 8-bit immediate short operand is interpreted as
2526                                         // a signed fraction and is stored in the specified
2527                                         // destination register. That is, the 8 - bit data is
2528                                         // stored in the eight MS bits of the destination operand,
2529                                         // and the remaining bits of the destination operand D are
2530                                         // zeroed."
2531                                         // The funny bit is that Motorola assembler can parse
2532                                         // something like 'move #$FF0000,b' into an I (immediate
2533                                         // short move) - so let's do that as well then...
2534                                         if (((immreg >= 4 && immreg <= 7) || immreg == 14 || immreg == 15) && force_imm != NUM_FORCE_LONG)
2535                                         {
2536                                                 if ((dspImmedEXVAL & 0xFFFF) == 0)
2537                                                 {
2538                                                         dspImmedEXVAL >>= 16;
2539                                                 }
2540                                         }
2541
2542                                         if (force_imm == NUM_FORCE_SHORT)
2543                                         {
2544                                                 if (dspImmedEXVAL < 0xFF && (int32_t)dspImmedEXVAL > -0x100)
2545                                                 {
2546                                                         // '#xx,D'
2547                                                         // value fits in 8 bits - immediate move
2548                                                         inst = B16(00100000, 00000000) + (immreg << 8) + (uint32_t)dspImmedEXVAL;
2549                                                         return inst;
2550                                                 }
2551                                                 else
2552                                                 {
2553                                                         if (optim_warn_flag)
2554                                                                 warn("forced short immediate value doesn't fit in 8 bits - switching to long");
2555                                                         force_imm = NUM_FORCE_LONG;
2556                                                 }
2557                                         }
2558
2559                                         if (force_imm == NUM_FORCE_LONG)
2560                                         {
2561                                                 // '#xxxxxx,D'
2562                                                 // it can either be
2563                                                 // X or Y Data move. I don't think it matters much
2564                                                 // which of the two it will be, so let's use X.
2565 deposit_immediate_long_with_register:
2566                                                 inst = B16(01000000, 11110100);
2567                                                 inst |= ((immreg & 0x18) << (12 - 3)) + ((immreg & 7) << 8);
2568                                                 deposit_extra_ea = DEPOSIT_EXTRA_WORD;
2569                                                 return inst;
2570                                         }
2571
2572                                         if (((int32_t)dspImmedEXVAL < 0x100) && ((int32_t)dspImmedEXVAL >= -0x100))
2573                                         {
2574                                                 // value fits in 8 bits - immediate move
2575 deposit_immediate_short_with_register:
2576                                                 inst = B16(00100000, 00000000) + (immreg << 8) + (uint32_t)dspImmedEXVAL;
2577                                                 return inst;
2578                                         }
2579                                         else
2580                                         {
2581                                                 // value doesn't fit in 8 bits, so it can either be
2582                                                 // X or Y Data move. I don't think it matters much
2583                                                 // which of the two it will be, so let's use X:.
2584                                                 // TODO: if we're just goto'ing perhaps the logic can be simplified
2585                                                 goto deposit_immediate_long_with_register;
2586                                         }
2587                                 }
2588                                 else
2589                                 {
2590                                         if (force_imm != NUM_FORCE_SHORT)
2591                                         {
2592                                                 // '#xxxxxx,D'
2593                                                 // TODO: if we're just goto'ing perhaps the logic can be simplified
2594                                                 goto deposit_immediate_long_with_register;
2595                                         }
2596                                         else
2597                                         {
2598                                                 // '#xx,D' - I mode
2599                                                 // No visibility of the number so let's add a fixup for this
2600                                                 AddFixup(FU_DSPIMM8, sloc, dspImmedEXPR);
2601                                                 inst = B16(00100000, 00000000);
2602                                                 inst |= ((immreg & 0x18) << (11 - 3)) + ((immreg & 7) << 8);
2603                                                 return inst;
2604                                         }
2605                                 }
2606                         }
2607                         else
2608                         {
2609                                 // Float constant
2610                                 if (dspImmedEXATTR & DEFINED)
2611                                 {
2612                                         double f = *(double *)&dspImmedEXVAL;
2613                                         // Check direct.c for ossom comments regarding conversion!
2614 //N.B.: This is bogus, we need to fix this so it does this the right way... !!! FIX !!!
2615                                         dspImmedEXVAL = ((uint32_t)(int32_t)round(f * (1 << 23))) & 0xFFFFFF;
2616                                         double g;
2617                                         g = f * (1 << 23);
2618                                         g = round(g);
2619
2620                                         if ((dspImmedEXVAL & 0xFFFF) == 0)
2621                                         {
2622                                                 // Value's 16 lower bits are not set so the value can
2623                                                 // fit in a single byte (check parallel I move quoted
2624                                                 // above)
2625                                                 if (optim_warn_flag)
2626                                                         warn("Immediate value fits inside 8 bits, so using instruction short format");
2627
2628                                                 dspImmedEXVAL >>= 16;
2629                                                 goto deposit_immediate_short_with_register;
2630                                         }
2631
2632                                         if (force_imm == NUM_FORCE_SHORT)
2633                                         {
2634                                                 if ((dspImmedEXVAL & 0xFFFF) != 0)
2635                                                 {
2636                                                         if (optim_warn_flag)
2637                                                                 warn("Immediate value short format forced but value does not fit inside 8 bits - switching to long format");
2638
2639                                                         goto deposit_immediate_long_with_register;
2640                                                 }
2641
2642                                                 return error("internal assembler error: we haven't implemented floating point constants in parallel mode parser yet!");
2643                                         }
2644
2645                                         // If we reach here we either have NUM_FORCE_LONG or nothing, so we might as well store a long.
2646                                         goto deposit_immediate_long_with_register;
2647                                 }
2648                                 else
2649                                 {
2650                                         if (force_imm == NUM_FORCE_SHORT)
2651                                         {
2652                                                 goto deposit_immediate_short_with_register;
2653                                         }
2654                                         else
2655                                         {
2656                                                 // Just deposit a float fixup
2657                                                 AddFixup(FU_DSPIMMFL8, sloc, dspImmedEXPR);
2658                                                 inst = B16(00100000, 00000000);
2659                                                 inst |= ((immreg & 0x18) << (12 - 3)) + ((immreg & 7) << 8);
2660                                                 return inst;
2661                                         }
2662                                 }
2663                         }
2664                 }
2665                 else
2666                 {
2667                         // At this point we can only have '#xxxxxx,D1 S2,D2' (X:R Class I)
2668                         switch (immreg)
2669                         {
2670                         case 4: D1 = 0 << 10;break;  // X0
2671                         case 5: D1 = 1 << 10;break;  // X1
2672                         case 14: D1 = 2 << 10;break; // A
2673                         case 15: D1 = 3 << 10;break; // B
2674                         default: return error("unrecognised X:R parallel move syntax: D1 can only be x0,x1,a,b in '#xxxxxx,D1 S2,D2'"); break;
2675                         }
2676
2677                         switch (*tok++)
2678                         {
2679                         case KW_A: S2 = 0 << 9; break;
2680                         case KW_B: S2 = 1 << 9; break;
2681                         default: return error("unrecognised X:R parallel move syntax: S2 can only be A or B in '#xxxxxx,D1 S2,D2'"); break;
2682                         }
2683
2684                         if (*tok++ != ',')
2685                                 return error("unrecognised X:R parallel move syntax: expected comma after '#xxxxxx,D1 S2'");
2686
2687                         switch (*tok++)
2688                         {
2689                         case KW_Y0: D2 = 0 << 8; break;
2690                         case KW_Y1: D2 = 1 << 8; break;
2691                         default: return error("unrecognised X:R parallel move syntax: D2 can only be Y0 or Y1 in '#xxxxxx,D1 S2,D2'"); break;
2692                         }
2693
2694                         if (*tok != EOL)
2695                                 return error("unrecognised X:R parallel move syntax: expected end-of-line after '#xxxxxx,D1 S2,D2'");
2696
2697                         inst = B16(00010000, 10110100) | D1 | S2 | D2;
2698                         deposit_extra_ea = DEPOSIT_EXTRA_WORD;
2699                         return inst;
2700                 }
2701         }
2702         else if (*tok == KW_X)
2703         {
2704                 if (tok[1] == ',')
2705                         // Hey look, it's just the register X and not the addressing mode - fall through to general case
2706                         goto parse_everything_else;
2707
2708                 tok++;
2709
2710                 if (*tok++ != ':')
2711                         return error("expected ':' after 'X' in parallel move (i.e. X:)");
2712
2713                 // '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'
2714                 return parse_x(1, B16(01000000, 00000000), 0, 1);
2715         }
2716         else if (*tok == KW_Y)
2717         {
2718                 if (tok[1] == ',')
2719                         // Hey look, it's just the register y and not the addressing mode - fall through to general case
2720                         goto parse_everything_else;
2721
2722                 tok++;
2723
2724                 if (*tok++ != ':')
2725                         return error("expected ':' after 'Y' in parallel move (i.e. Y:)");
2726
2727                 // 'Y:ea,D' or 'Y:aa,D'
2728                 return parse_y(B16(01001000, 10000000), 0, 0, 0);
2729         }
2730         else if (*tok == KW_L)
2731         {
2732                 // 'L:ea,D' or 'L:aa,D'
2733                 tok++;
2734                 if (*tok++ != ':')
2735                         return error("expected ':' after 'L' in parallel move (i.e. L:)");
2736
2737                 return parse_l(1, B16(01000000, 11000000), 0);
2738         }
2739         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))
2740         {
2741                 // Everything else - brace for impact!
2742                 // R:   'S,D'
2743                 // X:   'S,X:ea' 'S,X:aa'
2744                 // X:R  'S,X:ea S2,D2' 'A,X:ea X0,A' 'B,X:ea X0,B'
2745                 // Y:   'S,Y:ea' 'S,Y:aa'
2746                 // 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'
2747                 // L:   'S,L:ea' 'S,L:aa'
2748                 LONG L_S1;
2749 parse_everything_else:
2750                 L_S1 = *tok++;
2751                 S1 = SDreg(L_S1);
2752
2753                 if (*tok++ != ',')
2754                         return error("Comma expected after 'S')");
2755
2756                 if (*tok == KW_X)
2757                 {
2758                         // 'S,X:ea' 'S,X:aa' 'S,X:ea S2,D2' 'S1,X:eax Y:eay,D2' 'S1,X:eax S2,Y:eay'
2759                         // 'A,X:ea X0,A' 'B,X:ea X0,B'
2760                         tok++;
2761
2762                         if (*tok++ != ':')
2763                                 return error("unrecognised X: parallel move syntax: expected ':' after 'S,X'");
2764
2765                         return parse_x(0, B16(01000000, 00000000), S1, 1);
2766                 }
2767                 else if (*tok == KW_Y)
2768                 {
2769                         // 'S,Y:ea' 'S,Y:aa'
2770                         tok++;
2771
2772                         if (*tok++ != ':')
2773                                 return error("unrecognised Y: parallel move syntax: expected ':' after 'S,Y'");
2774
2775                         return parse_y(B16(0000000, 00000000), S1, 0, 0);
2776                 }
2777                 else if (*tok == KW_L)
2778                 {
2779                         // 'S,L:ea' 'S,L:aa'
2780                         tok++;
2781
2782                         if (*tok++ != ':')
2783                                 return error("unrecognised L: parallel move syntax: expected ':' after 'S,L'");
2784
2785                         return parse_l(1, B16(00000000, 00000000), L_S1);
2786                 }
2787                 else if ((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2))
2788                 {
2789                         // 'S,D'
2790                         // 'S1,D1 Y:ea,D2' 'S1,D1 S2,Y:ea' 'S1,D1 #xxxxxx,D2'
2791                         // 'Y0,A A,Y:ea' 'Y0,B B,Y:ea'
2792                         D1 = SDreg(*tok++);
2793
2794                         if (*tok == EOL)
2795                         {
2796                                 // R 'S,D'
2797                                 inst = B16(00100000, 00000000);
2798                                 inst |= (S1 << 5) | (D1);
2799                                 return inst;
2800                         }
2801                         else if (*tok == KW_Y)
2802                         {
2803                                 // 'S1,D1 Y:ea,D2'
2804                                 tok++;
2805                                 if (*tok++ != ':')
2806                                         return error("expected ':' after 'Y' in parallel move (i.e. Y:)");
2807                                 return parse_y(B16(00010000, 01000000), S1, D1, 0);
2808
2809                         }
2810                         else if (*tok == KW_A || *tok == KW_B || *tok == KW_Y0 || *tok == KW_Y1)
2811                         {
2812                                 // 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' 'S1,D1 S2,Y:ea'
2813                                 S2 = SDreg(*tok++);
2814
2815                                 if (S1 == 6 && D1 == 14 && S2 == 14)
2816                                 {
2817                                         // 'Y0,A A,Y:ea'
2818                                         if (*tok++ != ',')
2819                                                 return error("unrecognised Y: parallel move syntax: expected ',' after Y0,A A");
2820
2821                                         if (*tok++ != KW_Y)
2822                                                 return error("unrecognised Y: parallel move syntax: expected 'Y' after Y0,A A,");
2823
2824                                         if (*tok++ != ':')
2825                                                 return error("unrecognised Y: parallel move syntax: expected ':' after Y0,A A,Y");
2826
2827                                         ea1 = checkea_full(EOL, Y_ERRORS);
2828
2829                                         if (ea1 == ERROR)
2830                                                 return ERROR;
2831
2832                                         inst = B16(00001000, 10000000);
2833                                         inst |= 0 << 8;
2834                                         inst |= ea1;
2835                                         return inst;
2836                                 }
2837                                 else if (S1 == 6 && D1 == 15 && S2 == 15)
2838                                 {
2839                                         // 'Y0,B B,Y:ea'
2840                                         if (*tok++ != ',')
2841                                                 return error("unrecognised Y: parallel move syntax: expected ',' after Y0,B B");
2842
2843                                         if (*tok++ != KW_Y)
2844                                                 return error("unrecognised Y: parallel move syntax: expected 'Y' after Y0,B B,");
2845
2846                                         if (*tok++ != ':')
2847                                                 return error("unrecognised Y: parallel move syntax: expected ':' after Y0,B B,Y");
2848
2849                                         ea1 = checkea_full(EOL, Y_ERRORS);
2850
2851                                         if (ea1 == ERROR)
2852                                                 return ERROR;
2853
2854                                         inst = B16(00001000, 10000000);
2855                                         inst |= 1 << 8;
2856                                         inst |= ea1;
2857                                         return inst;
2858                                 }
2859                                 else if ((S1 == 14 || S1 == 15) && (D1 == 4 || D1 == 5) && (S2 == 6 || S2 == 7 || S2 == 14 || S2 == 15))
2860                                 {
2861                                         //'S1,D1 S2,Y:ea'
2862                                         if (*tok++ != ',')
2863                                                 return error("unrecognised Y: parallel move syntax: expected ',' after S1,D1 S2");
2864
2865                                         if (*tok++ != KW_Y)
2866                                                 return error("unrecognised Y: parallel move syntax: expected 'Y' after S1,D1 S2,");
2867
2868                                         if (*tok++ != ':')
2869                                                 return error("unrecognised Y: parallel move syntax: expected ':' after S1,D1 S2,Y");
2870
2871                                         ea1 = checkea_full(EOL, Y_ERRORS);
2872
2873                                         if (ea1 == ERROR)
2874                                                 return ERROR;
2875
2876                                         inst = B16(00010000, 01000000);
2877                                         inst |= (S1 & 1) << 11;
2878                                         inst |= (D1 & 1) << 10;
2879                                         inst |= ((S2 & 8) << (10 - 4)) | ((S2 & 1) << 8);
2880                                         inst |= ea1;
2881                                         return inst;
2882                                 }
2883                                 else
2884                                         return error("unrecognised Y: parallel move syntax: only 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' allowed'");
2885                                 // Check for Y:
2886                         }
2887                         else if (*tok == '#')
2888                         {
2889                                 // R:Y: 'S1,D1 #xxxxxx,D2'
2890                                 tok++;
2891
2892                                 if (*tok == '>')
2893                                 {
2894                                         // Well, forcing an immediate to be 24 bits is legal here
2895                                         // but then it's the only available option so my guess is that this
2896                                         // is simply superfluous. So let's just eat the character
2897                                         tok++;
2898                                 }
2899
2900                                 if (expr(dspaaEXPR, &dspaaEXVAL, &dspaaEXATTR, &dspaaESYM) != OK)
2901                                         return ERROR;
2902
2903                                 if ((dspImmedEXATTR & DEFINED) && (dspImmedEXVAL > 0xFFFFFF))
2904                                         return error("immediate is bigger than $FFFFFF");
2905
2906                                 deposit_extra_ea = DEPOSIT_EXTRA_WORD;
2907
2908                                 if (*tok++ != ',')
2909                                         return error("Comma expected after 'S1,D1 #xxxxxx')");
2910
2911                                 // S1 is a or b, D1 is x0 or x1 and d2 is y0, y1, a or b
2912                                 switch (*tok++)
2913                                 {
2914                                 case KW_Y0: D2 = 0 << 8; break;
2915                                 case KW_Y1: D2 = 1 << 8; break;
2916                                 case KW_A:  D2 = 2 << 8; break;
2917                                 case KW_B:  D2 = 3 << 8; break;
2918                                 default:    return error("unrecognised R:Y: parallel move syntax: D2 must be y0, y1, a or b in 'S1,D1 #xxxxxx,D2'");
2919                                 }
2920
2921                                 if (S1 == 14 || S1 == 15)
2922                                 {
2923                                         if (D1 == 4 || D1 == 5)
2924                                         {
2925                                                 inst = B16(00010000, 11110100);
2926                                                 inst |= (S1 & 1) << 11;
2927                                                 inst |= (D1 & 1) << 10;
2928                                                 inst |= D2;
2929                                                 dspImmedEXVAL = dspaaEXVAL;
2930                                                 return inst;
2931                                         }
2932                                         else
2933                                                 return error("unrecognised R:Y: parallel move syntax: D1 must be x0 or x1 in 'S1,D1 #xxxxxx,D2'");
2934                                 }
2935                                 else
2936                                         return error("unrecognised R:Y: parallel move syntax: S1 must be a or b in 'S1,D1 #xxxxxx,D2'");
2937                         }
2938                         else
2939                                 return error("unrecognised R:Y: parallel move syntax: Unexpected text after S,D in 'S1,D1 #xxxxxx,D2'");
2940                 }
2941                 else
2942                         return error("unrecognised R:Y: parallel move syntax: Unexpected text after 'S,'");
2943         }
2944         else if (*tok == '(')
2945         {
2946                 // U: 'ea'
2947                 // U 'ea' can only be '(Rn)-Nn', '(Rn)+Nn', '(Rn)-' or '(Rn)+'
2948                 tok++;
2949
2950                 if (*tok >= KW_R0 && *tok <= KW_R7)
2951                 {
2952                         ea1 = (*tok++ - KW_R0);
2953                 }
2954                 else
2955                         return error("unrecognised U parallel move syntax: expected 'Rn' after '('");
2956
2957                 if (*tok++ != ')')
2958                         return error("unrecognised U parallel move syntax: expected ')' after '(Rn'");
2959
2960                 if (*tok == '+')
2961                 {
2962                         tok++;
2963
2964                         if (*tok == EOL)
2965                                 // (Rn)+
2966                                 ea1 |= 3 << 3;
2967                         else if (*tok >= KW_N0 && *tok <= KW_N7)
2968                         {
2969                                 // (Rn)+Nn
2970                                 if ((*tok++ & 7) != ea1)
2971                                         return error("unrecognised U parallel move syntax: Same register number expected for Rn, Nn in '(Rn)+Nn')");
2972
2973                                 ea1 |= 1 << 3;
2974
2975                                 if (*tok != EOL)
2976                                         return error("unrecognised U parallel move syntax: expected End-Of-Line after '(Rn)+Nn'");
2977                         }
2978                         else
2979                                 return error("unrecognised U parallel move syntax: expected End-Of-Line or 'Nn' after '(Rn)+'");
2980                 }
2981                 else if (*tok == '-')
2982                 {
2983                         tok++;
2984
2985                         if (*tok == EOL)
2986                         {
2987                                 // (Rn)-
2988                                 ea1 |= 2 << 3;
2989                                 tok++;
2990                         }
2991                         else if (*tok >= KW_N0 && *tok <= KW_N7)
2992                         {
2993                                 // (Rn)-Nn
2994                                 if ((*tok++ & 7) != ea1)
2995                                         return error("unrecognised U parallel move syntax: Same register number expected for Rn, Nn in '(Rn)-Nn')");
2996
2997                                 ea1 |= 0 << 3;
2998
2999                                 if (*tok != EOL)
3000                                         return error("unrecognised U parallel move syntax: expected End-Of-Line after '(Rn)-Nn'");
3001                         }
3002                 }
3003
3004                 inst = B16(00100000, 01000000);
3005                 inst |= ea1;
3006                 return inst;
3007         }
3008         else
3009                 return error("extra (unexpected) text found");
3010
3011         return OK;
3012 }
3013