Add legalization helper instructions.
The isplit_lohi instruction breaks an integer into two halves. This will typically be used to get the two halves of an `i64` value on 32-bit CPUs. The iconcat_lohi is the reverse operation. It reconstructs the `i64` from the low and high bits.
This commit is contained in:
@@ -823,6 +823,14 @@ Conversion operations
|
|||||||
.. autoinst:: fcvt_from_uint
|
.. autoinst:: fcvt_from_uint
|
||||||
.. autoinst:: fcvt_from_sint
|
.. autoinst:: fcvt_from_sint
|
||||||
|
|
||||||
|
Legalization operations
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
These instructions are used as helpers when legalizing types and operations for
|
||||||
|
the target ISA.
|
||||||
|
|
||||||
|
.. autoinst:: isplit_lohi
|
||||||
|
.. autoinst:: iconcat_lohi
|
||||||
|
|
||||||
Base instruction group
|
Base instruction group
|
||||||
======================
|
======================
|
||||||
|
|||||||
@@ -1105,4 +1105,42 @@ fcvt_from_sint = Instruction(
|
|||||||
""",
|
""",
|
||||||
ins=x, outs=a)
|
ins=x, outs=a)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Legalization helper instructions.
|
||||||
|
#
|
||||||
|
|
||||||
|
WideInt = TypeVar(
|
||||||
|
'WideInt', 'A scalar integer type from `i16` upwards',
|
||||||
|
ints=(16, 64))
|
||||||
|
x = Operand('x', WideInt)
|
||||||
|
lo = Operand(
|
||||||
|
'lo', WideInt.half_width(), 'The low bits of `x`')
|
||||||
|
hi = Operand(
|
||||||
|
'hi', WideInt.half_width(), 'The high bits of `x`')
|
||||||
|
|
||||||
|
isplit_lohi = Instruction(
|
||||||
|
'isplit_lohi', r"""
|
||||||
|
Split a scalar integer into low and high parts.
|
||||||
|
|
||||||
|
Returns the low half of `x` and the high half of `x` as two independent
|
||||||
|
values.
|
||||||
|
""",
|
||||||
|
ins=x, outs=(lo, hi))
|
||||||
|
|
||||||
|
|
||||||
|
NarrowInt = TypeVar(
|
||||||
|
'NarrowInt', 'A scalar integer type up to `i32`',
|
||||||
|
ints=(8, 32))
|
||||||
|
lo = Operand('lo', NarrowInt)
|
||||||
|
hi = Operand('hi', NarrowInt)
|
||||||
|
a = Operand(
|
||||||
|
'a', NarrowInt.double_width(),
|
||||||
|
doc='The concatenation of `lo` and `hi`')
|
||||||
|
|
||||||
|
iconcat_lohi = Instruction(
|
||||||
|
'iconcat_lohi', r"""
|
||||||
|
Concatenate low and high bits to form a larger integer type.
|
||||||
|
""",
|
||||||
|
ins=(lo, hi), outs=a)
|
||||||
|
|
||||||
instructions.close()
|
instructions.close()
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ UnaryImm = InstructionFormat(imm64)
|
|||||||
UnaryIeee32 = InstructionFormat(ieee32)
|
UnaryIeee32 = InstructionFormat(ieee32)
|
||||||
UnaryIeee64 = InstructionFormat(ieee64)
|
UnaryIeee64 = InstructionFormat(ieee64)
|
||||||
UnaryImmVector = InstructionFormat(immvector)
|
UnaryImmVector = InstructionFormat(immvector)
|
||||||
|
UnarySplit = InstructionFormat(value, multiple_results=True)
|
||||||
|
|
||||||
Binary = InstructionFormat(value, value)
|
Binary = InstructionFormat(value, value)
|
||||||
BinaryImm = InstructionFormat(value, imm64)
|
BinaryImm = InstructionFormat(value, imm64)
|
||||||
|
|||||||
@@ -120,6 +120,12 @@ pub enum InstructionData {
|
|||||||
opcode: Opcode,
|
opcode: Opcode,
|
||||||
ty: Type, // TBD: imm: Box<ImmVectorData>
|
ty: Type, // TBD: imm: Box<ImmVectorData>
|
||||||
},
|
},
|
||||||
|
UnarySplit {
|
||||||
|
opcode: Opcode,
|
||||||
|
ty: Type,
|
||||||
|
second_result: Value,
|
||||||
|
arg: Value,
|
||||||
|
},
|
||||||
Binary {
|
Binary {
|
||||||
opcode: Opcode,
|
opcode: Opcode,
|
||||||
ty: Type,
|
ty: Type,
|
||||||
|
|||||||
@@ -185,6 +185,7 @@ fn write_instruction(w: &mut Write,
|
|||||||
UnaryIeee32 { imm, .. } => writeln!(w, " {}", imm),
|
UnaryIeee32 { imm, .. } => writeln!(w, " {}", imm),
|
||||||
UnaryIeee64 { imm, .. } => writeln!(w, " {}", imm),
|
UnaryIeee64 { imm, .. } => writeln!(w, " {}", imm),
|
||||||
UnaryImmVector { .. } => writeln!(w, " [...]"),
|
UnaryImmVector { .. } => writeln!(w, " [...]"),
|
||||||
|
UnarySplit { arg, .. } => writeln!(w, " {}", arg),
|
||||||
Binary { args, .. } => writeln!(w, " {}, {}", args[0], args[1]),
|
Binary { args, .. } => writeln!(w, " {}, {}", args[0], args[1]),
|
||||||
BinaryImm { arg, imm, .. } => writeln!(w, " {}, {}", arg, imm),
|
BinaryImm { arg, imm, .. } => writeln!(w, " {}, {}", arg, imm),
|
||||||
BinaryImmRev { imm, arg, .. } => writeln!(w, " {}, {}", imm, arg),
|
BinaryImmRev { imm, arg, .. } => writeln!(w, " {}, {}", imm, arg),
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ impl Context {
|
|||||||
InstructionData::UnaryImmVector { .. } => {}
|
InstructionData::UnaryImmVector { .. } => {}
|
||||||
|
|
||||||
InstructionData::Unary { ref mut arg, .. } |
|
InstructionData::Unary { ref mut arg, .. } |
|
||||||
|
InstructionData::UnarySplit { ref mut arg, .. } |
|
||||||
InstructionData::BinaryImm { ref mut arg, .. } |
|
InstructionData::BinaryImm { ref mut arg, .. } |
|
||||||
InstructionData::BinaryImmRev { ref mut arg, .. } |
|
InstructionData::BinaryImmRev { ref mut arg, .. } |
|
||||||
InstructionData::ExtractLane { ref mut arg, .. } |
|
InstructionData::ExtractLane { ref mut arg, .. } |
|
||||||
@@ -1013,6 +1014,14 @@ impl<'a> Parser<'a> {
|
|||||||
InstructionFormat::UnaryImmVector => {
|
InstructionFormat::UnaryImmVector => {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
InstructionFormat::UnarySplit => {
|
||||||
|
InstructionData::UnarySplit {
|
||||||
|
opcode: opcode,
|
||||||
|
ty: VOID,
|
||||||
|
second_result: NO_VALUE,
|
||||||
|
arg: try!(self.match_value("expected SSA value operand")),
|
||||||
|
}
|
||||||
|
}
|
||||||
InstructionFormat::Binary => {
|
InstructionFormat::Binary => {
|
||||||
let lhs = try!(self.match_value("expected SSA value first operand"));
|
let lhs = try!(self.match_value("expected SSA value first operand"));
|
||||||
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
try!(self.match_token(Token::Comma, "expected ',' between operands"));
|
||||||
|
|||||||
Reference in New Issue
Block a user