示例#1
0
文件: ana.cpp 项目: nealey/vera
//------------------------------------------------------------------------
// Fetchs an instruction (uses ua_next_xxx()) of a correct size (ready for decoding)
// Returns the size of the instruction
int fetch_instruction(uint32 *w)
{
  uint16 hw = ua_next_word();
  int r = detect_inst_len(hw);
  if ( r == 4 )
    *w = (ua_next_word() << 16) | hw;
  else
    *w = hw;
  return r;
}
示例#2
0
文件: ana.cpp 项目: nealey/vera
//--------------------------------------------------------------------------
inline void aa16(op_t &x, char dtyp)
{
  cmd.auxpref |= aux_disp16;
  x.type = o_mem;
  x.dtyp = dtyp;
  x.addr = ua_next_word();
}
示例#3
0
文件: ana.cpp 项目: nealey/vera
//--------------------------------------------------------------------------
inline void imm16(op_t &x)
{
  cmd.auxpref |= aux_disp16;
  x.type  = o_imm;
  x.dtyp  = dt_word;
  x.value = ua_next_word();
}
示例#4
0
文件: ana.cpp 项目: nealey/vera
//--------------------------------------------------------------------------
inline void ds16(op_t &x, int reg, char dtyp)
{
  cmd.auxpref |= aux_disp16;
  x.type = o_displ;
  x.dtyp = dtyp;
  x.reg  = reg & 7;
  x.addr = ua_next_word();
}
示例#5
0
文件: ana.cpp 项目: nealey/vera
//----------------------------------------------------------------------
static int LoadIndex(void)
{
  register ushort top;

  cmd.Op1.type = o_mem;
//  cmd.Op1.ref = 0;
  cmd.Op1.offb = char(cmd.size);
  cmd.Op1.addr = top = cmd.wid ? ua_next_word() : ua_next_byte();
  if(   ((cmd.Op1.dtyp == dt_qword || cmd.Op1.dtyp == dt_double) && !++top)
     || top >= curSeg.DataSize) {

    if ( !debugmode) return(0 );
    ++cmd.Op1.ref;
  }
  return(1);
}
示例#6
0
//----------------------------------------------------------------------
int idaapi ana(void)
{
  cmd.Op1.dtyp = dt_byte;
  code = ua_next_byte();
  cmd.itype = (is_cmos ? cmos : nmos)[code];
  if ( cmd.itype == M65_null ) return 0;

  switch ( code & 0x1F )
  {
// +08  PHP     PLP     PHA     PLA     DEY     TAY     INY     INX     Implied
// +18  CLC     SEC     CLI     SEI     TYA     CLV     CLD     SED     Implied
// +1a  NOP*    NOP*    NOP*    NOP*    TXS     TSX     NOP*    NOP*    Implied
// +1a  inc     dec     phy     ply     txs     tsx     phx     ply
    case 0x1A:
    case 0x08:
    case 0x18:
      switch ( cmd.itype )
      {
        case M65_inc:
        case M65_dec:
          cmd.Op1.type = o_reg;
          cmd.Op1.reg = rA;
      }
      break;
// +0a  ASL     ROL     LSR     ROR     TXA     TAX     DEX     NOP     Accu/impl
    case 0x0A:
      switch ( cmd.itype )
      {
        case M65_asl:
        case M65_rol:
        case M65_lsr:
        case M65_ror:
          cmd.Op1.type = o_reg;
          cmd.Op1.reg = rA;
      }
      break;
// +00  BRK     JSR     RTI     RTS     NOP*/bra LDY     CPY     CPX     Impl/immed
// +02   t       t       t       t      NOP*t    LDX     NOP*t   NOP*t     ? /immed
// +09  ORA     AND     EOR     ADC     NOP*     LDA     CMP     SBC     Immediate
// +0b  ANC**   ANC**   ASR**   ARR**   ANE**    LXA**   SBX**   SBC*    Immediate
    case 0x00:
    case 0x02:
    case 0x09:
    case 0x0B:
      switch ( cmd.itype ) {
        case M65_jsr:
          cmd.Op1.dtyp = dt_code;
          cmd.Op1.type = o_near;
          cmd.Op1.addr = ua_next_word();
          break;
        case M65_brk:
        case M65_rti:
        case M65_rts:
          break;
        case M65_bra:
          goto M65_RELATIVE;
        default:
          cmd.Op1.type = o_imm;
          cmd.Op1.value = ua_next_byte();
          break;
      }
      break;
// +0c NOP*/tsb BIT     JMP     JMP  () STY     LDY     CPY     CPX     Absolute
// +0d  ORA     AND     EOR     ADC     STA     LDA     CMP     SBC     Absolute
// +0e  ASL     ROL     LSR     ROR     STX     LDX     DEC     INC     Absolute
// +0f  SLO*    RLA*    SRE*    RRA*    SAX*    LAX*    DCP*    ISB*    Absolute
// +0f  bbr0    bbr2    bbr4    bbr6    bbs0    bbs2    bbs4    bbs6    Zero page relative
    case 0x0F:
      if ( is_cmos ) goto ZP_RELATIVE;
    case 0x0C:
    case 0x0D:
    case 0x0E:
M65_ABSOLUTE:
      switch ( cmd.itype )
      {
        case M65_jmp:
          cmd.Op1.dtyp = dt_code;
          cmd.Op1.type = o_near;
          break;
        case M65_jmpi:
          cmd.Op1.dtyp = dt_word;
          cmd.indirect = 1;
          /* no break */
        default:
          cmd.Op1.type = o_mem;
          break;
      }
      cmd.Op1.addr = ua_next_word();
      break;
// +1c NOP*/trb NOP*/bit NOP*   NOP*/jmp SHY**/stz LDY     NOP*    NOP*    Absolute,x
// +1d  ORA      AND     EOR     ADC     STA       LDA     CMP     SBC     Absolute,x
// +1e  ASL      ROL     LSR     ROR     SHX**y)   LDX  y) DEC     INC     Absolute,x
// +1f  SLO*     RLA*    SRE*    RRA*    SHA**y)   LAX* y) DCP     ISB     Absolute,x
// +0f  bbr1     bbr3    bbr5    bbr7    bbs1      bbs3    bbs5    bbs7    Zero page relative
    case 0x1F:
      if ( is_cmos )
      {
ZP_RELATIVE:
        cmd.Op1.type = o_mem;
        cmd.Op1.addr = ua_next_byte();
        cmd.Op2.dtyp = dt_code;
        cmd.Op2.type = o_near;
        char x = ua_next_byte();
        cmd.Op2.addr = cmd.ip + cmd.size + x;
        break;
      }
      /* fall thru */
    case 0x1C:
    case 0x1D:
    case 0x1E:
      cmd.Op1.type = o_displ;
      cmd.Op1.phrase = rX;
      switch ( cmd.itype )
      {
        case M65_stz:
          if ( code == 0x9E ) break;
        case M65_trb:
          goto M65_ABSOLUTE;
        case M65_shx:
        case M65_sha:
        case M65_ldx:
        case M65_lax:
          cmd.Op1.phrase = rY;
          break;
        case M65_jmpi:
          cmd.Op1.phrase = riX;
          break;
      }
      cmd.Op1.addr = ua_next_word();
      break;
// +19  ORA     AND     EOR     ADC     STA     LDA     CMP     SBC     Absolute,y
// +1b  SLO*    RLA*    SRE*    RRA*    SHS**   LAS**   DCP*    ISB*    Absolute,y
    case 0x19:
    case 0x1B:
      cmd.Op1.type = o_displ;
      cmd.Op1.phrase = rY;
      cmd.Op1.addr = ua_next_word();
      break;
// +10  BPL     BMI     BVC     BVS     BCC     BCS     BNE     BEQ     Relative
    case 0x10:
M65_RELATIVE:
      cmd.Op1.dtyp = dt_code;
      cmd.Op1.type = o_near;
      {
        char x = ua_next_byte();
        cmd.Op1.addr = cmd.ip + cmd.size + x;
      }
      break;
// +01  ORA     AND     EOR     ADC     STA     LDA     CMP     SBC     (indir,x)
// +03  SLO*    RLA*    SRE*    RRA*    SAX*    LAX* y) DCP*    ISB*    (indir,x)
    case 0x01:
    case 0x03:
      cmd.Op1.type = o_displ;
      cmd.Op1.phrase = uint16((cmd.itype == M65_lax) ? riY : riX);
      cmd.Op1.addr = ua_next_byte();    // а для LAX?
      break;
// +11  ORA     AND     EOR     ADC     STA     LDA     CMP     SBC     (indir),y
// +13  SLO*    RLA*    SRE*    RRA*    SHA**   LAX*    DCP*    ISB*    (indir),y
    case 0x11:
    case 0x13:
      cmd.Op1.type = o_displ;
      cmd.Op1.phrase = riY;
      cmd.Op1.addr = ua_next_byte();
      break;
// +04 NOP*/tsb BIT     NOP*   NOP*/stz STY     LDY     CPY     CPX     Zeropage
// +05  ORA     AND     EOR     ADC     STA     LDA     CMP     SBC     Zeropage
// +06  ASL     ROL     LSR     ROR     STX     LDX     DEC     INC     Zeropage
// +07  SLO*    RLA*    SRE*    RRA*    SAX*    LAX*    DCP*    ISB*    Zeropage
// +07  rmb0    rmb2    rmb4    rmb6    smb0    smb2    smb4    smb6    Zeropage
    case 0x04:
    case 0x05:
    case 0x06:
    case 0x07:
ZEROPAGE:
      cmd.Op1.type = o_mem;
      cmd.Op1.addr = ua_next_byte();
      break;
// +14 NOP*/trb NOP*/bit NOP*   NOP*/stz STY     LDY     NOP*    NOP*    Zeropage,x
// +15  ORA     AND      EOR     ADC     STA     LDA     CMP     SBC     Zeropage,x
// +16  ASL     ROL      LSR     ROR     STX  y) LDX  y) DEC     INC     Zeropage,x
// +17  SLO*    RLA*     SRE*    RRA*    SAX* y) LAX* y) DCP     ISB     Zeropage,x
// +17  rmb1    rmb3     rmb5    rmb7    smb1    smb3    smb5    smb7    Zeropage
    case 0x17:
      if ( is_cmos ) goto ZEROPAGE;
      /* fall thru */
    case 0x14:
    case 0x15:
    case 0x16:
      cmd.Op1.type = o_displ;
      cmd.Op1.phrase = zX;
      switch ( cmd.itype ) {
        case M65_trb:
          goto ZEROPAGE;
        case M65_stx:
        case M65_sax:
        case M65_ldx:
        case M65_lax:
          cmd.Op1.phrase = zY;
          break;
      }
      cmd.Op1.addr = ua_next_byte();
      break;
// +12  ora     and     eor     adc     sta     lda     cmp     sbc     Zeropage, indirect
    case 0x12:
      cmd.indirect = 1;
      cmd.Op1.type = o_mem;
      cmd.Op1.addr = ua_next_byte();
      break;
    default:
      error("ana: bad code %x",code);
  }
  if ( cmd.itype == M65_nop ) cmd.Op1.type = o_void;
  return cmd.size;
}
示例#7
0
文件: ana.cpp 项目: nealey/vera
// fill the cmd structure according to the addressing mode of the
// current analyzed instruction
static void fill_cmd(m740_addr_mode_t addr, const uchar flags = 0) {

    switch ( addr ) {
        case A_IMM:            // immediate
            set_op_imm(cmd.Op1, ua_next_byte());
            break;

        case A_ACC:            // accumulator
            set_op_acc(cmd.Op1);
            break;

        case A_ZP:            // zero page
            if ( cmd.itype == m740_ldm ) {    // special case
                set_op_imm(cmd.Op1, ua_next_byte());
                set_op_mem(cmd.Op2, ua_next_byte(), flags);
            }
            else
                set_op_mem(cmd.Op1, ua_next_byte(), flags);
            break;

        case A_ZPX:            // zero page X
            set_op_displ(ua_next_byte(), rX);
            cmd.auxpref |= INSN_DISPL_ZPX;
            break;

        case A_ZPY:            // zero page Y
            set_op_displ(ua_next_byte(), rY);
            cmd.auxpref |= INSN_DISPL_ZPY;
            break;

        case A_ABS:            // absolute
            if ( cmd.itype == m740_jmp || cmd.itype == m740_jsr ) {
                set_op_addr(cmd.Op1, ua_next_word());
            }
            else {
                set_op_mem(cmd.Op1, ua_next_word(), flags);
            }
            break;

        case A_ABSX:        // absolute X
            set_op_displ(ua_next_word(), rX);
            cmd.auxpref |= INSN_DISPL_ABSX;
            break;

        case A_ABSY:        // absolute Y
            set_op_displ(ua_next_word(), rY);
            cmd.auxpref |= INSN_DISPL_ABSY;
            break;

        case A_IMPL:        // implied
            // nothing to do..
            break;

        case A_REL:            // relative
            set_op_addr(cmd.Op1, (signed char) ua_next_byte() + cmd.ea + 2);
            break;

        case A_INDX:        // indirect X
            set_op_displ(ua_next_byte(), rX, dt_word);
            cmd.auxpref |= INSN_DISPL_INDX;
            break;

        case A_INDY:        // indirect Y
            set_op_displ(ua_next_byte(), rY, dt_word);
            cmd.auxpref |= INSN_DISPL_INDY;
            break;

        case A_INDABS:        // indirect absolute
            set_op_mem(cmd.Op1, ua_next_word(), flags, dt_word);
            cmd.Op1.specflag1 |= OP_ADDR_IND;
            break;

        case A_ZPIND:        // zero page indirect
            set_op_mem(cmd.Op1, ua_next_byte(), 0, dt_word);
            cmd.Op1.specflag1 |= OP_ADDR_IND;
            break;

        case A_SP:            // special page
            set_op_addr(cmd.Op1, ua_next_byte() | 0xFF00);
            cmd.Op1.specflag1 |= OP_ADDR_SP;
            break;

        case A_ZPB:            // zero page bit
            set_op_mem(cmd.Op2, ua_next_byte(), flags, dt_word);
            break;

        case A_ACCB:        // accumulator bit
            set_op_acc(cmd.Op2);
            break;

        case A_ACCBREL:        // accumulator bit relative
            set_op_acc(cmd.Op2);
            set_op_addr(cmd.Op3, (signed char) ua_next_byte() + cmd.ea + 2);
            break;

        case A_ZPBREL:        // zero page bit relative
            set_op_mem(cmd.Op2, ua_next_byte(), flags);
            set_op_addr(cmd.Op3, (signed char) ua_next_byte() + cmd.ea + 3);
            break;

        default:
            IDA_ERROR("Invalid addressing mode in fill_cmd()");
    }
}
示例#8
0
//----------------------------------------------------------------------
// analyze an basic instruction
static int ana_basic(void) {
  // get the command code byte
  ushort code = ua_next_byte();

  // decode the special case (annoying) instructions
  switch ( code ) {
  case 0x30:
    reg_operand(0, true, false, true, ua_next_byte());
    return finalise_insn(SAM8_JP);

  case 0x31: {
    // need to decode second byte to determine exact type
    ushort tmp = ua_next_byte();
    switch ( tmp & 0x03 ) {
    case 0:
      imm_operand(0, 1, tmp & 0xF0, dt_byte);
      return finalise_insn(SAM8_SRP);

    case 1:
      imm_operand(0, 1, tmp & 0xF8, dt_byte);
      return finalise_insn(SAM8_SRP1);

    case 2:
      imm_operand(0, 1, tmp & 0xF8, dt_byte);
      return finalise_insn(SAM8_SRP0);

    case 3:
      return 0; // invalid instruction
    }
  }

  case 0x82: case 0x92: case 0x83: case 0x93: {
    // work out correct code
    ushort opcode = 0;
    switch ( code ) {
    case 0x82: opcode = SAM8_PUSHUD; break;
    case 0x92: opcode = SAM8_POPUD; break;
    case 0x83: opcode = SAM8_PUSHUI; break;
    case 0x93: opcode = SAM8_POPUI; break;
    }

    // setup operands
    if ( (opcode == SAM8_POPUD) || (opcode == SAM8_POPUI) ) {
      reg_operand(1, true, false, false, ua_next_byte());
      reg_operand(0, false, false, false, ua_next_byte());
    } else {
      reg_operand(0, true, false, false, ua_next_byte());
      reg_operand(1, false, false, false, ua_next_byte());
    }
    return finalise_insn(opcode);
  }

  case 0xC2: case 0xD2: {
    // work out correct code
    ushort opcode = 0;
    switch ( code ) {
    case 0xC2: opcode = SAM8_CPIJE; break;
    case 0xD2: opcode = SAM8_CPIJNE; break;
    }

    // decode it
    ushort tmp = ua_next_byte();
    reg_operand(0, false, true, false, bottom_nibble(tmp));
    reg_operand(1, true, true, false, top_nibble(tmp));
    code_operand(2, 2, cmd.ea + 3 + (char) ua_next_byte());
    return finalise_insn(opcode);
  }

  case 0xE2: case 0xF2: case 0xC3: case 0xD3: case 0xE3: case 0xF3: {
    // need the next byte to tell whether data or code memory
    ushort opcode = 0;
    ushort tmp = ua_next_byte();
    ushort operandT = top_nibble(tmp);
    ushort operandB = bottom_nibble(tmp);
    if ( operandB & 1 ) {
      switch ( code ) {
      case 0xE2: opcode = SAM8_LDED; break;
      case 0xF2: opcode = SAM8_LDEPD; break;
      case 0xC3: opcode = SAM8_LDE; break;
      case 0xD3: opcode = SAM8_LDE; break;
      case 0xE3: opcode = SAM8_LDEI; break;
      case 0xF3: opcode = SAM8_LDEPI; break;
      }
      operandB--;
    } else {
      switch ( code ) {
      case 0xE2: opcode = SAM8_LDCD; break;
      case 0xF2: opcode = SAM8_LDCPD; break;
      case 0xC3: opcode = SAM8_LDC; break;
      case 0xD3: opcode = SAM8_LDC; break;
      case 0xE3: opcode = SAM8_LDCI; break;
      case 0xF3: opcode = SAM8_LDCPI; break;
      }
    }

    // decode it
    if ( code & 0x10 ) {
      reg_operand(0, true, true, true, operandB);
      reg_operand(1, false, true, false, operandT);
    } else {
      reg_operand(0, false, true, false, operandT);
      reg_operand(1, true, true, true, operandB);
    }
    return finalise_insn(opcode);
  }

  case 0xD4: {
    // get indirect address & check it is valid
    ushort tmp = ua_next_byte();
    if ( tmp & 1 ) return 0;

    // generate operation
    ind_code_operand(0, 1, tmp);
    return finalise_insn(SAM8_CALL);
  }

  case 0xF4:
    reg_operand(0, true, false, true, ua_next_byte());
    return finalise_insn(SAM8_CALL);

  case 0xF6:
    code_operand(0, 1, ua_next_word());
    return finalise_insn(SAM8_CALL);

  case 0xE4: {
    reg_operand(1, false, false, false, ua_next_byte());
    reg_operand(0, false, false, false, ua_next_byte());
    return finalise_insn(SAM8_LD);
  }

  case 0xE5: {
    reg_operand(1, true, false, false, ua_next_byte());
    reg_operand(0, false, false, false, ua_next_byte());
    return finalise_insn(SAM8_LD);
  }

  case 0xF5: {
    reg_operand(1, false, false, false, ua_next_byte());
    reg_operand(0, true, false, false, ua_next_byte());
    return finalise_insn(SAM8_LD);
  }

  case 0xD5:
    return 0; // invalid instruction

  case 0x87: case 0x97: {
    // get next byte
    ushort tmp = ua_next_byte();

    // setup operands
    switch ( code ) {
    case 0x87:
      reg_operand(0, false, true, false, top_nibble(tmp));
      idx_reg_operand(1, ua_next_byte(), bottom_nibble(tmp));
      break;

    case 0x97:
      idx_reg_operand(0, ua_next_byte(), bottom_nibble(tmp));
      reg_operand(1, false, true, false, top_nibble(tmp));
      break;
    }

    // finalise the instruction
    return finalise_insn(SAM8_LD);
  }

  case 0xd6:
    reg_operand(0, true, false, false, ua_next_byte());
    imm_operand(1, 2, ua_next_byte(), dt_byte);
    return finalise_insn(SAM8_LD);

  case 0xe6:
    reg_operand(0, false, false, false, ua_next_byte());
    imm_operand(1, 2, ua_next_byte(), dt_byte);
    return finalise_insn(SAM8_LD);

  case 0xc7: {
    ushort tmp = ua_next_byte();
    reg_operand(0, false, true, false, top_nibble(tmp));
    reg_operand(1, true, true, false, bottom_nibble(tmp));
    return finalise_insn(SAM8_LD);
  }

  case 0xd7: {
    ushort tmp = ua_next_byte();
    reg_operand(0, true, true, false, top_nibble(tmp));
    reg_operand(1, false, true, false, bottom_nibble(tmp));
    return finalise_insn(SAM8_LD);
  }

  case 0xa7: case 0xb7: {
    // extract data
    ushort tmp = ua_next_byte();

    // decode opcode + setup operands
    ushort opcode;
    switch ( bottom_nibble(tmp) ) {
    case 0:
      opcode = SAM8_LDC;
      switch ( code ) {
      case 0xa7:
        reg_operand(0, false, true, false, top_nibble(tmp));
        addr_cdata_operand(1, 2, next_word_le());
        break;

      case 0xb7:
        addr_cdata_operand(0, 2, next_word_le());
        reg_operand(1, false, true, false, top_nibble(tmp));
        break;
      }
      break;

    case 1:
      opcode = SAM8_LDE;
      switch ( code ) {
      case 0xa7:
        reg_operand(0, false, true, false, top_nibble(tmp));
        addr_edata_operand(1, 2, next_word_le());
        break;

      case 0xb7:
        addr_edata_operand(0, 2, next_word_le());
        reg_operand(1, false, true, false, top_nibble(tmp));
        break;
      }
      break;

    default:
      // extract operand nibbles
      ushort operandT = top_nibble(tmp);
      ushort operandB = bottom_nibble(tmp);

      // decode the correct opcode
      if ( operandB & 1 ) {
        opcode = SAM8_LDE;
        operandB--;
      } else {
        opcode = SAM8_LDC;
      }

      // generate operands
      switch ( code ) {
      case 0xA7:
        reg_operand(0, false, true, false, operandT);
        if ( opcode == SAM8_LDC )
          idx_cdata_operand(1, 2, next_word_le(), operandB);
        else idx_edata_operand(1, 2, next_word_le(), operandB);
        break;

      case 0xB7:
        if ( opcode == SAM8_LDC )
          idx_cdata_operand(0, 2, next_word_le(), operandB);
        else idx_edata_operand(0, 2, next_word_le(), operandB);
        reg_operand(1, false, true, false, operandT);
        break;
      }
    }

    // finalise instruction
    return finalise_insn(opcode);
  }

  case 0xE7: case 0xF7: {
    // extract data
    ushort tmp = ua_next_byte();
    ushort operandT = top_nibble(tmp);
    ushort operandB = bottom_nibble(tmp);

    // decode the correct opcode
    ushort opcode;
    if ( operandB & 1 ) {
      opcode = SAM8_LDE;
      operandB--;
    } else {
      opcode = SAM8_LDC;
    }

    // generate operands
    switch ( code ) {
    case 0xE7:
      reg_operand(0, false, true, false, operandT);
      if ( opcode == SAM8_LDC )
        idx_cdata_operand(1, 2, (int) (char) ua_next_byte(), operandB);
      else idx_edata_operand(1, 2, (int) (char) ua_next_byte(), operandB);
      break;

    case 0xF7:
      if ( opcode == SAM8_LDC )
        idx_cdata_operand(0, 2, (int) (char) ua_next_byte(), operandB);
      else idx_edata_operand(0, 2, (int) (char) ua_next_byte(), operandB);
      reg_operand(1, false, true, false, operandT);
      break;
    }

    // finalise the instruction
    return finalise_insn(opcode);
  }

  case 0x84: case 0x85: case 0x86:
  case 0x94: case 0x95: case 0x96: {
    // decode correct opcode
    ushort opcode = 0;
    switch ( top_nibble(code) ) {
    case 8: opcode = SAM8_MULT; break;
    case 9: opcode = SAM8_DIV; break;
    }

    // Now, generate instruction
    ushort src = ua_next_byte();
    ushort dst = ua_next_byte();
    reg_operand(0, false, false, true, dst);
    switch ( bottom_nibble(code) ) {
    case 4: reg_operand(1, false, false, false, src); break;
    case 5: reg_operand(1, true, false, false, src); break;
    case 6: imm_operand(1, 1, src, dt_byte); break;
    }
    return finalise_insn(opcode);
  }

  case 0xC4: case 0xC5: {
    // get data
    ushort src = ua_next_byte();
    ushort dst = ua_next_byte();

    // generate instruction
    reg_operand(0, false, false, true, dst);

    // decode addrmode for opcode 2
    switch ( code ) {
    case 0xC4: reg_operand(1, false, false, true, src); break;
    case 0xC5: reg_operand(1, true, false, false, src); break;
    }
    return finalise_insn(SAM8_LDW);
  }

  case 0xC6:
    reg_operand(0, false, false, true, ua_next_byte());
    imm_operand(1, 2, ua_next_word(), dt_word);
    return finalise_insn(SAM8_LDW);

  case 0x17: {
    // get data
    ushort operandA = ua_next_byte();
    ushort src = ua_next_byte();

    // ensure operandA bit0 is 0
    if ( operandA & 1 ) return 0;

    // generate instruction
    reg_operand(0, false, true, false, top_nibble(operandA));
    regbit_operand(1, false, src, bottom_nibble(operandA) >> 1);
    return finalise_insn(SAM8_BCP);
  }

  case 0x37: {
    // get data
    ushort operandA = ua_next_byte();
    ushort dst = ua_next_byte();

    // generate operands
    code_operand(0, 2, cmd.ea + 3 + (char) dst);
    regbit_operand(1, true,
                   top_nibble(operandA), bottom_nibble(operandA) >> 1);

    // generate operand
    switch ( operandA & 1 ) {
    case 0: return finalise_insn(SAM8_BTJRF);
    case 1: return finalise_insn(SAM8_BTJRT);
    }
  }

  case 0x57: {
    // get data
    ushort operandA = ua_next_byte();

    // ensure operandA bit0 is 0
    if ( operandA & 1 ) return 0;

    // generate instruction
    regbit_operand(0, true,
                   top_nibble(operandA), bottom_nibble(operandA) >> 1);
    return finalise_insn(SAM8_BITC);
  }

  case 0x77: {
    // get data
    ushort operandA = ua_next_byte();

    // generate instruction
    regbit_operand(0, true,
                   top_nibble(operandA), bottom_nibble(operandA) >> 1);
    switch ( operandA & 1 ) {
    case 0: return finalise_insn(SAM8_BITR);
    case 1: return finalise_insn(SAM8_BITS);
    }
  }
  }


  // Decode bit instructions
  if ( (bottom_nibble(code) == 7) && (top_nibble(code) < 8) ) {
    static const uint16 codeTable[] = {
                        SAM8_BOR, SAM8_null,
                        SAM8_BXOR, SAM8_null,
                        SAM8_LDB, SAM8_null,
                        SAM8_BAND, SAM8_null };
    // extract data
    ushort operandA = ua_next_byte();
    ushort operandB = ua_next_byte();

    // generate instruction
    switch ( operandA & 1 ) {
    case 0:
      reg_operand(0, false, true, false, top_nibble(operandA));
      regbit_operand(1, false, operandB, bottom_nibble(operandA) >> 1);
      break;

    case 1:
      regbit_operand(0, false, operandB, bottom_nibble(operandA) >> 1);
      reg_operand(1, false, true, false, top_nibble(operandA));
      break;
    }
    return finalise_insn(codeTable[top_nibble(code)]);
  }


  // Do the instructions with stuff encoded in them
  switch ( bottom_nibble(code) ) {
  case 0x08:
    reg_operand(0, false, true, false, top_nibble(code));
    reg_operand(1, false, false, false, ua_next_byte());
    return finalise_insn(SAM8_LD);

  case 0x09:
    reg_operand(0, false, false, false, ua_next_byte());
    reg_operand(1, false, true, false, top_nibble(code));
    return finalise_insn(SAM8_LD);

  case 0x0A:
    reg_operand(0, false, true, false, top_nibble(code));
    code_operand(1, 1, cmd.ea + 2 + (char) ua_next_byte());
    return finalise_insn(SAM8_DJNZ);

  case 0x0B:
    code_operand(0, 1, cmd.ea + 2 + (char) ua_next_byte());
    return finalise_insn(SAM8_JR, top_nibble(code));

  case 0x0C:
    reg_operand(0, false, true, false, top_nibble(code));
    imm_operand(1, 1, ua_next_byte(), dt_byte);
    return finalise_insn(SAM8_LD);

  case 0x0D:
    code_operand(0, 1, ua_next_word()); // UNSURE ****
    return finalise_insn(SAM8_JP, top_nibble(code));

  case 0x0E:
    reg_operand(0, false, true, false, top_nibble(code));
    return finalise_insn(SAM8_INC);

  case 0x0F: {
    static const uint16 codeTable[] = {
                        SAM8_NEXT, SAM8_ENTER,
                        SAM8_EXIT, SAM8_WFI,
                        SAM8_SB0,  SAM8_SB1,
                        SAM8_IDLE, SAM8_STOP,
                        SAM8_DI,   SAM8_EI,
                        SAM8_RET,  SAM8_IRET,
                        SAM8_RCF,  SAM8_SCF,
                        SAM8_CCF,  SAM8_NOP };
    return finalise_insn(codeTable[top_nibble(code)]);
  }
  }

  // Do R/RR/IR-only mode instructions
  if ( bottom_nibble(code) < 2 ) {
    static const uint16 codeTable[] = {
                        SAM8_DEC, SAM8_RLC,
                        SAM8_INC, SAM8_null,
                        SAM8_DA, SAM8_POP,
                        SAM8_COM, SAM8_PUSH,
                        SAM8_DECW, SAM8_RL,
                        SAM8_INCW, SAM8_CLR,
                        SAM8_RRC, SAM8_SRA,
                        SAM8_RR, SAM8_SWAP };
    // do the operand
    if ( code & 1 ) {
      reg_operand(0, true, false, false, ua_next_byte());
    } else {
      if ( (top_nibble(code) == 8) || (top_nibble(code) == 0xA) ) {
        reg_operand(0, false, false, true, ua_next_byte());
      } else {
        reg_operand(0, false, false, false, ua_next_byte());
      }
    }

    // finalise it
    return finalise_insn(codeTable[top_nibble(code)]);
  }

  // Decode arithmetic-style instructions
  if ( (bottom_nibble(code) > 1) && (bottom_nibble(code) < 7) ) {
    static const uint16 codeTable[] = {
                        SAM8_ADD,  SAM8_ADC,
                        SAM8_SUB,  SAM8_SBC,
                        SAM8_OR,   SAM8_AND,
                        SAM8_TCM,  SAM8_TM,
                        SAM8_null, SAM8_null,
                        SAM8_CP,   SAM8_XOR,
                        SAM8_null, SAM8_null,
                        SAM8_null, SAM8_null };
    ushort operandA = ua_next_byte();
    switch ( bottom_nibble(code) ) {
    case 2:
      reg_operand(0, false, true, false, top_nibble(operandA));
      reg_operand(1, false, true, false, bottom_nibble(operandA));
      return finalise_insn(codeTable[top_nibble(code)]);

    case 3:
      reg_operand(0, false, true, false, top_nibble(operandA));
      reg_operand(1, true, true, false, bottom_nibble(operandA));
      return finalise_insn(codeTable[top_nibble(code)]);

    case 4:
      reg_operand(0, false, false, false, ua_next_byte());
      reg_operand(1, false, false, false, operandA);
      return finalise_insn(codeTable[top_nibble(code)]);

    case 5:
      reg_operand(0, false, false, false, ua_next_byte());
      reg_operand(1, true, false, false, operandA);
      return finalise_insn(codeTable[top_nibble(code)]);

    case 6:
      reg_operand(0, false, false, false, operandA);
      imm_operand(1, 1, ua_next_byte(), dt_byte);
      return finalise_insn(codeTable[top_nibble(code)]);
    }
  }

  // If we get here, we've got an invalid instruction
  return 0;
}
示例#9
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;
    }
