#[derive(Debug, Clone)]
pub struct SystemzEncodingBuilder {
bytes: Vec<u8>,
}
impl SystemzEncodingBuilder {
pub fn new() -> Self {
SystemzEncodingBuilder { bytes: Vec::new() }
}
pub fn u8(&mut self, val: u8) -> &mut Self {
self.bytes.push(val);
self
}
pub fn u16(&mut self, val: u16) -> &mut Self {
self.bytes.push((val >> 8) as u8);
self.bytes.push(val as u8);
self
}
pub fn u32(&mut self, val: u32) -> &mut Self {
self.bytes.push((val >> 24) as u8);
self.bytes.push((val >> 16) as u8);
self.bytes.push((val >> 8) as u8);
self.bytes.push(val as u8);
self
}
pub fn reg(&mut self, reg: u8, pos: u8) -> &mut Self {
let idx = self.bytes.len() - 1;
self.bytes[idx] |= (reg & 0x0F) << pos;
self
}
pub fn build(self) -> Vec<u8> {
self.bytes
}
}
pub fn encode_rr(opcode: u8, r1: u8, r2: u8) -> Vec<u8> {
let word: u16 = ((opcode as u16) << 8) | (((r1 & 0x0F) as u16) << 4) | ((r2 & 0x0F) as u16);
vec![(word >> 8) as u8, word as u8]
}
pub fn encode_rx(opcode: u8, r1: u8, x2: u8, b2: u8, d2: u16) -> Vec<u8> {
let d2 = d2 & 0x0FFF;
let word: u32 = ((opcode as u32) << 24)
| (((r1 & 0x0F) as u32) << 20)
| (((x2 & 0x0F) as u32) << 16)
| (((b2 & 0x0F) as u32) << 12)
| (d2 as u32);
vec![
(word >> 24) as u8,
(word >> 16) as u8,
(word >> 8) as u8,
word as u8,
]
}
pub fn encode_rxy(opcode: u8, r1: u8, x2: u8, b2: u8, d2: i32, op2: u8) -> Vec<u8> {
let dl2 = (d2 & 0x0F) as u8;
let dh2 = ((d2 >> 4) & 0xFF) as u8;
let high: u32 = ((opcode as u32) << 24)
| (((r1 & 0x0F) as u32) << 20)
| (((x2 & 0x0F) as u32) << 16)
| (((b2 & 0x0F) as u32) << 12)
| (dl2 as u32) << 8
| (dh2 as u32);
vec![
(high >> 24) as u8,
(high >> 16) as u8,
(high >> 8) as u8,
high as u8,
0u8,
op2,
]
}
pub fn encode_ri(opcode: u8, r1: u8, op2: u8, i2: i16) -> Vec<u8> {
let word: u32 = ((opcode as u32) << 24)
| (((r1 & 0x0F) as u32) << 20)
| (((op2 & 0x0F) as u32) << 16)
| ((i2 as u16) as u32);
vec![
(word >> 24) as u8,
(word >> 16) as u8,
(word >> 8) as u8,
word as u8,
]
}
pub fn encode_ril(opcode: u8, r1: u8, op2: u8, i2: i32) -> Vec<u8> {
let high: u32 =
((opcode as u32) << 24) | (((r1 & 0x0F) as u32) << 20) | (((op2 & 0x0F) as u32) << 16);
vec![
(high >> 24) as u8,
(high >> 16) as u8,
(high >> 8) as u8,
high as u8,
((i2 as u32) >> 8) as u8,
i2 as u8,
]
}
pub fn encode_rre(opcode: u16, r1: u8, r2: u8) -> Vec<u8> {
let word: u32 = ((opcode as u32) << 16) | (((r1 & 0x0F) as u32) << 4) | ((r2 & 0x0F) as u32);
vec![
(word >> 24) as u8,
(word >> 16) as u8,
(word >> 8) as u8,
word as u8,
]
}
pub fn encode_rrf(opcode: u16, r1: u8, r2: u8, r3: u8, m4: u8) -> Vec<u8> {
let word: u32 = ((opcode as u32) << 16)
| (((r3 & 0x0F) as u32) << 12)
| (((m4 & 0x0F) as u32) << 8)
| (((r1 & 0x0F) as u32) << 4)
| ((r2 & 0x0F) as u32);
vec![
(word >> 24) as u8,
(word >> 16) as u8,
(word >> 8) as u8,
word as u8,
]
}
pub fn encode_si(opcode: u8, i2: u8, b1: u8, d1: u16) -> Vec<u8> {
let d1 = d1 & 0x0FFF;
let word: u32 =
((opcode as u32) << 24) | ((i2 as u32) << 16) | (((b1 & 0x0F) as u32) << 12) | (d1 as u32);
vec![
(word >> 24) as u8,
(word >> 16) as u8,
(word >> 8) as u8,
word as u8,
]
}
pub fn encode_sil(opcode: u16, b1: u8, d1: u16, i2: u16) -> Vec<u8> {
let d1 = d1 & 0x0FFF;
let high: u32 = ((opcode as u32) << 16) | (((b1 & 0x0F) as u32) << 12) | (d1 as u32);
vec![
(high >> 24) as u8,
(high >> 16) as u8,
(high >> 8) as u8,
high as u8,
(i2 >> 8) as u8,
i2 as u8,
]
}
pub fn encode_rs(opcode: u8, r1: u8, r3: u8, b2: u8, d2: u16) -> Vec<u8> {
let d2 = d2 & 0x0FFF;
let word: u32 = ((opcode as u32) << 24)
| (((r1 & 0x0F) as u32) << 20)
| (((r3 & 0x0F) as u32) << 16)
| (((b2 & 0x0F) as u32) << 12)
| (d2 as u32);
vec![
(word >> 24) as u8,
(word >> 16) as u8,
(word >> 8) as u8,
word as u8,
]
}
pub fn encode_rsy(opcode: u8, r1: u8, r3: u8, b2: u8, d2: i32, op2: u8) -> Vec<u8> {
let dl2 = (d2 & 0x0F) as u8;
let dh2 = ((d2 >> 4) & 0xFF) as u8;
let high: u32 = ((opcode as u32) << 24)
| (((r1 & 0x0F) as u32) << 20)
| (((r3 & 0x0F) as u32) << 16)
| (((b2 & 0x0F) as u32) << 12)
| ((dl2 as u32) << 8)
| (dh2 as u32);
vec![
(high >> 24) as u8,
(high >> 16) as u8,
(high >> 8) as u8,
high as u8,
0u8,
op2,
]
}
pub fn encode_ss(opcode: u8, len: u8, b1: u8, d1: u16, b2: u8, d2: u16) -> Vec<u8> {
let d1 = d1 & 0x0FFF;
let d2 = d2 & 0x0FFF;
let l = if len == 0 { 0 } else { len - 1 }; let high: u32 = ((opcode as u32) << 24) | ((l as u32) << 16);
let mid: u16 = (((b1 & 0x0F) as u16) << 12) | (d1 as u16);
let low: u16 = (((b2 & 0x0F) as u16) << 12) | (d2 as u16);
vec![
(high >> 24) as u8,
(high >> 16) as u8,
(mid >> 8) as u8,
mid as u8,
(low >> 8) as u8,
low as u8,
]
}
pub fn encode_sse(opcode: u16, b1: u8, d1: u16, b2: u8, d2: u16) -> Vec<u8> {
let d1 = d1 & 0x0FFF;
let d2 = d2 & 0x0FFF;
let high: u32 = ((opcode as u32) << 16) | (((b1 & 0x0F) as u32) << 12) | (d1 as u32);
let low: u16 = (((b2 & 0x0F) as u16) << 12) | (d2 as u16);
vec![
(high >> 24) as u8,
(high >> 16) as u8,
(high >> 8) as u8,
high as u8,
(low >> 8) as u8,
low as u8,
]
}
pub fn encode_rsl(opcode: u8, r1: u8, r3: u8, b2: u8, d2: u16, m3: u8, op2: u8) -> Vec<u8> {
let d2 = d2 & 0x0FFF;
let high: u32 = ((opcode as u32) << 24)
| (((r1 & 0x0F) as u32) << 20)
| (((r3 & 0x0F) as u32) << 16)
| (((b2 & 0x0F) as u32) << 12)
| (d2 as u32);
let low: u16 = (((m3 & 0x0F) as u16) << 12) | ((op2 & 0x0F) as u16) << 8;
vec![
(high >> 24) as u8,
(high >> 16) as u8,
(high >> 8) as u8,
high as u8,
(low >> 8) as u8,
low as u8,
]
}
pub fn encode_rsi(opcode: u8, r1: u8, r3: u8, i2: i16) -> Vec<u8> {
let word: u32 = ((opcode as u32) << 24)
| (((r1 & 0x0F) as u32) << 20)
| (((r3 & 0x0F) as u32) << 16)
| ((i2 as u16) as u32);
vec![
(word >> 24) as u8,
(word >> 16) as u8,
(word >> 8) as u8,
word as u8,
]
}
pub fn encode_rie(opcode: u8, r1: u8, op2: u8, r3: u8, m3: u8, i2: i16, op3: u8) -> Vec<u8> {
let high: u32 = ((opcode as u32) << 24)
| (((r1 & 0x0F) as u32) << 20)
| (((op2 & 0x0F) as u32) << 16)
| (((r3 & 0x0F) as u32) << 12)
| (((m3 & 0x0F) as u32) << 8)
| ((i2 as u16) as u32);
vec![
(high >> 24) as u8,
(high >> 16) as u8,
(high >> 8) as u8,
high as u8,
(i2 >> 8) as u8,
op3,
]
}
pub fn encode_ris(opcode: u8, r1: u8, m3: u8, b4: u8, d4: u16, i2: u8, op2: u8) -> Vec<u8> {
let d4 = d4 & 0x0FFF;
let high: u32 = ((opcode as u32) << 24)
| (((r1 & 0x0F) as u32) << 20)
| (((m3 & 0x0F) as u32) << 16)
| (((b4 & 0x0F) as u32) << 12)
| (d4 as u32);
let low: u16 = ((i2 as u16) << 8) | (op2 as u16);
vec![
(high >> 24) as u8,
(high >> 16) as u8,
(high >> 8) as u8,
high as u8,
(low >> 8) as u8,
low as u8,
]
}
pub fn encode_vri(opcode: u16, v1: u8, v2: u8, v3: u8, i2: u16, m4: u8) -> Vec<u8> {
let i2 = i2 & 0x0FFF;
let high: u32 = ((opcode as u32) << 16)
| (((v1 & 0x1F) as u32) << 11)
| (((v2 & 0x1F) as u32) << 6)
| (((v3 & 0x1F) as u32) << 1);
let low: u16 = ((i2 as u16) << 4) | ((m4 & 0x0F) as u16);
vec![
(high >> 24) as u8,
(high >> 16) as u8,
(high >> 8) as u8,
high as u8,
(low >> 8) as u8,
low as u8,
]
}
pub fn encode_vrs(opcode: u16, v1: u8, v2: u8, r3: u8, op2: u8, m4: u8) -> Vec<u8> {
let high: u32 = ((opcode as u32) << 16)
| (((v1 & 0x1F) as u32) << 11)
| (((v2 & 0x1F) as u32) << 6)
| (((r3 & 0x0F) as u32) << 1);
let low: u16 = (((op2 & 0x0F) as u16) << 12) | ((m4 & 0x0F) as u16) << 8;
vec![
(high >> 24) as u8,
(high >> 16) as u8,
(high >> 8) as u8,
high as u8,
(low >> 8) as u8,
low as u8,
]
}
pub fn encode_vrv(opcode: u16, v1: u8, v2: u8, r3: u8, m5: u8, v4: u8, m6: u8) -> Vec<u8> {
let high: u32 = ((opcode as u32) << 16)
| (((v1 & 0x1F) as u32) << 11)
| (((v2 & 0x1F) as u32) << 6)
| (((r3 & 0x0F) as u32) << 1);
let low: u16 =
(((m5 & 0x0F) as u16) << 12) | (((v4 & 0x1F) as u16) << 7) | ((m6 & 0x0F) as u16);
vec![
(high >> 24) as u8,
(high >> 16) as u8,
(high >> 8) as u8,
high as u8,
(low >> 8) as u8,
low as u8,
]
}
pub fn encode_vrx(opcode: u16, v1: u8, x2: u8, b2: u8, d2: u16, m3: u8) -> Vec<u8> {
let d2 = d2 & 0x0FFF;
let high: u32 = ((opcode as u32) << 16)
| (((v1 & 0x1F) as u32) << 11)
| (((x2 & 0x0F) as u32) << 7)
| (((b2 & 0x0F) as u32) << 3)
| ((d2 >> 9) & 0x07) as u32;
let low: u16 = ((d2 & 0x1FF) as u16) << 7 | (((m3 & 0x0F) as u16) << 3);
vec![
(high >> 24) as u8,
(high >> 16) as u8,
(high >> 8) as u8,
high as u8,
(low >> 8) as u8,
low as u8,
]
}
pub fn encode_vsi(opcode: u16, v1: u8, b2: u8, d2: u16, i3: u8) -> Vec<u8> {
let d2 = d2 & 0x0FFF;
let high: u32 = ((opcode as u32) << 16)
| (((v1 & 0x1F) as u32) << 11)
| (((b2 & 0x0F) as u32) << 3)
| ((d2 >> 9) & 0x07) as u32;
let low: u16 = (((d2 & 0x1FF) as u16) << 7) | ((i3 & 0xFF) as u16);
vec![
(high >> 24) as u8,
(high >> 16) as u8,
(high >> 8) as u8,
high as u8,
(low >> 8) as u8,
low as u8,
]
}
pub fn encode_branch_disp16(disp: i32) -> i16 {
((disp >> 1) as i16)
}
pub fn encode_branch_disp32(disp: i64) -> i32 {
((disp >> 1) as i32)
}
pub fn decode_branch_disp16(encoded: i16) -> i32 {
(encoded as i32) << 1
}
pub fn decode_branch_disp32(encoded: i32) -> i64 {
(encoded as i64) << 1
}
pub fn is_s16(val: i64) -> bool {
val >= -32768 && val <= 32767
}
pub fn is_u16(val: u64) -> bool {
val <= 65535
}
pub fn is_s32(val: i64) -> bool {
val >= -2147483648 && val <= 2147483647
}
pub fn is_u8(val: u64) -> bool {
val <= 255
}
pub fn encode_s16(val: i64) -> Option<i16> {
if is_s16(val) {
Some(val as i16)
} else {
None
}
}
pub fn encode_u16(val: u64) -> Option<u16> {
if is_u16(val) {
Some(val as u16)
} else {
None
}
}
pub fn sext16(val: i16) -> i64 {
val as i64
}
pub fn sext32(val: i32) -> i64 {
val as i64
}
pub struct SystemzFullMCEncoder;
impl SystemzFullMCEncoder {
pub fn new() -> Self {
SystemzFullMCEncoder
}
pub fn encode_rr_instr(opcode: u8, r1: u8, r2: u8) -> Vec<u8> {
encode_rr(opcode, r1, r2)
}
pub fn encode_rx_instr(opcode: u8, r1: u8, x2: u8, b2: u8, d2: u16) -> Vec<u8> {
encode_rx(opcode, r1, x2, b2, d2)
}
pub fn encode_rxy_instr(opcode: u8, r1: u8, x2: u8, b2: u8, d2: i32, op2: u8) -> Vec<u8> {
encode_rxy(opcode, r1, x2, b2, d2, op2)
}
pub fn encode_ri_instr(opcode: u8, r1: u8, op2: u8, i2: i16) -> Vec<u8> {
encode_ri(opcode, r1, op2, i2)
}
pub fn encode_ril_instr(opcode: u8, r1: u8, op2: u8, i2: i32) -> Vec<u8> {
encode_ril(opcode, r1, op2, i2)
}
pub fn encode_rre_instr(opcode: u16, r1: u8, r2: u8) -> Vec<u8> {
encode_rre(opcode, r1, r2)
}
pub fn encode_rrf_instr(opcode: u16, r1: u8, r2: u8, r3: u8, m4: u8) -> Vec<u8> {
encode_rrf(opcode, r1, r2, r3, m4)
}
pub fn encode_si_instr(opcode: u8, i2: u8, b1: u8, d1: u16) -> Vec<u8> {
encode_si(opcode, i2, b1, d1)
}
pub fn encode_sil_instr(opcode: u16, b1: u8, d1: u16, i2: u16) -> Vec<u8> {
encode_sil(opcode, b1, d1, i2)
}
pub fn encode_rs_instr(opcode: u8, r1: u8, r3: u8, b2: u8, d2: u16) -> Vec<u8> {
encode_rs(opcode, r1, r3, b2, d2)
}
pub fn encode_rsy_instr(opcode: u8, r1: u8, r3: u8, b2: u8, d2: i32, op2: u8) -> Vec<u8> {
encode_rsy(opcode, r1, r3, b2, d2, op2)
}
pub fn encode_ss_instr(opcode: u8, len: u8, b1: u8, d1: u16, b2: u8, d2: u16) -> Vec<u8> {
encode_ss(opcode, len, b1, d1, b2, d2)
}
pub fn encode_sse_instr(opcode: u16, b1: u8, d1: u16, b2: u8, d2: u16) -> Vec<u8> {
encode_sse(opcode, b1, d1, b2, d2)
}
pub fn encode_vrx_instr(opcode: u16, v1: u8, x2: u8, b2: u8, d2: u16, m3: u8) -> Vec<u8> {
encode_vrx(opcode, v1, x2, b2, d2, m3)
}
pub fn encode_vsi_instr(opcode: u16, v1: u8, b2: u8, d2: u16, i3: u8) -> Vec<u8> {
encode_vsi(opcode, v1, b2, d2, i3)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_encode_rr() {
let bytes = encode_rr(0x07, 14, 14); assert_eq!(bytes, vec![0x07, 0xFE]);
}
#[test]
fn test_encode_rx() {
let bytes = encode_rx(0x58, 1, 0, 3, 0x10); assert_eq!(bytes.len(), 4);
assert_eq!(bytes[0], 0x58);
}
#[test]
fn test_encode_rxy() {
let bytes = encode_rxy(0xE3, 1, 0, 3, 4096, 0x04); assert_eq!(bytes.len(), 6);
assert_eq!(bytes[0], 0xE3);
assert_eq!(bytes[5], 0x04);
}
#[test]
fn test_encode_ri() {
let bytes = encode_ri(0xA7, 1, 0x0A, 42); assert_eq!(bytes.len(), 4);
assert_eq!(bytes[0], 0xA7);
}
#[test]
fn test_encode_ril() {
let bytes = encode_ril(0xC0, 1, 0x00, 0x12345678); assert_eq!(bytes.len(), 6);
assert_eq!(bytes[0], 0xC0);
}
#[test]
fn test_encode_rre() {
let bytes = encode_rre(0xB904, 1, 2); assert_eq!(bytes.len(), 4);
assert_eq!(bytes[0], 0xB9);
assert_eq!(bytes[1], 0x04);
}
#[test]
fn test_encode_rrf() {
let bytes = encode_rrf(0xB9E2, 1, 2, 3, 8); assert_eq!(bytes.len(), 4);
assert_eq!(bytes[0], 0xB9);
assert_eq!(bytes[1], 0xE2);
}
#[test]
fn test_encode_si() {
let bytes = encode_si(0x92, 0xFF, 3, 0x10); assert_eq!(bytes.len(), 4);
}
#[test]
fn test_encode_ss() {
let bytes = encode_ss(0xD2, 8, 3, 0x100, 4, 0x200); assert_eq!(bytes.len(), 6);
assert_eq!(bytes[0], 0xD2);
assert_eq!(bytes[1], 7); }
#[test]
fn test_encode_ss_length_zero() {
let bytes = encode_ss(0xD2, 0, 3, 0x100, 4, 0x200); assert_eq!(bytes[1], 0);
}
#[test]
fn test_encode_sse() {
let bytes = encode_sse(0xE502, 3, 0x100, 4, 0x200);
assert_eq!(bytes.len(), 6);
assert_eq!(bytes[0], 0xE5);
assert_eq!(bytes[1], 0x02);
}
#[test]
fn test_encode_rs() {
let bytes = encode_rs(0x98, 1, 2, 3, 0x10); assert_eq!(bytes.len(), 4);
}
#[test]
fn test_encode_rsy() {
let bytes = encode_rsy(0xEB, 1, 2, 3, 65536, 0x04);
assert_eq!(bytes.len(), 6);
}
#[test]
fn test_encode_sil() {
let bytes = encode_sil(0xE54C, 3, 0x100, 0xABCD);
assert_eq!(bytes.len(), 6);
}
#[test]
fn test_encode_rie() {
let bytes = encode_rie(0xEC, 1, 0x0D, 2, 0, 100, 0x44);
assert_eq!(bytes.len(), 6);
assert_eq!(bytes[0], 0xEC);
}
#[test]
fn test_encode_ris() {
let bytes = encode_ris(0xEC, 1, 0x05, 3, 0x100, 0xAB, 0x59);
assert_eq!(bytes.len(), 6);
}
#[test]
fn test_encode_rsl() {
let bytes = encode_rsl(0xEB, 1, 2, 3, 0x100, 0x0E, 0x80);
assert_eq!(bytes.len(), 6);
}
#[test]
fn test_encode_rsi() {
let bytes = encode_rsi(0xEB, 1, 2, 100);
assert_eq!(bytes.len(), 4);
}
#[test]
fn test_encode_vri() {
let bytes = encode_vri(0xE700, 3, 5, 7, 0x123, 0x0A);
assert_eq!(bytes.len(), 6);
}
#[test]
fn test_encode_vrs() {
let bytes = encode_vrs(0xE700, 3, 5, 2, 0x0C, 0x08);
assert_eq!(bytes.len(), 6);
}
#[test]
fn test_encode_vrv() {
let bytes = encode_vrv(0xE700, 3, 5, 2, 0x0C, 7, 0x08);
assert_eq!(bytes.len(), 6);
}
#[test]
fn test_encode_vrx() {
let bytes = encode_vrx(0xE706, 3, 0, 4, 0x100, 0x0A);
assert_eq!(bytes.len(), 6);
}
#[test]
fn test_encode_vsi() {
let bytes = encode_vsi(0xE700, 3, 4, 0x100, 0xAB);
assert_eq!(bytes.len(), 6);
}
#[test]
fn test_branch_disp16() {
let disp = encode_branch_disp16(0x1000);
assert_eq!(disp as i32, 0x800);
let decoded = decode_branch_disp16(disp);
assert_eq!(decoded, 0x1000);
}
#[test]
fn test_branch_disp32() {
let disp = encode_branch_disp32(0x10000);
assert_eq!(disp as i64, 0x8000);
let decoded = decode_branch_disp32(disp);
assert_eq!(decoded, 0x10000);
}
#[test]
fn test_branch_disp_negative() {
let disp = encode_branch_disp16(-256);
assert_eq!(decode_branch_disp16(disp), -256);
}
#[test]
fn test_is_s16() {
assert!(is_s16(0));
assert!(is_s16(32767));
assert!(is_s16(-32768));
assert!(!is_s16(32768));
assert!(!is_s16(-32769));
}
#[test]
fn test_is_u16() {
assert!(is_u16(0));
assert!(is_u16(65535));
assert!(!is_u16(65536));
}
#[test]
fn test_is_s32() {
assert!(is_s32(0));
assert!(is_s32(2147483647));
assert!(is_s32(-2147483648));
assert!(!is_s32(2147483648));
}
#[test]
fn test_encode_s16_succeed() {
assert_eq!(encode_s16(42), Some(42));
assert_eq!(encode_s16(-1), Some(-1));
assert_eq!(encode_s16(32768), None);
}
#[test]
fn test_encode_u16_succeed() {
assert_eq!(encode_u16(42), Some(42));
assert_eq!(encode_u16(65536), None);
}
#[test]
fn test_sext16() {
assert_eq!(sext16(-1i16), -1i64);
assert_eq!(sext16(42i16), 42i64);
}
#[test]
fn test_sext32() {
assert_eq!(sext32(-1i32), -1i64);
}
#[test]
fn test_encoding_builder() {
let mut builder = SystemzEncodingBuilder::new();
builder.u8(0x07).reg(14, 4).reg(14, 0);
assert_eq!(builder.build(), vec![0x07, 0xFE]);
}
#[test]
fn test_full_encoder_rr() {
let enc = SystemzFullMCEncoder::new();
let bytes = enc.encode_rr_instr(0x07, 14, 14);
assert_eq!(bytes, vec![0x07, 0xFE]);
}
#[test]
fn test_full_encoder_all_formats() {
let enc = SystemzFullMCEncoder::new();
assert_eq!(enc.encode_rr_instr(0x07, 1, 2).len(), 2);
assert_eq!(enc.encode_rx_instr(0x58, 1, 0, 3, 0).len(), 4);
assert_eq!(enc.encode_ri_instr(0xA7, 1, 0x0A, 42).len(), 4);
assert_eq!(enc.encode_ril_instr(0xC0, 1, 0, 0).len(), 6);
assert_eq!(enc.encode_rre_instr(0xB904, 1, 2).len(), 4);
assert_eq!(enc.encode_rrf_instr(0xB9E2, 1, 2, 3, 8).len(), 4);
assert_eq!(enc.encode_si_instr(0x92, 0, 3, 0).len(), 4);
assert_eq!(enc.encode_ss_instr(0xD2, 1, 3, 0, 4, 0).len(), 6);
assert_eq!(enc.encode_sse_instr(0xE502, 3, 0, 4, 0).len(), 6);
assert_eq!(enc.encode_rs_instr(0x98, 1, 2, 3, 0).len(), 4);
assert_eq!(enc.encode_rsy_instr(0xEB, 1, 2, 3, 0, 0x04).len(), 6);
assert_eq!(enc.encode_sil_instr(0xE54C, 3, 0, 0).len(), 6);
}
#[test]
fn test_encode_ss_multiple_lengths() {
for len in 0..16u8 {
let bytes = encode_ss(0xD2, len, 3, 0x100, 4, 0x200);
let expected_encoded = if len == 0 { 0 } else { len - 1 };
assert_eq!(
bytes[1], expected_encoded,
"len={} should encode as {}",
len, expected_encoded
);
}
}
#[test]
fn test_encode_rx_displacement_limits() {
let bytes = encode_rx(0x58, 1, 0, 3, 4095);
assert_eq!(bytes.len(), 4);
let bytes = encode_rx(0x58, 1, 0, 3, 0);
assert_eq!(bytes.len(), 4);
}
#[test]
fn test_encode_rxy_displacement_limits() {
let bytes = encode_rxy(0xE3, 1, 0, 3, -524288, 0x04);
assert_eq!(bytes.len(), 6);
let bytes = encode_rxy(0xE3, 1, 0, 3, 524287, 0x04);
assert_eq!(bytes.len(), 6);
}
#[test]
fn test_encode_ri_negative_immediate() {
let bytes = encode_ri(0xA7, 1, 0x0A, -100);
assert_eq!(bytes.len(), 4);
let i2_field = ((bytes[2] as u16) << 8) | (bytes[3] as u16);
assert_eq!(i2_field as i16, -100i16);
}
#[test]
fn test_encode_rxy_negative_displacement() {
let bytes = encode_rxy(0xE3, 1, 0, 3, -4096, 0x04);
assert_eq!(bytes.len(), 6);
}
#[test]
fn test_encode_rsy_displacement() {
let bytes = encode_rsy(0xEB, 1, 2, 3, 1048576, 0x04);
assert_eq!(bytes.len(), 6);
}
#[test]
fn test_is_u8() {
assert!(is_u8(0));
assert!(is_u8(255));
assert!(!is_u8(256));
}
#[test]
fn test_encode_builder_complex() {
let mut builder = SystemzEncodingBuilder::new();
builder.u8(0xB9).u8(0x04);
builder.reg(1, 4);
builder.bytes[0] |= 0; let bytes = builder.build();
assert_eq!(bytes.len(), 2);
}
#[test]
fn test_encode_ri_multiple_values() {
let tests = [
(42_i16, vec![0xA7, 0x1A, 0x00, 0x2A]),
(-1_i16, vec![0xA7, 0x1A, 0xFF, 0xFF]),
];
for &(imm, expected) in &tests {
let bytes = encode_ri(0xA7, 1, 0x0A, imm);
assert_eq!(bytes[2..], expected[2..], "imm={}", imm);
}
}
#[test]
fn test_encode_ril_all() {
let tests = [0x00000000i32, 0x7FFFFFFFi32, -1i32, 0x80000000u32 as i32];
for &imm in &tests {
let bytes = encode_ril(0xC0, 1, 0x00, imm);
assert_eq!(bytes.len(), 6);
}
}
#[test]
fn test_encode_si_multiple() {
for i2 in 0..=255u8 {
let bytes = encode_si(0x92, i2, 3, 0x100);
assert_eq!(bytes.len(), 4);
assert_eq!(bytes[1], i2, "i2={} not encoded", i2);
}
}
#[test]
fn test_encode_rrf_masks() {
for m4 in 0..16u8 {
let bytes = encode_rrf(0xB9E2, 1, 2, 3, m4);
assert_eq!(bytes.len(), 4);
}
}
#[test]
fn test_encode_ss_all_bases() {
for b1 in 0..16u8 {
for b2 in 0..16u8 {
let bytes = encode_ss(0xD2, 8, b1, 0x100, b2, 0x200);
assert_eq!(bytes.len(), 6);
}
}
}
#[test]
fn test_encode_vri_multiple() {
for v1 in 0..32u8 {
if v1 == 5 {
continue;
} let bytes = encode_vri(0xE700, v1, 3, 7, 0x100, 0x0A);
assert_eq!(bytes.len(), 6);
}
}
#[test]
fn test_encode_vrs_multiple() {
for r3 in 0..16u8 {
let bytes = encode_vrs(0xE700, 3, 5, r3, 0x0C, 0x08);
assert_eq!(bytes.len(), 6);
}
}
#[test]
fn test_encode_vrv_multiple() {
for v4 in 0..32u8 {
if v4 % 8 != 0 {
continue;
}
let bytes = encode_vrv(0xE700, 3, 5, 2, 0x0C, v4, 0x08);
assert_eq!(bytes.len(), 6);
}
}
#[test]
fn test_encode_vrx_displacement() {
for d2 in [0u16, 0xFFF, 0x7FF, 0x100, 0x800] {
let bytes = encode_vrx(0xE706, 3, 0, 4, d2, 0x0A);
assert_eq!(bytes.len(), 6);
}
}
#[test]
fn test_encode_vsi_displacement() {
for d2 in [0u16, 0xFFF, 0x100] {
let bytes = encode_vsi(0xE700, 3, 4, d2, 0xAB);
assert_eq!(bytes.len(), 6);
}
}
#[test]
fn test_branch_disp16_roundtrip() {
let tests = [0, 2, -2, 0x1000, -0x1000, 0x7FFE, -0x8000];
for &disp in &tests {
let encoded = encode_branch_disp16(disp);
let decoded = decode_branch_disp16(encoded);
assert_eq!(decoded, disp, "roundtrip failed for {}", disp);
}
}
#[test]
fn test_branch_disp32_roundtrip() {
let tests: &[i64] = &[0, 2, -2, 0x10000, -0x10000, 0x7FFFFFFE, -0x80000000];
for &disp in tests {
let encoded = encode_branch_disp32(disp);
let decoded = decode_branch_disp32(encoded);
assert_eq!(decoded, disp, "roundtrip failed for {}", disp);
}
}
#[test]
fn test_full_encoder_vector_instrs() {
let enc = SystemzFullMCEncoder::new();
assert_eq!(enc.encode_vrx_instr(0xE706, 3, 0, 4, 0x100, 0x0A).len(), 6);
assert_eq!(enc.encode_vsi_instr(0xE700, 3, 4, 0x100, 0xAB).len(), 6);
}
#[test]
fn test_encode_rie_all_combinations() {
let enc = SystemzFullMCEncoder::new();
for r1 in 0..4u8 {
for r3 in 0..4u8 {
let bytes = encode_rie(0xEC, r1, 0x0D, r3, 0, 42, 0x44);
assert_eq!(bytes.len(), 6);
}
}
}
#[test]
fn test_encode_ris_all() {
for m3 in 0..4u8 {
let bytes = encode_ris(0xEC, 1, m3, 3, 0x100, 0xAB, 0x59);
assert_eq!(bytes.len(), 6);
}
}
#[test]
fn test_extend_immediates() {
assert_eq!(sext16(-1i16), -1i64);
assert_eq!(sext16(32767i16), 32767i64);
assert_eq!(sext32(-1i32), -1i64);
assert_eq!(sext32(2147483647i32), 2147483647i64);
}
}