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))
|
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):
|
class BoundInstruction(object):
|
||||||
"""
|
"""
|
||||||
@@ -675,6 +686,10 @@ class BoundInstruction(object):
|
|||||||
def __init__(self, inst, typevars):
|
def __init__(self, inst, typevars):
|
||||||
self.inst = inst
|
self.inst = inst
|
||||||
self.typevars = typevars
|
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):
|
def bind(self, *args):
|
||||||
"""
|
"""
|
||||||
@@ -690,6 +705,17 @@ class BoundInstruction(object):
|
|||||||
"""
|
"""
|
||||||
return self.bind(ValueType.by_name(name))
|
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
|
# Defining targets
|
||||||
|
|
||||||
@@ -769,17 +795,12 @@ class Encoding(object):
|
|||||||
|
|
||||||
def __init__(self, cpumode, inst, recipe, encbits):
|
def __init__(self, cpumode, inst, recipe, encbits):
|
||||||
assert isinstance(cpumode, CPUMode)
|
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)
|
assert isinstance(recipe, EncRecipe)
|
||||||
|
self.inst, self.typevars = inst.fully_bound()
|
||||||
self.cpumode = cpumode
|
self.cpumode = cpumode
|
||||||
assert real_inst.format == recipe.format, (
|
assert self.inst.format == recipe.format, (
|
||||||
"Format {} must match recipe: {}".format(
|
"Format {} must match recipe: {}".format(
|
||||||
inst.format, recipe.format))
|
self.inst.format, recipe.format))
|
||||||
self.inst = inst
|
|
||||||
self.recipe = recipe
|
self.recipe = recipe
|
||||||
self.encbits = encbits
|
self.encbits = encbits
|
||||||
|
|
||||||
|
|||||||
@@ -10,12 +10,20 @@ from recipes import OP, R
|
|||||||
for inst, f3, f7 in [
|
for inst, f3, f7 in [
|
||||||
(base.iadd, 0b000, 0b0000000),
|
(base.iadd, 0b000, 0b0000000),
|
||||||
(base.isub, 0b000, 0b0100000),
|
(base.isub, 0b000, 0b0100000),
|
||||||
(base.ishl, 0b001, 0b0000000),
|
|
||||||
(base.ushr, 0b101, 0b0000000),
|
|
||||||
(base.sshr, 0b101, 0b0100000),
|
|
||||||
(base.bxor, 0b100, 0b0000000),
|
(base.bxor, 0b100, 0b0000000),
|
||||||
(base.bor, 0b110, 0b0000000),
|
(base.bor, 0b110, 0b0000000),
|
||||||
(base.band, 0b111, 0b0000000)
|
(base.band, 0b111, 0b0000000)
|
||||||
]:
|
]:
|
||||||
RV32.enc(inst.i32, R, OP(f3, f7))
|
RV32.enc(inst.i32, R, OP(f3, f7))
|
||||||
RV64.enc(inst.i64, 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