示例#10
0
//----------------------------------------------------------------------
int idaapi ana(void)
{
  cmd.Op1.dtyp = dt_byte;
  uint8 code = ua_next_byte();

  // Fetch instruction info
  const struct opcode_info_t &opinfo = get_opcode_info(code);
  cmd.itype = opinfo.itype;

  int op_i = 0;
  if ( opinfo.dreg != -1 )
  {
    cmd.Operands[op_i].type = o_reg;
    cmd.Operands[op_i].phrase = opinfo.dreg;
    op_i++;
  }

  switch ( opinfo.addr )
  {
    case IMPLIED:
      if ( cmd.itype == SPC_tcall )
      {
        cmd.Operands[op_i].type   = o_displ;
        cmd.Operands[op_i].phrase = rTCall;
        cmd.Operands[op_i].value  = code >> 4;
        cmd.Operands[op_i].addr   = 0xffde - (cmd.Operands[op_i].value << 1);
        op_i++;
      }
      break;
    case INDIR_IX:
      cmd.Operands[op_i].type = o_phrase;
      cmd.Operands[op_i].phrase = riX;
      op_i++;
      break;
    case INDIR_IX_INC:
      cmd.Operands[op_i].type = o_phrase;
      cmd.Operands[op_i].phrase = riXinc;
      op_i++;
      break;
    case INDIR_IX_IY:
      cmd.Operands[op_i].type = o_phrase;
      cmd.Operands[op_i].phrase = riX;
      op_i++;
      cmd.Operands[op_i].type = o_phrase;
      cmd.Operands[op_i].phrase = riY;
      op_i++;
      break;
    case IMM:
      cmd.Operands[op_i].type = o_imm;
      cmd.Operands[op_i].value = ua_next_byte();
      cmd.Operands[op_i].dtyp = dt_byte;
      op_i++;
      break;
    case IMM_DP:
      cmd.Operands[op_i + 1].type = o_imm;
      cmd.Operands[op_i + 1].value = ua_next_byte();
      cmd.Operands[op_i + 1].dtyp = dt_byte;

      cmd.Operands[op_i].type   = o_displ;
      cmd.Operands[op_i].phrase = rD;
      cmd.Operands[op_i].addr   = ua_next_byte();
      cmd.Operands[op_i].dtyp   = dt_byte;

      op_i += 2;
      break;
    case ABS:
      cmd.Operands[op_i].type = o_mem;
      cmd.Operands[op_i].addr = ua_next_word();
      if ( cmd.itype == SPC_call || cmd.itype == SPC_jmp )
      {
        cmd.Operands[op_i].type = o_near;
        cmd.Operands[op_i].full_target_ea = cmd.Operands[op_i].addr;
      }
      else
        cmd.Operands[op_i].dtyp = dt_byte;
      op_i++;
      break;
    case ABS_IX:
    case ABS_IY:
      cmd.Operands[op_i].type   = o_displ;
      cmd.Operands[op_i].phrase = opinfo.addr == ABS_IX ? rAbsX : rAbsY;
      cmd.Operands[op_i].addr   = ua_next_word();
      cmd.Operands[op_i].dtyp   = dt_byte;
      op_i++;
      break;
    case ABS_IX_INDIR:
      cmd.Operands[op_i].type   = o_displ;
      cmd.Operands[op_i].phrase = rAbsXi;
      cmd.Operands[op_i].addr   = ua_next_word();
      if ( cmd.itype == SPC_jmp )
        cmd.Operands[op_i].dtyp = dt_word;
      else
        cmd.Operands[op_i].dtyp = dt_byte;
      op_i++;
      break;
    case BIT_OP:
      {
        uint16 v = ua_next_word();
        cmd.Operands[op_i].type   = o_displ;
        if ( code == 0x2a || code == 0x6a )
            cmd.Operands[op_i].phrase = rDbitnot;
        else
            cmd.Operands[op_i].phrase = rDbit;
        cmd.Operands[op_i].addr   = v & 0x1fff;
        cmd.Operands[op_i].value  = v >> 13;
        cmd.Operands[op_i].dtyp   = dt_byte;
        op_i++;
      }
      break;
    case DP:
      if ( cmd.itype == SPC_pcall )
      {
        cmd.Operands[op_i].type = o_displ;
        cmd.Operands[op_i].phrase = rPCall;
        cmd.Operands[op_i].value  = ua_next_byte();
        cmd.Operands[op_i].addr = 0xff00 | cmd.Operands[op_i].value;
        op_i++;
      }
      else
      {
        cmd.Operands[op_i].type   = o_displ;
        cmd.Operands[op_i].phrase = rD;
        cmd.Operands[op_i].addr   = ua_next_byte();
        if ( cmd.itype == SPC_decw || cmd.itype == SPC_incw || cmd.itype == SPC_cmpw
          || cmd.itype == SPC_addw || cmd.itype == SPC_subw || cmd.itype == SPC_movw)
          cmd.Operands[op_i].dtyp   = dt_word;
        else
          cmd.Operands[op_i].dtyp   = dt_byte;
        op_i++;
      }
      break;
    case DP_IY:
    case DP_IX:
      cmd.Operands[op_i].type   = o_displ;
      cmd.Operands[op_i].phrase = opinfo.addr == DP_IX ? rDX : rDY;
      cmd.Operands[op_i].addr   = ua_next_byte();
      cmd.Operands[op_i].dtyp   = dt_byte;
      op_i++;
      break;
    case DP_IX_INDIR:
      cmd.Operands[op_i].type   = o_displ;
      cmd.Operands[op_i].phrase = riDX;
      cmd.Operands[op_i].addr   = ua_next_byte();
      cmd.Operands[op_i].dtyp   = dt_byte;
      op_i++;
      break;
    case DP_INDIR_IY:
      cmd.Operands[op_i].type   = o_displ;
      cmd.Operands[op_i].phrase = rDiY;
      cmd.Operands[op_i].addr   = ua_next_byte();
      cmd.Operands[op_i].dtyp   = dt_byte;
      op_i++;
      break;
    case DP_DP:
      cmd.Operands[op_i + 1].type   = o_displ;
      cmd.Operands[op_i + 1].phrase = rD;
      cmd.Operands[op_i + 1].addr   = ua_next_byte();
      cmd.Operands[op_i + 1].dtyp   = dt_byte;

      cmd.Operands[op_i].type   = o_displ;
      cmd.Operands[op_i].phrase = rD;
      cmd.Operands[op_i].addr   = ua_next_byte();
      cmd.Operands[op_i].dtyp   = dt_byte;

      op_i += 2;
      break;
    case DP_PC_REL:
	case DP_IX_PC_REL:
      cmd.Operands[op_i].type   = o_displ;
      if ( opinfo.addr == DP_IX_PC_REL )
        cmd.Operands[op_i].phrase = rDX;
      else
        cmd.Operands[op_i].phrase = rD;
      cmd.Operands[op_i].addr   = ua_next_byte();
      cmd.Operands[op_i].dtyp   = dt_byte;
      op_i++;

      cmd.Operands[op_i].type = o_near;
      {
        char x = ua_next_byte();
        cmd.Operands[op_i].addr = uint16(cmd.ip + cmd.size + x);
      }
      op_i++;
      break;
    case PC_REL:
      cmd.Operands[op_i].type = o_near;
      {
        char x = ua_next_byte();
        cmd.Operands[op_i].addr = uint16(cmd.ip + cmd.size + x);
      }
      op_i++;
      break;
    default:
      warning("ana: bad code 0x%x, @: 0x%a (IP=%a)", code, cmd.ea, cmd.ip);
      return 0;
  }
示例#11
0
文件: ana.cpp 项目: nealey/vera
//----------------------------------------------------------------------
int ana(void)
{
  CIC_param ctype;
  register segment_t *s = getMySeg(cmd.ea); // also set curSeg

  if ( s->type != SEG_CODE || cmd.ip >= curSeg.CodeSize ) {
    warning("Can't decode non-code fragment!");
    return(0);
  }

  cmd.Op1.dtyp = dt_void;
  cmd.wid = cmd.swit = 0;
  cmd.Op1.ref = 0;

  if ( (cmd.itype = ua_next_byte()) == j_wide ) {
    if(   (cmd.itype = ua_next_byte()) == j_iinc
       || (cmd.itype >= j_iload && cmd.itype <= j_aload)
       || (cmd.itype >= j_istore && cmd.itype <= j_astore)
       || cmd.itype == j_ret) cmd.wid = 1; //_w
    else {
      if ( !debugmode) return(0 );
      cmd.size = 1;
      cmd.itype = j_wide;
    }
  }

  if ( cmd.itype >= j_lastnorm ) {
    if ( !debugmode) return(0 );
    if ( cmd.itype < j_quick_last ) {
      static const uchar redefcmd[j_quick_last - j_lastnorm] = {
            j_ldc,                    //j_ldc_quick
            j_ldcw,                   //j_ldcw_quick
            j_ldc2w,                  //j_ldc2w_quick
            j_getfield,               //j_getfield_quick
            j_putfield,               //j_putfield_quick
            j_getfield,               //j_getfield2_quick
            j_putfield,               //j_putfield2_quick
            j_getstatic,              //j_getstatic_quick
            j_putstatic,              //j_putstatic_quick
            j_getstatic,              //j_getstatic2_quick
            j_putstatic,              //j_putstatic2_quick
            j_invokevirtual,          //j_invokevirtual_quick
            j_invokespecial,          //j_invokenonvirtual_quick
            j_a_invokesuper,          //j_invokesuper_quick
            j_invokestatic,           //j_invokestatic_quick
            j_invokeinterface,        //j_invokeinterface_quick
            j_a_invokevirtualobject,  //j_invokevirtualobject_quick
            j_a_invokeignored,        //j_invokeignored_quick
            j_new,                    //j_new_quick
            j_anewarray,              //j_anewarray_quick
            j_multianewarray,         //j_multianewarray_quick
            j_checkcast,              //j_checkcast_quick
            j_instanceof,             //j_instanceof_quick
            j_invokevirtual,          //j_invokevirtual_quick_w
            j_getfield,               //j_getfield_quick_w
            j_putfield                //j_putfield_quick_w
        };

      cmd.wid = 2; //_quick;
      switch ( cmd.itype ) {
        case j_getstatic2_quick:
        case j_putstatic2_quick:
        case j_getfield2_quick:
        case j_putfield2_quick:
          cmd.wid = 3;  //2_quick
          break;
        case j_invokevirtual_quick_w:
        case j_getfield_quick_w:
        case j_putfield_quick_w:
          cmd.wid = 4;  //_quick_w
          break;
        default:
          break;
      }
      cmd.itype = redefcmd[cmd.itype - j_lastnorm];
    } else if ( cmd.itype < j_software) return(0 );
           else cmd.itype -= (j_software - j_a_software);
  }
//---
  switch ( cmd.itype ) {
    default:
      {
        register unsigned refs, ref2f;

        if ( cmd.itype >= j_iload_0 && cmd.itype <= j_aload_3 ) {
          refs = (cmd.itype - j_iload_0) % 4;
          ref2f = (cmd.itype - j_iload_0) / 4;
          ref2f =   ref2f == ((j_lload_0 - j_iload_0) / 4)
                 || ref2f == ((j_dload_0 - j_iload_0) / 4);
          goto refer;
        }
        if ( cmd.itype >= j_istore_0 && cmd.itype <= j_astore_3 ) {
          refs = (cmd.itype - j_istore_0) % 4;
          ref2f = (cmd.itype - j_istore_0) / 4;
          ref2f =    ref2f == ((j_lstore_0 - j_istore_0) / 4)
                  || ref2f == ((j_dstore_0 - j_istore_0) / 4);
refer:
          cmd.Op1.addr = curSeg.DataBase + (ushort)refs;
          cmd.Op1.ref = (uchar)(ref2f + 1);
          if ( (ushort)(refs + ref2f) >= curSeg.DataSize ) cmd.Op1.ref |= 0x80;
          break;
        }
      } // end refs/refx
      if ( cmd.itype < j_ifeq || cmd.itype > j_jsr ) break;
    case j_ifnull:
    case j_ifnonnull:
      cmd.Op1.addr = (short)ua_next_word();
b_near:
      cmd.Op1.type = o_near;
      cmd.Op1.offb = 1;
      cmd.Op1.addr += cmd.ip;
      if ( cmd.Op1.addr >= curSeg.CodeSize ) goto set_bad_ref;
      break;

    case j_goto_w:
    case j_jsr_w:
      cmd.Op1.addr = ua_next_long();
      goto b_near;

    case j_bipush:
      cmd.Op1.dtyp = dt_byte;
      cmd.Op1.value = (char)ua_next_byte();
      goto setdat;
    case j_sipush:
      cmd.Op1.dtyp = dt_word;
      cmd.Op1.value = (short)ua_next_word();
setdat:
      cmd.Op1.type = o_imm;
      cmd.Op1.offb = 1;
      break;

    case j_ldc:
      cmd.Op1.cp_ind = ua_next_byte();
      ctype = C_4byte;
      goto constchk;
    case j_ldcw:
      ctype = C_4byte;
      goto const2w;
    case j_ldc2w:
      ctype = C_8byte;
const2w:
      cmd.Op1.cp_ind = ua_next_word();
constchk:
      if ( !ConstLoad(ctype)) return(0 );
      break;

    case j_getstatic:
    case j_putstatic:
    case j_getfield:
    case j_putfield:
      if ( cmd.wid > 1 ) {     //_quick form
        cmd.Op1.type = o_imm;
        cmd.Op1.ref = 2;        //#data
        cmd.Op1.offb = 1;
        if ( cmd.wid == 4 ) { //???
          cmd.Op1.dtyp = dt_word;
          cmd.Op1.value = ua_next_word();
        } else {
          cmd.Op1.dtyp = dt_byte;
          cmd.Op1.value = ua_next_byte();
          ++cmd.size;           // SKIP
        }
        break;
      }
      ctype = C_Field;
      goto const2w;

    case j_new:
      ctype = C_Class;
      goto const2w;

    case j_anewarray:
//\\ ?/
    case j_checkcast:
    case j_instanceof:
      ctype = C_TypeName;
      goto const2w;

    case j_a_invokesuper:
    case j_a_invokeignored:
      goto fictarg;
    case j_invokevirtual:
    case j_a_invokevirtualobject:
      cmd.Op2.dtyp = dt_void;
      if ( cmd.wid > 1 ) {
        if ( cmd.wid == 4 ) {
fictarg:
          cmd.Op1.value = ua_next_word(); //???
          cmd.Op1.dtyp = dt_word;
        } else {
          cmd.Op2.type = o_imm;
          cmd.Op1.ref = 2;        //#data
          cmd.Op1.dtyp = cmd.Op2.dtyp = dt_byte;
          cmd.Op1.value = ua_next_byte();
          cmd.Op2.offb = 2;
          cmd.Op2.value = ua_next_byte();
        }
        cmd.Op1.offb = 1;
        cmd.Op1.type = o_imm;
        cmd.Op1.ref = 2;        //#data
        break;
      }
    case j_invokespecial:
    case j_invokestatic:
    case j_invokedynamic:
      ctype = C_Method;
      goto const2w;
    case j_invokeinterface:
      ctype = C_Interface;
      cmd.Op1.cp_ind = ua_next_word();
      cmd.Op2.type = o_imm;
      cmd.Op2.ref = 1;          //not descriptor
      cmd.Op2.dtyp = dt_byte;
      cmd.Op2.value = ua_next_byte();
      if ( cmd.wid > 1 ) {
        cmd.Op3.type = o_imm;
        cmd.Op3.ref = 2;        //#data
        cmd.Op3.value = ua_next_byte();
        cmd.Op3.offb = 4;
        cmd.Op3.dtyp = dt_byte;
      } else {
        ++cmd.size;  //reserved
        cmd.Op3.dtyp = dt_void;
      }
      goto constchk;

    case j_multianewarray:
      cmd.Op1.cp_ind = ua_next_word();
      cmd.Op2.type = o_imm;
      cmd.Op2.ref = 1;         // not descriptor
      cmd.Op2.dtyp = dt_byte;
      if ( (cmd.Op2.value = ua_next_byte()) == 0 && !debugmode) return(0 );
      ctype = C_Type;
      goto constchk;

    case j_iinc:
    case j_iload:
    case j_istore:
      cmd.Op1.dtyp = dt_dword;
      goto memref;
    case j_lload:
    case j_lstore:
      cmd.Op1.dtyp = dt_qword;
      goto memref;
    case j_fload:
    case j_fstore:
      cmd.Op1.dtyp = dt_float;
      goto memref;
    case j_dload:
    case j_dstore:
      cmd.Op1.dtyp = dt_double;
      goto memref;
    case j_aload:
    case j_astore:
      cmd.Op1.dtyp = dt_string;
      goto memref;
    case j_ret:
      cmd.Op1.dtyp = dt_code;
memref:
      if ( !LoadIndex()) return(0 );
      if ( cmd.itype == j_iinc ) {
        cmd.Op2.type = o_imm;
        cmd.Op2.ref = 0;
        cmd.Op2.offb = (uchar)cmd.size;
//\\??? Это надо???
        if ( cmd.wid ) {
          cmd.Op2.dtyp = dt_word;
          cmd.Op2.value = (short)ua_next_word();
        } else {
          cmd.Op2.dtyp = dt_byte;
          cmd.Op2.value = (char)ua_next_byte();
        }
      }
      break;

    case j_tableswitch:
    case j_lookupswitch:
      {
        int32 count;
        register uint32 top;

        cmd.swit = 1;
        for(top = (4  - uint32((cmd.ip + cmd.size) % 4)) & 3; top; top--)
          if ( ua_next_byte() ) {
            if ( !debugmode) return(0 );
            cmd.swit |= 0100;
          }
        cmd.Op3.type = o_near;
        cmd.Op3.offb = (uchar)cmd.size;
        cmd.Op3.addr = ua_next_long();
        cmd.Op3.addr += cmd.ip;
        cmd.Op3.ref = 0;

        if ( cmd.Op3.addr >= curSeg.CodeSize ) {
          if ( !debugmode) return(0 );
          ++cmd.Op3.ref;
        }

        cmd.swit |= 2;  // start out arguments

        count = ua_next_long();
        if ( cmd.itype == j_tableswitch ) {
          cmd.Op1.type  = o_imm;
          cmd.Op1.dtyp  = dt_dword;
          cmd.Op1.value = count;  // minimal value
          cmd.Op2.ref   = 0;
          cmd.Op2.type  = o_imm;
          cmd.Op2.dtyp  = dt_dword;
          count = (uint32(cmd.Op2.value = ua_next_long()) - count + 1);
        }
        cmd.Op3.value = count;
        cmd.Op2.addr = cmd.ip + cmd.size;
        top = uint32(curSeg.CodeSize - cmd.ip);
        while ( count-- ) {
          if ( cmd.itype == j_lookupswitch) ua_next_long( ); // skip pairs;
          if ( (cmd.ip + ua_next_long()) >= curSeg.CodeSize ) {
            if ( !debugmode) return(0 );
            cmd.swit |= 0200;
          }
          if ( (uint32)cmd.size >= top) return(0 );
        }
      }
      break;

    case j_newarray:
      cmd.Op1.type = o_array;       // type!
      cmd.Op1.offb = 1;
      if(   (cmd.Op1.cp_type = ua_next_byte()) < T_BOOLEAN
         || (uchar)cmd.Op1.cp_type > T_LONG) {
set_bad_ref:
        if ( !debugmode) return(0 );
        ++cmd.Op1.ref;
      }
      break;
  } // switch ( cmd.itype )

  return(cmd.size);
}
示例#12
0
文件: ana.cpp 项目: nealey/vera
//--------------------------------------------------------------------------
int ana(void)
{
  int code = ua_next_byte();
  int saved_code = code;
  char dtyp = dt_byte;
  if ( code < 0x60 )
  {
    cmd.itype = A2[code];
  }
  else
  {
    if ( code & 8 )
    {
      cmd.auxpref |= aux_word;
      dtyp = dt_word;
    }
    else
    {
      cmd.auxpref |= aux_byte;
      dtyp = dt_byte;
    }
    cmd.itype = A2tail[(code>>4)-6];
  }
  if ( cmd.itype == H8500_null ) return 0;
  switch ( code )
  {
    case 0x02:  // ldm.w @sp+, <reglist>
//      cmd.auxpref |= aux_word;
      phrase(cmd.Op1, SP, ph_post, dt_word);
      cmd.Op2.type = o_reglist;
      cmd.Op2.reg  = ua_next_byte();
      if ( !cmd.Op2.reg ) return 0;
      break;
    case 0x12:  // stm.w <reglist>, @-sp
//      cmd.auxpref |= aux_word;
      cmd.Op1.type = o_reglist;
      cmd.Op1.reg  = ua_next_byte();
      if ( !cmd.Op1.reg ) return 0;
      phrase(cmd.Op2, SP, ph_pre, dt_word);
      break;
    case 0x01:  // scb/f
      cmd.auxpref |= aux_f;
      break;
    case 0x06:  // scb/ne
      cmd.auxpref |= aux_ne;
      break;
    case 0x07:  // scb/eq
      cmd.auxpref |= aux_eq;
      break;
    case 0x08:  // trapa #xx
      code = ua_next_byte();
      if ( (code & 0xF0) != 0x10 ) return 0;
      cmd.Op1.type = o_imm;
      cmd.Op1.dtyp = dt_byte;
      cmd.Op1.value = code & 15;
      break;
    case 0x0F:  // unlk
      reg(cmd.Op1, FP, dt_word);
      break;
    case 0x10:  // jmp @aa:16
    case 0x18:  // jsr @aa:16
      aa16(cmd.Op1, dt_code);
      cmd.Op1.type = o_near;
      cmd.Op1.addr += cmd.ea & ~0xFFFF;
      break;
    case 0x17:  // link #xx:8
      reg(cmd.Op1, FP, dt_word);
      imm8(cmd.Op2);
      break;
    case 0x1F:  // link #xx:16
      reg(cmd.Op1, FP, dt_word);
      imm16(cmd.Op2);
      break;
    case 0x03:  // pjsr @aa:24
    case 0x13:  // pjmp @aa:24
      {
        cmd.auxpref |= aux_disp24;
        uint32 page   = ua_next_byte();
        cmd.Op1.type = o_far;
        cmd.Op1.dtyp = dt_code;
        cmd.Op1.addr = (page<<16) | ua_next_word();
      }
      break;
    case 0x04:  // #xx:8
      cmd.auxpref |= aux_byte;
    case 0x14:  // #xx:8
      imm8(cmd.Op1);
      break;
    case 0x05:  // #aa:8.B
      cmd.auxpref |= aux_byte;
      aa8(cmd.Op1, dt_byte);
      break;
    case 0x15:  // #aa:16.B
      cmd.auxpref |= aux_byte;
      aa16(cmd.Op1, dt_byte);
      break;
    case 0x0C:  // #xx:16
      cmd.auxpref |= aux_word;
    case 0x1C:  // #xx:16
      imm16(cmd.Op1);
      break;
    case 0x0D:  // #aa:8.W
      cmd.auxpref |= aux_word;
      aa8(cmd.Op1, dt_word);
      dtyp = dt_word;
      break;
    case 0x1D:  // #aa:16.W
      cmd.auxpref |= aux_word;
      aa16(cmd.Op1, dt_word);
      dtyp = dt_word;
      break;
    case 0x0E:                                  // bsr d:8
    case 0x20: case 0x21: case 0x22: case 0x23: // d:8
    case 0x24: case 0x25: case 0x26: case 0x27:
    case 0x28: case 0x29: case 0x2A: case 0x2B:
    case 0x2C: case 0x2D: case 0x2E: case 0x2F:
      d8(cmd.Op1);
      break;
    case 0x1E:                                  // bsr d:16
    case 0x30: case 0x31: case 0x32: case 0x33: // d:16
    case 0x34: case 0x35: case 0x36: case 0x37:
    case 0x38: case 0x39: case 0x3A: case 0x3B:
    case 0x3C: case 0x3D: case 0x3E: case 0x3F:
      {
        cmd.auxpref |= aux_disp16;
        int32 disp = short(ua_next_word());
        cmd.Op1.type = o_near;
        cmd.Op1.dtyp = dt_code;
        cmd.Op1.addr = cmd.ip + cmd.size + disp;
      }
      break;
    case 0x40: case 0x41: case 0x42: case 0x43: // cmp:e #xx:8, Rn
    case 0x44: case 0x45: case 0x46: case 0x47:
    case 0x50: case 0x51: case 0x52: case 0x53: // mov:e #xx:8, Rn
    case 0x54: case 0x55: case 0x56: case 0x57:
      cmd.auxpref |= aux_byte;
      imm8(cmd.Op1);
      reg(cmd.Op2, code, dtyp);
      break;
    case 0x48: case 0x49: case 0x4A: case 0x4B: // cmp:i #xx:16, Rn
    case 0x4C: case 0x4D: case 0x4E: case 0x4F:
    case 0x58: case 0x59: case 0x5A: case 0x5B: // mov:i #xx:16, Rn
    case 0x5C: case 0x5D: case 0x5E: case 0x5F:
      cmd.auxpref |= aux_word;
      imm16(cmd.Op1);
      reg(cmd.Op2, code, dtyp);
      break;
    case 0x60: case 0x61: case 0x62: case 0x63: // @aa:8, Rn
    case 0x64: case 0x65: case 0x66: case 0x67:
    case 0x68: case 0x69: case 0x6A: case 0x6B:
    case 0x6C: case 0x6D: case 0x6E: case 0x6F:
      aa8(cmd.Op1, dtyp);
      reg(cmd.Op2, code, dtyp);
      break;
    case 0x70: case 0x71: case 0x72: case 0x73: // Rn, @aa:8
    case 0x74: case 0x75: case 0x76: case 0x77:
    case 0x78: case 0x79: case 0x7A: case 0x7B:
    case 0x7C: case 0x7D: case 0x7E: case 0x7F:
      reg(cmd.Op1, code, dtyp);
      aa8(cmd.Op2, dtyp);
      break;
    case 0x80: case 0x81: case 0x82: case 0x83: // mov:f @(d:8, R6), Rn
    case 0x84: case 0x85: case 0x86: case 0x87:
    case 0x88: case 0x89: case 0x8A: case 0x8B:
    case 0x8C: case 0x8D: case 0x8E: case 0x8F:
      ds8(cmd.Op1, R6, dtyp);
      reg(cmd.Op2, code, dtyp);
      break;
    case 0x90: case 0x91: case 0x92: case 0x93: // mov:f Rn, @(d:8, R6)
    case 0x94: case 0x95: case 0x96: case 0x97:
    case 0x98: case 0x99: case 0x9A: case 0x9B:
    case 0x9C: case 0x9D: case 0x9E: case 0x9F:
      reg(cmd.Op1, code, dtyp);
      ds8(cmd.Op2, R6, dtyp);
      break;
    case 0xA0: case 0xA1: case 0xA2: case 0xA3: // Rn, Rn
    case 0xA4: case 0xA5: case 0xA6: case 0xA7:
    case 0xA8: case 0xA9: case 0xAA: case 0xAB:
    case 0xAC: case 0xAD: case 0xAE: case 0xAF:
      reg(cmd.Op1, code, dtyp);
      break;
    case 0xB0: case 0xB1: case 0xB2: case 0xB3: // @-Rn, Rn
    case 0xB4: case 0xB5: case 0xB6: case 0xB7:
    case 0xB8: case 0xB9: case 0xBA: case 0xBB:
    case 0xBC: case 0xBD: case 0xBE: case 0xBF:
      phrase(cmd.Op1, code, ph_pre, dtyp);
      break;
    case 0xC0: case 0xC1: case 0xC2: case 0xC3: // @Rn+, Rn
    case 0xC4: case 0xC5: case 0xC6: case 0xC7:
    case 0xC8: case 0xC9: case 0xCA: case 0xCB:
    case 0xCC: case 0xCD: case 0xCE: case 0xCF:
      phrase(cmd.Op1, code, ph_post, dtyp);
      break;
    case 0xD0: case 0xD1: case 0xD2: case 0xD3: // @Rn, Rn
    case 0xD4: case 0xD5: case 0xD6: case 0xD7:
    case 0xD8: case 0xD9: case 0xDA: case 0xDB:
    case 0xDC: case 0xDD: case 0xDE: case 0xDF:
      phrase(cmd.Op1, code, ph_normal, dtyp);
      break;
    case 0xE0: case 0xE1: case 0xE2: case 0xE3: // @(d:8,Rn), Rn
    case 0xE4: case 0xE5: case 0xE6: case 0xE7:
    case 0xE8: case 0xE9: case 0xEA: case 0xEB:
    case 0xEC: case 0xED: case 0xEE: case 0xEF:
      ds8(cmd.Op1, code, dtyp);
      break;
    case 0xF0: case 0xF1: case 0xF2: case 0xF3: // @(d:16,Rn), Rn
    case 0xF4: case 0xF5: case 0xF6: case 0xF7:
    case 0xF8: case 0xF9: case 0xFA: case 0xFB:
    case 0xFC: case 0xFD: case 0xFE: case 0xFF:
      ds16(cmd.Op1, code, dtyp);
      break;
  }
  while ( cmd.itype > H8500_last )     // while MAPs are not resolved
  {
    int index = -(3+short(cmd.itype));
    if ( index < 0 || index >= qnumber(tables) ) interr("ana1");
    code = ua_next_byte();
    if ( code < 0x20 )
    {
      cmd.itype = tables[index].head[code];
    }
    else
    {
      cmd.itype = tables[index].tail[(code>>3)-4];
      reg(cmd.Op2, code, dtyp);
    }
    if ( index == 3 ) switch ( saved_code ) // MAP6
    {
      case 0x01:
      case 0x06:
      case 0x07:
        if ( cmd.itype != H8500_scb ) return 0;
        break;
      case 0x11:
        if ( cmd.itype != H8500_prts
          && cmd.itype != H8500_prtd
          && cmd.itype != H8500_jmp
          && cmd.itype != H8500_pjmp
          && cmd.itype != H8500_jsr
          && cmd.itype != H8500_pjsr ) return 0;
        break;
      default:
        if ( cmd.itype != H8500_movfpe
          && cmd.itype != H8500_movtpe
          && cmd.itype != H8500_dadd
          && cmd.itype != H8500_dsub ) return 0;
    }
    switch ( cmd.itype )
    {
      case H8500_null:
        return 0;
      case H8500_add_q:
        cmd.Op2 = cmd.Op1;
        switch ( code )
        {
          case 0x08: immv(cmd.Op1, 1);  break;
          case 0x09: immv(cmd.Op1, 2);  break;
          case 0x0C: immv(cmd.Op1, -1); break;
          case 0x0D: immv(cmd.Op1, -2); break;
        }
        break;
      case H8500_bset:
      case H8500_bclr:
      case H8500_bnot:
      case H8500_btst:
        cmd.Op2 = cmd.Op1;
        if ( code < 0xC0 )
          reg(cmd.Op1, code, dtyp);
        else
          immv(cmd.Op1, code & 15);
        break;
      case H8500_mov_g:
        if ( (code & 0xF8) == 0x80 ) break;
        cmd.Op2 = cmd.Op1;
        if ( code == 0x06 )
        {
          if ( (cmd.auxpref & aux_word) == 0 ) cmd.auxpref |= aux_byte;
          cmd.Op1.type  = o_imm;
          cmd.Op1.dtyp  = dt_byte;
          cmd.Op1.value = ua_next_byte();
        }
        else if ( code == 0x07 )
        {
          if ( (cmd.auxpref & aux_byte) == 0 ) cmd.auxpref |= aux_word;
          cmd.auxpref  |= aux_mov16;
          cmd.Op1.type  = o_imm;
          cmd.Op1.dtyp  = dt_word;
          cmd.Op1.value = ua_next_word();
        }
        else
          reg(cmd.Op1, code, dtyp);
        break;
      case H8500_cmp_g:
        if ( code > 5 ) break;
        cmd.Op2 = cmd.Op1;
        if ( code == 0x04 )
        {
          cmd.auxpref  |= aux_byte;
          cmd.Op1.type  = o_imm;
          cmd.Op1.dtyp  = dt_byte;
          cmd.Op1.value = ua_next_byte();
        }
        else
        {
          cmd.auxpref  |= aux_word;
          cmd.Op1.type  = o_imm;
          cmd.Op1.dtyp  = dt_word;
          cmd.Op1.value = ua_next_word();
        }
        break;
      case H8500_andc:
      case H8500_orc:
      case H8500_xorc:
      case H8500_ldc:
      case H8500_stc:
        cmd.Op2.reg += SR;
        if ( cmd.Op2.reg == RES1 || cmd.Op2.reg == CP ) return 0;
        if ( ((cmd.auxpref & aux_word) != 0) != (cmd.Op2.reg == SR) ) return 0;
        if ( cmd.itype != H8500_stc ) break;
        // no break
      case H8500_movtpe:
        {
          op_t x  = cmd.Op1;
          cmd.Op1 = cmd.Op2;
          cmd.Op2 = x;
        }
        break;
      case H8500_pjmp:
      case H8500_pjsr:
      case H8500_jmp:
      case H8500_jsr:
        cmd.Op2.type = o_void;
        switch ( code & 0xF0 )
        {
          case 0xC0:
          case 0xD0: phrase(cmd.Op1, code, ph_normal, dt_code); break;
          case 0xE0: ds8(cmd.Op1, code, dt_code); break;
          case 0xF0: ds16(cmd.Op1, code, dt_code); break;
        }
        break;
      case H8500_rtd:
      case H8500_prtd:
        if ( code == 0x14 )
          imm8(cmd.Op1);
        else
          imm16(cmd.Op1);
        break;
      case H8500_scb:
        cmd.Op1 = cmd.Op2;
        d8(cmd.Op2);
        break;
      case H8500_dadd:
      case H8500_dsub:
        if ( (cmd.auxpref & aux_byte) == 0 ) return 0;
        cmd.auxpref &= ~aux_byte;
        break;
    }
  }
  if ( (idpflags & AFIDP_MIXSIZE) == 0 ) // Disassemble mixed size instructions?
  {
    if ( (cmd.auxpref & aux_word) && cmd.Op1.dtyp == dt_byte
      || (cmd.auxpref & aux_byte) && cmd.Op1.dtyp == dt_word )
          if ( cmd.itype != H8500_mov_g ) return 0;
  }
  return cmd.size;
}