* Narrow `allow(dead_code)` declarations Having module wide `allow(dead_code)` may hide some code that's really dead. In this commit I just narrowed the declarations to the specific enum variants that were not used (as it seems reasonable to keep them and their handling in all the matches, for future use). And the compiler found more dead code that I think we can remove safely in the short term. With this, the only files annotated with a module-wide `allow(dead_code)` are isle-generated files. * resurrect some functions as test helpers
203 lines
4.9 KiB
Rust
203 lines
4.9 KiB
Rust
//! S390x ISA definitions: immediate constants.
|
|
|
|
use crate::machinst::{AllocationConsumer, PrettyPrint};
|
|
use std::string::String;
|
|
|
|
/// An unsigned 12-bit immediate.
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub struct UImm12 {
|
|
/// The value.
|
|
value: u16,
|
|
}
|
|
|
|
impl UImm12 {
|
|
pub fn maybe_from_u64(value: u64) -> Option<UImm12> {
|
|
if value < 4096 {
|
|
Some(UImm12 {
|
|
value: value as u16,
|
|
})
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
/// Create a zero immediate of this format.
|
|
pub fn zero() -> UImm12 {
|
|
UImm12 { value: 0 }
|
|
}
|
|
|
|
/// Bits for encoding.
|
|
pub fn bits(&self) -> u32 {
|
|
u32::from(self.value)
|
|
}
|
|
}
|
|
|
|
/// A signed 20-bit immediate.
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub struct SImm20 {
|
|
/// The value.
|
|
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,
|
|
}
|
|
}
|
|
|
|
/// Bits for encoding.
|
|
pub fn bits(&self) -> u32 {
|
|
let encoded: u32 = self.value as u32;
|
|
encoded & 0xfffff
|
|
}
|
|
}
|
|
|
|
/// A 16-bit immediate with a {0,16,32,48}-bit shift.
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub struct UImm16Shifted {
|
|
/// The value.
|
|
pub bits: u16,
|
|
/// Result is `bits` shifted 16*shift bits to the left.
|
|
pub shift: u8,
|
|
}
|
|
|
|
impl UImm16Shifted {
|
|
/// Construct a UImm16Shifted from an arbitrary 64-bit constant if possible.
|
|
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,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A 32-bit immediate with a {0,32}-bit shift.
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub struct UImm32Shifted {
|
|
/// The value.
|
|
pub bits: u32,
|
|
/// Result is `bits` shifted 32*shift bits to the left.
|
|
pub shift: u8,
|
|
}
|
|
|
|
impl UImm32Shifted {
|
|
/// Construct a UImm32Shifted from an arbitrary 64-bit constant if possible.
|
|
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)
|
|
}
|
|
}
|