diff --git a/lib/cretonne/meta/cdsl/isa.py b/lib/cretonne/meta/cdsl/isa.py index a2387bc0ff..bc85f7fb8f 100644 --- a/lib/cretonne/meta/cdsl/isa.py +++ b/lib/cretonne/meta/cdsl/isa.py @@ -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): diff --git a/lib/cretonne/meta/cdsl/registers.py b/lib/cretonne/meta/cdsl/registers.py index caaacd20e4..880f9096d4 100644 --- a/lib/cretonne/meta/cdsl/registers.py +++ b/lib/cretonne/meta/cdsl/registers.py @@ -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 diff --git a/lib/cretonne/meta/gen_encoding.py b/lib/cretonne/meta/gen_encoding.py index c56db8fc79..135940dd23 100644 --- a/lib/cretonne/meta/gen_encoding.py +++ b/lib/cretonne/meta/gen_encoding.py @@ -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)) diff --git a/lib/cretonne/meta/isa/riscv/encodings.py b/lib/cretonne/meta/isa/riscv/encodings.py index ffc848ef06..2b59964007 100644 --- a/lib/cretonne/meta/isa/riscv/encodings.py +++ b/lib/cretonne/meta/isa/riscv/encodings.py @@ -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)) diff --git a/lib/cretonne/meta/isa/riscv/recipes.py b/lib/cretonne/meta/isa/riscv/recipes.py index b5aa56bc85..1a7e98d0fe 100644 --- a/lib/cretonne/meta/isa/riscv/recipes.py +++ b/lib/cretonne/meta/isa/riscv/recipes.py @@ -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) diff --git a/lib/cretonne/src/isa/riscv/binemit.rs b/lib/cretonne/src/isa/riscv/binemit.rs index 12a3eb462f..e025b3f9d4 100644 --- a/lib/cretonne/src/isa/riscv/binemit.rs +++ b/lib/cretonne/src/isa/riscv/binemit.rs @@ -333,3 +333,11 @@ fn recipe_ujcall(func: &Function, inst: Inst, sink: &mut panic!("Expected Call format: {:?}", func.dfg[inst]); } } + +fn recipe_gpsp(_func: &Function, _inst: Inst, _sink: &mut CS) { + unimplemented!(); +} + +fn recipe_gpfi(_func: &Function, _inst: Inst, _sink: &mut CS) { + unimplemented!(); +}