Define register banks.
Add a RegBank class for describing CPU register banks. Define register banks for all the ISA stubs. The ARM32 floating point bank in particular requires attention.
This commit is contained in:
80
lib/cretonne/meta/cdsl/registers.py
Normal file
80
lib/cretonne/meta/cdsl/registers.py
Normal file
@@ -0,0 +1,80 @@
|
||||
"""
|
||||
Register set definitions
|
||||
------------------------
|
||||
|
||||
Each ISA defines a separate register set that is used by the register allocator
|
||||
and the final binary encoding of machine code.
|
||||
|
||||
The CPU registers are first divided into disjoint register banks, represented
|
||||
by a `RegBank` instance. Registers in different register banks never interfere
|
||||
with each other. A typical CPU will have a general purpose and a floating point
|
||||
register bank.
|
||||
|
||||
A register bank consists of a number of *register units* which are the smallest
|
||||
indivisible units of allocation and interference. A register unit doesn't
|
||||
necesarily correspond to a particular number of bits in a register, it is more
|
||||
like a placeholder that can be used to determine of a register is taken or not.
|
||||
|
||||
The register allocator works with *register classes* which can allocate one or
|
||||
more register units at a time. A register class allocates more than one
|
||||
register unit at a time when its registers are composed of smaller alocatable
|
||||
units. For example, the ARM double precision floating point registers are
|
||||
composed of two single precision registers. """
|
||||
from __future__ import absolute_import
|
||||
from . import is_power_of_two, next_power_of_two
|
||||
|
||||
|
||||
try:
|
||||
from typing import Sequence # noqa
|
||||
from .isa import TargetISA # noqa
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
class RegBank(object):
|
||||
"""
|
||||
A register bank belonging to an ISA.
|
||||
|
||||
A register bank controls a set of *register units* disjoint from all the
|
||||
other register banks in the ISA. The register units are numbered uniquely
|
||||
within the target ISA, and the units in a register bank form a contiguous
|
||||
sequence starting from a sufficiently aligned point that their low bits can
|
||||
be used directly when encoding machine code instructions.
|
||||
|
||||
Register units can be given generated names like `r0`, `r1`, ..., or a
|
||||
tuple of special register unit names can be provided.
|
||||
|
||||
:param name: Name of this register bank.
|
||||
:param doc: Documentation string.
|
||||
:param units: Number of register units.
|
||||
:param prefix: Prefix for generated unit names.
|
||||
:param names: Special names for the first units. May be shorter than
|
||||
`units`, the remaining units are named using `prefix`.
|
||||
"""
|
||||
|
||||
def __init__(self, name, isa, doc, units, prefix='p', names=()):
|
||||
# type: (str, TargetISA, str, int, str, Sequence[str]) -> None
|
||||
self.name = name
|
||||
self.isa = isa
|
||||
self.first_unit = 0
|
||||
self.units = units
|
||||
self.prefix = prefix
|
||||
self.names = names
|
||||
|
||||
assert len(names) <= units
|
||||
|
||||
if isa.regbanks:
|
||||
# Get the next free unit number.
|
||||
last = isa.regbanks[-1]
|
||||
u = last.first_unit + last.units
|
||||
align = units
|
||||
if not is_power_of_two(align):
|
||||
align = next_power_of_two(align)
|
||||
self.first_unit = (u + align - 1) & -align
|
||||
|
||||
isa.regbanks.append(self)
|
||||
|
||||
def __repr__(self):
|
||||
# type: () -> str
|
||||
return ('RegBank({}, units={}, first_unit={})'
|
||||
.format(self.name, self.units, self.first_unit))
|
||||
Reference in New Issue
Block a user