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."""
|
"""Defining instruction set architectures."""
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
from .predicates import And
|
from .predicates import And
|
||||||
from .registers import RegClass, Register
|
from .registers import RegClass, Register, Stack
|
||||||
from .ast import Apply
|
from .ast import Apply
|
||||||
|
|
||||||
# The typing module is only required by mypy, and we don't use these imports
|
# 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 .settings import SettingGroup # noqa
|
||||||
from .types import ValueType # noqa
|
from .types import ValueType # noqa
|
||||||
from .registers import RegBank # noqa
|
from .registers import RegBank # noqa
|
||||||
OperandConstraint = Union[RegClass, Register, int]
|
OperandConstraint = Union[RegClass, Register, int, Stack]
|
||||||
ConstraintSeq = Union[OperandConstraint, Tuple[OperandConstraint, ...]]
|
ConstraintSeq = Union[OperandConstraint, Tuple[OperandConstraint, ...]]
|
||||||
# Instruction specification for encodings. Allows for predicated
|
# Instruction specification for encodings. Allows for predicated
|
||||||
# instructions.
|
# instructions.
|
||||||
@@ -187,6 +187,7 @@ class EncRecipe(object):
|
|||||||
- A `Register` specifying a fixed-register operand.
|
- A `Register` specifying a fixed-register operand.
|
||||||
- An integer indicating that this result is tied to a value operand, so
|
- An integer indicating that this result is tied to a value operand, so
|
||||||
they must use the same register.
|
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
|
The `branch_range` argument must be provided for recipes that can encode
|
||||||
branch instructions. It is an `(origin, bits)` tuple describing the exact
|
branch instructions. It is an `(origin, bits)` tuple describing the exact
|
||||||
@@ -245,7 +246,9 @@ class EncRecipe(object):
|
|||||||
# Check that it is in range.
|
# Check that it is in range.
|
||||||
assert c >= 0 and c < len(self.ins)
|
assert c >= 0 and c < len(self.ins)
|
||||||
else:
|
else:
|
||||||
assert isinstance(c, RegClass) or isinstance(c, Register)
|
assert (isinstance(c, RegClass)
|
||||||
|
or isinstance(c, Register)
|
||||||
|
or isinstance(c, Stack))
|
||||||
return seq
|
return seq
|
||||||
|
|
||||||
def ties(self):
|
def ties(self):
|
||||||
|
|||||||
@@ -340,3 +340,15 @@ class Register(object):
|
|||||||
# type: (RegClass, int) -> None
|
# type: (RegClass, int) -> None
|
||||||
self.regclass = rc
|
self.regclass = rc
|
||||||
self.unit = unit
|
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
|
from collections import OrderedDict, defaultdict
|
||||||
import math
|
import math
|
||||||
import itertools
|
import itertools
|
||||||
from cdsl.registers import RegClass, Register
|
from cdsl.registers import RegClass, Register, Stack
|
||||||
from cdsl.predicates import FieldPredicate
|
from cdsl.predicates import FieldPredicate
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -519,6 +519,10 @@ def emit_operand_constraints(
|
|||||||
assert cons == tied[n], "Invalid tied constraint"
|
assert cons == tied[n], "Invalid tied constraint"
|
||||||
fmt.format('kind: ConstraintKind::Tied({}),', cons)
|
fmt.format('kind: ConstraintKind::Tied({}),', cons)
|
||||||
fmt.format('regclass: {},', recipe.ins[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:
|
else:
|
||||||
raise AssertionError(
|
raise AssertionError(
|
||||||
'Unsupported constraint {}'.format(cons))
|
'Unsupported constraint {}'.format(cons))
|
||||||
|
|||||||
@@ -6,8 +6,9 @@ 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 LOAD, STORE
|
||||||
from .recipes import R, Rshamt, Ricmp, I, Iicmp, Iret
|
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 .settings import use_m
|
||||||
from cdsl.ast import Var
|
from cdsl.ast import Var
|
||||||
|
|
||||||
@@ -114,3 +115,11 @@ 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())
|
||||||
|
|
||||||
|
# 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 __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 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 UnaryImm, BranchIcmp, Branch, Jump, Call
|
from base.formats import Unary, 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
|
||||||
@@ -134,3 +135,13 @@ SBzero = EncRecipe(
|
|||||||
'SBzero', Branch, size=4,
|
'SBzero', Branch, size=4,
|
||||||
ins=(GPR), outs=(),
|
ins=(GPR), outs=(),
|
||||||
branch_range=(0, 13))
|
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]);
|
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