Add unsigned 128-bit immediate
This commit is contained in:
@@ -264,6 +264,74 @@ impl FromStr for Uimm32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A 128-bit unsigned integer immediate operand.
|
||||||
|
///
|
||||||
|
/// This is used as an immediate value in SIMD instructions
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
|
||||||
|
pub struct Uimm128(pub [u8; 16]);
|
||||||
|
|
||||||
|
impl Display for Uimm128 {
|
||||||
|
// print a 128-bit vector in hexadecimal, e.g. 0x000102030405060708090a0b0c0d0e0f
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
write!(f, "0x")?;
|
||||||
|
let mut anything_written = false;
|
||||||
|
for &b in self.0.iter() {
|
||||||
|
if b == 0 && !anything_written {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
anything_written = true;
|
||||||
|
write!(f, "{:02x}", b)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !anything_written {
|
||||||
|
write!(f, "00")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u64> for Uimm128 {
|
||||||
|
fn from(x: u64) -> Self {
|
||||||
|
let mut buffer: [u8; 16] = [0; 16]; // zero-fill
|
||||||
|
(0..8).for_each(|byte| buffer[15 - byte] = (x >> (byte as u64 * 8) & 0xff) as u8); // insert each byte from the u64 into v after byte position 8
|
||||||
|
Uimm128(buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&[u8]> for Uimm128 {
|
||||||
|
fn from(slice: &[u8]) -> Self {
|
||||||
|
assert_eq!(slice.len(), 16);
|
||||||
|
let mut buffer = [0; 16];
|
||||||
|
buffer.copy_from_slice(slice);
|
||||||
|
Uimm128(buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Uimm128 {
|
||||||
|
type Err = &'static str;
|
||||||
|
|
||||||
|
// parse a 128-bit vector from a hexadecimal string, formatted as above
|
||||||
|
fn from_str(s: &str) -> Result<Self, &'static str> {
|
||||||
|
if s.len() <= 2 || &s[0..2] != "0x" {
|
||||||
|
Err("Expected a hexadecimal string, e.g. 0x1234")
|
||||||
|
} else if s.len() % 2 != 0 {
|
||||||
|
Err("Hexadecimal string must have an even number of digits")
|
||||||
|
} else if s.len() > 32 {
|
||||||
|
Err("Hexadecimal string has too many digits to fit in a 128-bit vector")
|
||||||
|
} else {
|
||||||
|
let mut buffer = [0; 16]; // zero-fill
|
||||||
|
let start_at = 16 - s.len() / 2;
|
||||||
|
for i in (2..s.len()).step_by(2) {
|
||||||
|
let byte = u8::from_str_radix(&s[i..i + 2], 16)
|
||||||
|
.or_else(|_| Err("Unable to parse as hexadecimal"))?;
|
||||||
|
let position = start_at + (i / 2);
|
||||||
|
buffer[position] = byte;
|
||||||
|
}
|
||||||
|
Ok(Uimm128(buffer))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 32-bit signed immediate offset.
|
/// 32-bit signed immediate offset.
|
||||||
///
|
///
|
||||||
/// This is used to encode an immediate offset for load/store instructions. All supported ISAs have
|
/// This is used to encode an immediate offset for load/store instructions. All supported ISAs have
|
||||||
@@ -884,6 +952,38 @@ mod tests {
|
|||||||
parse_err::<Uimm64>("0x0_0000_0000_0000_0000", "Too many hexadecimal digits");
|
parse_err::<Uimm64>("0x0_0000_0000_0000_0000", "Too many hexadecimal digits");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn format_uimm128() {
|
||||||
|
assert_eq!(Uimm128::from(0).to_string(), "0x00");
|
||||||
|
assert_eq!(Uimm128::from(42).to_string(), "0x2a");
|
||||||
|
assert_eq!(Uimm128::from(3735928559).to_string(), "0xdeadbeef");
|
||||||
|
assert_eq!(
|
||||||
|
Uimm128::from(0x0102030405060708).to_string(),
|
||||||
|
"0x0102030405060708"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_uimm128() {
|
||||||
|
parse_ok::<Uimm128>("0x00", "0x00");
|
||||||
|
parse_ok::<Uimm128>("0x00000042", "0x42");
|
||||||
|
parse_ok::<Uimm128>(
|
||||||
|
"0x0102030405060708090a0b0c0d0e0f",
|
||||||
|
"0x0102030405060708090a0b0c0d0e0f",
|
||||||
|
);
|
||||||
|
|
||||||
|
parse_err::<Uimm128>("", "Expected a hexadecimal string, e.g. 0x1234");
|
||||||
|
parse_err::<Uimm128>("0x", "Expected a hexadecimal string, e.g. 0x1234");
|
||||||
|
parse_err::<Uimm128>(
|
||||||
|
"0x042",
|
||||||
|
"Hexadecimal string must have an even number of digits",
|
||||||
|
);
|
||||||
|
parse_err::<Uimm128>(
|
||||||
|
"0x00000000000000000000000000000000000000000000000000",
|
||||||
|
"Hexadecimal string has too many digits to fit in a 128-bit vector",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn format_offset32() {
|
fn format_offset32() {
|
||||||
assert_eq!(Offset32(0).to_string(), "");
|
assert_eq!(Offset32(0).to_string(), "");
|
||||||
|
|||||||
Reference in New Issue
Block a user