Remove uses of reg_mod from s390x (#5073)

Remove uses of reg_mod from the s390x backend. This required moving away from using r0/r1 as the result registers from a few different pseudo instructions, standardizing instead on r2/r3. That change was necessary as regalloc2 will not correctly allocate registers that aren't listed in the allocatable set, which r0/r1 are not.

Co-authored-by: Ulrich Weigand <ulrich.weigand@de.ibm.com>
Co-authored-by: Chris Fallin <chris@cfallin.org>
This commit is contained in:
Trevor Elliott
2022-10-21 09:22:16 -07:00
committed by GitHub
parent 204d4c332c
commit d9753fac2b
19 changed files with 1215 additions and 758 deletions

View File

@@ -11,6 +11,39 @@ use crate::trace;
use core::convert::TryFrom;
use regalloc2::Allocation;
/// Debug macro for testing that a regpair is valid: that the high register is even, and the low
/// register is one higher than the high register.
macro_rules! debug_assert_valid_regpair {
($hi:expr, $lo:expr) => {
if cfg!(debug_assertions) {
match ($hi.to_real_reg(), $lo.to_real_reg()) {
(Some(hi), Some(lo)) => {
assert!(
hi.hw_enc() % 2 == 0,
"High register is not even: {}",
show_reg($hi)
);
assert_eq!(
hi.hw_enc() + 1,
lo.hw_enc(),
"Low register is not valid: {}, {}",
show_reg($hi),
show_reg($lo)
);
}
_ => {
panic!(
"Expected real registers for {} {}",
show_reg($hi),
show_reg($lo)
);
}
}
}
};
}
/// Type(s) of memory instructions available for mem_finalize.
pub struct MemInstType {
/// True if 12-bit unsigned displacement is supported.
@@ -1654,52 +1687,87 @@ impl MachInstEmit for Inst {
put(sink, &enc_ril_a(opcode, rd.to_reg(), imm.bits));
}
&Inst::SMulWide { rn, rm } => {
&Inst::SMulWide { rd, rn, rm } => {
let rn = allocs.next(rn);
let rm = allocs.next(rm);
let rd1 = allocs.next_writable(rd.hi);
let rd2 = allocs.next_writable(rd.lo);
debug_assert_valid_regpair!(rd1.to_reg(), rd2.to_reg());
let opcode = 0xb9ec; // MGRK
put(sink, &enc_rrf_ab(opcode, gpr(0), rn, rm, 0));
put(sink, &enc_rrf_ab(opcode, rd1.to_reg(), rn, rm, 0));
}
&Inst::UMulWide { rn } => {
&Inst::UMulWide { rd, ri, rn } => {
let rn = allocs.next(rn);
let rd1 = allocs.next_writable(rd.hi);
let rd2 = allocs.next_writable(rd.lo);
debug_assert_valid_regpair!(rd1.to_reg(), rd2.to_reg());
let ri = allocs.next(ri);
debug_assert_eq!(rd2.to_reg(), ri);
let opcode = 0xb986; // MLGR
put(sink, &enc_rre(opcode, gpr(0), rn));
put(sink, &enc_rre(opcode, rd1.to_reg(), rn));
}
&Inst::SDivMod32 { rn } => {
&Inst::SDivMod32 { rd, ri, rn } => {
let rn = allocs.next(rn);
let rd1 = allocs.next_writable(rd.hi);
let rd2 = allocs.next_writable(rd.lo);
debug_assert_valid_regpair!(rd1.to_reg(), rd2.to_reg());
let ri = allocs.next(ri);
debug_assert_eq!(rd2.to_reg(), ri);
let opcode = 0xb91d; // DSGFR
let trap_code = TrapCode::IntegerDivisionByZero;
put_with_trap(sink, &enc_rre(opcode, gpr(0), rn), trap_code);
put_with_trap(sink, &enc_rre(opcode, rd1.to_reg(), rn), trap_code);
}
&Inst::SDivMod64 { rn } => {
&Inst::SDivMod64 { rd, ri, rn } => {
let rn = allocs.next(rn);
let rd1 = allocs.next_writable(rd.hi);
let rd2 = allocs.next_writable(rd.lo);
debug_assert_valid_regpair!(rd1.to_reg(), rd2.to_reg());
let ri = allocs.next(ri);
debug_assert_eq!(rd2.to_reg(), ri);
let opcode = 0xb90d; // DSGR
let trap_code = TrapCode::IntegerDivisionByZero;
put_with_trap(sink, &enc_rre(opcode, gpr(0), rn), trap_code);
put_with_trap(sink, &enc_rre(opcode, rd1.to_reg(), rn), trap_code);
}
&Inst::UDivMod32 { rn } => {
&Inst::UDivMod32 { rd, ri, rn } => {
let rn = allocs.next(rn);
let rd1 = allocs.next_writable(rd.hi);
let rd2 = allocs.next_writable(rd.lo);
debug_assert_valid_regpair!(rd1.to_reg(), rd2.to_reg());
let ri1 = allocs.next(ri.hi);
let ri2 = allocs.next(ri.lo);
debug_assert_eq!(rd1.to_reg(), ri1);
debug_assert_eq!(rd2.to_reg(), ri2);
let opcode = 0xb997; // DLR
let trap_code = TrapCode::IntegerDivisionByZero;
put_with_trap(sink, &enc_rre(opcode, gpr(0), rn), trap_code);
put_with_trap(sink, &enc_rre(opcode, rd1.to_reg(), rn), trap_code);
}
&Inst::UDivMod64 { rn } => {
&Inst::UDivMod64 { rd, ri, rn } => {
let rn = allocs.next(rn);
let rd1 = allocs.next_writable(rd.hi);
let rd2 = allocs.next_writable(rd.lo);
debug_assert_valid_regpair!(rd1.to_reg(), rd2.to_reg());
let ri1 = allocs.next(ri.hi);
let ri2 = allocs.next(ri.lo);
debug_assert_eq!(rd1.to_reg(), ri1);
debug_assert_eq!(rd2.to_reg(), ri2);
let opcode = 0xb987; // DLGR
let trap_code = TrapCode::IntegerDivisionByZero;
put_with_trap(sink, &enc_rre(opcode, gpr(0), rn), trap_code);
put_with_trap(sink, &enc_rre(opcode, rd1.to_reg(), rn), trap_code);
}
&Inst::Flogr { rn } => {
&Inst::Flogr { rd, rn } => {
let rn = allocs.next(rn);
let rd1 = allocs.next_writable(rd.hi);
let rd2 = allocs.next_writable(rd.lo);
debug_assert_valid_regpair!(rd1.to_reg(), rd2.to_reg());
let opcode = 0xb983; // FLOGR
put(sink, &enc_rre(opcode, gpr(0), rn));
put(sink, &enc_rre(opcode, rd1.to_reg(), rn));
}
&Inst::ShiftRR {
@@ -1732,12 +1800,15 @@ impl MachInstEmit for Inst {
&Inst::RxSBG {
op,
rd,
ri,
rn,
start_bit,
end_bit,
rotate_amt,
} => {
let rd = allocs.next_writable(rd);
let ri = allocs.next(ri);
debug_assert_eq!(rd.to_reg(), ri);
let rn = allocs.next(rn);
let opcode = match op {
@@ -2069,8 +2140,21 @@ impl MachInstEmit for Inst {
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 } => {
&Inst::AtomicCas32 {
rd,
ri,
rn,
ref mem,
}
| &Inst::AtomicCas64 {
rd,
ri,
rn,
ref mem,
} => {
let rd = allocs.next_writable(rd);
let ri = allocs.next(ri);
debug_assert_eq!(rd.to_reg(), ri);
let rn = allocs.next(rn);
let mem = mem.with_allocs(&mut allocs);
@@ -2280,22 +2364,28 @@ impl MachInstEmit for Inst {
let opcode = 0xc01; // LGFI
put(sink, &enc_ril_a(opcode, rd.to_reg(), imm as u32));
}
&Inst::CMov32 { rd, cond, rm } => {
&Inst::CMov32 { rd, cond, ri, rm } => {
let rd = allocs.next_writable(rd);
let ri = allocs.next(ri);
debug_assert_eq!(rd.to_reg(), ri);
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 } => {
&Inst::CMov64 { rd, cond, ri, rm } => {
let rd = allocs.next_writable(rd);
let ri = allocs.next(ri);
debug_assert_eq!(rd.to_reg(), ri);
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 } => {
&Inst::CMov32SImm16 { rd, cond, ri, imm } => {
let rd = allocs.next_writable(rd);
let ri = allocs.next(ri);
debug_assert_eq!(rd.to_reg(), ri);
let opcode = 0xec42; // LOCHI
put(
@@ -2303,8 +2393,10 @@ impl MachInstEmit for Inst {
&enc_rie_g(opcode, rd.to_reg(), imm as u16, cond.bits()),
);
}
&Inst::CMov64SImm16 { rd, cond, imm } => {
&Inst::CMov64SImm16 { rd, cond, ri, imm } => {
let rd = allocs.next_writable(rd);
let ri = allocs.next(ri);
debug_assert_eq!(rd.to_reg(), ri);
let opcode = 0xec46; // LOCGHI
put(
@@ -2334,8 +2426,10 @@ impl MachInstEmit for Inst {
};
put(sink, &enc_ril_a(opcode, rd.to_reg(), imm.bits));
}
&Inst::Insert64UImm16Shifted { rd, imm } => {
&Inst::Insert64UImm16Shifted { rd, ri, imm } => {
let rd = allocs.next_writable(rd);
let ri = allocs.next(ri);
debug_assert_eq!(rd.to_reg(), ri);
let opcode = match imm.shift {
0 => 0xa53, // IILL
@@ -2346,8 +2440,10 @@ impl MachInstEmit for Inst {
};
put(sink, &enc_ri_a(opcode, rd.to_reg(), imm.bits));
}
&Inst::Insert64UImm32Shifted { rd, imm } => {
&Inst::Insert64UImm32Shifted { rd, ri, imm } => {
let rd = allocs.next_writable(rd);
let ri = allocs.next(ri);
debug_assert_eq!(rd.to_reg(), ri);
let opcode = match imm.shift {
0 => 0xc09, // IILF
@@ -2356,11 +2452,20 @@ impl MachInstEmit for Inst {
};
put(sink, &enc_ril_a(opcode, rd.to_reg(), imm.bits));
}
&Inst::LoadAR { rd, ar } | &Inst::InsertAR { rd, ar } => {
&Inst::LoadAR { rd, ar } => {
let rd = allocs.next_writable(rd);
let opcode = 0xb24f; // EAR
put(sink, &enc_rre(opcode, rd.to_reg(), gpr(ar)));
}
&Inst::InsertAR { rd, ri, ar } => {
let rd = allocs.next_writable(rd);
let ri = allocs.next(ri);
debug_assert_eq!(rd.to_reg(), ri);
let opcode = 0xb24f; // EAR
put(sink, &enc_rre(opcode, rd.to_reg(), gpr(ar)));
}
&Inst::LoadSymbolReloc {
rd,
ref symbol_reloc,
@@ -2407,8 +2512,10 @@ impl MachInstEmit for Inst {
put(sink, &enc_vrr_a(opcode, rd.to_reg(), rn, 0, 0, 0));
}
}
&Inst::FpuCMov32 { rd, cond, rm } => {
&Inst::FpuCMov32 { rd, cond, ri, rm } => {
let rd = allocs.next_writable(rd);
let ri = allocs.next(ri);
debug_assert_eq!(rd.to_reg(), ri);
let rm = allocs.next(rm);
if is_fpr(rd.to_reg()) && is_fpr(rm) {
@@ -2423,8 +2530,10 @@ impl MachInstEmit for Inst {
put(sink, &enc_vrr_a(opcode, rd.to_reg(), rm, 0, 0, 0));
}
}
&Inst::FpuCMov64 { rd, cond, rm } => {
&Inst::FpuCMov64 { rd, cond, ri, rm } => {
let rd = allocs.next_writable(rd);
let ri = allocs.next(ri);
debug_assert_eq!(rd.to_reg(), ri);
let rm = allocs.next(rm);
if is_fpr(rd.to_reg()) && is_fpr(rm) {
@@ -3010,8 +3119,10 @@ impl MachInstEmit for Inst {
let opcode = 0xe756; // VLR
put(sink, &enc_vrr_a(opcode, rd.to_reg(), rn, 0, 0, 0));
}
&Inst::VecCMov { rd, cond, rm } => {
&Inst::VecCMov { rd, cond, ri, rm } => {
let rd = allocs.next_writable(rd);
let ri = allocs.next(ri);
debug_assert_eq!(rd.to_reg(), ri);
let rm = allocs.next(rm);
let opcode = 0xa74; // BCR
@@ -3097,20 +3208,49 @@ impl MachInstEmit for Inst {
};
put(sink, &enc_vri_a(opcode, rd.to_reg(), imm as u16, m3));
}
&Inst::VecLoadLane {
size,
rd,
ref mem,
lane_imm,
}
| &Inst::VecLoadLaneUndef {
size,
rd,
ri,
ref mem,
lane_imm,
}
| &Inst::VecLoadLaneRev {
size,
rd,
ri,
ref mem,
lane_imm,
} => {
let rd = allocs.next_writable(rd);
let ri = allocs.next(ri);
debug_assert_eq!(rd.to_reg(), ri);
let mem = mem.with_allocs(&mut allocs);
let opcode_vrx = match (self, size) {
(&Inst::VecLoadLane { .. }, 8) => 0xe700, // VLEB
(&Inst::VecLoadLane { .. }, 16) => 0xe701, // VLEH
(&Inst::VecLoadLane { .. }, 32) => 0xe703, // VLEF
(&Inst::VecLoadLane { .. }, 64) => 0xe702, // VLEG
(&Inst::VecLoadLaneRev { .. }, 16) => 0xe601, // VLEBRH
(&Inst::VecLoadLaneRev { .. }, 32) => 0xe603, // VLEBRF
(&Inst::VecLoadLaneRev { .. }, 64) => 0xe602, // VLEBRG
_ => unreachable!(),
};
let rd = rd.to_reg();
mem_vrx_emit(
rd,
&mem,
opcode_vrx,
lane_imm.into(),
true,
sink,
emit_info,
state,
);
}
&Inst::VecLoadLaneUndef {
size,
rd,
ref mem,
@@ -3126,17 +3266,10 @@ impl MachInstEmit for Inst {
let mem = mem.with_allocs(&mut allocs);
let (opcode_vrx, opcode_rx, opcode_rxy) = match (self, size) {
(&Inst::VecLoadLane { .. }, 8) => (0xe700, None, None), // VLEB
(&Inst::VecLoadLane { .. }, 16) => (0xe701, None, None), // VLEH
(&Inst::VecLoadLane { .. }, 32) => (0xe703, None, None), // VLEF
(&Inst::VecLoadLane { .. }, 64) => (0xe702, None, None), // VLEG
(&Inst::VecLoadLaneUndef { .. }, 8) => (0xe700, None, None), // VLEB
(&Inst::VecLoadLaneUndef { .. }, 16) => (0xe701, None, None), // VLEH
(&Inst::VecLoadLaneUndef { .. }, 32) => (0xe703, Some(0x78), Some(0xed64)), // VLEF, LE(Y)
(&Inst::VecLoadLaneUndef { .. }, 64) => (0xe702, Some(0x68), Some(0xed65)), // VLEG, LD(Y)
(&Inst::VecLoadLaneRev { .. }, 16) => (0xe601, None, None), // VLEBRH
(&Inst::VecLoadLaneRev { .. }, 32) => (0xe603, None, None), // VLEBRF
(&Inst::VecLoadLaneRev { .. }, 64) => (0xe602, None, None), // VLEBRG
(&Inst::VecLoadLaneRevUndef { .. }, 16) => (0xe601, None, None), // VLEBRH
(&Inst::VecLoadLaneRevUndef { .. }, 32) => (0xe603, None, None), // VLEBRF
(&Inst::VecLoadLaneRevUndef { .. }, 64) => (0xe602, None, None), // VLEBRG
@@ -3207,11 +3340,14 @@ impl MachInstEmit for Inst {
&Inst::VecInsertLane {
size,
rd,
ri,
rn,
lane_imm,
lane_reg,
} => {
let rd = allocs.next_writable(rd);
let ri = allocs.next(ri);
debug_assert_eq!(rd.to_reg(), ri);
let rn = allocs.next(rn);
let lane_reg = allocs.next(lane_reg);
@@ -3288,10 +3424,13 @@ impl MachInstEmit for Inst {
&Inst::VecInsertLaneImm {
size,
rd,
ri,
imm,
lane_imm,
} => {
let rd = allocs.next_writable(rd);
let ri = allocs.next(ri);
debug_assert_eq!(rd.to_reg(), ri);
let opcode = match size {
8 => 0xe740, // VLEIB

View File

@@ -2208,21 +2208,78 @@ fn test_s390x_binemit() {
"clgite %r7, 65535",
));
let w_regpair = WritableRegPair {
hi: writable_gpr(2),
lo: writable_gpr(3),
};
let regpair = RegPair {
hi: gpr(2),
lo: gpr(3),
};
insns.push((
Inst::SMulWide {
rd: w_regpair,
rn: gpr(5),
rm: gpr(6),
},
"B9EC6005",
"mgrk %r0, %r5, %r6",
"B9EC6025",
"mgrk %r2, %r5, %r6",
));
insns.push((
Inst::UMulWide {
rd: w_regpair,
ri: gpr(3),
rn: gpr(5),
},
"B9860025",
"mlgr %r2, %r5",
));
insns.push((
Inst::SDivMod32 {
rd: w_regpair,
ri: gpr(3),
rn: gpr(5),
},
"B91D0025",
"dsgfr %r2, %r5",
));
insns.push((
Inst::SDivMod64 {
rd: w_regpair,
ri: gpr(3),
rn: gpr(5),
},
"B90D0025",
"dsgr %r2, %r5",
));
insns.push((
Inst::UDivMod32 {
rd: w_regpair,
ri: regpair,
rn: gpr(5),
},
"B9970025",
"dlr %r2, %r5",
));
insns.push((
Inst::UDivMod64 {
rd: w_regpair,
ri: regpair,
rn: gpr(5),
},
"B9870025",
"dlgr %r2, %r5",
));
insns.push((Inst::UMulWide { rn: gpr(5) }, "B9860005", "mlgr %r0, %r5"));
insns.push((Inst::SDivMod32 { rn: gpr(5) }, "B91D0005", "dsgfr %r0, %r5"));
insns.push((Inst::SDivMod64 { rn: gpr(5) }, "B90D0005", "dsgr %r0, %r5"));
insns.push((Inst::UDivMod32 { rn: gpr(5) }, "B9970005", "dlr %r0, %r5"));
insns.push((Inst::UDivMod64 { rn: gpr(5) }, "B9870005", "dlgr %r0, %r5"));
insns.push((Inst::Flogr { rn: gpr(5) }, "B9830005", "flogr %r0, %r5"));
insns.push((
Inst::Flogr {
rd: w_regpair,
rn: gpr(5),
},
"B9830025",
"flogr %r2, %r5",
));
insns.push((
Inst::ShiftRR {
@@ -2581,6 +2638,7 @@ fn test_s390x_binemit() {
Inst::RxSBG {
op: RxSBGOp::Insert,
rd: writable_gpr(4),
ri: gpr(4),
rn: gpr(5),
start_bit: 8,
end_bit: 32,
@@ -2593,6 +2651,7 @@ fn test_s390x_binemit() {
Inst::RxSBG {
op: RxSBGOp::And,
rd: writable_gpr(4),
ri: gpr(4),
rn: gpr(5),
start_bit: 8,
end_bit: 32,
@@ -2605,6 +2664,7 @@ fn test_s390x_binemit() {
Inst::RxSBG {
op: RxSBGOp::Or,
rd: writable_gpr(4),
ri: gpr(4),
rn: gpr(5),
start_bit: 8,
end_bit: 32,
@@ -2617,6 +2677,7 @@ fn test_s390x_binemit() {
Inst::RxSBG {
op: RxSBGOp::Xor,
rd: writable_gpr(4),
ri: gpr(4),
rn: gpr(5),
start_bit: 8,
end_bit: 32,
@@ -3265,6 +3326,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::AtomicCas32 {
rd: writable_gpr(4),
ri: gpr(4),
rn: gpr(5),
mem: MemArg::BXD12 {
base: zero_reg(),
@@ -3279,6 +3341,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::AtomicCas32 {
rd: writable_gpr(4),
ri: gpr(4),
rn: gpr(5),
mem: MemArg::BXD12 {
base: zero_reg(),
@@ -3293,6 +3356,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::AtomicCas32 {
rd: writable_gpr(4),
ri: gpr(4),
rn: gpr(5),
mem: MemArg::BXD20 {
base: zero_reg(),
@@ -3307,6 +3371,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::AtomicCas32 {
rd: writable_gpr(4),
ri: gpr(4),
rn: gpr(5),
mem: MemArg::BXD20 {
base: zero_reg(),
@@ -3321,6 +3386,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::AtomicCas32 {
rd: writable_gpr(4),
ri: gpr(4),
rn: gpr(5),
mem: MemArg::BXD12 {
base: gpr(6),
@@ -3335,6 +3401,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::AtomicCas32 {
rd: writable_gpr(4),
ri: gpr(4),
rn: gpr(5),
mem: MemArg::BXD12 {
base: gpr(6),
@@ -3349,6 +3416,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::AtomicCas32 {
rd: writable_gpr(4),
ri: gpr(4),
rn: gpr(5),
mem: MemArg::BXD20 {
base: gpr(6),
@@ -3363,6 +3431,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::AtomicCas32 {
rd: writable_gpr(4),
ri: gpr(4),
rn: gpr(5),
mem: MemArg::BXD20 {
base: gpr(6),
@@ -3377,6 +3446,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::AtomicCas64 {
rd: writable_gpr(4),
ri: gpr(4),
rn: gpr(5),
mem: MemArg::BXD20 {
base: zero_reg(),
@@ -3391,6 +3461,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::AtomicCas64 {
rd: writable_gpr(4),
ri: gpr(4),
rn: gpr(5),
mem: MemArg::BXD20 {
base: zero_reg(),
@@ -3405,6 +3476,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::AtomicCas64 {
rd: writable_gpr(4),
ri: gpr(4),
rn: gpr(5),
mem: MemArg::BXD20 {
base: gpr(6),
@@ -3419,6 +3491,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::AtomicCas64 {
rd: writable_gpr(4),
ri: gpr(4),
rn: gpr(5),
mem: MemArg::BXD20 {
base: gpr(6),
@@ -6451,6 +6524,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::Insert64UImm16Shifted {
rd: writable_gpr(8),
ri: gpr(8),
imm: UImm16Shifted::maybe_from_u64(0x0000_0000_0000_ffff).unwrap(),
},
"A583FFFF",
@@ -6459,6 +6533,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::Insert64UImm16Shifted {
rd: writable_gpr(8),
ri: gpr(8),
imm: UImm16Shifted::maybe_from_u64(0x0000_0000_ffff_0000).unwrap(),
},
"A582FFFF",
@@ -6467,6 +6542,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::Insert64UImm16Shifted {
rd: writable_gpr(8),
ri: gpr(8),
imm: UImm16Shifted::maybe_from_u64(0x0000_ffff_0000_0000).unwrap(),
},
"A581FFFF",
@@ -6475,6 +6551,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::Insert64UImm16Shifted {
rd: writable_gpr(8),
ri: gpr(8),
imm: UImm16Shifted::maybe_from_u64(0xffff_0000_0000_0000).unwrap(),
},
"A580FFFF",
@@ -6483,6 +6560,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::Insert64UImm32Shifted {
rd: writable_gpr(8),
ri: gpr(8),
imm: UImm32Shifted::maybe_from_u64(0x0000_0000_ffff_ffff).unwrap(),
},
"C089FFFFFFFF",
@@ -6491,6 +6569,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::Insert64UImm32Shifted {
rd: writable_gpr(8),
ri: gpr(8),
imm: UImm32Shifted::maybe_from_u64(0xffff_ffff_0000_0000).unwrap(),
},
"C088FFFFFFFF",
@@ -6501,6 +6580,7 @@ fn test_s390x_binemit() {
Inst::CMov32 {
rd: writable_gpr(8),
cond: Cond::from_mask(1),
ri: gpr(8),
rm: gpr(9),
},
"B9F21089",
@@ -6510,6 +6590,7 @@ fn test_s390x_binemit() {
Inst::CMov64 {
rd: writable_gpr(8),
cond: Cond::from_mask(1),
ri: gpr(8),
rm: gpr(9),
},
"B9E21089",
@@ -6521,6 +6602,7 @@ fn test_s390x_binemit() {
rd: writable_gpr(8),
cond: Cond::from_mask(1),
imm: -32768,
ri: gpr(8),
},
"EC8180000042",
"lochio %r8, -32768",
@@ -6530,6 +6612,7 @@ fn test_s390x_binemit() {
rd: writable_gpr(8),
cond: Cond::from_mask(1),
imm: 32767,
ri: gpr(8),
},
"EC817FFF0042",
"lochio %r8, 32767",
@@ -6539,6 +6622,7 @@ fn test_s390x_binemit() {
rd: writable_gpr(8),
cond: Cond::from_mask(1),
imm: -32768,
ri: gpr(8),
},
"EC8180000046",
"locghio %r8, -32768",
@@ -6548,6 +6632,7 @@ fn test_s390x_binemit() {
rd: writable_gpr(8),
cond: Cond::from_mask(1),
imm: 32767,
ri: gpr(8),
},
"EC817FFF0046",
"locghio %r8, 32767",
@@ -6996,6 +7081,7 @@ fn test_s390x_binemit() {
},
Inst::AtomicCas32 {
rd: writable_gpr(4),
ri: gpr(4),
rn: gpr(5),
mem: MemArg::BXD12 {
base: gpr(6),
@@ -7046,6 +7132,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::FpuCMov32 {
rd: writable_vr(8),
ri: vr(8),
rm: vr(4),
cond: Cond::from_mask(1),
},
@@ -7055,6 +7142,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::FpuCMov32 {
rd: writable_vr(8),
ri: vr(8),
rm: vr(20),
cond: Cond::from_mask(1),
},
@@ -7064,6 +7152,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::FpuCMov64 {
rd: writable_vr(8),
ri: vr(8),
rm: vr(4),
cond: Cond::from_mask(1),
},
@@ -7073,6 +7162,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::FpuCMov64 {
rd: writable_vr(8),
ri: vr(8),
rm: vr(20),
cond: Cond::from_mask(1),
},
@@ -10851,6 +10941,7 @@ fn test_s390x_binemit() {
insns.push((
Inst::VecCMov {
rd: writable_vr(8),
ri: vr(8),
rm: vr(20),
cond: Cond::from_mask(1),
},
@@ -10982,6 +11073,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLane {
size: 8,
rd: writable_vr(17),
ri: vr(17),
mem: MemArg::BXD12 {
base: gpr(2),
index: zero_reg(),
@@ -10997,6 +11089,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLane {
size: 8,
rd: writable_vr(17),
ri: vr(17),
mem: MemArg::BXD12 {
base: gpr(2),
index: zero_reg(),
@@ -11012,6 +11105,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLane {
size: 8,
rd: writable_vr(17),
ri: vr(17),
mem: MemArg::BXD12 {
base: gpr(3),
index: gpr(2),
@@ -11027,6 +11121,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLane {
size: 8,
rd: writable_vr(17),
ri: vr(17),
mem: MemArg::BXD12 {
base: gpr(3),
index: gpr(2),
@@ -11042,6 +11137,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLane {
size: 16,
rd: writable_vr(17),
ri: vr(17),
mem: MemArg::BXD12 {
base: gpr(2),
index: zero_reg(),
@@ -11057,6 +11153,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLane {
size: 16,
rd: writable_vr(17),
ri: vr(17),
mem: MemArg::BXD12 {
base: gpr(2),
index: zero_reg(),
@@ -11072,6 +11169,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLane {
size: 16,
rd: writable_vr(17),
ri: vr(17),
mem: MemArg::BXD12 {
base: gpr(3),
index: gpr(2),
@@ -11087,6 +11185,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLane {
size: 16,
rd: writable_vr(17),
ri: vr(17),
mem: MemArg::BXD12 {
base: gpr(3),
index: gpr(2),
@@ -11102,6 +11201,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLane {
size: 32,
rd: writable_vr(17),
ri: vr(17),
mem: MemArg::BXD12 {
base: gpr(2),
index: zero_reg(),
@@ -11117,6 +11217,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLane {
size: 32,
rd: writable_vr(17),
ri: vr(17),
mem: MemArg::BXD12 {
base: gpr(2),
index: zero_reg(),
@@ -11132,6 +11233,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLane {
size: 32,
rd: writable_vr(17),
ri: vr(17),
mem: MemArg::BXD12 {
base: gpr(3),
index: gpr(2),
@@ -11147,6 +11249,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLane {
size: 32,
rd: writable_vr(17),
ri: vr(17),
mem: MemArg::BXD12 {
base: gpr(3),
index: gpr(2),
@@ -11162,6 +11265,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLane {
size: 64,
rd: writable_vr(17),
ri: vr(17),
mem: MemArg::BXD12 {
base: gpr(2),
index: zero_reg(),
@@ -11177,6 +11281,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLane {
size: 64,
rd: writable_vr(17),
ri: vr(17),
mem: MemArg::BXD12 {
base: gpr(2),
index: zero_reg(),
@@ -11192,6 +11297,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLane {
size: 64,
rd: writable_vr(17),
ri: vr(17),
mem: MemArg::BXD12 {
base: gpr(3),
index: gpr(2),
@@ -11207,6 +11313,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLane {
size: 64,
rd: writable_vr(17),
ri: vr(17),
mem: MemArg::BXD12 {
base: gpr(3),
index: gpr(2),
@@ -12062,6 +12169,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLaneRev {
size: 16,
rd: writable_vr(1),
ri: vr(1),
mem: MemArg::BXD12 {
base: gpr(2),
index: zero_reg(),
@@ -12077,6 +12185,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLaneRev {
size: 16,
rd: writable_vr(1),
ri: vr(1),
mem: MemArg::BXD12 {
base: gpr(2),
index: zero_reg(),
@@ -12092,6 +12201,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLaneRev {
size: 16,
rd: writable_vr(1),
ri: vr(1),
mem: MemArg::BXD12 {
base: gpr(3),
index: gpr(2),
@@ -12107,6 +12217,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLaneRev {
size: 16,
rd: writable_vr(1),
ri: vr(1),
mem: MemArg::BXD12 {
base: gpr(3),
index: gpr(2),
@@ -12122,6 +12233,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLaneRev {
size: 32,
rd: writable_vr(1),
ri: vr(1),
mem: MemArg::BXD12 {
base: gpr(2),
index: zero_reg(),
@@ -12137,6 +12249,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLaneRev {
size: 32,
rd: writable_vr(1),
ri: vr(1),
mem: MemArg::BXD12 {
base: gpr(2),
index: zero_reg(),
@@ -12152,6 +12265,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLaneRev {
size: 32,
rd: writable_vr(1),
ri: vr(1),
mem: MemArg::BXD12 {
base: gpr(3),
index: gpr(2),
@@ -12167,6 +12281,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLaneRev {
size: 32,
rd: writable_vr(1),
ri: vr(1),
mem: MemArg::BXD12 {
base: gpr(3),
index: gpr(2),
@@ -12182,6 +12297,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLaneRev {
size: 64,
rd: writable_vr(1),
ri: vr(1),
mem: MemArg::BXD12 {
base: gpr(2),
index: zero_reg(),
@@ -12197,6 +12313,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLaneRev {
size: 64,
rd: writable_vr(1),
ri: vr(1),
mem: MemArg::BXD12 {
base: gpr(2),
index: zero_reg(),
@@ -12212,6 +12329,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLaneRev {
size: 64,
rd: writable_vr(1),
ri: vr(1),
mem: MemArg::BXD12 {
base: gpr(3),
index: gpr(2),
@@ -12227,6 +12345,7 @@ fn test_s390x_binemit() {
Inst::VecLoadLaneRev {
size: 64,
rd: writable_vr(1),
ri: vr(1),
mem: MemArg::BXD12 {
base: gpr(3),
index: gpr(2),
@@ -12783,6 +12902,7 @@ fn test_s390x_binemit() {
Inst::VecInsertLane {
size: 8,
rd: writable_vr(8),
ri: vr(8),
rn: gpr(4),
lane_imm: 0,
lane_reg: zero_reg(),
@@ -12794,6 +12914,7 @@ fn test_s390x_binemit() {
Inst::VecInsertLane {
size: 8,
rd: writable_vr(8),
ri: vr(8),
rn: gpr(4),
lane_imm: 255,
lane_reg: zero_reg(),
@@ -12805,6 +12926,7 @@ fn test_s390x_binemit() {
Inst::VecInsertLane {
size: 8,
rd: writable_vr(24),
ri: vr(24),
rn: gpr(4),
lane_imm: 0,
lane_reg: gpr(3),
@@ -12816,6 +12938,7 @@ fn test_s390x_binemit() {
Inst::VecInsertLane {
size: 16,
rd: writable_vr(8),
ri: vr(8),
rn: gpr(4),
lane_imm: 0,
lane_reg: zero_reg(),
@@ -12827,6 +12950,7 @@ fn test_s390x_binemit() {
Inst::VecInsertLane {
size: 16,
rd: writable_vr(8),
ri: vr(8),
rn: gpr(4),
lane_imm: 255,
lane_reg: zero_reg(),
@@ -12838,6 +12962,7 @@ fn test_s390x_binemit() {
Inst::VecInsertLane {
size: 16,
rd: writable_vr(24),
ri: vr(24),
rn: gpr(4),
lane_imm: 0,
lane_reg: gpr(3),
@@ -12849,6 +12974,7 @@ fn test_s390x_binemit() {
Inst::VecInsertLane {
size: 32,
rd: writable_vr(8),
ri: vr(8),
rn: gpr(4),
lane_imm: 0,
lane_reg: zero_reg(),
@@ -12860,6 +12986,7 @@ fn test_s390x_binemit() {
Inst::VecInsertLane {
size: 32,
rd: writable_vr(8),
ri: vr(8),
rn: gpr(4),
lane_imm: 255,
lane_reg: zero_reg(),
@@ -12871,6 +12998,7 @@ fn test_s390x_binemit() {
Inst::VecInsertLane {
size: 32,
rd: writable_vr(24),
ri: vr(24),
rn: gpr(4),
lane_imm: 0,
lane_reg: gpr(3),
@@ -12882,6 +13010,7 @@ fn test_s390x_binemit() {
Inst::VecInsertLane {
size: 64,
rd: writable_vr(8),
ri: vr(8),
rn: gpr(4),
lane_imm: 0,
lane_reg: zero_reg(),
@@ -12893,6 +13022,7 @@ fn test_s390x_binemit() {
Inst::VecInsertLane {
size: 64,
rd: writable_vr(8),
ri: vr(8),
rn: gpr(4),
lane_imm: 255,
lane_reg: zero_reg(),
@@ -12904,6 +13034,7 @@ fn test_s390x_binemit() {
Inst::VecInsertLane {
size: 64,
rd: writable_vr(24),
ri: vr(24),
rn: gpr(4),
lane_imm: 0,
lane_reg: gpr(3),
@@ -13168,6 +13299,7 @@ fn test_s390x_binemit() {
Inst::VecInsertLaneImm {
size: 8,
rd: writable_vr(20),
ri: vr(20),
imm: 0x1234,
lane_imm: 15,
},
@@ -13178,6 +13310,7 @@ fn test_s390x_binemit() {
Inst::VecInsertLaneImm {
size: 16,
rd: writable_vr(20),
ri: vr(20),
imm: 0x1234,
lane_imm: 7,
},
@@ -13188,6 +13321,7 @@ fn test_s390x_binemit() {
Inst::VecInsertLaneImm {
size: 32,
rd: writable_vr(20),
ri: vr(20),
imm: 0x1234,
lane_imm: 3,
},
@@ -13198,6 +13332,7 @@ fn test_s390x_binemit() {
Inst::VecInsertLaneImm {
size: 64,
rd: writable_vr(20),
ri: vr(20),
imm: 0x1234,
lane_imm: 1,
},

View File

@@ -68,6 +68,29 @@ fn inst_size_test() {
assert_eq!(32, std::mem::size_of::<Inst>());
}
/// A register pair. Enum so it can be destructured in ISLE.
#[derive(Clone, Copy, Debug)]
pub struct RegPair {
pub hi: Reg,
pub lo: Reg,
}
/// A writable register pair. Enum so it can be destructured in ISLE.
#[derive(Clone, Copy, Debug)]
pub struct WritableRegPair {
pub hi: Writable<Reg>,
pub lo: Writable<Reg>,
}
impl WritableRegPair {
pub fn to_regpair(&self) -> RegPair {
RegPair {
hi: self.hi.to_reg(),
lo: self.lo.to_reg(),
}
}
}
/// Supported instruction sets
#[allow(non_camel_case_types)]
#[derive(Debug)]
@@ -342,10 +365,18 @@ impl Inst {
if let Some(imm) = UImm16Shifted::maybe_from_u64(lo) {
// 16-bit shifted immediate
insts.push(Inst::Insert64UImm16Shifted { rd, imm });
insts.push(Inst::Insert64UImm16Shifted {
rd,
ri: rd.to_reg(),
imm,
});
} else if let Some(imm) = UImm32Shifted::maybe_from_u64(lo) {
// 32-bit shifted immediate
insts.push(Inst::Insert64UImm32Shifted { rd, imm });
insts.push(Inst::Insert64UImm32Shifted {
rd,
ri: rd.to_reg(),
imm,
});
} else {
unreachable!();
}
@@ -508,31 +539,37 @@ fn s390x_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandC
collector.reg_reuse_def(rd, 1);
collector.reg_use(ri);
}
&Inst::SMulWide { rn, rm, .. } => {
&Inst::SMulWide { rd, rn, rm } => {
collector.reg_use(rn);
collector.reg_use(rm);
collector.reg_def(writable_gpr(0));
collector.reg_def(writable_gpr(1));
// FIXME: The pair is hard-coded as %r2/%r3 because regalloc cannot handle pairs. If
// that changes, all the hard-coded uses of %r2/%r3 can be changed.
collector.reg_fixed_def(rd.hi, gpr(2));
collector.reg_fixed_def(rd.lo, gpr(3));
}
&Inst::UMulWide { rn, .. } => {
&Inst::UMulWide { rd, ri, rn } => {
collector.reg_use(rn);
collector.reg_def(writable_gpr(0));
collector.reg_mod(writable_gpr(1));
collector.reg_fixed_def(rd.hi, gpr(2));
collector.reg_fixed_def(rd.lo, gpr(3));
collector.reg_fixed_use(ri, gpr(3));
}
&Inst::SDivMod32 { rn, .. } | &Inst::SDivMod64 { rn, .. } => {
&Inst::SDivMod32 { rd, ri, rn } | &Inst::SDivMod64 { rd, ri, rn } => {
collector.reg_use(rn);
collector.reg_def(writable_gpr(0));
collector.reg_mod(writable_gpr(1));
collector.reg_fixed_def(rd.hi, gpr(2));
collector.reg_fixed_def(rd.lo, gpr(3));
collector.reg_fixed_use(ri, gpr(3));
}
&Inst::UDivMod32 { rn, .. } | &Inst::UDivMod64 { rn, .. } => {
&Inst::UDivMod32 { rd, ri, rn } | &Inst::UDivMod64 { rd, ri, rn } => {
collector.reg_use(rn);
collector.reg_mod(writable_gpr(0));
collector.reg_mod(writable_gpr(1));
collector.reg_fixed_def(rd.hi, gpr(2));
collector.reg_fixed_def(rd.lo, gpr(3));
collector.reg_fixed_use(ri.hi, gpr(2));
collector.reg_fixed_use(ri.lo, gpr(3));
}
&Inst::Flogr { rn, .. } => {
&Inst::Flogr { rd, rn } => {
collector.reg_use(rn);
collector.reg_def(writable_gpr(0));
collector.reg_def(writable_gpr(1));
collector.reg_fixed_def(rd.hi, gpr(2));
collector.reg_fixed_def(rd.lo, gpr(3));
}
&Inst::ShiftRR {
rd, rn, shift_reg, ..
@@ -543,8 +580,9 @@ fn s390x_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandC
collector.reg_use(shift_reg);
}
}
&Inst::RxSBG { rd, rn, .. } => {
collector.reg_mod(rd);
&Inst::RxSBG { rd, ri, rn, .. } => {
collector.reg_reuse_def(rd, 1);
collector.reg_use(ri);
collector.reg_use(rn);
}
&Inst::RxSBGTest { rd, rn, .. } => {
@@ -590,12 +628,21 @@ fn s390x_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandC
memarg_operands(mem, collector);
}
&Inst::AtomicCas32 {
rd, rn, ref mem, ..
rd,
ri,
rn,
ref mem,
..
}
| &Inst::AtomicCas64 {
rd, rn, ref mem, ..
rd,
ri,
rn,
ref mem,
..
} => {
collector.reg_mod(rd);
collector.reg_reuse_def(rd, 1);
collector.reg_use(ri);
collector.reg_use(rn);
memarg_operands(mem, collector);
}
@@ -681,28 +728,34 @@ fn s390x_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandC
| &Inst::Mov64UImm32Shifted { rd, .. } => {
collector.reg_def(rd);
}
&Inst::CMov32 { rd, rm, .. } | &Inst::CMov64 { rd, rm, .. } => {
collector.reg_mod(rd);
&Inst::CMov32 { rd, ri, rm, .. } | &Inst::CMov64 { rd, ri, rm, .. } => {
collector.reg_reuse_def(rd, 1);
collector.reg_use(ri);
collector.reg_use(rm);
}
&Inst::CMov32SImm16 { rd, .. } | &Inst::CMov64SImm16 { rd, .. } => {
collector.reg_mod(rd);
&Inst::CMov32SImm16 { rd, ri, .. } | &Inst::CMov64SImm16 { rd, ri, .. } => {
collector.reg_reuse_def(rd, 1);
collector.reg_use(ri);
}
&Inst::Insert64UImm16Shifted { rd, .. } | &Inst::Insert64UImm32Shifted { rd, .. } => {
collector.reg_mod(rd);
&Inst::Insert64UImm16Shifted { rd, ri, .. }
| &Inst::Insert64UImm32Shifted { rd, ri, .. } => {
collector.reg_reuse_def(rd, 1);
collector.reg_use(ri);
}
&Inst::LoadAR { rd, .. } => {
collector.reg_def(rd);
}
&Inst::InsertAR { rd, .. } => {
collector.reg_mod(rd);
&Inst::InsertAR { rd, ri, .. } => {
collector.reg_reuse_def(rd, 1);
collector.reg_use(ri);
}
&Inst::FpuMove32 { rd, rn } | &Inst::FpuMove64 { rd, rn } => {
collector.reg_def(rd);
collector.reg_use(rn);
}
&Inst::FpuCMov32 { rd, rm, .. } | &Inst::FpuCMov64 { rd, rm, .. } => {
collector.reg_mod(rd);
&Inst::FpuCMov32 { rd, ri, rm, .. } | &Inst::FpuCMov64 { rd, ri, rm, .. } => {
collector.reg_reuse_def(rd, 1);
collector.reg_use(ri);
collector.reg_use(rm);
}
&Inst::FpuRR { rd, rn, .. } => {
@@ -858,8 +911,9 @@ fn s390x_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandC
collector.reg_def(rd);
collector.reg_use(rn);
}
&Inst::VecCMov { rd, rm, .. } => {
collector.reg_mod(rd);
&Inst::VecCMov { rd, ri, rm, .. } => {
collector.reg_reuse_def(rd, 1);
collector.reg_use(ri);
collector.reg_use(rm);
}
&Inst::MovToVec128 { rd, rn, rm } => {
@@ -880,8 +934,11 @@ fn s390x_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandC
&Inst::VecImmReplicate { rd, .. } => {
collector.reg_def(rd);
}
&Inst::VecLoadLane { rd, ref mem, .. } => {
collector.reg_mod(rd);
&Inst::VecLoadLane {
rd, ri, ref mem, ..
} => {
collector.reg_reuse_def(rd, 1);
collector.reg_use(ri);
memarg_operands(mem, collector);
}
&Inst::VecLoadLaneUndef { rd, ref mem, .. } => {
@@ -900,14 +957,22 @@ fn s390x_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandC
collector.reg_use(rd);
memarg_operands(mem, collector);
}
&Inst::VecLoadLaneRev { rd, ref mem, .. } => {
collector.reg_mod(rd);
&Inst::VecLoadLaneRev {
rd, ri, ref mem, ..
} => {
collector.reg_reuse_def(rd, 1);
collector.reg_use(ri);
memarg_operands(mem, collector);
}
&Inst::VecInsertLane {
rd, rn, lane_reg, ..
rd,
ri,
rn,
lane_reg,
..
} => {
collector.reg_mod(rd);
collector.reg_reuse_def(rd, 1);
collector.reg_use(ri);
collector.reg_use(rn);
collector.reg_use(lane_reg);
}
@@ -925,8 +990,9 @@ fn s390x_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandC
collector.reg_use(rn);
collector.reg_use(lane_reg);
}
&Inst::VecInsertLaneImm { rd, .. } => {
collector.reg_def(rd);
&Inst::VecInsertLaneImm { rd, ri, .. } => {
collector.reg_reuse_def(rd, 1);
collector.reg_use(ri);
}
&Inst::VecReplicateLane { rd, rn, .. } => {
collector.reg_def(rd);
@@ -1470,54 +1536,47 @@ impl Inst {
let rd = pretty_print_reg_mod(rd, ri, allocs);
format!("{} {}, {}", op, rd, imm.bits)
}
&Inst::SMulWide { rn, rm } => {
&Inst::SMulWide { rd, rn, rm } => {
let op = "mgrk";
let rn = pretty_print_reg(rn, allocs);
let rm = pretty_print_reg(rm, allocs);
let rd = pretty_print_reg(gpr(0), allocs);
let _r1 = allocs.next(gpr(1));
let rd = pretty_print_regpair(rd.to_regpair(), allocs);
format!("{} {}, {}, {}", op, rd, rn, rm)
}
&Inst::UMulWide { rn } => {
&Inst::UMulWide { rd, ri, rn } => {
let op = "mlgr";
let rn = pretty_print_reg(rn, allocs);
let rd = pretty_print_reg(gpr(0), allocs);
let _r1 = allocs.next(gpr(1));
let rd = pretty_print_regpair_mod_lo(rd, ri, allocs);
format!("{} {}, {}", op, rd, rn)
}
&Inst::SDivMod32 { rn, .. } => {
&Inst::SDivMod32 { rd, ri, rn } => {
let op = "dsgfr";
let rn = pretty_print_reg(rn, allocs);
let rd = pretty_print_reg(gpr(0), allocs);
let _r1 = allocs.next(gpr(1));
let rd = pretty_print_regpair_mod_lo(rd, ri, allocs);
format!("{} {}, {}", op, rd, rn)
}
&Inst::SDivMod64 { rn, .. } => {
&Inst::SDivMod64 { rd, ri, rn } => {
let op = "dsgr";
let rn = pretty_print_reg(rn, allocs);
let rd = pretty_print_reg(gpr(0), allocs);
let _r1 = allocs.next(gpr(1));
let rd = pretty_print_regpair_mod_lo(rd, ri, allocs);
format!("{} {}, {}", op, rd, rn)
}
&Inst::UDivMod32 { rn, .. } => {
&Inst::UDivMod32 { rd, ri, rn } => {
let op = "dlr";
let rn = pretty_print_reg(rn, allocs);
let rd = pretty_print_reg(gpr(0), allocs);
let _r1 = allocs.next(gpr(1));
let rd = pretty_print_regpair_mod(rd, ri, allocs);
format!("{} {}, {}", op, rd, rn)
}
&Inst::UDivMod64 { rn, .. } => {
&Inst::UDivMod64 { rd, ri, rn } => {
let op = "dlgr";
let rn = pretty_print_reg(rn, allocs);
let rd = pretty_print_reg(gpr(0), allocs);
let _r1 = allocs.next(gpr(1));
let rd = pretty_print_regpair_mod(rd, ri, allocs);
format!("{} {}, {}", op, rd, rn)
}
&Inst::Flogr { rn } => {
&Inst::Flogr { rd, rn } => {
let op = "flogr";
let rn = pretty_print_reg(rn, allocs);
let rd = pretty_print_reg(gpr(0), allocs);
let _r1 = allocs.next(gpr(1));
let rd = pretty_print_regpair(rd.to_regpair(), allocs);
format!("{} {}, {}", op, rd, rn)
}
&Inst::ShiftRR {
@@ -1549,6 +1608,7 @@ impl Inst {
&Inst::RxSBG {
op,
rd,
ri,
rn,
start_bit,
end_bit,
@@ -1560,7 +1620,7 @@ impl Inst {
RxSBGOp::Or => "rosbg",
RxSBGOp::Xor => "rxsbg",
};
let rd = pretty_print_reg(rd.to_reg(), allocs);
let rd = pretty_print_reg_mod(rd, ri, allocs);
let rn = pretty_print_reg(rn, allocs);
format!(
"{} {}, {}, {}, {}, {}",
@@ -1769,14 +1829,25 @@ impl Inst {
let mem = mem.pretty_print_default();
format!("{}{} {}, {}, {}", mem_str, op, rd, rn, mem)
}
&Inst::AtomicCas32 { rd, rn, ref mem } | &Inst::AtomicCas64 { rd, rn, ref mem } => {
&Inst::AtomicCas32 {
rd,
ri,
rn,
ref mem,
}
| &Inst::AtomicCas64 {
rd,
ri,
rn,
ref mem,
} => {
let (opcode_rs, opcode_rsy) = match self {
&Inst::AtomicCas32 { .. } => (Some("cs"), Some("csy")),
&Inst::AtomicCas64 { .. } => (None, Some("csg")),
_ => unreachable!(),
};
let rd = pretty_print_reg(rd.to_reg(), allocs);
let rd = pretty_print_reg_mod(rd, ri, allocs);
let rn = pretty_print_reg(rn, allocs);
let mem = mem.with_allocs(allocs);
let (mem_str, mem) = mem_finalize_for_show(
@@ -2047,8 +2118,8 @@ impl Inst {
};
format!("{} {}, {}", op, rd, imm.bits)
}
&Inst::Insert64UImm16Shifted { rd, ref imm } => {
let rd = pretty_print_reg(rd.to_reg(), allocs);
&Inst::Insert64UImm16Shifted { rd, ri, ref imm } => {
let rd = pretty_print_reg_mod(rd, ri, allocs);
let op = match imm.shift {
0 => "iill",
1 => "iilh",
@@ -2058,8 +2129,8 @@ impl Inst {
};
format!("{} {}, {}", op, rd, imm.bits)
}
&Inst::Insert64UImm32Shifted { rd, ref imm } => {
let rd = pretty_print_reg(rd.to_reg(), allocs);
&Inst::Insert64UImm32Shifted { rd, ri, ref imm } => {
let rd = pretty_print_reg_mod(rd, ri, allocs);
let op = match imm.shift {
0 => "iilf",
1 => "iihf",
@@ -2067,29 +2138,43 @@ impl Inst {
};
format!("{} {}, {}", op, rd, imm.bits)
}
&Inst::LoadAR { rd, ar } | &Inst::InsertAR { rd, ar } => {
&Inst::LoadAR { rd, ar } => {
let rd = pretty_print_reg(rd.to_reg(), allocs);
format!("ear {}, %a{}", rd, ar)
}
&Inst::CMov32 { rd, cond, rm } => {
let rd = pretty_print_reg(rd.to_reg(), allocs);
&Inst::InsertAR { rd, ri, ar } => {
let rd = pretty_print_reg_mod(rd, ri, allocs);
format!("ear {}, %a{}", rd, ar)
}
&Inst::CMov32 { rd, cond, ri, rm } => {
let rd = pretty_print_reg_mod(rd, ri, allocs);
let rm = pretty_print_reg(rm, allocs);
let cond = cond.pretty_print_default();
format!("locr{} {}, {}", cond, rd, rm)
}
&Inst::CMov64 { rd, cond, rm } => {
let rd = pretty_print_reg(rd.to_reg(), allocs);
&Inst::CMov64 { rd, cond, ri, rm } => {
let rd = pretty_print_reg_mod(rd, ri, allocs);
let rm = pretty_print_reg(rm, allocs);
let cond = cond.pretty_print_default();
format!("locgr{} {}, {}", cond, rd, rm)
}
&Inst::CMov32SImm16 { rd, cond, ref imm } => {
let rd = pretty_print_reg(rd.to_reg(), allocs);
&Inst::CMov32SImm16 {
rd,
cond,
ri,
ref imm,
} => {
let rd = pretty_print_reg_mod(rd, ri, allocs);
let cond = cond.pretty_print_default();
format!("lochi{} {}, {}", cond, rd, imm)
}
&Inst::CMov64SImm16 { rd, cond, ref imm } => {
let rd = pretty_print_reg(rd.to_reg(), allocs);
&Inst::CMov64SImm16 {
rd,
cond,
ri,
ref imm,
} => {
let rd = pretty_print_reg_mod(rd, ri, allocs);
let cond = cond.pretty_print_default();
format!("locghi{} {}, {}", cond, rd, imm)
}
@@ -2111,8 +2196,9 @@ impl Inst {
format!("vlr {}, {}", rd, rn)
}
}
&Inst::FpuCMov32 { rd, cond, rm } => {
&Inst::FpuCMov32 { rd, cond, ri, rm } => {
let (rd, rd_fpr) = pretty_print_fpr(rd.to_reg(), allocs);
let _ri = allocs.next(ri);
let (rm, rm_fpr) = pretty_print_fpr(rm, allocs);
if rd_fpr.is_some() && rm_fpr.is_some() {
let cond = cond.invert().pretty_print_default();
@@ -2122,8 +2208,9 @@ impl Inst {
format!("j{} 10 ; vlr {}, {}", cond, rd, rm)
}
}
&Inst::FpuCMov64 { rd, cond, rm } => {
&Inst::FpuCMov64 { rd, cond, ri, rm } => {
let (rd, rd_fpr) = pretty_print_fpr(rd.to_reg(), allocs);
let _ri = allocs.next(ri);
let (rm, rm_fpr) = pretty_print_fpr(rm, allocs);
if rd_fpr.is_some() && rm_fpr.is_some() {
let cond = cond.invert().pretty_print_default();
@@ -2753,8 +2840,8 @@ impl Inst {
let rn = pretty_print_reg(rn, allocs);
format!("vlr {}, {}", rd, rn)
}
&Inst::VecCMov { rd, cond, rm } => {
let rd = pretty_print_reg(rd.to_reg(), allocs);
&Inst::VecCMov { rd, cond, ri, rm } => {
let rd = pretty_print_reg_mod(rd, ri, allocs);
let rm = pretty_print_reg(rm, allocs);
let cond = cond.invert().pretty_print_default();
format!("j{} 10 ; vlr {}, {}", cond, rd, rm)
@@ -2830,16 +2917,46 @@ impl Inst {
&Inst::VecLoadLane {
size,
rd,
ri,
ref mem,
lane_imm,
}
| &Inst::VecLoadLaneRev {
size,
rd,
ri,
ref mem,
lane_imm,
} => {
let opcode_vrx = match (self, size) {
(&Inst::VecLoadLane { .. }, 8) => "vleb",
(&Inst::VecLoadLane { .. }, 16) => "vleh",
(&Inst::VecLoadLane { .. }, 32) => "vlef",
(&Inst::VecLoadLane { .. }, 64) => "vleg",
(&Inst::VecLoadLaneRev { .. }, 16) => "vlebrh",
(&Inst::VecLoadLaneRev { .. }, 32) => "vlebrf",
(&Inst::VecLoadLaneRev { .. }, 64) => "vlebrg",
_ => unreachable!(),
};
let (rd, _) = pretty_print_fpr(rd.to_reg(), allocs);
let _ri = allocs.next(ri);
let mem = mem.with_allocs(allocs);
let (mem_str, mem) = mem_finalize_for_show(
&mem,
state,
MemInstType {
have_d12: true,
have_d20: false,
have_pcrel: false,
have_unaligned_pcrel: false,
have_index: true,
},
);
let mem = mem.pretty_print_default();
format!("{}{} {}, {}, {}", mem_str, opcode_vrx, rd, mem, lane_imm)
}
| &Inst::VecLoadLaneUndef {
&Inst::VecLoadLaneUndef {
size,
rd,
ref mem,
@@ -2852,13 +2969,6 @@ impl Inst {
lane_imm,
} => {
let (opcode_vrx, opcode_rx, opcode_rxy) = match (self, size) {
(&Inst::VecLoadLane { .. }, 8) => ("vleb", None, None),
(&Inst::VecLoadLane { .. }, 16) => ("vleh", None, None),
(&Inst::VecLoadLane { .. }, 32) => ("vlef", None, None),
(&Inst::VecLoadLane { .. }, 64) => ("vleg", None, None),
(&Inst::VecLoadLaneRev { .. }, 16) => ("vlebrh", None, None),
(&Inst::VecLoadLaneRev { .. }, 32) => ("vlebrf", None, None),
(&Inst::VecLoadLaneRev { .. }, 64) => ("vlebrg", None, None),
(&Inst::VecLoadLaneUndef { .. }, 8) => ("vleb", None, None),
(&Inst::VecLoadLaneUndef { .. }, 16) => ("vleh", None, None),
(&Inst::VecLoadLaneUndef { .. }, 32) => ("vlef", Some("le"), Some("ley")),
@@ -2969,6 +3079,7 @@ impl Inst {
&Inst::VecInsertLane {
size,
rd,
ri,
rn,
lane_imm,
lane_reg,
@@ -2980,7 +3091,7 @@ impl Inst {
64 => "vlvgg",
_ => unreachable!(),
};
let rd = pretty_print_reg(rd.to_reg(), allocs);
let rd = pretty_print_reg_mod(rd, ri, allocs);
let rn = pretty_print_reg(rn, allocs);
let lane_reg = if lane_reg != zero_reg() {
format!("({})", pretty_print_reg(lane_reg, allocs))
@@ -3048,6 +3159,7 @@ impl Inst {
&Inst::VecInsertLaneImm {
size,
rd,
ri,
imm,
lane_imm,
} => {
@@ -3058,7 +3170,7 @@ impl Inst {
64 => "vleig",
_ => unreachable!(),
};
let rd = pretty_print_reg(rd.to_reg(), allocs);
let rd = pretty_print_reg_mod(rd, ri, allocs);
format!("{} {}, {}, {}", op, rd, imm, lane_imm)
}
&Inst::VecReplicateLane {

View File

@@ -5,6 +5,7 @@ use regalloc2::MachineEnv;
use regalloc2::PReg;
use regalloc2::VReg;
use crate::isa::s390x::inst::{RegPair, WritableRegPair};
use crate::machinst::*;
use crate::settings;
@@ -178,6 +179,24 @@ pub fn pretty_print_reg(reg: Reg, allocs: &mut AllocationConsumer<'_>) -> String
show_reg(reg)
}
pub fn pretty_print_regpair(pair: RegPair, allocs: &mut AllocationConsumer<'_>) -> String {
let hi = allocs.next(pair.hi);
let lo = allocs.next(pair.lo);
if let Some(hi_reg) = hi.to_real_reg() {
if let Some(lo_reg) = lo.to_real_reg() {
assert!(
hi_reg.hw_enc() + 1 == lo_reg.hw_enc(),
"Invalid regpair: {} {}",
show_reg(hi),
show_reg(lo)
);
return show_reg(hi);
}
}
format!("{}/{}", show_reg(hi), show_reg(lo))
}
pub fn pretty_print_reg_mod(
rd: Writable<Reg>,
ri: Reg,
@@ -192,6 +211,48 @@ pub fn pretty_print_reg_mod(
}
}
pub fn pretty_print_regpair_mod(
rd: WritableRegPair,
ri: RegPair,
allocs: &mut AllocationConsumer<'_>,
) -> String {
let rd_hi = allocs.next(rd.hi.to_reg());
let rd_lo = allocs.next(rd.lo.to_reg());
let ri_hi = allocs.next(ri.hi);
let ri_lo = allocs.next(ri.lo);
if rd_hi == ri_hi {
show_reg(rd_hi)
} else {
format!(
"{}/{}<-{}/{}",
show_reg(rd_hi),
show_reg(rd_lo),
show_reg(ri_hi),
show_reg(ri_lo)
)
}
}
pub fn pretty_print_regpair_mod_lo(
rd: WritableRegPair,
ri: Reg,
allocs: &mut AllocationConsumer<'_>,
) -> String {
let rd_hi = allocs.next(rd.hi.to_reg());
let rd_lo = allocs.next(rd.lo.to_reg());
let ri = allocs.next(ri);
if rd_lo == ri {
show_reg(rd_hi)
} else {
format!(
"{}/{}<-_/{}",
show_reg(rd_hi),
show_reg(rd_lo),
show_reg(ri),
)
}
}
pub fn pretty_print_fpr(reg: Reg, allocs: &mut AllocationConsumer<'_>) -> (String, Option<String>) {
let reg = allocs.next(reg);
(show_reg(reg), maybe_show_fpr(reg))