Switch Cranelift over to regalloc2. (#3989)
This PR switches Cranelift over to the new register allocator, regalloc2. See [this document](https://gist.github.com/cfallin/08553421a91f150254fe878f67301801) for a summary of the design changes. This switchover has implications for core VCode/MachInst types and the lowering pass. Overall, this change brings improvements to both compile time and speed of generated code (runtime), as reported in #3942: ``` Benchmark Compilation (wallclock) Execution (wallclock) blake3-scalar 25% faster 28% faster blake3-simd no diff no diff meshoptimizer 19% faster 17% faster pulldown-cmark 17% faster no diff bz2 15% faster no diff SpiderMonkey, 21% faster 2% faster fib(30) clang.wasm 42% faster N/A ```
This commit is contained in:
@@ -66,11 +66,13 @@ use crate::isa;
|
||||
use crate::isa::s390x::inst::*;
|
||||
use crate::isa::unwind::UnwindInst;
|
||||
use crate::machinst::*;
|
||||
use crate::machinst::{RealReg, Reg, RegClass, Writable};
|
||||
use crate::settings;
|
||||
use crate::{CodegenError, CodegenResult};
|
||||
use alloc::boxed::Box;
|
||||
use alloc::vec::Vec;
|
||||
use regalloc::{RealReg, Reg, RegClass, Set, Writable};
|
||||
use regalloc2::PReg;
|
||||
use regalloc2::VReg;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
@@ -235,7 +237,7 @@ impl ABIMachineSpec for S390xMachineDeps {
|
||||
|
||||
if let Some(reg) = candidate {
|
||||
ret.push(ABIArg::reg(
|
||||
reg.to_real_reg(),
|
||||
reg.to_real_reg().unwrap(),
|
||||
param.value_type,
|
||||
param.extension,
|
||||
param.purpose,
|
||||
@@ -279,7 +281,7 @@ impl ABIMachineSpec for S390xMachineDeps {
|
||||
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(),
|
||||
reg.to_real_reg().unwrap(),
|
||||
types::I64,
|
||||
ir::ArgumentExtension::None,
|
||||
ir::ArgumentPurpose::Normal,
|
||||
@@ -340,8 +342,11 @@ impl ABIMachineSpec for S390xMachineDeps {
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_ret() -> Inst {
|
||||
Inst::Ret { link: gpr(14) }
|
||||
fn gen_ret(rets: Vec<Reg>) -> Inst {
|
||||
Inst::Ret {
|
||||
link: gpr(14),
|
||||
rets,
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_add_imm(into_reg: Writable<Reg>, from_reg: Reg, imm: u32) -> SmallInstVec<Inst> {
|
||||
@@ -462,7 +467,7 @@ impl ABIMachineSpec for S390xMachineDeps {
|
||||
_call_conv: isa::CallConv,
|
||||
_setup_frame: bool,
|
||||
flags: &settings::Flags,
|
||||
clobbered_callee_saves: &Vec<Writable<RealReg>>,
|
||||
clobbered_callee_saves: &[Writable<RealReg>],
|
||||
fixed_frame_storage_size: u32,
|
||||
outgoing_args_size: u32,
|
||||
) -> (u64, SmallVec<[Inst; 16]>) {
|
||||
@@ -471,16 +476,15 @@ impl ABIMachineSpec for S390xMachineDeps {
|
||||
let mut clobbered_gpr = vec![];
|
||||
|
||||
for ® in clobbered_callee_saves.iter() {
|
||||
match reg.to_reg().get_class() {
|
||||
RegClass::I64 => clobbered_gpr.push(reg),
|
||||
RegClass::F64 => clobbered_fpr.push(reg),
|
||||
class => panic!("Unexpected RegClass: {:?}", class),
|
||||
match reg.to_reg().class() {
|
||||
RegClass::Int => clobbered_gpr.push(reg),
|
||||
RegClass::Float => clobbered_fpr.push(reg),
|
||||
}
|
||||
}
|
||||
|
||||
let mut first_clobbered_gpr = 16;
|
||||
for reg in clobbered_gpr {
|
||||
let enc = reg.to_reg().get_hw_encoding();
|
||||
let enc = reg.to_reg().hw_enc();
|
||||
if enc < first_clobbered_gpr {
|
||||
first_clobbered_gpr = enc;
|
||||
}
|
||||
@@ -499,7 +503,7 @@ impl ABIMachineSpec for S390xMachineDeps {
|
||||
if first_clobbered_gpr < 16 {
|
||||
let offset = 8 * first_clobbered_gpr as i64;
|
||||
insts.push(Inst::StoreMultiple64 {
|
||||
rt: gpr(first_clobbered_gpr as u8),
|
||||
rt: gpr(first_clobbered_gpr),
|
||||
rt2: gpr(15),
|
||||
mem: MemArg::reg_plus_off(stack_reg(), offset, MemFlags::trusted()),
|
||||
});
|
||||
@@ -509,7 +513,7 @@ impl ABIMachineSpec for S390xMachineDeps {
|
||||
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(),
|
||||
reg: gpr(i).to_real_reg().unwrap(),
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -535,7 +539,7 @@ impl ABIMachineSpec for S390xMachineDeps {
|
||||
// Save FPRs.
|
||||
for (i, reg) in clobbered_fpr.iter().enumerate() {
|
||||
insts.push(Inst::FpuStore64 {
|
||||
rd: reg.to_reg().to_reg(),
|
||||
rd: reg.to_reg().into(),
|
||||
mem: MemArg::reg_plus_off(
|
||||
stack_reg(),
|
||||
(i * 8) as i64 + outgoing_args_size as i64 + fixed_frame_storage_size as i64,
|
||||
@@ -558,7 +562,7 @@ impl ABIMachineSpec for S390xMachineDeps {
|
||||
fn gen_clobber_restore(
|
||||
call_conv: isa::CallConv,
|
||||
_: &settings::Flags,
|
||||
clobbers: &Set<Writable<RealReg>>,
|
||||
clobbers: &[Writable<RealReg>],
|
||||
fixed_frame_storage_size: u32,
|
||||
outgoing_args_size: u32,
|
||||
) -> SmallVec<[Inst; 16]> {
|
||||
@@ -568,7 +572,7 @@ impl ABIMachineSpec for S390xMachineDeps {
|
||||
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();
|
||||
let enc = reg.to_reg().hw_enc();
|
||||
if enc < first_clobbered_gpr {
|
||||
first_clobbered_gpr = enc;
|
||||
}
|
||||
@@ -578,7 +582,7 @@ impl ABIMachineSpec for S390xMachineDeps {
|
||||
// Restore FPRs.
|
||||
for (i, reg) in clobbered_fpr.iter().enumerate() {
|
||||
insts.push(Inst::FpuLoad64 {
|
||||
rd: Writable::from_reg(reg.to_reg().to_reg()),
|
||||
rd: Writable::from_reg(reg.to_reg().into()),
|
||||
mem: MemArg::reg_plus_off(
|
||||
stack_reg(),
|
||||
(i * 8) as i64 + outgoing_args_size as i64 + fixed_frame_storage_size as i64,
|
||||
@@ -603,7 +607,7 @@ impl ABIMachineSpec for S390xMachineDeps {
|
||||
offset += stack_size as i64;
|
||||
}
|
||||
insts.push(Inst::LoadMultiple64 {
|
||||
rt: writable_gpr(first_clobbered_gpr as u8),
|
||||
rt: writable_gpr(first_clobbered_gpr),
|
||||
rt2: writable_gpr(15),
|
||||
mem: MemArg::reg_plus_off(stack_reg(), offset, MemFlags::trusted()),
|
||||
});
|
||||
@@ -620,55 +624,43 @@ impl ABIMachineSpec for S390xMachineDeps {
|
||||
tmp: Writable<Reg>,
|
||||
_callee_conv: isa::CallConv,
|
||||
_caller_conv: isa::CallConv,
|
||||
) -> SmallVec<[(InstIsSafepoint, Inst); 2]> {
|
||||
) -> SmallVec<[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::Near) => insts.push(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 {
|
||||
insts.push(Inst::LoadExtNameFar {
|
||||
rd: tmp,
|
||||
name: Box::new(name.clone()),
|
||||
offset: 0,
|
||||
});
|
||||
insts.push(Inst::CallInd {
|
||||
link: writable_gpr(14),
|
||||
info: Box::new(CallIndInfo {
|
||||
rn: *reg,
|
||||
rn: tmp.to_reg(),
|
||||
uses,
|
||||
defs,
|
||||
opcode,
|
||||
}),
|
||||
},
|
||||
)),
|
||||
});
|
||||
}
|
||||
&CallDest::Reg(reg) => insts.push(Inst::CallInd {
|
||||
link: writable_gpr(14),
|
||||
info: Box::new(CallIndInfo {
|
||||
rn: *reg,
|
||||
uses,
|
||||
defs,
|
||||
opcode,
|
||||
}),
|
||||
}),
|
||||
}
|
||||
|
||||
insts
|
||||
@@ -686,9 +678,8 @@ impl ABIMachineSpec for S390xMachineDeps {
|
||||
fn get_number_of_spillslots_for_value(rc: RegClass) -> u32 {
|
||||
// We allocate in terms of 8-byte slots.
|
||||
match rc {
|
||||
RegClass::I64 => 1,
|
||||
RegClass::F64 => 1,
|
||||
_ => panic!("Unexpected register class!"),
|
||||
RegClass::Int => 1,
|
||||
RegClass::Float => 1,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -706,13 +697,13 @@ impl ABIMachineSpec for S390xMachineDeps {
|
||||
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()) {
|
||||
if is_reg_clobbered_by_call(call_conv_of_callee, x.to_reg().to_real_reg().unwrap()) {
|
||||
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()) {
|
||||
if is_reg_clobbered_by_call(call_conv_of_callee, v.to_reg().to_real_reg().unwrap()) {
|
||||
caller_saved.push(v);
|
||||
}
|
||||
}
|
||||
@@ -728,7 +719,7 @@ impl ABIMachineSpec for S390xMachineDeps {
|
||||
|
||||
fn get_clobbered_callee_saves(
|
||||
call_conv: isa::CallConv,
|
||||
regs: &Set<Writable<RealReg>>,
|
||||
regs: &[Writable<RealReg>],
|
||||
) -> Vec<Writable<RealReg>> {
|
||||
let mut regs: Vec<Writable<RealReg>> = regs
|
||||
.iter()
|
||||
@@ -738,7 +729,7 @@ impl ABIMachineSpec for S390xMachineDeps {
|
||||
|
||||
// Sort registers for deterministic code output. We can do an unstable
|
||||
// sort because the registers will be unique (there are no dups).
|
||||
regs.sort_unstable_by_key(|r| r.to_reg().get_index());
|
||||
regs.sort_unstable_by_key(|r| PReg::from(r.to_reg()).index());
|
||||
regs
|
||||
}
|
||||
|
||||
@@ -754,50 +745,47 @@ impl ABIMachineSpec for S390xMachineDeps {
|
||||
}
|
||||
|
||||
fn is_reg_saved_in_prologue(_call_conv: isa::CallConv, r: RealReg) -> bool {
|
||||
match r.get_class() {
|
||||
RegClass::I64 => {
|
||||
match r.class() {
|
||||
RegClass::Int => {
|
||||
// r6 - r15 inclusive are callee-saves.
|
||||
r.get_hw_encoding() >= 6 && r.get_hw_encoding() <= 15
|
||||
r.hw_enc() >= 6 && r.hw_enc() <= 15
|
||||
}
|
||||
RegClass::F64 => {
|
||||
RegClass::Float => {
|
||||
// f8 - f15 inclusive are callee-saves.
|
||||
r.get_hw_encoding() >= 8 && r.get_hw_encoding() <= 15
|
||||
r.hw_enc() >= 8 && r.hw_enc() <= 15
|
||||
}
|
||||
_ => panic!("Unexpected RegClass"),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_regs_saved_in_prologue(
|
||||
call_conv: isa::CallConv,
|
||||
regs: &Set<Writable<RealReg>>,
|
||||
regs: &[Writable<RealReg>],
|
||||
) -> (Vec<Writable<RealReg>>, Vec<Writable<RealReg>>) {
|
||||
let mut int_saves = vec![];
|
||||
let mut fpr_saves = vec![];
|
||||
for ® in regs.iter() {
|
||||
for ® in regs {
|
||||
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"),
|
||||
match reg.to_reg().class() {
|
||||
RegClass::Int => int_saves.push(reg),
|
||||
RegClass::Float => fpr_saves.push(reg),
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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.sort_by_key(|r| VReg::from(r.to_reg()).vreg());
|
||||
fpr_saves.sort_by_key(|r| VReg::from(r.to_reg()).vreg());
|
||||
(int_saves, fpr_saves)
|
||||
}
|
||||
|
||||
fn is_reg_clobbered_by_call(_call_conv: isa::CallConv, r: RealReg) -> bool {
|
||||
match r.get_class() {
|
||||
RegClass::I64 => {
|
||||
match r.class() {
|
||||
RegClass::Int => {
|
||||
// r0 - r5 inclusive are caller-saves.
|
||||
r.get_hw_encoding() <= 5
|
||||
r.hw_enc() <= 5
|
||||
}
|
||||
RegClass::F64 => {
|
||||
RegClass::Float => {
|
||||
// f0 - f7 inclusive are caller-saves.
|
||||
r.get_hw_encoding() <= 7
|
||||
r.hw_enc() <= 7
|
||||
}
|
||||
_ => panic!("Unexpected RegClass"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -601,7 +601,8 @@
|
||||
|
||||
;; A machine return instruction.
|
||||
(Ret
|
||||
(link Reg))
|
||||
(link Reg)
|
||||
(rets VecReg))
|
||||
|
||||
;; A placeholder instruction, generating no code, meaning that a function epilogue must be
|
||||
;; inserted there.
|
||||
@@ -696,11 +697,10 @@
|
||||
(VirtualSPOffsetAdj
|
||||
(offset i64))
|
||||
|
||||
;; A definition of a value label.
|
||||
(ValueLabelMarker
|
||||
(reg Reg)
|
||||
(label ValueLabel))
|
||||
|
||||
;; Pseudoinstruction to keep a value alive.
|
||||
(DummyUse
|
||||
(reg Reg))
|
||||
|
||||
;; An unwind pseudoinstruction describing the state of the
|
||||
;; machine at this program point.
|
||||
(Unwind
|
||||
|
||||
@@ -7,8 +7,7 @@ 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 crate::machinst::{PrettyPrint, Reg};
|
||||
|
||||
use std::string::String;
|
||||
|
||||
@@ -113,6 +112,40 @@ impl MemArg {
|
||||
pub(crate) fn can_trap(&self) -> bool {
|
||||
!self.get_flags().notrap()
|
||||
}
|
||||
|
||||
/// Edit registers with allocations.
|
||||
pub fn with_allocs(&self, allocs: &mut AllocationConsumer<'_>) -> Self {
|
||||
match self {
|
||||
&MemArg::BXD12 {
|
||||
base,
|
||||
index,
|
||||
disp,
|
||||
flags,
|
||||
} => MemArg::BXD12 {
|
||||
base: allocs.next(base),
|
||||
index: allocs.next(index),
|
||||
disp,
|
||||
flags,
|
||||
},
|
||||
&MemArg::BXD20 {
|
||||
base,
|
||||
index,
|
||||
disp,
|
||||
flags,
|
||||
} => MemArg::BXD20 {
|
||||
base: allocs.next(base),
|
||||
index: allocs.next(index),
|
||||
disp,
|
||||
flags,
|
||||
},
|
||||
&MemArg::RegOffset { reg, off, flags } => MemArg::RegOffset {
|
||||
reg: allocs.next(reg),
|
||||
off,
|
||||
flags,
|
||||
},
|
||||
x => x.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
@@ -183,49 +216,53 @@ impl Cond {
|
||||
}
|
||||
|
||||
impl PrettyPrint for MemArg {
|
||||
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
fn pretty_print(&self, _: u8, allocs: &mut AllocationConsumer<'_>) -> String {
|
||||
match self {
|
||||
&MemArg::BXD12 {
|
||||
base, index, disp, ..
|
||||
} => {
|
||||
let base = allocs.next(base);
|
||||
let index = allocs.next(index);
|
||||
if base != zero_reg() {
|
||||
if index != zero_reg() {
|
||||
format!(
|
||||
"{}({},{})",
|
||||
disp.show_rru(mb_rru),
|
||||
index.show_rru(mb_rru),
|
||||
base.show_rru(mb_rru)
|
||||
disp.pretty_print_default(),
|
||||
show_reg(index),
|
||||
show_reg(base),
|
||||
)
|
||||
} else {
|
||||
format!("{}({})", disp.show_rru(mb_rru), base.show_rru(mb_rru))
|
||||
format!("{}({})", disp.pretty_print_default(), show_reg(base))
|
||||
}
|
||||
} else {
|
||||
if index != zero_reg() {
|
||||
format!("{}({},)", disp.show_rru(mb_rru), index.show_rru(mb_rru))
|
||||
format!("{}({},)", disp.pretty_print_default(), show_reg(index))
|
||||
} else {
|
||||
format!("{}", disp.show_rru(mb_rru))
|
||||
format!("{}", disp.pretty_print_default())
|
||||
}
|
||||
}
|
||||
}
|
||||
&MemArg::BXD20 {
|
||||
base, index, disp, ..
|
||||
} => {
|
||||
let base = allocs.next(base);
|
||||
let index = allocs.next(index);
|
||||
if base != zero_reg() {
|
||||
if index != zero_reg() {
|
||||
format!(
|
||||
"{}({},{})",
|
||||
disp.show_rru(mb_rru),
|
||||
index.show_rru(mb_rru),
|
||||
base.show_rru(mb_rru)
|
||||
disp.pretty_print_default(),
|
||||
show_reg(index),
|
||||
show_reg(base),
|
||||
)
|
||||
} else {
|
||||
format!("{}({})", disp.show_rru(mb_rru), base.show_rru(mb_rru))
|
||||
format!("{}({})", disp.pretty_print_default(), show_reg(base))
|
||||
}
|
||||
} else {
|
||||
if index != zero_reg() {
|
||||
format!("{}({},)", disp.show_rru(mb_rru), index.show_rru(mb_rru))
|
||||
format!("{}({},)", disp.pretty_print_default(), show_reg(index))
|
||||
} else {
|
||||
format!("{}", disp.show_rru(mb_rru))
|
||||
format!("{}", disp.pretty_print_default())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -244,7 +281,7 @@ impl PrettyPrint for MemArg {
|
||||
}
|
||||
|
||||
impl PrettyPrint for Cond {
|
||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
fn pretty_print(&self, _: u8, _: &mut AllocationConsumer<'_>) -> String {
|
||||
let s = match self.mask {
|
||||
1 => "o",
|
||||
2 => "h",
|
||||
|
||||
@@ -5,8 +5,10 @@ use crate::ir::MemFlags;
|
||||
use crate::ir::{SourceLoc, TrapCode};
|
||||
use crate::isa::s390x::inst::*;
|
||||
use crate::isa::s390x::settings as s390x_settings;
|
||||
use crate::machinst::reg::count_operands;
|
||||
use crate::machinst::{Reg, RegClass};
|
||||
use core::convert::TryFrom;
|
||||
use regalloc::{Reg, RegClass};
|
||||
use regalloc2::Allocation;
|
||||
|
||||
/// Memory addressing mode finalization: convert "special" modes (e.g.,
|
||||
/// generic arbitrary stack offset) into real addressing modes, possibly by
|
||||
@@ -125,7 +127,7 @@ pub fn mem_emit(
|
||||
true,
|
||||
);
|
||||
for inst in mem_insts.into_iter() {
|
||||
inst.emit(sink, emit_info, state);
|
||||
inst.emit(&[], sink, emit_info, state);
|
||||
}
|
||||
|
||||
if add_trap && mem.can_trap() {
|
||||
@@ -195,7 +197,7 @@ pub fn mem_rs_emit(
|
||||
false,
|
||||
);
|
||||
for inst in mem_insts.into_iter() {
|
||||
inst.emit(sink, emit_info, state);
|
||||
inst.emit(&[], sink, emit_info, state);
|
||||
}
|
||||
|
||||
if add_trap && mem.can_trap() {
|
||||
@@ -237,7 +239,7 @@ pub fn mem_imm8_emit(
|
||||
) {
|
||||
let (mem_insts, mem) = mem_finalize(mem, state, true, true, false, false);
|
||||
for inst in mem_insts.into_iter() {
|
||||
inst.emit(sink, emit_info, state);
|
||||
inst.emit(&[], sink, emit_info, state);
|
||||
}
|
||||
|
||||
if add_trap && mem.can_trap() {
|
||||
@@ -275,7 +277,7 @@ pub fn mem_imm16_emit(
|
||||
) {
|
||||
let (mem_insts, mem) = mem_finalize(mem, state, true, false, false, false);
|
||||
for inst in mem_insts.into_iter() {
|
||||
inst.emit(sink, emit_info, state);
|
||||
inst.emit(&[], sink, emit_info, state);
|
||||
}
|
||||
|
||||
if add_trap && mem.can_trap() {
|
||||
@@ -300,17 +302,17 @@ pub fn mem_imm16_emit(
|
||||
// Instructions and subcomponents: emission
|
||||
|
||||
fn machreg_to_gpr(m: Reg) -> u8 {
|
||||
assert_eq!(m.get_class(), RegClass::I64);
|
||||
u8::try_from(m.to_real_reg().get_hw_encoding()).unwrap()
|
||||
assert_eq!(m.class(), RegClass::Int);
|
||||
u8::try_from(m.to_real_reg().unwrap().hw_enc()).unwrap()
|
||||
}
|
||||
|
||||
fn machreg_to_fpr(m: Reg) -> u8 {
|
||||
assert_eq!(m.get_class(), RegClass::F64);
|
||||
u8::try_from(m.to_real_reg().get_hw_encoding()).unwrap()
|
||||
assert_eq!(m.class(), RegClass::Float);
|
||||
u8::try_from(m.to_real_reg().unwrap().hw_enc()).unwrap()
|
||||
}
|
||||
|
||||
fn machreg_to_gpr_or_fpr(m: Reg) -> u8 {
|
||||
u8::try_from(m.to_real_reg().get_hw_encoding()).unwrap()
|
||||
u8::try_from(m.to_real_reg().unwrap().hw_enc()).unwrap()
|
||||
}
|
||||
|
||||
/// E-type instructions.
|
||||
@@ -936,7 +938,15 @@ impl MachInstEmit for Inst {
|
||||
type State = EmitState;
|
||||
type Info = EmitInfo;
|
||||
|
||||
fn emit(&self, sink: &mut MachBuffer<Inst>, emit_info: &Self::Info, state: &mut EmitState) {
|
||||
fn emit(
|
||||
&self,
|
||||
allocs: &[Allocation],
|
||||
sink: &mut MachBuffer<Inst>,
|
||||
emit_info: &Self::Info,
|
||||
state: &mut EmitState,
|
||||
) {
|
||||
let mut allocs = AllocationConsumer::new(allocs);
|
||||
|
||||
// Verify that we can emit this Inst in the current ISA
|
||||
let matches_isa_flags = |iset_requirement: &InstructionSet| -> bool {
|
||||
match iset_requirement {
|
||||
@@ -965,6 +975,10 @@ impl MachInstEmit for Inst {
|
||||
|
||||
match self {
|
||||
&Inst::AluRRR { alu_op, rd, rn, rm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rn = allocs.next(rn);
|
||||
let rm = allocs.next(rm);
|
||||
|
||||
let (opcode, have_rr) = match alu_op {
|
||||
ALUOp::Add32 => (0xb9f8, true), // ARK
|
||||
ALUOp::Add64 => (0xb9e8, true), // AGRK
|
||||
@@ -992,7 +1006,7 @@ impl MachInstEmit for Inst {
|
||||
};
|
||||
if have_rr && rd.to_reg() == rn {
|
||||
let inst = Inst::AluRR { alu_op, rd, rm };
|
||||
inst.emit(sink, emit_info, state);
|
||||
inst.emit(&[], sink, emit_info, state);
|
||||
} else {
|
||||
put(sink, &enc_rrf_ab(opcode, rd.to_reg(), rn, rm, 0));
|
||||
}
|
||||
@@ -1003,9 +1017,12 @@ impl MachInstEmit for Inst {
|
||||
rn,
|
||||
imm,
|
||||
} => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
if rd.to_reg() == rn {
|
||||
let inst = Inst::AluRSImm16 { alu_op, rd, imm };
|
||||
inst.emit(sink, emit_info, state);
|
||||
inst.emit(&[], sink, emit_info, state);
|
||||
} else {
|
||||
let opcode = match alu_op {
|
||||
ALUOp::Add32 => 0xecd8, // AHIK
|
||||
@@ -1016,6 +1033,9 @@ impl MachInstEmit for Inst {
|
||||
}
|
||||
}
|
||||
&Inst::AluRR { alu_op, rd, rm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rm = allocs.next(rm);
|
||||
|
||||
let (opcode, is_rre) = match alu_op {
|
||||
ALUOp::Add32 => (0x1a, false), // AR
|
||||
ALUOp::Add64 => (0xb908, true), // AGR
|
||||
@@ -1051,6 +1071,9 @@ impl MachInstEmit for Inst {
|
||||
rd,
|
||||
ref mem,
|
||||
} => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let mem = mem.with_allocs(&mut allocs);
|
||||
|
||||
let (opcode_rx, opcode_rxy) = match alu_op {
|
||||
ALUOp::Add32 => (Some(0x5a), Some(0xe35a)), // A(Y)
|
||||
ALUOp::Add32Ext16 => (Some(0x4a), Some(0xe34a)), // AH(Y)
|
||||
@@ -1083,10 +1106,12 @@ impl MachInstEmit for Inst {
|
||||
};
|
||||
let rd = rd.to_reg();
|
||||
mem_emit(
|
||||
rd, mem, opcode_rx, opcode_rxy, None, true, sink, emit_info, state,
|
||||
rd, &mem, opcode_rx, opcode_rxy, None, true, sink, emit_info, state,
|
||||
);
|
||||
}
|
||||
&Inst::AluRSImm16 { alu_op, rd, imm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
|
||||
let opcode = match alu_op {
|
||||
ALUOp::Add32 => 0xa7a, // AHI
|
||||
ALUOp::Add64 => 0xa7b, // AGHI
|
||||
@@ -1097,6 +1122,8 @@ impl MachInstEmit for Inst {
|
||||
put(sink, &enc_ri_a(opcode, rd.to_reg(), imm as u16));
|
||||
}
|
||||
&Inst::AluRSImm32 { alu_op, rd, imm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
|
||||
let opcode = match alu_op {
|
||||
ALUOp::Add32 => 0xc29, // AFI
|
||||
ALUOp::Add64 => 0xc28, // AGFI
|
||||
@@ -1107,6 +1134,8 @@ impl MachInstEmit for Inst {
|
||||
put(sink, &enc_ril_a(opcode, rd.to_reg(), imm as u32));
|
||||
}
|
||||
&Inst::AluRUImm32 { alu_op, rd, imm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
|
||||
let opcode = match alu_op {
|
||||
ALUOp::AddLogical32 => 0xc2b, // ALFI
|
||||
ALUOp::AddLogical64 => 0xc2a, // ALGFI
|
||||
@@ -1117,6 +1146,8 @@ impl MachInstEmit for Inst {
|
||||
put(sink, &enc_ril_a(opcode, rd.to_reg(), imm));
|
||||
}
|
||||
&Inst::AluRUImm16Shifted { alu_op, rd, imm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
|
||||
let opcode = match (alu_op, imm.shift) {
|
||||
(ALUOp::And32, 0) => 0xa57, // NILL
|
||||
(ALUOp::And32, 1) => 0xa56, // NILH
|
||||
@@ -1135,6 +1166,8 @@ impl MachInstEmit for Inst {
|
||||
put(sink, &enc_ri_a(opcode, rd.to_reg(), imm.bits));
|
||||
}
|
||||
&Inst::AluRUImm32Shifted { alu_op, rd, imm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
|
||||
let opcode = match (alu_op, imm.shift) {
|
||||
(ALUOp::And32, 0) => 0xc0b, // NILF
|
||||
(ALUOp::And64, 0) => 0xc0b, // NILF
|
||||
@@ -1151,38 +1184,53 @@ impl MachInstEmit for Inst {
|
||||
}
|
||||
|
||||
&Inst::SMulWide { rn, rm } => {
|
||||
let rn = allocs.next(rn);
|
||||
let rm = allocs.next(rm);
|
||||
|
||||
let opcode = 0xb9ec; // MGRK
|
||||
put(sink, &enc_rrf_ab(opcode, gpr(0), rn, rm, 0));
|
||||
}
|
||||
&Inst::UMulWide { rn } => {
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = 0xb986; // MLGR
|
||||
put(sink, &enc_rre(opcode, gpr(0), rn));
|
||||
}
|
||||
&Inst::SDivMod32 { rn } => {
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = 0xb91d; // DSGFR
|
||||
let srcloc = state.cur_srcloc();
|
||||
let trap_code = TrapCode::IntegerDivisionByZero;
|
||||
put_with_trap(sink, &enc_rre(opcode, gpr(0), rn), srcloc, trap_code);
|
||||
}
|
||||
&Inst::SDivMod64 { rn } => {
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = 0xb90d; // DSGR
|
||||
let srcloc = state.cur_srcloc();
|
||||
let trap_code = TrapCode::IntegerDivisionByZero;
|
||||
put_with_trap(sink, &enc_rre(opcode, gpr(0), rn), srcloc, trap_code);
|
||||
}
|
||||
&Inst::UDivMod32 { rn } => {
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = 0xb997; // DLR
|
||||
let srcloc = state.cur_srcloc();
|
||||
let trap_code = TrapCode::IntegerDivisionByZero;
|
||||
put_with_trap(sink, &enc_rre(opcode, gpr(0), rn), srcloc, trap_code);
|
||||
}
|
||||
&Inst::UDivMod64 { rn } => {
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = 0xb987; // DLGR
|
||||
let srcloc = state.cur_srcloc();
|
||||
let trap_code = TrapCode::IntegerDivisionByZero;
|
||||
put_with_trap(sink, &enc_rre(opcode, gpr(0), rn), srcloc, trap_code);
|
||||
}
|
||||
&Inst::Flogr { rn } => {
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = 0xb983; // FLOGR
|
||||
put(sink, &enc_rre(opcode, gpr(0), rn));
|
||||
}
|
||||
@@ -1194,6 +1242,10 @@ impl MachInstEmit for Inst {
|
||||
shift_imm,
|
||||
shift_reg,
|
||||
} => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rn = allocs.next(rn);
|
||||
let shift_reg = allocs.next(shift_reg);
|
||||
|
||||
let opcode = match shift_op {
|
||||
ShiftOp::RotL32 => 0xeb1d, // RLL
|
||||
ShiftOp::RotL64 => 0xeb1c, // RLLG
|
||||
@@ -1218,6 +1270,9 @@ impl MachInstEmit for Inst {
|
||||
end_bit,
|
||||
rotate_amt,
|
||||
} => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = match op {
|
||||
RxSBGOp::Insert => 0xec59, // RISBGN
|
||||
RxSBGOp::And => 0xec54, // RNSBG
|
||||
@@ -1245,6 +1300,9 @@ impl MachInstEmit for Inst {
|
||||
end_bit,
|
||||
rotate_amt,
|
||||
} => {
|
||||
let rd = allocs.next(rd);
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = match op {
|
||||
RxSBGOp::And => 0xec54, // RNSBG
|
||||
RxSBGOp::Or => 0xec56, // ROSBG
|
||||
@@ -1265,6 +1323,9 @@ impl MachInstEmit for Inst {
|
||||
}
|
||||
|
||||
&Inst::UnaryRR { op, rd, rn } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
match op {
|
||||
UnaryOp::Abs32 => {
|
||||
let opcode = 0x10; // LPR
|
||||
@@ -1316,6 +1377,9 @@ impl MachInstEmit for Inst {
|
||||
from_bits,
|
||||
to_bits,
|
||||
} => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = match (signed, from_bits, to_bits) {
|
||||
(_, 1, 32) => 0xb926, // LBR
|
||||
(_, 1, 64) => 0xb906, // LGBR
|
||||
@@ -1338,6 +1402,9 @@ impl MachInstEmit for Inst {
|
||||
}
|
||||
|
||||
&Inst::CmpRR { op, rn, rm } => {
|
||||
let rn = allocs.next(rn);
|
||||
let rm = allocs.next(rm);
|
||||
|
||||
let (opcode, is_rre) = match op {
|
||||
CmpOp::CmpS32 => (0x19, false), // CR
|
||||
CmpOp::CmpS64 => (0xb920, true), // CGR
|
||||
@@ -1354,6 +1421,9 @@ impl MachInstEmit for Inst {
|
||||
}
|
||||
}
|
||||
&Inst::CmpRX { op, rn, ref mem } => {
|
||||
let rn = allocs.next(rn);
|
||||
let mem = mem.with_allocs(&mut allocs);
|
||||
|
||||
let (opcode_rx, opcode_rxy, opcode_ril) = match op {
|
||||
CmpOp::CmpS32 => (Some(0x59), Some(0xe359), Some(0xc6d)), // C(Y), CRL
|
||||
CmpOp::CmpS32Ext16 => (Some(0x49), Some(0xe379), Some(0xc65)), // CH(Y), CHRL
|
||||
@@ -1367,10 +1437,12 @@ impl MachInstEmit for Inst {
|
||||
CmpOp::CmpL64Ext32 => (None, Some(0xe331), Some(0xc6e)), // CLGF, CLGFRL
|
||||
};
|
||||
mem_emit(
|
||||
rn, mem, opcode_rx, opcode_rxy, opcode_ril, true, sink, emit_info, state,
|
||||
rn, &mem, opcode_rx, opcode_rxy, opcode_ril, true, sink, emit_info, state,
|
||||
);
|
||||
}
|
||||
&Inst::CmpRSImm16 { op, rn, imm } => {
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = match op {
|
||||
CmpOp::CmpS32 => 0xa7e, // CHI
|
||||
CmpOp::CmpS64 => 0xa7f, // CGHI
|
||||
@@ -1379,6 +1451,8 @@ impl MachInstEmit for Inst {
|
||||
put(sink, &enc_ri_a(opcode, rn, imm as u16));
|
||||
}
|
||||
&Inst::CmpRSImm32 { op, rn, imm } => {
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = match op {
|
||||
CmpOp::CmpS32 => 0xc2d, // CFI
|
||||
CmpOp::CmpS64 => 0xc2c, // CGFI
|
||||
@@ -1387,6 +1461,8 @@ impl MachInstEmit for Inst {
|
||||
put(sink, &enc_ril_a(opcode, rn, imm as u32));
|
||||
}
|
||||
&Inst::CmpRUImm32 { op, rn, imm } => {
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = match op {
|
||||
CmpOp::CmpL32 => 0xc2f, // CLFI
|
||||
CmpOp::CmpL64 => 0xc2e, // CLGFI
|
||||
@@ -1401,6 +1477,9 @@ impl MachInstEmit for Inst {
|
||||
cond,
|
||||
trap_code,
|
||||
} => {
|
||||
let rn = allocs.next(rn);
|
||||
let rm = allocs.next(rm);
|
||||
|
||||
let opcode = match op {
|
||||
CmpOp::CmpS32 => 0xb972, // CRT
|
||||
CmpOp::CmpS64 => 0xb960, // CGRT
|
||||
@@ -1423,6 +1502,8 @@ impl MachInstEmit for Inst {
|
||||
cond,
|
||||
trap_code,
|
||||
} => {
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = match op {
|
||||
CmpOp::CmpS32 => 0xec72, // CIT
|
||||
CmpOp::CmpS64 => 0xec70, // CGIT
|
||||
@@ -1443,6 +1524,8 @@ impl MachInstEmit for Inst {
|
||||
cond,
|
||||
trap_code,
|
||||
} => {
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = match op {
|
||||
CmpOp::CmpL32 => 0xec73, // CLFIT
|
||||
CmpOp::CmpL64 => 0xec71, // CLGIT
|
||||
@@ -1463,6 +1546,10 @@ impl MachInstEmit for Inst {
|
||||
rn,
|
||||
ref mem,
|
||||
} => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rn = allocs.next(rn);
|
||||
let mem = mem.with_allocs(&mut allocs);
|
||||
|
||||
let opcode = match alu_op {
|
||||
ALUOp::Add32 => 0xebf8, // LAA
|
||||
ALUOp::Add64 => 0xebe8, // LAAG
|
||||
@@ -1481,7 +1568,7 @@ impl MachInstEmit for Inst {
|
||||
mem_rs_emit(
|
||||
rd,
|
||||
rn,
|
||||
mem,
|
||||
&mem,
|
||||
None,
|
||||
Some(opcode),
|
||||
true,
|
||||
@@ -1500,6 +1587,8 @@ impl MachInstEmit for Inst {
|
||||
sink.bind_label(loop_label);
|
||||
|
||||
for inst in (&body).into_iter() {
|
||||
let op_count = count_operands(inst);
|
||||
let sub_allocs = allocs.next_n(op_count);
|
||||
match &inst {
|
||||
// Replace a CondBreak with a branch to done_label.
|
||||
&Inst::CondBreak { cond } => {
|
||||
@@ -1507,9 +1596,9 @@ impl MachInstEmit for Inst {
|
||||
target: done_label,
|
||||
cond: *cond,
|
||||
};
|
||||
inst.emit(sink, emit_info, state);
|
||||
inst.emit(&sub_allocs[..], sink, emit_info, state);
|
||||
}
|
||||
_ => inst.emit(sink, emit_info, state),
|
||||
_ => inst.emit(&sub_allocs[..], sink, emit_info, state),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1517,13 +1606,17 @@ impl MachInstEmit for Inst {
|
||||
target: loop_label,
|
||||
cond,
|
||||
};
|
||||
inst.emit(sink, emit_info, state);
|
||||
inst.emit(&[], sink, emit_info, state);
|
||||
|
||||
// Emit label at the end of the loop.
|
||||
sink.bind_label(done_label);
|
||||
}
|
||||
&Inst::CondBreak { .. } => unreachable!(), // Only valid inside a Loop.
|
||||
&Inst::AtomicCas32 { rd, rn, ref mem } | &Inst::AtomicCas64 { rd, rn, ref mem } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rn = allocs.next(rn);
|
||||
let mem = mem.with_allocs(&mut allocs);
|
||||
|
||||
let (opcode_rs, opcode_rsy) = match self {
|
||||
&Inst::AtomicCas32 { .. } => (Some(0xba), Some(0xeb14)), // CS(Y)
|
||||
&Inst::AtomicCas64 { .. } => (None, Some(0xeb30)), // CSG
|
||||
@@ -1532,7 +1625,7 @@ impl MachInstEmit for Inst {
|
||||
|
||||
let rd = rd.to_reg();
|
||||
mem_rs_emit(
|
||||
rd, rn, mem, opcode_rs, opcode_rsy, true, sink, emit_info, state,
|
||||
rd, rn, &mem, opcode_rs, opcode_rsy, true, sink, emit_info, state,
|
||||
);
|
||||
}
|
||||
&Inst::Fence => {
|
||||
@@ -1556,6 +1649,9 @@ impl MachInstEmit for Inst {
|
||||
| &Inst::LoadRev64 { rd, ref mem }
|
||||
| &Inst::FpuLoad32 { rd, ref mem }
|
||||
| &Inst::FpuLoad64 { rd, ref mem } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let mem = mem.with_allocs(&mut allocs);
|
||||
|
||||
let (opcode_rx, opcode_rxy, opcode_ril) = match self {
|
||||
&Inst::Load32 { .. } => (Some(0x58), Some(0xe358), Some(0xc4d)), // L(Y), LRL
|
||||
&Inst::Load32ZExt8 { .. } => (None, Some(0xe394), None), // LLC
|
||||
@@ -1578,19 +1674,22 @@ impl MachInstEmit for Inst {
|
||||
};
|
||||
let rd = rd.to_reg();
|
||||
mem_emit(
|
||||
rd, mem, opcode_rx, opcode_rxy, opcode_ril, true, sink, emit_info, state,
|
||||
rd, &mem, opcode_rx, opcode_rxy, opcode_ril, true, sink, emit_info, state,
|
||||
);
|
||||
}
|
||||
&Inst::FpuLoadRev32 { rd, ref mem } | &Inst::FpuLoadRev64 { rd, ref mem } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let mem = mem.with_allocs(&mut allocs);
|
||||
|
||||
let opcode = match self {
|
||||
&Inst::FpuLoadRev32 { .. } => 0xe603, // VLEBRF
|
||||
&Inst::FpuLoadRev64 { .. } => 0xe602, // VLEBRG
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let (mem_insts, mem) = mem_finalize(mem, state, true, false, false, true);
|
||||
let (mem_insts, mem) = mem_finalize(&mem, state, true, false, false, true);
|
||||
for inst in mem_insts.into_iter() {
|
||||
inst.emit(sink, emit_info, state);
|
||||
inst.emit(&[], sink, emit_info, state);
|
||||
}
|
||||
|
||||
let srcloc = state.cur_srcloc();
|
||||
@@ -1620,6 +1719,9 @@ impl MachInstEmit for Inst {
|
||||
| &Inst::StoreRev64 { rd, ref mem }
|
||||
| &Inst::FpuStore32 { rd, ref mem }
|
||||
| &Inst::FpuStore64 { rd, ref mem } => {
|
||||
let rd = allocs.next(rd);
|
||||
let mem = mem.with_allocs(&mut allocs);
|
||||
|
||||
let (opcode_rx, opcode_rxy, opcode_ril) = match self {
|
||||
&Inst::Store8 { .. } => (Some(0x42), Some(0xe372), None), // STC(Y)
|
||||
&Inst::Store16 { .. } => (Some(0x40), Some(0xe370), Some(0xc47)), // STH(Y), STHRL
|
||||
@@ -1633,37 +1735,44 @@ impl MachInstEmit for Inst {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
mem_emit(
|
||||
rd, mem, opcode_rx, opcode_rxy, opcode_ril, true, sink, emit_info, state,
|
||||
rd, &mem, opcode_rx, opcode_rxy, opcode_ril, true, sink, emit_info, state,
|
||||
);
|
||||
}
|
||||
&Inst::StoreImm8 { imm, ref mem } => {
|
||||
let mem = mem.with_allocs(&mut allocs);
|
||||
|
||||
let opcode_si = 0x92; // MVI
|
||||
let opcode_siy = 0xeb52; // MVIY
|
||||
mem_imm8_emit(
|
||||
imm, mem, opcode_si, opcode_siy, true, sink, emit_info, state,
|
||||
imm, &mem, opcode_si, opcode_siy, true, sink, emit_info, state,
|
||||
);
|
||||
}
|
||||
&Inst::StoreImm16 { imm, ref mem }
|
||||
| &Inst::StoreImm32SExt16 { imm, ref mem }
|
||||
| &Inst::StoreImm64SExt16 { imm, ref mem } => {
|
||||
let mem = mem.with_allocs(&mut allocs);
|
||||
|
||||
let opcode = match self {
|
||||
&Inst::StoreImm16 { .. } => 0xe544, // MVHHI
|
||||
&Inst::StoreImm32SExt16 { .. } => 0xe54c, // MVHI
|
||||
&Inst::StoreImm64SExt16 { .. } => 0xe548, // MVGHI
|
||||
_ => unreachable!(),
|
||||
};
|
||||
mem_imm16_emit(imm, mem, opcode, true, sink, emit_info, state);
|
||||
mem_imm16_emit(imm, &mem, opcode, true, sink, emit_info, state);
|
||||
}
|
||||
&Inst::FpuStoreRev32 { rd, ref mem } | &Inst::FpuStoreRev64 { rd, ref mem } => {
|
||||
let rd = allocs.next(rd);
|
||||
let mem = mem.with_allocs(&mut allocs);
|
||||
|
||||
let opcode = match self {
|
||||
&Inst::FpuStoreRev32 { .. } => 0xe60b, // VSTEBRF
|
||||
&Inst::FpuStoreRev64 { .. } => 0xe60a, // VSTEBRG
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let (mem_insts, mem) = mem_finalize(mem, state, true, false, false, true);
|
||||
let (mem_insts, mem) = mem_finalize(&mem, state, true, false, false, true);
|
||||
for inst in mem_insts.into_iter() {
|
||||
inst.emit(sink, emit_info, state);
|
||||
inst.emit(&[], sink, emit_info, state);
|
||||
}
|
||||
|
||||
let srcloc = state.cur_srcloc();
|
||||
@@ -1682,6 +1791,8 @@ impl MachInstEmit for Inst {
|
||||
}
|
||||
|
||||
&Inst::LoadMultiple64 { rt, rt2, ref mem } => {
|
||||
let mem = mem.with_allocs(&mut allocs);
|
||||
|
||||
let opcode = 0xeb04; // LMG
|
||||
let rt = rt.to_reg();
|
||||
let rt2 = rt2.to_reg();
|
||||
@@ -1698,6 +1809,8 @@ impl MachInstEmit for Inst {
|
||||
);
|
||||
}
|
||||
&Inst::StoreMultiple64 { rt, rt2, ref mem } => {
|
||||
let mem = mem.with_allocs(&mut allocs);
|
||||
|
||||
let opcode = 0xeb24; // STMG
|
||||
mem_rs_emit(
|
||||
rt,
|
||||
@@ -1713,48 +1826,73 @@ impl MachInstEmit for Inst {
|
||||
}
|
||||
|
||||
&Inst::LoadAddr { rd, ref mem } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let mem = mem.with_allocs(&mut allocs);
|
||||
|
||||
let opcode_rx = Some(0x41); // LA
|
||||
let opcode_rxy = Some(0xe371); // LAY
|
||||
let opcode_ril = Some(0xc00); // LARL
|
||||
let rd = rd.to_reg();
|
||||
mem_emit(
|
||||
rd, mem, opcode_rx, opcode_rxy, opcode_ril, false, sink, emit_info, state,
|
||||
rd, &mem, opcode_rx, opcode_rxy, opcode_ril, false, sink, emit_info, state,
|
||||
);
|
||||
}
|
||||
|
||||
&Inst::Mov64 { rd, rm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rm = allocs.next(rm);
|
||||
|
||||
let opcode = 0xb904; // LGR
|
||||
put(sink, &enc_rre(opcode, rd.to_reg(), rm));
|
||||
}
|
||||
&Inst::Mov32 { rd, rm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rm = allocs.next(rm);
|
||||
|
||||
let opcode = 0x18; // LR
|
||||
put(sink, &enc_rr(opcode, rd.to_reg(), rm));
|
||||
}
|
||||
&Inst::Mov32Imm { rd, imm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
|
||||
let opcode = 0xc09; // IILF
|
||||
put(sink, &enc_ril_a(opcode, rd.to_reg(), imm));
|
||||
}
|
||||
&Inst::Mov32SImm16 { rd, imm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
|
||||
let opcode = 0xa78; // LHI
|
||||
put(sink, &enc_ri_a(opcode, rd.to_reg(), imm as u16));
|
||||
}
|
||||
&Inst::Mov64SImm16 { rd, imm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
|
||||
let opcode = 0xa79; // LGHI
|
||||
put(sink, &enc_ri_a(opcode, rd.to_reg(), imm as u16));
|
||||
}
|
||||
&Inst::Mov64SImm32 { rd, imm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
|
||||
let opcode = 0xc01; // LGFI
|
||||
put(sink, &enc_ril_a(opcode, rd.to_reg(), imm as u32));
|
||||
}
|
||||
&Inst::CMov32 { rd, cond, rm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rm = allocs.next(rm);
|
||||
|
||||
let opcode = 0xb9f2; // LOCR
|
||||
put(sink, &enc_rrf_cde(opcode, rd.to_reg(), rm, cond.bits(), 0));
|
||||
}
|
||||
&Inst::CMov64 { rd, cond, rm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rm = allocs.next(rm);
|
||||
|
||||
let opcode = 0xb9e2; // LOCGR
|
||||
put(sink, &enc_rrf_cde(opcode, rd.to_reg(), rm, cond.bits(), 0));
|
||||
}
|
||||
&Inst::CMov32SImm16 { rd, cond, imm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
|
||||
let opcode = 0xec42; // LOCHI
|
||||
put(
|
||||
sink,
|
||||
@@ -1762,6 +1900,8 @@ impl MachInstEmit for Inst {
|
||||
);
|
||||
}
|
||||
&Inst::CMov64SImm16 { rd, cond, imm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
|
||||
let opcode = 0xec46; // LOCGHI
|
||||
put(
|
||||
sink,
|
||||
@@ -1769,6 +1909,8 @@ impl MachInstEmit for Inst {
|
||||
);
|
||||
}
|
||||
&Inst::Mov64UImm16Shifted { rd, imm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
|
||||
let opcode = match imm.shift {
|
||||
0 => 0xa5f, // LLILL
|
||||
1 => 0xa5e, // LLILH
|
||||
@@ -1779,6 +1921,8 @@ impl MachInstEmit for Inst {
|
||||
put(sink, &enc_ri_a(opcode, rd.to_reg(), imm.bits));
|
||||
}
|
||||
&Inst::Mov64UImm32Shifted { rd, imm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
|
||||
let opcode = match imm.shift {
|
||||
0 => 0xc0f, // LLILF
|
||||
1 => 0xc0e, // LLIHF
|
||||
@@ -1787,6 +1931,8 @@ impl MachInstEmit for Inst {
|
||||
put(sink, &enc_ril_a(opcode, rd.to_reg(), imm.bits));
|
||||
}
|
||||
&Inst::Insert64UImm16Shifted { rd, imm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
|
||||
let opcode = match imm.shift {
|
||||
0 => 0xa53, // IILL
|
||||
1 => 0xa52, // IILH
|
||||
@@ -1797,6 +1943,8 @@ impl MachInstEmit for Inst {
|
||||
put(sink, &enc_ri_a(opcode, rd.to_reg(), imm.bits));
|
||||
}
|
||||
&Inst::Insert64UImm32Shifted { rd, imm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
|
||||
let opcode = match imm.shift {
|
||||
0 => 0xc09, // IILF
|
||||
1 => 0xc08, // IIHF
|
||||
@@ -1809,6 +1957,8 @@ impl MachInstEmit for Inst {
|
||||
ref name,
|
||||
offset,
|
||||
} => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
|
||||
let opcode = 0xa75; // BRAS
|
||||
let srcloc = state.cur_srcloc();
|
||||
let reg = writable_spilltmp_reg().to_reg();
|
||||
@@ -1823,38 +1973,58 @@ impl MachInstEmit for Inst {
|
||||
rd,
|
||||
mem: MemArg::reg(reg, MemFlags::trusted()),
|
||||
};
|
||||
inst.emit(sink, emit_info, state);
|
||||
inst.emit(&[], sink, emit_info, state);
|
||||
}
|
||||
|
||||
&Inst::FpuMove32 { rd, rn } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = 0x38; // LER
|
||||
put(sink, &enc_rr(opcode, rd.to_reg(), rn));
|
||||
}
|
||||
&Inst::FpuMove64 { rd, rn } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = 0x28; // LDR
|
||||
put(sink, &enc_rr(opcode, rd.to_reg(), rn));
|
||||
}
|
||||
&Inst::FpuCMov32 { rd, cond, rm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rm = allocs.next(rm);
|
||||
|
||||
let opcode = 0xa74; // BCR
|
||||
put(sink, &enc_ri_c(opcode, cond.invert().bits(), 4 + 2));
|
||||
let opcode = 0x38; // LER
|
||||
put(sink, &enc_rr(opcode, rd.to_reg(), rm));
|
||||
}
|
||||
&Inst::FpuCMov64 { rd, cond, rm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rm = allocs.next(rm);
|
||||
|
||||
let opcode = 0xa74; // BCR
|
||||
put(sink, &enc_ri_c(opcode, cond.invert().bits(), 4 + 2));
|
||||
let opcode = 0x28; // LDR
|
||||
put(sink, &enc_rr(opcode, rd.to_reg(), rm));
|
||||
}
|
||||
&Inst::MovToFpr { rd, rn } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = 0xb3c1; // LDGR
|
||||
put(sink, &enc_rre(opcode, rd.to_reg(), rn));
|
||||
}
|
||||
&Inst::MovFromFpr { rd, rn } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = 0xb3cd; // LGDR
|
||||
put(sink, &enc_rre(opcode, rd.to_reg(), rn));
|
||||
}
|
||||
&Inst::LoadFpuConst32 { rd, const_data } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
|
||||
let opcode = 0xa75; // BRAS
|
||||
let reg = writable_spilltmp_reg().to_reg();
|
||||
put(sink, &enc_ri_b(opcode, reg, 8));
|
||||
@@ -1863,9 +2033,11 @@ impl MachInstEmit for Inst {
|
||||
rd,
|
||||
mem: MemArg::reg(reg, MemFlags::trusted()),
|
||||
};
|
||||
inst.emit(sink, emit_info, state);
|
||||
inst.emit(&[], sink, emit_info, state);
|
||||
}
|
||||
&Inst::LoadFpuConst64 { rd, const_data } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
|
||||
let opcode = 0xa75; // BRAS
|
||||
let reg = writable_spilltmp_reg().to_reg();
|
||||
put(sink, &enc_ri_b(opcode, reg, 12));
|
||||
@@ -1874,14 +2046,21 @@ impl MachInstEmit for Inst {
|
||||
rd,
|
||||
mem: MemArg::reg(reg, MemFlags::trusted()),
|
||||
};
|
||||
inst.emit(sink, emit_info, state);
|
||||
inst.emit(&[], sink, emit_info, state);
|
||||
}
|
||||
|
||||
&Inst::FpuCopysign { rd, rn, rm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rn = allocs.next(rn);
|
||||
let rm = allocs.next(rm);
|
||||
|
||||
let opcode = 0xb372; // CPSDR
|
||||
put(sink, &enc_rrf_ab(opcode, rd.to_reg(), rn, rm, 0));
|
||||
}
|
||||
&Inst::FpuRR { fpu_op, rd, rn } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = match fpu_op {
|
||||
FPUOp1::Abs32 => 0xb300, // LPEBR
|
||||
FPUOp1::Abs64 => 0xb310, // LPDBR
|
||||
@@ -1897,6 +2076,9 @@ impl MachInstEmit for Inst {
|
||||
put(sink, &enc_rre(opcode, rd.to_reg(), rn));
|
||||
}
|
||||
&Inst::FpuRRR { fpu_op, rd, rm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rm = allocs.next(rm);
|
||||
|
||||
let opcode = match fpu_op {
|
||||
FPUOp2::Add32 => 0xb30a, // AEBR
|
||||
FPUOp2::Add64 => 0xb31a, // ADBR
|
||||
@@ -1911,6 +2093,10 @@ impl MachInstEmit for Inst {
|
||||
put(sink, &enc_rre(opcode, rd.to_reg(), rm));
|
||||
}
|
||||
&Inst::FpuRRRR { fpu_op, rd, rn, rm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rn = allocs.next(rn);
|
||||
let rm = allocs.next(rm);
|
||||
|
||||
let opcode = match fpu_op {
|
||||
FPUOp3::MAdd32 => 0xb30e, // MAEBR
|
||||
FPUOp3::MAdd64 => 0xb31e, // MADBR
|
||||
@@ -1920,6 +2106,9 @@ impl MachInstEmit for Inst {
|
||||
put(sink, &enc_rrd(opcode, rd.to_reg(), rm, rn));
|
||||
}
|
||||
&Inst::FpuToInt { op, rd, rn } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = match op {
|
||||
FpuToIntOp::F32ToI32 => 0xb398, // CFEBRA
|
||||
FpuToIntOp::F32ToU32 => 0xb39c, // CLFEBR
|
||||
@@ -1933,6 +2122,9 @@ impl MachInstEmit for Inst {
|
||||
put(sink, &enc_rrf_cde(opcode, rd.to_reg(), rn, 5, 0));
|
||||
}
|
||||
&Inst::IntToFpu { op, rd, rn } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = match op {
|
||||
IntToFpuOp::I32ToF32 => 0xb394, // CEFBRA
|
||||
IntToFpuOp::U32ToF32 => 0xb390, // CELFBR
|
||||
@@ -1946,6 +2138,9 @@ impl MachInstEmit for Inst {
|
||||
put(sink, &enc_rrf_cde(opcode, rd.to_reg(), rn, 0, 0));
|
||||
}
|
||||
&Inst::FpuRound { op, rd, rn } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let (opcode, m3) = match op {
|
||||
FpuRoundMode::Minus32 => (0xb357, 7), // FIEBR
|
||||
FpuRoundMode::Minus64 => (0xb35f, 7), // FIDBR
|
||||
@@ -1959,6 +2154,10 @@ impl MachInstEmit for Inst {
|
||||
put(sink, &enc_rrf_cde(opcode, rd.to_reg(), rn, m3, 0));
|
||||
}
|
||||
&Inst::FpuVecRRR { fpu_op, rd, rn, rm } => {
|
||||
let rd = allocs.next_writable(rd);
|
||||
let rn = allocs.next(rn);
|
||||
let rm = allocs.next(rm);
|
||||
|
||||
let (opcode, m4) = match fpu_op {
|
||||
FPUOp2::Max32 => (0xe7ef, 2), // VFMAX
|
||||
FPUOp2::Max64 => (0xe7ef, 3), // VFMAX
|
||||
@@ -1969,15 +2168,23 @@ impl MachInstEmit for Inst {
|
||||
put(sink, &enc_vrr(opcode, rd.to_reg(), rn, rm, m4, 8, 1));
|
||||
}
|
||||
&Inst::FpuCmp32 { rn, rm } => {
|
||||
let rn = allocs.next(rn);
|
||||
let rm = allocs.next(rm);
|
||||
|
||||
let opcode = 0xb309; // CEBR
|
||||
put(sink, &enc_rre(opcode, rn, rm));
|
||||
}
|
||||
&Inst::FpuCmp64 { rn, rm } => {
|
||||
let rn = allocs.next(rn);
|
||||
let rm = allocs.next(rm);
|
||||
|
||||
let opcode = 0xb319; // CDBR
|
||||
put(sink, &enc_rre(opcode, rn, rm));
|
||||
}
|
||||
|
||||
&Inst::Call { link, ref info } => {
|
||||
let link = allocs.next_writable(link);
|
||||
|
||||
let opcode = 0xc05; // BRASL
|
||||
let reloc = Reloc::S390xPCRel32Dbl;
|
||||
let srcloc = state.cur_srcloc();
|
||||
@@ -1998,17 +2205,22 @@ impl MachInstEmit for Inst {
|
||||
}
|
||||
}
|
||||
&Inst::CallInd { link, ref info } => {
|
||||
let link = allocs.next_writable(link);
|
||||
let rn = allocs.next(info.rn);
|
||||
|
||||
let opcode = 0x0d; // BASR
|
||||
let srcloc = state.cur_srcloc();
|
||||
if let Some(s) = state.take_stack_map() {
|
||||
sink.add_stack_map(StackMapExtent::UpcomingBytes(2), s);
|
||||
}
|
||||
put(sink, &enc_rr(opcode, link.to_reg(), info.rn));
|
||||
put(sink, &enc_rr(opcode, link.to_reg(), rn));
|
||||
if info.opcode.is_call() {
|
||||
sink.add_call_site(srcloc, info.opcode);
|
||||
}
|
||||
}
|
||||
&Inst::Ret { link } => {
|
||||
&Inst::Ret { link, .. } => {
|
||||
let link = allocs.next(link);
|
||||
|
||||
let opcode = 0x07; // BCR
|
||||
put(sink, &enc_rr(opcode, gpr(15), link));
|
||||
}
|
||||
@@ -2025,6 +2237,8 @@ impl MachInstEmit for Inst {
|
||||
put(sink, &enc_ril_c(opcode, 15, 0));
|
||||
}
|
||||
&Inst::IndirectBr { rn, .. } => {
|
||||
let rn = allocs.next(rn);
|
||||
|
||||
let opcode = 0x07; // BCR
|
||||
put(sink, &enc_rr(opcode, gpr(15), rn));
|
||||
}
|
||||
@@ -2079,6 +2293,8 @@ impl MachInstEmit for Inst {
|
||||
put_with_trap(sink, &enc_e(0x0000), srcloc, trap_code);
|
||||
}
|
||||
&Inst::JTSequence { ridx, ref targets } => {
|
||||
let ridx = allocs.next(ridx);
|
||||
|
||||
let table_label = sink.get_label();
|
||||
|
||||
// This sequence is *one* instruction in the vcode, and is expanded only here at
|
||||
@@ -2093,7 +2309,7 @@ impl MachInstEmit for Inst {
|
||||
target: table_label,
|
||||
},
|
||||
};
|
||||
inst.emit(sink, emit_info, state);
|
||||
inst.emit(&[], sink, emit_info, state);
|
||||
|
||||
// Set temp to target address by adding the value of the jump table entry.
|
||||
let inst = Inst::AluRX {
|
||||
@@ -2101,7 +2317,7 @@ impl MachInstEmit for Inst {
|
||||
rd: rtmp,
|
||||
mem: MemArg::reg_plus_reg(rtmp.to_reg(), ridx, MemFlags::trusted()),
|
||||
};
|
||||
inst.emit(sink, emit_info, state);
|
||||
inst.emit(&[], sink, emit_info, state);
|
||||
|
||||
// Branch to computed address. (`targets` here is only used for successor queries
|
||||
// and is not needed for emission.)
|
||||
@@ -2109,7 +2325,7 @@ impl MachInstEmit for Inst {
|
||||
rn: rtmp.to_reg(),
|
||||
targets: vec![],
|
||||
};
|
||||
inst.emit(sink, emit_info, state);
|
||||
inst.emit(&[], sink, emit_info, state);
|
||||
|
||||
// Emit jump table (table of 32-bit offsets).
|
||||
// The first entry is the default target, which is not emitted
|
||||
@@ -2138,13 +2354,11 @@ impl MachInstEmit for Inst {
|
||||
state.virtual_sp_offset += offset;
|
||||
}
|
||||
|
||||
&Inst::ValueLabelMarker { .. } => {
|
||||
// Nothing; this is only used to compute debug info.
|
||||
}
|
||||
|
||||
&Inst::Unwind { ref inst } => {
|
||||
sink.add_unwind(inst.clone());
|
||||
}
|
||||
|
||||
&Inst::DummyUse { .. } => {}
|
||||
}
|
||||
|
||||
let end_off = sink.cur_offset();
|
||||
@@ -2153,7 +2367,8 @@ impl MachInstEmit for Inst {
|
||||
state.clear_post_insn();
|
||||
}
|
||||
|
||||
fn pretty_print(&self, mb_rru: Option<&RealRegUniverse>, state: &mut EmitState) -> String {
|
||||
self.print_with_state(mb_rru, state)
|
||||
fn pretty_print_inst(&self, allocs: &[Allocation], state: &mut EmitState) -> String {
|
||||
let mut allocs = AllocationConsumer::new(allocs);
|
||||
self.print_with_state(state, &mut allocs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1585,7 +1585,7 @@ fn test_s390x_binemit() {
|
||||
op: CmpOp::CmpS32,
|
||||
rn: gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C61D00000003",
|
||||
@@ -1624,7 +1624,7 @@ fn test_s390x_binemit() {
|
||||
op: CmpOp::CmpS32Ext16,
|
||||
rn: gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C61500000003",
|
||||
@@ -1649,7 +1649,7 @@ fn test_s390x_binemit() {
|
||||
op: CmpOp::CmpS64,
|
||||
rn: gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C61800000003",
|
||||
@@ -1674,7 +1674,7 @@ fn test_s390x_binemit() {
|
||||
op: CmpOp::CmpS64Ext16,
|
||||
rn: gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C61400000003",
|
||||
@@ -1699,7 +1699,7 @@ fn test_s390x_binemit() {
|
||||
op: CmpOp::CmpS64Ext32,
|
||||
rn: gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C61C00000003",
|
||||
@@ -1738,7 +1738,7 @@ fn test_s390x_binemit() {
|
||||
op: CmpOp::CmpL32,
|
||||
rn: gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C61F00000003",
|
||||
@@ -1749,7 +1749,7 @@ fn test_s390x_binemit() {
|
||||
op: CmpOp::CmpL32Ext16,
|
||||
rn: gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C61700000003",
|
||||
@@ -1774,7 +1774,7 @@ fn test_s390x_binemit() {
|
||||
op: CmpOp::CmpL64,
|
||||
rn: gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C61A00000003",
|
||||
@@ -1785,7 +1785,7 @@ fn test_s390x_binemit() {
|
||||
op: CmpOp::CmpL64Ext16,
|
||||
rn: gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C61600000003",
|
||||
@@ -1810,7 +1810,7 @@ fn test_s390x_binemit() {
|
||||
op: CmpOp::CmpL64Ext32,
|
||||
rn: gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C61E00000003",
|
||||
@@ -4536,7 +4536,7 @@ fn test_s390x_binemit() {
|
||||
Inst::Load32 {
|
||||
rd: writable_gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C41D00000003",
|
||||
@@ -4546,7 +4546,7 @@ fn test_s390x_binemit() {
|
||||
Inst::Load32SExt16 {
|
||||
rd: writable_gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C41500000003",
|
||||
@@ -4556,7 +4556,7 @@ fn test_s390x_binemit() {
|
||||
Inst::Load32ZExt16 {
|
||||
rd: writable_gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C41200000003",
|
||||
@@ -4566,7 +4566,7 @@ fn test_s390x_binemit() {
|
||||
Inst::Load64 {
|
||||
rd: writable_gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C41800000003",
|
||||
@@ -4576,7 +4576,7 @@ fn test_s390x_binemit() {
|
||||
Inst::Load64SExt16 {
|
||||
rd: writable_gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C41400000003",
|
||||
@@ -4586,7 +4586,7 @@ fn test_s390x_binemit() {
|
||||
Inst::Load64ZExt16 {
|
||||
rd: writable_gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C41600000003",
|
||||
@@ -4596,7 +4596,7 @@ fn test_s390x_binemit() {
|
||||
Inst::Load64SExt32 {
|
||||
rd: writable_gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C41C00000003",
|
||||
@@ -4606,7 +4606,7 @@ fn test_s390x_binemit() {
|
||||
Inst::Load64ZExt32 {
|
||||
rd: writable_gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C41E00000003",
|
||||
@@ -5790,7 +5790,7 @@ fn test_s390x_binemit() {
|
||||
Inst::Store16 {
|
||||
rd: gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C41700000003",
|
||||
@@ -5800,7 +5800,7 @@ fn test_s390x_binemit() {
|
||||
Inst::Store32 {
|
||||
rd: gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C41F00000003",
|
||||
@@ -5810,7 +5810,7 @@ fn test_s390x_binemit() {
|
||||
Inst::Store64 {
|
||||
rd: gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C41B00000003",
|
||||
@@ -6035,7 +6035,7 @@ fn test_s390x_binemit() {
|
||||
Inst::LoadAddr {
|
||||
rd: writable_gpr(1),
|
||||
mem: MemArg::Label {
|
||||
target: MachLabel::from_block(1),
|
||||
target: MachLabel::from_block(BlockIndex::new(1)),
|
||||
},
|
||||
},
|
||||
"C01000000003",
|
||||
@@ -6499,7 +6499,7 @@ fn test_s390x_binemit() {
|
||||
|
||||
insns.push((
|
||||
Inst::Jump {
|
||||
dest: MachLabel::from_block(0),
|
||||
dest: MachLabel::from_block(BlockIndex::new(0)),
|
||||
},
|
||||
"C0F400000000",
|
||||
"jg label0",
|
||||
@@ -6507,7 +6507,7 @@ fn test_s390x_binemit() {
|
||||
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: MachLabel::from_block(0),
|
||||
target: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(1),
|
||||
},
|
||||
"C01400000000",
|
||||
@@ -6515,7 +6515,7 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: MachLabel::from_block(0),
|
||||
target: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(2),
|
||||
},
|
||||
"C02400000000",
|
||||
@@ -6523,7 +6523,7 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: MachLabel::from_block(0),
|
||||
target: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(3),
|
||||
},
|
||||
"C03400000000",
|
||||
@@ -6531,7 +6531,7 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: MachLabel::from_block(0),
|
||||
target: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(4),
|
||||
},
|
||||
"C04400000000",
|
||||
@@ -6539,7 +6539,7 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: MachLabel::from_block(0),
|
||||
target: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(5),
|
||||
},
|
||||
"C05400000000",
|
||||
@@ -6547,7 +6547,7 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: MachLabel::from_block(0),
|
||||
target: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(6),
|
||||
},
|
||||
"C06400000000",
|
||||
@@ -6555,7 +6555,7 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: MachLabel::from_block(0),
|
||||
target: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(7),
|
||||
},
|
||||
"C07400000000",
|
||||
@@ -6563,7 +6563,7 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: MachLabel::from_block(0),
|
||||
target: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(8),
|
||||
},
|
||||
"C08400000000",
|
||||
@@ -6571,7 +6571,7 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: MachLabel::from_block(0),
|
||||
target: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(9),
|
||||
},
|
||||
"C09400000000",
|
||||
@@ -6579,7 +6579,7 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: MachLabel::from_block(0),
|
||||
target: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(10),
|
||||
},
|
||||
"C0A400000000",
|
||||
@@ -6587,7 +6587,7 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: MachLabel::from_block(0),
|
||||
target: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(11),
|
||||
},
|
||||
"C0B400000000",
|
||||
@@ -6595,7 +6595,7 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: MachLabel::from_block(0),
|
||||
target: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(12),
|
||||
},
|
||||
"C0C400000000",
|
||||
@@ -6603,7 +6603,7 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: MachLabel::from_block(0),
|
||||
target: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(13),
|
||||
},
|
||||
"C0D400000000",
|
||||
@@ -6611,7 +6611,7 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::OneWayCondBr {
|
||||
target: MachLabel::from_block(0),
|
||||
target: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(14),
|
||||
},
|
||||
"C0E400000000",
|
||||
@@ -6620,8 +6620,8 @@ fn test_s390x_binemit() {
|
||||
|
||||
insns.push((
|
||||
Inst::CondBr {
|
||||
taken: MachLabel::from_block(0),
|
||||
not_taken: MachLabel::from_block(0),
|
||||
taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
not_taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(1),
|
||||
},
|
||||
"C01400000000C0F4FFFFFFFD",
|
||||
@@ -6629,8 +6629,8 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::CondBr {
|
||||
taken: MachLabel::from_block(0),
|
||||
not_taken: MachLabel::from_block(0),
|
||||
taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
not_taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(2),
|
||||
},
|
||||
"C02400000000C0F4FFFFFFFD",
|
||||
@@ -6638,8 +6638,8 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::CondBr {
|
||||
taken: MachLabel::from_block(0),
|
||||
not_taken: MachLabel::from_block(0),
|
||||
taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
not_taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(3),
|
||||
},
|
||||
"C03400000000C0F4FFFFFFFD",
|
||||
@@ -6647,8 +6647,8 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::CondBr {
|
||||
taken: MachLabel::from_block(0),
|
||||
not_taken: MachLabel::from_block(0),
|
||||
taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
not_taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(4),
|
||||
},
|
||||
"C04400000000C0F4FFFFFFFD",
|
||||
@@ -6656,8 +6656,8 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::CondBr {
|
||||
taken: MachLabel::from_block(0),
|
||||
not_taken: MachLabel::from_block(0),
|
||||
taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
not_taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(5),
|
||||
},
|
||||
"C05400000000C0F4FFFFFFFD",
|
||||
@@ -6665,8 +6665,8 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::CondBr {
|
||||
taken: MachLabel::from_block(0),
|
||||
not_taken: MachLabel::from_block(0),
|
||||
taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
not_taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(6),
|
||||
},
|
||||
"C06400000000C0F4FFFFFFFD",
|
||||
@@ -6674,8 +6674,8 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::CondBr {
|
||||
taken: MachLabel::from_block(0),
|
||||
not_taken: MachLabel::from_block(0),
|
||||
taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
not_taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(7),
|
||||
},
|
||||
"C07400000000C0F4FFFFFFFD",
|
||||
@@ -6683,8 +6683,8 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::CondBr {
|
||||
taken: MachLabel::from_block(0),
|
||||
not_taken: MachLabel::from_block(0),
|
||||
taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
not_taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(8),
|
||||
},
|
||||
"C08400000000C0F4FFFFFFFD",
|
||||
@@ -6692,8 +6692,8 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::CondBr {
|
||||
taken: MachLabel::from_block(0),
|
||||
not_taken: MachLabel::from_block(0),
|
||||
taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
not_taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(9),
|
||||
},
|
||||
"C09400000000C0F4FFFFFFFD",
|
||||
@@ -6701,8 +6701,8 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::CondBr {
|
||||
taken: MachLabel::from_block(0),
|
||||
not_taken: MachLabel::from_block(0),
|
||||
taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
not_taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(10),
|
||||
},
|
||||
"C0A400000000C0F4FFFFFFFD",
|
||||
@@ -6710,8 +6710,8 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::CondBr {
|
||||
taken: MachLabel::from_block(0),
|
||||
not_taken: MachLabel::from_block(0),
|
||||
taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
not_taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(11),
|
||||
},
|
||||
"C0B400000000C0F4FFFFFFFD",
|
||||
@@ -6719,8 +6719,8 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::CondBr {
|
||||
taken: MachLabel::from_block(0),
|
||||
not_taken: MachLabel::from_block(0),
|
||||
taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
not_taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(12),
|
||||
},
|
||||
"C0C400000000C0F4FFFFFFFD",
|
||||
@@ -6728,8 +6728,8 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::CondBr {
|
||||
taken: MachLabel::from_block(0),
|
||||
not_taken: MachLabel::from_block(0),
|
||||
taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
not_taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(13),
|
||||
},
|
||||
"C0D400000000C0F4FFFFFFFD",
|
||||
@@ -6737,8 +6737,8 @@ fn test_s390x_binemit() {
|
||||
));
|
||||
insns.push((
|
||||
Inst::CondBr {
|
||||
taken: MachLabel::from_block(0),
|
||||
not_taken: MachLabel::from_block(0),
|
||||
taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
not_taken: MachLabel::from_block(BlockIndex::new(0)),
|
||||
cond: Cond::from_mask(14),
|
||||
},
|
||||
"C0E400000000C0F4FFFFFFFD",
|
||||
@@ -6782,7 +6782,14 @@ fn test_s390x_binemit() {
|
||||
"basr %r14, %r1",
|
||||
));
|
||||
|
||||
insns.push((Inst::Ret { link: gpr(14) }, "07FE", "br %r14"));
|
||||
insns.push((
|
||||
Inst::Ret {
|
||||
link: gpr(14),
|
||||
rets: vec![],
|
||||
},
|
||||
"07FE",
|
||||
"br %r14",
|
||||
));
|
||||
|
||||
insns.push((Inst::Debugtrap, "0001", "debugtrap"));
|
||||
|
||||
@@ -8246,7 +8253,6 @@ fn test_s390x_binemit() {
|
||||
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, isa_flags);
|
||||
for (insn, expected_encoding, expected_printing) in insns {
|
||||
println!(
|
||||
@@ -8255,7 +8261,8 @@ fn test_s390x_binemit() {
|
||||
);
|
||||
|
||||
// Check the printed text is as expected.
|
||||
let actual_printing = insn.show_rru(Some(&rru));
|
||||
let actual_printing =
|
||||
insn.print_with_state(&mut EmitState::default(), &mut AllocationConsumer::new(&[]));
|
||||
assert_eq!(expected_printing, actual_printing);
|
||||
|
||||
let mut buffer = MachBuffer::new();
|
||||
@@ -8265,7 +8272,7 @@ fn test_s390x_binemit() {
|
||||
buffer.bind_label(label0);
|
||||
|
||||
// Emit the instruction.
|
||||
insn.emit(&mut buffer, &emit_info, &mut Default::default());
|
||||
insn.emit(&[], &mut buffer, &emit_info, &mut Default::default());
|
||||
|
||||
// Label 1 after the instruction.
|
||||
let label1 = buffer.get_label();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! S390x ISA definitions: immediate constants.
|
||||
|
||||
use regalloc::{PrettyPrint, RealRegUniverse};
|
||||
use crate::machinst::{AllocationConsumer, PrettyPrint};
|
||||
use std::string::String;
|
||||
|
||||
/// An unsigned 12-bit immediate.
|
||||
@@ -207,25 +207,25 @@ impl UImm32Shifted {
|
||||
}
|
||||
|
||||
impl PrettyPrint for UImm12 {
|
||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
fn pretty_print(&self, _: u8, _: &mut AllocationConsumer<'_>) -> String {
|
||||
format!("{}", self.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl PrettyPrint for SImm20 {
|
||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
fn pretty_print(&self, _: u8, _: &mut AllocationConsumer<'_>) -> String {
|
||||
format!("{}", self.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl PrettyPrint for UImm16Shifted {
|
||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
fn pretty_print(&self, _: u8, _: &mut AllocationConsumer<'_>) -> String {
|
||||
format!("{}", self.bits)
|
||||
}
|
||||
}
|
||||
|
||||
impl PrettyPrint for UImm32Shifted {
|
||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
fn pretty_print(&self, _: u8, _: &mut AllocationConsumer<'_>) -> String {
|
||||
format!("{}", self.bits)
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,12 @@
|
||||
//! S390x ISA definitions: registers.
|
||||
|
||||
use alloc::string::String;
|
||||
use regalloc2::MachineEnv;
|
||||
use regalloc2::PReg;
|
||||
use regalloc2::VReg;
|
||||
|
||||
use crate::machinst::*;
|
||||
use crate::settings;
|
||||
use regalloc::{RealRegUniverse, Reg, RegClass, RegClassInfo, Writable, NUM_REG_CLASSES};
|
||||
|
||||
//=============================================================================
|
||||
// Registers, the Universe thereof, and printing
|
||||
@@ -29,11 +34,8 @@ const FPR_INDICES: [u8; 16] = [
|
||||
/// 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],
|
||||
)
|
||||
let preg = PReg::new(num as usize, RegClass::Int);
|
||||
Reg::from(VReg::new(preg.index(), RegClass::Int))
|
||||
}
|
||||
|
||||
/// Get a writable reference to a GPR.
|
||||
@@ -44,11 +46,8 @@ pub fn writable_gpr(num: u8) -> Writable<Reg> {
|
||||
/// 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],
|
||||
)
|
||||
let preg = PReg::new(num as usize, RegClass::Float);
|
||||
Reg::from(VReg::new(preg.index(), RegClass::Float))
|
||||
}
|
||||
|
||||
/// Get a writable reference to a V-register.
|
||||
@@ -88,81 +87,73 @@ pub fn zero_reg() -> Reg {
|
||||
}
|
||||
|
||||
/// 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());
|
||||
pub fn create_machine_env(_flags: &settings::Flags) -> MachineEnv {
|
||||
fn preg(r: Reg) -> PReg {
|
||||
r.to_real_reg().unwrap().into()
|
||||
}
|
||||
|
||||
RealRegUniverse {
|
||||
regs,
|
||||
allocable,
|
||||
allocable_by_class,
|
||||
MachineEnv {
|
||||
preferred_regs_by_class: [
|
||||
vec![
|
||||
// no r0; can't use for addressing?
|
||||
// no r1; it is our spilltmp.
|
||||
preg(gpr(2)),
|
||||
preg(gpr(3)),
|
||||
preg(gpr(4)),
|
||||
preg(gpr(5)),
|
||||
],
|
||||
vec![
|
||||
preg(fpr(0)),
|
||||
preg(fpr(1)),
|
||||
preg(fpr(2)),
|
||||
preg(fpr(3)),
|
||||
preg(fpr(4)),
|
||||
preg(fpr(5)),
|
||||
preg(fpr(6)),
|
||||
preg(fpr(7)),
|
||||
],
|
||||
],
|
||||
non_preferred_regs_by_class: [
|
||||
vec![
|
||||
preg(gpr(6)),
|
||||
preg(gpr(7)),
|
||||
preg(gpr(8)),
|
||||
preg(gpr(9)),
|
||||
preg(gpr(10)),
|
||||
preg(gpr(11)),
|
||||
preg(gpr(12)),
|
||||
// no r13; it is our scratch reg.
|
||||
preg(gpr(14)),
|
||||
// no r15; it is the stack pointer.
|
||||
],
|
||||
vec![
|
||||
preg(fpr(8)),
|
||||
preg(fpr(9)),
|
||||
preg(fpr(10)),
|
||||
preg(fpr(11)),
|
||||
preg(fpr(12)),
|
||||
preg(fpr(13)),
|
||||
preg(fpr(14)),
|
||||
// no f15; it is our scratch reg.
|
||||
],
|
||||
],
|
||||
scratch_by_class: [preg(gpr(13)), preg(fpr(15))],
|
||||
fixed_stack_slots: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn show_reg(reg: Reg) -> String {
|
||||
if let Some(rreg) = reg.to_real_reg() {
|
||||
match rreg.class() {
|
||||
RegClass::Int => format!("%r{}", rreg.hw_enc()),
|
||||
RegClass::Float => format!("%f{}", rreg.hw_enc()),
|
||||
}
|
||||
} else {
|
||||
format!("%{:?}", reg)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pretty_print_reg(reg: Reg, allocs: &mut AllocationConsumer<'_>) -> String {
|
||||
let reg = allocs.next(reg);
|
||||
show_reg(reg)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
//! Unwind information for System V ABI (s390x).
|
||||
|
||||
use crate::isa::unwind::systemv::RegisterMappingError;
|
||||
use crate::machinst::{Reg, RegClass};
|
||||
use gimli::{write::CommonInformationEntry, Encoding, Format, Register};
|
||||
use regalloc::{Reg, RegClass};
|
||||
|
||||
/// Creates a new s390x common information entry (CIE).
|
||||
pub fn create_cie() -> CommonInformationEntry {
|
||||
@@ -64,10 +64,9 @@ pub fn map_reg(reg: Reg) -> Result<Register, RegisterMappingError> {
|
||||
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?")),
|
||||
match reg.class() {
|
||||
RegClass::Int => Ok(GPR_MAP[reg.to_real_reg().unwrap().hw_enc() as usize]),
|
||||
RegClass::Float => Ok(FPR_MAP[reg.to_real_reg().unwrap().hw_enc() as usize]),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2137,31 +2137,31 @@
|
||||
;;;; Rules for `trap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(rule (lower (trap trap_code))
|
||||
(safepoint (trap_impl trap_code)))
|
||||
(side_effect (trap_impl trap_code)))
|
||||
|
||||
|
||||
;;;; Rules for `resumable_trap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(rule (lower (resumable_trap trap_code))
|
||||
(safepoint (trap_impl trap_code)))
|
||||
(side_effect (trap_impl trap_code)))
|
||||
|
||||
|
||||
;;;; Rules for `trapz` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(rule (lower (trapz val trap_code))
|
||||
(safepoint (trap_if_bool (invert_bool (value_nonzero val)) trap_code)))
|
||||
(side_effect (trap_if_bool (invert_bool (value_nonzero val)) trap_code)))
|
||||
|
||||
|
||||
;;;; Rules for `trapnz` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(rule (lower (trapnz val trap_code))
|
||||
(safepoint (trap_if_bool (value_nonzero val) trap_code)))
|
||||
(side_effect (trap_if_bool (value_nonzero val) trap_code)))
|
||||
|
||||
|
||||
;;;; Rules for `resumable_trapnz` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(rule (lower (resumable_trapnz val trap_code))
|
||||
(safepoint (trap_if_bool (value_nonzero val) trap_code)))
|
||||
(side_effect (trap_if_bool (value_nonzero val) trap_code)))
|
||||
|
||||
|
||||
;;;; Rules for `debugtrap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -2179,7 +2179,7 @@
|
||||
;; the desired comparison here; there is no separate `ifcmp` lowering.
|
||||
|
||||
(rule (lower (trapif int_cc (ifcmp x y) trap_code))
|
||||
(safepoint (trap_if_bool (icmp_val $false int_cc x y) trap_code)))
|
||||
(side_effect (trap_if_bool (icmp_val $false int_cc x y) trap_code)))
|
||||
|
||||
;; Recognize the case of `iadd_ifcout` feeding into `trapif`. Note that
|
||||
;; in the case, the `iadd_ifcout` is generated by a separate lowering
|
||||
|
||||
@@ -11,7 +11,6 @@ use crate::machinst::lower::*;
|
||||
use crate::machinst::*;
|
||||
use crate::settings::Flags;
|
||||
use crate::CodegenResult;
|
||||
use regalloc::Reg;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
pub mod isle;
|
||||
|
||||
@@ -14,9 +14,8 @@ use crate::settings::Flags;
|
||||
use crate::{
|
||||
ir::{
|
||||
condcodes::*, immediates::*, types::*, AtomicRmwOp, Endianness, Inst, InstructionData,
|
||||
StackSlot, TrapCode, Value, ValueLabel, ValueList,
|
||||
StackSlot, TrapCode, Value, ValueList,
|
||||
},
|
||||
isa::s390x::inst::s390x_map_regs,
|
||||
isa::unwind::UnwindInst,
|
||||
machinst::{InsnOutput, LowerCtx},
|
||||
};
|
||||
@@ -43,15 +42,9 @@ pub(crate) fn lower<C>(
|
||||
where
|
||||
C: LowerCtx<I = MInst>,
|
||||
{
|
||||
lower_common(
|
||||
lower_ctx,
|
||||
flags,
|
||||
isa_flags,
|
||||
outputs,
|
||||
inst,
|
||||
|cx, insn| generated_code::constructor_lower(cx, insn),
|
||||
s390x_map_regs,
|
||||
)
|
||||
lower_common(lower_ctx, flags, isa_flags, outputs, inst, |cx, insn| {
|
||||
generated_code::constructor_lower(cx, insn)
|
||||
})
|
||||
}
|
||||
|
||||
/// The main entry point for branch lowering with ISLE.
|
||||
@@ -65,15 +58,9 @@ pub(crate) fn lower_branch<C>(
|
||||
where
|
||||
C: LowerCtx<I = MInst>,
|
||||
{
|
||||
lower_common(
|
||||
lower_ctx,
|
||||
flags,
|
||||
isa_flags,
|
||||
&[],
|
||||
branch,
|
||||
|cx, insn| generated_code::constructor_lower_branch(cx, insn, &targets.to_vec()),
|
||||
s390x_map_regs,
|
||||
)
|
||||
lower_common(lower_ctx, flags, isa_flags, &[], branch, |cx, insn| {
|
||||
generated_code::constructor_lower_branch(cx, insn, &targets.to_vec())
|
||||
})
|
||||
}
|
||||
|
||||
impl<C> generated_code::Context for IsleContext<'_, C, Flags, IsaFlags, 6>
|
||||
@@ -523,11 +510,6 @@ where
|
||||
|
||||
#[inline]
|
||||
fn emit(&mut self, inst: &MInst) -> Unit {
|
||||
self.emitted_insts.push((inst.clone(), false));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn emit_safepoint(&mut self, inst: &MInst) -> Unit {
|
||||
self.emitted_insts.push((inst.clone(), true));
|
||||
self.lower_ctx.emit(inst.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
src/clif.isle 443b34b797fc8ace
|
||||
src/prelude.isle c0751050a11e2686
|
||||
src/isa/s390x/inst.isle d91a16074ab186a8
|
||||
src/isa/s390x/lower.isle 1cc5a12adc8c75f9
|
||||
src/prelude.isle afd037c4d91c875c
|
||||
src/isa/s390x/inst.isle 8218bd9e8556446b
|
||||
src/isa/s390x/lower.isle 6a8de81f8dc4e568
|
||||
|
||||
@@ -79,7 +79,6 @@ pub trait Context {
|
||||
fn def_inst(&mut self, arg0: Value) -> Option<Inst>;
|
||||
fn offset32_to_u32(&mut self, arg0: Offset32) -> u32;
|
||||
fn emit(&mut self, arg0: &MInst) -> Unit;
|
||||
fn emit_safepoint(&mut self, arg0: &MInst) -> Unit;
|
||||
fn trap_code_division_by_zero(&mut self) -> TrapCode;
|
||||
fn trap_code_integer_overflow(&mut self) -> TrapCode;
|
||||
fn trap_code_bad_conversion_to_integer(&mut self) -> TrapCode;
|
||||
@@ -155,13 +154,13 @@ pub trait Context {
|
||||
fn same_reg(&mut self, arg0: Reg, arg1: WritableReg) -> Option<()>;
|
||||
}
|
||||
|
||||
/// Internal type SideEffectNoResult: defined at src/prelude.isle line 405.
|
||||
/// Internal type SideEffectNoResult: defined at src/prelude.isle line 402.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum SideEffectNoResult {
|
||||
Inst { inst: MInst },
|
||||
}
|
||||
|
||||
/// Internal type ProducesFlags: defined at src/prelude.isle line 427.
|
||||
/// Internal type ProducesFlags: defined at src/prelude.isle line 418.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ProducesFlags {
|
||||
ProducesFlagsSideEffect { inst: MInst },
|
||||
@@ -169,7 +168,7 @@ pub enum ProducesFlags {
|
||||
ProducesFlagsReturnsResultWithConsumer { inst: MInst, result: Reg },
|
||||
}
|
||||
|
||||
/// Internal type ConsumesFlags: defined at src/prelude.isle line 438.
|
||||
/// Internal type ConsumesFlags: defined at src/prelude.isle line 429.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ConsumesFlags {
|
||||
ConsumesFlagsReturnsResultWithProducer {
|
||||
@@ -666,6 +665,7 @@ pub enum MInst {
|
||||
},
|
||||
Ret {
|
||||
link: Reg,
|
||||
rets: VecReg,
|
||||
},
|
||||
EpiloguePlaceholder,
|
||||
Jump {
|
||||
@@ -715,9 +715,8 @@ pub enum MInst {
|
||||
VirtualSPOffsetAdj {
|
||||
offset: i64,
|
||||
},
|
||||
ValueLabelMarker {
|
||||
DummyUse {
|
||||
reg: Reg,
|
||||
label: ValueLabel,
|
||||
},
|
||||
Unwind {
|
||||
inst: UnwindInst,
|
||||
@@ -959,7 +958,7 @@ pub fn constructor_side_effect<C: Context>(
|
||||
inst: ref pattern1_0,
|
||||
} = pattern0_0
|
||||
{
|
||||
// Rule at src/prelude.isle line 410.
|
||||
// Rule at src/prelude.isle line 407.
|
||||
let expr0_0 = C::emit(ctx, pattern1_0);
|
||||
let expr1_0 = C::output_none(ctx);
|
||||
return Some(expr1_0);
|
||||
@@ -967,24 +966,6 @@ pub fn constructor_side_effect<C: Context>(
|
||||
return None;
|
||||
}
|
||||
|
||||
// Generated as internal constructor for term safepoint.
|
||||
pub fn constructor_safepoint<C: Context>(
|
||||
ctx: &mut C,
|
||||
arg0: &SideEffectNoResult,
|
||||
) -> Option<InstOutput> {
|
||||
let pattern0_0 = arg0;
|
||||
if let &SideEffectNoResult::Inst {
|
||||
inst: ref pattern1_0,
|
||||
} = pattern0_0
|
||||
{
|
||||
// Rule at src/prelude.isle line 416.
|
||||
let expr0_0 = C::emit_safepoint(ctx, pattern1_0);
|
||||
let expr1_0 = C::output_none(ctx);
|
||||
return Some(expr1_0);
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
// Generated as internal constructor for term produces_flags_get_reg.
|
||||
pub fn constructor_produces_flags_get_reg<C: Context>(
|
||||
ctx: &mut C,
|
||||
@@ -996,7 +977,7 @@ pub fn constructor_produces_flags_get_reg<C: Context>(
|
||||
result: pattern1_1,
|
||||
} = pattern0_0
|
||||
{
|
||||
// Rule at src/prelude.isle line 454.
|
||||
// Rule at src/prelude.isle line 445.
|
||||
return Some(pattern1_1);
|
||||
}
|
||||
return None;
|
||||
@@ -1013,7 +994,7 @@ pub fn constructor_produces_flags_ignore<C: Context>(
|
||||
inst: ref pattern1_0,
|
||||
result: pattern1_1,
|
||||
} => {
|
||||
// Rule at src/prelude.isle line 459.
|
||||
// Rule at src/prelude.isle line 450.
|
||||
let expr0_0 = ProducesFlags::ProducesFlagsSideEffect {
|
||||
inst: pattern1_0.clone(),
|
||||
};
|
||||
@@ -1023,7 +1004,7 @@ pub fn constructor_produces_flags_ignore<C: Context>(
|
||||
inst: ref pattern1_0,
|
||||
result: pattern1_1,
|
||||
} => {
|
||||
// Rule at src/prelude.isle line 461.
|
||||
// Rule at src/prelude.isle line 452.
|
||||
let expr0_0 = ProducesFlags::ProducesFlagsSideEffect {
|
||||
inst: pattern1_0.clone(),
|
||||
};
|
||||
@@ -1052,7 +1033,7 @@ pub fn constructor_consumes_flags_concat<C: Context>(
|
||||
result: pattern3_1,
|
||||
} = pattern2_0
|
||||
{
|
||||
// Rule at src/prelude.isle line 468.
|
||||
// Rule at src/prelude.isle line 459.
|
||||
let expr0_0 = C::value_regs(ctx, pattern1_1, pattern3_1);
|
||||
let expr1_0 = ConsumesFlags::ConsumesFlagsTwiceReturnsValueRegs {
|
||||
inst1: pattern1_0.clone(),
|
||||
@@ -1082,7 +1063,7 @@ pub fn constructor_with_flags<C: Context>(
|
||||
inst: ref pattern3_0,
|
||||
result: pattern3_1,
|
||||
} => {
|
||||
// Rule at src/prelude.isle line 493.
|
||||
// Rule at src/prelude.isle line 484.
|
||||
let expr0_0 = C::emit(ctx, pattern1_0);
|
||||
let expr1_0 = C::emit(ctx, pattern3_0);
|
||||
let expr2_0 = C::value_reg(ctx, pattern3_1);
|
||||
@@ -1093,7 +1074,7 @@ pub fn constructor_with_flags<C: Context>(
|
||||
inst2: ref pattern3_1,
|
||||
result: pattern3_2,
|
||||
} => {
|
||||
// Rule at src/prelude.isle line 499.
|
||||
// Rule at src/prelude.isle line 490.
|
||||
let expr0_0 = C::emit(ctx, pattern1_0);
|
||||
let expr1_0 = C::emit(ctx, pattern3_0);
|
||||
let expr2_0 = C::emit(ctx, pattern3_1);
|
||||
@@ -1106,7 +1087,7 @@ pub fn constructor_with_flags<C: Context>(
|
||||
inst4: ref pattern3_3,
|
||||
result: pattern3_4,
|
||||
} => {
|
||||
// Rule at src/prelude.isle line 511.
|
||||
// Rule at src/prelude.isle line 502.
|
||||
let expr0_0 = C::emit(ctx, pattern1_0);
|
||||
let expr1_0 = C::emit(ctx, pattern3_0);
|
||||
let expr2_0 = C::emit(ctx, pattern3_1);
|
||||
@@ -1127,7 +1108,7 @@ pub fn constructor_with_flags<C: Context>(
|
||||
result: pattern3_1,
|
||||
} = pattern2_0
|
||||
{
|
||||
// Rule at src/prelude.isle line 487.
|
||||
// Rule at src/prelude.isle line 478.
|
||||
let expr0_0 = C::emit(ctx, pattern1_0);
|
||||
let expr1_0 = C::emit(ctx, pattern3_0);
|
||||
let expr2_0 = C::value_regs(ctx, pattern1_1, pattern3_1);
|
||||
@@ -1147,7 +1128,7 @@ pub fn constructor_with_flags_reg<C: Context>(
|
||||
) -> Option<Reg> {
|
||||
let pattern0_0 = arg0;
|
||||
let pattern1_0 = arg1;
|
||||
// Rule at src/prelude.isle line 528.
|
||||
// Rule at src/prelude.isle line 519.
|
||||
let expr0_0 = constructor_with_flags(ctx, pattern0_0, pattern1_0)?;
|
||||
let expr1_0: usize = 0;
|
||||
let expr2_0 = C::value_regs_get(ctx, expr0_0, expr1_0);
|
||||
@@ -8098,13 +8079,13 @@ pub fn constructor_lower<C: Context>(ctx: &mut C, arg0: Inst) -> Option<InstOutp
|
||||
&Opcode::Trap => {
|
||||
// Rule at src/isa/s390x/lower.isle line 2139.
|
||||
let expr0_0 = constructor_trap_impl(ctx, pattern2_1)?;
|
||||
let expr1_0 = constructor_safepoint(ctx, &expr0_0)?;
|
||||
let expr1_0 = constructor_side_effect(ctx, &expr0_0)?;
|
||||
return Some(expr1_0);
|
||||
}
|
||||
&Opcode::ResumableTrap => {
|
||||
// Rule at src/isa/s390x/lower.isle line 2145.
|
||||
let expr0_0 = constructor_trap_impl(ctx, pattern2_1)?;
|
||||
let expr1_0 = constructor_safepoint(ctx, &expr0_0)?;
|
||||
let expr1_0 = constructor_side_effect(ctx, &expr0_0)?;
|
||||
return Some(expr1_0);
|
||||
}
|
||||
_ => {}
|
||||
@@ -8358,7 +8339,7 @@ pub fn constructor_lower<C: Context>(ctx: &mut C, arg0: Inst) -> Option<InstOutp
|
||||
ctx, expr0_0, pattern2_2, pattern8_0, pattern8_1,
|
||||
)?;
|
||||
let expr2_0 = constructor_trap_if_bool(ctx, &expr1_0, pattern2_3)?;
|
||||
let expr3_0 = constructor_safepoint(ctx, &expr2_0)?;
|
||||
let expr3_0 = constructor_side_effect(ctx, &expr2_0)?;
|
||||
return Some(expr3_0);
|
||||
}
|
||||
&Opcode::IaddIfcout => {
|
||||
@@ -8391,21 +8372,21 @@ pub fn constructor_lower<C: Context>(ctx: &mut C, arg0: Inst) -> Option<InstOutp
|
||||
let expr0_0 = constructor_value_nonzero(ctx, pattern2_1)?;
|
||||
let expr1_0 = constructor_invert_bool(ctx, &expr0_0)?;
|
||||
let expr2_0 = constructor_trap_if_bool(ctx, &expr1_0, pattern2_2)?;
|
||||
let expr3_0 = constructor_safepoint(ctx, &expr2_0)?;
|
||||
let expr3_0 = constructor_side_effect(ctx, &expr2_0)?;
|
||||
return Some(expr3_0);
|
||||
}
|
||||
&Opcode::Trapnz => {
|
||||
// Rule at src/isa/s390x/lower.isle line 2157.
|
||||
let expr0_0 = constructor_value_nonzero(ctx, pattern2_1)?;
|
||||
let expr1_0 = constructor_trap_if_bool(ctx, &expr0_0, pattern2_2)?;
|
||||
let expr2_0 = constructor_safepoint(ctx, &expr1_0)?;
|
||||
let expr2_0 = constructor_side_effect(ctx, &expr1_0)?;
|
||||
return Some(expr2_0);
|
||||
}
|
||||
&Opcode::ResumableTrapnz => {
|
||||
// Rule at src/isa/s390x/lower.isle line 2163.
|
||||
let expr0_0 = constructor_value_nonzero(ctx, pattern2_1)?;
|
||||
let expr1_0 = constructor_trap_if_bool(ctx, &expr0_0, pattern2_2)?;
|
||||
let expr2_0 = constructor_safepoint(ctx, &expr1_0)?;
|
||||
let expr2_0 = constructor_side_effect(ctx, &expr1_0)?;
|
||||
return Some(expr2_0);
|
||||
}
|
||||
_ => {}
|
||||
|
||||
@@ -7,15 +7,13 @@ use crate::isa::s390x::settings as s390x_settings;
|
||||
use crate::isa::unwind::systemv::RegisterMappingError;
|
||||
use crate::isa::{Builder as IsaBuilder, TargetIsa};
|
||||
use crate::machinst::{
|
||||
compile, MachCompileResult, MachTextSectionBuilder, TextSectionBuilder, VCode,
|
||||
compile, MachCompileResult, MachTextSectionBuilder, Reg, TextSectionBuilder, VCode,
|
||||
};
|
||||
use crate::result::CodegenResult;
|
||||
use crate::settings as shared_settings;
|
||||
|
||||
use alloc::{boxed::Box, vec::Vec};
|
||||
use core::fmt;
|
||||
|
||||
use regalloc::{PrettyPrint, RealRegUniverse, Reg};
|
||||
use regalloc2::MachineEnv;
|
||||
use target_lexicon::{Architecture, Triple};
|
||||
|
||||
// New backend:
|
||||
@@ -24,7 +22,7 @@ pub(crate) mod inst;
|
||||
mod lower;
|
||||
mod settings;
|
||||
|
||||
use inst::create_reg_universe;
|
||||
use inst::create_machine_env;
|
||||
|
||||
use self::inst::EmitInfo;
|
||||
|
||||
@@ -33,7 +31,7 @@ pub struct S390xBackend {
|
||||
triple: Triple,
|
||||
flags: shared_settings::Flags,
|
||||
isa_flags: s390x_settings::Flags,
|
||||
reg_universe: RealRegUniverse,
|
||||
machine_env: MachineEnv,
|
||||
}
|
||||
|
||||
impl S390xBackend {
|
||||
@@ -43,12 +41,12 @@ impl S390xBackend {
|
||||
flags: shared_settings::Flags,
|
||||
isa_flags: s390x_settings::Flags,
|
||||
) -> S390xBackend {
|
||||
let reg_universe = create_reg_universe(&flags);
|
||||
let machine_env = create_machine_env(&flags);
|
||||
S390xBackend {
|
||||
triple,
|
||||
flags,
|
||||
isa_flags,
|
||||
reg_universe,
|
||||
machine_env,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,10 +56,10 @@ impl S390xBackend {
|
||||
&self,
|
||||
func: &Function,
|
||||
flags: shared_settings::Flags,
|
||||
) -> CodegenResult<VCode<inst::Inst>> {
|
||||
) -> CodegenResult<(VCode<inst::Inst>, regalloc2::Output)> {
|
||||
let emit_info = EmitInfo::new(flags.clone(), self.isa_flags.clone());
|
||||
let abi = Box::new(abi::S390xABICallee::new(func, flags, self.isa_flags())?);
|
||||
compile::compile::<S390xBackend>(func, self, abi, &self.reg_universe, emit_info)
|
||||
compile::compile::<S390xBackend>(func, self, abi, &self.machine_env, emit_info)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,28 +70,27 @@ impl TargetIsa for S390xBackend {
|
||||
want_disasm: bool,
|
||||
) -> CodegenResult<MachCompileResult> {
|
||||
let flags = self.flags();
|
||||
let vcode = self.compile_vcode(func, flags.clone())?;
|
||||
let (buffer, bb_starts, bb_edges) = vcode.emit();
|
||||
let frame_size = vcode.frame_size();
|
||||
let value_labels_ranges = vcode.value_labels_ranges();
|
||||
let stackslot_offsets = vcode.stackslot_offsets().clone();
|
||||
let (vcode, regalloc_result) = self.compile_vcode(func, flags.clone())?;
|
||||
|
||||
let disasm = if want_disasm {
|
||||
Some(vcode.show_rru(Some(&create_reg_universe(flags))))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let want_disasm = want_disasm || log::log_enabled!(log::Level::Debug);
|
||||
let emit_result = vcode.emit(®alloc_result, want_disasm, flags.machine_code_cfg_info());
|
||||
let frame_size = emit_result.frame_size;
|
||||
let value_labels_ranges = emit_result.value_labels_ranges;
|
||||
let buffer = emit_result.buffer.finish();
|
||||
let stackslot_offsets = emit_result.stackslot_offsets;
|
||||
|
||||
let buffer = buffer.finish();
|
||||
if let Some(disasm) = emit_result.disasm.as_ref() {
|
||||
log::debug!("disassembly:\n{}", disasm);
|
||||
}
|
||||
|
||||
Ok(MachCompileResult {
|
||||
buffer,
|
||||
frame_size,
|
||||
disasm,
|
||||
disasm: emit_result.disasm,
|
||||
value_labels_ranges,
|
||||
stackslot_offsets,
|
||||
bb_starts,
|
||||
bb_edges,
|
||||
bb_starts: emit_result.bb_offsets,
|
||||
bb_edges: emit_result.bb_edges,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -296,10 +293,11 @@ mod test {
|
||||
// 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,
|
||||
236, 50, 18, 52, 0, 216, 167, 62, 0, 0, 192, 100, 0, 0, 0, 11, 236, 67, 18, 52, 0, 216,
|
||||
167, 78, 0, 0, 192, 100, 255, 255, 255, 251, 167, 62, 0, 0, 192, 100, 255, 255, 255,
|
||||
246, 236, 35, 237, 204, 0, 216, 7, 254,
|
||||
];
|
||||
|
||||
assert_eq!(code, &golden[..]);
|
||||
|
||||
Reference in New Issue
Block a user