use crate::systemz::systemz_instr_info::{SystemzInstrInfo, SystemzOpcode};
use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SystemzFullSelOpcode {
Add32,
Add64,
AddImm16,
AddImm32,
Sub32,
Sub64,
SubImm16,
Mul32,
Mul64,
MulImm16,
SDiv32,
SDiv64,
UDiv32,
UDiv64,
SRem32,
SRem64,
URem32,
URem64,
And32,
And64,
AndImm16,
Or32,
Or64,
OrImm16,
Xor32,
Xor64,
XorImm16,
Neg32,
Neg64,
Abs32,
Abs64,
Shl32,
Shl64,
ShlImm,
Sra32,
Sra64,
SraImm,
Srl32,
Srl64,
SrlImm,
Rotl32,
Rotl64,
Load8,
Load8Sext,
Load8Zext,
Load16,
Load16Sext,
Load16Zext,
Load32,
Load32Sext,
Load32Zext,
Load64,
LoadAddr,
LoadAddrLong,
LoadImm16,
LoadImm32,
LoadImm64,
LoadHalfUpper,
LoadHalfLower,
Store8,
Store16,
Store32,
Store64,
StoreChar,
Cmp32,
Cmp64,
Cmp8,
Cmp16,
CmpImm16,
CmpImm32,
CmpLogical32,
CmpLogical64,
CmpLogicalImm16,
TestUnderMask8,
TestUnderMask16,
Br,
BrCond,
BrCondLong,
BrCount,
BrCount64,
BrIndex,
BrIndex64,
Call,
CallReg,
Return,
FAdd32,
FAdd64,
FAdd128,
FSub32,
FSub64,
FSub128,
FMul32,
FMul64,
FMul128,
FDiv32,
FDiv64,
FDiv128,
FCmp32,
FCmp64,
FCmp128,
FNeg32,
FNeg64,
FAbs32,
FAbs64,
FSqrt32,
FSqrt64,
FSqrt128,
Fma32,
Fma64,
FConv,
VAddB,
VAddH,
VAddF,
VAddG,
VSubB,
VSubH,
VSubF,
VSubG,
VMulB,
VMulH,
VMulF,
VMulG,
VMulLo,
VMulHi,
VAnd,
VOr,
VXor,
VNot,
VCmpEq,
VCmpGt,
VCmpLt,
VShift,
VPerm,
VSplat,
DecAdd,
DecSub,
DecMul,
DecDiv,
DecCmp,
DecTest,
DecPack,
DecUnpk,
DecShift,
DecEdit,
DecCvtToBin,
DecCvtFromBin,
CipherMsg,
CipherMsgChained,
CipherMsgCounter,
ComputeIntMsgDigest,
ComputeLastMsgDigest,
ComputeMsgAuthCode,
Copy,
CopyToReg,
CopyFromReg,
Constant32,
Constant64,
FrameIndex,
GlobalAddr,
Trap,
Noop,
}
#[derive(Debug, Clone)]
pub struct SystemzFullSelNode {
pub opcode: SystemzFullSelOpcode,
pub operands: Vec<SystemzFullOperand>,
pub result_reg: Option<u8>,
pub phys_reg: Option<u8>,
pub cc_user: bool,
}
#[derive(Debug, Clone)]
pub enum SystemzFullOperand {
Gpr(u8),
Fpr(u8),
Vr(u8),
Ar(u8),
Imm8(i8),
Imm16(i16),
Imm32(i32),
Imm64(i64),
ImmU8(u8),
ImmU16(u16),
ImmU32(u32),
Addr {
base: u8,
disp: i64,
index: Option<u8>,
},
AddrLong {
base: u8,
disp: i64,
index: Option<u8>,
},
Label(String),
CC(u8),
Mask(u8),
Length(u8),
ShiftAmount(u8),
}
pub struct SystemzFullInstructionSelector {
instr_info: SystemzInstrInfo,
reg_map: HashMap<u32, u8>,
next_vreg: u32,
cc_map: HashMap<u32, u8>,
label_map: HashMap<String, u64>,
}
impl SystemzFullInstructionSelector {
pub fn new() -> Self {
SystemzFullInstructionSelector {
instr_info: SystemzInstrInfo::new(),
reg_map: HashMap::new(),
next_vreg: 0,
cc_map: HashMap::new(),
label_map: HashMap::new(),
}
}
fn alloc_vreg(&mut self) -> u32 {
let vreg = self.next_vreg;
self.next_vreg += 1;
vreg
}
pub fn select_add(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
let mut result = Vec::new();
match node.opcode {
SystemzFullSelOpcode::Add32 => {
result.push(SystemzFullSelNode {
opcode: SystemzFullSelOpcode::Add32,
operands: vec![
SystemzFullOperand::Gpr(node.result_reg.unwrap_or(0)),
SystemzFullOperand::Gpr(0),
],
result_reg: node.result_reg,
phys_reg: None,
cc_user: true,
});
}
SystemzFullSelOpcode::Add64 => {
result.push(SystemzFullSelNode {
opcode: SystemzFullSelOpcode::Add64,
operands: vec![
SystemzFullOperand::Gpr(node.result_reg.unwrap_or(0)),
SystemzFullOperand::Gpr(0),
],
result_reg: node.result_reg,
phys_reg: None,
cc_user: true,
});
}
SystemzFullSelOpcode::AddImm16 => {
if let Some(imm) = node.operands.iter().find_map(|o| {
if let SystemzFullOperand::Imm16(v) = o {
Some(*v)
} else {
None
}
}) {
result.push(SystemzFullSelNode {
opcode: SystemzFullSelOpcode::AddImm16,
operands: vec![
SystemzFullOperand::Gpr(node.result_reg.unwrap_or(0)),
SystemzFullOperand::Imm16(imm),
],
result_reg: node.result_reg,
phys_reg: None,
cc_user: true,
});
}
}
_ => {}
}
result
}
pub fn select_sub(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
let mut result = Vec::new();
match node.opcode {
SystemzFullSelOpcode::Sub32 | SystemzFullSelOpcode::Sub64 => {
result.push(SystemzFullSelNode {
opcode: node.opcode,
operands: vec![
SystemzFullOperand::Gpr(node.result_reg.unwrap_or(0)),
SystemzFullOperand::Gpr(0),
],
result_reg: node.result_reg,
phys_reg: None,
cc_user: true,
});
}
_ => {}
}
result
}
pub fn select_and(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
match node.opcode {
SystemzFullSelOpcode::And32 | SystemzFullSelOpcode::And64 => {
vec![SystemzFullSelNode {
opcode: node.opcode,
operands: vec![
SystemzFullOperand::Gpr(node.result_reg.unwrap_or(0)),
SystemzFullOperand::Gpr(0),
],
result_reg: node.result_reg,
phys_reg: None,
cc_user: true,
}]
}
SystemzFullSelOpcode::AndImm16 => {
let imm = node.operands.iter().find_map(|o| {
if let SystemzFullOperand::ImmU16(v) = o {
Some(*v)
} else {
None
}
});
imm.map(|i| SystemzFullSelNode {
opcode: node.opcode,
operands: vec![
SystemzFullOperand::Gpr(node.result_reg.unwrap_or(0)),
SystemzFullOperand::ImmU16(i),
],
result_reg: node.result_reg,
phys_reg: None,
cc_user: true,
})
.into_iter()
.collect()
}
_ => Vec::new(),
}
}
pub fn select_or(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
match node.opcode {
SystemzFullSelOpcode::Or32 | SystemzFullSelOpcode::Or64 => {
vec![SystemzFullSelNode {
opcode: node.opcode,
operands: vec![
SystemzFullOperand::Gpr(node.result_reg.unwrap_or(0)),
SystemzFullOperand::Gpr(0),
],
result_reg: node.result_reg,
phys_reg: None,
cc_user: true,
}]
}
SystemzFullSelOpcode::OrImm16 => {
let imm = node.operands.iter().find_map(|o| {
if let SystemzFullOperand::ImmU16(v) = o {
Some(*v)
} else {
None
}
});
imm.map(|i| SystemzFullSelNode {
opcode: node.opcode,
operands: vec![
SystemzFullOperand::Gpr(node.result_reg.unwrap_or(0)),
SystemzFullOperand::ImmU16(i),
],
result_reg: node.result_reg,
phys_reg: None,
cc_user: true,
})
.into_iter()
.collect()
}
_ => Vec::new(),
}
}
pub fn select_xor(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
match node.opcode {
SystemzFullSelOpcode::Xor32 | SystemzFullSelOpcode::Xor64 => {
vec![SystemzFullSelNode {
opcode: node.opcode,
operands: vec![
SystemzFullOperand::Gpr(node.result_reg.unwrap_or(0)),
SystemzFullOperand::Gpr(0),
],
result_reg: node.result_reg,
phys_reg: None,
cc_user: true,
}]
}
_ => Vec::new(),
}
}
pub fn select_mul(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
let result_reg = node.result_reg.unwrap_or(0);
match node.opcode {
SystemzFullSelOpcode::Mul32 => {
vec![SystemzFullSelNode {
opcode: SystemzFullSelOpcode::Mul32,
operands: vec![
SystemzFullOperand::Gpr(result_reg),
SystemzFullOperand::Gpr(0),
],
result_reg: Some(result_reg),
phys_reg: None,
cc_user: false,
}]
}
SystemzFullSelOpcode::Mul64 => {
vec![SystemzFullSelNode {
opcode: SystemzFullSelOpcode::Mul64,
operands: vec![
SystemzFullOperand::Gpr(result_reg & 0xE), SystemzFullOperand::Gpr(0),
],
result_reg: Some(result_reg & 0xE),
phys_reg: None,
cc_user: false,
}]
}
_ => Vec::new(),
}
}
pub fn select_div(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
let result_reg = node.result_reg.unwrap_or(0) & 0xE; match node.opcode {
SystemzFullSelOpcode::SDiv32 => {
vec![SystemzFullSelNode {
opcode: SystemzFullSelOpcode::SDiv32,
operands: vec![
SystemzFullOperand::Gpr(result_reg),
SystemzFullOperand::Gpr(0),
],
result_reg: Some(result_reg),
phys_reg: None,
cc_user: false,
}]
}
SystemzFullSelOpcode::SDiv64 => {
vec![SystemzFullSelNode {
opcode: SystemzFullSelOpcode::SDiv64,
operands: vec![
SystemzFullOperand::Gpr(result_reg),
SystemzFullOperand::Gpr(0),
],
result_reg: Some(result_reg),
phys_reg: None,
cc_user: false,
}]
}
SystemzFullSelOpcode::UDiv32 | SystemzFullSelOpcode::UDiv64 => {
vec![SystemzFullSelNode {
opcode: node.opcode,
operands: vec![
SystemzFullOperand::Gpr(result_reg),
SystemzFullOperand::Gpr(0),
],
result_reg: Some(result_reg),
phys_reg: None,
cc_user: false,
}]
}
_ => Vec::new(),
}
}
pub fn select_load(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
let result_reg = node.result_reg.unwrap_or(0);
let addr = node.operands.iter().find_map(|o| {
if let SystemzFullOperand::Addr { base, disp, index } = o {
Some((*base, *disp, *index))
} else {
None
}
});
if let Some((base, disp, index)) = addr {
vec![SystemzFullSelNode {
opcode: node.opcode,
operands: vec![
SystemzFullOperand::Gpr(result_reg),
SystemzFullOperand::Addr {
base,
disp: disp as i64,
index,
},
],
result_reg: Some(result_reg),
phys_reg: None,
cc_user: false,
}]
} else {
Vec::new()
}
}
pub fn select_store(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
let src_reg = node.operands.first().and_then(|o| {
if let SystemzFullOperand::Gpr(r) = o {
Some(*r)
} else {
None
}
});
let addr = node.operands.iter().skip(1).find_map(|o| {
if let SystemzFullOperand::Addr { base, disp, index } = o {
Some((*base, *disp, *index))
} else {
None
}
});
if let (Some(src), Some((base, disp, index))) = (src_reg, addr) {
vec![SystemzFullSelNode {
opcode: node.opcode,
operands: vec![
SystemzFullOperand::Gpr(src),
SystemzFullOperand::Addr { base, disp, index },
],
result_reg: None,
phys_reg: None,
cc_user: false,
}]
} else {
Vec::new()
}
}
pub fn select_load_addr(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
let result_reg = node.result_reg.unwrap_or(0);
vec![SystemzFullSelNode {
opcode: node.opcode,
operands: vec![
SystemzFullOperand::Gpr(result_reg),
node.operands
.get(1)
.cloned()
.unwrap_or(SystemzFullOperand::Imm32(0)),
],
result_reg: Some(result_reg),
phys_reg: None,
cc_user: false,
}]
}
pub fn select_load_imm(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
let result_reg = node.result_reg.unwrap_or(0);
let imm = node.operands.iter().find_map(|o| match o {
SystemzFullOperand::Imm16(v) => Some(*v as i64),
SystemzFullOperand::Imm32(v) => Some(*v as i64),
SystemzFullOperand::Imm64(v) => Some(*v),
_ => None,
});
if let Some(value) = imm {
vec![SystemzFullSelNode {
opcode: node.opcode,
operands: vec![
SystemzFullOperand::Gpr(result_reg),
SystemzFullOperand::Imm64(value),
],
result_reg: Some(result_reg),
phys_reg: None,
cc_user: false,
}]
} else {
Vec::new()
}
}
pub fn select_compare(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
let r1 = node.operands.iter().find_map(|o| {
if let SystemzFullOperand::Gpr(r) = o {
Some(*r)
} else {
None
}
});
let r2_or_imm = node.operands.get(1).cloned();
if let Some(r1) = r1 {
vec![SystemzFullSelNode {
opcode: node.opcode,
operands: {
let mut ops = vec![SystemzFullOperand::Gpr(r1)];
if let Some(o) = r2_or_imm {
ops.push(o);
}
ops
},
result_reg: None,
phys_reg: None,
cc_user: true, }]
} else {
Vec::new()
}
}
pub fn select_branch(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
match node.opcode {
SystemzFullSelOpcode::Br => {
let target = node.operands.iter().find_map(|o| {
if let SystemzFullOperand::Label(s) = o {
Some(s.clone())
} else {
None
}
});
target
.map(|t| SystemzFullSelNode {
opcode: SystemzFullSelOpcode::Br,
operands: vec![
SystemzFullOperand::Mask(15), SystemzFullOperand::Label(t),
],
result_reg: None,
phys_reg: None,
cc_user: false,
})
.into_iter()
.collect()
}
SystemzFullSelOpcode::BrCond => {
let cond = node.operands.iter().find_map(|o| {
if let SystemzFullOperand::Mask(m) = o {
Some(*m)
} else {
None
}
});
let target = node.operands.iter().find_map(|o| {
if let SystemzFullOperand::Label(s) = o {
Some(s.clone())
} else {
None
}
});
if let (Some(mask), Some(target)) = (cond, target) {
vec![SystemzFullSelNode {
opcode: SystemzFullSelOpcode::BrCond,
operands: vec![
SystemzFullOperand::Mask(mask),
SystemzFullOperand::Label(target),
],
result_reg: None,
phys_reg: None,
cc_user: false,
}]
} else {
Vec::new()
}
}
SystemzFullSelOpcode::BrCondLong => {
let cond = node.operands.iter().find_map(|o| {
if let SystemzFullOperand::Mask(m) = o {
Some(*m)
} else {
None
}
});
let target = node.operands.iter().find_map(|o| {
if let SystemzFullOperand::Label(s) = o {
Some(s.clone())
} else {
None
}
});
if let (Some(mask), Some(target)) = (cond, target) {
vec![SystemzFullSelNode {
opcode: SystemzFullSelOpcode::BrCondLong,
operands: vec![
SystemzFullOperand::Mask(mask),
SystemzFullOperand::Label(target),
],
result_reg: None,
phys_reg: None,
cc_user: false,
}]
} else {
Vec::new()
}
}
SystemzFullSelOpcode::BrCount => {
vec![SystemzFullSelNode {
opcode: SystemzFullSelOpcode::BrCount,
operands: node.operands.clone(),
result_reg: None,
phys_reg: None,
cc_user: false,
}]
}
SystemzFullSelOpcode::BrCount64 => {
vec![SystemzFullSelNode {
opcode: SystemzFullSelOpcode::BrCount64,
operands: node.operands.clone(),
result_reg: None,
phys_reg: None,
cc_user: false,
}]
}
SystemzFullSelOpcode::Call => {
let target = node.operands.iter().find_map(|o| {
if let SystemzFullOperand::Label(s) = o {
Some(s.clone())
} else {
None
}
});
target
.map(|t| SystemzFullSelNode {
opcode: SystemzFullSelOpcode::Call,
operands: vec![
SystemzFullOperand::Gpr(14), SystemzFullOperand::Label(t),
],
result_reg: None,
phys_reg: None,
cc_user: false,
})
.into_iter()
.collect()
}
SystemzFullSelOpcode::CallReg => {
let target_reg = node.operands.iter().find_map(|o| {
if let SystemzFullOperand::Gpr(r) = o {
Some(*r)
} else {
None
}
});
target_reg
.map(|r| SystemzFullSelNode {
opcode: SystemzFullSelOpcode::CallReg,
operands: vec![SystemzFullOperand::Gpr(14), SystemzFullOperand::Gpr(r)],
result_reg: None,
phys_reg: None,
cc_user: false,
})
.into_iter()
.collect()
}
SystemzFullSelOpcode::Return => {
vec![SystemzFullSelNode {
opcode: SystemzFullSelOpcode::Return,
operands: vec![SystemzFullOperand::Mask(15), SystemzFullOperand::Gpr(14)],
result_reg: None,
phys_reg: None,
cc_user: false,
}]
}
_ => Vec::new(),
}
}
pub fn select_fadd(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
let r1 = node.operands.iter().find_map(|o| {
if let SystemzFullOperand::Fpr(r) = o {
Some(*r)
} else {
None
}
});
let r2 = node.operands.iter().skip(1).find_map(|o| {
if let SystemzFullOperand::Fpr(r) = o {
Some(*r)
} else {
None
}
});
if let (Some(r1), Some(r2)) = (r1, r2) {
vec![SystemzFullSelNode {
opcode: node.opcode,
operands: vec![SystemzFullOperand::Fpr(r1), SystemzFullOperand::Fpr(r2)],
result_reg: node.result_reg,
phys_reg: None,
cc_user: false,
}]
} else {
Vec::new()
}
}
pub fn select_fsub(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
self.select_fadd(node) }
pub fn select_fmul(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
self.select_fadd(node) }
pub fn select_fdiv(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
self.select_fadd(node) }
pub fn select_fcmp(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
self.select_fadd(node) }
pub fn select_vadd(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
let v1 = node.operands.iter().find_map(|o| {
if let SystemzFullOperand::Vr(v) = o {
Some(*v)
} else {
None
}
});
let v2 = node.operands.iter().skip(1).find_map(|o| {
if let SystemzFullOperand::Vr(v) = o {
Some(*v)
} else {
None
}
});
let v3 = node.operands.iter().skip(2).find_map(|o| {
if let SystemzFullOperand::Vr(v) = o {
Some(*v)
} else {
None
}
});
if let (Some(v1), Some(v2), Some(v3)) = (v1, v2, v3) {
vec![SystemzFullSelNode {
opcode: node.opcode,
operands: vec![
SystemzFullOperand::Vr(v1),
SystemzFullOperand::Vr(v2),
SystemzFullOperand::Vr(v3),
],
result_reg: node.result_reg,
phys_reg: None,
cc_user: false,
}]
} else {
Vec::new()
}
}
pub fn select_vsub(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
self.select_vadd(node)
}
pub fn select_vmul(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
self.select_vadd(node)
}
pub fn select_vand(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
self.select_vadd(node)
}
pub fn select_decimal_arith(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
let l1 = node.operands.iter().find_map(|o| {
if let SystemzFullOperand::Length(l) = o {
Some(*l)
} else {
None
}
});
let l2 = node.operands.iter().skip(1).find_map(|o| {
if let SystemzFullOperand::Length(l) = o {
Some(*l)
} else {
None
}
});
if let (Some(l1), Some(l2)) = (l1, l2) {
vec![SystemzFullSelNode {
opcode: node.opcode,
operands: vec![
SystemzFullOperand::Length(l1),
SystemzFullOperand::Length(l2),
],
result_reg: node.result_reg,
phys_reg: None,
cc_user: true,
}]
} else {
Vec::new()
}
}
pub fn select_decimal_cmp(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
self.select_decimal_arith(node)
}
pub fn select_decimal_test(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
vec![SystemzFullSelNode {
opcode: SystemzFullSelOpcode::DecTest,
operands: node.operands.clone(),
result_reg: None,
phys_reg: None,
cc_user: true,
}]
}
pub fn select_zap(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
vec![SystemzFullSelNode {
opcode: SystemzFullSelOpcode::DecAdd,
operands: node.operands.clone(),
result_reg: node.result_reg,
phys_reg: None,
cc_user: true,
}]
}
pub fn select_edit(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
vec![SystemzFullSelNode {
opcode: node.opcode,
operands: node.operands.clone(),
result_reg: node.result_reg,
phys_reg: None,
cc_user: true,
}]
}
pub fn select_srp(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
vec![SystemzFullSelNode {
opcode: SystemzFullSelOpcode::DecShift,
operands: node.operands.clone(),
result_reg: node.result_reg,
phys_reg: None,
cc_user: true,
}]
}
pub fn select_cvb(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
vec![SystemzFullSelNode {
opcode: SystemzFullSelOpcode::DecCvtToBin,
operands: node.operands.clone(),
result_reg: node.result_reg,
phys_reg: None,
cc_user: false,
}]
}
pub fn select_cvd(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
vec![SystemzFullSelNode {
opcode: SystemzFullSelOpcode::DecCvtFromBin,
operands: node.operands.clone(),
result_reg: node.result_reg,
phys_reg: None,
cc_user: false,
}]
}
pub fn select_cipher_msg(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
vec![SystemzFullSelNode {
opcode: SystemzFullSelOpcode::CipherMsg,
operands: node.operands.clone(),
result_reg: node.result_reg,
phys_reg: None,
cc_user: true,
}]
}
pub fn select_cipher_msg_chained(
&mut self,
node: &SystemzFullSelNode,
) -> Vec<SystemzFullSelNode> {
vec![SystemzFullSelNode {
opcode: SystemzFullSelOpcode::CipherMsgChained,
operands: node.operands.clone(),
result_reg: node.result_reg,
phys_reg: None,
cc_user: true,
}]
}
pub fn select_cipher_msg_counter(
&mut self,
node: &SystemzFullSelNode,
) -> Vec<SystemzFullSelNode> {
vec![SystemzFullSelNode {
opcode: SystemzFullSelOpcode::CipherMsgCounter,
operands: node.operands.clone(),
result_reg: node.result_reg,
phys_reg: None,
cc_user: true,
}]
}
pub fn select_imd(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
vec![SystemzFullSelNode {
opcode: SystemzFullSelOpcode::ComputeIntMsgDigest,
operands: node.operands.clone(),
result_reg: node.result_reg,
phys_reg: None,
cc_user: true,
}]
}
pub fn select_lmd(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
vec![SystemzFullSelNode {
opcode: SystemzFullSelOpcode::ComputeLastMsgDigest,
operands: node.operands.clone(),
result_reg: node.result_reg,
phys_reg: None,
cc_user: true,
}]
}
pub fn select_mac(&mut self, node: &SystemzFullSelNode) -> Vec<SystemzFullSelNode> {
vec![SystemzFullSelNode {
opcode: SystemzFullSelOpcode::ComputeMsgAuthCode,
operands: node.operands.clone(),
result_reg: node.result_reg,
phys_reg: None,
cc_user: true,
}]
}
}
pub mod cc_masks {
pub const ALWAYS: u8 = 15; pub const NEVER: u8 = 0; pub const EQUAL: u8 = 8; pub const NOT_EQUAL: u8 = 7; pub const LOW: u8 = 4; pub const NOT_LOW: u8 = 11; pub const HIGH: u8 = 2; pub const NOT_HIGH: u8 = 13; pub const OVERFLOW: u8 = 1; pub const NOT_OVERFLOW: u8 = 14; pub const LE: u8 = 12; pub const GT: u8 = 3; pub const LT: u8 = 4; pub const GE: u8 = 11; }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_select_add_32() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::Add32,
operands: vec![SystemzFullOperand::Gpr(1), SystemzFullOperand::Gpr(2)],
result_reg: Some(1),
phys_reg: None,
cc_user: true,
};
let result = sel.select_add(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_mul_32() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::Mul32,
operands: vec![SystemzFullOperand::Gpr(0), SystemzFullOperand::Gpr(2)],
result_reg: Some(0),
phys_reg: None,
cc_user: false,
};
let result = sel.select_mul(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_branch_unconditional() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::Br,
operands: vec![SystemzFullOperand::Label("target".to_string())],
result_reg: None,
phys_reg: None,
cc_user: false,
};
let result = sel.select_branch(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_branch_conditional() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::BrCond,
operands: vec![
SystemzFullOperand::Mask(cc_masks::EQUAL),
SystemzFullOperand::Label("target".to_string()),
],
result_reg: None,
phys_reg: None,
cc_user: false,
};
let result = sel.select_branch(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_call() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::Call,
operands: vec![SystemzFullOperand::Label("printf".to_string())],
result_reg: None,
phys_reg: None,
cc_user: false,
};
let result = sel.select_branch(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_return() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::Return,
operands: Vec::new(),
result_reg: None,
phys_reg: None,
cc_user: false,
};
let result = sel.select_branch(&node);
assert!(!result.is_empty());
assert_eq!(result[0].operands.len(), 2);
}
#[test]
fn test_select_fadd() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::FAdd32,
operands: vec![SystemzFullOperand::Fpr(0), SystemzFullOperand::Fpr(2)],
result_reg: Some(0),
phys_reg: None,
cc_user: false,
};
let result = sel.select_fadd(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_vadd() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::VAddB,
operands: vec![
SystemzFullOperand::Vr(0),
SystemzFullOperand::Vr(1),
SystemzFullOperand::Vr(2),
],
result_reg: Some(0),
phys_reg: None,
cc_user: false,
};
let result = sel.select_vadd(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_decimal_arith() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::DecAdd,
operands: vec![SystemzFullOperand::Length(8), SystemzFullOperand::Length(4)],
result_reg: Some(0),
phys_reg: None,
cc_user: true,
};
let result = sel.select_decimal_arith(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_cipher() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::CipherMsg,
operands: vec![SystemzFullOperand::Gpr(0), SystemzFullOperand::Gpr(1)],
result_reg: Some(0),
phys_reg: None,
cc_user: true,
};
let result = sel.select_cipher_msg(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_load() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::Load32,
operands: vec![
SystemzFullOperand::Gpr(1),
SystemzFullOperand::Addr {
base: 3,
disp: 0,
index: None,
},
],
result_reg: Some(1),
phys_reg: None,
cc_user: false,
};
let result = sel.select_load(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_store() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::Store32,
operands: vec![
SystemzFullOperand::Gpr(2),
SystemzFullOperand::Addr {
base: 3,
disp: 8,
index: None,
},
],
result_reg: None,
phys_reg: None,
cc_user: false,
};
let result = sel.select_store(&node);
assert!(!result.is_empty());
}
#[test]
fn test_cc_masks_values() {
assert_eq!(cc_masks::ALWAYS, 15);
assert_eq!(cc_masks::EQUAL, 8);
assert_eq!(cc_masks::NOT_EQUAL, 7);
assert_eq!(cc_masks::LOW, 4);
assert_eq!(cc_masks::HIGH, 2);
}
#[test]
fn test_select_load_imm() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::LoadImm16,
operands: vec![SystemzFullOperand::Gpr(1), SystemzFullOperand::Imm16(42)],
result_reg: Some(1),
phys_reg: None,
cc_user: false,
};
let result = sel.select_load_imm(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_compare() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::Cmp32,
operands: vec![SystemzFullOperand::Gpr(1), SystemzFullOperand::Gpr(2)],
result_reg: None,
phys_reg: None,
cc_user: true,
};
let result = sel.select_compare(&node);
assert!(!result.is_empty());
assert!(result[0].cc_user);
}
#[test]
fn test_select_div_64() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::SDiv64,
operands: vec![SystemzFullOperand::Gpr(0), SystemzFullOperand::Gpr(2)],
result_reg: Some(0),
phys_reg: None,
cc_user: false,
};
let result = sel.select_div(&node);
assert!(!result.is_empty());
}
#[test]
fn test_all_crypto_ops() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::CipherMsgCounter,
operands: vec![SystemzFullOperand::Gpr(0)],
result_reg: Some(0),
phys_reg: None,
cc_user: true,
};
assert!(!sel.select_cipher_msg_counter(&node).is_empty());
assert!(!sel.select_imd(&node).is_empty());
assert!(!sel.select_lmd(&node).is_empty());
assert!(!sel.select_mac(&node).is_empty());
}
#[test]
fn test_select_zap_edit_srp_cvb_cvd() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::DecAdd,
operands: vec![SystemzFullOperand::Length(4)],
result_reg: Some(0),
phys_reg: None,
cc_user: true,
};
assert!(!sel.select_zap(&node).is_empty());
assert!(!sel.select_edit(&node).is_empty());
assert!(!sel.select_srp(&node).is_empty());
assert!(!sel.select_cvb(&node).is_empty());
assert!(!sel.select_cvd(&node).is_empty());
}
#[test]
fn test_select_load_all_sizes() {
let mut sel = SystemzFullInstructionSelector::new();
let ops = vec![
SystemzFullSelOpcode::Load8,
SystemzFullSelOpcode::Load8Sext,
SystemzFullSelOpcode::Load8Zext,
SystemzFullSelOpcode::Load16,
SystemzFullSelOpcode::Load16Sext,
SystemzFullSelOpcode::Load16Zext,
SystemzFullSelOpcode::Load32,
SystemzFullSelOpcode::Load64,
];
for op in &ops {
let node = SystemzFullSelNode {
opcode: *op,
operands: vec![
SystemzFullOperand::Gpr(1),
SystemzFullOperand::Addr {
base: 5,
disp: 0,
index: None,
},
],
result_reg: Some(1),
phys_reg: None,
cc_user: false,
};
let result = sel.select_load(&node);
assert!(!result.is_empty(), "load {:?} produced empty result", op);
}
}
#[test]
fn test_select_store_all_sizes() {
let mut sel = SystemzFullInstructionSelector::new();
let ops = vec![
SystemzFullSelOpcode::Store8,
SystemzFullSelOpcode::Store16,
SystemzFullSelOpcode::Store32,
SystemzFullSelOpcode::Store64,
];
for op in &ops {
let node = SystemzFullSelNode {
opcode: *op,
operands: vec![
SystemzFullOperand::Gpr(2),
SystemzFullOperand::Addr {
base: 5,
disp: 16,
index: Some(4),
},
],
result_reg: None,
phys_reg: None,
cc_user: false,
};
let result = sel.select_store(&node);
assert!(!result.is_empty(), "store {:?} produced empty result", op);
}
}
#[test]
fn test_select_and_or_xor_all() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::And32,
operands: vec![SystemzFullOperand::Gpr(1), SystemzFullOperand::Gpr(2)],
result_reg: Some(1),
phys_reg: None,
cc_user: true,
};
assert!(!sel.select_and(&node).is_empty());
assert!(!sel.select_or(&node).is_empty());
assert!(!sel.select_xor(&node).is_empty());
}
#[test]
fn test_select_and_imm() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::AndImm16,
operands: vec![
SystemzFullOperand::Gpr(3),
SystemzFullOperand::ImmU16(0xFF00),
],
result_reg: Some(3),
phys_reg: None,
cc_user: true,
};
let result = sel.select_and(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_or_imm() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::OrImm16,
operands: vec![
SystemzFullOperand::Gpr(4),
SystemzFullOperand::ImmU16(0x00FF),
],
result_reg: Some(4),
phys_reg: None,
cc_user: true,
};
let result = sel.select_or(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_sub_all() {
let mut sel = SystemzFullInstructionSelector::new();
for op in &[SystemzFullSelOpcode::Sub32, SystemzFullSelOpcode::Sub64] {
let node = SystemzFullSelNode {
opcode: *op,
operands: vec![SystemzFullOperand::Gpr(1), SystemzFullOperand::Gpr(2)],
result_reg: Some(1),
phys_reg: None,
cc_user: true,
};
assert!(!sel.select_sub(&node).is_empty(), "sub {:?} empty", op);
}
}
#[test]
fn test_select_add_imm16() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::AddImm16,
operands: vec![SystemzFullOperand::Gpr(5), SystemzFullOperand::Imm16(100)],
result_reg: Some(5),
phys_reg: None,
cc_user: true,
};
let result = sel.select_add(&node);
assert!(!result.is_empty());
}
#[test]
fn test_cc_masks_all() {
assert_eq!(cc_masks::NEVER, 0);
assert_eq!(cc_masks::LE, 12);
assert_eq!(cc_masks::GT, 3);
assert_eq!(cc_masks::LT, 4);
assert_eq!(cc_masks::GE, 11);
assert_eq!(cc_masks::OVERFLOW, 1);
assert_eq!(cc_masks::NOT_OVERFLOW, 14);
}
#[test]
fn test_select_branch_count() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::BrCount,
operands: vec![
SystemzFullOperand::Gpr(8),
SystemzFullOperand::Label("loop".to_string()),
],
result_reg: None,
phys_reg: None,
cc_user: false,
};
let result = sel.select_branch(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_branch_count_64() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::BrCount64,
operands: vec![
SystemzFullOperand::Gpr(9),
SystemzFullOperand::Label("loop64".to_string()),
],
result_reg: None,
phys_reg: None,
cc_user: false,
};
let result = sel.select_branch(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_call_reg() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::CallReg,
operands: vec![SystemzFullOperand::Gpr(2)],
result_reg: None,
phys_reg: None,
cc_user: false,
};
let result = sel.select_branch(&node);
assert!(!result.is_empty());
assert_eq!(result[0].operands[0], SystemzFullOperand::Gpr(14));
}
#[test]
fn test_select_branch_cond_long() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::BrCondLong,
operands: vec![
SystemzFullOperand::Mask(cc_masks::NOT_EQUAL),
SystemzFullOperand::Label("far_target".to_string()),
],
result_reg: None,
phys_reg: None,
cc_user: false,
};
let result = sel.select_branch(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_fcmp() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::FCmp64,
operands: vec![SystemzFullOperand::Fpr(2), SystemzFullOperand::Fpr(4)],
result_reg: None,
phys_reg: None,
cc_user: true,
};
let result = sel.select_fcmp(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_fsub_fmul_fdiv() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::FSub64,
operands: vec![SystemzFullOperand::Fpr(0), SystemzFullOperand::Fpr(2)],
result_reg: Some(0),
phys_reg: None,
cc_user: false,
};
assert!(!sel.select_fsub(&node).is_empty());
assert!(!sel.select_fmul(&node).is_empty());
assert!(!sel.select_fdiv(&node).is_empty());
}
#[test]
fn test_select_vsub_vmul_vand() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::VSubB,
operands: vec![
SystemzFullOperand::Vr(0),
SystemzFullOperand::Vr(1),
SystemzFullOperand::Vr(3),
],
result_reg: Some(0),
phys_reg: None,
cc_user: false,
};
assert!(!sel.select_vsub(&node).is_empty());
assert!(!sel.select_vmul(&node).is_empty());
assert!(!sel.select_vand(&node).is_empty());
}
#[test]
fn test_select_decimal_cmp() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::DecCmp,
operands: vec![
SystemzFullOperand::Length(10),
SystemzFullOperand::Length(5),
],
result_reg: None,
phys_reg: None,
cc_user: true,
};
assert!(!sel.select_decimal_cmp(&node).is_empty());
}
#[test]
fn test_select_decimal_test() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::DecTest,
operands: vec![SystemzFullOperand::Length(6)],
result_reg: None,
phys_reg: None,
cc_user: true,
};
assert!(!sel.select_decimal_test(&node).is_empty());
}
#[test]
fn test_select_vsub_vmul_vand_all() {
let mut sel = SystemzFullInstructionSelector::new();
let ops = vec![
SystemzFullSelOpcode::VSubB,
SystemzFullSelOpcode::VSubH,
SystemzFullSelOpcode::VSubF,
SystemzFullSelOpcode::VSubG,
];
for op in &ops {
let node = SystemzFullSelNode {
opcode: *op,
operands: vec![
SystemzFullOperand::Vr(1),
SystemzFullOperand::Vr(2),
SystemzFullOperand::Vr(3),
],
result_reg: Some(1),
phys_reg: None,
cc_user: false,
};
assert!(!sel.select_vsub(&node).is_empty(), "{:?} empty", op);
}
}
#[test]
fn test_select_fadd_all_sizes() {
let mut sel = SystemzFullInstructionSelector::new();
let ops = vec![
SystemzFullSelOpcode::FAdd32,
SystemzFullSelOpcode::FAdd64,
SystemzFullSelOpcode::FSub32,
SystemzFullSelOpcode::FSub64,
SystemzFullSelOpcode::FMul32,
SystemzFullSelOpcode::FMul64,
SystemzFullSelOpcode::FDiv32,
SystemzFullSelOpcode::FDiv64,
];
for op in &ops {
let node = SystemzFullSelNode {
opcode: *op,
operands: vec![SystemzFullOperand::Fpr(0), SystemzFullOperand::Fpr(2)],
result_reg: Some(0),
phys_reg: None,
cc_user: false,
};
assert!(!sel.select_fadd(&node).is_empty(), "{:?} empty", op);
}
}
#[test]
fn test_select_all_vadd_ops() {
let mut sel = SystemzFullInstructionSelector::new();
let ops = vec![
SystemzFullSelOpcode::VAddB,
SystemzFullSelOpcode::VAddH,
SystemzFullSelOpcode::VAddF,
SystemzFullSelOpcode::VAddG,
];
for op in &ops {
let node = SystemzFullSelNode {
opcode: *op,
operands: vec![
SystemzFullOperand::Vr(0),
SystemzFullOperand::Vr(1),
SystemzFullOperand::Vr(2),
],
result_reg: Some(0),
phys_reg: None,
cc_user: false,
};
assert!(!sel.select_vadd(&node).is_empty(), "{:?} empty", op);
}
}
#[test]
fn test_select_all_decimal_ops() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::DecAdd,
operands: vec![SystemzFullOperand::Length(8), SystemzFullOperand::Length(4)],
result_reg: Some(0),
phys_reg: None,
cc_user: true,
};
assert!(!sel.select_decimal_arith(&node).is_empty());
assert!(!sel.select_decimal_cmp(&node).is_empty());
assert!(!sel.select_decimal_test(&node).is_empty());
assert!(!sel.select_zap(&node).is_empty());
assert!(!sel.select_edit(&node).is_empty());
assert!(!sel.select_srp(&node).is_empty());
}
#[test]
fn test_select_cipher_all() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::CipherMsg,
operands: vec![SystemzFullOperand::Gpr(0), SystemzFullOperand::Gpr(1)],
result_reg: Some(0),
phys_reg: None,
cc_user: true,
};
assert!(!sel.select_cipher_msg(&node).is_empty());
assert!(!sel.select_cipher_msg_chained(&node).is_empty());
assert!(!sel.select_cipher_msg_counter(&node).is_empty());
assert!(!sel.select_imd(&node).is_empty());
assert!(!sel.select_lmd(&node).is_empty());
assert!(!sel.select_mac(&node).is_empty());
}
#[test]
fn test_select_add_negative_imm() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::AddImm16,
operands: vec![SystemzFullOperand::Gpr(3), SystemzFullOperand::Imm16(-100)],
result_reg: Some(3),
phys_reg: None,
cc_user: true,
};
let result = sel.select_add(&node);
assert!(!result.is_empty());
}
#[test]
fn test_select_compare_imm() {
let mut sel = SystemzFullInstructionSelector::new();
let node = SystemzFullSelNode {
opcode: SystemzFullSelOpcode::CmpImm16,
operands: vec![SystemzFullOperand::Gpr(5), SystemzFullOperand::Imm16(0)],
result_reg: None,
phys_reg: None,
cc_user: true,
};
let result = sel.select_compare(&node);
assert!(!result.is_empty());
assert!(result[0].cc_user);
}
#[test]
fn test_select_load_addr_all() {
let mut sel = SystemzFullInstructionSelector::new();
let ops = vec![
SystemzFullSelOpcode::LoadAddr,
SystemzFullSelOpcode::LoadAddrLong,
];
for op in &ops {
let node = SystemzFullSelNode {
opcode: *op,
operands: vec![
SystemzFullOperand::Gpr(1),
SystemzFullOperand::Addr {
base: 5,
disp: 256,
index: None,
},
],
result_reg: Some(1),
phys_reg: None,
cc_user: false,
};
assert!(!sel.select_load_addr(&node).is_empty(), "{:?}", op);
}
}
#[test]
fn test_select_load_imm_all() {
let mut sel = SystemzFullInstructionSelector::new();
let ops = vec![
SystemzFullSelOpcode::LoadImm16,
SystemzFullSelOpcode::LoadImm32,
SystemzFullSelOpcode::LoadImm64,
];
let tests: Vec<(SystemzFullSelOpcode, SystemzFullOperand)> = vec![
(
SystemzFullSelOpcode::LoadImm16,
SystemzFullOperand::Imm16(42),
),
(
SystemzFullSelOpcode::LoadImm32,
SystemzFullOperand::Imm32(100000),
),
(
SystemzFullSelOpcode::LoadImm64,
SystemzFullOperand::Imm64(0xDEADBEEF),
),
];
for (op, imm) in &tests {
let node = SystemzFullSelNode {
opcode: *op,
operands: vec![SystemzFullOperand::Gpr(1), imm.clone()],
result_reg: Some(1),
phys_reg: None,
cc_user: false,
};
assert!(!sel.select_load_imm(&node).is_empty(), "{:?}", op);
}
}
}