Path: blob/main/cranelift/codegen/src/isa/s390x/inst/args.rs
1693 views
//! S390x ISA definitions: instruction arguments.12use crate::ir::MemFlags;3use crate::ir::condcodes::{FloatCC, IntCC};4use crate::isa::s390x::inst::*;56//=============================================================================7// Instruction sub-components (memory addresses): definitions89/// A memory argument to load/store, encapsulating the possible addressing modes.10#[derive(Clone, Debug)]11pub enum MemArg {12//13// Real IBM Z addressing modes:14//15/// Base register, index register, and 12-bit unsigned displacement.16BXD12 {17base: Reg,18index: Reg,19disp: UImm12,20flags: MemFlags,21},2223/// Base register, index register, and 20-bit signed displacement.24BXD20 {25base: Reg,26index: Reg,27disp: SImm20,28flags: MemFlags,29},3031/// PC-relative Reference to a label.32Label { target: MachLabel },3334/// PC-relative Reference to a constant pool entry.35Constant { constant: VCodeConstant },3637/// PC-relative Reference to a near symbol.38Symbol {39name: Box<ExternalName>,40offset: i32,41flags: MemFlags,42},4344//45// Virtual addressing modes that are lowered at emission time:46//47/// Arbitrary offset from a register. Converted to generation of large48/// offsets with multiple instructions as necessary during code emission.49RegOffset { reg: Reg, off: i64, flags: MemFlags },5051/// Offset from the stack pointer at function entry.52InitialSPOffset { off: i64 },5354/// Offset from the top of the incoming argument area.55IncomingArgOffset { off: i64 },5657/// Offset from the bottom of the outgoing argument area.58OutgoingArgOffset { off: i64 },5960/// Offset into the slot area of the stack, which lies just above the61/// outgoing argument area that's setup by the function prologue.62/// At emission time, this is converted to `SPOffset` with a fixup added to63/// the offset constant. The fixup is a running value that is tracked as64/// emission iterates through instructions in linear order, and can be65/// adjusted up and down with [Inst::VirtualSPOffsetAdj].66///67/// The standard ABI is in charge of handling this (by emitting the68/// adjustment meta-instructions). See the diagram in the documentation69/// for [crate::isa::aarch64::abi](the ABI module) for more details.70SlotOffset { off: i64 },7172/// Offset into the spill area of the stack.73SpillOffset { off: i64 },74}7576impl MemArg {77/// Memory reference using an address in a register.78pub fn reg(reg: Reg, flags: MemFlags) -> MemArg {79MemArg::BXD12 {80base: reg,81index: zero_reg(),82disp: UImm12::zero(),83flags,84}85}8687/// Memory reference using the sum of two registers as an address.88pub fn reg_plus_reg(reg1: Reg, reg2: Reg, flags: MemFlags) -> MemArg {89MemArg::BXD12 {90base: reg1,91index: reg2,92disp: UImm12::zero(),93flags,94}95}9697/// Memory reference using the sum of a register an offset as address.98pub fn reg_plus_off(reg: Reg, off: i64, flags: MemFlags) -> MemArg {99MemArg::RegOffset { reg, off, flags }100}101102pub(crate) fn get_flags(&self) -> MemFlags {103match self {104MemArg::BXD12 { flags, .. } => *flags,105MemArg::BXD20 { flags, .. } => *flags,106MemArg::RegOffset { flags, .. } => *flags,107MemArg::Label { .. } => MemFlags::trusted(),108MemArg::Constant { .. } => MemFlags::trusted(),109MemArg::Symbol { flags, .. } => *flags,110MemArg::InitialSPOffset { .. } => MemFlags::trusted(),111MemArg::IncomingArgOffset { .. } => MemFlags::trusted(),112MemArg::OutgoingArgOffset { .. } => MemFlags::trusted(),113MemArg::SlotOffset { .. } => MemFlags::trusted(),114MemArg::SpillOffset { .. } => MemFlags::trusted(),115}116}117}118119//=============================================================================120// Instruction sub-components (conditions, branches and branch targets):121// definitions122123/// Condition for conditional branches.124#[derive(Clone, Copy, Debug, PartialEq, Eq)]125pub struct Cond {126mask: u8,127}128129impl Cond {130pub fn from_mask(mask: u8) -> Cond {131assert!(mask >= 1 && mask <= 14);132Cond { mask }133}134135pub fn from_intcc(cc: IntCC) -> Cond {136let mask = match cc {137IntCC::Equal => 8,138IntCC::NotEqual => 4 | 2,139IntCC::SignedGreaterThanOrEqual => 8 | 2,140IntCC::SignedGreaterThan => 2,141IntCC::SignedLessThanOrEqual => 8 | 4,142IntCC::SignedLessThan => 4,143IntCC::UnsignedGreaterThanOrEqual => 8 | 2,144IntCC::UnsignedGreaterThan => 2,145IntCC::UnsignedLessThanOrEqual => 8 | 4,146IntCC::UnsignedLessThan => 4,147};148Cond { mask }149}150151pub fn from_floatcc(cc: FloatCC) -> Cond {152let mask = match cc {153FloatCC::Ordered => 8 | 4 | 2,154FloatCC::Unordered => 1,155FloatCC::Equal => 8,156FloatCC::NotEqual => 4 | 2 | 1,157FloatCC::OrderedNotEqual => 4 | 2,158FloatCC::UnorderedOrEqual => 8 | 1,159FloatCC::LessThan => 4,160FloatCC::LessThanOrEqual => 8 | 4,161FloatCC::GreaterThan => 2,162FloatCC::GreaterThanOrEqual => 8 | 2,163FloatCC::UnorderedOrLessThan => 4 | 1,164FloatCC::UnorderedOrLessThanOrEqual => 8 | 4 | 1,165FloatCC::UnorderedOrGreaterThan => 2 | 1,166FloatCC::UnorderedOrGreaterThanOrEqual => 8 | 2 | 1,167};168Cond { mask }169}170171/// Return the inverted condition.172pub fn invert(self) -> Cond {173Cond {174mask: !self.mask & 15,175}176}177178/// Return the machine encoding of this condition.179pub fn bits(self) -> u8 {180self.mask181}182}183184impl PrettyPrint for MemArg {185fn pretty_print(&self, _: u8) -> String {186match self {187&MemArg::BXD12 {188base, index, disp, ..189} => {190if base != zero_reg() {191if index != zero_reg() {192format!(193"{}({},{})",194disp.pretty_print_default(),195show_reg(index),196show_reg(base),197)198} else {199format!("{}({})", disp.pretty_print_default(), show_reg(base))200}201} else {202if index != zero_reg() {203format!("{}({},)", disp.pretty_print_default(), show_reg(index))204} else {205format!("{}", disp.pretty_print_default())206}207}208}209&MemArg::BXD20 {210base, index, disp, ..211} => {212if base != zero_reg() {213if index != zero_reg() {214format!(215"{}({},{})",216disp.pretty_print_default(),217show_reg(index),218show_reg(base),219)220} else {221format!("{}({})", disp.pretty_print_default(), show_reg(base))222}223} else {224if index != zero_reg() {225format!("{}({},)", disp.pretty_print_default(), show_reg(index))226} else {227format!("{}", disp.pretty_print_default())228}229}230}231&MemArg::Label { target } => target.to_string(),232&MemArg::Constant { constant } => format!("[const({})]", constant.as_u32()),233&MemArg::Symbol {234ref name, offset, ..235} => format!("{} + {}", name.display(None), offset),236// Eliminated by `mem_finalize()`.237&MemArg::InitialSPOffset { .. }238| &MemArg::IncomingArgOffset { .. }239| &MemArg::OutgoingArgOffset { .. }240| &MemArg::SlotOffset { .. }241| &MemArg::SpillOffset { .. }242| &MemArg::RegOffset { .. } => {243panic!("Unexpected pseudo mem-arg mode (stack-offset or generic reg-offset)!")244}245}246}247}248249impl PrettyPrint for Cond {250fn pretty_print(&self, _: u8) -> String {251let s = match self.mask {2521 => "o",2532 => "h",2543 => "nle",2554 => "l",2565 => "nhe",2576 => "lh",2587 => "ne",2598 => "e",2609 => "nlh",26110 => "he",26211 => "nl",26312 => "le",26413 => "nh",26514 => "no",266_ => unreachable!(),267};268s.to_string()269}270}271272273