+class SVP64OperandMeta(type):
+ class SVP64NonZeroOperand(NonZeroOperand):
+ def assemble(self, value, insn):
+ if isinstance(value, str):
+ value = int(value, 0)
+ if not isinstance(value, int):
+ raise ValueError("non-integer operand")
+
+ # FIXME: this is really weird
+ if self.record.name in ("svstep", "svstep."):
+ value += 1 # compensation
+
+ return super().assemble(value=value, insn=insn)
+
+ __TRANSFORM = {
+ NonZeroOperand: SVP64NonZeroOperand,
+ }
+
+ def __new__(metacls, name, bases, ns):
+ bases = list(bases)
+ for (origin_cls, target_cls) in metacls.__TRANSFORM.items():
+ for (index, base_cls) in enumerate(bases):
+ if base_cls is origin_cls:
+ bases[index] = target_cls
+ break
+ bases = tuple(bases)
+
+ return super().__new__(metacls, name, bases, ns)
+
+
+class SVP64Operand(Operand, metaclass=SVP64OperandMeta):
+ def __init__(self, record, *args, **kwargs):
+ return super().__init__(record=record, *args, **kwargs)
+
+ @property
+ def span(self):
+ return tuple(map(lambda bit: (bit + 32), super().span))
+
+
+class RMSelector:
+ def __init__(self, insn, record):
+ self.__insn = insn
+ self.__record = record
+ return super().__init__()
+
+ def __repr__(self):
+ return repr(self.rm)
+
+ @property
+ def insn(self):
+ return self.__insn
+
+ @property
+ def record(self):
+ return self.__record
+
+ @property
+ def rm(self):
+ rm = getattr(self.insn.prefix.rm, self.record.svp64.mode.name.lower())
+
+ # The idea behind these tables is that they are now literally
+ # in identical format to insndb.csv and minor_xx.csv and can
+ # be done precisely as that. The only thing to watch out for
+ # is the insertion of Rc=1 as a "mask/value" bit and likewise
+ # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
+ # as the LSB.
+ table = None
+ if self.record.svp64.mode is _SVMode.NORMAL:
+ # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
+ # mode Rc mask Rc member
+ table = (
+ (0b000000, 0b111000, "simple"), # simple (no Rc)
+ (0b001000, 0b111000, "mr"), # mapreduce (no Rc)
+ (0b010001, 0b110001, "ffrc1"), # ffirst, Rc=1
+ (0b010000, 0b110001, "ffrc0"), # ffirst, Rc=0
+ (0b100000, 0b110000, "sat"), # saturation (no Rc)
+ (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
+ (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
+ )
+ search = ((int(self.insn.prefix.rm.normal.mode) << 1) | self.record.Rc)
+
+ elif self.record.svp64.mode is _SVMode.LDST_IMM:
+ # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
+ # mode Rc mask Rc member
+ # ironically/coincidentally this table is identical to NORMAL
+ # mode except reserved in place of mr
+ table = (
+ (0b000000, 0b111000, "simple"), # simple (no Rc)
+ (0b001000, 0b111000, "post"), # post (no Rc)
+ (0b010001, 0b110001, "ffrc1"), # ffirst, Rc=1
+ (0b010000, 0b110001, "ffrc0"), # ffirst, Rc=0
+ (0b100000, 0b110000, "sat"), # saturation (no Rc)
+ (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
+ (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
+ )
+ search = ((int(self.insn.prefix.rm.ldst_imm.mode) << 1) | self.record.Rc)
+
+ elif self.record.svp64.mode is _SVMode.LDST_IDX:
+ # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
+ # mode Rc mask Rc member
+ table = (
+ (0b000000, 0b110000, "simple"), # simple (no Rc)
+ (0b010000, 0b110000, "stride"), # strided, (no Rc)
+ (0b100000, 0b110000, "sat"), # saturation (no Rc)
+ (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
+ (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
+ )
+ search = ((int(self.insn.prefix.rm.ldst_idx.mode) << 1) | self.record.Rc)
+
+ elif self.record.svp64.mode is _SVMode.CROP:
+ # concatenate mode 5-bit with regtype (LSB) then do mask/map search
+ # mode 3b mask 3b member
+ table = (
+ (0b000000, 0b111000, "simple"), # simple
+ (0b001000, 0b111000, "mr"), # mapreduce
+ (0b100001, 0b100001, "ff3"), # ffirst, 3-bit CR
+ (0b100000, 0b100000, "ff5"), # ffirst, 5-bit CR
+ )
+ search = ((int(self.insn.prefix.rm.crop.mode) << 1) | int(self.record.svp64.extra_CR_3bit))
+
+ elif self.record.svp64.mode is _SVMode.BRANCH:
+ # just mode 2-bit
+ # mode mask member
+ table = (
+ (0b00, 0b11, "simple"), # simple
+ (0b01, 0b11, "vls"), # VLset
+ (0b10, 0b11, "ctr"), # CTR mode
+ (0b11, 0b11, "ctrvls"), # CTR+VLset mode
+ )
+ # slightly weird: doesn't have a 5-bit "mode" field like others
+ search = int(self.insn.prefix.rm.branch.mode.sel)
+
+ # look up in table
+ if table is not None:
+ for (value, mask, field) in table:
+ if ((value & mask) == (search & mask)):
+ return getattr(rm, field)
+
+ return rm
+
+ def __getattr__(self, key):
+ if key.startswith(f"_{self.__class__.__name__}__"):
+ return super().__getattribute__(key)
+
+ return getattr(self.rm, key)
+
+ def __setattr__(self, key, value):
+ if key.startswith(f"_{self.__class__.__name__}__"):
+ return super().__setattr__(key, value)
+
+ rm = self.rm
+ if not hasattr(rm, key):
+ raise AttributeError(key)
+
+ return setattr(rm, key, value)
+
+