translate.c
来自「xen虚拟机源代码安装包」· C语言 代码 · 共 2,200 行 · 第 1/5 页
C
2,200 行
/* SPARC translation Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at> Copyright (C) 2003-2005 Fabrice Bellard 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"#include "helper.h"#include "tcg-op.h"#define DEBUG_DISAS#define DYNAMIC_PC 1 /* dynamic pc value */#define JUMP_PC 2 /* dynamic pc value which takes only two values according to jump_pc[T2] *//* global register indexes */static TCGv cpu_env, cpu_T[2], cpu_regwptr;static TCGv cpu_cc_src, cpu_cc_src2, cpu_cc_dst;static TCGv cpu_psr, cpu_fsr, cpu_pc, cpu_npc, cpu_gregs[8];static TCGv cpu_cond, cpu_src1, cpu_src2, cpu_dst, cpu_addr, cpu_val;#ifdef TARGET_SPARC64static TCGv cpu_xcc;#endif/* local register indexes (only used inside old micro ops) */static TCGv cpu_tmp0, cpu_tmp32, cpu_tmp64;typedef struct DisasContext { target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */ target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */ target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */ int is_br; int mem_idx; int fpu_enabled; struct TranslationBlock *tb; uint32_t features;} DisasContext;// This function uses non-native bit order#define GET_FIELD(X, FROM, TO) \ ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))// This function uses the order in the manuals, i.e. bit 0 is 2^0#define GET_FIELD_SP(X, FROM, TO) \ GET_FIELD(X, 31 - (TO), 31 - (FROM))#define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)#define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1))#ifdef TARGET_SPARC64#define FFPREG(r) (r)#define DFPREG(r) (((r & 1) << 5) | (r & 0x1e))#define QFPREG(r) (((r & 1) << 5) | (r & 0x1c))#else#define FFPREG(r) (r)#define DFPREG(r) (r & 0x1e)#define QFPREG(r) (r & 0x1c)#endifstatic int sign_extend(int x, int len){ len = 32 - len; return (x << len) >> len;}#define IS_IMM (insn & (1<<13))/* floating point registers moves */static void gen_op_load_fpr_FT0(unsigned int src){ tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[src])); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, ft0));}static void gen_op_load_fpr_FT1(unsigned int src){ tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[src])); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, ft1));}static void gen_op_store_FT0_fpr(unsigned int dst){ tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, ft0)); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[dst]));}static void gen_op_load_fpr_DT0(unsigned int src){ tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[src])); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, dt0) + offsetof(CPU_DoubleU, l.upper)); tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[src + 1])); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, dt0) + offsetof(CPU_DoubleU, l.lower));}static void gen_op_load_fpr_DT1(unsigned int src){ tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[src])); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, dt1) + offsetof(CPU_DoubleU, l.upper)); tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[src + 1])); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, dt1) + offsetof(CPU_DoubleU, l.lower));}static void gen_op_store_DT0_fpr(unsigned int dst){ tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, dt0) + offsetof(CPU_DoubleU, l.upper)); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[dst])); tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, dt0) + offsetof(CPU_DoubleU, l.lower)); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[dst + 1]));}static void gen_op_load_fpr_QT0(unsigned int src){ tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[src])); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, qt0) + offsetof(CPU_QuadU, l.upmost)); tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[src + 1])); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, qt0) + offsetof(CPU_QuadU, l.upper)); tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[src + 2])); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, qt0) + offsetof(CPU_QuadU, l.lower)); tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[src + 3])); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, qt0) + offsetof(CPU_QuadU, l.lowest));}static void gen_op_load_fpr_QT1(unsigned int src){ tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[src])); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, qt1) + offsetof(CPU_QuadU, l.upmost)); tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[src + 1])); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, qt1) + offsetof(CPU_QuadU, l.upper)); tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[src + 2])); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, qt1) + offsetof(CPU_QuadU, l.lower)); tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[src + 3])); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, qt1) + offsetof(CPU_QuadU, l.lowest));}static void gen_op_store_QT0_fpr(unsigned int dst){ tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, qt0) + offsetof(CPU_QuadU, l.upmost)); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[dst])); tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, qt0) + offsetof(CPU_QuadU, l.upper)); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[dst + 1])); tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, qt0) + offsetof(CPU_QuadU, l.lower)); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[dst + 2])); tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, qt0) + offsetof(CPU_QuadU, l.lowest)); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fpr[dst + 3]));}/* moves */#ifdef CONFIG_USER_ONLY#define supervisor(dc) 0#ifdef TARGET_SPARC64#define hypervisor(dc) 0#endif#else#define supervisor(dc) (dc->mem_idx >= 1)#ifdef TARGET_SPARC64#define hypervisor(dc) (dc->mem_idx == 2)#else#endif#endif#ifdef TARGET_ABI32#define ABI32_MASK(addr) tcg_gen_andi_tl(addr, addr, 0xffffffffULL);#else#define ABI32_MASK(addr)#endifstatic inline void gen_movl_reg_TN(int reg, TCGv tn){ if (reg == 0) tcg_gen_movi_tl(tn, 0); else if (reg < 8) tcg_gen_mov_tl(tn, cpu_gregs[reg]); else { tcg_gen_ld_tl(tn, cpu_regwptr, (reg - 8) * sizeof(target_ulong)); }}static inline void gen_movl_TN_reg(int reg, TCGv tn){ if (reg == 0) return; else if (reg < 8) tcg_gen_mov_tl(cpu_gregs[reg], tn); else { tcg_gen_st_tl(tn, cpu_regwptr, (reg - 8) * sizeof(target_ulong)); }}static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong pc, target_ulong npc){ TranslationBlock *tb; tb = s->tb; if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) && (npc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK)) { /* jump to same page: we can use a direct jump */ tcg_gen_goto_tb(tb_num); tcg_gen_movi_tl(cpu_pc, pc); tcg_gen_movi_tl(cpu_npc, npc); tcg_gen_exit_tb((long)tb + tb_num); } else { /* jump to another page: currently not optimized */ tcg_gen_movi_tl(cpu_pc, pc); tcg_gen_movi_tl(cpu_npc, npc); tcg_gen_exit_tb(0); }}// XXX suboptimalstatic inline void gen_mov_reg_N(TCGv reg, TCGv src){ tcg_gen_extu_i32_tl(reg, src); tcg_gen_shri_tl(reg, reg, PSR_NEG_SHIFT); tcg_gen_andi_tl(reg, reg, 0x1);}static inline void gen_mov_reg_Z(TCGv reg, TCGv src){ tcg_gen_extu_i32_tl(reg, src); tcg_gen_shri_tl(reg, reg, PSR_ZERO_SHIFT); tcg_gen_andi_tl(reg, reg, 0x1);}static inline void gen_mov_reg_V(TCGv reg, TCGv src){ tcg_gen_extu_i32_tl(reg, src); tcg_gen_shri_tl(reg, reg, PSR_OVF_SHIFT); tcg_gen_andi_tl(reg, reg, 0x1);}static inline void gen_mov_reg_C(TCGv reg, TCGv src){ tcg_gen_extu_i32_tl(reg, src); tcg_gen_shri_tl(reg, reg, PSR_CARRY_SHIFT); tcg_gen_andi_tl(reg, reg, 0x1);}static inline void gen_cc_clear_icc(void){ tcg_gen_movi_i32(cpu_psr, 0);}#ifdef TARGET_SPARC64static inline void gen_cc_clear_xcc(void){ tcg_gen_movi_i32(cpu_xcc, 0);}#endif/* old op: if (!T0) env->psr |= PSR_ZERO; if ((int32_t) T0 < 0) env->psr |= PSR_NEG;*/static inline void gen_cc_NZ_icc(TCGv dst){ TCGv r_temp; int l1, l2; l1 = gen_new_label(); l2 = gen_new_label(); r_temp = tcg_temp_new(TCG_TYPE_TL); tcg_gen_andi_tl(r_temp, dst, 0xffffffffULL); tcg_gen_brcond_tl(TCG_COND_NE, r_temp, tcg_const_tl(0), l1); tcg_gen_ori_i32(cpu_psr, cpu_psr, PSR_ZERO); gen_set_label(l1); tcg_gen_ext_i32_tl(r_temp, dst); tcg_gen_brcond_tl(TCG_COND_GE, r_temp, tcg_const_tl(0), l2); tcg_gen_ori_i32(cpu_psr, cpu_psr, PSR_NEG); gen_set_label(l2);}#ifdef TARGET_SPARC64static inline void gen_cc_NZ_xcc(TCGv dst){ int l1, l2; l1 = gen_new_label(); l2 = gen_new_label(); tcg_gen_brcond_tl(TCG_COND_NE, dst, tcg_const_tl(0), l1); tcg_gen_ori_i32(cpu_xcc, cpu_xcc, PSR_ZERO); gen_set_label(l1); tcg_gen_brcond_tl(TCG_COND_GE, dst, tcg_const_tl(0), l2); tcg_gen_ori_i32(cpu_xcc, cpu_xcc, PSR_NEG); gen_set_label(l2);}#endif/* old op: if (T0 < src1) env->psr |= PSR_CARRY;*/static inline void gen_cc_C_add_icc(TCGv dst, TCGv src1){ TCGv r_temp; int l1; l1 = gen_new_label(); r_temp = tcg_temp_new(TCG_TYPE_TL); tcg_gen_andi_tl(r_temp, dst, 0xffffffffULL); tcg_gen_brcond_tl(TCG_COND_GEU, dst, src1, l1); tcg_gen_ori_i32(cpu_psr, cpu_psr, PSR_CARRY); gen_set_label(l1);}#ifdef TARGET_SPARC64static inline void gen_cc_C_add_xcc(TCGv dst, TCGv src1){ int l1; l1 = gen_new_label(); tcg_gen_brcond_tl(TCG_COND_GEU, dst, src1, l1); tcg_gen_ori_i32(cpu_xcc, cpu_xcc, PSR_CARRY); gen_set_label(l1);}#endif/* old op: if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31)) env->psr |= PSR_OVF;*/static inline void gen_cc_V_add_icc(TCGv dst, TCGv src1, TCGv src2){ TCGv r_temp; r_temp = tcg_temp_new(TCG_TYPE_TL); tcg_gen_xor_tl(r_temp, src1, src2); tcg_gen_xori_tl(r_temp, r_temp, -1); tcg_gen_xor_tl(cpu_tmp0, src1, dst); tcg_gen_and_tl(r_temp, r_temp, cpu_tmp0); tcg_gen_andi_tl(r_temp, r_temp, (1 << 31)); tcg_gen_shri_tl(r_temp, r_temp, 31 - PSR_OVF_SHIFT); tcg_gen_trunc_tl_i32(cpu_tmp32, r_temp); tcg_gen_or_i32(cpu_psr, cpu_psr, cpu_tmp32);}#ifdef TARGET_SPARC64static inline void gen_cc_V_add_xcc(TCGv dst, TCGv src1, TCGv src2){ TCGv r_temp; r_temp = tcg_temp_new(TCG_TYPE_TL); tcg_gen_xor_tl(r_temp, src1, src2); tcg_gen_xori_tl(r_temp, r_temp, -1); tcg_gen_xor_tl(cpu_tmp0, src1, dst); tcg_gen_and_tl(r_temp, r_temp, cpu_tmp0); tcg_gen_andi_tl(r_temp, r_temp, (1ULL << 63)); tcg_gen_shri_tl(r_temp, r_temp, 63 - PSR_OVF_SHIFT); tcg_gen_trunc_tl_i32(cpu_tmp32, r_temp); tcg_gen_or_i32(cpu_xcc, cpu_xcc, cpu_tmp32);}#endifstatic inline void gen_add_tv(TCGv dst, TCGv src1, TCGv src2){ TCGv r_temp; int l1; l1 = gen_new_label(); r_temp = tcg_temp_new(TCG_TYPE_TL); tcg_gen_xor_tl(r_temp, src1, src2); tcg_gen_xori_tl(r_temp, r_temp, -1); tcg_gen_xor_tl(cpu_tmp0, src1, dst); tcg_gen_and_tl(r_temp, r_temp, cpu_tmp0); tcg_gen_andi_tl(r_temp, r_temp, (1 << 31)); tcg_gen_brcond_tl(TCG_COND_EQ, r_temp, tcg_const_tl(0), l1); tcg_gen_helper_0_1(raise_exception, tcg_const_i32(TT_TOVF)); gen_set_label(l1);}static inline void gen_cc_V_tag(TCGv src1, TCGv src2){ int l1; l1 = gen_new_label(); tcg_gen_or_tl(cpu_tmp0, src1, src2); tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0x3); tcg_gen_brcond_tl(TCG_COND_EQ, cpu_tmp0, tcg_const_tl(0), l1); tcg_gen_ori_i32(cpu_psr, cpu_psr, PSR_OVF); gen_set_label(l1);}static inline void gen_tag_tv(TCGv src1, TCGv src2){ int l1; l1 = gen_new_label(); tcg_gen_or_tl(cpu_tmp0, src1, src2); tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0x3); tcg_gen_brcond_tl(TCG_COND_EQ, cpu_tmp0, tcg_const_tl(0), l1); tcg_gen_helper_0_1(raise_exception, tcg_const_i32(TT_TOVF)); gen_set_label(l1);}static inline void gen_op_add_cc(TCGv dst, TCGv src1, TCGv src2){
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?