Use EBB offsets for encoding RISC-V branches.

Stop emitting EBB relocations. Use the offsets computed by
relax_branches() to encode the correct displacements immediately.
This commit is contained in:
Jakob Stoklund Olesen
2017-04-06 11:18:38 -07:00
parent e56482d0fd
commit 1440b673fc
2 changed files with 49 additions and 20 deletions

View File

@@ -80,23 +80,40 @@ ebb0:
; Control Transfer Instructions ; Control Transfer Instructions
ebb1: ebb1:
; beq ; beq 0x000
br_icmp eq, v1, v2, ebb0 ; bin: Branch(ebb0) 01550063 br_icmp eq, v1, v2, ebb1 ; bin: 01550063
; bne ; bne 0xffc
br_icmp ne, v1, v2, ebb0 ; bin: Branch(ebb0) 01551063 br_icmp ne, v1, v2, ebb1 ; bin: ff551ee3
; blt ; blt 0xff8
br_icmp slt, v1, v2, ebb0 ; bin: Branch(ebb0) 01554063 br_icmp slt, v1, v2, ebb1 ; bin: ff554ce3
; bge ; bge 0xff4
br_icmp sge, v1, v2, ebb0 ; bin: Branch(ebb0) 01555063 br_icmp sge, v1, v2, ebb1 ; bin: ff555ae3
; bltu ; bltu 0xff0
br_icmp ult, v1, v2, ebb0 ; bin: Branch(ebb0) 01556063 br_icmp ult, v1, v2, ebb1 ; bin: ff5568e3
; bgeu ; bgeu 0xfec
br_icmp uge, v1, v2, ebb0 ; bin: Branch(ebb0) 01557063 br_icmp uge, v1, v2, ebb1 ; bin: ff5576e3
; Forward branches.
; beq 0x018
br_icmp eq, v2, v1, ebb2 ; bin: 00aa8c63
; bne 0x014
br_icmp ne, v2, v1, ebb2 ; bin: 00aa9a63
; blt 0x010
br_icmp slt, v2, v1, ebb2 ; bin: 00aac863
; bge 0x00c
br_icmp sge, v2, v1, ebb2 ; bin: 00aad663
; bltu 0x008
br_icmp ult, v2, v1, ebb2 ; bin: 00aae463
; bgeu 0x004
br_icmp uge, v2, v1, ebb2 ; bin: 00aaf263
jump ebb2
ebb2:
; beq x, %x0 ; beq x, %x0
brz v1, ebb0 ; bin: Branch(ebb0) 00050063 brz v1, ebb2 ; bin: 00050063
; bne x, %x0 ; bne x, %x0
brnz v1, ebb0 ; bin: Branch(ebb0) 00051063 brnz v1, ebb2 ; bin: fe051ee3
return return
} }

View File

@@ -3,10 +3,12 @@
use binemit::{CodeSink, Reloc, bad_encoding}; use binemit::{CodeSink, Reloc, bad_encoding};
use ir::{Function, Inst, InstructionData}; use ir::{Function, Inst, InstructionData};
use isa::RegUnit; use isa::RegUnit;
use predicates::is_signed_int;
include!(concat!(env!("OUT_DIR"), "/binemit-riscv.rs")); include!(concat!(env!("OUT_DIR"), "/binemit-riscv.rs"));
/// RISC-V relocation kinds. /// RISC-V relocation kinds.
#[allow(dead_code)]
pub enum RelocKind { pub enum RelocKind {
/// A conditional (SB-type) branch to an EBB. /// A conditional (SB-type) branch to an EBB.
Branch, Branch,
@@ -213,17 +215,17 @@ fn recipe_u<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS) {
/// imm rs2 rs1 funct3 imm opcode /// imm rs2 rs1 funct3 imm opcode
/// 25 20 15 12 7 0 /// 25 20 15 12 7 0
/// ///
/// The imm bits are not encoded by this function. They encode the relative distance to the
/// destination block, handled by a relocation.
///
/// Encoding bits: `opcode[6:2] | (funct3 << 5)` /// Encoding bits: `opcode[6:2] | (funct3 << 5)`
fn put_sb<CS: CodeSink + ?Sized>(bits: u16, rs1: RegUnit, rs2: RegUnit, sink: &mut CS) { fn put_sb<CS: CodeSink + ?Sized>(bits: u16, imm: i64, rs1: RegUnit, rs2: RegUnit, sink: &mut CS) {
let bits = bits as u32; let bits = bits as u32;
let opcode5 = bits & 0x1f; let opcode5 = bits & 0x1f;
let funct3 = (bits >> 5) & 0x7; let funct3 = (bits >> 5) & 0x7;
let rs1 = rs1 as u32 & 0x1f; let rs1 = rs1 as u32 & 0x1f;
let rs2 = rs2 as u32 & 0x1f; let rs2 = rs2 as u32 & 0x1f;
assert!(is_signed_int(imm, 13, 1), "SB out of range {:#x}", imm);
let imm = imm as u32;
// 0-6: opcode // 0-6: opcode
let mut i = 0x3; let mut i = 0x3;
i |= opcode5 << 2; i |= opcode5 << 2;
@@ -231,6 +233,12 @@ fn put_sb<CS: CodeSink + ?Sized>(bits: u16, rs1: RegUnit, rs2: RegUnit, sink: &m
i |= rs1 << 15; i |= rs1 << 15;
i |= rs2 << 20; i |= rs2 << 20;
// The displacement is completely hashed up.
i |= ((imm >> 11) & 0x1) << 7;
i |= ((imm >> 1) & 0xf) << 8;
i |= ((imm >> 5) & 0x3f) << 25;
i |= ((imm >> 12) & 0x1) << 31;
sink.put4(i); sink.put4(i);
} }
@@ -240,9 +248,11 @@ fn recipe_sb<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS)
ref args, ref args,
.. ..
} = func.dfg[inst] { } = func.dfg[inst] {
let dest = func.offsets[destination] as i64;
let disp = dest - sink.offset() as i64;
let args = &args.as_slice(&func.dfg.value_lists)[0..2]; let args = &args.as_slice(&func.dfg.value_lists)[0..2];
sink.reloc_ebb(RelocKind::Branch.into(), destination);
put_sb(func.encodings[inst].bits(), put_sb(func.encodings[inst].bits(),
disp,
func.locations[args[0]].unwrap_reg(), func.locations[args[0]].unwrap_reg(),
func.locations[args[1]].unwrap_reg(), func.locations[args[1]].unwrap_reg(),
sink); sink);
@@ -257,9 +267,11 @@ fn recipe_sbzero<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut
ref args, ref args,
.. ..
} = func.dfg[inst] { } = func.dfg[inst] {
let dest = func.offsets[destination] as i64;
let disp = dest - sink.offset() as i64;
let args = &args.as_slice(&func.dfg.value_lists)[0..1]; let args = &args.as_slice(&func.dfg.value_lists)[0..1];
sink.reloc_ebb(RelocKind::Branch.into(), destination);
put_sb(func.encodings[inst].bits(), put_sb(func.encodings[inst].bits(),
disp,
func.locations[args[0]].unwrap_reg(), func.locations[args[0]].unwrap_reg(),
0, 0,
sink); sink);