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);
|
||||
}
|
||||
232
idasdk76/module/pdp11/emu.cpp
Normal file
232
idasdk76/module/pdp11/emu.cpp
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void pdp11_t::loadR0data(const insn_t &insn, const op_t *x, int sme)
|
||||
{
|
||||
if ( insn.Op2.type == o_void )
|
||||
{
|
||||
if ( insn.itype != pdp_clr )
|
||||
goto undefdat;
|
||||
if ( sme )
|
||||
{
|
||||
if ( !insn.bytecmd )
|
||||
goto undefdat;
|
||||
emuR0data.b[1] = 0;
|
||||
return;
|
||||
}
|
||||
if ( insn.bytecmd )
|
||||
emuR0data.b[0] = 0;
|
||||
else
|
||||
emuR0data.w = 0;
|
||||
return;
|
||||
}
|
||||
if ( x != &insn.Op2 )
|
||||
return;
|
||||
if ( insn.Op1.type == o_imm )
|
||||
{
|
||||
if ( insn.itype == pdp_mov )
|
||||
{
|
||||
if ( !insn.bytecmd )
|
||||
{
|
||||
if ( sme )
|
||||
goto undefdat;
|
||||
emuR0data.w = (ushort)insn.Op1.value;
|
||||
return;
|
||||
}
|
||||
if ( !sme )
|
||||
emuR0data.b[0] = (uchar)insn.Op1.value;
|
||||
else
|
||||
emuR0data.b[1] = (uchar)insn.Op1.value;
|
||||
return;
|
||||
}
|
||||
if ( !insn.bytecmd )
|
||||
goto undefdat;
|
||||
undefbyt:
|
||||
if ( !sme )
|
||||
emuR0data.b[0] = 0xFF;
|
||||
else
|
||||
emuR0data.b[1] = 0xFF;
|
||||
return;
|
||||
}
|
||||
if ( insn.bytecmd )
|
||||
goto undefbyt;
|
||||
undefdat:
|
||||
emuR0data.w = 0xFFFF;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void pdp11_t::handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload)
|
||||
{
|
||||
ea_t jmpa;
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_near: // Jcc/ [jmp/call 37/67]
|
||||
case o_mem: // 37/67/77
|
||||
case o_far:
|
||||
jmpa = x.type == o_far
|
||||
? to_ea(x.segval, x.addr16)
|
||||
: map_code_ea(insn, x.addr16, x.n);
|
||||
if ( x.phrase == 0 )
|
||||
{
|
||||
insn.add_cref(jmpa, x.offb, fl_JN); // Jcc
|
||||
break;
|
||||
}
|
||||
extxref:
|
||||
if ( (x.phrase & 070) == 070 )
|
||||
goto xrefset;
|
||||
if ( insn.itype == pdp_jmp )
|
||||
insn.add_cref(jmpa, x.offb, fl_JF);
|
||||
else if ( insn.itype == pdp_jsr || insn.itype == pdp_call )
|
||||
{
|
||||
insn.add_cref(jmpa, x.offb, fl_CF);
|
||||
if ( !func_does_return(jmpa) )
|
||||
flow = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
xrefset:
|
||||
insn.create_op_data(jmpa, x);
|
||||
insn.add_dref(jmpa, x.offb, isload ? dr_R : dr_W);
|
||||
}
|
||||
break;
|
||||
case o_displ: // 6x/7x (!67/!77)
|
||||
set_immd(insn.ea);
|
||||
if ( !isload && x.phrase == (060 + rR0) && x.addr16 <= 1 )
|
||||
loadR0data(insn, &x, x.addr16);
|
||||
if ( !is_forced
|
||||
&& is_off(get_flags(insn.ea), x.n)
|
||||
&& (jmpa = get_offbase(insn.ea, x.n)) != BADADDR )
|
||||
{
|
||||
jmpa += x.addr16;
|
||||
goto extxref;
|
||||
}
|
||||
break;
|
||||
case o_imm: // 27
|
||||
if ( !x.ill_imm )
|
||||
{
|
||||
set_immd(insn.ea);
|
||||
if ( op_adds_xrefs(get_flags(insn.ea), x.n) )
|
||||
insn.add_off_drefs(x, dr_O, OOF_SIGNED);
|
||||
}
|
||||
break;
|
||||
case o_number: // EMT/TRAP/MARK/SPL
|
||||
if ( insn.itype == pdp_emt && get_cmt(NULL, insn.ea, false) <= 0 )
|
||||
{
|
||||
insn_t tmp = insn;
|
||||
op_t &tmpx = tmp.ops[x.n];
|
||||
if ( tmpx.value >= 0374 && tmpx.value <= 0375 )
|
||||
{
|
||||
tmp.Op2.value = (tmpx.value == 0375) ? emuR0data.b[1] : (emuR0 >> 8);
|
||||
tmp.Op2.type = o_imm;
|
||||
}
|
||||
qstring qbuf;
|
||||
if ( get_predef_insn_cmt(&qbuf, tmp) > 0 )
|
||||
set_cmt(tmp.ea, qbuf.c_str(), false);
|
||||
}
|
||||
break;
|
||||
case o_reg: // 0
|
||||
if ( x.reg == rR0 )
|
||||
{
|
||||
if ( insn.Op2.type == o_void ) // one operand insn
|
||||
{
|
||||
if ( insn.itype != pdp_clr )
|
||||
goto undefall;
|
||||
if ( insn.bytecmd )
|
||||
emuR0 &= 0xFF00;
|
||||
else
|
||||
emuR0 = 0;
|
||||
goto undefdata;
|
||||
}
|
||||
if ( &x == &insn.Op2 )
|
||||
{
|
||||
if ( insn.itype != pdp_mov )
|
||||
{
|
||||
if ( insn.bytecmd )
|
||||
{
|
||||
emuR0 |= 0xFF;
|
||||
goto undefdata;
|
||||
}
|
||||
goto undefall;
|
||||
}
|
||||
if ( insn.bytecmd )
|
||||
goto undefall;
|
||||
if ( insn.Op1.type == o_imm )
|
||||
{
|
||||
if ( (emuR0 = (ushort)insn.Op1.value) & 1 )
|
||||
goto undefdata;
|
||||
emuR0data.w = get_word(to_ea(insn.cs, emuR0));
|
||||
}
|
||||
else
|
||||
{
|
||||
undefall:
|
||||
emuR0 = 0xFFFF;
|
||||
undefdata:
|
||||
emuR0data.w = 0xFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case o_phrase: // 1x/2x/3x/4x/5x (!27/!37)
|
||||
if ( (x.phrase & 7) == rR0 )
|
||||
{
|
||||
if ( !isload && x.phrase == (010 + rR0) )
|
||||
loadR0data(insn, &x, 0);
|
||||
else if ( insn.Op2.type == o_void || &x == &insn.Op2 )
|
||||
goto undefall;
|
||||
}
|
||||
case o_fpreg: // FPP
|
||||
break;
|
||||
default:
|
||||
warning("%" FMT_EA "o (%s): bad optype %d", insn.ip, insn.get_canon_mnem(ph), x.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int pdp11_t::emu(const insn_t &insn)
|
||||
{
|
||||
bool flag1 = is_forced_operand(insn.ea, 0);
|
||||
bool flag2 = is_forced_operand(insn.ea, 1);
|
||||
|
||||
uint32 Feature = insn.get_canon_feature(ph);
|
||||
flow = (Feature & CF_STOP) == 0;
|
||||
|
||||
if ( Feature & CF_USE1 ) handle_operand(insn, insn.Op1, flag1, true);
|
||||
if ( Feature & CF_USE2 ) handle_operand(insn, insn.Op2, flag2, true);
|
||||
if ( Feature & CF_JUMP )
|
||||
remember_problem(PR_JUMP, insn.ea);
|
||||
|
||||
if ( Feature & CF_CHG1 ) handle_operand(insn, insn.Op1, flag1, false);
|
||||
if ( Feature & CF_CHG2 ) handle_operand(insn, insn.Op2, flag2, false);
|
||||
|
||||
ea_t newEA = insn.ea + insn.size;
|
||||
if ( insn.itype == pdp_emt && insn.Op1.value == 0376 )
|
||||
{
|
||||
create_byte(newEA, 2);
|
||||
goto prompt2;
|
||||
}
|
||||
else if ( flow && !(insn.itype == pdp_emt && insn.Op1.value == 0350) )
|
||||
{
|
||||
if ( insn.Op1.type == o_imm && insn.Op1.ill_imm )
|
||||
newEA += 2;
|
||||
if ( insn.Op2.type == o_imm && insn.Op2.ill_imm )
|
||||
{
|
||||
prompt2:
|
||||
newEA += 2;
|
||||
}
|
||||
add_cref(insn.ea, newEA, fl_F);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
86
idasdk76/module/pdp11/float.c
Normal file
86
idasdk76/module/pdp11/float.c
Normal file
@@ -0,0 +1,86 @@
|
||||
#include <ieee.h>
|
||||
#define E IEEE_E
|
||||
#define M IEEE_M
|
||||
#define EXONE IEEE_EXONE
|
||||
|
||||
// one of the many possible NaNs,
|
||||
// the one produced by the base converter
|
||||
const fpvalue_t ieee_nan = {{ 0, 0, 0, 0, 0xc000, 0xffff }};
|
||||
|
||||
fpvalue_error_t idaapi realcvt(void *m, fpvalue_t *e, uint16 swt)
|
||||
{
|
||||
eNI x;
|
||||
long exp;
|
||||
uint16 r, msk, *p = (uint16 *)m;
|
||||
|
||||
switch ( swt )
|
||||
{
|
||||
case 1: // in float
|
||||
case 0: // in trunc. float
|
||||
case 3: // in double
|
||||
ecleaz(x);
|
||||
x[0] = ((r = *p) & 0x8000) ? 0xffff : 0; /* fill in our sign */
|
||||
r &= (0377 << 7);
|
||||
if ( r == 0 )
|
||||
{
|
||||
if ( x[0] ) // negative and zero exponent = Undefined -> transformed to NaN
|
||||
{
|
||||
memcpy(e, &ieee_nan, sizeof(fpvalue_t));
|
||||
break;
|
||||
}
|
||||
// complain on dirty zero
|
||||
for ( msk = 0x7fff, r = swt + 1; r; r--, msk = 0xffff )
|
||||
if ( *p++ & msk )
|
||||
return REAL_ERROR_BADDATA; // signed zero accepted
|
||||
}
|
||||
else
|
||||
{
|
||||
x[E] = (r >> 7) + (EXONE - 0201); /* DEC exponent offset */
|
||||
x[M] = (*p++ & 0177) | 0200; /* now do the high order mantissa */
|
||||
if ( swt )
|
||||
memcpy(&x[M+1], p, swt*sizeof(uint16));
|
||||
eshift(x, -8); /* shift our mantissa down 8 bits */
|
||||
}
|
||||
emovo(x, e); // convert to IEEE format
|
||||
break;
|
||||
|
||||
case 011: // out float
|
||||
case 010: // out trunc. float
|
||||
case 013: // out double
|
||||
emovi(*e, x);
|
||||
r = swt & 3;
|
||||
if ( !x[E] )
|
||||
goto clear;
|
||||
if ( x[E] == E_SPECIAL_EXP )
|
||||
{
|
||||
// all of NaN, +/-Inf transformed to "Undefined value"
|
||||
x[0] = 0xffff;
|
||||
x[E] = 0;
|
||||
goto clear;
|
||||
}
|
||||
exp = (long )x[E] - (EXONE - 0201);
|
||||
if ( !emdnorm(x, 0, 0, exp, 56) || x[E] >= 0377 )
|
||||
return REAL_ERROR_RANGE; // overfloat
|
||||
if ( !x[E] )
|
||||
{
|
||||
clear:
|
||||
memset(p, 0, (r + 1)*sizeof(uint16));
|
||||
if ( x[0] )
|
||||
*p = 0x8000; // signed zero accepted
|
||||
}
|
||||
else
|
||||
{
|
||||
*p = (x[0] ? 0100000 : 0) | (x[E] << 7); /* sign & exp */
|
||||
eshift(x, 8);
|
||||
*p++ |= (x[M] & 0177);
|
||||
if ( r != 0 )
|
||||
memcpy(p, &x[M+1], r*sizeof(uint16));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return REAL_ERROR_FORMAT;
|
||||
}
|
||||
|
||||
return REAL_ERROR_OK;
|
||||
}
|
||||
129
idasdk76/module/pdp11/ins.cpp
Normal file
129
idasdk76/module/pdp11/ins.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* 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 <ida.hpp>
|
||||
#include <idp.hpp>
|
||||
#include "ins.hpp"
|
||||
|
||||
const instruc_t Instructions[] =
|
||||
{
|
||||
{ "", 0 }, // Unknown Operation
|
||||
{ "halt", CF_STOP }, // Stop CPU
|
||||
{ "wait", 0 }, // Wait Interrupt
|
||||
{ "rti", CF_STOP }, // Interrupt return
|
||||
{ "bpt", CF_CALL }, // Trap to Debugger
|
||||
{ "iot", CF_CALL }, // Trap to 20
|
||||
{ "reset", 0 }, // Reset CPU and device
|
||||
{ "rtt", CF_STOP }, // Interrupt return and ignore Dbf flag
|
||||
{ "mfpt", 0 }, // Load processor type
|
||||
{ "jmp", CF_USE1|CF_STOP }, // Jmp
|
||||
{ "rts", CF_USE1|CF_STOP }, // Return into Subroutine
|
||||
{ "spl", CF_USE1 }, // Set CPU Prioritet (>11-70)
|
||||
{ "nop", 0 }, // Not operation
|
||||
{ "clc", 0 }, // C=0
|
||||
{ "clv", 0 }, // V=0
|
||||
{ "clz", 0 }, // Z=0
|
||||
{ "cln", 0 }, // N=0
|
||||
{ "ccc", 0 }, // C=V=Z=N=0
|
||||
{ "sec", 0 }, // C=1
|
||||
{ "sev", 0 }, // V=1
|
||||
{ "sez", 0 }, // Z=1
|
||||
{ "sen", 0 }, // N=1
|
||||
{ "scc", 0 }, // C=V=Z=N=1
|
||||
{ "swab", CF_USE1|CF_CHG1 }, // Exchange byte
|
||||
{ "br", CF_USE1|CF_STOP }, // Relative Jmp
|
||||
{ "bne", CF_USE1 }, // Jmp if Z=1
|
||||
{ "beq", CF_USE1 }, // Jmp if Z=0
|
||||
{ "bge", CF_USE1 }, // Jmp if N^V=0
|
||||
{ "blt", CF_USE1 }, // Jmp if N^V=1
|
||||
{ "bgt", CF_USE1 }, // Jmp if Z|(N^V)=0
|
||||
{ "ble", CF_USE1 }, // Jmp if Z|(N^V)=1
|
||||
{ "jsr", CF_USE2|CF_CALL|CF_CHG1 }, // Call
|
||||
{ "clr", CF_CHG1 }, // Clear
|
||||
{ "com", CF_USE1|CF_CHG1 }, // Reverse
|
||||
{ "inc", CF_USE1|CF_CHG1 }, // Increment
|
||||
{ "dec", CF_USE1|CF_CHG1 }, // Decrement
|
||||
{ "neg", CF_USE1|CF_CHG1 }, // op = -op
|
||||
{ "adc", CF_USE1|CF_CHG1 }, // Add with Carry
|
||||
{ "sbc", CF_USE1|CF_CHG1 }, // Substract with Carry
|
||||
{ "tst", CF_USE1 }, // Test
|
||||
{ "ror", CF_USE1|CF_CHG1 }, // Cyclic shift right
|
||||
{ "rol", CF_USE1|CF_CHG1 }, // Cyclic shift left
|
||||
{ "asr", CF_USE1|CF_CHG1 }, // Arifmetic shift right
|
||||
{ "asl", CF_USE1|CF_CHG1 }, // Arifmetic shift left
|
||||
{ "mark", CF_USE1 }, // Return and empty stack
|
||||
{ "mfpi", CF_USE1 }, // Load from previous instr. space
|
||||
{ "mtpi", CF_USE1 }, // Store to previous instr. space
|
||||
{ "sxt", CF_CHG1 }, // N=>op
|
||||
{ "mov", CF_USE1|CF_CHG2 }, // Move
|
||||
{ "cmp", CF_USE1|CF_USE2 }, // Compare
|
||||
{ "bit", CF_USE1|CF_USE2 }, // Test bit's
|
||||
{ "bic", CF_USE1|CF_USE2|CF_CHG2 }, // Clear bit's
|
||||
{ "bis", CF_USE1|CF_USE2|CF_CHG2 }, // Set bit's
|
||||
{ "add", CF_USE1|CF_USE2|CF_CHG2 }, // Add
|
||||
{ "sub", CF_USE1|CF_USE2|CF_CHG2 }, // Substract
|
||||
{ "mul", CF_USE1|CF_USE2|CF_CHG2 }, // Multiple
|
||||
{ "div", CF_USE1|CF_USE2|CF_CHG2 }, // Divide
|
||||
{ "ash", CF_USE1|CF_USE2|CF_CHG2 }, // Multistep shift
|
||||
{ "ashc", CF_USE1|CF_USE2|CF_CHG2 }, // Multistep shift 2 reg
|
||||
{ "xor", CF_USE1|CF_USE2|CF_CHG2 }, // Exclusive or
|
||||
{ "fadd", CF_USE1|CF_CHG1 }, // Floating Add
|
||||
{ "fsub", CF_USE1|CF_CHG1 }, // Floating Substract
|
||||
{ "fmul", CF_USE1|CF_CHG1 }, // Floating Multiple
|
||||
{ "fdiv", CF_USE1|CF_CHG1 }, // Floating Divide
|
||||
{ "sob", CF_USE2|CF_CHG1 }, //
|
||||
{ "bpl", CF_USE1 }, // Jmp if N=0
|
||||
{ "bmi", CF_USE1 }, // Jmp if N=1
|
||||
{ "bhi", CF_USE1 }, // Jmp if ( !C)&(!Z )=0
|
||||
{ "blos", CF_USE1 }, // Jmp if C|Z=1
|
||||
{ "bvc", CF_USE1 }, // Jmp if V=0
|
||||
{ "bvs", CF_USE1 }, // Jmp if V=1
|
||||
{ "bcc", CF_USE1 }, // Jmp if C=0
|
||||
{ "bcs", CF_USE1 }, // Jmp if C=1
|
||||
{ "emt", CF_USE1|CF_CALL }, // Trap to system
|
||||
{ "trap", CF_USE1|CF_CALL }, // Trap to user/compiler
|
||||
{ "mtps", CF_USE1 }, // Store PSW
|
||||
{ "mfpd", CF_USE1 }, // Load from previous data space
|
||||
{ "mtpd", CF_USE1 }, // Store to previous data space
|
||||
{ "mfps", CF_USE1 }, // Load PSW
|
||||
{ "cfcc", 0 }, // Copy Cond.Codes into FPS to PSW
|
||||
{ "setf", 0 }, // Set Float
|
||||
{ "seti", 0 }, // Set Integer
|
||||
{ "setd", 0 }, // Set Double
|
||||
{ "setl", 0 }, // Set Long Integer
|
||||
{ "ldfps", CF_CHG1 }, // Load FPS
|
||||
{ "stfps", CF_USE1 }, // Store FPS
|
||||
{ "stst", 0 }, // Load interrupt status
|
||||
{ "clrd", CF_CHG1 }, // Clear
|
||||
{ "tstd", CF_USE1 }, // Test
|
||||
{ "absd", CF_USE1|CF_CHG1 }, // op = mod(op)
|
||||
{ "negd", CF_USE1|CF_CHG1 }, // op = -op
|
||||
{ "muld", CF_USE1|CF_USE2|CF_CHG2 }, // Multiple
|
||||
{ "modd", CF_USE1|CF_USE2|CF_CHG2 }, // Load Int. part
|
||||
{ "addd", CF_USE1|CF_USE2|CF_CHG2 }, // Add
|
||||
{ "ldd", CF_USE1|CF_USE2|CF_CHG2 }, // Load Acc
|
||||
{ "subd", CF_USE1|CF_USE2|CF_CHG2 }, // Substract
|
||||
{ "cmpd", CF_USE1|CF_USE2 }, // Compare
|
||||
{ "std", CF_USE1|CF_USE2|CF_CHG2 }, // Store Acc
|
||||
{ "divd", CF_USE1|CF_USE2|CF_CHG2 }, // Divide
|
||||
{ "stexp", CF_USE1 }, // Store exponent
|
||||
{ "stcdi", CF_USE1|CF_CHG2 }, // Store and convert
|
||||
{ "stcdf", CF_USE1|CF_CHG2 }, // Store and convert
|
||||
{ "ldexp", CF_CHG1 }, // Load exponent
|
||||
{ "ldcid", CF_USE2|CF_CHG1 }, // Load and convert
|
||||
{ "ldcfd", CF_USE2|CF_CHG1 }, // Load and convert
|
||||
{ "call", CF_USE1|CF_CALL }, // Jsr PC,
|
||||
{ "return", CF_STOP }, // Rts PC
|
||||
{ ".word", 0 }, // Complex Condition Codes
|
||||
};
|
||||
|
||||
CASSERT(qnumber(Instructions) == pdp_last);
|
||||
134
idasdk76/module/pdp11/ins.hpp
Normal file
134
idasdk76/module/pdp11/ins.hpp
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA)
|
||||
* Copyright (c) 1990-2021 Hex-Rays
|
||||
* PDP11 module.
|
||||
* Copyright (c) 1995-2006 by Iouri Kharon.
|
||||
* E-mail: yjh@styx.cabel.net
|
||||
*
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __INSTRS_HPP
|
||||
#define __INSTRS_HPP
|
||||
|
||||
extern const instruc_t Instructions[];
|
||||
|
||||
enum nameNum ENUM_SIZE(uint16)
|
||||
{
|
||||
pdp_null = 0, // Unknown Operation
|
||||
|
||||
pdp_halt, // Stop CPU
|
||||
pdp_wait, // Wait interrupt
|
||||
pdp_rti, // Interrupt return
|
||||
pdp_bpt, // Trap to Debbuger
|
||||
pdp_iot, // Trap to 20 (i/o)
|
||||
pdp_reset, // Reset CPU and device
|
||||
pdp_rtt, // Interrupt return and ignore dbg-flag
|
||||
pdp_mfpt, // Load Processor Type (* hi model)
|
||||
pdp_jmp, // Absolute jmp
|
||||
pdp_rts, // Return into subroutine
|
||||
pdp_spl, // Set Prior.
|
||||
pdp_nop, // Not operation
|
||||
pdp_clc, // Clear C bit in PSW
|
||||
pdp_clv, // Clear V bit in PSW
|
||||
pdp_clz, // Clear Z bit in PSW
|
||||
pdp_cln, // Clear N bit in PSW
|
||||
pdp_ccc, // Clear All Condition bits in PSW
|
||||
pdp_sec, // Set C bit in PSW
|
||||
pdp_sev, // Set V bit in PSW
|
||||
pdp_sez, // Set Z bit in PSW
|
||||
pdp_sen, // Set N bit in PSW
|
||||
pdp_scc, // Set All Condition bits bit in PSW
|
||||
pdp_swab, // Exchange byte in word
|
||||
pdp_br, // Relative jmp
|
||||
pdp_bne, // Jump if Z=0
|
||||
pdp_beq, // Jump if Z=1
|
||||
pdp_bge, // Jump if N^V=0
|
||||
pdp_blt, // Jump if N^V=1
|
||||
pdp_bgt, // Jump if Z|(N^V)=0
|
||||
pdp_ble, // Jump if Z|(N^V)=1
|
||||
pdp_jsr, // Call procedure
|
||||
pdp_clr, // Clear operand
|
||||
pdp_com, // Inverse operand
|
||||
pdp_inc, // Increment operand
|
||||
pdp_dec, // Decrement operand
|
||||
pdp_neg, // op = -op
|
||||
pdp_adc, // Add with Carry
|
||||
pdp_sbc, // Substract with Carry
|
||||
pdp_tst, // Test operand
|
||||
pdp_ror, // Cyclic shift rignt
|
||||
pdp_rol, // Cyclic shift left
|
||||
pdp_asr, // Arifmetic shift rignt
|
||||
pdp_asl, // Arifmetic shift left
|
||||
pdp_mark, // Return and empty stack
|
||||
pdp_mfpi, // Load from previous instruction space (*hi model)
|
||||
pdp_mtpi, // Store to previous instruction space (*hi model)
|
||||
pdp_sxt, // N=>op
|
||||
pdp_mov, // Move operand
|
||||
pdp_cmp, // Compare operands
|
||||
pdp_bit, // Check Bit's
|
||||
pdp_bic, // Clear Bit's
|
||||
pdp_bis, // Set Bit's
|
||||
pdp_add, // Add operands
|
||||
pdp_sub, // Substract operands
|
||||
pdp_mul, // Multiple Reg (*eis)
|
||||
pdp_div, // Divide Reg (*eis)
|
||||
pdp_ash, // Multistep shift (*eis)
|
||||
pdp_ashc, // Multistep shift 2 reg (*eis)
|
||||
pdp_xor, // Exclusive or (*eis)
|
||||
pdp_fadd, // Floating Add (*fis)
|
||||
pdp_fsub, // Floating Subtract (*fis)
|
||||
pdp_fmul, // Floating Multiple (*fis)
|
||||
pdp_fdiv, // Floating Divide (*fis)
|
||||
pdp_sob, //
|
||||
pdp_bpl, // Jump if N=0
|
||||
pdp_bmi, // Jump if N=1
|
||||
pdp_bhi, // Jump if (!C)&(!Z)=0
|
||||
pdp_blos, // Jump if C|Z=1
|
||||
pdp_bvc, // Jump if V=0
|
||||
pdp_bvs, // Jump if V=1
|
||||
pdp_bcc, // Jump if C=0
|
||||
pdp_bcs, // Jump if C=1
|
||||
pdp_emt, // Trap to System
|
||||
pdp_trap, // Trap to user/compiler
|
||||
pdp_mtps, // Store PSW (*lsi11 only)
|
||||
pdp_mfpd, // Load from previous data space (*hi model)
|
||||
pdp_mtpd, // Store to previous data space (*hi model)
|
||||
pdp_mfps, // Load PSW (*lsi11 only)
|
||||
// FPU instruction
|
||||
pdp_cfcc, // Copy cond.codes into FPS to PSW
|
||||
pdp_setf, // Set Float
|
||||
pdp_seti, // Set Integer
|
||||
pdp_setd, // Set Double
|
||||
pdp_setl, // Set Long Integer
|
||||
pdp_ldfps, // Load FPS
|
||||
pdp_stfps, // Store FPS
|
||||
pdp_stst, // Load interrupt status
|
||||
pdp_clrd, // Clear
|
||||
pdp_tstd, // Test
|
||||
pdp_absd, // op = mod(op)
|
||||
pdp_negd, // op = -op
|
||||
pdp_muld, // Multiple
|
||||
pdp_modd, // Get int. part
|
||||
pdp_addd, // Add
|
||||
pdp_ldd, // Load in Acc
|
||||
pdp_subd, // Substract
|
||||
pdp_cmpd, // Compare
|
||||
pdp_std, // Store into Acc
|
||||
pdp_divd, // Divide
|
||||
pdp_stexp, // Store exponent
|
||||
pdp_stcdi, // Store and convert double/float to integer/long
|
||||
pdp_stcdf, // Store and convert double/float to float/double
|
||||
pdp_ldexp, // Load exponent
|
||||
pdp_ldcif, // Load and convert integer/long to double/float
|
||||
pdp_ldcfd, // Load and convert float/double to double/float
|
||||
pdp_call, // Jsr PC,
|
||||
pdp_return, // RTS PC
|
||||
pdp_compcc, // Complex Condition Codes
|
||||
|
||||
pdp_last
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
47
idasdk76/module/pdp11/makefile
Normal file
47
idasdk76/module/pdp11/makefile
Normal file
@@ -0,0 +1,47 @@
|
||||
PROC=pdp11
|
||||
|
||||
|
||||
include ../module.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.cpp ins.hpp \
|
||||
pdp.hpp pdp_ml.h
|
||||
$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp emu.cpp ins.hpp \
|
||||
pdp.hpp pdp_ml.h
|
||||
$(F)ins$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \
|
||||
$(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \
|
||||
$(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp \
|
||||
$(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ins.cpp ins.hpp
|
||||
$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.hpp out.cpp \
|
||||
pdp.hpp pdp_ml.h
|
||||
$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp float.c ins.hpp \
|
||||
pdp.hpp pdp_ml.h reg.cpp
|
||||
386
idasdk76/module/pdp11/out.cpp
Normal file
386
idasdk76/module/pdp11/out.cpp
Normal file
@@ -0,0 +1,386 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
class out_pdp_t : public outctx_t
|
||||
{
|
||||
out_pdp_t(void) = delete; // not used
|
||||
pdp11_t &pm() { return *static_cast<pdp11_t *>(procmod); }
|
||||
public:
|
||||
void OutReg(int rgnum) { out_register(ph.reg_names[rgnum]); }
|
||||
bool out_operand(const op_t &x);
|
||||
void out_insn(void);
|
||||
void out_proc_mnem(void);
|
||||
};
|
||||
CASSERT(sizeof(out_pdp_t) == sizeof(outctx_t));
|
||||
|
||||
DECLARE_OUT_FUNCS(out_pdp_t)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool out_pdp_t::out_operand(const op_t &x)
|
||||
{
|
||||
ea_t segadr;
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_void:
|
||||
return 0;
|
||||
case o_reg:
|
||||
OutReg(x.reg);
|
||||
break;
|
||||
case o_fpreg:
|
||||
OutReg(x.reg + 8);
|
||||
break;
|
||||
case o_imm: // 27
|
||||
if ( x.ill_imm )
|
||||
{
|
||||
out_symbol('(');
|
||||
OutReg(rPC);
|
||||
out_symbol(')');
|
||||
out_symbol('+');
|
||||
}
|
||||
else
|
||||
{
|
||||
out_symbol('#');
|
||||
if ( x.dtype == dt_float || x.dtype == dt_double )
|
||||
{
|
||||
char str[MAXSTR];
|
||||
if ( print_fpval(str, sizeof(str), &x.value, 2) )
|
||||
{
|
||||
char *p = str;
|
||||
while ( *p == ' ' )
|
||||
p++;
|
||||
out_symbol('^');
|
||||
out_symbol('F');
|
||||
out_line(p, COLOR_NUMBER);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_long(x.value, 8);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
out_value(x, OOF_SIGNED | OOFW_IMM);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case o_mem: // 37/67/77
|
||||
case o_near: // jcc/ [jmp/call 37/67]
|
||||
case o_far:
|
||||
if ( x.phrase != 0 )
|
||||
{
|
||||
if ( x.phrase == 077 || x.phrase == 037 )
|
||||
out_symbol('@');
|
||||
if ( x.phrase == 037 )
|
||||
out_symbol('#');
|
||||
if ( x.addr16 < pm().ml.asect_top && !is_off(F, x.n) )
|
||||
{
|
||||
out_value(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
segadr = x.type == o_far
|
||||
? to_ea(x.segval, x.addr16)
|
||||
: map_code_ea(insn, x.addr16, x.n);
|
||||
if ( !out_name_expr(x, segadr, x.addr16) )
|
||||
{
|
||||
if ( x.type == o_far || x.addr16 < 0160000 )
|
||||
remember_problem(PR_NONAME, insn.ea);
|
||||
out_value(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_16);
|
||||
}
|
||||
break;
|
||||
case o_number: // EMT/TRAP/MARK/SPL
|
||||
out_value(x, OOF_NUMBER | OOFS_NOSIGN | OOFW_8);
|
||||
break;
|
||||
case o_displ: // 6x/7x (!67/!77)
|
||||
if ( x.phrase >= 070 )
|
||||
out_symbol('@');
|
||||
out_value(x, OOF_ADDR | OOF_SIGNED | OOFW_16);
|
||||
out_symbol('(');
|
||||
goto endregout;
|
||||
case o_phrase: // 1x/2x/3x/4x/5x (!27/!37)
|
||||
switch ( x.phrase >> 3 )
|
||||
{
|
||||
case 1:
|
||||
out_symbol('@');
|
||||
OutReg(x.phrase & 7);
|
||||
break;
|
||||
case 3:
|
||||
out_symbol('@');
|
||||
// fallthrough
|
||||
case 2:
|
||||
out_symbol('(');
|
||||
OutReg(x.phrase & 7);
|
||||
out_symbol(')');
|
||||
out_symbol('+');
|
||||
break;
|
||||
case 5:
|
||||
out_symbol('@');
|
||||
// fallthrough
|
||||
case 4:
|
||||
out_symbol('-');
|
||||
out_symbol('(');
|
||||
endregout:
|
||||
OutReg(x.phrase & 7);
|
||||
out_symbol(')');
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
warning("out: %" FMT_EA "o: bad optype %d", insn.ip, x.type);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_pdp_t::out_proc_mnem(void)
|
||||
{
|
||||
static const char *const postfix[] = { "", "b" };
|
||||
out_mnem(8, postfix[insn.bytecmd]);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_pdp_t::out_insn(void)
|
||||
{
|
||||
out_mnemonic();
|
||||
if ( insn.itype == pdp_compcc )
|
||||
{
|
||||
uint i = 0, code, first = 0;
|
||||
static const uint tabcc[8] =
|
||||
{
|
||||
pdp_clc, pdp_clv, pdp_clz, pdp_cln,
|
||||
pdp_sec, pdp_sev, pdp_sez, pdp_sen
|
||||
};
|
||||
code = insn.Op1.phrase;
|
||||
out_symbol('<');
|
||||
if ( code >= 020 )
|
||||
{
|
||||
if ( (code ^= 020) == 0 )
|
||||
out_line(COLSTR("nop!^O20", SCOLOR_INSN));
|
||||
i = 4;
|
||||
}
|
||||
for ( ; code; i++, code >>= 1 )
|
||||
{
|
||||
if ( code & 1 )
|
||||
{
|
||||
if ( first++ )
|
||||
out_symbol('!');
|
||||
out_line(ph.instruc[tabcc[i]].name, COLOR_INSN);
|
||||
}
|
||||
}
|
||||
out_symbol('>');
|
||||
}
|
||||
|
||||
out_one_operand(0);
|
||||
|
||||
if ( insn.Op2.type != o_void )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
out_one_operand(1);
|
||||
}
|
||||
|
||||
out_immchar_cmts();
|
||||
flush_outbuf();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void idaapi pdp_header(outctx_t &ctx)
|
||||
{
|
||||
ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//lint -esym(1764, ctx) could be made const
|
||||
//lint -esym(818, seg) could be made const
|
||||
void pdp11_t::pdp_segstart(outctx_t &ctx, segment_t *seg)
|
||||
{
|
||||
if ( seg->type == SEG_IMEM )
|
||||
{
|
||||
ctx.flush_buf(COLSTR(".ASECT", SCOLOR_ASMDIR), DEFAULT_INDENT);
|
||||
}
|
||||
else
|
||||
{
|
||||
qstring sname;
|
||||
get_visible_segm_name(&sname, seg);
|
||||
ctx.out_printf(COLSTR(".PSECT %s", SCOLOR_ASMDIR), sname.c_str());
|
||||
if ( seg->ovrname != 0 )
|
||||
{
|
||||
char bseg[MAX_NUMBUF];
|
||||
char breg[MAX_NUMBUF];
|
||||
btoa(bseg, sizeof(bseg), seg->ovrname & 0xFFFF, 10);
|
||||
btoa(breg, sizeof(breg), seg->ovrname >> 16, 10);
|
||||
ctx.out_printf(
|
||||
COLSTR(" %s Overlay Segment %s, Region %s", SCOLOR_AUTOCMT),
|
||||
ash.cmnt, bseg, breg);
|
||||
}
|
||||
ctx.flush_outbuf(0);
|
||||
}
|
||||
|
||||
if ( (inf_get_outflags() & OFLG_GEN_ORG) != 0 )
|
||||
{
|
||||
size_t org = size_t(ctx.insn_ea-get_segm_base(seg));
|
||||
if ( org != 0 && org != ml.asect_top && seg->comorg() )
|
||||
{
|
||||
ctx.out_tagon(COLOR_ASMDIR);
|
||||
ctx.out_line(ash.origin);
|
||||
ctx.out_line(ash.a_equ);
|
||||
if ( seg->type != SEG_IMEM )
|
||||
{
|
||||
ctx.out_line(ash.origin);
|
||||
ctx.out_char('+');
|
||||
}
|
||||
ctx.out_btoa(org);
|
||||
ctx.out_tagoff(COLOR_ASMDIR);
|
||||
ctx.flush_outbuf(DEFAULT_INDENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void pdp11_t::pdp_footer(outctx_t &ctx) const
|
||||
{
|
||||
if ( ash.end != NULL )
|
||||
{
|
||||
ctx.gen_empty_line();
|
||||
ctx.out_line(ash.end, COLOR_ASMDIR);
|
||||
qstring name;
|
||||
if ( get_colored_name(&name, inf_get_start_ea()) > 0 )
|
||||
{
|
||||
size_t i = strlen(ash.end);
|
||||
do
|
||||
ctx.out_char(' ');
|
||||
while ( ++i < 8 );
|
||||
ctx.out_line(name.begin());
|
||||
}
|
||||
ctx.flush_outbuf(DEFAULT_INDENT);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.gen_cmt_line("end of file");
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool pdp11_t::out_equ(outctx_t &ctx, ea_t ea) const
|
||||
{
|
||||
segment_t *s = getseg(ea);
|
||||
char buf[MAXSTR];
|
||||
if ( s != NULL )
|
||||
{
|
||||
if ( s->type != SEG_IMEM && !is_loaded(ea) )
|
||||
{
|
||||
char num[MAX_NUMBUF];
|
||||
btoa(num, sizeof(num), get_item_size(ea));
|
||||
nowarn_qsnprintf(buf, sizeof(buf), ash.a_bss, num);
|
||||
ctx.flush_buf(buf);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void pdp11_t::pdp_data(outctx_t &ctx, bool analyze_only) const
|
||||
{
|
||||
char buf[MAXSTR];
|
||||
ushort v[5];
|
||||
ea_t endea;
|
||||
ushort i, j;
|
||||
|
||||
ea_t ea = ctx.insn_ea;
|
||||
if ( out_equ(ctx, ea) )
|
||||
return;
|
||||
|
||||
i = 0;
|
||||
flags_t F = ctx.F;
|
||||
if ( !is_unknown(F) )
|
||||
{
|
||||
if ( is_word(F) && get_radix(F,0) == 16 )
|
||||
i = 2;
|
||||
else if ( is_dword(F) )
|
||||
i = 4;
|
||||
else if ( is_qword(F) )
|
||||
i = 8;
|
||||
else if ( is_tbyte(F) )
|
||||
i = 10;
|
||||
if ( i == 0 )
|
||||
{
|
||||
ctx.out_data(analyze_only);
|
||||
return;
|
||||
}
|
||||
|
||||
int radix = get_radix(F, 0);
|
||||
endea = get_item_end(ea);
|
||||
for ( ; ea < endea; ea += i )
|
||||
{
|
||||
memset(v, 0, sizeof(v));
|
||||
if ( get_bytes(v, i, ea) != i || r50_to_asc(buf, v, i/2) != 0 )
|
||||
{
|
||||
ctx.out_keyword(".word ");
|
||||
for ( j = 0; j < i/2; j++ )
|
||||
{
|
||||
if ( j )
|
||||
ctx.out_symbol(',');
|
||||
btoa(buf, sizeof(buf), v[j], radix);
|
||||
ctx.out_line(buf, COLOR_NUMBER);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.out_keyword(".rad50 ");
|
||||
ctx.out_tagon(COLOR_CHAR);
|
||||
ctx.out_char('/');
|
||||
ctx.out_line(buf);
|
||||
ctx.out_char('/');
|
||||
ctx.out_tagoff(COLOR_CHAR);
|
||||
}
|
||||
if ( ctx.flush_outbuf() )
|
||||
return; // too many lines
|
||||
}
|
||||
return;
|
||||
}
|
||||
// unknown
|
||||
if ( !is_loaded(ea) )
|
||||
{
|
||||
ctx.flush_buf(COLSTR(".blkb", SCOLOR_KEYWORD));
|
||||
}
|
||||
else
|
||||
{
|
||||
uchar c = get_byte(ea);
|
||||
|
||||
char cbuf[MAX_NUMBUF];
|
||||
btoa(cbuf, sizeof(cbuf), c);
|
||||
ctx.out_printf(COLSTR(".byte ", SCOLOR_KEYWORD)
|
||||
COLSTR("%4s ", SCOLOR_DNUM)
|
||||
COLSTR("%s %c", SCOLOR_AUTOCMT),
|
||||
cbuf,
|
||||
ash.cmnt,
|
||||
c >= ' ' ? c : ' ');
|
||||
if ( !(ea & 1) && (i = get_word(ea)) != 0 )
|
||||
{
|
||||
ctx.out_tagon(COLOR_AUTOCMT);
|
||||
ctx.out_char(' ');
|
||||
b2a32(buf, sizeof(buf), i, 2, 0);
|
||||
ctx.out_line(buf);
|
||||
ctx.out_char(' ');
|
||||
ushort w = i;
|
||||
r50_to_asc(buf, &w, 1);
|
||||
ctx.out_line(buf);
|
||||
ctx.out_tagoff(COLOR_AUTOCMT);
|
||||
}
|
||||
ctx.flush_outbuf();
|
||||
} // undefined
|
||||
}
|
||||
80
idasdk76/module/pdp11/pdp.hpp
Normal file
80
idasdk76/module/pdp11/pdp.hpp
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _PDP_HPP
|
||||
#define _PDP_HPP
|
||||
|
||||
#include "../idaidp.hpp"
|
||||
#include "ins.hpp"
|
||||
#include "pdp_ml.h"
|
||||
//-V::536 octal
|
||||
|
||||
#define UAS_SECT 0x0001 // Segments are named .SECTION
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Redefine temporary names
|
||||
//
|
||||
#define bytecmd auxpref_u8[0]
|
||||
|
||||
#define segval specval_shorts.low
|
||||
#define addr16 addr_shorts.low
|
||||
#define ill_imm specflag1
|
||||
|
||||
#define o_fpreg o_idpspec0
|
||||
#define o_number o_idpspec1
|
||||
//------------------------------------------------------------------------
|
||||
enum pdp_registers
|
||||
{
|
||||
rR0, rR1, rR2, rR3, rR4, rR5, rSP, rPC,
|
||||
rAC0, rAC1, rAC2, rAC3, rAC4, rAC5,
|
||||
rVcs, rVds
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void idaapi pdp_header(outctx_t &ctx);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct pdp11_t : public procmod_t
|
||||
{
|
||||
netnode ovrtrans;
|
||||
pdp_ml_t ml = { uint32(BADADDR), 0, 0, 0 };
|
||||
bool flow = false;
|
||||
ushort emuR0 = 0xFFFF;
|
||||
//lint -e708 'union initialization'
|
||||
union
|
||||
{
|
||||
ushort w;
|
||||
uchar b[2];
|
||||
} emuR0data = { 0xFFFF };
|
||||
|
||||
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
|
||||
|
||||
void jmpoper(insn_t &insn, op_t *Op, uint16 nibble);
|
||||
int ana(insn_t *_insn);
|
||||
|
||||
void pdp_segstart(outctx_t &ctx, segment_t *seg);
|
||||
|
||||
void loadR0data(const insn_t &insn, const op_t *x, int sme);
|
||||
void handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload);
|
||||
int emu(const insn_t &insn);
|
||||
|
||||
void pdp_footer(outctx_t &ctx) const;
|
||||
bool out_equ(outctx_t &ctx, ea_t ea) const;
|
||||
void pdp_data(outctx_t &ctx, bool analyze_only) const;
|
||||
|
||||
void load_from_idb();
|
||||
};
|
||||
|
||||
extern int data_id;
|
||||
#define PROCMOD_NODE_NAME "$ pdp-11 overlay translations"
|
||||
#define PROCMOD_NAME pdp11
|
||||
#endif
|
||||
42
idasdk76/module/pdp11/pdp_ml.h
Normal file
42
idasdk76/module/pdp11/pdp_ml.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef __pdp_ml_h__
|
||||
#define __pdp_ml_h__
|
||||
|
||||
struct pdp_ml_t
|
||||
{
|
||||
uint32 ovrtbl_base;
|
||||
uint16 ovrcallbeg, ovrcallend, asect_top;
|
||||
};
|
||||
|
||||
#define ovrname orgbase // for compatibily with old version
|
||||
// in Segment structure
|
||||
|
||||
enum store_mode_values
|
||||
{
|
||||
n_asect = -1,
|
||||
n_ovrbeg = -2,
|
||||
n_ovrend = -3,
|
||||
n_asciiX = -4,
|
||||
n_ovrbas = -5
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// The following events are supported by the PDP11 module in the ph.notify() function
|
||||
namespace pdp11_module_t
|
||||
{
|
||||
enum event_codes_t
|
||||
{
|
||||
ev_get_ml_ptr = processor_t::ev_loader,
|
||||
};
|
||||
|
||||
inline processor_t::event_t idp_ev(event_codes_t ev)
|
||||
{
|
||||
return processor_t::event_t(ev);
|
||||
}
|
||||
|
||||
inline bool get_ml_ptr(pdp_ml_t **ml, netnode **ml_ovrtrans)
|
||||
{
|
||||
return processor_t::notify(idp_ev(ev_get_ml_ptr), ml, ml_ovrtrans) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
310
idasdk76/module/pdp11/reg.cpp
Normal file
310
idasdk76/module/pdp11/reg.cpp
Normal file
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#define IEEE_SOURCE
|
||||
#include "pdp.hpp"
|
||||
int data_id;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static const char *const RegNames[] =
|
||||
{
|
||||
"R0","R1","R2","R3","R4","R5","SP","PC",
|
||||
"AC0", "AC1", "AC2", "AC3", "AC4", "AC5",
|
||||
"cs","ds"
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
static const char *const array_macro[] =
|
||||
{
|
||||
"",
|
||||
".macro .array of,type,cnt,val",
|
||||
".rept cnt",
|
||||
" type val",
|
||||
".endr",
|
||||
".endm .array",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const asm_t macro11 =
|
||||
{
|
||||
/*AS_UNEQU |*/ AS_COLON | AS_2CHRE | AS_NCHRE | ASH_HEXF5 | ASO_OCTF2 | ASD_DECF2 | AS_NCMAS | AS_ONEDUP | ASB_BINF1 | AS_RELSUP,
|
||||
UAS_SECT,
|
||||
"Macro-11 Assembler",
|
||||
0,
|
||||
array_macro, // header
|
||||
".", // org
|
||||
".END",
|
||||
|
||||
";", // comment string
|
||||
'\\', // string delimiter
|
||||
'\'', // char delimiter
|
||||
"\\\200", // special symbols in char and string constants
|
||||
|
||||
".ascii", // ascii string directive
|
||||
".byte", // byte directive
|
||||
".word", // word directive
|
||||
".long", // double words
|
||||
NULL, // no qwords
|
||||
NULL, // oword (16 bytes)
|
||||
".flt2",
|
||||
".flt4",
|
||||
NULL, // no tbytes
|
||||
NULL, // no packreal
|
||||
".array of #hs cnt=#d val=#v", // #h - header(.byte,.word)
|
||||
// #d - size of array
|
||||
// #v - value of array elements
|
||||
".blkb %s", // uninited data (reserve space)
|
||||
"=",
|
||||
NULL, // seg prefix
|
||||
".", // a_curip
|
||||
NULL, // func_header
|
||||
NULL, // func_footer
|
||||
".globl", // public
|
||||
".weak", // weak
|
||||
".globl", // extrn
|
||||
NULL, // comm
|
||||
NULL, // get_type_name
|
||||
NULL, // align
|
||||
'<', '>', // lbrace, rbrace
|
||||
NULL, // mod
|
||||
"&", // and
|
||||
"|", // or
|
||||
"^", // xor
|
||||
"!", // not
|
||||
NULL, // shl
|
||||
NULL, // shr
|
||||
NULL, // sizeof
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// floating point conversion
|
||||
#include "float.c"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void pdp11_t::load_from_idb()
|
||||
{
|
||||
ml.asect_top = (ushort)ovrtrans.altval(n_asect);
|
||||
ml.ovrcallbeg = (ushort)ovrtrans.altval(n_ovrbeg);
|
||||
ml.ovrcallend = (ushort)ovrtrans.altval(n_ovrend);
|
||||
ml.ovrtbl_base = (uint32)ovrtrans.altval(n_ovrbas);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// This old-style callback only returns the processor module object.
|
||||
static ssize_t idaapi notify(void *, int msgid, va_list)
|
||||
{
|
||||
if ( msgid == processor_t::ev_get_procmod )
|
||||
return size_t(SET_MODULE_DATA(pdp11_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ssize_t idaapi pdp11_t::on_event(ssize_t msgid, va_list va)
|
||||
{
|
||||
int retcode = 1;
|
||||
segment_t *sptr;
|
||||
|
||||
switch ( msgid )
|
||||
{
|
||||
case processor_t::ev_creating_segm:
|
||||
sptr = va_arg(va, segment_t *);
|
||||
sptr->defsr[rVds-ph.reg_first_sreg] = find_selector(inf_get_start_cs()); //sptr->sel;
|
||||
break;
|
||||
|
||||
case processor_t::ev_init:
|
||||
ovrtrans.create(PROCMOD_NODE_NAME); // it makes no harm to create it again
|
||||
break;
|
||||
|
||||
case processor_t::ev_term:
|
||||
clr_module_data(data_id);
|
||||
break;
|
||||
|
||||
case processor_t::ev_newprc:
|
||||
break;
|
||||
|
||||
case processor_t::ev_ending_undo:
|
||||
case processor_t::ev_oldfile:
|
||||
load_from_idb();
|
||||
break;
|
||||
|
||||
case pdp11_module_t::ev_get_ml_ptr:
|
||||
{
|
||||
pdp_ml_t **p_ml = va_arg(va, pdp_ml_t **);
|
||||
netnode **p_mn = va_arg(va, netnode **);
|
||||
if ( p_ml != NULL && p_mn != NULL )
|
||||
{
|
||||
*p_ml = &ml;
|
||||
*p_mn = &ovrtrans;
|
||||
retcode = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_out_mnem:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
out_mnem(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_header:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
pdp_header(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_footer:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
pdp_footer(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_segstart:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
segment_t *seg = va_arg(va, segment_t *);
|
||||
pdp_segstart(*ctx, seg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_ana_insn:
|
||||
{
|
||||
insn_t *out = va_arg(va, insn_t *);
|
||||
return ana(out);
|
||||
}
|
||||
|
||||
case processor_t::ev_emu_insn:
|
||||
{
|
||||
const insn_t *insn = va_arg(va, const insn_t *);
|
||||
return emu(*insn) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_insn:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
out_insn(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_operand:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
const op_t *op = va_arg(va, const op_t *);
|
||||
return out_opnd(*ctx, *op) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_data:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
bool analyze_only = va_argi(va, bool);
|
||||
pdp_data(*ctx, analyze_only);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_realcvt:
|
||||
{
|
||||
void *m = va_arg(va, void *);
|
||||
fpvalue_t *e = va_arg(va, fpvalue_t *);
|
||||
uint16 swt = va_argi(va, uint16);
|
||||
fpvalue_error_t code = realcvt(m, e, swt);
|
||||
return code == REAL_ERROR_OK ? 1 : code;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
retcode = 0;
|
||||
break;
|
||||
}
|
||||
return retcode;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
static const asm_t *const asms[] = { ¯o11, NULL };
|
||||
|
||||
#define FAMILY "DEC series:"
|
||||
static const char *const shnames[] = { "PDP11", NULL };
|
||||
static const char *const lnames[] = { FAMILY"DEC PDP-11", NULL };
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const uchar retcode_0[] = { 0200, 0000 };
|
||||
static const uchar retcode_1[] = { 0201, 0000 };
|
||||
static const uchar retcode_2[] = { 0202, 0000 };
|
||||
static const uchar retcode_3[] = { 0203, 0000 };
|
||||
static const uchar retcode_4[] = { 0204, 0000 };
|
||||
static const uchar retcode_5[] = { 0205, 0000 };
|
||||
static const uchar retcode_6[] = { 0206, 0000 };
|
||||
static const uchar retcode_7[] = { 0207, 0000 };
|
||||
static const uchar retcode_8[] = { 0002, 0000 };
|
||||
static const uchar retcode_9[] = { 0006, 0000 };
|
||||
|
||||
static const bytes_t retcodes[] =
|
||||
{
|
||||
{ sizeof(retcode_0), retcode_0 },
|
||||
{ sizeof(retcode_1), retcode_1 },
|
||||
{ sizeof(retcode_2), retcode_2 },
|
||||
{ sizeof(retcode_3), retcode_3 },
|
||||
{ sizeof(retcode_4), retcode_4 },
|
||||
{ sizeof(retcode_5), retcode_5 },
|
||||
{ sizeof(retcode_6), retcode_6 },
|
||||
{ sizeof(retcode_7), retcode_7 },
|
||||
{ sizeof(retcode_8), retcode_8 },
|
||||
{ sizeof(retcode_9), retcode_9 },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Processor Definition
|
||||
//-----------------------------------------------------------------------
|
||||
processor_t LPH =
|
||||
{
|
||||
IDP_INTERFACE_VERSION, // version
|
||||
PLFM_PDP, // id
|
||||
// flag
|
||||
PR_WORD_INS
|
||||
| PRN_OCT
|
||||
| PR_SEGTRANS,
|
||||
// flag2
|
||||
PR2_REALCVT // the module has 'realcvt' event implementation
|
||||
| PR2_IDP_OPTS, // the module has processor-specific configuration options
|
||||
8, // 8 bits in a byte for code segments
|
||||
8, // 8 bits in a byte for other segments
|
||||
|
||||
shnames,
|
||||
lnames,
|
||||
|
||||
asms,
|
||||
|
||||
notify,
|
||||
|
||||
RegNames, // Register names
|
||||
qnumber(RegNames), // Number of registers
|
||||
|
||||
rVcs,rVds,
|
||||
0, // size of a segment register
|
||||
rVcs,rVds,
|
||||
|
||||
NULL, // No known code start sequences
|
||||
retcodes,
|
||||
|
||||
0,pdp_last,
|
||||
Instructions, // instruc
|
||||
0, // size of tbyte
|
||||
{ 4,7,19,0 },
|
||||
|
||||
// Icode of return instruction. It is ok to give any of possible return
|
||||
// instructions
|
||||
pdp_return,
|
||||
};
|
||||
Reference in New Issue
Block a user