Add RISC-V encodings for spill and fill.

Add a Stack() class for specifying operand constraints for values on the
stack.

Add encoding recipes for RISC-V spill and fill instructions. Don't
implement the encoding recipe functions yet since we don't have the
stack slot layout yet.
This commit is contained in:
Jakob Stoklund Olesen
2017-06-13 13:39:52 -07:00
parent ea8a8a95a8
commit 5336bbd4cc
6 changed files with 53 additions and 6 deletions

View File

@@ -1,7 +1,7 @@
"""Defining instruction set architectures."""
from __future__ import absolute_import
from .predicates import And
from .registers import RegClass, Register
from .registers import RegClass, Register, Stack
from .ast import Apply
# The typing module is only required by mypy, and we don't use these imports
@@ -14,7 +14,7 @@ try:
from .settings import SettingGroup # noqa
from .types import ValueType # noqa
from .registers import RegBank # noqa
OperandConstraint = Union[RegClass, Register, int]
OperandConstraint = Union[RegClass, Register, int, Stack]
ConstraintSeq = Union[OperandConstraint, Tuple[OperandConstraint, ...]]
# Instruction specification for encodings. Allows for predicated
# instructions.
@@ -187,6 +187,7 @@ class EncRecipe(object):
- A `Register` specifying a fixed-register operand.
- An integer indicating that this result is tied to a value operand, so
they must use the same register.
- A `Stack` specifying a value in a stack slot.
The `branch_range` argument must be provided for recipes that can encode
branch instructions. It is an `(origin, bits)` tuple describing the exact
@@ -245,7 +246,9 @@ class EncRecipe(object):
# Check that it is in range.
assert c >= 0 and c < len(self.ins)
else:
assert isinstance(c, RegClass) or isinstance(c, Register)
assert (isinstance(c, RegClass)
or isinstance(c, Register)
or isinstance(c, Stack))
return seq
def ties(self):

View File

@@ -340,3 +340,15 @@ class Register(object):
# type: (RegClass, int) -> None
self.regclass = rc
self.unit = unit
class Stack(object):
"""
An operand that must be in a stack slot.
A `Stack` object can be used to indicate an operand constraint for a value
operand that must live in a stack slot.
"""
def __init__(self, rc):
# type: (RegClass) -> None
self.regclass = rc

View File

@@ -56,7 +56,7 @@ from unique_table import UniqueSeqTable
from collections import OrderedDict, defaultdict
import math
import itertools
from cdsl.registers import RegClass, Register
from cdsl.registers import RegClass, Register, Stack
from cdsl.predicates import FieldPredicate
try:
@@ -519,6 +519,10 @@ def emit_operand_constraints(
assert cons == tied[n], "Invalid tied constraint"
fmt.format('kind: ConstraintKind::Tied({}),', cons)
fmt.format('regclass: {},', recipe.ins[cons])
elif isinstance(cons, Stack):
assert n not in tied, "Can't tie stack operand"
fmt.line('kind: ConstraintKind::Stack,')
fmt.format('regclass: {},', cons.regclass)
else:
raise AssertionError(
'Unsupported constraint {}'.format(cons))

View File

@@ -6,8 +6,9 @@ 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 LOAD, STORE
from .recipes import R, Rshamt, Ricmp, I, Iicmp, Iret
from .recipes import U, UJ, UJcall, SB, SBzero
from .recipes import U, UJ, UJcall, SB, SBzero, GPsp, GPfi
from .settings import use_m
from cdsl.ast import Var
@@ -114,3 +115,11 @@ for inst, f3 in [
# is added by legalize_signature().
RV32.enc(base.x_return, Iret, JALR())
RV64.enc(base.x_return, Iret, JALR())
# Spill and fill.
RV32.enc(base.spill.i32, GPsp, STORE(0b010))
RV64.enc(base.spill.i32, GPsp, STORE(0b010))
RV64.enc(base.spill.i64, GPsp, STORE(0b011))
RV32.enc(base.fill.i32, GPfi, LOAD(0b010))
RV64.enc(base.fill.i32, GPfi, LOAD(0b010))
RV64.enc(base.fill.i64, GPfi, LOAD(0b011))

View File

@@ -11,8 +11,9 @@ instruction formats described in the reference:
from __future__ import absolute_import
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 UnaryImm, BranchIcmp, Branch, Jump, Call
from base.formats import Unary, 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
@@ -134,3 +135,13 @@ SBzero = EncRecipe(
'SBzero', Branch, size=4,
ins=(GPR), outs=(),
branch_range=(0, 13))
# Spill of a GPR.
GPsp = EncRecipe(
'GPsp', Unary, size=4,
ins=GPR, outs=Stack(GPR))
# Fill of a GPR.
GPfi = EncRecipe(
'GPfi', Unary, size=4,
ins=Stack(GPR), outs=GPR)

View File

@@ -333,3 +333,11 @@ fn recipe_ujcall<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut
panic!("Expected Call format: {:?}", func.dfg[inst]);
}
}
fn recipe_gpsp<CS: CodeSink + ?Sized>(_func: &Function, _inst: Inst, _sink: &mut CS) {
unimplemented!();
}
fn recipe_gpfi<CS: CodeSink + ?Sized>(_func: &Function, _inst: Inst, _sink: &mut CS) {
unimplemented!();
}