From: Richard Henderson <r...@smalltime.twiddle.net> This saves 3 bytes per memory operation.
Signed-off-by: Richard Henderson <r...@smalltime.twiddle.net> --- tcg/i386/tcg-target.inc.c | 44 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/tcg/i386/tcg-target.inc.c b/tcg/i386/tcg-target.inc.c index 11cbb3c..d8c2f6d 100644 --- a/tcg/i386/tcg-target.inc.c +++ b/tcg/i386/tcg-target.inc.c @@ -290,14 +290,13 @@ static inline int tcg_target_const_match(tcg_target_long val, TCGType type, # define P_REXW 0x1000 /* Set REX.W = 1 */ # define P_REXB_R 0x2000 /* REG field as byte register */ # define P_REXB_RM 0x4000 /* R/M field as byte register */ -# define P_GS 0x8000 /* gs segment override */ #else # define P_ADDR32 0 # define P_REXW 0 # define P_REXB_R 0 # define P_REXB_RM 0 -# define P_GS 0 #endif +#define P_SEG 0x8000 /* fs/gs segment override */ #define P_SIMDF3 0x10000 /* 0xf3 opcode prefix */ #define P_SIMDF2 0x20000 /* 0xf2 opcode prefix */ @@ -420,8 +419,8 @@ static void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x) { int rex; - if (opc & P_GS) { - tcg_out8(s, 0x65); + if (opc & P_SEG) { + tcg_out8(s, 0x65); /* %gs */ } if (opc & P_DATA16) { /* We should never be asking for both 16 and 64-bit operation. */ @@ -462,6 +461,9 @@ static void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x) #else static void tcg_out_opc(TCGContext *s, int opc) { + if (opc & P_SEG) { + tcg_out8(s, 0x64); /* %fs */ + } if (opc & P_DATA16) { tcg_out8(s, 0x66); } @@ -1461,7 +1463,7 @@ static void setup_guest_base(TCGContext *s) } # ifdef __linux__ if (arch_prctl(ARCH_SET_GS, guest_base) == 0) { - guest_base_flags = (TARGET_LONG_BITS == 32 ? P_GS | P_ADDR32 : P_GS); + guest_base_flags = P_SEG + (TARGET_LONG_BITS == 32) * P_ADDR32; return; } # endif @@ -1473,6 +1475,33 @@ static void setup_guest_base(TCGContext *s) tcg_out_movi(s, TCG_TYPE_PTR, guest_base_reg, guest_base); } } +#elif defined(__linux__) +# include <asm/ldt.h> +# include <sys/syscall.h> + +static int32_t guest_base_ofs; +static int guest_base_flags; +#define guest_base_reg -1 +static void setup_guest_base(TCGContext *s) +{ + if (guest_base != 0) { + struct user_desc desc = { + .entry_number = -1, + .base_addr = guest_base, + .limit = 0xfffff, + .seg_32bit = 1, + .limit_in_pages = 1, + .useable = 1, + }; + if (syscall(SYS_set_thread_area, &desc) == 0) { + int seg = desc.entry_number * 8 + 3; + asm volatile("movl %0,%%fs" : : "r"(seg)); + guest_base_flags = P_SEG; + return; + } + } + guest_base_ofs = guest_base; +} #else # define guest_base_flags 0 # define guest_base_reg -1 @@ -2310,6 +2339,9 @@ static void tcg_target_qemu_prologue(TCGContext *s) tcg_out_ld(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP, (ARRAY_SIZE(tcg_target_callee_save_regs) + 1) * 4); tcg_out_addi(s, TCG_REG_ESP, -stack_addend); +# if !defined(CONFIG_SOFTMMU) + setup_guest_base(s); +# endif /* jmp *tb. */ tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, TCG_REG_ESP, (ARRAY_SIZE(tcg_target_callee_save_regs) + 2) * 4 @@ -2317,11 +2349,9 @@ static void tcg_target_qemu_prologue(TCGContext *s) #else tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]); tcg_out_addi(s, TCG_REG_ESP, -stack_addend); - # if !defined(CONFIG_SOFTMMU) setup_guest_base(s); # endif - /* jmp *tb. */ tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[1]); #endif -- 2.5.5