Parse insertlane and extractlane instruction formats.
These instruction formats take immediate lane index operands. We store these as u8 fields and require them to be in decimal format in the source. No hexadecimal lane indexes are supported.
This commit is contained in:
@@ -247,6 +247,19 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Match and consume a u8 immediate.
|
||||||
|
// This is used for lane numbers in SIMD vectors.
|
||||||
|
fn match_u8(&mut self, err_msg: &str) -> Result<u8> {
|
||||||
|
if let Some(Token::Integer(text)) = self.token() {
|
||||||
|
self.consume();
|
||||||
|
// Lexer just gives us raw text that looks like an integer.
|
||||||
|
// Parse it as a u8 to check for overflow and other issues.
|
||||||
|
text.parse().map_err(|_| self.error("expected u8 decimal immediate"))
|
||||||
|
} else {
|
||||||
|
err!(self.loc, err_msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Match and consume an Ieee32 immediate.
|
// Match and consume an Ieee32 immediate.
|
||||||
fn match_ieee32(&mut self, err_msg: &str) -> Result<Ieee32> {
|
fn match_ieee32(&mut self, err_msg: &str) -> Result<Ieee32> {
|
||||||
if let Some(Token::Float(text)) = self.token() {
|
if let Some(Token::Float(text)) = self.token() {
|
||||||
@@ -831,8 +844,30 @@ impl<'a> Parser<'a> {
|
|||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::InsertLane |
|
InstructionFormat::InsertLane => {
|
||||||
InstructionFormat::ExtractLane |
|
let lhs = try!(self.match_value("expected SSA value first operand"));
|
||||||
|
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
||||||
|
let lane = try!(self.match_u8("expected lane number"));
|
||||||
|
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
||||||
|
let rhs = try!(self.match_value("expected SSA value last operand"));
|
||||||
|
InstructionData::InsertLane {
|
||||||
|
opcode: opcode,
|
||||||
|
ty: VOID,
|
||||||
|
lane: lane,
|
||||||
|
args: [lhs, rhs],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InstructionFormat::ExtractLane => {
|
||||||
|
let arg = try!(self.match_value("expected SSA value last operand"));
|
||||||
|
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
||||||
|
let lane = try!(self.match_u8("expected lane number"));
|
||||||
|
InstructionData::ExtractLane {
|
||||||
|
opcode: opcode,
|
||||||
|
ty: VOID,
|
||||||
|
lane: lane,
|
||||||
|
arg: arg,
|
||||||
|
}
|
||||||
|
}
|
||||||
InstructionFormat::BranchTable |
|
InstructionFormat::BranchTable |
|
||||||
InstructionFormat::Call => {
|
InstructionFormat::Call => {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
|
|||||||
@@ -15,6 +15,14 @@ ebb0:
|
|||||||
|
|
||||||
; Polymorphic istruction controlled by second operand.
|
; Polymorphic istruction controlled by second operand.
|
||||||
function select() {
|
function select() {
|
||||||
ebb0(vx0: i32, vx1:i32, vx2: b1):
|
ebb0(vx0: i32, vx1: i32, vx2: b1):
|
||||||
v0 = select vx2, vx0, vx1
|
v0 = select vx2, vx0, vx1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Lane indexes.
|
||||||
|
function lanes() {
|
||||||
|
ebb0:
|
||||||
|
v0 = iconst.i32x4 2
|
||||||
|
v1 = extractlane v0, 3
|
||||||
|
v2 = insertlane v0, 1, v1
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,3 +14,10 @@ function select() {
|
|||||||
ebb0(vx0: i32, vx1: i32, vx2: b1):
|
ebb0(vx0: i32, vx1: i32, vx2: b1):
|
||||||
v0 = select vx2, vx0, vx1
|
v0 = select vx2, vx0, vx1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function lanes() {
|
||||||
|
ebb0:
|
||||||
|
v0 = iconst.i32x4 2
|
||||||
|
v1 = extractlane v0, 3
|
||||||
|
v2 = insertlane v0, 1, v1
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user