update to ida 7.6, add builds

This commit is contained in:
2021-10-31 21:20:46 +02:00
parent e0e0f2be99
commit b1809fe2d9
1408 changed files with 279193 additions and 302468 deletions

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

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

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

View 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);

View 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

View 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

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

View 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

View 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

View 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[] = { &macro11, 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,
};