translate.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 2,495 行 · 第 1/5 页

C
2,495
字号
/* *  i386 translation * *  Copyright (c) 2003 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 <signal.h>#include <assert.h>#include "cpu.h"#include "exec-all.h"#include "disas.h"#include "helper.h"#include "tcg-op.h"#define PREFIX_REPZ   0x01#define PREFIX_REPNZ  0x02#define PREFIX_LOCK   0x04#define PREFIX_DATA   0x08#define PREFIX_ADR    0x10#ifdef TARGET_X86_64#define X86_64_ONLY(x) x#define X86_64_DEF(x...) x#define CODE64(s) ((s)->code64)#define REX_X(s) ((s)->rex_x)#define REX_B(s) ((s)->rex_b)/* XXX: gcc generates push/pop in some opcodes, so we cannot use them */#if 1#define BUGGY_64(x) NULL#endif#else#define X86_64_ONLY(x) NULL#define X86_64_DEF(x...)#define CODE64(s) 0#define REX_X(s) 0#define REX_B(s) 0#endif//#define MACRO_TEST   1/* global register indexes */static TCGv cpu_env, cpu_T[2], cpu_A0;/* local register indexes (only used inside old micro ops) */static TCGv cpu_tmp0, cpu_tmp1, cpu_tmp2, cpu_ptr0, cpu_ptr1;#ifdef TARGET_X86_64static int x86_64_hregs;#endiftypedef struct DisasContext {    /* current insn context */    int override; /* -1 if no override */    int prefix;    int aflag, dflag;    target_ulong pc; /* pc = eip + cs_base */    int is_jmp; /* 1 = means jump (stop translation), 2 means CPU                   static state change (stop translation) */    /* current block context */    target_ulong cs_base; /* base of CS segment */    int pe;     /* protected mode */    int code32; /* 32 bit code segment */#ifdef TARGET_X86_64    int lma;    /* long mode active */    int code64; /* 64 bit code segment */    int rex_x, rex_b;#endif    int ss32;   /* 32 bit stack segment */    int cc_op;  /* current CC operation */    int addseg; /* non zero if either DS/ES/SS have a non zero base */    int f_st;   /* currently unused */    int vm86;   /* vm86 mode */    int cpl;    int iopl;    int tf;     /* TF cpu flag */    int singlestep_enabled; /* "hardware" single step enabled */    int jmp_opt; /* use direct block chaining for direct jumps */    int mem_index; /* select memory access functions */    uint64_t flags; /* all execution flags */    struct TranslationBlock *tb;    int popl_esp_hack; /* for correct popl with esp base handling */    int rip_offset; /* only used in x86_64, but left for simplicity */    int cpuid_features;    int cpuid_ext_features;    int cpuid_ext2_features;} DisasContext;static void gen_eob(DisasContext *s);static void gen_jmp(DisasContext *s, target_ulong eip);static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);/* i386 arith/logic operations */enum {    OP_ADDL,    OP_ORL,    OP_ADCL,    OP_SBBL,    OP_ANDL,    OP_SUBL,    OP_XORL,    OP_CMPL,};/* i386 shift ops */enum {    OP_ROL,    OP_ROR,    OP_RCL,    OP_RCR,    OP_SHL,    OP_SHR,    OP_SHL1, /* undocumented */    OP_SAR = 7,};/* operand size */enum {    OT_BYTE = 0,    OT_WORD,    OT_LONG,    OT_QUAD,};enum {    /* I386 int registers */    OR_EAX,   /* MUST be even numbered */    OR_ECX,    OR_EDX,    OR_EBX,    OR_ESP,    OR_EBP,    OR_ESI,    OR_EDI,    OR_TMP0 = 16,    /* temporary operand register */    OR_TMP1,    OR_A0, /* temporary register used when doing address evaluation */};static inline void gen_op_movl_T0_0(void){    tcg_gen_movi_tl(cpu_T[0], 0);}static inline void gen_op_movl_T0_im(int32_t val){    tcg_gen_movi_tl(cpu_T[0], val);}static inline void gen_op_movl_T0_imu(uint32_t val){    tcg_gen_movi_tl(cpu_T[0], val);}static inline void gen_op_movl_T1_im(int32_t val){    tcg_gen_movi_tl(cpu_T[1], val);}static inline void gen_op_movl_T1_imu(uint32_t val){    tcg_gen_movi_tl(cpu_T[1], val);}static inline void gen_op_movl_A0_im(uint32_t val){    tcg_gen_movi_tl(cpu_A0, val);}#ifdef TARGET_X86_64static inline void gen_op_movq_A0_im(int64_t val){    tcg_gen_movi_tl(cpu_A0, val);}#endifstatic inline void gen_movtl_T0_im(target_ulong val){    tcg_gen_movi_tl(cpu_T[0], val);}static inline void gen_movtl_T1_im(target_ulong val){    tcg_gen_movi_tl(cpu_T[1], val);}static inline void gen_op_andl_T0_ffff(void){    tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);}static inline void gen_op_andl_T0_im(uint32_t val){    tcg_gen_andi_tl(cpu_T[0], cpu_T[0], val);}static inline void gen_op_movl_T0_T1(void){    tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);}static inline void gen_op_andl_A0_ffff(void){    tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffff);}#ifdef TARGET_X86_64#define NB_OP_SIZES 4#define DEF_REGS(prefix, suffix) \  prefix ## EAX ## suffix,\  prefix ## ECX ## suffix,\  prefix ## EDX ## suffix,\  prefix ## EBX ## suffix,\  prefix ## ESP ## suffix,\  prefix ## EBP ## suffix,\  prefix ## ESI ## suffix,\  prefix ## EDI ## suffix,\  prefix ## R8 ## suffix,\  prefix ## R9 ## suffix,\  prefix ## R10 ## suffix,\  prefix ## R11 ## suffix,\  prefix ## R12 ## suffix,\  prefix ## R13 ## suffix,\  prefix ## R14 ## suffix,\  prefix ## R15 ## suffix,#else /* !TARGET_X86_64 */#define NB_OP_SIZES 3#define DEF_REGS(prefix, suffix) \  prefix ## EAX ## suffix,\  prefix ## ECX ## suffix,\  prefix ## EDX ## suffix,\  prefix ## EBX ## suffix,\  prefix ## ESP ## suffix,\  prefix ## EBP ## suffix,\  prefix ## ESI ## suffix,\  prefix ## EDI ## suffix,#endif /* !TARGET_X86_64 */#if defined(WORDS_BIGENDIAN)#define REG_B_OFFSET (sizeof(target_ulong) - 1)#define REG_H_OFFSET (sizeof(target_ulong) - 2)#define REG_W_OFFSET (sizeof(target_ulong) - 2)#define REG_L_OFFSET (sizeof(target_ulong) - 4)#define REG_LH_OFFSET (sizeof(target_ulong) - 8)#else#define REG_B_OFFSET 0#define REG_H_OFFSET 1#define REG_W_OFFSET 0#define REG_L_OFFSET 0#define REG_LH_OFFSET 4#endifstatic inline void gen_op_mov_reg_TN(int ot, int t_index, int reg){    switch(ot) {    case OT_BYTE:        if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) {            tcg_gen_st8_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg]) + REG_B_OFFSET);        } else {            tcg_gen_st8_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg - 4]) + REG_H_OFFSET);        }        break;    case OT_WORD:        tcg_gen_st16_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET);        break;#ifdef TARGET_X86_64    case OT_LONG:        tcg_gen_st32_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET);        /* high part of register set to zero */        tcg_gen_movi_tl(cpu_tmp0, 0);        tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_LH_OFFSET);        break;    default:    case OT_QUAD:        tcg_gen_st_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg]));        break;#else    default:    case OT_LONG:        tcg_gen_st32_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET);        break;#endif    }}static inline void gen_op_mov_reg_T0(int ot, int reg){    gen_op_mov_reg_TN(ot, 0, reg);}static inline void gen_op_mov_reg_T1(int ot, int reg){    gen_op_mov_reg_TN(ot, 1, reg);}static inline void gen_op_mov_reg_A0(int size, int reg){    switch(size) {    case 0:        tcg_gen_st16_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET);        break;#ifdef TARGET_X86_64    case 1:        tcg_gen_st32_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET);        /* high part of register set to zero */        tcg_gen_movi_tl(cpu_tmp0, 0);        tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_LH_OFFSET);        break;    default:    case 2:        tcg_gen_st_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]));        break;#else    default:    case 1:        tcg_gen_st32_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET);        break;#endif    }}static inline void gen_op_mov_TN_reg(int ot, int t_index, int reg){    switch(ot) {    case OT_BYTE:        if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) {            goto std_case;        } else {            tcg_gen_ld8u_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg - 4]) + REG_H_OFFSET);        }        break;    default:    std_case:        tcg_gen_ld_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg]));        break;    }}static inline void gen_op_movl_A0_reg(int reg){    tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET);}static inline void gen_op_addl_A0_im(int32_t val){    tcg_gen_addi_tl(cpu_A0, cpu_A0, val);#ifdef TARGET_X86_64    tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);#endif}#ifdef TARGET_X86_64static inline void gen_op_addq_A0_im(int64_t val){    tcg_gen_addi_tl(cpu_A0, cpu_A0, val);}#endif    static void gen_add_A0_im(DisasContext *s, int val){#ifdef TARGET_X86_64    if (CODE64(s))        gen_op_addq_A0_im(val);    else#endif        gen_op_addl_A0_im(val);}static inline void gen_op_addl_T0_T1(void){    tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);}static inline void gen_op_jmp_T0(void){    tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, eip));}static inline void gen_op_addw_ESP_im(int32_t val){    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP]));    tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val);    tcg_gen_st16_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP]) + REG_W_OFFSET);}static inline void gen_op_addl_ESP_im(int32_t val){    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP]));    tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val);#ifdef TARGET_X86_64    tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffff);#endif    tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP]));}#ifdef TARGET_X86_64static inline void gen_op_addq_ESP_im(int32_t val){    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP]));    tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val);    tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP]));}#endifstatic inline void gen_op_set_cc_op(int32_t val){    tcg_gen_movi_tl(cpu_tmp0, val);    tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUState, cc_op));}static inline void gen_op_addl_A0_reg_sN(int shift, int reg){    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));    if (shift != 0)         tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);    tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);#ifdef TARGET_X86_64    tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);#endif}static inline void gen_op_movl_A0_seg(int reg){    tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUState, segs[reg].base) + REG_L_OFFSET);}static inline void gen_op_addl_A0_seg(int reg){    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, segs[reg].base));    tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);#ifdef TARGET_X86_64    tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);#endif}#ifdef TARGET_X86_64static inline void gen_op_movq_A0_seg(int reg){    tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUState, segs[reg].base));}static inline void gen_op_addq_A0_seg(int reg){    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, segs[reg].base));    tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);}static inline void gen_op_movq_A0_reg(int reg){    tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]));}static inline void gen_op_addq_A0_reg_sN(int shift, int reg){    tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));    if (shift != 0)         tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift);    tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);}#endifstatic GenOpFunc *gen_op_cmov_reg_T1_T0[NB_OP_SIZES - 1][CPU_NB_REGS] = {    [0] = {        DEF_REGS(gen_op_cmovw_, _T1_T0)    },    [1] = {        DEF_REGS(gen_op_cmovl_, _T1_T0)    },#ifdef TARGET_X86_64    [2] = {        DEF_REGS(gen_op_cmovq_, _T1_T0)    },#endif};

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?