diff --git a/filetests/isa/riscv/binary32.cton b/filetests/isa/riscv/binary32.cton index c2b300e07c..93b1a9cc2d 100644 --- a/filetests/isa/riscv/binary32.cton +++ b/filetests/isa/riscv/binary32.cton @@ -91,5 +91,10 @@ ebb0: ; bgeu br_icmp uge, v1, v2, ebb0 ; bin: Branch(ebb0) 01557063 + ; beq x, %x0 + brz v1, ebb0 ; bin: Branch(ebb0) 00050063 + ; bne x, %x0 + brnz v1, ebb0 ; bin: Branch(ebb0) 00051063 + return } diff --git a/lib/cretonne/meta/isa/riscv/encodings.py b/lib/cretonne/meta/isa/riscv/encodings.py index 0d677c54ca..162ccbd3ea 100644 --- a/lib/cretonne/meta/isa/riscv/encodings.py +++ b/lib/cretonne/meta/isa/riscv/encodings.py @@ -6,7 +6,7 @@ from base import instructions as base from base.immediates import intcc from .defs import RV32, RV64 from .recipes import OPIMM, OPIMM32, OP, OP32, LUI, BRANCH -from .recipes import JALR, R, Rshamt, Ricmp, I, Iicmp, Iret, U, SB +from .recipes import JALR, R, Rshamt, Ricmp, I, Iicmp, Iret, U, SB, SBzero from .settings import use_m from cdsl.ast import Var @@ -93,6 +93,15 @@ for cond, f3 in [ RV32.enc(base.br_icmp.i32(cond, x, y, dest, args), SB, BRANCH(f3)) RV64.enc(base.br_icmp.i64(cond, x, y, dest, args), SB, BRANCH(f3)) +for inst, f3 in [ + (base.brz, 0b000), + (base.brnz, 0b001) + ]: + RV32.enc(inst.i32, SBzero, BRANCH(f3)) + RV64.enc(inst.i64, SBzero, BRANCH(f3)) + RV32.enc(inst.b1, SBzero, BRANCH(f3)) + RV64.enc(inst.b1, SBzero, BRANCH(f3)) + # Returns are a special case of JALR. # Note: Return stack predictors will only recognize this as a return when the # return address is provided in `x1`. We may want a special encoding to enforce diff --git a/lib/cretonne/meta/isa/riscv/recipes.py b/lib/cretonne/meta/isa/riscv/recipes.py index 9fe3c6f14d..2be2192002 100644 --- a/lib/cretonne/meta/isa/riscv/recipes.py +++ b/lib/cretonne/meta/isa/riscv/recipes.py @@ -12,7 +12,7 @@ from __future__ import absolute_import from cdsl.isa import EncRecipe from cdsl.predicates import IsSignedInt from base.formats import Binary, BinaryImm, MultiAry, IntCompare, IntCompareImm -from base.formats import UnaryImm, BranchIcmp +from base.formats import UnaryImm, BranchIcmp, Branch from .registers import GPR # The low 7 bits of a RISC-V instruction is the base opcode. All 32-bit @@ -116,3 +116,6 @@ U = EncRecipe( # TODO: These instructions have a +/- 4 KB branch range. How to encode that # constraint? SB = EncRecipe('SB', BranchIcmp, ins=(GPR, GPR), outs=()) + +# SB-type branch instruction with rs2 fixed to zero. +SBzero = EncRecipe('SBzero', Branch, ins=(GPR), outs=()) diff --git a/lib/cretonne/src/isa/riscv/binemit.rs b/lib/cretonne/src/isa/riscv/binemit.rs index 888fa369ed..057fac11aa 100644 --- a/lib/cretonne/src/isa/riscv/binemit.rs +++ b/lib/cretonne/src/isa/riscv/binemit.rs @@ -246,3 +246,16 @@ fn recipe_sb(func: &Function, inst: Inst, sink: &mut CS) panic!("Expected BranchIcmp format: {:?}", func.dfg[inst]); } } + +fn recipe_sbzero(func: &Function, inst: Inst, sink: &mut CS) { + if let InstructionData::Branch { destination, ref args, .. } = func.dfg[inst] { + let args = &args.as_slice(&func.dfg.value_lists)[0..1]; + sink.reloc_ebb(RelocKind::Branch.into(), destination); + put_sb(func.encodings[inst].bits(), + func.locations[args[0]].unwrap_reg(), + 0, + sink); + } else { + panic!("Expected Branch format: {:?}", func.dfg[inst]); + } +}