summaryrefslogtreecommitdiff
path: root/src/state/shifter_value.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/state/shifter_value.rs')
-rw-r--r--src/state/shifter_value.rs130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/state/shifter_value.rs b/src/state/shifter_value.rs
new file mode 100644
index 0000000..58821fe
--- /dev/null
+++ b/src/state/shifter_value.rs
@@ -0,0 +1,130 @@
+/*
+ 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 crate::state::State;
+
+impl State {
+ #[must_use]
+ pub fn shifter_value(&self, shifter: Shifter) -> (u32, bool) {
+ use Shifter::*;
+
+ let c = self.read_cpsr() & 0b00100000000000000000000000000000 != 0x0;
+
+ let (value, carry) = match shifter {
+ Immediate(imm, rot) => {
+ let result = (imm as u32).rotate_right(rot as u32);
+ let c = if rot == 0x0 { c } else { result & 0b10000000000000000000000000000000 != 0x0 };
+
+ (result, c)
+ },
+
+ ArithmeticShiftRightImmediate(rm, imm) => {
+ let rm_value = self.read_register(rm);
+
+ let result = (rm_value as i32).wrapping_shr(imm as u32) as u32;
+ let c = false; // TODO
+
+ (result, c)
+ },
+
+ ArithmeticShiftRightRegister(rm, rs) => {
+ let rm_value = self.read_register(rm);
+ let rs_value = self.read_register(rs);
+
+ let result = (rm_value as i32).wrapping_shr(rs_value) as u32;
+ let c = false; // TODO
+
+ (result, c)
+ },
+
+ LogicalShiftLeftImmediate(rm, imm) => {
+ let rm_value = self.read_register(rm);
+
+ let result = rm_value.wrapping_shl(imm as u32);
+ let c = false; // TODO
+
+ (result, c)
+ },
+
+ LogicalShiftLeftRegister(rm, rs) => {
+ let rm_value = self.read_register(rm);
+ let rs_value = self.read_register(rs);
+
+ let result = rm_value.wrapping_shl(rs_value);
+ let c = false; // TODO
+
+ (result, c)
+ },
+
+ LogicalShiftRightImmediate(rm, imm) => {
+ let rm_value = self.read_register(rm);
+
+ let result = rm_value.wrapping_shr(imm as u32);
+ let c = false; // TODO
+
+ (result, c)
+ },
+
+ LogicalShiftRightRegister(rm, rs) => {
+ let rm_value = self.read_register(rm);
+ let rs_value = self.read_register(rs);
+
+ let result = rm_value.wrapping_shr(rs_value);
+ let c = false; // TODO
+
+ (result, c)
+ },
+
+ RotateRightImmediate(rm, imm) => {
+ let rm_value = self.read_register(rm);
+
+ let result = rm_value.rotate_right(imm as u32);
+ let c = false; // TODO
+
+ (result, c)
+ },
+
+ RotateRightRegister(rm, rs) => {
+ let rm_value = self.read_register(rm);
+ let rs_value = self.read_register(rs);
+
+ let result = rm_value.rotate_right(rs_value);
+ let c = false; // TODO
+
+ (result, c)
+ },
+
+ RotateRightExtend(rm) => {
+ let rm_value = self.read_register(rm);
+
+ let result = 0x0_u32; // TODO
+ let c = rm_value & 0b00000000000000000000000000000001 != 0x0;
+
+ (result, c)
+ },
+ };
+
+ return (value, carry);
+ }
+}