use crate::exception::ADDRESS_ERROR;
use crate::instruction::Size;
use std::num::Wrapping;
use std::ops::{BitAnd, BitOr, BitXor, Shl};
#[inline(always)]
pub const fn bit(data: u16, bit: u16) -> bool {
data & (1 << bit) != 0
}
#[inline(always)]
pub const fn bits(d: u16, beg: u16, end: u16) -> u16 {
let mask = (1 << (end + 1 - beg)) - 1;
d >> beg & mask
}
pub trait IsEven : Sized {
fn is_even(self) -> bool;
fn even(self) -> Result<Self, u8>;
}
impl IsEven for u32 {
#[inline(always)]
fn is_even(self) -> bool {
self & 1 == 0
}
#[inline(always)]
fn even(self) -> Result<Self, u8> {
if self.is_even() {
Ok(self)
} else {
Err(ADDRESS_ERROR)
}
}
}
impl IsEven for Wrapping<u32> {
#[inline(always)]
fn is_even(self) -> bool {
self.0 & 1 == 0
}
#[inline(always)]
fn even(self) -> Result<Self, u8> {
if self.is_even() {
Ok(self)
} else {
Err(ADDRESS_ERROR)
}
}
}
impl IsEven for usize {
#[inline(always)]
fn is_even(self) -> bool {
self & 1 == 0
}
#[inline(always)]
fn even(self) -> Result<Self, u8> {
if self.is_even() {
Ok(self)
} else {
Err(ADDRESS_ERROR)
}
}
}
pub trait SliceAs {
fn u32_be(self) -> u32;
fn i32_be_sized(self, size: Size) -> i32;
fn get_next_word(&mut self) -> u16;
}
impl SliceAs for &[u16] {
fn u32_be(self) -> u32 {
(self[0] as u32) << 16 | self[1] as u32
}
fn i32_be_sized(self, size: Size) -> i32 {
match size {
Size::Byte => self[0] as i8 as i32,
Size::Word => self[0] as i16 as i32,
Size::Long => self.u32_be() as i32,
}
}
fn get_next_word(&mut self) -> u16 {
let d = self[0];
*self = &self[1..];
d
}
}
pub trait CarryingOps<S, U> : Sized + Integer {
fn signed_carrying_add(self, rhs: Self, carry: bool) -> (S, bool);
fn unsigned_carrying_add(self, rhs: Self, carry: bool) -> (U, bool);
fn signed_borrowing_sub(self, rhs: Self, carry: bool) -> (S, bool);
fn unsigned_borrowing_sub(self, rhs: Self, carry: bool) -> (U, bool);
}
impl CarryingOps<i8, u8> for u8 {
fn signed_carrying_add(self, rhs: Self, carry: bool) -> (i8, bool) {
(self as i8).carrying_add(rhs as i8, carry)
}
fn unsigned_carrying_add(self, rhs: Self, carry: bool) -> (u8, bool) {
self.carrying_add(rhs, carry)
}
fn signed_borrowing_sub(self, rhs: Self, carry: bool) -> (i8, bool) {
(self as i8).borrowing_sub(rhs as i8, carry)
}
fn unsigned_borrowing_sub(self, rhs: Self, carry: bool) -> (u8, bool) {
self.borrowing_sub(rhs, carry)
}
}
impl CarryingOps<i16, u16> for u16 {
fn signed_carrying_add(self, rhs: Self, carry: bool) -> (i16, bool) {
(self as i16).carrying_add(rhs as i16, carry)
}
fn unsigned_carrying_add(self, rhs: Self, carry: bool) -> (u16, bool) {
self.carrying_add(rhs, carry)
}
fn signed_borrowing_sub(self, rhs: Self, carry: bool) -> (i16, bool) {
(self as i16).borrowing_sub(rhs as i16, carry)
}
fn unsigned_borrowing_sub(self, rhs: Self, carry: bool) -> (u16, bool) {
self.borrowing_sub(rhs, carry)
}
}
impl CarryingOps<i32, u32> for u32 {
fn signed_carrying_add(self, rhs: Self, carry: bool) -> (i32, bool) {
(self as i32).carrying_add(rhs as i32, carry)
}
fn unsigned_carrying_add(self, rhs: Self, carry: bool) -> (u32, bool) {
self.carrying_add(rhs, carry)
}
fn signed_borrowing_sub(self, rhs: Self, carry: bool) -> (i32, bool) {
(self as i32).borrowing_sub(rhs as i32, carry)
}
fn unsigned_borrowing_sub(self, rhs: Self, carry: bool) -> (u32, bool) {
self.borrowing_sub(rhs, carry)
}
}
pub trait Integer : Copy + PartialEq + PartialOrd +
BitAnd<Output = Self> + BitOr<Output = Self> + BitXor<Output = Self> +
Shl<Output = Self> {
const ZERO: Self;
const SIGN_BIT_MASK: Self;
}
macro_rules! impl_integer {
($t:ty, $sign:expr) => {
impl Integer for $t {
const ZERO: Self = 0;
const SIGN_BIT_MASK: Self = $sign;
}
};
}
impl_integer!(i8, -0x80);
impl_integer!(u8, 0x80);
impl_integer!(i16, -0x8000);
impl_integer!(u16, 0x8000);
impl_integer!(i32, -0x8000_0000);
impl_integer!(u32, 0x8000_0000);