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/