diff options
Diffstat (limited to 'yjit/src/asm/arm64/mod.rs')
-rw-r--r-- | yjit/src/asm/arm64/mod.rs | 22 |
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)); } |