summaryrefslogblamecommitdiff
path: root/src/state/shifter_value.rs
blob: 58821fedb14b4888fb0c77e48de3cb27787c80ad (plain) (tree)

































































































































                                                                                                                             
/*
	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);
	}
}