use crate::machinst::{AllocationConsumer, PrettyPrint};
use std::string::String;
#[derive(Clone, Copy, Debug)]
pub struct UImm12 {
value: u16,
}
impl UImm12 {
pub fn maybe_from_u64(value: u64) -> Option<UImm12> {
if value < 4096 {
Some(UImm12 {
value: value as u16,
})
} else {
None
}
}
pub fn zero() -> UImm12 {
UImm12 { value: 0 }
}
pub fn bits(&self) -> u32 {
u32::from(self.value)
}
}
#[derive(Clone, Copy, Debug)]
pub struct SImm20 {
value: i32,
}
impl SImm20 {
pub fn maybe_from_i64(value: i64) -> Option<SImm20> {
if value >= -524288 && value < 524288 {
Some(SImm20 {
value: value as i32,
})
} else {
None
}
}
pub fn from_uimm12(value: UImm12) -> SImm20 {
SImm20 {
value: value.bits() as i32,
}
}
pub fn bits(&self) -> u32 {
let encoded: u32 = self.value as u32;
encoded & 0xfffff
}
}
#[derive(Clone, Copy, Debug)]
pub struct UImm16Shifted {
pub bits: u16,
pub shift: u8,
}
impl UImm16Shifted {
pub fn maybe_from_u64(value: u64) -> Option<UImm16Shifted> {
let mask0 = 0x0000_0000_0000_ffffu64;
let mask1 = 0x0000_0000_ffff_0000u64;
let mask2 = 0x0000_ffff_0000_0000u64;
let mask3 = 0xffff_0000_0000_0000u64;
if value == (value & mask0) {
return Some(UImm16Shifted {
bits: (value & mask0) as u16,
shift: 0,
});
}
if value == (value & mask1) {
return Some(UImm16Shifted {
bits: ((value >> 16) & mask0) as u16,
shift: 1,
});
}
if value == (value & mask2) {
return Some(UImm16Shifted {
bits: ((value >> 32) & mask0) as u16,
shift: 2,
});
}
if value == (value & mask3) {
return Some(UImm16Shifted {
bits: ((value >> 48) & mask0) as u16,
shift: 3,
});
}
None
}
pub fn maybe_with_shift(imm: u16, shift: u8) -> Option<UImm16Shifted> {
let shift_enc = shift / 16;
if shift_enc > 3 {
None
} else {
Some(UImm16Shifted {
bits: imm,
shift: shift_enc,
})
}
}
pub fn negate_bits(&self) -> UImm16Shifted {
UImm16Shifted {
bits: !self.bits,
shift: self.shift,
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct UImm32Shifted {
pub bits: u32,
pub shift: u8,
}
impl UImm32Shifted {
pub fn maybe_from_u64(value: u64) -> Option<UImm32Shifted> {
let mask0 = 0x0000_0000_ffff_ffffu64;
let mask1 = 0xffff_ffff_0000_0000u64;
if value == (value & mask0) {
return Some(UImm32Shifted {
bits: (value & mask0) as u32,
shift: 0,
});
}
if value == (value & mask1) {
return Some(UImm32Shifted {
bits: ((value >> 32) & mask0) as u32,
shift: 1,
});
}
None
}
pub fn maybe_with_shift(imm: u32, shift: u8) -> Option<UImm32Shifted> {
let shift_enc = shift / 32;
if shift_enc > 3 {
None
} else {
Some(UImm32Shifted {
bits: imm,
shift: shift_enc,
})
}
}
pub fn negate_bits(&self) -> UImm32Shifted {
UImm32Shifted {
bits: !self.bits,
shift: self.shift,
}
}
}
impl PrettyPrint for UImm12 {
fn pretty_print(&self, _: u8, _: &mut AllocationConsumer<'_>) -> String {
format!("{}", self.value)
}
}
impl PrettyPrint for SImm20 {
fn pretty_print(&self, _: u8, _: &mut AllocationConsumer<'_>) -> String {
format!("{}", self.value)
}
}
impl PrettyPrint for UImm16Shifted {
fn pretty_print(&self, _: u8, _: &mut AllocationConsumer<'_>) -> String {
format!("{}", self.bits)
}
}
impl PrettyPrint for UImm32Shifted {
fn pretty_print(&self, _: u8, _: &mut AllocationConsumer<'_>) -> String {
format!("{}", self.bits)
}
}