summaryrefslogtreecommitdiff
path: root/src/shifter/extract.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/shifter/extract.rs')
-rw-r--r--src/shifter/extract.rs92
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);
+ },
+ };
+ }
+}