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:
@@ -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);
|
||||
|
||||
@@ -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((
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user