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

ruby-changes:73182

From: Kevin <ko1@a...>
Date: Tue, 30 Aug 2022 00:59:51 +0900 (JST)
Subject: [ruby-changes:73182] 15c6aacd39 (master): Encode MRS and MSR for AArch64 (https://github.com/Shopify/ruby/pull/315)

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

From 15c6aacd399b2bc7fb5ee2d6422451c4eb47941f Mon Sep 17 00:00:00 2001
From: Kevin Newton <kddnewton@g...>
Date: Wed, 13 Jul 2022 16:48:55 -0400
Subject: Encode MRS and MSR for AArch64
 (https://github.com/Shopify/ruby/pull/315)

---
 yjit/src/asm/arm64/arg/mod.rs      |  2 +
 yjit/src/asm/arm64/arg/sys_reg.rs  |  6 +++
 yjit/src/asm/arm64/inst/mod.rs     |  2 +
 yjit/src/asm/arm64/inst/sys_reg.rs | 86 ++++++++++++++++++++++++++++++++++++++
 yjit/src/asm/arm64/mod.rs          | 34 +++++++++++++++
 5 files changed, 130 insertions(+)
 create mode 100644 yjit/src/asm/arm64/arg/sys_reg.rs
 create mode 100644 yjit/src/asm/arm64/inst/sys_reg.rs

diff --git a/yjit/src/asm/arm64/arg/mod.rs b/yjit/src/asm/arm64/arg/mod.rs
index 0d2f1ac28a..bb779ab6df 100644
--- a/yjit/src/asm/arm64/arg/mod.rs
+++ b/yjit/src/asm/arm64/arg/mod.rs
@@ -4,7 +4,9 @@ https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/arg/mod.rs#L4
 mod bitmask_imm;
 mod condition;
 mod sf;
+mod sys_reg;
 
 pub use bitmask_imm::BitmaskImmediate;
 pub use condition::Condition;
 pub use sf::Sf;
+pub use sys_reg::SystemRegister;
diff --git a/yjit/src/asm/arm64/arg/sys_reg.rs b/yjit/src/asm/arm64/arg/sys_reg.rs
new file mode 100644
index 0000000000..41d71920cb
--- /dev/null
+++ b/yjit/src/asm/arm64/arg/sys_reg.rs
@@ -0,0 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/arg/sys_reg.rs#L1
+/// The encoded representation of an A64 system register.
+/// https://developer.arm.com/documentation/ddi0601/2022-06/AArch64-Registers/
+pub enum SystemRegister {
+    /// https://developer.arm.com/documentation/ddi0601/2022-06/AArch64-Registers/NZCV--Condition-Flags?lang=en
+    NZCV = 0b1_011_0100_0010_000
+}
diff --git a/yjit/src/asm/arm64/inst/mod.rs b/yjit/src/asm/arm64/inst/mod.rs
index f402f6765a..9dfc923f53 100644
--- a/yjit/src/asm/arm64/inst/mod.rs
+++ b/yjit/src/asm/arm64/inst/mod.rs
@@ -16,6 +16,7 @@ mod mov; https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/mod.rs#L16
 mod nop;
 mod shift_imm;
 mod store;
+mod sys_reg;
 
 pub use atomic::Atomic;
 pub use branch::Branch;
@@ -32,3 +33,4 @@ pub use mov::Mov; https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/mod.rs#L33
 pub use nop::Nop;
 pub use shift_imm::ShiftImm;
 pub use store::Store;
+pub use sys_reg::SysReg;
diff --git a/yjit/src/asm/arm64/inst/sys_reg.rs b/yjit/src/asm/arm64/inst/sys_reg.rs
new file mode 100644
index 0000000000..108737a870
--- /dev/null
+++ b/yjit/src/asm/arm64/inst/sys_reg.rs
@@ -0,0 +1,86 @@ https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/sys_reg.rs#L1
+use super::super::arg::SystemRegister;
+
+/// Which operation to perform (loading or storing the system register value).
+enum L {
+    /// Store the value of a general-purpose register in a system register.
+    MSR = 0,
+
+    /// Store the value of a system register in a general-purpose register.
+    MRS = 1
+}
+
+/// The struct that represents an A64 system register instruction that can be
+/// encoded.
+///
+/// MSR/MRS (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 |
+/// |  1  1  0  1    0  1  0  1    0  0     1                                                                       |
+/// |                                   L       o0 op1.....   CRn........   CRm........   op2..... rt.............. |
+/// +-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
+///
+pub struct SysReg {
+    /// The register to load the system register value into.
+    rt: u8,
+
+    /// Which system register to load or store.
+    systemreg: SystemRegister,
+
+    /// Which operation to perform (loading or storing the system register value).
+    l: L
+}
+
+impl SysReg {
+    /// MRS (register)
+    /// https://developer.arm.com/documentation/ddi0602/2022-03/Base-Instructions/MRS--Move-System-Register-?lang=en
+    pub fn mrs(rt: u8, systemreg: SystemRegister) -> Self {
+        SysReg { rt, systemreg, l: L::MRS }
+    }
+
+    /// MSR (register)
+    /// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/MSR--register---Move-general-purpose-register-to-System-Register-?lang=en
+    pub fn msr(systemreg: SystemRegister, rt: u8) -> Self {
+        SysReg { rt, systemreg, l: L::MSR }
+    }
+}
+
+/// https://developer.arm.com/documentation/ddi0602/2022-03/Index-by-Encoding/Branches--Exception-Generating-and-System-instructions?lang=en#systemmove
+const FAMILY: u32 = 0b110101010001;
+
+impl From<SysReg> for u32 {
+    /// Convert an instruction into a 32-bit value.
+    fn from(inst: SysReg) -> Self {
+        0
+        | (FAMILY << 20)
+        | ((inst.l as u32) << 21)
+        | ((inst.systemreg as u32) << 5)
+        | inst.rt as u32
+    }
+}
+
+impl From<SysReg> for [u8; 4] {
+    /// Convert an instruction into a 4 byte array.
+    fn from(inst: SysReg) -> [u8; 4] {
+        let result: u32 = inst.into();
+        result.to_le_bytes()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_mrs() {
+        let inst = SysReg::mrs(0, SystemRegister::NZCV);
+        let result: u32 = inst.into();
+        assert_eq!(0xd53b4200, result);
+    }
+
+    #[test]
+    fn test_msr() {
+        let inst = SysReg::msr(SystemRegister::NZCV, 0);
+        let result: u32 = inst.into();
+        assert_eq!(0xd51b4200, result);
+    }
+}
diff --git a/yjit/src/asm/arm64/mod.rs b/yjit/src/asm/arm64/mod.rs
index 3b5f1ff022..7adc1a2745 100644
--- a/yjit/src/asm/arm64/mod.rs
+++ b/yjit/src/asm/arm64/mod.rs
@@ -364,6 +364,30 @@ pub fn movz(cb: &mut CodeBlock, rd: A64Opnd, imm16: A64Opnd, shift: u8) { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/mod.rs#L364
     cb.write_bytes(&bytes);
 }
 
+/// MRS - move a system register into a general-purpose register
+pub fn mrs(cb: &mut CodeBlock, rt: A64Opnd, systemregister: SystemRegister) {
+    let bytes: [u8; 4] = match rt {
+        A64Opnd::Reg(rt) => {
+            SysReg::mrs(rt.reg_no, systemregister).into()
+        },
+        _ => panic!("Invalid operand combination to mrs instruction")
+    };
+
+    cb.write_bytes(&bytes);
+}
+
+/// MSR - move a general-purpose register into a system register
+pub fn msr(cb: &mut CodeBlock, systemregister: SystemRegister, rt: A64Opnd) {
+    let bytes: [u8; 4] = match rt {
+        A64Opnd::Reg(rt) => {
+            SysReg::msr(systemregister, rt.reg_no).into()
+        },
+        _ => panic!("Invalid operand combination to msr instruction")
+    };
+
+    cb.write_bytes(&bytes);
+}
+
 /// MVN - move a value in a register to another register, negating it
 pub fn mvn(cb: &mut CodeBlock, rd: A64Opnd, rm: A64Opnd) {
     let bytes: [u8; 4] = match (rd, rm) {
@@ -714,6 +738,16 @@ mod tests { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/mod.rs#L738
         check_bytes("600fa0d2", |cb| movz(cb, X0, A64Opnd::new_uimm(123), 16));
     }
 
+    #[test]
+    fn test_mrs() {
+        check_bytes("0a423bd5", |cb| mrs(cb, X10, SystemRegister::NZCV));
+    }
+
+    #[test]
+    fn test_msr() {
+        check_bytes("0a421bd5", |cb| msr(cb, SystemRegister::NZCV, X10));
+    }
+
     #[test]
     fn test_mvn() {
         check_bytes("ea032baa", |cb| mvn(cb, X10, X11));
-- 
cgit v1.2.1


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

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