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:
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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!();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user