Support IBM z/Architecture
This adds support for the IBM z/Architecture (s390x-ibm-linux). The status of the s390x backend in its current form is: - Wasmtime is fully functional and passes all tests on s390x. - All back-end features supported, with the exception of SIMD. - There is still a lot of potential for performance improvements. - Currently the only supported processor type is z15.
This commit is contained in:
7
build.rs
7
build.rs
@@ -219,6 +219,9 @@ fn ignore(testsuite: &str, testname: &str, strategy: &str) -> bool {
|
|||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
"Cranelift" => match (testsuite, testname) {
|
"Cranelift" => match (testsuite, testname) {
|
||||||
|
// No simd support yet for s390x.
|
||||||
|
("simd", _) if platform_is_s390x() => return true,
|
||||||
|
|
||||||
("simd", _) if cfg!(feature = "old-x86-backend") => return true, // skip all SIMD tests on old backend.
|
("simd", _) if cfg!(feature = "old-x86-backend") => return true, // skip all SIMD tests on old backend.
|
||||||
// These are new instructions that are not really implemented in any backend.
|
// These are new instructions that are not really implemented in any backend.
|
||||||
("simd", "simd_i8x16_arith2")
|
("simd", "simd_i8x16_arith2")
|
||||||
@@ -243,3 +246,7 @@ fn ignore(testsuite: &str, testname: &str, strategy: &str) -> bool {
|
|||||||
fn platform_is_x64() -> bool {
|
fn platform_is_x64() -> bool {
|
||||||
env::var("CARGO_CFG_TARGET_ARCH").unwrap() == "x86_64"
|
env::var("CARGO_CFG_TARGET_ARCH").unwrap() == "x86_64"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn platform_is_s390x() -> bool {
|
||||||
|
env::var("CARGO_CFG_TARGET_ARCH").unwrap() == "s390x"
|
||||||
|
}
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ unwind = ["gimli"]
|
|||||||
x86 = []
|
x86 = []
|
||||||
arm64 = []
|
arm64 = []
|
||||||
riscv = []
|
riscv = []
|
||||||
|
s390x = []
|
||||||
arm32 = [] # Work-in-progress codegen backend for ARM.
|
arm32 = [] # Work-in-progress codegen backend for ARM.
|
||||||
|
|
||||||
# Stub feature that does nothing, for Cargo-features compatibility: the new
|
# Stub feature that does nothing, for Cargo-features compatibility: the new
|
||||||
@@ -75,7 +76,8 @@ old-x86-backend = []
|
|||||||
all-arch = [
|
all-arch = [
|
||||||
"x86",
|
"x86",
|
||||||
"arm64",
|
"arm64",
|
||||||
"riscv"
|
"riscv",
|
||||||
|
"s390x"
|
||||||
]
|
]
|
||||||
|
|
||||||
# For dependent crates that want to serialize some parts of cranelift
|
# For dependent crates that want to serialize some parts of cranelift
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use std::fmt;
|
|||||||
mod arm32;
|
mod arm32;
|
||||||
mod arm64;
|
mod arm64;
|
||||||
mod riscv;
|
mod riscv;
|
||||||
|
mod s390x;
|
||||||
pub(crate) mod x86;
|
pub(crate) mod x86;
|
||||||
|
|
||||||
/// Represents known ISA target.
|
/// Represents known ISA target.
|
||||||
@@ -15,6 +16,7 @@ pub enum Isa {
|
|||||||
X86,
|
X86,
|
||||||
Arm32,
|
Arm32,
|
||||||
Arm64,
|
Arm64,
|
||||||
|
S390x,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Isa {
|
impl Isa {
|
||||||
@@ -31,6 +33,7 @@ impl Isa {
|
|||||||
match arch {
|
match arch {
|
||||||
"riscv" => Some(Isa::Riscv),
|
"riscv" => Some(Isa::Riscv),
|
||||||
"aarch64" => Some(Isa::Arm64),
|
"aarch64" => Some(Isa::Arm64),
|
||||||
|
"s390x" => Some(Isa::S390x),
|
||||||
x if ["x86_64", "i386", "i586", "i686"].contains(&x) => Some(Isa::X86),
|
x if ["x86_64", "i386", "i586", "i686"].contains(&x) => Some(Isa::X86),
|
||||||
x if x.starts_with("arm") || arch.starts_with("thumb") => Some(Isa::Arm32),
|
x if x.starts_with("arm") || arch.starts_with("thumb") => Some(Isa::Arm32),
|
||||||
_ => None,
|
_ => None,
|
||||||
@@ -39,7 +42,7 @@ impl Isa {
|
|||||||
|
|
||||||
/// Returns all supported isa targets.
|
/// Returns all supported isa targets.
|
||||||
pub fn all() -> &'static [Isa] {
|
pub fn all() -> &'static [Isa] {
|
||||||
&[Isa::Riscv, Isa::X86, Isa::Arm32, Isa::Arm64]
|
&[Isa::Riscv, Isa::X86, Isa::Arm32, Isa::Arm64, Isa::S390x]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +54,7 @@ impl fmt::Display for Isa {
|
|||||||
Isa::X86 => write!(f, "x86"),
|
Isa::X86 => write!(f, "x86"),
|
||||||
Isa::Arm32 => write!(f, "arm32"),
|
Isa::Arm32 => write!(f, "arm32"),
|
||||||
Isa::Arm64 => write!(f, "arm64"),
|
Isa::Arm64 => write!(f, "arm64"),
|
||||||
|
Isa::S390x => write!(f, "s390x"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,6 +66,7 @@ pub(crate) fn define(isas: &[Isa], shared_defs: &mut SharedDefinitions) -> Vec<T
|
|||||||
Isa::X86 => x86::define(shared_defs),
|
Isa::X86 => x86::define(shared_defs),
|
||||||
Isa::Arm32 => arm32::define(shared_defs),
|
Isa::Arm32 => arm32::define(shared_defs),
|
||||||
Isa::Arm64 => arm64::define(shared_defs),
|
Isa::Arm64 => arm64::define(shared_defs),
|
||||||
|
Isa::S390x => s390x::define(shared_defs),
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|||||||
31
cranelift/codegen/meta/src/isa/s390x/mod.rs
Normal file
31
cranelift/codegen/meta/src/isa/s390x/mod.rs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
use crate::cdsl::cpu_modes::CpuMode;
|
||||||
|
use crate::cdsl::instructions::{InstructionGroupBuilder, InstructionPredicateMap};
|
||||||
|
use crate::cdsl::isa::TargetIsa;
|
||||||
|
use crate::cdsl::recipes::Recipes;
|
||||||
|
use crate::cdsl::regs::IsaRegsBuilder;
|
||||||
|
use crate::cdsl::settings::SettingGroupBuilder;
|
||||||
|
|
||||||
|
use crate::shared::Definitions as SharedDefinitions;
|
||||||
|
|
||||||
|
pub(crate) fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
|
||||||
|
let inst_group = InstructionGroupBuilder::new(&mut shared_defs.all_instructions).build();
|
||||||
|
let settings = SettingGroupBuilder::new("s390x").build();
|
||||||
|
let regs = IsaRegsBuilder::new().build();
|
||||||
|
let recipes = Recipes::new();
|
||||||
|
let encodings_predicates = InstructionPredicateMap::new();
|
||||||
|
|
||||||
|
let mut mode = CpuMode::new("s390x");
|
||||||
|
let expand = shared_defs.transform_groups.by_name("expand");
|
||||||
|
mode.legalize_default(expand);
|
||||||
|
let cpu_modes = vec![mode];
|
||||||
|
|
||||||
|
TargetIsa::new(
|
||||||
|
"s390x",
|
||||||
|
inst_group,
|
||||||
|
settings,
|
||||||
|
regs,
|
||||||
|
recipes,
|
||||||
|
cpu_modes,
|
||||||
|
encodings_predicates,
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -116,6 +116,9 @@ pub fn generate(
|
|||||||
isa::Isa::Arm64 => {
|
isa::Isa::Arm64 => {
|
||||||
// aarch64 doesn't have platform-specific settings.
|
// aarch64 doesn't have platform-specific settings.
|
||||||
}
|
}
|
||||||
|
isa::Isa::S390x => {
|
||||||
|
// s390x doesn't have platform-specific settings.
|
||||||
|
}
|
||||||
isa::Isa::Arm32 | isa::Isa::Riscv => todo!(),
|
isa::Isa::Arm32 | isa::Isa::Riscv => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,6 +91,9 @@ mod arm32;
|
|||||||
#[cfg(feature = "arm64")]
|
#[cfg(feature = "arm64")]
|
||||||
pub(crate) mod aarch64;
|
pub(crate) mod aarch64;
|
||||||
|
|
||||||
|
#[cfg(feature = "s390x")]
|
||||||
|
mod s390x;
|
||||||
|
|
||||||
pub mod unwind;
|
pub mod unwind;
|
||||||
|
|
||||||
mod call_conv;
|
mod call_conv;
|
||||||
@@ -160,6 +163,7 @@ pub fn lookup_variant(triple: Triple, variant: BackendVariant) -> Result<Builder
|
|||||||
}
|
}
|
||||||
(Architecture::Arm { .. }, _) => isa_builder!(arm32, (feature = "arm32"), triple),
|
(Architecture::Arm { .. }, _) => isa_builder!(arm32, (feature = "arm32"), triple),
|
||||||
(Architecture::Aarch64 { .. }, _) => isa_builder!(aarch64, (feature = "arm64"), triple),
|
(Architecture::Aarch64 { .. }, _) => isa_builder!(aarch64, (feature = "arm64"), triple),
|
||||||
|
(Architecture::S390x { .. }, _) => isa_builder!(s390x, (feature = "s390x"), triple),
|
||||||
_ => Err(LookupError::Unsupported),
|
_ => Err(LookupError::Unsupported),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
770
cranelift/codegen/src/isa/s390x/abi.rs
Normal file
770
cranelift/codegen/src/isa/s390x/abi.rs
Normal file
@@ -0,0 +1,770 @@
|
|||||||
|
//! Implementation of a standard S390x ABI.
|
||||||
|
//!
|
||||||
|
//! This machine uses the "vanilla" ABI implementation from abi_impl.rs,
|
||||||
|
//! however a few details are different from the description there:
|
||||||
|
//!
|
||||||
|
//! - On s390x, the caller must provide a "register save area" of 160
|
||||||
|
//! bytes to any function it calls. The called function is free to use
|
||||||
|
//! this space for any purpose; usually to save callee-saved GPRs.
|
||||||
|
//! (Note that while this area is allocated by the caller, it is counted
|
||||||
|
//! as part of the callee's stack frame; in particular, the callee's CFA
|
||||||
|
//! is the top of the register save area, not the incoming SP value.)
|
||||||
|
//!
|
||||||
|
//! - Overflow arguments are passed on the stack starting immediately
|
||||||
|
//! above the register save area. On s390x, this space is allocated
|
||||||
|
//! only once directly in the prologue, using a size large enough to
|
||||||
|
//! hold overflow arguments for every call in the function.
|
||||||
|
//!
|
||||||
|
//! - On s390x we do not use a frame pointer register; instead, every
|
||||||
|
//! element of the stack frame is addressed via (constant) offsets
|
||||||
|
//! from the stack pointer. Note that due to the above (and because
|
||||||
|
//! there are no variable-sized stack allocations in cranelift), the
|
||||||
|
//! value of the stack pointer register never changes after the
|
||||||
|
//! initial allocation in the function prologue.
|
||||||
|
//!
|
||||||
|
//! Overall, the stack frame layout on s390x is as follows:
|
||||||
|
//!
|
||||||
|
//! ```plain
|
||||||
|
//! (high address)
|
||||||
|
//!
|
||||||
|
//! +---------------------------+
|
||||||
|
//! | ... |
|
||||||
|
//! CFA -----> | stack args |
|
||||||
|
//! +---------------------------+
|
||||||
|
//! | ... |
|
||||||
|
//! | 160 bytes reg save area |
|
||||||
|
//! SP at function entry -----> | (used to save GPRs) |
|
||||||
|
//! +---------------------------+
|
||||||
|
//! | ... |
|
||||||
|
//! | clobbered callee-saves |
|
||||||
|
//! | (used to save FPRs) |
|
||||||
|
//! unwind-frame base ----> | (alloc'd by prologue) |
|
||||||
|
//! +---------------------------+
|
||||||
|
//! | ... |
|
||||||
|
//! | spill slots |
|
||||||
|
//! | (accessed via nominal SP) |
|
||||||
|
//! | ... |
|
||||||
|
//! | stack slots |
|
||||||
|
//! | (accessed via nominal SP) |
|
||||||
|
//! nominal SP ---------------> | (alloc'd by prologue) |
|
||||||
|
//! +---------------------------+
|
||||||
|
//! | ... |
|
||||||
|
//! | args for call |
|
||||||
|
//! | outgoing reg save area |
|
||||||
|
//! SP during function ------> | (alloc'd by prologue) |
|
||||||
|
//! +---------------------------+
|
||||||
|
//!
|
||||||
|
//! (low address)
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
use crate::ir;
|
||||||
|
use crate::ir::condcodes::IntCC;
|
||||||
|
use crate::ir::types;
|
||||||
|
use crate::ir::MemFlags;
|
||||||
|
use crate::ir::Type;
|
||||||
|
use crate::isa;
|
||||||
|
use crate::isa::s390x::inst::*;
|
||||||
|
use crate::isa::unwind::UnwindInst;
|
||||||
|
use crate::machinst::*;
|
||||||
|
use crate::settings;
|
||||||
|
use crate::{CodegenError, CodegenResult};
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
use regalloc::{RealReg, Reg, RegClass, Set, Writable};
|
||||||
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
// We use a generic implementation that factors out ABI commonalities.
|
||||||
|
|
||||||
|
/// Support for the S390x ABI from the callee side (within a function body).
|
||||||
|
pub type S390xABICallee = ABICalleeImpl<S390xMachineDeps>;
|
||||||
|
|
||||||
|
/// Support for the S390x ABI from the caller side (at a callsite).
|
||||||
|
pub type S390xABICaller = ABICallerImpl<S390xMachineDeps>;
|
||||||
|
|
||||||
|
/// ABI Register usage
|
||||||
|
|
||||||
|
fn in_int_reg(ty: Type) -> bool {
|
||||||
|
match ty {
|
||||||
|
types::I8 | types::I16 | types::I32 | types::I64 | types::R64 => true,
|
||||||
|
types::B1 | types::B8 | types::B16 | types::B32 | types::B64 => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn in_flt_reg(ty: Type) -> bool {
|
||||||
|
match ty {
|
||||||
|
types::F32 | types::F64 => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_intreg_for_arg(idx: usize) -> Option<Reg> {
|
||||||
|
match idx {
|
||||||
|
0 => Some(regs::gpr(2)),
|
||||||
|
1 => Some(regs::gpr(3)),
|
||||||
|
2 => Some(regs::gpr(4)),
|
||||||
|
3 => Some(regs::gpr(5)),
|
||||||
|
4 => Some(regs::gpr(6)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_fltreg_for_arg(idx: usize) -> Option<Reg> {
|
||||||
|
match idx {
|
||||||
|
0 => Some(regs::fpr(0)),
|
||||||
|
1 => Some(regs::fpr(2)),
|
||||||
|
2 => Some(regs::fpr(4)),
|
||||||
|
3 => Some(regs::fpr(6)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_intreg_for_ret(idx: usize) -> Option<Reg> {
|
||||||
|
match idx {
|
||||||
|
0 => Some(regs::gpr(2)),
|
||||||
|
// ABI extension to support multi-value returns:
|
||||||
|
1 => Some(regs::gpr(3)),
|
||||||
|
2 => Some(regs::gpr(4)),
|
||||||
|
3 => Some(regs::gpr(5)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_fltreg_for_ret(idx: usize) -> Option<Reg> {
|
||||||
|
match idx {
|
||||||
|
0 => Some(regs::fpr(0)),
|
||||||
|
// ABI extension to support multi-value returns:
|
||||||
|
1 => Some(regs::fpr(2)),
|
||||||
|
2 => Some(regs::fpr(4)),
|
||||||
|
3 => Some(regs::fpr(6)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is the limit for the size of argument and return-value areas on the
|
||||||
|
/// stack. We place a reasonable limit here to avoid integer overflow issues
|
||||||
|
/// with 32-bit arithmetic: for now, 128 MB.
|
||||||
|
static STACK_ARG_RET_SIZE_LIMIT: u64 = 128 * 1024 * 1024;
|
||||||
|
|
||||||
|
impl Into<MemArg> for StackAMode {
|
||||||
|
fn into(self) -> MemArg {
|
||||||
|
match self {
|
||||||
|
StackAMode::FPOffset(off, _ty) => MemArg::InitialSPOffset { off },
|
||||||
|
StackAMode::NominalSPOffset(off, _ty) => MemArg::NominalSPOffset { off },
|
||||||
|
StackAMode::SPOffset(off, _ty) => {
|
||||||
|
MemArg::reg_plus_off(stack_reg(), off, MemFlags::trusted())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// S390x-specific ABI behavior. This struct just serves as an implementation
|
||||||
|
/// point for the trait; it is never actually instantiated.
|
||||||
|
pub struct S390xMachineDeps;
|
||||||
|
|
||||||
|
impl ABIMachineSpec for S390xMachineDeps {
|
||||||
|
type I = Inst;
|
||||||
|
|
||||||
|
fn word_bits() -> u32 {
|
||||||
|
64
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return required stack alignment in bytes.
|
||||||
|
fn stack_align(_call_conv: isa::CallConv) -> u32 {
|
||||||
|
8
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compute_arg_locs(
|
||||||
|
call_conv: isa::CallConv,
|
||||||
|
_flags: &settings::Flags,
|
||||||
|
params: &[ir::AbiParam],
|
||||||
|
args_or_rets: ArgsOrRets,
|
||||||
|
add_ret_area_ptr: bool,
|
||||||
|
) -> CodegenResult<(Vec<ABIArg>, i64, Option<usize>)> {
|
||||||
|
let mut next_gpr = 0;
|
||||||
|
let mut next_fpr = 0;
|
||||||
|
let mut next_stack: u64 = 0;
|
||||||
|
let mut ret = vec![];
|
||||||
|
|
||||||
|
if args_or_rets == ArgsOrRets::Args {
|
||||||
|
next_stack = 160;
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..params.len() {
|
||||||
|
let param = ¶ms[i];
|
||||||
|
|
||||||
|
// Validate "purpose".
|
||||||
|
match ¶m.purpose {
|
||||||
|
&ir::ArgumentPurpose::VMContext
|
||||||
|
| &ir::ArgumentPurpose::Normal
|
||||||
|
| &ir::ArgumentPurpose::StackLimit
|
||||||
|
| &ir::ArgumentPurpose::SignatureId => {}
|
||||||
|
_ => panic!(
|
||||||
|
"Unsupported argument purpose {:?} in signature: {:?}",
|
||||||
|
param.purpose, params
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
let intreg = in_int_reg(param.value_type);
|
||||||
|
let fltreg = in_flt_reg(param.value_type);
|
||||||
|
debug_assert!(intreg || fltreg);
|
||||||
|
debug_assert!(!(intreg && fltreg));
|
||||||
|
|
||||||
|
let (next_reg, candidate) = if intreg {
|
||||||
|
let candidate = match args_or_rets {
|
||||||
|
ArgsOrRets::Args => get_intreg_for_arg(next_gpr),
|
||||||
|
ArgsOrRets::Rets => get_intreg_for_ret(next_gpr),
|
||||||
|
};
|
||||||
|
(&mut next_gpr, candidate)
|
||||||
|
} else {
|
||||||
|
let candidate = match args_or_rets {
|
||||||
|
ArgsOrRets::Args => get_fltreg_for_arg(next_fpr),
|
||||||
|
ArgsOrRets::Rets => get_fltreg_for_ret(next_fpr),
|
||||||
|
};
|
||||||
|
(&mut next_fpr, candidate)
|
||||||
|
};
|
||||||
|
|
||||||
|
// In the Wasmtime ABI only the first return value can be in a register.
|
||||||
|
let candidate =
|
||||||
|
if call_conv.extends_wasmtime() && args_or_rets == ArgsOrRets::Rets && i > 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
candidate
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(reg) = candidate {
|
||||||
|
ret.push(ABIArg::reg(
|
||||||
|
reg.to_real_reg(),
|
||||||
|
param.value_type,
|
||||||
|
param.extension,
|
||||||
|
param.purpose,
|
||||||
|
));
|
||||||
|
*next_reg += 1;
|
||||||
|
} else {
|
||||||
|
// Compute size. Every argument or return value takes a slot of
|
||||||
|
// at least 8 bytes, except for return values in the Wasmtime ABI.
|
||||||
|
let size = (ty_bits(param.value_type) / 8) as u64;
|
||||||
|
let slot_size = if call_conv.extends_wasmtime() && args_or_rets == ArgsOrRets::Rets
|
||||||
|
{
|
||||||
|
size
|
||||||
|
} else {
|
||||||
|
std::cmp::max(size, 8)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Align the stack slot.
|
||||||
|
debug_assert!(slot_size.is_power_of_two());
|
||||||
|
next_stack = align_to(next_stack, slot_size);
|
||||||
|
|
||||||
|
// If the type is actually of smaller size (and the argument
|
||||||
|
// was not extended), it is passed right-aligned.
|
||||||
|
let offset = if size < slot_size && param.extension == ir::ArgumentExtension::None {
|
||||||
|
slot_size - size
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
ret.push(ABIArg::stack(
|
||||||
|
(next_stack + offset) as i64,
|
||||||
|
param.value_type,
|
||||||
|
param.extension,
|
||||||
|
param.purpose,
|
||||||
|
));
|
||||||
|
next_stack += slot_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next_stack = align_to(next_stack, 8);
|
||||||
|
|
||||||
|
let extra_arg = if add_ret_area_ptr {
|
||||||
|
debug_assert!(args_or_rets == ArgsOrRets::Args);
|
||||||
|
if let Some(reg) = get_intreg_for_arg(next_gpr) {
|
||||||
|
ret.push(ABIArg::reg(
|
||||||
|
reg.to_real_reg(),
|
||||||
|
types::I64,
|
||||||
|
ir::ArgumentExtension::None,
|
||||||
|
ir::ArgumentPurpose::Normal,
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
ret.push(ABIArg::stack(
|
||||||
|
next_stack as i64,
|
||||||
|
types::I64,
|
||||||
|
ir::ArgumentExtension::None,
|
||||||
|
ir::ArgumentPurpose::Normal,
|
||||||
|
));
|
||||||
|
next_stack += 8;
|
||||||
|
}
|
||||||
|
Some(ret.len() - 1)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
// To avoid overflow issues, limit the arg/return size to something
|
||||||
|
// reasonable -- here, 128 MB.
|
||||||
|
if next_stack > STACK_ARG_RET_SIZE_LIMIT {
|
||||||
|
return Err(CodegenError::ImplLimitExceeded);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((ret, next_stack as i64, extra_arg))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fp_to_arg_offset(_call_conv: isa::CallConv, _flags: &settings::Flags) -> i64 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_load_stack(mem: StackAMode, into_reg: Writable<Reg>, ty: Type) -> Inst {
|
||||||
|
Inst::gen_load(into_reg, mem.into(), ty)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_store_stack(mem: StackAMode, from_reg: Reg, ty: Type) -> Inst {
|
||||||
|
Inst::gen_store(mem.into(), from_reg, ty)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_move(to_reg: Writable<Reg>, from_reg: Reg, ty: Type) -> Inst {
|
||||||
|
Inst::gen_move(to_reg, from_reg, ty)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_extend(
|
||||||
|
to_reg: Writable<Reg>,
|
||||||
|
from_reg: Reg,
|
||||||
|
signed: bool,
|
||||||
|
from_bits: u8,
|
||||||
|
to_bits: u8,
|
||||||
|
) -> Inst {
|
||||||
|
assert!(from_bits < to_bits);
|
||||||
|
Inst::Extend {
|
||||||
|
rd: to_reg,
|
||||||
|
rn: from_reg,
|
||||||
|
signed,
|
||||||
|
from_bits,
|
||||||
|
to_bits,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_ret() -> Inst {
|
||||||
|
Inst::Ret { link: gpr(14) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_add_imm(into_reg: Writable<Reg>, from_reg: Reg, imm: u32) -> SmallInstVec<Inst> {
|
||||||
|
let mut insts = SmallVec::new();
|
||||||
|
if let Some(imm) = UImm12::maybe_from_u64(imm as u64) {
|
||||||
|
insts.push(Inst::LoadAddr {
|
||||||
|
rd: into_reg,
|
||||||
|
mem: MemArg::BXD12 {
|
||||||
|
base: from_reg,
|
||||||
|
index: zero_reg(),
|
||||||
|
disp: imm,
|
||||||
|
flags: MemFlags::trusted(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else if let Some(imm) = SImm20::maybe_from_i64(imm as i64) {
|
||||||
|
insts.push(Inst::LoadAddr {
|
||||||
|
rd: into_reg,
|
||||||
|
mem: MemArg::BXD20 {
|
||||||
|
base: from_reg,
|
||||||
|
index: zero_reg(),
|
||||||
|
disp: imm,
|
||||||
|
flags: MemFlags::trusted(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if from_reg != into_reg.to_reg() {
|
||||||
|
insts.push(Inst::mov64(into_reg, from_reg));
|
||||||
|
}
|
||||||
|
insts.push(Inst::AluRUImm32 {
|
||||||
|
alu_op: ALUOp::Add64,
|
||||||
|
rd: into_reg,
|
||||||
|
imm,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
insts
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_stack_lower_bound_trap(limit_reg: Reg) -> SmallInstVec<Inst> {
|
||||||
|
let mut insts = SmallVec::new();
|
||||||
|
insts.push(Inst::CmpTrapRR {
|
||||||
|
op: CmpOp::CmpL64,
|
||||||
|
rn: stack_reg(),
|
||||||
|
rm: limit_reg,
|
||||||
|
cond: Cond::from_intcc(IntCC::UnsignedLessThanOrEqual),
|
||||||
|
trap_code: ir::TrapCode::StackOverflow,
|
||||||
|
});
|
||||||
|
insts
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_epilogue_placeholder() -> Inst {
|
||||||
|
Inst::EpiloguePlaceholder
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_get_stack_addr(mem: StackAMode, into_reg: Writable<Reg>, _ty: Type) -> Inst {
|
||||||
|
let mem = mem.into();
|
||||||
|
Inst::LoadAddr { rd: into_reg, mem }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_stacklimit_reg() -> Reg {
|
||||||
|
spilltmp_reg()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_load_base_offset(into_reg: Writable<Reg>, base: Reg, offset: i32, ty: Type) -> Inst {
|
||||||
|
let mem = MemArg::reg_plus_off(base, offset.into(), MemFlags::trusted());
|
||||||
|
Inst::gen_load(into_reg, mem, ty)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_store_base_offset(base: Reg, offset: i32, from_reg: Reg, ty: Type) -> Inst {
|
||||||
|
let mem = MemArg::reg_plus_off(base, offset.into(), MemFlags::trusted());
|
||||||
|
Inst::gen_store(mem, from_reg, ty)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_sp_reg_adjust(imm: i32) -> SmallInstVec<Inst> {
|
||||||
|
if imm == 0 {
|
||||||
|
return SmallVec::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut insts = SmallVec::new();
|
||||||
|
if let Ok(imm) = i16::try_from(imm) {
|
||||||
|
insts.push(Inst::AluRSImm16 {
|
||||||
|
alu_op: ALUOp::Add64,
|
||||||
|
rd: writable_stack_reg(),
|
||||||
|
imm,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
insts.push(Inst::AluRSImm32 {
|
||||||
|
alu_op: ALUOp::Add64,
|
||||||
|
rd: writable_stack_reg(),
|
||||||
|
imm,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
insts
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_nominal_sp_adj(offset: i32) -> Inst {
|
||||||
|
Inst::VirtualSPOffsetAdj {
|
||||||
|
offset: offset.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_prologue_frame_setup(_flags: &settings::Flags) -> SmallInstVec<Inst> {
|
||||||
|
SmallVec::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_epilogue_frame_restore(_flags: &settings::Flags) -> SmallInstVec<Inst> {
|
||||||
|
SmallVec::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_probestack(_: u32) -> SmallInstVec<Self::I> {
|
||||||
|
// TODO: implement if we ever require stack probes on an s390x host
|
||||||
|
// (unlikely unless Lucet is ported)
|
||||||
|
smallvec![]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns stack bytes used as well as instructions. Does not adjust
|
||||||
|
// nominal SP offset; abi_impl generic code will do that.
|
||||||
|
fn gen_clobber_save(
|
||||||
|
call_conv: isa::CallConv,
|
||||||
|
flags: &settings::Flags,
|
||||||
|
clobbers: &Set<Writable<RealReg>>,
|
||||||
|
fixed_frame_storage_size: u32,
|
||||||
|
outgoing_args_size: u32,
|
||||||
|
) -> (u64, SmallVec<[Inst; 16]>) {
|
||||||
|
let mut insts = SmallVec::new();
|
||||||
|
|
||||||
|
// Collect clobbered registers.
|
||||||
|
let (clobbered_gpr, clobbered_fpr) = get_regs_saved_in_prologue(call_conv, clobbers);
|
||||||
|
let mut first_clobbered_gpr = 16;
|
||||||
|
for reg in clobbered_gpr {
|
||||||
|
let enc = reg.to_reg().get_hw_encoding();
|
||||||
|
if enc < first_clobbered_gpr {
|
||||||
|
first_clobbered_gpr = enc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let clobber_size = clobbered_fpr.len() * 8;
|
||||||
|
if flags.unwind_info() {
|
||||||
|
insts.push(Inst::Unwind {
|
||||||
|
inst: UnwindInst::DefineNewFrame {
|
||||||
|
offset_upward_to_caller_sp: 160,
|
||||||
|
offset_downward_to_clobbers: clobber_size as u32,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use STMG to save clobbered GPRs into save area.
|
||||||
|
if first_clobbered_gpr < 16 {
|
||||||
|
let offset = 8 * first_clobbered_gpr as i64;
|
||||||
|
insts.push(Inst::StoreMultiple64 {
|
||||||
|
rt: gpr(first_clobbered_gpr as u8),
|
||||||
|
rt2: gpr(15),
|
||||||
|
addr_reg: stack_reg(),
|
||||||
|
addr_off: SImm20::maybe_from_i64(offset).unwrap(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if flags.unwind_info() {
|
||||||
|
for i in first_clobbered_gpr..16 {
|
||||||
|
insts.push(Inst::Unwind {
|
||||||
|
inst: UnwindInst::SaveReg {
|
||||||
|
clobber_offset: clobber_size as u32 + (i * 8) as u32,
|
||||||
|
reg: gpr(i as u8).to_real_reg(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrement stack pointer.
|
||||||
|
let stack_size =
|
||||||
|
outgoing_args_size as i32 + clobber_size as i32 + fixed_frame_storage_size as i32;
|
||||||
|
insts.extend(Self::gen_sp_reg_adjust(-stack_size));
|
||||||
|
if flags.unwind_info() {
|
||||||
|
insts.push(Inst::Unwind {
|
||||||
|
inst: UnwindInst::StackAlloc {
|
||||||
|
size: stack_size as u32,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let sp_adj = outgoing_args_size as i32;
|
||||||
|
if sp_adj > 0 {
|
||||||
|
insts.push(Self::gen_nominal_sp_adj(sp_adj));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save FPRs.
|
||||||
|
for (i, reg) in clobbered_fpr.iter().enumerate() {
|
||||||
|
insts.push(Inst::FpuStore64 {
|
||||||
|
rd: reg.to_reg().to_reg(),
|
||||||
|
mem: MemArg::reg_plus_off(
|
||||||
|
stack_reg(),
|
||||||
|
(i * 8) as i64 + outgoing_args_size as i64 + fixed_frame_storage_size as i64,
|
||||||
|
MemFlags::trusted(),
|
||||||
|
),
|
||||||
|
});
|
||||||
|
if flags.unwind_info() {
|
||||||
|
insts.push(Inst::Unwind {
|
||||||
|
inst: UnwindInst::SaveReg {
|
||||||
|
clobber_offset: (i * 8) as u32,
|
||||||
|
reg: reg.to_reg(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(clobber_size as u64, insts)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_clobber_restore(
|
||||||
|
call_conv: isa::CallConv,
|
||||||
|
_: &settings::Flags,
|
||||||
|
clobbers: &Set<Writable<RealReg>>,
|
||||||
|
fixed_frame_storage_size: u32,
|
||||||
|
outgoing_args_size: u32,
|
||||||
|
) -> SmallVec<[Inst; 16]> {
|
||||||
|
let mut insts = SmallVec::new();
|
||||||
|
|
||||||
|
// Collect clobbered registers.
|
||||||
|
let (clobbered_gpr, clobbered_fpr) = get_regs_saved_in_prologue(call_conv, clobbers);
|
||||||
|
let mut first_clobbered_gpr = 16;
|
||||||
|
for reg in clobbered_gpr {
|
||||||
|
let enc = reg.to_reg().get_hw_encoding();
|
||||||
|
if enc < first_clobbered_gpr {
|
||||||
|
first_clobbered_gpr = enc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let clobber_size = clobbered_fpr.len() * 8;
|
||||||
|
|
||||||
|
// Restore FPRs.
|
||||||
|
for (i, reg) in clobbered_fpr.iter().enumerate() {
|
||||||
|
insts.push(Inst::FpuLoad64 {
|
||||||
|
rd: Writable::from_reg(reg.to_reg().to_reg()),
|
||||||
|
mem: MemArg::reg_plus_off(
|
||||||
|
stack_reg(),
|
||||||
|
(i * 8) as i64 + outgoing_args_size as i64 + fixed_frame_storage_size as i64,
|
||||||
|
MemFlags::trusted(),
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment stack pointer unless it will be restored implicitly.
|
||||||
|
let stack_size =
|
||||||
|
outgoing_args_size as i32 + clobber_size as i32 + fixed_frame_storage_size as i32;
|
||||||
|
let implicit_sp_restore = first_clobbered_gpr < 16
|
||||||
|
&& SImm20::maybe_from_i64(8 * first_clobbered_gpr as i64 + stack_size as i64).is_some();
|
||||||
|
if !implicit_sp_restore {
|
||||||
|
insts.extend(Self::gen_sp_reg_adjust(stack_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use LMG to restore clobbered GPRs from save area.
|
||||||
|
if first_clobbered_gpr < 16 {
|
||||||
|
let mut offset = 8 * first_clobbered_gpr as i64;
|
||||||
|
if implicit_sp_restore {
|
||||||
|
offset += stack_size as i64;
|
||||||
|
}
|
||||||
|
insts.push(Inst::LoadMultiple64 {
|
||||||
|
rt: writable_gpr(first_clobbered_gpr as u8),
|
||||||
|
rt2: writable_gpr(15),
|
||||||
|
addr_reg: stack_reg(),
|
||||||
|
addr_off: SImm20::maybe_from_i64(offset).unwrap(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
insts
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_call(
|
||||||
|
dest: &CallDest,
|
||||||
|
uses: Vec<Reg>,
|
||||||
|
defs: Vec<Writable<Reg>>,
|
||||||
|
opcode: ir::Opcode,
|
||||||
|
tmp: Writable<Reg>,
|
||||||
|
_callee_conv: isa::CallConv,
|
||||||
|
_caller_conv: isa::CallConv,
|
||||||
|
) -> SmallVec<[(InstIsSafepoint, Inst); 2]> {
|
||||||
|
let mut insts = SmallVec::new();
|
||||||
|
match &dest {
|
||||||
|
&CallDest::ExtName(ref name, RelocDistance::Near) => insts.push((
|
||||||
|
InstIsSafepoint::Yes,
|
||||||
|
Inst::Call {
|
||||||
|
link: writable_gpr(14),
|
||||||
|
info: Box::new(CallInfo {
|
||||||
|
dest: name.clone(),
|
||||||
|
uses,
|
||||||
|
defs,
|
||||||
|
opcode,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
&CallDest::ExtName(ref name, RelocDistance::Far) => {
|
||||||
|
insts.push((
|
||||||
|
InstIsSafepoint::No,
|
||||||
|
Inst::LoadExtNameFar {
|
||||||
|
rd: tmp,
|
||||||
|
name: Box::new(name.clone()),
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
));
|
||||||
|
insts.push((
|
||||||
|
InstIsSafepoint::Yes,
|
||||||
|
Inst::CallInd {
|
||||||
|
link: writable_gpr(14),
|
||||||
|
info: Box::new(CallIndInfo {
|
||||||
|
rn: tmp.to_reg(),
|
||||||
|
uses,
|
||||||
|
defs,
|
||||||
|
opcode,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
&CallDest::Reg(reg) => insts.push((
|
||||||
|
InstIsSafepoint::Yes,
|
||||||
|
Inst::CallInd {
|
||||||
|
link: writable_gpr(14),
|
||||||
|
info: Box::new(CallIndInfo {
|
||||||
|
rn: *reg,
|
||||||
|
uses,
|
||||||
|
defs,
|
||||||
|
opcode,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
|
||||||
|
insts
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_memcpy(
|
||||||
|
_call_conv: isa::CallConv,
|
||||||
|
_dst: Reg,
|
||||||
|
_src: Reg,
|
||||||
|
_size: usize,
|
||||||
|
) -> SmallVec<[Self::I; 8]> {
|
||||||
|
unimplemented!("StructArgs not implemented for S390X yet");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_number_of_spillslots_for_value(rc: RegClass, ty: Type) -> u32 {
|
||||||
|
// We allocate in terms of 8-byte slots.
|
||||||
|
match (rc, ty) {
|
||||||
|
(RegClass::I64, _) => 1,
|
||||||
|
(RegClass::F64, _) => 1,
|
||||||
|
_ => panic!("Unexpected register class!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the current virtual-SP offset from an instruction-emission state.
|
||||||
|
fn get_virtual_sp_offset_from_state(s: &EmitState) -> i64 {
|
||||||
|
s.virtual_sp_offset
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the nominal-SP-to-FP offset from an instruction-emission state.
|
||||||
|
fn get_nominal_sp_to_fp(s: &EmitState) -> i64 {
|
||||||
|
s.initial_sp_offset
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_regs_clobbered_by_call(call_conv_of_callee: isa::CallConv) -> Vec<Writable<Reg>> {
|
||||||
|
let mut caller_saved = Vec::new();
|
||||||
|
for i in 0..15 {
|
||||||
|
let x = writable_gpr(i);
|
||||||
|
if is_reg_clobbered_by_call(call_conv_of_callee, x.to_reg().to_real_reg()) {
|
||||||
|
caller_saved.push(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i in 0..15 {
|
||||||
|
let v = writable_fpr(i);
|
||||||
|
if is_reg_clobbered_by_call(call_conv_of_callee, v.to_reg().to_real_reg()) {
|
||||||
|
caller_saved.push(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
caller_saved
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_ext_mode(
|
||||||
|
_call_conv: isa::CallConv,
|
||||||
|
specified: ir::ArgumentExtension,
|
||||||
|
) -> ir::ArgumentExtension {
|
||||||
|
specified
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_reg_saved_in_prologue(_call_conv: isa::CallConv, r: RealReg) -> bool {
|
||||||
|
match r.get_class() {
|
||||||
|
RegClass::I64 => {
|
||||||
|
// r6 - r15 inclusive are callee-saves.
|
||||||
|
r.get_hw_encoding() >= 6 && r.get_hw_encoding() <= 15
|
||||||
|
}
|
||||||
|
RegClass::F64 => {
|
||||||
|
// f8 - f15 inclusive are callee-saves.
|
||||||
|
r.get_hw_encoding() >= 8 && r.get_hw_encoding() <= 15
|
||||||
|
}
|
||||||
|
_ => panic!("Unexpected RegClass"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_regs_saved_in_prologue(
|
||||||
|
call_conv: isa::CallConv,
|
||||||
|
regs: &Set<Writable<RealReg>>,
|
||||||
|
) -> (Vec<Writable<RealReg>>, Vec<Writable<RealReg>>) {
|
||||||
|
let mut int_saves = vec![];
|
||||||
|
let mut fpr_saves = vec![];
|
||||||
|
for ® in regs.iter() {
|
||||||
|
if is_reg_saved_in_prologue(call_conv, reg.to_reg()) {
|
||||||
|
match reg.to_reg().get_class() {
|
||||||
|
RegClass::I64 => int_saves.push(reg),
|
||||||
|
RegClass::F64 => fpr_saves.push(reg),
|
||||||
|
_ => panic!("Unexpected RegClass"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Sort registers for deterministic code output.
|
||||||
|
int_saves.sort_by_key(|r| r.to_reg().get_index());
|
||||||
|
fpr_saves.sort_by_key(|r| r.to_reg().get_index());
|
||||||
|
(int_saves, fpr_saves)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_reg_clobbered_by_call(_call_conv: isa::CallConv, r: RealReg) -> bool {
|
||||||
|
match r.get_class() {
|
||||||
|
RegClass::I64 => {
|
||||||
|
// r0 - r5 inclusive are caller-saves.
|
||||||
|
r.get_hw_encoding() <= 5
|
||||||
|
}
|
||||||
|
RegClass::F64 => {
|
||||||
|
// f0 - f7 inclusive are caller-saves.
|
||||||
|
r.get_hw_encoding() <= 7
|
||||||
|
}
|
||||||
|
_ => panic!("Unexpected RegClass"),
|
||||||
|
}
|
||||||
|
}
|
||||||
317
cranelift/codegen/src/isa/s390x/inst/args.rs
Normal file
317
cranelift/codegen/src/isa/s390x/inst/args.rs
Normal file
@@ -0,0 +1,317 @@
|
|||||||
|
//! S390x ISA definitions: instruction arguments.
|
||||||
|
|
||||||
|
// Some variants are never constructed, but we still want them as options in the future.
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use crate::ir::condcodes::{FloatCC, IntCC};
|
||||||
|
use crate::ir::MemFlags;
|
||||||
|
use crate::isa::s390x::inst::*;
|
||||||
|
use crate::machinst::MachLabel;
|
||||||
|
|
||||||
|
use regalloc::{PrettyPrint, RealRegUniverse, Reg};
|
||||||
|
|
||||||
|
use std::string::String;
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// Instruction sub-components (memory addresses): definitions
|
||||||
|
|
||||||
|
/// A memory argument to load/store, encapsulating the possible addressing modes.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum MemArg {
|
||||||
|
//
|
||||||
|
// Real IBM Z addressing modes:
|
||||||
|
//
|
||||||
|
/// Base register, index register, and 12-bit unsigned displacement.
|
||||||
|
BXD12 {
|
||||||
|
base: Reg,
|
||||||
|
index: Reg,
|
||||||
|
disp: UImm12,
|
||||||
|
flags: MemFlags,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Base register, index register, and 20-bit signed displacement.
|
||||||
|
BXD20 {
|
||||||
|
base: Reg,
|
||||||
|
index: Reg,
|
||||||
|
disp: SImm20,
|
||||||
|
flags: MemFlags,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// PC-relative Reference to a label.
|
||||||
|
Label { target: BranchTarget },
|
||||||
|
|
||||||
|
/// PC-relative Reference to a near symbol.
|
||||||
|
Symbol {
|
||||||
|
name: Box<ExternalName>,
|
||||||
|
offset: i32,
|
||||||
|
flags: MemFlags,
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Virtual addressing modes that are lowered at emission time:
|
||||||
|
//
|
||||||
|
/// Arbitrary offset from a register. Converted to generation of large
|
||||||
|
/// offsets with multiple instructions as necessary during code emission.
|
||||||
|
RegOffset { reg: Reg, off: i64, flags: MemFlags },
|
||||||
|
|
||||||
|
/// Offset from the stack pointer at function entry.
|
||||||
|
InitialSPOffset { off: i64 },
|
||||||
|
|
||||||
|
/// Offset from the "nominal stack pointer", which is where the real SP is
|
||||||
|
/// just after stack and spill slots are allocated in the function prologue.
|
||||||
|
/// At emission time, this is converted to `SPOffset` with a fixup added to
|
||||||
|
/// the offset constant. The fixup is a running value that is tracked as
|
||||||
|
/// emission iterates through instructions in linear order, and can be
|
||||||
|
/// adjusted up and down with [Inst::VirtualSPOffsetAdj].
|
||||||
|
///
|
||||||
|
/// The standard ABI is in charge of handling this (by emitting the
|
||||||
|
/// adjustment meta-instructions). It maintains the invariant that "nominal
|
||||||
|
/// SP" is where the actual SP is after the function prologue and before
|
||||||
|
/// clobber pushes. See the diagram in the documentation for
|
||||||
|
/// [crate::isa::s390x::abi](the ABI module) for more details.
|
||||||
|
NominalSPOffset { off: i64 },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MemArg {
|
||||||
|
/// Memory reference using an address in a register.
|
||||||
|
pub fn reg(reg: Reg, flags: MemFlags) -> MemArg {
|
||||||
|
MemArg::BXD12 {
|
||||||
|
base: reg,
|
||||||
|
index: zero_reg(),
|
||||||
|
disp: UImm12::zero(),
|
||||||
|
flags,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Memory reference using the sum of two registers as an address.
|
||||||
|
pub fn reg_plus_reg(reg1: Reg, reg2: Reg, flags: MemFlags) -> MemArg {
|
||||||
|
MemArg::BXD12 {
|
||||||
|
base: reg1,
|
||||||
|
index: reg2,
|
||||||
|
disp: UImm12::zero(),
|
||||||
|
flags,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Memory reference using the sum of a register an an offset as address.
|
||||||
|
pub fn reg_plus_off(reg: Reg, off: i64, flags: MemFlags) -> MemArg {
|
||||||
|
MemArg::RegOffset { reg, off, flags }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_flags(&self) -> MemFlags {
|
||||||
|
match self {
|
||||||
|
MemArg::BXD12 { flags, .. } => *flags,
|
||||||
|
MemArg::BXD20 { flags, .. } => *flags,
|
||||||
|
MemArg::RegOffset { flags, .. } => *flags,
|
||||||
|
MemArg::Label { .. } => MemFlags::trusted(),
|
||||||
|
MemArg::Symbol { flags, .. } => *flags,
|
||||||
|
MemArg::InitialSPOffset { .. } => MemFlags::trusted(),
|
||||||
|
MemArg::NominalSPOffset { .. } => MemFlags::trusted(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn can_trap(&self) -> bool {
|
||||||
|
!self.get_flags().notrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// Instruction sub-components (conditions, branches and branch targets):
|
||||||
|
// definitions
|
||||||
|
|
||||||
|
/// Condition for conditional branches.
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Cond {
|
||||||
|
mask: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Cond {
|
||||||
|
pub fn from_mask(mask: u8) -> Cond {
|
||||||
|
assert!(mask >= 1 && mask <= 14);
|
||||||
|
Cond { mask }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_intcc(cc: IntCC) -> Cond {
|
||||||
|
let mask = match cc {
|
||||||
|
IntCC::Equal => 8,
|
||||||
|
IntCC::NotEqual => 4 | 2,
|
||||||
|
IntCC::SignedGreaterThanOrEqual => 8 | 2,
|
||||||
|
IntCC::SignedGreaterThan => 2,
|
||||||
|
IntCC::SignedLessThanOrEqual => 8 | 4,
|
||||||
|
IntCC::SignedLessThan => 4,
|
||||||
|
IntCC::UnsignedGreaterThanOrEqual => 8 | 2,
|
||||||
|
IntCC::UnsignedGreaterThan => 2,
|
||||||
|
IntCC::UnsignedLessThanOrEqual => 8 | 4,
|
||||||
|
IntCC::UnsignedLessThan => 4,
|
||||||
|
IntCC::Overflow => 1,
|
||||||
|
IntCC::NotOverflow => 8 | 4 | 2,
|
||||||
|
};
|
||||||
|
Cond { mask }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_floatcc(cc: FloatCC) -> Cond {
|
||||||
|
let mask = match cc {
|
||||||
|
FloatCC::Ordered => 8 | 4 | 2,
|
||||||
|
FloatCC::Unordered => 1,
|
||||||
|
FloatCC::Equal => 8,
|
||||||
|
FloatCC::NotEqual => 4 | 2 | 1,
|
||||||
|
FloatCC::OrderedNotEqual => 4 | 2,
|
||||||
|
FloatCC::UnorderedOrEqual => 8 | 1,
|
||||||
|
FloatCC::LessThan => 4,
|
||||||
|
FloatCC::LessThanOrEqual => 8 | 4,
|
||||||
|
FloatCC::GreaterThan => 2,
|
||||||
|
FloatCC::GreaterThanOrEqual => 8 | 2,
|
||||||
|
FloatCC::UnorderedOrLessThan => 4 | 1,
|
||||||
|
FloatCC::UnorderedOrLessThanOrEqual => 8 | 4 | 1,
|
||||||
|
FloatCC::UnorderedOrGreaterThan => 2 | 1,
|
||||||
|
FloatCC::UnorderedOrGreaterThanOrEqual => 8 | 2 | 1,
|
||||||
|
};
|
||||||
|
Cond { mask }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the inverted condition.
|
||||||
|
pub fn invert(self) -> Cond {
|
||||||
|
Cond {
|
||||||
|
mask: !self.mask & 15,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the machine encoding of this condition.
|
||||||
|
pub fn bits(self) -> u8 {
|
||||||
|
self.mask
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A branch target. Either unresolved (basic-block index) or resolved (offset
|
||||||
|
/// from end of current instruction).
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub enum BranchTarget {
|
||||||
|
/// An unresolved reference to a Label, as passed into
|
||||||
|
/// `lower_branch_group()`.
|
||||||
|
Label(MachLabel),
|
||||||
|
/// A fixed PC offset.
|
||||||
|
ResolvedOffset(i32),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BranchTarget {
|
||||||
|
/// Return the target's label, if it is a label-based target.
|
||||||
|
pub fn as_label(self) -> Option<MachLabel> {
|
||||||
|
match self {
|
||||||
|
BranchTarget::Label(l) => Some(l),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the target's offset, if specified, or zero if label-based.
|
||||||
|
pub fn as_ri_offset_or_zero(self) -> u16 {
|
||||||
|
let off = match self {
|
||||||
|
BranchTarget::ResolvedOffset(off) => off >> 1,
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
assert!(off <= 0x7fff);
|
||||||
|
assert!(off >= -0x8000);
|
||||||
|
off as u16
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the target's offset, if specified, or zero if label-based.
|
||||||
|
pub fn as_ril_offset_or_zero(self) -> u32 {
|
||||||
|
let off = match self {
|
||||||
|
BranchTarget::ResolvedOffset(off) => off >> 1,
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
off as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrettyPrint for MemArg {
|
||||||
|
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
|
match self {
|
||||||
|
&MemArg::BXD12 {
|
||||||
|
base, index, disp, ..
|
||||||
|
} => {
|
||||||
|
if base != zero_reg() {
|
||||||
|
if index != zero_reg() {
|
||||||
|
format!(
|
||||||
|
"{}({},{})",
|
||||||
|
disp.show_rru(mb_rru),
|
||||||
|
index.show_rru(mb_rru),
|
||||||
|
base.show_rru(mb_rru)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
format!("{}({})", disp.show_rru(mb_rru), base.show_rru(mb_rru))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if index != zero_reg() {
|
||||||
|
format!("{}({},)", disp.show_rru(mb_rru), index.show_rru(mb_rru))
|
||||||
|
} else {
|
||||||
|
format!("{}", disp.show_rru(mb_rru))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&MemArg::BXD20 {
|
||||||
|
base, index, disp, ..
|
||||||
|
} => {
|
||||||
|
if base != zero_reg() {
|
||||||
|
if index != zero_reg() {
|
||||||
|
format!(
|
||||||
|
"{}({},{})",
|
||||||
|
disp.show_rru(mb_rru),
|
||||||
|
index.show_rru(mb_rru),
|
||||||
|
base.show_rru(mb_rru)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
format!("{}({})", disp.show_rru(mb_rru), base.show_rru(mb_rru))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if index != zero_reg() {
|
||||||
|
format!("{}({},)", disp.show_rru(mb_rru), index.show_rru(mb_rru))
|
||||||
|
} else {
|
||||||
|
format!("{}", disp.show_rru(mb_rru))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&MemArg::Label { ref target } => target.show_rru(mb_rru),
|
||||||
|
&MemArg::Symbol {
|
||||||
|
ref name, offset, ..
|
||||||
|
} => format!("{} + {}", name, offset),
|
||||||
|
// Eliminated by `mem_finalize()`.
|
||||||
|
&MemArg::InitialSPOffset { .. }
|
||||||
|
| &MemArg::NominalSPOffset { .. }
|
||||||
|
| &MemArg::RegOffset { .. } => {
|
||||||
|
panic!("Unexpected pseudo mem-arg mode (stack-offset or generic reg-offset)!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrettyPrint for Cond {
|
||||||
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
|
let s = match self.mask {
|
||||||
|
1 => "o",
|
||||||
|
2 => "h",
|
||||||
|
3 => "nle",
|
||||||
|
4 => "l",
|
||||||
|
5 => "nhe",
|
||||||
|
6 => "lh",
|
||||||
|
7 => "ne",
|
||||||
|
8 => "e",
|
||||||
|
9 => "nlh",
|
||||||
|
10 => "he",
|
||||||
|
11 => "nl",
|
||||||
|
12 => "le",
|
||||||
|
13 => "nh",
|
||||||
|
14 => "no",
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
s.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrettyPrint for BranchTarget {
|
||||||
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
|
match self {
|
||||||
|
&BranchTarget::Label(label) => format!("label{:?}", label.get()),
|
||||||
|
&BranchTarget::ResolvedOffset(off) => format!("{}", off),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1965
cranelift/codegen/src/isa/s390x/inst/emit.rs
Normal file
1965
cranelift/codegen/src/isa/s390x/inst/emit.rs
Normal file
File diff suppressed because it is too large
Load Diff
7140
cranelift/codegen/src/isa/s390x/inst/emit_tests.rs
Normal file
7140
cranelift/codegen/src/isa/s390x/inst/emit_tests.rs
Normal file
File diff suppressed because it is too large
Load Diff
231
cranelift/codegen/src/isa/s390x/inst/imms.rs
Normal file
231
cranelift/codegen/src/isa/s390x/inst/imms.rs
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
//! S390x ISA definitions: immediate constants.
|
||||||
|
|
||||||
|
use regalloc::{PrettyPrint, RealRegUniverse};
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a zero immediate of this format.
|
||||||
|
pub fn zero() -> SImm20 {
|
||||||
|
SImm20 { value: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the value that this constant represents.
|
||||||
|
pub fn value(&self) -> u64 {
|
||||||
|
(self.bits as u64) << (16 * 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 from_uimm16shifted(value: UImm16Shifted) -> UImm32Shifted {
|
||||||
|
if value.shift % 2 == 0 {
|
||||||
|
UImm32Shifted {
|
||||||
|
bits: value.bits as u32,
|
||||||
|
shift: value.shift / 2,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
UImm32Shifted {
|
||||||
|
bits: (value.bits as u32) << 16,
|
||||||
|
shift: value.shift / 2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn negate_bits(&self) -> UImm32Shifted {
|
||||||
|
UImm32Shifted {
|
||||||
|
bits: !self.bits,
|
||||||
|
shift: self.shift,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the value that this constant represents.
|
||||||
|
pub fn value(&self) -> u64 {
|
||||||
|
(self.bits as u64) << (32 * self.shift)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrettyPrint for UImm12 {
|
||||||
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
|
format!("{}", self.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrettyPrint for SImm20 {
|
||||||
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
|
format!("{}", self.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrettyPrint for UImm16Shifted {
|
||||||
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
|
format!("{}", self.bits)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrettyPrint for UImm32Shifted {
|
||||||
|
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||||
|
format!("{}", self.bits)
|
||||||
|
}
|
||||||
|
}
|
||||||
3411
cranelift/codegen/src/isa/s390x/inst/mod.rs
Normal file
3411
cranelift/codegen/src/isa/s390x/inst/mod.rs
Normal file
File diff suppressed because it is too large
Load Diff
168
cranelift/codegen/src/isa/s390x/inst/regs.rs
Normal file
168
cranelift/codegen/src/isa/s390x/inst/regs.rs
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
//! S390x ISA definitions: registers.
|
||||||
|
|
||||||
|
use crate::settings;
|
||||||
|
use regalloc::{RealRegUniverse, Reg, RegClass, RegClassInfo, Writable, NUM_REG_CLASSES};
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// Registers, the Universe thereof, and printing
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const GPR_INDICES: [u8; 16] = [
|
||||||
|
// r0 and r1 reserved
|
||||||
|
30, 31,
|
||||||
|
// r2 - r5 call-clobbered
|
||||||
|
16, 17, 18, 19,
|
||||||
|
// r6 - r14 call-saved (order reversed)
|
||||||
|
28, 27, 26, 25, 24, 23, 22, 21, 20,
|
||||||
|
// r15 (SP)
|
||||||
|
29,
|
||||||
|
];
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const FPR_INDICES: [u8; 16] = [
|
||||||
|
// f0 - f7 as pairs
|
||||||
|
0, 4, 1, 5, 2, 6, 3, 7,
|
||||||
|
// f8 - f15 as pairs
|
||||||
|
8, 12, 9, 13, 10, 14, 11, 15,
|
||||||
|
];
|
||||||
|
|
||||||
|
/// Get a reference to a GPR (integer register).
|
||||||
|
pub fn gpr(num: u8) -> Reg {
|
||||||
|
assert!(num < 16);
|
||||||
|
Reg::new_real(
|
||||||
|
RegClass::I64,
|
||||||
|
/* enc = */ num,
|
||||||
|
/* index = */ GPR_INDICES[num as usize],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a writable reference to a GPR.
|
||||||
|
pub fn writable_gpr(num: u8) -> Writable<Reg> {
|
||||||
|
Writable::from_reg(gpr(num))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a reference to a FPR (floating-point register).
|
||||||
|
pub fn fpr(num: u8) -> Reg {
|
||||||
|
assert!(num < 16);
|
||||||
|
Reg::new_real(
|
||||||
|
RegClass::F64,
|
||||||
|
/* enc = */ num,
|
||||||
|
/* index = */ FPR_INDICES[num as usize],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a writable reference to a V-register.
|
||||||
|
pub fn writable_fpr(num: u8) -> Writable<Reg> {
|
||||||
|
Writable::from_reg(fpr(num))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the stack-pointer register.
|
||||||
|
pub fn stack_reg() -> Reg {
|
||||||
|
gpr(15)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a writable reference to the stack-pointer register.
|
||||||
|
pub fn writable_stack_reg() -> Writable<Reg> {
|
||||||
|
Writable::from_reg(stack_reg())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the first temporary, sometimes "spill temporary", register. This register is
|
||||||
|
/// used to compute the address of a spill slot when a direct offset addressing mode from FP is not
|
||||||
|
/// sufficient (+/- 2^11 words). We exclude this register from regalloc and reserve it for this
|
||||||
|
/// purpose for simplicity; otherwise we need a multi-stage analysis where we first determine how
|
||||||
|
/// many spill slots we have, then perhaps remove the reg from the pool and recompute regalloc.
|
||||||
|
///
|
||||||
|
/// We use r1 for this because it's a scratch register but is slightly special (used for linker
|
||||||
|
/// veneers). We're free to use it as long as we don't expect it to live through call instructions.
|
||||||
|
pub fn spilltmp_reg() -> Reg {
|
||||||
|
gpr(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a writable reference to the spilltmp reg.
|
||||||
|
pub fn writable_spilltmp_reg() -> Writable<Reg> {
|
||||||
|
Writable::from_reg(spilltmp_reg())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn zero_reg() -> Reg {
|
||||||
|
gpr(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create the register universe for AArch64.
|
||||||
|
pub fn create_reg_universe(_flags: &settings::Flags) -> RealRegUniverse {
|
||||||
|
let mut regs = vec![];
|
||||||
|
let mut allocable_by_class = [None; NUM_REG_CLASSES];
|
||||||
|
|
||||||
|
// Numbering Scheme: we put FPRs first, then GPRs. The GPRs exclude several registers:
|
||||||
|
// r0 (we cannot use this for addressing // FIXME regalloc)
|
||||||
|
// r1 (spilltmp)
|
||||||
|
// r15 (stack pointer)
|
||||||
|
|
||||||
|
// FPRs.
|
||||||
|
let mut base = regs.len();
|
||||||
|
regs.push((fpr(0).to_real_reg(), "%f0".into()));
|
||||||
|
regs.push((fpr(2).to_real_reg(), "%f2".into()));
|
||||||
|
regs.push((fpr(4).to_real_reg(), "%f4".into()));
|
||||||
|
regs.push((fpr(6).to_real_reg(), "%f6".into()));
|
||||||
|
regs.push((fpr(1).to_real_reg(), "%f1".into()));
|
||||||
|
regs.push((fpr(3).to_real_reg(), "%f3".into()));
|
||||||
|
regs.push((fpr(5).to_real_reg(), "%f5".into()));
|
||||||
|
regs.push((fpr(7).to_real_reg(), "%f7".into()));
|
||||||
|
regs.push((fpr(8).to_real_reg(), "%f8".into()));
|
||||||
|
regs.push((fpr(10).to_real_reg(), "%f10".into()));
|
||||||
|
regs.push((fpr(12).to_real_reg(), "%f12".into()));
|
||||||
|
regs.push((fpr(14).to_real_reg(), "%f14".into()));
|
||||||
|
regs.push((fpr(9).to_real_reg(), "%f9".into()));
|
||||||
|
regs.push((fpr(11).to_real_reg(), "%f11".into()));
|
||||||
|
regs.push((fpr(13).to_real_reg(), "%f13".into()));
|
||||||
|
regs.push((fpr(15).to_real_reg(), "%f15".into()));
|
||||||
|
|
||||||
|
allocable_by_class[RegClass::F64.rc_to_usize()] = Some(RegClassInfo {
|
||||||
|
first: base,
|
||||||
|
last: regs.len() - 1,
|
||||||
|
suggested_scratch: Some(fpr(1).get_index()),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Caller-saved GPRs in the SystemV s390x ABI.
|
||||||
|
base = regs.len();
|
||||||
|
regs.push((gpr(2).to_real_reg(), "%r2".into()));
|
||||||
|
regs.push((gpr(3).to_real_reg(), "%r3".into()));
|
||||||
|
regs.push((gpr(4).to_real_reg(), "%r4".into()));
|
||||||
|
regs.push((gpr(5).to_real_reg(), "%r5".into()));
|
||||||
|
|
||||||
|
// Callee-saved GPRs in the SystemV s390x ABI.
|
||||||
|
// We start from r14 downwards in an attempt to allow the
|
||||||
|
// prolog to use as short a STMG as possible.
|
||||||
|
regs.push((gpr(14).to_real_reg(), "%r14".into()));
|
||||||
|
regs.push((gpr(13).to_real_reg(), "%r13".into()));
|
||||||
|
regs.push((gpr(12).to_real_reg(), "%r12".into()));
|
||||||
|
regs.push((gpr(11).to_real_reg(), "%r11".into()));
|
||||||
|
regs.push((gpr(10).to_real_reg(), "%r10".into()));
|
||||||
|
regs.push((gpr(9).to_real_reg(), "%r9".into()));
|
||||||
|
regs.push((gpr(8).to_real_reg(), "%r8".into()));
|
||||||
|
regs.push((gpr(7).to_real_reg(), "%r7".into()));
|
||||||
|
regs.push((gpr(6).to_real_reg(), "%r6".into()));
|
||||||
|
|
||||||
|
allocable_by_class[RegClass::I64.rc_to_usize()] = Some(RegClassInfo {
|
||||||
|
first: base,
|
||||||
|
last: regs.len() - 1,
|
||||||
|
suggested_scratch: Some(gpr(13).get_index()),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Other regs, not available to the allocator.
|
||||||
|
let allocable = regs.len();
|
||||||
|
regs.push((gpr(15).to_real_reg(), "%r15".into()));
|
||||||
|
regs.push((gpr(0).to_real_reg(), "%r0".into()));
|
||||||
|
regs.push((gpr(1).to_real_reg(), "%r1".into()));
|
||||||
|
|
||||||
|
// Assert sanity: the indices in the register structs must match their
|
||||||
|
// actual indices in the array.
|
||||||
|
for (i, reg) in regs.iter().enumerate() {
|
||||||
|
assert_eq!(i, reg.0.get_index());
|
||||||
|
}
|
||||||
|
|
||||||
|
RealRegUniverse {
|
||||||
|
regs,
|
||||||
|
allocable,
|
||||||
|
allocable_by_class,
|
||||||
|
}
|
||||||
|
}
|
||||||
2
cranelift/codegen/src/isa/s390x/inst/unwind.rs
Normal file
2
cranelift/codegen/src/isa/s390x/inst/unwind.rs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#[cfg(feature = "unwind")]
|
||||||
|
pub(crate) mod systemv;
|
||||||
197
cranelift/codegen/src/isa/s390x/inst/unwind/systemv.rs
Normal file
197
cranelift/codegen/src/isa/s390x/inst/unwind/systemv.rs
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
//! Unwind information for System V ABI (s390x).
|
||||||
|
|
||||||
|
use crate::isa::unwind::systemv::RegisterMappingError;
|
||||||
|
use gimli::{write::CommonInformationEntry, Encoding, Format, Register};
|
||||||
|
use regalloc::{Reg, RegClass};
|
||||||
|
|
||||||
|
/// Creates a new s390x common information entry (CIE).
|
||||||
|
pub fn create_cie() -> CommonInformationEntry {
|
||||||
|
use gimli::write::CallFrameInstruction;
|
||||||
|
|
||||||
|
let mut entry = CommonInformationEntry::new(
|
||||||
|
Encoding {
|
||||||
|
address_size: 8,
|
||||||
|
format: Format::Dwarf32,
|
||||||
|
version: 1,
|
||||||
|
},
|
||||||
|
1, // Code alignment factor
|
||||||
|
-8, // Data alignment factor
|
||||||
|
Register(14), // Return address column - register %r14
|
||||||
|
);
|
||||||
|
|
||||||
|
// Every frame will start with the call frame address (CFA) at %r15 + 160.
|
||||||
|
entry.add_instruction(CallFrameInstruction::Cfa(Register(15), 160));
|
||||||
|
|
||||||
|
entry
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Map Cranelift registers to their corresponding Gimli registers.
|
||||||
|
pub fn map_reg(reg: Reg) -> Result<Register, RegisterMappingError> {
|
||||||
|
const GPR_MAP: [gimli::Register; 16] = [
|
||||||
|
Register(0),
|
||||||
|
Register(1),
|
||||||
|
Register(2),
|
||||||
|
Register(3),
|
||||||
|
Register(4),
|
||||||
|
Register(5),
|
||||||
|
Register(6),
|
||||||
|
Register(7),
|
||||||
|
Register(8),
|
||||||
|
Register(9),
|
||||||
|
Register(10),
|
||||||
|
Register(11),
|
||||||
|
Register(12),
|
||||||
|
Register(13),
|
||||||
|
Register(14),
|
||||||
|
Register(15),
|
||||||
|
];
|
||||||
|
const FPR_MAP: [gimli::Register; 16] = [
|
||||||
|
Register(16),
|
||||||
|
Register(20),
|
||||||
|
Register(17),
|
||||||
|
Register(21),
|
||||||
|
Register(18),
|
||||||
|
Register(22),
|
||||||
|
Register(19),
|
||||||
|
Register(23),
|
||||||
|
Register(24),
|
||||||
|
Register(28),
|
||||||
|
Register(25),
|
||||||
|
Register(29),
|
||||||
|
Register(26),
|
||||||
|
Register(30),
|
||||||
|
Register(27),
|
||||||
|
Register(31),
|
||||||
|
];
|
||||||
|
|
||||||
|
match reg.get_class() {
|
||||||
|
RegClass::I64 => Ok(GPR_MAP[reg.get_hw_encoding() as usize]),
|
||||||
|
RegClass::F64 => Ok(FPR_MAP[reg.get_hw_encoding() as usize]),
|
||||||
|
_ => Err(RegisterMappingError::UnsupportedRegisterBank("class?")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct RegisterMapper;
|
||||||
|
|
||||||
|
impl crate::isa::unwind::systemv::RegisterMapper<Reg> for RegisterMapper {
|
||||||
|
fn map(&self, reg: Reg) -> Result<u16, RegisterMappingError> {
|
||||||
|
Ok(map_reg(reg)?.0)
|
||||||
|
}
|
||||||
|
fn sp(&self) -> u16 {
|
||||||
|
Register(15).0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::cursor::{Cursor, FuncCursor};
|
||||||
|
use crate::ir::{
|
||||||
|
types, AbiParam, ExternalName, Function, InstBuilder, Signature, StackSlotData,
|
||||||
|
StackSlotKind,
|
||||||
|
};
|
||||||
|
use crate::isa::{lookup, CallConv};
|
||||||
|
use crate::settings::{builder, Flags};
|
||||||
|
use crate::Context;
|
||||||
|
use gimli::write::Address;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use target_lexicon::triple;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_simple_func() {
|
||||||
|
let isa = lookup(triple!("s390x"))
|
||||||
|
.expect("expect s390x ISA")
|
||||||
|
.finish(Flags::new(builder()));
|
||||||
|
|
||||||
|
let mut context = Context::for_function(create_function(
|
||||||
|
CallConv::SystemV,
|
||||||
|
Some(StackSlotData::new(StackSlotKind::ExplicitSlot, 64)),
|
||||||
|
));
|
||||||
|
|
||||||
|
context.compile(&*isa).expect("expected compilation");
|
||||||
|
|
||||||
|
let fde = match context
|
||||||
|
.create_unwind_info(isa.as_ref())
|
||||||
|
.expect("can create unwind info")
|
||||||
|
{
|
||||||
|
Some(crate::isa::unwind::UnwindInfo::SystemV(info)) => {
|
||||||
|
info.to_fde(Address::Constant(1234))
|
||||||
|
}
|
||||||
|
_ => panic!("expected unwind information"),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(format!("{:?}", fde), "FrameDescriptionEntry { address: Constant(1234), length: 10, lsda: None, instructions: [(4, CfaOffset(224))] }");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_function(call_conv: CallConv, stack_slot: Option<StackSlotData>) -> Function {
|
||||||
|
let mut func =
|
||||||
|
Function::with_name_signature(ExternalName::user(0, 0), Signature::new(call_conv));
|
||||||
|
|
||||||
|
let block0 = func.dfg.make_block();
|
||||||
|
let mut pos = FuncCursor::new(&mut func);
|
||||||
|
pos.insert_block(block0);
|
||||||
|
pos.ins().return_(&[]);
|
||||||
|
|
||||||
|
if let Some(stack_slot) = stack_slot {
|
||||||
|
func.stack_slots.push(stack_slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
func
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_multi_return_func() {
|
||||||
|
let isa = lookup(triple!("s390x"))
|
||||||
|
.expect("expect s390x ISA")
|
||||||
|
.finish(Flags::new(builder()));
|
||||||
|
|
||||||
|
let mut context = Context::for_function(create_multi_return_function(
|
||||||
|
CallConv::SystemV,
|
||||||
|
Some(StackSlotData::new(StackSlotKind::ExplicitSlot, 64)),
|
||||||
|
));
|
||||||
|
|
||||||
|
context.compile(&*isa).expect("expected compilation");
|
||||||
|
|
||||||
|
let fde = match context
|
||||||
|
.create_unwind_info(isa.as_ref())
|
||||||
|
.expect("can create unwind info")
|
||||||
|
{
|
||||||
|
Some(crate::isa::unwind::UnwindInfo::SystemV(info)) => {
|
||||||
|
info.to_fde(Address::Constant(4321))
|
||||||
|
}
|
||||||
|
_ => panic!("expected unwind information"),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(format!("{:?}", fde), "FrameDescriptionEntry { address: Constant(4321), length: 26, lsda: None, instructions: [(4, CfaOffset(224))] }");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_multi_return_function(
|
||||||
|
call_conv: CallConv,
|
||||||
|
stack_slot: Option<StackSlotData>,
|
||||||
|
) -> Function {
|
||||||
|
let mut sig = Signature::new(call_conv);
|
||||||
|
sig.params.push(AbiParam::new(types::I32));
|
||||||
|
let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig);
|
||||||
|
|
||||||
|
let block0 = func.dfg.make_block();
|
||||||
|
let v0 = func.dfg.append_block_param(block0, types::I32);
|
||||||
|
let block1 = func.dfg.make_block();
|
||||||
|
let block2 = func.dfg.make_block();
|
||||||
|
|
||||||
|
let mut pos = FuncCursor::new(&mut func);
|
||||||
|
pos.insert_block(block0);
|
||||||
|
pos.ins().brnz(v0, block2, &[]);
|
||||||
|
pos.ins().jump(block1, &[]);
|
||||||
|
|
||||||
|
pos.insert_block(block1);
|
||||||
|
pos.ins().return_(&[]);
|
||||||
|
|
||||||
|
pos.insert_block(block2);
|
||||||
|
pos.ins().return_(&[]);
|
||||||
|
|
||||||
|
if let Some(stack_slot) = stack_slot {
|
||||||
|
func.stack_slots.push(stack_slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
func
|
||||||
|
}
|
||||||
|
}
|
||||||
2839
cranelift/codegen/src/isa/s390x/lower.rs
Normal file
2839
cranelift/codegen/src/isa/s390x/lower.rs
Normal file
File diff suppressed because it is too large
Load Diff
296
cranelift/codegen/src/isa/s390x/mod.rs
Normal file
296
cranelift/codegen/src/isa/s390x/mod.rs
Normal file
@@ -0,0 +1,296 @@
|
|||||||
|
//! IBM Z 64-bit Instruction Set Architecture.
|
||||||
|
|
||||||
|
use crate::ir::condcodes::IntCC;
|
||||||
|
use crate::ir::Function;
|
||||||
|
use crate::isa::s390x::settings as s390x_settings;
|
||||||
|
use crate::isa::unwind::systemv::RegisterMappingError;
|
||||||
|
use crate::isa::Builder as IsaBuilder;
|
||||||
|
use crate::machinst::{compile, MachBackend, MachCompileResult, TargetIsaAdapter, VCode};
|
||||||
|
use crate::result::CodegenResult;
|
||||||
|
use crate::settings as shared_settings;
|
||||||
|
|
||||||
|
use alloc::{boxed::Box, vec::Vec};
|
||||||
|
use core::hash::{Hash, Hasher};
|
||||||
|
|
||||||
|
use regalloc::{PrettyPrint, RealRegUniverse, Reg};
|
||||||
|
use target_lexicon::{Architecture, Triple};
|
||||||
|
|
||||||
|
// New backend:
|
||||||
|
mod abi;
|
||||||
|
pub(crate) mod inst;
|
||||||
|
mod lower;
|
||||||
|
mod settings;
|
||||||
|
|
||||||
|
use inst::create_reg_universe;
|
||||||
|
|
||||||
|
use self::inst::EmitInfo;
|
||||||
|
|
||||||
|
/// A IBM Z backend.
|
||||||
|
pub struct S390xBackend {
|
||||||
|
triple: Triple,
|
||||||
|
flags: shared_settings::Flags,
|
||||||
|
isa_flags: s390x_settings::Flags,
|
||||||
|
reg_universe: RealRegUniverse,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl S390xBackend {
|
||||||
|
/// Create a new IBM Z backend with the given (shared) flags.
|
||||||
|
pub fn new_with_flags(
|
||||||
|
triple: Triple,
|
||||||
|
flags: shared_settings::Flags,
|
||||||
|
isa_flags: s390x_settings::Flags,
|
||||||
|
) -> S390xBackend {
|
||||||
|
let reg_universe = create_reg_universe(&flags);
|
||||||
|
S390xBackend {
|
||||||
|
triple,
|
||||||
|
flags,
|
||||||
|
isa_flags,
|
||||||
|
reg_universe,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This performs lowering to VCode, register-allocates the code, computes block layout and
|
||||||
|
/// finalizes branches. The result is ready for binary emission.
|
||||||
|
fn compile_vcode(
|
||||||
|
&self,
|
||||||
|
func: &Function,
|
||||||
|
flags: shared_settings::Flags,
|
||||||
|
) -> CodegenResult<VCode<inst::Inst>> {
|
||||||
|
let emit_info = EmitInfo::new(flags.clone());
|
||||||
|
let abi = Box::new(abi::S390xABICallee::new(func, flags)?);
|
||||||
|
compile::compile::<S390xBackend>(func, self, abi, emit_info)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MachBackend for S390xBackend {
|
||||||
|
fn compile_function(
|
||||||
|
&self,
|
||||||
|
func: &Function,
|
||||||
|
want_disasm: bool,
|
||||||
|
) -> CodegenResult<MachCompileResult> {
|
||||||
|
let flags = self.flags();
|
||||||
|
let vcode = self.compile_vcode(func, flags.clone())?;
|
||||||
|
let buffer = vcode.emit();
|
||||||
|
let frame_size = vcode.frame_size();
|
||||||
|
let value_labels_ranges = vcode.value_labels_ranges();
|
||||||
|
let stackslot_offsets = vcode.stackslot_offsets().clone();
|
||||||
|
|
||||||
|
let disasm = if want_disasm {
|
||||||
|
Some(vcode.show_rru(Some(&create_reg_universe(flags))))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let buffer = buffer.finish();
|
||||||
|
|
||||||
|
Ok(MachCompileResult {
|
||||||
|
buffer,
|
||||||
|
frame_size,
|
||||||
|
disasm,
|
||||||
|
value_labels_ranges,
|
||||||
|
stackslot_offsets,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> &'static str {
|
||||||
|
"s390x"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn triple(&self) -> Triple {
|
||||||
|
self.triple.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flags(&self) -> &shared_settings::Flags {
|
||||||
|
&self.flags
|
||||||
|
}
|
||||||
|
|
||||||
|
fn isa_flags(&self) -> Vec<shared_settings::Value> {
|
||||||
|
self.isa_flags.iter().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hash_all_flags(&self, mut hasher: &mut dyn Hasher) {
|
||||||
|
self.flags.hash(&mut hasher);
|
||||||
|
self.isa_flags.hash(&mut hasher);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reg_universe(&self) -> &RealRegUniverse {
|
||||||
|
&self.reg_universe
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unsigned_add_overflow_condition(&self) -> IntCC {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unsigned_sub_overflow_condition(&self) -> IntCC {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "unwind")]
|
||||||
|
fn emit_unwind_info(
|
||||||
|
&self,
|
||||||
|
result: &MachCompileResult,
|
||||||
|
kind: crate::machinst::UnwindInfoKind,
|
||||||
|
) -> CodegenResult<Option<crate::isa::unwind::UnwindInfo>> {
|
||||||
|
use crate::isa::unwind::UnwindInfo;
|
||||||
|
use crate::machinst::UnwindInfoKind;
|
||||||
|
Ok(match kind {
|
||||||
|
UnwindInfoKind::SystemV => {
|
||||||
|
let mapper = self::inst::unwind::systemv::RegisterMapper;
|
||||||
|
Some(UnwindInfo::SystemV(
|
||||||
|
crate::isa::unwind::systemv::create_unwind_info_from_insts(
|
||||||
|
&result.buffer.unwind_info[..],
|
||||||
|
result.buffer.data.len(),
|
||||||
|
&mapper,
|
||||||
|
)?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "unwind")]
|
||||||
|
fn create_systemv_cie(&self) -> Option<gimli::write::CommonInformationEntry> {
|
||||||
|
Some(inst::unwind::systemv::create_cie())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "unwind")]
|
||||||
|
fn map_reg_to_dwarf(&self, reg: Reg) -> Result<u16, RegisterMappingError> {
|
||||||
|
inst::unwind::systemv::map_reg(reg).map(|reg| reg.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new `isa::Builder`.
|
||||||
|
pub fn isa_builder(triple: Triple) -> IsaBuilder {
|
||||||
|
assert!(triple.architecture == Architecture::S390x);
|
||||||
|
IsaBuilder {
|
||||||
|
triple,
|
||||||
|
setup: s390x_settings::builder(),
|
||||||
|
constructor: |triple, shared_flags, builder| {
|
||||||
|
let isa_flags = s390x_settings::Flags::new(&shared_flags, builder);
|
||||||
|
let backend = S390xBackend::new_with_flags(triple, shared_flags, isa_flags);
|
||||||
|
Box::new(TargetIsaAdapter::new(backend))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use crate::cursor::{Cursor, FuncCursor};
|
||||||
|
use crate::ir::types::*;
|
||||||
|
use crate::ir::{AbiParam, ExternalName, Function, InstBuilder, Signature};
|
||||||
|
use crate::isa::CallConv;
|
||||||
|
use crate::settings;
|
||||||
|
use crate::settings::Configurable;
|
||||||
|
use core::str::FromStr;
|
||||||
|
use target_lexicon::Triple;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_compile_function() {
|
||||||
|
let name = ExternalName::testcase("test0");
|
||||||
|
let mut sig = Signature::new(CallConv::SystemV);
|
||||||
|
sig.params.push(AbiParam::new(I32));
|
||||||
|
sig.returns.push(AbiParam::new(I32));
|
||||||
|
let mut func = Function::with_name_signature(name, sig);
|
||||||
|
|
||||||
|
let bb0 = func.dfg.make_block();
|
||||||
|
let arg0 = func.dfg.append_block_param(bb0, I32);
|
||||||
|
|
||||||
|
let mut pos = FuncCursor::new(&mut func);
|
||||||
|
pos.insert_block(bb0);
|
||||||
|
let v0 = pos.ins().iconst(I32, 0x1234);
|
||||||
|
let v1 = pos.ins().iadd(arg0, v0);
|
||||||
|
pos.ins().return_(&[v1]);
|
||||||
|
|
||||||
|
let mut shared_flags_builder = settings::builder();
|
||||||
|
shared_flags_builder.set("opt_level", "none").unwrap();
|
||||||
|
let shared_flags = settings::Flags::new(shared_flags_builder);
|
||||||
|
let isa_flags = s390x_settings::Flags::new(&shared_flags, s390x_settings::builder());
|
||||||
|
let backend = S390xBackend::new_with_flags(
|
||||||
|
Triple::from_str("s390x").unwrap(),
|
||||||
|
shared_flags,
|
||||||
|
isa_flags,
|
||||||
|
);
|
||||||
|
let result = backend
|
||||||
|
.compile_function(&mut func, /* want_disasm = */ false)
|
||||||
|
.unwrap();
|
||||||
|
let code = &result.buffer.data[..];
|
||||||
|
|
||||||
|
// ahi %r2, 0x1234
|
||||||
|
// br %r14
|
||||||
|
let golden = vec![0xa7, 0x2a, 0x12, 0x34, 0x07, 0xfe];
|
||||||
|
|
||||||
|
assert_eq!(code, &golden[..]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_branch_lowering() {
|
||||||
|
let name = ExternalName::testcase("test0");
|
||||||
|
let mut sig = Signature::new(CallConv::SystemV);
|
||||||
|
sig.params.push(AbiParam::new(I32));
|
||||||
|
sig.returns.push(AbiParam::new(I32));
|
||||||
|
let mut func = Function::with_name_signature(name, sig);
|
||||||
|
|
||||||
|
let bb0 = func.dfg.make_block();
|
||||||
|
let arg0 = func.dfg.append_block_param(bb0, I32);
|
||||||
|
let bb1 = func.dfg.make_block();
|
||||||
|
let bb2 = func.dfg.make_block();
|
||||||
|
let bb3 = func.dfg.make_block();
|
||||||
|
|
||||||
|
let mut pos = FuncCursor::new(&mut func);
|
||||||
|
pos.insert_block(bb0);
|
||||||
|
let v0 = pos.ins().iconst(I32, 0x1234);
|
||||||
|
let v1 = pos.ins().iadd(arg0, v0);
|
||||||
|
pos.ins().brnz(v1, bb1, &[]);
|
||||||
|
pos.ins().jump(bb2, &[]);
|
||||||
|
pos.insert_block(bb1);
|
||||||
|
pos.ins().brnz(v1, bb2, &[]);
|
||||||
|
pos.ins().jump(bb3, &[]);
|
||||||
|
pos.insert_block(bb2);
|
||||||
|
let v2 = pos.ins().iadd(v1, v0);
|
||||||
|
pos.ins().brnz(v2, bb2, &[]);
|
||||||
|
pos.ins().jump(bb1, &[]);
|
||||||
|
pos.insert_block(bb3);
|
||||||
|
let v3 = pos.ins().isub(v1, v0);
|
||||||
|
pos.ins().return_(&[v3]);
|
||||||
|
|
||||||
|
let mut shared_flags_builder = settings::builder();
|
||||||
|
shared_flags_builder.set("opt_level", "none").unwrap();
|
||||||
|
let shared_flags = settings::Flags::new(shared_flags_builder);
|
||||||
|
let isa_flags = s390x_settings::Flags::new(&shared_flags, s390x_settings::builder());
|
||||||
|
let backend = S390xBackend::new_with_flags(
|
||||||
|
Triple::from_str("s390x").unwrap(),
|
||||||
|
shared_flags,
|
||||||
|
isa_flags,
|
||||||
|
);
|
||||||
|
let result = backend
|
||||||
|
.compile_function(&mut func, /* want_disasm = */ false)
|
||||||
|
.unwrap();
|
||||||
|
let code = &result.buffer.data[..];
|
||||||
|
|
||||||
|
// FIXME: the branching logic should be optimized more
|
||||||
|
|
||||||
|
// ahi %r2, 4660
|
||||||
|
// chi %r2, 0
|
||||||
|
// jglh label1 ; jg label2
|
||||||
|
// jg label6
|
||||||
|
// jg label3
|
||||||
|
// ahik %r3, %r2, 4660
|
||||||
|
// chi %r3, 0
|
||||||
|
// jglh label4 ; jg label5
|
||||||
|
// jg label3
|
||||||
|
// jg label6
|
||||||
|
// chi %r2, 0
|
||||||
|
// jglh label7 ; jg label8
|
||||||
|
// jg label3
|
||||||
|
// ahi %r2, -4660
|
||||||
|
// br %r14
|
||||||
|
let golden = vec![
|
||||||
|
167, 42, 18, 52, 167, 46, 0, 0, 192, 100, 0, 0, 0, 11, 236, 50, 18, 52, 0, 216, 167,
|
||||||
|
62, 0, 0, 192, 100, 255, 255, 255, 251, 167, 46, 0, 0, 192, 100, 255, 255, 255, 246,
|
||||||
|
167, 42, 237, 204, 7, 254,
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_eq!(code, &golden[..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
9
cranelift/codegen/src/isa/s390x/settings.rs
Normal file
9
cranelift/codegen/src/isa/s390x/settings.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
//! S390X Settings.
|
||||||
|
|
||||||
|
use crate::settings::{self, detail, Builder, Value};
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
|
// Include code generated by `cranelift-codegen/meta/src/gen_settings.rs:`. This file contains a
|
||||||
|
// public `Flags` struct with an impl for all of the settings defined in
|
||||||
|
// `cranelift-codegen/meta/src/isa/s390x/settings.rs`.
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/settings-s390x.rs"));
|
||||||
1136
cranelift/filetests/filetests/isa/s390x/arithmetic.clif
Normal file
1136
cranelift/filetests/filetests/isa/s390x/arithmetic.clif
Normal file
File diff suppressed because it is too large
Load Diff
243
cranelift/filetests/filetests/isa/s390x/bitops.clif
Normal file
243
cranelift/filetests/filetests/isa/s390x/bitops.clif
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; BITREV
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
; FIXME: bitrev not yet implemented
|
||||||
|
|
||||||
|
;function %bitrev_i64(i64) -> i64 {
|
||||||
|
;block0(v0: i64):
|
||||||
|
; v1 = bitrev v0
|
||||||
|
; return v1
|
||||||
|
;}
|
||||||
|
;
|
||||||
|
;function %bitrev_i32(i32) -> i32 {
|
||||||
|
;block0(v0: i32):
|
||||||
|
; v1 = bitrev v0
|
||||||
|
; return v1
|
||||||
|
;}
|
||||||
|
;
|
||||||
|
;function %bitrev_i16(i16) -> i16 {
|
||||||
|
;block0(v0: i16):
|
||||||
|
; v1 = bitrev v0
|
||||||
|
; return v1
|
||||||
|
;}
|
||||||
|
;
|
||||||
|
;function %bitrev_i8(i8) -> i8 {
|
||||||
|
;block0(v0: i8):
|
||||||
|
; v1 = bitrev v0
|
||||||
|
; return v1
|
||||||
|
;}
|
||||||
|
;
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; CLZ
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %clz_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = clz v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: flogr %r0, %r2
|
||||||
|
; nextln: lgr %r2, %r0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %clz_i32(i32) -> i32 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = clz v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llgfr %r2, %r2
|
||||||
|
; nextln: flogr %r0, %r2
|
||||||
|
; nextln: lr %r2, %r0
|
||||||
|
; nextln: ahi %r2, -32
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %clz_i16(i16) -> i16 {
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = clz v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llghr %r2, %r2
|
||||||
|
; nextln: flogr %r0, %r2
|
||||||
|
; nextln: lr %r2, %r0
|
||||||
|
; nextln: ahi %r2, -48
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %clz_i8(i8) -> i8 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = clz v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llgcr %r2, %r2
|
||||||
|
; nextln: flogr %r0, %r2
|
||||||
|
; nextln: lr %r2, %r0
|
||||||
|
; nextln: ahi %r2, -56
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; CLS
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %cls_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = cls v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: srag %r3, %r2, 63
|
||||||
|
; nextln: xgr %r3, %r2
|
||||||
|
; nextln: flogr %r0, %r2
|
||||||
|
; nextln: lgr %r2, %r0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %cls_i32(i32) -> i32 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = cls v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgfr %r2, %r2
|
||||||
|
; nextln: srag %r3, %r2, 63
|
||||||
|
; nextln: xgr %r3, %r2
|
||||||
|
; nextln: flogr %r0, %r2
|
||||||
|
; nextln: lr %r2, %r0
|
||||||
|
; nextln: ahi %r2, -32
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %cls_i16(i16) -> i16 {
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = cls v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghr %r2, %r2
|
||||||
|
; nextln: srag %r3, %r2, 63
|
||||||
|
; nextln: xgr %r3, %r2
|
||||||
|
; nextln: flogr %r0, %r2
|
||||||
|
; nextln: lr %r2, %r0
|
||||||
|
; nextln: ahi %r2, -48
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %cls_i8(i8) -> i8 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = cls v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgbr %r2, %r2
|
||||||
|
; nextln: srag %r3, %r2, 63
|
||||||
|
; nextln: xgr %r3, %r2
|
||||||
|
; nextln: flogr %r0, %r2
|
||||||
|
; nextln: lr %r2, %r0
|
||||||
|
; nextln: ahi %r2, -56
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; CTZ
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %ctz_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = ctz v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lcgr %r3, %r2
|
||||||
|
; nextln: ngrk %r2, %r3, %r2
|
||||||
|
; nextln: flogr %r0, %r2
|
||||||
|
; nextln: locghie %r0, -1
|
||||||
|
; nextln: lghi %r2, 63
|
||||||
|
; nextln: sgr %r2, %r0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ctz_i32(i32) -> i32 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = ctz v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: oihl %r2, 1
|
||||||
|
; nextln: lcgr %r3, %r2
|
||||||
|
; nextln: ngrk %r2, %r3, %r2
|
||||||
|
; nextln: flogr %r0, %r2
|
||||||
|
; nextln: lhi %r2, 63
|
||||||
|
; nextln: sr %r2, %r0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ctz_i16(i16) -> i16 {
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = ctz v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: oilh %r2, 1
|
||||||
|
; nextln: lcgr %r3, %r2
|
||||||
|
; nextln: ngrk %r2, %r3, %r2
|
||||||
|
; nextln: flogr %r0, %r2
|
||||||
|
; nextln: lhi %r2, 63
|
||||||
|
; nextln: sr %r2, %r0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ctz_i8(i8) -> i8 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = ctz v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: oill %r2, 256
|
||||||
|
; nextln: lcgr %r3, %r2
|
||||||
|
; nextln: ngrk %r2, %r3, %r2
|
||||||
|
; nextln: flogr %r0, %r2
|
||||||
|
; nextln: lhi %r2, 63
|
||||||
|
; nextln: sr %r2, %r0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; POPCNT
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %popcnt_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = popcnt v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: popcnt %r2, %r2, 8
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %popcnt_i32(i32) -> i32 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = popcnt v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llgfr %r2, %r2
|
||||||
|
; nextln: popcnt %r2, %r2, 8
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %popcnt_i16(i16) -> i16 {
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = popcnt v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llghr %r2, %r2
|
||||||
|
; nextln: popcnt %r2, %r2, 8
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %popcnt_i8(i8) -> i8 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = popcnt v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: popcnt %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
490
cranelift/filetests/filetests/isa/s390x/bitwise.clif
Normal file
490
cranelift/filetests/filetests/isa/s390x/bitwise.clif
Normal file
@@ -0,0 +1,490 @@
|
|||||||
|
|
||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
; FIXME: add immediate operand versions
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; BAND
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %band_i64(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = band.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: ngr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %band_i64_mem(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = load.i64 v1
|
||||||
|
v3 = band.i64 v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: ng %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %band_i32(i32, i32) -> i32 {
|
||||||
|
block0(v0: i32, v1: i32):
|
||||||
|
v2 = band.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %band_i32_mem(i32, i64) -> i32 {
|
||||||
|
block0(v0: i32, v1: i64):
|
||||||
|
v2 = load.i32 v1
|
||||||
|
v3 = band.i32 v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: n %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %band_i32_memoff(i32, i64) -> i32 {
|
||||||
|
block0(v0: i32, v1: i64):
|
||||||
|
v2 = load.i32 v1+4096
|
||||||
|
v3 = band.i32 v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: ny %r2, 4096(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %band_i16(i16, i16) -> i16 {
|
||||||
|
block0(v0: i16, v1: i16):
|
||||||
|
v2 = band.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %band_i16_mem(i16, i64) -> i16 {
|
||||||
|
block0(v0: i16, v1: i64):
|
||||||
|
v2 = load.i16 v1
|
||||||
|
v3 = band.i16 v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llh %r3, 0(%r3)
|
||||||
|
; nextln: nr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %band_i8(i8, i8) -> i8 {
|
||||||
|
block0(v0: i8, v1: i8):
|
||||||
|
v2 = band.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %band_i8_mem(i8, i64) -> i8 {
|
||||||
|
block0(v0: i8, v1: i64):
|
||||||
|
v2 = load.i8 v1
|
||||||
|
v3 = band.i8 v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llc %r3, 0(%r3)
|
||||||
|
; nextln: nr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; BOR
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %bor_i64(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = bor.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: ogr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bor_i64_mem(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = load.i64 v1
|
||||||
|
v3 = bor.i64 v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: og %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bor_i32(i32, i32) -> i32 {
|
||||||
|
block0(v0: i32, v1: i32):
|
||||||
|
v2 = bor.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: or %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bor_i32_mem(i32, i64) -> i32 {
|
||||||
|
block0(v0: i32, v1: i64):
|
||||||
|
v2 = load.i32 v1
|
||||||
|
v3 = bor.i32 v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: o %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bor_i32_memoff(i32, i64) -> i32 {
|
||||||
|
block0(v0: i32, v1: i64):
|
||||||
|
v2 = load.i32 v1+4096
|
||||||
|
v3 = bor.i32 v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: oy %r2, 4096(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bor_i16(i16, i16) -> i16 {
|
||||||
|
block0(v0: i16, v1: i16):
|
||||||
|
v2 = bor.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: or %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bor_i16_mem(i16, i64) -> i16 {
|
||||||
|
block0(v0: i16, v1: i64):
|
||||||
|
v2 = load.i16 v1
|
||||||
|
v3 = bor.i16 v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llh %r3, 0(%r3)
|
||||||
|
; nextln: or %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bor_i8(i8, i8) -> i8 {
|
||||||
|
block0(v0: i8, v1: i8):
|
||||||
|
v2 = bor.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: or %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bor_i8_mem(i8, i64) -> i8 {
|
||||||
|
block0(v0: i8, v1: i64):
|
||||||
|
v2 = load.i8 v1
|
||||||
|
v3 = bor.i8 v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llc %r3, 0(%r3)
|
||||||
|
; nextln: or %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; BXOR
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %bxor_i64(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = bxor.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: xgr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bxor_i64_mem(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = load.i64 v1
|
||||||
|
v3 = bxor.i64 v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: xg %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bxor_i32(i32, i32) -> i32 {
|
||||||
|
block0(v0: i32, v1: i32):
|
||||||
|
v2 = bxor.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: xr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bxor_i32_mem(i32, i64) -> i32 {
|
||||||
|
block0(v0: i32, v1: i64):
|
||||||
|
v2 = load.i32 v1
|
||||||
|
v3 = bxor.i32 v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: x %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bxor_i32_memoff(i32, i64) -> i32 {
|
||||||
|
block0(v0: i32, v1: i64):
|
||||||
|
v2 = load.i32 v1+4096
|
||||||
|
v3 = bxor.i32 v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: xy %r2, 4096(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bxor_i16(i16, i16) -> i16 {
|
||||||
|
block0(v0: i16, v1: i16):
|
||||||
|
v2 = bxor.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: xr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bxor_i16_mem(i16, i64) -> i16 {
|
||||||
|
block0(v0: i16, v1: i64):
|
||||||
|
v2 = load.i16 v1
|
||||||
|
v3 = bxor.i16 v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llh %r3, 0(%r3)
|
||||||
|
; nextln: xr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bxor_i8(i8, i8) -> i8 {
|
||||||
|
block0(v0: i8, v1: i8):
|
||||||
|
v2 = bxor.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: xr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bxor_i8_mem(i8, i64) -> i8 {
|
||||||
|
block0(v0: i8, v1: i64):
|
||||||
|
v2 = load.i8 v1
|
||||||
|
v3 = bxor.i8 v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llc %r3, 0(%r3)
|
||||||
|
; nextln: xr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; BAND_NOT
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %band_not_i64(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = band_not.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nngrk %r2, %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %band_not_i32(i32, i32) -> i32 {
|
||||||
|
block0(v0: i32, v1: i32):
|
||||||
|
v2 = band_not.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nnrk %r2, %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %band_not_i16(i16, i16) -> i16 {
|
||||||
|
block0(v0: i16, v1: i16):
|
||||||
|
v2 = band_not.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nnrk %r2, %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %band_not_i8(i8, i8) -> i8 {
|
||||||
|
block0(v0: i8, v1: i8):
|
||||||
|
v2 = band_not.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nnrk %r2, %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; BOR_NOT
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %bor_not_i64(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = bor_not.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nogrk %r2, %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bor_not_i32(i32, i32) -> i32 {
|
||||||
|
block0(v0: i32, v1: i32):
|
||||||
|
v2 = bor_not.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nork %r2, %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bor_not_i16(i16, i16) -> i16 {
|
||||||
|
block0(v0: i16, v1: i16):
|
||||||
|
v2 = bor_not.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nork %r2, %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bor_not_i8(i8, i8) -> i8 {
|
||||||
|
block0(v0: i8, v1: i8):
|
||||||
|
v2 = bor_not.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nork %r2, %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; BXOR_NOT
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %bxor_not_i64(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = bxor_not.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nxgrk %r2, %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bxor_not_i32(i32, i32) -> i32 {
|
||||||
|
block0(v0: i32, v1: i32):
|
||||||
|
v2 = bxor_not.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nxrk %r2, %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bxor_not_i16(i16, i16) -> i16 {
|
||||||
|
block0(v0: i16, v1: i16):
|
||||||
|
v2 = bxor_not.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nxrk %r2, %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bxor_not_i8(i8, i8) -> i8 {
|
||||||
|
block0(v0: i8, v1: i8):
|
||||||
|
v2 = bxor_not.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nxrk %r2, %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; BNOT
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %bnot_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = bnot.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nogrk %r2, %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bnot_i32(i32) -> i32 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = bnot.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nork %r2, %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bnot_i16(i16) -> i16 {
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = bnot.i16 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nork %r2, %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bnot_i8(i8) -> i8 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = bnot.i8 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nork %r2, %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; BITSELECT
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %bitselect_i64(i64, i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64, v2: i64):
|
||||||
|
v3 = bitselect.i64 v0, v1, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: ngr %r3, %r2
|
||||||
|
; nextln: nngrk %r2, %r4, %r2
|
||||||
|
; nextln: ogr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bitselect_i32(i32, i32, i32) -> i32 {
|
||||||
|
block0(v0: i32, v1: i32, v2: i32):
|
||||||
|
v3 = bitselect.i32 v0, v1, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nr %r3, %r2
|
||||||
|
; nextln: nnrk %r2, %r4, %r2
|
||||||
|
; nextln: or %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bitselect_i16(i16, i16, i16) -> i16 {
|
||||||
|
block0(v0: i16, v1: i16, v2: i16):
|
||||||
|
v3 = bitselect.i16 v0, v1, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nr %r3, %r2
|
||||||
|
; nextln: nnrk %r2, %r4, %r2
|
||||||
|
; nextln: or %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bitselect_i8(i8, i8, i8) -> i8 {
|
||||||
|
block0(v0: i8, v1: i8, v2: i8):
|
||||||
|
v3 = bitselect.i8 v0, v1, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nr %r3, %r2
|
||||||
|
; nextln: nnrk %r2, %r4, %r2
|
||||||
|
; nextln: or %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
113
cranelift/filetests/filetests/isa/s390x/call.clif
Normal file
113
cranelift/filetests/filetests/isa/s390x/call.clif
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; CALL
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %call(i64) -> i64 {
|
||||||
|
fn0 = %g(i64) -> i64
|
||||||
|
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = call fn0(v0)
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stmg %r14, %r15, 112(%r15)
|
||||||
|
; nextln: aghi %r15, -160
|
||||||
|
; nextln: virtual_sp_offset_adjust 160
|
||||||
|
; nextln: bras %r1, 12 ; data %g + 0 ; lg %r3, 0(%r1)
|
||||||
|
; nextln: basr %r14, %r3
|
||||||
|
; nextln: lmg %r14, %r15, 272(%r15)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %call_uext(i32) -> i64 {
|
||||||
|
fn0 = %g(i32 uext) -> i64
|
||||||
|
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = call fn0(v0)
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stmg %r14, %r15, 112(%r15)
|
||||||
|
; nextln: aghi %r15, -160
|
||||||
|
; nextln: virtual_sp_offset_adjust 160
|
||||||
|
; nextln: llgfr %r2, %r2
|
||||||
|
; nextln: bras %r1, 12 ; data %g + 0 ; lg %r3, 0(%r1)
|
||||||
|
; nextln: basr %r14, %r3
|
||||||
|
; nextln: lmg %r14, %r15, 272(%r15)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ret_uext(i32) -> i32 uext {
|
||||||
|
block0(v0: i32):
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llgfr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %call_uext(i32) -> i64 {
|
||||||
|
fn0 = %g(i32 sext) -> i64
|
||||||
|
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = call fn0(v0)
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stmg %r14, %r15, 112(%r15)
|
||||||
|
; nextln: aghi %r15, -160
|
||||||
|
; nextln: virtual_sp_offset_adjust 160
|
||||||
|
; nextln: lgfr %r2, %r2
|
||||||
|
; nextln: bras %r1, 12 ; data %g + 0 ; lg %r3, 0(%r1)
|
||||||
|
; nextln: basr %r14, %r3
|
||||||
|
; nextln: lmg %r14, %r15, 272(%r15)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ret_uext(i32) -> i32 sext {
|
||||||
|
block0(v0: i32):
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgfr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %call_colocated(i64) -> i64 {
|
||||||
|
fn0 = colocated %g(i64) -> i64
|
||||||
|
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = call fn0(v0)
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stmg %r14, %r15, 112(%r15)
|
||||||
|
; nextln: aghi %r15, -160
|
||||||
|
; nextln: virtual_sp_offset_adjust 160
|
||||||
|
; nextln: brasl %r14, %g
|
||||||
|
; nextln: lmg %r14, %r15, 272(%r15)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f2(i32) -> i64 {
|
||||||
|
fn0 = %g(i32 uext) -> i64
|
||||||
|
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = call fn0(v0)
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; CALL_INDIRECT
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %call_indirect(i64, i64) -> i64 {
|
||||||
|
sig0 = (i64) -> i64
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = call_indirect.i64 sig0, v1(v0)
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stmg %r14, %r15, 112(%r15)
|
||||||
|
; nextln: aghi %r15, -160
|
||||||
|
; nextln: virtual_sp_offset_adjust 160
|
||||||
|
; nextln: basr %r14, %r3
|
||||||
|
; nextln: lmg %r14, %r15, 272(%r15)
|
||||||
|
; nextln: br %r14
|
||||||
62
cranelift/filetests/filetests/isa/s390x/condbr.clif
Normal file
62
cranelift/filetests/filetests/isa/s390x/condbr.clif
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
function %f(i64, i64) -> b1 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = icmp eq v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clgr %r2, %r3
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochie %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = icmp eq v0, v1
|
||||||
|
brnz v2, block1
|
||||||
|
jump block2
|
||||||
|
|
||||||
|
block1:
|
||||||
|
v4 = iconst.i64 1
|
||||||
|
return v4
|
||||||
|
|
||||||
|
block2:
|
||||||
|
v5 = iconst.i64 2
|
||||||
|
return v5
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: Block 0:
|
||||||
|
; check: clgr %r2, %r3
|
||||||
|
; nextln: jge label1 ; jg label2
|
||||||
|
; check: Block 1:
|
||||||
|
; check: lghi %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
; check: Block 2:
|
||||||
|
; check: lghi %r2, 2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = icmp eq v0, v1
|
||||||
|
brnz v2, block1
|
||||||
|
jump block1
|
||||||
|
|
||||||
|
block1:
|
||||||
|
v4 = iconst.i64 1
|
||||||
|
return v4
|
||||||
|
}
|
||||||
|
|
||||||
|
; FIXME: Should optimize away branches
|
||||||
|
|
||||||
|
; check: Block 0:
|
||||||
|
; check: clgr %r2, %r3
|
||||||
|
; nextln: jge label1 ; jg label2
|
||||||
|
; check: Block 1:
|
||||||
|
; check: jg label3
|
||||||
|
; check: Block 2:
|
||||||
|
; check: jg label3
|
||||||
|
; check: Block 3:
|
||||||
|
; check: lghi %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
43
cranelift/filetests/filetests/isa/s390x/condops.clif
Normal file
43
cranelift/filetests/filetests/isa/s390x/condops.clif
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
function %f(i8, i64, i64) -> i64 {
|
||||||
|
block0(v0: i8, v1: i64, v2: i64):
|
||||||
|
v3 = iconst.i8 42
|
||||||
|
v4 = icmp eq v0, v3
|
||||||
|
v5 = select.i64 v4, v1, v2
|
||||||
|
return v5
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llcr %r2, %r2
|
||||||
|
; nextln: clfi %r2, 42
|
||||||
|
; nextln: locgre %r4, %r3
|
||||||
|
; nextln: lgr %r2, %r4
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %g(b1, i8, i8) -> i8 {
|
||||||
|
block0(v0: b1, v1: i8, v2: i8):
|
||||||
|
v3 = select.i8 v0, v1, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; FIXME: optimize i8/i16 compares
|
||||||
|
|
||||||
|
; check: llcr %r2, %r2
|
||||||
|
; nextln: chi %r2, 0
|
||||||
|
; nextln: locrlh %r4, %r3
|
||||||
|
; nextln: lr %r2, %r4
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %i(i32, i8, i8) -> i8 {
|
||||||
|
block0(v0: i32, v1: i8, v2: i8):
|
||||||
|
v3 = iconst.i32 42
|
||||||
|
v4 = icmp.i32 eq v0, v3
|
||||||
|
v5 = select.i8 v4, v1, v2
|
||||||
|
return v5
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clfi %r2, 42
|
||||||
|
; nextln: locre %r4, %r3
|
||||||
|
; nextln: lr %r2, %r4
|
||||||
|
; nextln: br %r14
|
||||||
113
cranelift/filetests/filetests/isa/s390x/constants.clif
Normal file
113
cranelift/filetests/filetests/isa/s390x/constants.clif
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
function %f() -> b8 {
|
||||||
|
block0:
|
||||||
|
v0 = bconst.b8 true
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhi %r2, 255
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f() -> b16 {
|
||||||
|
block0:
|
||||||
|
v0 = bconst.b16 false
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhi %r2, 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f() -> i64 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i64 0
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghi %r2, 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f() -> i64 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i64 0xffff
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgfi %r2, 65535
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f() -> i64 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i64 0xffff0000
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llilh %r2, 65535
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f() -> i64 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i64 0xffff00000000
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llihl %r2, 65535
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f() -> i64 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i64 0xffff000000000000
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llihh %r2, 65535
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f() -> i64 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i64 0xffffffffffffffff
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghi %r2, -1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f() -> i64 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i64 0xffffffffffff0000
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgfi %r2, -65536
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f() -> i64 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i64 0xf34bf0a31212003a ; random digits
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llihf %r2, 4081840291
|
||||||
|
; nextln: iilf %r2, 303169594
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f() -> i64 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i64 0x12e900001ef40000 ; random digits with 2 clear half words
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llihh %r2, 4841
|
||||||
|
; nextln: iilh %r2, 7924
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f() -> i32 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i32 -1
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhi %r2, -1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
748
cranelift/filetests/filetests/isa/s390x/conversions.clif
Normal file
748
cranelift/filetests/filetests/isa/s390x/conversions.clif
Normal file
@@ -0,0 +1,748 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; UEXTEND
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %uextend_i32_i64(i32) -> i64 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = uextend.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llgfr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uextend_i16_i64(i16) -> i64 {
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = uextend.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llghr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uextend_i16_i32(i16) -> i32 {
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = uextend.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llhr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uextend_i8_i64(i8) -> i64 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = uextend.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llgcr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uextend_i8_i32(i8) -> i32 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = uextend.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llcr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uextend_i8_i16(i8) -> i16 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = uextend.i16 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llcr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; SEXTEND
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %sextend_i32_i64(i32) -> i64 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = sextend.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgfr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sextend_i16_i64(i16) -> i64 {
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = sextend.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sextend_i16_i32(i16) -> i32 {
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = sextend.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sextend_i8_i64(i8) -> i64 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = sextend.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgbr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sextend_i8_i32(i8) -> i32 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = sextend.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lbr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sextend_i8_i16(i8) -> i16 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = sextend.i16 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lbr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; IREDUCE
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %ireduce_i64_i32(i64, i64) -> i32 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = ireduce.i32 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ireduce_i64_i16(i64, i64) -> i16 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = ireduce.i16 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ireduce_i64_i8(i64, i64) -> i8 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = ireduce.i8 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ireduce_i32_i16(i32, i32) -> i16 {
|
||||||
|
block0(v0: i32, v1: i32):
|
||||||
|
v2 = ireduce.i16 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ireduce_i32_i8(i32, i32) -> i8 {
|
||||||
|
block0(v0: i32, v1: i32):
|
||||||
|
v2 = ireduce.i8 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ireduce_i16_i8(i16, i16) -> i8 {
|
||||||
|
block0(v0: i16, v1: i16):
|
||||||
|
v2 = ireduce.i8 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; BEXTEND
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %bextend_b32_b64(b32) -> b64 {
|
||||||
|
block0(v0: b32):
|
||||||
|
v1 = bextend.b64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgfr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bextend_b16_b64(b16) -> b64 {
|
||||||
|
block0(v0: b16):
|
||||||
|
v1 = bextend.b64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bextend_b16_b32(b16) -> b32 {
|
||||||
|
block0(v0: b16):
|
||||||
|
v1 = bextend.b32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bextend_b8_b64(b8) -> b64 {
|
||||||
|
block0(v0: b8):
|
||||||
|
v1 = bextend.b64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgbr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bextend_b8_b32(b8) -> b32 {
|
||||||
|
block0(v0: b8):
|
||||||
|
v1 = bextend.b32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lbr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bextend_b8_b16(b8) -> b16 {
|
||||||
|
block0(v0: b8):
|
||||||
|
v1 = bextend.b16 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lbr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bextend_b1_b64(b1) -> b64 {
|
||||||
|
block0(v0: b1):
|
||||||
|
v1 = bextend.b64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sllg %r2, %r2, 63
|
||||||
|
; nextln: srag %r2, %r2, 63
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bextend_b1_b32(b1) -> b32 {
|
||||||
|
block0(v0: b1):
|
||||||
|
v1 = bextend.b32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sllk %r2, %r2, 31
|
||||||
|
; nextln: srak %r2, %r2, 31
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bextend_b1_b16(b1) -> b16 {
|
||||||
|
block0(v0: b1):
|
||||||
|
v1 = bextend.b16 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sllk %r2, %r2, 31
|
||||||
|
; nextln: srak %r2, %r2, 31
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bextend_b1_b8(b1) -> b8 {
|
||||||
|
block0(v0: b1):
|
||||||
|
v1 = bextend.b8 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sllk %r2, %r2, 31
|
||||||
|
; nextln: srak %r2, %r2, 31
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; BREDUCE
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %breduce_b64_b32(b64, b64) -> b32 {
|
||||||
|
block0(v0: b64, v1: b64):
|
||||||
|
v2 = breduce.b32 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %breduce_b64_b16(b64, b64) -> b16 {
|
||||||
|
block0(v0: b64, v1: b64):
|
||||||
|
v2 = breduce.b16 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %breduce_b64_b8(b64, b64) -> b8 {
|
||||||
|
block0(v0: b64, v1: b64):
|
||||||
|
v2 = breduce.b8 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %breduce_b64_b1(b64, b64) -> b1 {
|
||||||
|
block0(v0: b64, v1: b64):
|
||||||
|
v2 = breduce.b1 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %breduce_b32_b16(b32, b32) -> b16 {
|
||||||
|
block0(v0: b32, v1: b32):
|
||||||
|
v2 = breduce.b16 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %breduce_b32_b8(b32, b32) -> b8 {
|
||||||
|
block0(v0: b32, v1: b32):
|
||||||
|
v2 = breduce.b8 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %breduce_b32_b1(b32, b32) -> b1 {
|
||||||
|
block0(v0: b32, v1: b32):
|
||||||
|
v2 = breduce.b1 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %breduce_b16_b8(b16, b16) -> b8 {
|
||||||
|
block0(v0: b16, v1: b16):
|
||||||
|
v2 = breduce.b8 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %breduce_b16_b1(b16, b16) -> b1 {
|
||||||
|
block0(v0: b16, v1: b16):
|
||||||
|
v2 = breduce.b1 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %breduce_b8_b1(b8, b8) -> b1 {
|
||||||
|
block0(v0: b8, v1: b8):
|
||||||
|
v2 = breduce.b1 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; BMASK
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %bmask_b64_i64(b64, b64) -> i64 {
|
||||||
|
block0(v0: b64, v1: b64):
|
||||||
|
v2 = bmask.i64 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bmask_b64_i32(b64, b64) -> i32 {
|
||||||
|
block0(v0: b64, v1: b64):
|
||||||
|
v2 = bmask.i32 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bmask_b64_i16(b64, b64) -> i16 {
|
||||||
|
block0(v0: b64, v1: b64):
|
||||||
|
v2 = bmask.i16 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bmask_b64_i8(b64, b64) -> i8 {
|
||||||
|
block0(v0: b64, v1: b64):
|
||||||
|
v2 = bmask.i8 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bmask_b32_i64(b32, b32) -> i64 {
|
||||||
|
block0(v0: b32, v1: b32):
|
||||||
|
v2 = bmask.i64 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgfr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bmask_b32_i32(b32, b32) -> i32 {
|
||||||
|
block0(v0: b32, v1: b32):
|
||||||
|
v2 = bmask.i32 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bmask_b32_i16(b32, b32) -> i16 {
|
||||||
|
block0(v0: b32, v1: b32):
|
||||||
|
v2 = bmask.i16 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bmask_b32_i8(b32, b32) -> i8 {
|
||||||
|
block0(v0: b32, v1: b32):
|
||||||
|
v2 = bmask.i8 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bmask_b16_i64(b16, b16) -> i64 {
|
||||||
|
block0(v0: b16, v1: b16):
|
||||||
|
v2 = bmask.i64 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bmask_b16_i32(b16, b16) -> i32 {
|
||||||
|
block0(v0: b16, v1: b16):
|
||||||
|
v2 = bmask.i32 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bmask_b16_i16(b16, b16) -> i16 {
|
||||||
|
block0(v0: b16, v1: b16):
|
||||||
|
v2 = bmask.i16 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bmask_b16_i8(b16, b16) -> i8 {
|
||||||
|
block0(v0: b16, v1: b16):
|
||||||
|
v2 = bmask.i8 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bmask_b8_i64(b8, b8) -> i64 {
|
||||||
|
block0(v0: b8, v1: b8):
|
||||||
|
v2 = bmask.i64 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgbr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bmask_b8_i32(b8, b8) -> i32 {
|
||||||
|
block0(v0: b8, v1: b8):
|
||||||
|
v2 = bmask.i32 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lbr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bmask_b8_i16(b8, b8) -> i16 {
|
||||||
|
block0(v0: b8, v1: b8):
|
||||||
|
v2 = bmask.i16 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lbr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bmask_b8_i8(b8, b8) -> i8 {
|
||||||
|
block0(v0: b8, v1: b8):
|
||||||
|
v2 = bmask.i8 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bmask_b1_i64(b1, b1) -> i64 {
|
||||||
|
block0(v0: b1, v1: b1):
|
||||||
|
v2 = bmask.i64 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sllg %r2, %r3, 63
|
||||||
|
; nextln: srag %r2, %r2, 63
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bmask_b1_i32(b1, b1) -> i32 {
|
||||||
|
block0(v0: b1, v1: b1):
|
||||||
|
v2 = bmask.i32 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sllk %r2, %r3, 31
|
||||||
|
; nextln: srak %r2, %r2, 31
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bmask_b1_i16(b1, b1) -> i16 {
|
||||||
|
block0(v0: b1, v1: b1):
|
||||||
|
v2 = bmask.i16 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sllk %r2, %r3, 31
|
||||||
|
; nextln: srak %r2, %r2, 31
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bmask_b1_i8(b1, b1) -> i8 {
|
||||||
|
block0(v0: b1, v1: b1):
|
||||||
|
v2 = bmask.i8 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sllk %r2, %r3, 31
|
||||||
|
; nextln: srak %r2, %r2, 31
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; BINT
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %bint_b64_i64(b64) -> i64 {
|
||||||
|
block0(v0: b64):
|
||||||
|
v1 = bint.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghi %r3, 1
|
||||||
|
; nextln: ngr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bint_b64_i32(b64) -> i32 {
|
||||||
|
block0(v0: b64):
|
||||||
|
v1 = bint.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nilf %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bint_b64_i16(b64) -> i16 {
|
||||||
|
block0(v0: b64):
|
||||||
|
v1 = bint.i16 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nill %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bint_b64_i8(b64) -> i8 {
|
||||||
|
block0(v0: b64):
|
||||||
|
v1 = bint.i8 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nill %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bint_b32_i64(b32) -> i64 {
|
||||||
|
block0(v0: b32):
|
||||||
|
v1 = bint.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghi %r3, 1
|
||||||
|
; nextln: ngr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bint_b32_i32(b32) -> i32 {
|
||||||
|
block0(v0: b32):
|
||||||
|
v1 = bint.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nilf %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bint_b32_i16(b32) -> i16 {
|
||||||
|
block0(v0: b32):
|
||||||
|
v1 = bint.i16 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nill %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bint_b32_i8(b32) -> i8 {
|
||||||
|
block0(v0: b32):
|
||||||
|
v1 = bint.i8 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nill %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bint_b16_i64(b16) -> i64 {
|
||||||
|
block0(v0: b16):
|
||||||
|
v1 = bint.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghi %r3, 1
|
||||||
|
; nextln: ngr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bint_b16_i32(b16) -> i32 {
|
||||||
|
block0(v0: b16):
|
||||||
|
v1 = bint.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nilf %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bint_b16_i16(b16) -> i16 {
|
||||||
|
block0(v0: b16):
|
||||||
|
v1 = bint.i16 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nill %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bint_b16_i8(b16) -> i8 {
|
||||||
|
block0(v0: b16):
|
||||||
|
v1 = bint.i8 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nill %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bint_b8_i64(b8) -> i64 {
|
||||||
|
block0(v0: b8):
|
||||||
|
v1 = bint.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghi %r3, 1
|
||||||
|
; nextln: ngr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bint_b8_i32(b8) -> i32 {
|
||||||
|
block0(v0: b8):
|
||||||
|
v1 = bint.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nilf %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bint_b8_i16(b8) -> i16 {
|
||||||
|
block0(v0: b8):
|
||||||
|
v1 = bint.i16 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nill %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bint_b8_i8(b8) -> i8 {
|
||||||
|
block0(v0: b8):
|
||||||
|
v1 = bint.i8 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nill %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bint_b1_i64(b1) -> i64 {
|
||||||
|
block0(v0: b1):
|
||||||
|
v1 = bint.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghi %r3, 1
|
||||||
|
; nextln: ngr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bint_b1_i32(b1) -> i32 {
|
||||||
|
block0(v0: b1):
|
||||||
|
v1 = bint.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nilf %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bint_b1_i16(b1) -> i16 {
|
||||||
|
block0(v0: b1):
|
||||||
|
v1 = bint.i16 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nill %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bint_b1_i8(b1) -> i8 {
|
||||||
|
block0(v0: b1):
|
||||||
|
v1 = bint.i8 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nill %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
355
cranelift/filetests/filetests/isa/s390x/div-traps.clif
Normal file
355
cranelift/filetests/filetests/isa/s390x/div-traps.clif
Normal file
@@ -0,0 +1,355 @@
|
|||||||
|
test compile
|
||||||
|
set avoid_div_traps=1
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; SDIV
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %sdiv_i64(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = sdiv.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgr %r1, %r2
|
||||||
|
; nextln: cgite %r3, 0
|
||||||
|
; nextln: llihf %r2, 2147483647
|
||||||
|
; nextln: iilf %r2, 4294967295
|
||||||
|
; nextln: xgr %r2, %r1
|
||||||
|
; nextln: ngr %r2, %r3
|
||||||
|
; nextln: cgite %r2, -1
|
||||||
|
; nextln: dsgr %r0, %r3
|
||||||
|
; nextln: lgr %r2, %r1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sdiv_i64_imm(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i64 2
|
||||||
|
v2 = sdiv.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgr %r1, %r2
|
||||||
|
; nextln: lghi %r2, 2
|
||||||
|
; nextln: dsgr %r0, %r2
|
||||||
|
; nextln: lgr %r2, %r1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sdiv_i32(i32, i32) -> i32 {
|
||||||
|
block0(v0: i32, v1: i32):
|
||||||
|
v2 = sdiv.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgfr %r1, %r2
|
||||||
|
; nextln: cite %r3, 0
|
||||||
|
; nextln: iilf %r2, 2147483647
|
||||||
|
; nextln: xr %r2, %r1
|
||||||
|
; nextln: nr %r2, %r3
|
||||||
|
; nextln: cite %r2, -1
|
||||||
|
; nextln: dsgfr %r0, %r3
|
||||||
|
; nextln: lr %r2, %r1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sdiv_i32_imm(i32) -> i32 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = iconst.i32 2
|
||||||
|
v2 = sdiv.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgfr %r1, %r2
|
||||||
|
; nextln: lhi %r2, 2
|
||||||
|
; nextln: dsgfr %r0, %r2
|
||||||
|
; nextln: lr %r2, %r1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sdiv_i16(i16, i16) -> i16 {
|
||||||
|
block0(v0: i16, v1: i16):
|
||||||
|
v2 = sdiv.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghr %r1, %r2
|
||||||
|
; nextln: lhr %r2, %r3
|
||||||
|
; nextln: cite %r2, 0
|
||||||
|
; nextln: lhi %r3, 32767
|
||||||
|
; nextln: xr %r3, %r1
|
||||||
|
; nextln: nr %r3, %r2
|
||||||
|
; nextln: cite %r3, -1
|
||||||
|
; nextln: dsgfr %r0, %r2
|
||||||
|
; nextln: lr %r2, %r1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sdiv_i16_imm(i16) -> i16 {
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = iconst.i16 2
|
||||||
|
v2 = sdiv.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghr %r1, %r2
|
||||||
|
; nextln: lhi %r2, 2
|
||||||
|
; nextln: dsgfr %r0, %r2
|
||||||
|
; nextln: lr %r2, %r1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sdiv_i8(i8, i8) -> i8 {
|
||||||
|
block0(v0: i8, v1: i8):
|
||||||
|
v2 = sdiv.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgbr %r1, %r2
|
||||||
|
; nextln: lbr %r2, %r3
|
||||||
|
; nextln: cite %r2, 0
|
||||||
|
; nextln: lhi %r3, 127
|
||||||
|
; nextln: xr %r3, %r1
|
||||||
|
; nextln: nr %r3, %r2
|
||||||
|
; nextln: cite %r3, -1
|
||||||
|
; nextln: dsgfr %r0, %r2
|
||||||
|
; nextln: lr %r2, %r1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sdiv_i8_imm(i8) -> i8 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = iconst.i8 2
|
||||||
|
v2 = sdiv.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgbr %r1, %r2
|
||||||
|
; nextln: lhi %r2, 2
|
||||||
|
; nextln: dsgfr %r0, %r2
|
||||||
|
; nextln: lr %r2, %r1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; UDIV
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %udiv_i64(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = udiv.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghi %r0, 0
|
||||||
|
; nextln: lgr %r1, %r2
|
||||||
|
; nextln: cgite %r3, 0
|
||||||
|
; nextln: dlgr %r0, %r3
|
||||||
|
; nextln: lgr %r2, %r1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %udiv_i64_imm(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i64 2
|
||||||
|
v2 = udiv.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghi %r0, 0
|
||||||
|
; nextln: lgr %r1, %r2
|
||||||
|
; nextln: lghi %r2, 2
|
||||||
|
; nextln: dlgr %r0, %r2
|
||||||
|
; nextln: lgr %r2, %r1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %udiv_i32(i32, i32) -> i32 {
|
||||||
|
block0(v0: i32, v1: i32):
|
||||||
|
v2 = udiv.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhi %r0, 0
|
||||||
|
; nextln: lr %r1, %r2
|
||||||
|
; nextln: cite %r3, 0
|
||||||
|
; nextln: dlr %r0, %r3
|
||||||
|
; nextln: lr %r2, %r1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %udiv_i32_imm(i32) -> i32 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = iconst.i32 2
|
||||||
|
v2 = udiv.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhi %r0, 0
|
||||||
|
; nextln: lr %r1, %r2
|
||||||
|
; nextln: lhi %r2, 2
|
||||||
|
; nextln: dlr %r0, %r2
|
||||||
|
; nextln: lr %r2, %r1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %udiv_i16(i16, i16) -> i16 {
|
||||||
|
block0(v0: i16, v1: i16):
|
||||||
|
v2 = udiv.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhi %r0, 0
|
||||||
|
; nextln: llhr %r1, %r2
|
||||||
|
; nextln: llhr %r2, %r3
|
||||||
|
; nextln: cite %r2, 0
|
||||||
|
; nextln: dlr %r0, %r2
|
||||||
|
; nextln: lr %r2, %r1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %udiv_i16_imm(i16) -> i16 {
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = iconst.i16 2
|
||||||
|
v2 = udiv.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhi %r0, 0
|
||||||
|
; nextln: llhr %r1, %r2
|
||||||
|
; nextln: lhi %r2, 2
|
||||||
|
; nextln: dlr %r0, %r2
|
||||||
|
; nextln: lr %r2, %r1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %udiv_i8(i8, i8) -> i8 {
|
||||||
|
block0(v0: i8, v1: i8):
|
||||||
|
v2 = udiv.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhi %r0, 0
|
||||||
|
; nextln: llcr %r1, %r2
|
||||||
|
; nextln: llcr %r2, %r3
|
||||||
|
; nextln: cite %r2, 0
|
||||||
|
; nextln: dlr %r0, %r2
|
||||||
|
; nextln: lr %r2, %r1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %udiv_i8_imm(i8) -> i8 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = iconst.i8 2
|
||||||
|
v2 = udiv.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhi %r0, 0
|
||||||
|
; nextln: llcr %r1, %r2
|
||||||
|
; nextln: lhi %r2, 2
|
||||||
|
; nextln: dlr %r0, %r2
|
||||||
|
; nextln: lr %r2, %r1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; SREM
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %srem_i64(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = srem.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgr %r1, %r2
|
||||||
|
; nextln: cgite %r3, 0
|
||||||
|
; nextln: cghi %r3, -1
|
||||||
|
; nextln: locghie %r1, 0
|
||||||
|
; nextln: dsgr %r0, %r3
|
||||||
|
; nextln: lgr %r2, %r0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %srem_i32(i32, i32) -> i32 {
|
||||||
|
block0(v0: i32, v1: i32):
|
||||||
|
v2 = srem.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgfr %r1, %r2
|
||||||
|
; nextln: cite %r3, 0
|
||||||
|
; nextln: dsgfr %r0, %r3
|
||||||
|
; nextln: lr %r2, %r0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %srem_i16(i16, i16) -> i16 {
|
||||||
|
block0(v0: i16, v1: i16):
|
||||||
|
v2 = srem.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghr %r1, %r2
|
||||||
|
; nextln: lhr %r2, %r3
|
||||||
|
; nextln: cite %r2, 0
|
||||||
|
; nextln: dsgfr %r0, %r2
|
||||||
|
; nextln: lr %r2, %r0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %srem_i8(i8, i8) -> i8 {
|
||||||
|
block0(v0: i8, v1: i8):
|
||||||
|
v2 = srem.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgbr %r1, %r2
|
||||||
|
; nextln: lbr %r2, %r3
|
||||||
|
; nextln: cite %r2, 0
|
||||||
|
; nextln: dsgfr %r0, %r2
|
||||||
|
; nextln: lr %r2, %r0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; UREM
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %urem_i64(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = urem.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghi %r0, 0
|
||||||
|
; nextln: lgr %r1, %r2
|
||||||
|
; nextln: cgite %r3, 0
|
||||||
|
; nextln: dlgr %r0, %r3
|
||||||
|
; nextln: lgr %r2, %r0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %urem_i32(i32, i32) -> i32 {
|
||||||
|
block0(v0: i32, v1: i32):
|
||||||
|
v2 = urem.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhi %r0, 0
|
||||||
|
; nextln: lr %r1, %r2
|
||||||
|
; nextln: cite %r3, 0
|
||||||
|
; nextln: dlr %r0, %r3
|
||||||
|
; nextln: lr %r2, %r0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %urem_i16(i16, i16) -> i16 {
|
||||||
|
block0(v0: i16, v1: i16):
|
||||||
|
v2 = urem.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhi %r0, 0
|
||||||
|
; nextln: llhr %r1, %r2
|
||||||
|
; nextln: llhr %r2, %r3
|
||||||
|
; nextln: cite %r2, 0
|
||||||
|
; nextln: dlr %r0, %r2
|
||||||
|
; nextln: lr %r2, %r0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %urem_i8(i8, i8) -> i8 {
|
||||||
|
block0(v0: i8, v1: i8):
|
||||||
|
v2 = urem.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhi %r0, 0
|
||||||
|
; nextln: llcr %r1, %r2
|
||||||
|
; nextln: llcr %r2, %r3
|
||||||
|
; nextln: cite %r2, 0
|
||||||
|
; nextln: dlr %r0, %r2
|
||||||
|
; nextln: lr %r2, %r0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
711
cranelift/filetests/filetests/isa/s390x/floating-point.clif
Normal file
711
cranelift/filetests/filetests/isa/s390x/floating-point.clif
Normal file
@@ -0,0 +1,711 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; F32CONST/F64CONST
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
; FIXME: should use FZERO instruction
|
||||||
|
; FIXME: should use out-of-line literal pool
|
||||||
|
|
||||||
|
function %f32const_zero() -> f32 {
|
||||||
|
block0:
|
||||||
|
v1 = f32const 0x0.0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: bras %r1, 8 ; data.f32 0 ; le %f0, 0(%r1)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f64const_zero() -> f64 {
|
||||||
|
block0:
|
||||||
|
v1 = f64const 0x0.0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: bras %r1, 12 ; data.f64 0 ; ld %f0, 0(%r1)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f32const_one() -> f32 {
|
||||||
|
block0:
|
||||||
|
v1 = f32const 0x1.0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: bras %r1, 8 ; data.f32 1 ; le %f0, 0(%r1)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f64const_one() -> f64 {
|
||||||
|
block0:
|
||||||
|
v1 = f64const 0x1.0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: bras %r1, 12 ; data.f64 1 ; ld %f0, 0(%r1)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; FADD
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %fadd_f32(f32, f32) -> f32 {
|
||||||
|
block0(v0: f32, v1: f32):
|
||||||
|
v2 = fadd v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: aebr %f0, %f2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fadd_f64(f64, f64) -> f64 {
|
||||||
|
block0(v0: f64, v1: f64):
|
||||||
|
v2 = fadd v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: adbr %f0, %f2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; FSUB
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %fsub_f32(f32, f32) -> f32 {
|
||||||
|
block0(v0: f32, v1: f32):
|
||||||
|
v2 = fsub v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sebr %f0, %f2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fsub_f64(f64, f64) -> f64 {
|
||||||
|
block0(v0: f64, v1: f64):
|
||||||
|
v2 = fsub v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sdbr %f0, %f2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; FMUL
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %fmul_f32(f32, f32) -> f32 {
|
||||||
|
block0(v0: f32, v1: f32):
|
||||||
|
v2 = fmul v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: meebr %f0, %f2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fmul_f64(f64, f64) -> f64 {
|
||||||
|
block0(v0: f64, v1: f64):
|
||||||
|
v2 = fmul v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: mdbr %f0, %f2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; FDIV
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %fdiv_f32(f32, f32) -> f32 {
|
||||||
|
block0(v0: f32, v1: f32):
|
||||||
|
v2 = fdiv v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: debr %f0, %f2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fdiv_f64(f64, f64) -> f64 {
|
||||||
|
block0(v0: f64, v1: f64):
|
||||||
|
v2 = fdiv v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: ddbr %f0, %f2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; FMIN
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %fmin_f32(f32, f32) -> f32 {
|
||||||
|
block0(v0: f32, v1: f32):
|
||||||
|
v2 = fmin v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: wfminsb %f0, %f0, %f2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fmin_f64(f64, f64) -> f64 {
|
||||||
|
block0(v0: f64, v1: f64):
|
||||||
|
v2 = fmin v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: wfmindb %f0, %f0, %f2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; FMAX
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %fmax_f32(f32, f32) -> f32 {
|
||||||
|
block0(v0: f32, v1: f32):
|
||||||
|
v2 = fmax v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: wfmaxsb %f0, %f0, %f2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fmax_f64(f64, f64) -> f64 {
|
||||||
|
block0(v0: f64, v1: f64):
|
||||||
|
v2 = fmax v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: wfmaxdb %f0, %f0, %f2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; SQRT
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %sqrt_f32(f32) -> f32 {
|
||||||
|
block0(v0: f32):
|
||||||
|
v1 = sqrt v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sqebr %f0, %f0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sqrt_f64(f64) -> f64 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = sqrt v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sqdbr %f0, %f0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; FABS
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %fabs_f32(f32) -> f32 {
|
||||||
|
block0(v0: f32):
|
||||||
|
v1 = fabs v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lpebr %f0, %f0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fabs_f64(f64) -> f64 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = fabs v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lpdbr %f0, %f0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; FNEG
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %fneg_f32(f32) -> f32 {
|
||||||
|
block0(v0: f32):
|
||||||
|
v1 = fneg v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lcebr %f0, %f0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fneg_f64(f64) -> f64 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = fneg v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lcdbr %f0, %f0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; FPROMOTE/FDEMOTE
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %fpromote_f32(f32) -> f64 {
|
||||||
|
block0(v0: f32):
|
||||||
|
v1 = fpromote.f64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: ldebr %f0, %f0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fdemote_f64(f64) -> f32 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = fdemote.f32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: ledbr %f0, %f0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; CEIL
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %ceil_f32(f32) -> f32 {
|
||||||
|
block0(v0: f32):
|
||||||
|
v1 = ceil v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: fiebr %f0, %f0, 6
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ceil_f64(f64) -> f64 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = ceil v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: fidbr %f0, %f0, 6
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; FLOOR
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %floor_f32(f32) -> f32 {
|
||||||
|
block0(v0: f32):
|
||||||
|
v1 = floor v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: fiebr %f0, %f0, 7
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %floor_f64(f64) -> f64 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = floor v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: fidbr %f0, %f0, 7
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; TRUNC
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %trunc_f32(f32) -> f32 {
|
||||||
|
block0(v0: f32):
|
||||||
|
v1 = trunc v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: fiebr %f0, %f0, 5
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %trunc_f64(f64) -> f64 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = trunc v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: fidbr %f0, %f0, 5
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; NEAREST
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %nearest_f32(f32) -> f32 {
|
||||||
|
block0(v0: f32):
|
||||||
|
v1 = nearest v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: fiebr %f0, %f0, 4
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %nearest_f64(f64) -> f64 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = nearest v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: fidbr %f0, %f0, 4
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; FMA
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %fma_f32(f32, f32, f32) -> f32 {
|
||||||
|
block0(v0: f32, v1: f32, v2: f32):
|
||||||
|
v3 = fma v0, v1, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; FIXME: regalloc
|
||||||
|
|
||||||
|
; check: maebr %f4, %f0, %f2
|
||||||
|
; nextln: ler %f0, %f4
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fma_f64(f64, f64, f64) -> f64 {
|
||||||
|
block0(v0: f64, v1: f64, v2: f64):
|
||||||
|
v3 = fma v0, v1, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: madbr %f4, %f0, %f2
|
||||||
|
; nextln: ldr %f0, %f4
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; FCOPYSIGN
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %fcopysign_f32(f32, f32) -> f32 {
|
||||||
|
block0(v0: f32, v1: f32):
|
||||||
|
v2 = fcopysign v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cpsdr %f0, %f2, %f0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcopysign_f64(f64, f64) -> f64 {
|
||||||
|
block0(v0: f64, v1: f64):
|
||||||
|
v2 = fcopysign v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cpsdr %f0, %f2, %f0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; FCVT_TO_UINT/FCVT_TO_SINT
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %fcvt_to_uint_f32_i32(f32) -> i32 {
|
||||||
|
block0(v0: f32):
|
||||||
|
v1 = fcvt_to_uint.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cebr %f0, %f0
|
||||||
|
; nextln: jno 6 ; trap
|
||||||
|
; nextln: clfebr %r2, 5, %f0, 0
|
||||||
|
; nextln: jno 6 ; trap
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_to_sint_f32_i32(f32) -> i32 {
|
||||||
|
block0(v0: f32):
|
||||||
|
v1 = fcvt_to_sint.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cebr %f0, %f0
|
||||||
|
; nextln: jno 6 ; trap
|
||||||
|
; nextln: cfebra %r2, 5, %f0, 0
|
||||||
|
; nextln: jno 6 ; trap
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_to_uint_f32_i64(f32) -> i64 {
|
||||||
|
block0(v0: f32):
|
||||||
|
v1 = fcvt_to_uint.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cebr %f0, %f0
|
||||||
|
; nextln: jno 6 ; trap
|
||||||
|
; nextln: clgebr %r2, 5, %f0, 0
|
||||||
|
; nextln: jno 6 ; trap
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_to_sint_f32_i64(f32) -> i64 {
|
||||||
|
block0(v0: f32):
|
||||||
|
v1 = fcvt_to_sint.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cebr %f0, %f0
|
||||||
|
; nextln: jno 6 ; trap
|
||||||
|
; nextln: cgebra %r2, 5, %f0, 0
|
||||||
|
; nextln: jno 6 ; trap
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_to_uint_f64_i32(f64) -> i32 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = fcvt_to_uint.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cdbr %f0, %f0
|
||||||
|
; nextln: jno 6 ; trap
|
||||||
|
; nextln: clfdbr %r2, 5, %f0, 0
|
||||||
|
; nextln: jno 6 ; trap
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_to_sint_f64_i32(f64) -> i32 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = fcvt_to_sint.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cdbr %f0, %f0
|
||||||
|
; nextln: jno 6 ; trap
|
||||||
|
; nextln: cfdbra %r2, 5, %f0, 0
|
||||||
|
; nextln: jno 6 ; trap
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_to_uint_f64_i64(f64) -> i64 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = fcvt_to_uint.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cdbr %f0, %f0
|
||||||
|
; nextln: jno 6 ; trap
|
||||||
|
; nextln: clgdbr %r2, 5, %f0, 0
|
||||||
|
; nextln: jno 6 ; trap
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_to_sint_f64_i64(f64) -> i64 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = fcvt_to_sint.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cdbr %f0, %f0
|
||||||
|
; nextln: jno 6 ; trap
|
||||||
|
; nextln: cgdbra %r2, 5, %f0, 0
|
||||||
|
; nextln: jno 6 ; trap
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; FCVT_FROM_UINT/FCVT_FROM_SINT
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %fcvt_from_uint_i32_f32(i32) -> f32 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = fcvt_from_uint.f32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: celfbr %f0, 0, %r2, 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_from_sint_i32_f32(i32) -> f32 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = fcvt_from_sint.f32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cefbra %f0, 0, %r2, 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_from_uint_i64_f32(i64) -> f32 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = fcvt_from_uint.f32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: celgbr %f0, 0, %r2, 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_from_sint_i64_f32(i64) -> f32 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = fcvt_from_sint.f32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cegbra %f0, 0, %r2, 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_from_uint_i32_f64(i32) -> f64 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = fcvt_from_uint.f64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cdlfbr %f0, 0, %r2, 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_from_sint_i32_f64(i32) -> f64 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = fcvt_from_sint.f64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cdfbra %f0, 0, %r2, 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_from_uint_i64_f64(i64) -> f64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = fcvt_from_uint.f64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cdlgbr %f0, 0, %r2, 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_from_sint_i64_f64(i64) -> f64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = fcvt_from_sint.f64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cdgbra %f0, 0, %r2, 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; FCVT_TO_UINT_SAT/FCVT_TO_SINT_SAT
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %fcvt_to_uint_sat_f32_i32(f32) -> i32 {
|
||||||
|
block0(v0: f32):
|
||||||
|
v1 = fcvt_to_uint_sat.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clfebr %r2, 5, %f0, 0
|
||||||
|
; nextln: cebr %f0, %f0
|
||||||
|
; nextln: lochio %r2, 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_to_sint_sat_f32_i32(f32) -> i32 {
|
||||||
|
block0(v0: f32):
|
||||||
|
v1 = fcvt_to_sint_sat.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cfebra %r2, 5, %f0, 0
|
||||||
|
; nextln: cebr %f0, %f0
|
||||||
|
; nextln: lochio %r2, 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_to_uint_sat_f32_i64(f32) -> i64 {
|
||||||
|
block0(v0: f32):
|
||||||
|
v1 = fcvt_to_uint_sat.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clgebr %r2, 5, %f0, 0
|
||||||
|
; nextln: cebr %f0, %f0
|
||||||
|
; nextln: locghio %r2, 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_to_sint_sat_f32_i64(f32) -> i64 {
|
||||||
|
block0(v0: f32):
|
||||||
|
v1 = fcvt_to_sint_sat.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cgebra %r2, 5, %f0, 0
|
||||||
|
; nextln: cebr %f0, %f0
|
||||||
|
; nextln: locghio %r2, 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_to_uint_sat_f64_i32(f64) -> i32 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = fcvt_to_uint_sat.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clfdbr %r2, 5, %f0, 0
|
||||||
|
; nextln: cdbr %f0, %f0
|
||||||
|
; nextln: lochio %r2, 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_to_sint_sat_f64_i32(f64) -> i32 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = fcvt_to_sint_sat.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cfdbra %r2, 5, %f0, 0
|
||||||
|
; nextln: cdbr %f0, %f0
|
||||||
|
; nextln: lochio %r2, 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_to_uint_sat_f64_i64(f64) -> i64 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = fcvt_to_uint_sat.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clgdbr %r2, 5, %f0, 0
|
||||||
|
; nextln: cdbr %f0, %f0
|
||||||
|
; nextln: locghio %r2, 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %fcvt_to_sint_sat_f64_i64(f64) -> i64 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = fcvt_to_sint_sat.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cgdbra %r2, 5, %f0, 0
|
||||||
|
; nextln: cdbr %f0, %f0
|
||||||
|
; nextln: locghio %r2, 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; BITCAST
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %bitcast_i64_f64(i64) -> f64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = bitcast.f64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: ldgr %f0, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bitcast_f64_i64(f64) -> i64 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = bitcast.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgdr %r2, %f0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bitcast_i32_f32(i32) -> f32 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = bitcast.f32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sllg %r2, %r2, 32
|
||||||
|
; nextln: ldgr %f0, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %bitcast_f32_i32(f32) -> i32 {
|
||||||
|
block0(v0: f32):
|
||||||
|
v1 = bitcast.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgdr %r2, %f0
|
||||||
|
; nextln: srlg %r2, %r2, 32
|
||||||
|
; nextln: br %r14
|
||||||
49
cranelift/filetests/filetests/isa/s390x/heap_addr.clif
Normal file
49
cranelift/filetests/filetests/isa/s390x/heap_addr.clif
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
function %dynamic_heap_check(i64 vmctx, i32) -> i64 {
|
||||||
|
gv0 = vmctx
|
||||||
|
gv1 = load.i32 notrap aligned gv0
|
||||||
|
heap0 = dynamic gv0, bound gv1, offset_guard 0x1000, index_type i32
|
||||||
|
|
||||||
|
block0(v0: i64, v1: i32):
|
||||||
|
v2 = heap_addr.i64 heap0, v1, 0
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: Block 0:
|
||||||
|
; check: l %r4, 0(%r2)
|
||||||
|
; nextln: ahi %r4, 0
|
||||||
|
; nextln: clr %r3, %r4
|
||||||
|
; nextln: jgnh label1 ; jg label2
|
||||||
|
; check: Block 1:
|
||||||
|
; check: llgfr %r5, %r3
|
||||||
|
; nextln: agr %r2, %r5
|
||||||
|
; nextln: lghi %r5, 0
|
||||||
|
; nextln: clr %r3, %r4
|
||||||
|
; nextln: locgrh %r2, %r5
|
||||||
|
; nextln: br %r14
|
||||||
|
; check: Block 2:
|
||||||
|
; check: trap
|
||||||
|
|
||||||
|
function %static_heap_check(i64 vmctx, i32) -> i64 {
|
||||||
|
gv0 = vmctx
|
||||||
|
heap0 = static gv0, bound 0x1_0000, offset_guard 0x1000, index_type i32
|
||||||
|
|
||||||
|
block0(v0: i64, v1: i32):
|
||||||
|
v2 = heap_addr.i64 heap0, v1, 0
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: Block 0:
|
||||||
|
; check: clfi %r3, 65536
|
||||||
|
; nextln: jgnh label1 ; jg label2
|
||||||
|
; check: Block 1:
|
||||||
|
; check: llgfr %r4, %r3
|
||||||
|
; nextln: agr %r2, %r4
|
||||||
|
; nextln: lghi %r4, 0
|
||||||
|
; nextln: clfi %r3, 65536
|
||||||
|
; nextln: locgrh %r2, %r4
|
||||||
|
; nextln: br %r14
|
||||||
|
; check: Block 2:
|
||||||
|
; check: trap
|
||||||
604
cranelift/filetests/filetests/isa/s390x/icmp.clif
Normal file
604
cranelift/filetests/filetests/isa/s390x/icmp.clif
Normal file
@@ -0,0 +1,604 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
function %icmp_slt_i64(i64, i64) -> b1 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = icmp.i64 slt v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cgr %r2, %r3
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i64_ext32(i64, i32) -> b1 {
|
||||||
|
block0(v0: i64, v1: i32):
|
||||||
|
v2 = sextend.i64 v1
|
||||||
|
v3 = icmp.i64 slt v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cgfr %r2, %r3
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i64_imm16(i64) -> b1 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i64 1
|
||||||
|
v2 = icmp.i64 slt v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cghi %r2, 1
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i64_imm32(i64) -> b1 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i64 32768
|
||||||
|
v2 = icmp.i64 slt v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cgfi %r2, 32768
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i64_mem(i64, i64) -> b1 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = load.i64 v1
|
||||||
|
v3 = icmp.i64 slt v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cg %r2, 0(%r3)
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i64_sym(i64) -> b1 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
v2 = load.i64 v1
|
||||||
|
v3 = icmp.i64 slt v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cgrl %r2, %sym + 0
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i64_mem_ext16(i64, i64) -> b1 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = sload16.i64 v1
|
||||||
|
v3 = icmp.i64 slt v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cgh %r2, 0(%r3)
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i64_sym_ext16(i64) -> b1 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
v2 = sload16.i64 v1
|
||||||
|
v3 = icmp.i64 slt v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cghrl %r2, %sym + 0
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i64_mem_ext32(i64, i64) -> b1 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = sload32.i64 v1
|
||||||
|
v3 = icmp.i64 slt v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cgf %r2, 0(%r3)
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i64_sym_ext32(i64) -> b1 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
v2 = sload32.i64 v1
|
||||||
|
v3 = icmp.i64 slt v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cgfrl %r2, %sym + 0
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i32(i32, i32) -> b1 {
|
||||||
|
block0(v0: i32, v1: i32):
|
||||||
|
v2 = icmp.i32 slt v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cr %r2, %r3
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i32_imm16(i32) -> b1 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = iconst.i32 1
|
||||||
|
v2 = icmp.i32 slt v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: chi %r2, 1
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i32_imm(i32) -> b1 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = iconst.i32 32768
|
||||||
|
v2 = icmp.i32 slt v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cfi %r2, 32768
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i32_mem(i32, i64) -> b1 {
|
||||||
|
block0(v0: i32, v1: i64):
|
||||||
|
v2 = load.i32 v1
|
||||||
|
v3 = icmp.i32 slt v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: c %r2, 0(%r3)
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i32_memoff(i32, i64) -> b1 {
|
||||||
|
block0(v0: i32, v1: i64):
|
||||||
|
v2 = load.i32 v1+4096
|
||||||
|
v3 = icmp.i32 slt v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cy %r2, 4096(%r3)
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i32_sym(i32) -> b1 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
v2 = load.i32 v1
|
||||||
|
v3 = icmp.i32 slt v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: crl %r2, %sym + 0
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i32_mem_ext16(i32, i64) -> b1 {
|
||||||
|
block0(v0: i32, v1: i64):
|
||||||
|
v2 = sload16.i32 v1
|
||||||
|
v3 = icmp.i32 slt v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: ch %r2, 0(%r3)
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i32_memoff_ext16(i32, i64) -> b1 {
|
||||||
|
block0(v0: i32, v1: i64):
|
||||||
|
v2 = sload16.i32 v1+4096
|
||||||
|
v3 = icmp.i32 slt v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: chy %r2, 4096(%r3)
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i32_sym_ext16(i32) -> b1 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
v2 = sload16.i32 v1
|
||||||
|
v3 = icmp.i32 slt v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: chrl %r2, %sym + 0
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i16(i16, i16) -> b1 {
|
||||||
|
block0(v0: i16, v1: i16):
|
||||||
|
v2 = icmp.i16 slt v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhr %r2, %r2
|
||||||
|
; nextln: lhr %r3, %r3
|
||||||
|
; nextln: cr %r2, %r3
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i16_imm(i16) -> b1 {
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = iconst.i16 1
|
||||||
|
v2 = icmp.i16 slt v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhr %r2, %r2
|
||||||
|
; nextln: chi %r2, 1
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i16_mem(i16, i64) -> b1 {
|
||||||
|
block0(v0: i16, v1: i64):
|
||||||
|
v2 = load.i16 v1
|
||||||
|
v3 = icmp.i16 slt v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhr %r2, %r2
|
||||||
|
; nextln: ch %r2, 0(%r3)
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i16_sym(i16) -> b1 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
v2 = load.i16 v1
|
||||||
|
v3 = icmp.i16 slt v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhr %r2, %r2
|
||||||
|
; nextln: chrl %r2, %sym + 0
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i8(i8, i8) -> b1 {
|
||||||
|
block0(v0: i8, v1: i8):
|
||||||
|
v2 = icmp.i8 slt v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lbr %r2, %r2
|
||||||
|
; nextln: lbr %r3, %r3
|
||||||
|
; nextln: cr %r2, %r3
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i8_imm(i8) -> b1 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = iconst.i8 1
|
||||||
|
v2 = icmp.i8 slt v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lbr %r2, %r2
|
||||||
|
; nextln: chi %r2, 1
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_slt_i8_mem(i8, i64) -> b1 {
|
||||||
|
block0(v0: i8, v1: i64):
|
||||||
|
v2 = load.i8 v1
|
||||||
|
v3 = icmp.i8 slt v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lbr %r2, %r2
|
||||||
|
; nextln: lb %r3, 0(%r3)
|
||||||
|
; nextln: cr %r2, %r3
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i64(i64, i64) -> b1 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = icmp.i64 ult v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clgr %r2, %r3
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i64_ext32(i64, i32) -> b1 {
|
||||||
|
block0(v0: i64, v1: i32):
|
||||||
|
v2 = uextend.i64 v1
|
||||||
|
v3 = icmp.i64 ult v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clgfr %r2, %r3
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i64_imm(i64) -> b1 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i64 1
|
||||||
|
v2 = icmp.i64 ult v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clgfi %r2, 1
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i64_mem(i64, i64) -> b1 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = load.i64 v1
|
||||||
|
v3 = icmp.i64 ult v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clg %r2, 0(%r3)
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i64_sym(i64) -> b1 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
v2 = load.i64 v1
|
||||||
|
v3 = icmp.i64 ult v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clgrl %r2, %sym + 0
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i64_mem_ext32(i64, i64) -> b1 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = uload32.i64 v1
|
||||||
|
v3 = icmp.i64 ult v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clgf %r2, 0(%r3)
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i64_sym_ext32(i64) -> b1 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
v2 = uload32.i64 v1
|
||||||
|
v3 = icmp.i64 ult v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clgfrl %r2, %sym + 0
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i64_sym_ext16(i64) -> b1 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
v2 = uload16.i64 v1
|
||||||
|
v3 = icmp.i64 ult v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clghrl %r2, %sym + 0
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i32(i32, i32) -> b1 {
|
||||||
|
block0(v0: i32, v1: i32):
|
||||||
|
v2 = icmp.i32 ult v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clr %r2, %r3
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i32_imm(i32) -> b1 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = iconst.i32 1
|
||||||
|
v2 = icmp.i32 ult v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clfi %r2, 1
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i32_mem(i32, i64) -> b1 {
|
||||||
|
block0(v0: i32, v1: i64):
|
||||||
|
v2 = load.i32 v1
|
||||||
|
v3 = icmp.i32 ult v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cl %r2, 0(%r3)
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i32_memoff(i32, i64) -> b1 {
|
||||||
|
block0(v0: i32, v1: i64):
|
||||||
|
v2 = load.i32 v1+4096
|
||||||
|
v3 = icmp.i32 ult v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cly %r2, 4096(%r3)
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i32_sym(i32) -> b1 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
v2 = load.i32 v1
|
||||||
|
v3 = icmp.i32 ult v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clrl %r2, %sym + 0
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i32_sym_ext16(i32) -> b1 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
v2 = uload16.i32 v1
|
||||||
|
v3 = icmp.i32 ult v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clhrl %r2, %sym + 0
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i16(i16, i16) -> b1 {
|
||||||
|
block0(v0: i16, v1: i16):
|
||||||
|
v2 = icmp.i16 ult v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llhr %r2, %r2
|
||||||
|
; nextln: llhr %r3, %r3
|
||||||
|
; nextln: clr %r2, %r3
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i16_imm(i16) -> b1 {
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = iconst.i16 1
|
||||||
|
v2 = icmp.i16 ult v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llhr %r2, %r2
|
||||||
|
; nextln: clfi %r2, 1
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i16_mem(i16, i64) -> b1 {
|
||||||
|
block0(v0: i16, v1: i64):
|
||||||
|
v2 = load.i16 v1
|
||||||
|
v3 = icmp.i16 ult v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llhr %r2, %r2
|
||||||
|
; nextln: llh %r3, 0(%r3)
|
||||||
|
; nextln: clr %r2, %r3
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i16_mem(i16) -> b1 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
v2 = load.i16 v1
|
||||||
|
v3 = icmp.i16 ult v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llhr %r2, %r2
|
||||||
|
; nextln: clhrl %r2, %sym + 0
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i8(i8, i8) -> b1 {
|
||||||
|
block0(v0: i8, v1: i8):
|
||||||
|
v2 = icmp.i8 ult v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llcr %r2, %r2
|
||||||
|
; nextln: llcr %r3, %r3
|
||||||
|
; nextln: clr %r2, %r3
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i8_imm(i8) -> b1 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = iconst.i8 1
|
||||||
|
v2 = icmp.i8 ult v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llcr %r2, %r2
|
||||||
|
; nextln: clfi %r2, 1
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %icmp_ult_i8_mem(i8, i64) -> b1 {
|
||||||
|
block0(v0: i8, v1: i64):
|
||||||
|
v2 = load.i8 v1
|
||||||
|
v3 = icmp.i8 ult v0, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llcr %r2, %r2
|
||||||
|
; nextln: llc %r3, 0(%r3)
|
||||||
|
; nextln: clr %r2, %r3
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochil %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
45
cranelift/filetests/filetests/isa/s390x/jumptable.clif
Normal file
45
cranelift/filetests/filetests/isa/s390x/jumptable.clif
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
function %f(i64) -> i64 {
|
||||||
|
jt0 = jump_table [block1, block2, block3]
|
||||||
|
|
||||||
|
block0(v0: i64):
|
||||||
|
br_table v0, block4, jt0
|
||||||
|
|
||||||
|
block1:
|
||||||
|
v1 = iconst.i64 1
|
||||||
|
jump block5(v1)
|
||||||
|
|
||||||
|
block2:
|
||||||
|
v2 = iconst.i64 2
|
||||||
|
jump block5(v2)
|
||||||
|
|
||||||
|
block3:
|
||||||
|
v3 = iconst.i64 3
|
||||||
|
jump block5(v3)
|
||||||
|
|
||||||
|
block4:
|
||||||
|
v4 = iconst.i64 4
|
||||||
|
jump block5(v4)
|
||||||
|
|
||||||
|
block5(v5: i64):
|
||||||
|
v6 = iadd.i64 v0, v5
|
||||||
|
return v6
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clgfi %r2, 3 ; jghe label1 ; sllg %r4, %r2, 2 ; larl %r3, 18 ; lgf %r4, 0(%r4, %r3) ; agrk %r3, %r3, %r4 ; br %r3 ; jt_entries
|
||||||
|
|
||||||
|
; check: lghi %r3, 1
|
||||||
|
; nextln: jg
|
||||||
|
|
||||||
|
; check: lghi %r3, 2
|
||||||
|
; nextln: jg
|
||||||
|
|
||||||
|
; check: lghi %r3, 3
|
||||||
|
; nextln: jg
|
||||||
|
|
||||||
|
; check: agr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
|
||||||
258
cranelift/filetests/filetests/isa/s390x/load-little.clif
Normal file
258
cranelift/filetests/filetests/isa/s390x/load-little.clif
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
function %load_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = load.i64 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lrvg %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %load_i64_sym() -> i64 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0:
|
||||||
|
v0 = symbol_value.i64 gv0
|
||||||
|
v1 = load.i64 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: larl %r1, %sym + 0 ; lrvg %r2, 0(%r1)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uload8_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = uload8.i64 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llgc %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sload8_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = sload8.i64 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgb %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uload16_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = uload16.i64 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lrvh %r2, 0(%r2)
|
||||||
|
; nextln: llghr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uload16_i64_sym() -> i64 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0:
|
||||||
|
v0 = symbol_value.i64 gv0
|
||||||
|
v1 = uload16.i64 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: larl %r1, %sym + 0 ; lrvh %r2, 0(%r1)
|
||||||
|
; nextln: llghr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sload16_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = sload16.i64 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lrvh %r2, 0(%r2)
|
||||||
|
; nextln: lghr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sload16_i64_sym() -> i64 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0:
|
||||||
|
v0 = symbol_value.i64 gv0
|
||||||
|
v1 = sload16.i64 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: larl %r1, %sym + 0 ; lrvh %r2, 0(%r1)
|
||||||
|
; nextln: lghr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uload32_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = uload32.i64 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lrv %r2, 0(%r2)
|
||||||
|
; nextln: llgfr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uload32_i64_sym() -> i64 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0:
|
||||||
|
v0 = symbol_value.i64 gv0
|
||||||
|
v1 = uload32.i64 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: larl %r1, %sym + 0 ; lrv %r2, 0(%r1)
|
||||||
|
; nextln: llgfr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sload32_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = sload32.i64 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lrv %r2, 0(%r2)
|
||||||
|
; nextln: lgfr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sload32_i64_sym() -> i64 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0:
|
||||||
|
v0 = symbol_value.i64 gv0
|
||||||
|
v1 = sload32.i64 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: larl %r1, %sym + 0 ; lrv %r2, 0(%r1)
|
||||||
|
; nextln: lgfr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %load_i32(i64) -> i32 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = load.i32 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lrv %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %load_i32_sym() -> i32 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0:
|
||||||
|
v0 = symbol_value.i64 gv0
|
||||||
|
v1 = load.i32 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: larl %r1, %sym + 0 ; lrv %r2, 0(%r1)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uload8_i32(i64) -> i32 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = uload8.i32 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llc %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sload8_i32(i64) -> i32 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = sload8.i32 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lb %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uload16_i32(i64) -> i32 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = uload16.i32 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lrvh %r2, 0(%r2)
|
||||||
|
; nextln: llhr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uload16_i32_sym() -> i32 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0:
|
||||||
|
v0 = symbol_value.i64 gv0
|
||||||
|
v1 = uload16.i32 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: larl %r1, %sym + 0 ; lrvh %r2, 0(%r1)
|
||||||
|
; nextln: llhr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sload16_i32(i64) -> i32 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = sload16.i32 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lrvh %r2, 0(%r2)
|
||||||
|
; nextln: lhr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sload16_i32_sym() -> i32 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0:
|
||||||
|
v0 = symbol_value.i64 gv0
|
||||||
|
v1 = sload16.i32 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: larl %r1, %sym + 0 ; lrvh %r2, 0(%r1)
|
||||||
|
; nextln: lhr %r2, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %load_i16(i64) -> i16 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = load.i16 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lrvh %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %load_i16_sym() -> i16 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0:
|
||||||
|
v0 = symbol_value.i64 gv0
|
||||||
|
v1 = load.i16 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: larl %r1, %sym + 0 ; lrvh %r2, 0(%r1)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uload8_i16(i64) -> i16 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = uload8.i16 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llc %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sload8_i16(i64) -> i16 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = sload8.i16 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lb %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %load_i8(i64) -> i8 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = load.i8 little v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llc %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
264
cranelift/filetests/filetests/isa/s390x/load.clif
Normal file
264
cranelift/filetests/filetests/isa/s390x/load.clif
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
function %load_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = load.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lg %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %load_i64_sym() -> i64 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0:
|
||||||
|
v0 = symbol_value.i64 gv0
|
||||||
|
v1 = load.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgrl %r2, %sym + 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uload8_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = uload8.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llgc %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sload8_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = sload8.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgb %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uload16_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = uload16.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llgh %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uload16_i64_sym() -> i64 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0:
|
||||||
|
v0 = symbol_value.i64 gv0
|
||||||
|
v1 = uload16.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llghrl %r2, %sym + 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sload16_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = sload16.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgh %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sload16_i64_sym() -> i64 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0:
|
||||||
|
v0 = symbol_value.i64 gv0
|
||||||
|
v1 = sload16.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghrl %r2, %sym + 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uload32_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = uload32.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llgf %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uload32_i64_sym() -> i64 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0:
|
||||||
|
v0 = symbol_value.i64 gv0
|
||||||
|
v1 = uload32.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llgfrl %r2, %sym + 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sload32_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = sload32.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgf %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sload32_i64_sym() -> i64 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0:
|
||||||
|
v0 = symbol_value.i64 gv0
|
||||||
|
v1 = sload32.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgfrl %r2, %sym + 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %load_i32(i64) -> i32 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = load.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: l %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %load_i32_sym() -> i32 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0:
|
||||||
|
v0 = symbol_value.i64 gv0
|
||||||
|
v1 = load.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lrl %r2, %sym + 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %load_i32_off(i64) -> i32 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = load.i32 v0+4096
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: ly %r2, 4096(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uload8_i32(i64) -> i32 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = uload8.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llc %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sload8_i32(i64) -> i32 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = sload8.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lb %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uload16_i32(i64) -> i32 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = uload16.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llh %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uload16_i32_sym() -> i32 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0:
|
||||||
|
v0 = symbol_value.i64 gv0
|
||||||
|
v1 = uload16.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llhrl %r2, %sym + 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sload16_i32(i64) -> i32 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = sload16.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lh %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sload16_i32_off(i64) -> i32 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = sload16.i32 v0+4096
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhy %r2, 4096(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sload16_i32_sym() -> i32 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0:
|
||||||
|
v0 = symbol_value.i64 gv0
|
||||||
|
v1 = sload16.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhrl %r2, %sym + 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %load_i16(i64) -> i16 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = load.i16 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llh %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %load_i16_sym() -> i16 {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0:
|
||||||
|
v0 = symbol_value.i64 gv0
|
||||||
|
v1 = load.i16 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llhrl %r2, %sym + 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %uload8_i16(i64) -> i16 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = uload8.i16 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llc %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sload8_i16(i64) -> i16 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = sload8.i16 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lb %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %load_i8(i64) -> i8 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = load.i8 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llc %r2, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
79
cranelift/filetests/filetests/isa/s390x/multivalue-ret.clif
Normal file
79
cranelift/filetests/filetests/isa/s390x/multivalue-ret.clif
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
;; Test default (non-SpiderMonkey) ABI.
|
||||||
|
function %f1() -> i64, i64, i64, i64 {
|
||||||
|
block1:
|
||||||
|
v0 = iconst.i64 1
|
||||||
|
v1 = iconst.i64 2
|
||||||
|
v2 = iconst.i64 3
|
||||||
|
v3 = iconst.i64 4
|
||||||
|
return v0, v1, v2, v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghi %r2, 1
|
||||||
|
; nextln: lghi %r3, 2
|
||||||
|
; nextln: lghi %r4, 3
|
||||||
|
; nextln: lghi %r5, 4
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f1() -> i64, i64, i64, i64, i64, i64 {
|
||||||
|
block1:
|
||||||
|
v0 = iconst.i64 1
|
||||||
|
v1 = iconst.i64 2
|
||||||
|
v2 = iconst.i64 3
|
||||||
|
v3 = iconst.i64 4
|
||||||
|
v4 = iconst.i64 5
|
||||||
|
v5 = iconst.i64 6
|
||||||
|
return v0, v1, v2, v3, v4, v5
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stmg %r12, %r15, 96(%r15)
|
||||||
|
; nextln: lgr %r14, %r2
|
||||||
|
; nextln: lghi %r2, 1
|
||||||
|
; nextln: lghi %r3, 2
|
||||||
|
; nextln: lghi %r4, 3
|
||||||
|
; nextln: lghi %r5, 4
|
||||||
|
; nextln: lghi %r13, 5
|
||||||
|
; nextln: lghi %r12, 6
|
||||||
|
; nextln: stg %r13, 0(%r14)
|
||||||
|
; nextln: stg %r12, 8(%r14)
|
||||||
|
; nextln: lmg %r12, %r15, 96(%r15)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;; Test default (non-SpiderMonkey) ABI.
|
||||||
|
function %f3() -> f64, f64, f64, f64 {
|
||||||
|
block1:
|
||||||
|
v0 = f64const 0x0.0
|
||||||
|
v1 = f64const 0x1.0
|
||||||
|
v2 = f64const 0x2.0
|
||||||
|
v3 = f64const 0x3.0
|
||||||
|
return v0, v1, v2, v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: bras %r1, 12 ; data.f64 0 ; ld %f0, 0(%r1)
|
||||||
|
; nextln: bras %r1, 12 ; data.f64 1 ; ld %f2, 0(%r1)
|
||||||
|
; nextln: bras %r1, 12 ; data.f64 2 ; ld %f4, 0(%r1)
|
||||||
|
; nextln: bras %r1, 12 ; data.f64 3 ; ld %f6, 0(%r1)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f4() -> f64, f64, f64, f64, f64, f64 {
|
||||||
|
block1:
|
||||||
|
v0 = f64const 0x0.0
|
||||||
|
v1 = f64const 0x1.0
|
||||||
|
v2 = f64const 0x2.0
|
||||||
|
v3 = f64const 0x3.0
|
||||||
|
v4 = f64const 0x4.0
|
||||||
|
v5 = f64const 0x5.0
|
||||||
|
return v0, v1, v2, v3, v4, v5
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: bras %r1, 12 ; data.f64 0 ; ld %f0, 0(%r1)
|
||||||
|
; nextln: bras %r1, 12 ; data.f64 1 ; ld %f2, 0(%r1)
|
||||||
|
; nextln: bras %r1, 12 ; data.f64 2 ; ld %f4, 0(%r1)
|
||||||
|
; nextln: bras %r1, 12 ; data.f64 3 ; ld %f6, 0(%r1)
|
||||||
|
; nextln: bras %r1, 12 ; data.f64 4 ; ld %f1, 0(%r1)
|
||||||
|
; nextln: bras %r1, 12 ; data.f64 5 ; ld %f3, 0(%r1)
|
||||||
|
; nextln: std %f1, 0(%r2)
|
||||||
|
; nextln: std %f3, 8(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
101
cranelift/filetests/filetests/isa/s390x/reftypes.clif
Normal file
101
cranelift/filetests/filetests/isa/s390x/reftypes.clif
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
function %f0(r64, r64) -> r64 {
|
||||||
|
block0(v0: r64, v1: r64):
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgr %r2, %r3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f1(r64) -> b1 {
|
||||||
|
block0(v0: r64):
|
||||||
|
v1 = is_null v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cghi %r2, 0
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochie %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f2(r64) -> b1 {
|
||||||
|
block0(v0: r64):
|
||||||
|
v1 = is_invalid v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: cghi %r2, -1
|
||||||
|
; nextln: lhi %r2, 0
|
||||||
|
; nextln: lochie %r2, 1
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f3() -> r64 {
|
||||||
|
block0:
|
||||||
|
v0 = null.r64
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghi %r2, 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %f4(r64, r64) -> r64, r64, r64 {
|
||||||
|
fn0 = %f(r64) -> b1
|
||||||
|
ss0 = explicit_slot 8
|
||||||
|
|
||||||
|
block0(v0: r64, v1: r64):
|
||||||
|
v2 = call fn0(v0)
|
||||||
|
stack_store.r64 v0, ss0
|
||||||
|
brz v2, block1(v1, v0)
|
||||||
|
jump block2(v0, v1)
|
||||||
|
|
||||||
|
block1(v3: r64, v4: r64):
|
||||||
|
jump block3(v3, v4)
|
||||||
|
|
||||||
|
block2(v5: r64, v6: r64):
|
||||||
|
jump block3(v5, v6)
|
||||||
|
|
||||||
|
block3(v7: r64, v8: r64):
|
||||||
|
v9 = stack_load.r64 ss0
|
||||||
|
return v7, v8, v9
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: Block 0:
|
||||||
|
; check: stmg %r12, %r15, 96(%r15)
|
||||||
|
; nextln: aghi %r15, -192
|
||||||
|
; nextln: virtual_sp_offset_adjust 160
|
||||||
|
; nextln: lgr %r13, %r2
|
||||||
|
; nextln: lgr %r12, %r3
|
||||||
|
; nextln: lgr %r2, %r13
|
||||||
|
; nextln: bras %r1, 12 ; data %f + 0 ; lg %r3, 0(%r1)
|
||||||
|
; nextln: stg %r2, 168(%r15)
|
||||||
|
; nextln: stg %r13, 176(%r15)
|
||||||
|
; nextln: stg %r12, 184(%r15)
|
||||||
|
; nextln: (safepoint: slots [S0, S1, S2]
|
||||||
|
; nextln: basr %r14, %r3
|
||||||
|
; nextln: lg %r13, 176(%r15)
|
||||||
|
; nextln: lg %r12, 184(%r15)
|
||||||
|
; nextln: la %r3, 160(%r15)
|
||||||
|
; nextln: stg %r13, 0(%r3)
|
||||||
|
; nextln: llcr %r2, %r2
|
||||||
|
; nextln: chi %r2, 0
|
||||||
|
; nextln: jgnlh label1 ; jg label3
|
||||||
|
; check: Block 1:
|
||||||
|
; check: jg label2
|
||||||
|
; check: Block 2:
|
||||||
|
; check: lgr %r2, %r12
|
||||||
|
; nextln: jg label5
|
||||||
|
; check: Block 3:
|
||||||
|
; check: jg label4
|
||||||
|
; check: Block 4:
|
||||||
|
; check: lgr %r2, %r13
|
||||||
|
; nextln: lgr %r13, %r12
|
||||||
|
; nextln: jg label5
|
||||||
|
; check: Block 5:
|
||||||
|
; check: la %r3, 160(%r15)
|
||||||
|
; nextln: lg %r3, 0(%r3)
|
||||||
|
; nextln: lgr %r4, %r3
|
||||||
|
; nextln: lgr %r3, %r13
|
||||||
|
; nextln: lmg %r12, %r15, 288(%r15)
|
||||||
|
; nextln: br %r14
|
||||||
12
cranelift/filetests/filetests/isa/s390x/saturating-ops.clif
Normal file
12
cranelift/filetests/filetests/isa/s390x/saturating-ops.clif
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
; FIXME: not yet supported
|
||||||
|
|
||||||
|
function %uaddsat64(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
; v2 = uadd_sat.i64 v0, v1
|
||||||
|
v2 = iconst.i64 0
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
461
cranelift/filetests/filetests/isa/s390x/shift-rotate.clif
Normal file
461
cranelift/filetests/filetests/isa/s390x/shift-rotate.clif
Normal file
@@ -0,0 +1,461 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; ROTR
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %rotr_i64_reg(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = rotr.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lcgr %r3, %r3
|
||||||
|
; nextln: rllg %r2, %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %rotr_i64_imm(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i32 17
|
||||||
|
v2 = rotr.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: rllg %r2, %r2, 47
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %rotr_i32_reg(i32, i32) -> i32 {
|
||||||
|
block0(v0: i32, v1: i32):
|
||||||
|
v2 = rotr.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lcr %r3, %r3
|
||||||
|
; nextln: rll %r2, %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %rotr_i32_imm(i32) -> i32 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = iconst.i32 17
|
||||||
|
v2 = rotr.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: rll %r2, %r2, 15
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %rotr_i16_reg(i16, i16) -> i16 {
|
||||||
|
block0(v0: i16, v1: i16):
|
||||||
|
v2 = rotr.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llhr %r2, %r2
|
||||||
|
; nextln: lr %r5, %r3
|
||||||
|
; nextln: lcr %r4, %r3
|
||||||
|
; nextln: nill %r5, 15
|
||||||
|
; nextln: nill %r4, 15
|
||||||
|
; nextln: sllk %r3, %r2, 0(%r5)
|
||||||
|
; nextln: srlk %r2, %r2, 0(%r4)
|
||||||
|
; nextln: ork %r2, %r3, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %rotr_i16_imm(i16) -> i16 {
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = iconst.i32 10
|
||||||
|
v2 = rotr.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llhr %r2, %r2
|
||||||
|
; nextln: sllk %r3, %r2, 6
|
||||||
|
; nextln: srlk %r2, %r2, 10
|
||||||
|
; nextln: ork %r2, %r3, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %rotr_i8_reg(i8, i8) -> i8 {
|
||||||
|
block0(v0: i8, v1: i8):
|
||||||
|
v2 = rotr.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llcr %r2, %r2
|
||||||
|
; nextln: lr %r5, %r3
|
||||||
|
; nextln: lcr %r4, %r3
|
||||||
|
; nextln: nill %r5, 7
|
||||||
|
; nextln: nill %r4, 7
|
||||||
|
; nextln: sllk %r3, %r2, 0(%r5)
|
||||||
|
; nextln: srlk %r2, %r2, 0(%r4)
|
||||||
|
; nextln: ork %r2, %r3, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %rotr_i8_imm(i8) -> i8 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = iconst.i32 3
|
||||||
|
v2 = rotr.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llcr %r2, %r2
|
||||||
|
; nextln: sllk %r3, %r2, 5
|
||||||
|
; nextln: srlk %r2, %r2, 3
|
||||||
|
; nextln: ork %r2, %r3, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; ROTL
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %rotl_i64_reg(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = rotl.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: rllg %r2, %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %rotl_i64_imm(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i32 17
|
||||||
|
v2 = rotl.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: rllg %r2, %r2, 17
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %rotl_i32_reg(i32, i32) -> i32 {
|
||||||
|
block0(v0: i32, v1: i32):
|
||||||
|
v2 = rotl.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: rll %r2, %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %rotl_i32_imm(i32) -> i32 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = iconst.i32 17
|
||||||
|
v2 = rotl.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: rll %r2, %r2, 17
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %rotl_i16_reg(i16, i16) -> i16 {
|
||||||
|
block0(v0: i16, v1: i16):
|
||||||
|
v2 = rotl.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llhr %r2, %r2
|
||||||
|
; nextln: lr %r4, %r3
|
||||||
|
; nextln: lcr %r3, %r3
|
||||||
|
; nextln: nill %r4, 15
|
||||||
|
; nextln: nill %r3, 15
|
||||||
|
; nextln: sllk %r3, %r2, 0(%r3)
|
||||||
|
; nextln: srlk %r2, %r2, 0(%r4)
|
||||||
|
; nextln: ork %r2, %r3, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %rotl_i16_imm(i16) -> i16 {
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = iconst.i32 10
|
||||||
|
v2 = rotl.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llhr %r2, %r2
|
||||||
|
; nextln: sllk %r3, %r2, 10
|
||||||
|
; nextln: srlk %r2, %r2, 6
|
||||||
|
; nextln: ork %r2, %r3, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %rotl_i8_reg(i8, i8) -> i8 {
|
||||||
|
block0(v0: i8, v1: i8):
|
||||||
|
v2 = rotl.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llcr %r2, %r2
|
||||||
|
; nextln: lr %r4, %r3
|
||||||
|
; nextln: lcr %r3, %r3
|
||||||
|
; nextln: nill %r4, 7
|
||||||
|
; nextln: nill %r3, 7
|
||||||
|
; nextln: sllk %r3, %r2, 0(%r3)
|
||||||
|
; nextln: srlk %r2, %r2, 0(%r4)
|
||||||
|
; nextln: ork %r2, %r3, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %rotr_i8_imm(i8) -> i8 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = iconst.i32 3
|
||||||
|
v2 = rotl.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llcr %r2, %r2
|
||||||
|
; nextln: sllk %r3, %r2, 3
|
||||||
|
; nextln: srlk %r2, %r2, 5
|
||||||
|
; nextln: ork %r2, %r3, %r2
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; USHR
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %ushr_i64_reg(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = ushr.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: srlg %r2, %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ushr_i64_imm(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i32 17
|
||||||
|
v2 = ushr.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: srlg %r2, %r2, 17
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ushr_i32_reg(i32, i32) -> i32 {
|
||||||
|
block0(v0: i32, v1: i32):
|
||||||
|
v2 = ushr.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: srlk %r2, %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ushr_i32_imm(i32) -> i32 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = iconst.i32 17
|
||||||
|
v2 = ushr.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: srlk %r2, %r2, 17
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ushr_i16_reg(i16, i16) -> i16 {
|
||||||
|
block0(v0: i16, v1: i16):
|
||||||
|
v2 = ushr.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; FIXME: check shift count ?
|
||||||
|
|
||||||
|
; check: llhr %r2, %r2
|
||||||
|
; nextln: nill %r3, 31
|
||||||
|
; nextln: srlk %r2, %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ushr_i16_imm(i16) -> i16 {
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = iconst.i32 10
|
||||||
|
v2 = ushr.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llhr %r2, %r2
|
||||||
|
; nextln: srlk %r2, %r2, 10
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ushr_i8_reg(i8, i8) -> i8 {
|
||||||
|
block0(v0: i8, v1: i8):
|
||||||
|
v2 = ushr.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llcr %r2, %r2
|
||||||
|
; nextln: nill %r3, 31
|
||||||
|
; nextln: srlk %r2, %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ushr_i8_imm(i8) -> i8 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = iconst.i32 3
|
||||||
|
v2 = ushr.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: llcr %r2, %r2
|
||||||
|
; nextln: srlk %r2, %r2, 3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; ISHL
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %ishl_i64_reg(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = ishl.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sllg %r2, %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ishl_i64_imm(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i32 17
|
||||||
|
v2 = ishl.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sllg %r2, %r2, 17
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ishl_i32_reg(i32, i32) -> i32 {
|
||||||
|
block0(v0: i32, v1: i32):
|
||||||
|
v2 = ishl.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sllk %r2, %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ishl_i32_imm(i32) -> i32 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = iconst.i32 17
|
||||||
|
v2 = ishl.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sllk %r2, %r2, 17
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ishl_i16_reg(i16, i16) -> i16 {
|
||||||
|
block0(v0: i16, v1: i16):
|
||||||
|
v2 = ishl.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nill %r3, 31
|
||||||
|
; nextln: sllk %r2, %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ishl_i16_imm(i16) -> i16 {
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = iconst.i32 10
|
||||||
|
v2 = ishl.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sllk %r2, %r2, 10
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ishl_i8_reg(i8, i8) -> i8 {
|
||||||
|
block0(v0: i8, v1: i8):
|
||||||
|
v2 = ishl.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: nill %r3, 31
|
||||||
|
; nextln: sllk %r2, %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %ishl_i8_imm(i8) -> i8 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = iconst.i32 3
|
||||||
|
v2 = ishl.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sllk %r2, %r2, 3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; SSHR
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %sshr_i64_reg(i64, i64) -> i64 {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
v2 = sshr.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: srag %r2, %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sshr_i64_imm(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i32 17
|
||||||
|
v2 = sshr.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: srag %r2, %r2, 17
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sshr_i32_reg(i32, i32) -> i32 {
|
||||||
|
block0(v0: i32, v1: i32):
|
||||||
|
v2 = sshr.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: srak %r2, %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sshr_i32_imm(i32) -> i32 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = iconst.i32 17
|
||||||
|
v2 = sshr.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: srak %r2, %r2, 17
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sshr_i16_reg(i16, i16) -> i16 {
|
||||||
|
block0(v0: i16, v1: i16):
|
||||||
|
v2 = sshr.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhr %r2, %r2
|
||||||
|
; nextln: nill %r3, 31
|
||||||
|
; nextln: srak %r2, %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sshr_i16_imm(i16) -> i16 {
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = iconst.i32 10
|
||||||
|
v2 = sshr.i16 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhr %r2, %r2
|
||||||
|
; nextln: srak %r2, %r2, 10
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sshr_i8_reg(i8, i8) -> i8 {
|
||||||
|
block0(v0: i8, v1: i8):
|
||||||
|
v2 = sshr.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lbr %r2, %r2
|
||||||
|
; nextln: nill %r3, 31
|
||||||
|
; nextln: srak %r2, %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %sshr_i8_imm(i8) -> i8 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = iconst.i32 3
|
||||||
|
v2 = sshr.i8 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lbr %r2, %r2
|
||||||
|
; nextln: srak %r2, %r2, 3
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
175
cranelift/filetests/filetests/isa/s390x/stack-limit.clif
Normal file
175
cranelift/filetests/filetests/isa/s390x/stack-limit.clif
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
function %foo() {
|
||||||
|
block0:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
function %stack_limit_leaf_zero(i64 stack_limit) {
|
||||||
|
block0(v0: i64):
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: br %r14
|
||||||
|
|
||||||
|
function %stack_limit_gv_leaf_zero(i64 vmctx) {
|
||||||
|
gv0 = vmctx
|
||||||
|
gv1 = load.i64 notrap aligned gv0
|
||||||
|
gv2 = load.i64 notrap aligned gv1+4
|
||||||
|
stack_limit = gv2
|
||||||
|
block0(v0: i64):
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: br %r14
|
||||||
|
|
||||||
|
|
||||||
|
function %stack_limit_call_zero(i64 stack_limit) {
|
||||||
|
fn0 = %foo()
|
||||||
|
block0(v0: i64):
|
||||||
|
call fn0()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clgrtle %r15, %r2
|
||||||
|
; nextln: stmg %r14, %r15, 112(%r15)
|
||||||
|
; nextln: aghi %r15, -160
|
||||||
|
; nextln: virtual_sp_offset_adjust 160
|
||||||
|
; nextln: bras %r1, 12 ; data %foo + 0 ; lg %r2, 0(%r1)
|
||||||
|
; nextln: basr %r14, %r2
|
||||||
|
; nextln: lmg %r14, %r15, 272(%r15)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %stack_limit_gv_call_zero(i64 vmctx) {
|
||||||
|
gv0 = vmctx
|
||||||
|
gv1 = load.i64 notrap aligned gv0
|
||||||
|
gv2 = load.i64 notrap aligned gv1+4
|
||||||
|
stack_limit = gv2
|
||||||
|
fn0 = %foo()
|
||||||
|
block0(v0: i64):
|
||||||
|
call fn0()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lg %r1, 0(%r2)
|
||||||
|
; nextln: lg %r1, 4(%r1)
|
||||||
|
; nextln: clgrtle %r15, %r1
|
||||||
|
; nextln: stmg %r14, %r15, 112(%r15)
|
||||||
|
; nextln: aghi %r15, -160
|
||||||
|
; nextln: virtual_sp_offset_adjust 160
|
||||||
|
; nextln: bras %r1, 12 ; data %foo + 0 ; lg %r2, 0(%r1)
|
||||||
|
; nextln: basr %r14, %r2
|
||||||
|
; nextln: lmg %r14, %r15, 272(%r15)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %stack_limit(i64 stack_limit) {
|
||||||
|
ss0 = explicit_slot 168
|
||||||
|
block0(v0: i64):
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: la %r1, 168(%r2)
|
||||||
|
; nextln: clgrtle %r15, %r1
|
||||||
|
; nextln: aghi %r15, -168
|
||||||
|
; nextln: aghi %r15, 168
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %large_stack_limit(i64 stack_limit) {
|
||||||
|
ss0 = explicit_slot 400000
|
||||||
|
block0(v0: i64):
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clgrtle %r15, %r2
|
||||||
|
; nextln: lay %r1, 400000(%r2)
|
||||||
|
; nextln: clgrtle %r15, %r1
|
||||||
|
; nextln: agfi %r15, -400000
|
||||||
|
; nextln: agfi %r15, 400000
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %huge_stack_limit(i64 stack_limit) {
|
||||||
|
ss0 = explicit_slot 4000000
|
||||||
|
block0(v0: i64):
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: clgrtle %r15, %r2
|
||||||
|
; nextln: lgr %r1, %r2
|
||||||
|
; nextln: algfi %r1, 4000000
|
||||||
|
; nextln: clgrtle %r15, %r1
|
||||||
|
; nextln: agfi %r15, -4000000
|
||||||
|
; nextln: agfi %r15, 4000000
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %limit_preamble(i64 vmctx) {
|
||||||
|
gv0 = vmctx
|
||||||
|
gv1 = load.i64 notrap aligned gv0
|
||||||
|
gv2 = load.i64 notrap aligned gv1+4
|
||||||
|
stack_limit = gv2
|
||||||
|
ss0 = explicit_slot 20
|
||||||
|
block0(v0: i64):
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lg %r1, 0(%r2)
|
||||||
|
; nextln: lg %r1, 4(%r1)
|
||||||
|
; nextln: la %r1, 24(%r1)
|
||||||
|
; nextln: clgrtle %r15, %r1
|
||||||
|
; nextln: aghi %r15, -24
|
||||||
|
; nextln: aghi %r15, 24
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %limit_preamble_large(i64 vmctx) {
|
||||||
|
gv0 = vmctx
|
||||||
|
gv1 = load.i64 notrap aligned gv0
|
||||||
|
gv2 = load.i64 notrap aligned gv1+4
|
||||||
|
stack_limit = gv2
|
||||||
|
ss0 = explicit_slot 400000
|
||||||
|
block0(v0: i64):
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lg %r1, 0(%r2)
|
||||||
|
; nextln: lg %r1, 4(%r1)
|
||||||
|
; nextln: clgrtle %r15, %r1
|
||||||
|
; nextln: lay %r1, 400000(%r1)
|
||||||
|
; nextln: clgrtle %r15, %r1
|
||||||
|
; nextln: agfi %r15, -400000
|
||||||
|
; nextln: agfi %r15, 400000
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %limit_preamble_huge(i64 vmctx) {
|
||||||
|
gv0 = vmctx
|
||||||
|
gv1 = load.i64 notrap aligned gv0
|
||||||
|
gv2 = load.i64 notrap aligned gv1+4
|
||||||
|
stack_limit = gv2
|
||||||
|
ss0 = explicit_slot 4000000
|
||||||
|
block0(v0: i64):
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lg %r1, 0(%r2)
|
||||||
|
; nextln: lg %r1, 4(%r1)
|
||||||
|
; nextln: clgrtle %r15, %r1
|
||||||
|
; nextln: algfi %r1, 4000000
|
||||||
|
; nextln: clgrtle %r15, %r1
|
||||||
|
; nextln: agfi %r15, -4000000
|
||||||
|
; nextln: agfi %r15, 4000000
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %limit_preamble_huge_offset(i64 vmctx) {
|
||||||
|
gv0 = vmctx
|
||||||
|
gv1 = load.i64 notrap aligned gv0+1000000
|
||||||
|
stack_limit = gv1
|
||||||
|
ss0 = explicit_slot 20
|
||||||
|
block0(v0: i64):
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lgfi %r1, 1000000 ; lg %r1, 0(%r1,%r2)
|
||||||
|
; nextln: la %r1, 24(%r1)
|
||||||
|
; nextln: clgrtle %r15, %r1
|
||||||
|
; nextln: aghi %r15, -24
|
||||||
|
; nextln: aghi %r15, 24
|
||||||
|
; nextln: br %r14
|
||||||
93
cranelift/filetests/filetests/isa/s390x/stack.clif
Normal file
93
cranelift/filetests/filetests/isa/s390x/stack.clif
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
; FIXME: Should allocate register save area.
|
||||||
|
|
||||||
|
function %stack_addr_small() -> i64 {
|
||||||
|
ss0 = explicit_slot 8
|
||||||
|
|
||||||
|
block0:
|
||||||
|
v0 = stack_addr.i64 ss0
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: aghi %r15, -8
|
||||||
|
; nextln: la %r2, 0(%r15)
|
||||||
|
; nextln: aghi %r15, 8
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %stack_addr_big() -> i64 {
|
||||||
|
ss0 = explicit_slot 100000
|
||||||
|
ss1 = explicit_slot 8
|
||||||
|
|
||||||
|
block0:
|
||||||
|
v0 = stack_addr.i64 ss0
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: agfi %r15, -100008
|
||||||
|
; nextln: la %r2, 0(%r15)
|
||||||
|
; nextln: agfi %r15, 100008
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
; FIXME: don't use stack_addr legalization for stack_load and stack_store
|
||||||
|
|
||||||
|
function %stack_load_small() -> i64 {
|
||||||
|
ss0 = explicit_slot 8
|
||||||
|
|
||||||
|
block0:
|
||||||
|
v0 = stack_load.i64 ss0
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: aghi %r15, -8
|
||||||
|
; nextln: la %r2, 0(%r15)
|
||||||
|
; nextln: lg %r2, 0(%r2)
|
||||||
|
; nextln: aghi %r15, 8
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %stack_load_big() -> i64 {
|
||||||
|
ss0 = explicit_slot 100000
|
||||||
|
ss1 = explicit_slot 8
|
||||||
|
|
||||||
|
block0:
|
||||||
|
v0 = stack_load.i64 ss0
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: agfi %r15, -100008
|
||||||
|
; nextln: la %r2, 0(%r15)
|
||||||
|
; nextln: lg %r2, 0(%r2)
|
||||||
|
; nextln: agfi %r15, 100008
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
|
||||||
|
function %stack_store_small(i64) {
|
||||||
|
ss0 = explicit_slot 8
|
||||||
|
|
||||||
|
block0(v0: i64):
|
||||||
|
stack_store.i64 v0, ss0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: aghi %r15, -8
|
||||||
|
; nextln: la %r3, 0(%r15)
|
||||||
|
; nextln: stg %r2, 0(%r3)
|
||||||
|
; nextln: aghi %r15, 8
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %stack_store_big(i64) {
|
||||||
|
ss0 = explicit_slot 100000
|
||||||
|
ss1 = explicit_slot 8
|
||||||
|
|
||||||
|
block0(v0: i64):
|
||||||
|
stack_store.i64 v0, ss0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: agfi %r15, -100008
|
||||||
|
; nextln: la %r3, 0(%r15)
|
||||||
|
; nextln: stg %r2, 0(%r3)
|
||||||
|
; nextln: agfi %r15, 100008
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
281
cranelift/filetests/filetests/isa/s390x/store-little.clif
Normal file
281
cranelift/filetests/filetests/isa/s390x/store-little.clif
Normal file
@@ -0,0 +1,281 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
function %store_i64(i64, i64) {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
store.i64 little v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: strvg %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_i64_sym(i64) {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
store.i64 little v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: larl %r1, %sym + 0 ; strvg %r2, 0(%r1)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_imm_i64(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i64 12345
|
||||||
|
store.i64 little v1, v0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghi %r3, 12345
|
||||||
|
; nextln: strvg %r3, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore8_i64(i64, i64) {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
istore8.i64 little v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stc %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore8_imm_i64(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i64 123
|
||||||
|
istore8.i64 little v1, v0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: mvi 0(%r2), 123
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore16_i64(i64, i64) {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
istore16.i64 little v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: strvh %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore16_i64_sym(i64) {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
istore16.i64 little v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: larl %r1, %sym + 0 ; strvh %r2, 0(%r1)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore16_imm_i64(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i64 12345
|
||||||
|
istore16.i64 little v1, v0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: mvhhi 0(%r2), 14640
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore32_i64(i64, i64) {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
istore32.i64 little v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: strv %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore32_i64_sym(i64) {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
istore32.i64 little v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: larl %r1, %sym + 0 ; strv %r2, 0(%r1)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore32_imm_i64(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i64 12345
|
||||||
|
istore32.i64 little v1, v0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lghi %r3, 12345
|
||||||
|
; nextln: strv %r3, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_i32(i32, i64) {
|
||||||
|
block0(v0: i32, v1: i64):
|
||||||
|
store.i32 little v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: strv %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_i32_sym(i32) {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
store.i32 little v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: larl %r1, %sym + 0 ; strv %r2, 0(%r1)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_imm_i32(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i32 12345
|
||||||
|
store.i32 little v1, v0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: lhi %r3, 12345
|
||||||
|
; nextln: strv %r3, 0(%r2)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore8_i32(i32, i64) {
|
||||||
|
block0(v0: i32, v1: i64):
|
||||||
|
istore8.i32 little v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stc %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore8_imm_i32(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i32 123
|
||||||
|
istore8.i32 little v1, v0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: mvi 0(%r2), 123
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore16_i32(i32, i64) {
|
||||||
|
block0(v0: i32, v1: i64):
|
||||||
|
istore16.i32 little v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: strvh %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore16_i32_sym(i32) {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
istore16.i32 little v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: larl %r1, %sym + 0 ; strvh %r2, 0(%r1)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore16_imm_i32(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i32 12345
|
||||||
|
istore16.i32 little v1, v0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: mvhhi 0(%r2), 14640
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_i16(i16, i64) {
|
||||||
|
block0(v0: i16, v1: i64):
|
||||||
|
store.i16 little v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: strvh %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_i16_sym(i16) {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
store.i16 little v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: larl %r1, %sym + 0 ; strvh %r2, 0(%r1)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_imm_i16(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i16 12345
|
||||||
|
store.i16 little v1, v0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: mvhhi 0(%r2), 14640
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore8_i16(i16, i64) {
|
||||||
|
block0(v0: i16, v1: i64):
|
||||||
|
istore8.i16 little v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stc %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore8_imm_i16(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i16 123
|
||||||
|
istore8.i16 little v1, v0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: mvi 0(%r2), 123
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_i8(i8, i64) {
|
||||||
|
block0(v0: i8, v1: i64):
|
||||||
|
store.i8 little v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stc %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_i8_off(i8, i64) {
|
||||||
|
block0(v0: i8, v1: i64):
|
||||||
|
store.i8 little v0, v1+4096
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stcy %r2, 4096(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_imm_i8(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i8 123
|
||||||
|
store.i8 little v1, v0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: mvi 0(%r2), 123
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_imm_i8_off(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i8 123
|
||||||
|
store.i8 little v1, v0+4096
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: mviy 4096(%r2), 123
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
296
cranelift/filetests/filetests/isa/s390x/store.clif
Normal file
296
cranelift/filetests/filetests/isa/s390x/store.clif
Normal file
@@ -0,0 +1,296 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
function %store_i64(i64, i64) {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
store.i64 v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stg %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_i64_sym(i64) {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
store.i64 v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stgrl %r2, %sym + 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_imm_i64(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i64 12345
|
||||||
|
store.i64 v1, v0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: mvghi 0(%r2), 12345
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore8_i64(i64, i64) {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
istore8.i64 v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stc %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore8_imm_i64(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i64 123
|
||||||
|
istore8.i64 v1, v0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: mvi 0(%r2), 123
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore16_i64(i64, i64) {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
istore16.i64 v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sth %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore16_i64_sym(i64) {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
istore16.i64 v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sthrl %r2, %sym + 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore16_imm_i64(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i64 12345
|
||||||
|
istore16.i64 v1, v0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: mvhhi 0(%r2), 12345
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore32_i64(i64, i64) {
|
||||||
|
block0(v0: i64, v1: i64):
|
||||||
|
istore32.i64 v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: st %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore32_i64_sym(i64) {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
istore32.i64 v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: strl %r2, %sym + 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore32_imm_i64(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i64 12345
|
||||||
|
istore32.i64 v1, v0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: mvhi 0(%r2), 12345
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_i32(i32, i64) {
|
||||||
|
block0(v0: i32, v1: i64):
|
||||||
|
store.i32 v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: st %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_i32_sym(i32) {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
store.i32 v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: strl %r2, %sym + 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_i32_off(i32, i64) {
|
||||||
|
block0(v0: i32, v1: i64):
|
||||||
|
store.i32 v0, v1+4096
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sty %r2, 4096(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_imm_i32(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i32 12345
|
||||||
|
store.i32 v1, v0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: mvhi 0(%r2), 12345
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore8_i32(i32, i64) {
|
||||||
|
block0(v0: i32, v1: i64):
|
||||||
|
istore8.i32 v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stc %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore8_imm_i32(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i32 123
|
||||||
|
istore8.i32 v1, v0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: mvi 0(%r2), 123
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore16_i32(i32, i64) {
|
||||||
|
block0(v0: i32, v1: i64):
|
||||||
|
istore16.i32 v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sth %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore16_i32_sym(i32) {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
istore16.i32 v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sthrl %r2, %sym + 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore16_imm_i32(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i32 12345
|
||||||
|
istore16.i32 v1, v0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: mvhhi 0(%r2), 12345
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_i16(i16, i64) {
|
||||||
|
block0(v0: i16, v1: i64):
|
||||||
|
store.i16 v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sth %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_i16_sym(i16) {
|
||||||
|
gv0 = symbol colocated %sym
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = symbol_value.i64 gv0
|
||||||
|
store.i16 v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sthrl %r2, %sym + 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_i16_off(i16, i64) {
|
||||||
|
block0(v0: i16, v1: i64):
|
||||||
|
store.i16 v0, v1+4096
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: sthy %r2, 4096(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_imm_i16(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i16 12345
|
||||||
|
store.i16 v1, v0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: mvhhi 0(%r2), 12345
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore8_i16(i16, i64) {
|
||||||
|
block0(v0: i16, v1: i64):
|
||||||
|
istore8.i16 v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stc %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %istore8_imm_i16(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i16 123
|
||||||
|
istore8.i16 v1, v0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: mvi 0(%r2), 123
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_i8(i8, i64) {
|
||||||
|
block0(v0: i8, v1: i64):
|
||||||
|
store.i8 v0, v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stc %r2, 0(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_i8_off(i8, i64) {
|
||||||
|
block0(v0: i8, v1: i64):
|
||||||
|
store.i8 v0, v1+4096
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stcy %r2, 4096(%r3)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_imm_i8(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i8 123
|
||||||
|
store.i8 v1, v0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: mvi 0(%r2), 123
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %store_imm_i8_off(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i8 123
|
||||||
|
store.i8 v1, v0+4096
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: mviy 4096(%r2), 123
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
54
cranelift/filetests/filetests/isa/s390x/symbols.clif
Normal file
54
cranelift/filetests/filetests/isa/s390x/symbols.clif
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; SYMBOL_VALUE
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %symbol_value() -> i64 {
|
||||||
|
gv0 = symbol %my_global
|
||||||
|
|
||||||
|
block0:
|
||||||
|
v0 = symbol_value.i64 gv0
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: bras %r1, 12 ; data %my_global + 0 ; lg %r2, 0(%r1)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %symbol_value_colocated() -> i64 {
|
||||||
|
gv0 = symbol colocated %my_global_colo
|
||||||
|
|
||||||
|
block0:
|
||||||
|
v0 = symbol_value.i64 gv0
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: larl %r2, %my_global_colo + 0
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; FUNC_ADDR
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %func_addr() -> i64 {
|
||||||
|
fn0 = %my_func(i64) -> i64
|
||||||
|
|
||||||
|
block0:
|
||||||
|
v0 = func_addr.i64 fn0
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: bras %r1, 12 ; data %my_func + 0 ; lg %r2, 0(%r1)
|
||||||
|
; nextln: br %r14
|
||||||
|
|
||||||
|
function %func_addr_colocated() -> i64 {
|
||||||
|
fn0 = colocated %my_func_colo(i64) -> i64
|
||||||
|
|
||||||
|
block0:
|
||||||
|
v0 = func_addr.i64 fn0
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: larl %r2, %my_func_colo + 0
|
||||||
|
; nextln: br %r14
|
||||||
91
cranelift/filetests/filetests/isa/s390x/traps.clif
Normal file
91
cranelift/filetests/filetests/isa/s390x/traps.clif
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
test compile
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; TRAP/RESUMABLE_TRAP
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %trap() {
|
||||||
|
block0:
|
||||||
|
trap user0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: trap
|
||||||
|
|
||||||
|
function %resumable_trap() {
|
||||||
|
block0:
|
||||||
|
trap user0
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: trap
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; TRAPZ
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %trapz(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i64 42
|
||||||
|
v2 = icmp eq v0, v1
|
||||||
|
trapz v2, user0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; FIXME: Does not use TrapIf internally as trapz is expanded.
|
||||||
|
; check: Block 0
|
||||||
|
; check: clgfi %r2, 42
|
||||||
|
; nextln: jge label1 ; jg label2
|
||||||
|
; check: Block 1:
|
||||||
|
; check: br %r14
|
||||||
|
; check: Block 2:
|
||||||
|
; check: trap
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; TRAPNZ/RESUMABLE_TRAPNZ
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %trapnz(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i64 42
|
||||||
|
v2 = icmp eq v0, v1
|
||||||
|
trapnz v2, user0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; FIXME: Does not use TrapIf internally as trapnz is expanded.
|
||||||
|
; check: Block 0
|
||||||
|
; check: clgfi %r2, 42
|
||||||
|
; nextln: jgne label1 ; jg label2
|
||||||
|
; check: Block 1:
|
||||||
|
; check: br %r14
|
||||||
|
; check: Block 2:
|
||||||
|
; check: trap
|
||||||
|
|
||||||
|
function %resumable_trapnz(i64) {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i64 42
|
||||||
|
v2 = icmp eq v0, v1
|
||||||
|
trapnz v2, user0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; FIXME: Does not use TrapIf internally as resumable_trapnz is expanded.
|
||||||
|
; check: Block 0
|
||||||
|
; check: clgfi %r2, 42
|
||||||
|
; nextln: jgne label1 ; jg label2
|
||||||
|
; check: Block 1:
|
||||||
|
; check: br %r14
|
||||||
|
; check: Block 2:
|
||||||
|
; check: trap
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; DEBUGTRAP
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
function %h() {
|
||||||
|
block0:
|
||||||
|
debugtrap
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: debugtrap
|
||||||
Reference in New Issue
Block a user