ruby-changes:73199
From: Kevin <ko1@a...>
Date: Tue, 30 Aug 2022 01:00:24 +0900 (JST)
Subject: [ruby-changes:73199] 4ae2c744ac (master): A lot of fixes coming from our pairing session (https://github.com/Shopify/ruby/pull/329)
https://git.ruby-lang.org/ruby.git/commit/?id=4ae2c744ac From 4ae2c744ac6b5b84f2bfebb9046c0c364863d7a4 Mon Sep 17 00:00:00 2001 From: Kevin Newton <kddnewton@g...> Date: Tue, 19 Jul 2022 17:44:39 -0400 Subject: A lot of fixes coming from our pairing session (https://github.com/Shopify/ruby/pull/329) * Move to/from SP on AArch64 * Consolidate loads and stores * Implement LDR post-index and LDR pre-index for AArch64 * Implement STR post-index and STR pre-index for AArch64 * Module entrypoints for LDR pre/post -index and STR pre/post -index * Use STR (pre-index) and LDR (post-index) to implement push/pop * Go back to using MOV for to/from SP --- yjit/src/asm/arm64/inst/load.rs | 124 -------------------- yjit/src/asm/arm64/inst/load_store.rs | 215 ++++++++++++++++++++++++++++++++++ yjit/src/asm/arm64/inst/mod.rs | 6 +- yjit/src/asm/arm64/inst/store.rs | 105 ----------------- yjit/src/asm/arm64/mod.rs | 108 ++++++++++++++++- yjit/src/backend/arm64/mod.rs | 12 +- 6 files changed, 326 insertions(+), 244 deletions(-) delete mode 100644 yjit/src/asm/arm64/inst/load.rs create mode 100644 yjit/src/asm/arm64/inst/load_store.rs delete mode 100644 yjit/src/asm/arm64/inst/store.rs diff --git a/yjit/src/asm/arm64/inst/load.rs b/yjit/src/asm/arm64/inst/load.rs deleted file mode 100644 index b64a6a96ac..0000000000 --- a/yjit/src/asm/arm64/inst/load.rs +++ /dev/null @@ -1,124 +0,0 @@ https://github.com/ruby/ruby/blob/trunk/#L0 -/// The size of the operands being operated on. -enum Size { - Size32 = 0b10, - 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 { - fn from(num_bits: u8) -> Self { - match num_bits { - 64 => Size::Size64, - 32 => Size::Size32, - _ => panic!("Invalid number of bits: {}", num_bits) - } - } -} - -/// The struct that represents an A64 data processing -- immediate instruction -/// that can be encoded. -/// -/// 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 0 0 | -/// | size. opc.. imm9.......................... rn.............. rt.............. | -/// +-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+ -/// -pub struct Load { - /// The number of the register to load the value into. - rt: u8, - - /// The base register with which to form the address. - rn: u8, - - /// 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 -} - -impl Load { - /// 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, 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 } - } -} - -/// https://developer.arm.com/documentation/ddi0602/2022-03/Index-by-Encoding/Loads-and-Stores?lang=en -const FAMILY: u32 = 0b0100; - -impl From<Load> for u32 { - /// Convert an instruction into a 32-bit value. - fn from(inst: Load) -> Self { - let imm9 = (inst.imm9 as u32) & ((1 << 9) - 1); - - 0 - | ((inst.size as u32) << 30) - | (0b11 << 28) - | (FAMILY << 25) - | ((inst.opc as u32) << 22) - | (imm9 << 12) - | ((inst.rn as u32) << 5) - | (inst.rt as u32) - } -} - -impl From<Load> for [u8; 4] { - /// Convert an instruction into a 4 byte array. - fn from(inst: Load) -> [u8; 4] { - let result: u32 = inst.into(); - result.to_le_bytes() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_ldur() { - let inst = Load::ldur(0, 1, 0, 64); - let result: u32 = inst.into(); - assert_eq!(0xf8400020, result); - } - - #[test] - fn test_ldur_with_imm() { - let inst = Load::ldur(0, 1, 123, 64); - 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/load_store.rs b/yjit/src/asm/arm64/inst/load_store.rs new file mode 100644 index 0000000000..80a67c837e --- /dev/null +++ b/yjit/src/asm/arm64/inst/load_store.rs @@ -0,0 +1,215 @@ https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/load_store.rs#L1 +/// The size of the operands being operated on. +enum Size { + Size32 = 0b10, + Size64 = 0b11, +} + +/// 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 { + fn from(num_bits: u8) -> Self { + match num_bits { + 64 => Size::Size64, + 32 => Size::Size32, + _ => panic!("Invalid number of bits: {}", num_bits) + } + } +} + +/// The operation to perform for this instruction. +enum Opc { + STR = 0b00, + LDR = 0b01, + LDURSW = 0b10 +} + +/// What kind of indexing to perform for this instruction. +enum Index { + None = 0b00, + PostIndex = 0b01, + PreIndex = 0b11 +} + +/// The struct that represents an A64 load or store instruction that can be +/// encoded. +/// +/// LDR/LDUR/LDURSW/STR/STUR +/// +-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+ +/// | 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 | +/// | size. opc.. imm9.......................... idx.. rn.............. rt.............. | +/// +-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+ +/// +pub struct LoadStore { + /// The number of the register to load the value into. + rt: u8, + + /// The base register with which to form the address. + rn: u8, + + /// What kind of indexing to perform for this instruction. + idx: Index, + + /// 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 +} + +impl LoadStore { + /// LDR (immediate, post-index) + /// https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/LDR--immediate---Load-Register--immediate-- + pub fn ldr_post(rt: u8, rn: u8, imm9: i16, num_bits: u8) -> Self { + Self { rt, rn, idx: Index::PostIndex, imm9, opc: Opc::LDR, size: num_bits.into() } + } + + /// LDR (immediate, pre-index) + /// https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/LDR--immediate---Load-Register--immediate-- + pub fn ldr_pre(rt: u8, rn: u8, imm9: i16, num_bits: u8) -> Self { + Self { rt, rn, idx: Index::PreIndex, imm9, opc: Opc::LDR, size: num_bits.into() } + } + + /// 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, idx: Index::None, imm9, opc: Opc::LDR, 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, idx: Index::None, imm9, opc: Opc::LDURSW, size: Size::Size32 } + } + + /// STR (immediate, post-index) + /// https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/STR--immediate---Store-Register--immediate-- + pub fn str_post(rt: u8, rn: u8, imm9: i16, num_bits: u8) -> Self { + Self { rt, rn, idx: Index::PostIndex, imm9, opc: Opc::STR, size: num_bits.into() } + } + + /// STR (immediate, pre-index) + /// https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/STR--immediate---Store-Register--immediate-- + pub fn str_pre(rt: u8, rn: u8, imm9: i16, num_bits: u8) -> Self { + Self { rt, rn, idx: Index::PreIndex, imm9, opc: Opc::STR, size: num_bits.into() } + } + + /// STUR (store register, unscaled) + /// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/STUR--Store-Register--unscaled--?lang=en + pub fn stur(rt: u8, rn: u8, imm9: i16, num_bits: u8) -> Self { + Self { rt, rn, idx: Index::None, imm9, opc: Opc::STR, size: num_bits.into() } + } +} + +/// https://developer.arm.com/documentation/ddi0602/2022-03/Index-by (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/