/* This module has been created by Petr Novak */ #include "xa.hpp" static int ana_basic(insn_t &insn); //---------------------------------------------------------------------- inline int ua_next_word_be(insn_t &insn) { int32 result; result = ((uchar)insn.get_next_byte()) << 8; result += (uchar)insn.get_next_byte(); return (int)result; } //---------------------------------------------------------------------- inline void opC(op_t &op) { op.type = o_reg; op.reg = rC; } //---------------------------------------------------------------------- // register direct static int op_rd(op_t &x, int reg, int dtype) { x.type = o_reg; x.dtype = uchar(dtype); x.reg = uint16((dtype == dt_byte ? rR0L : rR0) + reg); return 1; } //---------------------------------------------------------------------- // register indirect static int op_ph(op_t &x, uint16 phrase, int reg, int dtype) { x.type = o_phrase; x.dtype = uchar(dtype); x.phrase = phrase; // union with x.reg x.indreg = (uchar)reg; if ( (phrase != fRlistL) && (phrase != fRlistH) ) x.indreg += rR0; return 1; } //---------------------------------------------------------------------- // register indirect with displacement static int op_ds(op_t &x, uint16 phrase, int ireg, sval_t disp, int dtype) { if ( disp > 0xFD00L ) { disp = disp - 0x10000L; // heuristics: treat large values from -300h as negative } x.type = o_displ; x.dtype = uchar(dtype); x.phrase = phrase; x.indreg = rR0 + (uchar)ireg; x.addr = disp; return 1; } //---------------------------------------------------------------------- inline void op_mm(op_t &x, uval_t addr, int dtype) { x.type = o_mem; x.dtype = uchar(dtype); x.addr = addr; } //---------------------------------------------------------------------- inline void op_rel(const insn_t &insn, op_t &x, sval_t addr) { if ( addr > 32767 ) addr -= 0x10000L; x.type = o_near; x.dtype = dt_code; x.addr = (insn.ip + insn.size + 2*addr) & (~1L); } //---------------------------------------------------------------------- inline void op_near(op_t &x, uval_t addr) { x.type = o_near; x.dtype = dt_word; x.addr = addr; } //---------------------------------------------------------------------- inline void op_im(op_t &x, uval_t value, int dtype) { x.type = o_imm; x.dtype = uchar(dtype); x.value = value; } //---------------------------------------------------------------------- inline void op_bit(op_t &x, int type, uval_t addr) { x.type = optype_t(type); x.dtype = dt_word; x.addr = addr; } //---------------------------------------------------------------------- // analyze an basic instruction static int ana_basic(insn_t &insn) { static const nameNum xa_basic[16] = { XA_add, XA_addc, XA_sub, XA_subb, XA_cmp, XA_and, XA_or, XA_xor, XA_mov, XA_null, XA_null, XA_null, XA_null, XA_null, XA_null, XA_null, }; static const nameNum xa_branches[16] = { XA_bcc, XA_bcs, XA_bne, XA_beq, XA_bnv, XA_bov, XA_bpl, XA_bmi, XA_bg, XA_bl, XA_bge, XA_blt, XA_bgt, XA_ble, XA_br, XA_bkpt, }; static const nameNum xa_pushpop[] = { XA_push, XA_pushu, XA_pop, XA_popu, }; static const nameNum xa_bitops[] = { XA_clr, XA_setb, XA_mov, XA_mov, XA_anl, XA_anl, XA_orl, XA_orl, }; static const nameNum xa_Jxx[] = { XA_jb, XA_jnb, XA_jbc, XA_null, }; static const nameNum xa_misc[] = { XA_da, XA_sext, XA_cpl, XA_neg, }; static const nameNum xa_shifts[] = { XA_lsr, XA_asl, XA_asr, XA_norm, }; ushort code = insn.get_next_byte(); ushort nibble0 = (code & 0xF); ushort nibble1 = (code >> 4); signed char off; int size = 0; ushort b1; if ( nibble1 <= 0xB ) { switch ( nibble0 & 0x7 ) { case 0: // Specials case 7: // dtto switch ( code ) { case 0x00: // 00 - NOP insn.itype = XA_nop; break; case 0x07: // PUSH.B Rlist case 0x0F: // PUSH.W Rlist case 0x17: // PUSHU.B Rlist case 0x1F: // PUSHU.W Rlist case 0x27: // POP.B Rlist case 0x2F: // POP.W Rlist case 0x37: // POPU.B Rlist case 0x3F: // POPU.W Rlist case 0x47: // PUSH.B Rlist case 0x4F: // PUSH.W Rlist case 0x57: // PUSHU.B Rlist case 0x5F: // PUSHU.W Rlist case 0x67: // POP.B Rlist case 0x6F: // POP.W Rlist case 0x77: // POPU.B Rlist case 0x7F: // POPU.W Rlist size = (nibble0 < 8) ? dt_byte : dt_word; b1 = insn.get_next_byte(); // Rlist insn.itype = xa_pushpop[nibble1 & 3]; if ( nibble1 & 4 ) // High op_ph(insn.Op1, fRlistH, b1, size); else op_ph(insn.Op1, fRlistL, b1, size); break; case 0x08: // 08 - misc b1 = insn.get_next_byte(); switch ( b1 & 0xfc ) { case 0x00: // CLR case 0x10: // SETB insn.itype = xa_bitops[(b1>>4) & 7]; op_bit(insn.Op1, o_bit, ((b1&3)<<8) + (uchar)insn.get_next_byte()); break; case 0x20: // MOV C,bit insn.itype = xa_bitops[(b1>>4) & 7]; opC(insn.Op1); op_bit(insn.Op2, o_bit, ((b1&3)<<8) + (uchar)insn.get_next_byte()); break; case 0x30: // MOV bit,C insn.itype = xa_bitops[(b1>>4) & 7]; op_bit(insn.Op1, o_bit, ((b1&3)<<8) + (uchar)insn.get_next_byte()); opC(insn.Op2); break; case 0x40: // ANL C, bit case 0x50: // ANL C, /bit case 0x60: // ORL C, bit case 0x70: // ORL C, /bit insn.itype = xa_bitops[(b1>>4) & 7]; opC(insn.Op1); op_bit(insn.Op2, (b1&0x10)?o_bitnot:o_bit, ((b1&3)<<8) + (uchar)insn.get_next_byte()); break; default: // undefined return 0; } break; case 0x40: // LEA case 0x48: // LEA insn.itype = XA_lea; b1 = insn.get_next_byte(); if ( b1 & 0x88 ) return 0; op_rd(insn.Op1, b1>>4, dt_word); if ( code & 0x8 ) // 16bit offset op_ds(insn.Op2, fRid16, b1&0x07, (int32)ua_next_word_be(insn), dt_word); else op_ds(insn.Op2, fRid8, b1&0x07, (signed char)insn.get_next_byte(), dt_word); break; case 0x50: // XCH.B Rd,[Rs] case 0x58: // XCH.W Rd,[Rs] case 0x60: // XCH.B Rd,Rs case 0x68: // XCH.W Rd,Rs insn.itype = XA_xch; size = (nibble0 < 8) ? dt_byte : dt_word; b1 = insn.get_next_byte(); op_rd(insn.Op1, b1>>4, size); switch ( nibble1 ) { case 0x5: // Rd,[Rs] if ( b1 & 8 ) return 0; op_ds(insn.Op2, fRi, b1&7, 0, size); break; case 0x6: // Rd,Rs op_rd(insn.Op2, b1&0xf, size); break; } break; case 0x80: // MOVC case 0x88: // MOVC b1 = insn.get_next_byte(); size = (nibble0 < 8) ? dt_byte : dt_word; if ( b1 & 8 ) return 0; insn.itype = XA_movc; op_rd(insn.Op1, b1>>4, size); op_ph(insn.Op2, fRip, b1&7, size); break; case 0x87: // DJNZ Rd, rel8 case 0x8F: // POP, POPU, PUSH, PUSHU direct b1 = insn.get_next_byte(); size = (nibble0 < 8) ? dt_byte : dt_word; if ( b1 & 8 ) // DJNZ { if ( b1 & 7 ) return 0; insn.itype = XA_djnz; op_rd(insn.Op1, b1>>4, size); op_rel(insn, insn.Op2, (signed char)insn.get_next_byte()); } else { // POP, POPU, PUSH, PUSHU if ( b1 & 0xc0 ) return 0; insn.itype = xa_pushpop[3-((b1>>4)&3)]; op_mm(insn.Op1, ((b1 & 7) << 8) + insn.get_next_byte(), size); } break; case 0x90: // CPL, DA, SEXT case 0x98: // CPL & MOV [Rd+], [Rs+] & MOV direct, [Rs] b1 = insn.get_next_byte(); size = (nibble0 < 8) ? dt_byte : dt_word; switch ( b1 & 0x0f ) { case 0x0: // MOV [Rd+], [Rs+] case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: case 0x7: // MOV [Rd+], [Rs+] if ( b1 & 0x80 ) return 0; insn.itype = XA_mov; op_ph(insn.Op1, fRip, (b1>>4)&7, size); op_ph(insn.Op2, fRip, (b1&7), size); break; case 0x8: // DA case 0x9: // SEXT case 0xA: // CPL case 0xB: // NEG insn.itype = xa_misc[b1&3]; op_rd(insn.Op1, b1>>4, size); if ( (nibble0&8) != 0 && insn.itype == XA_da ) return 0; break; case 0xC: // MOVC A,[A+PC] 904C if ( (nibble0 != 0) & ((b1&0xf0) != 0xc0) ) return 0; insn.itype = XA_movc; op_rd(insn.Op1, rA, dt_byte); op_ph(insn.Op2, fApc, 0, dt_byte); break; case 0xE: // MOVC A,[A+DPTR] 904E if ( (nibble0 != 0) & ((b1&0xf0) != 0xc0) ) return 0; insn.itype = XA_movc; op_rd(insn.Op1, rA, dt_byte); op_ph(insn.Op2, fAdptr, 0, dt_byte); break; case 0xF: // MOV Rd,USP & MOV USP, Rs insn.itype = XA_mov; if ( nibble0&8 ) // USP,Rs { op_rd(insn.Op1, rUSP-rR0, dt_word); op_rd(insn.Op2, b1>>4, dt_word); } else { op_rd(insn.Op1, b1>>4, dt_word); op_rd(insn.Op2, rUSP-rR0, dt_word); } break; default: return 0; } break; case 0x97: // {JB,JBC,JNB} bit, rel8 & MOV direct, direct case 0x9F: // {JB,JBC,JNB} bit, rel8 & MOV direct, direct b1 = insn.get_next_byte(); if ( (b1 & 0x88) == 0x00 ) // MOV direct, direct { insn.itype = XA_mov; size = (nibble0 < 8) ? dt_byte : dt_word; op_mm(insn.Op1, ((b1 & 0x70) << 4) + (uchar)insn.get_next_byte(), size); op_mm(insn.Op2, ((b1 & 0x7) << 8) + (uchar)insn.get_next_byte(), size); } else { if ( nibble0 & 8 ) return 0; switch ( b1 & 0xfc ) { case 0x80: // JB case 0xA0: // JNB case 0xC0: // JBC insn.itype = xa_Jxx[(b1>>5)&3]; op_bit(insn.Op1, o_bit, ((b1&3)<<8) + (uchar)insn.get_next_byte()); op_rel(insn, insn.Op2, (signed char)insn.get_next_byte()); break; default: return 0; } } break; case 0xA0: // MOV.B direct, [Rs] & [Rd], direct & XCH case 0xA8: // MOV.W direct, [Rs] & [Rd], direct & XCH b1 = insn.get_next_byte(); size = (nibble0 < 8) ? dt_byte : dt_word; if ( b1 & 8 ) // XCH { insn.itype = XA_xch; op_rd(insn.Op1, b1>>4, size); op_mm(insn.Op2, ((b1 & 7) << 8) + (uchar)insn.get_next_byte(), size); } else { // MOV insn.itype = XA_mov; if ( b1 & 0x80 ) // direct, [Rs] { op_mm(insn.Op1, ((b1 & 7) << 8) + (uchar)insn.get_next_byte(), size); op_ds(insn.Op2, fRi, (b1>>4)&7, 0, size); } else { op_ds(insn.Op1, fRi, (b1>>4)&7, 0, size); op_mm(insn.Op2, ((b1 & 7) << 8) + (uchar)insn.get_next_byte(), size); } } break; case 0xA7: // MOVX case 0xAF: // MOVX insn.itype = XA_movx; size = (nibble0 < 8) ? dt_byte : dt_word; b1 = insn.get_next_byte(); if ( b1 & 8 ) // [Rd],Rs { op_ds(insn.Op1, fRi, b1&0x7, 0, size); op_rd(insn.Op2, b1>>4, size); } else { // Rd,[Rs] op_rd(insn.Op1, b1>>4, size); op_ds(insn.Op2, fRi, b1&0x7, 0, size); } break; case 0xB0: // RR case 0xB7: // RRC case 0xB8: // RR case 0xBF: // RRC insn.itype = (nibble0 & 7) ? XA_rrc : XA_rr; size = (nibble0 < 8) ? dt_byte : dt_word; b1 = insn.get_next_byte(); op_rd(insn.Op1, b1>>4, size); op_im(insn.Op2, b1&0xf, size); break; default: return 0; } break; default: switch ( nibble1 ) { case 0: // ADD case 1: // ADDC case 2: // SUB case 3: // SUBB case 4: // CMP case 5: // AND case 6: // OR case 7: // XOR case 8: // MOV insn.itype = xa_basic[nibble1]; size = (nibble0 < 8) ? dt_byte : dt_word; b1 = insn.get_next_byte(); switch ( nibble0 & 0x7 ) { case 0x1: // OP Rd,Rs op_rd(insn.Op1, b1>>4, size); op_rd(insn.Op2, b1&0xF, size); break; case 0x2: // OP Rd,[Rs] if ( b1 & 8 ) // [Rd], Rs { op_ds(insn.Op1, fRi, b1&7, 0, size); op_rd(insn.Op2, b1>>4, size); } else { op_rd(insn.Op1, b1>>4, size); op_ds(insn.Op2, fRi, b1&7, 0, size); } break; case 0x3: // OP Rd,[Rs+] if ( b1 & 8 ) // [Rd], Rs { op_ph(insn.Op1, fRip, (b1&7), size); op_rd(insn.Op2, b1>>4, size); } else { op_rd(insn.Op1, b1>>4, size); op_ph(insn.Op2, fRip, (b1&7), size); } break; case 0x4: // OP Rd,[Rs+o8] if ( b1 & 8 ) // [Rd], Rs { op_ds(insn.Op1, fRid8, (b1&7), (signed char)insn.get_next_byte(), size); op_rd(insn.Op2, b1>>4, size); } else { op_rd(insn.Op1, b1>>4, size); op_ds(insn.Op2, fRid8, (b1&7), (signed char)insn.get_next_byte(), size); } break; case 0x5: // OP Rd,[Rs+o16] if ( b1 & 8 ) // [Rd], Rs { op_ds(insn.Op1, fRid16, (b1&7), (int)ua_next_word_be(insn), size); op_rd(insn.Op2, b1>>4, size); } else { op_rd(insn.Op1, b1>>4, size); op_ds(insn.Op2, fRid16, (b1&7), (int)ua_next_word_be(insn), size); } break; case 0x6: // OP Rd,direct if ( b1 & 8 ) // direct, Rs { op_mm(insn.Op1, ((b1 & 7) << 8) + insn.get_next_byte(), size); op_rd(insn.Op2, b1>>4, size); } else { op_rd(insn.Op1, b1>>4, size); op_mm(insn.Op2, ((b1 & 7) << 8) + insn.get_next_byte(), size); } break; } break; case 9: // Immediate operations b1 = insn.get_next_byte(); insn.itype = xa_basic[b1 & 0x0f]; size = (nibble0 < 8) ? dt_byte : dt_word; switch ( nibble0 & 0x7 ) { case 0x1: op_rd(insn.Op1, b1>>4, size); op_im(insn.Op2, (size == dt_byte) ? insn.get_next_byte() : ua_next_word_be(insn), size); break; case 0x2: op_ds(insn.Op1, fRi, (b1>>4) & 0x7, 0, size); op_im(insn.Op2, (size == dt_byte) ? insn.get_next_byte() : ua_next_word_be(insn), size); break; case 0x3: op_ph(insn.Op1, fRip, (b1>>4) & 0x7, size); op_im(insn.Op2, (size == dt_byte) ? insn.get_next_byte() : ua_next_word_be(insn), size); break; case 0x4: op_ds(insn.Op1, fRid8, (b1>>4) & 0x7, (signed char)insn.get_next_byte(), size); op_im(insn.Op2, (size == dt_byte) ? insn.get_next_byte() : ua_next_word_be(insn), size); break; case 0x5: op_ds(insn.Op1, fRid16, (b1>>4) & 0x7, (int)ua_next_word_be(insn), size); op_im(insn.Op2, (size == dt_byte) ? insn.get_next_byte() : ua_next_word_be(insn), size); break; case 0x6: op_mm(insn.Op1, (((b1>>4) & 0x7) << 8) + insn.get_next_byte(), size); op_im(insn.Op2, (size == dt_byte) ? insn.get_next_byte() : ua_next_word_be(insn), size); break; } break; case 0xA: // ADDS case 0xB: // MOVS b1 = insn.get_next_byte(); insn.itype = (nibble1 == 0x0A) ? XA_adds : XA_movs; size = (nibble0 < 8) ? dt_byte : dt_word; off = b1 & 0xf; if ( off > 7 ) off -= 16; op_im(insn.Op2, (int32)off, size); switch ( nibble0 & 0x7 ) { case 0x1: op_rd(insn.Op1, b1>>4, size); break; case 0x2: op_ds(insn.Op1, fRi, (b1>>4) & 0x7, 0, size); break; case 0x3: op_ph(insn.Op1, fRip, (b1>>4) & 0x7, size); break; case 0x4: op_ds(insn.Op1, fRid8, (b1>>4) & 0x7, (signed char)insn.get_next_byte(), size); break; case 0x5: op_ds(insn.Op1, fRid16, (b1>>4) & 0x7, (int)ua_next_word_be(insn), size); break; case 0x6: op_mm(insn.Op1, (((b1>>4) & 0x7) << 8) + (uchar)insn.get_next_byte(), size); break; } break; } } } else { // nibble1 > B switch ( nibble1 ) { case 0xC: // Shifts, CALL, FCALL switch ( nibble0 & 0xc ) { case 0x0: size = dt_byte; break; case 0x8: size = dt_word; break; case 0xC: size = dt_dword; break; case 0x4: // Special instructions switch ( nibble0 ) { case 4: // FCALL addr24 insn.itype = XA_fcall; insn.Op1.type = o_far; insn.Op1.dtype = dt_code; insn.Op1.addr = (ushort)ua_next_word_be(insn); insn.Op1.specval = (uchar)insn.get_next_byte(); break; case 5: // CALL rel16 insn.itype = XA_call; op_rel(insn, insn.Op1, (int)ua_next_word_be(insn)); break; case 6: // CALL [Rs] b1 = insn.get_next_byte(); if ( b1 & 0xf8 ) return 0; insn.itype = XA_call; op_ds(insn.Op1, fRi, b1&7, 0, dt_word); break; default: return 0; } break; } if ( insn.itype == XA_null ) { insn.itype = xa_shifts[nibble0 & 3]; b1 = insn.get_next_byte(); op_rd(insn.Op1, b1>>4, size); op_rd(insn.Op2, b1&0xf, size); } break; case 0xD: // JMP, FJMP, rotations & shifts with #d4/#d5 switch ( nibble0 & 0xC ) { case 0x4: // Special instructions switch ( nibble0 ) { case 7: // rotate break; case 4: // FJMP addr24 insn.itype = XA_fjmp; insn.Op1.type = o_far; insn.Op1.dtype = dt_code; insn.Op1.addr = (ushort)ua_next_word_be(insn); insn.Op1.specval = (uchar)insn.get_next_byte(); break; case 5: // JMP rel16 insn.itype = XA_jmp; op_rel(insn, insn.Op1, (int)ua_next_word_be(insn)); break; case 6: // specials insn.itype = XA_jmp; b1 = insn.get_next_byte(); switch ( b1 & 0xf8 ) { case 0x10: // RESET if ( b1 & 7 ) return 0; insn.itype = XA_reset; break; case 0x30: // TRAP case 0x38: // TRAP insn.itype = XA_trap; op_im(insn.Op1, b1 & 0xf, dt_byte); break; case 0x40: // JMP [A+DPTR] if ( (b1&7) != 6 ) return 0; op_ph(insn.Op1, fAdptr, 0, dt_word); break; case 0x60: // JMP [[Rs+]] op_ph(insn.Op1, fRipi, b1&7, dt_word); break; case 0x70: // JMP [Rs] op_ph(insn.Op1, fRi, b1&7, dt_word); break; case 0x80: // RET if ( b1 & 7 ) return 0; insn.itype = XA_ret; break; case 0x90: // RETI if ( b1 & 7 ) return 0; insn.itype = XA_reti; break; default: return 0; } break; default: return 0; } break; case 0x0: size = dt_byte; break; case 0x8: size = dt_word; break; case 0xC: size = dt_dword; break; } if ( insn.itype == XA_null ) { insn.itype = xa_shifts[nibble0 & 3]; if ( insn.itype == XA_norm ) { // rotations size = (nibble0 < 8) ? dt_byte : dt_word; insn.itype = (nibble0 & 4) ? XA_rlc : XA_rl; b1 = insn.get_next_byte(); op_rd(insn.Op1, b1>>4, size); op_im(insn.Op2, b1&0xf, size); } else { // shifts b1 = insn.get_next_byte(); if ( size == dt_dword ) { op_rd(insn.Op1, (b1>>4)&0x0e, size); // Only even registers allowed op_im(insn.Op2, b1&0x1f, size); } else { op_rd(insn.Op1, b1>>4, size); op_im(insn.Op2, b1&0xf, size); } } } break; case 0xE: // DIV & MUL & cjne & jz/jnz b1 = insn.get_next_byte(); switch ( nibble0 ) { case 0x0: // MULU.B Rd,Rs insn.itype = XA_mulu; op_rd(insn.Op1, b1>>4, dt_byte); op_rd(insn.Op2, b1&0xf, dt_byte); break; case 0x1: // DIVU.B Rd,Rs insn.itype = XA_divu; op_rd(insn.Op1, b1>>4, dt_byte); op_rd(insn.Op2, b1&0xf, dt_byte); break; case 0x4: // MULU.W Rd,Rs insn.itype = XA_mulu; op_rd(insn.Op1, b1>>4, dt_word); op_rd(insn.Op2, b1&0xf, dt_word); break; case 0x5: // DIVU.W Rd,Rs insn.itype = XA_divu; op_rd(insn.Op1, b1>>4, dt_word); op_rd(insn.Op2, b1&0xf, dt_word); break; case 0x6: // MUL.W Rd,Rs insn.itype = XA_mul; op_rd(insn.Op1, b1>>4, dt_word); op_rd(insn.Op2, b1&0xf, dt_word); break; case 0x7: // DIV.W Rd, Rs insn.itype = XA_div; op_rd(insn.Op1, b1>>4, dt_word); op_rd(insn.Op2, b1&0xf, dt_word); break; case 0x8: // MUL & DIV Rd,#8 switch ( b1 & 0xf ) { case 0x0: // MULU.B Rd,#d8 insn.itype = XA_mulu; size = dt_byte; break; case 0x1: // DIVU.B Rd,#d8 insn.itype = XA_divu; size = dt_byte; break; case 0x3: // DIVU.W Rd,#d8 insn.itype = XA_divu; size = dt_word; break; case 0xB: // DIV.W Rd,#d8 insn.itype = XA_div; size = dt_word; break; default: return 0; } op_rd(insn.Op1, b1>>4, size); op_im(insn.Op2, insn.get_next_byte(), dt_word); break; case 0x9: // MUL & DIV Rd,#16 switch ( b1 & 0xf ) { case 0x0: // MULU.W Rd,#d16 insn.itype = XA_mulu; size = dt_word; break; case 0x1: // DIVU.D Rd,#d16 if ( b1&0x10 ) return 0; insn.itype = XA_divu; size = dt_dword; break; case 0x8: // MUL.W Rd,#d16 insn.itype = XA_mul; size = dt_word; break; case 0x9: // DIV.D Rd,#d16 if ( b1&0x10 ) return 0; insn.itype = XA_div; size = dt_dword; break; default: return 0; } op_rd(insn.Op1, b1>>4, size); op_im(insn.Op2, ua_next_word_be(insn), dt_byte); break; case 0xD: // DIVU.D Rd,Rs if ( b1&0x10 ) return 0; insn.itype = XA_divu; op_rd(insn.Op1, b1>>4, dt_dword); op_rd(insn.Op2, b1&0xf, dt_dword); break; case 0xF: // DIV.D Rd, Rs if ( b1&0x10 ) return 0; insn.itype = XA_div; op_rd(insn.Op1, b1>>4, dt_dword); op_rd(insn.Op2, b1&0xf, dt_dword); break; case 0x2: // cjne direct & [Rd] & DJNZ direct case 0xA: // cjne direct & [Rd] & DJNZ direct size = (nibble0 < 8) ? dt_byte : dt_word; if ( b1 & 8 ) { // DJNZ direct, rel8 insn.itype = XA_djnz; op_mm(insn.Op1, ((b1&7)<<8)+(uchar)insn.get_next_byte(), size); op_rel(insn, insn.Op2, (signed char)insn.get_next_byte()); } else { // CJNE.s Rd, direct, rel8 insn.itype = XA_cjne; op_rd(insn.Op1, b1>>4, size); op_mm(insn.Op2, ((b1&7)<<8)+(uchar)insn.get_next_byte(), size); op_rel(insn, insn.Op3, (signed char)insn.get_next_byte()); } break; case 0x3: // cjne #,rel case 0xB: // cjne #,rel if ( b1 & 7 ) return 0; insn.itype = XA_cjne; size = (nibble0 < 8) ? dt_byte : dt_word; off = insn.get_next_byte(); if ( b1 & 0x8 ) op_ds(insn.Op1, fRi, b1>>4, 0, size); else op_rd(insn.Op1, b1>>4, size); op_im(insn.Op2, size == dt_byte ? insn.get_next_byte() : ua_next_word_be(insn), size); op_rel(insn, insn.Op3, off); break; case 0xC: // JZ rel8 insn.itype = XA_jz; op_rel(insn, insn.Op1, (signed char)b1); break; case 0xE: // JNZ rel8 insn.itype = XA_jnz; op_rel(insn, insn.Op1, (signed char)b1); break; default: return 0; } break; case 0xF: // Bxx insn.itype = xa_branches[nibble0]; if ( nibble0 != 0xF ) { op_rel(insn, insn.Op1, (signed char)insn.get_next_byte()); } break; } } return insn.size; } //---------------------------------------------------------------------- // analyze an instruction int xa_t::ana(insn_t *_insn) { insn_t &insn = *_insn; insn.itype = XA_null; insn.Op1.dtype = dt_byte; insn.Op2.dtype = dt_byte; insn.Op3.dtype = dt_byte; switch ( ptype ) //-V785 Constant expression in switch statement { case prc_xaG3: return ana_basic(insn); } return 0; //lint !e527 statement is unreachable }