diff --git a/cranelift/filetests/isa/riscv/binary32.cton b/cranelift/filetests/isa/riscv/binary32.cton index 89771d8165..984b7b8a80 100644 --- a/cranelift/filetests/isa/riscv/binary32.cton +++ b/cranelift/filetests/isa/riscv/binary32.cton @@ -3,6 +3,8 @@ test binemit isa riscv function RV32I() { + fn0 = function foo() + ebb0: [-,%x10] v1 = iconst.i32 1 [-,%x21] v2 = iconst.i32 2 @@ -75,11 +77,14 @@ ebb0: [-,%x7] v140 = iconst.i32 0x12345000 ; bin: 123453b7 [-,%x16] v141 = iconst.i32 0xffffffff_fedcb000 ; bin: fedcb837 + ; Control Transfer Instructions + + ; jal %x1, fn0 + call fn0() ; bin: Call(fn0) 000000ef + brz v1, ebb3 fallthrough ebb1 - ; Control Transfer Instructions - ebb1: ; beq 0x000 br_icmp eq v1, v2, ebb1 ; bin: 01550063 diff --git a/lib/cretonne/meta/isa/riscv/encodings.py b/lib/cretonne/meta/isa/riscv/encodings.py index 21ff09e177..294015b4ea 100644 --- a/lib/cretonne/meta/isa/riscv/encodings.py +++ b/lib/cretonne/meta/isa/riscv/encodings.py @@ -6,7 +6,8 @@ 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, JALR, JAL -from .recipes import R, Rshamt, Ricmp, I, Iicmp, Iret, U, UJ, SB, SBzero +from .recipes import R, Rshamt, Ricmp, I, Iicmp, Iret +from .recipes import U, UJ, UJcall, SB, SBzero from .settings import use_m from cdsl.ast import Var @@ -84,6 +85,8 @@ RV64.enc(base.imul.i32, R, OP32(0b000, 0b0000001), isap=use_m) # Unconditional branches. RV32.enc(base.jump, UJ, JAL()) RV64.enc(base.jump, UJ, JAL()) +RV32.enc(base.call, UJcall, JAL()) +RV64.enc(base.call, UJcall, JAL()) # Conditional branches. for cond, f3 in [ diff --git a/lib/cretonne/meta/isa/riscv/recipes.py b/lib/cretonne/meta/isa/riscv/recipes.py index e30922613f..ad682fa74b 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, Branch, Jump +from base.formats import UnaryImm, BranchIcmp, Branch, Jump, Call from .registers import GPR # The low 7 bits of a RISC-V instruction is the base opcode. All 32-bit @@ -119,6 +119,7 @@ U = EncRecipe( # UJ-type unconditional branch instructions. UJ = EncRecipe('UJ', Jump, size=4, ins=(), outs=(), branch_range=(0, 21)) +UJcall = EncRecipe('UJcall', Call, size=4, ins=(), outs=()) # SB-type branch instructions. # TODO: These instructions have a +/- 4 KB branch range. How to encode that diff --git a/lib/cretonne/src/isa/riscv/binemit.rs b/lib/cretonne/src/isa/riscv/binemit.rs index e4cc5c05c6..94ba8b53bf 100644 --- a/lib/cretonne/src/isa/riscv/binemit.rs +++ b/lib/cretonne/src/isa/riscv/binemit.rs @@ -8,13 +8,12 @@ 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, + /// A jal call to a function. + Call, } -pub static RELOC_NAMES: [&'static str; 1] = ["Branch"]; +pub static RELOC_NAMES: [&'static str; 1] = ["Call"]; impl Into for RelocKind { fn into(self) -> Reloc { @@ -318,3 +317,13 @@ fn recipe_uj(func: &Function, inst: Inst, sink: &mut CS) panic!("Expected Jump format: {:?}", func.dfg[inst]); } } + +fn recipe_ujcall(func: &Function, inst: Inst, sink: &mut CS) { + if let InstructionData::Call { func_ref, .. } = func.dfg[inst] { + sink.reloc_func(RelocKind::Call.into(), func_ref); + // rd=%x1 is the standard link register. + put_uj(func.encodings[inst].bits(), 0, 1, sink); + } else { + panic!("Expected Call format: {:?}", func.dfg[inst]); + } +}