s390x: Improved TrapIf implementation (#6079)

Following up on the discussion in
https://github.com/bytecodealliance/wasmtime/pull/6011
this adds an improved implementation of TrapIf for s390x
using a single conditional branch instruction.

If the trap conditions is true, we branch into the middle of
the branch instruction - those middle two bytes are zero,
which matches the encoding of the trap instruction.

In addition, show the trap code for Trap and TrapIf
instructions in assembler output.
This commit is contained in:
Ulrich Weigand
2023-03-23 15:50:43 +01:00
committed by GitHub
parent a6925c21c5
commit 6f66abd5c7
64 changed files with 357 additions and 451 deletions

View File

@@ -682,6 +682,7 @@ fn enc_ril_b(opcode: u16, r1: Reg, ri2: u32) -> [u8; 6] {
let opcode1 = ((opcode >> 4) & 0xff) as u8;
let opcode2 = (opcode & 0xf) as u8;
let r1 = machreg_to_gpr(r1) & 0x0f;
let ri2 = ri2 >> 1;
enc[0] = opcode1;
enc[1] = r1 << 4 | opcode2;
@@ -700,6 +701,7 @@ fn enc_ril_c(opcode: u16, m1: u8, ri2: u32) -> [u8; 6] {
let opcode1 = ((opcode >> 4) & 0xff) as u8;
let opcode2 = (opcode & 0xf) as u8;
let m1 = m1 & 0x0f;
let ri2 = ri2 >> 1;
enc[0] = opcode1;
enc[1] = m1 << 4 | opcode2;
@@ -3590,14 +3592,19 @@ impl Inst {
put_with_trap(sink, &enc_e(0x0000), trap_code);
}
&Inst::TrapIf { cond, trap_code } => {
// Branch over trap if condition is false.
let opcode = 0xa74; // BCR
put(sink, &enc_ri_c(opcode, cond.invert().bits(), 4 + 2));
// Now emit the actual trap.
if let Some(s) = state.take_stack_map() {
sink.add_stack_map(StackMapExtent::UpcomingBytes(2), s);
sink.add_stack_map(StackMapExtent::UpcomingBytes(6), s);
}
put_with_trap(sink, &enc_e(0x0000), trap_code);
// We implement a TrapIf as a conditional branch into the middle
// of the branch (BRCL) instruction itself - those middle two bytes
// are zero, which matches the trap instruction itself.
let opcode = 0xc04; // BCRL
let enc = &enc_ril_c(opcode, cond.bits(), 2);
debug_assert!(enc.len() == 6 && enc[2] == 0 && enc[3] == 0);
// The trap must be placed on the last byte of the embedded trap
// instruction, so we need to emit the encoding in two parts.
put_with_trap(sink, &enc[0..4], trap_code);
put(sink, &enc[4..6]);
}
&Inst::JTSequence { ridx, ref targets } => {
let ridx = allocs.next(ridx);

View File

@@ -7027,22 +7027,22 @@ fn test_s390x_binemit() {
"br %r14",
));
insns.push((Inst::Debugtrap, "0001", "debugtrap"));
insns.push((Inst::Debugtrap, "0001", ".word 0x0001 # debugtrap"));
insns.push((
Inst::Trap {
trap_code: TrapCode::StackOverflow,
},
"0000",
"trap",
".word 0x0000 # trap=stk_ovf",
));
insns.push((
Inst::TrapIf {
cond: Cond::from_mask(1),
trap_code: TrapCode::StackOverflow,
},
"A7E400030000",
"jno 6 ; trap",
"C01400000001",
"jgo .+2 # trap=stk_ovf",
));
insns.push((

View File

@@ -3185,11 +3185,13 @@ impl Inst {
let cond = cond.pretty_print_default();
format!("jg{} {}", cond, target)
}
&Inst::Debugtrap => "debugtrap".to_string(),
&Inst::Trap { .. } => "trap".to_string(),
&Inst::TrapIf { cond, .. } => {
let cond = cond.invert().pretty_print_default();
format!("j{} 6 ; trap", cond)
&Inst::Debugtrap => ".word 0x0001 # debugtrap".to_string(),
&Inst::Trap { trap_code } => {
format!(".word 0x0000 # trap={}", trap_code)
}
&Inst::TrapIf { cond, trap_code } => {
let cond = cond.pretty_print_default();
format!("jg{} .+2 # trap={}", cond, trap_code)
}
&Inst::JTSequence { ridx, ref targets } => {
let ridx = pretty_print_reg(ridx, allocs);