summaryrefslogtreecommitdiff
path: root/yjit/src/asm/arm64/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'yjit/src/asm/arm64/mod.rs')
-rw-r--r--yjit/src/asm/arm64/mod.rs22
1 files changed, 22 insertions, 0 deletions
diff --git a/yjit/src/asm/arm64/mod.rs b/yjit/src/asm/arm64/mod.rs
index 6eebccaa61..3feee65197 100644
--- a/yjit/src/asm/arm64/mod.rs
+++ b/yjit/src/asm/arm64/mod.rs
@@ -272,6 +272,23 @@ pub fn cmp(cb: &mut CodeBlock, rn: A64Opnd, rm: A64Opnd) {
cb.write_bytes(&bytes);
}
+/// CSEL - conditionally select between two registers
+pub fn csel(cb: &mut CodeBlock, rd: A64Opnd, rn: A64Opnd, rm: A64Opnd, cond: u8) {
+ let bytes: [u8; 4] = match (rd, rn, rm) {
+ (A64Opnd::Reg(rd), A64Opnd::Reg(rn), A64Opnd::Reg(rm)) => {
+ assert!(
+ rd.num_bits == rn.num_bits && rn.num_bits == rm.num_bits,
+ "All operands must be of the same size."
+ );
+
+ Conditional::csel(rd.reg_no, rn.reg_no, rm.reg_no, cond, rd.num_bits).into()
+ },
+ _ => panic!("Invalid operand combination to csel instruction."),
+ };
+
+ cb.write_bytes(&bytes);
+}
+
/// LDADDAL - atomic add with acquire and release semantics
pub fn ldaddal(cb: &mut CodeBlock, rs: A64Opnd, rt: A64Opnd, rn: A64Opnd) {
let bytes: [u8; 4] = match (rs, rt, rn) {
@@ -761,6 +778,11 @@ mod tests {
}
#[test]
+ fn test_csel() {
+ check_bytes("6a018c9a", |cb| csel(cb, X10, X11, X12, Condition::EQ));
+ }
+
+ #[test]
fn test_ldaddal() {
check_bytes("8b01eaf8", |cb| ldaddal(cb, X10, X11, X12));
}