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

233 lines
5.9 KiB
C++

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