--- /dev/null
+#include <opid.h>
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define error(FORMAT, ...) \
+ do { \
+ (void)fprintf(stderr, FORMAT, ##__VA_ARGS__); \
+ } while (0)
+
+#define OPID_OPERAND_SIGNED (UINT32_C(1) << UINT32_C(0))
+#define OPID_OPERAND_GPR (UINT32_C(1) << UINT32_C(1))
+#define OPID_OPERAND_FPR (UINT32_C(1) << UINT32_C(2))
+#define OPID_OPERAND_PAIR (UINT32_C(1) << UINT32_C(3))
+#define OPID_OPERAND_CR3 (UINT32_C(1) << UINT32_C(4))
+#define OPID_OPERAND_CR5 (UINT32_C(1) << UINT32_C(5))
+#define OPID_OPERAND_NONZERO (UINT32_C(1) << UINT32_C(6))
+#define OPID_OPERAND_ADDRESS (UINT32_C(1) << UINT32_C(7))
+
+int
+main(void) {
+ ssize_t size;
+ uint32_t insn;
+ struct opid_ctx ctx;
+ enum opid_state state;
+ struct opid_operand const *operand;
+
+ do {
+ size = read(STDIN_FILENO, &insn, sizeof(insn));
+ if (size < 0) {
+ error("cannot fetch instruction: %s\n", strerror(errno));
+ return EXIT_FAILURE;
+ } else if (size == sizeof(uint32_t)) {
+ state = opid_disassemble(&ctx, insn);
+ if (state != OPID_SUCCESS) {
+ error("invalid instruction: %08" PRIx32 "\n", insn);
+ return EXIT_FAILURE;
+ }
+
+ printf("%s [", ctx.record->name);
+ opid_foreach_operand(&ctx, operand) {
+ printf("(%" PRIi32 " ",
+ (int32_t)operand->value);
+ if (operand->flags & OPID_OPERAND_SIGNED)
+ printf("s");
+ if (operand->flags & OPID_OPERAND_GPR)
+ printf("g");
+ if (operand->flags & OPID_OPERAND_FPR)
+ printf("f");
+ if (operand->flags & OPID_OPERAND_PAIR)
+ printf("p");
+ if (operand->flags & OPID_OPERAND_CR3)
+ printf("3");
+ if (operand->flags & OPID_OPERAND_CR5)
+ printf("5");
+ if (operand->flags & OPID_OPERAND_NONZERO)
+ printf("z");
+ if (operand->flags & OPID_OPERAND_ADDRESS)
+ printf("a");
+ printf(")");
+ }
+ printf("]\n");
+ } else if (size != 0) {
+ error("truncated instruction: %zu\n", (size_t)size);
+ return EXIT_FAILURE;
+ }
+ } while (size != 0);
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+import os
+import re
+import subprocess
+import tempfile
+import sys
+
+from openpower.insndb.core import (
+ Database,
+ Style,
+ WordInstruction,
+ SignedOperand,
+ GPROperand,
+ FPROperand,
+ PairOperand,
+ CR3Operand,
+ CR5Operand,
+ NonZeroOperand,
+)
+from openpower.decoder.power_enums import find_wiki_dir
+
+
+DIS_INSN_PATTERN = r"([A-Za-z0-9_\.]+)"
+DIS_VALUE_PATTERN = r"-?\d+"
+DIS_FLAGS_PATTERN = r"[sgfp35za]*"
+DIS_OPERAND_PATTERN = rf"(?:\({DIS_VALUE_PATTERN}\s+{DIS_FLAGS_PATTERN}\))*"
+DIS_PATTERN = fr"^{DIS_INSN_PATTERN}\s+\[({DIS_OPERAND_PATTERN})\]$"
+DIS_REGEX = re.compile(DIS_PATTERN)
+
+
+def opid_dis(db, insns):
+ with tempfile.TemporaryFile(mode="w+b") as stdin:
+ def remap_insn(insn):
+ (name, arguments) = insn
+ record = db[name]
+ insn = WordInstruction.assemble(record=db[name],
+ arguments=arguments)
+
+ def remap_operand(operand):
+ table = {
+ SignedOperand: "s",
+ GPROperand: "g",
+ FPROperand: "f",
+ PairOperand: "p",
+ CR3Operand: "3",
+ NonZeroOperand: "z",
+ CR5Operand: "5",
+ }
+ flags = []
+ for (cls, flag) in table.items():
+ if isinstance(operand, cls):
+ flags.append(flag)
+ flags = "".join(flags)
+ value = next(operand.disassemble(insn, style=Style.LEGACY))
+ return (value, flags)
+
+ operands = tuple(map(remap_operand,
+ insn.dynamic_operands(record=record)))
+
+ return (insn, name, operands)
+
+ def assert_eq(index, actual, expected):
+ if actual != expected:
+ print(f"[{index}]", "actual ", actual)
+ print(f"[{index}]", "expected", expected)
+ return False
+ return True
+
+ insns = tuple(map(remap_insn, insns))
+
+ for (insn, *_) in insns:
+ stdin.write(insn.bytes())
+ stdin.seek(0)
+
+ sp = subprocess.Popen("./opid-dis",
+ stdin=stdin,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ encoding="UTF-8")
+ (stdout, stderr) = sp.communicate()
+ if stderr:
+ sys.stderr.write(map(str.strip, stderr.splitlines()))
+ raise ValueError(stderr)
+
+ for (index, line) in enumerate(map(str.strip, stdout.splitlines())):
+ match = DIS_REGEX.match(line)
+ if match is None:
+ raise ValueError(line)
+ (name, operands) = match.groups()
+ operands = operands.replace(")(", ":")
+ operands = operands.replace("(", "").replace(")", "")
+ operands = tuple(tuple(operand.split(" ")) for operand in operands.split(":"))
+ print(line)
+ assert_eq(index=index, actual=name, expected=insns[index][1])
+ assert_eq(index=index, actual=operands, expected=insns[index][2])
+
+
+def main():
+ db = Database(find_wiki_dir())
+ opid_dis(db=db, insns=(
+ ("addpcis", ("1", "-1")),
+ ("addpcis", ("1", "0")),
+ ("addpcis", ("1", "+1")),
+ ("svshape2", ("8", "1", "31", "7", "1", "1")),
+ ("svshape", ("8", "1", "1", "14", "0")),
+ ))
+
+
+if __name__ == "__main__":
+ os.environ["SILENCELOG"] = "1"
+ main()