/* * Panasonic MN102 (PanaXSeries) processor module for IDA. * Copyright (c) 2000-2006 Konstantin Norvatoff, * Freeware. */ #include "pan.hpp" //--------------------------------------------------------------------------- // internal use only static uint32 LoadData(insn_t &insn, int bytes) { uint32 dt = 0; // load data for ( int i=0; i < bytes; i++ ) { uint32 nb = insn.get_next_byte(); dt |= nb << (8*i); } return dt; } //--------------------------------------------------------------------------- // load a label's address static void SetLabel(insn_t &insn, op_t &op, int bytes) { uint32 off; op.type = o_near; // load the data off = LoadData(insn, bytes); // sign extend switch ( bytes ) { // 1 byte case 1: if ( off&0x000080L ) off |= ~0x00007FL; break; // 2 bytes case 2: if ( off&0x008000L ) off |= ~0x007FFFL; break; // 3 bytes case 3: if ( off&0x800000L ) off |= ~0x7FFFFFL; break; } // sprintf(cc,"%lx",off); // msg(cc); op.addr = op.value = (off+(uint32)insn.size+insn.ea) & 0xFFFFFFL; // sprintf(cc,"==%lx",op.value); // msg(cc); // sprintf(cc,"==%lx",insn.ea); // msg(cc); // msg("\n"); } //--------------------------------------------------------------------------- // set immediate operand, only numbers static void SetImm(insn_t &insn, op_t &op, int bytes) { op.type = o_imm; // immediate op.dtype = dt_dword; op.addr = op.value = LoadData(insn, bytes); // number value } //--------------------------------------------------------------------------- static void SetImmC(op_t &op, int Val) { op.type = o_imm; // immediate op.dtype = dt_dword; op.flags |= OF_NUMBER; // number only op.addr = op.value = Val; // value } //--------------------------------------------------------------------------- // registe addressing static void SetReg(op_t &op,uchar Reg) { op.type = o_reg; op.reg = Reg; op.addr = op.value = 0; } //--------------------------------------------------------------------------- // indirect addressing static void SetRReg(op_t &op,uchar Reg) { op.type = o_reg; op.reg = Reg|0x80; // indirect op.addr = op.value = 0; } //--------------------------------------------------------------------------- // indirect addressing with a displacement static void SetDisplI(op_t &op,uchar Reg, uchar RegI) { op.type = o_reg; op.reg = (Reg&0x0F)|0x90|((RegI&3)<<5); op.addr = op.value = 0; } //--------------------------------------------------------------------------- // indirect addressing with a displacement static void SetDispl(insn_t &insn, op_t &op,uchar Reg, int OffSize) { op.type = o_displ; op.dtype = dt_dword; op.reg = Reg; op.addr = op.value = LoadData(insn, OffSize); } //--------------------------------------------------------------------------- // memory addressing static void SetMem(insn_t &insn, op_t &op, int AddrSize, uchar DataSize) { op.type = o_mem; op.addr = op.value = LoadData(insn, AddrSize); op.dtype = DataSize; } //--------------------------------------------------------------------------- // analyzer int idaapi mn102_ana(insn_t *_insn) { insn_t &insn = *_insn; uchar R1, R2; // read first byte uchar code = insn.get_next_byte(); // analyze high bits R1 = code&3; R2 = (code>>2)&3; insn.Op1.specflag1 = 0; insn.Op2.specflag1 = 0; switch ( code>>4 ) { // mov Dm, (An) case 0x00: insn.itype = mn102_mov; SetReg(insn.Op1,R1+rD0); SetRReg(insn.Op2,R2+rA0); break; // movb Dm, (An) case 0x01: insn.itype = mn102_movb; SetReg(insn.Op1,R1+rD0); SetRReg(insn.Op2,R2+rA0); break; // mov (An), Dm case 0x02: insn.itype = mn102_mov; SetReg(insn.Op2,R1+rD0); SetRReg(insn.Op1,R2+rA0); break; // movbu (An), Dm case 0x03: insn.itype = mn102_movbu; SetReg(insn.Op2,R1+rD0); SetRReg(insn.Op1,R2+rA0); break; // mov Dm, (d8,An) case 0x04: insn.itype = mn102_mov; SetReg(insn.Op1,R1+rD0); SetDispl(insn, insn.Op2,R2+rA0,1); break; // mov An, (d8,An); case 0x05: insn.itype = mn102_mov; SetReg(insn.Op1,R1+rA0); SetDispl(insn, insn.Op2,R2+rA0,1); break; // mov (d8,An), Dm case 0x06: insn.itype = mn102_mov; SetReg(insn.Op2,R1+rD0); SetDispl(insn, insn.Op1,R2+rA0,1); break; // mov (d8,An), Am case 0x07: insn.itype = mn102_mov; SetReg(insn.Op2,R1+rA0); SetDispl(insn, insn.Op1,R2+rA0,1); break; // mov Dn, Dm or mov imm8,Dn case 0x08: insn.itype = mn102_mov; if ( (code&3) == ((code>>2)&3) ) { // mov imm, Dn SetImm(insn, insn.Op1,1); SetReg(insn.Op2,R1+rD0); } else { SetReg(insn.Op1,R2+rD0); SetReg(insn.Op2,R1+rD0); } break; // add Dn, Dm case 0x09: insn.itype = mn102_add; SetReg(insn.Op1,R2+rD0); SetReg(insn.Op2,R1+rD0); break; // Sub Dn,Dm case 0x0A: insn.itype = mn102_sub; SetReg(insn.Op1,R2+rD0); SetReg(insn.Op2,R1+rD0); break; // Extx* Dn case 0x0B: switch ( code&0xC ) { // extx case 0x00: insn.itype = mn102_extx; break; case 0x04: insn.itype = mn102_extxu; break; case 0x08: insn.itype = mn102_extxb; break; case 0x0C: insn.itype = mn102_extxbu; break; } SetReg(insn.Op1,R1+rD0); break; // mov* Dn, (mem) case 0x0C: switch ( code&0xC ) { // mov Dn, (abs) case 0x00: insn.itype = mn102_mov; SetReg(insn.Op1,R1+rD0); SetMem(insn, insn.Op2, 2, dt_word); break; // movb Dn, (abs) case 0x04: insn.itype = mn102_movb; SetReg(insn.Op1,R1+rD0); SetMem(insn, insn.Op2, 2, dt_byte); break; // mov (abs), Dn case 0x08: insn.itype = mn102_mov; SetReg(insn.Op2,R1+rD0); SetMem(insn, insn.Op1, 2, dt_word); break; // movbu (abs), Dn case 0x0C: insn.itype = mn102_movbu; SetReg(insn.Op2,R1+rD0); SetMem(insn, insn.Op1, 2, dt_byte); break; } break; // add/cmp,mov case 0x0D: switch ( code&0xC ) { // add imm8, An case 0x00: SetReg(insn.Op2,R1+rA0); insn.itype = mn102_add; SetImm(insn, insn.Op1, 1); break; // add imm8, Dn case 0x04: SetReg(insn.Op2,R1+rD0); insn.itype = mn102_add; SetImm(insn, insn.Op1, 1); break; // cmp imm8, Dn case 0x08: SetReg(insn.Op2,R1+rD0); insn.itype = mn102_cmp; SetImm(insn, insn.Op1, 1); break; // mov imm16, An case 0x0c: SetReg(insn.Op2,R1+rA0); insn.itype = mn102_mov; SetImm(insn, insn.Op1, 2); insn.Op1.specflag1 = URB_ADDR; break; } break; // Jmps case 0x0E: { static const uchar Cmd[16] = { mn102_blt,mn102_bgt,mn102_bge,mn102_ble, mn102_bcs,mn102_bhi,mn102_bcc,mn102_bls, mn102_beq,mn102_bne,mn102_bra,mn102_rti, mn102_cmp,mn102_cmp,mn102_cmp,mn102_cmp }; insn.itype = Cmd[code&0xF]; switch ( insn.itype ) { // rti case mn102_rti: break; // cmp imm16, An case mn102_cmp: SetReg(insn.Op2,R1+rA0); SetImm(insn, insn.Op1, 2); break; // jmps default: SetLabel(insn, insn.Op1,1); break; } break; } // ExtCodes case 0x0F: switch ( code & 0xF ) { // F0 set case 0x00: code = insn.get_next_byte(); R1 = (code&3); R2 = (code>>2)&3; switch ( code&0xC0 ) { // complex set case 0x00: switch ( code&0x30 ) { // one more set case 0x00: if ( code & 2 ) return 0; SetRReg(insn.Op1,R2+rA0); if ( code & 1 ) insn.itype = mn102_jsr; else insn.itype = mn102_jmp; break; case 0x10: return 0; case 0x20: insn.itype = mn102_bset; SetReg(insn.Op1,R1+rD0); SetRReg(insn.Op2,R2+rA0); break; case 0x30: insn.itype = mn102_bclr; SetReg(insn.Op1,R1+rD0); SetRReg(insn.Op2,R2+rA0); break; } break; // movb (Di,An), Dm case 0x40: insn.itype = mn102_movb; SetReg(insn.Op2,R1+rD0); SetDisplI(insn.Op1,R2+rA0,code>>4); break; // movbu (Di,An), Dm case 0x80: insn.itype = mn102_movbu; SetReg(insn.Op2,R1+rD0); SetDisplI(insn.Op1,R2+rA0,code>>4); break; // movb Dm, (Di, An) case 0xC0: insn.itype = mn102_movb; SetReg(insn.Op1,R1+rD0); SetDisplI(insn.Op2,R2+rA0,code>>4); break; } break; // F1 set case 0x01: insn.itype = mn102_mov; code = insn.get_next_byte(); R1 = (code&3); R2 = (code>>2)&3; switch ( code&0xC0 ) { // mov (Di, An), Am case 0x00: SetReg(insn.Op2,R1+rA0); SetDisplI(insn.Op1,R2+rA0, code>>4); break; // mov (Di,An), Dm case 0x40: SetReg(insn.Op2,R1+rD0); SetDisplI(insn.Op1,R2+rA0, code>>4); break; // mov Am, (Di, An) case 0x80: SetReg(insn.Op1,R1+rD0); SetDisplI(insn.Op2,R2+rA0, code>>4); break; // mov Dm, (Di, An); case 0xC0: SetReg(insn.Op1,R1+rD0); SetDisplI(insn.Op2,R2+rA0, code>>4); break; } break; // F2 set case 0x02: code = insn.get_next_byte(); R1 = (code&3); R2 = (code>>2)&3; { static const uchar Cmd[16] = { mn102_add, mn102_sub, mn102_cmp, mn102_mov, mn102_add, mn102_sub, mn102_cmp, mn102_mov, mn102_addc, mn102_subc, 0, 0, mn102_add, mn102_sub, mn102_cmp, mn102_mov }; insn.itype = Cmd[code>>4]; if ( insn.itype == 0 ) return 0; switch ( code&0xC0 ) { case 0x00: SetReg(insn.Op1,R2+rD0); SetReg(insn.Op2,R1+rA0); break; case 0x40: SetReg(insn.Op1,R2+rA0); SetReg(insn.Op2,R1+rA0); break; case 0x80: SetReg(insn.Op1,R2+rD0); SetReg(insn.Op2,R1+rD0); break; case 0xC0: SetReg(insn.Op1,R2+rA0); SetReg(insn.Op2,R1+rD0); break; } } break; // F3 set case 0x03: code = insn.get_next_byte(); R1 = (code&3); R2 = (code>>2)&3; SetReg(insn.Op1,R2+rD0); SetReg(insn.Op2,R1+rD0); { static const uchar Cmd[16] = { mn102_and, mn102_or, mn102_xor, mn102_rol, mn102_mul, mn102_mulu, mn102_divu, 0, 0, mn102_cmp, 0, 0, mn102_ext, mn102_mov, mn102_not, 255 }; insn.itype = Cmd[code>>4]; switch ( insn.itype ) { // bad opcode case 0: return 0; // shifts case mn102_rol: SetReg(insn.Op1,R1+rD0); insn.Op2.type = o_void; { static const uchar Cmd2[4] = { mn102_rol,mn102_ror,mn102_asr,mn102_lsr }; insn.itype = Cmd2[(code>>2)&3]; } break; case mn102_ext: if ( code & 2 ) return 0; if ( code & 1 ) { insn.Op2.type = o_void; } else { insn.itype = mn102_mov; SetReg(insn.Op2,rMDR); } break; case mn102_mov: if ( R1 != 0 ) return 0; SetReg(insn.Op2,rPSW); break; case mn102_not: switch ( R2 ) { case 0: insn.itype = mn102_mov; SetReg(insn.Op1,rMDR); break; case 1: insn.Op2.type = o_void; SetReg(insn.Op1,R1+rD0); break; default: return 0; } break; case 255: switch ( R2 ) { case 0: insn.itype = mn102_mov; SetReg(insn.Op1,rPSW); break; case 3: insn.Op2.type = insn.Op1.type = o_void; switch ( R1 ) { case 0: insn.itype = mn102_pxst; break; // F3, FE case 2: { static const uchar lCmd[4] = { mn102_tbz, mn102_tbnz, mn102_bset, mn102_bclr }; code = insn.get_next_byte(); if ( code < 0xC0 || code >= 0xE0 ) return 0; insn.itype = lCmd[(code>>3)&3]; SetImmC(insn.Op1,1<<(code&7)); SetMem(insn, insn.Op2, 3, dt_byte); // if jump, use label if ( (code&0xF0) == 0xC0 ) SetLabel(insn, insn.Op3, 1); } break; // F3, FF case 3: { static const uchar lCmd[4] = { mn102_tbz, mn102_bset, mn102_tbnz, mn102_bclr }; code = insn.get_next_byte(); if ( code < 0x80 || code >= 0xC0 ) return 0; insn.itype = lCmd[(code>>4)&3]; SetImmC(insn.Op1,1<<(code&7)); SetDispl(insn, insn.Op2,(code&0x8)?rA3:rA2, 1); insn.Op3.dtype = dt_byte; // if jump, use label if ( (code & 0x10) == 0 ) SetLabel(insn, insn.Op3, 1); } break; default: return 0; } break; default: return 0; } break; // the rest does not need processing default: break; } } break; // F4 set - 5 bytes case 0x04: code = insn.get_next_byte(); R1 = (code&3); R2 = (code>>2)&3; switch ( code&0xF0 ) { // mov Dm, (D24,An) case 0x00: insn.itype = mn102_mov; SetReg(insn.Op1,R1+rD0); SetDispl(insn, insn.Op2,R2+rA0,3); break; case 0x10: insn.itype = mn102_mov; SetReg(insn.Op1,R1+rA0); SetDispl(insn, insn.Op2,R2+rA0,3); break; case 0x20: insn.itype = mn102_movb; SetReg(insn.Op1,R1+rD0); SetDispl(insn, insn.Op2,R2+rA0,3); break; case 0x30: insn.itype = mn102_movx; SetReg(insn.Op1,R1+rD0); SetDispl(insn, insn.Op2,R2+rA0,3); break; case 0x40: switch ( R2 ) { case 0: insn.itype = mn102_mov; SetMem(insn, insn.Op2,3,dt_dword); SetReg(insn.Op1,R1+rD0); break; case 1: insn.itype = mn102_movb; SetMem(insn, insn.Op2,3,dt_byte); SetReg(insn.Op1,R1+rD0); break; default: if ( code != 0x4B && code != 0x4F ) return 0; insn.itype = code == 0x4B ? mn102_bset : mn102_bclr; SetMem(insn, insn.Op2,3,dt_byte); SetImm(insn, insn.Op1,1); break; } break; case 0x50: if ( R2 != 0 ) return 0; insn.itype = mn102_mov; SetReg(insn.Op1,R1+rA0); SetMem(insn, insn.Op1,3,dt_tbyte); break; case 0x60: SetImm(insn, insn.Op1,3); SetReg(insn.Op2, R1+((R2&1)?rA0:rD0)); insn.itype = (R2&2)?mn102_sub:mn102_add; break; case 0x70: SetImm(insn, insn.Op1,3); insn.Op1.specflag1 = URB_ADDR; SetReg(insn.Op2,R1+((R2&1)?rA0:rD0)); insn.itype = (R2&2)?mn102_cmp:mn102_mov; break; case 0x80: insn.itype = mn102_mov; SetDispl(insn, insn.Op1,R2+rA0,3); SetReg(insn.Op2,R1+rD0); break; case 0x90: insn.itype = mn102_movbu; SetDispl(insn, insn.Op1,R2+rA0,3); SetReg(insn.Op2,R1+rD0); break; case 0xA0: insn.itype = mn102_movb; SetDispl(insn, insn.Op1,R2+rA0,3); SetReg(insn.Op2,R1+rD0); break; case 0xB0: insn.itype = mn102_movx; SetDispl(insn, insn.Op1,R2+rA0,3); SetReg(insn.Op2,R1+rD0); break; case 0xC0: SetReg(insn.Op2,R1+rD0); switch ( R2 ) { case 0: insn.itype = mn102_mov; SetMem(insn, insn.Op1,3,dt_word); break; case 1: insn.itype = mn102_movb; SetMem(insn, insn.Op1,3,dt_byte); break; case 2: insn.itype = mn102_movbu; SetMem(insn, insn.Op1,3,dt_byte); break; default: return 0; } break; case 0xD0: if ( R2 != 0 ) return 0; insn.itype = mn102_mov; SetMem(insn, insn.Op1,3,dt_tbyte); SetReg(insn.Op2,R1+rA0); break; case 0xE0: switch ( code ) { case 0xE0: insn.itype = mn102_jmp; SetLabel(insn, insn.Op1,3); break; case 0xE1: insn.itype = mn102_jsr; SetLabel(insn, insn.Op1,3); break; case 0xE3: case 0xE7: insn.itype = (code == 0xE3) ? mn102_bset : mn102_bclr; SetMem(insn, insn.Op2,2,dt_byte); SetImmC(insn.Op1,1); break; default: if ( code < 0xE8 ) return 0; insn.itype = (code&0x4)?mn102_bclr:mn102_bset; SetImmC(insn.Op1,1); SetDispl(insn, insn.Op2,rA0+(code&3),1); break; } break; case 0xF0: insn.itype = mn102_mov; SetDispl(insn, insn.Op1,R2+rA0,3); SetReg(insn.Op2,R1+rA0); break; } break; // F5 set case 0x05: code = insn.get_next_byte(); R1 = (code&3); R2 = (code>>2)&3; switch ( code&0xF0 ) { case 0x00: { static const uchar Cmd[4] = { mn102_and, mn102_btst, mn102_or, mn102_addnf }; SetImm(insn, insn.Op1,1); SetReg(insn.Op2,R1+rD0); insn.itype = Cmd[R2]; } break; // movb Dm,(d8,An) case 0x10: insn.itype = mn102_movb; SetReg(insn.Op1,R1+rD0); SetDispl(insn, insn.Op2,R2+rA0,1); break; // movb (d8,An), Dm case 0x20: insn.itype = mn102_movb; SetReg(insn.Op2,R1+rD0); SetDispl(insn, insn.Op1,R2+rA0,1); break; // movbu (d8,An), Dm case 0x30: insn.itype = mn102_movbu; SetReg(insn.Op2,R1+rD0); SetDispl(insn, insn.Op1,R2+rA0,1); break; // mulql dn, dm case 0x40: code = insn.get_next_byte(); if ( code > 1 ) return 0; insn.itype = (code == 0) ? mn102_mulql : mn102_mulqh; SetReg(insn.Op1,R2+rD0); SetReg(insn.Op2,R1+rD0); break; // movx Dm, (d8,An) case 0x50: insn.itype = mn102_movx; SetReg(insn.Op1,R1+rD0); SetDispl(insn, insn.Op2,R2+rA0,1); break; // mulq dn, dm case 0x60: code = insn.get_next_byte(); if ( code != 0x10 ) return 0; insn.itype = mn102_mulq; SetReg(insn.Op1,R2+rD0); SetReg(insn.Op2,R1+rD0); break; // movx (d8,An), Dm case 0x70: insn.itype = mn102_movx; SetDispl(insn, insn.Op1,R2+rA0,1); SetReg(insn.Op2,R1+rD0); break; case 0x80: case 0x90: case 0xA0: case 0xB0: { static const uchar Cmd[4] = { mn102_tbz, mn102_bset, mn102_tbnz, mn102_bclr }; insn.itype = Cmd[(code>>4)&3]; SetImmC(insn.Op1,1<<(code&7)); SetDispl(insn, insn.Op2,(code&0x8)?rA1:rA0,1); if ( (code & 0x10) == 0 ) SetLabel(insn, insn.Op3, 1); } break; case 0xC0: case 0xD0: { static const uchar Cmd[4] = { mn102_tbz, mn102_tbnz, mn102_bset, mn102_bclr }; insn.itype = Cmd[(code>>3)&3]; SetImmC(insn.Op1,1<<(code&7)); SetMem(insn, insn.Op2,2,dt_byte); if ( (code & 0x10) == 0 ) SetLabel(insn, insn.Op3, 1); } break; case 0xE0: { static const uchar Cmd[16] = { mn102_bltx,mn102_bgtx,mn102_bgex,mn102_blex, mn102_bcsx,mn102_bhix,mn102_bccx,mn102_blsx, mn102_beqx,mn102_bnex,0,0, mn102_bvcx,mn102_bvsx,mn102_bncx,mn102_bnsx }; insn.itype = Cmd[code&0xF]; if ( insn.itype == 0 ) return 0; SetLabel(insn, insn.Op1,1); } break; case 0xF0: if ( code < 0xFC && code > 0xF8 ) return 0; if ( code >= 0xFC ) { static const uchar Cmd[4] = { mn102_bvc, mn102_bvs, mn102_bnc, mn102_bns }; insn.itype = Cmd[R1]; SetLabel(insn, insn.Op1, 1); } else { code = insn.get_next_byte(); switch ( code ) { case 0x4: insn.itype = mn102_mulql; SetImm(insn, insn.Op1,1); SetReg(insn.Op2,R1+rD0); break; case 0x5: insn.itype = mn102_mulqh; SetImm(insn, insn.Op1,1); SetReg(insn.Op2,R1+rD0); break; case 0x8: insn.itype = mn102_mulql; SetImm(insn, insn.Op1,2); SetReg(insn.Op2,R1+rD0); break; case 0x9: insn.itype = mn102_mulqh; SetImm(insn, insn.Op1,2); SetReg(insn.Op2,R1+rD0); break; default: return 0; } } break; default: return 0; } break; // NOP case 0x06: insn.itype = mn102_nop; break; // F7 set case 0x07: code = insn.get_next_byte(); R1 = (code&3); R2 = (code>>2)&3; switch ( code&0xF0 ) { case 0x00: { static const uchar Cmd[4] = { mn102_and, mn102_btst, mn102_add, mn102_sub }; SetImm(insn, insn.Op1,2); SetReg(insn.Op2,R1+((R2&2)?rA0:rD0)); insn.itype = Cmd[R2]; } break; case 0x10: switch ( R2 ) { case 0: if ( R1 != 0 ) return 0; insn.itype = mn102_and; SetReg(insn.Op2,rPSW); break; case 1: if ( R1 != 0 ) return 0; insn.itype = mn102_or; SetReg(insn.Op2,rPSW); break; case 2: insn.itype = mn102_add; SetReg(insn.Op2,R1+rD0); break; case 3: insn.itype = mn102_sub; SetReg(insn.Op2,R1+rD0); break; } SetImm(insn, insn.Op1,2); break; case 0x20: if ( R2 != 0 ) return 0; insn.itype = mn102_mov; SetReg(insn.Op1,R1+rA0); SetMem(insn, insn.Op2,2,dt_tbyte); break; case 0x30: if ( R2 != 0 ) return 0; insn.itype = mn102_mov; SetReg(insn.Op2,R1+rA0); SetMem(insn, insn.Op1,2,dt_tbyte); break; case 0x40: { static const uchar Cmd[4] = { mn102_or, 0, mn102_cmp, mn102_xor }; insn.itype = Cmd[R2]; if ( insn.itype == 0 ) return 0; SetImm(insn, insn.Op1,2); SetReg(insn.Op2,R1+rD0); } break; case 0x50: insn.itype = mn102_movbu; SetDispl(insn, insn.Op1,R2+rA0,2); SetReg(insn.Op2,R1+rD0); break; case 0x60: insn.itype = mn102_movx; SetDispl(insn, insn.Op2,R2+rA0,2); SetReg(insn.Op1,R1+rD0); break; case 0x70: insn.itype = mn102_movx; SetDispl(insn, insn.Op1,R2+rA0,2); SetReg(insn.Op2,R1+rD0); break; case 0x80: insn.itype = mn102_mov; SetDispl(insn, insn.Op2,R2+rA0,2); SetReg(insn.Op1,R1+rD0); break; case 0x90: insn.itype = mn102_movb; SetDispl(insn, insn.Op2,R2+rA0,2); SetReg(insn.Op1,R1+rD0); break; case 0xA0: insn.itype = mn102_mov; SetDispl(insn, insn.Op2,R2+rA0,2); SetReg(insn.Op1,R1+rA0); break; case 0xB0: insn.itype = mn102_mov; SetDispl(insn, insn.Op1,R2+rA0,2); SetReg(insn.Op2,R1+rA0); break; case 0xC0: insn.itype = mn102_mov; SetDispl(insn, insn.Op1,R2+rA0,2); SetReg(insn.Op2,R1+rD0); break; case 0xD0: insn.itype = mn102_mov; SetDispl(insn, insn.Op1,R2+rA0,2); SetReg(insn.Op2,R1+rD0); break; default: return 0; } break; // mov imm16, Dn case 0x08: case 0x09: case 0x0A: case 0x0B: SetReg(insn.Op2,R1+rD0); SetImm(insn, insn.Op1, 2); insn.itype = mn102_mov; break; // jmp label16 case 0x0C: insn.itype = mn102_jmp; SetLabel(insn, insn.Op1,2); break; // jsr label16 case 0x0D: insn.itype = mn102_jsr; SetLabel(insn, insn.Op1,2); break; // rts case 0x0E: insn.itype = mn102_rts; break; // illegal code case 0x0F: return 0; } break; } return insn.size; }