[meta] Introduce the Immediates structure instead of using dynamic lookup;
This commit is contained in:
@@ -230,8 +230,7 @@ pub fn define<'defs>(
|
||||
-> InstructionPredicateNode {
|
||||
let x = var_pool.create("x");
|
||||
let y = var_pool.create("y");
|
||||
let cc =
|
||||
Literal::enumerator_for(shared_defs.operand_kinds.by_name("intcc"), intcc_field);
|
||||
let cc = Literal::enumerator_for(&shared_defs.imm.intcc, intcc_field);
|
||||
Apply::new(
|
||||
bound_inst.clone().into(),
|
||||
vec![Expr::Literal(cc), Expr::Var(x), Expr::Var(y)],
|
||||
@@ -313,8 +312,7 @@ pub fn define<'defs>(
|
||||
let y = var_pool.create("y");
|
||||
let dest = var_pool.create("dest");
|
||||
let args = var_pool.create("args");
|
||||
let cc =
|
||||
Literal::enumerator_for(shared_defs.operand_kinds.by_name("intcc"), intcc_field);
|
||||
let cc = Literal::enumerator_for(&shared_defs.imm.intcc, intcc_field);
|
||||
Apply::new(
|
||||
bound_inst.clone().into(),
|
||||
vec![
|
||||
|
||||
@@ -7,11 +7,13 @@ use crate::cdsl::instructions::{
|
||||
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::{immediates, types, OperandKinds};
|
||||
use crate::shared::immediates::Immediates;
|
||||
use crate::shared::types;
|
||||
|
||||
pub fn define(
|
||||
mut all_instructions: &mut AllInstructions,
|
||||
format_registry: &FormatRegistry,
|
||||
immediates: &Immediates,
|
||||
) -> InstructionGroup {
|
||||
let mut ig = InstructionGroupBuilder::new(
|
||||
"x86",
|
||||
@@ -249,8 +251,7 @@ pub fn define(
|
||||
.operands_out(vec![y, rflags]),
|
||||
);
|
||||
|
||||
let immediates = OperandKinds::from(immediates::define());
|
||||
let uimm8 = immediates.by_name("uimm8");
|
||||
let uimm8 = &immediates.uimm8;
|
||||
let TxN = &TypeVar::new(
|
||||
"TxN",
|
||||
"A SIMD vector type",
|
||||
|
||||
@@ -58,12 +58,7 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou
|
||||
let x86_umulx = x86_instructions.by_name("x86_umulx");
|
||||
let x86_smulx = x86_instructions.by_name("x86_smulx");
|
||||
|
||||
// List of immediates.
|
||||
let floatcc = shared.operand_kinds.by_name("floatcc");
|
||||
let imm64 = shared.operand_kinds.by_name("imm64");
|
||||
let intcc = shared.operand_kinds.by_name("intcc");
|
||||
let uimm8 = shared.operand_kinds.by_name("uimm8");
|
||||
let ieee64 = shared.operand_kinds.by_name("ieee64");
|
||||
let imm = &shared.imm;
|
||||
|
||||
// Division and remainder.
|
||||
//
|
||||
@@ -99,12 +94,12 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou
|
||||
// `ucomiss` or `ucomisd` instruction. The remaining codes need legalization
|
||||
// patterns.
|
||||
|
||||
let floatcc_eq = Literal::enumerator_for(floatcc, "eq");
|
||||
let floatcc_ord = Literal::enumerator_for(floatcc, "ord");
|
||||
let floatcc_ueq = Literal::enumerator_for(floatcc, "ueq");
|
||||
let floatcc_ne = Literal::enumerator_for(floatcc, "ne");
|
||||
let floatcc_uno = Literal::enumerator_for(floatcc, "uno");
|
||||
let floatcc_one = Literal::enumerator_for(floatcc, "one");
|
||||
let floatcc_eq = Literal::enumerator_for(&imm.floatcc, "eq");
|
||||
let floatcc_ord = Literal::enumerator_for(&imm.floatcc, "ord");
|
||||
let floatcc_ueq = Literal::enumerator_for(&imm.floatcc, "ueq");
|
||||
let floatcc_ne = Literal::enumerator_for(&imm.floatcc, "ne");
|
||||
let floatcc_uno = Literal::enumerator_for(&imm.floatcc, "uno");
|
||||
let floatcc_one = Literal::enumerator_for(&imm.floatcc, "one");
|
||||
|
||||
// Equality needs an explicit `ord` test which checks the parity bit.
|
||||
group.legalize(
|
||||
@@ -124,14 +119,14 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou
|
||||
],
|
||||
);
|
||||
|
||||
let floatcc_lt = &Literal::enumerator_for(floatcc, "lt");
|
||||
let floatcc_gt = &Literal::enumerator_for(floatcc, "gt");
|
||||
let floatcc_le = &Literal::enumerator_for(floatcc, "le");
|
||||
let floatcc_ge = &Literal::enumerator_for(floatcc, "ge");
|
||||
let floatcc_ugt = &Literal::enumerator_for(floatcc, "ugt");
|
||||
let floatcc_ult = &Literal::enumerator_for(floatcc, "ult");
|
||||
let floatcc_uge = &Literal::enumerator_for(floatcc, "uge");
|
||||
let floatcc_ule = &Literal::enumerator_for(floatcc, "ule");
|
||||
let floatcc_lt = &Literal::enumerator_for(&imm.floatcc, "lt");
|
||||
let floatcc_gt = &Literal::enumerator_for(&imm.floatcc, "gt");
|
||||
let floatcc_le = &Literal::enumerator_for(&imm.floatcc, "le");
|
||||
let floatcc_ge = &Literal::enumerator_for(&imm.floatcc, "ge");
|
||||
let floatcc_ugt = &Literal::enumerator_for(&imm.floatcc, "ugt");
|
||||
let floatcc_ult = &Literal::enumerator_for(&imm.floatcc, "ult");
|
||||
let floatcc_uge = &Literal::enumerator_for(&imm.floatcc, "uge");
|
||||
let floatcc_ule = &Literal::enumerator_for(&imm.floatcc, "ule");
|
||||
|
||||
// Inequalities that need to be reversed.
|
||||
for &(cc, rev_cc) in &[
|
||||
@@ -165,9 +160,9 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou
|
||||
let r2flags = var("r2flags");
|
||||
let index2 = var("index2");
|
||||
|
||||
let intcc_eq = Literal::enumerator_for(intcc, "eq");
|
||||
let imm64_minus_one = Literal::constant(imm64, -1);
|
||||
let imm64_63 = Literal::constant(imm64, 63);
|
||||
let intcc_eq = Literal::enumerator_for(&imm.intcc, "eq");
|
||||
let imm64_minus_one = Literal::constant(&imm.imm64, -1);
|
||||
let imm64_63 = Literal::constant(&imm.imm64, 63);
|
||||
group.legalize(
|
||||
def!(a = clz.I64(x)),
|
||||
vec![
|
||||
@@ -179,7 +174,7 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou
|
||||
],
|
||||
);
|
||||
|
||||
let imm64_31 = Literal::constant(imm64, 31);
|
||||
let imm64_31 = Literal::constant(&imm.imm64, 31);
|
||||
group.legalize(
|
||||
def!(a = clz.I32(x)),
|
||||
vec![
|
||||
@@ -191,7 +186,7 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou
|
||||
],
|
||||
);
|
||||
|
||||
let imm64_64 = Literal::constant(imm64, 64);
|
||||
let imm64_64 = Literal::constant(&imm.imm64, 64);
|
||||
group.legalize(
|
||||
def!(a = ctz.I64(x)),
|
||||
vec![
|
||||
@@ -201,7 +196,7 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou
|
||||
],
|
||||
);
|
||||
|
||||
let imm64_32 = Literal::constant(imm64, 32);
|
||||
let imm64_32 = Literal::constant(&imm.imm64, 32);
|
||||
group.legalize(
|
||||
def!(a = ctz.I32(x)),
|
||||
vec![
|
||||
@@ -232,13 +227,13 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou
|
||||
let qc0F = var("qc0F");
|
||||
let qc01 = var("qc01");
|
||||
|
||||
let imm64_1 = Literal::constant(imm64, 1);
|
||||
let imm64_4 = Literal::constant(imm64, 4);
|
||||
let imm64_1 = Literal::constant(&imm.imm64, 1);
|
||||
let imm64_4 = Literal::constant(&imm.imm64, 4);
|
||||
group.legalize(
|
||||
def!(qv16 = popcnt.I64(qv1)),
|
||||
vec![
|
||||
def!(qv3 = ushr_imm(qv1, imm64_1)),
|
||||
def!(qc77 = iconst(Literal::constant(imm64, 0x7777777777777777))),
|
||||
def!(qc77 = iconst(Literal::constant(&imm.imm64, 0x7777777777777777))),
|
||||
def!(qv4 = band(qv3, qc77)),
|
||||
def!(qv5 = isub(qv1, qv4)),
|
||||
def!(qv6 = ushr_imm(qv4, imm64_1)),
|
||||
@@ -249,11 +244,11 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou
|
||||
def!(qv11 = isub(qv8, qv10)),
|
||||
def!(qv12 = ushr_imm(qv11, imm64_4)),
|
||||
def!(qv13 = iadd(qv11, qv12)),
|
||||
def!(qc0F = iconst(Literal::constant(imm64, 0x0F0F0F0F0F0F0F0F))),
|
||||
def!(qc0F = iconst(Literal::constant(&imm.imm64, 0x0F0F0F0F0F0F0F0F))),
|
||||
def!(qv14 = band(qv13, qc0F)),
|
||||
def!(qc01 = iconst(Literal::constant(imm64, 0x0101010101010101))),
|
||||
def!(qc01 = iconst(Literal::constant(&imm.imm64, 0x0101010101010101))),
|
||||
def!(qv15 = imul(qv14, qc01)),
|
||||
def!(qv16 = ushr_imm(qv15, Literal::constant(imm64, 56))),
|
||||
def!(qv16 = ushr_imm(qv15, Literal::constant(&imm.imm64, 56))),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -281,7 +276,7 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou
|
||||
def!(lv16 = popcnt.I32(lv1)),
|
||||
vec![
|
||||
def!(lv3 = ushr_imm(lv1, imm64_1)),
|
||||
def!(lc77 = iconst(Literal::constant(imm64, 0x77777777))),
|
||||
def!(lc77 = iconst(Literal::constant(&imm.imm64, 0x77777777))),
|
||||
def!(lv4 = band(lv3, lc77)),
|
||||
def!(lv5 = isub(lv1, lv4)),
|
||||
def!(lv6 = ushr_imm(lv4, imm64_1)),
|
||||
@@ -292,11 +287,11 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou
|
||||
def!(lv11 = isub(lv8, lv10)),
|
||||
def!(lv12 = ushr_imm(lv11, imm64_4)),
|
||||
def!(lv13 = iadd(lv11, lv12)),
|
||||
def!(lc0F = iconst(Literal::constant(imm64, 0x0F0F0F0F))),
|
||||
def!(lc0F = iconst(Literal::constant(&imm.imm64, 0x0F0F0F0F))),
|
||||
def!(lv14 = band(lv13, lc0F)),
|
||||
def!(lc01 = iconst(Literal::constant(imm64, 0x01010101))),
|
||||
def!(lc01 = iconst(Literal::constant(&imm.imm64, 0x01010101))),
|
||||
def!(lv15 = imul(lv14, lc01)),
|
||||
def!(lv16 = ushr_imm(lv15, Literal::constant(imm64, 24))),
|
||||
def!(lv16 = ushr_imm(lv15, Literal::constant(&imm.imm64, 24))),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -313,9 +308,9 @@ pub fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGrou
|
||||
.chain_with(shared.transform_groups.by_name("narrow").id);
|
||||
|
||||
// SIMD
|
||||
let uimm8_zero = Literal::constant(uimm8, 0x00);
|
||||
let uimm8_one = Literal::constant(uimm8, 0x01);
|
||||
let ieee64_zero = Literal::constant(ieee64, 0x00);
|
||||
let uimm8_zero = Literal::constant(&imm.uimm8, 0x00);
|
||||
let uimm8_one = Literal::constant(&imm.uimm8, 0x01);
|
||||
let ieee64_zero = Literal::constant(&imm.ieee64, 0x00);
|
||||
let b = var("b");
|
||||
let c = var("c");
|
||||
let d = var("d");
|
||||
|
||||
@@ -20,6 +20,7 @@ pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
|
||||
let inst_group = instructions::define(
|
||||
&mut shared_defs.all_instructions,
|
||||
&shared_defs.format_registry,
|
||||
&shared_defs.imm,
|
||||
);
|
||||
legalize::define(shared_defs, &inst_group);
|
||||
|
||||
|
||||
@@ -332,7 +332,7 @@ pub fn define<'shared>(
|
||||
) -> RecipeGroup<'shared> {
|
||||
// The set of floating point condition codes that are directly supported.
|
||||
// Other condition codes need to be reversed or expressed as two tests.
|
||||
let floatcc = shared_defs.operand_kinds.by_name("floatcc");
|
||||
let floatcc = &shared_defs.imm.floatcc;
|
||||
let supported_floatccs: Vec<Literal> = ["ord", "uno", "one", "ueq", "gt", "ge", "ult", "ule"]
|
||||
.iter()
|
||||
.map(|name| Literal::enumerator_for(floatcc, name))
|
||||
|
||||
@@ -1,22 +1,8 @@
|
||||
use crate::cdsl::formats::{FormatRegistry, InstructionFormatBuilder as Builder};
|
||||
use crate::shared::immediates::Immediates;
|
||||
use crate::shared::OperandKinds;
|
||||
|
||||
pub fn define(immediates: &OperandKinds, entities: &OperandKinds) -> FormatRegistry {
|
||||
// Shorthands for immediates.
|
||||
let uimm8 = immediates.by_name("uimm8");
|
||||
let uimm32 = immediates.by_name("uimm32");
|
||||
let uimm128 = immediates.by_name("uimm128");
|
||||
let imm64 = immediates.by_name("imm64");
|
||||
let ieee32 = immediates.by_name("ieee32");
|
||||
let ieee64 = immediates.by_name("ieee64");
|
||||
let boolean = immediates.by_name("boolean");
|
||||
let intcc = immediates.by_name("intcc");
|
||||
let floatcc = immediates.by_name("floatcc");
|
||||
let memflags = immediates.by_name("memflags");
|
||||
let offset32 = immediates.by_name("offset32");
|
||||
let trapcode = immediates.by_name("trapcode");
|
||||
let regunit = immediates.by_name("regunit");
|
||||
|
||||
pub fn define(imm: &Immediates, entities: &OperandKinds) -> FormatRegistry {
|
||||
// Shorthands for entities.
|
||||
let global_value = entities.by_name("global_value");
|
||||
let ebb = entities.by_name("ebb");
|
||||
@@ -30,15 +16,15 @@ pub fn define(immediates: &OperandKinds, entities: &OperandKinds) -> FormatRegis
|
||||
let mut registry = FormatRegistry::new();
|
||||
|
||||
registry.insert(Builder::new("Unary").value());
|
||||
registry.insert(Builder::new("UnaryImm").imm(imm64));
|
||||
registry.insert(Builder::new("UnaryImm128").imm(uimm128));
|
||||
registry.insert(Builder::new("UnaryIeee32").imm(ieee32));
|
||||
registry.insert(Builder::new("UnaryIeee64").imm(ieee64));
|
||||
registry.insert(Builder::new("UnaryBool").imm(boolean));
|
||||
registry.insert(Builder::new("UnaryImm").imm(&imm.imm64));
|
||||
registry.insert(Builder::new("UnaryImm128").imm(&imm.uimm128));
|
||||
registry.insert(Builder::new("UnaryIeee32").imm(&imm.ieee32));
|
||||
registry.insert(Builder::new("UnaryIeee64").imm(&imm.ieee64));
|
||||
registry.insert(Builder::new("UnaryBool").imm(&imm.boolean));
|
||||
registry.insert(Builder::new("UnaryGlobalValue").imm(global_value));
|
||||
|
||||
registry.insert(Builder::new("Binary").value().value());
|
||||
registry.insert(Builder::new("BinaryImm").value().imm(imm64));
|
||||
registry.insert(Builder::new("BinaryImm").value().imm(&imm.imm64));
|
||||
|
||||
// The select instructions are controlled by the second VALUE operand.
|
||||
// The first VALUE operand is the controlling flag which has a derived type.
|
||||
@@ -60,43 +46,59 @@ pub fn define(immediates: &OperandKinds, entities: &OperandKinds) -> FormatRegis
|
||||
registry.insert(
|
||||
Builder::new("InsertLane")
|
||||
.value()
|
||||
.imm_with_name("lane", uimm8)
|
||||
.imm_with_name("lane", &imm.uimm8)
|
||||
.value(),
|
||||
);
|
||||
registry.insert(
|
||||
Builder::new("ExtractLane")
|
||||
.value()
|
||||
.imm_with_name("lane", uimm8),
|
||||
.imm_with_name("lane", &imm.uimm8),
|
||||
);
|
||||
|
||||
registry.insert(Builder::new("IntCompare").imm(intcc).value().value());
|
||||
registry.insert(Builder::new("IntCompareImm").imm(intcc).value().imm(imm64));
|
||||
registry.insert(Builder::new("IntCond").imm(intcc).value());
|
||||
registry.insert(Builder::new("IntCompare").imm(&imm.intcc).value().value());
|
||||
registry.insert(
|
||||
Builder::new("IntCompareImm")
|
||||
.imm(&imm.intcc)
|
||||
.value()
|
||||
.imm(&imm.imm64),
|
||||
);
|
||||
registry.insert(Builder::new("IntCond").imm(&imm.intcc).value());
|
||||
|
||||
registry.insert(Builder::new("FloatCompare").imm(floatcc).value().value());
|
||||
registry.insert(Builder::new("FloatCond").imm(floatcc).value());;
|
||||
registry.insert(
|
||||
Builder::new("FloatCompare")
|
||||
.imm(&imm.floatcc)
|
||||
.value()
|
||||
.value(),
|
||||
);
|
||||
registry.insert(Builder::new("FloatCond").imm(&imm.floatcc).value());;
|
||||
|
||||
registry.insert(Builder::new("IntSelect").imm(intcc).value().value().value());
|
||||
registry.insert(
|
||||
Builder::new("IntSelect")
|
||||
.imm(&imm.intcc)
|
||||
.value()
|
||||
.value()
|
||||
.value(),
|
||||
);
|
||||
|
||||
registry.insert(Builder::new("Jump").imm(ebb).varargs());
|
||||
registry.insert(Builder::new("Branch").value().imm(ebb).varargs());
|
||||
registry.insert(
|
||||
Builder::new("BranchInt")
|
||||
.imm(intcc)
|
||||
.imm(&imm.intcc)
|
||||
.value()
|
||||
.imm(ebb)
|
||||
.varargs(),
|
||||
);
|
||||
registry.insert(
|
||||
Builder::new("BranchFloat")
|
||||
.imm(floatcc)
|
||||
.imm(&imm.floatcc)
|
||||
.value()
|
||||
.imm(ebb)
|
||||
.varargs(),
|
||||
);
|
||||
registry.insert(
|
||||
Builder::new("BranchIcmp")
|
||||
.imm(intcc)
|
||||
.imm(&imm.intcc)
|
||||
.value()
|
||||
.value()
|
||||
.imm(ebb)
|
||||
@@ -107,7 +109,7 @@ pub fn define(immediates: &OperandKinds, entities: &OperandKinds) -> FormatRegis
|
||||
Builder::new("BranchTableEntry")
|
||||
.value()
|
||||
.value()
|
||||
.imm(uimm8)
|
||||
.imm(&imm.uimm8)
|
||||
.imm(jump_table),
|
||||
);
|
||||
registry.insert(Builder::new("BranchTableBase").imm(jump_table));
|
||||
@@ -117,74 +119,89 @@ pub fn define(immediates: &OperandKinds, entities: &OperandKinds) -> FormatRegis
|
||||
registry.insert(Builder::new("CallIndirect").imm(sig_ref).value().varargs());
|
||||
registry.insert(Builder::new("FuncAddr").imm(func_ref));
|
||||
|
||||
registry.insert(Builder::new("Load").imm(memflags).value().imm(offset32));
|
||||
registry.insert(
|
||||
Builder::new("Load")
|
||||
.imm(&imm.memflags)
|
||||
.value()
|
||||
.imm(&imm.offset32),
|
||||
);
|
||||
registry.insert(
|
||||
Builder::new("LoadComplex")
|
||||
.imm(memflags)
|
||||
.imm(&imm.memflags)
|
||||
.varargs()
|
||||
.imm(offset32),
|
||||
.imm(&imm.offset32),
|
||||
);
|
||||
registry.insert(
|
||||
Builder::new("Store")
|
||||
.imm(memflags)
|
||||
.imm(&imm.memflags)
|
||||
.value()
|
||||
.value()
|
||||
.imm(offset32),
|
||||
.imm(&imm.offset32),
|
||||
);
|
||||
registry.insert(
|
||||
Builder::new("StoreComplex")
|
||||
.imm(memflags)
|
||||
.imm(&imm.memflags)
|
||||
.value()
|
||||
.varargs()
|
||||
.imm(offset32),
|
||||
.imm(&imm.offset32),
|
||||
);
|
||||
registry.insert(Builder::new("StackLoad").imm(stack_slot).imm(offset32));
|
||||
registry.insert(Builder::new("StackLoad").imm(stack_slot).imm(&imm.offset32));
|
||||
registry.insert(
|
||||
Builder::new("StackStore")
|
||||
.value()
|
||||
.imm(stack_slot)
|
||||
.imm(offset32),
|
||||
.imm(&imm.offset32),
|
||||
);
|
||||
|
||||
// Accessing a WebAssembly heap.
|
||||
registry.insert(Builder::new("HeapAddr").imm(heap).value().imm(uimm32));
|
||||
registry.insert(Builder::new("HeapAddr").imm(heap).value().imm(&imm.uimm32));
|
||||
|
||||
// Accessing a WebAssembly table.
|
||||
registry.insert(Builder::new("TableAddr").imm(table).value().imm(offset32));
|
||||
registry.insert(
|
||||
Builder::new("TableAddr")
|
||||
.imm(table)
|
||||
.value()
|
||||
.imm(&imm.offset32),
|
||||
);
|
||||
|
||||
registry.insert(
|
||||
Builder::new("RegMove")
|
||||
.value()
|
||||
.imm_with_name("src", regunit)
|
||||
.imm_with_name("dst", regunit),
|
||||
.imm_with_name("src", &imm.regunit)
|
||||
.imm_with_name("dst", &imm.regunit),
|
||||
);
|
||||
registry.insert(
|
||||
Builder::new("CopySpecial")
|
||||
.imm_with_name("src", regunit)
|
||||
.imm_with_name("dst", regunit),
|
||||
.imm_with_name("src", &imm.regunit)
|
||||
.imm_with_name("dst", &imm.regunit),
|
||||
);
|
||||
registry.insert(Builder::new("CopyToSsa").imm_with_name("src", regunit));
|
||||
registry.insert(Builder::new("CopyToSsa").imm_with_name("src", &imm.regunit));
|
||||
registry.insert(
|
||||
Builder::new("RegSpill")
|
||||
.value()
|
||||
.imm_with_name("src", regunit)
|
||||
.imm_with_name("src", &imm.regunit)
|
||||
.imm_with_name("dst", stack_slot),
|
||||
);
|
||||
registry.insert(
|
||||
Builder::new("RegFill")
|
||||
.value()
|
||||
.imm_with_name("src", stack_slot)
|
||||
.imm_with_name("dst", regunit),
|
||||
.imm_with_name("dst", &imm.regunit),
|
||||
);
|
||||
|
||||
registry.insert(Builder::new("Trap").imm(trapcode));
|
||||
registry.insert(Builder::new("CondTrap").value().imm(trapcode));
|
||||
registry.insert(Builder::new("IntCondTrap").imm(intcc).value().imm(trapcode));
|
||||
registry.insert(Builder::new("Trap").imm(&imm.trapcode));
|
||||
registry.insert(Builder::new("CondTrap").value().imm(&imm.trapcode));
|
||||
registry.insert(
|
||||
Builder::new("IntCondTrap")
|
||||
.imm(&imm.intcc)
|
||||
.value()
|
||||
.imm(&imm.trapcode),
|
||||
);
|
||||
registry.insert(
|
||||
Builder::new("FloatCondTrap")
|
||||
.imm(floatcc)
|
||||
.imm(&imm.floatcc)
|
||||
.value()
|
||||
.imm(trapcode),
|
||||
.imm(&imm.trapcode),
|
||||
);
|
||||
|
||||
registry
|
||||
|
||||
@@ -2,154 +2,174 @@ use crate::cdsl::operands::{OperandKind, OperandKindBuilder as Builder};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub fn define() -> Vec<OperandKind> {
|
||||
let mut kinds = Vec::new();
|
||||
pub struct Immediates {
|
||||
/// A 64-bit immediate integer operand.
|
||||
///
|
||||
/// This type of immediate integer can interact with SSA values with any IntType type.
|
||||
pub imm64: OperandKind,
|
||||
|
||||
// A 64-bit immediate integer operand.
|
||||
//
|
||||
// This type of immediate integer can interact with SSA values with any
|
||||
// IntType type.
|
||||
let imm64 = Builder::new_imm("imm64")
|
||||
.doc("A 64-bit immediate integer.")
|
||||
.build();
|
||||
kinds.push(imm64);
|
||||
/// An unsigned 8-bit immediate integer operand.
|
||||
///
|
||||
/// This small operand is used to indicate lane indexes in SIMD vectors and immediate bit
|
||||
/// counts on shift instructions.
|
||||
pub uimm8: OperandKind,
|
||||
|
||||
// An unsigned 8-bit immediate integer operand.
|
||||
//
|
||||
// This small operand is used to indicate lane indexes in SIMD vectors and
|
||||
// immediate bit counts on shift instructions.
|
||||
let uimm8 = Builder::new_imm("uimm8")
|
||||
.doc("An 8-bit immediate unsigned integer.")
|
||||
.build();
|
||||
kinds.push(uimm8);
|
||||
/// An unsigned 32-bit immediate integer operand.
|
||||
pub uimm32: OperandKind,
|
||||
|
||||
// An unsigned 32-bit immediate integer operand.
|
||||
let uimm32 = Builder::new_imm("uimm32")
|
||||
.doc("A 32-bit immediate unsigned integer.")
|
||||
.build();
|
||||
kinds.push(uimm32);
|
||||
/// An unsigned 128-bit immediate integer operand.
|
||||
///
|
||||
/// This operand is used to pass entire 128-bit vectors as immediates to instructions like
|
||||
/// const.
|
||||
pub uimm128: OperandKind,
|
||||
|
||||
// An unsigned 128-bit immediate integer operand.
|
||||
//
|
||||
// This operand is used to pass entire 128-bit vectors as immediates to
|
||||
// instructions like const.
|
||||
let uimm128 = Builder::new_imm("uimm128")
|
||||
.doc("A 128-bit immediate unsigned integer.")
|
||||
.rust_type("ir::Constant")
|
||||
.build();
|
||||
kinds.push(uimm128);
|
||||
/// A 32-bit immediate signed offset.
|
||||
///
|
||||
/// This is used to represent an immediate address offset in load/store instructions.
|
||||
pub offset32: OperandKind,
|
||||
|
||||
// A 32-bit immediate signed offset.
|
||||
//
|
||||
// This is used to represent an immediate address offset in load/store
|
||||
// instructions.
|
||||
let offset32 = Builder::new_imm("offset32")
|
||||
.doc("A 32-bit immediate signed offset.")
|
||||
.default_member("offset")
|
||||
.build();
|
||||
kinds.push(offset32);
|
||||
/// A 32-bit immediate floating point operand.
|
||||
///
|
||||
/// IEEE 754-2008 binary32 interchange format.
|
||||
pub ieee32: OperandKind,
|
||||
|
||||
// A 32-bit immediate floating point operand.
|
||||
//
|
||||
// IEEE 754-2008 binary32 interchange format.
|
||||
let ieee32 = Builder::new_imm("ieee32")
|
||||
.doc("A 32-bit immediate floating point number.")
|
||||
.build();
|
||||
kinds.push(ieee32);
|
||||
/// A 64-bit immediate floating point operand.
|
||||
///
|
||||
/// IEEE 754-2008 binary64 interchange format.
|
||||
pub ieee64: OperandKind,
|
||||
|
||||
// A 64-bit immediate floating point operand.
|
||||
//
|
||||
// IEEE 754-2008 binary64 interchange format.
|
||||
let ieee64 = Builder::new_imm("ieee64")
|
||||
.doc("A 64-bit immediate floating point number.")
|
||||
.build();
|
||||
kinds.push(ieee64);
|
||||
/// An immediate boolean operand.
|
||||
///
|
||||
/// This type of immediate boolean can interact with SSA values with any BoolType type.
|
||||
pub boolean: OperandKind,
|
||||
|
||||
// An immediate boolean operand.
|
||||
//
|
||||
// This type of immediate boolean can interact with SSA values with any
|
||||
// BoolType type.
|
||||
let boolean = Builder::new_imm("boolean")
|
||||
.doc("An immediate boolean.")
|
||||
.rust_type("bool")
|
||||
.build();
|
||||
kinds.push(boolean);
|
||||
/// A condition code for comparing integer values.
|
||||
///
|
||||
/// This enumerated operand kind is used for the `icmp` instruction and corresponds to the
|
||||
/// condcodes::IntCC` Rust type.
|
||||
pub intcc: OperandKind,
|
||||
|
||||
// A condition code for comparing integer values.
|
||||
// This enumerated operand kind is used for the `icmp` instruction and corresponds to the
|
||||
// condcodes::IntCC` Rust type.
|
||||
let mut intcc_values = HashMap::new();
|
||||
intcc_values.insert("eq", "Equal");
|
||||
intcc_values.insert("ne", "NotEqual");
|
||||
intcc_values.insert("sge", "SignedGreaterThanOrEqual");
|
||||
intcc_values.insert("sgt", "SignedGreaterThan");
|
||||
intcc_values.insert("sle", "SignedLessThanOrEqual");
|
||||
intcc_values.insert("slt", "SignedLessThan");
|
||||
intcc_values.insert("uge", "UnsignedGreaterThanOrEqual");
|
||||
intcc_values.insert("ugt", "UnsignedGreaterThan");
|
||||
intcc_values.insert("ule", "UnsignedLessThanOrEqual");
|
||||
intcc_values.insert("ult", "UnsignedLessThan");
|
||||
let intcc = Builder::new_enum("intcc", intcc_values)
|
||||
.doc("An integer comparison condition code.")
|
||||
.default_member("cond")
|
||||
.rust_type("ir::condcodes::IntCC")
|
||||
.build();
|
||||
kinds.push(intcc);
|
||||
/// A condition code for comparing floating point values.
|
||||
///
|
||||
/// This enumerated operand kind is used for the `fcmp` instruction and corresponds to the
|
||||
/// `condcodes::FloatCC` Rust type.
|
||||
pub floatcc: OperandKind,
|
||||
|
||||
// A condition code for comparing floating point values. This enumerated operand kind is used
|
||||
// for the `fcmp` instruction and corresponds to the `condcodes::FloatCC` Rust type.
|
||||
let mut floatcc_values = HashMap::new();
|
||||
floatcc_values.insert("ord", "Ordered");
|
||||
floatcc_values.insert("uno", "Unordered");
|
||||
floatcc_values.insert("eq", "Equal");
|
||||
floatcc_values.insert("ne", "NotEqual");
|
||||
floatcc_values.insert("one", "OrderedNotEqual");
|
||||
floatcc_values.insert("ueq", "UnorderedOrEqual");
|
||||
floatcc_values.insert("lt", "LessThan");
|
||||
floatcc_values.insert("le", "LessThanOrEqual");
|
||||
floatcc_values.insert("gt", "GreaterThan");
|
||||
floatcc_values.insert("ge", "GreaterThanOrEqual");
|
||||
floatcc_values.insert("ult", "UnorderedOrLessThan");
|
||||
floatcc_values.insert("ule", "UnorderedOrLessThanOrEqual");
|
||||
floatcc_values.insert("ugt", "UnorderedOrGreaterThan");
|
||||
floatcc_values.insert("uge", "UnorderedOrGreaterThanOrEqual");
|
||||
let floatcc = Builder::new_enum("floatcc", floatcc_values)
|
||||
.doc("A floating point comparison condition code")
|
||||
.default_member("cond")
|
||||
.rust_type("ir::condcodes::FloatCC")
|
||||
.build();
|
||||
kinds.push(floatcc);
|
||||
/// Flags for memory operations like `load` and `store`.
|
||||
pub memflags: OperandKind,
|
||||
|
||||
// Flags for memory operations like :clif:inst:`load` and :clif:inst:`store`.
|
||||
let memflags = Builder::new_imm("memflags")
|
||||
.doc("Memory operation flags")
|
||||
.default_member("flags")
|
||||
.rust_type("ir::MemFlags")
|
||||
.build();
|
||||
kinds.push(memflags);
|
||||
/// A register unit in the current target ISA.
|
||||
pub regunit: OperandKind,
|
||||
|
||||
// A register unit in the current target ISA.
|
||||
let regunit = Builder::new_imm("regunit")
|
||||
.doc("A register unit in the target ISA")
|
||||
.rust_type("isa::RegUnit")
|
||||
.build();
|
||||
kinds.push(regunit);
|
||||
|
||||
// A trap code indicating the reason for trapping.
|
||||
//
|
||||
// The Rust enum type also has a `User(u16)` variant for user-provided trap
|
||||
// codes.
|
||||
let mut trapcode_values = HashMap::new();
|
||||
trapcode_values.insert("stk_ovf", "StackOverflow");
|
||||
trapcode_values.insert("heap_oob", "HeapOutOfBounds");
|
||||
trapcode_values.insert("int_ovf", "IntegerOverflow");
|
||||
trapcode_values.insert("int_divz", "IntegerDivisionByZero");
|
||||
let trapcode = Builder::new_enum("trapcode", trapcode_values)
|
||||
.doc("A trap reason code.")
|
||||
.default_member("code")
|
||||
.rust_type("ir::TrapCode")
|
||||
.build();
|
||||
kinds.push(trapcode);
|
||||
|
||||
return kinds;
|
||||
/// A trap code indicating the reason for trapping.
|
||||
///
|
||||
/// The Rust enum type also has a `User(u16)` variant for user-provided trap codes.
|
||||
pub trapcode: OperandKind,
|
||||
}
|
||||
|
||||
impl Immediates {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
imm64: Builder::new_imm("imm64")
|
||||
.doc("A 64-bit immediate integer.")
|
||||
.build(),
|
||||
|
||||
uimm8: Builder::new_imm("uimm8")
|
||||
.doc("An 8-bit immediate unsigned integer.")
|
||||
.build(),
|
||||
|
||||
uimm32: Builder::new_imm("uimm32")
|
||||
.doc("A 32-bit immediate unsigned integer.")
|
||||
.build(),
|
||||
|
||||
uimm128: Builder::new_imm("uimm128")
|
||||
.doc("A 128-bit immediate unsigned integer.")
|
||||
.rust_type("ir::Constant")
|
||||
.build(),
|
||||
|
||||
offset32: Builder::new_imm("offset32")
|
||||
.doc("A 32-bit immediate signed offset.")
|
||||
.default_member("offset")
|
||||
.build(),
|
||||
|
||||
ieee32: Builder::new_imm("ieee32")
|
||||
.doc("A 32-bit immediate floating point number.")
|
||||
.build(),
|
||||
|
||||
ieee64: Builder::new_imm("ieee64")
|
||||
.doc("A 64-bit immediate floating point number.")
|
||||
.build(),
|
||||
|
||||
boolean: Builder::new_imm("boolean")
|
||||
.doc("An immediate boolean.")
|
||||
.rust_type("bool")
|
||||
.build(),
|
||||
|
||||
intcc: {
|
||||
let mut intcc_values = HashMap::new();
|
||||
intcc_values.insert("eq", "Equal");
|
||||
intcc_values.insert("ne", "NotEqual");
|
||||
intcc_values.insert("sge", "SignedGreaterThanOrEqual");
|
||||
intcc_values.insert("sgt", "SignedGreaterThan");
|
||||
intcc_values.insert("sle", "SignedLessThanOrEqual");
|
||||
intcc_values.insert("slt", "SignedLessThan");
|
||||
intcc_values.insert("uge", "UnsignedGreaterThanOrEqual");
|
||||
intcc_values.insert("ugt", "UnsignedGreaterThan");
|
||||
intcc_values.insert("ule", "UnsignedLessThanOrEqual");
|
||||
intcc_values.insert("ult", "UnsignedLessThan");
|
||||
Builder::new_enum("intcc", intcc_values)
|
||||
.doc("An integer comparison condition code.")
|
||||
.default_member("cond")
|
||||
.rust_type("ir::condcodes::IntCC")
|
||||
.build()
|
||||
},
|
||||
|
||||
floatcc: {
|
||||
let mut floatcc_values = HashMap::new();
|
||||
floatcc_values.insert("ord", "Ordered");
|
||||
floatcc_values.insert("uno", "Unordered");
|
||||
floatcc_values.insert("eq", "Equal");
|
||||
floatcc_values.insert("ne", "NotEqual");
|
||||
floatcc_values.insert("one", "OrderedNotEqual");
|
||||
floatcc_values.insert("ueq", "UnorderedOrEqual");
|
||||
floatcc_values.insert("lt", "LessThan");
|
||||
floatcc_values.insert("le", "LessThanOrEqual");
|
||||
floatcc_values.insert("gt", "GreaterThan");
|
||||
floatcc_values.insert("ge", "GreaterThanOrEqual");
|
||||
floatcc_values.insert("ult", "UnorderedOrLessThan");
|
||||
floatcc_values.insert("ule", "UnorderedOrLessThanOrEqual");
|
||||
floatcc_values.insert("ugt", "UnorderedOrGreaterThan");
|
||||
floatcc_values.insert("uge", "UnorderedOrGreaterThanOrEqual");
|
||||
Builder::new_enum("floatcc", floatcc_values)
|
||||
.doc("A floating point comparison condition code")
|
||||
.default_member("cond")
|
||||
.rust_type("ir::condcodes::FloatCC")
|
||||
.build()
|
||||
},
|
||||
|
||||
memflags: Builder::new_imm("memflags")
|
||||
.doc("Memory operation flags")
|
||||
.default_member("flags")
|
||||
.rust_type("ir::MemFlags")
|
||||
.build(),
|
||||
|
||||
regunit: Builder::new_imm("regunit")
|
||||
.doc("A register unit in the target ISA")
|
||||
.rust_type("isa::RegUnit")
|
||||
.build(),
|
||||
|
||||
trapcode: {
|
||||
let mut trapcode_values = HashMap::new();
|
||||
trapcode_values.insert("stk_ovf", "StackOverflow");
|
||||
trapcode_values.insert("heap_oob", "HeapOutOfBounds");
|
||||
trapcode_values.insert("int_ovf", "IntegerOverflow");
|
||||
trapcode_values.insert("int_divz", "IntegerDivisionByZero");
|
||||
Builder::new_enum("trapcode", trapcode_values)
|
||||
.doc("A trap reason code.")
|
||||
.default_member("code")
|
||||
.rust_type("ir::TrapCode")
|
||||
.build()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,12 +8,13 @@ use crate::cdsl::operands::{create_operand as operand, create_operand_doc as ope
|
||||
use crate::cdsl::type_inference::Constraint::WiderOrEq;
|
||||
use crate::cdsl::types::{LaneType, ValueType};
|
||||
use crate::cdsl::typevar::{Interval, TypeSetBuilder, TypeVar};
|
||||
use crate::shared::immediates::Immediates;
|
||||
use crate::shared::{types, OperandKinds};
|
||||
|
||||
pub fn define(
|
||||
all_instructions: &mut AllInstructions,
|
||||
format_registry: &FormatRegistry,
|
||||
immediates: &OperandKinds,
|
||||
imm: &Immediates,
|
||||
entities: &OperandKinds,
|
||||
) -> InstructionGroup {
|
||||
let mut ig = InstructionGroupBuilder::new(
|
||||
@@ -24,20 +25,6 @@ pub fn define(
|
||||
);
|
||||
|
||||
// Operand kind shorthands.
|
||||
let intcc = immediates.by_name("intcc");
|
||||
let floatcc = immediates.by_name("floatcc");
|
||||
let trapcode = immediates.by_name("trapcode");
|
||||
let uimm8 = immediates.by_name("uimm8");
|
||||
let uimm32 = immediates.by_name("uimm32");
|
||||
let imm64 = immediates.by_name("imm64");
|
||||
let uimm128 = immediates.by_name("uimm128");
|
||||
let offset32 = immediates.by_name("offset32");
|
||||
let memflags = immediates.by_name("memflags");
|
||||
let ieee32 = immediates.by_name("ieee32");
|
||||
let ieee64 = immediates.by_name("ieee64");
|
||||
let boolean = immediates.by_name("boolean");
|
||||
let regunit = immediates.by_name("regunit");
|
||||
|
||||
let ebb = entities.by_name("ebb");
|
||||
let jump_table = entities.by_name("jump_table");
|
||||
let variable_args = entities.by_name("variable_args");
|
||||
@@ -142,7 +129,7 @@ pub fn define(
|
||||
|
||||
let addr = &operand("addr", iAddr);
|
||||
let c = &operand_doc("c", Testable, "Controlling value to test");
|
||||
let Cond = &operand("Cond", intcc);
|
||||
let Cond = &operand("Cond", &imm.intcc);
|
||||
let x = &operand("x", iB);
|
||||
let y = &operand("y", iB);
|
||||
let EBB = &operand_doc("EBB", ebb, "Destination extended basic block");
|
||||
@@ -253,7 +240,7 @@ pub fn define(
|
||||
.is_branch(true),
|
||||
);
|
||||
|
||||
let Cond = &operand("Cond", floatcc);
|
||||
let Cond = &operand("Cond", &imm.floatcc);
|
||||
let f = &operand("f", fflags);
|
||||
|
||||
ig.push(
|
||||
@@ -300,7 +287,7 @@ pub fn define(
|
||||
// These are the instructions which br_table legalizes to: they perform address computations,
|
||||
// using pointer-sized integers, so their type variables are more constrained.
|
||||
let x = &operand_doc("x", iAddr, "index into jump table");
|
||||
let Size = &operand_doc("Size", uimm8, "Size in bytes");
|
||||
let Size = &operand_doc("Size", &imm.uimm8, "Size in bytes");
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
@@ -365,7 +352,7 @@ pub fn define(
|
||||
.can_store(true),
|
||||
);
|
||||
|
||||
let code = &operand("code", trapcode);
|
||||
let code = &operand("code", &imm.trapcode);
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
@@ -418,7 +405,7 @@ pub fn define(
|
||||
.can_trap(true),
|
||||
);
|
||||
|
||||
let Cond = &operand("Cond", intcc);
|
||||
let Cond = &operand("Cond", &imm.intcc);
|
||||
let f = &operand("f", iflags);
|
||||
|
||||
ig.push(
|
||||
@@ -432,7 +419,7 @@ pub fn define(
|
||||
.can_trap(true),
|
||||
);
|
||||
|
||||
let Cond = &operand("Cond", floatcc);
|
||||
let Cond = &operand("Cond", &imm.floatcc);
|
||||
let f = &operand("f", fflags);
|
||||
|
||||
ig.push(
|
||||
@@ -539,11 +526,11 @@ pub fn define(
|
||||
);
|
||||
|
||||
let SS = &operand("SS", stack_slot);
|
||||
let Offset = &operand_doc("Offset", offset32, "Byte offset from base address");
|
||||
let Offset = &operand_doc("Offset", &imm.offset32, "Byte offset from base address");
|
||||
let x = &operand_doc("x", Mem, "Value to be stored");
|
||||
let a = &operand_doc("a", Mem, "Value loaded");
|
||||
let p = &operand("p", iAddr);
|
||||
let MemFlags = &operand("MemFlags", memflags);
|
||||
let MemFlags = &operand("MemFlags", &imm.memflags);
|
||||
let args = &operand_doc("args", variable_args, "Address arguments");
|
||||
|
||||
ig.push(
|
||||
@@ -876,7 +863,7 @@ pub fn define(
|
||||
|
||||
let x = &operand_doc("x", Mem, "Value to be stored");
|
||||
let a = &operand_doc("a", Mem, "Value loaded");
|
||||
let Offset = &operand_doc("Offset", offset32, "In-bounds offset into stack slot");
|
||||
let Offset = &operand_doc("Offset", &imm.offset32, "In-bounds offset into stack slot");
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
@@ -962,7 +949,7 @@ pub fn define(
|
||||
|
||||
let H = &operand("H", heap);
|
||||
let p = &operand("p", HeapOffset);
|
||||
let Size = &operand_doc("Size", uimm32, "Size in bytes");
|
||||
let Size = &operand_doc("Size", &imm.uimm32, "Size in bytes");
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
@@ -990,7 +977,7 @@ pub fn define(
|
||||
);
|
||||
let T = &operand("T", table);
|
||||
let p = &operand("p", TableOffset);
|
||||
let Offset = &operand_doc("Offset", offset32, "Byte offset from element address");
|
||||
let Offset = &operand_doc("Offset", &imm.offset32, "Byte offset from element address");
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
@@ -1013,7 +1000,7 @@ pub fn define(
|
||||
.operands_out(vec![addr]),
|
||||
);
|
||||
|
||||
let N = &operand("N", imm64);
|
||||
let N = &operand("N", &imm.imm64);
|
||||
let a = &operand_doc("a", Int, "A constant integer scalar or vector value");
|
||||
|
||||
ig.push(
|
||||
@@ -1030,7 +1017,7 @@ pub fn define(
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let N = &operand("N", ieee32);
|
||||
let N = &operand("N", &imm.ieee32);
|
||||
let a = &operand_doc("a", f32_, "A constant f32 scalar value");
|
||||
|
||||
ig.push(
|
||||
@@ -1046,7 +1033,7 @@ pub fn define(
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let N = &operand("N", ieee64);
|
||||
let N = &operand("N", &imm.ieee64);
|
||||
let a = &operand_doc("a", f64_, "A constant f64 scalar value");
|
||||
|
||||
ig.push(
|
||||
@@ -1062,7 +1049,7 @@ pub fn define(
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let N = &operand("N", boolean);
|
||||
let N = &operand("N", &imm.boolean);
|
||||
let a = &operand_doc("a", Bool, "A constant boolean scalar or vector value");
|
||||
|
||||
ig.push(
|
||||
@@ -1079,7 +1066,11 @@ pub fn define(
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let N = &operand_doc("N", uimm128, "The 16 immediate bytes of a 128-bit vector");
|
||||
let N = &operand_doc(
|
||||
"N",
|
||||
&imm.uimm128,
|
||||
"The 16 immediate bytes of a 128-bit vector",
|
||||
);
|
||||
let a = &operand_doc("a", TxN, "A constant vector value");
|
||||
|
||||
ig.push(
|
||||
@@ -1137,7 +1128,7 @@ pub fn define(
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let cc = &operand_doc("cc", intcc, "Controlling condition code");
|
||||
let cc = &operand_doc("cc", &imm.intcc, "Controlling condition code");
|
||||
let flags = &operand_doc("flags", iflags, "The machine's flag register");
|
||||
|
||||
ig.push(
|
||||
@@ -1217,8 +1208,8 @@ pub fn define(
|
||||
.can_load(true),
|
||||
);
|
||||
|
||||
let src = &operand("src", regunit);
|
||||
let dst = &operand("dst", regunit);
|
||||
let src = &operand("src", &imm.regunit);
|
||||
let dst = &operand("dst", &imm.regunit);
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
@@ -1302,7 +1293,7 @@ pub fn define(
|
||||
.other_side_effects(true),
|
||||
);
|
||||
|
||||
let Offset = &operand_doc("Offset", imm64, "Offset from current stack pointer");
|
||||
let Offset = &operand_doc("Offset", &imm.imm64, "Offset from current stack pointer");
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
@@ -1319,7 +1310,7 @@ pub fn define(
|
||||
.other_side_effects(true),
|
||||
);
|
||||
|
||||
let Offset = &operand_doc("Offset", imm64, "Offset from current stack pointer");
|
||||
let Offset = &operand_doc("Offset", &imm.imm64, "Offset from current stack pointer");
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
@@ -1498,7 +1489,7 @@ pub fn define(
|
||||
|
||||
let x = &operand_doc("x", TxN, "SIMD vector to modify");
|
||||
let y = &operand_doc("y", &TxN.lane_of(), "New lane value");
|
||||
let Idx = &operand_doc("Idx", uimm8, "Lane index");
|
||||
let Idx = &operand_doc("Idx", &imm.uimm8, "Lane index");
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
@@ -1532,7 +1523,7 @@ pub fn define(
|
||||
);
|
||||
|
||||
let a = &operand("a", &Int.as_bool());
|
||||
let Cond = &operand("Cond", intcc);
|
||||
let Cond = &operand("Cond", &imm.intcc);
|
||||
let x = &operand("x", Int);
|
||||
let y = &operand("y", Int);
|
||||
|
||||
@@ -1566,7 +1557,7 @@ pub fn define(
|
||||
|
||||
let a = &operand("a", b1);
|
||||
let x = &operand("x", iB);
|
||||
let Y = &operand("Y", imm64);
|
||||
let Y = &operand("Y", &imm.imm64);
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
@@ -1757,7 +1748,7 @@ pub fn define(
|
||||
|
||||
let a = &operand("a", iB);
|
||||
let x = &operand("x", iB);
|
||||
let Y = &operand("Y", imm64);
|
||||
let Y = &operand("Y", &imm.imm64);
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
@@ -2092,7 +2083,7 @@ pub fn define(
|
||||
);
|
||||
|
||||
let x = &operand("x", iB);
|
||||
let Y = &operand("Y", imm64);
|
||||
let Y = &operand("Y", &imm.imm64);
|
||||
let a = &operand("a", iB);
|
||||
|
||||
ig.push(
|
||||
@@ -2145,7 +2136,7 @@ pub fn define(
|
||||
|
||||
let x = &operand_doc("x", Int, "Scalar or vector value to shift");
|
||||
let y = &operand_doc("y", iB, "Number of bits to shift");
|
||||
let Y = &operand("Y", imm64);
|
||||
let Y = &operand("Y", &imm.imm64);
|
||||
let a = &operand("a", Int);
|
||||
|
||||
ig.push(
|
||||
@@ -2375,7 +2366,7 @@ pub fn define(
|
||||
.simd_lanes(Interval::All)
|
||||
.build(),
|
||||
);
|
||||
let Cond = &operand("Cond", floatcc);
|
||||
let Cond = &operand("Cond", &imm.floatcc);
|
||||
let x = &operand("x", Float);
|
||||
let y = &operand("y", Float);
|
||||
let a = &operand("a", &Float.as_bool());
|
||||
@@ -2687,7 +2678,7 @@ pub fn define(
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let Cond = &operand("Cond", intcc);
|
||||
let Cond = &operand("Cond", &imm.intcc);
|
||||
let f = &operand("f", iflags);
|
||||
let a = &operand("a", b1);
|
||||
|
||||
@@ -2705,7 +2696,7 @@ pub fn define(
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
let Cond = &operand("Cond", floatcc);
|
||||
let Cond = &operand("Cond", &imm.floatcc);
|
||||
let f = &operand("f", fflags);
|
||||
|
||||
ig.push(
|
||||
|
||||
@@ -2,12 +2,11 @@ use crate::cdsl::ast::{var, ExprBuilder, Literal};
|
||||
use crate::cdsl::instructions::{Instruction, InstructionGroup};
|
||||
use crate::cdsl::xform::{TransformGroupBuilder, TransformGroups};
|
||||
|
||||
use crate::shared::OperandKinds;
|
||||
|
||||
use crate::shared::immediates::Immediates;
|
||||
use crate::shared::types::Float::{F32, F64};
|
||||
use crate::shared::types::Int::{I16, I32, I64, I8};
|
||||
|
||||
pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformGroups {
|
||||
pub fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGroups {
|
||||
let mut narrow = TransformGroupBuilder::new(
|
||||
"narrow",
|
||||
r#"
|
||||
@@ -139,12 +138,6 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG
|
||||
expand.custom_legalize(insts.by_name("stack_load"), "expand_stack_load");
|
||||
expand.custom_legalize(insts.by_name("stack_store"), "expand_stack_store");
|
||||
|
||||
// List of immediates.
|
||||
let imm64 = immediates.by_name("imm64");
|
||||
let ieee32 = immediates.by_name("ieee32");
|
||||
let ieee64 = immediates.by_name("ieee64");
|
||||
let intcc = immediates.by_name("intcc");
|
||||
|
||||
// List of variables to reuse in patterns.
|
||||
let x = var("x");
|
||||
let y = var("y");
|
||||
@@ -298,7 +291,7 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG
|
||||
}
|
||||
|
||||
for &(int_ty, num) in &[(I8, 24), (I16, 16)] {
|
||||
let imm = Literal::constant(imm64, -num);
|
||||
let imm = Literal::constant(&imm.imm64, -num);
|
||||
|
||||
widen.legalize(
|
||||
def!(a = clz.int_ty(b)),
|
||||
@@ -322,7 +315,7 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG
|
||||
}
|
||||
|
||||
for &(int_ty, num) in &[(I8, 1 << 8), (I16, 1 << 16)] {
|
||||
let num = Literal::constant(imm64, num);
|
||||
let num = Literal::constant(&imm.imm64, num);
|
||||
widen.legalize(
|
||||
def!(a = ctz.int_ty(b)),
|
||||
vec![
|
||||
@@ -423,7 +416,7 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG
|
||||
}
|
||||
|
||||
for cc in &["eq", "ne", "ugt", "ult", "uge", "ule"] {
|
||||
let w_cc = Literal::enumerator_for(intcc, cc);
|
||||
let w_cc = Literal::enumerator_for(&imm.intcc, cc);
|
||||
widen.legalize(
|
||||
def!(a = icmp_imm.int_ty(w_cc, b, c)),
|
||||
vec![def!(x = uextend.I32(b)), def!(a = icmp_imm(w_cc, x, c))],
|
||||
@@ -439,7 +432,7 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG
|
||||
}
|
||||
|
||||
for cc in &["sgt", "slt", "sge", "sle"] {
|
||||
let w_cc = Literal::enumerator_for(intcc, cc);
|
||||
let w_cc = Literal::enumerator_for(&imm.intcc, cc);
|
||||
widen.legalize(
|
||||
def!(a = icmp_imm.int_ty(w_cc, b, c)),
|
||||
vec![def!(x = sextend.I32(b)), def!(a = icmp_imm(w_cc, x, c))],
|
||||
@@ -534,7 +527,7 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG
|
||||
}
|
||||
|
||||
//# Expand bnot using xor.
|
||||
let minus_one = Literal::constant(imm64, -1);
|
||||
let minus_one = Literal::constant(&imm.imm64, -1);
|
||||
expand.legalize(
|
||||
def!(a = bnot(x)),
|
||||
vec![def!(y = iconst(minus_one)), def!(a = bxor(x, y))],
|
||||
@@ -543,82 +536,82 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG
|
||||
//# Expand bitrev
|
||||
//# Adapted from Stack Overflow.
|
||||
//# https://stackoverflow.com/questions/746171/most-efficient-algorithm-for-bit-reversal-from-msb-lsb-to-lsb-msb-in-c
|
||||
let imm64_1 = Literal::constant(imm64, 1);
|
||||
let imm64_2 = Literal::constant(imm64, 2);
|
||||
let imm64_4 = Literal::constant(imm64, 4);
|
||||
let imm64_1 = Literal::constant(&imm.imm64, 1);
|
||||
let imm64_2 = Literal::constant(&imm.imm64, 2);
|
||||
let imm64_4 = Literal::constant(&imm.imm64, 4);
|
||||
|
||||
widen.legalize(
|
||||
def!(a = bitrev.I8(x)),
|
||||
vec![
|
||||
def!(a1 = band_imm(x, Literal::constant(imm64, 0xaa))),
|
||||
def!(a1 = band_imm(x, Literal::constant(&imm.imm64, 0xaa))),
|
||||
def!(a2 = ushr_imm(a1, imm64_1)),
|
||||
def!(a3 = band_imm(x, Literal::constant(imm64, 0x55))),
|
||||
def!(a3 = band_imm(x, Literal::constant(&imm.imm64, 0x55))),
|
||||
def!(a4 = ishl_imm(a3, imm64_1)),
|
||||
def!(b = bor(a2, a4)),
|
||||
def!(b1 = band_imm(b, Literal::constant(imm64, 0xcc))),
|
||||
def!(b1 = band_imm(b, Literal::constant(&imm.imm64, 0xcc))),
|
||||
def!(b2 = ushr_imm(b1, imm64_2)),
|
||||
def!(b3 = band_imm(b, Literal::constant(imm64, 0x33))),
|
||||
def!(b3 = band_imm(b, Literal::constant(&imm.imm64, 0x33))),
|
||||
def!(b4 = ishl_imm(b3, imm64_2)),
|
||||
def!(c = bor(b2, b4)),
|
||||
def!(c1 = band_imm(c, Literal::constant(imm64, 0xf0))),
|
||||
def!(c1 = band_imm(c, Literal::constant(&imm.imm64, 0xf0))),
|
||||
def!(c2 = ushr_imm(c1, imm64_4)),
|
||||
def!(c3 = band_imm(c, Literal::constant(imm64, 0x0f))),
|
||||
def!(c3 = band_imm(c, Literal::constant(&imm.imm64, 0x0f))),
|
||||
def!(c4 = ishl_imm(c3, imm64_4)),
|
||||
def!(a = bor(c2, c4)),
|
||||
],
|
||||
);
|
||||
|
||||
let imm64_8 = Literal::constant(imm64, 8);
|
||||
let imm64_8 = Literal::constant(&imm.imm64, 8);
|
||||
|
||||
widen.legalize(
|
||||
def!(a = bitrev.I16(x)),
|
||||
vec![
|
||||
def!(a1 = band_imm(x, Literal::constant(imm64, 0xaaaa))),
|
||||
def!(a1 = band_imm(x, Literal::constant(&imm.imm64, 0xaaaa))),
|
||||
def!(a2 = ushr_imm(a1, imm64_1)),
|
||||
def!(a3 = band_imm(x, Literal::constant(imm64, 0x5555))),
|
||||
def!(a3 = band_imm(x, Literal::constant(&imm.imm64, 0x5555))),
|
||||
def!(a4 = ishl_imm(a3, imm64_1)),
|
||||
def!(b = bor(a2, a4)),
|
||||
def!(b1 = band_imm(b, Literal::constant(imm64, 0xcccc))),
|
||||
def!(b1 = band_imm(b, Literal::constant(&imm.imm64, 0xcccc))),
|
||||
def!(b2 = ushr_imm(b1, imm64_2)),
|
||||
def!(b3 = band_imm(b, Literal::constant(imm64, 0x3333))),
|
||||
def!(b3 = band_imm(b, Literal::constant(&imm.imm64, 0x3333))),
|
||||
def!(b4 = ishl_imm(b3, imm64_2)),
|
||||
def!(c = bor(b2, b4)),
|
||||
def!(c1 = band_imm(c, Literal::constant(imm64, 0xf0f0))),
|
||||
def!(c1 = band_imm(c, Literal::constant(&imm.imm64, 0xf0f0))),
|
||||
def!(c2 = ushr_imm(c1, imm64_4)),
|
||||
def!(c3 = band_imm(c, Literal::constant(imm64, 0x0f0f))),
|
||||
def!(c3 = band_imm(c, Literal::constant(&imm.imm64, 0x0f0f))),
|
||||
def!(c4 = ishl_imm(c3, imm64_4)),
|
||||
def!(d = bor(c2, c4)),
|
||||
def!(d1 = band_imm(d, Literal::constant(imm64, 0xff00))),
|
||||
def!(d1 = band_imm(d, Literal::constant(&imm.imm64, 0xff00))),
|
||||
def!(d2 = ushr_imm(d1, imm64_8)),
|
||||
def!(d3 = band_imm(d, Literal::constant(imm64, 0x00ff))),
|
||||
def!(d3 = band_imm(d, Literal::constant(&imm.imm64, 0x00ff))),
|
||||
def!(d4 = ishl_imm(d3, imm64_8)),
|
||||
def!(a = bor(d2, d4)),
|
||||
],
|
||||
);
|
||||
|
||||
let imm64_16 = Literal::constant(imm64, 16);
|
||||
let imm64_16 = Literal::constant(&imm.imm64, 16);
|
||||
|
||||
expand.legalize(
|
||||
def!(a = bitrev.I32(x)),
|
||||
vec![
|
||||
def!(a1 = band_imm(x, Literal::constant(imm64, 0xaaaaaaaa))),
|
||||
def!(a1 = band_imm(x, Literal::constant(&imm.imm64, 0xaaaaaaaa))),
|
||||
def!(a2 = ushr_imm(a1, imm64_1)),
|
||||
def!(a3 = band_imm(x, Literal::constant(imm64, 0x55555555))),
|
||||
def!(a3 = band_imm(x, Literal::constant(&imm.imm64, 0x55555555))),
|
||||
def!(a4 = ishl_imm(a3, imm64_1)),
|
||||
def!(b = bor(a2, a4)),
|
||||
def!(b1 = band_imm(b, Literal::constant(imm64, 0xcccccccc))),
|
||||
def!(b1 = band_imm(b, Literal::constant(&imm.imm64, 0xcccccccc))),
|
||||
def!(b2 = ushr_imm(b1, imm64_2)),
|
||||
def!(b3 = band_imm(b, Literal::constant(imm64, 0x33333333))),
|
||||
def!(b3 = band_imm(b, Literal::constant(&imm.imm64, 0x33333333))),
|
||||
def!(b4 = ishl_imm(b3, imm64_2)),
|
||||
def!(c = bor(b2, b4)),
|
||||
def!(c1 = band_imm(c, Literal::constant(imm64, 0xf0f0f0f0))),
|
||||
def!(c1 = band_imm(c, Literal::constant(&imm.imm64, 0xf0f0f0f0))),
|
||||
def!(c2 = ushr_imm(c1, imm64_4)),
|
||||
def!(c3 = band_imm(c, Literal::constant(imm64, 0x0f0f0f0f))),
|
||||
def!(c3 = band_imm(c, Literal::constant(&imm.imm64, 0x0f0f0f0f))),
|
||||
def!(c4 = ishl_imm(c3, imm64_4)),
|
||||
def!(d = bor(c2, c4)),
|
||||
def!(d1 = band_imm(d, Literal::constant(imm64, 0xff00ff00))),
|
||||
def!(d1 = band_imm(d, Literal::constant(&imm.imm64, 0xff00ff00))),
|
||||
def!(d2 = ushr_imm(d1, imm64_8)),
|
||||
def!(d3 = band_imm(d, Literal::constant(imm64, 0x00ff00ff))),
|
||||
def!(d3 = band_imm(d, Literal::constant(&imm.imm64, 0x00ff00ff))),
|
||||
def!(d4 = ishl_imm(d3, imm64_8)),
|
||||
def!(e = bor(d2, d4)),
|
||||
def!(e1 = ushr_imm(e, imm64_16)),
|
||||
@@ -628,21 +621,21 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG
|
||||
);
|
||||
|
||||
#[allow(overflowing_literals)]
|
||||
let imm64_0xaaaaaaaaaaaaaaaa = Literal::constant(imm64, 0xaaaaaaaaaaaaaaaa);
|
||||
let imm64_0x5555555555555555 = Literal::constant(imm64, 0x5555555555555555);
|
||||
let imm64_0xaaaaaaaaaaaaaaaa = Literal::constant(&imm.imm64, 0xaaaaaaaaaaaaaaaa);
|
||||
let imm64_0x5555555555555555 = Literal::constant(&imm.imm64, 0x5555555555555555);
|
||||
#[allow(overflowing_literals)]
|
||||
let imm64_0xcccccccccccccccc = Literal::constant(imm64, 0xcccccccccccccccc);
|
||||
let imm64_0x3333333333333333 = Literal::constant(imm64, 0x3333333333333333);
|
||||
let imm64_0xcccccccccccccccc = Literal::constant(&imm.imm64, 0xcccccccccccccccc);
|
||||
let imm64_0x3333333333333333 = Literal::constant(&imm.imm64, 0x3333333333333333);
|
||||
#[allow(overflowing_literals)]
|
||||
let imm64_0xf0f0f0f0f0f0f0f0 = Literal::constant(imm64, 0xf0f0f0f0f0f0f0f0);
|
||||
let imm64_0x0f0f0f0f0f0f0f0f = Literal::constant(imm64, 0x0f0f0f0f0f0f0f0f);
|
||||
let imm64_0xf0f0f0f0f0f0f0f0 = Literal::constant(&imm.imm64, 0xf0f0f0f0f0f0f0f0);
|
||||
let imm64_0x0f0f0f0f0f0f0f0f = Literal::constant(&imm.imm64, 0x0f0f0f0f0f0f0f0f);
|
||||
#[allow(overflowing_literals)]
|
||||
let imm64_0xff00ff00ff00ff00 = Literal::constant(imm64, 0xff00ff00ff00ff00);
|
||||
let imm64_0x00ff00ff00ff00ff = Literal::constant(imm64, 0x00ff00ff00ff00ff);
|
||||
let imm64_0xff00ff00ff00ff00 = Literal::constant(&imm.imm64, 0xff00ff00ff00ff00);
|
||||
let imm64_0x00ff00ff00ff00ff = Literal::constant(&imm.imm64, 0x00ff00ff00ff00ff);
|
||||
#[allow(overflowing_literals)]
|
||||
let imm64_0xffff0000ffff0000 = Literal::constant(imm64, 0xffff0000ffff0000);
|
||||
let imm64_0x0000ffff0000ffff = Literal::constant(imm64, 0x0000ffff0000ffff);
|
||||
let imm64_32 = Literal::constant(imm64, 32);
|
||||
let imm64_0xffff0000ffff0000 = Literal::constant(&imm.imm64, 0xffff0000ffff0000);
|
||||
let imm64_0x0000ffff0000ffff = Literal::constant(&imm.imm64, 0x0000ffff0000ffff);
|
||||
let imm64_32 = Literal::constant(&imm.imm64, 32);
|
||||
|
||||
expand.legalize(
|
||||
def!(a = bitrev.I64(x)),
|
||||
@@ -680,8 +673,12 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG
|
||||
|
||||
// Floating-point sign manipulations.
|
||||
for &(ty, const_inst, minus_zero) in &[
|
||||
(F32, f32const, &Literal::bits(ieee32, 0x80000000)),
|
||||
(F64, f64const, &Literal::bits(ieee64, 0x8000000000000000)),
|
||||
(F32, f32const, &Literal::bits(&imm.ieee32, 0x80000000)),
|
||||
(
|
||||
F64,
|
||||
f64const,
|
||||
&Literal::bits(&imm.ieee64, 0x8000000000000000),
|
||||
),
|
||||
] {
|
||||
expand.legalize(
|
||||
def!(a = fabs.ty(x)),
|
||||
@@ -724,9 +721,9 @@ pub fn define(insts: &InstructionGroup, immediates: &OperandKinds) -> TransformG
|
||||
)
|
||||
.chain_with(expand_id);
|
||||
|
||||
let imm64_0 = Literal::constant(imm64, 0);
|
||||
let intcc_ne = Literal::enumerator_for(intcc, "ne");
|
||||
let intcc_eq = Literal::enumerator_for(intcc, "eq");
|
||||
let imm64_0 = Literal::constant(&imm.imm64, 0);
|
||||
let intcc_ne = Literal::enumerator_for(&imm.intcc, "ne");
|
||||
let intcc_eq = Literal::enumerator_for(&imm.intcc, "eq");
|
||||
|
||||
expand_flags.legalize(
|
||||
def!(trapnz(x, c)),
|
||||
|
||||
@@ -14,11 +14,13 @@ use crate::cdsl::operands::OperandKind;
|
||||
use crate::cdsl::settings::SettingGroup;
|
||||
use crate::cdsl::xform::TransformGroups;
|
||||
|
||||
use crate::shared::immediates::Immediates;
|
||||
|
||||
pub struct Definitions {
|
||||
pub settings: SettingGroup,
|
||||
pub all_instructions: AllInstructions,
|
||||
pub instructions: InstructionGroup,
|
||||
pub operand_kinds: OperandKinds,
|
||||
pub imm: Immediates,
|
||||
pub format_registry: FormatRegistry,
|
||||
pub transform_groups: TransformGroups,
|
||||
}
|
||||
@@ -26,28 +28,12 @@ pub struct Definitions {
|
||||
pub struct OperandKinds(Vec<OperandKind>);
|
||||
|
||||
impl OperandKinds {
|
||||
pub fn new() -> Self {
|
||||
Self(Vec::new())
|
||||
}
|
||||
|
||||
pub fn by_name(&self, name: &'static str) -> &OperandKind {
|
||||
self.0
|
||||
.iter()
|
||||
.find(|op| op.name == name)
|
||||
.expect(&format!("unknown Operand name: {}", name))
|
||||
}
|
||||
|
||||
pub fn push(&mut self, operand_kind: OperandKind) {
|
||||
assert!(
|
||||
self.0
|
||||
.iter()
|
||||
.find(|existing| existing.name == operand_kind.name)
|
||||
.is_none(),
|
||||
"trying to insert operand kind '{}' for the second time",
|
||||
operand_kind.name
|
||||
);
|
||||
self.0.push(operand_kind);
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<OperandKind>> for OperandKinds {
|
||||
@@ -59,7 +45,7 @@ impl From<Vec<OperandKind>> for OperandKinds {
|
||||
pub fn define() -> Definitions {
|
||||
let mut all_instructions = AllInstructions::new();
|
||||
|
||||
let immediates = OperandKinds(immediates::define());
|
||||
let immediates = Immediates::new();
|
||||
let entities = OperandKinds(entities::define());
|
||||
let format_registry = formats::define(&immediates, &entities);
|
||||
let instructions = instructions::define(
|
||||
@@ -74,7 +60,7 @@ pub fn define() -> Definitions {
|
||||
settings: settings::define(),
|
||||
all_instructions,
|
||||
instructions,
|
||||
operand_kinds: immediates,
|
||||
imm: immediates,
|
||||
format_registry,
|
||||
transform_groups,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user