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

ruby-changes:73193

From: Kevin <ko1@a...>
Date: Tue, 30 Aug 2022 01:00:04 +0900 (JST)
Subject: [ruby-changes:73193] 0da253e72c (master): Port print_int to the new backend (https://github.com/Shopify/ruby/pull/321)

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

From 0da253e72cc80c1dbf8517f5217b59a64ec0f44e Mon Sep 17 00:00:00 2001
From: Kevin Newton <kddnewton@g...>
Date: Fri, 15 Jul 2022 16:14:55 -0400
Subject: Port print_int to the new backend
 (https://github.com/Shopify/ruby/pull/321)

* Port print_int to the new backend

* Tests for print_int and print_str
---
 yjit/src/asm/arm64/inst/load.rs |  42 +++++++++++----
 yjit/src/asm/arm64/inst/mod.rs  |   2 +
 yjit/src/asm/arm64/inst/sbfm.rs |  77 ++++++++++++++++++++++++++++
 yjit/src/asm/arm64/mod.rs       |  40 +++++++++++++++
 yjit/src/asm/arm64/opnd.rs      |  64 +++++++++++------------
 yjit/src/backend/arm64/mod.rs   |  28 ++++++++++
 yjit/src/backend/ir.rs          |   5 ++
 yjit/src/backend/x86_64/mod.rs  |   4 ++
 yjit/src/utils.rs               | 110 +++++++++++++++++++++++-----------------
 9 files changed, 284 insertions(+), 88 deletions(-)
 create mode 100644 yjit/src/asm/arm64/inst/sbfm.rs

diff --git a/yjit/src/asm/arm64/inst/load.rs b/yjit/src/asm/arm64/inst/load.rs
index 727dad52f7..b64a6a96ac 100644
--- a/yjit/src/asm/arm64/inst/load.rs
+++ b/yjit/src/asm/arm64/inst/load.rs
@@ -4,6 +4,12 @@ enum Size { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/load.rs#L4
     Size64 = 0b11,
 }
 
+/// The operation to perform for this instruction.
+enum Opc {
+    LDUR = 0b01,
+    LDURSW = 0b10
+}
+
 /// A convenience function so that we can convert the number of bits of an
 /// register operand directly into an Sf enum variant.
 impl From<u8> for Size {
@@ -22,8 +28,8 @@ impl From<u8> for Size { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/load.rs#L28
 /// LDUR
 /// +-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
 /// | 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  1    1  0  0  0    0  1  0                                   0  0                                   |
-/// | size.                                imm9..........................         rn.............. rt.............. |
+/// |        1  1    1  0  0  0          0                                   0  0                                   |
+/// | size.                       opc..       imm9..........................         rn.............. rt.............. |
 /// +-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
 ///
 pub struct Load {
@@ -36,6 +42,9 @@ pub struct Load { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/load.rs#L42
     /// The optional signed immediate byte offset from the base register.
     imm9: i16,
 
+    /// The operation to perform for this instruction.
+    opc: Opc,
+
     /// The size of the operands being operated on.
     size: Size
 }
@@ -44,12 +53,13 @@ impl Load { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/load.rs#L53
     /// LDUR (load register, unscaled)
     /// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDUR--Load-Register--unscaled--?lang=en
     pub fn ldur(rt: u8, rn: u8, imm9: i16, num_bits: u8) -> Self {
-        Self {
-            rt,
-            rn,
-            imm9,
-            size: num_bits.into()
-        }
+        Self { rt, rn, imm9, opc: Opc::LDUR, size: num_bits.into() }
+    }
+
+    /// LDURSW (load register, unscaled, signed)
+    /// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDURSW--Load-Register-Signed-Word--unscaled--?lang=en
+    pub fn ldursw(rt: u8, rn: u8, imm9: i16) -> Self {
+        Self { rt, rn, imm9, opc: Opc::LDURSW, size: Size::Size32 }
     }
 }
 
@@ -65,7 +75,7 @@ impl From<Load> for u32 { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/load.rs#L75
         | ((inst.size as u32) << 30)
         | (0b11 << 28)
         | (FAMILY << 25)
-        | (1 << 22)
+        | ((inst.opc as u32) << 22)
         | (imm9 << 12)
         | ((inst.rn as u32) << 5)
         | (inst.rt as u32)
@@ -97,4 +107,18 @@ mod tests { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/load.rs#L107
         let result: u32 = inst.into();
         assert_eq!(0xf847b020, result);
     }
+
+    #[test]
+    fn test_ldursw() {
+        let inst = Load::ldursw(0, 1, 0);
+        let result: u32 = inst.into();
+        assert_eq!(0xb8800020, result);
+    }
+
+    #[test]
+    fn test_ldursw_with_imm() {
+        let inst = Load::ldursw(0, 1, 123);
+        let result: u32 = inst.into();
+        assert_eq!(0xb887b020, result);
+    }
 }
diff --git a/yjit/src/asm/arm64/inst/mod.rs b/yjit/src/asm/arm64/inst/mod.rs
index 752ee64aa3..5d4d252d93 100644
--- a/yjit/src/asm/arm64/inst/mod.rs
+++ b/yjit/src/asm/arm64/inst/mod.rs
@@ -15,6 +15,7 @@ mod logical_reg; https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/mod.rs#L15
 mod mov;
 mod nop;
 mod pc_rel;
+mod sbfm;
 mod shift_imm;
 mod store;
 mod sys_reg;
@@ -33,6 +34,7 @@ pub use logical_reg::LogicalReg; https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/mod.rs#L34
 pub use mov::Mov;
 pub use nop::Nop;
 pub use pc_rel::PCRelative;
+pub use sbfm::SBFM;
 pub use shift_imm::ShiftImm;
 pub use store::Store;
 pub use sys_reg::SysReg;
diff --git a/yjit/src/asm/arm64/inst/sbfm.rs b/yjit/src/asm/arm64/inst/sbfm.rs
new file mode 100644
index 0000000000..4fbb567ed0
--- /dev/null
+++ b/yjit/src/asm/arm64/inst/sbfm.rs
@@ -0,0 +1,77 @@ https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/sbfm.rs#L1
+use super::super::arg::Sf;
+
+/// The struct that represents an A64 signed bitfield move instruction that can
+/// be encoded.
+///
+/// SBFM
+/// +-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
+/// | 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  0  1    0  0  1  1    0                                                                                |
+/// | sf                             N  immr...............   imms............... rn.............. rd.............. |
+/// +-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
+///
+pub struct SBFM {
+    /// The number for the general-purpose register to load the value into.
+    rd: u8,
+
+    /// The number for the general-purpose register to copy from.
+    rn: u8,
+
+    /// The leftmost bit number to be moved from the source.
+    imms: u8,
+
+    // The right rotate amount.
+    immr: u8,
+
+    /// Whether or not this is a 64-bit operation.
+    n: bool,
+
+    /// The size of this operation.
+    sf: Sf
+}
+
+impl SBFM {
+    /// SXTW
+    /// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/SXTW--Sign-Extend-Word--an-alias-of-SBFM-?lang=en
+    pub fn sxtw(rd: u8, rn: u8) -> Self {
+        Self { rd, rn, immr: 0, imms: 31, n: true, sf: Sf::Sf64 }
+    }
+}
+
+/// https://developer.arm.com/documentation/ddi0602/2022-03/Index-by-Encoding/Data-Processing----Immediate?lang=en#bitfield
+const FAMILY: u32 = 0b1001;
+
+impl From<SBFM> for u32 {
+    /// Convert an instruction into a 32-bit value.
+    fn from(inst: SBFM) -> Self {
+        0
+        | ((inst.sf as u32) << 31)
+        | (FAMILY << 25)
+        | (1 << 24)
+        | ((inst.n as u32) << 22)
+        | ((inst.immr as u32) << 16)
+        | ((inst.imms as u32) << 10)
+        | ((inst.rn as u32) << 5)
+        | inst.rd as u32
+    }
+}
+
+impl From<SBFM> for [u8; 4] {
+    /// Convert an instruction into a 4 byte array.
+    fn from(inst: SBFM) -> [u8; 4] {
+        let result: u32 = inst.into();
+        result.to_le_bytes()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_sxtw() {
+        let inst = SBFM::sxtw(0, 1);
+        let result: u32 = inst.into();
+        assert_eq!(0x93407c20, result);
+    }
+}
diff --git a/yjit/src/asm/arm64/mod.rs b/yjit/src/asm/arm64/mod.rs
index ca69b33d9e..6eebccaa61 100644
--- a/yjit/src/asm/arm64/mod.rs
+++ b/yjit/src/asm/arm64/mod.rs
@@ -321,6 +321,21 @@ pub fn ldur(cb: &mut CodeBlock, rt: A64Opnd, rn: A64Opnd) { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/mod.rs#L321
     cb.write_bytes(&bytes);
 }
 
+/// LDURSW - load a 32-bit memory address into a register and sign-extend it
+pub fn ldursw(cb: &mut CodeBlock, rt: A64Opnd, rn: A64Opnd) {
+    let bytes: [u8; 4] = match (rt, rn) {
+        (A64Opnd::Reg(rt), A64Opnd::Mem(rn)) => {
+            assert!(rt.num_bits == rn.num_bits, "Expected registers to be the same size");
+            assert!(imm_fits_bits(rn.disp.into(), 9), "Expected displacement to be 9 bits or less");
+
+            Load::ldursw(rt.reg_no, rn.base_reg_no, rn.disp as i16).into()
+        },
+        _ => panic!("Invalid operand combination to ldursw instruction.")
+    };
+
+    cb.write_bytes(&bytes);
+}
+
 /// LSL - logical shift left a register by an immediate
 pub fn lsl(cb: &mut CodeBlock, rd: A64Opnd, rn: A64Opnd, shift: A64Opnd) {
     let bytes: [u8; 4] = match (rd, rn, shift) {
@@ -558,6 +573,21 @@ pub fn subs(cb: &mut CodeBlock, rd: A64Opnd, rn: A64Opnd, rm: A64Opnd) { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/mod.rs#L573
     cb.write_bytes(&bytes);
 }
 
+/// SXTW - sign extend a 32-bit register into a 64-bit register
+pub fn sxtw(cb: &mut CodeBlock, rd: A64Opnd, rn: A64Opnd) {
+    let bytes: [u8; 4] = match (rd, rn) {
+        (A64Opnd::Reg(rd), A64Opnd::Reg(rn)) => {
+            assert_eq!(rd.num_bits, 64, "rd must be 64-bits wide.");
+            assert_eq!(rn.num_bits, 32, "rn must be 32-bits wide.");
+
+            SBFM::sxtw(rd.reg_no, rn.reg_no).into()
+        },
+        _ => panic!("Invalid operand combination to sxtw instruction."),
+    };
+
+    cb.write_bytes(&bytes);
+}
+
 /// RET - unconditionally return to a location in a register, defaults to X30
 pub fn ret(cb: &mu (... truncated)

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

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