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

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;
}