Verify that type variables have been fully bound.

The shift instructions have two type variables since the shift amount can be a
differently sized integer. Fix the RISC-V shift encodings to reflect this, and
allow i64 registers to be shifted by an i32 amount.
This commit is contained in:
Jakob Stoklund Olesen
2016-08-04 10:21:48 -07:00
parent c1d32167dc
commit 24c97ce6e5
2 changed files with 40 additions and 11 deletions

View File

@@ -666,6 +666,17 @@ class Instruction(object):
"""
return self.bind(ValueType.by_name(name))
def fully_bound(self):
"""
Verify that all typevars have been bound, and return a
`(inst, typevars)` pair.
This version in `Instruction` itself allows non-polymorphic
instructions to duck-type as `BoundInstruction`\s.
"""
assert not self.is_polymorphic, self
return (self, ())
class BoundInstruction(object):
"""
@@ -675,6 +686,10 @@ class BoundInstruction(object):
def __init__(self, inst, typevars):
self.inst = inst
self.typevars = typevars
assert len(typevars) <= 1 + len(inst.other_typevars)
def __str__(self):
return '.'.join([self.inst.name,] + map(str, self.typevars))
def bind(self, *args):
"""
@@ -690,6 +705,17 @@ class BoundInstruction(object):
"""
return self.bind(ValueType.by_name(name))
def fully_bound(self):
"""
Verify that all typevars have been bound, and return a
`(inst, typevars)` pair.
"""
if len(self.typevars) < 1 + len(self.inst.other_typevars):
unb = ', '.join(str(tv) for tv in self.inst.other_typevars[len(self.typevars) - 1:])
raise AssertionError("Unbound typevar {} in {}".format(unb, self))
assert len(self.typevars) == 1 + len(self.inst.other_typevars)
return (self.inst, self.typevars)
# Defining targets
@@ -769,17 +795,12 @@ class Encoding(object):
def __init__(self, cpumode, inst, recipe, encbits):
assert isinstance(cpumode, CPUMode)
if isinstance(inst, BoundInstruction):
real_inst = inst.inst
else:
real_inst = inst
assert isinstance(real_inst, Instruction)
assert isinstance(recipe, EncRecipe)
self.inst, self.typevars = inst.fully_bound()
self.cpumode = cpumode
assert real_inst.format == recipe.format, (
assert self.inst.format == recipe.format, (
"Format {} must match recipe: {}".format(
inst.format, recipe.format))
self.inst = inst
self.inst.format, recipe.format))
self.recipe = recipe
self.encbits = encbits

View File

@@ -10,12 +10,20 @@ from recipes import OP, R
for inst, f3, f7 in [
(base.iadd, 0b000, 0b0000000),
(base.isub, 0b000, 0b0100000),
(base.ishl, 0b001, 0b0000000),
(base.ushr, 0b101, 0b0000000),
(base.sshr, 0b101, 0b0100000),
(base.bxor, 0b100, 0b0000000),
(base.bor, 0b110, 0b0000000),
(base.band, 0b111, 0b0000000)
]:
RV32.enc(inst.i32, R, OP(f3, f7))
RV64.enc(inst.i64, R, OP(f3, f7))
# Dynamic shifts have the same masking semantics as the cton base instructions
for inst, f3, f7 in [
(base.ishl, 0b001, 0b0000000),
(base.ushr, 0b101, 0b0000000),
(base.sshr, 0b101, 0b0100000),
]:
RV32.enc(inst.i32.i32, R, OP(f3, f7))
RV64.enc(inst.i64.i64, R, OP(f3, f7))
# Allow i32 shift amounts in 64-bit shifts.
RV64.enc(inst.i64.i32, R, OP(f3, f7))