[meta] Remove name lookups in formats;
This does a lot at once, since there was no clear way to split the three commits: - Instruction need to be passed an explicit InstructionFormat, - InstructionFormat deduplication is checked once all entities have been defined;
This commit is contained in:
@@ -53,11 +53,7 @@ pub(crate) fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
|
||||
let settings = define_settings(&shared_defs.settings);
|
||||
let regs = define_regs();
|
||||
|
||||
let inst_group = InstructionGroupBuilder::new(
|
||||
&mut shared_defs.all_instructions,
|
||||
&shared_defs.format_registry,
|
||||
)
|
||||
.build();
|
||||
let inst_group = InstructionGroupBuilder::new(&mut shared_defs.all_instructions).build();
|
||||
|
||||
// CPU modes for 32-bit ARM and Thumb2.
|
||||
let mut a32 = CpuMode::new("A32");
|
||||
|
||||
@@ -49,11 +49,7 @@ pub(crate) fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
|
||||
let settings = define_settings(&shared_defs.settings);
|
||||
let regs = define_registers();
|
||||
|
||||
let inst_group = InstructionGroupBuilder::new(
|
||||
&mut shared_defs.all_instructions,
|
||||
&shared_defs.format_registry,
|
||||
)
|
||||
.build();
|
||||
let inst_group = InstructionGroupBuilder::new(&mut shared_defs.all_instructions).build();
|
||||
|
||||
let mut a64 = CpuMode::new("A64");
|
||||
|
||||
|
||||
@@ -89,11 +89,7 @@ pub(crate) fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
|
||||
let settings = define_settings(&shared_defs.settings);
|
||||
let regs = define_registers();
|
||||
|
||||
let inst_group = InstructionGroupBuilder::new(
|
||||
&mut shared_defs.all_instructions,
|
||||
&shared_defs.format_registry,
|
||||
)
|
||||
.build();
|
||||
let inst_group = InstructionGroupBuilder::new(&mut shared_defs.all_instructions).build();
|
||||
|
||||
// CPU modes for 32-bit and 64-bit operation.
|
||||
let mut rv_32 = CpuMode::new("RV32");
|
||||
|
||||
@@ -46,23 +46,7 @@ impl RecipeGroup {
|
||||
}
|
||||
|
||||
pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeGroup {
|
||||
// Format shorthands.
|
||||
let formats = &shared_defs.format_registry;
|
||||
|
||||
let f_binary = formats.by_name("Binary");
|
||||
let f_binary_imm = formats.by_name("BinaryImm");
|
||||
let f_branch = formats.by_name("Branch");
|
||||
let f_branch_icmp = formats.by_name("BranchIcmp");
|
||||
let f_call = formats.by_name("Call");
|
||||
let f_call_indirect = formats.by_name("CallIndirect");
|
||||
let f_copy_to_ssa = formats.by_name("CopyToSsa");
|
||||
let f_int_compare = formats.by_name("IntCompare");
|
||||
let f_int_compare_imm = formats.by_name("IntCompareImm");
|
||||
let f_jump = formats.by_name("Jump");
|
||||
let f_multiary = formats.by_name("MultiAry");
|
||||
let f_regmove = formats.by_name("RegMove");
|
||||
let f_unary = formats.by_name("Unary");
|
||||
let f_unary_imm = formats.by_name("UnaryImm");
|
||||
let formats = &shared_defs.formats;
|
||||
|
||||
// Register classes shorthands.
|
||||
let gpr = regs.class_by_name("GPR");
|
||||
@@ -73,7 +57,7 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
// R-type 32-bit instructions: These are mostly binary arithmetic instructions.
|
||||
// The encbits are `opcode[6:2] | (funct3 << 5) | (funct7 << 8)
|
||||
recipes.push(
|
||||
EncodingRecipeBuilder::new("R", f_binary, 4)
|
||||
EncodingRecipeBuilder::new("R", &formats.binary, 4)
|
||||
.operands_in(vec![gpr, gpr])
|
||||
.operands_out(vec![gpr])
|
||||
.emit("put_r(bits, in_reg0, in_reg1, out_reg0, sink);"),
|
||||
@@ -81,7 +65,7 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
|
||||
// R-type with an immediate shift amount instead of rs2.
|
||||
recipes.push(
|
||||
EncodingRecipeBuilder::new("Rshamt", f_binary_imm, 4)
|
||||
EncodingRecipeBuilder::new("Rshamt", &formats.binary_imm, 4)
|
||||
.operands_in(vec![gpr])
|
||||
.operands_out(vec![gpr])
|
||||
.emit("put_rshamt(bits, in_reg0, imm.into(), out_reg0, sink);"),
|
||||
@@ -89,18 +73,18 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
|
||||
// R-type encoding of an integer comparison.
|
||||
recipes.push(
|
||||
EncodingRecipeBuilder::new("Ricmp", f_int_compare, 4)
|
||||
EncodingRecipeBuilder::new("Ricmp", &formats.int_compare, 4)
|
||||
.operands_in(vec![gpr, gpr])
|
||||
.operands_out(vec![gpr])
|
||||
.emit("put_r(bits, in_reg0, in_reg1, out_reg0, sink);"),
|
||||
);
|
||||
|
||||
recipes.push(
|
||||
EncodingRecipeBuilder::new("Ii", f_binary_imm, 4)
|
||||
EncodingRecipeBuilder::new("Ii", &formats.binary_imm, 4)
|
||||
.operands_in(vec![gpr])
|
||||
.operands_out(vec![gpr])
|
||||
.inst_predicate(InstructionPredicate::new_is_signed_int(
|
||||
&*f_binary_imm,
|
||||
&*formats.binary_imm,
|
||||
"imm",
|
||||
12,
|
||||
0,
|
||||
@@ -110,10 +94,10 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
|
||||
// I-type instruction with a hardcoded %x0 rs1.
|
||||
recipes.push(
|
||||
EncodingRecipeBuilder::new("Iz", f_unary_imm, 4)
|
||||
EncodingRecipeBuilder::new("Iz", &formats.unary_imm, 4)
|
||||
.operands_out(vec![gpr])
|
||||
.inst_predicate(InstructionPredicate::new_is_signed_int(
|
||||
&*f_unary_imm,
|
||||
&*&formats.unary_imm,
|
||||
"imm",
|
||||
12,
|
||||
0,
|
||||
@@ -123,11 +107,11 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
|
||||
// I-type encoding of an integer comparison.
|
||||
recipes.push(
|
||||
EncodingRecipeBuilder::new("Iicmp", f_int_compare_imm, 4)
|
||||
EncodingRecipeBuilder::new("Iicmp", &formats.int_compare_imm, 4)
|
||||
.operands_in(vec![gpr])
|
||||
.operands_out(vec![gpr])
|
||||
.inst_predicate(InstructionPredicate::new_is_signed_int(
|
||||
&*f_int_compare_imm,
|
||||
&*&formats.int_compare_imm,
|
||||
"imm",
|
||||
12,
|
||||
0,
|
||||
@@ -137,8 +121,9 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
|
||||
// I-type encoding for `jalr` as a return instruction. We won't use the immediate offset. The
|
||||
// variable return values are not encoded.
|
||||
recipes.push(EncodingRecipeBuilder::new("Iret", f_multiary, 4).emit(
|
||||
r#"
|
||||
recipes.push(
|
||||
EncodingRecipeBuilder::new("Iret", &formats.multiary, 4).emit(
|
||||
r#"
|
||||
// Return instructions are always a jalr to %x1.
|
||||
// The return address is provided as a special-purpose link argument.
|
||||
put_i(
|
||||
@@ -149,11 +134,12 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
sink,
|
||||
);
|
||||
"#,
|
||||
));
|
||||
),
|
||||
);
|
||||
|
||||
// I-type encoding for `jalr` as a call_indirect.
|
||||
recipes.push(
|
||||
EncodingRecipeBuilder::new("Icall", f_call_indirect, 4)
|
||||
EncodingRecipeBuilder::new("Icall", &formats.call_indirect, 4)
|
||||
.operands_in(vec![gpr])
|
||||
.emit(
|
||||
r#"
|
||||
@@ -171,7 +157,7 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
|
||||
// Copy of a GPR is implemented as addi x, 0.
|
||||
recipes.push(
|
||||
EncodingRecipeBuilder::new("Icopy", f_unary, 4)
|
||||
EncodingRecipeBuilder::new("Icopy", &formats.unary, 4)
|
||||
.operands_in(vec![gpr])
|
||||
.operands_out(vec![gpr])
|
||||
.emit("put_i(bits, in_reg0, 0, out_reg0, sink);"),
|
||||
@@ -179,14 +165,14 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
|
||||
// Same for a GPR regmove.
|
||||
recipes.push(
|
||||
EncodingRecipeBuilder::new("Irmov", f_regmove, 4)
|
||||
EncodingRecipeBuilder::new("Irmov", &formats.reg_move, 4)
|
||||
.operands_in(vec![gpr])
|
||||
.emit("put_i(bits, src, 0, dst, sink);"),
|
||||
);
|
||||
|
||||
// Same for copy-to-SSA -- GPR regmove.
|
||||
recipes.push(
|
||||
EncodingRecipeBuilder::new("copytossa", f_copy_to_ssa, 4)
|
||||
EncodingRecipeBuilder::new("copytossa", &formats.copy_to_ssa, 4)
|
||||
// No operands_in to mention, because a source register is specified directly.
|
||||
.operands_out(vec![gpr])
|
||||
.emit("put_i(bits, src, 0, out_reg0, sink);"),
|
||||
@@ -194,10 +180,10 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
|
||||
// U-type instructions have a 20-bit immediate that targets bits 12-31.
|
||||
recipes.push(
|
||||
EncodingRecipeBuilder::new("U", f_unary_imm, 4)
|
||||
EncodingRecipeBuilder::new("U", &formats.unary_imm, 4)
|
||||
.operands_out(vec![gpr])
|
||||
.inst_predicate(InstructionPredicate::new_is_signed_int(
|
||||
&*f_unary_imm,
|
||||
&*&formats.unary_imm,
|
||||
"imm",
|
||||
32,
|
||||
12,
|
||||
@@ -207,7 +193,7 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
|
||||
// UJ-type unconditional branch instructions.
|
||||
recipes.push(
|
||||
EncodingRecipeBuilder::new("UJ", f_jump, 4)
|
||||
EncodingRecipeBuilder::new("UJ", &formats.jump, 4)
|
||||
.branch_range((0, 21))
|
||||
.emit(
|
||||
r#"
|
||||
@@ -218,7 +204,7 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
),
|
||||
);
|
||||
|
||||
recipes.push(EncodingRecipeBuilder::new("UJcall", f_call, 4).emit(
|
||||
recipes.push(EncodingRecipeBuilder::new("UJcall", &formats.call, 4).emit(
|
||||
r#"
|
||||
sink.reloc_external(Reloc::RiscvCall,
|
||||
&func.dfg.ext_funcs[func_ref].name,
|
||||
@@ -230,7 +216,7 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
|
||||
// SB-type branch instructions.
|
||||
recipes.push(
|
||||
EncodingRecipeBuilder::new("SB", f_branch_icmp, 4)
|
||||
EncodingRecipeBuilder::new("SB", &formats.branch_icmp, 4)
|
||||
.operands_in(vec![gpr, gpr])
|
||||
.branch_range((0, 13))
|
||||
.emit(
|
||||
@@ -244,7 +230,7 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
|
||||
// SB-type branch instruction with rs2 fixed to zero.
|
||||
recipes.push(
|
||||
EncodingRecipeBuilder::new("SBzero", f_branch, 4)
|
||||
EncodingRecipeBuilder::new("SBzero", &formats.branch, 4)
|
||||
.operands_in(vec![gpr])
|
||||
.branch_range((0, 13))
|
||||
.emit(
|
||||
@@ -258,7 +244,7 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
|
||||
// Spill of a GPR.
|
||||
recipes.push(
|
||||
EncodingRecipeBuilder::new("GPsp", f_unary, 4)
|
||||
EncodingRecipeBuilder::new("GPsp", &formats.unary, 4)
|
||||
.operands_in(vec![gpr])
|
||||
.operands_out(vec![Stack::new(gpr)])
|
||||
.emit("unimplemented!();"),
|
||||
@@ -266,7 +252,7 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
|
||||
// Fill of a GPR.
|
||||
recipes.push(
|
||||
EncodingRecipeBuilder::new("GPfi", f_unary, 4)
|
||||
EncodingRecipeBuilder::new("GPfi", &formats.unary, 4)
|
||||
.operands_in(vec![Stack::new(gpr)])
|
||||
.operands_out(vec![gpr])
|
||||
.emit("unimplemented!();"),
|
||||
@@ -274,7 +260,7 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
|
||||
// Stack-slot to same stack-slot copy, which is guaranteed to turn into a no-op.
|
||||
recipes.push(
|
||||
EncodingRecipeBuilder::new("stacknull", f_unary, 0)
|
||||
EncodingRecipeBuilder::new("stacknull", &formats.unary, 0)
|
||||
.operands_in(vec![Stack::new(gpr)])
|
||||
.operands_out(vec![Stack::new(gpr)])
|
||||
.emit(""),
|
||||
@@ -282,7 +268,7 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
|
||||
// No-op fills, created by late-stage redundant-fill removal.
|
||||
recipes.push(
|
||||
EncodingRecipeBuilder::new("fillnull", f_unary, 0)
|
||||
EncodingRecipeBuilder::new("fillnull", &formats.unary, 0)
|
||||
.operands_in(vec![Stack::new(gpr)])
|
||||
.operands_out(vec![gpr])
|
||||
.clobbers_flags(false)
|
||||
|
||||
@@ -374,7 +374,7 @@ pub(crate) fn define(
|
||||
r: &RecipeGroup,
|
||||
) -> PerCpuModeEncodings {
|
||||
let shared = &shared_defs.instructions;
|
||||
let formats = &shared_defs.format_registry;
|
||||
let formats = &shared_defs.formats;
|
||||
|
||||
// Shorthands for instructions.
|
||||
let adjust_sp_down = shared.by_name("adjust_sp_down");
|
||||
@@ -774,8 +774,8 @@ pub(crate) fn define(
|
||||
e.enc64(iconst.bind(I32), rec_pu_id.opcodes(&MOV_IMM));
|
||||
|
||||
// The 32-bit immediate movl also zero-extends to 64 bits.
|
||||
let f_unary_imm = formats.by_name("UnaryImm");
|
||||
let is_unsigned_int32 = InstructionPredicate::new_is_unsigned_int(&*f_unary_imm, "imm", 32, 0);
|
||||
let is_unsigned_int32 =
|
||||
InstructionPredicate::new_is_unsigned_int(&*formats.unary_imm, "imm", 32, 0);
|
||||
|
||||
e.enc64_func(
|
||||
iconst.bind(I64),
|
||||
@@ -801,7 +801,7 @@ pub(crate) fn define(
|
||||
}
|
||||
e.enc64(bconst.bind(B64), rec_pu_id_bool.opcodes(&MOV_IMM).rex());
|
||||
|
||||
let is_zero_int = InstructionPredicate::new_is_zero_int(f_unary_imm, "imm");
|
||||
let is_zero_int = InstructionPredicate::new_is_zero_int(&formats.unary_imm, "imm");
|
||||
e.enc_both_instp(
|
||||
iconst.bind(I8),
|
||||
rec_u_id_z.opcodes(&XORB),
|
||||
@@ -880,8 +880,8 @@ pub(crate) fn define(
|
||||
e.enc64_isap(ctz.bind(I32), rec_urm.opcodes(&TZCNT), use_bmi1);
|
||||
|
||||
// Loads and stores.
|
||||
let f_load_complex = formats.by_name("LoadComplex");
|
||||
let is_load_complex_length_two = InstructionPredicate::new_length_equals(&*f_load_complex, 2);
|
||||
let is_load_complex_length_two =
|
||||
InstructionPredicate::new_length_equals(&*formats.load_complex, 2);
|
||||
|
||||
for recipe in &[rec_ldWithIndex, rec_ldWithIndexDisp8, rec_ldWithIndexDisp32] {
|
||||
e.enc_i32_i64_instp(
|
||||
@@ -925,9 +925,8 @@ pub(crate) fn define(
|
||||
);
|
||||
}
|
||||
|
||||
let f_store_complex = formats.by_name("StoreComplex");
|
||||
let is_store_complex_length_three =
|
||||
InstructionPredicate::new_length_equals(&*f_store_complex, 3);
|
||||
InstructionPredicate::new_length_equals(&*formats.store_complex, 3);
|
||||
|
||||
for recipe in &[rec_stWithIndex, rec_stWithIndexDisp8, rec_stWithIndexDisp32] {
|
||||
e.enc_i32_i64_instp(
|
||||
@@ -1233,8 +1232,8 @@ pub(crate) fn define(
|
||||
);
|
||||
|
||||
// 64-bit, colocated, both PIC and non-PIC. Use the lea instruction's pc-relative field.
|
||||
let f_func_addr = formats.by_name("FuncAddr");
|
||||
let is_colocated_func = InstructionPredicate::new_is_colocated_func(&*f_func_addr, "func_ref");
|
||||
let is_colocated_func =
|
||||
InstructionPredicate::new_is_colocated_func(&*formats.func_addr, "func_ref");
|
||||
e.enc64_instp(
|
||||
func_addr.bind(I64),
|
||||
rec_pcrel_fnaddr8.opcodes(&LEA).rex().w(),
|
||||
@@ -1293,8 +1292,7 @@ pub(crate) fn define(
|
||||
e.enc32(call, rec_call_id.opcodes(&CALL_RELATIVE));
|
||||
|
||||
// 64-bit, colocated, both PIC and non-PIC. Use the call instruction's pc-relative field.
|
||||
let f_call = formats.by_name("Call");
|
||||
let is_colocated_func = InstructionPredicate::new_is_colocated_func(&*f_call, "func_ref");
|
||||
let is_colocated_func = InstructionPredicate::new_is_colocated_func(&*formats.call, "func_ref");
|
||||
e.enc64_instp(call, rec_call_id.opcodes(&CALL_RELATIVE), is_colocated_func);
|
||||
|
||||
// 64-bit, non-colocated, PIC. There is no 64-bit non-colocated non-PIC version, since non-PIC
|
||||
@@ -1564,18 +1562,16 @@ pub(crate) fn define(
|
||||
|
||||
// Floating-point constants equal to 0.0 can be encoded using either `xorps` or `xorpd`, for
|
||||
// 32-bit and 64-bit floats respectively.
|
||||
let f_unary_ieee32 = formats.by_name("UnaryIeee32");
|
||||
let is_zero_32_bit_float =
|
||||
InstructionPredicate::new_is_zero_32bit_float(&*f_unary_ieee32, "imm");
|
||||
InstructionPredicate::new_is_zero_32bit_float(&*formats.unary_ieee32, "imm");
|
||||
e.enc32_instp(
|
||||
f32const,
|
||||
rec_f32imm_z.opcodes(&XORPS),
|
||||
is_zero_32_bit_float.clone(),
|
||||
);
|
||||
|
||||
let f_unary_ieee64 = formats.by_name("UnaryIeee64");
|
||||
let is_zero_64_bit_float =
|
||||
InstructionPredicate::new_is_zero_64bit_float(&*f_unary_ieee64, "imm");
|
||||
InstructionPredicate::new_is_zero_64bit_float(&*formats.unary_ieee64, "imm");
|
||||
e.enc32_instp(
|
||||
f64const,
|
||||
rec_f64imm_z.opcodes(&XORPD),
|
||||
@@ -1847,18 +1843,17 @@ pub(crate) fn define(
|
||||
// this must be encoded prior to the MOVUPS implementation (below) so the compiler sees this
|
||||
// encoding first
|
||||
for ty in ValueType::all_lane_types().filter(allowed_simd_type) {
|
||||
let f_unary_const = formats.by_name("UnaryConst");
|
||||
let instruction = vconst.bind(vector(ty, sse_vector_size));
|
||||
|
||||
let is_zero_128bit =
|
||||
InstructionPredicate::new_is_all_zeroes(&*f_unary_const, "constant_handle");
|
||||
InstructionPredicate::new_is_all_zeroes(&*formats.unary_const, "constant_handle");
|
||||
let template = rec_vconst_optimized.nonrex().opcodes(&PXOR);
|
||||
e.enc_32_64_func(instruction.clone(), template, |builder| {
|
||||
builder.inst_predicate(is_zero_128bit)
|
||||
});
|
||||
|
||||
let is_ones_128bit =
|
||||
InstructionPredicate::new_is_all_ones(&*f_unary_const, "constant_handle");
|
||||
InstructionPredicate::new_is_all_ones(&*formats.unary_const, "constant_handle");
|
||||
let template = rec_vconst_optimized.nonrex().opcodes(&PCMPEQB);
|
||||
e.enc_32_64_func(instruction, template, |builder| {
|
||||
builder.inst_predicate(is_ones_128bit)
|
||||
@@ -2038,9 +2033,11 @@ pub(crate) fn define(
|
||||
};
|
||||
|
||||
let instruction = icmp.bind(vector(ty, sse_vector_size));
|
||||
let f_int_compare = formats.by_name("IntCompare");
|
||||
let has_eq_condition_code =
|
||||
InstructionPredicate::new_has_condition_code(&*f_int_compare, IntCC::Equal, "cond");
|
||||
let has_eq_condition_code = InstructionPredicate::new_has_condition_code(
|
||||
&*formats.int_compare,
|
||||
IntCC::Equal,
|
||||
"cond",
|
||||
);
|
||||
let template = rec_icscc_fpr.nonrex().opcodes(opcodes);
|
||||
e.enc_32_64_func(instruction, template, |builder| {
|
||||
let builder = builder.inst_predicate(has_eq_condition_code);
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use crate::cdsl::formats::FormatRegistry;
|
||||
use crate::cdsl::instructions::{
|
||||
AllInstructions, InstructionBuilder as Inst, InstructionGroup, InstructionGroupBuilder,
|
||||
};
|
||||
use crate::cdsl::operands::{create_operand as operand, create_operand_doc as operand_doc};
|
||||
use crate::cdsl::types::ValueType;
|
||||
use crate::cdsl::typevar::{Interval, TypeSetBuilder, TypeVar};
|
||||
|
||||
use crate::shared::formats::Formats;
|
||||
use crate::shared::immediates::Immediates;
|
||||
use crate::shared::types;
|
||||
|
||||
pub(crate) fn define(
|
||||
mut all_instructions: &mut AllInstructions,
|
||||
format_registry: &FormatRegistry,
|
||||
formats: &Formats,
|
||||
immediates: &Immediates,
|
||||
) -> InstructionGroup {
|
||||
let mut ig = InstructionGroupBuilder::new(&mut all_instructions, format_registry);
|
||||
let mut ig = InstructionGroupBuilder::new(&mut all_instructions);
|
||||
|
||||
let iflags: &TypeVar = &ValueType::Special(types::Flag::IFlags.into()).into();
|
||||
|
||||
@@ -43,6 +44,7 @@ pub(crate) fn define(
|
||||
|
||||
Return both quotient and remainder.
|
||||
"#,
|
||||
&formats.ternary,
|
||||
)
|
||||
.operands_in(vec![nlo, nhi, d])
|
||||
.operands_out(vec![q, r])
|
||||
@@ -62,6 +64,7 @@ pub(crate) fn define(
|
||||
|
||||
Return both quotient and remainder.
|
||||
"#,
|
||||
&formats.ternary,
|
||||
)
|
||||
.operands_in(vec![nlo, nhi, d])
|
||||
.operands_out(vec![q, r])
|
||||
@@ -82,6 +85,7 @@ pub(crate) fn define(
|
||||
Polymorphic over all scalar integer types, but does not support vector
|
||||
types.
|
||||
"#,
|
||||
&formats.binary,
|
||||
)
|
||||
.operands_in(vec![argL, argR])
|
||||
.operands_out(vec![resLo, resHi]),
|
||||
@@ -96,6 +100,7 @@ pub(crate) fn define(
|
||||
Polymorphic over all scalar integer types, but does not support vector
|
||||
types.
|
||||
"#,
|
||||
&formats.binary,
|
||||
)
|
||||
.operands_in(vec![argL, argR])
|
||||
.operands_out(vec![resLo, resHi]),
|
||||
@@ -132,6 +137,7 @@ pub(crate) fn define(
|
||||
|
||||
This instruction does not trap.
|
||||
"#,
|
||||
&formats.unary,
|
||||
)
|
||||
.operands_in(vec![x])
|
||||
.operands_out(vec![a]),
|
||||
@@ -154,6 +160,7 @@ pub(crate) fn define(
|
||||
When the two operands don't compare as LT, `y` is returned unchanged,
|
||||
even if it is a signalling NaN.
|
||||
"#,
|
||||
&formats.binary,
|
||||
)
|
||||
.operands_in(vec![x, y])
|
||||
.operands_out(vec![a]),
|
||||
@@ -172,6 +179,7 @@ pub(crate) fn define(
|
||||
When the two operands don't compare as GT, `y` is returned unchanged,
|
||||
even if it is a signalling NaN.
|
||||
"#,
|
||||
&formats.binary,
|
||||
)
|
||||
.operands_in(vec![x, y])
|
||||
.operands_out(vec![a]),
|
||||
@@ -190,6 +198,7 @@ pub(crate) fn define(
|
||||
This is polymorphic in i32 and i64. However, it is only implemented for i64
|
||||
in 64-bit mode, and only for i32 in 32-bit mode.
|
||||
"#,
|
||||
&formats.unary,
|
||||
)
|
||||
.operands_in(vec![x])
|
||||
.other_side_effects(true)
|
||||
@@ -208,6 +217,7 @@ pub(crate) fn define(
|
||||
This is polymorphic in i32 and i64. However, it is only implemented for i64
|
||||
in 64-bit mode, and only for i32 in 32-bit mode.
|
||||
"#,
|
||||
&formats.nullary,
|
||||
)
|
||||
.operands_out(vec![x])
|
||||
.other_side_effects(true)
|
||||
@@ -229,6 +239,7 @@ pub(crate) fn define(
|
||||
This is polymorphic in i32 and i64. It is implemented for both i64 and
|
||||
i32 in 64-bit mode, and only for i32 in 32-bit mode.
|
||||
"#,
|
||||
&formats.unary,
|
||||
)
|
||||
.operands_in(vec![x])
|
||||
.operands_out(vec![y, rflags]),
|
||||
@@ -241,6 +252,7 @@ pub(crate) fn define(
|
||||
Bit Scan Forwards -- returns the bit-index of the least significant 1
|
||||
in the word. Is otherwise identical to 'bsr', just above.
|
||||
"#,
|
||||
&formats.unary,
|
||||
)
|
||||
.operands_in(vec![x])
|
||||
.operands_out(vec![y, rflags]),
|
||||
@@ -269,6 +281,7 @@ pub(crate) fn define(
|
||||
Packed Shuffle Doublewords -- copies data from either memory or lanes in an extended
|
||||
register and re-orders the data according to the passed immediate byte.
|
||||
"#,
|
||||
&formats.extract_lane,
|
||||
)
|
||||
.operands_in(vec![a, i]) // TODO allow copying from memory here (need more permissive type than TxN)
|
||||
.operands_out(vec![a]),
|
||||
@@ -281,6 +294,7 @@ pub(crate) fn define(
|
||||
Packed Shuffle Bytes -- re-orders data in an extended register using a shuffle
|
||||
mask from either memory or another extended register
|
||||
"#,
|
||||
&formats.binary,
|
||||
)
|
||||
.operands_in(vec![a, b]) // TODO allow re-ordering from memory here (need more permissive type than TxN)
|
||||
.operands_out(vec![a]),
|
||||
@@ -298,6 +312,7 @@ pub(crate) fn define(
|
||||
The lane index, ``Idx``, is an immediate value, not an SSA value. It
|
||||
must indicate a valid lane index for the type of ``x``.
|
||||
"#,
|
||||
&formats.extract_lane,
|
||||
)
|
||||
.operands_in(vec![x, Idx])
|
||||
.operands_out(vec![a]),
|
||||
@@ -325,6 +340,7 @@ pub(crate) fn define(
|
||||
The lane index, ``Idx``, is an immediate value, not an SSA value. It
|
||||
must indicate a valid lane index for the type of ``x``.
|
||||
"#,
|
||||
&formats.insert_lane,
|
||||
)
|
||||
.operands_in(vec![x, Idx, y])
|
||||
.operands_out(vec![a]),
|
||||
@@ -347,10 +363,11 @@ pub(crate) fn define(
|
||||
Inst::new(
|
||||
"x86_insertps",
|
||||
r#"
|
||||
Insert a lane of ``y`` into ``x`` at using ``Idx`` to encode both which lane the value is
|
||||
extracted from and which it is inserted to. This is similar to x86_pinsr but inserts
|
||||
Insert a lane of ``y`` into ``x`` at using ``Idx`` to encode both which lane the value is
|
||||
extracted from and which it is inserted to. This is similar to x86_pinsr but inserts
|
||||
floats, which are already stored in an XMM register.
|
||||
"#,
|
||||
&formats.insert_lane,
|
||||
)
|
||||
.operands_in(vec![x, Idx, y])
|
||||
.operands_out(vec![a]),
|
||||
@@ -366,6 +383,7 @@ pub(crate) fn define(
|
||||
r#"
|
||||
Move the low 64 bits of the float vector ``y`` to the low 64 bits of float vector ``x``
|
||||
"#,
|
||||
&formats.binary,
|
||||
)
|
||||
.operands_in(vec![x, y])
|
||||
.operands_out(vec![a]),
|
||||
@@ -377,6 +395,7 @@ pub(crate) fn define(
|
||||
r#"
|
||||
Move the low 64 bits of the float vector ``y`` to the high 64 bits of float vector ``x``
|
||||
"#,
|
||||
&formats.binary,
|
||||
)
|
||||
.operands_in(vec![x, y])
|
||||
.operands_out(vec![a]),
|
||||
@@ -401,41 +420,48 @@ pub(crate) fn define(
|
||||
.includes_scalars(false)
|
||||
.build(),
|
||||
);
|
||||
|
||||
let x = &operand_doc("x", IxN, "Vector value to shift");
|
||||
let y = &operand_doc("y", I64x2, "Number of bits to shift");
|
||||
let a = &operand("a", IxN);
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
"x86_psll",
|
||||
r#"
|
||||
Shift Packed Data Left Logical -- This implements the behavior of the shared instruction
|
||||
Shift Packed Data Left Logical -- This implements the behavior of the shared instruction
|
||||
``ishl`` but alters the shift operand to live in an XMM register as expected by the PSLL*
|
||||
family of instructions.
|
||||
"#,
|
||||
&formats.binary,
|
||||
)
|
||||
.operands_in(vec![x, y])
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
"x86_psrl",
|
||||
r#"
|
||||
Shift Packed Data Right Logical -- This implements the behavior of the shared instruction
|
||||
Shift Packed Data Right Logical -- This implements the behavior of the shared instruction
|
||||
``ushr`` but alters the shift operand to live in an XMM register as expected by the PSRL*
|
||||
family of instructions.
|
||||
"#,
|
||||
&formats.binary,
|
||||
)
|
||||
.operands_in(vec![x, y])
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
"x86_psra",
|
||||
r#"
|
||||
Shift Packed Data Right Arithmetic -- This implements the behavior of the shared
|
||||
instruction ``sshr`` but alters the shift operand to live in an XMM register as expected by
|
||||
Shift Packed Data Right Arithmetic -- This implements the behavior of the shared
|
||||
instruction ``sshr`` but alters the shift operand to live in an XMM register as expected by
|
||||
the PSRA* family of instructions.
|
||||
"#,
|
||||
&formats.binary,
|
||||
)
|
||||
.operands_in(vec![x, y])
|
||||
.operands_out(vec![a]),
|
||||
|
||||
@@ -20,7 +20,7 @@ pub(crate) fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
|
||||
|
||||
let inst_group = instructions::define(
|
||||
&mut shared_defs.all_instructions,
|
||||
&shared_defs.format_registry,
|
||||
&shared_defs.formats,
|
||||
&shared_defs.imm,
|
||||
);
|
||||
legalize::define(shared_defs, &inst_group);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user