Files
2021-10-31 21:20:46 +02:00

1897 lines
114 KiB
C++

/*
* Interactive disassembler (IDA).
* Copyright (c) 1990-99 by Ilfak Guilfanov.
* ALL RIGHTS RESERVED.
* E-mail: ig@datarescue.com
*
* Texas Instruments's TMS5320C55
*
*/
//lint -e704 shift right of signed quantity
//lint -e1764 could be declared const
#include "tms320c55.hpp"
#include <segregs.hpp>
#define MAX_BYTE_USER_PARALLELIZED 0x5F
#define BYTE_MMAP 0x98
#define BYTE_PORT1 0x99
#define BYTE_PORT2 0x9A
#define BYTE_LR 0x9C
#define BYTE_CR 0x9D
//--------------------------------------------------------------------------
// class to store a bytes cache
#define BYTES_SIZE 32 // maximum cache size (maximum number of bytes)
class bytes_c
{
public:
bytes_c(insn_t &_insn) : insn(_insn), size(0), i(0)
{
memset(bytes, 0, sizeof(bytes));
}
private:
insn_t &insn;
int bytes[BYTES_SIZE];
int size;
int i;
public:
void reset(void) { i = 0; }
int get_next(void);
int get(int j) const { return bytes[j]; }
void set_cache(bytevec_t &bytes);
};
//--------------------------------------------------------------------------
// get the next byte
int bytes_c::get_next(void)
{
if ( i == size )
{
// if ( size >= CACHE_SIZE ) return NULL;
// load a new byte into the cache
bytes[size] = get_byte(insn.ea+size);
size++;
}
return bytes[i++];
}
//--------------------------------------------------------------------------
// set cache contents
void bytes_c::set_cache(bytevec_t &_bytes)
{
int n = _bytes.size();
n = qmin(n, qnumber(bytes)); //lint !e666 expression with side effects
for ( size_t j=0; j < n; j++ )
bytes[j] = _bytes[j];
size = n;
reset();
}
#define OP_MASK_N 15 // maximum nomber of op_mask_t for an instruction
struct mask_t;
// function to generate an operand
typedef void (*func_op_mask_t)(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &optional_op);
typedef struct
{
func_op_mask_t func; // function to set operand
int64 mask; // mask of operand
} op_mask_t;
struct mask_t
{
int64 code; // full opcode of instruction
int64 mask; // full mask of instruction
char size; // number of bytes for instruction
ushort itype; //lint !e958 padding is required to align members
op_mask_t op_mask[OP_MASK_N]; //lint !e958 padding is required to align members
// function and mask to set operands
};
//--------------------------------------------------------------------------
// verify if a given byte match a byte (0 <= n <= mask_t.size-1) from a code and mask
static bool byte_match_code_mask(const mask_t *mask, int64 byte, char n, char lbytesize = 8)
{
// compute nshift and nmask
int nshift = (mask->size - 1 - n) * lbytesize;
int64 nmask = 0;
for ( int i = 0; i < lbytesize; i++ )
nmask = (nmask << 1) | 1;
// shift code and mask to get current byte
int64 mask_code = (mask->code >> nshift) & nmask;
int64 mask_mask = (mask->mask >> nshift) & nmask;
byte &= nmask;
return (mask_code & mask_mask) == (byte & mask_mask);
}
//--------------------------------------------------------------------------
#define OP_BITS 30 // bits effectively reserved for masks (other bits are reserved for special operators)
#define OP_MASK (~(int64(0xFFFFFFFF) << OP_BITS)) // effective mask
#define OP_MASK_5 (~(make_ulonglong(0x3FFFFFF, 0) << (OP_BITS+8))) // effective mask
#define OP_MASK_6 (~(make_ulonglong(0x3FFFF, 0) << (OP_BITS+16))) // effective mask
#define OP_OP_NULL 0
#define OP_OP_IMM 1
#define OP_IMM(imm) ((OP_OP_IMM << OP_BITS)|(imm)) // return offset = imm
#define OP_TRUE OP_IMM(1) // return offset = 1
#define OP_OP_NOT 2
#define OP_NOT(mask) ((OP_OP_NOT << OP_BITS)|(mask)) // return (~offset) & 1
// return a masked operand or the result of a special operation
#define OP_IMM_5(imm) (make_longlong(0x00000000, 0x40)|(imm)) // return offset = imm
#define OP_IMM_6(imm) (make_longlong(0x00000000, 0x4000)|(imm)) // return offset = imm
#define OP_TRUE_5 OP_IMM_5(1) // return offset = 1
#define OP_TRUE_6 OP_IMM_6(1) // return offset = 1
static int64 get_masked_operand(int64 code, int64 mask)
{
if ( mask == 0 )
return 0;
bool no = false;
// special operations
switch ( mask >> OP_BITS )
{
case OP_OP_NULL:
break;
case OP_OP_IMM:
return mask & OP_MASK;
case OP_OP_NOT:
no = true;
break;
default:
break;
}
code &= (mask & OP_MASK);
while ( (mask & 1) == 0 )
{
code = code >> 1;
mask = mask >> 1;
}
if ( no )
code = (~code) & 1;
return code;
}
//--------------------------------------------------------------------------
static int get_signed(int byte, int mask)
{
int bits = mask >> 1;
int sign = bits + 1;
if ( byte & sign ) // offset < 0
byte = ( byte & bits ) - sign;
else // offset >= 0
byte = byte & mask;
return byte;
}
//--------------------------------------------------------------------------
inline int get_signed64(int64 byte, int mask)
{
return get_signed((int)byte, mask);
}
//--------------------------------------------------------------------------
inline int get_unsigned(int byte, int mask)
{
byte = byte & mask;
return byte;
}
//--------------------------------------------------------------------------
static int64 get_masked_operand_5(int64 code, int64 mask)
{
if ( mask == 0 )
return 0;
bool no = false;
// special operations
int Switch=mask >> (OP_BITS+8);
switch ( Switch )
{
case OP_OP_NULL: break;
case OP_OP_IMM:
return mask & OP_MASK_5;
case OP_OP_NOT:
no = true;
break;
default:
INTERR(10262);
}
code &= (mask & OP_MASK_5);
while ( (mask & 1) == 0 )
{
code = code >> 1;
mask = mask >> 1;
}
if ( no )
code = (~code) & 1;
return code;
}
//--------------------------------------------------------------------------
static int64 get_masked_operand_6(int64 code, int64 mask, bool /*bTest*/)
{
if ( mask == 0 )
return 0;
bool no = false;
// special operations
int Switch = mask >> (OP_BITS+16);
switch ( Switch )
{
case OP_OP_NULL: break;
case OP_OP_IMM:
return mask & OP_MASK_6;
case OP_OP_NOT:
no = true;
break;
default:
INTERR(10263);
}
code &= mask & OP_MASK_6;
while ( (mask & 1) == 0 )
{
code = code >> 1;
mask = mask >> 1;
}
if ( no )
code = (~code) & 1;
return code;
}
//--------------------------------------------------------------------------
// process mask->op_mask[op_mask_n] on insn.ops[op_n] (if op.n not modified) and eventually modify op_n
bool tms320c55_t::process_masks_operand(
insn_t &insn,
const mask_t *mask,
int64 code,
int64 op_mask_n,
unsigned *p_opnum,
bool bTest)
{
// initialize an operand to work on
op_t work;
unsigned opnum = *p_opnum;
if ( opnum < UA_MAXOP )
work = insn.ops[opnum];
else
work = insn.ops[UA_MAXOP-1];
const op_mask_t *op_mask = &mask->op_mask[int(op_mask_n)];
if ( op_mask->func == NULL )
return false;
int64 opv = mask->size == 5 ? get_masked_operand_5(code, op_mask->mask)
: mask->size == 6 ? get_masked_operand_6(code, op_mask->mask, bTest)
: get_masked_operand(code, op_mask->mask);
op_mask->func(mask, opv, &work, insn, optional_op);
if ( work.type != o_void ) // if the operand was modified
{
if ( work.n == opnum ) // the function worked on the current operand
{
if ( opnum >= UA_MAXOP )
return false; // error if not enough operands in insn
insn.ops[opnum] = work; // save the new operand
*p_opnum = ++opnum; // go to the next operand
}
else // the function modified the previous operand
{
if ( work.n >= UA_MAXOP )
return false;
insn.ops[work.n] = work; // save the new precedent operand (modified)
}
}
return true;
}
//--------------------------------------------------------------------------
// get number of bytes for a given instruction opcode (left-aligned in dword)
static int get_insn_size(const mask_t *masks, uint32 opcode)
{
const mask_t *p = masks;
while ( p->mask != 0 )
{
if ( p->size <= 4 && (p->mask & (opcode>>(8*(4-p->size)))) == p->code )
return p->size;
p++;
}
return 0;
}
//--------------------------------------------------------------------------
// analyze code by processing all necessary masks
void tms320c55_t::process_masks(
insn_t &insn,
const mask_t *masks,
ushort itype_null,
bytes_c &bytes,
char lbytesize)
{
insn.itype = itype_null;
insn.size = 1;
const mask_t *p = masks;
while ( p->mask != 0 )
{
bytes.reset();
ushort nbytes = 0;
while ( nbytes < p->size
&& byte_match_code_mask(p, bytes.get_next(), (uchar &)nbytes, lbytesize) )
{
nbytes++;
}
if ( nbytes == p->size ) // if bytes matches all bytes from code and mask
{
int i;
insn.itype = p->itype;
insn.size = nbytes;
// compute full code
int64 code = 0;
for ( i = 0; i < nbytes; i++ )
code = (code << lbytesize) | bytes.get(i);
// process operands
unsigned opnum = 0;
for ( i = 0; i < OP_MASK_N; i++ )
{
bool bTest = p->size == 6 && i == 2;
if ( !process_masks_operand(insn, p, code, i, &opnum, bTest) )
break;
}
return;
}
p++;
}
}
//--------------------------------------------------------------------------
// permit a mask_func_n to work on the last operand
static bool get_last_op(op_t *op, const insn_t &insn)
{
int n;
for ( n = 0; n < 6; n++ ) // find the first o_void operand
if ( insn.ops[n].type == o_void )
break;
if ( n == 0 )
return false; // no precedent operand
*op = insn.ops[n-1]; // copy the precedent operand to the current position
return true;
}
//--------------------------------------------------------------------------
// format instruction name
static void get_name_chars(
char *buf,
size_t bufsize,
bool incl_chars,
const char *name,
const char *chars)
{
char *bufend = qstpncpy(buf, name, bufsize);
if ( incl_chars )
qstrncpy(bufend, chars, bufsize - (bufend-buf));
}
//--------------------------------------------------------------------------
// instructions
// find instruction insn+"chars" with same operands:
// parallel indicate an instructions on 2 lines
// name1_chars indicate if we must have "chars" added to the first line
// name2_chars indicate if we must have "chars" added to the second line
// instructions in instruc_t Instructions[] must be sorted as follow:
// insn1 - insn2 - ... - insn"chars"1 - insn"chars"2 - ...
static bool find_insn_suffix(
insn_t &insn,
const char *chars,
ushort itype_last,
bool parallel,
bool name1_chars,
bool name2_chars)
{
const char *insn_name1 = Instructions[insn.itype].name;
char insn_name1_chars[MAXSTR];
get_name_chars(insn_name1_chars, sizeof(insn_name1_chars), name1_chars, insn_name1, chars);
const char *insn_name2 = NULL;
char insn_name2_chars[MAXSTR];
insn_name2_chars[0] = '\0';
if ( parallel )
{
insn_name2 = strchr(insn_name1, 0)+1;
get_name_chars(insn_name2_chars, sizeof(insn_name2_chars), name2_chars, insn_name2, chars);
}
ushort i = insn.itype + 1;
// jump over same instruction names (but eventually different number of params)
while ( streq(Instructions[i].name, insn_name1)
&& (!parallel || streq(strchr(Instructions[i].name, 0)+1, insn_name2)) ) //-V575 potential null pointer
{
if ( ++i == itype_last )
return false;
}
// loop until current instruction names are the same as what we are searching for (name or name+chars)
while ( !streq(Instructions[i].name, insn_name1_chars)
|| (parallel && !streq(strchr(Instructions[i].name, 0)+1, insn_name2_chars)) )
{
if ( ++i == itype_last )
return false;
}
// loop until current instruction has same params
uint32 insn_feature = Instructions[insn.itype].feature;
while ( Instructions[i].feature != insn_feature )
{
if ( ++i == itype_last )
return false;
}
insn.itype = i;
return true;
}
#define insn_chars(NAME, CHARS, PARALLEL, NAME1_CHARS, NAME2_CHARS) \
static void NAME(const mask_t *, int64 offset, op_t *, insn_t &insn, char &) \
{ \
if ( (offset & 1) != 0 ) \
{ \
bool ok = find_insn_suffix(insn, CHARS, TMS320C55_last, PARALLEL,\
NAME1_CHARS, NAME2_CHARS); \
if ( !ok ) \
error("interr: ana: adjust_insn_suffix"); \
} \
}
insn_chars(insn_1_R_2_R, "r", true, true, true) // insn_1_R_2_R %
insn_chars(insn_1_40_2_40, "40", true, true, true) // insn_1_40_2_40 g
insn_chars(insn_1_2_R, "r", true, false, true) // insn_1_2_R %
insn_chars(insn_1_2_40, "40", true, false, true) // insn_1_2_40 g
insn_chars(insn_1_R, "r", false, true, false) // insn_1_R %
insn_chars(insn_1_40, "40", false, true, false) // insn_1_40 g
insn_chars(insn_1_R_2, "r", true, true, false) // insn_1_R_2 %
insn_chars(insn_1_U, "u", false, true, false) // insn_1_U u
insn_chars(insn_1_P, "p", false, true, false) // insn_1_P swap()
insn_chars(insn_1_4, "4", false, true, false) // insn_1_4 swap()
// set user parellel
static void insn_UP(const mask_t *, int64, op_t *, insn_t &insn, char &)
{
insn.SpecialModes |= TMS_MODE_USER_PARALLEL;
}
// built-in parallelism
static void blt_prll(const mask_t *, int64, op_t *, insn_t &insn, char &)
{ // count the number of actual operands
insn.Parallel = 0;
for ( int i = 0; i < UA_MAXOP; i++ )
{
if ( insn.ops[i].type == o_void )
break;
insn.Parallel++;
}
}
// simulated user parallelism
// static void usr_prll(const mask_t *mask, int64 offset, op_t *op)
// {
// if ( offset & 1 )
// {
// blt_prll(mask, offset, op);
// insn.SpecialModes |= TMS_MODE_SIMULATE_USER_PARALLEL;
// }
// }
// ? actually not used, but will probably be used for non-documented opcodes
// need also to add new instructions "ins1\nins2" in ins.hpp & ins.cpp
// immediates
#define op_imm(NAME, DTYP) \
static void op_##NAME(const mask_t *, int64 offset, op_t *op, insn_t &, char &) \
{ \
op->type = o_imm; \
op->value = (uval_t)offset; \
op->dtype = dt_##DTYP; \
}
op_imm(k8, byte) // op_k8
op_imm(k16, word) // op_k16
#define op_k4 op_k8
#define op_k5 op_k8
#define op_k7 op_k8
#define op_k9 op_k16
#define op_k12 op_k16
//--------------------------------------------------------------------------
static void op_min_k4(const mask_t *, int64 offset, op_t *op, insn_t &, char &)
{
op->type = o_imm;
op->value = (uval_t)-offset;
op->dtype = dt_byte;
op->tms_signed = true;
}
//--------------------------------------------------------------------------
static void op_K8(const mask_t *, int64 offset, op_t *op, insn_t &, char &)
{
op->type = o_imm;
op->value = get_signed64(offset, 0xFF);
op->dtype = dt_byte;
op->tms_signed = true;
}
//--------------------------------------------------------------------------
static void op_K16(const mask_t *, int64 offset, op_t *op, insn_t &, char &)
{
op->type = o_imm;
op->value = get_signed64(offset, 0xFFFF);
op->dtype = dt_word;
op->tms_signed = true;
}
//--------------------------------------------------------------------------
/*
static void op_K23(const mask_t *, int64 offset, op_t *op, insn_t &, char &)
{
op->type = o_imm;
op->value = get_unsigned(offset, 0x7FFFFF);
op->dtype = dt_3byte;
}
*/
//--------------------------------------------------------------------------
static void op_1(const mask_t *, int64, op_t *op, insn_t &, char &)
{
op->type = o_imm;
op->value = 1;
op->dtype = dt_byte;
}
//--------------------------------------------------------------------------
static void op_min_1(const mask_t *, int64, op_t *op, insn_t &, char &)
{
op->type = o_imm;
op->value = uval_t(-1);
op->dtype = dt_byte;
op->tms_signed = true;
}
//--------------------------------------------------------------------------
// registers
static void op_src(const mask_t *, int64 offset, op_t *op, insn_t &, char &optional_op) // FSSS, FDDD
{
op->type = o_reg;
op->dtype = dt_word;
op->reg = AC0 + uint16(offset);
optional_op = op->n;
}
#define op_dst op_src
#define op_ACw op_src
#define op_ACx op_src
#define op_ACy op_src
#define op_ACz op_src
#define op_TAx op_src // ARx or Tx
#define op_TAy op_src // ARy or Ty
// optional operand
static void opt_src(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // FSSS, FDDD
{
if ( optional_op != -1
&& insn.ops[uchar(optional_op)].type == o_reg
&& insn.ops[uchar(optional_op)].reg == AC0 + offset )
{
return; // no operand if same than the source
}
// add the operand
op_src(mask, offset, op, insn, optional_op);
optional_op = -1;
insn.itype++;
}
#define opt_dst opt_src
#define opt_ACy opt_src
#define op_reg(NAME, REG) \
static void op_##NAME(const mask_t *, int64 offset, op_t *op, insn_t &, char &)\
{ \
op->type = o_reg; \
op->dtype = dt_word; \
op->reg = REG + uint16(offset); \
}
op_reg(Tx, T0) // op_Tx
op_reg(TCx, TC1) // op_TCx
op_reg(TRNx, TRN0) // op_TRNx
#define op_TCy op_TCx
op_reg(ARx, AR0) // op_ARx
op_reg(DPH, DPH) // op_DPH
op_reg(PDP, PDP) // op_PDP
op_reg(BK03, BK03) // op_BK03
op_reg(BK47, BK47) // op_BK47
op_reg(BKC, BKC) // op_BKC
op_reg(CSR, CSR) // op_CSR
op_reg(BRC0, BRC0) // op_BRC0
op_reg(BRC1, BRC1) // op_BRC1
op_reg(SP, SP) // op_SP
op_reg(SSP, SSP) // op_SSP
op_reg(CDP, CDP) // op_CDP
op_reg(RPTC, RPTC) // op_RPTC
op_reg(STx_55, ST0_55) // op_STx_55
op_reg(DP, DP) // op_DP
op_reg(BSA01, BSA01) // op_BSA01
op_reg(BSA23, BSA23) // op_BSA23
op_reg(BSA45, BSA45) // op_BSA45
op_reg(BSA67, BSA67) // op_BSA67
op_reg(BSAC, BSAC) // op_BSAC
op_reg(TRN0, TRN0) // op_TRN0
op_reg(TRN1, TRN1) // op_TRN1
op_reg(TC1, TC1) // op_TC1
op_reg(TC2, TC2) // op_TC2
op_reg(CARRY, CARRY) // op_CARRY
op_reg(BORROW, BORROW) // op_BORROW
op_reg(RETA, RETA) // op_RETA
op_reg(MDP05, MDP05) // op_MDP05
op_reg(MDP67, MDP67) // op_MDP67
//--------------------------------------------------------------------------
static void op_xsrc(const mask_t *, int64 offset, op_t *op, insn_t &, char &) // XSSS, XDDD
{ // AC0 AC1 AC2 AC3 XSP XSSP XDP XCDP XAR0 -> XAR7
static const ushort regs[] =
{
AC0, AC1, AC2, AC3, XSP, XSSP, XDP, XCDP,
XAR0, XAR1, XAR2, XAR3, XAR4, XAR5, XAR6, XAR7
};
op->type = o_reg;
op->dtype = dt_dword;
op->reg = regs[int(offset)];
}
#define op_xdst op_xsrc
//--------------------------------------------------------------------------
static void op_Xmem(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // XXXMMM, YYYMMM
{
op_ARx(mask, offset >> 3, op, insn, optional_op);
op->tms_modifier = TMS_MODIFIER_REG + (offset & 0x7);
}
#define op_Ymem op_Xmem
//--------------------------------------------------------------------------
static void op_Cmem(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // mm
{
op_CDP(mask, 0, op, insn, optional_op);
op->tms_modifier = TMS_MODIFIER_REG + (offset & 0x3);
}
//--------------------------------------------------------------------------
static void op_mem(
const mask_t *mask,
int64 offset,
op_t *op,
op_dtype_t dtype,
insn_t &insn,
char optional_op,
bool ARn_mod = false) // AAAAAAAI
{
insn.OpMem = 1 + op->n;
if ( !(offset & 1) ) // @dma
{ // direct memory address
sel_t cpl = get_sreg(insn.ea, CPL);
if ( cpl == BADSEL )
cpl = 0;
if ( !cpl )
{ // use DP
op->type = o_mem;
op->tms_regH = DPH;
op->tms_regP = DP;
op->addr = ea_t(offset >> 1);
op->tms_modifier = TMS_MODIFIER_DMA;
}
else
{ // use SP
op->type = o_reg;
op->reg = SP;
op->value = ea_t(offset >> 1);
op->tms_modifier = TMS_MODIFIER_REG_OFFSET;
}
}
else
{ // indirect memory access
if ( (offset & 0x1F) == 0x11 ) // xxx1 0001
{
int bits = int(offset >> 5);
switch ( bits )
{
case 0: // *ABS16(#k16)
op->type = o_mem;
op->tms_regH = DPH;
op->addr = (get_byte(insn.ea+insn.size) << 8)
| get_byte(insn.ea+insn.size+1);
op->tms_modifier = TMS_MODIFIER_ABS16;
insn.size += 2;
break;
case 1: // *(#k23)
op->type = o_mem;
op->addr = (get_byte(insn.ea+insn.size) << 16)
| (get_byte(insn.ea+insn.size+1) << 8)
| get_byte(insn.ea+insn.size+2);
op->tms_modifier = TMS_MODIFIER_PTR;
insn.size += 3;
break;
case 2: // port(#k16)
op->type = o_io;
op->addr = (get_byte(insn.ea+insn.size) << 8)
| get_byte(insn.ea+insn.size+1);
op->tms_modifier = TMS_MODIFIER_PORT;
insn.size += 2;
break;
case 3: // *CDP
case 4: // *CDP+
case 5: // *CDP-
op_CDP(mask, 0, op, insn, optional_op);
op->tms_modifier= TMS_MODIFIER_REG + uchar(bits)-3;
break;
case 6: // *CDP(#K16)
case 7: // *+CDP(#K16)
op_CDP(mask, 0, op, insn, optional_op);
op->value = get_signed((get_byte(insn.ea+insn.size) << 8)
| get_byte(insn.ea+insn.size+1), 0xFFFF);
op->tms_modifier = TMS_MODIFIER_REG_OFFSET + uchar(bits)-6;
insn.size += 2;
break;
}
}
else
{
op_ARx(mask, offset >> 5, op, insn, optional_op);
int bits = (offset >> 1) & 0xF;
if ( (offset & 0x11) == 0x01 ) // xxx0 xxx1
{
switch ( bits )
{
case 0: // *ARn
case 1: // *ARn+
case 2: // *ARn-
op->tms_modifier= TMS_MODIFIER_REG + uchar(bits);
break;
case 3: // *(ARn+T0)
op->tms_modifier= TMS_MODIFIER_REG_P_T0;
break;
case 4: // *(ARn-T0)
op->tms_modifier= TMS_MODIFIER_REG_M_T0;
break;
case 5: // *ARn(T0)
op->tms_modifier= TMS_MODIFIER_REG_T0;
break;
case 6: // *ARn(#K16)
case 7: // *+ARn(#K16)
op->value = get_signed((get_byte(insn.ea+insn.size) << 8)
| get_byte(insn.ea+insn.size+1), 0xFFFF);
op->tms_modifier = TMS_MODIFIER_REG_OFFSET + uchar(bits)-6;
insn.size += 2;
break;
}
}
else // xxx1 xxx1
{
int lbits = (offset >> 1) & 0x7;
sel_t arms = get_sreg(insn.ea, ARMS);
if ( arms == BADSEL )
arms = 0;
if ( ARn_mod || !arms )
{
switch ( lbits )
{
case 1: // *(ARn+T1)
op->tms_modifier= TMS_MODIFIER_REG_P_T1;
break;
case 2: // *(ARn-T1)
op->tms_modifier= TMS_MODIFIER_REG_M_T1;
break;
case 3: // *ARn(T1)
case 4: // *+ARn
case 5: // *-ARn
case 6: // *(ARn+T0B)
case 7: // *(ARn-T0B)
op->tms_modifier= TMS_MODIFIER_REG_T1 + uchar(lbits)-3;
break;
}
}
else
{ // *ARn(short(#value))
op->value = lbits;
op->tms_modifier = TMS_MODIFIER_REG_SHORT_OFFSET;
}
}
}
}
op->dtype = dtype;
}
//--------------------------------------------------------------------------
static void op_Smem(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // AAAAAAAI //-V669 'optional_op' argument is a non-constant reference
{
op_mem(mask, offset, op, dt_word, insn, optional_op);
}
//--------------------------------------------------------------------------
static void op_Lmem(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // AAAAAAAI //-V669 'optional_op' argument is a non-constant reference
{
op_mem(mask, offset, op, dt_dword, insn, optional_op);
}
//--------------------------------------------------------------------------
static void op_ARn_mod(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // AAAAAAAI //-V669 'optional_op' argument is a non-constant reference
{
op_mem(mask, offset, op, dt_word, insn, optional_op, true);
}
//--------------------------------------------------------------------------
// @dma = bit number
static void op_Baddr(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // AAAAAAAI //-V669 'optional_op' argument is a non-constant reference
{
if ( !(offset & 1) ) // @dma
{
op->type = o_imm;
op->value = ea_t(offset >> 1);
op->dtype = dt_byte;
op->tms_prefix = '@';
op->tms_signed = false;
}
else
{
op_mem(mask, offset, op, dt_byte, insn, optional_op);
}
}
//lint -emacro(572,fn_operator) excessive shift value
#define fn_operator(NAME, OPERATOR) \
static void fn_##NAME(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) \
{ \
if ( offset & 1 ) \
{ \
get_last_op(op, insn); \
op->tms_operator1 |= TMS_OPERATOR_##OPERATOR & 0xFF; \
/*lint -e572 Excessive shift value*/ \
op->tms_operator2 |= (TMS_OPERATOR_##OPERATOR >> 8); \
} \
}
fn_operator(not, NOT) // fn_not
fn_operator(T3, T3) // fn_T3 U
fn_operator(uns, UNS) // fn_uns u
fn_operator(rnd, RND) // fn_rnd %
fn_operator(hb, HB) // fn_hb
fn_operator(lb, LB) // fn_lb
fn_operator(hi, HI) // fn_hi
fn_operator(lo, LO) // fn_lo
fn_operator(sat, SAT) // fn_sat = fn_uns
fn_operator(dbl, DBL) // fn_dbl
fn_operator(pair, PAIR) // fn_pair
fn_operator(dual, DUAL) // fn_dual
//--------------------------------------------------------------------------
static void op_BitIn(const mask_t *, int64 offset, op_t *op, insn_t &, char &)
{
op->type = o_reg;
op->dtype = dt_byte;
op->reg = (offset & 1) ? TC2 : CARRY;
}
#define op_BitOut op_BitIn
//--------------------------------------------------------------------------
static void op_swap(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op)
{
insn.Op1.type = o_reg;
insn.Op1.dtype = dt_word;
insn.Op2.type = o_reg;
insn.Op2.dtype = dt_word;
switch ( offset )
{
case 0x00: insn.Op1.reg = AC0; insn.Op2.reg = AC2; break;
case 0x01: insn.Op1.reg = AC1; insn.Op2.reg = AC3; break;
case 0x04: insn.Op1.reg = T0; insn.Op2.reg = T2; break;
case 0x05: insn.Op1.reg = T1; insn.Op2.reg = T3; break;
case 0x08: insn.Op1.reg = AR0; insn.Op2.reg = AR2; break;
case 0x09: insn.Op1.reg = AR1; insn.Op2.reg = AR3; break;
case 0x0C: insn.Op1.reg = AR4; insn.Op2.reg = T0; break;
case 0x0D: insn.Op1.reg = AR5; insn.Op2.reg = T1; break;
case 0x0E: insn.Op1.reg = AR6; insn.Op2.reg = T2; break;
case 0x0F: insn.Op1.reg = AR7; insn.Op2.reg = T3; break;
case 0x10: insn_1_P(mask, 1, op, insn, optional_op); insn.Op1.reg = AC0; insn.Op2.reg = AC2; break;
case 0x14: insn_1_P(mask, 1, op, insn, optional_op); insn.Op1.reg = T0; insn.Op2.reg = T2; break;
case 0x18: insn_1_P(mask, 1, op, insn, optional_op); insn.Op1.reg = AR0; insn.Op2.reg = AR2; break;
case 0x1C: insn_1_P(mask, 1, op, insn, optional_op); insn.Op1.reg = AR4; insn.Op2.reg = T0; break;
case 0x1E: insn_1_P(mask, 1, op, insn, optional_op); insn.Op1.reg = AR6; insn.Op2.reg = T2; break;
case 0x2C: insn_1_4(mask, 1, op, insn, optional_op); insn.Op1.reg = AR4; insn.Op2.reg = T0; break;
case 0x38: insn.Op1.reg = AR0; insn.Op2.reg = AR1; break;
default: insn.itype = TMS320C55_null;
}
}
//--------------------------------------------------------------------------
// get address for the branch offset base
// in case of parallel execution, this is the end of the second, parallel instruction
static ea_t get_next_ip(insn_t &insn)
{
ea_t next = insn.ip + insn.size;
if ( insn.size <= 3 )
{
uchar nextbyte = get_byte(insn.ea + insn.size);
if ( nextbyte <= MAX_BYTE_USER_PARALLELIZED && (nextbyte & 1) )
{
// next instruction is executed in parallel, so take it into account
insn_t tmp;
next += decode_insn(&tmp, insn.ea + insn.size);
}
}
return next;
}
//--------------------------------------------------------------------------
// code addresses
static void op_l4(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) // llll
{
op->type = o_near;
op->addr = (get_next_ip(insn) + offset) & 0xFFFFFF;
op->dtype = dt_code;
}
static void op_L7(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) // LLLLLLL
{
op->type = o_near;
op->addr = (get_next_ip(insn) + get_signed64(offset, 0x7F)) & 0xFFFFFF;
op->dtype = dt_code;
}
static void op_L8(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) // LLLLLLLL
{
op->type = o_near;
op->addr = (get_next_ip(insn) + get_signed64(offset, 0xFF)) & 0xFFFFFF;
op->dtype = dt_code;
}
static void op_L16(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) // LLLLLLLL LLLLLLLL
{
op->type = o_near;
op->addr = (get_next_ip(insn) + get_signed64(offset, 0xFFFF)) & 0xFFFFFF;
op->dtype = dt_code;
}
static void op_pmad(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &)
{
op->type = o_near;
op->addr = (get_next_ip(insn) + offset) & 0xFFFFFF;
op->dtype = dt_code;
}
static void op_P24(const mask_t *, int64, op_t *op, insn_t &insn, char &) // get_byte included
{
op->type = o_near;
op->addr = (get_byte(insn.ea+insn.size+0) << 16)
| (get_byte(insn.ea+insn.size+1) << 8)
| get_byte(insn.ea+insn.size+2);
op->dtype = dt_code;
insn.size += 3;
}
// data addresses
static void op_D16(const mask_t *, int64 offset, op_t *op, insn_t &, char &)
{
op->type = o_mem;
op->addr = ea_t(offset);
op->dtype = dt_word;
}
// various
static void op_SHIFTW(const mask_t *, int64 offset, op_t *op, insn_t &, char &)
{
op->type = o_shift;
op->value = (signed short)get_signed64(offset, 0x3F);
}
//--------------------------------------------------------------------------
// shift left
static void shl_SHIFTW(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &)
{
get_last_op(op, insn);
op->tms_shift = TMS_OP_SHIFTL_IMM;
op->tms_shift_value = (signed short)get_signed64(offset, 0x3F);
if ( short(op->tms_shift_value) < 0 )
{
op->tms_shift = TMS_OP_SHIFTR_IMM;
op->tms_shift_value = -op->tms_shift_value; //lint !e2501 negation of value of unsigned type
}
}
//--------------------------------------------------------------------------
// shift left out of brackets
static void slo_SHIFTW(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op)
{
shl_SHIFTW(mask, offset, op, insn, optional_op);
op->tms_shift |= TMS_OP_SHIFT_OUT;
}
//--------------------------------------------------------------------------
// shift right
static void shl_SHFT(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &)
{
get_last_op(op, insn);
op->tms_shift = TMS_OP_SHIFTL_IMM;
op->tms_shift_value = (uint16)offset;
}
//--------------------------------------------------------------------------
static void shl_Tx(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &)
{
get_last_op(op, insn);
op->tms_shift = TMS_OP_SHIFTL_REG;
op->tms_shift_value = T0 + uint16(offset);
}
//--------------------------------------------------------------------------
static void shl_T2(const mask_t *, int64, op_t *op, insn_t &insn, char &)
{
get_last_op(op, insn);
op->tms_shift = TMS_OP_SHIFTL_REG;
op->tms_shift_value = T2;
}
//--------------------------------------------------------------------------
static void shl_16(const mask_t *, int64, op_t *op, insn_t &insn, char &)
{
get_last_op(op, insn);
op->tms_shift = TMS_OP_SHIFTL_IMM;
op->tms_shift_value = 16;
}
//--------------------------------------------------------------------------
static void shr(const mask_t *, int64 imm, op_t *op, insn_t &insn, char &)
{
get_last_op(op, insn);
op->tms_shift = TMS_OP_SHIFTR_IMM;
op->tms_shift_value = uint16(imm);
}
//--------------------------------------------------------------------------
static void eq_K16(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &)
{
get_last_op(op, insn);
op->tms_shift = TMS_OP_EQ;
op->tms_shift_value = (uint16)get_signed64(offset, 0xFFFF);
}
//--------------------------------------------------------------------------
static void neq_0(const mask_t *, int64, op_t *op, insn_t &insn, char &)
{
get_last_op(op, insn);
op->tms_shift = TMS_OP_NEQ;
op->tms_shift_value = 0;
}
//--------------------------------------------------------------------------
static void RELOP(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) // cc
{
get_last_op(op, insn);
op->type = o_relop;
op->tms_relop = offset & 0x3;
}
//--------------------------------------------------------------------------
static void RELOP_dst(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op)
{
get_last_op(op, insn);
op->tms_relop_type = TMS_RELOP_REG;
ushort sav = op->reg;
op_src(mask, offset, op, insn, optional_op);
op->type = o_relop;
op->value = op->reg;
op->reg = sav;
}
//--------------------------------------------------------------------------
static void RELOP_K8(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &)
{
get_last_op(op, insn);
op->tms_relop_type = TMS_RELOP_IMM;
op->value = (signed short)get_signed64(offset, 0xFF);
}
//--------------------------------------------------------------------------
static void op_cond(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // CCC CCCC
{
op->reg = 0;
if ( (offset>>4) <= 0x5 ) // <= 101 xxxx
{ // src <comparison operator> 0
op_src(mask, offset & 0xF, op, insn, optional_op);
op->type = o_cond;
op->value = offset & 0x70;
}
else if ( (offset>>2) == 0x18 ) // == 110 00xx
{ // overflow(ACx)
op_src(mask, offset & 0x3, op, insn, optional_op);
op->type = o_cond;
op->value = offset & 0x7C;
}
else if ( (offset>>2) == 0x19 ) // == 110 01xx
{ // TC1, TC2, CARRY, reserved
if ( offset == 0x67 ) // 110 0111
insn.itype = TMS320C55_null; // reserved
else
{
op->type = o_cond;
op->value = (uval_t)offset;
}
}
else if ( (offset>>2) == 0x1A ) // == 110 10xx
{ // TC1 & TC2, TC1 & !TC2, !TC1 & TC2, !TC1 & !TC2
op->type = o_cond;
op->value = (uval_t)offset;
}
else if ( (offset>>2) == 0x1B ) // == 110 11xx
{
insn.itype = TMS320C55_null; // reserved
}
else if ( (offset>>2) == 0x1C ) // == 111 00xx
{ // !overflow(ACx)
op_src(mask, offset & 0x3, op, insn, optional_op);
op->type = o_cond;
op->value = offset & 0x7C;
}
else
{
if ( offset == 0x77 ) // 111 0111
insn.itype = TMS320C55_null; // reserved
else
{
op->type = o_cond;
op->value = (uval_t)offset;
}
}
}
//--------------------------------------------------------------------------
//lint -e648 overflow in computing constant for operator '<<': signed shift result (0x80000000) sets the sign bit of the shift expression's type ('int') and becomes negative expanded from macro 'OP_NOT'
static const mask_t masks[] =
{
// 0000000E XDDDX000 error manual
{ 0x000000, 0xFE0000, 3, TMS320C55_rptcc, {{ op_k8, 0x0000FF }, { op_cond, 0x007F00 }}},
{ 0x020000, 0xFE0000, 3, TMS320C55_retcc, {{ op_cond, 0x007F00 }}},
{ 0x040000, 0xFE0000, 3, TMS320C55_bcc, {{ op_L8, 0x0000FF }, { op_cond, 0x007F00 }}},
{ 0x060000, 0xFE0000, 3, TMS320C55_b, {{ op_L16, 0x00FFFF }}},
{ 0x080000, 0xFE0000, 3, TMS320C55_call, {{ op_L16, 0x00FFFF }}},
// 0000101E GGGGGGGG Glllllll error manual
{ 0x0C0000, 0xFE0000, 3, TMS320C55_rpt, {{ op_k16, 0x00FFFF }}},
{ 0x0E0000, 0xFE0000, 3, TMS320C55_rptb, {{ op_pmad, 0x00FFFF }}},
{ 0x100000, 0xFE0F00, 3, TMS320C55_and1, {{ op_ACx, 0x003000 }, { shl_SHIFTW, 0x00003F }, { opt_ACy, 0x00C000 }}},
{ 0x100100, 0xFE0F00, 3, TMS320C55_or1, {{ op_ACx, 0x003000 }, { shl_SHIFTW, 0x00003F }, { opt_ACy, 0x00C000 }}},
{ 0x100200, 0xFE0F00, 3, TMS320C55_xor1, {{ op_ACx, 0x003000 }, { shl_SHIFTW, 0x00003F }, { opt_ACy, 0x00C000 }}},
{ 0x100300, 0xFE0F00, 3, TMS320C55_add2, {{ op_ACx, 0x003000 }, { shl_SHIFTW, 0x00003F }, { op_ACy, 0x00C000 }}},
{ 0x100400, 0xFE0F00, 3, TMS320C55_sub2, {{ op_ACx, 0x003000 }, { shl_SHIFTW, 0x00003F }, { op_ACy, 0x00C000 }}},
{ 0x100500, 0xFE0F00, 3, TMS320C55_sfts2, {{ op_ACx, 0x003000 }, { op_SHIFTW, 0x00003F }, { opt_ACy, 0x00C000 }}},
{ 0x100600, 0xFE0F00, 3, TMS320C55_sftsc2, {{ op_ACx, 0x003000 }, { op_SHIFTW, 0x00003F }, { opt_ACy, 0x00C000 }}}, // SFTA
{ 0x100700, 0xFE0F00, 3, TMS320C55_sftl2, {{ op_ACx, 0x003000 }, { op_SHIFTW, 0x00003F }, { opt_ACy, 0x00C000 }}},
{ 0x100800, 0xFE0F00, 3, TMS320C55_exp, {{ op_ACx, 0x003000 }, { op_Tx, 0x000030 }}},
{ 0x100900, 0xFE0F00, 3, TMS320C55_mant_nexp, {{ op_ACx, 0x003000 }, { op_ACy, 0x00C000 }, { blt_prll, 0 }, { op_ACx, 0x003000 }, { op_Tx, 0x000030 }}},
{ 0x100A00, 0xFE0F00, 3, TMS320C55_bcnt, {{ op_ACx, 0x003000 }, { op_ACy, 0x0000C0 }, { op_TCx, 0x000001 }, { op_Tx, 0x000030 }}},
{ 0x100C00, 0xFE0F00, 3, TMS320C55_maxdiff, {{ op_ACx, 0x003000 }, { op_ACy, 0x0000C0 }, { op_ACz, 0x00C000 }, { op_ACw, 0x000030 }}},
{ 0x100D00, 0xFE0F00, 3, TMS320C55_dmaxdiff, {{ op_ACx, 0x003000 }, { op_ACy, 0x0000C0 }, { op_ACz, 0x00C000 }, { op_ACw, 0x000030 }, { op_TRNx, 0x000001 }}},
{ 0x100E00, 0xFE0F00, 3, TMS320C55_mindiff, {{ op_ACx, 0x003000 }, { op_ACy, 0x0000C0 }, { op_ACz, 0x00C000 }, { op_ACw, 0x000030 }}},
{ 0x100F00, 0xFE0F00, 3, TMS320C55_dmindiff, {{ op_ACx, 0x003000 }, { op_ACy, 0x0000C0 }, { op_ACz, 0x00C000 }, { op_ACw, 0x000030 }, { op_TRNx, 0x000001 }}},
{ 0x120000, 0xFE0300, 3, TMS320C55_cmp, {{ insn_1_U, 0x000004 }, { op_src, 0x00F000 }, { RELOP, 0x000C00 }, { RELOP_dst, 0x0000F0 }, { op_TCx, 0x000001 }}},
{ 0x120100, 0xFE0308, 3, TMS320C55_cmpand, {{ insn_1_U, 0x000004 }, { op_src, 0x00F000 }, { RELOP, 0x000C00 }, { RELOP_dst, 0x0000F0 }, { op_TCy, 0x000002 }, { op_TCx, 0x000001 }}},
{ 0x120108, 0xFE0308, 3, TMS320C55_cmpand, {{ insn_1_U, 0x000004 }, { op_src, 0x00F000 }, { RELOP, 0x000C00 }, { RELOP_dst, 0x0000F0 }, { op_TCy, 0x000002 }, { fn_not, OP_TRUE }, { op_TCx, 0x000001 }}},
{ 0x120200, 0xFE0308, 3, TMS320C55_cmpor, {{ insn_1_U, OP_NOT(0x000004) }, { op_src, 0x00F000 }, { RELOP, 0x000C00 }, { RELOP_dst, 0x0000F0 }, { op_TCy, 0x000002 }, { op_TCx, 0x000001 }}},
{ 0x120208, 0xFE0308, 3, TMS320C55_cmpor, {{ insn_1_U, OP_NOT(0x000004) }, { op_src, 0x00F000 }, { RELOP, 0x000C00 }, { RELOP_dst, 0x0000F0 }, { op_TCy, 0x000002 }, { fn_not, OP_TRUE }, { op_TCx, 0x000001 }}},
{ 0x120300, 0xFE0308, 3, TMS320C55_rol, {{ op_BitOut, 0x000001 }, { op_src, 0x00F000 }, { op_BitIn, 0x000002 }, { op_dst, 0x0000F0 }}},
{ 0x120308, 0xFE0308, 3, TMS320C55_ror, {{ op_BitIn, 0x000002 }, { op_src, 0x00F000 }, { op_BitOut, 0x000001 }, { op_dst, 0x0000F0 }}},
{ 0x140000, 0xFE000F, 3, TMS320C55_aadd, {{ op_TAx, 0x00F000 }, { op_TAy, 0x0000F0 }}},
{ 0x140001, 0xFE000F, 3, TMS320C55_amov, {{ op_TAx, 0x00F000 }, { op_TAy, 0x0000F0 }}},
{ 0x140002, 0xFE000F, 3, TMS320C55_asub, {{ op_TAx, 0x00F000 }, { op_TAy, 0x0000F0 }}},
{ 0x140004, 0xFE000F, 3, TMS320C55_aadd, {{ op_k8, 0x00FF00 }, { op_TAx, 0x0000F0 }}},
{ 0x140005, 0xFE000F, 3, TMS320C55_amov, {{ op_k8, 0x00FF00 }, { op_TAx, 0x0000F0 }}},
{ 0x140006, 0xFE000F, 3, TMS320C55_asub, {{ op_k8, 0x00FF00 }, { op_TAx, 0x0000F0 }}},
{ 0x140008, 0xFE000F, 3, TMS320C55_aadd, {{ op_TAx, 0x00F000 }, { op_TAy, 0x0000F0 }}},
{ 0x140009, 0xFE000F, 3, TMS320C55_amov, {{ op_TAx, 0x00F000 }, { op_TAy, 0x0000F0 }}},
{ 0x14000A, 0xFE000F, 3, TMS320C55_asub, {{ op_TAx, 0x00F000 }, { op_TAy, 0x0000F0 }}},
{ 0x14000C, 0xFE000F, 3, TMS320C55_aadd, {{ op_k8, 0x00FF00 }, { op_TAx, 0x0000F0 }}},
{ 0x14000D, 0xFE000F, 3, TMS320C55_amov, {{ op_k8, 0x00FF00 }, { op_TAx, 0x0000F0 }}},
{ 0x14000E, 0xFE000F, 3, TMS320C55_asub, {{ op_k8, 0x00FF00 }, { op_TAx, 0x0000F0 }}},
{ 0x160000, 0xFE000F, 3, TMS320C55_mov2, {{ op_k7, 0x0007F0 }, { op_DPH, 0 }}},
{ 0x160001, 0xFE000F, 3, TMS320C55_mov2, {{ op_k7, 0x0007F0 }, { op_MDP05, 0 }}},
{ 0x160002, 0xFE000F, 3, TMS320C55_mov2, {{ op_k7, 0x0007F0 }, { op_MDP67, 0 }}},
{ 0x160003, 0xFE000F, 3, TMS320C55_mov2, {{ op_k9, 0x001FF0 }, { op_PDP, 0 }}},
{ 0x160004, 0xFE000F, 3, TMS320C55_mov2, {{ op_k12, 0x00FFF0 }, { op_BK03, 0 }}},
{ 0x160005, 0xFE000F, 3, TMS320C55_mov2, {{ op_k12, 0x00FFF0 }, { op_BK47, 0 }}},
{ 0x160006, 0xFE000F, 3, TMS320C55_mov2, {{ op_k12, 0x00FFF0 }, { op_BKC, 0 }}},
{ 0x160008, 0xFE000F, 3, TMS320C55_mov2, {{ op_k12, 0x00FFF0 }, { op_CSR, 0 }}},
{ 0x160009, 0xFE000F, 3, TMS320C55_mov2, {{ op_k12, 0x00FFF0 }, { op_BRC0, 0 }}},
{ 0x16000A, 0xFE000F, 3, TMS320C55_mov2, {{ op_k12, 0x00FFF0 }, { op_BRC1, 0 }}},
// 0001011E xxxxxxxk kkkk11xx error manual
{ 0x180000, 0xFE0000, 3, TMS320C55_and3, {{ op_k8, 0x00FF00 }, { op_src, 0x00000F }, { op_dst, 0x0000F0 }}},
{ 0x1A0000, 0xFE0000, 3, TMS320C55_or3, {{ op_k8, 0x00FF00 }, { op_src, 0x00000F }, { op_dst, 0x0000F0 }}},
{ 0x1C0000, 0xFE0000, 3, TMS320C55_xor3, {{ op_k8, 0x00FF00 }, { op_src, 0x00000F }, { op_dst, 0x0000F0 }}},
{ 0x1E0000, 0xFE0002, 3, TMS320C55_mpyk2, {{ insn_1_R, 0x000001 }, { op_K8, 0x00FF00 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}},
{ 0x1E0002, 0xFE0002, 3, TMS320C55_mack3, {{ insn_1_R, 0x000001 }, { op_Tx, 0x00000C }, { op_K8, 0x00FF00 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}},
{ 0x20, 0xFE, 1, TMS320C55_nop },
{ 0x2200, 0xFE00, 2, TMS320C55_mov2, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}},
{ 0x2400, 0xFE00, 2, TMS320C55_add1, {{ op_src, 0x00F0 }, { opt_dst, 0x000F }}},
{ 0x2600, 0xFE00, 2, TMS320C55_sub1, {{ op_src, 0x00F0 }, { opt_dst, 0x000F }}},
{ 0x2800, 0xFE00, 2, TMS320C55_and2, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}},
{ 0x2A00, 0xFE00, 2, TMS320C55_or2, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}},
{ 0x2C00, 0xFE00, 2, TMS320C55_xor2, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}},
{ 0x2E00, 0xFE00, 2, TMS320C55_max1, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}},
{ 0x3000, 0xFE00, 2, TMS320C55_min1, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}},
{ 0x3200, 0xFE00, 2, TMS320C55_abs1, {{ op_src, 0x00F0 }, { opt_dst, 0x000F }}},
{ 0x3400, 0xFE00, 2, TMS320C55_neg1, {{ op_src, 0x00F0 }, { opt_dst, 0x000F }}},
{ 0x3600, 0xFE00, 2, TMS320C55_not1, {{ op_src, 0x00F0 }, { opt_dst, 0x000F }}},
{ 0x3800, 0xFE00, 2, TMS320C55_psh2, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}},
{ 0x3A00, 0xFE00, 2, TMS320C55_pop2, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}},
{ 0x3C00, 0xFE00, 2, TMS320C55_mov2, {{ op_k4, 0x00F0 }, { op_dst, 0x000F }}},
{ 0x3E00, 0xFE00, 2, TMS320C55_mov2, {{ op_min_k4, 0x00F0 }, { op_dst, 0x000F }}},
{ 0x4000, 0xFE00, 2, TMS320C55_add2, {{ op_k4, 0x00F0 }, { op_dst, 0x000F }}},
{ 0x4200, 0xFE00, 2, TMS320C55_sub2, {{ op_k4, 0x00F0 }, { op_dst, 0x000F }}},
{ 0x4400, 0xFEC0, 2, TMS320C55_mov2, {{ op_ACx, 0x0030 }, { fn_hi, OP_TRUE }, { op_TAx, 0x000F }}},
{ 0x4440, 0xFED0, 2, TMS320C55_sfts2, {{ op_dst, 0x000F }, { op_min_1, 0 }}},
{ 0x4450, 0xFED0, 2, TMS320C55_sfts2, {{ op_dst, 0x000F }, { op_1, 0 }}},
{ 0x4480, 0xFEF0, 2, TMS320C55_mov2, {{ op_SP, 0 }, { op_TAx, 0x000F }}},
{ 0x4490, 0xFEF0, 2, TMS320C55_mov2, {{ op_SSP, 0 }, { op_TAx, 0x000F }}},
{ 0x44A0, 0xFEF0, 2, TMS320C55_mov2, {{ op_CDP, 0 }, { op_TAx, 0x000F }}},
{ 0x44C0, 0xFEF0, 2, TMS320C55_mov2, {{ op_BRC0, 0 }, { op_TAx, 0x000F }}},
{ 0x44D0, 0xFEF0, 2, TMS320C55_mov2, {{ op_BRC1, 0 }, { op_TAx, 0x000F }}},
{ 0x44E0, 0xFEF0, 2, TMS320C55_mov2, {{ op_RPTC, 0 }, { op_TAx, 0x000F }}},
{ 0x4600, 0xFE09, 2, TMS320C55_bclr2, {{ op_k4, 0x00F0 }, { op_STx_55, 0x0006 }}},
{ 0x4601, 0xFE09, 2, TMS320C55_bset2, {{ op_k4, 0x00F0 }, { op_STx_55, 0x0006 }}},
// 0100011E xxxx1000 error manual
// 0100011E xxxx1001 error manual
// 0100011E xxxx1010 error manual
// 0100011E xxxx1100 error manual
{ 0x4800, 0xFE07, 2, TMS320C55_rpt, {{ op_CSR, 0 }}},
{ 0x4801, 0xFE07, 2, TMS320C55_rptadd, {{ op_CSR, 0 }, { op_TAx, 0x00F0 }}},
{ 0x4802, 0xFE07, 2, TMS320C55_rptadd, {{ op_CSR, 0 }, { op_k4, 0x00F0 }}},
{ 0x4803, 0xFE07, 2, TMS320C55_rptsub, {{ op_CSR, 0 }, { op_k4, 0x00F0 }}},
{ 0x4804, 0xFE07, 2, TMS320C55_ret },
{ 0x4805, 0xFE07, 2, TMS320C55_reti },
{ 0x4A00, 0xFE80, 2, TMS320C55_b, {{ op_L7, 0x007F }}},
{ 0x4A80, 0xFE80, 2, TMS320C55_rptblocal, {{ op_pmad, 0x007F }}},
{ 0x4C00, 0xFE00, 2, TMS320C55_rpt, {{ op_k8, 0x00FF }}},
{ 0x4E00, 0xFE00, 2, TMS320C55_aadd, {{ op_K8, 0x00FF }, { op_SP, 0 }}},
{ 0x5000, 0xFE07, 2, TMS320C55_sftl2, {{ op_dst, 0x00F0 }, { op_1, 0 }}},
{ 0x5001, 0xFE07, 2, TMS320C55_sftl2, {{ op_dst, 0x00F0 }, { op_min_1, 0 }}},
{ 0x5002, 0xFE07, 2, TMS320C55_pop1, {{ op_dst, 0x00F0 }}},
{ 0x5003, 0xFE07, 2, TMS320C55_pop1, {{ op_ACx, 0x0030 }, { fn_dbl, OP_TRUE }}},
{ 0x5004, 0xFE07, 2, TMS320C55_popboth, {{ op_xsrc, 0x00F0 }}}, // not in documentation
{ 0x5005, 0xFE07, 2, TMS320C55_pshboth, {{ op_xsrc, 0x00F0 }}}, // not in documentation
{ 0x5006, 0xFE07, 2, TMS320C55_psh1, {{ op_dst, 0x00F0 }}},
{ 0x5007, 0xFE07, 2, TMS320C55_psh1, {{ op_ACx, 0x0030 }, { fn_dbl, OP_TRUE }}},
{ 0x5200, 0xFE0C, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_ACx, 0x0003 }, { fn_hi, OP_TRUE }}},
{ 0x5208, 0xFE0F, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_SP, 0 }}},
{ 0x5209, 0xFE0F, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_SSP, 0 }}},
{ 0x520A, 0xFE0F, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_CDP, 0 }}},
{ 0x520C, 0xFE0F, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_CSR, 0 }}},
{ 0x520D, 0xFE0F, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_BRC1, 0 }}},
{ 0x520E, 0xFE0F, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_BRC0, 0 }}},
{ 0x5400, 0xFE0F, 2, TMS320C55_addv1, {{ op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}},
{ 0x5401, 0xFE0F, 2, TMS320C55_addrv1, {{ op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}},
{ 0x5402, 0xFE0E, 2, TMS320C55_sqa1, {{ insn_1_R, 0x0001 }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}},
{ 0x5404, 0xFE0E, 2, TMS320C55_sqs1, {{ insn_1_R, 0x0001 }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}},
{ 0x5406, 0xFE0E, 2, TMS320C55_mpy1, {{ insn_1_R, 0x0001 }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}},
{ 0x5408, 0xFE0E, 2, TMS320C55_sqr1, {{ insn_1_R, 0x0001 }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}},
{ 0x540A, 0xFE0E, 2, TMS320C55_round1, {{ op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, // error manual: unused bits
{ 0x540C, 0xFE0E, 2, TMS320C55_sat1, {{ insn_1_R, 0x0001 }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}},
{ 0x5600, 0xFE02, 2, TMS320C55_mac3, {{ insn_1_R, 0x0001 }, { op_ACx, 0x0030 }, { op_Tx, 0x000C }, { opt_ACy, 0x00C0 }, { op_ACy, 0x00C0 }}},
{ 0x5602, 0xFE02, 2, TMS320C55_mas2, {{ insn_1_R, 0x0001 }, { op_Tx, 0x000C }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}},
{ 0x5800, 0xFE02, 2, TMS320C55_mpy2, {{ insn_1_R, 0x0001 }, { op_Tx, 0x000C }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}},
{ 0x5802, 0xFE02, 2, TMS320C55_mac4, {{ insn_1_R, 0x0001 }, { op_ACy, 0x00C0 }, { op_Tx, 0x000C }, { op_ACx, 0x0030 }, { op_ACy, 0x00C0 }}},
{ 0x5A00, 0xFE03, 2, TMS320C55_add2, {{ op_ACx, 0x0030 }, { shl_Tx, 0x000C }, { op_ACy, 0x00C0 }}},
{ 0x5A01, 0xFE03, 2, TMS320C55_sub2, {{ op_ACx, 0x0030 }, { shl_Tx, 0x000C }, { op_ACy, 0x00C0 }}},
{ 0x5A02, 0xFE02, 2, TMS320C55_sftcc, {{ op_ACx, 0x00C0 }, { op_TCx, 0x0001 }}},
{ 0x5C00, 0xFE03, 2, TMS320C55_sftl2, {{ op_ACx, 0x0030 }, { op_Tx, 0x000C }, { opt_ACy, 0x00C0 }}},
{ 0x5C01, 0xFE03, 2, TMS320C55_sfts2, {{ op_ACx, 0x0030 }, { op_Tx, 0x000C }, { opt_ACy, 0x00C0 }}},
{ 0x5C02, 0xFE03, 2, TMS320C55_sftsc2, {{ op_ACx, 0x0030 }, { op_Tx, 0x000C }, { opt_ACy, 0x00C0 }}},
{ 0x5E00, 0xFEC0, 2, TMS320C55_swap, {{ op_swap, 0x003F }}},
{ 0x5E80, 0xFEC0, 2, TMS320C55_nop_16 },
{ 0x6000, 0xF800, 2, TMS320C55_bcc, {{ op_l4, 0x0780 }, { op_cond, 0x007F }}},
{ 0x6800, 0xFF00, 2, TMS320C55_bcc, {{ op_P24, 0 }, { op_cond, 0x007F }}}, // compiler bug
{ 0x6900, 0xFF00, 2, TMS320C55_callcc, {{ op_P24, 0 }, { op_cond, 0x007F }}},
{ 0x6A, 0xFF, 1, TMS320C55_b, {{ op_P24, 0 }}},
{ 0x6C, 0xFF, 1, TMS320C55_call, {{ op_P24, 0 }}},
{ 0x6D000000, 0xFF000000, 4, TMS320C55_bcc, {{ op_L16, 0x0000FFFF }, { op_cond, 0x007F0000 }}},
{ 0x6E000000, 0xFF000000, 4, TMS320C55_callcc, {{ op_L16, 0x0000FFFF }, { op_cond, 0x007F0000 }}},
{ 0x6F000000, 0xFF000000, 4, TMS320C55_bcc, {{ insn_1_U, 0x00010000 }, { op_L8, 0x000000FF }, { op_src, 0x00F00000 }, { RELOP, 0x000C0000 }, { RELOP_K8, 0x0000FF00 }}},
{ 0x70000000, 0xFF000000, 4, TMS320C55_add2, {{ op_K16, 0x00FFFF00 }, { shl_SHFT, 0x0000000F }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}},
{ 0x71000000, 0xFF000000, 4, TMS320C55_sub2, {{ op_K16, 0x00FFFF00 }, { shl_SHFT, 0x0000000F }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}},
{ 0x72000000, 0xFF000000, 4, TMS320C55_and2, {{ op_k16, 0x00FFFF00 }, { shl_SHFT, 0x0000000F }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}},
{ 0x73000000, 0xFF000000, 4, TMS320C55_or2, {{ op_k16, 0x00FFFF00 }, { shl_SHFT, 0x0000000F }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}},
{ 0x74000000, 0xFF000000, 4, TMS320C55_xor2, {{ op_k16, 0x00FFFF00 }, { shl_SHFT, 0x0000000F }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}},
{ 0x75000000, 0xFF000000, 4, TMS320C55_mov2, {{ op_K16, 0x00FFFF00 }, { shl_SHFT, 0x0000000F }, { op_ACx, 0x00000030 }}},
{ 0x76000000, 0xFF00000C, 4, TMS320C55_bfxtr, {{ op_k16, 0x00FFFF00 }, { op_ACx, 0x00000003 }, { op_dst, 0x000000F0 }}},
{ 0x76000004, 0xFF00000C, 4, TMS320C55_bfxpa, {{ op_k16, 0x00FFFF00 }, { op_ACx, 0x00000003 }, { op_dst, 0x000000F0 }}},
{ 0x76000008, 0xFF00000C, 4, TMS320C55_mov2, {{ op_K16, 0x00FFFF00 }, { op_dst, 0x000000F0 }}},
{ 0x77000000, 0xFF000000, 4, TMS320C55_amov, {{ op_D16, 0x00FFFF00 }, { op_TAx, 0x000000F0 }}},
{ 0x78000000, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_DP, 0 }}},
{ 0x78000002, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_SSP, 0 }}},
{ 0x78000004, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_CDP, 0 }}},
{ 0x78000006, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_BSA01, 0 }}},
{ 0x78000008, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_BSA23, 0 }}},
{ 0x7800000A, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_BSA45, 0 }}},
{ 0x7800000C, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_BSA67, 0 }}},
{ 0x7800000E, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_BSAC, 0 }}},
{ 0x78000010, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_SP, 0 }}},
{ 0x79000000, 0xFF000002, 4, TMS320C55_mpyk2, {{ insn_1_R, 0x00000001 }, { op_K16, 0x00FFFF00 }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}},
{ 0x79000002, 0xFF000002, 4, TMS320C55_mack3, {{ insn_1_R, 0x00000001 }, { op_Tx, 0x0000000C }, { op_K16, 0x00FFFF00 }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}},
{ 0x7A000000, 0xFF00000E, 4, TMS320C55_add2, {{ op_K16, 0x00FFFF00 }, { shl_16, 0, }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}},
{ 0x7A000002, 0xFF00000E, 4, TMS320C55_sub2, {{ op_K16, 0x00FFFF00 }, { shl_16, 0, }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}},
{ 0x7A000004, 0xFF00000E, 4, TMS320C55_and2, {{ op_k16, 0x00FFFF00 }, { shl_16, 0, }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}},
{ 0x7A000006, 0xFF00000E, 4, TMS320C55_or2, {{ op_k16, 0x00FFFF00 }, { shl_16, 0, }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}},
{ 0x7A000008, 0xFF00000E, 4, TMS320C55_xor2, {{ op_k16, 0x00FFFF00 }, { shl_16, 0, }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}},
{ 0x7A00000A, 0xFF00000E, 4, TMS320C55_mov2, {{ op_K16, 0x00FFFF00 }, { shl_16, 0, }, { op_ACx, 0x00000030 }}},
{ 0x7A00000C, 0xFF00000E, 4, TMS320C55_idle },
{ 0x7B000000, 0xFF000000, 4, TMS320C55_add2, {{ op_K16, 0x00FFFF00 }, { op_src, 0x0000000F }, { opt_dst, 0x000000F0 }}},
{ 0x7C000000, 0xFF000000, 4, TMS320C55_sub2, {{ op_K16, 0x00FFFF00 }, { op_src, 0x0000000F }, { opt_dst, 0x000000F0 }}},
{ 0x7D000000, 0xFF000000, 4, TMS320C55_and2, {{ op_k16, 0x00FFFF00 }, { op_src, 0x0000000F }, { op_dst, 0x000000F0 }}},
{ 0x7E000000, 0xFF000000, 4, TMS320C55_or2, {{ op_k16, 0x00FFFF00 }, { op_src, 0x0000000F }, { op_dst, 0x000000F0 }}},
{ 0x7F000000, 0xFF000000, 4, TMS320C55_xor2, {{ op_k16, 0x00FFFF00 }, { op_src, 0x0000000F }, { op_dst, 0x000000F0 }}},
{ 0x800000, 0xFF000C, 3, TMS320C55_mov2, {{ op_Xmem, 0x00FC00 }, { fn_dbl, OP_TRUE, }, { op_Ymem, 0x0003F0 }, { fn_dbl, OP_TRUE }}},
{ 0x800004, 0xFF000C, 3, TMS320C55_mov2, {{ op_Xmem, 0x00FC00 }, { op_Ymem, 0x0003F0 }}},
{ 0x800008, 0xFF000C, 3, TMS320C55_mov3, {{ op_ACx, 0x000003 }, { op_Xmem, 0x00FC00, }, { op_Ymem, 0x0003F0 }}},
{ 0x810000, 0xFF000C, 3, TMS320C55_add3, {{ op_Xmem, 0x00FC00 }, { op_Ymem, 0x0003F0, }, { op_ACx, 0x000003 }}},
{ 0x810004, 0xFF000C, 3, TMS320C55_sub3, {{ op_Xmem, 0x00FC00 }, { op_Ymem, 0x0003F0, }, { op_ACx, 0x000003 }}},
{ 0x810008, 0xFF000C, 3, TMS320C55_mov3, {{ op_Xmem, 0x00FC00 }, { op_Ymem, 0x0003F0, }, { op_ACx, 0x000003 }}},
{ 0x82000000, 0xFF000C00, 4, TMS320C55_mpy_mpy, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}},
{ 0x82000400, 0xFF000C00, 4, TMS320C55_mac_mpy, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}},
{ 0x82000800, 0xFF000C00, 4, TMS320C55_mas_mpy, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}},
{ 0x82000C00, 0xFF000C00, 4, TMS320C55_amar_mpy, {{ insn_1_2_R, 0x00000001 }, { insn_1_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x0000000C }}},
{ 0x83000000, 0xFF000C00, 4, TMS320C55_mac_mac, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}},
{ 0x83000400, 0xFF000C00, 4, TMS320C55_mas_mac, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}},
{ 0x83000800, 0xFF000C00, 4, TMS320C55_mac_mac, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { shr, OP_IMM(16) }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}},
{ 0x83000C00, 0xFF000C00, 4, TMS320C55_amar_mac, {{ insn_1_2_R, 0x00000001 }, { insn_1_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x0000000C }}},
{ 0x84000000, 0xFF000C00, 4, TMS320C55_mas_mac, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }, { shr, OP_IMM(16) }}},
{ 0x84000400, 0xFF000C00, 4, TMS320C55_amar_mac, {{ insn_1_2_R, 0x00000001 }, { insn_1_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x0000000C }, { shr, OP_IMM(16) }}},
{ 0x84000800, 0xFF000C00, 4, TMS320C55_mpy_mac, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }, { shr, OP_IMM(16) }}},
{ 0x84000C00, 0xFF000C00, 4, TMS320C55_mac_mac, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { shr, OP_IMM(16) }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }, { shr, OP_IMM(16) }}},
{ 0x85000000, 0xFF000C00, 4, TMS320C55_amar_mas, {{ insn_1_2_R, 0x00000001 }, { insn_1_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x0000000C }}},
{ 0x85000400, 0xFF000C00, 4, TMS320C55_mas_mas, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}},
{ 0x85000800, 0xFF000C00, 4, TMS320C55_amar3, {{ op_Xmem, 0x00FC0000 }, { op_Ymem, 0x0003F000 }, { op_Cmem, 0x00000300 }}},
{ 0x85000C00, 0xFF000C10, 4, TMS320C55_firsadd, {{ op_Xmem, 0x00FC0000 }, { op_Ymem, 0x0003F000 }, { op_Cmem, 0x00000300 }, { op_ACx, 0x000000C0 }, { op_ACy, 0x0000000C }}}, // error manual: unused bits: DDx0DDU% p552
{ 0x85000C10, 0xFF000C10, 4, TMS320C55_firssub, {{ op_Xmem, 0x00FC0000 }, { op_Ymem, 0x0003F000 }, { op_Cmem, 0x00000300 }, { op_ACx, 0x000000C0 }, { op_ACy, 0x0000000C }}}, // error manual: unused bits: DDx0DDU% p552
{ 0x86000000, 0xFF0000E0, 4, TMS320C55_mpym3, {{ insn_1_R, 0x00000001 }, { insn_1_40, 0x00000010 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000008 }, { fn_T3, 0x00000002 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000004 }, { op_ACx, 0x00000300 }}},
{ 0x86000020, 0xFF0000E0, 4, TMS320C55_macm3, {{ insn_1_R, 0x00000001 }, { insn_1_40, 0x00000010 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000008 }, { fn_T3, 0x00000002 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000004 }, { op_ACx, 0x00000C00 }, { opt_ACy, 0x00000300 }}},
{ 0x86000040, 0xFF0000E0, 4, TMS320C55_macm3, {{ insn_1_R, 0x00000001 }, { insn_1_40, 0x00000010 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000008 }, { fn_T3, 0x00000002 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000004 }, { op_ACx, 0x00000C00 }, { shr, OP_IMM(16) }, { opt_ACy, 0x00000300 }}},
{ 0x86000060, 0xFF0000E0, 4, TMS320C55_masm3, {{ insn_1_R, 0x00000001 }, { insn_1_40, 0x00000010 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000008 }, { fn_T3, 0x00000002 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000004 }, { op_ACx, 0x00000C00 }, { opt_ACy, 0x00000300 }}},
{ 0x86000080, 0xFF0000E0, 4, TMS320C55_masm_mov, {{ insn_1_R_2, 0x00000001 }, { op_Xmem, 0x00FC0000 }, { fn_T3, 0x00000002 }, { op_Tx, 0x0000000C }, { op_ACx, 0x00000C00 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { shl_16, 0 }, { op_ACy, 0x00000300 }}},
{ 0x860000A0, 0xFF0000E0, 4, TMS320C55_macm_mov, {{ insn_1_R_2, 0x00000001 }, { op_Xmem, 0x00FC0000 }, { fn_T3, 0x00000002 }, { op_Tx, 0x0000000C }, { op_ACx, 0x00000C00 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { shl_16, 0 }, { op_ACy, 0x00000300 }}},
{ 0x860000C0, 0xFF0000E0, 4, TMS320C55_lms, {{ op_Xmem, 0x00FC0000 }, { op_Ymem, 0x0003F000 }, { op_ACx, 0x00000C00 }, { op_ACy, 0x00000300 }}},
{ 0x860000E0, 0xFF0000F0, 4, TMS320C55_sqdst, {{ op_Xmem, 0x00FC0000 }, { op_Ymem, 0x0003F000 }, { op_ACx, 0x00000C00 }, { op_ACy, 0x00000300 }}},
{ 0x860000F0, 0xFF0000F0, 4, TMS320C55_abdst, {{ op_Xmem, 0x00FC0000 }, { op_Ymem, 0x0003F000 }, { op_ACx, 0x00000C00 }, { op_ACy, 0x00000300 }}},
{ 0x87000000, 0xFF0000E0, 4, TMS320C55_mpym_mov, {{ insn_1_R_2, 0x00000001 }, { op_Xmem, 0x00FC0000 }, { fn_T3, 0x00000002 }, { op_Tx, 0x0000000C }, { op_ACy, 0x00000300 }, { blt_prll, 0, }, { op_ACx, 0x00000C00 }, { fn_hi, OP_TRUE }, { shl_T2, 0 }, { op_Ymem, 0x0003F000 }}},
{ 0x87000020, 0xFF0000E0, 4, TMS320C55_macm_mov, {{ insn_1_R_2, 0x00000001 }, { op_Xmem, 0x00FC0000 }, { fn_T3, 0x00000002 }, { op_Tx, 0x0000000C }, { op_ACy, 0x00000300 }, { blt_prll, 0, }, { op_ACx, 0x00000C00 }, { fn_hi, OP_TRUE }, { shl_T2, 0 }, { op_Ymem, 0x0003F000 }}},
{ 0x87000040, 0xFF0000E0, 4, TMS320C55_masm_mov, {{ insn_1_R_2, 0x00000001 }, { op_Xmem, 0x00FC0000 }, { fn_T3, 0x00000002 }, { op_Tx, 0x0000000C }, { op_ACy, 0x00000300 }, { blt_prll, 0, }, { op_ACx, 0x00000C00 }, { fn_hi, OP_TRUE }, { shl_T2, 0 }, { op_Ymem, 0x0003F000 }}},
{ 0x87000080, 0xFF0000E0, 4, TMS320C55_add_mov, {{ op_Xmem, 0x00FC0000 }, { shl_16, 0, }, { op_ACx, 0x00000C00 }, { op_ACy, 0x00000300 }, { blt_prll, 0, }, { op_ACy, 0x00000300 }, { fn_hi, OP_TRUE, }, { shl_T2, 0 }, { op_Ymem, 0x0003F000 }}},
{ 0x870000A0, 0xFF0000E0, 4, TMS320C55_sub_mov, {{ op_Xmem, 0x00FC0000 }, { shl_16, 0, }, { op_ACx, 0x00000C00 }, { op_ACy, 0x00000300 }, { blt_prll, 0, }, { op_ACy, 0x00000300 }, { fn_hi, OP_TRUE, }, { shl_T2, 0 }, { op_Ymem, 0x0003F000 }}},
{ 0x870000C0, 0xFF0000E0, 4, TMS320C55_mov_mov, {{ op_Xmem, 0x00FC0000 }, { shl_16, 0, }, { op_ACy, 0x00000300 }, { blt_prll, 0, }, { op_ACx, 0x00000C00 }, { fn_hi, OP_TRUE }, { shl_T2, 0, }, { op_Ymem, 0x0003F000 }}},
{ 0x8A0000A0, 0xFF0000F0, 4, TMS320C55_mov_mov, {{ op_Xmem, 0x00FC0000 }, { op_dst, 0x00000F00 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { op_dst, 0x0000000F }}},
{ make_longlong(0x00001000, 0x008A), make_longlong(0x0000F700, 0x00FF), 5, TMS320C55_mov_aadd, {{ op_Smem, 0xFF000000 }, { op_dst, 0x000F0000 }, { blt_prll, 0 }, { op_src, 0x00000000F0 }, { op_dst, 0x0000F00000 }}},
{ make_longlong(0x0000D600, 0x008A), make_longlong(0x0000FF00, 0x00FF), 5, TMS320C55_mov_add, {{ op_Xmem, 0xFC000000 }, { op_dst, 0x000F0000 }, { blt_prll, 0 }, { op_Ymem, 0x0003F00000 }, { op_dst, 0x00000000F0 }, { op_src, 0x000000000F }}},
{ make_longlong(0x0000E708, 0x008A), make_longlong(0x0000FF0C, 0x00FF), 5, TMS320C55_mov_mov, {{ op_Xmem, 0xFC000000 }, { op_dst, 0x000F0000 }, { blt_prll, 0 }, { op_ACx, 0x00000000C0 }, { shl_Tx, 0x0000000030 }, { fn_hi, OP_TRUE_5 }, { fn_rnd, 0x0000000001 }, { op_Ymem, 0x0003F00000 }}},
{ 0x8B0004B4, 0xFF000FFF, 4, TMS320C55_amar_amar, {{ op_Xmem, 0x00FC0000 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }}},
{ make_longlong(0x00001400, 0x008C), make_longlong(0x0000F700, 0x00FF), 5, TMS320C55_mov_aadd, {{ op_src, 0x000F0000 }, { op_Smem, 0xFF000000 }, { blt_prll, 0 }, { op_k8, 0x00000000FF }, { op_dst, 0x0000F00000 }}},
{ make_longlong(0x000CB000, 0x008D), make_longlong(0x000FFC03, 0x00FF), 5, TMS320C55_btst_mov, {{ op_k4, 0x000000F0 }, { op_Xmem, 0xFC000000 }, { op_TCx, 0x00000001 }, { blt_prll, 0 }, { op_Ymem, 0x0003F00000 }, { shl_16, 0 }, { op_ACx, 0x00000300 }}},
{ make_longlong(0x061A0000, 0x8D00), make_longlong(0x0FF70000, 0xFF00), 6, TMS320C55_add_asub, {{ op_Smem, make_longlong(0x00000000, 0x00FF) }, { op_dst, make_longlong(0x0000F000, 0x0000) }, { op_src, 0x000000000F00 }, { blt_prll, 0 }, { op_src, 0x0000000000F0 }, { op_dst, 0x0000F0000000 }}},
{ make_longlong(0x0B100500, 0x8E00), make_longlong(0x0FF70F00, 0xFF00), 6, TMS320C55_mov_aadd, {{ op_xdst, make_longlong(0x0000F000, 0x0000) }, { op_Lmem, make_longlong(0x00000000, 0x00FF) }, { fn_dbl, OP_TRUE_6 }, { blt_prll, 0 }, { op_src, 0x0000000000F0 }, { op_dst, 0x0000F0000000 }}},
{ make_longlong(0x0B160500, 0x8E00), make_longlong(0x0FF70F00, 0xFF00), 6, TMS320C55_mov_asub, {{ op_xdst, make_longlong(0x0000F000, 0x0000) }, { op_Lmem, make_longlong(0x00000000, 0x00FF) }, { fn_dbl, OP_TRUE_6 }, { blt_prll, 0 }, { op_k8, 0x0000000000FF }, { op_dst, 0x0000F0000000 }}},
{ make_longlong(0x0D100800, 0x8E00), make_longlong(0x0FF70F00, 0xFF00), 6, TMS320C55_mov_aadd, {{ op_Lmem, make_longlong(0x00000000, 0x00FF) }, { fn_dbl, OP_TRUE_6 }, { op_ACx, 0x000000003000 }, { blt_prll, 0 }, { op_src, 0x0000000000F0 }, { op_dst, 0x0000F0000000 }}},
{ make_longlong(0x0B140500, 0x8E00), make_longlong(0x0FF70F00, 0xFF00), 6, TMS320C55_mov_aadd, {{ op_xdst, make_longlong(0x0000F000, 0x0000) }, { op_Lmem, make_longlong(0x00000000, 0x00FF) }, { fn_dbl, OP_TRUE_6 }, { blt_prll, 0 }, { op_k8, 0x0000000000FF }, { op_dst, 0x0000F0000000 }}},
{ make_longlong(0x0B140800, 0x8E00), make_longlong(0x0FF70F00, 0xFF00), 6, TMS320C55_mov_aadd, {{ op_ACx, make_longlong(0x00003000, 0x0000) }, { op_Lmem, make_longlong(0x00000000, 0x00FF) }, { fn_dbl, OP_TRUE_6 }, { blt_prll, 0 }, { op_k8, 0x0000000000FF }, { op_dst, 0x0000F0000000 }}},
{ make_longlong(0x0B100800, 0x8E00), make_longlong(0x0FF70F00, 0xFF00), 6, TMS320C55_mov_aadd, {{ op_ACx, make_longlong(0x00003000, 0x0000) }, { op_Lmem, make_longlong(0x00000000, 0x00FF) }, { fn_dbl, OP_TRUE_6 }, { blt_prll, 0 }, { op_src, 0x0000000000F0 }, { op_dst, 0x0000F0000000 }}},
{ make_longlong(0x06140000, 0x8E00), make_longlong(0x0FF70000, 0xFF00), 6, TMS320C55_mov_aadd, {{ op_k8, make_longlong(0x0000FF00, 0x0000) }, { op_Lmem, make_longlong(0x00000000, 0x00FF) }, { blt_prll, 0 }, { op_k8, 0x0000000000FF }, { op_dst, 0x0000F0000000 }}},
{ make_longlong(0x0DEB080D, 0x8E00), make_longlong(0x0FFF0F0F, 0xFF00), 6, TMS320C55_mov_mov, {{ op_Xmem, make_longlong(0x00000000, 0x00FC) }, { fn_dbl, OP_TRUE_6 }, { op_ACx, 0x000000003000 }, { blt_prll, 0 }, { op_ACx, 0x000000000030 }, { shr, OP_IMM_6(1) }, { op_Ymem, make_longlong(0xF0000000, 0x0003) }, { fn_dual, OP_TRUE_6 }}},
{ make_longlong(0x0EEB040D, 0x8E00), make_longlong(0x0FFF0F0F, 0xFF00), 6, TMS320C55_sub_mov, {{ op_Xmem, make_longlong(0x00000000, 0x00FC) }, { fn_dual, OP_TRUE_6 }, { op_ACx, 0x00000000C000 }, { op_ACy, 0x000000003000 }, { blt_prll, 0 }, { op_ACx, 0x000000000030 }, { shr, OP_IMM_6(1 ) }, { op_Ymem, make_longlong(0xF0000000, 0x03) }, { fn_dual, OP_TRUE_6 }}},
{ make_longlong(0x0EEB000D, 0x8E00), make_longlong(0x0FFF0F0F, 0xFF00), 6, TMS320C55_add_mov, {{ op_Xmem, make_longlong(0x00000000, 0x00FC) }, { fn_dual, OP_TRUE_6 }, { op_ACx, 0x00000000C000 }, { op_ACy, 0x000000003000 }, { blt_prll, 0 }, { op_ACx, 0x000000000030 }, { shr, OP_IMM_6(1 ) }, { op_Ymem, make_longlong(0xF0000000, 0x03) }, { fn_dual, OP_TRUE_6 }}},
{ make_longlong(0x0EEB0408, 0x8E00), make_longlong(0x0FFF0F0F, 0xFF00), 6, TMS320C55_sub_mov, {{ op_Xmem, make_longlong(0x00000000, 0x00FC) }, { fn_dual, OP_TRUE_6 }, { op_ACx, 0x00000000C000 }, { op_ACy, 0x000000003000 }, { blt_prll, 0 }, { op_ACx, 0x000000000030 }, { op_Ymem, make_longlong(0xF0000000, 0x0003) }, { fn_dbl, OP_TRUE_6 }}},
{ make_longlong(0x0EEB0008, 0x8E00), make_longlong(0x0FFF0F0F, 0xFF00), 6, TMS320C55_add_mov, {{ op_Xmem, make_longlong(0x00000000, 0x00FC) }, { fn_dual, OP_TRUE_6 }, { op_ACx, 0x00000000C000 }, { op_ACy, 0x000000003000 }, { blt_prll, 0 }, { op_ACx, 0x000000000030 }, { op_Ymem, make_longlong(0xF0000000, 0x0003) }, { fn_dbl, OP_TRUE_6 }}},
// 10001xxx error manual
{ 0x9000, 0xFF00, 2, TMS320C55_mov2, {{op_xsrc, 0x00F0 }, {op_xdst, 0x000F}}},
{ 0x9100, 0xFF00, 2, TMS320C55_b, {{ op_ACx, 0x0003 }}},
{ 0x9200, 0xFF00, 2, TMS320C55_call, {{ op_ACx, 0x0003 }}},
{ 0x9400, 0xFF00, 2, TMS320C55_reset },
{ 0x9500, 0xFF80, 2, TMS320C55_intr, {{ op_k5, 0x001F }}},
{ 0x9580, 0xFF80, 2, TMS320C55_trap, {{ op_k5, 0x001F }}},
{ 0x9600, 0xFF80, 2, TMS320C55_xcc, {{ op_cond, 0x007F }}},
{ 0x9680, 0xFF80, 2, TMS320C55_xccpart, {{ op_cond, 0x007F }}},
// 10010111 error manual
// mmap()
// port()
// <instruction>.LR
// <instruction>.CR
{ 0x9E00, 0xFF80, 2, TMS320C55_xcc, {{ op_cond, 0x007F }, { insn_UP, 0 }}},
{ 0x9E80, 0xFF80, 2, TMS320C55_xccpart, {{ op_cond, 0x007F }}},
{ 0x9F00, 0xFF80, 2, TMS320C55_xcc, {{ op_cond, 0x007F }}},
{ 0x9F80, 0xFF80, 2, TMS320C55_xccpart, {{ op_cond, 0x007F }}},
{ 0xA000, 0xF000, 2, TMS320C55_mov2, {{ op_Smem, 0x00FF }, { op_dst, 0x0F00 }}},
{ 0xB000, 0xFC00, 2, TMS320C55_mov2, {{ op_Smem, 0x00FF }, { shl_16, 0 }, { op_ACx, 0x0300 }}},
{ 0xB400, 0xFF00, 2, TMS320C55_amar1, {{ op_Smem, 0x00FF }}},
{ 0xB500, 0xFF00, 2, TMS320C55_psh1, {{ op_Smem, 0x00FF }}},
{ 0xB600, 0xFF00, 2, TMS320C55_delay, {{ op_Smem, 0x00FF }}},
{ 0xB700, 0xFF00, 2, TMS320C55_psh1, {{ op_Lmem, 0x00FF }, { fn_dbl, OP_TRUE }}},
{ 0xB800, 0xFF00, 2, TMS320C55_pop1, {{ op_Lmem, 0x00FF }, { fn_dbl, OP_TRUE }}},
{ 0xBB00, 0xFF00, 2, TMS320C55_pop1, {{ op_Smem, 0x00FF }}},
{ 0xBC00, 0xFC00, 2, TMS320C55_mov2, {{ op_ACx, 0x0300 }, { fn_hi, OP_TRUE }, { op_Smem, 0x00FF }}},
{ 0xC000, 0xF000, 2, TMS320C55_mov2, {{ op_src, 0x0F00 }, { op_Smem, 0x00FF }}},
{ 0xD00000, 0xFF0040, 3, TMS320C55_macmz, {{ op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Cmem, 0x000003 }, { op_ACx, 0x000030 }}},
{ 0xD00040, 0xFF0040, 3, TMS320C55_macmrz, {{ op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Cmem, 0x000003 }, { op_ACx, 0x000030 }}},
{ 0xD10000, 0xFF000C, 3, TMS320C55_mpym3, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Cmem, 0x000003 }, { op_ACx, 0x000030 }}},
{ 0xD10004, 0xFF000C, 3, TMS320C55_macm3, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Cmem, 0x000003 }, { op_ACx, 0x000030 }}},
{ 0xD10008, 0xFF000C, 3, TMS320C55_masm3, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Cmem, 0x000003 }, { op_ACx, 0x000030 }}},
{ 0xD20000, 0xFF000C, 3, TMS320C55_macm2, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}},
{ 0xD20004, 0xFF000C, 3, TMS320C55_masm2, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}},
{ 0xD20008, 0xFF000C, 3, TMS320C55_sqam2, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}},
{ 0xD2000C, 0xFF000C, 3, TMS320C55_sqsm2, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}},
{ 0xD30000, 0xFF000C, 3, TMS320C55_mpym2, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}},
{ 0xD30008, 0xFF000C, 3, TMS320C55_sqrm, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_ACx, 0x000030 }}},
{ 0xD30004, 0xFF0004, 3, TMS320C55_mpym3, {{ insn_1_R, 0x000040 }, { insn_1_U, 0x000008 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Tx, 0x000003 }, { op_ACx, 0x000030 }}},
{ 0xD40000, 0xFF0000, 3, TMS320C55_macm3, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Tx, 0x00000C }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}},
{ 0xD50000, 0xFF0000, 3, TMS320C55_masm3, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Tx, 0x00000C }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}},
{ 0xD60000, 0xFF0000, 3, TMS320C55_add2, {{ op_Smem, 0x00FF00 }, { op_src, 0x00000F }, { opt_dst, 0x0000F0 }}},
{ 0xD70000, 0xFF0000, 3, TMS320C55_sub2, {{ op_Smem, 0x00FF00 }, { op_src, 0x00000F }, { opt_dst, 0x0000F0 }}},
{ 0xD80000, 0xFF0000, 3, TMS320C55_sub3, {{ op_src, 0x00000F }, { op_Smem, 0x00FF00 }, { op_dst, 0x0000F0 }}},
{ 0xD90000, 0xFF0000, 3, TMS320C55_and3, {{ op_Smem, 0x00FF00 }, { op_src, 0x00000F }, { op_dst, 0x0000F0 }}},
{ 0xDA0000, 0xFF0000, 3, TMS320C55_or3, {{ op_Smem, 0x00FF00 }, { op_src, 0x00000F }, { op_dst, 0x0000F0 }}},
{ 0xDB0000, 0xFF0000, 3, TMS320C55_xor3, {{ op_Smem, 0x00FF00 }, { op_src, 0x00000F }, { op_dst, 0x0000F0 }}},
{ 0xDC0000, 0xFF0002, 3, TMS320C55_btst, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TCx, 0x000001 }}},
{ 0xDC0002, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_DP, 0 }}},
{ 0xDC0012, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_CDP, 0 }}},
{ 0xDC0022, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BSA01, 0 }}},
{ 0xDC0032, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BSA23, 0 }}},
{ 0xDC0042, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BSA45, 0 }}},
{ 0xDC0052, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BSA67, 0 }}},
{ 0xDC0062, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BSAC, 0 }}},
{ 0xDC0072, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_SP, 0 }}},
{ 0xDC0082, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_SSP, 0 }}},
{ 0xDC0092, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BK03, 0 }}},
{ 0xDC00A2, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BK47, 0 }}},
{ 0xDC00B2, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BKC, 0 }}},
{ 0xDC00C2, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_DPH, 0 }}},
{ 0xDC00D2, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_MDP05, 0 }}},
{ 0xDC00E2, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_MDP67, 0 }}},
{ 0xDC00F2, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_PDP, 0 }}},
{ 0xDC0003, 0xFF0073, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_CSR, 0 }}},
{ 0xDC0013, 0xFF0073, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BRC0, 0 }}},
{ 0xDC0023, 0xFF0073, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BRC1, 0 }}},
{ 0xDC0033, 0xFF0073, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_TRN0, 0 }}},
{ 0xDC0043, 0xFF0073, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_TRN1, 0 }}},
{ 0xDD0000, 0xFF0003, 3, TMS320C55_add2, {{ op_Smem, 0x00FF00 }, { shl_Tx, 0x00000C }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}},
{ 0xDD0001, 0xFF0003, 3, TMS320C55_sub2, {{ op_Smem, 0x00FF00 }, { shl_Tx, 0x00000C }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}},
{ 0xDD0002, 0xFF0003, 3, TMS320C55_addsub2cc, {{ op_Smem, 0x00FF00 }, { op_ACx, 0x0000C0 }, { op_Tx, 0x00000C }, { op_TC1, 0, }, { op_TC2, 0, }, { op_ACy, 0x000030 }}},
{ 0xDD0003, 0xFF0003, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { shl_Tx, 0x00000C }, { fn_rnd, 0x000040 }, { op_ACx, 0x000030 }}},
{ 0xDE0000, 0xFF000F, 3, TMS320C55_addsubcc4, {{ op_Smem, 0x00FF00 }, { op_ACx, 0x0000C0 }, { op_TC1, 0 }, { op_ACy, 0x000030 }}},
{ 0xDE0001, 0xFF000F, 3, TMS320C55_addsubcc4, {{ op_Smem, 0x00FF00 }, { op_ACx, 0x0000C0 }, { op_TC2, 0 }, { op_ACy, 0x000030 }}},
{ 0xDE0002, 0xFF000F, 3, TMS320C55_addsubcc4, {{ op_Smem, 0x00FF00 }, { op_ACx, 0x0000C0 }, { op_TC1, 0 }, { op_TC2, 0, }, { op_ACy, 0x000030 }}},
{ 0xDE0003, 0xFF000F, 3, TMS320C55_subc2, {{ op_Smem, 0x00FF00 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}},
{ 0xDE0004, 0xFF000F, 3, TMS320C55_add2, {{ op_Smem, 0x00FF00 }, { shl_16, 0 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}},
{ 0xDE0005, 0xFF000F, 3, TMS320C55_sub2, {{ op_Smem, 0x00FF00 }, { shl_16, 0 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}},
{ 0xDE0006, 0xFF000F, 3, TMS320C55_sub3, {{ op_ACx, 0x0000C0 }, { op_Smem, 0x00FF00 }, { shl_16, 0 }, { op_ACy, 0x000030 }}},
{ 0xDE0008, 0xFF000F, 3, TMS320C55_addsub, {{ op_Tx, 0x0000C0 }, { op_Smem, 0x00FF00 }, { op_ACx, 0x000030 }}},
{ 0xDE0009, 0xFF000F, 3, TMS320C55_subadd, {{ op_Tx, 0x0000C0 }, { op_Smem, 0x00FF00 }, { op_ACx, 0x000030 }}},
{ 0xDF0000, 0xFF000E, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { fn_hb, OP_TRUE }, { fn_uns, OP_NOT(0x000001) }, { op_dst, 0x0000F0 }}},
{ 0xDF0002, 0xFF000E, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { fn_lb, OP_TRUE }, { fn_uns, OP_NOT(0x000001) }, { op_dst, 0x0000F0 }}},
{ 0xDF0004, 0xFF000E, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { fn_uns, 0x000001 }, { op_ACx, 0x000030 }}},
{ 0xDF0008, 0xFF000E, 3, TMS320C55_add3, {{ op_Smem, 0x00FF00 }, { fn_uns, 0x000001 }, { op_CARRY, 0 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}},
{ 0xDF000A, 0xFF000E, 3, TMS320C55_sub3, {{ op_Smem, 0x00FF00 }, { fn_uns, 0x000001 }, { op_BORROW, 0 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}},
{ 0xDF000C, 0xFF000E, 3, TMS320C55_add2, {{ op_Smem, 0x00FF00 }, { fn_uns, 0x000001 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}},
{ 0xDF000E, 0xFF000E, 3, TMS320C55_sub2, {{ op_Smem, 0x00FF00 }, { fn_uns, 0x000001 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}},
{ 0xE00000, 0xFF0000, 3, TMS320C55_btst, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TCx, 0x000001 }}},
{ 0xE10000, 0xFF0000, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { fn_lb, OP_TRUE }, { slo_SHIFTW, 0x00003F }, { op_ACx, 0x0000C0 }}},
{ 0xE20000, 0xFF0000, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { fn_hb, OP_TRUE }, { slo_SHIFTW, 0x00003F }, { op_ACx, 0x0000C0 }}},
{ 0xE30000, 0xFF000E, 3, TMS320C55_btstset, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TC1 }}},
{ 0xE30002, 0xFF000E, 3, TMS320C55_btstset, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TC2 }}},
{ 0xE30004, 0xFF000E, 3, TMS320C55_btstclr, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TC1 }}},
{ 0xE30006, 0xFF000E, 3, TMS320C55_btstclr, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TC2 }}},
{ 0xE30008, 0xFF000E, 3, TMS320C55_btstnot, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TC1 }}},
{ 0xE3000A, 0xFF000E, 3, TMS320C55_btstnot, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TC2 }}},
{ 0xE3000C, 0xFF000F, 3, TMS320C55_bset2, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }}},
{ 0xE3000D, 0xFF000F, 3, TMS320C55_bclr2, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }}},
{ 0xE3000E, 0xFF000E, 3, TMS320C55_bnot, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }}},
{ 0xE40000, 0xFF0004, 3, TMS320C55_psh2, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }}},
{ 0xE40004, 0xFF0004, 3, TMS320C55_pop2, {{ op_dst, 0x0000F0 }, { op_Smem, 0x00FF00 }}},
{ 0xE50004, 0xFF000D, 3, TMS320C55_mov2, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }, { fn_hb, OP_TRUE }}},
{ 0xE50005, 0xFF000D, 3, TMS320C55_mov2, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }, { fn_lb, OP_TRUE }}},
{ 0xE50008, 0xFF00FC, 3, TMS320C55_mov2, {{ op_DP, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE50018, 0xFF00FC, 3, TMS320C55_mov2, {{ op_CDP, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE50028, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BSA01, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE50038, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BSA23, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE50048, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BSA45, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE50058, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BSA67, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE50068, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BSAC, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE50078, 0xFF00FC, 3, TMS320C55_mov2, {{ op_SP, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE50088, 0xFF00FC, 3, TMS320C55_mov2, {{ op_SSP, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE50098, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BK03, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE500A8, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BK47, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE500B8, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BKC, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE500C8, 0xFF00FC, 3, TMS320C55_mov2, {{ op_DPH, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE500D8, 0xFF00FC, 3, TMS320C55_mov2, {{ op_MDP05, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE500E8, 0xFF00FC, 3, TMS320C55_mov2, {{ op_MDP67, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE500F8, 0xFF00FC, 3, TMS320C55_mov2, {{ op_PDP, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE5000C, 0xFF007C, 3, TMS320C55_mov2, {{ op_CSR, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE5001C, 0xFF007C, 3, TMS320C55_mov2, {{ op_BRC0, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE5002C, 0xFF007C, 3, TMS320C55_mov2, {{ op_BRC1, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE5003C, 0xFF007C, 3, TMS320C55_mov2, {{ op_TRN0, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE5004C, 0xFF007C, 3, TMS320C55_mov2, {{ op_TRN1, 0 }, { op_Smem, 0x00FF00 }}},
{ 0xE60000, 0xFF0000, 3, TMS320C55_mov2, {{ op_K8, 0x0000FF }, { op_Smem, 0x00FF00 }}},
{ 0xE70000, 0xFF000C, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { shl_Tx, 0x000030 }, { op_Smem, 0x00FF00 }}},
{ 0xE70008, 0xFF000C, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { shl_Tx, 0x000030 }, { fn_hi, OP_TRUE, }, { fn_rnd, 0x000001 }, { op_Smem, 0x00FF00 }}},
{ 0xE7000C, 0xFF000C, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { shl_Tx, 0x000030 }, { fn_sat, OP_TRUE, }, { fn_hi, OP_TRUE }, { fn_rnd, 0x000001 }, { fn_uns, 0x000002 }, { op_Smem, 0x00FF00 }}},
{ 0xE80000, 0xFF0004, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { fn_hi, OP_TRUE }, { fn_rnd, 0x000001 }, { op_Smem, 0x00FF00 }}},
{ 0xE80004, 0xFF0004, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { fn_sat, OP_TRUE }, { fn_hi, OP_TRUE }, { fn_rnd, 0x000001 }, { fn_uns, 0x000002 }, { op_Smem, 0x00FF00 }}},
{ 0xE90000, 0xFF0000, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { shl_SHIFTW, 0x00003F }, { op_Smem, 0x00FF00 }}},
{ 0xEA0000, 0xFF0000, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { shl_SHIFTW, 0x00003F }, { fn_hi, OP_TRUE }, { op_Smem, 0x00FF00 }}},
{ 0xEB0004, 0xFF000D, 3, TMS320C55_mov2, {{ op_RETA, 0 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}},
{ 0xEB0005, 0xFF000D, 3, TMS320C55_mov2, {{ op_xsrc, 0x0000F0 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}}, // not in documentation
{ 0xEB0008, 0xFF000D, 3, TMS320C55_mov2, {{ op_ACx, 0x000030 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}},
{ 0xEB0009, 0xFF000D, 3, TMS320C55_mov2, {{ op_ACx, 0x000030 }, { fn_sat, OP_TRUE }, { fn_uns, 0x000002 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}},
{ 0xEB000C, 0xFF000F, 3, TMS320C55_mov2, {{ op_TAx, 0x0000F0 }, { fn_pair, OP_TRUE }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}},
{ 0xEB000D, 0xFF000F, 3, TMS320C55_mov2, {{ op_ACx, 0x0000F0 }, { shr, OP_IMM(1) }, { op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }}},
{ 0xEB000E, 0xFF000F, 3, TMS320C55_mov2, {{ op_ACx, 0x0000F0 }, { fn_hi, OP_TRUE }, { fn_pair, OP_TRUE }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}},
{ 0xEB000F, 0xFF000F, 3, TMS320C55_mov2, {{ op_ACx, 0x0000F0 }, { fn_lo, OP_TRUE }, { fn_pair, OP_TRUE }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}},
{ 0xEC0000, 0xFF000E, 3, TMS320C55_bset2, {{ op_Baddr, 0x00FF00 }, { op_src, 0x0000F0 }}},
{ 0xEC0002, 0xFF000E, 3, TMS320C55_bclr2, {{ op_Baddr, 0x00FF00 }, { op_src, 0x0000F0 }}},
{ 0xEC0004, 0xFF000E, 3, TMS320C55_btstp, {{ op_Baddr, 0x00FF00 }, { op_src, 0x0000F0 }}},
{ 0xEC0006, 0xFF000E, 3, TMS320C55_bnot, {{ op_Baddr, 0x00FF00 }, { op_src, 0x0000F0 }}},
{ 0xEC0008, 0xFF000E, 3, TMS320C55_btst, {{ op_Baddr, 0x00FF00 }, { op_src, 0x0000F0 }, { op_TCx, 0x000001 }}},
{ 0xEC000E, 0xFF000F, 3, TMS320C55_amar2, {{ op_Smem, 0x00FF00 }, { op_xdst, 0x0000F0 }}},
{ 0xED0000, 0xFF000E, 3, TMS320C55_add2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}},
{ 0xED0002, 0xFF000E, 3, TMS320C55_sub2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}},
{ 0xED0004, 0xFF000E, 3, TMS320C55_sub3, {{ op_ACx, 0x0000C0 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_ACy, 0x000030 }}},
{ 0xED0006, 0xFF000E, 3, TMS320C55_mov2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_RETA, 0 }}},
{ 0xED0008, 0xFF000E, 3, TMS320C55_mov2, {{ insn_1_40, 0x000001 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_ACx, 0x000030 }}},
{ 0xED000A, 0xFF000E, 3, TMS320C55_mov2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_ACx, 0x000030 }, { fn_hi, OP_TRUE, }, { fn_pair, OP_TRUE }}},
{ 0xED000C, 0xFF000E, 3, TMS320C55_mov2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_ACx, 0x000030 }, { fn_lo, OP_TRUE, }, { fn_pair, OP_TRUE }}},
{ 0xED000E, 0xFF000F, 3, TMS320C55_mov2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_TAx, 0x0000F0 }, { fn_pair, OP_TRUE }}},
{ 0xED000F, 0xFF000F, 3, TMS320C55_mov2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_xdst, 0x0000F0 }}},
{ 0xEE0000, 0xFF000E, 3, TMS320C55_add2, {{ op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}},
{ 0xEE0002, 0xFF000E, 3, TMS320C55_sub2, {{ op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}},
{ 0xEE0004, 0xFF000E, 3, TMS320C55_sub3, {{ op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_ACx, 0x0000C0 }, { op_ACy, 0x000030 }}},
{ 0xEE0006, 0xFF000E, 3, TMS320C55_sub3, {{ op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_Tx, 0x0000C0 }, { op_ACx, 0x000030 }}},
{ 0xEE0008, 0xFF000E, 3, TMS320C55_add3, {{ op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_Tx, 0x0000C0 }, { op_ACx, 0x000030 }}},
{ 0xEE000A, 0xFF000E, 3, TMS320C55_sub3, {{ op_Tx, 0x0000C0 }, { op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_ACx, 0x000030 }}},
{ 0xEE000C, 0xFF000E, 3, TMS320C55_addsub, {{ op_Tx, 0x0000C0 }, { op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_ACx, 0x000030 }}},
{ 0xEE000E, 0xFF000E, 3, TMS320C55_subadd, {{ op_Tx, 0x0000C0 }, { op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_ACx, 0x000030 }}},
{ 0xEF0000, 0xFF000C, 3, TMS320C55_mov2, {{ op_Cmem, 0x000003 }, { op_Smem, 0x00FF00 }}},
{ 0xEF0004, 0xFF000C, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_Cmem, 0x000003 }}},
{ 0xEF0008, 0xFF000C, 3, TMS320C55_mov2, {{ op_Cmem, 0x000003 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}},
{ 0xEF000C, 0xFF000C, 3, TMS320C55_mov2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_Cmem, 0x000003 }}},
{ 0xF0000000, 0xFF000000, 4, TMS320C55_cmp, {{ op_Smem, 0x00FF0000 }, { eq_K16, 0x0000FFFF }, { op_TC1, 0 }}},
{ 0xF1000000, 0xFF000000, 4, TMS320C55_cmp, {{ op_Smem, 0x00FF0000 }, { eq_K16, 0x0000FFFF }, { op_TC2, 0 }}},
{ 0xF2000000, 0xFF000000, 4, TMS320C55_band, {{ op_Smem, 0x00FF0000 }, { op_k16, 0x0000FFFF }, { op_TC1, 0 }}},
{ 0xF3000000, 0xFF000000, 4, TMS320C55_band, {{ op_Smem, 0x00FF0000 }, { op_k16, 0x0000FFFF }, { op_TC2, 0 }}},
{ 0xF4000000, 0xFF000000, 4, TMS320C55_and2, {{ op_k16, 0x0000FFFF }, { op_Smem, 0x00FF0000 }}},
{ 0xF5000000, 0xFF000000, 4, TMS320C55_or2, {{ op_k16, 0x0000FFFF }, { op_Smem, 0x00FF0000 }}},
{ 0xF6000000, 0xFF000000, 4, TMS320C55_xor2, {{ op_k16, 0x0000FFFF }, { op_Smem, 0x00FF0000 }}},
{ 0xF7000000, 0xFF000000, 4, TMS320C55_add2, {{ op_K16, 0x0000FFFF }, { op_Smem, 0x00FF0000 }}},
{ 0xF8000000, 0xFF000004, 4, TMS320C55_mpymk, {{ insn_1_R, 0x00000001 }, { op_Smem, 0x00FF0000 }, { fn_T3, 0x00000002 }, { op_K8, 0x0000FF00 }, { op_ACx, 0x00000030 }}},
{ 0xF8000004, 0xFF000004, 4, TMS320C55_macmk3, {{ insn_1_R, 0x00000001 }, { op_Smem, 0x00FF0000 }, { fn_T3, 0x00000002 }, { op_K8, 0x0000FF00 }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}},
{ 0xF9000000, 0xFF00000C, 4, TMS320C55_add2, {{ op_Smem, 0x00FF0000 }, { fn_uns, 0x00008000 }, { slo_SHIFTW, 0x00003F00 }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}},
{ 0xF9000004, 0xFF00000C, 4, TMS320C55_sub2, {{ op_Smem, 0x00FF0000 }, { fn_uns, 0x00008000 }, { slo_SHIFTW, 0x00003F00 }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}},
{ 0xF9000008, 0xFF00000C, 4, TMS320C55_mov2, {{ op_Smem, 0x00FF0000 }, { fn_uns, 0x00008000 }, { slo_SHIFTW, 0x00003F00 }, { op_ACx, 0x00000030 }}},
{ 0xFA000000, 0xFF000004, 4, TMS320C55_mov2, {{ op_ACx, 0x000000C0 }, { shl_SHIFTW, 0x00003F00 }, { fn_hi, OP_TRUE }, { fn_rnd, 0x00000001 }, { op_Smem, 0x00FF0000 }}},
{ 0xFA000004, 0xFF000004, 4, TMS320C55_mov2, {{ op_ACx, 0x000000C0 }, { shl_SHIFTW, 0x00003F00 }, { fn_sat, OP_TRUE }, { fn_hi, OP_TRUE }, { fn_rnd, 0x00000001 }, { fn_uns, 0x00008000 }, { op_Smem, 0x00FF0000 }}},
{ 0xFB000000, 0xFF000000, 4, TMS320C55_mov2, {{ op_K16, 0x0000FFFF }, { op_Smem, 0x00FF0000 }}},
{ 0xFC000000, 0xFF000000, 4, TMS320C55_bcc, {{ op_L16, 0x0000FFFF }, { op_ARn_mod, 0x00FF0000 }, { neq_0, OP_TRUE }}},
{ 0, 0, 0, TMS320C55_null }
};
//--------------------------------------------------------------------------
// unpack an "sdual" instruction operand ( 6->8 bits )
static uchar unpack_opsdual(uchar packed)
{
static const uchar lowpart[8] = { 0, 1, 2, 3, 9, 4, 10, 5 };
return ((lowpart[packed&7] | ((packed<<1) & 0x70)) << 1) | 1;
}
//--------------------------------------------------------------------------
// unpack an "sdual" instruction
// these are probably instructions from C55x+ processor
static bool unpack_sdual(ea_t ea, bytevec_t *insn1, bytevec_t *insn2)
{
// sdual instruction packs two parallel instructions
uint32 word = 0;
for ( int i=0; i < 4; i++ )
word = (word << 8) | get_byte(ea + i);
uchar opc1 = ((word >> 20) & 0xF0) | ((word >> 8) & 0x0F);
uchar opc2 = (word & 0xFF);
if ( opc2 & 0x80 )
{
// 3 | 2 | 1 |
// 1098 7654|321098 76|5432 1098|76543210
// | | |
// 1000 1011|100010 10|1001 1100|11000001
// o1h | opd1 opd2 o1l| opc2
//
// opcode1 = o1h:o1l
// opcode2 = opc2
// opd1 and opd2 are packed operand parts
uchar ops1 = (word >> 18) & 0x3F;
uchar ops2 = (word >> 12) & 0x3F;
int insn1_len = get_insn_size(masks, opc1<<24);
if ( insn1_len < 2 )
return false;
int insn2_len = get_insn_size(masks, opc2<<24);
if ( insn2_len < 2 )
{
// try to add extra bytes (skip operand byte)
uint32 w2 = (opc2<<24) | (get_byte(ea + insn1_len+2) << 8);
insn2_len = get_insn_size(masks, w2);
if ( insn2_len < 2 )
{
w2 |= get_byte(ea + insn1_len+3);
insn2_len = get_insn_size(masks, w2);
}
}
if ( insn2_len < 2 )
return false;
if ( insn1 )
{
insn1->clear();
// add real opcode and operands
insn1->push_back(opc1);
insn1->push_back(unpack_opsdual(ops1));
// add extra bytes
for ( int i=4; i < insn1_len+2; i++ )
insn1->push_back(get_byte(ea + i));
}
if ( insn2 )
{
insn2->clear();
insn2->push_back(opc2);
insn2->push_back(unpack_opsdual(ops2));
for ( int i=insn1_len+2; i < (insn1_len+insn2_len); i++ )
insn2->push_back(get_byte(ea + i));
}
}
else
{
// unpacked insn1 can be 2, 3, or 4 bytes
// insn2 is always 3 bytes
//
// source bytes: ab cd ef gh ij kl mn op
// case 2+3:
// insn1 = bf cd
// insn2 = g4 ij eh
// case 3+3:
// insn1 = bf cd ij
// insn2 = g4 kl eh
// case 4+3:
// insn1 = bf cd ij kl
// insn2 = g4 mn eh
uint32 w1 = (opc1<<24) | (word & 0x00FF0000); // bfcd0000
uint32 w2 = (((word&0xF0)|4)<<24) | (word&0xF000) | ((word&0x0F)<<8); // g400eh00
int insn1_len = get_insn_size(masks, w1);
if ( insn1_len == 0 )
{
// try to add one byte
w1 |= (get_byte(ea + 4) << 8);
insn1_len = get_insn_size(masks, w1);
if ( insn1_len == 0 || insn1_len < 3 )
{
w1 |= get_byte(ea + 5);
insn1_len = get_insn_size(masks, w1);
if ( insn1_len != 4 )
return false;
}
}
int insn2_len = get_insn_size(masks, w2);
if ( insn1_len < 2 || insn2_len != 3 )
return false;
if ( insn1 )
{
insn1->clear();
insn1->push_back((w1>>24)&0xFF);
insn1->push_back((w1>>16)&0xFF);
// add extra bytes
for ( int i=4; i < insn1_len + 2; i++ )
insn1->push_back(get_byte(ea + i));
}
if ( insn2 )
{
insn2->clear();
insn2->push_back((w2>>24)&0xFF);
insn2->push_back(get_byte(ea + insn1_len + 2));
insn2->push_back((w2>>8)&0xFF);
}
}
return true;
}
//--------------------------------------------------------------------------
void ana_status_bits(insn_t &insn)
{
if ( (insn.itype == TMS320C55_bclr2 || insn.itype == TMS320C55_bset2)
&& insn.Op2.type == o_reg
&& insn.Op1.type == o_imm )
{
int reg = -1;
switch ( insn.Op2.reg )
{
case ST0_55:
{
static const int regs[] =
{
-1, -1, -1, -1, -1, -1, -1, -1,
-1, ACOV1, ACOV0, CARRY, TC2, TC1, ACOV3, ACOV2
};
reg = regs[int(insn.Op1.value)];
break;
}
case ST1_55:
{
static const int regs[] =
{
-1, -1, -1, -1, -1, C54CM, FRCT, C16,
SXMD, SATD, M40, INTM, HM, XF, CPL, BRAF
};
reg = regs[int(insn.Op1.value)];
break;
}
case ST2_55:
{
static const int regs[] =
{
AR0LC, AR1LC, AR2LC, AR3LC, AR4LC, AR5LC, AR6LC, AR7LC,
CDPLC, -1, RDM, EALLOW, DBGM, -1, -1, ARMS
};
reg = regs[int(insn.Op1.value)];
break;
}
case ST3_55:
{
static const int regs[] =
{
SST, SMUL, CLKOFF, -1, -1, SATA, MPNMC, CBERR,
-1, -1, -1, -1, HINT, CACLR, CAEN, CAFRZ
};
reg = regs[int(insn.Op1.value)];
break;
}
}
if ( reg != -1 )
{
insn.itype = (insn.itype == TMS320C55_bclr2) ? TMS320C55_bclr1 : TMS320C55_bset1;
insn.Op1.type = o_reg;
insn.Op1.reg = uint16(reg);
insn.Op2.type = o_void;
}
}
}
//--------------------------------------------------------------------------
int tms320c55_t::ana(insn_t *_insn)
{
insn_t &insn = *_insn;
optional_op = -1;
bytes_c bytes(insn);
uchar firstbyte = bytes.get_next();
int sdual_len = helper.altval_ea(insn.ea, TAG_SDUAL);
if ( sdual_len != 0 )
{
// this is a second part of sdual instruction
bytevec_t insn_bytes;
if ( !unpack_sdual(insn.ea - sdual_len, NULL, &insn_bytes) )
return 0;
bytes.set_cache(insn_bytes);
process_masks(insn, masks, TMS320C55_null, bytes, 8); // analyze opcode
if ( insn.itype == TMS320C55_null || insn.size != insn_bytes.size() )
return 0;
ana_status_bits(insn);
insn.SpecialModes |= TMS_MODE_USER_PARALLEL;
return insn.size;
}
else
{
// a normal instruction ?
process_masks(insn, masks, TMS320C55_null, bytes, 8); // analyze opcode
if ( insn.size != 0 && insn.itype != TMS320C55_null )
{
helper.altdel_ea(insn.ea + insn.size, TAG_SDUAL);
}
else if ( (firstbyte & 0xF8) == 0x88 )
{
// "sdual" instruction; unpack it
bytevec_t insn_bytes;
if ( !unpack_sdual(insn.ea, &insn_bytes, NULL) )
return 0;
bytes.set_cache(insn_bytes);
process_masks(insn, masks, TMS320C55_null, bytes, 8); // analyze opcode
if ( insn.itype != TMS320C55_null && insn.size == insn_bytes.size() )
{
ana_status_bits(insn);
// remember that next address is the second part
helper.altset_ea(insn.ea + insn.size, insn.size, TAG_SDUAL);
return insn.size;
}
}
}
// analyze special bits access
ana_status_bits(insn);
// analyze user-parallelized instructions
if ( firstbyte <= MAX_BYTE_USER_PARALLELIZED && (firstbyte & 1) ) // instruction has E bit set
insn.SpecialModes |= TMS_MODE_USER_PARALLEL;
// analyze postfixes
uchar nextbyte = get_byte(insn.ea+insn.size); // is_mapped() not necessary here
switch ( nextbyte )
{
case BYTE_MMAP: // mmap()
if ( insn.OpMem != 0 )
{
int n = insn.OpMem - 1;
if ( insn.ops[n].type == o_mem
&& insn.ops[n].tms_regH == DPH
&& insn.ops[n].tms_regP == DP
&& insn.ops[n].tms_modifier == TMS_MODIFIER_DMA )
{ // @dma using DP
insn.ops[n].tms_regH = 0;
insn.ops[n].tms_regP = 0;
insn.ops[n].tms_modifier = TMS_MODIFIER_MMAP;
insn.size++;
}
else if ( insn.ops[n].type == o_reg
&& insn.ops[n].reg == SP
&& insn.ops[n].tms_modifier == TMS_MODIFIER_REG_OFFSET )
{ // @dma using SP
insn.ops[n].addr = insn.ops[n].value;
insn.ops[n].type = o_mem;
insn.ops[n].tms_regH = 0;
insn.ops[n].tms_regP = 0;
insn.ops[n].tms_modifier = TMS_MODIFIER_MMAP;
insn.size++;
}
}
break;
case BYTE_PORT1:
case BYTE_PORT2: // port()
if ( insn.OpMem != 0 )
{
int n = insn.OpMem - 1;
switch ( insn.ops[n].type )
{
case o_mem:
insn.ops[n].type = o_io;
insn.ops[n].tms_regH = 0;
insn.ops[n].tms_regP = PDP;
insn.ops[n].addr = insn.ops[n].addr >> 1;
insn.ops[n].tms_modifier = TMS_MODIFIER_PORT_AT;
insn.size++;
break;
case o_reg:
insn.ops[n].tms_operator1 |= TMS_OPERATOR_PORT & 0xFF;
insn.ops[n].tms_operator2 |= (TMS_OPERATOR_PORT >> 8);
insn.size++;
break;
}
}
break;
case BYTE_LR:
case BYTE_CR: // .lr & .cr
insn.SpecialModes |= nextbyte == BYTE_LR ? TMS_MODE_LR : TMS_MODE_CR;
insn.size++;
break;
}
if ( insn.itype == TMS320C55_null )
return 0;
return insn.size;
}