1177 lines
34 KiB
C++
1177 lines
34 KiB
C++
/*
|
|
* Interactive disassembler (IDA).
|
|
* Version 3.05
|
|
* Copyright (c) 1990-95 by Ilfak Guilfanov.
|
|
* ALL RIGHTS RESERVED.
|
|
* FIDO: 2:5020/209
|
|
* E-mail: ig@estar.msk.su
|
|
*
|
|
*/
|
|
|
|
#include "tms.hpp"
|
|
|
|
//----------------------------------------------------------------------
|
|
inline ushort get_next_byte(insn_t &insn)
|
|
{
|
|
return (ushort)get_wide_byte(insn.ea + insn.size++);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
inline void op_daddr(insn_t &insn, op_t &o) // 16-bit address data
|
|
{
|
|
o.type = o_mem;
|
|
o.addr = get_next_byte(insn);
|
|
o.sib = 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
inline void op_paddr(insn_t &insn, op_t &o) // 16-bit address prog
|
|
{
|
|
o.type = o_near;
|
|
o.addr = get_next_byte(insn);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
inline void op_ioaddr(insn_t &insn, op_t &o) // 16-bit port address
|
|
{
|
|
o.dtype = dt_word;
|
|
o.type = o_imm;
|
|
o.value = get_next_byte(insn);
|
|
o.sib = 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
int tms320c5_t::op_iaa(const insn_t &insn, op_t &o) const // direct or indirect address
|
|
{
|
|
if ( code & 0x80 )
|
|
{
|
|
o.type = o_phrase;
|
|
o.phrase = (code & 0x7F);
|
|
if ( (o.phrase & 0x70) == 0x30 )
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
o.type = o_mem;
|
|
o.addr = (get_sreg(insn.ea, rDP)<<7) + (code & 0x7F);
|
|
o.sib = 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
int tms320c5_t::op_indir(op_t &o) // direct or indirect address
|
|
{ // optional
|
|
o.type = o_phrase;
|
|
o.phrase = (code & 0x7F);
|
|
if ( (o.phrase & 0x70) == 0x30 )
|
|
return 0;
|
|
if ( (o.phrase & 0x70) == 0 )
|
|
o.clr_shown();
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
int tms320c5_t::op_maa(const insn_t &insn, op_t &o) const // memory-mapped register from code
|
|
{
|
|
if ( !op_iaa(insn, o) )
|
|
return 0;
|
|
if ( o.type == o_mem )
|
|
o.addr = (code & 0x7F);
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
inline void op_ar(op_t &o, uint16 ar) // aux register
|
|
{
|
|
o.type = o_reg;
|
|
o.reg = rAr0 + ar;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
inline void op_imm(insn_t &insn, op_t &o) // 16-bit immediate
|
|
{
|
|
o.dtype = dt_word;
|
|
o.type = o_imm;
|
|
o.value = get_next_byte(insn);
|
|
o.sib = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
inline void op_shift(op_t &o, int shift) // shift
|
|
{
|
|
o.type = o_imm;
|
|
o.value = shift;
|
|
o.sib = 2;
|
|
if ( o.value == 0 )
|
|
o.clr_shown();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void tms320c5_t::op_short(op_t &o) const // short immediate
|
|
{
|
|
o.dtype = dt_byte;
|
|
o.type = o_imm;
|
|
o.value = code & 0xFF;
|
|
o.sib = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
inline void op_cbit(op_t &o, int bit)
|
|
{
|
|
o.type = o_bit;
|
|
o.value = bit;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
int tms320c5_t::op_cond(op_t &o) const
|
|
{
|
|
o.type = o_cond;
|
|
o.Cond = uint16(o.value = (code & 0x3FF));
|
|
int mask = int(o.value>>0) & 0xF;
|
|
int cond = int(o.value>>4) & 0xF;
|
|
if ( ((mask>>2) & 3) == 3 ) // Z L
|
|
{
|
|
switch ( (cond>>2)&3 )
|
|
{
|
|
case 0:
|
|
case 1:
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void tms320c5_t::op_bit(op_t &o) const
|
|
{
|
|
o.type = o_imm;
|
|
// strange? documentation say this way: o.value = 15 - ((code >> 8) & 0xF);
|
|
// assembler works this way:
|
|
o.value = (code >> 8) & 0xF;
|
|
o.sib = 3;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
int tms320c5_t::ana_c2(insn_t &insn)
|
|
{
|
|
uchar subcode = (code >> 8) & 0xF;
|
|
switch ( code >> 12 )
|
|
{
|
|
// 0000 SSSS MDDD DDDD TMS2_add
|
|
// 0001 SSSS MDDD DDDD TMS2_sub
|
|
// 0010 SSSS MDDD DDDD TMS2_lac
|
|
case 0:
|
|
insn.itype = TMS2_add;
|
|
goto iaa_shift;
|
|
case 1:
|
|
insn.itype = TMS2_sub;
|
|
goto iaa_shift;
|
|
case 2:
|
|
insn.itype = TMS2_lac;
|
|
iaa_shift:
|
|
if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
op_shift(insn.Op2, subcode);
|
|
break;
|
|
|
|
// 0011 0RRR MDDD DDDD TMS2_lar
|
|
// 0011 1000 MDDD DDDD TMS2_mpy
|
|
// 0011 1001 MDDD DDDD TMS2_sqra
|
|
// 0011 1010 MDDD DDDD TMS2_mpya
|
|
// 0011 1011 MDDD DDDD TMS2_mpys
|
|
// 0011 1100 MDDD DDDD TMS2_lt
|
|
// 0011 1101 MDDD DDDD TMS2_lta
|
|
// 0011 1110 MDDD DDDD TMS2_ltp
|
|
// 0011 1111 MDDD DDDD TMS2_ltd
|
|
case 3:
|
|
if ( subcode < 8 )
|
|
{
|
|
insn.itype = TMS2_lar;
|
|
op_ar(insn.Op1, subcode);
|
|
if ( !op_iaa(insn, insn.Op2) )
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
static const uchar codes[8] =
|
|
{
|
|
TMS2_mpy, TMS2_sqra, TMS2_mpya, TMS2_mpys,
|
|
TMS2_lt, TMS2_lta, TMS2_ltp, TMS2_ltd
|
|
};
|
|
insn.itype = codes[subcode-8];
|
|
if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
}
|
|
break;
|
|
|
|
// 0100 0000 MDDD DDDD TMS2_zalh
|
|
// 0100 0001 MDDD DDDD TMS2_zals
|
|
// 0100 0010 MDDD DDDD TMS2_lact
|
|
// 0100 0011 MDDD DDDD TMS2_addc
|
|
// 0100 0100 MDDD DDDD TMS2_subh
|
|
// 0100 0101 MDDD DDDD TMS2_subs
|
|
// 0100 0110 MDDD DDDD TMS2_subt
|
|
// 0100 0111 MDDD DDDD TMS2_subc
|
|
// 0100 1000 MDDD DDDD TMS2_addh
|
|
// 0100 1001 MDDD DDDD TMS2_adds
|
|
// 0100 1010 MDDD DDDD TMS2_addt
|
|
// 0100 1011 MDDD DDDD TMS2_rpt
|
|
// 0100 1100 MDDD DDDD TMS2_xor
|
|
// 0100 1101 MDDD DDDD TMS2_or
|
|
// 0100 1110 MDDD DDDD TMS2_and
|
|
// 0100 1111 MDDD DDDD TMS2_subb
|
|
case 4:
|
|
{
|
|
static const ushort codes[16] =
|
|
{
|
|
TMS2_zalh, TMS2_zals, TMS2_lact, TMS2_addc,
|
|
TMS2_subh, TMS2_subs, TMS2_subt, TMS2_subc,
|
|
TMS2_addh, TMS2_adds, TMS2_addt, TMS2_rpt,
|
|
TMS2_xor, TMS2_or, TMS2_and, TMS2_subb
|
|
};
|
|
insn.itype = codes[subcode];
|
|
if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
}
|
|
break;
|
|
|
|
// 0101 0000 MDDD DDDD TMS2_lst
|
|
// 0101 0001 MDDD DDDD TMS2_lst1
|
|
// 0101 0010 MDDD DDDD TMS2_ldp
|
|
// 0101 0011 MDDD DDDD TMS2_lph
|
|
// 0101 0100 MDDD DDDD TMS2_pshd
|
|
// 0101 0101 0000 0000 TMS2_nop
|
|
// 0101 0101 1000 1RRR TMS2_larp
|
|
// 0101 0101 MDDD DDDD TMS2_mar
|
|
// 0101 0110 MDDD DDDD TMS2_dmov
|
|
// 0101 0111 MDDD DDDD TMS2_bitt
|
|
// 0101 1000 MDDD DDDD TMS2_tblr
|
|
// 0101 1001 MDDD DDDD TMS2_tblw
|
|
// 0101 1010 MDDD DDDD TMS2_sqrs
|
|
// 0101 1011 MDDD DDDD TMS2_lts
|
|
// 0101 1100 MDDD DDDD +1 TMS2_macd
|
|
// 0101 1101 MDDD DDDD +1 TMS2_mac
|
|
// 0101 1110 1DDD DDDD +1 TMS2_bc
|
|
// 0101 1111 1DDD DDDD +1 TMS2_bnc
|
|
case 5:
|
|
{
|
|
static const ushort codes[16] =
|
|
{
|
|
TMS2_lst, TMS2_lst1, TMS2_ldp, TMS2_lph,
|
|
TMS2_pshd, TMS2_mar, TMS2_dmov, TMS2_bitt,
|
|
TMS2_tblr, TMS2_tblw, TMS2_sqrs, TMS2_lts,
|
|
TMS2_macd, TMS2_mac, TMS2_bc, TMS2_bnc
|
|
};
|
|
insn.itype = codes[subcode];
|
|
if ( subcode >= 12 )
|
|
{
|
|
op_paddr(insn, insn.Op1);
|
|
if ( subcode >= 14 )
|
|
{
|
|
if ( !op_indir(insn.Op2) )
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
if ( !op_iaa(insn, insn.Op2) )
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( subcode == 5 )
|
|
{
|
|
if ( (code & 0x80) == 0 )
|
|
{
|
|
insn.itype = TMS2_nop;
|
|
insn.Op1.type = o_void;
|
|
break;
|
|
}
|
|
else if ( (code & 0xF8) == 0x88 )
|
|
{
|
|
insn.itype = TMS2_larp;
|
|
insn.Op1.type = o_reg;
|
|
insn.Op1.reg = rAr0 + (code & 7);
|
|
break;
|
|
}
|
|
}
|
|
if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
}
|
|
}
|
|
break;
|
|
|
|
// 0110 0XXX MDDD DDDD TMS2_sacl
|
|
// 0110 1XXX MDDD DDDD TMS2_sach
|
|
case 6:
|
|
insn.itype = (subcode & 8) ? TMS2_sach : TMS2_sacl;
|
|
if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
op_shift(insn.Op2, subcode & 7);
|
|
break;
|
|
|
|
// 0111 0RRR MDDD DDDD TMS2_sar
|
|
// 0111 1000 MDDD DDDD TMS2_sst
|
|
// 0111 1001 MDDD DDDD TMS2_sst1
|
|
// 0111 1010 MDDD DDDD TMS2_popd
|
|
// 0111 1011 MDDD DDDD TMS2_zalr
|
|
// 0111 1100 MDDD DDDD TMS2_spl
|
|
// 0111 1101 MDDD DDDD TMS2_sph
|
|
// 0111 1110 KKKK KKKK TMS2_adrk
|
|
// 0111 1111 KKKK KKKK TMS2_sbrk
|
|
case 7:
|
|
if ( subcode < 8 )
|
|
{
|
|
insn.itype = TMS2_sar;
|
|
op_ar(insn.Op1, subcode);
|
|
if ( !op_iaa(insn, insn.Op2) )
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
static const ushort codes[8] =
|
|
{
|
|
TMS2_sst, TMS2_sst1, TMS2_popd, TMS2_zalr,
|
|
TMS2_spl, TMS2_sph, TMS2_adrk, TMS2_sbrk
|
|
};
|
|
insn.itype = codes[subcode-8];
|
|
if ( subcode >= 14 )
|
|
op_short(insn.Op1);
|
|
else if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
}
|
|
break;
|
|
|
|
// 1000 AAAA MDDD DDDD TMS2_in
|
|
case 8:
|
|
insn.itype = TMS2_in;
|
|
if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
insn.Op2.value = subcode;
|
|
insn.Op2.type = o_imm;
|
|
insn.Op2.sib = 1;
|
|
break;
|
|
|
|
// 1001 BBBB MDDD DDDD TMS2_bit
|
|
case 9:
|
|
insn.itype = TMS2_bit;
|
|
if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
insn.Op2.value = subcode;
|
|
insn.Op2.type = o_imm;
|
|
insn.Op2.sib = 0;
|
|
break;
|
|
|
|
// 101K KKKK KKKK KKKK TMS2_mpyk
|
|
case 0xA:
|
|
case 0xB:
|
|
insn.itype = TMS2_mpyk;
|
|
insn.Op1.value = code & 0x1FFF;
|
|
if ( (insn.Op1.value & 0x1000) != 0 )
|
|
insn.Op1.value |= ~0x1FFF; // extend sign
|
|
insn.Op1.type = o_imm;
|
|
insn.Op1.sib = 0;
|
|
break;
|
|
|
|
// 1100 0RRR KKKK KKKK TMS2_lark
|
|
// 1100 100K KKKK KKKK TMS2_ldpk
|
|
// 1100 1010 0000 0000 TMS2_zac
|
|
// 1100 1010 KKKK KKKK TMS2_lack
|
|
// 1100 1011 KKKK KKKK TMS2_rptk
|
|
// 1100 1100 KKKK KKKK TMS2_addk
|
|
// 1100 1101 KKKK KKKK TMS2_subk
|
|
// 1100 1110 0000 0000 TMS2_eint
|
|
// 1100 1110 0000 0001 TMS2_dint
|
|
// 1100 1110 0000 0010 TMS2_rovm
|
|
// 1100 1110 0000 0011 TMS2_sovm
|
|
// 1100 1110 0000 0100 TMS2_cnfd
|
|
// 1100 1110 0000 0101 TMS2_cnfp
|
|
// 1100 1110 0000 0110 TMS2_rsxm
|
|
// 1100 1110 0000 0111 TMS2_ssxm
|
|
// 1100 1110 0000 10KK TMS2_spm
|
|
// 1100 1110 0000 1100 TMS2_rxf
|
|
// 1100 1110 0000 1101 TMS2_sxf
|
|
// 1100 1110 0000 111K TMS2_fort
|
|
// 1100 1110 0001 0100 TMS2_pac
|
|
// 1100 1110 0001 0101 TMS2_apac
|
|
// 1100 1110 0001 0110 TMS2_spac
|
|
// 1100 1110 0001 1000 TMS2_sfl
|
|
// 1100 1110 0001 1001 TMS2_sfr
|
|
// 1100 1110 0001 1011 TMS2_abs
|
|
// 1100 1110 0001 1100 TMS2_push
|
|
// 1100 1110 0001 1101 TMS2_pop
|
|
// 1100 1110 0001 1110 TMS2_trap
|
|
// 1100 1110 0001 1111 TMS2_idle
|
|
// 1100 1110 0010 0000 TMS2_rtxm
|
|
// 1100 1110 0010 0001 TMS2_stxm
|
|
// 1100 1110 0010 0011 TMS2_neg
|
|
// 1100 1110 0010 0100 TMS2_cala
|
|
// 1100 1110 0010 0101 TMS2_bacc
|
|
// 1100 1110 0010 0110 TMS2_ret
|
|
// 1100 1110 0010 0111 TMS2_cmpl
|
|
// 1100 1110 0011 0000 TMS2_rc
|
|
// 1100 1110 0011 0001 TMS2_sc
|
|
// 1100 1110 0011 0010 TMS2_rtc
|
|
// 1100 1110 0011 0011 TMS2_stc
|
|
// 1100 1110 0011 0100 TMS2_rol
|
|
// 1100 1110 0011 0101 TMS2_ror
|
|
// 1100 1110 0011 0110 TMS2_rfsm
|
|
// 1100 1110 0011 0111 TMS2_sfsm
|
|
// 1100 1110 0011 1000 TMS2_rhm
|
|
// 1100 1110 0011 1001 TMS2_shm
|
|
// 1100 1110 0011 11KK TMS2_conf
|
|
// 1100 1110 0101 00KK TMS2_cmpr
|
|
// 1100 1110 1AAA 0010 TMS2_norm
|
|
// 1100 1111 MDDD DDDD TMS2_mpyu
|
|
case 0xC:
|
|
switch ( subcode )
|
|
{
|
|
default: // 1100 0RRR KKKK KKKK TMS2_lark
|
|
insn.itype = TMS2_lark;
|
|
op_ar(insn.Op1, subcode);
|
|
op_short(insn.Op2);
|
|
break;
|
|
case 8:
|
|
case 9: // 1100 100K KKKK KKKK TMS2_ldpk
|
|
insn.itype = TMS2_ldpk;
|
|
insn.Op1.dtype = dt_word;
|
|
insn.Op1.value = code & 0x1FF;
|
|
insn.Op1.type = o_imm;
|
|
insn.Op1.sib = 0;
|
|
break;
|
|
case 0xA:
|
|
if ( code == 0xCA00 )
|
|
{
|
|
insn.itype = TMS2_zac;
|
|
break;
|
|
}
|
|
insn.itype = TMS2_lack;
|
|
goto LOAD_SHORT;
|
|
case 0xB:
|
|
insn.itype = TMS2_rptk;
|
|
op_short(insn.Op1);
|
|
insn.Op1.sib = 1;
|
|
break;
|
|
case 0xC:
|
|
insn.itype = TMS2_addk;
|
|
goto LOAD_SHORT;
|
|
case 0xD:
|
|
insn.itype = TMS2_subk;
|
|
LOAD_SHORT:
|
|
op_short(insn.Op1);
|
|
break;
|
|
case 0xE:
|
|
switch ( (code>>4) & 0xF )
|
|
{
|
|
// 0000 0000 TMS2_eint
|
|
// 0000 0001 TMS2_dint
|
|
// 0000 0010 TMS2_rovm
|
|
// 0000 0011 TMS2_sovm
|
|
// 0000 0100 TMS2_cnfd
|
|
// 0000 0101 TMS2_cnfp
|
|
// 0000 0110 TMS2_rsxm
|
|
// 0000 0111 TMS2_ssxm
|
|
// 0000 10KK TMS2_spm
|
|
// 0000 1100 TMS2_rxf
|
|
// 0000 1101 TMS2_sxf
|
|
// 0000 111K TMS2_fort
|
|
case 0:
|
|
{
|
|
static const ushort codes[] =
|
|
{
|
|
TMS2_eint, TMS2_dint, TMS2_rovm, TMS2_sovm,
|
|
TMS2_cnfd, TMS2_cnfp, TMS2_rsxm, TMS2_ssxm,
|
|
TMS2_spm, TMS2_spm, TMS2_spm, TMS2_spm,
|
|
TMS2_rxf, TMS2_sxf, TMS2_fort, TMS2_fort
|
|
};
|
|
insn.itype = codes[code & 0xF];
|
|
if ( insn.itype == TMS2_spm )
|
|
{
|
|
insn.Op1.value = code & 3;
|
|
insn.Op1.type = o_imm;
|
|
insn.Op1.sib = 0;
|
|
}
|
|
else if ( insn.itype == TMS2_fort )
|
|
{
|
|
insn.Op1.value = code & 1;
|
|
insn.Op1.type = o_imm;
|
|
insn.Op1.sib = 0;
|
|
}
|
|
}
|
|
break;
|
|
|
|
// 0001 0100 TMS2_pac
|
|
// 0001 0101 TMS2_apac
|
|
// 0001 0110 TMS2_spac
|
|
// 0001 1000 TMS2_sfl
|
|
// 0001 1001 TMS2_sfr
|
|
// 0001 1011 TMS2_abs
|
|
// 0001 1100 TMS2_push
|
|
// 0001 1101 TMS2_pop
|
|
// 0001 1110 TMS2_trap
|
|
// 0001 1111 TMS2_idle
|
|
case 1:
|
|
{
|
|
static const ushort codes[] =
|
|
{
|
|
TMS_null, TMS_null, TMS_null, TMS_null,
|
|
TMS2_pac, TMS2_apac, TMS2_spac, TMS_null,
|
|
TMS2_sfl, TMS2_sfr, TMS_null, TMS2_abs,
|
|
TMS2_push, TMS2_pop, TMS2_trap, TMS2_idle
|
|
};
|
|
insn.itype = codes[code & 0xF];
|
|
}
|
|
break;
|
|
|
|
// 0010 0000 TMS2_rtxm
|
|
// 0010 0001 TMS2_stxm
|
|
// 0010 0011 TMS2_neg
|
|
// 0010 0100 TMS2_cala
|
|
// 0010 0101 TMS2_bacc
|
|
// 0010 0110 TMS2_ret
|
|
// 0010 0111 TMS2_cmpl
|
|
case 2:
|
|
if ( (code & 0xF) < 8 )
|
|
{
|
|
static const ushort codes[] =
|
|
{
|
|
TMS2_rtxm, TMS2_stxm, TMS_null, TMS2_neg,
|
|
TMS2_cala, TMS2_bacc, TMS2_ret, TMS2_cmpl
|
|
};
|
|
insn.itype = codes[code & 0xF];
|
|
}
|
|
break;
|
|
|
|
// 0011 0000 TMS2_rc
|
|
// 0011 0001 TMS2_sc
|
|
// 0011 0010 TMS2_rtc
|
|
// 0011 0011 TMS2_stc
|
|
// 0011 0100 TMS2_rol
|
|
// 0011 0101 TMS2_ror
|
|
// 0011 0110 TMS2_rfsm
|
|
// 0011 0111 TMS2_sfsm
|
|
// 0011 1000 TMS2_rhm
|
|
// 0011 1001 TMS2_shm
|
|
// 0011 11KK TMS2_conf
|
|
case 3:
|
|
if ( (code & 0xF) >= 0xC )
|
|
{
|
|
insn.itype = TMS2_conf;
|
|
insn.Op1.value = code & 3;
|
|
insn.Op1.type = o_imm;
|
|
insn.Op1.sib = 0;
|
|
}
|
|
else
|
|
{
|
|
static const ushort codes[] =
|
|
{
|
|
TMS2_rc, TMS2_sc, TMS2_rtc, TMS2_stc,
|
|
TMS2_rol, TMS2_ror, TMS2_rfsm, TMS2_sfsm,
|
|
TMS2_rhm, TMS2_shm, TMS_null, TMS_null,
|
|
};
|
|
insn.itype = codes[code & 0xF];
|
|
}
|
|
break;
|
|
|
|
// 0101 00KK TMS2_cmpr
|
|
case 5:
|
|
if ( (code & 0xC) == 0 )
|
|
{
|
|
insn.itype = TMS2_cmpr;
|
|
insn.Op1.value = code & 3;
|
|
insn.Op1.type = o_imm;
|
|
insn.Op1.sib = 0;
|
|
}
|
|
break;
|
|
|
|
// 1AAA 0010 TMS2_norm
|
|
case 0x8:
|
|
case 0x9:
|
|
case 0xA:
|
|
case 0xB:
|
|
case 0xC:
|
|
case 0xD:
|
|
case 0xE:
|
|
case 0xF:
|
|
insn.itype = TMS2_norm;
|
|
op_indir(insn.Op1);
|
|
break;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
break;
|
|
case 0xF: // 1100 1111 MDDD DDDD TMS2_mpyu
|
|
insn.itype = TMS2_mpyu;
|
|
if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
// 1101 0RRR 0000 0000 +1 TMS2_lrlk
|
|
// 1101 SSSS 0000 0001 +1 TMS2_lalk
|
|
// 1101 SSSS 0000 0010 +1 TMS2_adlk
|
|
// 1101 SSSS 0000 0011 +1 TMS2_sblk
|
|
// 1101 SSSS 0000 0100 +1 TMS2_andk
|
|
// 1101 SSSS 0000 0101 +1 TMS2_ork
|
|
// 1101 SSSS 0000 0110 +1 TMS2_xork
|
|
case 0xD:
|
|
{
|
|
uint opcode = code & 0xFF;
|
|
if ( opcode == 0 )
|
|
{
|
|
if ( subcode >= 8 )
|
|
return 0;
|
|
insn.itype = TMS2_lrlk;
|
|
op_ar(insn.Op1, subcode);
|
|
op_imm(insn, insn.Op2);
|
|
}
|
|
else if ( opcode < 7 )
|
|
{
|
|
static const ushort codes[] =
|
|
{
|
|
0, TMS2_lalk, TMS2_adlk, TMS2_sblk,
|
|
TMS2_andk, TMS2_ork, TMS2_xork,
|
|
};
|
|
insn.itype = codes[opcode];
|
|
op_imm(insn, insn.Op1);
|
|
op_shift(insn.Op2, subcode);
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
break;
|
|
|
|
// 1110 AAAA MDDD DDDD TMS2_out
|
|
case 0xE:
|
|
insn.itype = TMS2_out;
|
|
if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
insn.Op2.value = subcode;
|
|
insn.Op2.type = o_imm;
|
|
insn.Op2.sib = 1;
|
|
break;
|
|
|
|
// 1111 0000 1DDD DDDD +1 TMS2_bv
|
|
// 1111 0001 1DDD DDDD +1 TMS2_bgz
|
|
// 1111 0010 1DDD DDDD +1 TMS2_blez
|
|
// 1111 0011 1DDD DDDD +1 TMS2_blz
|
|
// 1111 0100 1DDD DDDD +1 TMS2_bgez
|
|
// 1111 0101 1DDD DDDD +1 TMS2_bnz
|
|
// 1111 0110 1DDD DDDD +1 TMS2_bz
|
|
// 1111 0111 1DDD DDDD +1 TMS2_bnv
|
|
// 1111 1000 1DDD DDDD +1 TMS2_bbz
|
|
// 1111 1001 1DDD DDDD +1 TMS2_bbnz
|
|
// 1111 1010 1DDD DDDD +1 TMS2_bioz
|
|
// 1111 1011 1DDD DDDD +1 TMS2_banz
|
|
// 1111 1100 MDDD DDDD +1 TMS2_blkp
|
|
// 1111 1101 MDDD DDDD +1 TMS2_blkd
|
|
// 1111 1110 1DDD DDDD +1 TMS2_call
|
|
// 1111 1111 1DDD DDDD +1 TMS2_b
|
|
case 0xF:
|
|
{
|
|
static const ushort codes[16] =
|
|
{
|
|
TMS2_bv, TMS2_bgz, TMS2_blez, TMS2_blz,
|
|
TMS2_bgez, TMS2_bnz, TMS2_bz, TMS2_bnv,
|
|
TMS2_bbz, TMS2_bbnz, TMS2_bioz, TMS2_banz,
|
|
TMS2_blkp, TMS2_blkd, TMS2_call, TMS2_b
|
|
};
|
|
insn.itype = codes[subcode];
|
|
op_paddr(insn, insn.Op1);
|
|
switch ( insn.itype )
|
|
{
|
|
case TMS2_blkd:
|
|
insn.Op1.type = o_mem;
|
|
insn.Op1.sib = 1;
|
|
// fallthrough
|
|
case TMS2_blkp:
|
|
if ( !op_iaa(insn, insn.Op2) )
|
|
return 0;
|
|
break;
|
|
default:
|
|
if ( !op_indir(insn.Op2) )
|
|
return 0;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
//----------------------------------------------------------------------
|
|
int tms320c5_t::ana(insn_t *_insn)
|
|
{
|
|
insn_t &insn = *_insn;
|
|
code = get_next_byte(insn);
|
|
uchar subcode = (code >> 8) & 0xF;
|
|
uint nibble;
|
|
|
|
if ( isC2() )
|
|
{
|
|
if ( !ana_c2(insn) )
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
switch ( code >> 12 )
|
|
{
|
|
case 0:
|
|
if ( subcode < 8 )
|
|
{
|
|
insn.itype = TMS_lar;
|
|
op_ar(insn.Op1, subcode);
|
|
if ( !op_iaa(insn, insn.Op2) )
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
{
|
|
static const uchar codes[8] =
|
|
{
|
|
TMS_lamm, TMS_smmr, TMS_subc, TMS_rpt,
|
|
TMS_out, TMS_ldp, TMS_lst, TMS_lst
|
|
};
|
|
insn.itype = codes[subcode-8];
|
|
}
|
|
if ( subcode == 0xC )
|
|
op_ioaddr(insn, insn.Op2);
|
|
case08_common:
|
|
{
|
|
int ok = (subcode == 0x8 || subcode == 0x9)
|
|
? op_maa(insn, insn.Op1)
|
|
: op_iaa(insn, insn.Op1);
|
|
if ( !ok )
|
|
return 0;
|
|
}
|
|
if ( subcode == 0x9 )
|
|
op_daddr(insn, insn.Op2);
|
|
if ( subcode >= 0xE )
|
|
{
|
|
if ( insn.itype == TMS_sst )
|
|
op_maa(insn, insn.Op1);
|
|
insn.Op2 = insn.Op1;
|
|
insn.Op2.n = 1;
|
|
insn.Op1.type = o_imm;
|
|
insn.Op1.value = subcode & 1;
|
|
insn.Op1.sib = 0;
|
|
}
|
|
}
|
|
break;
|
|
case 8:
|
|
if ( subcode < 8 )
|
|
{
|
|
insn.itype = TMS_sar;
|
|
op_ar(insn.Op1, subcode);
|
|
if ( !op_iaa(insn, insn.Op2) )
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
static const uchar codes[8] =
|
|
{
|
|
TMS_samm, TMS_lmmr, TMS_popd, TMS_mar,
|
|
TMS_spl, TMS_sph, TMS_sst, TMS_sst
|
|
};
|
|
insn.itype = codes[subcode-8];
|
|
if ( subcode == 0xB && (code & 0xFF) == 0 )
|
|
{
|
|
insn.itype = TMS_nop;
|
|
insn.Op1.type = o_void;
|
|
break;
|
|
}
|
|
goto case08_common;
|
|
}
|
|
break;
|
|
case 1:
|
|
insn.itype = TMS_lacc;
|
|
goto iaa_shift;
|
|
case 2:
|
|
insn.itype = TMS_add;
|
|
goto iaa_shift;
|
|
case 3:
|
|
insn.itype = TMS_sub;
|
|
iaa_shift:
|
|
if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
op_shift(insn.Op2, subcode);
|
|
break;
|
|
case 4:
|
|
insn.itype = TMS_bit;
|
|
if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
op_bit(insn.Op2);
|
|
break;
|
|
case 5:
|
|
{
|
|
static const uchar codes[16] =
|
|
{
|
|
TMS_mpya, TMS_mpys, TMS_sqra, TMS_sqrs,
|
|
TMS_mpy, TMS_mpyu, TMS_null, TMS_bldp,
|
|
TMS_xpl, TMS_opl, TMS_apl, TMS_cpl,
|
|
TMS_xpl2, TMS_opl2, TMS_apl2, TMS_cpl2
|
|
};
|
|
insn.itype = codes[subcode];
|
|
if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
op_t *o;
|
|
if ( subcode >= 0xC )
|
|
{
|
|
op_imm(insn, insn.Op1);
|
|
o = &insn.Op2;
|
|
}
|
|
else
|
|
{
|
|
o = &insn.Op1;
|
|
}
|
|
if ( !op_iaa(insn, *o) )
|
|
return 0;
|
|
}
|
|
break;
|
|
case 6:
|
|
{
|
|
static const uchar codes[16] =
|
|
{
|
|
TMS_addc, TMS_add, TMS_adds, TMS_addt,
|
|
TMS_subb, TMS_sub, TMS_subs, TMS_subt,
|
|
TMS_zalr, TMS_lacl, TMS_lacc, TMS_lact,
|
|
TMS_xor, TMS_or, TMS_and, TMS_bitt
|
|
};
|
|
insn.itype = codes[subcode];
|
|
if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
if ( insn.itype == TMS_lacc
|
|
|| insn.itype == TMS_add
|
|
|| insn.itype == TMS_sub )
|
|
{
|
|
op_shift(insn.Op2, 16);
|
|
}
|
|
}
|
|
break;
|
|
case 7:
|
|
{
|
|
static const uchar codes[16] =
|
|
{
|
|
TMS_lta, TMS_ltp, TMS_ltd, TMS_lt,
|
|
TMS_lts, TMS_lph, TMS_pshd, TMS_dmov,
|
|
TMS_adrk, TMS_b, TMS_call, TMS_banz,
|
|
TMS_sbrk, TMS_bd, TMS_calld, TMS_banzd
|
|
};
|
|
insn.itype = codes[subcode];
|
|
if ( subcode < 8 )
|
|
{
|
|
if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
if ( subcode != 8 && subcode != 0xC )
|
|
{
|
|
op_paddr(insn, insn.Op1);
|
|
if ( !op_iaa(insn, insn.Op2) || insn.Op2.type != o_phrase )
|
|
insn.itype = TMS_null;
|
|
}
|
|
else
|
|
{
|
|
op_short(insn.Op1);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 9:
|
|
insn.itype = (subcode & 8) ? TMS_sach : TMS_sacl;
|
|
if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
op_shift(insn.Op2, subcode&7);
|
|
break;
|
|
case 0xA:
|
|
{
|
|
static const uchar codes[16] =
|
|
{
|
|
TMS_norm, TMS_null, TMS_mac, TMS_macd,
|
|
TMS_blpd, TMS_blpd, TMS_tblr, TMS_tblw,
|
|
TMS_bldd, TMS_bldd, TMS_mads, TMS_madd,
|
|
TMS_bldd, TMS_bldd, TMS_splk, TMS_in
|
|
};
|
|
insn.itype = codes[subcode];
|
|
switch ( subcode )
|
|
{
|
|
case 0:
|
|
if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
if ( (code & 0x80) == 0 )
|
|
insn.itype = TMS_null;
|
|
break;
|
|
case 4: // blpd bmar, ?
|
|
case 0xC: // bldd bmar, ?
|
|
insn.Op1.type = o_reg;
|
|
insn.Op1.reg = rBMAR;
|
|
if ( !op_iaa(insn, insn.Op2) )
|
|
return 0;
|
|
break;
|
|
case 0xD: // bldd ?, bmar
|
|
if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
insn.Op2.type = o_reg;
|
|
insn.Op2.reg = rBMAR;
|
|
break;
|
|
case 2: // mac
|
|
case 3: // macd
|
|
case 5: // blpd
|
|
op_paddr(insn, insn.Op1);
|
|
if ( !op_iaa(insn, insn.Op2) )
|
|
return 0;
|
|
break;
|
|
case 8:
|
|
op_daddr(insn, insn.Op1);
|
|
if ( !op_iaa(insn, insn.Op2) )
|
|
return 0;
|
|
break;
|
|
case 9:
|
|
if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
op_daddr(insn, insn.Op2);
|
|
break;
|
|
case 0xE:
|
|
op_imm(insn, insn.Op1);
|
|
if ( !op_iaa(insn, insn.Op2) )
|
|
return 0;
|
|
break;
|
|
case 0xF:
|
|
if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
op_ioaddr(insn, insn.Op2);
|
|
break;
|
|
default:
|
|
if ( !op_iaa(insn, insn.Op1) )
|
|
return 0;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 0xB:
|
|
switch ( subcode )
|
|
{
|
|
case 0: case 1: case 2: case 3:
|
|
case 4: case 5: case 6: case 7:
|
|
insn.itype = TMS_lar;
|
|
op_ar(insn.Op1, subcode);
|
|
op_short(insn.Op2);
|
|
break;
|
|
case 8: case 9: case 0xA: case 0xB:
|
|
case 0xC:
|
|
{
|
|
static const uchar codes[] =
|
|
{
|
|
TMS_add, TMS_lacl, TMS_sub, TMS_rpt, TMS_ldp
|
|
};
|
|
insn.itype = codes[subcode-8]; //lint !e676 possibly indexing before the beginning of an allocation
|
|
op_short(insn.Op1);
|
|
}
|
|
break;
|
|
case 0xD:
|
|
insn.itype = TMS_ldp;
|
|
op_short(insn.Op1);
|
|
insn.Op1.value |= 0x100;
|
|
break;
|
|
case 0xE:
|
|
nibble = (code & 0xF);
|
|
switch ( (code >> 4) & 0xF )
|
|
{
|
|
case 0: case 1: case 2: case 3:
|
|
{
|
|
static const uchar codes[] =
|
|
{
|
|
TMS_abs, TMS_cmpl, TMS_neg, TMS_pac,
|
|
TMS_apac, TMS_spac, TMS_null, TMS_null,
|
|
TMS_null, TMS_sfl, TMS_sfr, TMS_null,
|
|
TMS_rol, TMS_ror, TMS_null, TMS_null,
|
|
|
|
TMS_addb, TMS_adcb, TMS_andb, TMS_orb,
|
|
TMS_rolb, TMS_rorb, TMS_sflb, TMS_sfrb,
|
|
TMS_sbb, TMS_sbbb, TMS_xorb, TMS_crgt,
|
|
TMS_crlt, TMS_exar, TMS_sacb, TMS_lacb,
|
|
|
|
TMS_bacc, TMS_baccd, TMS_idle, TMS_idle2,
|
|
TMS_null, TMS_null, TMS_null, TMS_null,
|
|
TMS_null, TMS_null, TMS_null, TMS_null,
|
|
TMS_null, TMS_null, TMS_null, TMS_null,
|
|
|
|
TMS_cala, TMS_null, TMS_pop, TMS_null,
|
|
TMS_null, TMS_null, TMS_null, TMS_null,
|
|
TMS_reti, TMS_null, TMS_rete, TMS_null,
|
|
TMS_push, TMS_calad, TMS_null, TMS_null
|
|
};
|
|
insn.itype = codes[code & 0x3F];
|
|
}
|
|
break;
|
|
case 4:
|
|
insn.itype = (code & 1) ? TMS_setc : TMS_clrc;
|
|
op_cbit(insn.Op1, (code>>1)&7);
|
|
break;
|
|
case 5:
|
|
{
|
|
static const uchar codes[] =
|
|
{
|
|
TMS_null, TMS_trap, TMS_nmi, TMS_null,
|
|
TMS_null, TMS_null, TMS_null, TMS_null,
|
|
TMS_zpr, TMS_zap, TMS_sath, TMS_satl,
|
|
TMS_null, TMS_null, TMS_null, TMS_null
|
|
};
|
|
insn.itype = codes[nibble];
|
|
}
|
|
break;
|
|
case 6:
|
|
case 7:
|
|
insn.itype = TMS_intr;
|
|
insn.Op1.type = o_imm;
|
|
insn.Op1.value = (code & 0x1F);
|
|
insn.Op1.sib = 1;
|
|
break;
|
|
case 8:
|
|
if ( nibble < 4 )
|
|
{
|
|
static const uchar codes[] =
|
|
{
|
|
TMS_mpy, TMS_and, TMS_or, TMS_xor
|
|
};
|
|
insn.itype = codes[nibble];
|
|
op_imm(insn, insn.Op1);
|
|
if ( nibble != 0 )
|
|
op_shift(insn.Op2, 16);
|
|
}
|
|
break;
|
|
case 9:
|
|
if ( nibble == 0 )
|
|
insn.itype = TMS_estop;
|
|
break;
|
|
case 0xC:
|
|
switch ( nibble )
|
|
{
|
|
case 4:
|
|
insn.itype = TMS_rpt;
|
|
op_imm(insn, insn.Op1);
|
|
break;
|
|
case 5:
|
|
insn.itype = TMS_rptz;
|
|
op_imm(insn, insn.Op1);
|
|
break;
|
|
case 6:
|
|
insn.itype = TMS_rptb;
|
|
op_paddr(insn, insn.Op1);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case 0xF:
|
|
nibble = (code & 0xF);
|
|
switch ( (code>>4) & 0xF )
|
|
{
|
|
case 0:
|
|
if ( code & 8 )
|
|
{
|
|
insn.itype = TMS_lar;
|
|
op_ar(insn.Op1, code & 7);
|
|
op_imm(insn, insn.Op2);
|
|
}
|
|
else
|
|
{
|
|
insn.itype = TMS_spm;
|
|
op_short(insn.Op1);
|
|
insn.Op1.sib = 1;
|
|
}
|
|
break;
|
|
case 4:
|
|
if ( (nibble & 0xC) == 4 )
|
|
{
|
|
insn.itype = TMS_cmpr;
|
|
insn.Op1.type = o_imm;
|
|
insn.Op1.value = nibble & 3;
|
|
insn.Op1.sib = 1;
|
|
}
|
|
break;
|
|
case 0xE:
|
|
insn.itype = TMS_bsar;
|
|
op_shift(insn.Op1, nibble+1);
|
|
break;
|
|
case 8:
|
|
case 9:
|
|
case 0xA:
|
|
case 0xB:
|
|
case 0xC:
|
|
case 0xD:
|
|
{
|
|
static const uchar codes[] =
|
|
{
|
|
TMS_lacc, TMS_add, TMS_sub, TMS_and, TMS_or, TMS_xor
|
|
};
|
|
insn.itype = codes[(code>>4) & 0x7];
|
|
op_imm(insn, insn.Op1);
|
|
op_shift(insn.Op2, nibble);
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case 0xC:
|
|
case 0xD:
|
|
insn.itype = TMS_mpy;
|
|
insn.Op1.dtype = dt_word;
|
|
insn.Op1.type = o_imm;
|
|
insn.Op1.value = (code & 0x1FFF);
|
|
if ( (insn.Op1.value & 0x1000) != 0 )
|
|
insn.Op1.value |= ~0x1FFF; // extend sign
|
|
insn.Op1.sib = 0;
|
|
break;
|
|
case 0xE:
|
|
case 0xF:
|
|
switch ( subcode>>2 )
|
|
{
|
|
case 0:
|
|
insn.itype = (code & 0x1000) ? TMS_bcndd : TMS_bcnd;
|
|
op_paddr(insn, insn.Op1);
|
|
if ( !op_cond(insn.Op2) )
|
|
return 0;
|
|
break;
|
|
case 1:
|
|
insn.itype = TMS_xc;
|
|
insn.Op1.type = o_imm;
|
|
insn.Op1.value = (code & 0x1000) ? 2 : 1;
|
|
insn.Op1.sib = 1;
|
|
if ( !op_cond(insn.Op2) )
|
|
return 0;
|
|
break;
|
|
case 2:
|
|
insn.itype = (code & 0x1000) ? TMS_ccd : TMS_cc;
|
|
op_paddr(insn, insn.Op1);
|
|
if ( !op_cond(insn.Op2) )
|
|
return 0;
|
|
break;
|
|
case 3:
|
|
if ( (code & 0xEFFF) == 0xEF00 )
|
|
insn.itype = (code & 0x1000) ? TMS_retd : TMS_ret;
|
|
else
|
|
{
|
|
insn.itype = (code & 0x1000) ? TMS_retcd : TMS_retc;
|
|
if ( !op_cond(insn.Op1) )
|
|
return 0;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if ( insn.itype == TMS_null )
|
|
return 0;
|
|
return insn.size;
|
|
}
|