📄 translate.c
字号:
/* pre increment */ } else { /* post increment */ gen_op_addl_T1_im(4); } } else { if (insn & (1 << 24)) { /* pre decrement */ if (n != 1) gen_op_addl_T1_im(-((n - 1) * 4)); } else { /* post decrement */ gen_op_addl_T1_im(-(n * 4)); } } gen_movl_reg_T1(s, rn); } if (loaded_base) { gen_op_movl_T0_T2(); gen_movl_reg_T0(s, rn); } if ((insn & (1 << 22)) && !user) { /* Restore CPSR from SPSR. */ gen_op_movl_T0_spsr(); gen_op_movl_cpsr_T0(0xffffffff); s->is_jmp = DISAS_UPDATE; } } break; case 0xa: case 0xb: { int32_t offset; /* branch (and link) */ val = (int32_t)s->pc; if (insn & (1 << 24)) { gen_op_movl_T0_im(val); gen_op_movl_reg_TN[0][14](); } offset = (((int32_t)insn << 8) >> 8); val += (offset << 2) + 4; gen_jmp(s, val); } break; case 0xc: case 0xd: case 0xe: /* Coprocessor. */ op1 = (insn >> 8) & 0xf; switch (op1) { case 10: case 11: if (disas_vfp_insn (env, s, insn)) goto illegal_op; break; case 15: if (disas_cp15_insn (s, insn)) goto illegal_op; break; default: /* unknown coprocessor. */ goto illegal_op; } break; case 0xf: /* swi */ gen_op_movl_T0_im((long)s->pc); gen_op_movl_reg_TN[0][15](); gen_op_swi(); s->is_jmp = DISAS_JUMP; break; default: illegal_op: gen_op_movl_T0_im((long)s->pc - 4); gen_op_movl_reg_TN[0][15](); gen_op_undef_insn(); s->is_jmp = DISAS_JUMP; break; } }}static void disas_thumb_insn(DisasContext *s){ uint32_t val, insn, op, rm, rn, rd, shift, cond; int32_t offset; int i; insn = lduw_code(s->pc); s->pc += 2; switch (insn >> 12) { case 0: case 1: rd = insn & 7; op = (insn >> 11) & 3; if (op == 3) { /* add/subtract */ rn = (insn >> 3) & 7; gen_movl_T0_reg(s, rn); if (insn & (1 << 10)) { /* immediate */ gen_op_movl_T1_im((insn >> 6) & 7); } else { /* reg */ rm = (insn >> 6) & 7; gen_movl_T1_reg(s, rm); } if (insn & (1 << 9)) gen_op_subl_T0_T1_cc(); else gen_op_addl_T0_T1_cc(); gen_movl_reg_T0(s, rd); } else { /* shift immediate */ rm = (insn >> 3) & 7; shift = (insn >> 6) & 0x1f; gen_movl_T0_reg(s, rm); gen_shift_T0_im_thumb[op](shift); gen_movl_reg_T0(s, rd); } break; case 2: case 3: /* arithmetic large immediate */ op = (insn >> 11) & 3; rd = (insn >> 8) & 0x7; if (op == 0) { gen_op_movl_T0_im(insn & 0xff); } else { gen_movl_T0_reg(s, rd); gen_op_movl_T1_im(insn & 0xff); } switch (op) { case 0: /* mov */ gen_op_logic_T0_cc(); break; case 1: /* cmp */ gen_op_subl_T0_T1_cc(); break; case 2: /* add */ gen_op_addl_T0_T1_cc(); break; case 3: /* sub */ gen_op_subl_T0_T1_cc(); break; } if (op != 1) gen_movl_reg_T0(s, rd); break; case 4: if (insn & (1 << 11)) { rd = (insn >> 8) & 7; /* load pc-relative. Bit 1 of PC is ignored. */ val = s->pc + 2 + ((insn & 0xff) * 4); val &= ~(uint32_t)2; gen_op_movl_T1_im(val); gen_ldst(ldl, s); gen_movl_reg_T0(s, rd); break; } if (insn & (1 << 10)) { /* data processing extended or blx */ rd = (insn & 7) | ((insn >> 4) & 8); rm = (insn >> 3) & 0xf; op = (insn >> 8) & 3; switch (op) { case 0: /* add */ gen_movl_T0_reg(s, rd); gen_movl_T1_reg(s, rm); gen_op_addl_T0_T1(); gen_movl_reg_T0(s, rd); break; case 1: /* cmp */ gen_movl_T0_reg(s, rd); gen_movl_T1_reg(s, rm); gen_op_subl_T0_T1_cc(); break; case 2: /* mov/cpy */ gen_movl_T0_reg(s, rm); gen_movl_reg_T0(s, rd); break; case 3:/* branch [and link] exchange thumb register */ if (insn & (1 << 7)) { val = (uint32_t)s->pc | 1; gen_op_movl_T1_im(val); gen_movl_reg_T1(s, 14); } gen_movl_T0_reg(s, rm); gen_bx(s); break; } break; } /* data processing register */ rd = insn & 7; rm = (insn >> 3) & 7; op = (insn >> 6) & 0xf; if (op == 2 || op == 3 || op == 4 || op == 7) { /* the shift/rotate ops want the operands backwards */ val = rm; rm = rd; rd = val; val = 1; } else { val = 0; } if (op == 9) /* neg */ gen_op_movl_T0_im(0); else if (op != 0xf) /* mvn doesn't read its first operand */ gen_movl_T0_reg(s, rd); gen_movl_T1_reg(s, rm); switch (op) { case 0x0: /* and */ gen_op_andl_T0_T1(); gen_op_logic_T0_cc(); break; case 0x1: /* eor */ gen_op_xorl_T0_T1(); gen_op_logic_T0_cc(); break; case 0x2: /* lsl */ gen_op_shll_T1_T0_cc(); gen_op_logic_T1_cc(); break; case 0x3: /* lsr */ gen_op_shrl_T1_T0_cc(); gen_op_logic_T1_cc(); break; case 0x4: /* asr */ gen_op_sarl_T1_T0_cc(); gen_op_logic_T1_cc(); break; case 0x5: /* adc */ gen_op_adcl_T0_T1_cc(); break; case 0x6: /* sbc */ gen_op_sbcl_T0_T1_cc(); break; case 0x7: /* ror */ gen_op_rorl_T1_T0_cc(); gen_op_logic_T1_cc(); break; case 0x8: /* tst */ gen_op_andl_T0_T1(); gen_op_logic_T0_cc(); rd = 16; break; case 0x9: /* neg */ gen_op_subl_T0_T1_cc(); break; case 0xa: /* cmp */ gen_op_subl_T0_T1_cc(); rd = 16; break; case 0xb: /* cmn */ gen_op_addl_T0_T1_cc(); rd = 16; break; case 0xc: /* orr */ gen_op_orl_T0_T1(); gen_op_logic_T0_cc(); break; case 0xd: /* mul */ gen_op_mull_T0_T1(); gen_op_logic_T0_cc(); break; case 0xe: /* bic */ gen_op_bicl_T0_T1(); gen_op_logic_T0_cc(); break; case 0xf: /* mvn */ gen_op_notl_T1(); gen_op_logic_T1_cc(); val = 1; rm = rd; break; } if (rd != 16) { if (val) gen_movl_reg_T1(s, rm); else gen_movl_reg_T0(s, rd); } break; case 5: /* load/store register offset. */ rd = insn & 7; rn = (insn >> 3) & 7; rm = (insn >> 6) & 7; op = (insn >> 9) & 7; gen_movl_T1_reg(s, rn); gen_movl_T2_reg(s, rm); gen_op_addl_T1_T2(); if (op < 3) /* store */ gen_movl_T0_reg(s, rd); switch (op) { case 0: /* str */ gen_ldst(stl, s); break; case 1: /* strh */ gen_ldst(stw, s); break; case 2: /* strb */ gen_ldst(stb, s); break; case 3: /* ldrsb */ gen_ldst(ldsb, s); break; case 4: /* ldr */ gen_ldst(ldl, s); break; case 5: /* ldrh */ gen_ldst(lduw, s); break; case 6: /* ldrb */ gen_ldst(ldub, s); break; case 7: /* ldrsh */ gen_ldst(ldsw, s); break; } if (op >= 3) /* load */ gen_movl_reg_T0(s, rd); break; case 6: /* load/store word immediate offset */ rd = insn & 7; rn = (insn >> 3) & 7; gen_movl_T1_reg(s, rn); val = (insn >> 4) & 0x7c; gen_op_movl_T2_im(val); gen_op_addl_T1_T2(); if (insn & (1 << 11)) { /* load */ gen_ldst(ldl, s); gen_movl_reg_T0(s, rd); } else { /* store */ gen_movl_T0_reg(s, rd); gen_ldst(stl, s); } break; case 7: /* load/store byte immediate offset */ rd = insn & 7; rn = (insn >> 3) & 7; gen_movl_T1_reg(s, rn); val = (insn >> 6) & 0x1f; gen_op_movl_T2_im(val); gen_op_addl_T1_T2(); if (insn & (1 << 11)) { /* load */ gen_ldst(ldub, s); gen_movl_reg_T0(s, rd); } else { /* store */ gen_movl_T0_reg(s, rd); gen_ldst(stb, s); } break; case 8: /* load/store halfword immediate offset */ rd = insn & 7; rn = (insn >> 3) & 7; gen_movl_T1_reg(s, rn); val = (insn >> 5) & 0x3e; gen_op_movl_T2_im(val); gen_op_addl_T1_T2(); if (insn & (1 << 11)) { /* load */ gen_ldst(lduw, s); gen_movl_reg_T0(s, rd); } else { /* store */ gen_movl_T0_reg(s, rd); gen_ldst(stw, s); } break; case 9: /* load/store from stack */ rd = (insn >> 8) & 7; gen_movl_T1_reg(s, 13); val = (insn & 0xff) * 4; gen_op_movl_T2_im(val); gen_op_addl_T1_T2(); if (insn & (1 << 11)) { /* load */ gen_ldst(ldl, s); gen_movl_reg_T0(s, rd); } else { /* store */ gen_movl_T0_reg(s, rd); gen_ldst(stl, s); } break; case 10: /* add to high reg */ rd = (insn >> 8) & 7; if (insn & (1 << 11)) { /* SP */ gen_movl_T0_reg(s, 13); } else { /* PC. bit 1 is ignored. */ gen_op_movl_T0_im((s->pc + 2) & ~(uint32_t)2); } val = (insn & 0xff) * 4; gen_op_movl_T1_im(val); gen_op_addl_T0_T1(); gen_movl_reg_T0(s, rd); break; case 11: /* misc */ op = (insn >> 8) & 0xf; switch (op) { case 0: /* adjust stack pointer */ gen_movl_T1_reg(s, 13
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -