Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

s390x: Add z14 support #2991

Merged
merged 1 commit into from
Jun 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 39 additions & 2 deletions cranelift/codegen/meta/src/isa/s390x/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,50 @@ 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::cdsl::settings::{SettingGroup, SettingGroupBuilder};

use crate::shared::Definitions as SharedDefinitions;

fn define_settings(_shared: &SettingGroup) -> SettingGroup {
let mut settings = SettingGroupBuilder::new("s390x");

// The baseline architecture for cranelift is z14 (arch12),
// so we list only facilities of later processors here.

// z15 (arch13) facilities
let has_mie2 = settings.add_bool(
"has_mie2",
"Has Miscellaneous-Instruction-Extensions Facility 2 support.",
"",
false,
);
let has_vxrs_ext2 = settings.add_bool(
"has_vxrs_ext2",
"Has Vector-Enhancements Facility 2 support.",
"",
false,
);

// Architecture level presets
settings.add_preset(
"arch13",
"Thirteenth Edition of the z/Architecture.",
preset!(has_mie2 && has_vxrs_ext2),
);

// Processor presets
settings.add_preset(
"z15",
"IBM z15 processor.",
preset!(has_mie2 && has_vxrs_ext2),
);

settings.build()
}

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 settings = define_settings(&shared_defs.settings);
let regs = IsaRegsBuilder::new().build();
let recipes = Recipes::new();
let encodings_predicates = InstructionPredicateMap::new();
Expand Down
31 changes: 27 additions & 4 deletions cranelift/codegen/src/isa/s390x/inst/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::ir::condcodes::IntCC;
use crate::ir::MemFlags;
use crate::ir::{SourceLoc, TrapCode};
use crate::isa::s390x::inst::*;
use crate::isa::s390x::settings as s390x_settings;
use core::convert::TryFrom;
use log::debug;
use regalloc::{Reg, RegClass};
Expand Down Expand Up @@ -905,17 +906,20 @@ impl EmitState {
}

/// Constant state used during function compilation.
pub struct EmitInfo(settings::Flags);
pub struct EmitInfo {
flags: settings::Flags,
isa_flags: s390x_settings::Flags,
}

impl EmitInfo {
pub(crate) fn new(flags: settings::Flags) -> Self {
Self(flags)
pub(crate) fn new(flags: settings::Flags, isa_flags: s390x_settings::Flags) -> Self {
Self { flags, isa_flags }
}
}

impl MachInstEmitInfo for EmitInfo {
fn flags(&self) -> &settings::Flags {
&self.0
&self.flags
}
}

Expand All @@ -924,6 +928,25 @@ impl MachInstEmit for Inst {
type Info = EmitInfo;

fn emit(&self, sink: &mut MachBuffer<Inst>, emit_info: &Self::Info, state: &mut EmitState) {
// Verify that we can emit this Inst in the current ISA
let matches_isa_flags = |iset_requirement: &InstructionSet| -> bool {
match iset_requirement {
// Baseline ISA is z14
InstructionSet::Base => true,
// Miscellaneous-Instruction-Extensions Facility 2 (z15)
InstructionSet::MIE2 => emit_info.isa_flags.has_mie2(),
// Vector-Enhancements Facility 2 (z15)
InstructionSet::VXRS_EXT2 => emit_info.isa_flags.has_vxrs_ext2(),
}
};
let isa_requirements = self.available_in_isa();
if !matches_isa_flags(&isa_requirements) {
panic!(
"Cannot emit inst '{:?}' for target; failed to match ISA requirements: {:?}",
self, isa_requirements
)
}

// N.B.: we *must* not exceed the "worst-case size" used to compute
// where to insert islands, except when islands are explicitly triggered
// (with an `EmitIsland`). We check this in debug builds. This is `mut`
Expand Down
9 changes: 8 additions & 1 deletion cranelift/codegen/src/isa/s390x/inst/emit_tests.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::ir::MemFlags;
use crate::isa::s390x::inst::*;
use crate::isa::s390x::settings as s390x_settings;
use crate::isa::test_utils;
use crate::settings;
use alloc::vec::Vec;
Expand Down Expand Up @@ -7767,8 +7768,14 @@ fn test_s390x_binemit() {
));

let flags = settings::Flags::new(settings::builder());

use crate::settings::Configurable;
let mut isa_flag_builder = s390x_settings::builder();
isa_flag_builder.enable("arch13").unwrap();
let isa_flags = s390x_settings::Flags::new(&flags, isa_flag_builder);

let rru = create_reg_universe(&flags);
let emit_info = EmitInfo::new(flags);
let emit_info = EmitInfo::new(flags, isa_flags);
for (insn, expected_encoding, expected_printing) in insns {
println!(
"S390x: {:?}, {}, {}",
Expand Down
173 changes: 161 additions & 12 deletions cranelift/codegen/src/isa/s390x/inst/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ mod emit_tests;
//=============================================================================
// Instructions (top level): definition

/// Supported instruction sets
#[allow(non_camel_case_types)]
#[derive(Debug)]
pub(crate) enum InstructionSet {
/// Baseline ISA for cranelift is z14.
Base,
/// Miscellaneous-Instruction-Extensions Facility 2 (z15)
MIE2,
/// Vector-Enhancements Facility 2 (z15)
VXRS_EXT2,
}

/// An ALU operation. This can be paired with several instruction formats
/// below (see `Inst`) in any combination.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -70,6 +82,17 @@ pub enum ALUOp {
XorNot64,
}

impl ALUOp {
pub(crate) fn available_from(&self) -> InstructionSet {
match self {
ALUOp::AndNot32 | ALUOp::AndNot64 => InstructionSet::MIE2,
ALUOp::OrrNot32 | ALUOp::OrrNot64 => InstructionSet::MIE2,
ALUOp::XorNot32 | ALUOp::XorNot64 => InstructionSet::MIE2,
_ => InstructionSet::Base,
}
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum UnaryOp {
Abs32,
Expand All @@ -82,6 +105,15 @@ pub enum UnaryOp {
PopcntReg,
}

impl UnaryOp {
pub(crate) fn available_from(&self) -> InstructionSet {
match self {
UnaryOp::PopcntReg => InstructionSet::MIE2,
_ => InstructionSet::Base,
}
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum ShiftOp {
RotL32,
Expand Down Expand Up @@ -941,18 +973,6 @@ pub enum Inst {
},
}

fn count_zero_half_words(mut value: u64) -> usize {
let mut count = 0;
for _ in 0..4 {
if value & 0xffff == 0 {
count += 1;
}
value >>= 16;
}

count
}

#[test]
fn inst_size_test() {
// This test will help with unintentionally growing the size
Expand All @@ -961,6 +981,135 @@ fn inst_size_test() {
}

impl Inst {
/// Retrieve the ISA feature set in which the instruction is available.
fn available_in_isa(&self) -> InstructionSet {
match self {
// These instructions are part of the baseline ISA for cranelift (z14)
Inst::Nop0
| Inst::Nop2
| Inst::AluRRSImm16 { .. }
| Inst::AluRR { .. }
| Inst::AluRX { .. }
| Inst::AluRSImm16 { .. }
| Inst::AluRSImm32 { .. }
| Inst::AluRUImm32 { .. }
| Inst::AluRUImm16Shifted { .. }
| Inst::AluRUImm32Shifted { .. }
| Inst::ShiftRR { .. }
| Inst::SMulWide { .. }
| Inst::UMulWide { .. }
| Inst::SDivMod32 { .. }
| Inst::SDivMod64 { .. }
| Inst::UDivMod32 { .. }
| Inst::UDivMod64 { .. }
| Inst::Flogr { .. }
| Inst::CmpRR { .. }
| Inst::CmpRX { .. }
| Inst::CmpRSImm16 { .. }
| Inst::CmpRSImm32 { .. }
| Inst::CmpRUImm32 { .. }
| Inst::CmpTrapRR { .. }
| Inst::CmpTrapRSImm16 { .. }
| Inst::CmpTrapRUImm16 { .. }
| Inst::AtomicRmw { .. }
| Inst::AtomicCas32 { .. }
| Inst::AtomicCas64 { .. }
| Inst::Fence
| Inst::Load32 { .. }
| Inst::Load32ZExt8 { .. }
| Inst::Load32SExt8 { .. }
| Inst::Load32ZExt16 { .. }
| Inst::Load32SExt16 { .. }
| Inst::Load64 { .. }
| Inst::Load64ZExt8 { .. }
| Inst::Load64SExt8 { .. }
| Inst::Load64ZExt16 { .. }
| Inst::Load64SExt16 { .. }
| Inst::Load64ZExt32 { .. }
| Inst::Load64SExt32 { .. }
| Inst::LoadRev16 { .. }
| Inst::LoadRev32 { .. }
| Inst::LoadRev64 { .. }
| Inst::Store8 { .. }
| Inst::Store16 { .. }
| Inst::Store32 { .. }
| Inst::Store64 { .. }
| Inst::StoreImm8 { .. }
| Inst::StoreImm16 { .. }
| Inst::StoreImm32SExt16 { .. }
| Inst::StoreImm64SExt16 { .. }
| Inst::StoreRev16 { .. }
| Inst::StoreRev32 { .. }
| Inst::StoreRev64 { .. }
| Inst::LoadMultiple64 { .. }
| Inst::StoreMultiple64 { .. }
| Inst::Mov32 { .. }
| Inst::Mov64 { .. }
| Inst::Mov32Imm { .. }
| Inst::Mov32SImm16 { .. }
| Inst::Mov64SImm16 { .. }
| Inst::Mov64SImm32 { .. }
| Inst::Mov64UImm16Shifted { .. }
| Inst::Mov64UImm32Shifted { .. }
| Inst::Insert64UImm16Shifted { .. }
| Inst::Insert64UImm32Shifted { .. }
| Inst::Extend { .. }
| Inst::CMov32 { .. }
| Inst::CMov64 { .. }
| Inst::CMov32SImm16 { .. }
| Inst::CMov64SImm16 { .. }
| Inst::FpuMove32 { .. }
| Inst::FpuMove64 { .. }
| Inst::FpuCMov32 { .. }
| Inst::FpuCMov64 { .. }
| Inst::MovToFpr { .. }
| Inst::MovFromFpr { .. }
| Inst::FpuRR { .. }
| Inst::FpuRRR { .. }
| Inst::FpuRRRR { .. }
| Inst::FpuCopysign { .. }
| Inst::FpuCmp32 { .. }
| Inst::FpuCmp64 { .. }
| Inst::FpuLoad32 { .. }
| Inst::FpuStore32 { .. }
| Inst::FpuLoad64 { .. }
| Inst::FpuStore64 { .. }
| Inst::LoadFpuConst32 { .. }
| Inst::LoadFpuConst64 { .. }
| Inst::FpuToInt { .. }
| Inst::IntToFpu { .. }
| Inst::FpuRound { .. }
| Inst::FpuVecRRR { .. }
| Inst::Call { .. }
| Inst::CallInd { .. }
| Inst::Ret { .. }
| Inst::EpiloguePlaceholder
| Inst::Jump { .. }
| Inst::CondBr { .. }
| Inst::TrapIf { .. }
| Inst::OneWayCondBr { .. }
| Inst::IndirectBr { .. }
| Inst::Debugtrap
| Inst::Trap { .. }
| Inst::JTSequence { .. }
| Inst::LoadExtNameFar { .. }
| Inst::LoadAddr { .. }
| Inst::VirtualSPOffsetAdj { .. }
| Inst::ValueLabelMarker { .. }
| Inst::Unwind { .. } => InstructionSet::Base,

// These depend on the opcode
Inst::AluRRR { alu_op, .. } => alu_op.available_from(),
Inst::UnaryRR { op, .. } => op.available_from(),

// These are all part of VXRS_EXT2
Inst::FpuLoadRev32 { .. }
| Inst::FpuStoreRev32 { .. }
| Inst::FpuLoadRev64 { .. }
| Inst::FpuStoreRev64 { .. } => InstructionSet::VXRS_EXT2,
}
}

/// Create a 64-bit move instruction.
pub fn mov64(to_reg: Writable<Reg>, from_reg: Reg) -> Inst {
assert!(to_reg.to_reg().get_class() == from_reg.get_class());
Expand Down
Loading