update to ida 7.6, add builds
This commit is contained in:
403
idasdk76/module/pdp11/ana.cpp
Normal file
403
idasdk76/module/pdp11/ana.cpp
Normal file
@@ -0,0 +1,403 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA)
|
||||
* Copyright (c) 1990-98 by Ilfak Guilfanov.
|
||||
* E-mail: ig@datarescue.com
|
||||
* PDP11 module.
|
||||
* Copyright (c) 1995-2006 by Iouri Kharon.
|
||||
* E-mail: yjh@styx.cabel.net
|
||||
*
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "pdp.hpp"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void loadoper(insn_t &insn, op_t *Op, uint16 nibble)
|
||||
{
|
||||
ushort base;
|
||||
switch ( nibble )
|
||||
{
|
||||
case 027:
|
||||
{
|
||||
flags_t F1 = get_flags(insn.ea);
|
||||
flags_t F2 = get_flags(insn.ea+insn.size);
|
||||
Op->type = o_imm;
|
||||
Op->ill_imm = is_head(F1) ? !is_tail(F2) : is_head(F2);
|
||||
Op->offb = (uchar)insn.size;
|
||||
Op->value = insn.get_next_word();
|
||||
}
|
||||
break;
|
||||
case 037:
|
||||
case 077:
|
||||
case 067:
|
||||
Op->type = o_mem;
|
||||
Op->offb = (uchar)insn.size;
|
||||
base = insn.get_next_word();
|
||||
if ( (Op->phrase = nibble) != 037 )
|
||||
base += (short)(insn.ip + insn.size);
|
||||
Op->addr16 = base;
|
||||
break;
|
||||
default:
|
||||
if ( (nibble & 070) == 0 )
|
||||
{
|
||||
Op->type = o_reg;
|
||||
Op->reg = nibble;
|
||||
}
|
||||
else
|
||||
{
|
||||
Op->phrase = nibble;
|
||||
if ( nibble < 060 )
|
||||
{
|
||||
Op->type = o_phrase;
|
||||
}
|
||||
else
|
||||
{
|
||||
Op->type = o_displ;
|
||||
Op->offb = (uchar)insn.size;
|
||||
Op->addr16 = insn.get_next_word();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void pdp11_t::jmpoper(insn_t &insn, op_t *Op, uint16 nibble)
|
||||
{
|
||||
loadoper(insn, Op, nibble);
|
||||
if ( Op->type == o_mem && Op->phrase != 077 )
|
||||
Op->type = o_near;
|
||||
if ( Op->type == o_near
|
||||
&& Op->addr16 >= ml.ovrcallbeg
|
||||
&& Op->addr16 <= ml.ovrcallend )
|
||||
{
|
||||
uint32 trans = (uint32)ovrtrans.altval(Op->addr16);
|
||||
// msg("addr=%o, trans=%lo\n", Op->addr16, trans);
|
||||
if ( trans != 0 )
|
||||
{
|
||||
segment_t *S = getseg(trans);
|
||||
if ( S != NULL )
|
||||
{
|
||||
Op->type = o_far;
|
||||
Op->segval = (uint16)S->sel;
|
||||
Op->addr16 = (ushort)(trans - to_ea(Op->segval,0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int pdp11_t::ana(insn_t *_insn)
|
||||
{
|
||||
insn_t &insn = *_insn;
|
||||
|
||||
static const char twoop[5] = { pdp_mov, pdp_cmp, pdp_bit, pdp_bic, pdp_bis };
|
||||
static const char onecmd[12] =
|
||||
{
|
||||
pdp_clr, pdp_com, pdp_inc, pdp_dec,
|
||||
pdp_neg, pdp_adc, pdp_sbc, pdp_tst, pdp_ror, pdp_rol,
|
||||
pdp_asr, pdp_asl
|
||||
};
|
||||
static const char cc2com[8] =
|
||||
{
|
||||
pdp_bpl, pdp_bmi, pdp_bhi, pdp_blos,
|
||||
pdp_bvc, pdp_bvs, pdp_bcc, pdp_bcs
|
||||
};
|
||||
|
||||
if ( insn.ip & 1 )
|
||||
return 0;
|
||||
|
||||
insn.Op1.dtype = insn.Op2.dtype = dt_word;
|
||||
// insn.bytecmd = 0;
|
||||
|
||||
uint code = insn.get_next_word();
|
||||
|
||||
uchar nibble0 = (code & 077);
|
||||
uchar nibble1 = (code >> 6 ) & 077;
|
||||
uchar nibble2 = (code >> 12) & 017;
|
||||
uchar nib1swt = nibble1 >> 3;
|
||||
|
||||
switch ( nibble2 )
|
||||
{
|
||||
case 017:
|
||||
if ( nibble1 == 0 )
|
||||
{
|
||||
switch ( nibble0 )
|
||||
{
|
||||
case 0: insn.itype = pdp_cfcc; break;
|
||||
case 1: insn.itype = pdp_setf; break;
|
||||
case 2: insn.itype = pdp_seti; break;
|
||||
case 011: insn.itype = pdp_setd; break;
|
||||
case 012: insn.itype = pdp_setl; break;
|
||||
default: return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
loadoper(insn, &insn.Op1, nibble0);
|
||||
if ( nib1swt != 0 )
|
||||
{
|
||||
static const char fpcom2[14] =
|
||||
{
|
||||
pdp_muld, pdp_modd, pdp_addd,
|
||||
pdp_ldd, pdp_subd, pdp_cmpd, pdp_std, pdp_divd, pdp_stexp,
|
||||
pdp_stcdi, pdp_stcdf, pdp_ldexp, pdp_ldcif, pdp_ldcfd
|
||||
};
|
||||
insn.Op2.type = o_fpreg;
|
||||
insn.Op2.reg = (nibble1 & 3);
|
||||
insn.Op2.dtype = dt_double;
|
||||
int idx = (nibble1 >> 2) - 2;
|
||||
QASSERT(10084, idx >= 0 && idx < qnumber(fpcom2));
|
||||
insn.itype = fpcom2[idx];
|
||||
if ( insn.itype != pdp_ldexp && insn.itype != pdp_stexp )
|
||||
{
|
||||
if ( insn.Op1.type == o_reg )
|
||||
insn.Op1.type = o_fpreg;
|
||||
if ( insn.itype != pdp_stcdi && insn.itype != pdp_ldcif )
|
||||
insn.Op1.dtype = dt_double;
|
||||
}
|
||||
if ( insn.itype == pdp_std
|
||||
|| insn.itype == pdp_stexp
|
||||
|| insn.itype == pdp_stcdi
|
||||
|| insn.itype == pdp_stcdf )
|
||||
{
|
||||
op_t temp;
|
||||
temp = insn.Op2;
|
||||
insn.Op2 = insn.Op1;
|
||||
insn.Op1 = temp;
|
||||
insn.Op1.n = 0;
|
||||
insn.Op2.n = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static const char fpcom1[7] =
|
||||
{
|
||||
pdp_ldfps, pdp_stfps, pdp_stst, pdp_clrd,
|
||||
pdp_tstd, pdp_absd, pdp_negd
|
||||
};
|
||||
if ( nibble1 >= 4 )
|
||||
{
|
||||
insn.Op1.dtype = insn.Op2.dtype = dt_double;
|
||||
if ( insn.Op1.type == o_reg )
|
||||
insn.Op1.type = o_fpreg;
|
||||
}
|
||||
QASSERT(10085, (nibble1-1) >= 0 && nibble1-1 < qnumber(fpcom1));
|
||||
insn.itype = fpcom1[nibble1 - 1]; //lint !e676 possibly indexing before the beginning of an allocation
|
||||
}
|
||||
break;
|
||||
|
||||
case 7:
|
||||
switch ( nib1swt )
|
||||
{
|
||||
case 6: // CIS
|
||||
return 0;
|
||||
case 5: // FIS
|
||||
{
|
||||
static const char ficom[4] = { pdp_fadd, pdp_fsub, pdp_fmul, pdp_fdiv };
|
||||
if ( nibble1 != 050 || nibble0 >= 040 )
|
||||
return 0;
|
||||
insn.Op1.type = o_reg;
|
||||
insn.Op1.reg = nibble0 & 7;
|
||||
insn.itype = ficom[nibble0 >> 3];
|
||||
break;
|
||||
}
|
||||
case 7: // SOB
|
||||
insn.itype = pdp_sob;
|
||||
insn.Op1.type = o_reg;
|
||||
insn.Op1.reg = nibble1 & 7;
|
||||
insn.Op2.type = o_near;
|
||||
insn.Op2.phrase = 0;
|
||||
insn.Op2.addr16 = (ushort)(insn.ip + 2 - (2*nibble0));
|
||||
break;
|
||||
default:
|
||||
{
|
||||
static const char eiscom[5] = { pdp_mul, pdp_div, pdp_ash, pdp_ashc, pdp_xor };
|
||||
insn.Op2.type = o_reg;
|
||||
insn.Op2.reg = nibble1 & 7;
|
||||
loadoper(insn, &insn.Op1, nibble0);
|
||||
insn.itype = eiscom[nib1swt];
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 016:
|
||||
insn.itype = pdp_sub;
|
||||
goto twoopcmd;
|
||||
case 6:
|
||||
insn.itype = pdp_add;
|
||||
goto twoopcmd;
|
||||
default: // Normal 2 op
|
||||
insn.itype = twoop[(nibble2 & 7) - 1];
|
||||
insn.bytecmd = ((nibble2 & 010) != 0);
|
||||
twoopcmd:
|
||||
loadoper(insn, &insn.Op1, nibble1);
|
||||
loadoper(insn, &insn.Op2, nibble0);
|
||||
break;
|
||||
|
||||
case 010:
|
||||
if ( nibble1 >= 070 )
|
||||
return 0;
|
||||
if ( nibble1 >= 064 )
|
||||
{
|
||||
static const char mt1cmd[4] = { pdp_mtps, pdp_mfpd, pdp_mtpd, pdp_mfps };
|
||||
insn.itype = mt1cmd[nibble1 - 064];
|
||||
loadoper(insn, &insn.Op1, nibble0);
|
||||
break;
|
||||
}
|
||||
if ( nibble1 >= 050 )
|
||||
{
|
||||
insn.bytecmd = 1;
|
||||
oneoper:
|
||||
loadoper(insn, &insn.Op1, nibble0);
|
||||
insn.itype = onecmd[nibble1 - 050];
|
||||
break;
|
||||
}
|
||||
if ( nibble1 >= 040 )
|
||||
{
|
||||
insn.Op1.type = o_number; // EMT/TRAP
|
||||
insn.Op1.value = code & 0377;
|
||||
insn.itype = (nibble1 >= 044) ? pdp_trap : pdp_emt;
|
||||
break;
|
||||
}
|
||||
insn.itype = cc2com[nibble1 >> 2];
|
||||
condoper:
|
||||
insn.Op1.type = o_near;
|
||||
insn.Op1.phrase = 0;
|
||||
insn.Op1.addr16 = (ushort)(insn.ip + insn.size + (2*(short)((char)code)));
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if ( nibble1 >= 070 )
|
||||
return 0;
|
||||
if ( nibble1 > 064 )
|
||||
{
|
||||
static const char mt2cmd[3] = { pdp_mfpi, pdp_mtpi, pdp_sxt };
|
||||
insn.itype = mt2cmd[nibble1 - 065];
|
||||
loadoper(insn, &insn.Op1, nibble0);
|
||||
break;
|
||||
}
|
||||
if ( nibble1 == 064 )
|
||||
{
|
||||
insn.itype = pdp_mark;
|
||||
insn.Op1.type = o_number;
|
||||
insn.Op1.value = nibble0;
|
||||
break;
|
||||
}
|
||||
if ( nibble1 >= 050 )
|
||||
goto oneoper;
|
||||
if ( nibble1 >= 040 )
|
||||
{
|
||||
if ( (nibble1 & 7) == 7 )
|
||||
{
|
||||
insn.itype = pdp_call;
|
||||
jmpoper(insn, &insn.Op1, nibble0);
|
||||
}
|
||||
else
|
||||
{
|
||||
insn.itype = pdp_jsr;
|
||||
insn.Op1.type = o_reg;
|
||||
insn.Op1.reg = nibble1 & 7;
|
||||
jmpoper(insn, &insn.Op2, nibble0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
switch ( nibble1 )
|
||||
{
|
||||
case 3:
|
||||
insn.itype = pdp_swab;
|
||||
loadoper(insn, &insn.Op1, nibble0);
|
||||
break;
|
||||
case 1:
|
||||
insn.itype = pdp_jmp;
|
||||
jmpoper(insn, &insn.Op1, nibble0);
|
||||
break;
|
||||
case 2:
|
||||
if ( nibble0 == 7 )
|
||||
{
|
||||
insn.itype = pdp_return;
|
||||
break;
|
||||
}
|
||||
if ( nibble0 < 7 )
|
||||
{
|
||||
insn.itype = pdp_rts;
|
||||
insn.Op1.type = o_reg;
|
||||
insn.Op1.reg = nibble0;
|
||||
break;
|
||||
}
|
||||
if ( nibble0 < 030 )
|
||||
return 0;
|
||||
if ( nibble0 < 040 )
|
||||
{
|
||||
insn.itype = pdp_spl;
|
||||
insn.Op1.value = nibble0 & 7;
|
||||
insn.Op1.type = o_number;
|
||||
break;
|
||||
}
|
||||
switch ( nibble0 & 037 )
|
||||
{
|
||||
case 000: insn.itype = pdp_nop; break;
|
||||
case 001: insn.itype = pdp_clc; break;
|
||||
case 002: insn.itype = pdp_clv; break;
|
||||
case 004: insn.itype = pdp_clz; break;
|
||||
case 010: insn.itype = pdp_cln; break;
|
||||
case 017: insn.itype = pdp_ccc; break;
|
||||
case 021: insn.itype = pdp_sec; break;
|
||||
case 022: insn.itype = pdp_sev; break;
|
||||
case 024: insn.itype = pdp_sez; break;
|
||||
case 030: insn.itype = pdp_sen; break;
|
||||
case 037: insn.itype = pdp_scc; break;
|
||||
default:
|
||||
insn.itype = pdp_compcc;
|
||||
insn.Op1.phrase = nibble0 & 037;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
{
|
||||
static const char misc0[16] =
|
||||
{
|
||||
pdp_halt, pdp_wait, pdp_rti, pdp_bpt,
|
||||
pdp_iot, pdp_reset, pdp_rtt, pdp_mfpt
|
||||
};
|
||||
if ( nibble0 > 7 )
|
||||
return 0;
|
||||
insn.itype = misc0[nibble0];
|
||||
break;
|
||||
}
|
||||
default: // >=4
|
||||
{
|
||||
static const char lcc2com[7] =
|
||||
{
|
||||
pdp_br, pdp_bne, pdp_beq, pdp_bge,
|
||||
pdp_blt, pdp_bgt, pdp_ble
|
||||
};
|
||||
insn.itype = lcc2com[(nibble1 >> 2) - 1];
|
||||
goto condoper;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ( insn.bytecmd )
|
||||
{
|
||||
if ( insn.Op1.type == o_mem && insn.Op1.phrase != 077
|
||||
|| insn.Op1.type == o_displ && (insn.Op1.phrase & 070) == 060 )
|
||||
{
|
||||
insn.Op1.dtype = dt_byte;
|
||||
}
|
||||
if ( insn.Op2.type == o_mem && insn.Op2.phrase != 077
|
||||
|| insn.Op2.type == o_displ && (insn.Op2.phrase & 070) == 060 )
|
||||
{
|
||||
insn.Op2.dtype = dt_byte;
|
||||
}
|
||||
}
|
||||
|
||||
if ( insn.Op1.type == o_imm && insn.Op1.ill_imm )
|
||||
insn.size -= 2;
|
||||
if ( insn.Op2.type == o_imm && insn.Op2.ill_imm )
|
||||
insn.size -= 2;
|
||||
|
||||
return int(insn.size);
|
||||
}
|
||||
Reference in New Issue
Block a user