summaryrefslogblamecommitdiff
path: root/src/predicate.rs
blob: 737ff7f18c6355838328c942c4b2442e16c8f8b9 (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 std::mem::transmute;

#[derive(Clone, Copy)]
#[repr(u8)]
pub enum Predicate {
	Eq = 0b0000,
	Ne = 0b0001,
	Cs = 0b0010, // Hs
	Cc = 0b0011, // Lo
	Mi = 0b0100,
	Pl = 0b0101,
	Vs = 0b0110,
	Vc = 0b0111,
	Hi = 0b1000,
	Ls = 0b1001,
	Ge = 0b1010,
	Lt = 0b1011,
	Gt = 0b1100,
	Le = 0b1101,
	Al = 0b1110,
	Nv = 0b1111,
}

impl Predicate {
	pub fn from_raw(mut raw: u8) -> Self {
		raw &= 0b00001111;
		return unsafe { transmute(raw) };
	}

	pub fn test(self, cpsr: u32) -> bool {
		let v = cpsr & 0b00010000000000000000000000000000 != 0x0;
		let c = cpsr & 0b00100000000000000000000000000000 != 0x0;
		let z = cpsr & 0b01000000000000000000000000000000 != 0x0;
		let n = cpsr & 0b10000000000000000000000000000000 != 0x0;

		use Predicate::*;
		return match self {
			Eq => z,
			Ne => !z,
			Cs => c,
			Cc => !c,
			Mi => n,
			Pl => !n,
			Vs => v,
			Vc => !v,
			Hi => c && !z,
			Ls => !c && z,
			Ge => n == v,
			Lt => n != v,
			Gt => !z && n == v,
			Le => z && n != v,
			Al => true,
			Nv => false, // Unpredictable in ARMv4.
		};
	}

	pub fn code(self) -> &'static str {
		use Predicate::*;
		return match self {
			Eq => "eq",
			Ne => "ne",
			Cs => "cs",
			Cc => "cc",
			Mi => "mi",
			Pl => "pl",
			Vs => "vs",
			Vc => "vc",
			Hi => "hi",
			Ls => "ls",
			Ge => "ge",
			Lt => "lt",
			Gt => "gt",
			Le => "le",
			Al => "al",
			Nv => "nv",
		};
	}
}