diff options
Diffstat (limited to 'src/lj_asm_x86.h')
-rw-r--r-- | src/lj_asm_x86.h | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/src/lj_asm_x86.h b/src/lj_asm_x86.h index 512e0534..718cb12e 100644 --- a/src/lj_asm_x86.h +++ b/src/lj_asm_x86.h | |||
@@ -1956,7 +1956,7 @@ static void asm_bswap(ASMState *as, IRIns *ir) | |||
1956 | #define asm_bor(as, ir) asm_intarith(as, ir, XOg_OR) | 1956 | #define asm_bor(as, ir) asm_intarith(as, ir, XOg_OR) |
1957 | #define asm_bxor(as, ir) asm_intarith(as, ir, XOg_XOR) | 1957 | #define asm_bxor(as, ir) asm_intarith(as, ir, XOg_XOR) |
1958 | 1958 | ||
1959 | static void asm_bitshift(ASMState *as, IRIns *ir, x86Shift xs) | 1959 | static void asm_bitshift(ASMState *as, IRIns *ir, x86Shift xs, x86Op xv) |
1960 | { | 1960 | { |
1961 | IRRef rref = ir->op2; | 1961 | IRRef rref = ir->op2; |
1962 | IRIns *irr = IR(rref); | 1962 | IRIns *irr = IR(rref); |
@@ -1965,11 +1965,27 @@ static void asm_bitshift(ASMState *as, IRIns *ir, x86Shift xs) | |||
1965 | int shift; | 1965 | int shift; |
1966 | dest = ra_dest(as, ir, RSET_GPR); | 1966 | dest = ra_dest(as, ir, RSET_GPR); |
1967 | shift = irr->i & (irt_is64(ir->t) ? 63 : 31); | 1967 | shift = irr->i & (irt_is64(ir->t) ? 63 : 31); |
1968 | if (!xv && shift && (as->flags & JIT_F_BMI2)) { | ||
1969 | Reg left = asm_fuseloadm(as, ir->op1, RSET_GPR, irt_is64(ir->t)); | ||
1970 | if (left != dest) { /* BMI2 rotate right by constant. */ | ||
1971 | emit_i8(as, xs == XOg_ROL ? -shift : shift); | ||
1972 | emit_mrm(as, VEX_64IR(ir, XV_RORX), dest, left); | ||
1973 | return; | ||
1974 | } | ||
1975 | } | ||
1968 | switch (shift) { | 1976 | switch (shift) { |
1969 | case 0: break; | 1977 | case 0: break; |
1970 | case 1: emit_rr(as, XO_SHIFT1, REX_64IR(ir, xs), dest); break; | 1978 | case 1: emit_rr(as, XO_SHIFT1, REX_64IR(ir, xs), dest); break; |
1971 | default: emit_shifti(as, REX_64IR(ir, xs), dest, shift); break; | 1979 | default: emit_shifti(as, REX_64IR(ir, xs), dest, shift); break; |
1972 | } | 1980 | } |
1981 | } else if ((as->flags & JIT_F_BMI2) && xv) { /* BMI2 variable shifts. */ | ||
1982 | Reg left, right; | ||
1983 | dest = ra_dest(as, ir, RSET_GPR); | ||
1984 | right = ra_alloc1(as, rref, RSET_GPR); | ||
1985 | left = asm_fuseloadm(as, ir->op1, rset_exclude(RSET_GPR, right), | ||
1986 | irt_is64(ir->t)); | ||
1987 | emit_mrm(as, VEX_64IR(ir, xv) ^ (right << 19), dest, left); | ||
1988 | return; | ||
1973 | } else { /* Variable shifts implicitly use register cl (i.e. ecx). */ | 1989 | } else { /* Variable shifts implicitly use register cl (i.e. ecx). */ |
1974 | Reg right; | 1990 | Reg right; |
1975 | dest = ra_dest(as, ir, rset_exclude(RSET_GPR, RID_ECX)); | 1991 | dest = ra_dest(as, ir, rset_exclude(RSET_GPR, RID_ECX)); |
@@ -1995,11 +2011,11 @@ static void asm_bitshift(ASMState *as, IRIns *ir, x86Shift xs) | |||
1995 | */ | 2011 | */ |
1996 | } | 2012 | } |
1997 | 2013 | ||
1998 | #define asm_bshl(as, ir) asm_bitshift(as, ir, XOg_SHL) | 2014 | #define asm_bshl(as, ir) asm_bitshift(as, ir, XOg_SHL, XV_SHLX) |
1999 | #define asm_bshr(as, ir) asm_bitshift(as, ir, XOg_SHR) | 2015 | #define asm_bshr(as, ir) asm_bitshift(as, ir, XOg_SHR, XV_SHRX) |
2000 | #define asm_bsar(as, ir) asm_bitshift(as, ir, XOg_SAR) | 2016 | #define asm_bsar(as, ir) asm_bitshift(as, ir, XOg_SAR, XV_SARX) |
2001 | #define asm_brol(as, ir) asm_bitshift(as, ir, XOg_ROL) | 2017 | #define asm_brol(as, ir) asm_bitshift(as, ir, XOg_ROL, 0) |
2002 | #define asm_bror(as, ir) asm_bitshift(as, ir, XOg_ROR) | 2018 | #define asm_bror(as, ir) asm_bitshift(as, ir, XOg_ROR, 0) |
2003 | 2019 | ||
2004 | /* -- Comparisons --------------------------------------------------------- */ | 2020 | /* -- Comparisons --------------------------------------------------------- */ |
2005 | 2021 | ||