示例#1
0
/*
header: frame.hpp
#<pydoc>
def add_stkvar3(op, v, flags):
    """
    Automatically add stack variable if doesn't exist
    Processor modules should use ua_stkvar2()
    @param op: reference to instruction operand
    @param v: immediate value in the operand (usually op.addr)
    @param flags: combination of STKVAR_... constants
    @return: Boolean
    """
    pass
#</pydoc>
*/
bool py_add_stkvar3(PyObject *py_op, PyObject *py_v, int flags)
{
  PYW_GIL_CHECK_LOCKED_SCOPE();
  op_t *op = op_t_get_clink(py_op);
  uint64 v;
  return ( op == NULL || !PyW_GetNumber(py_v, &v) || !add_stkvar3(*op, sval_t(v), flags)) ? false : true;
}
示例#2
0
/*
#<pydoc>
def get_stkvar(op, v):
    """
    Get pointer to stack variable
    @param op: reference to instruction operand
    @param v: immediate value in the operand (usually op.addr)
    @return:
        - None on failure
        - tuple(member_t, actval)
          where actval: actual value used to fetch stack variable
    """
    pass
#</pydoc>
*/
PyObject *py_get_stkvar(PyObject *py_op, PyObject *py_v)
{
  PYW_GIL_CHECK_LOCKED_SCOPE();
  op_t *op = op_t_get_clink(py_op);
  uint64 v;
  if ( op == NULL || !PyW_GetNumber(py_v, &v) )
    Py_RETURN_NONE;

  sval_t actval;
  member_t *member = get_stkvar(*op, sval_t(v), &actval);
  if ( member == NULL )
    Py_RETURN_NONE;

  return Py_BuildValue("(O" PY_SFMT64 ")",
    SWIG_NewPointerObj(SWIG_as_voidptr(member), SWIGTYPE_p_member_t, 0),
    pyl_t(actval));
}
示例#3
0
文件: ana.cpp 项目: nealey/vera
//------------------------------------------------------------------------
// Decodes an instruction "w" into cmd structure
bool decode_instruction(uint32 w, insn_t &cmd)
{
#define PARSE_L12 (((w & 1) << 11) | (w >> 21))
#define PARSE_R1  (w & 0x1F)
#define PARSE_R2  ((w & 0xF800) >> 11)

  typedef struct
  {
    int itype;
    int flags;
  } itype_flags_t;
  // If an instruction deals with displacement it should
  // initialize this pointer to the operand location.
  // At the end we will transform the operand to o_mem
  // if we know how to resolve its address
  op_t *displ_op = NULL;

  do
  {
    uint32 op;

    //
    // Format I
    //
    op = (w & 0x7E0) >> 5; // Take bit5->bit10
    if ( op <= 0xF )
    {
      static const int inst_1[] =
      {
        /* MOV reg1, reg2 */ NEC850_MOV,             /* NOT reg1, reg2 */ NEC850_NOT,
        /* DIVH  reg1, reg2 */ NEC850_DIVH,          /* JMP [reg1] */ NEC850_JMP,
        /* SATSUBR reg1, reg2 */ NEC850_SATSUBR,     /* SATSUB reg1, reg2 */ NEC850_SATSUB,
        /* SATADD reg1, reg2 */ NEC850_SATADD,       /* MULH reg1, reg2 */ NEC850_MULH,
        /* OR reg1, reg2 */ NEC850_OR,               /* XOR reg1, reg2 */ NEC850_XOR,
        /* AND reg1, reg2 */ NEC850_AND,             /* TST reg1, reg2 */ NEC850_TST,
        /* SUBR reg1, reg2 */ NEC850_SUBR,           /* SUB reg1, reg2 */ NEC850_SUB,
        /* ADD reg1, reg2 */ NEC850_ADD,             /* CMP reg1, reg2 */ NEC850_CMP
      };

      //
      // NOP, Equivalent to MOV R, r (where R=r=0)
      if ( w == 0 )
      {
        cmd.itype    = NEC850_NOP;
        cmd.Op1.type = o_void;
        cmd.Op1.dtyp = dt_void;
        break;
      }

      if ( is_v850e )
      {
        if ( w == 0xF840 )
        {
          cmd.itype = NEC850_DBTRAP;
          break;
        }
      }
      uint16 r1 = PARSE_R1;
      uint16 r2 = PARSE_R2;

      cmd.itype     = inst_1[op];
      cmd.Op1.reg   = r1;
      cmd.Op1.type  = o_reg;
      cmd.Op1.dtyp  = dt_dword;

      if ( is_v850e )
      {
        if ( r2 == 0 )
        {
          if ( cmd.itype == NEC850_DIVH )
          {
            cmd.itype = NEC850_SWITCH;
            break;
          }
          else if ( cmd.itype == NEC850_SATSUBR )
          {
            cmd.itype = NEC850_ZXB;
            break;
          }
          else if ( cmd.itype == NEC850_SATSUB )
          {
            cmd.itype = NEC850_SXB;
            break;
          }
          else if ( cmd.itype == NEC850_SATADD )
          {
            cmd.itype = NEC850_ZXH;
            break;
          }
          else if ( cmd.itype == NEC850_MULH )
          {
            cmd.itype = NEC850_SXH;
            break;
          }
        }
        // case when r2 != 0
        else
        {
          // SLD.BU / SLD.HU
          if ( cmd.itype == NEC850_JMP )
          {
            bool   sld_hu = (w >> 4) & 1;
            uint32 addr = w & 0xF;

            if ( sld_hu )
            {
              cmd.itype       = NEC850_SLD_HU;
              cmd.Op1.dtyp    = dt_word;
              addr          <<= 1;
            }
            else
            {
              cmd.itype       = NEC850_SLD_BU;
              cmd.Op1.dtyp    = dt_byte;
            }

            cmd.Op1.type      = o_displ;
            displ_op          = &cmd.Op1;
            cmd.Op1.reg       = rEP;
            cmd.Op1.addr      = addr;
            cmd.Op1.specflag1 = N850F_USEBRACKETS;

            cmd.Op2.type      = o_reg;
            cmd.Op2.reg       = r2;
            cmd.Op2.dtyp      = dt_dword;

            break;
          }
        }
      }
      if ( cmd.itype == NEC850_JMP && r2 == 0 )
      {
        cmd.Op1.specflag1 = N850F_USEBRACKETS;
      }
      else
      {
        cmd.Op2.reg   = r2;
        cmd.Op2.type  = o_reg;
        cmd.Op2.dtyp  = dt_dword;
      }
      break;
    }
    // Format II
    else if ( op >= 0x10 && op <= 0x17 )
    {
      // flag used for sign extension
      static const itype_flags_t inst_2[] =
      {
        { NEC850_MOV,    1 }, /* MOV imm5, reg2 */
        { NEC850_SATADD, 1},  /* SATADD imm5, reg2 */
        { NEC850_ADD,    1 }, /* ADD imm5, reg2 */
        { NEC850_CMP,    1 }, /* CMP imm5, reg2 */
        { NEC850_SHR,    0 }, /* SHR imm5, reg2 */
        { NEC850_SAR,    0 }, /* SAR imm5, reg2 */
        { NEC850_SHL,    0 }, /* SHL imm5, reg2 */
        { NEC850_MULH,   1 }, /* MULH imm5, reg2 */
      };
      op -= 0x10;

      cmd.itype = inst_2[op].itype;
      uint16 r2 = PARSE_R2;

      if ( is_v850e )
      {
        //
        // CALLT
        //
        if ( r2 == 0 && (cmd.itype == NEC850_SATADD || cmd.itype == NEC850_MOV) )
        {
          cmd.itype     = NEC850_CALLT;
          cmd.Op1.dtyp  = dt_byte;
          cmd.Op1.type  = o_imm;
          cmd.Op1.value = w & 0x3F;
          break;
        }
      }

      sval_t v = PARSE_R1;
      if ( inst_2[op].flags == 1 )
      {
        SIGN_EXTEND(sval_t, v, 5);
        cmd.Op1.specflag1 |= N850F_OUTSIGNED;
      }

      cmd.Op1.type  = o_imm;
      cmd.Op1.value = v;
      cmd.Op1.dtyp  = dt_byte;

      cmd.Op2.type  = o_reg;
      cmd.Op2.reg   = r2;
      cmd.Op2.dtyp  = dt_dword;

      // ADD imm, reg -> reg = reg + imm
      if ( cmd.itype == NEC850_ADD && r2 == rSP)
        cmd.auxpref |= N850F_SP;
      break;
    }
    // Format VI
    else if ( op >= 0x30 && op <= 0x37 )
    {
      static const itype_flags_t inst_6[] =
      {
        { NEC850_ADDI,      1 }, /* ADDI imm16, reg1, reg2 */
        { NEC850_MOVEA,     1 }, /* MOVEA imm16, reg1, reg2 */
        { NEC850_MOVHI,     0 }, /* MOVHI imm16, reg1, reg2 */
        { NEC850_SATSUBI,   1 }, /* SATSUBI imm16, reg1, reg2 */
        { NEC850_ORI,       0 }, /* ORI imm16, reg1, reg2 */
        { NEC850_XORI,      0 }, /* XORI imm16, reg1, reg2 */
        { NEC850_ANDI,      0 }, /* ANDI imm16, reg1, reg2 */
        { NEC850_MULHI,     0 }, /* MULHI  imm16, reg1, reg2 */
      };
      op -= 0x30;
      cmd.itype = inst_6[op].itype;

      uint16 r1     = PARSE_R1;
      uint16 r2     = PARSE_R2;
      uint32 imm    = w >> 16;

      //
      // V850E instructions
      if ( is_v850e && r2 == 0 )
      {
        // MOV imm32, R
        if ( cmd.itype == NEC850_MOVEA )
        {
          imm            |= ua_next_word() << 16;
          cmd.Op1.type    = o_imm;
          cmd.Op1.dtyp    = dt_dword;
          cmd.Op1.value   = imm;
          cmd.itype       = NEC850_MOV;

          cmd.Op2.type   = o_reg;
          cmd.Op2.reg    = r1;
          cmd.Op2.dtyp   = dt_dword;
          break;
        }
        // DISPOSE imm5, list12 (reg1 == 0)
        // DISPOSE imm5, list12, [reg1]
        else if ( cmd.itype == NEC850_SATSUBI || cmd.itype == NEC850_MOVHI )
        {
          uint16 r1 = (w >> 16) & 0x1F;
          uint16 L  = PARSE_L12;

          cmd.auxpref   |= N850F_SP; // SP reference

          cmd.Op1.value  = (w & 0x3E) >> 1;
          cmd.Op1.type   = o_imm;
          cmd.Op1.dtyp   = dt_byte;

          cmd.Op2.value  = L;
          cmd.Op2.type   = o_reglist;
          cmd.Op2.dtyp   = dt_word;

          if ( r1 != 0 )
          {
            cmd.Op3.dtyp = dt_dword;
            cmd.Op3.type = o_reg;
            cmd.Op3.reg  = r1;
            cmd.Op3.specflag1 = N850F_USEBRACKETS;

            cmd.itype = NEC850_DISPOSE_r;
          }
          else
          {
            cmd.itype = NEC850_DISPOSE_r0;
          }
          break;
        }
      }
      bool is_signed     = inst_6[op].flags == 1;
      cmd.Op1.type       = o_imm;
      cmd.Op1.dtyp       = dt_dword;
      cmd.Op1.value      = is_signed ? sval_t(int16(imm)) : imm;
      cmd.Op1.specflag1 |= N850F_OUTSIGNED;

      cmd.Op2.type       = o_reg;
      cmd.Op2.reg        = r1;
      cmd.Op2.dtyp       = dt_dword;

      cmd.Op3.type       = o_reg;
      cmd.Op3.reg        = r2;
      cmd.Op3.dtyp       = dt_dword;

      // (ADDI|MOVEA) imm, sp, sp -> sp = sp + imm
      if ( (cmd.itype == NEC850_ADDI || cmd.itype == NEC850_MOVEA)
        && ((r1 == rSP) && (r2 == rSP)) )
      {
        cmd.auxpref |= N850F_SP;
      }
      break;
    }
示例#4
0
文件: emu.cpp 项目: nealey/vera
//----------------------------------------------------------------------
int idaapi emu(void)
{
    uint32 Feature = cmd.get_canon_feature();
    int flag1 = is_forced_operand(cmd.ea, 0);
    int flag2 = is_forced_operand(cmd.ea, 1);
    int flag3 = is_forced_operand(cmd.ea, 2);

    flow = (Feature & CF_STOP) == 0;

    if ( Feature & CF_USE1 ) process_operand(cmd.Op1, flag1, 1);
    if ( Feature & CF_USE2 ) process_operand(cmd.Op2, flag2, 1);
    if ( Feature & CF_USE3 ) process_operand(cmd.Op3, flag3, 1);

    if ( Feature & CF_CHG1 ) process_operand(cmd.Op1, flag1, 0);
    if ( Feature & CF_CHG2 ) process_operand(cmd.Op2, flag2, 0);
    if ( Feature & CF_CHG3 ) process_operand(cmd.Op3, flag3, 0);

//
//      Check for:
//        - the register bank changes
//        - PCLATH changes
//        - PCL changes
//
    for ( int i=0; i < 3; i++ )
    {
        int reg = 0;
        switch ( i )
        {
        case 0:
            reg = BANK;
            if ( !is_bank() ) continue;
            break;
        case 1:
            reg = PCLATH;
            if ( !is_pclath() ) continue;
            break;
        case 2:
            reg = -1;
            if ( !is_pcl() ) continue;
            break;
        }
        sel_t v = (reg == -1) ? cmd.ip : getSR(cmd.ea, reg);
        if ( cmd.Op2.type == o_reg && cmd.Op2.reg == F )
        {
//      split(reg, v);
        }
        else
        {
            switch ( cmd.itype )
            {
            case PIC_bcf:
            case PIC_bcf3:
            case PIC_bsf:
            case PIC_bsf3:
                if ( ((ptype == PIC12) && (cmd.Op2.value == 5) )  // bank selector
                        || ((ptype == PIC14) && (
                                (reg == BANK && (cmd.Op2.value == 5 || cmd.Op2.value == 6))
                                || (reg == PCLATH && (cmd.Op2.value == 3 || cmd.Op2.value == 4))))
                        || ((ptype == PIC16) && (sval_t(cmd.Op2.value) >= 0 && cmd.Op2.value <= 3)))
                {
                    if ( v == BADSEL ) v = 0;
                    int shift = 0;
                    if ( ptype == PIC14 && reg == BANK ) shift = 5;
                    if ( cmd.itype == PIC_bcf ) v = v & ~(1 << (cmd.Op2.value-shift));
                    else v = v | (1 << (cmd.Op2.value-shift));
                    split(reg, v);
                }
                break;
            case PIC_clrf:
            case PIC_clrf2:
                split(reg, 0);
                break;
            case PIC_swapf:
            case PIC_swapf3:
                split(reg, ((v>>4) & 15) | ((v & 15) << 4));
                break;
            case PIC_movwf:
            case PIC_movwf2:
            case PIC_addlw:
            case PIC_andlw:
            case PIC_iorlw:
            case PIC_sublw:
            case PIC_xorlw:
            {
                insn_t saved = cmd;
                if ( decode_prev_insn(cmd.ea) != BADADDR
                        && ( cmd.itype == PIC_movlw ) )
                {
                    switch ( saved.itype )
                    {
                    case PIC_movwf:
                    case PIC_movwf2:
                        v = cmd.Op1.value;
                        break;
                    case PIC_addlw:
                        v += cmd.Op1.value;
                        break;
                    case PIC_andlw:
                        v &= cmd.Op1.value;
                        break;
                    case PIC_iorlw:
                        v |= cmd.Op1.value;
                        break;
                    case PIC_sublw:
                        v -= cmd.Op1.value;
                        break;
                    case PIC_xorlw:
                        v ^= cmd.Op1.value;
                        break;
                    }
                }
                else
                {
                    v = BADSEL;
                }
                cmd = saved;
            }
            split(reg, v);
            break;
            case PIC_movlw:
                split(reg, cmd.Op2.value);
                break;
            }
        }
    }

// Such as , IDA doesn't seem to convert the following:
// tris 6
// into
// tris PORTB ( or whatever )

    if ( cmd.itype == PIC_tris && !isDefArg0(uFlag) )
        set_offset(cmd.ea, 0, dataseg);

//   movlw value
// followed by a
//   movwf FSR
// should convert value into an offset , because FSR is used as a pointer to
// the INDF (indirect addressing file)

    if ( ptype == PIC12 || ptype == PIC14
            && cmd.itype == PIC_movwf
            && cmd.Op1.type == o_mem
            && (cmd.Op1.addr & 0x7F) == 0x4 )    // FSR
    {
        insn_t saved = cmd;
        if ( decode_prev_insn(cmd.ea) != BADADDR
                && cmd.itype == PIC_movlw )
        {
            set_offset(cmd.ea, 0, dataseg);
        }
        cmd = saved;
    }

// Also - it seems to make sense to me that a
//   movlw value
// followed by a
//   tris PORTn  (or movwf TRISn)
// should convert value into a binary , because the bits indicate whether a
// port is defined for input or output.

    if ( is_load_tris_reg() )
    {
        insn_t saved = cmd;
        if ( decode_prev_insn(cmd.ea) != BADADDR
                && cmd.itype == PIC_movlw )
        {
            op_bin(cmd.ea, 0);
        }
        cmd = saved;
    }

// Move litteral to BSR

    if ( cmd.itype == PIC_movlb1 ) split(BANK, cmd.Op1.value);

//
//      Determine if the next instruction should be executed
//
    if ( !flow ) flow = conditional_insn();
    if ( segtype(cmd.ea) == SEG_XTRN ) flow = 0;
    if ( flow ) ua_add_cref(0,cmd.ea+cmd.size,fl_F);

    return 1;
}