diff options
author | Kevin Newton <[email protected]> | 2022-06-07 13:37:49 -0400 |
---|---|---|
committer | Takashi Kokubun <[email protected]> | 2022-08-29 08:46:54 -0700 |
commit | 26ba0a454c1d08df0afacca2786330198a1daee0 (patch) | |
tree | 96aede1816f8a103ba7e58e00795fdee0711eb16 /yjit/src/asm/arm64/inst | |
parent | e22134277b81124ba2ce4cf3e08ad0983c0432c9 (diff) |
RET A64 instructions (https://github.com/Shopify/ruby/pull/294)
Diffstat (limited to 'yjit/src/asm/arm64/inst')
-rw-r--r-- | yjit/src/asm/arm64/inst/branches_and_system.rs | 70 | ||||
-rw-r--r-- | yjit/src/asm/arm64/inst/mod.rs | 1 |
2 files changed, 71 insertions, 0 deletions
diff --git a/yjit/src/asm/arm64/inst/branches_and_system.rs b/yjit/src/asm/arm64/inst/branches_and_system.rs new file mode 100644 index 0000000000..6eece11b88 --- /dev/null +++ b/yjit/src/asm/arm64/inst/branches_and_system.rs @@ -0,0 +1,70 @@ +use super::{ + super::opnd::*, + family::Family, + sf::Sf +}; + +/// The struct that represents an A64 branches and system instruction that can +/// be encoded. +/// +/// RET +/// +-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+ +/// | 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 1 0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 | +/// | rn.............. rm.............. | +/// +-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+ +/// +struct BranchesAndSystem { + /// The register holding the address to be branched to. + rn: u8 +} + +impl BranchesAndSystem { + /// RET + /// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/RET--Return-from-subroutine-?lang=en + pub fn ret(rn: &A64Opnd) -> Self { + match rn { + A64Opnd::None => BranchesAndSystem { rn: 30 }, + A64Opnd::Reg(reg) => BranchesAndSystem { rn: reg.reg_no }, + _ => panic!("Invalid operand for RET") + } + } +} + +impl From<BranchesAndSystem> for u32 { + /// Convert a data processing instruction into a 32-bit value. + fn from(inst: BranchesAndSystem) -> Self { + 0 + | (0b11 << 30) + | (Family::BranchesAndSystem as u32).wrapping_shl(25) + | (0b1001011111 << 16) + | (inst.rn as u32).wrapping_shl(5) + } +} + +impl From<BranchesAndSystem> for [u8; 4] { + /// Convert a data processing instruction into a 4 byte array. + fn from(inst: BranchesAndSystem) -> [u8; 4] { + let result: u32 = inst.into(); + result.to_le_bytes() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_ret() { + let inst = BranchesAndSystem::ret(&A64Opnd::None); + let result: u32 = inst.into(); + assert_eq!(0xd65f03C0, result); + } + + #[test] + fn test_ret_rn() { + let inst = BranchesAndSystem::ret(&X20); + let result: u32 = inst.into(); + assert_eq!(0xd65f0280, result); + } +} diff --git a/yjit/src/asm/arm64/inst/mod.rs b/yjit/src/asm/arm64/inst/mod.rs index 5a0e148ff9..becf4251bd 100644 --- a/yjit/src/asm/arm64/inst/mod.rs +++ b/yjit/src/asm/arm64/inst/mod.rs @@ -1,3 +1,4 @@ +mod branches_and_system; mod data_processing_immediate; mod data_processing_register; mod family; |