Skip to content

Commit

Permalink
s390x: Improved TrapIf implementation
Browse files Browse the repository at this point in the history
Following up on the discussion in
bytecodealliance#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.
  • Loading branch information
uweigand committed Mar 21, 2023
1 parent 861220c commit ed14bcb
Show file tree
Hide file tree
Showing 14 changed files with 238 additions and 335 deletions.
18 changes: 12 additions & 6 deletions cranelift/codegen/src/isa/s390x/inst/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -3590,14 +3592,18 @@ 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);
// 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);
Expand Down
4 changes: 2 additions & 2 deletions cranelift/codegen/src/isa/s390x/inst/emit_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7041,8 +7041,8 @@ fn test_s390x_binemit() {
cond: Cond::from_mask(1),
trap_code: TrapCode::StackOverflow,
},
"A7E400030000",
"jno 6 ; trap",
"C01400000001",
"jgo .+2",
));

insns.push((
Expand Down
4 changes: 2 additions & 2 deletions cranelift/codegen/src/isa/s390x/inst/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3188,8 +3188,8 @@ impl Inst {
&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)
let cond = cond.pretty_print_default();
format!("jg{} .+2", cond)
}
&Inst::JTSequence { ridx, ref targets } => {
let ridx = pretty_print_reg(ridx, allocs);
Expand Down
Loading

0 comments on commit ed14bcb

Please sign in to comment.