Path: blob/main/cranelift/codegen/src/isa/s390x/inst/regs.rs
1693 views
//! S390x ISA definitions: registers.12use alloc::string::String;3use regalloc2::PReg;45use crate::isa::s390x::inst::{RegPair, WritableRegPair};6use crate::machinst::*;78//=============================================================================9// Registers, the Universe thereof, and printing1011/// Get a reference to a GPR (integer register).12pub const fn gpr(num: u8) -> Reg {13Reg::from_real_reg(gpr_preg(num))14}1516pub(crate) const fn gpr_preg(num: u8) -> PReg {17assert!(num < 16);18PReg::new(num as usize, RegClass::Int)19}2021/// Get a writable reference to a GPR.22pub fn writable_gpr(num: u8) -> Writable<Reg> {23Writable::from_reg(gpr(num))24}2526/// Get a reference to a VR (vector register).27pub const fn vr(num: u8) -> Reg {28Reg::from_real_reg(vr_preg(num))29}3031pub(crate) const fn vr_preg(num: u8) -> PReg {32assert!(num < 32);33PReg::new(num as usize, RegClass::Float)34}3536/// Get a writable reference to a VR.37pub fn writable_vr(num: u8) -> Writable<Reg> {38Writable::from_reg(vr(num))39}4041/// Test whether a vector register is overlapping an FPR.42pub fn is_fpr(r: Reg) -> bool {43let r = r.to_real_reg().unwrap();44assert!(r.class() == RegClass::Float);45return r.hw_enc() < 16;46}4748/// Get a reference to the stack-pointer register.49pub fn stack_reg() -> Reg {50gpr(15)51}5253/// Get a writable reference to the stack-pointer register.54pub fn writable_stack_reg() -> Writable<Reg> {55Writable::from_reg(stack_reg())56}5758/// Get a reference to the first temporary, sometimes "spill temporary", register. This register is59/// used to compute the address of a spill slot when a direct offset addressing mode from FP is not60/// sufficient (+/- 2^11 words). We exclude this register from regalloc and reserve it for this61/// purpose for simplicity; otherwise we need a multi-stage analysis where we first determine how62/// many spill slots we have, then perhaps remove the reg from the pool and recompute regalloc.63///64/// We use r1 for this because it's a scratch register but is slightly special (used for linker65/// veneers). We're free to use it as long as we don't expect it to live through call instructions.66pub fn spilltmp_reg() -> Reg {67gpr(1)68}6970/// Get a writable reference to the spilltmp reg.71pub fn writable_spilltmp_reg() -> Writable<Reg> {72Writable::from_reg(spilltmp_reg())73}7475pub fn zero_reg() -> Reg {76gpr(0)77}7879pub fn show_reg(reg: Reg) -> String {80if let Some(rreg) = reg.to_real_reg() {81match rreg.class() {82RegClass::Int => format!("%r{}", rreg.hw_enc()),83RegClass::Float => format!("%v{}", rreg.hw_enc()),84RegClass::Vector => unreachable!(),85}86} else {87format!("%{reg:?}")88}89}9091pub fn maybe_show_fpr(reg: Reg) -> Option<String> {92if let Some(rreg) = reg.to_real_reg() {93if is_fpr(reg) {94return Some(format!("%f{}", rreg.hw_enc()));95}96}97None98}99100pub fn pretty_print_reg(reg: Reg) -> String {101show_reg(reg)102}103104pub fn pretty_print_regpair(pair: RegPair) -> String {105let hi = pair.hi;106let lo = pair.lo;107if let Some(hi_reg) = hi.to_real_reg() {108if let Some(lo_reg) = lo.to_real_reg() {109assert!(110hi_reg.hw_enc() + 1 == lo_reg.hw_enc(),111"Invalid regpair: {} {}",112show_reg(hi),113show_reg(lo)114);115return show_reg(hi);116}117}118119format!("{}/{}", show_reg(hi), show_reg(lo))120}121122pub fn pretty_print_fp_regpair(pair: RegPair) -> String {123let hi = pair.hi;124let lo = pair.lo;125if let Some(hi_reg) = hi.to_real_reg() {126if let Some(lo_reg) = lo.to_real_reg() {127assert!(128hi_reg.hw_enc() + 2 == lo_reg.hw_enc(),129"Invalid regpair: {} {}",130show_reg(hi),131show_reg(lo)132);133return maybe_show_fpr(hi).unwrap();134}135}136137format!("{}/{}", show_reg(hi), show_reg(lo))138}139140pub fn pretty_print_reg_mod(rd: Writable<Reg>, ri: Reg) -> String {141let output = rd.to_reg();142let input = ri;143if output == input {144show_reg(output)145} else {146format!("{}<-{}", show_reg(output), show_reg(input))147}148}149150pub fn pretty_print_regpair_mod(rd: WritableRegPair, ri: RegPair) -> String {151let rd_hi = rd.hi.to_reg();152let rd_lo = rd.lo.to_reg();153let ri_hi = ri.hi;154let ri_lo = ri.lo;155if rd_hi == ri_hi {156show_reg(rd_hi)157} else {158format!(159"{}/{}<-{}/{}",160show_reg(rd_hi),161show_reg(rd_lo),162show_reg(ri_hi),163show_reg(ri_lo)164)165}166}167168pub fn pretty_print_regpair_mod_lo(rd: WritableRegPair, ri: Reg) -> String {169let rd_hi = rd.hi.to_reg();170let rd_lo = rd.lo.to_reg();171if rd_lo == ri {172show_reg(rd_hi)173} else {174format!(175"{}/{}<-_/{}",176show_reg(rd_hi),177show_reg(rd_lo),178show_reg(ri),179)180}181}182183pub fn pretty_print_fpr(reg: Reg) -> (String, Option<String>) {184(show_reg(reg), maybe_show_fpr(reg))185}186187188