Infer REX prefix for SIMD operations; fixes #1127
- Convert recipes to have necessary size calculator - Add a missing binemit function, `put_dynrexmp3` - Modify the meta-encodings of x86 SIMD instructions to use `infer_rex()`, mostly through the `enc_both_inferred()` helper - Fix up tests that previously always emitted a REX prefix
This commit is contained in:
@@ -547,41 +547,35 @@ pub(crate) fn define<'shared>(
|
||||
);
|
||||
|
||||
// XX /r
|
||||
recipes.add_template(
|
||||
Template::new(
|
||||
EncodingRecipeBuilder::new("rr", &formats.binary, 1)
|
||||
.operands_in(vec![gpr, gpr])
|
||||
.operands_out(vec![0])
|
||||
.emit(
|
||||
r#"
|
||||
recipes.add_template_inferred(
|
||||
EncodingRecipeBuilder::new("rr", &formats.binary, 1)
|
||||
.operands_in(vec![gpr, gpr])
|
||||
.operands_out(vec![0])
|
||||
.emit(
|
||||
r#"
|
||||
{{PUT_OP}}(bits, rex2(in_reg0, in_reg1), sink);
|
||||
modrm_rr(in_reg0, in_reg1, sink);
|
||||
"#,
|
||||
),
|
||||
regs,
|
||||
)
|
||||
.inferred_rex_compute_size("size_with_inferred_rex_for_inreg0_inreg1"),
|
||||
),
|
||||
"size_with_inferred_rex_for_inreg0_inreg1",
|
||||
);
|
||||
|
||||
// XX /r with operands swapped. (RM form).
|
||||
recipes.add_template(
|
||||
Template::new(
|
||||
EncodingRecipeBuilder::new("rrx", &formats.binary, 1)
|
||||
.operands_in(vec![gpr, gpr])
|
||||
.operands_out(vec![0])
|
||||
.emit(
|
||||
r#"
|
||||
recipes.add_template_inferred(
|
||||
EncodingRecipeBuilder::new("rrx", &formats.binary, 1)
|
||||
.operands_in(vec![gpr, gpr])
|
||||
.operands_out(vec![0])
|
||||
.emit(
|
||||
r#"
|
||||
{{PUT_OP}}(bits, rex2(in_reg1, in_reg0), sink);
|
||||
modrm_rr(in_reg1, in_reg0, sink);
|
||||
"#,
|
||||
),
|
||||
regs,
|
||||
)
|
||||
.inferred_rex_compute_size("size_with_inferred_rex_for_inreg0_inreg1"),
|
||||
),
|
||||
"size_with_inferred_rex_for_inreg0_inreg1",
|
||||
);
|
||||
|
||||
// XX /r with FPR ins and outs. A form.
|
||||
recipes.add_template_recipe(
|
||||
recipes.add_template_inferred(
|
||||
EncodingRecipeBuilder::new("fa", &formats.binary, 1)
|
||||
.operands_in(vec![fpr, fpr])
|
||||
.operands_out(vec![0])
|
||||
@@ -591,10 +585,11 @@ pub(crate) fn define<'shared>(
|
||||
modrm_rr(in_reg1, in_reg0, sink);
|
||||
"#,
|
||||
),
|
||||
"size_with_inferred_rex_for_inreg0_inreg1",
|
||||
);
|
||||
|
||||
// XX /r with FPR ins and outs. A form with input operands swapped.
|
||||
recipes.add_template_recipe(
|
||||
recipes.add_template_inferred(
|
||||
EncodingRecipeBuilder::new("fax", &formats.binary, 1)
|
||||
.operands_in(vec![fpr, fpr])
|
||||
.operands_out(vec![1])
|
||||
@@ -604,11 +599,13 @@ pub(crate) fn define<'shared>(
|
||||
modrm_rr(in_reg0, in_reg1, sink);
|
||||
"#,
|
||||
),
|
||||
// The operand order does not matter for calculating whether a REX prefix is needed.
|
||||
"size_with_inferred_rex_for_inreg0_inreg1",
|
||||
);
|
||||
|
||||
// XX /r with FPR ins and outs. A form with a byte immediate.
|
||||
{
|
||||
recipes.add_template_recipe(
|
||||
recipes.add_template_inferred(
|
||||
EncodingRecipeBuilder::new("fa_ib", &formats.insert_lane, 2)
|
||||
.operands_in(vec![fpr, fpr])
|
||||
.operands_out(vec![0])
|
||||
@@ -626,6 +623,7 @@ pub(crate) fn define<'shared>(
|
||||
sink.put1(imm as u8);
|
||||
"#,
|
||||
),
|
||||
"size_with_inferred_rex_for_inreg0_inreg1",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -740,7 +738,7 @@ pub(crate) fn define<'shared>(
|
||||
);
|
||||
|
||||
// XX /r, RM form, FPR -> FPR.
|
||||
recipes.add_template_recipe(
|
||||
recipes.add_template_inferred(
|
||||
EncodingRecipeBuilder::new("furm", &formats.unary, 1)
|
||||
.operands_in(vec![fpr])
|
||||
.operands_out(vec![fpr])
|
||||
@@ -751,6 +749,7 @@ pub(crate) fn define<'shared>(
|
||||
modrm_rr(in_reg0, out_reg0, sink);
|
||||
"#,
|
||||
),
|
||||
"size_with_inferred_rex_for_inreg0_outreg0",
|
||||
);
|
||||
|
||||
// Same as furm, but with the source register specified directly.
|
||||
@@ -768,21 +767,18 @@ pub(crate) fn define<'shared>(
|
||||
);
|
||||
|
||||
// XX /r, RM form, GPR -> FPR.
|
||||
recipes.add_template(
|
||||
Template::new(
|
||||
EncodingRecipeBuilder::new("frurm", &formats.unary, 1)
|
||||
.operands_in(vec![gpr])
|
||||
.operands_out(vec![fpr])
|
||||
.clobbers_flags(false)
|
||||
.emit(
|
||||
r#"
|
||||
recipes.add_template_inferred(
|
||||
EncodingRecipeBuilder::new("frurm", &formats.unary, 1)
|
||||
.operands_in(vec![gpr])
|
||||
.operands_out(vec![fpr])
|
||||
.clobbers_flags(false)
|
||||
.emit(
|
||||
r#"
|
||||
{{PUT_OP}}(bits, rex2(in_reg0, out_reg0), sink);
|
||||
modrm_rr(in_reg0, out_reg0, sink);
|
||||
"#,
|
||||
),
|
||||
regs,
|
||||
)
|
||||
.inferred_rex_compute_size("size_with_inferred_rex_for_inreg0_outreg0"),
|
||||
),
|
||||
"size_with_inferred_rex_for_inreg0_outreg0",
|
||||
);
|
||||
|
||||
// XX /r, RM form, FPR -> GPR.
|
||||
@@ -909,31 +905,28 @@ pub(crate) fn define<'shared>(
|
||||
|
||||
// XX /n ib with 8-bit immediate sign-extended.
|
||||
{
|
||||
recipes.add_template(
|
||||
Template::new(
|
||||
EncodingRecipeBuilder::new("r_ib", &formats.binary_imm, 2)
|
||||
.operands_in(vec![gpr])
|
||||
.operands_out(vec![0])
|
||||
.inst_predicate(InstructionPredicate::new_is_signed_int(
|
||||
&*formats.binary_imm,
|
||||
"imm",
|
||||
8,
|
||||
0,
|
||||
))
|
||||
.emit(
|
||||
r#"
|
||||
recipes.add_template_inferred(
|
||||
EncodingRecipeBuilder::new("r_ib", &formats.binary_imm, 2)
|
||||
.operands_in(vec![gpr])
|
||||
.operands_out(vec![0])
|
||||
.inst_predicate(InstructionPredicate::new_is_signed_int(
|
||||
&*formats.binary_imm,
|
||||
"imm",
|
||||
8,
|
||||
0,
|
||||
))
|
||||
.emit(
|
||||
r#"
|
||||
{{PUT_OP}}(bits, rex1(in_reg0), sink);
|
||||
modrm_r_bits(in_reg0, bits, sink);
|
||||
let imm: i64 = imm.into();
|
||||
sink.put1(imm as u8);
|
||||
"#,
|
||||
),
|
||||
regs,
|
||||
)
|
||||
.inferred_rex_compute_size("size_with_inferred_rex_for_inreg0"),
|
||||
),
|
||||
"size_with_inferred_rex_for_inreg0",
|
||||
);
|
||||
|
||||
recipes.add_template_recipe(
|
||||
recipes.add_template_inferred(
|
||||
EncodingRecipeBuilder::new("f_ib", &formats.binary_imm, 2)
|
||||
.operands_in(vec![fpr])
|
||||
.operands_out(vec![0])
|
||||
@@ -951,6 +944,7 @@ pub(crate) fn define<'shared>(
|
||||
sink.put1(imm as u8);
|
||||
"#,
|
||||
),
|
||||
"size_with_inferred_rex_for_inreg0",
|
||||
);
|
||||
|
||||
// XX /n id with 32-bit immediate sign-extended.
|
||||
@@ -981,7 +975,7 @@ pub(crate) fn define<'shared>(
|
||||
|
||||
// XX /r ib with 8-bit unsigned immediate (e.g. for pshufd)
|
||||
{
|
||||
recipes.add_template_recipe(
|
||||
recipes.add_template_inferred(
|
||||
EncodingRecipeBuilder::new("r_ib_unsigned_fpr", &formats.extract_lane, 2)
|
||||
.operands_in(vec![fpr])
|
||||
.operands_out(vec![fpr])
|
||||
@@ -999,12 +993,13 @@ pub(crate) fn define<'shared>(
|
||||
sink.put1(imm as u8);
|
||||
"#,
|
||||
),
|
||||
"size_with_inferred_rex_for_inreg0_outreg0",
|
||||
);
|
||||
}
|
||||
|
||||
// XX /r ib with 8-bit unsigned immediate (e.g. for extractlane)
|
||||
{
|
||||
recipes.add_template_recipe(
|
||||
recipes.add_template_inferred(
|
||||
EncodingRecipeBuilder::new("r_ib_unsigned_gpr", &formats.extract_lane, 2)
|
||||
.operands_in(vec![fpr])
|
||||
.operands_out(vec![gpr])
|
||||
@@ -1018,13 +1013,13 @@ pub(crate) fn define<'shared>(
|
||||
let imm:i64 = lane.into();
|
||||
sink.put1(imm as u8);
|
||||
"#,
|
||||
),
|
||||
), "size_with_inferred_rex_for_inreg0_outreg0"
|
||||
);
|
||||
}
|
||||
|
||||
// XX /r ib with 8-bit unsigned immediate (e.g. for insertlane)
|
||||
{
|
||||
recipes.add_template_recipe(
|
||||
recipes.add_template_inferred(
|
||||
EncodingRecipeBuilder::new("r_ib_unsigned_r", &formats.insert_lane, 2)
|
||||
.operands_in(vec![fpr, gpr])
|
||||
.operands_out(vec![0])
|
||||
@@ -1042,6 +1037,7 @@ pub(crate) fn define<'shared>(
|
||||
sink.put1(imm as u8);
|
||||
"#,
|
||||
),
|
||||
"size_with_inferred_rex_for_inreg0_inreg1",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2825,7 +2821,7 @@ pub(crate) fn define<'shared>(
|
||||
);
|
||||
|
||||
// XX /r, RM form. Compare two FPR registers and set flags.
|
||||
recipes.add_template_recipe(
|
||||
recipes.add_template_inferred(
|
||||
EncodingRecipeBuilder::new("fcmp", &formats.binary, 1)
|
||||
.operands_in(vec![fpr, fpr])
|
||||
.operands_out(vec![reg_rflags])
|
||||
@@ -2835,6 +2831,7 @@ pub(crate) fn define<'shared>(
|
||||
modrm_rr(in_reg1, in_reg0, sink);
|
||||
"#,
|
||||
),
|
||||
"size_with_inferred_rex_for_inreg0_inreg1",
|
||||
);
|
||||
|
||||
{
|
||||
@@ -3089,7 +3086,7 @@ pub(crate) fn define<'shared>(
|
||||
.inferred_rex_compute_size("size_with_inferred_rex_for_inreg0_inreg1"),
|
||||
);
|
||||
|
||||
recipes.add_template_recipe(
|
||||
recipes.add_template_inferred(
|
||||
EncodingRecipeBuilder::new("icscc_fpr", &formats.int_compare, 1)
|
||||
.operands_in(vec![fpr, fpr])
|
||||
.operands_out(vec![0])
|
||||
@@ -3100,6 +3097,7 @@ pub(crate) fn define<'shared>(
|
||||
modrm_rr(in_reg1, in_reg0, sink);
|
||||
"#,
|
||||
),
|
||||
"size_with_inferred_rex_for_inreg0_inreg1",
|
||||
);
|
||||
|
||||
{
|
||||
@@ -3219,7 +3217,7 @@ pub(crate) fn define<'shared>(
|
||||
.iter()
|
||||
.map(|name| Literal::enumerator_for(floatcc, name))
|
||||
.collect();
|
||||
recipes.add_template_recipe(
|
||||
recipes.add_template_inferred(
|
||||
EncodingRecipeBuilder::new("pfcmp", &formats.float_compare, 2)
|
||||
.operands_in(vec![fpr, fpr])
|
||||
.operands_out(vec![0])
|
||||
@@ -3248,6 +3246,7 @@ pub(crate) fn define<'shared>(
|
||||
sink.put1(imm);
|
||||
"#,
|
||||
),
|
||||
"size_with_inferred_rex_for_inreg0_inreg1",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user