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

1451 lines
45 KiB
C++

/*
* Interactive disassembler (IDA).
* Copyright (c) 1990-99 by Ilfak Guilfanov.
* ALL RIGHTS RESERVED.
* E-mail: ig@datarescue.com
*
* Texas Instruments's TMS5320C54
*
*/
#include "tms320c54.hpp"
#include <segregs.hpp>
//--------------------------------------------------------------------------
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;
}
//--------------------------------------------------------------------------
static void op_reg_word(insn_t &insn, int op, ushort reg)
{
if ( op <= 3 )
{
insn.ops[op-1].type = o_reg;
insn.ops[op-1].dtype = dt_byte;
insn.ops[op-1].reg = reg;
}
else
{
insn.Op4_type = o_reg;
insn.Op4_value = (uchar)reg;
}
}
//--------------------------------------------------------------------------
static void op_bit(op_t &op, char value, bool NoCardinal = true)
{
op.type = o_bit;
op.dtype = dt_byte;
op.value = value;
op.NoCardinal = NoCardinal;
}
//--------------------------------------------------------------------------
static void op_imm(op_t &op, int value, bool Signed = false, bool NoCardinal = false)
{
op.type = o_imm;
op.dtype = dt_byte;
op.value = value;
op.Signed = Signed;
op.NoCardinal = NoCardinal;
}
//--------------------------------------------------------------------------
static void op_mem(insn_t &insn, op_t &op, char dtype, int byte, bool mmr = false)
{
op.dtype = dtype;
if ( (byte & 0x80) == 0 ) // Direct addressing mode
{
op.addr = byte & 0x7F;
if ( !mmr )
{
sel_t cpl = get_sreg(insn.ea, CPL);
if ( cpl == BADSEL )
cpl = 0;
if ( !cpl ) // check ST1:CPL
op.type = o_mem; // use DP
else
op.type = o_local; // use SP if CPL is set
}
else // MMR (Memory-Mapped Registers)
op.type = o_mmr;
}
else // Indirect addressing mode
{ // Single-Operand Addressing
op.type = o_displ;
op.reg = AR0 + (byte & 0x07);
op.IndirectAddressingMOD = (byte>>3) & 0xF;
if ( op.IndirectAddressingMOD >= 0xC ) // 16-bit long offset (lk)
{
if ( !mmr )
{
if ( op.IndirectAddressingMOD == ABSOLUTE_INDIRECT_ADRESSING )
op.type = o_farmem;
op.addr = get_wide_byte(insn.ea+insn.size);
insn.size++;
}
else // invalide indirect addressing modes (p141)
{
insn.itype = TMS320C54_null;
}
}
}
}
#define op_Smem(insn, OP, BYTE) op_mem(insn, OP, dt_byte, BYTE, false)
#define op_MMR(insn, OP, BYTE) op_mem(insn, OP, dt_byte, BYTE, true)
#define op_Lmem(insn, OP, BYTE) op_mem(insn, OP, dt_word, BYTE, false)
//--------------------------------------------------------------------------
static void op_MMRxy(insn_t &insn, const op_t &op, ushort byte)
{
byte &= 0x0F;
if ( byte <= 7 )
op_reg_word(insn, op.n+1, AR0+byte);
else
op_reg_word(insn, op.n+1, SP);
}
#define op_MMRx(insn, OP, BYTE) op_MMRxy(insn, OP, (BYTE)>>4)
#define op_MMRy(insn, OP, BYTE) op_MMRxy(insn, OP, BYTE)
//--------------------------------------------------------------------------
static void op_XYmem(op_t &op, int four)
{
four &= 0xF;
op.type = o_displ;
op.reg = AR2 + (four & 0x3);
// map Dual-Operand Indirect Addressing Types to Single-Operand Indirect Addressing Types
four = (four>>2) & 0x3;
if ( four < 3 )
op.IndirectAddressingMOD = (uchar)four;
else
op.IndirectAddressingMOD = 11;
}
#define op_Xmem(OP,BYTE) op_XYmem(OP, (BYTE)>>4)
#define op_Ymem(OP,BYTE) op_XYmem(OP, BYTE)
//--------------------------------------------------------------------------
static void op_src_dst(insn_t &insn, int op, int src_dst)
{
op_reg_word(insn, op, (src_dst & 1) ? B : A);
}
//--------------------------------------------------------------------------
static void op_lk(insn_t &insn, op_t &op)
{
op_imm(op, get_wide_byte(insn.ea+insn.size), false, false);
insn.size++;
}
//--------------------------------------------------------------------------
static void op_pmad(insn_t &insn, op_t &op)
{
op.type = o_near;
op.dtype = dt_code;
op.addr = get_wide_byte(insn.ea+insn.size);
insn.size++;
}
//--------------------------------------------------------------------------
static void op_pmad_data(insn_t &insn, op_t &op)
{
op.type = o_near;
op.dtype = dt_byte; // o_near with dt_byte - rare combination!
op.addr = get_wide_byte(insn.ea+insn.size);
insn.size++;
}
//--------------------------------------------------------------------------
static void op_extpmad(insn_t &insn, op_t &op, int byte)
{
op.type = o_far;
op.dtype = dt_code;
op.addr = ((byte & 0x7F) << 16) | get_wide_byte(insn.ea+insn.size);
insn.size++;
}
//--------------------------------------------------------------------------
static void op_dmad(insn_t &insn, op_t &op)
{
op.type = o_farmem;
op.dtype = dt_byte;
op.addr = get_wide_byte(insn.ea+insn.size);
insn.size++;
}
//--------------------------------------------------------------------------
static void op_PA(insn_t &insn, op_t &op)
{
op.type = o_imm;
op.dtype = dt_byte;
op.value = get_wide_byte(insn.ea+insn.size);
op.NoCardinal = true;
op.IOimm = true;
insn.size++;
}
//--------------------------------------------------------------------------
static void op_cond8(insn_t &insn, op_t &op, uchar byte)
{
if ( get_cond8(byte) == NULL )
{
insn.itype = TMS320C54_null;
return;
}
op.type = o_cond8;
op.value = byte;
}
//--------------------------------------------------------------------------
static void op_cond8(insn_t &insn, uchar op, uchar byte)
{
if ( get_cond8(byte) == NULL )
{
insn.itype = TMS320C54_null;
}
else if ( op <= 3 && op > 0 )
{
op_cond8(insn, insn.ops[op-1], byte);
}
else
{
insn.Op4_type = o_cond8;
insn.Op4_value = byte;
}
}
//--------------------------------------------------------------------------
static void op_cond4(insn_t &insn, op_t &op, uchar quart)
{
quart &= 0xF;
// map cond4 to cond8
op_cond8(insn, op, COND8_FROM_COND4 | quart);
}
//--------------------------------------------------------------------------
static void op_cond2(op_t &op, int cond)
{
op.type = o_cond2;
op.value = cond & 0x3;
}
//--------------------------------------------------------------------------
// insn.itype must be set to <op> operands
static void ops_conds(insn_t &insn, uchar op, int byte)
{
byte &= 0xFF;
int bits7_6 = (byte >> 6) & 0x3;
uchar n = 0; // number of operands added
if ( bits7_6 == 1 ) // Group 1, = 01?? ????
{
if ( byte & 0x7 ) // Category A, 01?? ?MMM with MMM != 0
op_cond8(insn, op+n++, byte & 0xCF); // & 1100 1111
if ( byte & 0x30 ) // Category B, 01MM ???? with MM != 0
op_cond8(insn, op+n++, byte & 0xF8); // & 1111 1000
}
else if ( bits7_6 == 0 ) // Group 2, = 00?? ????
{
if ( byte & 0x30 ) // Category A, & 0011 0000
op_cond8(insn, op+n++, byte & 0x30); // & 0011 0000
if ( byte & 0x0C ) // Category B, & 0000 1100
op_cond8(insn, op+n++, byte & 0x0C); // & 0000 1100
if ( byte & 0x03 ) // Category C, & 0000 0011
op_cond8(insn, op+n++, byte & 0x03); // & 0000 0011
}
else
insn.itype = TMS320C54_null;
if ( insn.itype != TMS320C54_null )
{
if ( n == 0 )
op_cond8(insn, op+n++, COND8_UNC);
// modify insn.itype
if ( op-1+n <= 3 )
insn.itype += n-1;
else
insn.itype += 3-op;
}
}
//--------------------------------------------------------------------------
void ana_TMS320C54(insn_t *_insn)
{
insn_t &insn = *_insn;
ushort code = (ushort)get_wide_byte(insn.ea);
insn.size = 1;
uchar bits7_0 = code & 0xFF;
uchar bits4_0 = code & 0x1F;
uchar bits3_0 = code & 0xF;
uchar bits2_0 = code & 0x7;
uchar bits1_0 = code & 0x3;
bool bit0 = code & 1;
uchar bits8_3 = (code >> 3) & 0x3F;
ushort bits15_4 = code >> 4;
uchar bits7_4 = bits15_4 & 0xF;
uchar bits7_5 = bits7_4 >> 1;
uchar bits6_5 = bits7_5 & 0x3;
uchar bit7 = bits7_0 >> 7;
uchar bits15_8 = code >> 8;
uchar bits11_8 = bits15_8 & 0xF;
uchar bits9_8 = bits11_8 & 0x3;
bool bit8 = bits9_8 & 1;
uchar bits15_9 = code >> 9;
uchar bits11_9 = bits15_9 & 0x7;
uchar bits10_9 = bits11_9 & 0x3;
bool bit9 = bits10_9 & 1;
uchar bits15_10 = code >> 10;
uchar bits12_10 = bits15_10 & 0x7;
uchar bits11_10 = bits12_10 & 0x3;
uchar bits15_12 = code >> 12;
if ( bits15_8 <= 0x2F ) // <= 0010 11RS
// 0000 000S IAAA AAAA ADD Smem, src
// 0000 001S IAAA AAAA ADDS Smem, src
// 0000 010S IAAA AAAA ADD Smem, TS, src
// 0000 011S IAAA AAAA ADDC Smem, src
// 0000 100S IAAA AAAA SUB Smem, src
// 0000 101S IAAA AAAA SUBS Smem, src
// 0000 110S IAAA AAAA SUB Smem, TS, src
// 0000 111S IAAA AAAA SUBB Smem, src
// 0001 000D IAAA AAAA LD Smem, dst
// 0001 001D IAAA AAAA LDU Smem, dst
// 0001 010D IAAA AAAA LD Smem, TS, dst
// 0001 011D IAAA AAAA LDR Smem, dst
// 0001 100S IAAA AAAA AND Smem, src
// 0001 101S IAAA AAAA OR Smem, src
// 0001 110S IAAA AAAA XOR Smem, src
// 0001 111S IAAA AAAA SUBC Smem, src
// 0010 00RD IAAA AAAA MPY[R] Smem, dst
// 0010 010D IAAA AAAA MPYU Smem, dst
// 0010 011D IAAA AAAA SQUR Smem, dst
// 0010 10RS IAAA AAAA MAC[R] Smem, src
// 0010 11RS IAAA AAAA MAS[R] Smem, src
{
static const ushort codes[24] =
{
TMS320C54_add2, TMS320C54_adds, TMS320C54_add3, TMS320C54_addc,
TMS320C54_sub2, TMS320C54_subs, TMS320C54_sub3, TMS320C54_subb,
TMS320C54_ld2, TMS320C54_ldu, TMS320C54_ld3, TMS320C54_ldr,
TMS320C54_and2, TMS320C54_or2, TMS320C54_xor2, TMS320C54_subc,
TMS320C54_mpy2, TMS320C54_mpyr2, TMS320C54_mpyu, TMS320C54_squr,
TMS320C54_mac2, TMS320C54_macr2, TMS320C54_mas2, TMS320C54_masr2
};
insn.itype = codes[bits15_9];
op_Smem(insn, insn.Op1, code);
if ( insn.itype != TMS320C54_add3
&& insn.itype != TMS320C54_sub3
&& insn.itype != TMS320C54_ld3 )
{
op_src_dst(insn, 2, bit8);
}
else
{
op_reg_word(insn, 2, TS);
op_src_dst(insn, 3, bit8);
}
}
else if ( bits15_8 == 0x30 ) // == 0011 0000
{
// 0011 0000 IAAA AAAA LD Smem, T
insn.itype = TMS320C54_ld2;
op_Smem(insn, insn.Op1, code);
op_reg_word(insn, 2, T);
}
else if ( bits15_8 == 0x32 ) // == 0011 0010
{
// 0011 0010 IAAA AAAA LD Smem, ASM
insn.itype = TMS320C54_ld2;
op_Smem(insn, insn.Op1, code);
op_reg_word(insn, 2, ASM);
}
else if ( bits15_8 <= 0x37 ) // <= 0011 01R1
// 0011 0001 IAAA AAAA MPYA Smem
// 0011 0011 IAAA AAAA MASA Smem [,B]
// 0011 0100 IAAA AAAA BITT Smem
// 0011 0110 IAAA AAAA POLY Smem
// 0011 01R1 IAAA AAAA MACA[R] Smem [,B]
{
static const ushort codes[8] =
{
TMS320C54_null, TMS320C54_mpya, TMS320C54_null, TMS320C54_masa1,
TMS320C54_bitt, TMS320C54_maca1, TMS320C54_poly, TMS320C54_macar1
};
insn.itype = codes[bits11_8];
if ( insn.itype != TMS320C54_null )
op_Smem(insn, insn.Op1, code);
}
else if ( bits15_8 <= 0x3B ) // <= 0011 101S
// 0011 100S IAAA AAAA SQURA Smem, src
// 0011 101S IAAA AAAA SQURS Smem, src
{
insn.itype = bit9 ? TMS320C54_squrs : TMS320C54_squra;
op_Smem(insn, insn.Op1, code);
op_src_dst(insn, 2, bit8);
}
else if ( bits15_8 <= 0x45 ) // <= 0100 0101
{
// 0011 11SD IAAA AAAA ADD Smem, 16, src [,dst]
// 0100 00SD IAAA AAAA SUB Smem, 16, src [,dst]
// 0100 010D IAAA AAAA LD Smem, 16, dst
static const ushort codes[4] =
{
TMS320C54_sub3, TMS320C54_ld3, TMS320C54_null, TMS320C54_add3
};
insn.itype = codes[bits11_10];
if ( insn.itype != TMS320C54_null )
{
op_Smem(insn, insn.Op1, code);
op_bit(insn.Op2, 16);
if ( insn.itype != TMS320C54_ld3 )
{
op_src_dst(insn, 3, bit9);
if ( bit8 != bit9 )
op_src_dst(insn, 4, bit8);
}
else
op_src_dst(insn, 3, bit8);
}
}
else if ( bits15_8 == 0x46 ) // <= 0100 0110
{
// 0100 0110 IAAA AAAA LD Smem, DP
insn.itype = TMS320C54_ld2;
op_Smem(insn, insn.Op1, code);
op_reg_word(insn, 2, DP);
}
else if ( bits15_8 == 0x47 ) // <= 0100 0111
// 0100 0111 IAAA AAAA RPT Smem
{
insn.itype = TMS320C54_rpt;
op_Smem(insn, insn.Op1, code);
}
else if ( bits15_8 <= 0x4A ) // <= 0100 1010
// 0100 100D IAAA AAAA LDM MMR, dst
// 0100 1010 IAAA AAAA PSHM MMR
{
insn.itype = bit9 ? TMS320C54_pshm : TMS320C54_ldm;
op_MMR(insn, insn.Op1, code);
if ( insn.itype == TMS320C54_ldm )
op_src_dst(insn, 2, bit8);
}
else if ( bits15_8 <= 0x4D ) // <= 0100 1101
// 0100 1011 IAAA AAAA PSHD Smem
// 0100 1100 IAAA AAAA LTD Smem
// 0100 1101 IAAA AAAA DELAY Smem
{
static const ushort codes[4] =
{
TMS320C54_ltd, TMS320C54_delay, TMS320C54_null, TMS320C54_pshd
};
insn.itype = codes[bits9_8];
if ( insn.itype != TMS320C54_null )
op_Smem(insn, insn.Op1, code);
}
else if ( bits15_8 <= 0x4F ) // <= 0100 111S
// 0100 111S IAAA AAAA DST src, Lmem
{
insn.itype = TMS320C54_dst;
op_src_dst(insn, 1, bit8);
op_Lmem(insn, insn.Op2, code);
}
else if ( bits15_8 <= 0x5F ) // <= 0101 111D
// 0101 00SD IAAA AAAA DADD Lmem, src [,dst]
// 0101 010S IAAA AAAA DSUB Lmem, src
// 0101 011D IAAA AAAA DLD Lmem, dst
// 0101 100S IAAA AAAA DRSUB Lmem, src
// 0101 101D IAAA AAAA DADST Lmem, dst
// 0101 110D IAAA AAAA DSUBT Lmem, dst
// 0101 111D IAAA AAAA DSADT Lmem, dst
{
static const ushort codes[8] =
{
TMS320C54_dadd2, TMS320C54_dadd2, TMS320C54_dsub, TMS320C54_dld,
TMS320C54_drsub, TMS320C54_dadst, TMS320C54_dsubt, TMS320C54_dsadt
};
insn.itype = codes[bits11_9];
op_Lmem(insn, insn.Op1, code);
if ( insn.itype != TMS320C54_dadd2 )
{
op_src_dst(insn, 2, bit8);
}
else
{
op_src_dst(insn, 2, bit9);
if ( bit8 != bit9 )
{
op_src_dst(insn, 3, bit8);
insn.itype++;
}
}
}
else if ( bits15_8 <= 0x67 ) // <= 0110 01SD
// 0110 0000 IAAA AAAA 16-bit constant CMPM Smem, #lk
// 0110 0001 IAAA AAAA 16-bit constant BITF Smem, #lk
// 0110 001D IAAA AAAA 16-bit constant MPY Smem, #lk, dst
// 0110 01SD IAAA AAAA 16-bit constant MAC Smem, #lk, src [,dst]
{
static const ushort codes[8] =
{
TMS320C54_cmpm, TMS320C54_bitf, TMS320C54_mpy3, TMS320C54_mpy3,
TMS320C54_mac3, TMS320C54_mac3, TMS320C54_mac3, TMS320C54_mac3
};
insn.itype = codes[bits11_8];
op_Smem(insn, insn.Op1, code);
op_lk(insn, insn.Op2); // constant always = last word
if ( insn.itype == TMS320C54_mpy3 )
{
op_src_dst(insn, 3, bit8);
}
else if ( insn.itype == TMS320C54_mac3 )
{
op_src_dst(insn, 3, bit9);
if ( bit8 != bit9 )
op_src_dst(insn, 4, bit8);
}
}
else if ( bits15_8 <= 0x6B ) // <= 0110 1011
// 0110 1000 IAAA AAAA 16-bit constant ANDM #lk, Smem
// 0110 1001 IAAA AAAA 16-bit constant ORM #lk, Smem
// 0110 1010 IAAA AAAA XORM #lk, Smem
// 0110 1011 IAAA AAAA 16-bit constant ADDM #lk, Smem
{
static const ushort codes[4] =
{
TMS320C54_andm, TMS320C54_orm, TMS320C54_xorm, TMS320C54_addm
};
insn.itype = codes[bits9_8];
op_Smem(insn, insn.Op2, code);
op_lk(insn, insn.Op1); // constant always = last word
}
else if ( bits15_8 == 0x6D ) // == 0110 1101
// 0110 1101 IAAA AAAA MAR Smem
{
insn.itype = TMS320C54_mar;
op_Smem(insn, insn.Op1, code);
}
else if ( bits15_8 == 0x6F ) // == 0110 1111
// 0110 1111 IAAA AAAA 0000 110D 010S HIFT LD Smem [,SHIFT], dst
// 0110 1111 IAAA AAAA 0000 110S 011S HIFT STH src [,SHIFT], Smem
// 0110 1111 IAAA AAAA 0000 110S 100S HIFT STL src [,SHIFT], Smem
// 0110 1111 IAAA AAAA 0000 11SD 000S HIFT ADD Smem [,SHIFT], src [,dst]
// 0110 1111 IAAA AAAA 0000 11SD 001S HIFT SUB Smem [,SHIFT], src [,dst]
{
op_t op;
op = insn.Op1;
op_Smem(insn, op, code); // IAAA AAAA/Smem eventual offset must be read before 2nd opcode byte!
int code2 = get_wide_byte(insn.ea+insn.size);
insn.size += 1;
int mask1 = code2 & 0xFEE0; //-V537 not misprint
int mask2 = code2 & 0xFCE0;
if ( mask1 == 0x0C40 )
insn.itype = TMS320C54_ld2;
else if ( mask1 == 0x0C60 )
insn.itype = TMS320C54_sth2;
else if ( mask1 == 0x0C80 )
insn.itype = TMS320C54_stl2;
else if ( mask2 == 0x0C00 )
insn.itype = TMS320C54_add2;
else if ( mask2 == 0x0C20 )
insn.itype = TMS320C54_sub2;
else
insn.itype = TMS320C54_null;
if ( insn.itype != TMS320C54_null )
{
uchar n = 2; // current operand
uchar shift = (uchar)get_signed(code2, 0x1F);
if ( shift != 0 )
{
op_bit(insn.Op2, shift);
n++;
insn.itype++;
}
if ( insn.itype == TMS320C54_ld2 || insn.itype == TMS320C54_ld3 )
{
op.n = 0;
insn.Op1 = op; // op_Smem(insn, insn.Op1, code);
op_src_dst(insn, n, code2>>8);
}
else if ( insn.itype == TMS320C54_sth2 || insn.itype == TMS320C54_stl2
|| insn.itype == TMS320C54_sth3 || insn.itype == TMS320C54_stl3 )
{
op_src_dst(insn, 1, code2>>8);
op.n = n-1;
insn.ops[n-1] = op; // op_Smem(insn, insn.ops[n-1], code);
}
else if ( insn.itype == TMS320C54_add2 || insn.itype == TMS320C54_sub2
|| insn.itype == TMS320C54_add3 || insn.itype == TMS320C54_sub3 )
{
int code2_bit9 = (code2>>9) & 1;
int code2_bit8 = (code2>>8) & 1;
op.n = 0;
insn.Op1 = op; // op_Smem(insn, insn.Op1, code);
op_src_dst(insn, n, code2_bit9);
if ( code2_bit8 != code2_bit9 )
{
n++;
op_src_dst(insn, n, code2_bit8);
if ( n < 4 )
insn.itype++;
}
}
}
}
else if ( (bits15_8 & 0xFD) == 0x6C ) // == 0110 11Z0
// 0110 11Z0 IAAA AAAA 16-bit constant BANZ[D] pmad, Sind
{
insn.itype = bit9 ? TMS320C54_banzd : TMS320C54_banz;
op_Smem(insn, insn.Op2, code);
op_pmad(insn, insn.Op1);
if ( insn.Op2.type == o_mem )
{ // Sind = Smem to code
insn.Op2.type = o_near;
insn.Op2.dtype = dt_code;
}
}
else if ( bits15_12 < 0x7 ) // < 0111
insn.itype = TMS320C54_null;
else if ( bits15_8 <= 0x73 ) // <= 0111 0000
// 0111 0000 IAAA AAAA 16-bit constant MVKD dmad, Smem
// 0111 0001 IAAA AAAA 16-bit constant MVDK Smem, dmad
// 0111 0010 IAAA AAAA 16-bit constant MVDM dmad, MMR
// 0111 0011 IAAA AAAA 16-bit constant MVMD MMR, dmad
{
static const ushort codes[4] =
{
TMS320C54_mvkd, TMS320C54_mvdk, TMS320C54_mvdm, TMS320C54_mvmd
};
insn.itype = codes[bits9_8];
switch ( insn.itype )
{
case TMS320C54_mvkd:
op_Smem(insn, insn.Op2, code);
op_dmad(insn, insn.Op1);
break;
case TMS320C54_mvdk:
op_Smem(insn, insn.Op1, code);
op_dmad(insn, insn.Op2);
break;
case TMS320C54_mvdm:
op_dmad(insn, insn.Op1);
op_MMR(insn, insn.Op2, code);
break;
case TMS320C54_mvmd:
op_MMR(insn, insn.Op1, code);
op_dmad(insn, insn.Op2);
break;
}
}
else if ( bits15_8 <= 0x75 ) // <= 0111 0101
// 0111 0100 IAAA AAAA Port address PORTR PA, Smem
// 0111 0101 IAAA AAAA Port address PORTW Smem, PA
{
insn.itype = bit8 ? TMS320C54_portw : TMS320C54_portr;
op_Smem(insn, insn.ops[1-bit8], code);
op_PA(insn, insn.ops[bit8]);
}
else if ( bits15_8 <= 0x77 ) // <= 0111 0111
// 0111 0110 IAAA AAAA 16-bit constant ST #lk, Smem
// 0111 0111 IAAA AAAA 16-bit constant STM #lk, MMR
{
insn.itype = bit8 ? TMS320C54_stm : TMS320C54_st;
op_mem(insn, insn.Op2, dt_byte, code, bit8);
op_lk(insn, insn.Op1); // constant always = last word
}
else if ( bits15_8 <= 0x7B ) // <= 0111 101S
// 0111 100S IAAA AAAA 16-bit constant MACP Smem, pmad, src
// 0111 101S IAAA AAAA 16-bit constant MACD Smem, pmad, src
{
insn.itype = bit9 ? TMS320C54_macd : TMS320C54_macp;
op_Smem(insn, insn.Op1, code);
op_pmad_data(insn, insn.Op2);
op_src_dst(insn, 3, bit8);
}
else if ( bits15_8 <= 0x7D ) // <= 0111 1101
// 0111 1100 IAAA AAAA 16-bit constant MVPD pmad, Smem
// 0111 1101 IAAA AAAA 16-bit constant MVDP Smem, pmad
{
insn.itype = bit8 ? TMS320C54_mvdp : TMS320C54_mvpd;
op_Smem(insn, insn.ops[1-bit8], code);
op_pmad_data(insn, insn.ops[bit8]);
}
else if ( bits15_8 <= 0x7F ) // <= 0111 1111
// 0111 1110 IAAA AAAA READA Smem
// 0111 1111 IAAA AAAA WRITA Smem
{
insn.itype = bit8 ? TMS320C54_writa : TMS320C54_reada;
op_Smem(insn, insn.Op1, code);
}
else if ( bits15_8 <= 0x83 ) // <= 1000 001S
// 1000 000S IAAA AAAA STL src, Smem
// 1000 001S IAAA AAAA STH src, Smem
{
insn.itype = bit9 ? TMS320C54_sth2 : TMS320C54_stl2;
op_src_dst(insn, 1, bit8);
op_Smem(insn, insn.Op2, code);
}
else if ( bits15_8 <= 0x87 ) // <= 1000 001S
// 1000 010S IAAA AAAA STL src, ASM, Smem
// 1000 011S IAAA AAAA STH src, ASM, Smem
{
insn.itype = bit9 ? TMS320C54_sth3 : TMS320C54_stl3;
op_src_dst(insn, 1, bit8);
op_reg_word(insn, 2, ASM);
op_Smem(insn, insn.Op3, code);
}
else if ( bits15_8 <= 0x89 ) // <= 1000 100S
// 1000 100S IAAA AAAA STLM src, MMR
{
insn.itype = TMS320C54_stlm;
op_src_dst(insn, 1, bit8);
op_MMR(insn, insn.Op2, code);
}
else if ( bits15_8 == 0x8A ) // == 1000 1010
// 1000 1010 IAAA AAAA POPM MMR
{
insn.itype = TMS320C54_popm;
op_MMR(insn, insn.Op1, code);
}
else if ( bits15_8 == 0x8B ) // == 1000 1011
// 1000 1011 IAAA AAAA POPD Smem
{
insn.itype = TMS320C54_popd;
op_Smem(insn, insn.Op1, code);
}
else if ( bits15_8 <= 0x8D ) // <= 1000 1101
// 1000 1100 IAAA AAAA ST T, Smem
// 1000 1101 IAAA AAAA ST TRN, Smem
{
insn.itype = TMS320C54_st;
op_reg_word(insn, 1, bit8 ? TRN : T);
op_Smem(insn, insn.Op2, code);
}
else if ( bits15_8 <= 0x8F ) // <= 1000 111S
// 1000 111S IAAA AAAA CMPS src, Smem
{
insn.itype = TMS320C54_cmps;
op_src_dst(insn, 1, bit8);
op_Smem(insn, insn.Op2, code);
}
else if ( bits15_8 <= 0x96 ) // <= 1001 0110
// 1001 000S XXXX SHFT ADD Xmem, SHFT, src
// 1001 001S XXXX SHFT SUB Xmem, SHFT, src
// 1001 010D XXXX SHFT LD Xmem, SHFT, dst
// 1001 0110 XXXX BITC BIT Xmem, BITC
{
static const ushort codes[4] =
{
TMS320C54_add3, TMS320C54_sub3, TMS320C54_ld3, TMS320C54_bit
};
insn.itype = codes[bits10_9];
op_Xmem(insn.Op1, code);
op_bit(insn.Op2, code & 0x0F);
if ( insn.itype != TMS320C54_bit )
op_src_dst(insn, 3, bit8);
}
else if ( bits15_8 == 0x97 ) // == 1001 0111
{
insn.itype = TMS320C54_null;
}
else if ( bits15_8 <= 0x9B ) // <= 1001 101S
// 1001 100S XXXX SHFT STL src, SHFT, Xmem
// 1001 101S XXXX SHFT STH src, SHFT, Xmem
{
insn.itype = bit9 ? TMS320C54_sth3 : TMS320C54_stl3;
op_src_dst(insn, 1, bit8);
op_bit(insn.Op2, code & 0x0F);
op_Xmem(insn.Op3, code);
}
else if ( bits15_8 <= 0x9D ) // <= 1001 1101
// 1001 1100 XXXX COND STRCD Xmem, cond
// 1001 1101 XXXX COND SRCCD Xmem, cond
{
insn.itype = bit8 ? TMS320C54_srccd : TMS320C54_strcd;
op_Xmem(insn.Op1, code);
op_cond4(insn, insn.Op2, (uchar)code);
}
else if ( bits15_8 <= 0x9F ) // <= 1001 111S
// 1001 111S XXXX COND SACCD src, Xmem, cond
{
insn.itype = TMS320C54_saccd;
op_src_dst(insn, 1, bit8);
op_Xmem(insn.Op2, code);
op_cond4(insn, insn.Op3, (uchar)code);
}
else if ( bits15_8 <= 0xA7 ) // <= 1010 011S
// 1010 000D XXXX YYYY ADD Xmem, Ymem, dst
// 1010 001D XXXX YYYY SUB Xmem, Ymem, dst
// 1010 010D XXXX YYYY MPY Xmem, Ymem, dst
// 1010 011S XXXX YYYY MACSU Xmem, Ymem, src
{
static const ushort codes[4] =
{
TMS320C54_add3, TMS320C54_sub3, TMS320C54_mpy3, TMS320C54_macsu
};
insn.itype = codes[bits10_9];
op_Xmem(insn.Op1, code);
op_Ymem(insn.Op2, code);
op_src_dst(insn, 3, bit8);
}
else if ( bits15_8 <= 0xAF ) // <= 1010 11RD
// 1010 10RD XXXX YYYY LD Xmem, dst || MAC[R] Ymem [,dst_]
// 1010 11RD XXXX YYYY LD Xmem, dst || MAS[R] Ymem [,dst_]
{
static const ushort codes[4] =
{
TMS320C54_ld_mac, TMS320C54_ld_macr, TMS320C54_ld_mas, TMS320C54_ld_masr
};
insn.itype = codes[bits10_9];
insn.IsParallel = 1;
op_Xmem(insn.Op1, code);
op_src_dst(insn, 2, bit8);
op_Ymem(insn.Op3, code);
op_src_dst(insn, 4, 1-bit8); // dst_
}
else if ( bits15_8 <= 0xBF ) // <= 1010 11RD
// 1011 0RSD XXXX YYYY MAC[R] Xmem, Ymem, src [,dst]
// 1011 1RSD XXXX YYYY MAS[R] Xmem, Ymem, src [,dst]
{
static const ushort codes[4] =
{
TMS320C54_mac3, TMS320C54_macr3, TMS320C54_mas3, TMS320C54_masr3
};
insn.itype = codes[bits11_10];
op_Xmem(insn.Op1, code);
op_Ymem(insn.Op2, code);
op_src_dst(insn, 3, bit9);
if ( bit8 != bit9 )
op_src_dst(insn, 4, bit8);
}
else if ( bits15_8 <= 0xDF ) // <= 1101 1RSD
// 1100 00SD XXXX YYYY ST src, Ymem || ADD Xmem, dst
// 1100 01SD XXXX YYYY ST src, Ymem || SUB Xmem, dst
// 1100 10SD XXXX YYYY ST src, Ymem || LD Xmem, dst
// 1100 11SD XXXX YYYY ST src, Ymem || MPY Xmem, dst
// 1101 0RSD XXXX YYYY ST src, Ymem || MAC[R] Xmem, dst
// 1101 1RSD XXXX YYYY ST src, Ymem || MAS[R] Xmem, dst
{
static const ushort codes[8] =
{
TMS320C54_st_add, TMS320C54_st_sub, TMS320C54_st_ld, TMS320C54_st_mpy,
TMS320C54_st_mac, TMS320C54_st_macr, TMS320C54_st_mas, TMS320C54_st_masr
};
insn.itype = codes[bits12_10];
insn.IsParallel = 1;
op_src_dst(insn, 1, bit9);
op_Ymem(insn.Op2, code);
op_Xmem(insn.Op3, code);
op_src_dst(insn, 4, bit8);
}
else if ( bits15_8 <= 0xE3 ) // <= 1101 1RSD
// 1110 0000 XXXX YYYY 16-bit constant FIRS Xmem, Ymem, pmad
// 1110 0001 XXXX YYYY LMS Xmem, Ymem
// 1110 0010 XXXX YYYY SQDST Xmem, Ymem
// 1110 0011 XXXX YYYY ABDST Xmem, Ymem
{
static const ushort codes[4] =
{
TMS320C54_firs, TMS320C54_lms, TMS320C54_sqdst, TMS320C54_abdst
};
insn.itype = codes[bits9_8];
op_Xmem(insn.Op1, code);
op_Ymem(insn.Op2, code);
if ( insn.itype == TMS320C54_firs )
op_pmad_data(insn, insn.Op3);
}
else if ( bits15_8 == 0xE5 ) // == 1110 0101
// 1110 0101 XXXX YYYY MVDD Xmem, Ymem
{
insn.itype = TMS320C54_mvdd;
op_Xmem(insn.Op1, code);
op_Ymem(insn.Op2, code);
}
else if ( bits15_8 <= 0xE6 ) // <= 1110 01S0
// 1110 01S0 XXXX YYYY ST src, Ymem || LD Xmem, T
{
insn.itype = TMS320C54_st_ld;
insn.IsParallel = 1;
op_src_dst(insn, 1, bit9);
op_Ymem(insn.Op2, code);
op_Xmem(insn.Op3, code);
op_reg_word(insn, 4, T);
}
else if ( bits15_8 == 0xE7 ) // == 1110 0111
// 1110 0111 MMRX MMRY MVMM MMRx, MMRy
{
insn.itype = TMS320C54_mvmm;
op_MMRx(insn, insn.Op1, code);
op_MMRy(insn, insn.Op2, code);
}
else if ( bits15_8 <= 0xE9 ) // <= 1110 100D
// 1110 100D KKKK KKKK LD #K, dst
{
insn.itype = TMS320C54_ld2;
op_imm(insn.Op1, code & 0xFF);
op_src_dst(insn, 2, bit8);
}
else if ( bits15_8 <= 0xEB ) // <= 1110 101k
// 1110 101K KKKK KKKK LD #k9, DP
{
insn.itype = TMS320C54_ld2;
op_imm(insn.Op1, code & 0x1FF);
op_reg_word(insn, 2, DP);
}
else if ( bits15_8 == 0xEC ) // == 1110 1100
// 1110 1100 KKKK KKKK RPT #K
{
insn.itype = TMS320C54_rpt;
op_imm(insn.Op1, code & 0xFF);
}
else if ( bits15_8 == 0xED ) // == 1110 1101
// 1110 1101 000K KKKK LD #k5, ASM
{
insn.itype = TMS320C54_ld2;
op_bit(insn.Op1, (uchar)get_signed(code, 0x1F), false);
op_reg_word(insn, 2, ASM);
}
else if ( bits15_8 == 0xEE ) // == 1110 1110
// 1110 1110 KKKK KKKK FRAME k
{
insn.itype = TMS320C54_frame;
op_imm(insn.Op1, get_signed(code, 0xFF), true, true);
}
else if ( bits15_12 < 0xF )
insn.itype = TMS320C54_null;
else if ( code == 0xF070 ) // == 1111 0000 0111 0000
// 1111 0000 0111 0000 16-bit constant RPT #lk
{
insn.itype = TMS320C54_rpt;
op_lk(insn, insn.Op1);
}
else if ( (bits15_4 & 0xFEF) == 0xF02 ) // == 1111 000D 0010
// 1111 000D 0010 SHFT 16-bit constant LD #lk [,SHFT], dst
{
insn.itype = TMS320C54_ld3;
op_lk(insn, insn.Op1);
op_bit(insn.Op2, code & 0x0F);
op_src_dst(insn, 3, bit8);
}
else if ( (code & 0xFEFF) == 0xF062 ) // == 1111 000D 0110 0010
// 1111 000D 0110 0010 16-bit constant LD #lk, 16, dst
{
insn.itype = TMS320C54_ld3;
op_lk(insn, insn.Op1);
op_bit(insn.Op2, 16);
op_src_dst(insn, 3, bit8);
}
else if ( (code & 0xFEFF) == 0xF066 ) // == 1111 000D 0110 0110
// 1111 000D 0110 0110 16-bit constant MPY #lk, dst
{
insn.itype = TMS320C54_mpy2;
op_lk(insn, insn.Op1);
op_src_dst(insn, 2, bit8);
}
else if ( (code & 0xFEFF) == 0xF071 ) // == 1111 000D 0111 0001
// 1111 000D 0111 0001 16-bit constant RPTZ dst, #lk
{
insn.itype = TMS320C54_rptz;
op_src_dst(insn, 1, bit8);
op_lk(insn, insn.Op2);
}
else if ( bits15_10 == 0x3C ) // == 1111 00xx
{
if ( bits7_4 <= 0x5 )
// 1111 00SD 0000 SHFT 16-bit constant ADD #lk [,SHFT], src [,dst]
// 1111 00SD 0001 SHFT 16-bit constant SUB #lk [,SHFT], src [,dst]
// 1111 00SD 0011 SHFT 16-bit constant AND #lk [,SHFT] ,src [,dst]
// 1111 00SD 0100 SHFT 16-bit constant OR #lk [,SHFT], src [,dst]
// 1111 00SD 0101 SHFT 16-bit constant XOR #lk [,SHFT], src [,dst]
{
static const ushort codes[6] =
{
TMS320C54_add3, TMS320C54_sub3, TMS320C54_null, TMS320C54_and3,
TMS320C54_or3, TMS320C54_xor3
};
insn.itype = codes[bits7_4];
if ( insn.itype != TMS320C54_null )
{
op_lk(insn, insn.Op1);
if ( bits3_0 != 0 )
{
op_bit(insn.Op2, bits3_0);
op_src_dst(insn, 3, bit9);
if ( bit8 != bit9 )
op_src_dst(insn, 4, bit8);
}
else
{
op_src_dst(insn, 2, bit9);
if ( bit8 != bit9 )
op_src_dst(insn, 3, bit8);
else
insn.itype--;
}
}
}
else if ( bits7_4 == 0x6 && bits3_0 <= 0x5 )
// 1111 00SD 0110 0000 16-bit constant ADD #lk, 16, src [,dst]
// 1111 00SD 0110 0001 16-bit constant SUB #lk, 16, src [,dst]
// 1111 00SD 0110 0011 16-bit constant AND #lk, 16, src [,dst]
// 1111 00SD 0110 0100 16-bit constant OR #lk, 16, src [,dst]
// 1111 00SD 0110 0101 16-bit constant XOR #lk, 16, src [,dst]
{
static const ushort codes[6] =
{
TMS320C54_add3, TMS320C54_sub3, TMS320C54_null, TMS320C54_and3,
TMS320C54_or3, TMS320C54_xor3
};
insn.itype = codes[bits3_0];
if ( insn.itype != TMS320C54_null )
{
op_lk(insn, insn.Op1);
op_bit(insn.Op2, 16);
op_src_dst(insn, 3, bit9);
if ( bit8 != bit9 )
op_src_dst(insn, 4, bit8);
}
}
else if ( bits7_4 == 0x6 && bits3_0 == 0x7 )
// 1111 00SD 0110 0111 16-bit constant MAC #lk, src [,dst]
{
insn.itype = TMS320C54_mac2;
op_lk(insn, insn.Op1);
op_src_dst(insn, 2, bit9);
if ( bit8 != bit9 )
{
op_src_dst(insn, 3, bit8);
insn.itype++;
}
}
else if ( bits7_5 >= 0x4 )
// 1111 00SD 100S HIFT AND src [,SHIFT] [,dst]
// 1111 00SD 101S HIFT OR src [,SHIFT] [,dst]
// 1111 00SD 110S HIFT XOR src [,SHIFT] [,dst]
// 1111 00SD 111S HIFT SFTL src, SHIFT [,dst]
{
static const ushort codes[4] =
{
TMS320C54_and1, TMS320C54_or1, TMS320C54_xor1, TMS320C54_sftl2,
};
insn.itype = codes[bits6_5];
op_src_dst(insn, 1, bit9);
uchar shift = (uchar)get_signed(code, 0x1F);
int n = 2; // current operand
if ( insn.itype == TMS320C54_sftl2 || shift != 0 )
{
op_bit(insn.ops[n-1], shift);
n++;
if ( insn.itype != TMS320C54_sftl2 )
insn.itype++;
}
if ( bit8 != bit9 )
{
op_src_dst(insn, n, bit8);
insn.itype++;
}
}
else if ( bits8_3 == 0xE ) // == 0 0111 0
// 1111 00Z0 0111 0010 16-bit constant RPTB[D] pmad
// 1111 00Z0 0111 0011 16-bit constant B[D] pmad
// 1111 00Z0 0111 0100 16-bit constant CALL[D] pmad
{
static const ushort codes[8] =
{
TMS320C54_null, TMS320C54_null, TMS320C54_rptb, TMS320C54_b,
TMS320C54_call, TMS320C54_null, TMS320C54_null, TMS320C54_null
};
insn.itype = codes[bits2_0];
if ( insn.itype != TMS320C54_null )
{
if ( bit9 )
{
switch ( insn.itype )
{
case TMS320C54_rptb: insn.itype = TMS320C54_rptbd; break;
case TMS320C54_b: insn.itype = TMS320C54_bd; break;
case TMS320C54_call: insn.itype = TMS320C54_calld; break;
}
}
op_pmad(insn, insn.Op1);
}
}
else
insn.itype = TMS320C54_null;
}
else if ( bits15_10 == 0x3D ) // == 1111 01xx
{
if ( code == 0xF495 ) // == 1111 0100 1001 0101
// 1111 0100 1001 0101 NOP
insn.itype = TMS320C54_nop;
else if ( (code & 0xFFF8) == 0xF4A0 ) // == 1111 0100 1010 0KKK
// 1111 0100 1010 0KKK LD #k3, ARP
{
insn.itype = TMS320C54_ld2;
op_imm(insn.Op1, code & 0x7);
op_reg_word(insn, 2, ARP);
}
else if ( (code & 0xFFE0) == 0xF4C0 ) // == 1111 0100 110K KKKK
// 1111 0100 110K KKKK TRAP K
{
insn.itype = TMS320C54_trap;
op_imm(insn.Op1, code & 0x001F, false, true);
}
else if ( bits7_4 <= 0x7 )
// 1111 01SD 000S HIFT ADD src [,SHIFT] [,dst]
// 1111 01SD 001S HIFT SUB src [,SHIFT] [,dst]
// 1111 01SD 010S HIFT LD src [,SHIFT], dst
// 1111 01SD 011S HIFT SFTA src, SHIFT [,dst]
{
static const ushort codes[4] =
{
TMS320C54_add1, TMS320C54_sub1, TMS320C54_ld1, TMS320C54_sfta2
};
insn.itype = codes[bits7_5];
op_src_dst(insn, 1, bit9);
uchar shift = (uchar)get_signed(code, 0x1F);
int n = 2; // current operand
if ( insn.itype == TMS320C54_sfta2 || shift != 0 )
{
op_bit(insn.ops[n-1], shift);
n++;
if ( insn.itype != TMS320C54_sfta2 )
insn.itype++;
}
if ( insn.itype == TMS320C54_ld1 || insn.itype == TMS320C54_ld2 || bit8 != bit9 )
{
op_src_dst(insn, n, bit8);
insn.itype++;
}
}
else if ( bits7_0 < 0x80 ) // < 1000 0000
{
insn.itype = TMS320C54_null;
}
else if ( bits7_0 <= 0x82 ) // <= 1000 0010
// 1111 01SD 1000 0000 ADD src, ASM [,dst]
// 1111 01SD 1000 0001 SUB src, ASM [,dst]
// 1111 01SD 1000 0010 LD src, ASM [,dst]
{
static const ushort codes[3] =
{
TMS320C54_add2, TMS320C54_sub2, TMS320C54_ld2
};
insn.itype = codes[bits2_0];
op_src_dst(insn, 1, bit9);
op_reg_word(insn, 2, ASM);
if ( bit8 != bit9 )
{
op_src_dst(insn, 3, bit8);
insn.itype++;
}
}
else if ( bit9 == 0 && bits7_0 == 0x83 ) // == 1111 010S 1000 0011
// 1111 010S 1000 0011 SAT src
{
insn.itype = TMS320C54_sat;
op_src_dst(insn, 1, bit8);
}
else if ( bits7_0 <= 0x85 ) // <= 1000 0101
// 1111 01SD 1000 0100 NEG src [,dst]
// 1111 01SD 1000 0101 ABS src [,dst]
{
insn.itype = bit0 ? TMS320C54_abs1 : TMS320C54_neg1;
op_src_dst(insn, 1, bit9);
if ( bit8 != bit9 )
{
op_src_dst(insn, 2, bit8);
insn.itype++;
}
}
else if ( bit9 == 0 && bits7_0 <= 0x87 ) // <= 1000 0111
// 1111 010D 1000 0110 MAX dst
// 1111 010D 1000 0111 MIN dst
{
insn.itype = bit0 ? TMS320C54_min : TMS320C54_max;
op_src_dst(insn, 1, bit8);
}
else if ( bits7_0 <= 0x8B ) // <= 1000 101R
// 1111 01SD 1000 100R MACA[R] T, src [,dst]
// 1111 01SD 1000 101R MASA[R] T, src [,dst]
{
static const ushort codes[4] =
{
TMS320C54_maca2, TMS320C54_macar2, TMS320C54_masa2, TMS320C54_masar2
};
insn.itype = codes[bits1_0];
op_reg_word(insn, 1, T);
op_src_dst(insn, 2, bit9);
if ( bit8 != bit9 )
{
op_src_dst(insn, 3, bit8);
insn.itype++;
}
}
else if ( bits7_0 <= 0x94 ) // <= 1001 0100
// 1111 010D 1000 1100 MPYA dst
// 1111 010D 1000 1101 SQUR A, dst
// 1111 010S 1000 1110 EXP src
// 1111 01SD 1000 1111 NORM src [,dst]
// 1111 010S 1001 0000 ROR src
// 1111 010S 1001 0001 ROL src
// 1111 010S 1001 0010 ROLTC src
// 1111 01SD 1001 0011 CMPL src [,dst]
// 1111 010S 1001 0100 SFTC src
{
static const ushort codes[9] =
{
TMS320C54_mpya, TMS320C54_squr, TMS320C54_exp, TMS320C54_norm1,
TMS320C54_ror, TMS320C54_rol, TMS320C54_roltc, TMS320C54_cmpl1,
TMS320C54_sftc
};
insn.itype = codes[bits4_0-0xC]; //lint !e676 possibly indexing before the beginning of an allocation
if ( insn.itype == TMS320C54_squr )
{
if ( !bit9 )
{
op_reg_word(insn, 1, A);
op_src_dst(insn, 2, bit8);
}
else
insn.itype = TMS320C54_null;
}
else if ( insn.itype == TMS320C54_norm1 || insn.itype == TMS320C54_cmpl1 )
{
op_src_dst(insn, 1, bit9);
if ( bit8 != bit9 )
{
op_src_dst(insn, 2, bit8);
insn.itype++;
}
}
else
{
if ( !bit9 )
op_src_dst(insn, 1, bit8);
else
insn.itype = TMS320C54_null;
}
}
else if ( bit8 == 0 && bits7_0 == 0x9B ) // == 1111 01Z0 1001 1011
// 1111 01Z0 1001 1011 RETF[D]
insn.itype = bit9 ? TMS320C54_retfd : TMS320C54_retf;
else if ( bits7_0 == 0x9F ) // == 1001 1111
// 1111 01SD 1001 1111 RND src [,dst]
{
insn.itype = TMS320C54_rnd1;
op_src_dst(insn, 1, bit9);
if ( bit8 != bit9 )
{
op_src_dst(insn, 2, bit8);
insn.itype++;
}
}
else if ( bits7_4 == 0xA ) // == 1010 1ARX
// 1111 01CC 1010 1ARX CMPR CC, ARx
{
insn.itype = TMS320C54_cmpr;
op_cond2(insn.Op1, bits15_8);
op_reg_word(insn, 2, AR0+bits2_0);
}
else if ( bits7_4 == 0xB ) // == 1111 01N0 1011 SBIT
// 1111 01N0 1011 SBIT RSBX N, SBIT
// 1111 01N1 1011 SBIT SSBX N, SBIT
{
uchar reg = rnone;
if ( bit9 == 0 ) // ST0
{
switch ( bits3_0 )
{
case 9 : reg = OVB; break;
case 10 : reg = OVA; break;
case 11 : reg = C; break;
case 12 : reg = TC; break;
}
}
else // ST1
{
switch ( bits3_0 )
{
case 5 : reg = CMPT; break;
case 6 : reg = FRCT; break;
case 7 : reg = C16; break;
case 8 : reg = SXM; break;
case 9 : reg = OVM; break;
case 11 : reg = INTM; break;
case 12 : reg = HM; break;
case 13 : reg = XF; break;
case 14 : reg = CPL; break;
case 15 : reg = BRAF; break;
}
}
if ( reg != rnone )
{
insn.itype = bit8 ? TMS320C54_ssbx1 : TMS320C54_rsbx1;
op_reg_word(insn, 1, reg);
}
else
{
insn.itype = bit8 ? TMS320C54_ssbx2 : TMS320C54_rsbx2;
op_bit(insn.Op1, bit9);
op_bit(insn.Op2, bits3_0);
}
}
else if ( (code & 0xFFE0) == 0xF7C0 ) // == 1111 0111 110K KKKK
// 1111 0111 110K KKKK INTR k
{
insn.itype = TMS320C54_intr;
op_imm(insn.Op1, bits4_0, false, true);
}
else if ( code == 0xF7E0 ) // == 1111 0111 1110 0000
// 1111 0111 1110 0000 RESET
insn.itype = TMS320C54_reset;
else if ( bits7_0 == 0xE1 ) // == 1111 01NN 1110 0001
// 1111 01NN 1110 0001 IDLE k
{
insn.itype = TMS320C54_idle;
op_bit(insn.Op1, 1+bit9+(bit8<<1));
}
else if ( bits7_4 == 0xE ) // == 1111 01ZS 1110 nnnn
// 1111 01ZS 1110 0010 BACC[D] src
// 1111 01ZS 1110 0011 CALA[D] src
// 1111 01Z0 1110 0100 FRET[D]
// 1111 01Z0 1110 0101 FRETE[D]
// 1111 01ZS 1110 0110 FBACC[D] src
// 1111 01ZS 1110 0111 FCALA[D] src
// 1111 01Z0 1110 1011 RETE[D]
{
static const ushort codes[16] =
{
TMS320C54_null, TMS320C54_null, TMS320C54_bacc, TMS320C54_cala,
TMS320C54_fret, TMS320C54_frete, TMS320C54_fbacc, TMS320C54_fcala,
TMS320C54_null, TMS320C54_null, TMS320C54_null, TMS320C54_rete,
TMS320C54_null, TMS320C54_null, TMS320C54_null, TMS320C54_null
};
insn.itype = codes[bits3_0];
if ( insn.itype != TMS320C54_null )
{
if ( insn.itype == TMS320C54_bacc
|| insn.itype == TMS320C54_cala
|| insn.itype == TMS320C54_fbacc
|| insn.itype == TMS320C54_fcala )
{
op_src_dst(insn, 1, bit8);
}
else if ( bit8 )
{
insn.itype = TMS320C54_null;
}
if ( insn.itype != TMS320C54_null && bit9 )
insn.itype++;
}
}
else
insn.itype = TMS320C54_null;
}
else if ( bits15_10 == 0x3E ) // == 1111 10xx
{
if ( bit7 )
// 1111 10Z0 1 7bit constant=pmad(22-16) 16-bit constant=pmad(15-0) FB[D] extpmad
// 1111 10Z1 1 7bit constant=pmad(22-16) 16-bit constant=pmad(15-0) FCALL[D] extpmad
{
static const ushort codes[4] =
{
TMS320C54_fb, TMS320C54_fcall, TMS320C54_fbd, TMS320C54_fcalld
};
insn.itype = codes[bits9_8];
op_extpmad(insn, insn.Op1, code);
}
else
// 1111 10Z0 CCCC CCCC 16-bit constant BC[D] pmad, cond [,cond] [,cond]
// 1111 10Z1 CCCC CCCC 16-bit constant CC[D] pmad, cond [,cond] [,cond]
{
static const ushort codes[4] =
{
TMS320C54_bc2, TMS320C54_cc2, TMS320C54_bcd2, TMS320C54_ccd2
};
insn.itype = codes[bits9_8];
op_pmad(insn, insn.Op1);
ops_conds(insn, 2, code);
}
}
else if ( bits15_10 == 0x3F ) // == 1111 11xx
{
if ( bit8 )
// 1111 11N1 CCCC CCCC XC n, cond [,cond] [,cond]
{
insn.itype = TMS320C54_xc2;
uchar n = bit9+1;
op_bit(insn.Op1, n);
ops_conds(insn, 2, code);
/*
ea_t ea = insn.ea + insn.size;
for ( int i=0; i<n ; i++ ) // loop for all instructions to ignore
{
insn_t insn;
int size = ana(ea, insn);
if ( size == 0 )
{
ea = BADADDR;
break;
}
ea += size;
}
if ( ea != BADADDR ) // jump is possible
{
insn.Op1.type = o_near;
insn.Op1.dtype = dt_code;
insn.Op1.addr = ea;
}
*/
}
else if ( bits7_0 == 0 )
// 1111 11Z0 0000 0000 RET[D]
insn.itype = bit9 ? TMS320C54_retd : TMS320C54_ret;
else
// 1111 11Z0 CCCC CCCC RC[D] cond [,cond] [,cond]
{
insn.itype = bit9 ? TMS320C54_rcd1 : TMS320C54_rc1;
ops_conds(insn, 1, code);
}
}
}
//--------------------------------------------------------------------------
int tms320c54_t::ana(insn_t *insn)
{
switch ( ptype )
{
case TMS320C54:
ana_TMS320C54(insn);
break;
default:
error("interr: ana: ana()");
}
if ( insn->itype == TMS320C54_null )
return 0;
return insn->size;
}