|
|
|
@ -2744,6 +2744,49 @@ static const TCGOutOpBinary outop_remu = { |
|
|
|
.base.static_constraint = C_NotImplemented, |
|
|
|
}; |
|
|
|
|
|
|
|
static TCGConstraintSetIndex cset_shift(TCGType type, unsigned flags) |
|
|
|
{ |
|
|
|
return have_bmi2 ? C_O1_I2(r, r, ri) : C_O1_I2(r, 0, ci); |
|
|
|
} |
|
|
|
|
|
|
|
static void tgen_shl(TCGContext *s, TCGType type, |
|
|
|
TCGReg a0, TCGReg a1, TCGReg a2) |
|
|
|
{ |
|
|
|
int rexw = type == TCG_TYPE_I32 ? 0 : P_REXW; |
|
|
|
if (have_bmi2) { |
|
|
|
tcg_out_vex_modrm(s, OPC_SHLX + rexw, a0, a2, a1); |
|
|
|
} else { |
|
|
|
tcg_out_modrm(s, OPC_SHIFT_cl + rexw, SHIFT_SHL, a0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static void tgen_shli(TCGContext *s, TCGType type, |
|
|
|
TCGReg a0, TCGReg a1, tcg_target_long a2) |
|
|
|
{ |
|
|
|
int rexw = type == TCG_TYPE_I32 ? 0 : P_REXW; |
|
|
|
|
|
|
|
/* For small constant 3-operand shift, use LEA. */ |
|
|
|
if (a0 != a1 && a2 >= 1 && a2 <= 3) { |
|
|
|
if (a2 == 1) { |
|
|
|
/* shl $1,a1,a0 -> lea (a1,a1),a0 */ |
|
|
|
tcg_out_modrm_sib_offset(s, OPC_LEA + rexw, a0, a1, a1, 0, 0); |
|
|
|
} else { |
|
|
|
/* shl $n,a1,a0 -> lea 0(,a1,n),a0 */ |
|
|
|
tcg_out_modrm_sib_offset(s, OPC_LEA + rexw, a0, -1, a1, a2, 0); |
|
|
|
} |
|
|
|
return; |
|
|
|
} |
|
|
|
tcg_out_mov(s, type, a0, a1); |
|
|
|
tcg_out_shifti(s, SHIFT_SHL + rexw, a0, a2); |
|
|
|
} |
|
|
|
|
|
|
|
static const TCGOutOpBinary outop_shl = { |
|
|
|
.base.static_constraint = C_Dynamic, |
|
|
|
.base.dynamic_constraint = cset_shift, |
|
|
|
.out_rrr = tgen_shl, |
|
|
|
.out_rri = tgen_shli, |
|
|
|
}; |
|
|
|
|
|
|
|
static void tgen_sub(TCGContext *s, TCGType type, |
|
|
|
TCGReg a0, TCGReg a1, TCGReg a2) |
|
|
|
{ |
|
|
|
@ -2879,21 +2922,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type, |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
OP_32_64(shl): |
|
|
|
/* For small constant 3-operand shift, use LEA. */ |
|
|
|
if (const_a2 && a0 != a1 && (a2 - 1) < 3) { |
|
|
|
if (a2 - 1 == 0) { |
|
|
|
/* shl $1,a1,a0 -> lea (a1,a1),a0 */ |
|
|
|
tcg_out_modrm_sib_offset(s, OPC_LEA + rexw, a0, a1, a1, 0, 0); |
|
|
|
} else { |
|
|
|
/* shl $n,a1,a0 -> lea 0(,a1,n),a0 */ |
|
|
|
tcg_out_modrm_sib_offset(s, OPC_LEA + rexw, a0, -1, a1, a2, 0); |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
c = SHIFT_SHL; |
|
|
|
vexop = OPC_SHLX; |
|
|
|
goto gen_shift_maybe_vex; |
|
|
|
OP_32_64(shr): |
|
|
|
c = SHIFT_SHR; |
|
|
|
vexop = OPC_SHRX; |
|
|
|
@ -3759,8 +3787,6 @@ tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags) |
|
|
|
case INDEX_op_st_i64: |
|
|
|
return C_O0_I2(re, r); |
|
|
|
|
|
|
|
case INDEX_op_shl_i32: |
|
|
|
case INDEX_op_shl_i64: |
|
|
|
case INDEX_op_shr_i32: |
|
|
|
case INDEX_op_shr_i64: |
|
|
|
case INDEX_op_sar_i32: |
|
|
|
|