Add RISC-V encodings for call_indirect.
This commit is contained in:
@@ -4,6 +4,7 @@ isa riscv
|
|||||||
|
|
||||||
function %RV32I(i32 link [%x1]) -> i32 link [%x1] {
|
function %RV32I(i32 link [%x1]) -> i32 link [%x1] {
|
||||||
fn0 = function %foo()
|
fn0 = function %foo()
|
||||||
|
sig0 = signature()
|
||||||
|
|
||||||
ebb0(v9999: i32):
|
ebb0(v9999: i32):
|
||||||
[-,%x10] v1 = iconst.i32 1
|
[-,%x10] v1 = iconst.i32 1
|
||||||
@@ -86,6 +87,10 @@ ebb0(v9999: i32):
|
|||||||
; jal %x1, fn0
|
; jal %x1, fn0
|
||||||
call fn0() ; bin: Call(fn0) 000000ef
|
call fn0() ; bin: Call(fn0) 000000ef
|
||||||
|
|
||||||
|
; jalr %x1, %x10
|
||||||
|
call_indirect sig0, v1() ; bin: 000500e7
|
||||||
|
call_indirect sig0, v2() ; bin: 000a80e7
|
||||||
|
|
||||||
brz v1, ebb3
|
brz v1, ebb3
|
||||||
brnz v1, ebb1
|
brnz v1, ebb1
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ 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 LOAD, STORE
|
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 .recipes import U, UJ, UJcall, SB, SBzero, GPsp, GPfi
|
||||||
from .settings import use_m
|
from .settings import use_m
|
||||||
from cdsl.ast import Var
|
from cdsl.ast import Var
|
||||||
@@ -115,6 +115,8 @@ for inst, f3 in [
|
|||||||
# is added by legalize_signature().
|
# is added by legalize_signature().
|
||||||
RV32.enc(base.x_return, Iret, JALR())
|
RV32.enc(base.x_return, Iret, JALR())
|
||||||
RV64.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.
|
# Spill and fill.
|
||||||
RV32.enc(base.spill.i32, GPsp, STORE(0b010))
|
RV32.enc(base.spill.i32, GPsp, STORE(0b010))
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ from cdsl.isa import EncRecipe
|
|||||||
from cdsl.predicates import IsSignedInt
|
from cdsl.predicates import IsSignedInt
|
||||||
from cdsl.registers import Stack
|
from cdsl.registers import Stack
|
||||||
from base.formats import Binary, BinaryImm, MultiAry, IntCompare, IntCompareImm
|
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
|
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
|
||||||
@@ -113,6 +114,9 @@ Iicmp = EncRecipe(
|
|||||||
# The variable return values are not encoded.
|
# The variable return values are not encoded.
|
||||||
Iret = EncRecipe('Iret', MultiAry, size=4, ins=(), outs=())
|
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.
|
# Copy of a GPR is implemented as addi x, 0.
|
||||||
Icopy = EncRecipe('Icopy', Unary, size=4, ins=GPR, outs=GPR)
|
Icopy = EncRecipe('Icopy', Unary, size=4, ins=GPR, outs=GPR)
|
||||||
|
|
||||||
|
|||||||
@@ -182,6 +182,15 @@ fn recipe_iret<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS
|
|||||||
sink);
|
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) {
|
fn recipe_icopy<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS) {
|
||||||
if let InstructionData::Unary { arg, .. } = func.dfg[inst] {
|
if let InstructionData::Unary { arg, .. } = func.dfg[inst] {
|
||||||
put_i(func.encodings[inst].bits(),
|
put_i(func.encodings[inst].bits(),
|
||||||
|
|||||||
Reference in New Issue
Block a user