From 24c97ce6e5d85c484e43632f78d8e8509c08b0f4 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Thu, 4 Aug 2016 10:21:48 -0700 Subject: [PATCH] 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. --- meta/cretonne/__init__.py | 37 ++++++++++++++++++++++++++-------- meta/target/riscv/encodings.py | 14 ++++++++++--- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/meta/cretonne/__init__.py b/meta/cretonne/__init__.py index 01b74747b5..7214cac75f 100644 --- a/meta/cretonne/__init__.py +++ b/meta/cretonne/__init__.py @@ -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 diff --git a/meta/target/riscv/encodings.py b/meta/target/riscv/encodings.py index fa3f7d055d..fb6602184c 100644 --- a/meta/target/riscv/encodings.py +++ b/meta/target/riscv/encodings.py @@ -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))