From d8e0718e50c59dbd0f00ae31c7acd6aeadfb5c8a Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Mon, 29 Aug 2022 23:14:31 -0700 Subject: [PATCH] use a decorator for constructing CUSTOM_INSNS (cherry picked from commit 63fd4ebc03ea0a7d51a1cf8d215affe45e0f0b33) --- src/openpower/sv/trans/svp64.py | 139 +++++++++++++++++++++----------- 1 file changed, 91 insertions(+), 48 deletions(-) diff --git a/src/openpower/sv/trans/svp64.py b/src/openpower/sv/trans/svp64.py index 51e4afcc..ad8a0f62 100644 --- a/src/openpower/sv/trans/svp64.py +++ b/src/openpower/sv/trans/svp64.py @@ -22,6 +22,7 @@ import functools import os import sys from collections import OrderedDict +import inspect from openpower.decoder.pseudo.pagereader import ISA from openpower.decoder.power_svp64 import SVP64RM, get_regtype, decode_extra @@ -47,6 +48,38 @@ def instruction(*fields): return functools.reduce(instruction, fields, 0) +CUSTOM_INSNS = {} + + +def _insn(name, *args, **kwargs): + return name, args, kwargs + + +def _custom_insns(*insns): + """ a decorator that adds the function to `CUSTOM_INSNS` """ + + def decorator(fn): + FIELDS_ARG = object() + if len(insns) == 0: + insns_ = (fn.__name__, (), {}), + else: + insns_ = insns + for name, args, kwargs in insns_: + if not isinstance(name, str): + raise TypeError("instruction name must be a str: {name!r}") + if name in CUSTOM_INSNS: + raise ValueError(f"duplicate instruction mnemonic: {name!r}") + # use getcallargs to check that arguments work: + inspect.getcallargs(fn, FIELDS_ARG, *args, **kwargs) + CUSTOM_INSNS[name] = functools.partial(fn, *args, **kwargs) + return fn + return decorator + + +@_custom_insns( + _insn("setvl", Rc=0), + _insn("setvl.", Rc=1), +) def setvl(fields, Rc): """ setvl is a *32-bit-only* instruction. It controls SVSTATE. @@ -79,6 +112,10 @@ def setvl(fields, Rc): ) +@_custom_insns( + _insn("svstep", Rc=0), + _insn("svstep.", Rc=1), +) def svstep(fields, Rc): """ svstep is a 32-bit instruction. It updates SVSTATE. @@ -109,6 +146,7 @@ def svstep(fields, Rc): ) +@_custom_insns() def svshape(fields): """ svshape is a *32-bit-only* instruction. It updates SVSHAPE and SVSTATE. @@ -139,6 +177,7 @@ def svshape(fields): ) +@_custom_insns() def svindex(fields): """ svindex is a *32-bit-only* instruction. It is a convenience @@ -169,6 +208,7 @@ def svindex(fields): ) +@_custom_insns() def svremap(fields): """ this is a *32-bit-only* instruction. It updates the SVSHAPE SPR @@ -204,6 +244,7 @@ def svremap(fields): # them (that's being fixed!) # they can - if implementations then choose - be Vectorised # because they are general-purpose scalar instructions +@_custom_insns() def bmask(fields): """ 1.6.2.2 BM2-FORM @@ -224,6 +265,10 @@ def bmask(fields): ) +@_custom_insns( + _insn("fsins", Rc=0), + _insn("fsins.", Rc=1), +) def fsins(fields, Rc): # XXX WARNING THESE ARE NOT APPROVED BY OPF ISA WG # however we are out of space with opcode 22 @@ -243,6 +288,10 @@ def fsins(fields, Rc): ) +@_custom_insns( + _insn("fcoss", Rc=0), + _insn("fcoss.", Rc=1), +) def fcoss(fields, Rc): # XXX WARNING THESE ARE NOT APPROVED BY OPF ISA WG # however we are out of space with opcode 22 @@ -262,6 +311,10 @@ def fcoss(fields, Rc): ) +@_custom_insns( + _insn("ternlogi", Rc=0), + _insn("ternlogi.", Rc=1), +) def ternlogi(fields, Rc): # XXX WARNING THESE ARE NOT APPROVED BY OPF ISA WG # however we are out of space with opcode 22 @@ -282,21 +335,31 @@ def ternlogi(fields, Rc): ) -def grev(fields, Rc, imm, wide): +@_custom_insns( + _insn("grev", Rc=0, imm=0, word=0), + _insn("grevw", Rc=0, imm=0, word=1), + _insn("grevi", Rc=0, imm=1, word=0), + _insn("grevwi", Rc=0, imm=1, word=1), + _insn("grev.", Rc=1, imm=0, word=0), + _insn("grevw.", Rc=1, imm=0, word=1), + _insn("grevi.", Rc=1, imm=1, word=0), + _insn("grevwi.", Rc=1, imm=1, word=1), +) +def grev(fields, Rc, imm, word): # XXX WARNING THESE ARE NOT APPROVED BY OPF ISA WG # however we are out of space with opcode 22 insn = PO = 5 # _ matches fields in table at: - # https://libre-soc.org/openPOwer/sv/bitmanip/ + # https://libre-soc.org/openpower/sv/bitmanip/ XO = 0b1_0010_110 - if wide: + if word: XO |= 0b100_000 if imm: XO |= 0b1000_000 (RT, RA, XBI) = fields insn = (insn << 5) | RT insn = (insn << 5) | RA - if imm and not wide: + if imm and not word: assert 0 <= XBI < 64 insn = (insn << 6) | XBI insn = (insn << 9) | XO @@ -308,6 +371,28 @@ def grev(fields, Rc, imm, wide): return insn +@_custom_insns( + _insn("maxs", XO=0b0111001110, Rc=0), + _insn("maxs.", XO=0b0111001110, Rc=1), + _insn("maxu", XO=0b0011001110, Rc=0), + _insn("maxu.", XO=0b0011001110, Rc=1), + _insn("minu", XO=0b0001001110, Rc=0), + _insn("minu.", XO=0b0001001110, Rc=1), + _insn("mins", XO=0b0101001110, Rc=0), + _insn("mins.", XO=0b0101001110, Rc=1), + _insn("absdu", XO=0b1011110110, Rc=0), + _insn("absdu.", XO=0b1011110110, Rc=1), + _insn("absds", XO=0b1001110110, Rc=0), + _insn("absds.", XO=0b1001110110, Rc=1), + _insn("avgadd", XO=0b1101001110, Rc=0), + _insn("avgadd.", XO=0b1101001110, Rc=1), + _insn("absdacu", XO=0b1111110110, Rc=0), + _insn("absdacu.", XO=0b1111110110, Rc=1), + _insn("absdacs", XO=0b0111110110, Rc=0), + _insn("absdacs.", XO=0b0111110110, Rc=1), + _insn("cprop", XO=0b0110001110, Rc=0), + _insn("cprop.", XO=0b0110001110, Rc=1), +) def av(fields, XO, Rc): # 1.6.7 X-FORM # |0 |6 |7|8|9 |10 |11|12|13 |15|16|17 |20|21 |31 | @@ -324,6 +409,7 @@ def av(fields, XO, Rc): ) +@_custom_insns() def fmvis(fields): # XXX WARNING THESE ARE NOT APPROVED BY OPF ISA WG # V3.0B 1.6.6 DX-FORM @@ -346,6 +432,7 @@ def fmvis(fields): ) +@_custom_insns() def fishmv(fields): # XXX WARNING THESE ARE NOT APPROVED BY OPF ISA WG # V3.0B 1.6.6 DX-FORM @@ -368,50 +455,6 @@ def fishmv(fields): ) -CUSTOM_INSNS = {} -for (name, hook) in ( - ("setvl", setvl), - ("svstep", svstep), - ("fsins", fsins), - ("fcoss", fcoss), - ("ternlogi", ternlogi), -): - CUSTOM_INSNS[name] = functools.partial(hook, Rc=False) - CUSTOM_INSNS[f"{name}."] = functools.partial(hook, Rc=True) -CUSTOM_INSNS["bmask"] = bmask -CUSTOM_INSNS["svshape"] = svshape -CUSTOM_INSNS["svindex"] = svindex -CUSTOM_INSNS["svremap"] = svremap -CUSTOM_INSNS["fmvis"] = fmvis -CUSTOM_INSNS["fishmv"] = fishmv - -for (name, imm, wide) in ( - ("grev", False, False), - ("grevi", True, False), - ("grevw", False, True), - ("grevwi", True, True), -): - CUSTOM_INSNS[name] = functools.partial(grev, - imm=("i" in name), wide=("w" in name), Rc=False) - CUSTOM_INSNS[f"{name}."] = functools.partial(grev, - imm=("i" in name), wide=("w" in name), Rc=True) - -for (name, XO) in ( - ("maxs", 0b0111001110), - ("maxu", 0b0011001110), - ("minu", 0b0001001110), - ("mins", 0b0101001110), - ("absdu", 0b1011110110), - ("absds", 0b1001110110), - ("avgadd", 0b1101001110), - ("absdacu", 0b1111110110), - ("absdacs", 0b0111110110), - ("cprop", 0b0110001110), -): - CUSTOM_INSNS[name] = functools.partial(av, XO=XO, Rc=False) - CUSTOM_INSNS[f"{name}."] = functools.partial(av, XO=XO, Rc=True) - - # decode GPR into sv extra def get_extra_gpr(etype, regmode, field): if regmode == 'scalar': -- 2.30.2