Add RISC-V call instruction encodings.
Calls are jal with a fixed %x1 link register.
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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 [
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user