[前][次][番号順一覧][スレッド一覧]

ruby-changes:73156

From: Kevin <ko1@a...>
Date: Tue, 30 Aug 2022 00:57:23 +0900 (JST)
Subject: [ruby-changes:73156] 27dd43bbc5 (master): TST, CMP, AND/ANDS with registers (https://github.com/Shopify/ruby/pull/301)

https://git.ruby-lang.org/ruby.git/commit/?id=27dd43bbc5

From 27dd43bbc52eb2040d46370fb0170d4d420223e1 Mon Sep 17 00:00:00 2001
From: Kevin Newton <kddnewton@g...>
Date: Fri, 17 Jun 2022 17:26:13 -0400
Subject: TST, CMP, AND/ANDS with registers
 (https://github.com/Shopify/ruby/pull/301)

* Add TST instruction and AND/ANDS entrypoints for immediates

* TST/AND/ANDS for registers

* CMP instruction
---
 yjit/src/asm/arm64/inst/data_imm.rs    |  13 ++++
 yjit/src/asm/arm64/inst/data_reg.rs    |  13 ++++
 yjit/src/asm/arm64/inst/logical_imm.rs |  13 ++++
 yjit/src/asm/arm64/inst/logical_reg.rs | 125 ++++++++++++++++++++++++++++++++
 yjit/src/asm/arm64/inst/mod.rs         | 126 +++++++++++++++++++++++++++++++++
 5 files changed, 290 insertions(+)
 create mode 100644 yjit/src/asm/arm64/inst/logical_reg.rs

diff --git a/yjit/src/asm/arm64/inst/data_imm.rs b/yjit/src/asm/arm64/inst/data_imm.rs
index 0d0a6ff325..950cf3421e 100644
--- a/yjit/src/asm/arm64/inst/data_imm.rs
+++ b/yjit/src/asm/arm64/inst/data_imm.rs
@@ -80,6 +80,12 @@ impl DataImm { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/data_imm.rs#L80
         }
     }
 
+    /// CMP (immediate)
+    /// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/CMP--immediate---Compare--immediate---an-alias-of-SUBS--immediate--?lang=en
+    pub fn cmp(rn: u8, imm12: u16, num_bits: u8) -> Self {
+        Self::subs(31, rn, imm12, num_bits)
+    }
+
     /// SUB (immediate)
     /// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/SUB--immediate---Subtract--immediate--?lang=en
     pub fn sub(rd: u8, rn: u8, imm12: u16, num_bits: u8) -> Self {
@@ -156,6 +162,13 @@ mod tests { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/data_imm.rs#L162
         assert_eq!(0xb1001c20, result);
     }
 
+    #[test]
+    fn test_cmp() {
+        let inst = DataImm::cmp(0, 7, 64);
+        let result: u32 = inst.into();
+        assert_eq!(0xf1001c1f, result);
+    }
+
     #[test]
     fn test_sub() {
         let inst = DataImm::sub(0, 1, 7, 64);
diff --git a/yjit/src/asm/arm64/inst/data_reg.rs b/yjit/src/asm/arm64/inst/data_reg.rs
index 8635ab804b..40f026d1fd 100644
--- a/yjit/src/asm/arm64/inst/data_reg.rs
+++ b/yjit/src/asm/arm64/inst/data_reg.rs
@@ -86,6 +86,12 @@ impl DataReg { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/data_reg.rs#L86
         }
     }
 
+    /// CMP (shifted register)
+    /// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/CMP--shifted-register---Compare--shifted-register---an-alias-of-SUBS--shifted-register--?lang=en
+    pub fn cmp(rn: u8, rm: u8, num_bits: u8) -> Self {
+        Self::subs(31, rn, rm, num_bits)
+    }
+
     /// SUB (shifted register)
     /// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/SUB--shifted-register---Subtract--shifted-register--?lang=en
     pub fn sub(rd: u8, rn: u8, rm: u8, num_bits: u8) -> Self {
@@ -165,6 +171,13 @@ mod tests { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/data_reg.rs#L171
         assert_eq!(0xab020020, result);
     }
 
+    #[test]
+    fn test_cmp() {
+        let inst = DataReg::cmp(0, 1, 64);
+        let result: u32 = inst.into();
+        assert_eq!(0xeb01001f, result);
+    }
+
     #[test]
     fn test_sub() {
         let inst = DataReg::sub(0, 1, 2, 64);
diff --git a/yjit/src/asm/arm64/inst/logical_imm.rs b/yjit/src/asm/arm64/inst/logical_imm.rs
index 63a4556d85..88de8ba4a1 100644
--- a/yjit/src/asm/arm64/inst/logical_imm.rs
+++ b/yjit/src/asm/arm64/inst/logical_imm.rs
@@ -49,6 +49,12 @@ impl LogicalImm { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/logical_imm.rs#L49
     pub fn ands(rd: u8, rn: u8, imm: BitmaskImmediate, num_bits: u8) -> Self {
         Self { rd, rn, imm, opc: Opc::Ands, sf: num_bits.into() }
     }
+
+    /// TST (immediate)
+    /// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/TST--immediate---Test-bits--immediate---an-alias-of-ANDS--immediate--?lang=en
+    pub fn tst(rn: u8, imm: BitmaskImmediate, num_bits: u8) -> Self {
+        Self::ands(31, rn, imm, num_bits)
+    }
 }
 
 /// https://developer.arm.com/documentation/ddi0602/2022-03/Index-by-Encoding/Data-Processing----Immediate?lang=en#log_imm
@@ -94,4 +100,11 @@ mod tests { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/logical_imm.rs#L100
         let result: u32 = inst.into();
         assert_eq!(0xf2400820, result);
     }
+
+    #[test]
+    fn test_tst() {
+        let inst = LogicalImm::tst(1, 7.try_into().unwrap(), 64);
+        let result: u32 = inst.into();
+        assert_eq!(0xf240083f, result);
+    }
 }
diff --git a/yjit/src/asm/arm64/inst/logical_reg.rs b/yjit/src/asm/arm64/inst/logical_reg.rs
new file mode 100644
index 0000000000..929d80b1a7
--- /dev/null
+++ b/yjit/src/asm/arm64/inst/logical_reg.rs
@@ -0,0 +1,125 @@ https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/logical_reg.rs#L1
+use super::sf::Sf;
+
+/// The type of shift to perform on the second operand register.
+enum Shift {
+    LSL = 0b00, // logical shift left (unsigned)
+    LSR = 0b01, // logical shift right (unsigned)
+    ASR = 0b10, // arithmetic shift right (signed)
+    ROR = 0b11  // rotate right (unsigned)
+}
+
+// Which operation to perform.
+enum Opc {
+    /// The AND operation.
+    And = 0b00,
+
+    /// The ANDS operation.
+    Ands = 0b11
+}
+
+/// The struct that represents an A64 logical register instruction that can be
+/// encoded.
+///
+/// AND/ANDS (shifted register)
+/// +-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
+/// | 31 30 29 28 | 27 26 25 24 | 23 22 21 20 | 19 18 17 16 | 15 14 13 12 | 11 10 09 08 | 07 06 05 04 | 03 02 01 00 |
+/// |           0    1  0  1  0          0                                                                          |
+/// | sf opc..                    shift    rm..............   imm6............... rn.............. rd.............. |
+/// +-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
+///
+pub struct LogicalReg {
+    /// The register number of the destination register.
+    rd: u8,
+
+    /// The register number of the first operand register.
+    rn: u8,
+
+    /// The amount to shift the second operand register.
+    imm6: u8,
+
+    /// The register number of the second operand register.
+    rm: u8,
+
+    /// The type of shift to perform on the second operand register.
+    shift: Shift,
+
+    /// The opcode for this instruction.
+    opc: Opc,
+
+    /// Whether or not this instruction is operating on 64-bit operands.
+    sf: Sf
+}
+
+impl LogicalReg {
+    /// AND (shifted register)
+    /// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/AND--shifted-register---Bitwise-AND--shifted-register--?lang=en
+    pub fn and(rd: u8, rn: u8, rm: u8, num_bits: u8) -> Self {
+        Self { rd, rn, imm6: 0, rm, shift: Shift::LSL, opc: Opc::And, sf: num_bits.into() }
+    }
+
+    /// ANDS (shifted register)
+    /// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/ANDS--shifted-register---Bitwise-AND--shifted-register---setting-flags-?lang=en
+    pub fn ands(rd: u8, rn: u8, rm: u8, num_bits: u8) -> Self {
+        Self { rd, rn, imm6: 0, rm, shift: Shift::LSL, opc: Opc::Ands, sf: num_bits.into() }
+    }
+
+    /// TST (shifted register)
+    /// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/TST--shifted-register---Test--shifted-register---an-alias-of-ANDS--shifted-register--?lang=en
+    pub fn tst(rn: u8, rm: u8, num_bits: u8) -> Self {
+        Self { rd: 31, rn, imm6: 0, rm, shift: Shift::LSL, opc: Opc::Ands, sf: num_bits.into() }
+    }
+}
+
+/// https://developer.arm.com/documentation/ddi0602/2022-03/Index-by-Encoding/Data-Processing----Register?lang=en
+const FAMILY: u32 = 0b0101;
+
+impl From<LogicalReg> for u32 {
+    /// Convert an instruction into a 32-bit value.
+    fn from(inst: LogicalReg) -> Self {
+        let imm6 = (inst.imm6 as u32) & ((1 << 6) - 1);
+
+        0
+        | ((inst.sf as u32) << 31)
+        | ((inst.opc as u32) << 29)
+        | (FAMILY << 25)
+        | ((inst.shift as u32) << 22)
+        | ((inst.rm as u32) << 16)
+        | (imm6 << 10)
+        | ((inst.rn as u32) << 5)
+        | inst.rd as u32
+    }
+}
+
+impl From<LogicalReg> for [u8; 4] {
+    /// Convert an instruction into a 4 byte array.
+    fn from(inst: LogicalReg) -> [u8; 4] {
+        let result: u32 = inst.into();
+        result.to_le_bytes()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_and() {
+        let inst = LogicalReg::and(0, 1, 2, 64);
+        let result: u32 = inst.into();
+        assert_eq!(0x8a020020, result);
+    }
+
+    #[test]
+    fn test_ands() {
+        let inst = LogicalReg::ands(0, 1, 2, 64);
+        let result: u32 = inst.into();
+        assert_eq!(0xea020020, result);
+    }
+
+    #[test]
+    fn test_tst() {
+        let inst = LogicalReg::tst(0, 1, 64);
+        let result: u32 = inst.into();
+        assert_eq!(0xea01001f, result);
+    }
+}
diff --git a/yjit/src/asm/arm64/inst/mod.rs b/yjit/src/asm/arm64/inst/mod.rs
index 83cdd26d1d..7d05f28604 100644
--- a/yjit/src/asm/arm64/inst/mod.rs
+++ b/yjit/src/asm/arm64/inst/mod.rs
@@ -6,6 +6,7 @@ mod data_imm; https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/mod.rs#L6
 mod data_reg;
 mod load;
 mod logical_imm;
+mod logical_reg;
 mod mov;
 mod sf;
 mod store;
@@ -18,6 +19,8 @@ use call::Call; https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/mod.rs#L19
 use data_imm::DataImm;
 use data_reg::DataReg;
 use load::Load;
+use logical_imm::LogicalImm;
+use logical_reg::LogicalReg;
 use mov::Mov;
 use store::Store;
 
@@ -85,6 +88,50 @@ pub fn adds(cb: &mut CodeBlock, rd: A64Opnd, rn: A64Opnd, rm: A64Opnd) { https://github.com/ruby/ruby (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]