68kgen
68kgen.o
68ktab.h
-68kmn
+68k.tab
6502kw.h
opkw.h
*.o
#include "sect.h"
#include "token.h"
+#define DEF_KW
+#include "kwtab.h"
+
#define UPSEG_SIZE 0x10010L // size of 6502 code buffer, 64K+16bytes
// Internal vars
#define A65_IMMEDH 12
#define A65_IMMEDL 13
-#define NMACHOPS 56 // Number of machine ops
-#define NMODES 14 // Number of addressing modes
-#define NOP 0xEA // 6502 NOP instruction
-#define ILLEGAL 0xFF // 'Illegal instr' marker
-#define END65 0xFF // End-of-an-instr-list
+#define NMACHOPS 56 // Number of machine ops
+#define NMODES 14 // Number of addressing modes
+#define NOP 0xEA // 6502 NOP instruction
+#define ILLEGAL 0xFF // 'Illegal instr' marker
+#define END65 0xFF // End-of-an-instr-list
static char imodes[] =
{
- A65_IMMED, 0x69, A65_ABS, 0x6d, A65_ZP, 0x65, A65_INDX, 0x61, A65_INDY, 0x71,
- A65_ZPX, 0x75, A65_ABSX, 0x7d, A65_ABSY, 0x79, END65,
- A65_IMMED, 0x29, A65_ABS, 0x2d, A65_ZP, 0x25, A65_INDX, 0x21, A65_INDY, 0x31,
- A65_ZPX, 0x35, A65_ABSX, 0x3d, A65_ABSY, 0x39, END65,
- A65_ABS, 0x0e, A65_ZP, 0x06, A65_IMPL, 0x0a, A65_ZPX, 0x16, A65_ABSX,
- 0x1e, END65,
+ A65_IMMED, 0x69, A65_ABS, 0x6D, A65_ZP, 0x65, A65_INDX, 0x61, A65_INDY, 0x71,
+ A65_ZPX, 0x75, A65_ABSX, 0x7D, A65_ABSY, 0x79, END65,
+ A65_IMMED, 0x29, A65_ABS, 0x2D, A65_ZP, 0x25, A65_INDX, 0x21, A65_INDY, 0x31,
+ A65_ZPX, 0x35, A65_ABSX, 0x3D, A65_ABSY, 0x39, END65,
+ A65_ABS, 0x0E, A65_ZP, 0x06, A65_IMPL, 0x0A, A65_ZPX, 0x16, A65_ABSX,
+ 0x1E, END65,
A65_REL, 0x90, END65,
- A65_REL, 0xb0, END65,
- A65_REL, 0xf0, END65,
- A65_REL, 0xd0, END65,
+ A65_REL, 0xB0, END65,
+ A65_REL, 0xF0, END65,
+ A65_REL, 0xD0, END65,
A65_REL, 0x30, END65,
A65_REL, 0x10, END65,
A65_REL, 0x50, END65,
A65_REL, 0x70, END65,
- A65_ABS, 0x2c, A65_ZP, 0x24, END65,
+ A65_ABS, 0x2C, A65_ZP, 0x24, END65,
A65_IMPL, 0x00, END65,
A65_IMPL, 0x18, END65,
- A65_IMPL, 0xd8, END65,
+ A65_IMPL, 0xD8, END65,
A65_IMPL, 0x58, END65,
- A65_IMPL, 0xb8, END65,
- A65_IMMED, 0xc9, A65_ABS, 0xcd, A65_ZP, 0xc5, A65_INDX, 0xc1, A65_INDY, 0xd1,
- A65_ZPX, 0xd5, A65_ABSX, 0xdd, A65_ABSY, 0xd9, END65,
- A65_IMMED, 0xe0, A65_ABS, 0xec, A65_ZP, 0xe4, END65,
- A65_IMMED, 0xc0, A65_ABS, 0xcc, A65_ZP, 0xc4, END65,
- A65_ABS, 0xce, A65_ZP, 0xc6, A65_ZPX, 0xd6, A65_ABSX, 0xde, END65,
- A65_IMPL, 0xca, END65,
+ A65_IMPL, 0xB8, END65,
+ A65_IMMED, 0xC9, A65_ABS, 0xCD, A65_ZP, 0xC5, A65_INDX, 0xC1, A65_INDY, 0xD1,
+ A65_ZPX, 0xD5, A65_ABSX, 0xDD, A65_ABSY, 0xD9, END65,
+ A65_IMMED, 0xE0, A65_ABS, 0xEC, A65_ZP, 0xE4, END65,
+ A65_IMMED, 0xC0, A65_ABS, 0xCC, A65_ZP, 0xC4, END65,
+ A65_ABS, 0xCE, A65_ZP, 0xC6, A65_ZPX, 0xD6, A65_ABSX, 0xDE, END65,
+ A65_IMPL, 0xCA, END65,
A65_IMPL, 0x88, END65,
- A65_IMMED, 0x49, A65_ABS, 0x4d, A65_ZP, 0x45, A65_INDX, 0x41, A65_INDY, 0x51,
- A65_ZPX, 0x55, A65_ABSX, 0x5d, A65_ABSY, 0x59, END65,
- A65_ABS, 0xee, A65_ZP, 0xe6, A65_ZPX, 0xf6, A65_ABSX, 0xfe, END65,
- A65_IMPL, 0xe8, END65,
- A65_IMPL, 0xc8, END65,
- A65_ABS, 0x4c, A65_IND, 0x6c, END65,
+ A65_IMMED, 0x49, A65_ABS, 0x4D, A65_ZP, 0x45, A65_INDX, 0x41, A65_INDY, 0x51,
+ A65_ZPX, 0x55, A65_ABSX, 0x5D, A65_ABSY, 0x59, END65,
+ A65_ABS, 0xEE, A65_ZP, 0xE6, A65_ZPX, 0xF6, A65_ABSX, 0xFE, END65,
+ A65_IMPL, 0xE8, END65,
+ A65_IMPL, 0xC8, END65,
+ A65_ABS, 0x4C, A65_IND, 0x6C, END65,
A65_ABS, 0x20, END65,
- A65_IMMED, 0xa9, A65_ABS, 0xad, A65_ZP, 0xa5, A65_INDX, 0xa1, A65_INDY, 0xb1,
- A65_ZPX, 0xb5, A65_ABSX, 0xbd, A65_ABSY, 0xb9, A65_IMMEDH, 0xa9, A65_IMMEDL, 0xa9, END65,
- A65_IMMED, 0xa2, A65_ABS, 0xae, A65_ZP, 0xa6, A65_ABSY, 0xbe,
- A65_ZPY, 0xb6, A65_IMMEDH, 0xa2, A65_IMMEDL, 0xa2, END65,
- A65_IMMED, 0xa0, A65_ABS, 0xac, A65_ZP, 0xa4, A65_ZPX, 0xb4,
- A65_ABSX, 0xbc, A65_IMMEDH, 0xa0, A65_IMMEDL, 0xa0, END65,
- A65_ABS, 0x4e, A65_ZP, 0x46, A65_IMPL, 0x4a, A65_ZPX, 0x56,
- A65_ABSX, 0x5e, END65,
- A65_IMPL, 0xea, END65,
- A65_IMMED, 0x09, A65_ABS, 0x0d, A65_ZP, 0x05, A65_INDX, 0x01, A65_INDY, 0x11,
- A65_ZPX, 0x15, A65_ABSX, 0x1d, A65_ABSY, 0x19, END65,
+ A65_IMMED, 0xA9, A65_ABS, 0xAD, A65_ZP, 0xA5, A65_INDX, 0xA1, A65_INDY, 0xB1,
+ A65_ZPX, 0xB5, A65_ABSX, 0xBD, A65_ABSY, 0xB9, A65_IMMEDH, 0xA9, A65_IMMEDL, 0xA9, END65,
+ A65_IMMED, 0xA2, A65_ABS, 0xAE, A65_ZP, 0xA6, A65_ABSY, 0xBE,
+ A65_ZPY, 0xB6, A65_IMMEDH, 0xA2, A65_IMMEDL, 0xA2, END65,
+ A65_IMMED, 0xA0, A65_ABS, 0xAC, A65_ZP, 0xA4, A65_ZPX, 0xB4,
+ A65_ABSX, 0xBC, A65_IMMEDH, 0xA0, A65_IMMEDL, 0xA0, END65,
+ A65_ABS, 0x4E, A65_ZP, 0x46, A65_IMPL, 0x4A, A65_ZPX, 0x56,
+ A65_ABSX, 0x5E, END65,
+ A65_IMPL, 0xEA, END65,
+ A65_IMMED, 0x09, A65_ABS, 0x0D, A65_ZP, 0x05, A65_INDX, 0x01, A65_INDY, 0x11,
+ A65_ZPX, 0x15, A65_ABSX, 0x1D, A65_ABSY, 0x19, END65,
A65_IMPL, 0x48, END65,
A65_IMPL, 0x08, END65,
A65_IMPL, 0x68, END65,
A65_IMPL, 0x28, END65,
- A65_ABS, 0x2e, A65_ZP, 0x26, A65_IMPL, 0x2a, A65_ZPX, 0x36,
- A65_ABSX, 0x3e, END65,
- A65_ABS, 0x6e, A65_ZP, 0x66, A65_IMPL, 0x6a, A65_ZPX, 0x76,
- A65_ABSX, 0x7e, END65,
+ A65_ABS, 0x2E, A65_ZP, 0x26, A65_IMPL, 0x2A, A65_ZPX, 0x36,
+ A65_ABSX, 0x3E, END65,
+ A65_ABS, 0x6E, A65_ZP, 0x66, A65_IMPL, 0x6A, A65_ZPX, 0x76,
+ A65_ABSX, 0x7E, END65,
A65_IMPL, 0x40, END65,
A65_IMPL, 0x60, END65,
- A65_IMMED, 0xe9, A65_ABS, 0xed, A65_ZP, 0xe5, A65_INDX, 0xe1, A65_INDY, 0xf1,
- A65_ZPX, 0xf5, A65_ABSX, 0xfd, A65_ABSY, 0xf9, END65,
+ A65_IMMED, 0xE9, A65_ABS, 0xED, A65_ZP, 0xE5, A65_INDX, 0xE1, A65_INDY, 0xF1,
+ A65_ZPX, 0xF5, A65_ABSX, 0xFD, A65_ABSY, 0xF9, END65,
A65_IMPL, 0x38, END65,
- A65_IMPL, 0xf8, END65,
+ A65_IMPL, 0xF8, END65,
A65_IMPL, 0x78, END65,
- A65_ABS, 0x8d, A65_ZP, 0x85, A65_INDX, 0x81, A65_INDY, 0x91, A65_ZPX, 0x95,
- A65_ABSX, 0x9d, A65_ABSY, 0x99, END65,
- A65_ABS, 0x8e, A65_ZP, 0x86, A65_ZPY, 0x96, END65,
- A65_ABS, 0x8c, A65_ZP, 0x84, A65_ZPX, 0x94, END65,
- A65_IMPL, 0xaa, END65,
- A65_IMPL, 0xa8, END65,
- A65_IMPL, 0xba, END65,
- A65_IMPL, 0x8a, END65,
- A65_IMPL, 0x9a, END65,
+ A65_ABS, 0x8D, A65_ZP, 0x85, A65_INDX, 0x81, A65_INDY, 0x91, A65_ZPX, 0x95,
+ A65_ABSX, 0x9D, A65_ABSY, 0x99, END65,
+ A65_ABS, 0x8E, A65_ZP, 0x86, A65_ZPY, 0x96, END65,
+ A65_ABS, 0x8C, A65_ZP, 0x84, A65_ZPX, 0x94, END65,
+ A65_IMPL, 0xAA, END65,
+ A65_IMPL, 0xA8, END65,
+ A65_IMPL, 0xBA, END65,
+ A65_IMPL, 0x8A, END65,
+ A65_IMPL, 0x9A, END65,
A65_IMPL, 0x98, END65
};
amode = A65_IMPL;
break;
+ case KW_A:
+ if (tok[1] != EOL)
+ goto badmode;
+
+ amode = A65_IMPL;
+ tok++;
+ break;
+
case '#':
tok++;
{
// (foo),y
tok++;
+#if 0
p = string[tok[1]];
// Sleazo tolower() -----------------vvvvvvvvvvv
tok += 2;
amode = A65_INDY;
+#else
+ if (tok[0] == KW_Y)
+ amode = A65_INDY;
+
+ if (tok[1] != EOL)
+ goto badmode;
+
+ tok++;
+#endif
}
else
amode = A65_IND;
else if (*tok == ',')
{
tok++;
+#if 0
p = string[tok[1]];
if (*tok != SYMBOL || p[1] != EOS)
amode = A65_ABSY;
else
goto badmode;
+#else
+ if (tok[0] == KW_X)
+ {
+ amode = A65_ABSX;
+ tok++;
+ }
+ else if (tok[0] == KW_Y)
+ {
+ amode = A65_ABSY;
+ tok++;
+ }
+
+ if (tok[0] != EOL)
+ goto badmode;
+#endif
}
else
goto badmode;
D_rword(eval);
break;
- //
- // Deposit 3 NOPs for illegal things
- //
+ //
+ // Deposit 3 NOPs for illegal things (why 3? why not 30? or zero?)
+ //
default:
case ILLEGAL:
for(i=0; i<3; i++)
if (sloc > 0x10000L)
fatal("6502 code pointer > 64K");
+//Now why use this instead of at_eol()?
if (*tok != EOL)
error(extra_stuff);
}
for(uint16_t * l=&orgmap[0][0]; l<currentorg; l+=2)
{
+/*
+Why are we assuming endianness here? This is retarded
+*/
exeheader[1] = l[0];
exeheader[2] = l[1] - 1;
void procln(int namc, char ** namv)
{
int i, j;
- char * s;
// alias for previous entry
if (namc == 1)
{
- fprintf(kfp, "%s\t%d\n", namv[0], kwnum-1+1000);
+ fprintf(kfp, "%s\t%d\n", namv[0], kwnum - 1 + 1000);
return;
}
if (*namv[1] == '!')
printf("CGSPECIAL");
- else for (s = namv[1], i=0; *s; ++s)
+ else for(char * s=namv[1], i=0; *s; s++)
printf("%sSIZ%c", (i++ ? "|" : ""), *s);
printf(", %s, %s, ", namv[2], namv[3]);
// enforce little fascist percent signs
if (*namv[4] == '%')
{
- for(i=1, j=0; i<17; ++i)
+ for(i=1, j=0; i<17; i++)
{
j <<= 1;
if (namv[4][i] == '1' || isupper(namv[4][i]))
- ++j;
+ j++;
}
printf("0x%04x, ", j);
printf("%s, ", namv[4]);
if (namc == 7 && *namv[6] == '+')
- printf("%d, ", kwnum+1);
+ printf("%d, ", kwnum + 1);
else
printf("0, ");
{
uint64_t address;
- if (!rgpu && !rdsp && !robjproc && !m6502)
- return error(".org permitted only in GPU/DSP/OP and 6502 sections");
+ if (!rgpu && !rdsp && !robjproc && !m6502 && !dsp56001)
+ return error(".org permitted only in GPU/DSP/OP, 56001 and 6502 sections");
- if (abs_expr(&address) == ERROR)
+ // M56K can leave the expression off the org for some reason :-/
+ if ((abs_expr(&address) == ERROR) && !dsp56001)
{
error("cannot determine org'd address");
return ERROR;
orgaddr = address;
orgactive = 1;
}
- else
+ else if (m6502)
{
- // 6502. We also kludge `lsloc' so the listing generator doesn't try
+ // 6502. We also kludge 'lsloc' so the listing generator doesn't try
// to spew out megabytes.
if (address > 0xFFFF)
return error(range_error);
chptr = scode->chptr + address;
orgaddr = address;
orgactive = 1;
- at_eol();
+ }
+ else if (dsp56001)
+ {
}
+ at_eol();
return 0;
}
case '/':
formatting = 1;
- if (tok[1] != SYMBOL)
+ // "X" & "L" get tokenized now... :-/ Probably should look into preventing this kind of thing from happening (was added with DSP56K code)
+ if ((tok[1] != SYMBOL) && (tok[1] != KW_L) && (tok[1] != KW_X))
goto token_err;
-// strcpy(prntstr, (char *)tok[2]);
- strcpy(prntstr, string[tok[2]]);
-
- switch(prntstr[0])
+ if (tok[1] == KW_L)
{
- case 'l': case 'L': wordlong = 1; break;
- case 'w': case 'W': wordlong = 0; break;
- case 'x': case 'X': outtype = 0; break;
- case 'd': case 'D': outtype = 1; break;
- case 'u': case 'U': outtype = 2; break;
- default:
- error("unknown print format flag");
- return ERROR;
+ wordlong = 1;
+ tok += 2;
+ }
+ else if (tok[1] == KW_X)
+ {
+ outtype = 0;
+ tok += 2;
+ }
+ else
+ {
+ strcpy(prntstr, string[tok[2]]);
+
+ switch(prntstr[0])
+ {
+ case 'l': case 'L': wordlong = 1; break;
+ case 'w': case 'W': wordlong = 0; break;
+ case 'x': case 'X': outtype = 0; break;
+ case 'd': case 'D': outtype = 1; break;
+ case 'u': case 'U': outtype = 2; break;
+ default:
+ error("unknown print format flag");
+ return ERROR;
+ }
+
+ tok += 3;
}
- tok += 3;
break;
case ',':
tok++;
return 0;
token_err:
- error("illegal print token");
+ error("illegal print token [@ '%s']", prntstr);
return ERROR;
}
uint64_t eval;
- if (cursect != M6502)
+ if ((cursect & (M6502 | M56KPXYL)) == 0)
{
if ((siz != SIZB) && (sloc & 1)) // Automatic .even
auto_even();
for(p=string[tok[1]]; *p!=EOS; p++)
D_byte(*p);
}
- else if(*tok == STRINGA8)
+ else if (*tok == STRINGA8)
{
for(p=string[tok[1]]; *p!=EOS; p++)
D_byte(strtoa8[*p]);
//
int d_68000(void)
{
- rgpu = rdsp = robjproc = 0;
+ rgpu = rdsp = robjproc = dsp56001 = 0;
// Switching from gpu/dsp sections should reset any ORG'd Address
orgactive = 0;
orgwarning = 0;
//
-// DSP56001
+// .56001 - Switch to DSP56001 assembler
//
int d_56001(void)
{
- return error("Not yet, child. Be patient.");
+ dsp56001 = 1;
+ rgpu = rdsp = robjproc = 0;
+ SaveSection();
+
+ if (obj_format == LOD || obj_format == P56)
+ SwitchSection(M56001P);
+
+ return 0;
}
rgpu = 1; // Set GPU assembly
rdsp = 0; // Unset DSP assembly
robjproc = 0; // Unset OP assembly
+ dsp56001 = 0; // Unset 56001 assembly
regbank = BANK_N; // Set no default register bank
return 0;
}
rdsp = 1; // Set DSP assembly
rgpu = 0; // Unset GPU assembly
robjproc = 0; // Unset OP assembly
+ dsp56001 = 0; // Unset 56001 assembly
regbank = BANK_N; // Set no default register bank
return 0;
}
robjproc = 1; // Set OP assembly
rgpu = 0; // Unset GPU assembly
rdsp = 0; // Unset DSP assembly
+ dsp56001 = 0; // Unset 56001 assembly
return OK;
}
--- /dev/null
+//
+// RMAC - Reboot's Macro Assembler for all Atari computers
+// DSP56K.C - General DSP56001 routines
+// Copyright (C) 199x Landon Dyer, 2011-2017 Reboot and Friends
+// RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
+// Source utilised with the kind permission of Landon Dyer
+//
+
+#include "rmac.h"
+#include "dsp56k.h"
+
+DSP_ORG dsp_orgmap[1024]; // Mark all 56001 org changes
+DSP_ORG * dsp_currentorg = &dsp_orgmap[0];
+int dsp_written_data_in_current_org = 0;
+
--- /dev/null
+//
+// RMAC - Reboot's Macro Assembler for all Atari computers
+// DSP56K.H - General DSP56001 routines
+// Copyright (C) 199x Landon Dyer, 2011-2017 Reboot and Friends
+// RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
+// Source utilised with the kind permission of Landon Dyer
+//
+
+#pragma once
+
+#include "rmac.h"
+#include "sect.h"
+
+// Exported variables.
+#define DSP_MAX_RAM (32*3*1024) // 32k 24-bit words
+#define DSP_ORG struct dsp56001_orgentry
+
+enum MEMTYPES
+{
+ ORG_P,
+ ORG_X,
+ ORG_Y,
+ ORG_L
+} ;
+
+DSP_ORG
+{
+ enum MEMTYPES memtype;
+ uint8_t * start;
+ uint8_t * end;
+ uint32_t orgadr;
+ CHUNK * chunk;
+};
+
+extern DSP_ORG dsp_orgmap[1024]; // Mark all 56001 org changes
+extern DSP_ORG * dsp_currentorg;
+extern int dsp_written_data_in_current_org;
+
+#define dprintf(...) p_buf += sprintf(p_buf, __VA_ARGS__)
+
+// Exported functions
+
--- /dev/null
+abs M_ACC56 M_AM_NONE PARMOVE %mmmmmmmmmmmmmmmm0010d110 dsp_ab d=(a=0, b=1)\r
+asl M_ACC56 M_AM_NONE PARMOVE %mmmmmmmmmmmmmmmm0011d010 dsp_ab d=(a=0, b=1)\r
+asr M_ACC56 M_AM_NONE PARMOVE %mmmmmmmmmmmmmmmm0010d010 dsp_ab d=(a=0, b=1)\r
+clr M_ACC56 M_AM_NONE PARMOVE %mmmmmmmmmmmmmmmm0001d011 dsp_ab d=(a=0, b=1)\r
+lsl M_ACC56 M_AM_NONE PARMOVE %mmmmmmmmmmmmmmmm0011d011 dsp_ab d=(a=0, b=1)\r
+lsr M_ACC56 M_AM_NONE PARMOVE %mmmmmmmmmmmmmmmm0010d011 dsp_ab d=(a=0, b=1)\r
+not M_ACC56 M_AM_NONE PARMOVE %mmmmmmmmmmmmmmmm0001d111 dsp_ab d=(a=0, b=1)\r
+addl M_ACC56 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0001d010 dsp_baab d=(b,a=0, a,b=1)\r
+addr M_ACC56 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0000d010 dsp_baab d=(b,a=0, a,b=1)\r
+add M_ACC56 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0001d000 dsp_baab + d=(a=0, b=1)\r
+- M_ALL48 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0jjjd000 dsp_acc48 jjj=(x=2, y=3, x0=4, y0=5, x1=6, y1=7), d=(a=0, b=1)\r
+cmp M_ACC56 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0000d101 dsp_baab + d=(a=0, b=1)\r
+- M_ALU24 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0jjjd101 dsp_acc48 jjj=(x=2, y=3, x0=4, y0=5, x1=6, y1=7), d=(a=0, b=1)\r
+cmpm M_ACC56 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0000d111 dsp_baab + d=(a=0, b=1)\r
+- M_ALU24 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0jjjd111 dsp_acc48 jjj=(x=2, y=3, x0=4, y0=5, x1=6, y1=7), d=(a=0, b=1)\r
+sub M_ACC56 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0001d100 dsp_baab + d=(a=0, b=1)\r
+- M_ALL48 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0jjjd100 dsp_acc48 jjj=(x=2, y=3, x0=4, y0=5, x1=6, y1=7), d=(a=0, b=1)\r
+tfr M_ACC56 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0000d001 dsp_baab + d=(a=0, b=1)\r
+- M_ALU24 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0jjjd001 dsp_acc48 jjj=(x=2, y=3, x0=4, y0=5, x1=6, y1=7), d=(a=0, b=1) \r
+rnd M_ACC56 M_AM_NONE PARMOVE %mmmmmmmmmmmmmmmm0001d001 dsp_ab d=(a=0, b=1)\r
+rol M_ACC56 M_AM_NONE PARMOVE %mmmmmmmmmmmmmmmm0011d111 dsp_ab d=(a=0, b=1)\r
+ror M_ACC56 M_AM_NONE PARMOVE %mmmmmmmmmmmmmmmm0010d111 dsp_ab d=(a=0, b=1)\r
+subl M_ACC56 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0001d110 dsp_baab d=(b,a=0, a,b=1)\r
+subr M_ACC56 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0000d110 dsp_baab d=(b,a=0, a,b=1)\r
+tst M_ACC56 M_AM_NONE PARMOVE %mmmmmmmmmmmmmmmm0000d011 dsp_ab d=(a=0, b=1)\r
+enddo M_AM_NONE M_AM_NONE NOPARMO %000000000000000010001100 dsp_self\r
+illegal M_AM_NONE M_AM_NONE NOPARMO %000000000000000000000101 dsp_self\r
+nop M_AM_NONE M_AM_NONE NOPARMO %000000000000000000000000 dsp_self\r
+reset M_AM_NONE M_AM_NONE NOPARMO %000000000000000010000100 dsp_self\r
+rti M_AM_NONE M_AM_NONE NOPARMO %000000000000000000000100 dsp_self\r
+rts M_AM_NONE M_AM_NONE NOPARMO %000000000000000000001100 dsp_self\r
+stop M_AM_NONE M_AM_NONE NOPARMO %000000000000000010000111 dsp_self\r
+swi M_AM_NONE M_AM_NONE NOPARMO %000000000000000000000110 dsp_self\r
+wait M_AM_NONE M_AM_NONE NOPARMO %000000000000000010000110 dsp_self\r
+adc M_INP48 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm001jd001 dsp_xyab j=(x=0, y=1), d=(a=0, b=1)\r
+sbc M_INP48 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm001jd101 dsp_xyab s1 (j)=(x=0,y=1),s2 (d)=(a=0,b=1)\r
+and M_ALU24 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm01jjd110 dsp_x0y0ab jj=(x0=0, x1=2, y0=1, y1=3), d=(a=0, b=1)\r
+eor M_ALU24 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm01jjd011 dsp_x0y0ab jj=(x0=0, x1=2, y0=1, y1=3), d=(a=0, b=1)\r
+div M_ALU24 M_ACC56 NOPARMO %000000011000000001jjd000 dsp_x0y0ab jj=(x0=0, x1=2, y0=1, y1=3), d=(a=0, b=1)\r
+or M_ALU24 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm01jjd010 dsp_x0y0ab jj=(x0=0, x1=2, y0=1, y1=3), d=(a=0, b=1)\r
+andi M_DSPIM8 M_DSPPCU NOPARMO %00000000iiiiiiii101110ee dsp_immcr ee=(mr=0, ccr=1, omr=2)\r
+ori M_DSPIM8 M_DSPPCU NOPARMO %00000000iiiiiiii111110ee dsp_immcr ee=(mr=0, ccr=1, omr=2)\r
+tcc M_ACC56 M_ACC56 NOPARMO %00000010000000000jjjd000 dsp_baab + s1,d1 [s2,d2]\r
+- M_ALL48 M_ACC56 NOPARMO %00000010000000000jjjd000 dsp_tcc2 s1,d1 [s2,d2]\r
+ths M_ACC56 M_ACC56 NOPARMO %00000010000000000jjjd000 dsp_baab + s1,d1 [s2,d2]\r
+- M_ALL48 M_ACC56 NOPARMO %00000010000000000jjjd000 dsp_tcc2 s1,d1 [s2,d2]\r
+tcs M_ACC56 M_ACC56 NOPARMO %00000010100000000jjjd000 dsp_baab + s1,d1 [s2,d2]\r
+- M_ALL48 M_ACC56 NOPARMO %00000010100000000jjjd000 dsp_tcc2 s1,d1 [s2,d2]\r
+tlo M_ACC56 M_ACC56 NOPARMO %00000010100000000jjjd000 dsp_baab + s1,d1 [s2,d2]\r
+- M_ALL48 M_ACC56 NOPARMO %00000010100000000jjjd000 dsp_tcc2 s1,d1 [s2,d2]\r
+tec M_ACC56 M_ACC56 NOPARMO %00000010010100000jjjd000 dsp_baab + s1,d1 [s2,d2]\r
+- M_ALL48 M_ACC56 NOPARMO %00000010010100000jjjd000 dsp_tcc2 s1,d1 [s2,d2]\r
+teq M_ACC56 M_ACC56 NOPARMO %00000010101000000jjjd000 dsp_baab + s1,d1 [s2,d2]\r
+- M_ALL48 M_ACC56 NOPARMO %00000010101000000jjjd000 dsp_tcc2 s1,d1 [s2,d2]\r
+tes M_ACC56 M_ACC56 NOPARMO %00000010110100000jjjd000 dsp_baab + s1,d1 [s2,d2]\r
+- M_ALL48 M_ACC56 NOPARMO %00000010110100000jjjd000 dsp_tcc2 s1,d1 [s2,d2]\r
+tge M_ACC56 M_ACC56 NOPARMO %00000010000100000jjjd000 dsp_baab + s1,d1 [s2,d2]\r
+- M_ALL48 M_ACC56 NOPARMO %00000010000100000jjjd000 dsp_tcc2 s1,d1 [s2,d2]\r
+tgt M_ACC56 M_ACC56 NOPARMO %00000010011100000jjjd000 dsp_baab + s1,d1 [s2,d2]\r
+- M_ALL48 M_ACC56 NOPARMO %00000010011100000jjjd000 dsp_tcc2 s1,d1 [s2,d2]\r
+tlc M_ACC56 M_ACC56 NOPARMO %00000010011000000jjjd000 dsp_baab + s1,d1 [s2,d2]\r
+- M_ALL48 M_ACC56 NOPARMO %00000010011000000jjjd000 dsp_tcc2 s1,d1 [s2,d2]\r
+tle M_ACC56 M_ACC56 NOPARMO %00000010111100000jjjd000 dsp_baab + s1,d1 [s2,d2]\r
+- M_ALL48 M_ACC56 NOPARMO %00000010111100000jjjd000 dsp_tcc2 s1,d1 [s2,d2]\r
+tls M_ACC56 M_ACC56 NOPARMO %00000010111000000jjjd000 dsp_baab + s1,d1 [s2,d2]\r
+- M_ALL48 M_ACC56 NOPARMO %00000010111000000jjjd000 dsp_tcc2 s1,d1 [s2,d2]\r
+tlt M_ACC56 M_ACC56 NOPARMO %00000010100100000jjjd000 dsp_baab + s1,d1 [s2,d2]\r
+- M_ALL48 M_ACC56 NOPARMO %00000010100100000jjjd000 dsp_tcc2 s1,d1 [s2,d2]\r
+tmi M_ACC56 M_ACC56 NOPARMO %00000010101100000jjjd000 dsp_baab + s1,d1 [s2,d2]\r
+- M_ALL48 M_ACC56 NOPARMO %00000010101100000jjjd000 dsp_tcc2 s1,d1 [s2,d2]\r
+tne M_ACC56 M_ACC56 NOPARMO %00000010001000000jjjd000 dsp_baab + s1,d1 [s2,d2]\r
+- M_ALL48 M_ACC56 NOPARMO %00000010001000000jjjd000 dsp_tcc2 s1,d1 [s2,d2]\r
+tnr M_ACC56 M_ACC56 NOPARMO %00000010110000000jjjd000 dsp_baab + s1,d1 [s2,d2]\r
+- M_ALL48 M_ACC56 NOPARMO %00000010110000000jjjd000 dsp_tcc2 s1,d1 [s2,d2]\r
+tpl M_ACC56 M_ACC56 NOPARMO %00000010001100000jjjd000 dsp_baab + s1,d1 [s2,d2]\r
+- M_ALL48 M_ACC56 NOPARMO %00000010001100000jjjd000 dsp_tcc2 s1,d1 [s2,d2]\r
+tnn M_ACC56 M_ACC56 NOPARMO %00000010010000000jjjd000 dsp_baab + s1,d1 [s2,d2]\r
+- M_ALL48 M_ACC56 NOPARMO %00000010010000000jjjd000 dsp_tcc2 s1,d1 [s2,d2]\r
+jcc M_DSPABS12 M_AM_NONE NOPARMO %000011100000aaaaaaaaaaaa dsp_abs12 + Jcc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101011mmmrrr10100000 dsp_ea Jcc ea mmmrrr=ea \r
+jhs M_DSPABS12 M_AM_NONE NOPARMO %000011100000aaaaaaaaaaaa dsp_abs12 + Jcc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101011mmmrrr10100000 dsp_ea Jcc ea mmmrrr=ea \r
+jcs M_DSPABS12 M_AM_NONE NOPARMO %000011101000aaaaaaaaaaaa dsp_abs12 + Jcc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101011mmmrrr10101000 dsp_ea Jcc ea mmmrrr=ea \r
+jlo M_DSPABS12 M_AM_NONE NOPARMO %000011101000aaaaaaaaaaaa dsp_abs12 + Jcc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101011mmmrrr10101000 dsp_ea Jcc ea mmmrrr=ea \r
+jec M_DSPABS12 M_AM_NONE NOPARMO %000011100101aaaaaaaaaaaa dsp_abs12 + Jcc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101011mmmrrr10100101 dsp_ea Jcc ea mmmrrr=ea \r
+jeq M_DSPABS12 M_AM_NONE NOPARMO %000011101010aaaaaaaaaaaa dsp_abs12 + Jcc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101011mmmrrr10101010 dsp_ea Jcc ea mmmrrr=ea \r
+jes M_DSPABS12 M_AM_NONE NOPARMO %000011101101aaaaaaaaaaaa dsp_abs12 + Jcc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101011mmmrrr10101101 dsp_ea Jcc ea mmmrrr=ea \r
+jge M_DSPABS12 M_AM_NONE NOPARMO %000011100001aaaaaaaaaaaa dsp_abs12 + Jcc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101011mmmrrr10100001 dsp_ea Jcc ea mmmrrr=ea \r
+jgt M_DSPABS12 M_AM_NONE NOPARMO %000011100111aaaaaaaaaaaa dsp_abs12 + Jcc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101011mmmrrr10100111 dsp_ea Jcc ea mmmrrr=ea \r
+jge M_DSPABS12 M_AM_NONE NOPARMO %000011100001aaaaaaaaaaaa dsp_abs12 + Jcc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101011mmmrrr10100001 dsp_ea Jcc ea mmmrrr=ea \r
+jlc M_DSPABS12 M_AM_NONE NOPARMO %000011100110aaaaaaaaaaaa dsp_abs12 + Jcc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101011mmmrrr10100110 dsp_ea Jcc ea mmmrrr=ea \r
+jle M_DSPABS12 M_AM_NONE NOPARMO %000011101111aaaaaaaaaaaa dsp_abs12 + Jcc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101011mmmrrr10101111 dsp_ea Jcc ea mmmrrr=ea \r
+jls M_DSPABS12 M_AM_NONE NOPARMO %000011101110aaaaaaaaaaaa dsp_abs12 + Jcc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101011mmmrrr10101110 dsp_ea Jcc ea mmmrrr=ea \r
+jlt M_DSPABS12 M_AM_NONE NOPARMO %000011101001aaaaaaaaaaaa dsp_abs12 + Jcc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101011mmmrrr10101001 dsp_ea Jcc ea mmmrrr=ea \r
+jmi M_DSPABS12 M_AM_NONE NOPARMO %000011101011aaaaaaaaaaaa dsp_abs12 + Jcc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101011mmmrrr10101011 dsp_ea Jcc ea mmmrrr=ea \r
+jne M_DSPABS12 M_AM_NONE NOPARMO %000011100010aaaaaaaaaaaa dsp_abs12 + Jcc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101011mmmrrr10100010 dsp_ea Jcc ea mmmrrr=ea \r
+jnr M_DSPABS12 M_AM_NONE NOPARMO %000011101100aaaaaaaaaaaa dsp_abs12 + Jcc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101011mmmrrr10101100 dsp_ea Jcc ea mmmrrr=ea \r
+jpl M_DSPABS12 M_AM_NONE NOPARMO %000011100011aaaaaaaaaaaa dsp_abs12 + Jcc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101011mmmrrr10100011 dsp_ea Jcc ea mmmrrr=ea \r
+jnn M_DSPABS12 M_AM_NONE NOPARMO %000011100100aaaaaaaaaaaa dsp_abs12 + Jcc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101011mmmrrr10100100 dsp_ea Jcc ea mmmrrr=ea \r
+jmp M_DSPABS12 M_AM_NONE NOPARMO %000011000000aaaaaaaaaaaa dsp_abs12 + JMP xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101011mmmrrr10000000 dsp_ea JMP ea (+optional 24bit address) \r
+jscc M_DSPABS12 M_AM_NONE NOPARMO %000011110000aaaaaaaaaaaa dsp_abs12 + JScc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101111mmmrrr10100000 dsp_ea JScc ea mmmrrr=ea (+optional 24bit address) \r
+jshs M_DSPABS12 M_AM_NONE NOPARMO %000011110000aaaaaaaaaaaa dsp_abs12 + JScc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101111mmmrrr10100000 dsp_ea JScc ea mmmrrr=ea (+optional 24bit address) \r
+jscs M_DSPABS12 M_AM_NONE NOPARMO %000011111000aaaaaaaaaaaa dsp_abs12 + JScc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101111mmmrrr10101000 dsp_ea JScc ea mmmrrr=ea (+optional 24bit address) \r
+jslo M_DSPABS12 M_AM_NONE NOPARMO %000011111000aaaaaaaaaaaa dsp_abs12 + JScc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101111mmmrrr10101000 dsp_ea JScc ea mmmrrr=ea (+optional 24bit address) \r
+jsec M_DSPABS12 M_AM_NONE NOPARMO %000011110101aaaaaaaaaaaa dsp_abs12 + JScc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101111mmmrrr10100101 dsp_ea JScc ea mmmrrr=ea (+optional 24bit address) \r
+jseq M_DSPABS12 M_AM_NONE NOPARMO %000011111010aaaaaaaaaaaa dsp_abs12 + JScc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101111mmmrrr10101010 dsp_ea JScc ea mmmrrr=ea (+optional 24bit address) \r
+jses M_DSPABS12 M_AM_NONE NOPARMO %000011111101aaaaaaaaaaaa dsp_abs12 + JScc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101111mmmrrr10101101 dsp_ea JScc ea mmmrrr=ea (+optional 24bit address) \r
+jsge M_DSPABS12 M_AM_NONE NOPARMO %000011110001aaaaaaaaaaaa dsp_abs12 + JScc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101111mmmrrr10100001 dsp_ea JScc ea mmmrrr=ea (+optional 24bit address) \r
+jsgt M_DSPABS12 M_AM_NONE NOPARMO %000011110111aaaaaaaaaaaa dsp_abs12 + JScc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101111mmmrrr10100111 dsp_ea JScc ea mmmrrr=ea (+optional 24bit address) \r
+jslc M_DSPABS12 M_AM_NONE NOPARMO %000011110110aaaaaaaaaaaa dsp_abs12 + JScc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101111mmmrrr10100110 dsp_ea JScc ea mmmrrr=ea (+optional 24bit address) \r
+jsle M_DSPABS12 M_AM_NONE NOPARMO %000011111111aaaaaaaaaaaa dsp_abs12 + JScc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101111mmmrrr10101111 dsp_ea JScc ea mmmrrr=ea (+optional 24bit address) \r
+jsls M_DSPABS12 M_AM_NONE NOPARMO %000011111110aaaaaaaaaaaa dsp_abs12 + JScc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101111mmmrrr10101110 dsp_ea JScc ea mmmrrr=ea (+optional 24bit address) \r
+jslt M_DSPABS12 M_AM_NONE NOPARMO %000011111001aaaaaaaaaaaa dsp_abs12 + JScc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101111mmmrrr10101001 dsp_ea JScc ea mmmrrr=ea (+optional 24bit address) \r
+jsmi M_DSPABS12 M_AM_NONE NOPARMO %000011111011aaaaaaaaaaaa dsp_abs12 + JScc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101111mmmrrr10101011 dsp_ea JScc ea mmmrrr=ea (+optional 24bit address) \r
+jsne M_DSPABS12 M_AM_NONE NOPARMO %000011110010aaaaaaaaaaaa dsp_abs12 + JScc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101111mmmrrr10100010 dsp_ea JScc ea mmmrrr=ea (+optional 24bit address) \r
+jsnr M_DSPABS12 M_AM_NONE NOPARMO %000011111100aaaaaaaaaaaa dsp_abs12 + JScc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101111mmmrrr10101100 dsp_ea JScc ea mmmrrr=ea (+optional 24bit address) \r
+jspl M_DSPABS12 M_AM_NONE NOPARMO %000011110011aaaaaaaaaaaa dsp_abs12 + JScc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101111mmmrrr10100011 dsp_ea JScc ea mmmrrr=ea (+optional 24bit address) \r
+jsnn M_DSPABS12 M_AM_NONE NOPARMO %000011110100aaaaaaaaaaaa dsp_abs12 + JScc xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101111mmmrrr10100100 dsp_ea JScc ea mmmrrr=ea (+optional 24bit address) \r
+jsr M_DSPABS12 M_AM_NONE NOPARMO %000011010000aaaaaaaaaaaa dsp_abs12 + JSR xxx aaaaaaaaaaaa=12bit address \r
+- C_DSPABSEA M_AM_NONE NOPARMO %0000101111mmmrrr10000000 dsp_ea JSR ea mmmrrr=ea (+optional 24bit address) \r
+neg M_ACC56 M_AM_NONE PARMOVE %mmmmmmmmmmmmmmmm0011d110 dsp_ab d=(a=0, b=1)\r
+bchg C_DSPIM M_DSPEA NOPARMO %0000101101mmmrrr0s0bbbbb dsp_ea_imm5 + bchg #n,X:ea / #n,Y:ea mmmrrr=ea, s=(X=0, Y=1), bbbbb=0-31\r
+- C_DSPIM M_DSPAA NOPARMO %0000101100aaaaaa0s0bbbbb dsp_ea_imm5 + bchg #n,X:aa / bchg #n,Y:aa\r
+- C_DSPIM M_DSPPP NOPARMO %0000101110pppppp0s0bbbbb dsp_ea_imm5 + bchg #n,X:pp / bchg #n,Y:pp\r
+- C_DSPIM C_DD NOPARMO %00001011110001dd010bbbbb dsp_reg_imm5 + bchg #n,D DDD See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_DDD NOPARMO %0000101111001ddd010bbbbb dsp_reg_imm5 + bchg #n,D DDD See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_TTT NOPARMO %0000101111010ddd010bbbbb dsp_reg_imm5 + bchg #n,D TTT See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_NNN NOPARMO %0000101111011ddd010bbbbb dsp_reg_imm5 + bchg #n,D NNN See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_FFF NOPARMO %0000101111100ddd010bbbbb dsp_reg_imm5 + bchg #n,D FFF See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_GGG NOPARMO %0000101111111ddd010bbbbb dsp_reg_imm5 bchg #n,D GGG See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+bclr C_DSPIM M_DSPEA NOPARMO %0000101001mmmrrr0s0bbbbb dsp_ea_imm5 + bclr #n,X:ea / #n,Y:ea mmmrrr=ea, s=(X=0, Y=1), bbbbb=0-31\r
+- C_DSPIM M_DSPAA NOPARMO %0000101000aaaaaa0s0bbbbb dsp_ea_imm5 + bclr #n,X:aa / bclr #n,Y:aa\r
+- C_DSPIM M_DSPPP NOPARMO %0000101010pppppp0s0bbbbb dsp_ea_imm5 + bclr #n,X:pp / bclr #n,Y:pp\r
+- C_DSPIM C_DDD NOPARMO %0000101011001ddd010bbbbb dsp_reg_imm5 + bclr #n,D DDD See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_DD NOPARMO %00001010110001dd010bbbbb dsp_reg_imm5 + bclr #n,D DDD See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_TTT NOPARMO %0000101011010ddd010bbbbb dsp_reg_imm5 + bclr #n,D TTT See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_NNN NOPARMO %0000101011011ddd010bbbbb dsp_reg_imm5 + bclr #n,D NNN See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_FFF NOPARMO %0000101011100ddd010bbbbb dsp_reg_imm5 + bclr #n,D FFF See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_GGG NOPARMO %0000101011111ddd010bbbbb dsp_reg_imm5 bclr #n,D GGG See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+bset C_DSPIM M_DSPEA NOPARMO %0000101001mmmrrr0s1bbbbb dsp_ea_imm5 + bset #n,X:ea / #n,Y:ea mmmrrr=ea, s=(X=0, Y=1), bbbbb=0-31\r
+- C_DSPIM M_DSPAA NOPARMO %0000101000aaaaaa0s1bbbbb dsp_ea_imm5 + bset #n,X:aa / bset #n,Y:aa\r
+- C_DSPIM M_DSPPP NOPARMO %0000101010pppppp0s1bbbbb dsp_ea_imm5 + bset #n,X:pp / bset #n,Y:pp\r
+- C_DSPIM C_DD NOPARMO %00001010110001dd011bbbbb dsp_reg_imm5 + bset #n,D DDD See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_DDD NOPARMO %0000101011001ddd011bbbbb dsp_reg_imm5 + bset #n,D DDD See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_TTT NOPARMO %0000101011010ddd011bbbbb dsp_reg_imm5 + bset #n,D TTT See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_NNN NOPARMO %0000101011011ddd011bbbbb dsp_reg_imm5 + bset #n,D NNN See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_FFF NOPARMO %0000101011100ddd011bbbbb dsp_reg_imm5 + bset #n,D FFF See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_GGG NOPARMO %0000101011111ddd011bbbbb dsp_reg_imm5 bset #n,D GGG See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+btst C_DSPIM M_DSPEA NOPARMO %0000101101mmmrrr0s1bbbbb dsp_ea_imm5 + btst#n,X:ea / #n,Y:ea mmmrrr=ea, s=(X=0, Y=1), bbbbb=0-31\r
+- C_DSPIM M_DSPAA NOPARMO %0000101100aaaaaa0s1bbbbb dsp_ea_imm5 + btst #n,X:aa / btst #n,Y:aa\r
+- C_DSPIM M_DSPPP NOPARMO %0000101110pppppp0s1bbbbb dsp_ea_imm5 + btst #n,X:pp / btst #n,Y:pp\r
+- C_DSPIM C_DDD NOPARMO %0000101111001ddd011bbbbb dsp_reg_imm5 + btst #n,D DDD See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_DD NOPARMO %00001011110001dd011bbbbb dsp_reg_imm5 + btst #n,D DDD See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_TTT NOPARMO %0000101111010ddd011bbbbb dsp_reg_imm5 + btst #n,D TTT See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_NNN NOPARMO %0000101111011ddd011bbbbb dsp_reg_imm5 + btst #n,D NNN See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_FFF NOPARMO %0000101111100ddd011bbbbb dsp_reg_imm5 + btst #n,D FFF See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_GGG NOPARMO %0000101111111ddd011bbbbb dsp_reg_imm5 btst #n,D GGG See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+do M_DSPEA C_DSPABS24 NOPARMO %0000011001mmmrrr0s000000 dsp_ea_abs16 + DO X:ea,expr / DO Y:ea,expr mmmrrr=ea, s=(X=0, Y=1), expr=16bit in extension word\r
+- M_DSPAA C_DSPABS24 NOPARMO %0000011000aaaaaa0s000000 dsp_ea_abs16 + DO X:aa,expr / DO Y:aa,expr aaaaaa=aa, s=(X=0, Y=1), expr=16bit in extension word\r
+- C_DSPIM C_DSPABS24 NOPARMO %00000110iiiiiiii1000hhhh dsp_imm12_abs16 + DO #xxx,expr hhhhiiiiiiii=12bit immediate, expr=16bit in extension word\r
+- M_ALU24 C_DSPABS24 NOPARMO %0000011011000ddd00000000 dsp_alu24_abs16 + DO S,expr x0, x1, y0, y1\r
+- C_DDD C_DSPABS24 NOPARMO %0000011011001ddd00000000 dsp_reg_abs16 + DO S,expr DDD See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_TTT C_DSPABS24 NOPARMO %0000011011010ddd00000000 dsp_reg_abs16 + DO S,expr TTT See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_NNN C_DSPABS24 NOPARMO %0000011011011ddd00000000 dsp_reg_abs16 + DO S,expr NNN See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_FFF C_DSPABS24 NOPARMO %0000011011100ddd00000000 dsp_reg_abs16 + DO S,expr FFF See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_GGG C_DSPABS24 NOPARMO %0000011011111ddd00000000 dsp_reg_abs16 DO S,expr GGG See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+rep C_DSPIM M_AM_NONE NOPARMO %00000110iiiiiiii1010hhhh dsp_imm12 + rep #xx\r
+- M_DSPEA M_AM_NONE NOPARMO %0000011001mmmrrr0s100000 dsp_ea + rep x:ea / y:ea\r
+- M_DSPAA M_AM_NONE NOPARMO %0000011000aaaaaa0s100000 dsp_ea + rep x:aa / y:aa\r
+- M_ALU24 M_AM_NONE NOPARMO %0000011011000ddd00100000 dsp_alu24 + rep S,expr x0, x1, y0, y1\r
+- C_DDD M_AM_NONE NOPARMO %0000011011001ddd00100000 dsp_reg + rep S DDD See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_TTT M_AM_NONE NOPARMO %0000011011010ddd00100000 dsp_reg + rep S TTT See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_NNN M_AM_NONE NOPARMO %0000011011011ddd00100000 dsp_reg + rep S NNN See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_FFF M_AM_NONE NOPARMO %0000011011100ddd00100000 dsp_reg + rep S FFF See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_GGG M_AM_NONE NOPARMO %0000011011111ddd00100000 dsp_reg rep S GGG See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+jsclr C_DSPIM M_DSPEA NOPARMO %0000101101mmmrrr1s0bbbbb dsp_ea_imm5_abs16 + JSCLR #n,X:ea,xxxx / #n,Y:ea,xxxx n=bbbbb=0-31, ea=mmmrrr, xxxx=16bit extension, s=(X=0, Y=1)\r
+- C_DSPIM M_DSPAA NOPARMO %0000101100aaaaaa1s0bbbbb dsp_ea_imm5_abs16 + JSCLR #n,X:aa,xxxx / #n,Y:aa,xxxx n=bbbbb=0-31, aa=aaaaaa=short address, s=(X=0, Y=1)\r
+- C_DSPIM M_DSPPP NOPARMO %0000101110pppppp1s0bbbbb dsp_ea_imm5_abs16 + JSCLR #n,X:pp,xxxx / #n,Y:pp,xxxx n=bbbbb=0-31, pp=pppppp=short i/o address, s=(X=0, Y=1)\r
+- C_DSPIM C_DD NOPARMO %00001011110001dd000bbbbb dsp_reg_imm5_abs16 + JSCLR #n,S,xxxx DDD See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_DDD NOPARMO %0000101111001ddd000bbbbb dsp_reg_imm5_abs16 + JSCLR #n,S,xxxx DDD See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_TTT NOPARMO %0000101111010ddd000bbbbb dsp_reg_imm5_abs16 + JSCLR #n,S,xxxx TTT See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_NNN NOPARMO %0000101111011ddd000bbbbb dsp_reg_imm5_abs16 + JSCLR #n,S,xxxx NNN See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_FFF NOPARMO %0000101111100ddd000bbbbb dsp_reg_imm5_abs16 + JSCLR #n,S,xxxx FFF See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_GGG NOPARMO %0000101111101ddd000bbbbb dsp_reg_imm5_abs16 JSCLR #n,S,xxxx GGG See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+jset C_DSPIM M_DSPEA NOPARMO %0000101001mmmrrr1s1bbbbb dsp_ea_imm5_abs16 + JSET #n,X:ea,xxxx / #n,Y:ea,xxxx n=bbbbb=0-31, ea=mmmrrr, xxxx=16bit extension, s=(X=0, Y=1)\r
+- C_DSPIM M_DSPAA NOPARMO %0000101000aaaaaa1s1bbbbb dsp_ea_imm5_abs16 + JSET #n,X:aa,xxxx / #n,Y:aa,xxxx n=bbbbb=0-31, aa=aaaaaa=short address, s=(X=0, Y=1)\r
+- C_DSPIM M_DSPPP NOPARMO %0000101010pppppp1s1bbbbb dsp_ea_imm5_abs16 + JSET #n,X:pp,xxxx / #n,Y:pp,xxxx n=bbbbb=0-31, pp=pppppp=short i/o address, s=(X=0, Y=1)\r
+- C_DSPIM C_DD NOPARMO %00001010110001dd001bbbbb dsp_reg_imm5_abs16 + JSET #n,S,xxxx DDD See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_DDD NOPARMO %0000101011001ddd001bbbbb dsp_reg_imm5_abs16 + JSET #n,S,xxxx DDD See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_TTT NOPARMO %0000101011010ddd001bbbbb dsp_reg_imm5_abs16 + JSET #n,S,xxxx TTT See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_NNN NOPARMO %0000101011011ddd001bbbbb dsp_reg_imm5_abs16 + JSET #n,S,xxxx NNN See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_FFF NOPARMO %0000101011100ddd001bbbbb dsp_reg_imm5_abs16 + JSET #n,S,xxxx FFF See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_GGG NOPARMO %0000101011101ddd001bbbbb dsp_reg_imm5_abs16 JSET #n,S,xxxx GGG See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+jsset C_DSPIM M_DSPEA NOPARMO %0000101101mmmrrr1s1bbbbb dsp_ea_imm5_abs16 + JSSET #n,X:ea,xxxx / JSSET #n,Y:ea,xxxx n=bbbbb=0-31, ea=mmmrrr, xxxx=16bit extension, s=(X=0, Y=1)\r
+- C_DSPIM M_DSPAA NOPARMO %0000101100aaaaaa1s1bbbbb dsp_ea_imm5_abs16 + JSSET #n,X:aa,xxxx / #n,Y:aa,xxxx n=bbbbb=0-31, aa=aaaaaa=short address, s=(X=0, Y=1)\r
+- C_DSPIM M_DSPPP NOPARMO %0000101110pppppp1s1bbbbb dsp_ea_imm5_abs16 + JSSET #n,X:pp,xxxx / #n,Y:pp,xxxx n=bbbbb=0-31, pp=pppppp=short i/o address, s=(X=0, Y=1)\r
+- C_DSPIM C_DD NOPARMO %00001011110001dd001bbbbb dsp_reg_imm5_abs16 + JSSET #n,S,xxxx DDD See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_DDD NOPARMO %0000101111001ddd001bbbbb dsp_reg_imm5_abs16 + JSSET #n,S,xxxx DDD See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_TTT NOPARMO %0000101111010ddd001bbbbb dsp_reg_imm5_abs16 + JSSET #n,S,xxxx TTT See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_NNN NOPARMO %0000101111011ddd001bbbbb dsp_reg_imm5_abs16 + JSSET #n,S,xxxx NNN See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_FFF NOPARMO %0000101111100ddd001bbbbb dsp_reg_imm5_abs16 + JSSET #n,S,xxxx FFF See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_GGG NOPARMO %0000101111101ddd001bbbbb dsp_reg_imm5_abs16 JSSET #n,S,xxxx GGG See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+jclr C_DSPIM M_DSPEA NOPARMO %0000101001mmmrrr1s0bbbbb dsp_ea_imm5_abs16 + JCLR #n,X:ea,xxxx / #n,Y:ea,xxxx n=bbbbb=0-31, ea=mmmrrr, xxxx=16bit extension, s=(X=0, Y=1)\r
+- C_DSPIM M_DSPAA NOPARMO %0000101000aaaaaa1s0bbbbb dsp_ea_imm5_abs16 + JCLR #n,X:aa,xxxx / #n,Y:aa,xxxx n=bbbbb=0-31, aa=aaaaaa=short address, s=(X=0, Y=1)\r
+- C_DSPIM M_DSPPP NOPARMO %0000101010pppppp1s0bbbbb dsp_ea_imm5_abs16 + JCLR #n,X:pp,xxxx / #n,Y:pp,xxxx n=bbbbb=0-31, pp=pppppp=short i/o address, s=(X=0, Y=1)\r
+- C_DSPIM C_DD NOPARMO %00001010110001dd000bbbbb dsp_reg_imm5_abs16 + JCLR #n,S,xxxx DDD See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_DDD NOPARMO %0000101011001ddd000bbbbb dsp_reg_imm5_abs16 + JCLR #n,S,xxxx DDD See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_TTT NOPARMO %0000101011010ddd000bbbbb dsp_reg_imm5_abs16 + JCLR #n,S,xxxx TTT See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_NNN NOPARMO %0000101011011ddd000bbbbb dsp_reg_imm5_abs16 + JCLR #n,S,xxxx NNN See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_FFF NOPARMO %0000101011100ddd000bbbbb dsp_reg_imm5_abs16 + JCLR #n,S,xxxx FFF See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+- C_DSPIM C_GGG NOPARMO %0000101011101ddd000bbbbb dsp_reg_imm5_abs16 JCLR #n,S,xxxx GGG See A.9 Instruction Encoding and Table A-18 for specific register encodings.\r
+lua M_DSPEA C_LUADST NOPARMO %00000100010mmrrr0001dddd dsp_ea_lua mmrrr=ea (subset), dddd=(bit 3=(0=Rn, 1=Nn), bits 2-0=0-7)\r
+norm M_DSPR M_ACC56 NOPARMO %0000000111011rrr0001d101 dsp_ab_rn norm Rn,D D=(a=0, b=1)\r
+move M_AM_NONE M_AM_NONE PARMOVE %mmmmmmmmmmmmmmmm00000000 dsp_self\r
+movec M_DSPIM8 C_MOVEC NOPARMO %00000101iiiiiiii101ddddd dsp_immmovec + move(c) #xx,d1\r
+- M_DSPEA C_MOVEC NOPARMO %0000010111mmmrrr0s1ddddd dsp_movec_ea + move(c) x:ea,d1 / y:ea,d1\r
+- C_MOVEC M_DSPEA NOPARMO %0000010101mmmrrr0s1ddddd dsp_movec_ea + move(c) s1,x:ea / s1,y:ea\r
+- C_DSPIM C_MOVEC NOPARMO %0000010111110100001ddddd dsp_movec_ea + move(c) #xxxx,d1\r
+- M_DSPAA C_MOVEC NOPARMO %0000010110aaaaaa0s1ddddd dsp_movec_aa + move(c) x:aa,d1 / y:aa,d1 \r
+- C_MOVEC M_DSPAA NOPARMO %0000010100aaaaaa0s1ddddd dsp_movec_aa + move(c) s1,x:aa / s1,y:aa\r
+- C_MOVEC M_ALU24 NOPARMO %0000010001000eee101ddddd dsp_movec_reg + move(c) s1,d2 \r
+- C_MOVEC C_DDD NOPARMO %0000010001001eee101ddddd dsp_movec_reg + move(c) s1,d2 \r
+- C_MOVEC C_TTT NOPARMO %0000010001010eee101ddddd dsp_movec_reg + move(c) s1,d2 \r
+- C_MOVEC C_NNN NOPARMO %0000010001011eee101ddddd dsp_movec_reg + move(c) s1,d2 \r
+- C_MOVEC C_FFF NOPARMO %0000010001100eee101ddddd dsp_movec_reg + move(c) s1,d2 \r
+- C_MOVEC C_GGG NOPARMO %0000010001111eee101ddddd dsp_movec_reg + move(c) s1,d2 \r
+- M_ALU24 C_MOVEC NOPARMO %0000010011000eee101ddddd dsp_movec_reg + move(c) s2,d1\r
+- C_DDD C_MOVEC NOPARMO %0000010011001eee101ddddd dsp_movec_reg + move(c) s2,d1\r
+- C_TTT C_MOVEC NOPARMO %0000010011010eee101ddddd dsp_movec_reg + move(c) s2,d1\r
+- C_NNN C_MOVEC NOPARMO %0000010011011eee101ddddd dsp_movec_reg + move(c) s2,d1\r
+- C_FFF C_MOVEC NOPARMO %0000010011100eee101ddddd dsp_movec_reg + move(c) s2,d1\r
+- C_GGG C_MOVEC NOPARMO %0000010011111eee101ddddd dsp_movec_reg move(c) s2,d1\r
+movem M_ALU24 M_DSPEA NOPARMO %0000011101mmmrrr10000ddd dsp_movem_ea + move(m) s,p:ea / p:ea,d\r
+- C_DDD M_DSPEA NOPARMO %0000011101mmmrrr10001ddd dsp_movem_ea + move(m) s,p:ea / p:ea,d\r
+- C_TTT M_DSPEA NOPARMO %0000011101mmmrrr10010ddd dsp_movem_ea + move(m) s,p:ea / p:ea,d\r
+- C_NNN M_DSPEA NOPARMO %0000011101mmmrrr10011ddd dsp_movem_ea + move(m) s,p:ea / p:ea,d\r
+- C_FFF M_DSPEA NOPARMO %0000011101mmmrrr10100ddd dsp_movem_ea + move(m) s,p:ea / p:ea,d\r
+- C_GGG M_DSPEA NOPARMO %0000011101mmmrrr10111ddd dsp_movem_ea + move(m) s,p:ea / p:ea,d\r
+- M_DSPEA M_ALU24 NOPARMO %0000011111mmmrrr10000ddd dsp_movem_ea + move(m) s,p:ea / p:ea,d\r
+- M_DSPEA C_DDD NOPARMO %0000011111mmmrrr10001ddd dsp_movem_ea + move(m) s,p:ea / p:ea,d\r
+- M_DSPEA C_TTT NOPARMO %0000011111mmmrrr10010ddd dsp_movem_ea + move(m) s,p:ea / p:ea,d\r
+- M_DSPEA C_NNN NOPARMO %0000011111mmmrrr10011ddd dsp_movem_ea + move(m) s,p:ea / p:ea,d\r
+- M_DSPEA C_FFF NOPARMO %0000011111mmmrrr10100ddd dsp_movem_ea + move(m) s,p:ea / p:ea,d\r
+- M_DSPEA C_GGG NOPARMO %0000011111mmmrrr10111ddd dsp_movem_ea + move(m) s,p:ea / p:ea,d\r
+- M_ALU24 M_DSPAA NOPARMO %0000011100aaaaaa00000ddd dsp_movem_aa + move(m) s,p:aa / p:aa,d\r
+- C_DDD M_DSPAA NOPARMO %0000011100aaaaaa00001ddd dsp_movem_aa + move(m) s,p:aa / p:aa,d\r
+- C_TTT M_DSPAA NOPARMO %0000011100aaaaaa00010ddd dsp_movem_aa + move(m) s,p:aa / p:aa,d\r
+- C_NNN M_DSPAA NOPARMO %0000011100aaaaaa00011ddd dsp_movem_aa + move(m) s,p:aa / p:aa,d\r
+- C_FFF M_DSPAA NOPARMO %0000011100aaaaaa00100ddd dsp_movem_aa + move(m) s,p:aa / p:aa,d\r
+- C_GGG M_DSPAA NOPARMO %0000011100aaaaaa00111ddd dsp_movem_aa + move(m) s,p:aa / p:aa,d\r
+- M_DSPAA M_ALU24 NOPARMO %0000011110aaaaaa00000ddd dsp_movem_aa + move(m) s,p:aa / p:aa,d\r
+- M_DSPAA C_DDD NOPARMO %0000011110aaaaaa00001ddd dsp_movem_aa + move(m) s,p:aa / p:aa,d\r
+- M_DSPAA C_TTT NOPARMO %0000011110aaaaaa00010ddd dsp_movem_aa + move(m) s,p:aa / p:aa,d\r
+- M_DSPAA C_NNN NOPARMO %0000011110aaaaaa00011ddd dsp_movem_aa + move(m) s,p:aa / p:aa,d\r
+- M_DSPAA C_FFF NOPARMO %0000011110aaaaaa00100ddd dsp_movem_aa + move(m) s,p:aa / p:aa,d\r
+- M_DSPAA C_GGG NOPARMO %0000011110aaaaaa00111ddd dsp_movem_aa move(m) s,p:aa / p:aa,d\r
+mac M_ALU24 M_ALU24 PARMOVE %mmmmmmmmmmmmmmmm1qqqdk10 dsp_mult mac -+s1,s2,d / mac -+s2,s1,d\r
+macr M_ALU24 M_ALU24 PARMOVE %mmmmmmmmmmmmmmmm1qqqdk11 dsp_mult macr -+s1,s2,d / macr -+s2,s1,d\r
+mpy M_ALU24 M_ALU24 PARMOVE %mmmmmmmmmmmmmmmm1qqqdk00 dsp_mult mpy -+s1,d2,d / -+s2,s1,d\r
+mpyr M_ALU24 M_ALU24 PARMOVE %mmmmmmmmmmmmmmmm1qqqdk01 dsp_mult mpyr -+s1,d2,d / -+s2,s1,d\r
+movep M_DSPEA M_DSPPP NOPARMO %0000100s11mmmrrr1spppppp dsp_movep_ea + movep p:ea,x:pp / p:ea,y:pp \r
+- M_DSPAA M_DSPPP NOPARMO %0000100s11mmmrrr1spppppp dsp_movep_ea + movep p:aa,x:pp / p:aa,y:pp \r
+- M_DSPPP M_DSPEA NOPARMO %0000100s01mmmrrr1spppppp dsp_movep_ea + x:pp,p:ea / y:pp,p:ea\r
+- M_DSPPP M_DSPPP NOPARMO %0000100s01mmmrrr1spppppp dsp_movep_ea + x:pp,p:ea / y:pp,p:ea\r
+- M_DSPPP M_DSPAA NOPARMO %0000100s01mmmrrr1spppppp dsp_movep_ea + x:pp,p:aa / y:pp,p:aa\r
+- C_DSPIM M_DSPPP NOPARMO %0000100s111101001spppppp dsp_movep_ea + #xxxxxx,x:pp / #xxxxxx,y:pp\r
+- C_DSPIM M_DSPEA NOPARMO %0000100s111101001spppppp dsp_movep_ea + #xxxxxx,x:pp / #xxxxxx,y:pp\r
+- M_ALU24 M_DSPPP NOPARMO %0000100s11000ddd0spppppp dsp_movep_reg + movep s,x:pp / s,y:pp\r
+- C_DDD M_DSPPP NOPARMO %0000100s11001ddd0spppppp dsp_movep_reg + movep s,x:pp / s,y:pp\r
+- C_TTT M_DSPPP NOPARMO %0000100s11010ddd0spppppp dsp_movep_reg + movep s,x:pp / s,y:pp\r
+- C_NNN M_DSPPP NOPARMO %0000100s11011ddd0spppppp dsp_movep_reg + movep s,x:pp / s,y:pp\r
+- C_FFF M_DSPPP NOPARMO %0000100s11100ddd0spppppp dsp_movep_reg + movep s,x:pp / s,y:pp\r
+- C_GGG M_DSPPP NOPARMO %0000100s11111ddd0spppppp dsp_movep_reg + movep s,x:pp / s,y:pp\r
+- M_DSPPP M_ALU24 NOPARMO %0000100s01000ddd0spppppp dsp_movep_reg + movep x:pp,d / y:pp,d\r
+- M_DSPPP C_DDD NOPARMO %0000100s01001ddd0spppppp dsp_movep_reg + movep x:pp,d / y:pp,d\r
+- M_DSPPP C_TTT NOPARMO %0000100s01010ddd0spppppp dsp_movep_reg + movep x:pp,d / y:pp,d\r
+- M_DSPPP C_NNN NOPARMO %0000100s01011ddd0spppppp dsp_movep_reg + movep x:pp,d / y:pp,d\r
+- M_DSPPP C_FFF NOPARMO %0000100s01100ddd0spppppp dsp_movep_reg + movep x:pp,d / y:pp,d\r
+- M_DSPPP C_GGG NOPARMO %0000100s01111ddd0spppppp dsp_movep_reg movep x:pp,d / y:pp,d\r
+debug M_AM_NONE M_AM_NONE NOPARMO %000000000000001000000000 dsp_self\r
+debugcc M_AM_NONE M_AM_NONE NOPARMO %000000000000001100000000 dsp_self\r
+debughs M_AM_NONE M_AM_NONE NOPARMO %000000000000001100000000 dsp_self\r
+debugcs M_AM_NONE M_AM_NONE NOPARMO %000000000000001100001000 dsp_self\r
+debuglo M_AM_NONE M_AM_NONE NOPARMO %000000000000001100001000 dsp_self\r
+debugec M_AM_NONE M_AM_NONE NOPARMO %000000000000001100000101 dsp_self\r
+debugeq M_AM_NONE M_AM_NONE NOPARMO %000000000000001100001010 dsp_self\r
+debuges M_AM_NONE M_AM_NONE NOPARMO %000000000000001100001101 dsp_self\r
+debugge M_AM_NONE M_AM_NONE NOPARMO %000000000000001100000001 dsp_self\r
+debuggt M_AM_NONE M_AM_NONE NOPARMO %000000000000001100000111 dsp_self\r
+debuglc M_AM_NONE M_AM_NONE NOPARMO %000000000000001100000110 dsp_self\r
+debugle M_AM_NONE M_AM_NONE NOPARMO %000000000000001100001111 dsp_self\r
+debugls M_AM_NONE M_AM_NONE NOPARMO %000000000000001100001110 dsp_self\r
+debuglt M_AM_NONE M_AM_NONE NOPARMO %000000000000001100001001 dsp_self\r
+debugmi M_AM_NONE M_AM_NONE NOPARMO %000000000000001100001011 dsp_self\r
+debugne M_AM_NONE M_AM_NONE NOPARMO %000000000000001100000010 dsp_self\r
+debugnr M_AM_NONE M_AM_NONE NOPARMO %000000000000001100001100 dsp_self\r
+debugpl M_AM_NONE M_AM_NONE NOPARMO %000000000000001100000011 dsp_self\r
+debugnn M_AM_NONE M_AM_NONE NOPARMO %000000000000001100000100 dsp_self\r
+\r
+\r
--- /dev/null
+//
+// RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
+// AMODE.C - DSP 56001 Addressing Modes
+// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends
+// RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
+// Source utilised with the kind permission of Landon Dyer
+//
+
+#include "dsp56k_amode.h"
+#include "error.h"
+#include "token.h"
+#include "expr.h"
+#include "rmac.h"
+#include "procln.h"
+#include "sect.h"
+#include "math.h"
+
+#define DEF_KW
+#include "kwtab.h"
+#define DEF_MN
+#include "mntab.h"
+
+// Address-mode information
+int nmodes; // Number of addr'ing modes found
+int dsp_am0; // Addressing mode
+int dsp_a0reg; // Register
+TOKEN dsp_a0expr[EXPRSIZE]; // Expression
+uint64_t dsp_a0exval; // Expression's value
+WORD dsp_a0exattr; // Expression's attribute
+LONG dsp_a0memspace; // Addressing mode's memory space (P, X, Y)
+SYM * dsp_a0esym; // External symbol involved in expr
+
+int dsp_am1; // Addressing mode
+int dsp_a1reg; // Register
+TOKEN dsp_a1expr[EXPRSIZE]; // Expression
+uint64_t dsp_a1exval; // Expression's value
+WORD dsp_a1exattr; // Expression's attribute
+LONG dsp_a1memspace; // Addressing mode's memory space (P, X, Y)
+SYM * dsp_a1esym; // External symbol involved in expr
+
+int dsp_am2; // Addressing mode
+int dsp_a2reg; // Register
+TOKEN dsp_a2expr[EXPRSIZE]; // Expression
+uint64_t dsp_a2exval; // Expression's value
+WORD dsp_a2exattr; // Expression's attribute
+SYM * dsp_a2esym; // External symbol involved in expr
+
+int dsp_am3; // Addressing mode
+int dsp_a3reg; // Register
+TOKEN dsp_a3expr[EXPRSIZE]; // Expression
+uint64_t dsp_a3exval; // Expression's value
+WORD dsp_a3exattr; // Expression's attribute
+SYM * dsp_a3esym; // External symbol involved in expr
+
+TOKEN dspImmedEXPR[EXPRSIZE]; // Expression
+uint64_t dspImmedEXVAL; // Expression's value
+WORD dspImmedEXATTR; // Expression's attribute
+SYM * dspImmedESYM; // External symbol involved in expr
+int deposit_extra_ea; // Optional effective address extension
+TOKEN dspaaEXPR[EXPRSIZE]; // Expression
+uint64_t dspaaEXVAL; // Expression's value
+WORD dspaaEXATTR; // Expression's attribute
+SYM * dspaaESYM; // External symbol involved in expr
+
+int dsp_k; // Multiplications sign
+
+static inline LONG checkea(const uint32_t termchar, const int strings);
+
+// ea checking error strings put into a table because I'm not sure there's an easy way to do otherwise
+// (the messages start getting differerent in many places so it will get awkward to code those in)
+// (I'd rather burn some RAM in order to have more helpful error messages than the other way round)
+
+#define X_ERRORS 0
+#define Y_ERRORS 1
+#define L_ERRORS 2
+#define P_ERRORS 3
+
+const char *ea_errors[][12] = {
+ // X:
+ {
+ "unrecognised X: parallel move syntax: expected '(' after 'X:-'", // 0
+ "unrecognised X: parallel move syntax: expected ')' after 'X:-(Rn'", // 1
+ "unrecognised X: parallel move syntax: expected R0-R7 after 'X:-('", // 2
+ "unrecognised X: parallel move syntax: expected N0-N7 after 'X:(Rn+'", // 3
+ "unrecognised X: parallel move syntax: expected same register number in Rn and Nn for 'X:(Rn+Nn)'", // 4
+ "unrecognised X: parallel move syntax: expected ')' after 'X:(Rn+Nn'", // 5
+ "unrecognised X: parallel move syntax: expected same register number in Rn and Nn for 'X:(Rn)+Nn'", // 6
+ "unrecognised X: parallel move syntax: expected N0-N7 after 'X:(Rn)+'", // 7
+ "unrecognised X: parallel move syntax: expected same register number in Rn and Nn for 'X:(Rn)-Nn'", // 8
+ "unrecognised X: parallel move syntax: expected N0-N7 after 'X:(Rn)-'", // 9
+ "unrecognised X: parallel move syntax: expected '+', '-' or ',' after 'X:(Rn)'", // 10
+ "unrecognised X: parallel move syntax: expected '+' or ')' after 'X:(Rn'", // 11
+ },
+ // Y:
+ {
+ "unrecognised Y: parallel move syntax: expected '(' after 'Y:-'", // 0
+ "unrecognised Y: parallel move syntax: expected ')' after 'Y:-(Rn'", // 1
+ "unrecognised Y: parallel move syntax: expected R0-R7 after 'Y:-('", // 2
+ "unrecognised Y: parallel move syntax: expected N0-N7 after 'Y:(Rn+'", // 3
+ "unrecognised Y: parallel move syntax: expected same register number in Rn and Nn for 'Y:(Rn+Nn)'", // 4
+ "unrecognised Y: parallel move syntax: expected ')' after 'Y:(Rn+Nn'", // 5
+ "unrecognised Y: parallel move syntax: expected same register number in Rn and Nn for 'Y:(Rn)+Nn'", // 6
+ "unrecognised Y: parallel move syntax: expected N0-N7 after 'Y:(Rn)+'", // 7
+ "unrecognised Y: parallel move syntax: expected same register number in Rn and Nn for 'Y:(Rn)-Nn'", // 8
+ "unrecognised Y: parallel move syntax: expected N0-N7 after 'Y:(Rn)-'", // 9
+ "unrecognised Y: parallel move syntax: expected '+', '-' or ',' after 'Y:(Rn)'", // 10
+ "unrecognised Y: parallel move syntax: expected '+' or ')' after 'Y:(Rn'", // 11
+ },
+ // L:
+ {
+ "unrecognised L: parallel move syntax: expected '(' after 'L:-'", // 0
+ "unrecognised L: parallel move syntax: expected ')' after 'L:-(Rn'", // 1
+ "unrecognised L: parallel move syntax: expected R0-R7 after 'L:-('", // 2
+ "unrecognised L: parallel move syntax: expected N0-N7 after 'L:(Rn+'", // 3
+ "unrecognised L: parallel move syntax: expected same register number in Rn and Nn for 'L:(Rn+Nn)'", // 4
+ "unrecognised L: parallel move syntax: expected ')' after 'L:(Rn+Nn'", // 5
+ "unrecognised L: parallel move syntax: expected same register number in Rn and Nn for 'L:(Rn)+Nn'", // 6
+ "unrecognised L: parallel move syntax: expected N0-N7 after 'L:(Rn)+'", // 7
+ "unrecognised L: parallel move syntax: expected same register number in Rn and Nn for 'L:(Rn)-Nn'", // 8
+ "unrecognised L: parallel move syntax: expected N0-N7 after 'L:(Rn)-'", // 9
+ "unrecognised L: parallel move syntax: expected '+', '-' or ',' after 'L:(Rn)'", // 10
+ "unrecognised L: parallel move syntax: expected '+' or ')' after 'L:(Rn'", // 11
+ },
+ // P:
+ {
+ "unrecognised P: effective address syntax: expected '(' after 'P:-'", // 0
+ "unrecognised P: effective address syntax: expected ')' after 'P:-(Rn'", // 1
+ "unrecognised P: effective address syntax: expected R0-R7 after 'P:-('", // 2
+ "unrecognised P: effective address syntax: expected N0-N7 after 'P:(Rn+'", // 3
+ "unrecognised P: effective address syntax: expected same register number in Rn and Nn for 'P:(Rn+Nn)'", // 4
+ "unrecognised P: effective address syntax: expected ')' after 'P:(Rn+Nn'", // 5
+ "unrecognised P: effective address syntax: expected same register number in Rn and Nn for 'P:(Rn)+Nn'", // 6
+ "unrecognised P: effective address syntax: expected N0-N7 after 'P:(Rn)+'", // 7
+ "unrecognised P: effective address syntax: expected same register number in Rn and Nn for 'P:(Rn)-Nn'", // 8
+ "unrecognised P: effective address syntax: expected N0-N7 after 'P:(Rn)-'", // 9
+ "unrecognised P: effective address syntax: expected '+', '-' or ',' after 'P:(Rn)'", // 10
+ "unrecognised P: effective address syntax: expected '+' or ')' after 'P:(Rn'", // 11
+ }
+};
+
+enum
+{
+ NUM_NORMAL = 0,
+ NUM_FORCE_LONG = 1,
+ NUM_FORCE_SHORT = 2
+};
+
+//
+// Parse a single addressing mode
+//
+static inline int dsp_parmode(int *am, int *areg, TOKEN * AnEXPR, uint64_t * AnEXVAL, WORD * AnEXATTR, SYM ** AnESYM, LONG *memspace, LONG *perspace, const int operand)
+{
+ if (*tok == KW_A || *tok == KW_B)
+ {
+ *am = M_ACC56;
+ *areg = *tok++;
+ return OK;
+ }
+ else if (*tok == '#')
+ {
+ tok++;
+
+ if (*tok == '<')
+ {
+ // Immediate Short Addressing Mode Force Operator
+ tok++;
+ if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+ return ERROR;
+ if (*AnEXVAL > 0xfff && *AnEXVAL<-4096)
+ return error("immediate short addressing mode forced but address is bigger than $fff");
+ if ((int32_t)*AnEXVAL <= 0xff && (int32_t)*AnEXVAL>-0x100)
+ {
+ *am = M_DSPIM8;
+ return OK;
+ }
+ *am = M_DSPIM12;
+ return OK;
+ }
+ else if (*tok == '>')
+ {
+ // Immediate Long Addressing Mode Force Operator
+ tok++;
+ if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+ return ERROR;
+ if ((int32_t)*AnEXVAL > 0xffffff || (int32_t)*AnEXVAL < -0xffffff)
+ return error("long immediate is bigger than $ffffff");
+ *am = M_DSPIM;
+ return OK;
+ }
+
+ if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+ return ERROR;
+
+ if (*AnEXATTR & DEFINED)
+ {
+ if ((int32_t)*AnEXVAL < 0x100 && (int32_t)*AnEXVAL >= -0x100)
+ {
+ *AnEXVAL &= 0xff;
+ *am = M_DSPIM8;
+ }
+ else if (*AnEXVAL < 0x1000)
+ *am = M_DSPIM12;
+ else
+ *am = M_DSPIM;
+ }
+ else
+ {
+ // We have no clue what size our immediate will be
+ // so we have to assume the worst
+ *am = M_DSPIM;
+ }
+ return OK;
+ }
+ else if (*tok >= KW_X0 && *tok <= KW_Y1)
+ {
+ *am = M_ALU24;
+ *areg = *tok++;
+ return OK;
+ }
+ else if (*tok == KW_X && *(tok + 1) == ':')
+ {
+ tok = tok + 2;
+ if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
+ {
+ if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+ return ERROR;
+ if (*AnEXATTR & DEFINED)
+ {
+ if (*AnEXVAL > 0xffffff)
+ return error("long address is bigger than $ffffff");
+ *memspace = 0 << 6; // Mark we're on X memory space
+
+ // Check if value is between $ffc0 and $ffff, AKA X:pp
+ {
+ uint32_t temp = (LONG)(((int32_t)(((uint32_t)*AnEXVAL) << (32 - 6))) >> (32 - 6)); // Sign extend 6 to 32 bits
+ if ((temp >= 0xffffffc0 /* Check for 32bit sign extended number */
+ && ((int32_t)*AnEXVAL<0)) /* Check if 32bit signed number is negative*/
+ ||(*AnEXVAL<0xffff && *AnEXVAL>=0x8000)) /* Check if 16bit number is negative*/
+ {
+ *AnEXVAL = temp;
+ *am = M_DSPPP;
+ *memspace = 0 << 6; // Mark we're on X memory space
+ *perspace = 0 << 16; // Mark we're on X peripheral space
+ *areg = *AnEXVAL & 0x3f; // Since this is only going to get used in dsp_ea_imm5...
+ return OK;
+ }
+
+ }
+
+ // If the symbol/expression is defined then check for valid range.
+ // Otherwise the value had better fit or Fixups will bark!
+ if (*AnEXVAL > 0x3f)
+ {
+ *am = M_DSPEA;
+ *areg = DSP_EA_ABS;
+ }
+ else
+ {
+ *am = M_DSPAA;
+ }
+ }
+ else
+ {
+ // Assume the worst
+ *memspace = 0 << 6; // Mark we're on X memory space
+ *am = M_DSPEA;
+ *areg = DSP_EA_ABS;
+ }
+ return OK;
+ }
+ else if (*tok == '<')
+ {
+ // X:aa
+ // Short Addressing Mode Force Operator in the case of '<'
+ tok++;
+ if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+ return ERROR;
+
+ // If the symbol/expression is defined then check for valid range.
+ // Otherwise the value had better fit or Fixups will bark!
+ if (*AnEXATTR & DEFINED)
+ {
+ if (*AnEXVAL > 0x3f)
+ return error("short addressing mode forced but address is bigger than $3f");
+ }
+ else
+ {
+ // Mark it as a fixup
+ deposit_extra_ea = DEPOSIT_EXTRA_FIXUP;
+ }
+ *am = M_DSPAA;
+ *memspace = 0 << 6; // Mark we're on X memory space
+ *areg = (int)*AnEXVAL; // Since this is only going to get used in dsp_ea_imm5...
+ return OK;
+ }
+ else if (*tok == '>')
+ {
+ // Long Addressing Mode Force Operator
+ tok++;
+
+ if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
+ {
+ if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+ return ERROR;
+ if (*AnEXATTR&DEFINED)
+ {
+ if (*AnEXVAL > 0xffffff)
+ return error("long address is bigger than $ffffff");
+ *memspace = 0 << 6; // Mark we're on X memory space
+
+ *am = M_DSPEA;
+ *areg = DSP_EA_ABS;
+ }
+ else
+ {
+ // Assume the worst
+ *memspace = 0 << 6; // Mark we're on X memory space
+ *am = M_DSPEA;
+ *areg = DSP_EA_ABS;
+ }
+ return OK;
+ }
+ }
+ else if (*tok == SHL) // '<<'
+ {
+ // I/O Short Addressing Mode Force Operator
+ // X:pp
+ tok++;
+ if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+ return ERROR;
+
+ // If the symbol/expression is defined then check for valid range.
+ // Otherwise the value had better fit or Fixups will bark!
+ if (*AnEXATTR & DEFINED)
+ {
+ *AnEXVAL = (LONG)(((int32_t)(((uint32_t)*AnEXVAL) << (32 - 6))) >> (32 - 6)); // Sign extend 6 to 32 bits
+ if (*AnEXVAL < 0xffffffc0)
+ return error("I/O Short Addressing Mode addresses must be between $ffc0 and $ffff");
+ }
+ *am = M_DSPPP;
+ *memspace = 0 << 6; // Mark we're on X memory space
+ *perspace = 0 << 16; // Mark we're on X peripheral space
+ *areg = *AnEXVAL & 0x3f; // Since this is only going to get used in dsp_ea_imm5...
+ return OK;
+ }
+
+ if ((*areg = checkea(0, X_ERRORS)) != ERROR)
+ {
+ // TODO: what if we need M_DSPAA here????
+ *memspace = 0 << 6; // Mark we're on X memory space
+ *am = M_DSPEA;
+ return OK;
+ }
+ else
+ return ERROR;
+
+ }
+ else if (*tok == KW_Y && *(tok + 1) == ':')
+ {
+ tok = tok + 2;
+
+ if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
+ {
+ if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+ return ERROR;
+ if (*AnEXVAL > 0xffffff)
+ return error("long address is bigger than $ffffff");
+ *memspace = 1 << 6; // Mark we're on Y memory space
+
+ // Check if value is between $ffc0 and $ffff, AKA Y:pp
+ {
+ uint32_t temp = (LONG)(((int32_t)(((uint32_t)*AnEXVAL) << (32 - 6))) >> (32 - 6)); // Sign extend 6 to 32 bits
+ if ((temp >= 0xffffffc0 /* Check for 32bit sign extended number */
+ && ((int32_t)*AnEXVAL<0)) /* Check if 32bit signed number is negative*/
+ || (*AnEXVAL<0xffff && *AnEXVAL >= 0x8000)) /* Check if 16bit number is negative*/
+ {
+ *AnEXVAL = temp;
+ *am = M_DSPPP;
+ *perspace = 1 << 16; // Mark we're on X peripheral space
+ *areg = *AnEXVAL & 0x3f; // Since this is only going to get used in dsp_ea_imm5...
+ return OK;
+ }
+
+ }
+
+ // If the symbol/expression is defined then check for valid range.
+ // Otherwise the value had better fit or Fixups will bark!
+ if (*AnEXATTR & DEFINED)
+ {
+ if (*AnEXVAL > 0x3f)
+ {
+ *am = M_DSPEA;
+ *areg = DSP_EA_ABS;
+ }
+ else
+ {
+ *am = M_DSPAA;
+ }
+ }
+ else
+ {
+ *am = M_DSPEA;
+ *areg = DSP_EA_ABS;
+ }
+
+ return OK;
+ }
+ else if (*tok == '<')
+ {
+ // Y:aa
+ // Short Addressing Mode Force Operator in the case of '<'
+ tok++;
+ if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+ return ERROR;
+
+ // If the symbol/expression is defined then check for valid range.
+ // Otherwise the value had better fit or Fixups will bark!
+ if (*AnEXATTR & DEFINED)
+ {
+ if (*AnEXVAL > 0x3f)
+ {
+ warn("short addressing mode forced but address is bigger than $3f - switching to long");
+ *am = M_DSPEA;
+ *memspace = 1 << 6; // Mark we're on Y memory space
+ *areg = DSP_EA_ABS;
+ return OK;
+ }
+ }
+ else
+ {
+ // Mark it as a fixup
+ deposit_extra_ea = DEPOSIT_EXTRA_FIXUP;
+ }
+
+ *am = M_DSPAA;
+ *memspace = 1 << 6; // Mark we're on Y memory space
+ *areg = (int)*AnEXVAL; // Since this is only going to get used in dsp_ea_imm5...
+ return OK;
+ }
+ else if (*tok == '>')
+ {
+ // Long Addressing Mode Force Operator
+ tok++;
+
+ if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
+ {
+ if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+ return ERROR;
+ if (*AnEXATTR&DEFINED)
+ {
+ if (*AnEXVAL > 0xffffff)
+ return error("long address is bigger than $ffffff");
+ *memspace = 1 << 6; // Mark we're on Y memory space
+
+ *am = M_DSPEA;
+ *areg = DSP_EA_ABS;
+ }
+ else
+ {
+ // Assume the worst
+ *memspace = 1 << 6; // Mark we're on Y memory space
+ *am = M_DSPEA;
+ *areg = DSP_EA_ABS;
+ }
+ return OK;
+ }
+ }
+ else if (*tok == SHL) // '<<'
+ {
+ // I/O Short Addressing Mode Force Operator
+ // Y:pp
+ tok++;
+ if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+ return ERROR;
+
+ // If the symbol/expression is defined then check for valid range.
+ // Otherwise the value had better fit or Fixups will bark!
+ if (*AnEXATTR & DEFINED)
+ {
+ *AnEXVAL = (LONG)(((int32_t)(((uint32_t)*AnEXVAL) << (32 - 6))) >> (32 - 6)); // Sign extend 6 to 32 bits
+ if (*AnEXVAL < 0xffffffc0)
+ return error("I/O Short Addressing Mode addresses must be between $ffe0 and $1f");
+ }
+ *am = M_DSPPP;
+ *memspace = 1 << 6; // Mark we're on Y memory space
+ *perspace = 1 << 16; // Mark we're on Y peripheral space
+ *areg = *AnEXVAL & 0x3f; // Since this is only going to get used in dsp_ea_imm5...
+ return OK;
+ }
+
+ if ((*areg = checkea(0, X_ERRORS)) != ERROR)
+ {
+ *memspace = 1 << 6; // Mark we're on Y memory space
+ *am = M_DSPEA;
+ return OK;
+ }
+ else
+ return ERROR;
+ // TODO: add absolute address checks
+
+ }
+ else if (*tok >= KW_X&&*tok <= KW_Y)
+ {
+ *am = M_INP48;
+ *areg = *tok++;
+ return OK;
+ }
+ else if (*tok >= KW_M0 && *tok <= KW_M7)
+ {
+ *am = M_DSPM;
+ *areg = (*tok++) & 7;
+ return OK;
+ }
+ else if (*tok >= KW_R0 && *tok <= KW_R7)
+ {
+ *am = M_DSPR;
+ *areg = (*tok++) - KW_R0;
+ return OK;
+ }
+ else if (*tok >= KW_N0 && *tok <= KW_N7)
+ {
+ *am = M_DSPN;
+ *areg = (*tok++) & 7;
+ return OK;
+ }
+ else if (*tok == KW_A0 || *tok == KW_A1 || *tok == KW_B0 || *tok == KW_B1)
+ {
+ *am = M_ACC24;
+ *areg = *tok++;
+ return OK;
+ }
+ else if (*tok == KW_A2 || *tok == KW_B2)
+ {
+ *am = M_ACC8;
+ *areg = *tok++;
+ return OK;
+ }
+ else if (*tok == '-' && (*(tok + 1) == KW_X0 || *(tok + 1) == KW_X1 || *(tok + 1) == KW_Y0 || *(tok + 1) == KW_Y1))
+ {
+ // '-X0', '-Y0', '-X1' or '-Y1', used in multiplications
+ tok++;
+
+ // Check to see if this is the first operand
+ if (operand != 0)
+ return error("-x0/-x1/-y0/-y1 only allowed in the first operand");
+
+ *am = M_ALU24;
+ *areg = *tok++;
+ dsp_k = 1 << 2;
+ return OK;
+ }
+ else if (*tok == '+' && (*(tok + 1) == KW_X0 || *(tok + 1) == KW_X1 || *(tok + 1) == KW_Y0 || *(tok + 1) == KW_Y1))
+ {
+ // '+X0', '+Y0', '+X1' or '+Y1', used in multiplications
+ tok++;
+
+ // Check to see if this is the first operand
+ if (operand != 0)
+ return error("+x0/+x1/+y0/+y1 only allowed in the first operand");
+
+ *am = M_ALU24;
+ *areg = *tok++;
+ dsp_k = 0 << 2;
+ return OK;
+ }
+ else if (*tok == '(' || *tok == '-')
+ {
+ // Could be either an expression or ea mode
+ if (*tok + 1 == SYMBOL)
+ {
+ tok++;
+
+ if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+ return ERROR;
+
+ *am = M_DSPIM;
+ return OK;
+ }
+ if ((*areg = checkea(0, P_ERRORS)) != ERROR)
+ {
+ *am = M_DSPEA;
+ return OK;
+ }
+ else
+ return ERROR;
+ // TODO: add absolute address checks
+ return error("internal assembler error: parmode checking for '(' and '-' does not have absolute address checks yet!");
+ }
+ else if (*tok == KW_P && *(tok + 1) == ':')
+ {
+ tok = tok + 2;
+ if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
+ {
+ // Address
+ if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+ return ERROR;
+ if (*AnEXVAL > 0xffffff)
+ return error("long address is bigger than $ffffff");
+ if (*AnEXVAL > 0x3f)
+ {
+ *am = M_DSPEA;
+ *areg = DSP_EA_ABS;
+ }
+ else
+ {
+ *areg = (int)*AnEXVAL; // Lame, but what the hell
+ *am = M_DSPAA;
+ }
+ return OK;
+ }
+ else if (*tok == '<')
+ {
+ // X:aa
+ // Short Addressing Mode Force Operator in the case of '<'
+ tok++;
+ if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+ return ERROR;
+ if (*AnEXVAL > 0x3f)
+ return error("short addressing mode forced but address is bigger than $3f");
+ *am = M_DSPAA;
+ *areg = (int)*AnEXVAL; // Since this is only going to get used in dsp_ea_imm5...
+ return OK;
+ }
+ else if (*tok == '>')
+ {
+ // Long Addressing Mode Force Operator
+ tok++;
+ // Immediate Short Addressing Mode Force Operator
+ if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+ return ERROR;
+ if (*AnEXATTR & DEFINED)
+ {
+ if (*AnEXVAL > 0xffffff)
+ return error("long address is bigger than $ffffff");
+ }
+ *am = M_DSPEA;
+ *areg = DSP_EA_ABS;
+ return OK;
+ }
+
+ if ((*areg = checkea(0, P_ERRORS)) != ERROR)
+ {
+ *am = M_DSPEA;
+ return OK;
+ }
+ else
+ return ERROR;
+
+ }
+ else if (*tok == SHL)
+ {
+ // I/O Short Addressing Mode Force Operator
+ tok++;
+ if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+ return ERROR;
+ if (*AnEXVAL > 0xfff)
+ return error("I/O short addressing mode forced but address is bigger than $fff");
+ *am = M_DSPABS06;
+ return OK;
+ }
+ else if (*tok == '<')
+ {
+ // Short Addressing Mode Force Operator
+ tok++;
+ if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+ return ERROR;
+ if (*AnEXATTR & DEFINED)
+ {
+ if (*AnEXVAL > 0xfff)
+ return error("short addressing mode forced but address is bigger than $fff");
+ }
+ *am = M_DSPABS12;
+ return OK;
+ }
+ else if (*tok == '>')
+ {
+ // Long Addressing Mode Force Operator
+ tok++;
+ // Immediate Short Addressing Mode Force Operator
+ if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+ return ERROR;
+ if (*AnEXATTR & DEFINED)
+ {
+ if (*AnEXVAL > 0xffffff)
+ return error("long address is bigger than $ffffff");
+ }
+ *am = M_DSPEA;
+ *areg = DSP_EA_ABS;
+ return OK;
+ }
+
+ else if (*tok == KW_PC || *tok == KW_CCR || *tok == KW_SR || *tok == KW_SP || (*tok >= KW_MR&&*tok <= KW_SS))
+ {
+ *areg = *tok++;
+ *am = M_DSPPCU;
+ return OK;
+ }
+ // expr
+ else
+ {
+ if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK)
+ return ERROR;
+
+ // We'll store M_DSPEA_ABS in areg and if we have
+ // any extra info, it'll go in am
+ if (*AnEXATTR & DEFINED)
+ {
+ *areg = DSP_EA_ABS;
+ if (*AnEXVAL < 0x1000)
+ *am = M_DSPABS12;
+ else if (*AnEXVAL < 0x10000)
+ *am = M_DSPABS16;
+ else if (*AnEXVAL < 0x1000000)
+ *am = M_DSPABS24;
+ else
+ return error("address must be smaller than $1000000");
+ return OK;
+ }
+ else
+ {
+ // Well, we have no opinion on the expression's size, so let's assume the worst
+ *areg = DSP_EA_ABS;
+ *am = M_DSPABS24;
+ return OK;
+ }
+ }
+ return error("internal assembler error: Please report this error message: 'reached the end of dsp_parmode' with the line of code that caused it. Thanks, and sorry for the inconvenience"); // Something bad happened
+}
+
+//
+// Parse all addressing modes except parallel moves
+//
+int dsp_amode(int maxea)
+{
+ LONG dummy;
+ // Initialize global return values
+ nmodes = dsp_a0reg = dsp_a1reg = 0;
+ dsp_am0 = dsp_am1 = M_AM_NONE;
+ dsp_a0expr[0] = dsp_a1expr[0] = ENDEXPR;
+ dsp_a0exval = 0;
+ dsp_a1exval = 0;
+ dsp_a0exattr = dsp_a1exattr = 0;
+ dsp_a0esym = dsp_a1esym = (SYM *)NULL;
+ dsp_a0memspace = dsp_a1memspace = -1;
+ dsp_a0perspace = dsp_a1perspace = -1;
+ dsp_k = 0;
+
+ // If at EOL, then no addr modes at all
+ if (*tok == EOL)
+ return 0;
+
+ if (dsp_parmode(&dsp_am0, &dsp_a0reg, dsp_a0expr, &dsp_a0exval, &dsp_a0exattr, &dsp_a0esym, &dsp_a0memspace, &dsp_a0perspace, 0) == ERROR)
+ return ERROR;
+
+
+ // If caller wants only one mode, return just one (ignore comma);
+ // If there is no second addressing mode (no comma), then return just one anyway.
+ nmodes = 1;
+
+ if (*tok != ',')
+ {
+ if (dsp_k != 0)
+ return error("-x0/-x1/-y0/-y1 only allowed in multiply operations");
+
+ return 1;
+ }
+
+ // Eat the comma
+ tok++;
+
+ // Parse second addressing mode
+ if (dsp_parmode(&dsp_am1, &dsp_a1reg, dsp_a1expr, &dsp_a1exval, &dsp_a1exattr, &dsp_a1esym, &dsp_a1memspace, &dsp_a1perspace, 1) == ERROR)
+ return ERROR;
+
+ if (maxea == 2 || *tok == EOL)
+ {
+ if (dsp_k != 0)
+ return error("-x0/-x1/-y0/-y1 only allowed in multiply operations");
+
+ nmodes = 2;
+ return 2;
+ }
+
+ if (*tok == ',')
+ {
+ // Only MAC-like or jsset/clr/tst/chg instructions here
+ tok++;
+ if (dsp_parmode(&dsp_am2, &dsp_a2reg, dsp_a2expr, &dsp_a2exval, &dsp_a2exattr, &dsp_a2esym, &dummy, &dummy, 2) == ERROR)
+ return ERROR;
+ if (maxea == 3)
+ return 3;
+ if (*tok != EOL)
+ return error(extra_stuff);
+ nmodes = 3;
+ return 3;
+
+ }
+
+ // Only Tcc instructions here, and then only those that accept 4 operands
+
+ if (dsp_parmode(&dsp_am2, &dsp_a2reg, dsp_a2expr, &dsp_a2exval, &dsp_a2exattr, &dsp_a2esym, &dummy, &dummy, 2) == ERROR)
+ return ERROR;
+
+ if (*tok++ != ',')
+ return error("expected 4 parameters");
+
+ if (dsp_parmode(&dsp_am3, &dsp_a3reg, dsp_a3expr, &dsp_a3exval, &dsp_a3exattr, &dsp_a3esym, &dummy, &dummy, 3) == ERROR)
+ return ERROR;
+
+ if (*tok == EOL)
+ {
+ if (dsp_k != 0)
+ return error("-x0/-x1/-y0/-y1 only allowed in multiply operations");
+
+ nmodes = 4;
+ return 4;
+ }
+ else
+ {
+ // Tcc instructions do not support parallel moves, so any remaining tokens are garbage
+ return error(extra_stuff);
+ }
+
+ return error("internal assembler error: Please report this error message: 'reached the end of dsp_amode' with the line of code that caused it. Thanks, and sorry for the inconvenience"); //Something bad happened
+
+}
+
+
+//
+// Helper function which gives us the encoding of a DSP register
+//
+static inline int SDreg(int reg)
+{
+ if (reg >= KW_X0 && reg <= KW_N7)
+ return reg & 0xff;
+ else if (reg >= KW_A0&® <= KW_A2)
+ return (8 >> (reg & 7)) | 8;
+ else //if (reg>=KW_R0&®<=KW_R7)
+ return reg - KW_R0 + 16;
+ // Handy map for the above:
+ // (values are of course taken from keytab)
+ // Register | Value | Return value
+ // x0 | 260 | 4
+ // x1 | 261 | 5
+ // y0 | 262 | 6
+ // y1 | 263 | 7
+ // b0 | 265 | 8
+ // b2 | 267 | 9
+ // b1 | 269 | 10
+ // a | 270 | 14
+ // b | 271 | 15
+ // n0 | 280 | 24
+ // n1 | 281 | 25
+ // n2 | 282 | 26
+ // n3 | 283 | 27
+ // n4 | 284 | 28
+ // n5 | 285 | 29
+ // n6 | 286 | 30
+ // n7 | 287 | 31
+ // a0 | 136 | 0
+ // a1 | 137 | 1
+ // a2 | 138 | 2
+ // r0 | 151 | 16
+ // r1 | 152 | 17
+ // r2 | 153 | 18
+ // r3 | 154 | 19
+ // r4 | 155 | 20
+ // r5 | 156 | 21
+ // r6 | 157 | 22
+ // r7 | 158 | 23
+}
+
+
+//
+// Check for X:Y: parallel mode syntax
+//
+static inline LONG check_x_y(LONG ea1, LONG S1)
+{
+ LONG inst;
+ LONG eax_temp, eay_temp;
+ LONG D1, D2, S2, ea2;
+ LONG K_D1, K_D2;
+ LONG w = 1 << 7; // S1=0, D1=1<<14
+ if ((ea1 & 0x38) == DSP_EA_POSTINC || (ea1 & 0x38) == DSP_EA_POSTINC1 ||
+ (ea1 & 0x38) == DSP_EA_POSTDEC1 || (ea1 & 0x38) == DSP_EA_NOUPD)
+ {
+
+ switch (ea1 & 0x38)
+ {
+ case DSP_EA_POSTINC: ea1 = (ea1&(~0x38)) | 0x8;break;
+ case DSP_EA_POSTINC1: ea1 = (ea1&(~0x38)) | 0x18;break;
+ case DSP_EA_POSTDEC1: ea1 = (ea1&(~0x38)) | 0x10;break;
+ case DSP_EA_NOUPD: ea1 = (ea1&(~0x38)) | 0x00;break;
+ }
+
+ if (S1 == 0)
+ {
+ // 'X:eax,D1 Y:eay,D2', 'X:eax,D1 S2,Y:eay'
+ // Check for D1
+ switch (K_D1 = *tok++)
+ {
+ case KW_X0: D1 = 0 << 10; break;
+ case KW_X1: D1 = 1 << 10; break;
+ case KW_A: D1 = 2 << 10; break;
+ case KW_B: D1 = 3 << 10; break;
+ default: return error("unrecognised X:Y: parallel move syntax: expected x0, x1, a or b after 'X:eax,'");
+ }
+ }
+ else
+ {
+ // 'S1,X:eax Y:eay,D2' 'S1,X:eax S2,Y:eay'
+ w = 0;
+ switch (S1)
+ {
+ case 4: D1 = 0 << 10; break;
+ case 5: D1 = 1 << 10; break;
+ case 14: D1 = 2 << 10; break;
+ case 15: D1 = 3 << 10; break;
+ default: return error("unrecognised X:Y: parallel move syntax: S1 can only be x0, x1, a or b in 'S1,X:eax'");
+ }
+ }
+
+ if (*tok == KW_Y)
+ {
+ tok++;
+ // 'X:eax,D1 Y:eay,D2' 'S1,X:eax Y:eay,D2'
+ if (*tok++ != ':')
+ return error("unrecognised X:Y: parallel move syntax: expected ':' after 'X:ea,D1/S1,X:ea Y'");
+ if (*tok++ == '(')
+ {
+ if (*tok >= KW_R0 && *tok <= KW_R7)
+ {
+ ea2 = (*tok++ - KW_R0);
+ if (((ea1 & 7) < 4 && ea2 < 4) || ((ea1 & 7) >= 4 && ea2 > 4))
+ return error("unrecognised X:Y: parallel move syntax: eax and eay register banks must be different in 'X:ea,D1/S1,X:ea Y:eay,D2'");
+ }
+ else
+ return error("unrecognised X:Y: parallel move syntax: expected 'Rn' after 'X:ea,D1/S1,X:ea Y:('");
+ // If eax register is r0-r3 then eay register is r4-r7.
+ // Encode that to 2 bits (i.e. eay value is 0-3)
+ eax_temp = (ea2 & 3) << 5; // Store register temporarily
+ if (*tok++ != ')')
+ return error("unrecognised X:Y: parallel move syntax: expected ')' after 'X:ea,D1/S1,X:ea Y:(Rn'");
+ if (*tok == '+')
+ {
+ tok++;
+ if (*tok == ',')
+ {
+ // (Rn)+
+ ea2 = 3 << 12;
+ tok++;
+ }
+ else if (*tok >= KW_N0 && *tok <= KW_N7)
+ {
+ // (Rn)+Nn
+ if ((*tok++ & 7) != ea2)
+ return error("unrecognised X:Y: parallel move syntax(Same register number expected for Rn, Nn in 'X:ea,D1/S1,X:ea Y:(Rn)+Nn,D')");
+ ea2 = 1 << 12;
+ if (*tok++ != ',')
+ return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea Y:(Rn)+Nn'");
+ }
+ else
+ return error("unrecognised X:Y: parallel move syntax: expected ',' or 'Nn' after 'X:ea,D1/S1,X:ea Y:(Rn)+'");
+
+ }
+ else if (*tok == '-')
+ {
+ // (Rn)-
+ ea2 = 2 << 12;
+ tok++;
+ if (*tok++ != ',')
+ return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea Y:(Rn)-'");
+ }
+ else if (*tok++ == ',')
+ {
+ // (Rn)
+ ea2 = 0 << 12;
+ }
+ else
+ return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea Y:eay'");
+
+ ea2 |= eax_temp; // OR eay back from temp
+
+ switch (K_D2 = *tok++)
+ {
+ case KW_Y0: D2 = 0 << 8; break;
+ case KW_Y1: D2 = 1 << 8; break;
+ case KW_A: D2 = 2 << 8; break;
+ case KW_B: D2 = 3 << 8; break;
+ default: return error("unrecognised X:Y: parallel move syntax: expected y0, y1, a or b after 'X:ea,D1/S1,X:ea Y:eay,'");
+ }
+
+ if (*tok != EOL)
+ return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea Y:eay,D'");
+
+ if (S1 == 0)
+ if (K_D1 == K_D2)
+ return error("unrecognised X:Y: parallel move syntax: D1 and D2 cannot be the same in 'X:ea,D1 Y:eay,D2'");
+
+ inst = B16(11000000, 00000000) | w;
+ inst |= ea1 | D1 | ea2 | D2;
+ return inst;
+ }
+ else
+ return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' after 'X:ea,D1/S1,X:ea Y:'");
+ }
+ else if (*tok == KW_Y0 || *tok == KW_Y1 || *tok == KW_A || *tok == KW_B)
+ {
+ // 'X:eax,D1 S2,Y:eay' 'S1,X:eax1 S2,Y:eay'
+ switch (*tok++)
+ {
+ case KW_Y0: S2 = 0 << 8; break;
+ case KW_Y1: S2 = 1 << 8; break;
+ case KW_A: S2 = 2 << 8; break;
+ case KW_B: S2 = 3 << 8; break;
+ default: return error("unrecognised X:Y: parallel move syntax: expected y0, y1, a or b after 'X:ea,D1/S1,X:ea Y:eay,'");
+ }
+
+ if (*tok++ != ',')
+ return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea S2'");
+
+ if (*tok++ == KW_Y)
+ {
+ // 'X:eax,D1 Y:eay,D2' 'S1,X:eax Y:eay,D2'
+ if (*tok++ != ':')
+ return error("unrecognised X:Y: parallel move syntax: expected ':' after 'X:ea,D1/S1,X:ea Y'");
+ if (*tok++ == '(')
+ {
+ if (*tok >= KW_R0 && *tok <= KW_R7)
+ {
+ ea2 = (*tok++ - KW_R0);
+ if (((ea1 & 7) < 4 && ea2 < 4) || ((ea1 & 7) >= 4 && ea2 > 4))
+ return error("unrecognised X:Y: parallel move syntax: eax and eay register banks must be different in 'X:ea,D1/S1,X:ea S2,Y:eay'");
+ }
+ else
+ return error("unrecognised X:Y: parallel move syntax: expected 'Rn' after 'X:ea,D1/S1,X:ea S2,Y:('");
+ // If eax register is r0-r3 then eay register is r4-r7.
+ // Encode that to 2 bits (i.e. eay value is 0-3)
+ eay_temp = (ea2 & 3) << 5; //Store register temporarily
+ if (*tok++ != ')')
+ return error("unrecognised X:Y: parallel move syntax: expected ')' after 'X:ea,D1/S1,X:ea S2,Y:(Rn'");
+ if (*tok == '+')
+ {
+ tok++;
+ if (*tok == EOL)
+ // (Rn)+
+ ea2 = 3 << 12;
+ else if (*tok >= KW_N0 && *tok <= KW_N7)
+ {
+ // (Rn)+Nn
+ if ((*tok++ & 7) != ea2)
+ return error("unrecognised X:Y: parallel move syntax(Same register number expected for Rn, Nn in 'X:ea,D1/S1,X:ea S2,Y:(Rn)+Nn')");
+ ea2 = 1 << 12;
+ if (*tok != EOL)
+ return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea S2,Y:(Rn)+Nn'");
+ }
+ else
+ return error("unrecognised X:Y: parallel move syntax: expected ',' or 'Nn' after 'X:ea,D1/S1,X:ea S2,Y:(Rn)+'");
+
+ }
+ else if (*tok == '-')
+ {
+ // (Rn)-
+ ea2 = 2 << 12;
+ tok++;
+ if (*tok != EOL)
+ return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea S2,Y:(Rn)-'");
+ }
+ else if (*tok == EOL)
+ {
+ // (Rn)
+ ea2 = 0 << 12;
+ }
+ else
+ return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea S2,Y:eay'");
+
+ ea2 |= eay_temp; //OR eay back from temp
+
+ inst = B16(10000000, 00000000) | w;
+ inst |= (ea1 & 0x1f) | D1 | S2 | ea2;
+ return inst;
+ }
+ else
+ return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' after 'X:ea,D1/S1,X:ea Y:'");
+
+ }
+ else
+ return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' in 'X:ea,D1/S1,X:ea'");
+ }
+ else
+ return error("unrecognised X:Y: or X:R parallel move syntax: expected Y:, A or B after 'X:ea,D1/S1,X:ea S2,'");
+
+
+ }
+ return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' in 'X:ea,D1/S1,X:ea'");
+}
+
+//
+// Parse X: addressing space parallel moves
+//
+static inline LONG parse_x(const int W, LONG inst, const LONG S1, const int check_for_x_y)
+{
+ int immreg; // Immediate register destination
+ LONG S2, D1, D2; // Source and Destinations
+ LONG ea1; // ea bitfields
+ uint32_t termchar = ','; // Termination character for ea checks
+ int force_imm = NUM_NORMAL; // Holds forced immediate value (i.e. '<' or '>')
+ ea1 = -1; // initialise e1 (useful for some code paths)
+ if (W == 0)
+ termchar = EOL;
+ if (*tok == '-')
+ {
+ if (tok[1] == CONST || tok[1] == FCONST)
+ {
+ tok++;
+ dspImmedEXVAL = *tok++;
+ goto x_check_immed;
+ }
+ // This could be either -(Rn), -aa or -ea. Check for immediate first
+ if (tok[1] == SYMBOL)
+ {
+ if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) == OK)
+ {
+ if (S1 != 0)
+ {
+ x_checkea_right:
+
+ // 'S1,X:ea S2,D2', 'A,X:ea X0,A', 'B,X:ea X0,B', 'S1,X:eax Y:eay,D2', 'S1,X:eax S2,Y:eay'
+ if (*tok == KW_X0 && tok[1] == ',' && tok[2] == KW_A)
+ {
+ // 'A,X:ea X0,A'
+ if (ea1 == DSP_EA_ABS)
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+ if (S1 != 14)
+ return error("unrecognised X:R parallel move syntax: S1 can only be a in 'a,X:ea x0,a'");
+ if (ea1 == -1)
+ return error("unrecognised X:R parallel move syntax: absolute address not allowed in 'a,X:ea x0,a'");
+ if (ea1 == B8(00110100))
+ return error("unrecognised X:R parallel move syntax: immediate data not allowed in 'a,X:ea x0,a'");
+ inst = B16(00001000, 00000000) | ea1 | (0 << 8);
+ return inst;
+ }
+ else if (*tok == KW_X0 && tok[1] == ',' && tok[2] == KW_B)
+ {
+ // 'B,X:ea X0,B'
+ if (ea1 == DSP_EA_ABS)
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+ if (S1 != 15)
+ return error("unrecognised X:R parallel move syntax: S1 can only be b in 'b,X:ea x0,b'");
+ if (ea1 == -1)
+ return error("unrecognised X:R parallel move syntax: absolute address not allowed in 'b,X:ea x0,b'");
+ if (ea1 == B8(00110100))
+ return error("unrecognised X:R parallel move syntax: immediate data not allowed in 'b,X:ea x0,b'");
+ inst = B16(00001001, 00000000) | ea1 | (1 << 8);
+ return inst;
+ }
+ else if (*tok == KW_A || *tok == KW_B)
+ {
+ // 'S1,X:ea S2,D2', 'S1,X:eax S2,Y:eay'
+
+ switch (S1)
+ {
+ case 4: D1 = 0 << 10; break;
+ case 5: D1 = 1 << 10; break;
+ case 14: D1 = 2 << 10; break;
+ case 15: D1 = 3 << 10; break;
+ default: return error("unrecognised X:R parallel move syntax: S1 can only be x0, x1, a or b in 'S1,X:ea S2,D2'");
+ }
+
+ if (tok[1] == ',' && tok[2] == KW_Y)
+ {
+ // 'S1,X:eax S2,Y:eay'
+ return check_x_y(ea1, S1);
+ }
+
+ // 'S1,X:ea S2,D2'
+ if (ea1 == DSP_EA_ABS)
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+
+ switch (*tok++)
+ {
+ case KW_A: S2 = 0 << 9; break;
+ case KW_B: S2 = 1 << 9; break;
+ default: return error("unrecognised X:R parallel move syntax: expected a or b after 'S1,X:eax'");
+ }
+ if (*tok++ != ',')
+ return error("unrecognised X:R parallel move syntax: expected ',' after 'S1,X:eax S2'");
+
+ if (*tok == KW_Y0 || *tok == KW_Y1)
+ {
+ if (*tok++ == KW_Y0)
+ D2 = 0 << 8;
+ else
+ D2 = 1 << 8;
+
+ if (*tok != EOL)
+ return error("unrecognised X:R parallel move syntax: unexpected text after 'X:eax,D1 S2,S2'");
+
+ inst = B16(00010000, 00000000) | (0 << 7);
+ inst |= ea1 | D1 | S2 | D2;
+ return inst;
+ }
+ else
+ return error("unrecognised X:R parallel move syntax: expected y0 or y1 after 'X:eax,D1 S2,'");
+
+ }
+ else if (*tok == KW_Y)
+ {
+ // 'S1,X:eax Y:eay,D2'
+ return check_x_y(ea1, S1);
+ }
+ else if (*tok == KW_Y0 || *tok == KW_Y1)
+ {
+ // 'S1,X:eax S2,Y:eay'
+ return check_x_y(ea1, S1);
+ }
+ else
+ return error("unrecognised X:Y or X:R parallel move syntax: expected y0 or y1 after 'X:eax,D1/X:ea,D1");
+ }
+ else
+ {
+ // Only check for aa if we have a defined number in our hands or we've
+ // been asked to use a short number format. The former case we'll just test
+ // it to see if it's small enough. The later - it's the programmer's call
+ // so he'd better have a small address or the fixups will bite him/her in the arse!
+ if (dspImmedEXATTR&DEFINED || force_imm == NUM_FORCE_SHORT)
+ {
+
+ // It's an immediate, so ea or eax is probably an absolute address
+ // (unless it's aa if the immediate is small enough)
+ // 'X:ea,D' or 'X:aa,D' or 'X:ea,D1 S2,D2' or 'X:eax,D1 Y:eay,D2' or 'X:eax,D1 S2,Y:eay'
+ x_check_immed:
+ // Check for aa (which is 6 bits zero extended)
+ if (dspImmedEXVAL < 0x40 && force_imm != NUM_FORCE_LONG)
+ {
+ if (W == 1)
+ {
+ // It might be X:aa but we're not 100% sure yet.
+ // If it is, the only possible syntax here is 'X:aa,D'.
+ // So check ahead to see if EOL follows D, then we're good to go.
+ if (*tok == ',' && ((*(tok + 1) >= KW_X0 && *(tok + 1) <= KW_N7) || (*(tok + 1) >= KW_R0 && *(tok + 1) <= KW_R7) || (*(tok + 1) >= KW_A0 && *(tok + 1) <= KW_A2)) && *(tok + 2) == EOL)
+ {
+ // Yup, we're good to go - 'X:aa,D' it is
+ tok++;
+ immreg = SDreg(*tok++);
+ inst = inst | (uint32_t)dspImmedEXVAL;
+ inst |= ((immreg & 0x18) << (12 - 3)) + ((immreg & 7) << 8);
+ inst |= 1 << 7; // W
+ return inst;
+ }
+ }
+ else
+ {
+ if (*tok == EOL)
+ {
+ // 'S,X:aa'
+ inst = inst | (uint32_t)dspImmedEXVAL;
+ inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8);
+ return inst;
+ }
+ else
+ {
+ // 'S1,X:ea S2,D2', 'A,X:ea X0,A', 'B,X:ea X0,B',
+ // 'S1,X:eax Y:eay,D2', 'S1,X:eax S2,Y:eay'
+ ea1 = DSP_EA_ABS;
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+ goto x_checkea_right;
+ }
+ }
+ }
+ }
+
+ // Well, that settles it - we do have an ea in our hands
+ if (W == 1)
+ {
+ // 'X:ea,D' [... S2,d2]
+ if (*tok++ != ',')
+ return error("unrecognised X: parallel move syntax: expected ',' after 'X:ea'");
+ if ((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2))
+ {
+ D1 = SDreg(*tok++);
+ if (*tok == EOL)
+ {
+ // 'X:ea,D'
+ inst = inst | B8(01000000) | (1 << 7);
+ inst |= ((D1 & 0x18) << (12 - 3)) + ((D1 & 7) << 8);
+ inst |= ea1;
+ if (ea1 == DSP_EA_ABS)
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+ return inst;
+ }
+ else
+ {
+ // 'X:ea,D1 S2,D2'
+ if (*tok == KW_A || *tok == KW_B)
+ {
+ S2 = SDreg(*tok++);
+ if (*tok++ != ',')
+ return error("unrecognised X:R parallel move syntax: expected comma after X:ea,D1 S2");
+ if (*tok == KW_Y0 || *tok == KW_Y1)
+ {
+ D2 = SDreg(*tok++);
+ if (*tok != EOL)
+ return error("unrecognised X:R parallel move syntax: expected EOL after X:ea,D1 S2,D2");
+ inst = B16(00010000, 00000000) | (1 << 7);
+ inst |= ((D1 & 0x8) << (12 - 4)) + ((D1 & 1) << 10);
+ inst |= (S2 & 1) << 9;
+ inst |= (D2 & 1) << 8;
+ inst |= ea1;
+ return inst;
+ }
+ else
+ return error("unrecognised X:R parallel move syntax: expected y0,y1 after X:ea,D1 S2,");
+ }
+ else
+ return error("unrecognised X:R parallel move syntax: expected a,b after X:ea,D1");
+ }
+ }
+ else
+ return error("unrecognised X: parallel move syntax: expected x0,x1,y0,y1,a0,b0,a2,b2,a1,b1,a,b,r0-r7,n0-n7 after 'X:ea,'");
+ }
+ else
+ {
+ if (*tok == EOL)
+ {
+ // 'S,X:ea'
+ inst = inst | B8(01000000) | (0 << 7);
+ inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8);
+ inst |= ea1;
+ if (ea1 == DSP_EA_ABS)
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+ return inst;
+ }
+ else
+ {
+ // 'S1,X:ea S2,D2', 'A,X:ea X0,A', 'B,X:ea X0,B',
+ // 'S1,X:eax Y:eay,D2', 'S1,X:eax S2,Y:eay'
+ goto x_checkea_right;
+ }
+ }
+
+ }
+ }
+ }
+ else
+ {
+ // It's not an immediate, check for '-(Rn)'
+ ea1 = checkea(termchar, X_ERRORS);
+
+ if (ea1 == ERROR)
+ return ERROR;
+
+ goto x_gotea1;
+
+ }
+ }
+ else if (*tok == '#')
+ {
+ tok++;
+ if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+ return ERROR;
+ // Okay so we have immediate data - mark it down
+ ea1 = DSP_EA_IMM;
+ // Now, proceed to the main code for this branch
+ goto x_gotea1;
+ }
+ else if (*tok == '(')
+ {
+ // Maybe we got an expression here, check for it
+ if (tok[1] == CONST || tok[1] == FCONST || tok[1] == SUNARY || tok[1] == SYMBOL || tok[1] == STRING)
+ {
+ // Evaluate the expression and go to immediate code path
+ expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM);
+ goto x_check_immed;
+ }
+
+ // Nope, let's check for ea then
+ ea1 = checkea(termchar, X_ERRORS);
+ if (ea1 == ERROR)
+ return ERROR;
+
+ x_gotea1:
+ if (W == 1)
+ {
+ if (*tok++ != ',')
+ return error("Comma expected after 'X:(Rn)')");
+
+ // It might be 'X:(Rn..)..,D' but we're not 100% sure yet.
+ // If it is, the only possible syntax here is 'X:ea,D'.
+ // So check ahead to see if EOL follows D, then we're good to go.
+ if (((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2)) && *(tok + 1) == EOL)
+ {
+ //'X:ea,D'
+ D1 = SDreg(*tok++);
+
+ inst = inst | B8(01000000) | (1 << 7);
+ inst |= ea1;
+ inst |= ((D1 & 0x18) << (12 - 3)) + ((D1 & 7) << 8);
+ return inst;
+ }
+ }
+ else
+ {
+ if (*tok == EOL)
+ {
+ //'S,X:ea'
+ inst = inst | B8(01000000) | (0 << 7);
+ inst |= ea1;
+ inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8);
+ return inst;
+ }
+ else
+ {
+ goto x_checkea_right;
+ }
+ }
+ // 'X:eax,D1 Y:eay,D2', 'X:eax,D1 S2,Y:eay' or 'X:ea,D1 S2,D2'
+ // Check ahead for S2,D2 - if that's true then we have 'X:ea,D1 S2,D2'
+ if ((*tok == KW_X0 || *tok == KW_X1 || *tok == KW_A || *tok == KW_B) && (*(tok + 1) == KW_A || *(tok + 1) == KW_B) && (*(tok + 2) == ',') && (*(tok + 3) == KW_Y0 || (*(tok + 3) == KW_Y1)))
+ {
+ // 'X:ea,D1 S2,D2'
+ // Check if D1 is x0, x1, a or b
+ switch (*tok++)
+ {
+ case KW_X0: D1 = 0 << 10; break;
+ case KW_X1: D1 = 1 << 10; break;
+ case KW_A: D1 = 2 << 10; break;
+ case KW_B: D1 = 3 << 10; break;
+ default: return error("unrecognised X:R parallel move syntax: expected x0, x1, a or b after 'X:eax,'");
+ }
+
+ switch (*tok++)
+ {
+ case KW_A: S2 = 0 << 9; break;
+ case KW_B: S2 = 1 << 9; break;
+ default: return error("unrecognised X:R parallel move syntax: expected a or b after 'X:eax,D1 '");
+ }
+
+ if (*tok++ != ',')
+ return error("unrecognised X:R parallel move syntax: expected ',' after 'X:eax,D1 S2'");
+
+ if (*tok == KW_Y0 || *tok == KW_Y1)
+ {
+ if (*tok++ == KW_Y0)
+ D2 = 0 << 8;
+ else
+ D2 = 1 << 8;
+
+ if (*tok != EOL)
+ return error("unrecognised X:R parallel move syntax: unexpected text after 'X:eax,D1 S2,S2'");
+
+ inst = B16(00010000, 00000000) | (W << 7);
+ inst |= ea1 | D1 | S2 | D2;
+ return inst;
+ }
+ else
+ return error("unrecognised X:R parallel move syntax: expected y0 or y1 after 'X:eax,D1 S2,'");
+
+ }
+
+ // Check to see if we got eax (which is a subset of ea)
+ if (check_for_x_y)
+ {
+ if ((inst = check_x_y(ea1, 0)) != 0)
+ return inst;
+ else
+ {
+ // Rewind pointer as it might be an expression and check for it
+ tok--;
+ if (expr(dspaaEXPR, &dspaaEXVAL, &dspaaEXATTR, &dspaaESYM) != OK)
+ return ERROR;
+ // Yes, we have an expression, so we now check for
+ // 'X:ea,D' or 'X:aa,D' or 'X:ea,D1 S2,D2' or 'X:eax,D1 Y:eay,D2' or 'X:eax,D1 S2,Y:eay'
+ goto x_check_immed;
+ }
+ }
+ }
+ else if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
+ {
+ // Check for immediate address
+ if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+ return ERROR;
+
+ // We set ea1 here - if it's aa instead of ea
+ // then it won't be used anyway
+ ea1 = DSP_EA_ABS;
+ if (!(dspImmedEXATTR&DEFINED))
+ {
+ force_imm = NUM_FORCE_LONG;
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+ }
+
+ goto x_check_immed;
+ }
+ else if (*tok == '>')
+ {
+ // Check for immediate address forced long
+ tok++;
+ if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+ return ERROR;
+ if (dspImmedEXATTR & DEFINED)
+ if (dspImmedEXVAL > 0xffffff)
+ return error("long address is bigger than $ffffff");
+
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+
+ force_imm = NUM_FORCE_LONG;
+ ea1 = DSP_EA_ABS;
+ goto x_check_immed;
+ }
+ else if (*tok == '<')
+ {
+ // Check for immediate address forced short
+ tok++;
+ if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+ return ERROR;
+ force_imm = NUM_FORCE_SHORT;
+ if (dspImmedEXATTR & DEFINED)
+ {
+ if (dspImmedEXVAL > 0x3f)
+ {
+ warn("short addressing mode forced but address is bigger than $3f - switching to long");
+ force_imm = NUM_FORCE_LONG;
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+ ea1 = DSP_EA_ABS;
+ }
+ }
+ else
+ {
+ // This might end up as something like 'move Y:<adr,register'
+ // so let's mark it as an extra aa fixup here.
+ // Note: we are branching to x_check_immed without a
+ // defined dspImmed so it's going to be 0. It probably
+ // doesn't harm anything.
+ deposit_extra_ea = DEPOSIT_EXTRA_FIXUP;
+ }
+
+ goto x_check_immed;
+ }
+ return error("unknown x: addressing mode");
+}
+
+
+//
+// Parse Y: addressing space parallel moves
+//
+static inline LONG parse_y(LONG inst, LONG S1, LONG D1, LONG S2)
+{
+ int immreg; // Immediate register destination
+ LONG D2; // Destination
+ LONG ea1; // ea bitfields
+ int force_imm = NUM_NORMAL; // Holds forced immediate value (i.e. '<' or '>')
+ if (*tok == '-')
+ {
+ if (tok[1] == CONST || tok[1] == FCONST)
+ {
+ tok++;
+ dspImmedEXVAL = *tok++;
+ goto y_check_immed;
+ }
+ // This could be either -(Rn), -aa or -ea. Check for immediate first
+ if (*tok == SYMBOL || tok[1] == SYMBOL)
+ {
+ if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) == OK)
+ {
+ // Only check for aa if we have a defined number in our hands or we've
+ // been asked to use a short number format. The former case we'll just test
+ // it to see if it's small enough. The later - it's the programmer's call
+ // so he'd better have a small address or the fixups will bite him/her in the arse!
+ if (dspImmedEXATTR&DEFINED || force_imm == NUM_FORCE_SHORT)
+ {
+ // It's an immediate, so ea is probably an absolute address
+ // (unless it's aa if the immediate is small enough)
+ // 'Y:ea,D', 'Y:aa,D', 'S,Y:ea' or 'S,Y:aa'
+ y_check_immed:
+ // Check for aa (which is 6 bits zero extended)
+ if (dspImmedEXVAL < 0x40 && force_imm != NUM_FORCE_LONG)
+ {
+ // It might be Y:aa but we're not 100% sure yet.
+ // If it is, the only possible syntax here is 'Y:aa,D'/'S,Y:aa'.
+ // So check ahead to see if EOL follows D, then we're good to go.
+ if (*tok == EOL && S1 != 0)
+ {
+ // 'S,Y:aa'
+ inst = B16(01001000, 00000000);
+ inst |= dspImmedEXVAL;
+ inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8);
+ return inst;
+ }
+ if (*tok == ',' && ((*(tok + 1) >= KW_X0 && *(tok + 1) <= KW_N7) || (*(tok + 1) >= KW_R0 && *(tok + 1) <= KW_R7) || (*(tok + 1) >= KW_A0 && *(tok + 1) <= KW_A2)) && *(tok + 2) == EOL)
+ {
+ // Yup, we're good to go - 'Y:aa,D' it is
+ tok++;
+ immreg = SDreg(*tok++);
+ inst |= dspImmedEXVAL;
+ inst |= ((immreg & 0x18) << (12 - 3)) + ((immreg & 7) << 8);
+ return inst;
+ }
+ }
+ }
+ // Well, that settles it - we do have a ea in our hands
+ if (*tok == EOL && S1 != 0)
+ {
+ // 'S,Y:ea'
+ inst = B16(01001000, 01110000);
+ inst |= ea1;
+ inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8);
+ if (ea1 == DSP_EA_ABS)
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+ return inst;
+ }
+ if (*tok++ != ',')
+ return error("unrecognised Y: parallel move syntax: expected ',' after 'Y:ea'");
+ if (D1 == 0 && S1 == 0)
+ {
+ // 'Y:ea,D'
+ if ((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2))
+ {
+ D1 = SDreg(*tok++);
+ if (*tok != EOL)
+ return error("unrecognised Y: parallel move syntax: expected EOL after 'Y:ea,D'");
+ inst |= B16(00000000, 01110000);
+ inst |= ea1;
+ inst |= ((D1 & 0x18) << (12 - 3)) + ((D1 & 7) << 8);
+ if (ea1 == DSP_EA_ABS)
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+ return inst;
+ }
+ else
+ 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,'");
+ }
+ else
+ {
+ // 'S1,D1 Y:ea,D2'
+ if (*tok == KW_A || *tok == KW_B || *tok == KW_Y0 || *tok == KW_Y1)
+ {
+ D2 = SDreg(*tok++);
+ inst |= ea1;
+ inst |= 1 << 7;
+ inst |= (S1 & 1) << 11;
+ inst |= (D1 & 1) << 10;
+ inst |= (D2 & 8) << (9 - 3);
+ inst |= (D2 & 1) << 8;
+ return inst;
+ }
+ else
+ return error("unrecognised R:Y: parallel move syntax: expected a,b after 'S1,D1 Y:ea,'");
+ }
+ }
+ else
+ return ERROR;
+ }
+ else
+ {
+ // It's not an immediate, check for '-(Rn)'
+ ea1 = checkea(',', Y_ERRORS);
+
+ if (ea1 == ERROR)
+ return ERROR;
+
+ goto y_gotea1;
+
+ }
+ }
+ else if (*tok == '#')
+ {
+ tok++;
+ if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+ return ERROR;
+ // Okay so we have immediate data - mark it down
+ ea1 = DSP_EA_IMM;
+ // Now, proceed to the main code for this branch
+ goto y_gotea1;
+ }
+ else if (*tok == '(')
+ {
+ // Maybe we got an expression here, check for it
+ if (tok[1] == CONST || tok[1] == FCONST || tok[1] == SUNARY || tok[1] == SYMBOL || tok[1] == STRING)
+ {
+ // Evaluate the expression and go to immediate code path
+ expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM);
+ goto y_check_immed;
+ }
+
+ // Nope, let's check for ea then
+ if (S1 == 0 || (S1 != 0 && D1 != 0))
+ ea1 = checkea(',', Y_ERRORS);
+ else
+ ea1 = checkea(EOL, Y_ERRORS);
+
+ if (ea1 == ERROR)
+ return ERROR;
+
+ y_gotea1:
+ if (S1 != 0 && *tok == EOL)
+ {
+ // 'S,Y:ea'
+ inst = B16(01001000, 01000000);
+ inst |= ea1;
+ inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8);
+ return inst;
+ }
+ else if (S1 != 0 && D1 != 0 && S2 == 0)
+ {
+ // 'S1,D1 Y:ea,D2'
+ switch (S1)
+ {
+ case 14: S1 = 0 << 11; break; // A
+ case 15: S1 = 1 << 11; break; // B
+ default: return error("unrecognised R:Y parallel move syntax: S1 can only be A or B in 'S1,D1 Y:ea,D2'"); break;
+ }
+ switch (D1)
+ {
+ case 4: D1 = 0 << 10; break; // X0
+ case 5: D1 = 1 << 10; break; // X1
+ default: return error("unrecognised R:Y parallel move syntax: D1 can only be x0 or x1 in 'S1,D1 Y:ea,D2'");break;
+ }
+ if (*tok++ != ',')
+ return error("unrecognised R:Y parallel move syntax: expected ',' after 'S1,D1 Y:ea'");
+ switch (*tok++)
+ {
+ case KW_Y0: D2 = 0 << 8; break;
+ case KW_Y1: D2 = 1 << 8; break;
+ case KW_A: D2 = 2 << 8; break;
+ case KW_B: D2 = 3 << 8; break;
+ default: return error("unrecognised R:Y parallel move syntax: D2 can only be y0, y1, a or b after 'S1,D1 Y:ea'");
+ }
+ inst = B16(00010000, 11000000);
+ inst |= S1 | D1 | D2;
+ inst |= ea1;
+ return inst;
+ }
+ if (*tok++ != ',')
+ return error("Comma expected after 'Y:(Rn)')");
+ // It might be 'Y:(Rn..)..,D' but we're not 100% sure yet.
+ // If it is, the only possible syntax here is 'Y:ea,D'.
+ // So check ahead to see if EOL follows D, then we're good to go.
+ if (((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2)) && *(tok + 1) == EOL)
+ {
+ //'Y:ea,D'
+ D1 = SDreg(*tok++);
+ inst |= B16(00000000, 01000000);
+ inst |= ea1;
+ inst |= ((D1 & 0x18) << (12 - 3)) + ((D1 & 7) << 8);
+ return inst;
+ }
+ }
+ else if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
+ {
+ // Check for immediate address
+ if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+ return ERROR;
+
+ // Yes, we have an expression, so we now check for
+ // 'Y:ea,D' or 'Y:aa,D'
+ ea1 = DSP_EA_ABS; // Reluctant - but it's probably correct
+ if (!(dspImmedEXATTR&DEFINED))
+ {
+ force_imm = NUM_FORCE_LONG;
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+ }
+
+ goto y_check_immed;
+ }
+ else if (*tok == '>')
+ {
+ // Check for immediate address forced long
+ tok++;
+ if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+ return ERROR;
+ if (dspImmedEXATTR & DEFINED)
+ if (dspImmedEXVAL > 0xffffff)
+ return error("long address is bigger than $ffffff");
+
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+
+ force_imm = NUM_FORCE_LONG;
+ ea1 = DSP_EA_ABS;
+ goto y_check_immed;
+ }
+ else if (*tok == '<')
+ {
+ tok++;
+ if (S1 != 0 && D1 != 0)
+ {
+ // We're in 'S1,D1 Y:ea,D2' or 'S1,D1 S1,Y:ea'
+ // there's no Y:aa mode here, so we'll force long
+ warn("forced short addressing in R:Y mode is not allowed - switching to long");
+
+ if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+ return ERROR;
+
+ ea1 = DSP_EA_ABS;
+
+ force_imm = NUM_FORCE_LONG;
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+ goto y_check_immed;
+ }
+ else
+ {
+ // Check for immediate address forced short
+ ea1 = DSP_EA_ABS; // Reluctant - but it's probably correct
+
+ if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+ return ERROR;
+ force_imm = NUM_FORCE_SHORT;
+ if (dspImmedEXATTR & DEFINED)
+ {
+ if (dspImmedEXVAL > 0xfff)
+ {
+ warn("short addressing mode forced but address is bigger than $fff - switching to long");
+ ea1 = DSP_EA_ABS;
+ force_imm = NUM_FORCE_LONG;
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+ }
+ }
+ else
+ {
+ // This might end up as something like 'move Y:<adr,register'
+ // so let's mark it as an extra aa fixup here.
+ // Note: we are branching to y_check_immed without a
+ // defined dspImmed so it's going to be 0. It probably
+ // doesn't harm anything.
+ deposit_extra_ea = DEPOSIT_EXTRA_FIXUP;
+ }
+
+ goto y_check_immed;
+ }
+ }
+
+ return error("unrecognised Y: parallel move syntax");
+}
+
+
+//
+// Parse L: addressing space parallel moves
+//
+static inline LONG parse_l(const int W, LONG inst, LONG S1)
+{
+ int immreg; // Immediate register destination
+ LONG D1; // Source and Destinations
+ LONG ea1; // ea bitfields
+ int force_imm = NUM_NORMAL; // Holds forced immediate value (i.e. '<' or '>')
+ if (*tok == '-')
+ {
+ if (*tok == CONST || tok[1] == FCONST)
+ {
+ tok++;
+ dspImmedEXVAL = *tok++;
+ goto l_check_immed;
+ }
+ // This could be either -(Rn), -aa or -ea. Check for immediate first
+ // Maybe we got an expression here, check for it
+ if (*tok == SYMBOL || tok[1] == SYMBOL)
+ {
+ // Evaluate the expression and go to immediate code path
+ if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) == OK)
+ {
+ // Only check for aa if we have a defined number in our hands or we've
+ // been asked to use a short number format. The former case we'll just test
+ // it to see if it's small enough. The later - it's the programmer's call
+ // so he'd better have a small address or the fixups will bite him/her in the arse!
+ if (dspImmedEXATTR&DEFINED || force_imm == NUM_FORCE_SHORT)
+ {
+ // It's an immediate, so ea is probably an absolute address
+ // (unless it's aa if the immediate is small enough)
+ // 'L:ea,D' or 'L:aa,D'
+ l_check_immed:
+ // Check for aa (which is 6 bits zero extended)
+ if (*tok == EOL)
+ {
+ // 'S,L:aa'
+ if (dspImmedEXVAL < 0x40 && force_imm != NUM_FORCE_LONG)
+ {
+ // 'S,L:aa'
+ if (S1 == KW_A)
+ S1 = 4;
+ else if (S1 == KW_B)
+ S1 = 5;
+ else
+ S1 &= 7;
+
+ inst = B16(01000000, 00000000);
+ inst |= dspImmedEXVAL;
+ inst |= ((S1 & 0x4) << (11 - 2)) + ((S1 & 3) << 8);
+ return inst;
+ }
+ else
+ {
+ // 'S,L:ea'
+ if (S1 == KW_A)
+ S1 = 4;
+ else if (S1 == KW_B)
+ S1 = 5;
+ else
+ S1 &= 7;
+
+ if (ea1 == DSP_EA_ABS)
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+
+ inst |= B16(01000000, 01110000);
+ inst |= ((S1 & 0x4) << (11 - 2)) + ((S1 & 3) << 8);
+ inst |= ea1;
+ return inst;
+ }
+
+ }
+ if (*tok++ != ',')
+ return error("unrecognised L: parallel move syntax: expected ',' after 'L:ea/L:aa'");
+ // Check for allowed registers for D (a0, b0, x, y, a, b, ab or ba)
+ if (!((*tok >= KW_A10 && *(tok + 1) <= KW_BA) || (*tok >= KW_A && *tok <= KW_B)))
+ return error("unrecognised L: parallel move syntax: expected a0, b0, x, y, a, b, ab or ba after 'L:ea/L:aa'");
+
+ if (dspImmedEXVAL < (1 << 6) && (dspImmedEXATTR&DEFINED))
+ {
+ // 'L:aa,D'
+ l_aa:
+ immreg = *tok++;
+ if (immreg == KW_A)
+ immreg = 4;
+ else if (immreg == KW_B)
+ immreg = 5;
+ else
+ immreg &= 7;
+
+ if (*tok != EOL)
+ return error("unrecognised L: parallel move syntax: expected End-Of-Line after L:aa,D");
+
+ inst &= B16(11111111, 10111111);
+ inst |= dspImmedEXVAL;
+ inst |= ((immreg & 0x4) << (11 - 2)) + ((immreg & 3) << 8);
+ return inst;
+ }
+ }
+
+ if (deposit_extra_ea == DEPOSIT_EXTRA_FIXUP)
+ {
+ // Hang on, we've got a L:<aa here, let's do that instead
+ goto l_aa;
+ }
+
+ // Well, that settles it - we do have a ea in our hands
+ // 'L:ea,D'
+ D1 = *tok++;
+ if (D1 == KW_A)
+ D1 = 4;
+ else if (D1 == KW_B)
+ D1 = 5;
+ else
+ D1 &= 7;
+
+ if (*tok != EOL)
+ return error("unrecognised L: parallel move syntax: expected End-Of-Line after L:ea,D");
+
+ inst |= B16(00000000, 00110000);
+ inst |= ((D1 & 0x4) << (11 - 2)) + ((D1 & 3) << 8);
+ return inst;
+ }
+ }
+ else
+ {
+ //It's not an immediate, check for '-(Rn)'
+ ea1 = checkea(',', L_ERRORS);
+
+ if (ea1 == ERROR)
+ return ERROR;
+
+ goto l_gotea1;
+
+ }
+ }
+ else if (*tok == '(')
+ {
+ // Maybe we got an expression here, check for it
+ if (tok[1] == CONST || tok[1] == FCONST || tok[1] == SUNARY || tok[1] == SYMBOL || tok[1] == STRING)
+ {
+ // Evaluate the expression and go to immediate code path
+ expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM);
+ goto l_check_immed;
+ }
+
+ //Nope, let's check for ea then
+ if (S1 == 0)
+ ea1 = checkea(',', L_ERRORS);
+ else
+ ea1 = checkea(EOL, L_ERRORS);
+
+ if (ea1 == ERROR)
+ return ERROR;
+
+ l_gotea1:
+ if (*tok == EOL)
+ {
+ // 'S,L:ea'
+ inst = B16(01000000, 01000000);
+ if (S1 == KW_A)
+ S1 = 4;
+ else if (S1 == KW_B)
+ S1 = 5;
+ else
+ S1 &= 7;
+
+ inst |= ea1;
+ inst |= ((S1 & 0x4) << (11 - 2)) + ((S1 & 3) << 8);
+ return inst;
+ }
+ else if (*tok++ != ',')
+ return error("Comma expected after 'L:(Rn)')");
+
+ // It might be 'L:(Rn..)..,D' but we're not 100% sure yet.
+ // If it is, the only possible syntax here is 'L:ea,D'.
+ // So check ahead to see if EOL follows D, then we're good to go.
+ if (((*tok >= KW_A10 && *tok <= KW_BA) || (*tok >= KW_A && *tok <= KW_B)) && *(tok + 1) == EOL)
+ {
+ //'L:ea,D'
+ D1 = *tok++;
+ if (D1 == KW_A)
+ D1 = 4;
+ else if (D1 == KW_B)
+ D1 = 5;
+ else
+ D1 &= 7;
+
+ inst |= ea1;
+ inst |= ((D1 & 0x4) << (11 - 2)) + ((D1 & 3) << 8);
+ return inst;
+ }
+ }
+ else if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
+ {
+ // Check for immediate address
+ if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+ return ERROR;
+
+ // We set ea1 here - if it's aa instead of ea
+ // then it won't be used anyway
+ ea1 = DSP_EA_ABS;
+ if (!(dspImmedEXATTR & DEFINED))
+ {
+ force_imm = NUM_FORCE_LONG;
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+ }
+ else if (dspImmedEXVAL > 0x3f)
+ {
+ // Definitely no aa material, so it's going to be a long
+ // Mark that we need to deposit an extra word
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+ }
+
+ // Yes, we have an expression, so we now check for
+ // 'L:ea,D' or 'L:aa,D'
+ goto l_check_immed;
+ }
+ else if (*tok == '>')
+ {
+ // Check for immediate address forced long
+ tok++;
+ if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+ return ERROR;
+ if (dspImmedEXATTR & DEFINED)
+ if (dspImmedEXVAL > 0xffffff)
+ return error("long address is bigger than $ffffff");
+
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+
+ force_imm = NUM_FORCE_LONG;
+ goto l_check_immed;
+ }
+ else if (*tok == '<')
+ {
+ // Check for immediate address forced short
+ tok++;
+ if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+ return ERROR;
+ if (dspImmedEXATTR & DEFINED)
+ {
+ if (dspImmedEXVAL > 0xfff)
+ return error("short addressing mode forced but address is bigger than $fff");
+ }
+ else
+ {
+ // This might end up as something like 'move Y:<adr,register'
+ // so let's mark it as an extra aa fixup here.
+ // Note: we are branching to l_check_immed without a
+ // defined dspImmed so it's going to be 0. It probably
+ // doesn't harm anything.
+ deposit_extra_ea = DEPOSIT_EXTRA_FIXUP;
+ }
+
+ force_imm = NUM_FORCE_SHORT;
+ goto l_check_immed;
+ }
+
+ 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");
+}
+
+
+//
+// Checks for all ea cases where indexed addressing is concenred
+//
+static inline LONG checkea(const uint32_t termchar, const int strings)
+{
+ LONG ea;
+ if (*tok == '-')
+ {
+ // -(Rn)
+ tok++;
+ if (*tok++ != '(')
+ return error(ea_errors[strings][0]);
+ if (*tok >= KW_R0 && *tok <= KW_R7)
+ {
+ // We got '-(Rn' so mark it down
+ ea = DSP_EA_PREDEC1 | (*tok++ - KW_R0);
+ if (*tok++ != ')')
+ return error(ea_errors[strings][1]);
+ // Now, proceed to the main code for this branch
+ return ea;
+ }
+ else
+ return error(ea_errors[strings][2]);
+ }
+ else if (*tok == '(')
+ {
+ // Checking for ea of type (Rn)
+ tok++;
+ if (*tok >= KW_R0 && *tok <= KW_R7)
+ {
+ // We're in 'X:(Rn..)..,D', 'X:(Rn..)..,D1 Y:eay,D2', 'X:(Rn..)..,D1 S2,Y:eay'
+ ea = *tok++ - KW_R0;
+ if (*tok == '+')
+ {
+ // '(Rn+Nn)'
+ tok++;
+ if (*tok < KW_N0 || *tok > KW_N7)
+ return error(ea_errors[strings][3]);
+ if ((*tok++ & 7) != ea)
+ return error(ea_errors[strings][4]);
+ ea |= DSP_EA_INDEX;
+ if (*tok++ != ')')
+ return error(ea_errors[strings][5]);
+ return ea;
+ }
+ else if (*tok == ')')
+ {
+ // Check to see if we have '(Rn)+', '(Rn)-', '(Rn)-Nn', '(Rn)+Nn' or '(Rn)'
+ tok++;
+ if (*tok == '+')
+ {
+ tok++;
+ if (termchar == ',')
+ {
+ if (*tok == ',')
+ {
+ // (Rn)+
+ ea |= DSP_EA_POSTINC1;
+ return ea;
+ }
+ else if (*tok >= KW_N0 && *tok <= KW_N7)
+ {
+ // (Rn)+Nn
+ if ((*tok++ & 7) != ea)
+ return error(ea_errors[strings][6]);
+ ea |= DSP_EA_POSTINC;
+ return ea;
+ }
+ else
+ return error(ea_errors[strings][7]);
+ }
+ else
+ {
+ if (*tok >= KW_N0 && *tok <= KW_N7)
+ {
+ // (Rn)+Nn
+ if ((*tok++ & 7) != ea)
+ return error(ea_errors[strings][6]);
+ ea |= DSP_EA_POSTINC;
+ return ea;
+ }
+ else
+ {
+ // (Rn)+
+ ea |= DSP_EA_POSTINC1;
+ return ea;
+ }
+ }
+ }
+ else if (*tok == '-')
+ {
+ tok++;
+ if (termchar == ',')
+ {
+ if (*tok == ',')
+ {
+ // (Rn)-
+ ea |= DSP_EA_POSTDEC1;
+ return ea;
+ }
+ else if (*tok >= KW_N0 && *tok <= KW_N7)
+ {
+ // (Rn)-Nn
+ if ((*tok++ & 7) != ea)
+ return error(ea_errors[strings][8]);
+ ea |= DSP_EA_POSTDEC;
+ return ea;
+ }
+ else
+ return error(ea_errors[strings][9]);
+ }
+ else
+ {
+ if (*tok >= KW_N0 && *tok <= KW_N7)
+ {
+ // (Rn)-Nn
+ if ((*tok++ & 7) != ea)
+ return error(ea_errors[strings][8]);
+ ea |= DSP_EA_POSTDEC;
+ return ea;
+ }
+ else
+ {
+ // (Rn)-
+ ea |= DSP_EA_POSTDEC1;
+ return ea;
+ }
+ }
+ }
+ else if (termchar == ',')
+ {
+ if (*tok == ',')
+ {
+ // (Rn)
+ ea |= DSP_EA_NOUPD;
+ return ea;
+ }
+ else
+ return error(ea_errors[strings][10]);
+ }
+ else
+ {
+ // (Rn)
+ ea |= DSP_EA_NOUPD;
+ return ea;
+ }
+ }
+ else
+ return error(ea_errors[strings][11]);
+ }
+ }
+ 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");
+}
+
+
+//
+// Checks for all ea cases, i.e. all addressing modes that checkea handles
+// plus immediate addresses included forced short/long ones.
+// In other words this is a superset of checkea (and in fact calls checkea).
+//
+LONG checkea_full(const uint32_t termchar, const int strings)
+{
+ LONG ea1;
+
+ if (*tok == CONST || *tok == FCONST || *tok == SYMBOL)
+ {
+ // Check for immediate address
+ if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+ return ERROR;
+
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+
+ // Yes, we have an expression
+ return DSP_EA_ABS;
+ }
+ else if (*tok == '>')
+ {
+ // Check for immediate address forced long
+ tok++;
+ if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+ return ERROR;
+ if (dspImmedEXATTR & DEFINED)
+ if (dspImmedEXVAL > 0xffffff)
+ return error("long address is bigger than $ffffff");
+
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+
+ // Yes, we have an expression
+ return DSP_EA_ABS;
+ }
+ else if (*tok == '<')
+ {
+ // Check for immediate address forced short
+ tok++;
+ if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+ return ERROR;
+ if (dspImmedEXATTR & DEFINED)
+ if (dspImmedEXVAL > 0xfff)
+ return error("short addressing mode forced but address is bigger than $fff");
+
+ // Yes, we have an expression
+ return DSP_EA_ABS;
+ }
+ else
+ {
+ ea1 = checkea(termchar, strings);
+ if (ea1 == ERROR)
+ return ERROR;
+ else
+ return ea1;
+ }
+
+}
+
+//
+// Main routine to check parallel move modes.
+// It's quite complex so it's split into a few procedures (in fact most of the above ones).
+// A big effort was made so this can be managable and not too hacky, however one look at
+// the 56001 manual regarding parallel moves and you'll know that this is not an easy
+// problem to deal with!
+// dest=destination register from the main opcode. This must not be the same as D1 or D2
+// and that even goes for stuff like dest=A, D1=A0/1/2!!!
+//
+LONG parmoves(WORD dest)
+{
+ int force_imm; // Addressing mode force operator
+ int immreg; // Immediate register destination
+ LONG inst; // 16 bit bitfield that has the parallel move opcode
+ LONG S1, S2, D1, D2; // Source and Destinations
+ LONG ea1; // ea bitfields
+
+ if (*tok == EOL)
+ {
+ // No parallel move
+ return B16(00100000, 00000000);
+ }
+ if (*tok == '#')
+ {
+ // '#xxxxxx,D', '#xx,D'
+ tok++;
+ force_imm = NUM_NORMAL;
+ if (*tok == '>')
+ {
+ force_imm = NUM_FORCE_LONG;
+ tok++;
+ }
+ else if (*tok == '<')
+ {
+ force_imm = NUM_FORCE_SHORT;
+ tok++;
+ }
+
+ if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK)
+ return ERROR;
+
+ if (*tok++ != ',')
+ return error("expected comma");
+
+ if (!((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2)))
+ return error("expected x0,x1,y0,y1,a0,b0,a2,b2,a1,b1,a,b,r0-r7,n0-n7 after immediate");
+ immreg = SDreg(*tok++);
+
+ if (*tok == EOL)
+ {
+ if (!(dspImmedEXATTR & FLOAT))
+ {
+ if (dspImmedEXATTR & DEFINED)
+ {
+ // From I parallel move:
+ // "If the destination register D is X0, X1, Y0, Y1, A, or B, the 8-bit immediate short operand
+ // is interpreted as a signed fraction and is stored in the specified destination register.
+ // That is, the 8 - bit data is stored in the eight MS bits of the destination operand, and the
+ // remaining bits of the destination operand D are zeroed."
+ // The funny bit is that Motorola assembler can parse something like 'move #$FF0000,b' into an
+ // I (immediate short move) - so let's do that as well then...
+ if (((immreg >= 4 && immreg <= 7) || immreg == 14 || immreg == 15) && force_imm != NUM_FORCE_LONG)
+ {
+ if ((dspImmedEXVAL & 0xffff) == 0)
+ {
+ dspImmedEXVAL >>= 16;
+ }
+ }
+ if (force_imm == NUM_FORCE_SHORT)
+ {
+ if (dspImmedEXVAL<0xff && (int32_t)dspImmedEXVAL>-0x100)
+ {
+ // '#xx,D'
+ // value fits in 8 bits - immediate move
+ inst = B16(00100000, 00000000) + (immreg << 8) + (uint32_t)dspImmedEXVAL;
+ return inst;
+ }
+ else
+ {
+ warn("forced short immediate value doesn't fit in 8 bits - switching to long");
+ force_imm = NUM_FORCE_LONG;
+ }
+ }
+ if (force_imm == NUM_FORCE_LONG)
+ {
+ // '#xxxxxx,D'
+ // it can either be
+ // X or Y Data move. I don't think it matters much
+ // which of the two it will be, so let's use X.
+ deposit_immediate_long_with_register:
+ inst = B16(01000000, 11110100);
+ inst |= ((immreg & 0x18) << (12 - 3)) + ((immreg & 7) << 8);
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+ return inst;
+ }
+ if (((int32_t)dspImmedEXVAL < 0x100) && ((int32_t)dspImmedEXVAL >= -0x100))
+ {
+ // value fits in 8 bits - immediate move
+ deposit_immediate_short_with_register:
+ inst = B16(00100000, 00000000) + (immreg << 8) + (uint32_t)dspImmedEXVAL;
+ return inst;
+ }
+ else
+ {
+ // value doesn't fit in 8 bits, so it can either be
+ // X or Y Data move. I don't think it matters much
+ // which of the two it will be, so let's use X:.
+ // TODO: if we're just goto'ing perhaps the logic can be simplified
+ goto deposit_immediate_long_with_register;
+ }
+ }
+ else
+ {
+ if (force_imm != NUM_FORCE_SHORT)
+ {
+ // '#xxxxxx,D'
+ // TODO: if we're just goto'ing perhaps the logic can be simplified
+ goto deposit_immediate_long_with_register;
+ }
+ else
+ {
+ // '#xx,D' - I mode
+ // No visibility of the number so let's add a fixup for this
+ AddFixup(FU_DSPIMM8, sloc, dspImmedEXPR);
+ inst = B16(00100000, 00000000);
+ inst |= ((immreg & 0x18) << (11 - 3)) + ((immreg & 7) << 8);
+ return inst;
+ }
+
+ }
+ }
+ else
+ {
+ // Float constant
+ if (dspImmedEXATTR & DEFINED)
+ {
+
+ double f = *(double *)&dspImmedEXVAL;
+ // Check direct.c for ossom comments regarding conversion!
+ dspImmedEXVAL = ((uint32_t)(int32_t)round(f*(1 << 23))) & 0xffffff;
+ double g;
+ g = f*(1 << 23);
+ g = round(g);
+
+ if ((dspImmedEXVAL & 0xffff) == 0)
+ {
+ // Value's 16 lower bits are not set so the value can fit in a single byte
+ // (check parallel I move quoted above)
+ warn("Immediate value fits inside 8 bits, so using instruction short format");
+ dspImmedEXVAL >>= 16;
+ goto deposit_immediate_short_with_register;
+ }
+
+ if (force_imm == NUM_FORCE_SHORT)
+ {
+ if ((dspImmedEXVAL & 0xffff) != 0)
+ {
+ warn("Immediate value short format forced but value does not fit inside 8 bits - switching to long format");
+ goto deposit_immediate_long_with_register;
+ }
+ return error("internal assembler error: we haven't implemented floating point constants in parallel mode parser yet!");
+ }
+ // If we reach here we either have NUM_FORCE_LONG or nothing, so we might as well store a long.
+ goto deposit_immediate_long_with_register;
+ }
+ else
+ {
+ if (force_imm == NUM_FORCE_SHORT)
+ {
+ goto deposit_immediate_short_with_register;
+ }
+ else
+ {
+ // Just deposit a float fixup
+ AddFixup(FU_DSPIMMFL8, sloc, dspImmedEXPR);
+ inst = B16(00100000, 00000000);
+ inst |= ((immreg & 0x18) << (12 - 3)) + ((immreg & 7) << 8);
+ return inst;
+ }
+ }
+ }
+ }
+ else
+ {
+ // At this point we can only have '#xxxxxx,D1 S2,D2' (X:R Class I)
+
+ switch (immreg)
+ {
+ case 4: D1 = 0 << 10;break; // X0
+ case 5: D1 = 1 << 10;break; // X1
+ case 14: D1 = 2 << 10;break; // A
+ case 15: D1 = 3 << 10;break; // B
+ default: return error("unrecognised X:R parallel move syntax: D1 can only be x0,x1,a,b in '#xxxxxx,D1 S2,D2'"); break;
+ }
+
+ switch (*tok++)
+ {
+ case KW_A: S2 = 0 << 9; break;
+ case KW_B: S2 = 1 << 9; break;
+ default: return error("unrecognised X:R parallel move syntax: S2 can only be A or B in '#xxxxxx,D1 S2,D2'"); break;
+ }
+
+ if (*tok++ != ',')
+ return error("unrecognised X:R parallel move syntax: expected comma after '#xxxxxx,D1 S2'");
+
+ switch (*tok++)
+ {
+ case KW_Y0: D2 = 0 << 8; break;
+ case KW_Y1: D2 = 1 << 8; break;
+ default: return error("unrecognised X:R parallel move syntax: D2 can only be Y0 or Y1 in '#xxxxxx,D1 S2,D2'"); break;
+ }
+
+ if (*tok != EOL)
+ return error("unrecognised X:R parallel move syntax: expected end-of-line after '#xxxxxx,D1 S2,D2'");
+
+ inst = B16(00010000, 10110100) | D1 | S2 | D2;
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+ return inst;
+ }
+ }
+ else if (*tok == KW_X)
+ {
+ if (tok[1] == ',')
+ // Hey look, it's just the register X and not the addressing mode - fall through to general case
+ goto parse_everything_else;
+
+ tok++;
+
+ if (*tok++ != ':')
+ return error("expected ':' after 'X' in parallel move (i.e. X:)");
+
+ // 'X:ea,D' or 'X:aa,D' or 'X:ea,D1 S2,D2' or 'X:eax,D1 Y:eay,D2' or 'X:eax,D1 S2,Y:eay'
+ return parse_x(1, B16(01000000, 00000000), 0, 1);
+ }
+ else if (*tok == KW_Y)
+ {
+ if (tok[1] == ',')
+ // Hey look, it's just the register y and not the addressing mode - fall through to general case
+ goto parse_everything_else;
+
+ tok++;
+ if (*tok++ != ':')
+ return error("expected ':' after 'Y' in parallel move (i.e. Y:)");
+
+ // 'Y:ea,D' or 'Y:aa,D'
+ return parse_y(B16(01001000, 10000000), 0, 0, 0);
+ }
+ else if (*tok == KW_L)
+ {
+ // 'L:ea,D' or 'L:aa,D'
+ tok++;
+ if (*tok++ != ':')
+ return error("expected ':' after 'L' in parallel move (i.e. L:)");
+
+ return parse_l(1, B16(01000000, 11000000), 0);
+ }
+ else if ((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2) || (*tok >= KW_A10 && *tok <= KW_BA))
+ {
+ // Everything else - brace for impact!
+ // R: 'S,D'
+ // X: 'S,X:ea' 'S,X:aa'
+ // X:R 'S,X:ea S2,D2' 'A,X:ea X0,A' 'B,X:ea X0,B'
+ // Y: 'S,Y:ea' 'S,Y:aa'
+ // R:Y: 'S1,D1 Y:ea,D2' 'S1,D1 S2,Y:ea' 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' 'S1,D1 #xxxxxx,D2' 'Y0,A A,Y:ea' 'Y0,B B,Y:ea'
+ // L: 'S,L:ea' 'S,L:aa'
+ LONG L_S1;
+parse_everything_else:
+ L_S1 = *tok++;
+ S1 = SDreg(L_S1);
+
+ if (*tok++ != ',')
+ return error("Comma expected after 'S')");
+
+ if (*tok == KW_X)
+ {
+ // 'S,X:ea' 'S,X:aa' 'S,X:ea S2,D2' 'S1,X:eax Y:eay,D2' 'S1,X:eax S2,Y:eay'
+ // 'A,X:ea X0,A' 'B,X:ea X0,B'
+ tok++;
+ if (*tok++ != ':')
+ return error("unrecognised X: parallel move syntax: expected ':' after 'S,X'");
+ return parse_x(0, B16(01000000, 00000000), S1, 1);
+ }
+ else if (*tok == KW_Y)
+ {
+ // 'S,Y:ea' 'S,Y:aa'
+ tok++;
+ if (*tok++ != ':')
+ return error("unrecognised Y: parallel move syntax: expected ':' after 'S,Y'");
+ return parse_y(B16(0000000, 00000000), S1, 0, 0);
+ }
+ else if (*tok == KW_L)
+ {
+ // 'S,L:ea' 'S,L:aa'
+ tok++;
+ if (*tok++ != ':')
+ return error("unrecognised L: parallel move syntax: expected ':' after 'S,L'");
+ return parse_l(1, B16(00000000, 00000000), L_S1);
+ }
+ else if ((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2))
+ {
+ // 'S,D'
+ // 'S1,D1 Y:ea,D2' 'S1,D1 S2,Y:ea' 'S1,D1 #xxxxxx,D2'
+ // 'Y0,A A,Y:ea' 'Y0,B B,Y:ea'
+ D1 = SDreg(*tok++);
+ if (*tok == EOL)
+ {
+ // R 'S,D'
+ inst = B16(00100000, 00000000);
+ inst |= (S1 << 5) | (D1);
+ return inst;
+ }
+ else if (*tok == KW_Y)
+ {
+ // 'S1,D1 Y:ea,D2'
+ tok++;
+ if (*tok++ != ':')
+ return error("expected ':' after 'Y' in parallel move (i.e. Y:)");
+ return parse_y(B16(00010000, 01000000), S1, D1, 0);
+
+ }
+ else if (*tok == KW_A || *tok == KW_B || *tok == KW_Y0 || *tok == KW_Y1)
+ {
+ // 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' 'S1,D1 S2,Y:ea'
+ S2 = SDreg(*tok++);
+ if (S1 == 6 && D1 == 14 && S2 == 14)
+ {
+ // 'Y0,A A,Y:ea'
+ if (*tok++ != ',')
+ return error("unrecognised Y: parallel move syntax: expected ',' after Y0,A A");
+ if (*tok++ != KW_Y)
+ return error("unrecognised Y: parallel move syntax: expected 'Y' after Y0,A A,");
+ if (*tok++ != ':')
+ return error("unrecognised Y: parallel move syntax: expected ':' after Y0,A A,Y");
+ ea1 = checkea_full(EOL, Y_ERRORS);
+ if (ea1 == ERROR)
+ return ERROR;
+ inst = B16(00001000, 10000000);
+ inst |= 0 << 8;
+ inst |= ea1;
+ return inst;
+ }
+ else if (S1 == 6 && D1 == 15 && S2 == 15)
+ {
+ // 'Y0,B B,Y:ea'
+ if (*tok++ != ',')
+ return error("unrecognised Y: parallel move syntax: expected ',' after Y0,B B");
+ if (*tok++ != KW_Y)
+ return error("unrecognised Y: parallel move syntax: expected 'Y' after Y0,B B,");
+ if (*tok++ != ':')
+ return error("unrecognised Y: parallel move syntax: expected ':' after Y0,B B,Y");
+ ea1 = checkea_full(EOL, Y_ERRORS);
+ if (ea1 == ERROR)
+ return ERROR;
+ inst = B16(00001000, 10000000);
+ inst |= 1 << 8;
+ inst |= ea1;
+ return inst;
+ }
+ else if ((S1 == 14 || S1 == 15) && (D1 == 4 || D1 == 5) && (S2 == 6 || S2 == 7 || S2 == 14 || S2 == 15))
+ {
+ //'S1,D1 S2,Y:ea'
+ if (*tok++ != ',')
+ return error("unrecognised Y: parallel move syntax: expected ',' after S1,D1 S2");
+ if (*tok++ != KW_Y)
+ return error("unrecognised Y: parallel move syntax: expected 'Y' after S1,D1 S2,");
+ if (*tok++ != ':')
+ return error("unrecognised Y: parallel move syntax: expected ':' after S1,D1 S2,Y");
+ ea1 = checkea_full(EOL, Y_ERRORS);
+ if (ea1 == ERROR)
+ return ERROR;
+ inst = B16(00010000, 01000000);
+ inst |= (S1 & 1) << 11;
+ inst |= (D1 & 1) << 10;
+ inst |= ((S2 & 8) << (10 - 4)) | ((S2 & 1) << 8);
+ inst |= ea1;
+ return inst;
+ }
+ else
+ return error("unrecognised Y: parallel move syntax: only 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' allowed'");
+ // Check for Y:
+ }
+ else if (*tok == '#')
+ {
+ // R:Y: 'S1,D1 #xxxxxx,D2'
+ tok++;
+ if (*tok == '>')
+ {
+ // Well, forcing an immediate to be 24 bits is legal here
+ // but then it's the only available option so my guess is that this
+ // is simply superfluous. So let's just eat the character
+ tok++;
+ }
+ if (expr(dspaaEXPR, &dspaaEXVAL, &dspaaEXATTR, &dspaaESYM) != OK)
+ return ERROR;
+ if (dspImmedEXATTR & DEFINED)
+ if (dspImmedEXVAL > 0xffffff)
+ return error("immediate is bigger than $ffffff");
+ deposit_extra_ea = DEPOSIT_EXTRA_WORD;
+ if (*tok++ != ',')
+ return error("Comma expected after 'S1,D1 #xxxxxx')");
+ // S1 is a or b, D1 is x0 or x1 and d2 is y0, y1, a or b
+ switch (*tok++)
+ {
+ case KW_Y0: D2 = 0 << 8; break;
+ case KW_Y1: D2 = 1 << 8; break;
+ case KW_A: D2 = 2 << 8; break;
+ case KW_B: D2 = 3 << 8; break;
+ default: return error("unrecognised R:Y: parallel move syntax: D2 must be y0, y1, a or b in 'S1,D1 #xxxxxx,D2'");
+ }
+
+ if (S1 == 14 || S1 == 15)
+ {
+ if (D1 == 4 || D1 == 5)
+ {
+ inst = B16(00010000, 11110100);
+ inst |= (S1 & 1) << 11;
+ inst |= (D1 & 1) << 10;
+ inst |= D2;
+ dspImmedEXVAL = dspaaEXVAL;
+ return inst;
+ }
+ else
+ return error("unrecognised R:Y: parallel move syntax: D1 must be x0 or x1 in 'S1,D1 #xxxxxx,D2'");
+ }
+ else
+ return error("unrecognised R:Y: parallel move syntax: S1 must be a or b in 'S1,D1 #xxxxxx,D2'");
+ }
+ else
+ return error("unrecognised R:Y: parallel move syntax: Unexpected text after S,D in 'S1,D1 #xxxxxx,D2'");
+ }
+ else
+ return error("unrecognised R:Y: parallel move syntax: Unexpected text after 'S,'");
+ }
+ else if (*tok == '(')
+ {
+ // U: 'ea'
+ // U 'ea' can only be '(Rn)-Nn', '(Rn)+Nn', '(Rn)-' or '(Rn)+'
+ tok++;
+ if (*tok >= KW_R0 && *tok <= KW_R7)
+ {
+ ea1 = (*tok++ - KW_R0);
+ }
+ else
+ return error("unrecognised U parallel move syntax: expected 'Rn' after '('");
+ if (*tok++ != ')')
+ return error("unrecognised U parallel move syntax: expected ')' after '(Rn'");
+ if (*tok == '+')
+ {
+ tok++;
+ if (*tok == EOL)
+ // (Rn)+
+ ea1 |= 3 << 3;
+ else if (*tok >= KW_N0 && *tok <= KW_N7)
+ {
+ // (Rn)+Nn
+ if ((*tok++ & 7) != ea1)
+ return error("unrecognised U parallel move syntax: Same register number expected for Rn, Nn in '(Rn)+Nn')");
+ ea1 |= 1 << 3;
+ if (*tok != EOL)
+ return error("unrecognised U parallel move syntax: expected End-Of-Line after '(Rn)+Nn'");
+ }
+ else
+ return error("unrecognised U parallel move syntax: expected End-Of-Line or 'Nn' after '(Rn)+'");
+
+ }
+ else if (*tok == '-')
+ {
+ tok++;
+ if (*tok == EOL)
+ {
+ // (Rn)-
+ ea1 |= 2 << 3;
+ tok++;
+ }
+ else if (*tok >= KW_N0 && *tok <= KW_N7)
+ {
+ // (Rn)-Nn
+ if ((*tok++ & 7) != ea1)
+ return error("unrecognised U parallel move syntax: Same register number expected for Rn, Nn in '(Rn)-Nn')");
+ ea1 |= 0 << 3;
+ if (*tok != EOL)
+ return error("unrecognised U parallel move syntax: expected End-Of-Line after '(Rn)-Nn'");
+ }
+ }
+
+ inst = B16(00100000, 01000000);
+ inst |= ea1;
+ return inst;
+ }
+ else
+ return error("extra (unexpected) text found");
+
+ return OK;
+}
+
--- /dev/null
+//
+// RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
+// DSP56K_AMODE.H - Addressing Modes for Motorola DSP56001
+// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends
+// RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
+// Source utilised with the kind permission of Landon Dyer
+//
+
+#ifndef __DSP56K_AMODE_H__
+#define __DSP56K_AMODE_H__
+
+#include "rmac.h"
+#include "amode.h"
+
+// Addressing-mode masks
+
+#define M_ACC56 0x00000001L // Accumulators A=A2:A1:A0 and B=B2:B1:B0
+#define M_ACC48 0x00000002L // Accumulators AB=A1:B1, BA=B1:A1, A10=A1:A0, B10=B1:B0
+#define M_ACC24 0x00000004L // Accumulators A0, A1, B0 and B1
+#define M_ACC8 0x00000008L // Accumulators A2 and B2
+#define M_INP48 0x00000010L // Input registers X=X1:X0 and Y=Y1:Y0
+#define M_ALU24 0x00000020L // Data ALU input registers X1, X0, Y1, Y0
+#define M_DSPIM 0x00000040L // #data
+#define M_DSPIM12 0x00000080L // #data
+//#define M_DSPIM24 0x0000010 // #data
+#define M_DSPPCU 0x00000200L // Program control unit registers PC, MR, CCR, SR, OMR, LA, LC, SP, SS, SSH, SSL
+#define M_DSPEA 0x00000400L // Effective addressing modes (Rn)-Nn, (Rn)+Nn, (Rn)-, (Rn)+, (Rn), (Rn+Nn), -(Rn), <absolute address>
+#define M_DSPAA 0x00000800L // 6-bit Absolute Short Address
+#define M_DSPPP 0x00001000L // 6-bit I/O Short Address
+#define M_DSPM 0x00002000L // Modifier registers M0-M7
+#define M_DSPR 0x00004000L // Address registers R0-R7
+#define M_DSPN 0x00008000L // Address offset registers N0-N7
+#define M_DSPABS12 0x00010000L // xxx.12bit
+#define M_DSPABS24 0x00020000L // xxx.24bit
+#define M_DSPABS06 0x00040000L // xxx.6bit
+#define M_DSPABS16 0x00080000L // xxx.16bit
+#define M_DSPIM8 0x00100000L // #data
+
+#define M_ALL48 (M_ACC56|M_INP48|M_ALU24) // Input registers X=X1:X0, Y=Y1:Y0, A=A2:A1:A0, B=B2:B1:B0, X0, X1, Y0, Y1
+
+#define C_DD (M_ALU24) // 4 registers in data ALU: x0, x1, y0, y1
+#define C_DDD (M_ACC56|M_ACC24|M_ACC8) // 8 accumulators in data ALU: a0, b0, a2, b2, a1, b1, a, b
+#define C_LLL (M_ACC56|M_ACC48|M_INP48) // 8 extended-precision registers in data ALU: a10, b10, x, y, a, b, ab, ba
+#define C_FFF (M_DSPM) // 8 address modifier registers in address ALU: m0-m7
+#define C_NNN (M_DSPN) // 8 address offset registers in address ALU: n0-n7
+#define C_TTT (M_DSPR) // 8 address registers in address: r0-r7
+#define C_GGG (M_DSPPCU) // 8 program controller registers: sr, omr, sp, ssh, la, lc
+#define C_A18 (M_ALU24|C_DDD|C_LLL|C_FFF|C_NNN|C_TTT|C_GGG) // All of the above registers
+
+#define C_DSPABS24 (M_DSPABS06|M_DSPABS12|M_DSPABS16|M_DSPABS24) // Everything up to 24-bit addresses
+#define C_DSPABSEA (C_DSPABS24|M_DSPEA) // All absolute addresses and all other ea addressing modes
+#define C_DSPABS16 (M_DSPABS06|M_DSPABS12|M_DSPABS16) // Everything up to 16-bit addresses
+#define C_LUADST (M_DSPR|M_DSPN) // Mask for LUA instruction destination
+#define C_MOVEC (M_DSPM|M_DSPPCU) // M0-M7 and SR, OMR, LA, LC, SP, SS, SSH, SSL
+#define C_DSPIM (M_DSPIM8 | M_DSPIM | M_DSPIM12) // All the immmediate sizes we want to alias
+
+// Xn Input Register X1 or X0 (24 Bits)
+// Yn Input Register Y1 or Y0 (24 Bits)
+// An Accumulator Registers A2, A1, A0 (A2 \97 8 Bits, A1 and A0 \97 24 Bits)
+// Bn Accumulator Registers B2, B1, B0 (B2 \97 8 Bits, B1 and B0 \97 24 Bits)
+// X Input Register X = X1: X0 (48 Bits)
+// Y Input Register Y = Y1: Y0 (48 Bits)
+// A Accumulator A = A2: A1: A0 (56 Bits)*
+// B Accumulator B = B2: B1: B0 (56 BIts)*
+// AB Accumulators A and B = A1: B1 (48 Bits)*
+// BA Accumulators B and A = B1: A1 (48 Bits)*
+// A10 Accumulator A = A1: A0 (48 Bits)
+// B10 Accumulator B= B1:B0 (48 bits)
+
+// Attribute masks
+#define PARMOVE 0x00000001L
+#define NOPARMO 0x00000000L
+
+// DSP EA modes
+
+#define DSP_EA_POSTDEC B8(00000000)
+#define DSP_EA_POSTINC B8(00001000)
+#define DSP_EA_POSTDEC1 B8(00010000)
+#define DSP_EA_POSTINC1 B8(00011000)
+#define DSP_EA_NOUPD B8(00100000)
+#define DSP_EA_INDEX B8(00101000)
+#define DSP_EA_PREDEC1 B8(00111000)
+#define DSP_EA_ABS B8(00110000)
+#define DSP_EA_IMM B8(00110100)
+
+
+// Mnemonic table structure
+#define MNTABDSP struct _mntabdsp
+MNTABDSP {
+ LONG mn0, mn1; // Addressing modes
+ WORD mnattr; // Attributes (PARMOVE, ...)
+ LONG mninst; // Instruction mask
+ WORD mncont; // Continuation (or -1)
+ int (* mnfunc)(LONG); // Mnemonic builder
+};
+
+// Addressing mode variables, output of dsp_amode()
+int dsp_am0; // Addressing mode
+int dsp_a0reg; // Register
+int dsp_am1; // Addressing mode
+int dsp_a1reg; // Register
+int dsp_am2; // Addressing mode
+int dsp_a2reg; // Register
+int dsp_am3; // Addressing mode
+int dsp_a3reg; // Register
+
+TOKEN dsp_a0expr[EXPRSIZE]; // Expression
+uint64_t dsp_a0exval; // Expression's value
+WORD dsp_a0exattr; // Expression's attribute
+SYM * dsp_a0esym; // External symbol involved in expr
+LONG dsp_a0memspace; // Addressing mode's memory space (P, X, Y)
+LONG dsp_a0perspace; // Peripheral space (X, Y - used in movep)
+TOKEN dsp_a1expr[EXPRSIZE]; // Expression
+uint64_t dsp_a1exval; // Expression's value
+WORD dsp_a1exattr; // Expression's attribute
+SYM * dsp_a1esym; // External symbol involved in expr
+LONG dsp_a1memspace; // Addressing mode's memory space (P, X, Y)
+LONG dsp_a1perspace; // Peripheral space (X, Y - used in movep)
+TOKEN dsp_a2expr[EXPRSIZE]; // Expression
+uint64_t dsp_a2exval; // Expression's value
+WORD dsp_a2exattr; // Expression's attribute
+SYM * dsp_a2esym; // External symbol involved in expr
+TOKEN dsp_a3expr[EXPRSIZE]; // Expression
+uint64_t dsp_a3exval; // Expression's value
+WORD dsp_a3exattr; // Expression's attribute
+SYM * dsp_a3esym; // External symbol involved in expr
+int dsp_k; // Multiplications sign
+TOKEN dspImmedEXPR[EXPRSIZE]; // Expression
+uint64_t dspImmedEXVAL; // Expression's value
+WORD dspImmedEXATTR; // Expression's attribute
+SYM * dspImmedESYM; // External symbol involved in expr
+int deposit_extra_ea; // Optional effective address extension
+
+
+// Extra ea deposit modes
+enum
+{
+ DEPOSIT_EXTRA_WORD = 1,
+ DEPOSIT_EXTRA_FIXUP = 2,
+};
+
+
+// Prototypes
+int dsp_amode(int maxea);
+LONG parmoves(WORD dest);
+int dsp_tcc4(LONG inst);
+
+#endif // __DSP56K_AMODE_H__
+
--- /dev/null
+//
+// RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
+// DSP56L_MACH.C - Code Generation for Motorola DSP56001
+// Copyright (C) 199x Landon Dyer, 2011-2018 Reboot and Friends
+// RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
+// Source utilised with the kind permission of Landon Dyer
+//
+
+#include "dsp56k_mach.h"
+#include "direct.h"
+#include "dsp56k.h"
+#include "error.h"
+#include "rmac.h"
+#include "sect.h"
+#include "token.h"
+
+#define DEF_KW
+#include "kwtab.h"
+
+
+// Globals
+unsigned int dsp_orgaddr; // DSP 56001 ORG address
+unsigned int dsp_orgseg; // DSP 56001 ORG segment
+
+
+// Fucntion prototypes
+int m_unimp(WORD, WORD), m_badmode(WORD, WORD);
+int dsp_ab(LONG);
+int dsp_baab(LONG inst);
+int dsp_acc48(LONG inst);
+int dsp_self(LONG inst);
+int dsp_xyab(LONG inst);
+int dsp_x0y0ab(LONG inst);
+int dsp_immcr(LONG inst);
+int dsp_immmovec(LONG inst);
+int dsp_imm12(LONG inst);
+int dsp_tcc2(LONG inst);
+int dsp_tcc4(LONG inst);
+int dsp_ea(LONG inst);
+int dsp_ea_imm5(LONG inst);
+int dsp_abs12(LONG inst);
+int dsp_reg_imm5(LONG inst);
+int dsp_ea_abs16(LONG inst);
+int dsp_reg_abs16(LONG inst);
+int dsp_imm12_abs16(LONG inst);
+int dsp_alu24_abs16(LONG inst);
+int dsp_reg(LONG inst);
+int dsp_alu24(LONG inst);
+int dsp_reg_imm5_abs16(LONG inst);
+int dsp_ea_imm5_abs16(LONG inst);
+int dsp_ea_lua(LONG inst);
+int dsp_ab_rn(LONG inst);
+int dsp_movec_ea(LONG inst);
+int dsp_movec_aa(LONG inst);
+int dsp_movec_reg(LONG inst);
+int dsp_mult(LONG inst);
+int dsp_movem_ea(LONG inst);
+int dsp_movem_aa(LONG inst);
+int dsp_movep_ea(LONG inst);
+int dsp_movep_reg(LONG inst);
+
+
+// Common error messages
+
+
+// Include code tables
+MNTABDSP dsp56k_machtab[] = {
+ { 0xFFFFFFFF, 0xFFFFFFFF, 0x0000, 0x0000, 0, (int (*)(LONG))m_badmode }, // 0
+ #include "dsp56ktab.h"
+ { 0L, 0L, 0x0000, 0x0000, 0, (int (*)(LONG))m_unimp } // Last entry
+};
+
+
+static inline int dsp_extra_ea()
+{
+ if (deposit_extra_ea == DEPOSIT_EXTRA_WORD)
+ {
+ if (!(dspImmedEXATTR&FLOAT))
+ {
+ if (dspImmedEXATTR & DEFINED)
+ {
+ D_dsp(dspImmedEXVAL);
+ }
+ else
+ {
+ // TODO: what if it's an address and not an immediate? Does it matter at all?
+ AddFixup(FU_DSPIMM24, sloc, dspImmedEXPR);
+ D_dsp(0);
+ }
+ }
+ else
+ {
+ if (dspImmedEXATTR & DEFINED)
+ {
+ D_dsp(dspImmedEXVAL);
+ }
+ else
+ {
+ // TODO: what if it's an address and not an immediate? Does it matter at all?
+ AddFixup(FU_DSPIMMFL24, sloc, dspImmedEXPR);
+ D_dsp(0);
+ }
+ }
+ }
+ else if (deposit_extra_ea == DEPOSIT_EXTRA_FIXUP)
+ {
+ // Probably superfluous check (we're not likely to land here with a
+ // known aa) but oh well
+ if (!(dspImmedEXATTR & DEFINED))
+ {
+ // Since we already deposited the word to be fixup'd we need to
+ // subtract 1 from sloc
+ chptr -= 3;
+ AddFixup(FU_DSPADR06, sloc - 1, dspImmedEXPR);
+ chptr += 3;
+ }
+ }
+
+ return OK;
+}
+
+
+int dsp_ab(LONG inst)
+{
+ inst |= (dsp_a0reg & 1) << 3;
+ D_dsp(inst);
+ dsp_extra_ea(); // Deposit effective address if needed
+ return OK;
+}
+
+
+int dsp_baab(LONG inst)
+{
+ if (dsp_a0reg == dsp_a1reg)
+ return error("source and destination registers must not be the same");
+
+ inst |= ((dsp_a0reg + 1) & 1) << 3;
+ D_dsp(inst);
+ dsp_extra_ea(); // Deposit effective address if needed
+
+ return OK;
+}
+
+
+int dsp_acc48(LONG inst)
+{
+ if (dsp_a0reg == dsp_a1reg)
+ return error("source and destination registers must not be the same");
+
+ inst |= (dsp_a1reg & 1) << 3;
+
+ switch (dsp_a0reg)
+ {
+ case KW_X: inst |= 2 << 4; break;
+ case KW_Y: inst |= 3 << 4; break;
+ case KW_X0: inst |= 4 << 4;break;
+ case KW_Y0: inst |= 5 << 4;break;
+ case KW_X1: inst |= 6 << 4;break;
+ case KW_Y1: inst |= 7 << 4;break;
+ default: return error("dsp_acc48: shouldn't reach here!");
+ }
+
+ D_dsp(inst);
+ dsp_extra_ea(); // Deposit effective address if needed
+
+ return OK;
+}
+
+
+int dsp_self(LONG inst)
+{
+ D_dsp(inst);
+ dsp_extra_ea(); // Deposit effective address if needed
+
+ return OK;
+}
+
+
+int dsp_xyab(LONG inst)
+{
+ if (dsp_a0reg == dsp_a1reg)
+ return error("source and destination registers must not be the same");
+
+ inst |= (dsp_a0reg & 1) << 4;
+ inst |= (dsp_a1reg & 1) << 3;
+ D_dsp(inst);
+ dsp_extra_ea(); // Deposit effective address if needed
+
+ return OK;
+}
+
+
+int dsp_x0y0ab(LONG inst)
+{
+ if (dsp_a0reg == dsp_a1reg)
+ return error("source and destination registers must not be the same");
+
+ int inverse = (dsp_a0reg & 3);
+ inverse = ((inverse & 1) << 1) | ((inverse & 2) >> 1);
+ inst |= inverse << 4;
+ inst |= (dsp_a1reg & 1) << 3;
+ D_dsp(inst);
+ dsp_extra_ea(); // Deposit effective address if needed
+
+ return OK;
+}
+
+
+int dsp_immcr(LONG inst)
+{
+ switch (dsp_a1reg)
+ {
+ case KW_CCR: inst |= 1; break;
+ case KW_MR:inst |= 0; break;
+ case KW_OMR:inst |= 2; break;
+ default: return error("invalid destination register (only ccr, mr, omr allowed");
+ }
+
+ if (dsp_a0exattr & DEFINED)
+ {
+ inst |= dsp_a0exval << 8;
+ D_dsp(inst);
+ }
+ else
+ {
+ AddFixup(FU_DSPIMM8, sloc, dsp_a0expr);
+ D_dsp(inst);
+ }
+
+ return OK;
+}
+
+
+int dsp_immmovec(LONG inst)
+{
+ switch (dsp_a1reg)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7: inst |= dsp_a1reg; break; // M0-M7
+ case KW_SR: inst |= 25; break;
+ case KW_OMR: inst |= 26; break;
+ case KW_SP: inst |= 27; break;
+ case KW_SSH: inst |= 28; break;
+ case KW_SSL: inst |= 29; break;
+ case KW_LA: inst |= 30; break;
+ case KW_LC: inst |= 31; break;
+ default: return error("invalid destination register (only m0-m7, SR, OMR, SP, SSH, SSL, LA, LC allowed");
+ }
+
+ if (dsp_a0exattr & DEFINED)
+ {
+ inst |= (dsp_a0exval & 0xff) << 8;
+ D_dsp(inst);
+ }
+ else
+ {
+ AddFixup(FU_DSPIMM8, sloc, dsp_a0expr);
+ D_dsp(inst);
+ }
+
+ return OK;
+}
+
+
+int dsp_imm12(LONG inst)
+{
+ if (dsp_a0exattr & DEFINED)
+ {
+ if ((dsp_am0 & (M_DSPIM12 | M_DSPIM8)) == 0)
+ return error("immediate out of range ($000-$fff)");
+ inst |= ((dsp_a0exval & 0x0ff) << 8) | ((dsp_a0exval & 0xf00) >> 8);
+ D_dsp(inst);
+ }
+ else
+ {
+ AddFixup(FU_DSPIMM12, sloc, dsp_a0expr);
+ D_dsp(inst);
+ }
+
+ return OK;
+}
+
+
+// Tcc instructions with 2 operands (48bit)
+int dsp_tcc2(LONG inst)
+{
+ if (dsp_a0reg == dsp_a1reg)
+ return error("First pair of source and destination registers must not be the same");
+
+ int inverse;
+ inverse = (dsp_a0reg & 7);
+ inverse = ((inverse & 1) << 1) | ((inverse & 2) >> 1) | (inverse & 4);
+ inst |= inverse << 4;
+ inst |= ((dsp_a1reg) & 1) << 3;
+ D_dsp(inst);
+
+ return OK;
+}
+
+
+// Tcc instructions with 4 operands
+int dsp_tcc4(LONG inst)
+{
+ if (dsp_a0reg == dsp_a1reg)
+ return error("First pair of source and destination registers must not be the same");
+
+ if (dsp_am2 != M_DSPR || dsp_am3 != M_DSPR)
+ return error("Second pair of source and destination registers must be R0-R7");
+
+ if (dsp_am0 == M_ACC56 && dsp_am1 == M_ACC56)
+ {
+ inst |= ((dsp_a0reg + 1) & 1) << 3;
+ }
+ else
+ {
+ int inverse;
+ inverse = (dsp_a0reg & 7);
+ inverse = ((inverse & 1) << 1) | ((inverse & 2) >> 1) | (inverse & 4);
+ inst |= inverse << 4;
+ inst |= ((dsp_a1reg) & 1) << 3;
+ }
+
+ inst |= 1 << 16;
+ inst |= (dsp_a2reg << 8) | (dsp_a3reg);
+ D_dsp(inst);
+
+ return OK;
+}
+
+
+// Just store ea
+int dsp_ea(LONG inst)
+{
+ inst |= dsp_a0reg << 8;
+
+ if (dsp_a0memspace != -1)
+ inst |= dsp_a0memspace;
+
+ if (dsp_am0 == M_DSPAA)
+ inst |= ((dsp_a0exval & 0x3f) << 8);
+
+ D_dsp(inst);
+
+ if (dsp_a0reg == DSP_EA_ABS)
+ {
+ if (dsp_a0exattr & DEFINED)
+ {
+ D_dsp(dsp_a0exval);
+ }
+ else
+ {
+ AddFixup(FU_DSPADR24, sloc, dsp_a0expr);
+ D_dsp(0);
+ }
+ }
+
+ return OK;
+}
+
+
+// Store ea and 5-bit constant
+int dsp_ea_imm5(LONG inst)
+{
+ if (dsp_a1memspace == -1)
+ return error("Only X: or Y: memory space allowed");
+
+ if (dsp_a0exattr & DEFINED)
+ {
+ int v = (int)dsp_a0exval;
+
+ if (v < 0 || v > 23)
+ return error("immediate value must be between 0 and 23");
+
+ if (dsp_a1reg == DSP_EA_ABS)
+ {
+ inst |= (v | dsp_a1memspace | (dsp_a1reg << 8));
+ }
+ else
+ {
+ inst |= ((dsp_a1exval & 0x3F) << 8) | v | dsp_a1memspace | (dsp_a1reg << 8);
+ }
+
+ D_dsp(inst);
+
+ if (dsp_a1reg == DSP_EA_ABS)
+ {
+ if (dsp_a1exattr & DEFINED)
+ {
+ D_dsp(dsp_a1exval);
+ }
+ else
+ {
+ AddFixup(FU_DSPADR24, sloc, dsp_a1expr);
+ D_dsp(0);
+ }
+ }
+ }
+ else
+ {
+ if (dsp_a1reg == DSP_EA_ABS)
+ {
+ inst |= dsp_a1memspace | (dsp_a1reg << 8);
+ }
+ else
+ {
+ inst |= ((dsp_a1exval & 0x3F) << 8) | dsp_a1memspace | (dsp_a1reg << 8);
+ }
+
+ AddFixup(FU_DSPIMM5, sloc, dsp_a0expr);
+ D_dsp(inst);
+
+ if (dsp_a1reg == DSP_EA_ABS)
+ {
+ if (dsp_a1exattr & DEFINED)
+ {
+ D_dsp(dsp_a1exval);
+ }
+ else
+ {
+ AddFixup(FU_DSPADR24, sloc, dsp_a1expr);
+ D_dsp(0);
+ }
+ }
+ }
+
+ return OK;
+}
+
+
+// Processes the input register according to table A-18 of the Motorola DSP
+// manual and returns the correct encoding.
+// Note: returns only the 3 lower bits of the table. The rest is handled in
+// dsp56ktab.
+static inline LONG tab_A18(int *am, int *reg)
+{
+ switch (*am)
+ {
+ case M_ALU24:
+ return (*reg & 7);
+ case M_DSPM:
+ case M_DSPN:
+ case M_DSPR:
+ return *reg;
+ break;
+ case M_ACC56:
+ case M_ACC24:
+ case M_ACC8:
+ if (*reg == KW_A1)
+ return 4;
+ else
+ return (*reg & 7);
+
+ break;
+ case M_DSPPCU:
+ switch (*reg)
+ {
+ case KW_SR: return 1; break;
+ case KW_OMR: return 2; break;
+ case KW_SP: return 3; break;
+ case KW_SSH: return 4; break;
+ case KW_SSL: return 5; break;
+ case KW_LA: return 6; break;
+ case KW_LC: return 7; break;
+ default:
+ return error("specified control register not allowed as destination");
+ break;
+ }
+
+ break;
+ default:
+ return error("reached at the end of tab_A18 - shouldn't happen!");
+ }
+}
+
+
+// Store register (table A-18 in the motorola manual) and 5-bit constant
+int dsp_reg_imm5(LONG inst)
+{
+ LONG reg;
+
+ if ((reg = tab_A18(&dsp_am1, &dsp_a1reg)) == ERROR)
+ return ERROR;
+
+ inst |= (reg << 8);
+
+ if (dsp_a0exattr & DEFINED)
+ {
+ int v = (int)dsp_a0exval;
+
+ if (v < 0 || v > 23)
+ return error("immediate value must be between 0 and 23");
+
+ inst |= v;
+ D_dsp(inst);
+ }
+ else
+ {
+ AddFixup(FU_DSPIMM5, sloc, dsp_a0expr);
+ D_dsp(inst);
+ }
+
+ return OK;
+}
+
+
+// Store 12-bit address
+int dsp_abs12(LONG inst)
+{
+ if (dsp_a0exattr & DEFINED)
+ {
+ int v = (int)dsp_a0exval;
+
+ if (v < 0 || v > 0xFFF)
+ return error("immediate out of range ($000-$FFF)");
+
+ inst |= v;
+ D_dsp(inst);
+ }
+ else
+ {
+ AddFixup(FU_DSPADR12, sloc, dsp_a0expr);
+ D_dsp(inst);
+ }
+
+ return OK;
+}
+
+
+// Manipulate expr to append a '-1'. Used specifically for DO.
+void append_minus_1(TOKEN * expr)
+{
+ // Find where the end of expression is
+ while (*expr != ENDEXPR)
+ {
+ if (*expr == SYMBOL || *expr == CONST || *expr == FCONST)
+ expr++;
+ else if (*expr == ACONST)
+ expr += 3;
+
+ expr++;
+ }
+
+ // Overwrite ENDEXPR and append '-1'
+ *expr++ = CONST;
+ uint64_t *expr64 = (uint64_t *)expr;
+ *expr64++ = 1;
+ expr = (uint32_t *)expr64;
+ *expr++ = '-';
+ *expr = ENDEXPR;
+}
+
+
+// Store a 12bit immediate and 16bit address.
+// Note: This function is specifically handling DO. DO has a requirement of
+// storing the address of a label minus 1! Quoting the manual:
+// "Note: The assembler calculates the end-of-loop address to be loaded
+// into LA (the absolute address extension word) by evaluating the end
+// -of-loop expression <expr> and subtracting one. This is done to
+// accommodate the case where the last word in the DO loop is a two-word
+// instruction. Thus, the end-of-loop expression <expr> in the source
+// code must represent the address of the instruction AFTER the last
+// instruction in the loop as shown in the example."
+// This is fine if we know the address already, but a problem when we
+// don't.
+int dsp_imm12_abs16(LONG inst)
+{
+ if (dsp_a0exattr & DEFINED)
+ {
+ if ((dsp_am0 & (M_DSPIM12 | M_DSPIM8)) == 0)
+ return error("immediate out of range ($000-$FFF)");
+
+ inst |= ((dsp_a0exval & 0x0FF) << 8) | ((dsp_a0exval & 0xF00) >> 8);
+ D_dsp(inst);
+ }
+ else
+ {
+ AddFixup(FU_DSPIMM12, sloc, dsp_a0expr);
+ D_dsp(inst);
+ }
+
+ if (dsp_a1exattr & DEFINED)
+ {
+ D_dsp((a1exval - 1));
+ }
+ else
+ {
+ append_minus_1(dsp_a1expr);
+ AddFixup(FU_DSPADR16, sloc, dsp_a1expr);
+ D_dsp(0);
+ }
+
+ return OK;
+}
+
+
+// Just store ea and 16bit address
+// Note: this function is specifically handling DO.
+// The same notes as dsp_imm12_abs16 apply here.
+int dsp_ea_abs16(LONG inst)
+{
+ if ((dsp_a0reg == DSP_EA_ABS && dsp_a0memspace == -1) || dsp_a1reg == DSP_EA_IMM)
+ return error("immediate values > 31 or absolute values not allowed");
+
+ if (dsp_a0exattr & DEFINED)
+ {
+ if (dsp_a0exval > 31)
+ return error("absolute address (aa) bigger than $1F");
+
+ inst |= dsp_a0exval << 8;
+ }
+
+ inst |= dsp_a0reg << 8;
+
+ if (dsp_a0memspace == -1)
+ return error("only X:, Y: address spaces allowed");
+
+ if ((deposit_extra_ea == DEPOSIT_EXTRA_FIXUP) || (dsp_a0reg == DSP_EA_ABS && dsp_am0 == M_DSPEA))
+ {
+ // Change instruction to aa instead of ea. TODO: check if this is true
+ // for all cases
+ inst = 0x060000;
+ inst |= dsp_a0memspace;
+
+ // Probably superfluous check (we're not likely to land here with a
+ // known aa) but oh well
+ if (!(dsp_a0exattr & DEFINED))
+ {
+ AddFixup(FU_DSPADR06, sloc, dsp_a0expr);
+ D_dsp(inst);
+ }
+ else
+ {
+ D_dsp(inst);
+ }
+ }
+ else
+ {
+ inst |= dsp_a0memspace;
+ D_dsp(inst);
+ }
+
+ if (dsp_a1exattr & DEFINED)
+ {
+ D_dsp((dsp_a1exval - 1));
+ }
+ else
+ {
+ append_minus_1(dsp_a1expr);
+ AddFixup(FU_DSPADR16, sloc, dsp_a1expr);
+ D_dsp(0);
+ }
+
+ return OK;
+}
+
+
+// Store register (table A-18 in the motorola manual) 5-bit constant and 16bit address
+// Note: this function is specifically handling DO.
+// The same notes as dsp_imm12_abs16 apply here.
+int dsp_reg_abs16(LONG inst)
+{
+ LONG reg;
+
+ if ((reg = tab_A18(&dsp_am0, &dsp_a0reg)) == ERROR)
+ return ERROR;
+
+ inst |= reg << 8;
+
+ if (dsp_a1exattr & DEFINED)
+ {
+ int v = (int)dsp_a1exval - 1;
+ D_dsp(inst);
+ D_dsp(v);
+ }
+ else
+ {
+ D_dsp(inst);
+ append_minus_1(dsp_a1expr);
+ AddFixup(FU_DSPADR16, sloc, dsp_a1expr);
+ D_dsp(0);
+ }
+
+ return OK;
+}
+
+
+// Store ALU24 register and 16bit address
+// Note: this function is specifically handling DO.
+// The same notes as dsp_imm12_abs16 apply here.
+int dsp_alu24_abs16(LONG inst)
+{
+ inst |= (dsp_a0reg & 7) << 8;
+
+ if (dsp_a1exattr & DEFINED)
+ {
+ int v = (int)dsp_a1exval - 1;
+ D_dsp(inst);
+ D_dsp(v);
+ }
+ else
+ {
+ D_dsp(inst);
+ append_minus_1(dsp_a1expr);
+ AddFixup(FU_DSPADR16, sloc, dsp_a1expr);
+ D_dsp(0);
+ }
+
+ return OK;
+}
+
+
+// Store register (table A-18 in the motorola manual)
+int dsp_reg(LONG inst)
+{
+ LONG reg;
+
+ if ((reg = tab_A18(&dsp_am0, &dsp_a0reg)) == ERROR)
+ return ERROR;
+
+ inst |= reg << 8;
+ D_dsp(inst);
+
+ return OK;
+}
+
+
+int dsp_alu24(LONG inst)
+{
+ inst |= (dsp_a0reg & 7) << 8;
+ D_dsp(inst);
+
+ return OK;
+}
+
+
+// Store register (table A-18 in the motorola manual) and 5-bit constant
+int dsp_reg_imm5_abs16(LONG inst)
+{
+ LONG reg;
+
+ // First, check that we have at best an 16bit absolute address in
+ // operand 3 since we don't check that anywhere else
+ if (dsp_a2exattr & DEFINED)
+ {
+ if ((dsp_am2 & C_DSPABS16) == 0)
+ return error("expected 16-bit address as third operand.");
+ }
+
+ if ((reg = tab_A18(&dsp_am1, &dsp_a1reg)) == ERROR)
+ return ERROR;
+
+ inst |= reg << 8;
+
+ if (dsp_a0exattr & DEFINED)
+ {
+ int v = (int)dsp_a0exval;
+
+ if (v < 0 || v > 23)
+ return error("immediate value must be between 0 and 23");
+
+ inst |= v;
+ D_dsp(inst);
+
+ if (dsp_a2exattr & DEFINED)
+ {
+ int v = (int)dsp_a2exval;
+ D_dsp(v);
+ }
+ else
+ {
+ AddFixup(FU_DSPADR16, sloc, dsp_a2expr);
+ D_dsp(0);
+ }
+ }
+ else
+ {
+ AddFixup(FU_DSPIMM5, sloc, dsp_a0expr);
+ D_dsp(inst);
+
+ if (dsp_a2exattr & DEFINED)
+ {
+ int v = (int)dsp_a2exval;
+ D_dsp(v);
+ }
+ else
+ {
+ AddFixup(FU_DSPADR16, sloc, dsp_a2expr);
+ D_dsp(0);
+ }
+ }
+
+ return OK;
+}
+
+
+// Store ea, 5-bit constant and 16-bit address in the extension word
+int dsp_ea_imm5_abs16(LONG inst)
+{
+ // First, check that we have at best an 16bit absolute address in
+ // operand 3 since we don't check that anywhere else
+ if (dsp_a2exattr&DEFINED)
+ {
+ if ((dsp_am2&C_DSPABS16) == 0)
+ return error("expected 16-bit address as third operand.");
+ }
+
+ if (dsp_a1memspace == -1)
+ return error("Only X: or Y: memory space allowed");
+
+ if (dsp_am1 == M_DSPAA)
+ {
+ if (dsp_a1exattr & DEFINED)
+ inst |= (dsp_a1exval & 0x3F) << 8;
+ else
+ AddFixup(FU_DSPADR06, sloc, dsp_a1expr);
+ }
+
+ if (dsp_am1 == M_DSPPP)
+ {
+ if (dsp_a1exattr & DEFINED)
+ inst |= (dsp_a1exval & 0x3f) << 8;
+ else
+ AddFixup(FU_DSPPP06, sloc, dsp_a1expr);
+ }
+
+ if (dsp_a0exattr & DEFINED)
+ {
+ int v = (int)dsp_a0exval;
+
+ if (v < 0 || v > 23)
+ return error("immediate value must be between 0 and 23");
+
+ inst |= (dsp_a1reg << 8) | v | dsp_a1memspace;
+ D_dsp(inst);
+
+ if (dsp_a2exattr & DEFINED)
+ {
+ int v = (int)dsp_a2exval;
+ D_dsp(v);
+ }
+ else
+ {
+ AddFixup(FU_DSPADR16, sloc, dsp_a2expr);
+ D_dsp(0);
+ }
+ }
+ else
+ {
+ inst |= (dsp_a1reg << 8) | dsp_a1memspace;
+ AddFixup(FU_DSPIMM5, sloc, dsp_a0expr);
+ D_dsp(inst);
+
+ if (dsp_a2exattr & DEFINED)
+ {
+ int v = (int)dsp_a2exval;
+ D_dsp(v);
+ }
+ else
+ {
+ AddFixup(FU_DSPADR16, sloc, dsp_a2expr);
+ D_dsp(0);
+ }
+ }
+
+ return OK;
+}
+
+
+int dsp_ea_lua(LONG inst)
+{
+ int am = dsp_a0reg & 0x38;
+
+ if (am != DSP_EA_POSTDEC && am != DSP_EA_POSTINC &&
+ am != DSP_EA_POSTDEC1 && am != DSP_EA_POSTINC1)
+ return error("addressing mode not allowed");
+
+ inst |= dsp_a0reg << 8;
+
+ if (dsp_am1 == M_DSPN)
+ inst |= 1 << 3;
+
+ inst |= dsp_a1reg;
+ D_dsp(inst);
+
+ return OK;
+}
+
+
+int dsp_ab_rn(LONG inst)
+{
+ inst |= (dsp_a1reg & 1) << 3;
+ inst |= (dsp_a0reg) << 8;
+ D_dsp(inst);
+
+ return OK;
+}
+
+
+int dsp_movec_ea(LONG inst)
+{
+ int ea = dsp_a1reg;
+ int memspace = dsp_a1memspace;
+ WORD exattr = dsp_a1exattr;
+ LONG exval = (uint32_t)dsp_a1exval;
+ TOKEN * expr = dsp_a1expr;
+ int reg = dsp_a0reg;
+ int am = dsp_am0;
+ int reg2 = dsp_a1reg;
+
+ if (dsp_am0 == M_DSPEA || (dsp_am0 & C_DSPIM))
+ {
+ ea = dsp_a0reg;
+ exattr = dsp_a0exattr;
+ exval = (uint32_t)dsp_a0exval;
+ memspace = dsp_a0memspace;
+ expr = dsp_a0expr;
+ reg = dsp_a1reg;
+ reg2 = dsp_a0reg;
+ am = dsp_am1;
+ }
+
+ // Abort if unsupported registers are requested
+ if (reg == KW_PC || reg == KW_MR || reg == KW_CCR)
+ return error("illegal registers for instruction.");
+
+ if (dsp_am0 & C_DSPIM)
+ memspace = 0;
+
+ if (memspace == -1)
+ return error("only x: or y: memory spaces allowed.");
+
+ // No memspace required when loading an immediate
+ if (dsp_am0 & C_DSPIM)
+ memspace = 0;
+
+ reg = tab_A18(&am, ®);
+ inst |= (ea << 8) | memspace | reg;
+
+ if (am == M_DSPPCU)
+ inst |= 3 << 3;
+
+ D_dsp(inst);
+
+ if (reg2 == DSP_EA_ABS || (dsp_am0 & C_DSPIM))
+ {
+ if (exattr & DEFINED)
+ {
+ int v = exval;
+ D_dsp(v);
+ }
+ else
+ {
+ if (dsp_am0 == M_DSPIM)
+ {
+ AddFixup(FU_DSPIMM24, sloc, expr);
+ D_dsp(0);
+ }
+ else
+ {
+ AddFixup(FU_DSPADR24, sloc, expr);
+ D_dsp(0);
+ }
+ }
+ }
+
+ return OK;
+}
+
+
+int dsp_movec_aa(LONG inst)
+{
+ int ea = dsp_a1reg;
+ int memspace = dsp_a1memspace;
+ WORD exattr = dsp_a1exattr;
+ LONG exval = (uint32_t)dsp_a1exval;
+ TOKEN * expr = dsp_a1expr;
+ int reg = dsp_a0reg;
+ int am = dsp_am0;
+ int reg2 = dsp_a1reg;
+
+ if (dsp_am0 == M_DSPAA)
+ {
+ ea = dsp_a0reg;
+ exattr = dsp_a0exattr;
+ exval = (uint32_t)dsp_a0exval;
+ memspace = dsp_a0memspace;
+ expr = dsp_a0expr;
+ reg = dsp_a1reg;
+ reg2 = dsp_a0reg;
+ am = dsp_am1;
+ }
+
+ // Abort if unsupported registers are requested
+ if (reg == KW_PC || reg == KW_MR || reg == KW_CCR)
+ return error("PC, MR, CCR are illegal registers for this instruction.");
+
+ if (memspace == -1)
+ return error("only x: or y: memory spaces allowed.");
+
+ reg = tab_A18(&am, ®);
+ inst |= (ea << 8) | memspace | reg;
+
+ if (am == M_DSPPCU)
+ inst |= 3 << 3;
+
+ if (exattr & DEFINED)
+ {
+ inst |= exval << 8;
+ D_dsp(inst);
+ }
+ else
+ {
+ AddFixup(FU_DSPADR06, sloc, expr);
+ D_dsp(inst);
+ }
+
+ return OK;
+}
+
+
+int dsp_movec_reg(LONG inst)
+{
+ int am0 = dsp_am0;
+ int am1 = dsp_am1;
+
+ // Abort if unsupported registers are requested
+ if (dsp_a0reg == KW_PC || dsp_a0reg == KW_MR || dsp_a0reg == KW_CCR ||
+ dsp_a1reg == KW_PC || dsp_a1reg == KW_MR || dsp_a1reg == KW_CCR)
+ return error("PC, MR, CCR are illegal registers for this instruction.");
+
+ int reg1 = tab_A18(&dsp_am0, &dsp_a0reg);
+ int reg2 = tab_A18(&dsp_am1, &dsp_a1reg);
+
+ if (inst & (1 << 15))
+ {
+ // S1,D2
+ }
+ else
+ {
+ // S2,D1
+ int temp = am0;
+ am0 = am1;
+ am1 = temp;
+ temp = reg1;
+ reg1 = reg2;
+ reg2 = temp;
+ }
+
+ switch (am0)
+ {
+ case M_ALU24: reg1 |= 0x00; break;
+ case M_ACC8:
+ case M_ACC24: reg1 |= 0x08; break;
+ case M_ACC56: reg1 |= 0x0E; break;
+ case M_DSPR: reg1 |= 0x10; break;
+ case M_DSPN: reg1 |= 0x18; break;
+ case M_DSPM: reg1 |= 0x20; break;
+ case M_DSPPCU: reg1 |= 0x38; break;
+ default:
+ return error("reached the end of dsp_movec_reg case 1 - should not happen!");
+ }
+
+ switch (am1)
+ {
+ case M_DSPM: reg2 |= 0x00; break;
+ case M_DSPPCU: reg2 |= 0x18; break;
+ default:
+ return error("reached the end of dsp_movec_reg case 2 - should not happen!");
+ }
+
+ inst |= (reg1 << 8) | reg2;
+ D_dsp(inst);
+
+ return OK;
+}
+
+
+int dsp_mult(LONG inst)
+{
+ if (dsp_am2 != M_ACC56)
+ return error("only A or B allowed as third operand.");
+
+ switch (((dsp_a0reg & 3) << 2) + (dsp_a1reg & 3))
+ {
+ case (0 << 2) + 0: inst |= 0 << 4; break; // x0 x0
+ case (2 << 2) + 2: inst |= 1 << 4; break; // y0 y0
+ case (1 << 2) + 0: inst |= 2 << 4; break; // x1 x0
+ case (0 << 2) + 1: inst |= 2 << 4; break; // x0 x1
+ case (3 << 2) + 2: inst |= 3 << 4; break; // y1 y0
+ case (2 << 2) + 3: inst |= 3 << 4; break; // y0 y1
+ case (0 << 2) + 3: inst |= 4 << 4; break; // x0 y1
+ case (3 << 2) + 0: inst |= 4 << 4; break; // y1 x0
+ case (2 << 2) + 0: inst |= 5 << 4; break; // y0 x0
+ case (0 << 2) + 2: inst |= 5 << 4; break; // x0 y0
+ case (1 << 2) + 2: inst |= 6 << 4; break; // x1 y0
+ case (2 << 2) + 1: inst |= 6 << 4; break; // y0 x1
+ case (3 << 2) + 1: inst |= 7 << 4; break; // y1 x1
+ case (1 << 2) + 3: inst |= 7 << 4; break; // x1 y1
+ default:
+ return error("x0/y0/x1/y1 combination not allowed for multiplication.");
+ }
+
+ if (dsp_a2reg == KW_B)
+ inst |= 1 << 3;
+
+ inst |= dsp_k;
+ D_dsp(inst);
+ dsp_extra_ea(); // Deposit effective address if needed
+
+ return OK;
+}
+
+
+int dsp_movem_ea(LONG inst)
+{
+ int ea = dsp_a1reg;
+ int memspace = dsp_a0memspace;
+ WORD exattr = dsp_a1exattr;
+ LONG exval = (uint32_t)dsp_a1exval;
+ TOKEN * expr = dsp_a1expr;
+ int reg = dsp_a0reg;
+ int am = dsp_am0;
+ int reg2 = dsp_a1reg;
+
+ if (dsp_am0 == M_DSPEA || dsp_am0 == M_DSPIM)
+ {
+ ea = dsp_a0reg;
+ exattr = dsp_a0exattr;
+ exval = (uint32_t)dsp_a0exval;
+ memspace = dsp_a0memspace;
+ expr = dsp_a0expr;
+ reg = dsp_a1reg;
+ reg2 = dsp_a0reg;
+ am = dsp_am1;
+ inst |= 1 << 15;
+ }
+
+ // Abort if unsupported registers are requested
+ if (reg == KW_PC || reg == KW_MR || reg == KW_CCR)
+ return error("illegal registers for instruction.");
+
+ if (memspace != -1)
+ return error("only p: memory space allowed.");
+
+ reg = tab_A18(&am, ®);
+ inst |= (ea << 8) | reg;
+
+ if (am == M_DSPPCU)
+ inst |= 3 << 3;
+
+ D_dsp(inst);
+
+ if (reg2 == DSP_EA_ABS || dsp_am0 == M_DSPIM)
+ {
+ if (exattr & DEFINED)
+ {
+ int v = exval;
+ D_dsp(v);
+ }
+ else
+ {
+ if (dsp_am0 == M_DSPIM)
+ {
+ AddFixup(FU_DSPIMM24, sloc, expr);
+ D_dsp(0);
+ }
+ else
+ {
+ AddFixup(FU_DSPADR24, sloc, expr);
+ D_dsp(0);
+ }
+ }
+ }
+
+ return OK;
+}
+
+
+int dsp_movem_aa(LONG inst)
+{
+ int ea = dsp_a1reg;
+ int memspace = dsp_a1memspace;
+ WORD exattr = dsp_a1exattr;
+ LONG exval = (uint32_t)dsp_a1exval;
+ TOKEN * expr = dsp_a1expr;
+ int reg = dsp_a0reg;
+ int am = dsp_am0;
+ int reg2 = dsp_a1reg;
+
+ if (dsp_am0 == M_DSPAA)
+ {
+ ea = dsp_a0reg;
+ exattr = dsp_a0exattr;
+ exval = (uint32_t)dsp_a0exval;
+ memspace = dsp_a0memspace;
+ expr = dsp_a0expr;
+ reg = dsp_a1reg;
+ reg2 = dsp_a0reg;
+ am = dsp_am1;
+ }
+
+ // Abort if unsupported registers are requested
+ if (reg == KW_PC || reg == KW_MR || reg == KW_CCR)
+ return error("PC, MR, CCR are illegal registers for this instruction.");
+
+ if (memspace != -1)
+ return error("only p: memory space allowed.");
+
+ reg = tab_A18(&am, ®);
+ inst |= (ea << 8) | reg;
+
+ if (am == M_DSPPCU)
+ inst |= 3 << 3;
+
+ if (exattr & DEFINED)
+ {
+ inst |= exval << 8;
+ D_dsp(inst);
+ }
+ else
+ {
+ AddFixup(FU_DSPADR06, sloc, expr);
+ D_dsp(inst);
+ }
+
+ return OK;
+}
+
+
+int dsp_movep_ea(LONG inst)
+{
+ // movep doesn't allow any aa modes but we might detect this during amode
+ // detection. No worries, just change it to ea with extra address instead
+ if (dsp_am0 == M_DSPAA)
+ {
+ dsp_a0reg = DSP_EA_ABS;
+ dsp_a1reg = 0;
+ }
+ if (dsp_am1 == M_DSPAA)
+ {
+ dsp_a0reg = 0;
+ dsp_a1reg = DSP_EA_ABS;
+ }
+
+ // So we might encounter something like 'movep x:pp,x:pp' which we
+ // obviously flagged as M_DSPPP during ea parsing. In this case we give up
+ // and declare the second term as a classic absolute address (we chop off
+ // the high bits too) and let the routine treat is as such. At least that's
+ // what Motorola's assembler seems to be doing.
+ if (dsp_am0 == M_DSPPP && dsp_am1 == M_DSPPP)
+ {
+ dsp_am1 = DSP_EA_ABS;
+ dsp_a1reg = DSP_EA_ABS;
+ dsp_a1exval &= 0xFFFF;
+ }
+
+ // Assume first operand is :pp
+ int ea = dsp_a1reg;
+ int memspace = dsp_a1memspace;
+ int perspace = dsp_a0perspace;
+ WORD exattr = dsp_a1exattr;
+ WORD exattr2 = dsp_a0exattr;
+ LONG exval = (uint32_t)dsp_a1exval;
+ LONG exval2 = (uint32_t)dsp_a0exval;
+ TOKEN * expr = dsp_a1expr;
+ TOKEN * expr2 = dsp_a0expr;
+ int reg = dsp_a0reg;
+ int am = dsp_am0;
+ int reg2 = dsp_a1reg;
+
+ if (dsp_am1 == M_DSPPP)
+ {
+ ea = dsp_a0reg;
+ exattr = dsp_a0exattr;
+ exattr2 = dsp_a1exattr;
+ exval = (uint32_t)dsp_a0exval;
+ exval2 = (uint32_t)dsp_a1exval;
+ memspace = dsp_a0memspace;
+ perspace = dsp_a1perspace;
+ expr = dsp_a0expr;
+ expr2 = dsp_a1expr;
+ reg = dsp_a1reg;
+ reg2 = dsp_a0reg;
+ am = dsp_am1;
+ }
+
+ if (dsp_a0perspace == -1 && dsp_a1perspace == -1)
+ {
+ // Ok, so now we have to guess which of the two parameters is X:pp or
+ // Y:pp. This happened because we didn't get a << marker in any of the
+ // addressing modes
+ if (((dsp_a0exattr | dsp_a1exattr) & DEFINED) == 0)
+ // You have got to be shitting me...
+ // One way to deal with this (for example X:ea,X:pp / X:pp,X:ea
+ // aliasing would be to check number ranges and see which one is
+ // negative. ...unless one of the two isn't known during this phase
+ return error("internal assembler error: could not deduce movep syntax");
+
+ if (dsp_a0exattr & DEFINED)
+ {
+ if (dsp_a0exval >= 0xFFC0 && dsp_a0exval <= 0xFFFF)
+ {
+ // First operand is :pp - do nothing
+ perspace = dsp_a0memspace << 10;
+ // When the source contains a << then we bolt on the :pp
+ // address during ea parsing, but since we couldn't recognise
+ // the addressing mode in this case let's just insert it right
+ // now...
+ reg |= (dsp_a0exval & 0x3F);
+ }
+ }
+
+ if (dsp_a1exattr & DEFINED)
+ {
+ if (dsp_a1exval >= 0xFFC0 && dsp_a1exval <= 0xFFFF)
+ {
+ ea = dsp_a0reg;
+ exattr = dsp_a0exattr;
+ exval = (uint32_t)dsp_a0exval;
+ memspace = dsp_a0memspace;
+ perspace = dsp_a1memspace << 10;
+ expr = dsp_a0expr;
+ reg = dsp_a0reg;
+ reg2 = dsp_a1reg;
+ am = dsp_am1;
+ // See above
+ reg |= (dsp_a1exval & 0x3F);
+ }
+ }
+
+ if (perspace == -1)
+ // You have got to be shitting me (twice)...
+ return error("internal assembler error: could not deduce movep syntax");
+ }
+
+ inst |= reg | (ea << 8) | perspace; // reg contains memory space
+
+ if ((dsp_am0 & (M_DSPIM | M_DSPIM8 | M_DSPIM12)) == 0)
+ {
+ if (memspace == -1)
+ {
+ inst &= ~(1 << 7);
+ inst |= 1 << 6;
+ }
+ else
+ inst |= memspace;
+ }
+
+ if (am == M_DSPPP)
+ {
+ if (exattr2&DEFINED)
+ {
+ inst |= (exval2 & 0x3F);
+ D_dsp(inst);
+ }
+ else
+ {
+ AddFixup(FU_DSPIMM5, sloc, expr2);
+ D_dsp(inst);
+ }
+ }
+ else
+ {
+ D_dsp(inst);
+ }
+
+ if (dsp_am0 & (M_DSPIM | M_DSPIM8 | M_DSPIM12))
+ {
+ if (dsp_a0exattr & DEFINED)
+ {
+ int v = (int)dsp_a0exval;
+ D_dsp(v);
+ }
+ else
+ {
+ AddFixup(FU_DSPADR16, sloc, dsp_a0expr);
+ D_dsp(0);
+ }
+ }
+ else if (reg2 == DSP_EA_ABS)
+ {
+ if (exattr & DEFINED)
+ {
+ int v = exval;
+ D_dsp(v);
+ }
+ else
+ {
+ AddFixup(FU_DSPADR24, sloc, expr);
+ D_dsp(0);
+ }
+ }
+
+ return OK;
+}
+
+
+int dsp_movep_reg(LONG inst)
+{
+ // Assume first operand is :pp
+ int ea = dsp_a0reg;
+ int memspace = dsp_a0memspace;
+ int perspace = dsp_a0perspace;
+ WORD exattr = dsp_a1exattr;
+ LONG exval = (uint32_t)dsp_a1exval;
+ TOKEN * expr = dsp_a1expr;
+ int reg = dsp_a0reg;
+ int am = dsp_am1;
+ int reg2 = dsp_a1reg;
+
+ if (dsp_am1 == M_DSPPP)
+ {
+ ea = dsp_a1reg;
+ exattr = dsp_a0exattr;
+ exval = (uint32_t)dsp_a0exval;
+ memspace = dsp_a1memspace;
+ perspace = dsp_a1perspace;
+ expr = dsp_a0expr;
+ reg = dsp_a1reg;
+ reg2 = dsp_a0reg;
+ am = dsp_am0;
+ }
+
+ // Abort if unsupported registers are requested
+ if (reg == KW_PC || reg == KW_MR || reg == KW_CCR)
+ return error("illegal registers for instruction.");
+
+ reg2 = tab_A18(&am, ®2);
+ inst |= (reg2 << 8) | reg;
+
+ if (perspace == -1)
+ return error("only x: or y: memory space allowed.");
+ else
+ inst |= perspace;
+
+ D_dsp(inst);
+
+ if (reg2 == DSP_EA_ABS)
+ {
+ if (exattr & DEFINED)
+ {
+ int v = exval;
+ D_dsp(v);
+ }
+ else
+ {
+ AddFixup(FU_DSPADR24, sloc, expr);
+ D_dsp(0);
+ }
+ }
+
+ return OK;
+}
+
--- /dev/null
+//
+// RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
+// DSP56L_MACH.C - Code Generation for Motorola DSP56001
+// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends
+// RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
+// Source utilised with the kind permission of Landon Dyer
+//
+
+#ifndef __DSP56KMACH_H__
+#define __DSP56KMACH_H__
+
+#include "rmac.h"
+#include "dsp56k_amode.h"
+
+// Exported variables
+extern MNTABDSP dsp56k_machtab[];
+extern unsigned int dsp_orgaddr;
+extern unsigned int dsp_orgseg;
+
+// Exported functions
+extern int dsp_mult(LONG inst);
+
+#endif // __DSP56KMACH_H__
+
--- /dev/null
+//
+// RMAC - Reboot's Macro Assembler for all Atari computers
+// 68KGEN.C - Tool to Generate 68000 Opcode Table
+// Copyright (C) 199x Landon Dyer, 2011-2018 Reboot and Friends
+// RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
+// Source utilised with the kind permission of Landon Dyer
+//
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+
+#define EOS '\0'
+
+int kwnum = 1; /* current op# for kwgen output */
+FILE * kfp; /* keyword file */
+int lineno = 0;
+
+// Function prototypes
+void error(char *, char *);
+void procln(int, char **);
+
+
+int main(int argc, char ** argv)
+{
+ char * namv[256];
+ char * s;
+ int namcnt;
+ char ln[256];
+
+ if ((argc == 2) && ((kfp = fopen(argv[1], "w")) == NULL))
+ error("Cannot create: %s", argv[1]);
+
+ while (fgets(ln, 256, stdin) != NULL)
+ {
+ lineno++; /* bump line# */
+
+ if (*ln == '#') /* ignore comments */
+ continue;
+
+ /*
+ * Tokenize line (like the way "argc, argv" works)
+ * and pass it to the parser.
+ */
+ namcnt = 0;
+ s = ln;
+
+ while (*s)
+ {
+ if (isspace(*s))
+ ++s;
+ else
+ {
+ namv[namcnt++] = s;
+
+ while (*s && !isspace(*s))
+ s++;
+
+ if (isspace(*s))
+ *s++ = EOS;
+ }
+ }
+
+ if (namcnt)
+ procln(namcnt, namv);
+ }
+
+ return 0;
+}
+
+
+//
+// Parse line
+//
+void procln(int namc, char ** namv)
+{
+ int i, j;
+
+ // alias for previous entry
+ if (namc == 1)
+ {
+ fprintf(kfp, "%s\t%d\n", namv[0], kwnum - 1 + 2000);
+ return;
+ }
+
+ if (namc < 5)
+ {
+ fprintf(stderr, "%d: missing fields\n", lineno);
+ exit(1);
+ }
+
+ // output keyword name
+ if (*namv[0] != '-')
+ fprintf(kfp, "%s\t%d\n", namv[0], kwnum + 2000);
+
+ printf("/*%4d %-6s*/ {", kwnum, namv[0]);
+
+ printf("%s, %s, %s, ", namv[1], namv[2], namv[3]);
+
+ // enforce little fascist percent signs
+ if (*namv[4] == '%')
+ {
+ for(i=1, j=0; i<25; i++)
+ {
+ j <<= 1;
+
+ if (namv[4][i] == '1' || isupper(namv[4][i]))
+ j++;
+ }
+
+ printf("0x%06x, ", j);
+ }
+ else
+ printf("%s, ", namv[4]);
+
+ if (namc >= 7 && *namv[6] == '+')
+ printf("%d, ", kwnum + 1);
+ else
+ printf("0, ");
+
+ printf("%s},\n", namv[5]);
+
+ kwnum++;
+}
+
+
+void error(char * s, char * s1)
+{
+ fprintf(stderr, s, s1);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
CR_STREQ, CR_MACDEF,
CR_DATE, CR_TIME,
CR_ABSCOUNT, 0,
- '!', '~', UNMINUS, 0, // UNARY
+ '!', '~', UNMINUS, UNLT, UNGT, 0, // UNARY
'*', '/', '%', 0, // MULT
'+', '-', 0, // ADD
SHL, SHR, 0, // SHIFT
const char missym_error[] = "missing symbol";
const char str_error[] = "missing symbol or string";
+const char noflt_error[] = "operator not usable with float";
// Convert expression to postfix
static PTR evalTokenBuffer; // Deposit tokens here (this is really a
//
int expr1(void)
{
- TOKEN t;
- SYM * sy;
- char * p, * p2;
+ char * p;
WORD w;
- int j;
int class = tokenClass[*tok];
- if (*tok == '-' || *tok == '+' || class == UNARY)
+ if (*tok == '-' || *tok == '+' || *tok == '<' || *tok == '>' || class == UNARY)
{
- t = *tok++;
+ TOKEN t = *tok++;
if (expr2() != OK)
return ERROR;
if (t == '-')
t = UNMINUS;
+ else if (t == '<')
+ t = UNLT;
+ else if (t == '>')
+ t = UNGT;
// With leading + we don't have to deposit anything to the buffer
// because there's no unary '+' nor we have to do anything about it
return error(missym_error);
p = string[*tok++];
- j = (*p == '.' ? curenv : 0);
- w = ((sy = lookup(p, LABEL, j)) != NULL && (sy->sattr & w) ? 1 : 0);
+ int j = (*p == '.' ? curenv : 0);
+ SYM * sy = lookup(p, LABEL, j);
+ w = ((sy != NULL) && (sy->sattr & w ? 1 : 0));
*evalTokenBuffer.u32++ = CONST;
*evalTokenBuffer.u64++ = (uint64_t)w;
break;
if (*tok != SYMBOL && *tok != STRING)
return error(str_error);
- p2 = string[tok[1]];
+ char * p2 = string[tok[1]];
tok += 2;
w = (WORD)(!strcmp(p, p2));
//
int expr2(void)
{
- char * p;
- SYM * sy;
- int j;
PTR ptk;
switch (*tok++)
tok = ptk.u32;
break;
case SYMBOL:
- p = string[*tok++];
- j = (*p == '.' ? curenv : 0);
- sy = lookup(p, LABEL, j);
+ {
+ char * p = string[*tok++];
+ int j = (*p == '.' ? curenv : 0);
+ SYM * sy = lookup(p, LABEL, j);
if (sy == NULL)
sy = NewSymbol(p, LABEL, j);
symbolPtr[symbolNum] = sy;
symbolNum++;
break;
+ }
case STRING:
*evalTokenBuffer.u32++ = CONST;
*evalTokenBuffer.u64++ = str_value(string[*tok++]);
tok += 2;
}
+ // Holy hell... This is likely due to the fact that LSR is mistakenly set as a SUNARY type... Need to fix this... !!! FIX !!!
+ else if (m6502)
+ {
+ *evalTokenBuffer.u32++ = *tok++;
+ }
else
{
// Unknown type here... Alert the user!,
- error("undefined RISC register in expression");
+ error("undefined RISC register in expression [token=$%X]", *tok);
// Prevent spurious error reporting...
tok++;
return ERROR;
break;
+ case UNLT: // Unary < (get the low byte of a word)
+//printf("evexpr(): UNLT\n");
+ if (*sattr & TDB)
+ return error(seg_error);
+
+ if (*sattr & FLOAT)
+ return error(noflt_error);
+
+ *sval = (int64_t)((*sval) & 0x00FF);
+ *sattr = ABS | DEFINED; // Expr becomes absolute
+ break;
+
+ case UNGT: // Unary > (get the high byte of a word)
+//printf("evexpr(): UNGT\n");
+ if (*sattr & TDB)
+ return error(seg_error);
+
+ if (*sattr & FLOAT)
+ return error(noflt_error);
+
+ *sval = (int64_t)(((*sval) >> 8) & 0x00FF);
+ *sattr = ABS | DEFINED; // Expr becomes absolute
+ break;
+
case '!':
//printf("evexpr(): !\n");
if (*sattr & TDB)
fp5 229
fp6 230
fp7 231
-mr 272
-omr 273
-la 274
-lc 275
-ssh 276
-ssl 277
-ss 278
.equ 61
equ 61
date 121
abscount 122
+x0 260
+x1 261
+y0 262
+y1 263
+b0 265
+b2 267
+b1 269
+a 270
+b 271
+n0 280
+n1 281
+n2 282
+n3 283
+n4 284
+n5 285
+n6 286
+n7 287
+m0 288
+m1 289
+m2 290
+m3 291
+m4 292
+m5 293
+m6 294
+m7 295
+mr 304
+omr 305
+la 306
+lc 307
+ssh 308
+ssl 309
+ss 310
+
+l 302
+p 303
+
+a10 312
+b10 313
+x 314
+y 315
+ab 318
+ba 319
#
-# RMAC - Reboot's Macro Assembler for the Atari Jaguar
-# Copyright (C) 199x Landon Dyer, 2011 Reboot & Friends
+# RMAC - Reboot's Macro Assembler for all Atari computers
+# Copyright (C) 199x Landon Dyer, 2011-2018 Reboot & Friends
# MAKEFILE for *nix
#
endif
-rm = /bin/rm -f
+RM = /bin/rm -f
CC = $(CROSS)gcc
HOSTCC = gcc
#CFLAGS = -std=$(STD) -D_DEFAULT_SOURCE -g -D__GCCUNIX__ -I. -O2 -MMD
CFLAGS = -std=$(STD) -D_DEFAULT_SOURCE -g -D__GCCUNIX__ -I. -O2
-SRCS = 6502.c amode.c debug.c direct.c eagen.c error.c expr.c fltpoint.c listing.c mach.c macro.c mark.c object.c op.c procln.c riscasm.c rmac.c sect.c symbol.c token.c
-
-OBJS = 6502.o amode.o debug.o direct.o eagen.o error.o expr.o fltpoint.o listing.o mach.o macro.o mark.o object.o op.o procln.o riscasm.o rmac.o sect.o symbol.o token.o
+OBJS = 6502.o amode.o debug.o direct.o dsp56k.o dsp56k_amode.o dsp56k_mach.o eagen.o error.o expr.o fltpoint.o listing.o mach.o macro.o mark.o object.o op.o procln.o riscasm.o rmac.o sect.o symbol.o token.o
#
# Build everything
#
-all : mntab.h 68ktab.h kwtab.h risckw.h 6502kw.h opkw.h rmac
+#all: mntab.h 68ktab.h kwtab.h risckw.h 6502kw.h opkw.h dsp56ktab.h rmac
+all: rmac
@echo
@echo "Don't forget to bump the version number before commiting!"
@echo
# definitions
#
-mntab.h : mntab 68kmn kwgen
- cat mntab 68kmn | ./kwgen mn >mntab.h
+68ktab.h 68k.tab: 68k.mch 68kgen
+ ./68kgen 68k.tab <68k.mch >68ktab.h
+
+dsp56ktab.h dsp56k.tab: dsp56k.mch dsp56kgen
+ ./dsp56kgen dsp56k.tab <dsp56k.mch >dsp56ktab.h
-68ktab.h 68kmn : 68ktab 68ktab 68kgen
- ./68kgen 68kmn <68ktab >68ktab.h
+mntab.h: direct.tab 68k.tab kwgen
+ cat direct.tab 68k.tab | ./kwgen mn >mntab.h
-kwtab.h : kwtab kwgen
- ./kwgen kw <kwtab >kwtab.h
+kwtab.h: kw.tab kwgen
+ ./kwgen kw <kw.tab >kwtab.h
-6502kw.h : 6502.tbl kwgen
- ./kwgen mp <6502.tbl >6502kw.h
+6502kw.h: 6502.tab kwgen
+ ./kwgen mp <6502.tab >6502kw.h
-risckw.h : kwtab kwgen
- ./kwgen mr <risctab >risckw.h
+risckw.h: risc.tab kwgen
+ ./kwgen mr <risc.tab >risckw.h
-opkw.h : op.tab kwgen
+opkw.h: op.tab kwgen
./kwgen mo <op.tab >opkw.h
+# Looks like this is not needed...
+dsp56kkw.h: dsp56k.tab kwgen
+ ./kwgen dsp <dsp56k.tab >dsp56kkw.h
+
#
# Build tools
#
-kwgen.o : kwgen.c
- $(HOSTCC) $(CFLAGS) -c kwgen.c
-
-kwgen : kwgen.o
- $(HOSTCC) $(CFLAGS) -o kwgen kwgen.o
-
-68kgen.o : 68kgen.c
- $(HOSTCC) $(CFLAGS) -c 68kgen.c
-
-68kgen : 68kgen.o
- $(HOSTCC) $(CFLAGS) -o 68kgen 68kgen.o
+%gen: %gen.c
+ $(HOSTCC) $(CFLAGS) -c $<
+ $(HOSTCC) $(CFLAGS) -o $*gen $<
#
# Build RMAC executable
#
-6502.o : 6502.c 6502.h
- $(CC) $(CFLAGS) -c 6502.c
-
-amode.o : amode.c amode.h
- $(CC) $(CFLAGS) -c amode.c
-
-debug.o : debug.c debug.h
- $(CC) $(CFLAGS) -c debug.c
-
-direct.o : direct.c direct.h
- $(CC) $(CFLAGS) -c direct.c
-
-eagen.o : eagen.c eagen.h eagen0.c
- $(CC) $(CFLAGS) -c eagen.c
-
-error.o : error.c error.h
- $(CC) $(CFLAGS) -c error.c
-
-expr.o : expr.c expr.h
- $(CC) $(CFLAGS) -c expr.c
-
-fltpoint.o : fltpoint.c fltpoint.h
- $(CC) $(CFLAGS) -c fltpoint.c
-
-listing.o : listing.c listing.h
- $(CC) $(CFLAGS) -c listing.c
-
-mach.o : mach.c mach.h
- $(CC) $(CFLAGS) -c mach.c
-
-macro.o : macro.c macro.h
- $(CC) $(CFLAGS) -c macro.c
-
-mark.o : mark.c mark.h
- $(CC) $(CFLAGS) -c mark.c
-
-object.o : object.c object.h
- $(CC) $(CFLAGS) -c object.c
-
-op.o : op.c op.h
- $(CC) $(CFLAGS) -c op.c
-
-procln.o : procln.c procln.h
- $(CC) $(CFLAGS) -c procln.c
-
-riscasm.o : riscasm.c riscasm.h
- $(CC) $(CFLAGS) -c riscasm.c
-
-rmac.o : rmac.c rmac.h
- $(CC) $(CFLAGS) -c rmac.c
-
-sect.o : sect.c sect.h
- $(CC) $(CFLAGS) -c sect.c
-
-symbol.o : symbol.c symbol.h
- $(CC) $(CFLAGS) -c symbol.c
-
-token.o : token.c token.h
- $(CC) $(CFLAGS) -c token.c
+%.o: %.c %.h
+ $(CC) $(CFLAGS) -c $<
-rmac : $(OBJS)
+rmac: $(OBJS)
$(CC) $(CFLAGS) -o rmac $(OBJS) -lm
#
#
clean:
- $(rm) $(OBJS) kwgen.o 68kgen.o rmac kwgen 68kgen kwtab.h 68ktab.h mntab.h risckw.h 6502kw.h opkw.h
+ $(RM) $(OBJS) kwgen.o 68kgen.o rmac kwgen 68kgen 68k.tab kwtab.h 68ktab.h mntab.h risckw.h 6502kw.h opkw.h dsp56kgen dsp56kgen.o dsp56k.tab dsp56kkw.h dsp56ktab.h
#
# Dependencies
#
6502.o: 6502.c direct.h rmac.h symbol.h token.h expr.h error.h mach.h \
- procln.h riscasm.h sect.h
-68kgen.o: 68kgen.c
+ procln.h riscasm.h sect.h kwtab.h
+68kgen: 68kgen.c
amode.o: amode.c amode.h rmac.h symbol.h error.h expr.h mach.h procln.h \
- token.h sect.h kwtab.h mntab.h parmode.h
+ token.h sect.h riscasm.h kwtab.h mntab.h parmode.h
debug.o: debug.c debug.h rmac.h symbol.h amode.h direct.h token.h expr.h \
- mark.h sect.h
+ mark.h sect.h riscasm.h
direct.o: direct.c direct.h rmac.h symbol.h token.h 6502.h amode.h \
error.h expr.h fltpoint.h listing.h mach.h macro.h mark.h procln.h \
riscasm.h sect.h kwtab.h
+dsp56k.o: dsp56k.c rmac.h symbol.h dsp56k.h sect.h riscasm.h
+dsp56k_amode.o: dsp56k_amode.c dsp56k_amode.h rmac.h symbol.h amode.h \
+ error.h token.h expr.h procln.h sect.h riscasm.h kwtab.h mntab.h
+dsp56k_mach.o: dsp56k_mach.c dsp56k_mach.h rmac.h symbol.h dsp56k_amode.h \
+ amode.h direct.h token.h dsp56k.h sect.h riscasm.h error.h kwtab.h \
+ dsp56ktab.h
+dsp56kgen: dsp56kgen.c
eagen.o: eagen.c eagen.h rmac.h symbol.h amode.h error.h fltpoint.h \
mach.h mark.h riscasm.h sect.h token.h eagen0.c
error.o: error.c error.h rmac.h symbol.h listing.h token.h
expr.o: expr.c expr.h rmac.h symbol.h direct.h token.h error.h listing.h \
mach.h procln.h riscasm.h sect.h kwtab.h
fltpoint.o: fltpoint.c fltpoint.h
-kwgen.o: kwgen.c
+kwgen: kwgen.c
listing.o: listing.c listing.h rmac.h symbol.h error.h procln.h token.h \
- sect.h version.h
+ sect.h riscasm.h version.h
mach.o: mach.c mach.h rmac.h symbol.h amode.h direct.h token.h eagen.h \
error.h expr.h procln.h riscasm.h sect.h kwtab.h 68ktab.h
macro.o: macro.c macro.h rmac.h symbol.h debug.h direct.h token.h error.h \
mark.o: mark.c mark.h rmac.h symbol.h error.h object.h riscasm.h sect.h
object.o: object.c object.h rmac.h symbol.h 6502.h direct.h token.h \
error.h mark.h riscasm.h sect.h
-op.o: op.c op.h rmac.h symbol.h direct.h token.h error.h expr.h \
- fltpoint.h mark.h procln.h riscasm.h sect.h
+op.o: op.c op.h direct.h rmac.h symbol.h token.h error.h expr.h \
+ fltpoint.h mark.h procln.h riscasm.h sect.h opkw.h
procln.o: procln.c procln.h rmac.h symbol.h token.h 6502.h amode.h \
- direct.h error.h expr.h listing.h mach.h macro.h op.h riscasm.h sect.h \
- kwtab.h mntab.h risckw.h 6502kw.h opkw.h
+ direct.h dsp56kkw.h error.h expr.h listing.h mach.h macro.h op.h riscasm.h \
+ sect.h kwtab.h mntab.h risckw.h 6502kw.h opkw.h
riscasm.o: riscasm.c riscasm.h rmac.h symbol.h amode.h direct.h token.h \
error.h expr.h mark.h procln.h sect.h risckw.h kwtab.h
rmac.o: rmac.c rmac.h symbol.h 6502.h debug.h direct.h token.h error.h \
expr.h listing.h mark.h macro.h object.h procln.h riscasm.h sect.h \
version.h
-sect.o: sect.c sect.h rmac.h symbol.h 6502.h direct.h token.h error.h \
- expr.h listing.h mach.h mark.h riscasm.h
+sect.o: sect.c sect.h rmac.h symbol.h riscasm.h 6502.h direct.h token.h \
+ error.h expr.h listing.h mach.h mark.h
symbol.o: symbol.c symbol.h error.h rmac.h listing.h object.h procln.h \
token.h
token.o: token.c token.h rmac.h symbol.h direct.h error.h macro.h \
- procln.h sect.h kwtab.h
+ procln.h sect.h riscasm.h kwtab.h
#include "6502.h"
#include "amode.h"
#include "direct.h"
+#include "dsp56k_amode.h"
+#include "dsp56k_mach.h"
#include "error.h"
#include "expr.h"
#include "listing.h"
#define DECL_MO // Include OP keyword state machine tables
#include "opkw.h"
+#define DEF_DSP // Include DSP56K keywords definitions
+#define DECL_DSP // Include DSP56K keyword state machine tables
+#include "dsp56kkw.h"
+
+
IFENT * ifent; // Current ifent
static IFENT ifent0; // Root ifent
IFENT * f_ifent; // Freelist of ifents
}
}
+ // If we are in 56K mode and still in need of a mnemonic then search for one
+ if (dsp56001 && ((state < 0) || (state >= 1000)))
+ {
+ for(state=0, p=opname; state>=0;)
+ {
+ j = dspbase[state] + (int)tolowertab[*p];
+
+ // Reject, character doesn't match
+ if (dspcheck[j] != state)
+ {
+ state = -1; // No match
+ break;
+ }
+
+ // Must accept or reject at EOS
+ if (!*++p)
+ {
+ state = dspaccept[j]; // (-1 on no terminal match)
+ break;
+ }
+
+ state = dsptab[j];
+ }
+
+ // Call DSP code generator if we found a mnemonic
+ if (state >= 2000)
+ {
+ LONG parcode;
+ int operands;
+ MNTABDSP * md = &dsp56k_machtab[state - 2000];
+ deposit_extra_ea = 0; // Assume no extra word needed
+
+ if (md->mnfunc == dsp_mult)
+ {
+ // Special case for multiplication instructions: they require
+ // 3 operands
+ if ((operands = dsp_amode(3)) == ERROR)
+ goto loop;
+ }
+ else if ((md->mnattr & PARMOVE) && md->mn0 != M_AM_NONE)
+ {
+ if (dsp_amode(2) == ERROR)
+ goto loop;
+ }
+ else if ((md->mnattr & PARMOVE) && md->mn0 == M_AM_NONE)
+ {
+ // Instructions that have parallel moves but use no operands
+ // (probably only move). In this case, don't parse addressing
+ // modes--just go straight to parallel parse
+ dsp_am0 = dsp_am1 = M_AM_NONE;
+ }
+ else
+ {
+ // Non parallel move instructions can have up to 4 parameters
+ // (well, only tcc instructions really)
+ if ((operands = dsp_amode(4)) == ERROR)
+ goto loop;
+
+ if (operands == 4)
+ {
+ dsp_tcc4(md->mninst);
+ goto loop;
+ }
+ }
+
+ if (md->mnattr & PARMOVE)
+ {
+ // Check for parallel moves
+ if ((parcode = parmoves(dsp_a1reg)) == ERROR)
+ goto loop;
+ }
+ else
+ {
+ if (*tok != EOL)
+ error("parallel moves not allowed with this instruction");
+
+ parcode = 0;
+ }
+
+ while ((dsp_am0 & md->mn0) == 0 || (dsp_am1 & md->mn1) == 0)
+ md = &dsp56k_machtab[md->mncont];
+
+ (*md->mnfunc)(md->mninst | (parcode << 8));
+ goto loop;
+ }
+ }
+
// Invoke macro or complain about bad mnemonic
if (state < 0)
{
// Keep a backup of chptr (used for optimisations during codegen)
chptr_opcode = chptr;
- for(;;)
- {
- if ((m->mnattr & siz) && (amsk0 & m->mn0) != 0 && (amsk1 & m->mn1) != 0)
- {
- (*m->mnfunc)(m->mninst, siz);
- goto loop;
- }
-
+ while ((m->mnattr & siz) && (amsk0 & m->mn0) == 0 || (amsk1 & m->mn1) == 0)
m = &machtab[m->mncont];
- }
+
+ (*m->mnfunc)(m->mninst, siz);
+ goto loop;
}
#define DATA 0x0002 // Relative to data
#define BSS 0x0004 // Relative to BSS
#define M6502 0x0008 // 6502/microprocessor (absolute)
+#define M56001P 0x0010 // DSP 56001 Program RAM
+#define M56001X 0x0020 // DSP 56001 X RAM
+#define M56001Y 0x0040 // DSP 56001 Y RAM
+#define M56001L 0x0080 // DSP 56001 L RAM
#define TDB (TEXT|DATA|BSS) // Mask for text+data+bss
+#define M56KPXYL (M56001P|M56001X|M56001Y|M56001L) // Mask for 56K stuff
// Sizes
#define SIZB 0x0001 // .b
//
void MakeSection(int sno, uint16_t attr)
{
- SECT * p = §[sno];
- p->scattr = attr;
- p->sloc = 0;
- p->orgaddr = 0;
- p->scode = p->sfcode = NULL;
- p->sfix = p->sffix = NULL;
+ SECT * sp = §[sno];
+ sp->scattr = attr;
+ sp->sloc = 0;
+ sp->orgaddr = 0;
+ sp->scode = sp->sfcode = NULL;
+ sp->sfix = sp->sffix = NULL;
}
{
CHUNK * cp;
cursect = sno;
- SECT * p = §[sno];
+ SECT * sp = §[sno];
m6502 = (sno == M6502); // Set 6502-mode flag
// Copy section vars
- scattr = p->scattr;
- sloc = p->sloc;
- scode = p->scode;
- orgaddr = p->orgaddr;
+ scattr = sp->scattr;
+ sloc = sp->sloc;
+ scode = sp->scode;
+ orgaddr = sp->orgaddr;
// Copy code chunk vars
if ((cp = scode) != NULL)
chptr = cp->chptr + ch_size;
// For 6502 mode, add the last org'd address
+// Why?
+/*
+Because the way this is set up it treats the 6502 assembly space as a single 64K space (+ 16 bytes, for some reason) and just bobbles around inside that space and uses a stack of org "pointers" to show where the data ended up.
+
+This is a piss poor way to handle things, and for fucks sake, we can do better than this!
+*/
if (m6502)
chptr = cp->chptr + orgaddr;
}
//
void SaveSection(void)
{
- SECT * p = §[cursect];
+ SECT * sp = §[cursect];
- p->scattr = scattr; // Bailout section vars
- p->sloc = sloc;
- p->orgaddr = orgaddr;
+ sp->scattr = scattr; // Bailout section vars
+ sp->sloc = sloc;
+ sp->orgaddr = orgaddr;
if (scode != NULL) // Bailout code chunk
scode->ch_size = ch_size;
if (fup->orgaddr)
addr = fup->orgaddr;
-
eval = (quad & 0xFFFFFC0000FFFFFFLL) | ((addr & 0x3FFFF8) << 21);
}
else if (w & FU_OBJDATA)
#define __SECT_H__
#include "rmac.h"
+#include "riscasm.h"
// Macros to deposit code in the current section (in Big Endian)
#define D_byte(b) {chcheck(1);*chptr++=(uint8_t)(b); sloc++; ch_size++; \
sloc+=2; ch_size+=2;if(orgactive) orgaddr += 2;}
// Macro for the 56001. Word size on this device is 24 bits wide. I hope that
-// orgaddr += 1 means that the addresses in the device reflect this.
+// orgaddr += 1 means that the addresses in the device reflect this. [A: Yes.]
#define D_dsp(w) {chcheck(3);*chptr++=(uint8_t)(w>>16); \
*chptr++=(uint8_t)(w>>8); *chptr++=(uint8_t)w; \
sloc+=1; ch_size += 3; if(orgactive) orgaddr += 1; \
#define FU_BYTEH 0x0008 // Fixup 6502 high byte of immediate word
#define FU_BYTEL 0x0009 // Fixup 6502 low byte of immediate word
#define FU_QUAD 0x000A // Fixup quad-word (8 bytes)
+#define FU_56001 0x000B // Generic fixup code for all 56001 modes
+#define FU_56001_B 0x000C // Generic fixup code for all 56001 modes (ggn: I have no shame)
#define FU_SEXT 0x0010 // Ok to sign extend
#define FU_PCREL 0x0020 // Subtract PC first
#define FU_DONE 0x8000 // Fixup has been done
// FPU fixups
-#define FU_FLOATSING 0x000B // Fixup 32-bit float
-#define FU_FLOATDOUB 0x000C // Fixup 64-bit float
-#define FU_FLOATEXT 0x000D // Fixup 96-bit float
+#define FU_FLOATSING 0x000D // Fixup 32-bit float
+#define FU_FLOATDOUB 0x000E // Fixup 64-bit float
+#define FU_FLOATEXT 0x000F // Fixup 96-bit float
// OP fixups
#define FU_OBJLINK 0x10000 // Fixup OL link addr (bits 24-42, drop last 3)
#define FU_OBJDATA 0x20000 // Fixup OL data addr (bits 43-63, drop last 3)
+// DSP56001 fixups
+// TODO: Sadly we don't have any spare bits left inside a 16-bit word
+// so we use the 2nd nibble as control code and
+// stick $B or $C in the lower nibble - then it's picked up as
+// FU_56001 by the fixup routine and then a second switch
+// selects fixup mode. Since we now have 32 bits, we can fix this!
+// [N.B.: This isn't true anymore, we now have 32 bits! :-P]
+#define FU_DSPIMM5 0x090B // Fixup 5-bit immediate
+#define FU_DSPADR12 0x0A0B // Fixup 12-bit address
+#define FU_DSPADR24 0x0B0B // Fixup 24-bit address
+#define FU_DSPADR16 0x0C0B // Fixup 24-bit address
+#define FU_DSPIMM12 0x0D0B // Fixup 12-bit immediate
+#define FU_DSPIMM24 0x0E0B // Fixup 24-bit immediate
+#define FU_DSPIMM8 0x0F0B // Fixup 8-bit immediate
+#define FU_DSPADR06 0x090C // Fixup 6-bit address
+#define FU_DSPPP06 0x0A0C // Fixup 6 bit pp address
+#define FU_DSPIMMFL8 0x0B0C // Fixup 8-bit immediate float
+#define FU_DSPIMMFL16 0x0C0C // Fixup 16-bit immediate float
+#define FU_DSPIMMFL24 0x0D0C // Fixup 24-bit immediate float
+
// Chunks are used to hold generated code and fixup records
#define CHUNK struct _chunk
#define DOTQ 'Q' // .q or .Q (essentially an alias for P)
#define DOTS 'S' // .s or .S (FPU Single)
#define ENDEXPR 'E' // End of expression
+#define UNLT 0x81 // Unary '<' (low byte)
+#define UNGT 0x82 // Unary '>' (high byte)
// ^^ operators
#define CR_DEFINED 'p' // ^^defined - is symbol defined?