Add RISC-V encodings for call_indirect.

This commit is contained in:
Jakob Stoklund Olesen
2017-06-14 16:14:16 -07:00
parent 66af915eed
commit 9eb0778f9b
4 changed files with 22 additions and 2 deletions

View File

@@ -4,6 +4,7 @@ isa riscv
function %RV32I(i32 link [%x1]) -> i32 link [%x1] {
fn0 = function %foo()
sig0 = signature()
ebb0(v9999: i32):
[-,%x10] v1 = iconst.i32 1
@@ -86,6 +87,10 @@ ebb0(v9999: i32):
; jal %x1, fn0
call fn0() ; bin: Call(fn0) 000000ef
; jalr %x1, %x10
call_indirect sig0, v1() ; bin: 000500e7
call_indirect sig0, v2() ; bin: 000a80e7
brz v1, ebb3
brnz v1, ebb1

View File

@@ -7,7 +7,7 @@ from base.immediates import intcc
from .defs import RV32, RV64
from .recipes import OPIMM, OPIMM32, OP, OP32, LUI, BRANCH, JALR, JAL
from .recipes import LOAD, STORE
from .recipes import R, Rshamt, Ricmp, I, Iicmp, Iret, Icopy
from .recipes import R, Rshamt, Ricmp, I, Iicmp, Iret, Icall, Icopy
from .recipes import U, UJ, UJcall, SB, SBzero, GPsp, GPfi
from .settings import use_m
from cdsl.ast import Var
@@ -115,6 +115,8 @@ for inst, f3 in [
# is added by legalize_signature().
RV32.enc(base.x_return, Iret, JALR())
RV64.enc(base.x_return, Iret, JALR())
RV32.enc(base.call_indirect.i32, Icall, JALR())
RV64.enc(base.call_indirect.i64, Icall, JALR())
# Spill and fill.
RV32.enc(base.spill.i32, GPsp, STORE(0b010))

View File

@@ -13,7 +13,8 @@ from cdsl.isa import EncRecipe
from cdsl.predicates import IsSignedInt
from cdsl.registers import Stack
from base.formats import Binary, BinaryImm, MultiAry, IntCompare, IntCompareImm
from base.formats import Unary, UnaryImm, BranchIcmp, Branch, Jump, Call
from base.formats import Unary, UnaryImm, BranchIcmp, Branch, Jump
from base.formats import Call, IndirectCall
from .registers import GPR
# The low 7 bits of a RISC-V instruction is the base opcode. All 32-bit
@@ -113,6 +114,9 @@ Iicmp = EncRecipe(
# The variable return values are not encoded.
Iret = EncRecipe('Iret', MultiAry, size=4, ins=(), outs=())
# I-type encoding for `jalr` as an indirect call.
Icall = EncRecipe('Icall', IndirectCall, size=4, ins=GPR, outs=())
# Copy of a GPR is implemented as addi x, 0.
Icopy = EncRecipe('Icopy', Unary, size=4, ins=GPR, outs=GPR)

View File

@@ -182,6 +182,15 @@ fn recipe_iret<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS
sink);
}
fn recipe_icall<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS) {
// Indirect instructions are jalr with rd=%x1.
put_i(func.encodings[inst].bits(),
func.locations[func.dfg.inst_args(inst)[0]].unwrap_reg(),
0, // no offset.
1, // rd = %x1: link register.
sink);
}
fn recipe_icopy<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS) {
if let InstructionData::Unary { arg, .. } = func.dfg[inst] {
put_i(func.encodings[inst].bits(),