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:
@@ -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
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user