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 + -
显示快捷键?