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