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

ruby-changes:74500

From: Aaron <ko1@a...>
Date: Tue, 15 Nov 2022 10:05:18 +0900 (JST)
Subject: [ruby-changes:74500] e74d82f674 (master): Implement LDURH on Aarch64

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

From e74d82f67447d10347b154d5e9b098397e80567c Mon Sep 17 00:00:00 2001
From: Aaron Patterson <tenderlove@r...>
Date: Mon, 14 Nov 2022 16:15:50 -0800
Subject: Implement LDURH on Aarch64

When RUBY_DEBUG is enabled, shape ids are 16 bits.  I would like to do
16 bit comparisons, so I need to load halfwords sometimes.  This commit
adds LDURH so that I can load halfwords.

  https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDURH--Load-Register-Halfword--unscaled--?lang=en

I verified the bytes using clang:

```
$ cat asmthing.s
.global _start
.align 2

_start:
  ldurh w10, [x1]
  ldurh w10, [x1, #123]
$ as asmthing.s -o asmthing.o && objdump --disassemble asmthing.o

asmthing.o:	file format mach-o arm64

Disassembly of section __TEXT,__text:

0000000000000000 <ltmp0>:
       0: 2a 00 40 78  	ldurh	w10, [x1]
       4: 2a b0 47 78  	ldurh	w10, [x1, #123]
```
---
 yjit/src/asm/arm64/inst/load_store.rs | 14 ++++++++++++++
 yjit/src/asm/arm64/mod.rs             | 22 ++++++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/yjit/src/asm/arm64/inst/load_store.rs b/yjit/src/asm/arm64/inst/load_store.rs
index e877c6de77..d08398380a 100644
--- a/yjit/src/asm/arm64/inst/load_store.rs
+++ b/yjit/src/asm/arm64/inst/load_store.rs
@@ -3,6 +3,7 @@ use super::super::arg::truncate_imm; https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/load_store.rs#L3
 /// The size of the operands being operated on.
 enum Size {
     Size8 = 0b00,
+    Size16 = 0b01,
     Size32 = 0b10,
     Size64 = 0b11,
 }
@@ -82,6 +83,12 @@ impl LoadStore { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/load_store.rs#L83
         Self { rt, rn, idx: Index::None, imm9, opc: Opc::LDR, size: num_bits.into() }
     }
 
+    /// LDURH Load Register Halfword (unscaled)
+    /// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDURH--Load-Register-Halfword--unscaled--?lang=en
+    pub fn ldurh(rt: u8, rn: u8, imm9: i16) -> Self {
+        Self { rt, rn, idx: Index::None, imm9, opc: Opc::LDR, size: Size::Size16 }
+    }
+
     /// LDURB (load register, byte, unscaled)
     /// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDURB--Load-Register-Byte--unscaled--?lang=en
     pub fn ldurb(rt: u8, rn: u8, imm9: i16) -> Self {
@@ -171,6 +178,13 @@ mod tests { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/load_store.rs#L178
         assert_eq!(0x38400020, result);
     }
 
+    #[test]
+    fn test_ldurh() {
+        let inst = LoadStore::ldurh(0, 1, 0);
+        let result: u32 = inst.into();
+        assert_eq!(0x78400020, result);
+    }
+
     #[test]
     fn test_ldur_with_imm() {
         let inst = LoadStore::ldur(0, 1, 123, 64);
diff --git a/yjit/src/asm/arm64/mod.rs b/yjit/src/asm/arm64/mod.rs
index e5697e26fb..683711259e 100644
--- a/yjit/src/asm/arm64/mod.rs
+++ b/yjit/src/asm/arm64/mod.rs
@@ -536,6 +536,22 @@ pub fn ldur(cb: &mut CodeBlock, rt: A64Opnd, rn: A64Opnd) { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/mod.rs#L536
     cb.write_bytes(&bytes);
 }
 
+/// LDURH - load a byte from memory, zero-extend it, and write it to a register
+pub fn ldurh(cb: &mut CodeBlock, rt: A64Opnd, rn: A64Opnd) {
+    let bytes: [u8; 4] = match (rt, rn) {
+        (A64Opnd::Reg(rt), A64Opnd::Mem(rn)) => {
+            assert!(rt.num_bits == 32, "Rt should be a 32 bit register");
+            assert!(rn.num_bits == 64, "Rn should be a 64 bit register");
+            assert!(mem_disp_fits_bits(rn.disp), "Expected displacement to be 9 bits or less");
+
+            LoadStore::ldurh(rt.reg_no, rn.base_reg_no, rn.disp as i16).into()
+        },
+        _ => panic!("Invalid operands for LDURH")
+    };
+
+    cb.write_bytes(&bytes);
+}
+
 /// LDURB - load a byte from memory, zero-extend it, and write it to a register
 pub fn ldurb(cb: &mut CodeBlock, rt: A64Opnd, rn: A64Opnd) {
     let bytes: [u8; 4] = match (rt, rn) {
@@ -1309,6 +1325,12 @@ mod tests { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/mod.rs#L1325
         check_bytes("6ac54078", |cb| ldrh_post(cb, W10, A64Opnd::new_mem(64, X11, 12)));
     }
 
+    #[test]
+    fn test_ldurh_memory() {
+        check_bytes("2a004078", |cb| ldurh(cb, W10, A64Opnd::new_mem(64, X1, 0)));
+        check_bytes("2ab04778", |cb| ldurh(cb, W10, A64Opnd::new_mem(64, X1, 123)));
+    }
+
     #[test]
     fn test_ldur_memory() {
         check_bytes("20b047f8", |cb| ldur(cb, X0, A64Opnd::new_mem(64, X1, 123)));
-- 
cgit v1.2.3


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

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