?? translate.c
字號(hào):
/* * ARM translation * * Copyright (c) 2003 Fabrice Bellard * Copyright (c) 2005-2007 CodeSourcery * Copyright (c) 2007 OpenedHand, Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * 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 arm_feature(env, ARM_FEATURE_V6)#define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)#define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)#define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)#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; /* Thumb-2 condtional execution bits. */ int condexec_mask; int condexec_cond; struct TranslationBlock *tb; int singlestep_enabled; int thumb; int is_mem;#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/* These instructions trap after executing, so defer them until after the conditional executions state has been updated. */#define DISAS_WFI 4#define DISAS_SWI 5#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"#define PAS_OP(pfx) { \ gen_op_ ## pfx ## add16_T0_T1, \ gen_op_ ## pfx ## addsubx_T0_T1, \ gen_op_ ## pfx ## subaddx_T0_T1, \ gen_op_ ## pfx ## sub16_T0_T1, \ gen_op_ ## pfx ## add8_T0_T1, \ NULL, \ NULL, \ gen_op_ ## pfx ## sub8_T0_T1 }static GenOpFunc *gen_arm_parallel_addsub[8][8] = { {}, PAS_OP(s), PAS_OP(q), PAS_OP(sh), {}, PAS_OP(u), PAS_OP(uq), PAS_OP(uh),};#undef PAS_OP/* For unknown reasons Arm and Thumb-2 use arbitrarily diffenet encodings. */#define PAS_OP(pfx) { \ gen_op_ ## pfx ## add8_T0_T1, \ gen_op_ ## pfx ## add16_T0_T1, \ gen_op_ ## pfx ## addsubx_T0_T1, \ NULL, \ gen_op_ ## pfx ## sub8_T0_T1, \ gen_op_ ## pfx ## sub16_T0_T1, \ gen_op_ ## pfx ## subaddx_T0_T1, \ NULL }static GenOpFunc *gen_thumb2_parallel_addsub[8][8] = { PAS_OP(s), PAS_OP(q), PAS_OP(sh), {}, PAS_OP(u), PAS_OP(uq), PAS_OP(uh), {}};#undef PAS_OPstatic 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_cc[3] = { gen_op_shll_T0_im_thumb_cc, gen_op_shrl_T0_im_thumb_cc, gen_op_sarl_T0_im_thumb_cc,};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 { \ s->is_mem = 1; \ 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);
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -