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

ruby-changes:73121

From: Maxime <ko1@a...>
Date: Tue, 30 Aug 2022 00:53:35 +0900 (JST)
Subject: [ruby-changes:73121] a1b8c94738 (master): * Arm64 Beginnings (https://github.com/Shopify/ruby/pull/291)

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

From a1b8c947380716a5ffca2b1888a6310e8132b00c Mon Sep 17 00:00:00 2001
From: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@s...>
Date: Wed, 15 Jun 2022 13:10:13 -0400
Subject: * Arm64 Beginnings (https://github.com/Shopify/ruby/pull/291)

* Initial setup for aarch64

* ADDS and SUBS

* ADD and SUB for immediates

* Revert moved code

* Documentation

* Rename Arm64* to A64*

* Comments on shift types

* Share sig_imm_size and unsig_imm_size
---
 yjit/src/asm/arm64/README.md                       |  18 ++
 .../asm/arm64/inst/data_processing_immediate.rs    | 198 ++++++++++++++++++++
 .../src/asm/arm64/inst/data_processing_register.rs | 202 +++++++++++++++++++++
 yjit/src/asm/arm64/inst/family.rs                  |  34 ++++
 yjit/src/asm/arm64/inst/mod.rs                     |  32 ++++
 yjit/src/asm/arm64/inst/sf.rs                      |  19 ++
 yjit/src/asm/arm64/mod.rs                          |   4 +
 yjit/src/asm/arm64/opnd.rs                         | 159 ++++++++++++++++
 yjit/src/asm/mod.rs                                |  73 ++++++++
 yjit/src/asm/x86_64/mod.rs                         |  46 +----
 yjit/src/asm/x86_64/tests.rs                       |  12 --
 yjit/src/backend/arm64/mod.rs                      |  63 +++++++
 yjit/src/backend/ir.rs                             |   4 +-
 13 files changed, 810 insertions(+), 54 deletions(-)
 create mode 100644 yjit/src/asm/arm64/README.md
 create mode 100644 yjit/src/asm/arm64/inst/data_processing_immediate.rs
 create mode 100644 yjit/src/asm/arm64/inst/data_processing_register.rs
 create mode 100644 yjit/src/asm/arm64/inst/family.rs
 create mode 100644 yjit/src/asm/arm64/inst/mod.rs
 create mode 100644 yjit/src/asm/arm64/inst/sf.rs
 create mode 100644 yjit/src/asm/arm64/mod.rs
 create mode 100644 yjit/src/asm/arm64/opnd.rs
 create mode 100644 yjit/src/backend/arm64/mod.rs

diff --git a/yjit/src/asm/arm64/README.md b/yjit/src/asm/arm64/README.md
new file mode 100644
index 0000000000..3d0ec57d34
--- /dev/null
+++ b/yjit/src/asm/arm64/README.md
@@ -0,0 +1,18 @@ https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/README.md#L1
+# Arm64
+
+This module is responsible for encoding YJIT operands into an appropriate Arm64 encoding.
+
+## Architecture
+
+Every instruction in the Arm64 instruction set is 32 bits wide and is represented in little-endian order. Because they're all going to the same size, we represent each instruction by a struct that implements `From<T> for u32`, which contains the mechanism for encoding each instruction.
+
+Generally each set of instructions falls under a certain family (like data processing -- register). These instructions are encoded similarly, so we group them into their own submodules. The encoding for each type is shown in the documentation for the struct that ends up being created.
+
+In general each set of bytes inside of the struct has either a direct value (usually a `u8`/`u16`) or some kind of `enum` that can be converted directly into a `u32`.
+
+## Helpful links
+
+* [Arm A64 Instruction Set Architecture](https://developer.arm.com/documentation/ddi0596/2021-12?lang=en) Official documentation
+* [armconverter.com](https://armconverter.com/) A website that encodes Arm assembly syntax
+* [hatstone](https://github.com/tenderlove/hatstone) A wrapper around the Capstone disassembler written in Ruby
+* [onlinedisassembler.com](https://onlinedisassembler.com/odaweb/) A web-based disassembler
diff --git a/yjit/src/asm/arm64/inst/data_processing_immediate.rs b/yjit/src/asm/arm64/inst/data_processing_immediate.rs
new file mode 100644
index 0000000000..12498848b2
--- /dev/null
+++ b/yjit/src/asm/arm64/inst/data_processing_immediate.rs
@@ -0,0 +1,198 @@ https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/data_processing_immediate.rs#L1
+use super::{
+    super::opnd::*,
+    family::Family,
+    sf::Sf
+};
+
+/// The operation being performed by this instruction.
+enum Op {
+    Add = 0b0,
+    Sub = 0b1
+}
+
+// Whether or not to update the flags when this instruction is performed.
+enum S {
+    LeaveFlags = 0b0,
+    UpdateFlags = 0b1
+}
+
+/// How much to shift the immediate by.
+enum Shift {
+    LSL0 = 0b0, // no shift
+    LSL12 = 0b1 // logical shift left by 12 bits
+}
+
+/// The struct that represents an A64 data processing -- immediate instruction
+/// that can be encoded.
+///
+/// Add/subtract (immediate)
+/// +-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
+/// | 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 |
+/// |           1    0  0  0  1    0                                                                                |
+/// | sf op  S                       sh imm12.................................... rn.............. rd.............. |
+/// +-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
+///
+pub struct DataProcessingImmediate {
+    /// Whether or not this instruction is operating on 64-bit operands.
+    sf: Sf,
+
+    /// The opcode for this instruction.
+    op: Op,
+
+    /// Whether or not to update the flags when this instruction is performed.
+    s: S,
+
+    /// How much to shift the immediate by.
+    shift: Shift,
+
+    /// The value of the immediate.
+    imm12: u16,
+
+    /// The register number of the first operand register.
+    rn: u8,
+
+    /// The register number of the destination register.
+    rd: u8
+}
+
+impl DataProcessingImmediate {
+    /// ADD (immediate)
+    /// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/ADD--immediate---Add--immediate--?lang=en
+    pub fn add(rd: &A64Opnd, rn: &A64Opnd, imm12: &A64Opnd) -> Self {
+        let (rd, rn, imm12) = Self::unwrap(rd, rn, imm12);
+
+        Self {
+            sf: rd.num_bits.into(),
+            op: Op::Add,
+            s: S::LeaveFlags,
+            shift: Shift::LSL0,
+            imm12: imm12.value as u16,
+            rn: rn.reg_no,
+            rd: rd.reg_no
+        }
+    }
+
+    /// ADDS (immediate, set flags)
+    /// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/ADDS--immediate---Add--immediate---setting-flags-?lang=en
+    pub fn adds(rd: &A64Opnd, rn: &A64Opnd, imm12: &A64Opnd) -> Self {
+        let (rd, rn, imm12) = Self::unwrap(rd, rn, imm12);
+
+        Self {
+            sf: rd.num_bits.into(),
+            op: Op::Add,
+            s: S::UpdateFlags,
+            shift: Shift::LSL0,
+            imm12: imm12.value as u16,
+            rn: rn.reg_no,
+            rd: rd.reg_no
+        }
+    }
+
+    /// SUB (immediate)
+    /// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/SUB--immediate---Subtract--immediate--?lang=en
+    pub fn sub(rd: &A64Opnd, rn: &A64Opnd, imm12: &A64Opnd) -> Self {
+        let (rd, rn, imm12) = Self::unwrap(rd, rn, imm12);
+
+        Self {
+            sf: rd.num_bits.into(),
+            op: Op::Sub,
+            s: S::LeaveFlags,
+            shift: Shift::LSL0,
+            imm12: imm12.value as u16,
+            rn: rn.reg_no,
+            rd: rd.reg_no
+        }
+    }
+
+    /// SUBS (immediate, set flags)
+    /// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/SUBS--immediate---Subtract--immediate---setting-flags-?lang=en
+    pub fn subs(rd: &A64Opnd, rn: &A64Opnd, imm12: &A64Opnd) -> Self {
+        let (rd, rn, imm12) = Self::unwrap(rd, rn, imm12);
+
+        Self {
+            sf: rd.num_bits.into(),
+            op: Op::Sub,
+            s: S::UpdateFlags,
+            shift: Shift::LSL0,
+            imm12: imm12.value as u16,
+            rn: rn.reg_no,
+            rd: rd.reg_no
+        }
+    }
+
+    /// Extract out two registers and an immediate from the given operands.
+    /// Panic if any of the operands do not match the expected type or size.
+    fn unwrap<'a>(rd: &'a A64Opnd, rn: &'a A64Opnd, imm12: &'a A64Opnd) -> (&'a A64Reg, &'a A64Reg, &'a A64UImm) {
+        match (rd, rn, imm12) {
+            (A64Opnd::Reg(rd), A64Opnd::Reg(rn), A64Opnd::UImm(imm12)) => {
+                assert!(rd.num_bits == rn.num_bits, "Both rd and rn operands to a data processing immediate instruction must be of the same size.");
+                assert!(imm12.num_bits <= 12, "The immediate operand to a data processing immediate instruction must be 12 bits or less.");
+                (rd, rn, imm12)
+            },
+            _ => {
+                panic!("Expected 2 register operands and an immediate operand for a data processing immediate instruction.");
+            }
+        }
+    }
+}
+
+impl From<DataProcessingImmediate> for u32 {
+    /// Convert a data processing instruction into a 32-bit value.
+    fn from(inst: DataProcessingImmediate) -> Self {
+        0
+        | (inst.sf as u32).wrapping_shl(31)
+        | (inst.op as u32).wrapping_shl(30)
+        | (inst.s as u32).wrapping_shl(29)
+        | (Family::DataProcessingImmediate as u32).wrapping_shl(25)
+        | (0b1 << 24)
+        | (inst.shift as u32).wrapping_shl(22)
+        | (inst.imm12 as u32).wrapping_shl(10)
+        | (inst.rn as u32).wrapping_shl(5)
+        | inst.rd as u32
+    }
+}
+
+impl From<DataProcessingImmediate> for [u8; 4] {
+    /// Convert a data processing instruction into a 4 byte array.
+    fn from(inst: DataProcessingImmediate) -> [u8; 4] {
+        let result: u32 = inst.into();
+        result.to_le_bytes()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_add() {
+        let uimm12 = A64Opnd::new_uimm(7);
+        let inst = DataProcessingImmediate::add(&X0, &X1, &uimm12);
+        let result: u32 = inst.into();
+        assert_eq!(0x91001c20, result);
+    }
+
+    #[test]
+    fn test_adds() {
+        let uimm12 = A64Opnd::new_uimm(7);
+        let inst = DataProcessingImmediate::adds(&X0, &X1, &uimm12);
+   (... truncated)

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

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