📄 translate.c
字号:
/* * ARM translation * * Copyright (c) 2003 Fabrice Bellard * Copyright (c) 2005 CodeSourcery, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <stdarg.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <inttypes.h>#include "cpu.h"#include "exec-all.h"#include "disas.h"#define ENABLE_ARCH_5J 0#define ENABLE_ARCH_6 1#define ENABLE_ARCH_6T2 1#define ARCH(x) if (!ENABLE_ARCH_##x) goto illegal_op;/* internal defines */typedef struct DisasContext { target_ulong pc; int is_jmp; /* Nonzero if this instruction has been conditionally skipped. */ int condjmp; /* The label that will be jumped to when the instruction is skipped. */ int condlabel; struct TranslationBlock *tb; int singlestep_enabled; int thumb;#if !defined(CONFIG_USER_ONLY) int user;#endif} DisasContext;#if defined(CONFIG_USER_ONLY)#define IS_USER(s) 1#else#define IS_USER(s) (s->user)#endif#define DISAS_JUMP_NEXT 4#ifdef USE_DIRECT_JUMP#define TBPARAM(x)#else#define TBPARAM(x) (long)(x)#endif/* XXX: move that elsewhere */static uint16_t *gen_opc_ptr;static uint32_t *gen_opparam_ptr;extern FILE *logfile;extern int loglevel;enum {#define DEF(s, n, copy_size) INDEX_op_ ## s,#include "opc.h"#undef DEF NB_OPS,};#include "gen-op.h"static GenOpFunc1 *gen_test_cc[14] = { gen_op_test_eq, gen_op_test_ne, gen_op_test_cs, gen_op_test_cc, gen_op_test_mi, gen_op_test_pl, gen_op_test_vs, gen_op_test_vc, gen_op_test_hi, gen_op_test_ls, gen_op_test_ge, gen_op_test_lt, gen_op_test_gt, gen_op_test_le,};const uint8_t table_logic_cc[16] = { 1, /* and */ 1, /* xor */ 0, /* sub */ 0, /* rsb */ 0, /* add */ 0, /* adc */ 0, /* sbc */ 0, /* rsc */ 1, /* andl */ 1, /* xorl */ 0, /* cmp */ 0, /* cmn */ 1, /* orr */ 1, /* mov */ 1, /* bic */ 1, /* mvn */}; static GenOpFunc1 *gen_shift_T1_im[4] = { gen_op_shll_T1_im, gen_op_shrl_T1_im, gen_op_sarl_T1_im, gen_op_rorl_T1_im,};static GenOpFunc *gen_shift_T1_0[4] = { NULL, gen_op_shrl_T1_0, gen_op_sarl_T1_0, gen_op_rrxl_T1,};static GenOpFunc1 *gen_shift_T2_im[4] = { gen_op_shll_T2_im, gen_op_shrl_T2_im, gen_op_sarl_T2_im, gen_op_rorl_T2_im,};static GenOpFunc *gen_shift_T2_0[4] = { NULL, gen_op_shrl_T2_0, gen_op_sarl_T2_0, gen_op_rrxl_T2,};static GenOpFunc1 *gen_shift_T1_im_cc[4] = { gen_op_shll_T1_im_cc, gen_op_shrl_T1_im_cc, gen_op_sarl_T1_im_cc, gen_op_rorl_T1_im_cc,};static GenOpFunc *gen_shift_T1_0_cc[4] = { NULL, gen_op_shrl_T1_0_cc, gen_op_sarl_T1_0_cc, gen_op_rrxl_T1_cc,};static GenOpFunc *gen_shift_T1_T0[4] = { gen_op_shll_T1_T0, gen_op_shrl_T1_T0, gen_op_sarl_T1_T0, gen_op_rorl_T1_T0,};static GenOpFunc *gen_shift_T1_T0_cc[4] = { gen_op_shll_T1_T0_cc, gen_op_shrl_T1_T0_cc, gen_op_sarl_T1_T0_cc, gen_op_rorl_T1_T0_cc,};static GenOpFunc *gen_op_movl_TN_reg[3][16] = { { gen_op_movl_T0_r0, gen_op_movl_T0_r1, gen_op_movl_T0_r2, gen_op_movl_T0_r3, gen_op_movl_T0_r4, gen_op_movl_T0_r5, gen_op_movl_T0_r6, gen_op_movl_T0_r7, gen_op_movl_T0_r8, gen_op_movl_T0_r9, gen_op_movl_T0_r10, gen_op_movl_T0_r11, gen_op_movl_T0_r12, gen_op_movl_T0_r13, gen_op_movl_T0_r14, gen_op_movl_T0_r15, }, { gen_op_movl_T1_r0, gen_op_movl_T1_r1, gen_op_movl_T1_r2, gen_op_movl_T1_r3, gen_op_movl_T1_r4, gen_op_movl_T1_r5, gen_op_movl_T1_r6, gen_op_movl_T1_r7, gen_op_movl_T1_r8, gen_op_movl_T1_r9, gen_op_movl_T1_r10, gen_op_movl_T1_r11, gen_op_movl_T1_r12, gen_op_movl_T1_r13, gen_op_movl_T1_r14, gen_op_movl_T1_r15, }, { gen_op_movl_T2_r0, gen_op_movl_T2_r1, gen_op_movl_T2_r2, gen_op_movl_T2_r3, gen_op_movl_T2_r4, gen_op_movl_T2_r5, gen_op_movl_T2_r6, gen_op_movl_T2_r7, gen_op_movl_T2_r8, gen_op_movl_T2_r9, gen_op_movl_T2_r10, gen_op_movl_T2_r11, gen_op_movl_T2_r12, gen_op_movl_T2_r13, gen_op_movl_T2_r14, gen_op_movl_T2_r15, },};static GenOpFunc *gen_op_movl_reg_TN[2][16] = { { gen_op_movl_r0_T0, gen_op_movl_r1_T0, gen_op_movl_r2_T0, gen_op_movl_r3_T0, gen_op_movl_r4_T0, gen_op_movl_r5_T0, gen_op_movl_r6_T0, gen_op_movl_r7_T0, gen_op_movl_r8_T0, gen_op_movl_r9_T0, gen_op_movl_r10_T0, gen_op_movl_r11_T0, gen_op_movl_r12_T0, gen_op_movl_r13_T0, gen_op_movl_r14_T0, gen_op_movl_r15_T0, }, { gen_op_movl_r0_T1, gen_op_movl_r1_T1, gen_op_movl_r2_T1, gen_op_movl_r3_T1, gen_op_movl_r4_T1, gen_op_movl_r5_T1, gen_op_movl_r6_T1, gen_op_movl_r7_T1, gen_op_movl_r8_T1, gen_op_movl_r9_T1, gen_op_movl_r10_T1, gen_op_movl_r11_T1, gen_op_movl_r12_T1, gen_op_movl_r13_T1, gen_op_movl_r14_T1, gen_op_movl_r15_T1, },};static GenOpFunc1 *gen_op_movl_TN_im[3] = { gen_op_movl_T0_im, gen_op_movl_T1_im, gen_op_movl_T2_im,};static GenOpFunc1 *gen_shift_T0_im_thumb[3] = { gen_op_shll_T0_im_thumb, gen_op_shrl_T0_im_thumb, gen_op_sarl_T0_im_thumb,};static inline void gen_bx(DisasContext *s){ s->is_jmp = DISAS_UPDATE; gen_op_bx_T0();}#if defined(CONFIG_USER_ONLY)#define gen_ldst(name, s) gen_op_##name##_raw()#else#define gen_ldst(name, s) do { \ if (IS_USER(s)) \ gen_op_##name##_user(); \ else \ gen_op_##name##_kernel(); \ } while (0)#endifstatic inline void gen_movl_TN_reg(DisasContext *s, int reg, int t){ int val; if (reg == 15) { /* normaly, since we updated PC, we need only to add one insn */ if (s->thumb) val = (long)s->pc + 2; else val = (long)s->pc + 4; gen_op_movl_TN_im[t](val); } else { gen_op_movl_TN_reg[t][reg](); }}static inline void gen_movl_T0_reg(DisasContext *s, int reg){ gen_movl_TN_reg(s, reg, 0);}static inline void gen_movl_T1_reg(DisasContext *s, int reg){ gen_movl_TN_reg(s, reg, 1);}static inline void gen_movl_T2_reg(DisasContext *s, int reg){ gen_movl_TN_reg(s, reg, 2);}static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t){ gen_op_movl_reg_TN[t][reg](); if (reg == 15) { s->is_jmp = DISAS_JUMP; }}static inline void gen_movl_reg_T0(DisasContext *s, int reg){ gen_movl_reg_TN(s, reg, 0);}static inline void gen_movl_reg_T1(DisasContext *s, int reg){ gen_movl_reg_TN(s, reg, 1);}/* Force a TB lookup after an instruction that changes the CPU state. */static inline void gen_lookup_tb(DisasContext *s){ gen_op_movl_T0_im(s->pc); gen_movl_reg_T0(s, 15); s->is_jmp = DISAS_UPDATE;}static inline void gen_add_data_offset(DisasContext *s, unsigned int insn){ int val, rm, shift, shiftop; if (!(insn & (1 << 25))) { /* immediate */ val = insn & 0xfff; if (!(insn & (1 << 23))) val = -val; if (val != 0) gen_op_addl_T1_im(val); } else { /* shift/register */ rm = (insn) & 0xf; shift = (insn >> 7) & 0x1f; gen_movl_T2_reg(s, rm); shiftop = (insn >> 5) & 3; if (shift != 0) { gen_shift_T2_im[shiftop](shift); } else if (shiftop != 0) { gen_shift_T2_0[shiftop](); } if (!(insn & (1 << 23))) gen_op_subl_T1_T2(); else gen_op_addl_T1_T2(); }}static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn){ int val, rm; if (insn & (1 << 22)) { /* immediate */ val = (insn & 0xf) | ((insn >> 4) & 0xf0); if (!(insn & (1 << 23))) val = -val; if (val != 0) gen_op_addl_T1_im(val); } else { /* register */ rm = (insn) & 0xf; gen_movl_T2_reg(s, rm); if (!(insn & (1 << 23))) gen_op_subl_T1_T2(); else gen_op_addl_T1_T2(); }}#define VFP_OP(name) \static inline void gen_vfp_##name(int dp) \{ \ if (dp) \ gen_op_vfp_##name##d(); \ else \ gen_op_vfp_##name##s(); \}VFP_OP(add)VFP_OP(sub)VFP_OP(mul)VFP_OP(div)VFP_OP(neg)VFP_OP(abs)VFP_OP(sqrt)VFP_OP(cmp)VFP_OP(cmpe)VFP_OP(F1_ld0)VFP_OP(uito)VFP_OP(sito)VFP_OP(toui)VFP_OP(touiz)VFP_OP(tosi)VFP_OP(tosiz)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -