aboutsummaryrefslogtreecommitdiffstats
path: root/yjit/src/backend
diff options
context:
space:
mode:
authorKevin Newton <kddnewton@gmail.com>2022-08-11 08:32:06 -0400
committerTakashi Kokubun <takashikkbn@gmail.com>2022-08-29 08:47:10 -0700
commit7f4ab24f2b99c87874a5540a55026ea5a3d43d3e (patch)
tree9430ef0ce2828c5f4621d2f4f2ce4735612f9ad6 /yjit/src/backend
parent4d811d7a2b92d110e3e70cb77e5f499acfa7112a (diff)
downloadruby-7f4ab24f2b99c87874a5540a55026ea5a3d43d3e.tar.gz
Op::Xor for backend IR (https://github.com/Shopify/ruby/pull/397)
Diffstat (limited to 'yjit/src/backend')
-rw-r--r--yjit/src/backend/arm64/mod.rs15
-rw-r--r--yjit/src/backend/ir.rs5
-rw-r--r--yjit/src/backend/x86_64/mod.rs6
3 files changed, 24 insertions, 2 deletions
diff --git a/yjit/src/backend/arm64/mod.rs b/yjit/src/backend/arm64/mod.rs
index 440c4368c5..2cd893923a 100644
--- a/yjit/src/backend/arm64/mod.rs
+++ b/yjit/src/backend/arm64/mod.rs
@@ -216,7 +216,7 @@ impl Assembler
}
}
},
- Op::And | Op::Or => {
+ Op::And | Op::Or | Op::Xor => {
match (opnds[0], opnds[1]) {
(Opnd::Reg(_), Opnd::Reg(_)) => {
asm.push_insn(insn.op, vec![opnds[0], opnds[1]], insn.target, insn.text, insn.pos_marker);
@@ -615,6 +615,9 @@ impl Assembler
Op::Or => {
orr(cb, insn.out.into(), insn.opnds[0].into(), insn.opnds[1].into());
},
+ Op::Xor => {
+ eor(cb, insn.out.into(), insn.opnds[0].into(), insn.opnds[1].into());
+ },
Op::Not => {
mvn(cb, insn.out.into(), insn.opnds[0].into());
},
@@ -1085,6 +1088,16 @@ mod tests {
}
#[test]
+ fn test_emit_xor() {
+ let (mut asm, mut cb) = setup_asm();
+
+ let opnd = asm.xor(Opnd::Reg(X0_REG), Opnd::Reg(X1_REG));
+ asm.store(Opnd::mem(64, Opnd::Reg(X2_REG), 0), opnd);
+
+ asm.compile_with_num_regs(&mut cb, 1);
+ }
+
+ #[test]
#[cfg(feature = "disasm")]
fn test_simple_disasm() -> std::result::Result<(), capstone::Error> {
// Test drive Capstone with simple input
diff --git a/yjit/src/backend/ir.rs b/yjit/src/backend/ir.rs
index 2dfb859fe9..ef8cd5e872 100644
--- a/yjit/src/backend/ir.rs
+++ b/yjit/src/backend/ir.rs
@@ -63,6 +63,10 @@ pub enum Op
// binary OR operation.
Or,
+ // This is the same as the OP_ADD instruction, except that it performs the
+ // binary XOR operation.
+ Xor,
+
// Perform the NOT operation on an individual operand, and return the result
// as a new operand. This operand can then be used as the operand on another
// instruction.
@@ -992,6 +996,7 @@ def_push_2_opnd!(add, Op::Add);
def_push_2_opnd!(sub, Op::Sub);
def_push_2_opnd!(and, Op::And);
def_push_2_opnd!(or, Op::Or);
+def_push_2_opnd!(xor, Op::Xor);
def_push_1_opnd!(not, Op::Not);
def_push_2_opnd!(lshift, Op::LShift);
def_push_2_opnd!(rshift, Op::RShift);
diff --git a/yjit/src/backend/x86_64/mod.rs b/yjit/src/backend/x86_64/mod.rs
index 417474ee68..d474c9fe59 100644
--- a/yjit/src/backend/x86_64/mod.rs
+++ b/yjit/src/backend/x86_64/mod.rs
@@ -139,7 +139,7 @@ impl Assembler
}).collect();
match insn.op {
- Op::Add | Op::Sub | Op::And | Op::Cmp | Op::Or | Op::Test => {
+ Op::Add | Op::Sub | Op::And | Op::Cmp | Op::Or | Op::Test | Op::Xor => {
let (opnd0, opnd1) = match (insn.opnds[0], insn.opnds[1]) {
(Opnd::Mem(_), Opnd::Mem(_)) => {
(asm.load(opnds[0]), asm.load(opnds[1]))
@@ -328,6 +328,10 @@ impl Assembler
or(cb, insn.opnds[0].into(), insn.opnds[1].into());
},
+ Op::Xor => {
+ xor(cb, insn.opnds[0].into(), insn.opnds[1].into());
+ },
+
Op::Not => {
not(cb, insn.opnds[0].into())
},