Add encodings for Intel dynamic shift instructions.
These instructions have a fixed register constraint; the shift amount is passed in CL. Add meta language syntax so a fixed register can be specified as "GPR.rcx".
This commit is contained in:
@@ -12,12 +12,12 @@ 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
|
||||
necessarily 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
|
||||
register unit at a time when its registers are composed of smaller allocatable
|
||||
units. For example, the ARM double precision floating point registers are
|
||||
composed of two single precision registers.
|
||||
"""
|
||||
@@ -151,6 +151,18 @@ class RegBank(object):
|
||||
# sub-class.
|
||||
rc2.subclasses.append(rc1)
|
||||
|
||||
def unit_by_name(self, name):
|
||||
# type: (str) -> int
|
||||
"""
|
||||
Get a register unit in this bank by name.
|
||||
"""
|
||||
if name in self.names:
|
||||
r = self.names.index(name)
|
||||
elif name.startswith(self.prefix):
|
||||
r = int(name[len(self.prefix):])
|
||||
assert r < self.units, 'Invalid register name: ' + name
|
||||
return self.first_unit + r
|
||||
|
||||
|
||||
class RegClass(object):
|
||||
"""
|
||||
@@ -242,6 +254,15 @@ class RegClass(object):
|
||||
|
||||
return RegClass(self.bank, count=c, width=w, start=s)
|
||||
|
||||
def __getattr__(self, attr):
|
||||
# type: (str) -> Register
|
||||
"""
|
||||
Get a specific register in the class by name.
|
||||
|
||||
For example: `GPR.r5`.
|
||||
"""
|
||||
return Register(self, self.bank.unit_by_name(attr))
|
||||
|
||||
def mask(self):
|
||||
# type: () -> List[int]
|
||||
"""
|
||||
@@ -298,8 +319,8 @@ class Register(object):
|
||||
Specific registers are used to describe constraints on instructions where
|
||||
some operands must use a fixed register.
|
||||
|
||||
Register objects should be created using the indexing syntax on the
|
||||
register class.
|
||||
Register instances can be created with the constructor, or accessed as
|
||||
attributes on the register class: `GPR.rcx`.
|
||||
"""
|
||||
def __init__(self, rc, unit):
|
||||
# type: (RegClass, int) -> None
|
||||
|
||||
@@ -4,7 +4,14 @@ Intel Encodings.
|
||||
from __future__ import absolute_import
|
||||
from base import instructions as base
|
||||
from .defs import I32
|
||||
from .recipes import Op1rr
|
||||
from .recipes import Op1rr, Op1rc
|
||||
from .recipes import OP
|
||||
|
||||
I32.enc(base.iadd.i32, Op1rr, OP(0x01))
|
||||
|
||||
# 32-bit shifts and rotates.
|
||||
# Note that the dynamic shift amount is only masked by 5 or 6 bits; the 8-bit
|
||||
# and 16-bit shifts would need explicit masking.
|
||||
I32.enc(base.ishl.i32.i32, Op1rc, OP(0xd3, rrr=4))
|
||||
I32.enc(base.ushr.i32.i32, Op1rc, OP(0xd3, rrr=5))
|
||||
I32.enc(base.sshr.i32.i32, Op1rc, OP(0xd3, rrr=7))
|
||||
|
||||
@@ -65,3 +65,6 @@ def OP(op, pp=0, mm=0, rrr=0, w=0):
|
||||
|
||||
# XX /r
|
||||
Op1rr = EncRecipe('Op1rr', Binary, size=2, ins=(GPR, GPR), outs=0)
|
||||
|
||||
# XX /n with one arg in %rcx, for shifts.
|
||||
Op1rc = EncRecipe('Op1rc', Binary, size=2, ins=(GPR, GPR.rcx), outs=0)
|
||||
|
||||
Reference in New Issue
Block a user