Add operand kind and format for unsigned 128-bit immediates
This commit is contained in:
@@ -5,6 +5,7 @@ pub fn define(immediates: &OperandKinds, entities: &OperandKinds) -> FormatRegis
|
|||||||
// Shorthands for immediates.
|
// Shorthands for immediates.
|
||||||
let uimm8 = immediates.by_name("uimm8");
|
let uimm8 = immediates.by_name("uimm8");
|
||||||
let uimm32 = immediates.by_name("uimm32");
|
let uimm32 = immediates.by_name("uimm32");
|
||||||
|
let uimm128 = immediates.by_name("uimm128");
|
||||||
let imm64 = immediates.by_name("imm64");
|
let imm64 = immediates.by_name("imm64");
|
||||||
let ieee32 = immediates.by_name("ieee32");
|
let ieee32 = immediates.by_name("ieee32");
|
||||||
let ieee64 = immediates.by_name("ieee64");
|
let ieee64 = immediates.by_name("ieee64");
|
||||||
@@ -30,6 +31,7 @@ pub fn define(immediates: &OperandKinds, entities: &OperandKinds) -> FormatRegis
|
|||||||
|
|
||||||
registry.insert(Builder::new("Unary").value());
|
registry.insert(Builder::new("Unary").value());
|
||||||
registry.insert(Builder::new("UnaryImm").imm(imm64));
|
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("UnaryIeee32").imm(ieee32));
|
||||||
registry.insert(Builder::new("UnaryIeee64").imm(ieee64));
|
registry.insert(Builder::new("UnaryIeee64").imm(ieee64));
|
||||||
registry.insert(Builder::new("UnaryBool").imm(boolean));
|
registry.insert(Builder::new("UnaryBool").imm(boolean));
|
||||||
|
|||||||
@@ -29,6 +29,16 @@ pub fn define() -> Vec<OperandKind> {
|
|||||||
.build();
|
.build();
|
||||||
kinds.push(uimm32);
|
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.
|
||||||
|
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.
|
// A 32-bit immediate signed offset.
|
||||||
//
|
//
|
||||||
// This is used to represent an immediate address offset in load/store
|
// This is used to represent an immediate address offset in load/store
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ pub fn define(
|
|||||||
let uimm8 = immediates.by_name("uimm8");
|
let uimm8 = immediates.by_name("uimm8");
|
||||||
let uimm32 = immediates.by_name("uimm32");
|
let uimm32 = immediates.by_name("uimm32");
|
||||||
let imm64 = immediates.by_name("imm64");
|
let imm64 = immediates.by_name("imm64");
|
||||||
|
let uimm128 = immediates.by_name("uimm128");
|
||||||
let offset32 = immediates.by_name("offset32");
|
let offset32 = immediates.by_name("offset32");
|
||||||
let memflags = immediates.by_name("memflags");
|
let memflags = immediates.by_name("memflags");
|
||||||
let ieee32 = immediates.by_name("ieee32");
|
let ieee32 = immediates.by_name("ieee32");
|
||||||
@@ -1088,6 +1089,22 @@ pub fn define(
|
|||||||
.operands_out(vec![a]),
|
.operands_out(vec![a]),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let N = &operand_doc("N", uimm128, "The 16 immediate bytes of a 128-bit vector");
|
||||||
|
let a = &operand_doc("a", TxN, "A constant vector value");
|
||||||
|
|
||||||
|
ig.push(
|
||||||
|
Inst::new(
|
||||||
|
"vconst",
|
||||||
|
r#"
|
||||||
|
SIMD vector constant.
|
||||||
|
|
||||||
|
Construct a vector with the given immediate bytes.
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.operands_in(vec![N])
|
||||||
|
.operands_out(vec![a]),
|
||||||
|
);
|
||||||
|
|
||||||
let a = &operand_doc("a", Ref, "A constant reference null value");
|
let a = &operand_doc("a", Ref, "A constant reference null value");
|
||||||
|
|
||||||
ig.push(
|
ig.push(
|
||||||
|
|||||||
@@ -679,6 +679,7 @@ impl<'a> Verifier<'a> {
|
|||||||
// Exhaustive list so we can't forget to add new formats
|
// Exhaustive list so we can't forget to add new formats
|
||||||
Unary { .. }
|
Unary { .. }
|
||||||
| UnaryImm { .. }
|
| UnaryImm { .. }
|
||||||
|
| UnaryImm128 { .. }
|
||||||
| UnaryIeee32 { .. }
|
| UnaryIeee32 { .. }
|
||||||
| UnaryIeee64 { .. }
|
| UnaryIeee64 { .. }
|
||||||
| UnaryBool { .. }
|
| UnaryBool { .. }
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
use crate::entity::SecondaryMap;
|
use crate::entity::SecondaryMap;
|
||||||
use crate::ir::entities::AnyEntity;
|
use crate::ir::entities::AnyEntity;
|
||||||
|
use crate::ir::immediates::Uimm128;
|
||||||
use crate::ir::{
|
use crate::ir::{
|
||||||
DataFlowGraph, DisplayFunctionAnnotations, Ebb, Function, Inst, SigRef, Type, Value, ValueDef,
|
DataFlowGraph, DisplayFunctionAnnotations, Ebb, Function, Inst, SigRef, Type, Value, ValueDef,
|
||||||
ValueLoc,
|
ValueLoc,
|
||||||
@@ -487,6 +488,11 @@ pub fn write_operands(
|
|||||||
match dfg[inst] {
|
match dfg[inst] {
|
||||||
Unary { arg, .. } => write!(w, " {}", arg),
|
Unary { arg, .. } => write!(w, " {}", arg),
|
||||||
UnaryImm { imm, .. } => write!(w, " {}", imm),
|
UnaryImm { imm, .. } => write!(w, " {}", imm),
|
||||||
|
UnaryImm128 { imm, .. } => {
|
||||||
|
let data = dfg.constants.get(imm);
|
||||||
|
let uimm128 = Uimm128::from(&data[..]);
|
||||||
|
write!(w, " {}", uimm128)
|
||||||
|
}
|
||||||
UnaryIeee32 { imm, .. } => write!(w, " {}", imm),
|
UnaryIeee32 { imm, .. } => write!(w, " {}", imm),
|
||||||
UnaryIeee64 { imm, .. } => write!(w, " {}", imm),
|
UnaryIeee64 { imm, .. } => write!(w, " {}", imm),
|
||||||
UnaryBool { imm, .. } => write!(w, " {}", imm),
|
UnaryBool { imm, .. } => write!(w, " {}", imm),
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use crate::testfile::{Comment, Details, TestFile};
|
|||||||
use cranelift_codegen::entity::EntityRef;
|
use cranelift_codegen::entity::EntityRef;
|
||||||
use cranelift_codegen::ir;
|
use cranelift_codegen::ir;
|
||||||
use cranelift_codegen::ir::entities::AnyEntity;
|
use cranelift_codegen::ir::entities::AnyEntity;
|
||||||
use cranelift_codegen::ir::immediates::{Ieee32, Ieee64, Imm64, Offset32, Uimm32, Uimm64};
|
use cranelift_codegen::ir::immediates::{Ieee32, Ieee64, Imm64, Offset32, Uimm128, Uimm32, Uimm64};
|
||||||
use cranelift_codegen::ir::instructions::{InstructionData, InstructionFormat, VariableArgs};
|
use cranelift_codegen::ir::instructions::{InstructionData, InstructionFormat, VariableArgs};
|
||||||
use cranelift_codegen::ir::types::INVALID;
|
use cranelift_codegen::ir::types::INVALID;
|
||||||
use cranelift_codegen::ir::{
|
use cranelift_codegen::ir::{
|
||||||
@@ -546,6 +546,23 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Match and consume a Uimm128 immediate; due to size restrictions on InstructionData, Uimm128 is boxed in cranelift-codegen/meta/src/shared/immediates.rs
|
||||||
|
fn match_uimm128(&mut self, err_msg: &str) -> ParseResult<Uimm128> {
|
||||||
|
if let Some(Token::Integer(text)) = self.token() {
|
||||||
|
self.consume();
|
||||||
|
// Lexer just gives us raw text that looks like hex code.
|
||||||
|
// Parse it as an Uimm128 to check for overflow and other issues.
|
||||||
|
text.parse().map_err(|e| {
|
||||||
|
self.error(&format!(
|
||||||
|
"expected u128 hexadecimal immediate, failed to parse: {}",
|
||||||
|
e
|
||||||
|
))
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
err!(self.loc, err_msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Match and consume a Uimm64 immediate.
|
// Match and consume a Uimm64 immediate.
|
||||||
fn match_uimm64(&mut self, err_msg: &str) -> ParseResult<Uimm64> {
|
fn match_uimm64(&mut self, err_msg: &str) -> ParseResult<Uimm64> {
|
||||||
if let Some(Token::Integer(text)) = self.token() {
|
if let Some(Token::Integer(text)) = self.token() {
|
||||||
@@ -2109,6 +2126,14 @@ impl<'a> Parser<'a> {
|
|||||||
opcode,
|
opcode,
|
||||||
imm: self.match_imm64("expected immediate integer operand")?,
|
imm: self.match_imm64("expected immediate integer operand")?,
|
||||||
},
|
},
|
||||||
|
InstructionFormat::UnaryImm128 => {
|
||||||
|
let uimm128 = self.match_uimm128("expected immediate hexadecimal operand")?;
|
||||||
|
let constant_handle = ctx.function.dfg.constants.insert(uimm128.0.to_vec());
|
||||||
|
InstructionData::UnaryImm128 {
|
||||||
|
opcode,
|
||||||
|
imm: constant_handle,
|
||||||
|
}
|
||||||
|
}
|
||||||
InstructionFormat::UnaryIeee32 => InstructionData::UnaryIeee32 {
|
InstructionFormat::UnaryIeee32 => InstructionData::UnaryIeee32 {
|
||||||
opcode,
|
opcode,
|
||||||
imm: self.match_ieee32("expected immediate 32-bit float operand")?,
|
imm: self.match_ieee32("expected immediate 32-bit float operand")?,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use cranelift_codegen::ir::immediates::Uimm128;
|
||||||
use cranelift_codegen::ir::{Ebb, Function, Inst, InstructionData, Signature};
|
use cranelift_codegen::ir::{Ebb, Function, Inst, InstructionData, Signature};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
|
||||||
@@ -261,6 +262,14 @@ pub fn get_inst_data(inst_index: Inst, func: &Function) -> SerInstData {
|
|||||||
opcode: opcode.to_string(),
|
opcode: opcode.to_string(),
|
||||||
imm: imm.to_string(),
|
imm: imm.to_string(),
|
||||||
},
|
},
|
||||||
|
InstructionData::UnaryImm128 { opcode, imm } => {
|
||||||
|
let data = func.dfg.constants.get(imm);
|
||||||
|
let uimm128 = Uimm128::from(&data[..]);
|
||||||
|
SerInstData::UnaryImm {
|
||||||
|
opcode: opcode.to_string(),
|
||||||
|
imm: uimm128.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
InstructionData::UnaryIeee32 { opcode, imm } => SerInstData::UnaryIeee32 {
|
InstructionData::UnaryIeee32 { opcode, imm } => SerInstData::UnaryIeee32 {
|
||||||
opcode: opcode.to_string(),
|
opcode: opcode.to_string(),
|
||||||
imm: imm.to_string(),
|
imm: imm.to_string(),
|
||||||
|
|||||||
Reference in New Issue
Block a user