diff options
Diffstat (limited to 'src/shifter/extract.rs')
-rw-r--r-- | src/shifter/extract.rs | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/src/shifter/extract.rs b/src/shifter/extract.rs new file mode 100644 index 0000000..d4ff6e0 --- /dev/null +++ b/src/shifter/extract.rs @@ -0,0 +1,92 @@ +/* + Copyright 2021-2023 Gabriel Jensen. + + This file is part of Luma. + + Luma is free software: you can redistribute it + and/or modify it under the terms of the GNU + Affero General Public License as published by + the Free Software Foundation, either version 3 + of the License, or (at your option) any later + version. + + Luma is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU + Affero General Public License along with Luma. + If not, see <https://www.gnu.org/licenses/>. +*/ + +use crate::shifter::Shifter; + +use std::hint::unreachable_unchecked; + +impl Shifter { + pub fn extract(opcode: u32) -> Self { + use Shifter::*; + + match opcode & 0b00000010000000000000000000000000 != 0x0 { + false => { + let rm = (opcode & 0b00000000000000000000000000001111) as u8; + + let shift = (opcode & 0b00000000000000000000000001100000).wrapping_shr(0x5) as u8; + let register_shift = opcode & 0b00000000000000000000000000010000 != 0x0; + + match register_shift { + false => { + let imm = (opcode & 0b00000000000000000000111110000000).wrapping_shr(0x7) as u8; + + return match shift { + 0b11 => match imm { + 0x0 => RotateRightExtend( rm), + imm => RotateRightImmediate(rm, imm), + }, + + shift => { + match shift { + 0b00 => LogicalShiftLeftImmediate(rm, imm), + + 0b01 => LogicalShiftRightImmediate(rm, match imm { + 0x0 => 0x20, + imm => imm, + }), + + 0b10 => ArithmeticShiftRightImmediate(rm, match imm { + 0x0 => 0x20, + imm => imm, + }), + + _ => unsafe { unreachable_unchecked() }, + } + }, + }; + }, + + true => { + let rs = (opcode & 0b0000000000000000000111100000000).wrapping_shr(0x8) as u8; + + return match shift { + 0b00 => LogicalShiftLeftRegister( rm, rs), + 0b01 => LogicalShiftRightRegister( rm, rs), + 0b10 => ArithmeticShiftRightRegister(rm, rs), + 0b11 => RotateRightRegister( rm, rs), + + _ => unsafe { unreachable_unchecked() }, + }; + }, + }; + }, + + true => { + let imm = (opcode & 0b00000000000000000000000011111111) as u8; + let rot = (opcode & 0b00000000000000000000111100000000).wrapping_shr(0x7) as u8; + + return Immediate(imm, rot); + }, + }; + } +} |