/* * Interactive disassembler (IDA). * Version 3.05 * Copyright (c) 1990-95 by Ilfak Guilfanov. * ALL RIGHTS RESERVED. * FIDO: 2:5020/209 * E-mail: ig@estar.msk.su * */ #include "i860.hpp" //---------------------------------------------------------------------- void i860_t::op_s1ni(op_t &x) { x.reg = op_s1(); x.type = o_reg; } //---------------------------------------------------------------------- void i860_t::op_s2(op_t &x) { x.reg = op_s2(); x.type = o_reg; } //---------------------------------------------------------------------- void i860_t::op_fs1(op_t &x) { x.reg = op_s1() + R_f0; x.type = o_reg; } //---------------------------------------------------------------------- void i860_t::op_fs2(op_t &x) { x.reg = op_s2() + R_f0; x.type = o_reg; } //---------------------------------------------------------------------- void i860_t::op_s1s(op_t &x) { if ( code & bit26 ) // immediate src1 { x.type = o_imm; x.value = short(code); } else { op_s1ni(x); } } //---------------------------------------------------------------------- void i860_t::op_s1u(op_t &x) { if ( code & bit26 ) // immediate src1 { x.type = o_imm; x.value = ushort(code); } else { op_s1ni(x); } } //---------------------------------------------------------------------- void i860_t::op_s1s2(op_t &x) { x.reg = op_s2(); if ( code & bit26 ) // immediate src1 { x.type = o_displ; x.addr = short(code); if ( code & bit28 ) x.addr &= ~1L; if ( x.reg == 0 ) x.type = o_mem; } else { x.type = o_phrase; x.addr = op_s1(); } } //---------------------------------------------------------------------- void i860_t::op_dest(op_t &x) { x.reg = op_ds(); x.type = o_reg; } //---------------------------------------------------------------------- void i860_t::op_fdest(op_t &x) { x.reg = op_ds() + R_f0; x.type = o_reg; } //---------------------------------------------------------------------- char i860_t::dsize_28_0(void) const { if ( code & bit28 ) return (code & bit0) ? dt_dword : dt_word; return dt_byte; } //---------------------------------------------------------------------- char i860_t::dsize_1_2(void) const { if ( code & bit1 ) return dt_dword; return (code & bit2) ? dt_byte16 : dt_qword; } //---------------------------------------------------------------------- char i860_t::dsize_10_9(void) const { if ( code & bit10 ) return (code & bit9) ? dt_dword : dt_dword; return (code & bit9) ? dt_word : dt_byte; } //---------------------------------------------------------------------- void i860_t::op_stoff(op_t &x) { x.type = o_displ; x.reg = op_s2(); x.addr = short((code & 0x7FF) + (op_ds() << 11)); // extend sign } //---------------------------------------------------------------------- //lint -e{1764} Reference parameter '' could be declared const ref void i860_t::op_bteoff(insn_t &insn, op_t &x) { x.type = o_near; x.addr = insn.ea + insn.size + (sval_t((code & 0x7FF)+(op_ds()<<11)) << 2); // extend sign x.dtype = dt_code; } //---------------------------------------------------------------------- //lint -e{1764} Reference parameter '' could be declared const ref void i860_t::op_lbroff(insn_t &insn, op_t &x) const { x.type = o_near; sval_t lbr = code & 0x3FFFFFFL; if ( code & bit25 ) lbr |= ~uval_t(0x3FFFFFF); // extend sign x.addr = insn.ea + insn.size + (lbr << 2); x.dtype = dt_code; } //---------------------------------------------------------------------- void i860_t::op_ainc(op_t &x) { op_s1s2(x); if ( code & bit0 ) x.reg = - x.reg; //lint !e2501 negation of value of unsigned type if ( x.type == o_displ || x.type == o_mem ) { x.addr &= ~3L; if ( (code & bit1) == 0 ) x.addr &= ~7L; } x.dtype = dsize_1_2(); } //---------------------------------------------------------------------- int i860_t::op_ctl(op_t &x) { op_s2(x); if ( x.reg > (is860XP() ? 11 : 5) ) return 0; x.reg += R_fir; return 1; } //---------------------------------------------------------------------- int i860_t::i860_ana(insn_t *_insn) { if ( _insn == NULL ) return 0; insn_t &insn = *_insn; if ( (insn.ea & 3) != 0 ) return 0; // only four byte boundaries code = insn.get_next_dword(); insn.Op1.dtype = dt_dword; insn.Op2.dtype = dt_dword; insn.Op3.dtype = dt_dword; insn.itype = I860_null; switch ( code>>26 ) { case 0x00: case 0x01: case 0x04: case 0x05: insn.itype = I860_ld; op_s1s2(insn.Op1); op_dest(insn.Op2); insn.Op1.dtype = dsize_28_0(); insn.Op2.dtype = insn.Op1.dtype; break; case 0x03: case 0x07: insn.itype = I860_st; op_s1ni(insn.Op2); op_stoff(insn.Op1); insn.Op1.dtype = dsize_28_0(); insn.Op2.dtype = insn.Op1.dtype; break; case 0x02: insn.itype = I860_ixfr; op_s1ni(insn.Op1); op_fdest(insn.Op2); break; case 0x08: case 0x09: insn.itype = I860_fld; op_ainc(insn.Op1); op_fdest(insn.Op2); insn.Op2.dtype = insn.Op1.dtype; break; case 0x0A: case 0x0B: insn.itype = I860_fst; op_fdest(insn.Op1); op_ainc(insn.Op2); insn.Op1.dtype = insn.Op2.dtype; break; case 0x0D: insn.itype = I860_flush; op_ainc(insn.Op1); break; case 0x0F: insn.itype = I860_pst_d; op_fdest(insn.Op1); op_ainc(insn.Op2); insn.Op1.dtype = insn.Op2.dtype; break; case 0x0C: if ( !op_ctl(insn.Op1) ) break; op_dest(insn.Op2); insn.itype = I860_ld_c; break; case 0x0E: op_s1ni(insn.Op1); if ( !op_ctl(insn.Op2) ) break; insn.itype = I860_st_c; break; case 0x10: insn.itype = I860_bri; op_s1ni(insn.Op1); break; case 0x11: insn.itype = I860_trap; op_s1ni(insn.Op1); op_s2(insn.Op2); op_dest(insn.Op3); break; case 0x12: FPunit(insn); break; case 0x13: COREunit(insn); break; case 0x14: case 0x16: case 0x15: case 0x17: insn.itype = (code & bit27) ? I860_bte : I860_btne; if ( code & bit26 ) // small immediate { insn.Op1.type = o_imm; insn.Op1.value = op_s1(); } else { op_s1ni(insn.Op1); } op_s2(insn.Op2); op_bteoff(insn, insn.Op3); break; case 0x18: case 0x19: op_ainc(insn.Op1); op_fdest(insn.Op2); insn.Op2.dtype = insn.Op1.dtype; if ( !is860XP() && insn.Op2.dtype == dt_byte16 ) break; insn.itype = I860_pfld; break; case 0x1A: insn.itype = I860_br; op_lbroff(insn, insn.Op1); break; case 0x1B: insn.itype = I860_call; op_lbroff(insn, insn.Op1); break; case 0x1C: case 0x1D: insn.itype = (code & bit26) ? I860_bc_t : I860_bc; op_lbroff(insn, insn.Op1); break; case 0x1E: case 0x1F: insn.itype = (code & bit26) ? I860_bnc_t : I860_bnc; op_lbroff(insn, insn.Op1); break; case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: insn.itype = (code & bit27) ? (code & bit28) ? I860_subs : I860_subu : (code & bit28) ? I860_adds : I860_addu; op_s1s(insn.Op1); op_s2(insn.Op2); op_dest(insn.Op3); break; case 0x28: case 0x29: case 0x2A: case 0x2B: insn.itype = (code & bit27) ? I860_shr : I860_shl; op_s1u(insn.Op1); op_s2(insn.Op2); op_dest(insn.Op3); break; case 0x2C: insn.itype = I860_shrd; op_s1ni(insn.Op1); op_s2(insn.Op2); op_dest(insn.Op3); break; case 0x2D: insn.itype = I860_bla; op_s1ni(insn.Op1); op_s2(insn.Op2); op_bteoff(insn, insn.Op3); break; case 0x2E: case 0x2F: insn.itype = I860_shra; op_s1u(insn.Op1); op_s2(insn.Op2); op_dest(insn.Op3); break; case 0x30: case 0x31: case 0x33: insn.itype = (code & bit27) ? I860_andh : I860_and; goto common; case 0x34: case 0x35: case 0x37: insn.itype = (code & bit27) ? I860_andnoth : I860_andnot; goto common; case 0x38: case 0x39: case 0x3B: insn.itype = (code & bit27) ? I860_orh : I860_or; goto common; case 0x3C: case 0x3D: case 0x3F: insn.itype = (code & bit27) ? I860_xorh : I860_xor; common: op_s1u(insn.Op1); op_s2(insn.Op2); op_dest(insn.Op3); break; } if ( insn.itype == I860_null ) return 0; return 4; } //---------------------------------------------------------------------- void i860_t::COREunit(insn_t &insn) { if ( (code & 0x1E0) != 0 ) return; switch ( code & 0x1F ) { case 1: insn.itype = I860_lock; break; case 2: insn.itype = I860_calli; op_s1ni(insn.Op1); insn.Op1.dtype = dt_code; break; case 4: insn.itype = I860_introvr; break; case 7: insn.itype = I860_unlock; break; case 8: if ( !is860XP() ) break; insn.itype = I860_ldio; common: op_s2(insn.Op1); op_dest(insn.Op2); insn.Op1.dtype = dsize_10_9(); insn.Op2.dtype = insn.Op1.dtype; break; case 9: if ( !is860XP() ) break; insn.itype = I860_stio; op_s1ni(insn.Op1); op_s2(insn.Op2); insn.Op1.dtype = dsize_10_9(); insn.Op2.dtype = insn.Op1.dtype; break; case 0x0A: if ( !is860XP() ) break; insn.itype = I860_ldint; goto common; case 0x0B: if ( !is860XP() ) break; insn.itype = I860_scyc; op_s2(insn.Op1); break; } } //---------------------------------------------------------------------- void i860_t::FPunit(insn_t &insn) { switch ( code & 0x7F ) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x0E: case 0x0F: case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: { static const int Pintrs[] = { I860_r2p1, I860_r2pt, I860_r2ap1, I860_r2apt, I860_i2p1, I860_i2pt, I860_i2ap1, I860_i2apt, I860_rat1p2, I860_m12apm, I860_ra1p2, I860_m12ttpa, I860_iat1p2, I860_m12tpm, I860_ia1p2, I860_m12tpa, I860_r2s1, I860_r2st, I860_r2as1, I860_r2ast, I860_i2s1, I860_i2st, I860_i2as1, I860_i2ast, I860_rat1s2, I860_m12asm, I860_ra1s2, I860_m12ttsa, I860_iat1s2, I860_m12tsm, I860_ia1s2, I860_m12tsa }; static const int Mintrs[] = { I860_mr2p1, I860_mr2pt, I860_mr2mp1,I860_mr2mpt, I860_mi2p1, I860_mi2pt, I860_mi2mp1,I860_mi2mpt, I860_mrmt1p2,I860_mm12mpm,I860_mrm1p2,I860_mm12ttpm, I860_mimt1p2,I860_mm12tpm,I860_mim1p2,I860_null, I860_mr2s1, I860_mr2st, I860_mr2ms1,I860_mr2mst, I860_mi2s1, I860_mi2st, I860_mi2ms1,I860_mi2mst, I860_mrmt1s2,I860_mm12msm,I860_mrm1s2,I860_mm12ttsm, I860_mimt1s2,I860_mm12tsm,I860_mim1s2,I860_null }; if ( isDS() ) break; insn.itype = uint16(((code & Pbit) ? Pintrs : Mintrs)[ int(code) & 0xF ]); } common3: op_fs1(insn.Op1); op_fs2(insn.Op2); op_dest(insn.Op3); common: if ( code & Dbit ) insn.auxpref |= aux_dual; if ( code & Sbit ) insn.auxpref |= aux_sdbl; if ( code & Rbit ) insn.auxpref |= aux_rdbl; break; case 0x20: if ( isDS() ) break; insn.itype = (code & Pbit) ? I860_pfmul : I860_fmul; goto common3; case 0x21: insn.itype = I860_fmlow_dd; goto common3; case 0x22: if ( isDS() ) break; insn.itype = I860_frcp; common22: op_fs2(insn.Op1); op_dest(insn.Op2); goto common; case 0x23: if ( isDS() ) break; insn.itype = I860_frsqr; goto common22; case 0x24: if ( (code & (Rbit|Sbit)) != (Rbit|Sbit) ) break; insn.itype = I860_pfmul3_dd; goto common3; case 0x30: if ( isDS() ) break; insn.itype = (code & Pbit) ? I860_pfadd : I860_fadd; goto common3; case 0x31: if ( isDS() ) break; insn.itype = (code & Pbit) ? I860_pfsub : I860_fsub; goto common3; case 0x32: if ( !isSDDD() ) break; insn.itype = (code & Pbit) ? I860_pfix : I860_fix; goto common21; case 0x33: insn.itype = (code & Pbit) ? I860_pfamov : I860_famov; goto common21; case 0x34: if ( isDS() ) break; insn.itype = (code & Rbit) ? I860_pfle : I860_pfgt; goto common3; case 0x35: if ( isDS() ) break; insn.itype = I860_pfeq; goto common3; case 0x3A: if ( !isSDDD() ) break; insn.itype = (code & Pbit) ? I860_pftrunc : I860_ftrunc; goto common21; case 0x40: insn.itype = I860_fxfr; common21: op_fs1(insn.Op1); op_dest(insn.Op2); goto common; case 0x49: if ( !isSSDD() ) break; insn.itype = (code & Pbit) ? I860_pfiadd : I860_fiadd; goto common3; case 0x4D: if ( !isSSDD() ) break; insn.itype = (code & Pbit) ? I860_pfisub : I860_fisub; goto common3; case 0x57: insn.itype = (code & Pbit) ? I860_pfzchkl: I860_fzchkl;goto common3; case 0x5F: insn.itype = (code & Pbit) ? I860_pfzchks: I860_fzchks;goto common3; case 0x50: insn.itype = (code & Pbit) ? I860_pfaddp : I860_faddp; goto common3; case 0x51: insn.itype = (code & Pbit) ? I860_pfaddz : I860_faddz; goto common3; case 0x5A: insn.itype = (code & Pbit) ? I860_pform : I860_form; goto common21; } }