Add RISC-V call instruction encodings.

Calls are jal with a fixed %x1 link register.
This commit is contained in:
Jakob Stoklund Olesen
2017-04-06 15:36:03 -07:00
parent b4ac520332
commit 4ee519e620
4 changed files with 26 additions and 8 deletions

View File

@@ -3,6 +3,8 @@ test binemit
isa riscv isa riscv
function RV32I() { function RV32I() {
fn0 = function foo()
ebb0: ebb0:
[-,%x10] v1 = iconst.i32 1 [-,%x10] v1 = iconst.i32 1
[-,%x21] v2 = iconst.i32 2 [-,%x21] v2 = iconst.i32 2
@@ -75,11 +77,14 @@ ebb0:
[-,%x7] v140 = iconst.i32 0x12345000 ; bin: 123453b7 [-,%x7] v140 = iconst.i32 0x12345000 ; bin: 123453b7
[-,%x16] v141 = iconst.i32 0xffffffff_fedcb000 ; bin: fedcb837 [-,%x16] v141 = iconst.i32 0xffffffff_fedcb000 ; bin: fedcb837
; Control Transfer Instructions
; jal %x1, fn0
call fn0() ; bin: Call(fn0) 000000ef
brz v1, ebb3 brz v1, ebb3
fallthrough ebb1 fallthrough ebb1
; Control Transfer Instructions
ebb1: ebb1:
; beq 0x000 ; beq 0x000
br_icmp eq v1, v2, ebb1 ; bin: 01550063 br_icmp eq v1, v2, ebb1 ; bin: 01550063

View File

@@ -6,7 +6,8 @@ from base import instructions as base
from base.immediates import intcc from base.immediates import intcc
from .defs import RV32, RV64 from .defs import RV32, RV64
from .recipes import OPIMM, OPIMM32, OP, OP32, LUI, BRANCH, JALR, JAL 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 .settings import use_m
from cdsl.ast import Var from cdsl.ast import Var
@@ -84,6 +85,8 @@ RV64.enc(base.imul.i32, R, OP32(0b000, 0b0000001), isap=use_m)
# Unconditional branches. # Unconditional branches.
RV32.enc(base.jump, UJ, JAL()) RV32.enc(base.jump, UJ, JAL())
RV64.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. # Conditional branches.
for cond, f3 in [ for cond, f3 in [

View File

@@ -12,7 +12,7 @@ from __future__ import absolute_import
from cdsl.isa import EncRecipe from cdsl.isa import EncRecipe
from cdsl.predicates import IsSignedInt from cdsl.predicates import IsSignedInt
from base.formats import Binary, BinaryImm, MultiAry, IntCompare, IntCompareImm 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 from .registers import GPR
# The low 7 bits of a RISC-V instruction is the base opcode. All 32-bit # 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-type unconditional branch instructions.
UJ = EncRecipe('UJ', Jump, size=4, ins=(), outs=(), branch_range=(0, 21)) UJ = EncRecipe('UJ', Jump, size=4, ins=(), outs=(), branch_range=(0, 21))
UJcall = EncRecipe('UJcall', Call, size=4, ins=(), outs=())
# SB-type branch instructions. # SB-type branch instructions.
# TODO: These instructions have a +/- 4 KB branch range. How to encode that # TODO: These instructions have a +/- 4 KB branch range. How to encode that

View File

@@ -8,13 +8,12 @@ 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 jal call to a function.
Branch, Call,
} }
pub static RELOC_NAMES: [&'static str; 1] = ["Branch"]; pub static RELOC_NAMES: [&'static str; 1] = ["Call"];
impl Into<Reloc> for RelocKind { impl Into<Reloc> for RelocKind {
fn into(self) -> Reloc { fn into(self) -> Reloc {
@@ -318,3 +317,13 @@ fn recipe_uj<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS)
panic!("Expected Jump format: {:?}", func.dfg[inst]); panic!("Expected Jump format: {:?}", func.dfg[inst]);
} }
} }
fn recipe_ujcall<CS: CodeSink + ?Sized>(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]);
}
}