diff --git a/filetests/isa/riscv/binary32.cton b/filetests/isa/riscv/binary32.cton index 8055289c65..bdcbde9dd2 100644 --- a/filetests/isa/riscv/binary32.cton +++ b/filetests/isa/riscv/binary32.cton @@ -80,23 +80,40 @@ ebb0: ; Control Transfer Instructions ebb1: - ; beq - br_icmp eq, v1, v2, ebb0 ; bin: Branch(ebb0) 01550063 - ; bne - br_icmp ne, v1, v2, ebb0 ; bin: Branch(ebb0) 01551063 - ; blt - br_icmp slt, v1, v2, ebb0 ; bin: Branch(ebb0) 01554063 - ; bge - br_icmp sge, v1, v2, ebb0 ; bin: Branch(ebb0) 01555063 - ; bltu - br_icmp ult, v1, v2, ebb0 ; bin: Branch(ebb0) 01556063 - ; bgeu - br_icmp uge, v1, v2, ebb0 ; bin: Branch(ebb0) 01557063 + ; beq 0x000 + br_icmp eq, v1, v2, ebb1 ; bin: 01550063 + ; bne 0xffc + br_icmp ne, v1, v2, ebb1 ; bin: ff551ee3 + ; blt 0xff8 + br_icmp slt, v1, v2, ebb1 ; bin: ff554ce3 + ; bge 0xff4 + br_icmp sge, v1, v2, ebb1 ; bin: ff555ae3 + ; bltu 0xff0 + br_icmp ult, v1, v2, ebb1 ; bin: ff5568e3 + ; bgeu 0xfec + 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 - brz v1, ebb0 ; bin: Branch(ebb0) 00050063 + brz v1, ebb2 ; bin: 00050063 ; bne x, %x0 - brnz v1, ebb0 ; bin: Branch(ebb0) 00051063 + brnz v1, ebb2 ; bin: fe051ee3 return } diff --git a/lib/cretonne/src/isa/riscv/binemit.rs b/lib/cretonne/src/isa/riscv/binemit.rs index 213d8a132e..a392d76a07 100644 --- a/lib/cretonne/src/isa/riscv/binemit.rs +++ b/lib/cretonne/src/isa/riscv/binemit.rs @@ -3,10 +3,12 @@ use binemit::{CodeSink, Reloc, bad_encoding}; use ir::{Function, Inst, InstructionData}; use isa::RegUnit; +use predicates::is_signed_int; include!(concat!(env!("OUT_DIR"), "/binemit-riscv.rs")); /// RISC-V relocation kinds. +#[allow(dead_code)] pub enum RelocKind { /// A conditional (SB-type) branch to an EBB. Branch, @@ -213,17 +215,17 @@ fn recipe_u(func: &Function, inst: Inst, sink: &mut CS) { /// imm rs2 rs1 funct3 imm opcode /// 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)` -fn put_sb(bits: u16, rs1: RegUnit, rs2: RegUnit, sink: &mut CS) { +fn put_sb(bits: u16, imm: i64, rs1: RegUnit, rs2: RegUnit, sink: &mut CS) { let bits = bits as u32; let opcode5 = bits & 0x1f; let funct3 = (bits >> 5) & 0x7; let rs1 = rs1 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 let mut i = 0x3; i |= opcode5 << 2; @@ -231,6 +233,12 @@ fn put_sb(bits: u16, rs1: RegUnit, rs2: RegUnit, sink: &m i |= rs1 << 15; 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); } @@ -240,9 +248,11 @@ fn recipe_sb(func: &Function, inst: Inst, sink: &mut CS) ref args, .. } = 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]; - sink.reloc_ebb(RelocKind::Branch.into(), destination); put_sb(func.encodings[inst].bits(), + disp, func.locations[args[0]].unwrap_reg(), func.locations[args[1]].unwrap_reg(), sink); @@ -257,9 +267,11 @@ fn recipe_sbzero(func: &Function, inst: Inst, sink: &mut ref args, .. } = 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]; - sink.reloc_ebb(RelocKind::Branch.into(), destination); put_sb(func.encodings[inst].bits(), + disp, func.locations[args[0]].unwrap_reg(), 0, sink);