From 910796a4026b15604f8e14a1c8bb96f2b726b84b Mon Sep 17 00:00:00 2001
From: Andrew Miranti <andrew.h.miranti@gmail.com>
Date: Wed, 9 Jan 2019 14:12:01 -0600
Subject: [PATCH] Temporary commit

---
 build.sh                                    |  14 +-
 decoder-syntax.k => decoder-configuration.k |  69 +-------
 decoder.k                                   |  47 +++--
 generator/build.py                          |   4 +
 generator/disasm_to_iclass.py               |  11 +-
 generator/generate.py                       | 126 ++++---------
 generator/generate_all.py                   | 186 --------------------
 test-decoder.k                              |  57 ++++++
 8 files changed, 144 insertions(+), 370 deletions(-)
 rename decoder-syntax.k => decoder-configuration.k (86%)
 create mode 100644 generator/build.py
 delete mode 100755 generator/generate_all.py
 create mode 100644 test-decoder.k

diff --git a/build.sh b/build.sh
index 0569a82..e8afeb9 100755
--- a/build.sh
+++ b/build.sh
@@ -1,9 +1,7 @@
 #!/bin/bash
-kompile --backend ocaml decoder.k &
-until ps -f | grep -m 1 "[0-9] ocamlc"; do sleep 10 ; done
-killall -9 java
-#sleep 1
-#wait $(ps -f | grep "[0-9] ocamlc" | grep -Eo "[0-9]+" | head -1)
-#cd decoder-kompiled
-#ocamlfind c -g -passopt stdlib.cma -linkpkg -a -o realdef.cma realdef.cmo
-#cd ..
+CURR=$(pwd)
+cd "$(dirname $0)/generator"
+./generate.py $(< ./disasm_to_iclass.py $@) > ../generated_decoder_rules.k
+cd ..
+kompile decoder.k --backend ocaml -I $X86_SEMANTICS
+cd $CURR
diff --git a/decoder-syntax.k b/decoder-configuration.k
similarity index 86%
rename from decoder-syntax.k
rename to decoder-configuration.k
index 5cb4c61..02e9977 100644
--- a/decoder-syntax.k
+++ b/decoder-configuration.k
@@ -1,59 +1,7 @@
-/*BEGIN_LEGAL 
- *
- * Adapted from Intel's XED (Copyright (c) 2018 Intel Corporation)
- *                         
- * END_LEGAL */
-
-require "registers.k"
-require "categories.k"
-
-module DECODER-SYNTAX
-  imports DOMAINS-SYNTAX
-
-  syntax HexToken ::= r"0x[0-9a-fA-F]+" [token, prec(2)]
-
-  syntax Stmt ::= "Disassemble" "(" HexToken "," HexToken ")"
-  syntax Stmts ::= List{Stmt, ";"}
-
-  syntax Ints ::= List{Int, " "}
-
-  syntax Pgm ::= Stmts ";"
-endmodule
-
-module DECODER-CONVERSIONS
-  imports DECODER-SYNTAX
-  imports DOMAINS
-
-  syntax HexTokens ::= List{HexToken, " "}
-
-  syntax Int ::= HexStringToInt(String) [function]
-  rule HexStringToInt(S:String) => String2Base(S, 16)
-
-  syntax String ::= StringifyHexToken(HexToken) [function, hook(STRING.token2string)]
-
-  syntax String ::= removeFirstTwoChars(String) [function]
-  rule removeFirstTwoChars(S) => substrString(S, 2, lengthString(S))
-
-  syntax String ::= HexTokenToString(HexToken) [function]
-  rule HexTokenToString(H) => removeFirstTwoChars(StringifyHexToken(H))
-
-  syntax Ints ::= HexTokenToInts(HexToken) [function]
-  syntax Ints ::= ImplHexTokenToInts(String) [function]
-
-  rule HexTokenToInts(Ht) => ImplHexTokenToInts(HexTokenToString(Ht))
-
-  rule ImplHexTokenToInts("") => .Ints
-  rule ImplHexTokenToInts(S) => String2Base(substrString(S, 0, 2), 16) ImplHexTokenToInts(substrString(S, 2, lengthString(S))) requires 2 dividesInt lengthString(S) andBool lengthString(S) >Int 0
-
-  syntax Int ::= HexTokenToInt(HexToken) [function]
-  rule HexTokenToInt(H) => HexStringToInt(HexTokenToString(H))
-
-  syntax KResult ::= HexToken
-endmodule
+requires "registers.k"
+requires "categories.k"
 
 module DECODER-CONFIGURATION
-  imports DECODER-SYNTAX
-  imports DECODER-CONVERSIONS
   imports DOMAINS
   imports REGISTERS-SYNTAX
   imports CATEGORIES-SYNTAX
@@ -201,15 +149,7 @@ module DECODER-CONFIGURATION
                   </decoderInternal>
 
 
-  configuration <T color="yellow">
-                  <k color="green"> $PGM:Pgm </k>
-                  <MemCache color="purple"> .Map </MemCache>
-                  <ROM color="red"> .List </ROM>
-                  <entry color="blue"> 0 </entry>
-
-                  <output stream="stdout"> .List </output>
-
-                  <decoder>
+  configuration <decoder>
                     <mode> mode64 </mode>
                     <smode> mode64 </smode>
                     <instructionpointer> 0 </instructionpointer>
@@ -349,7 +289,4 @@ module DECODER-CONFIGURATION
 
                     </decoderInternal>
                   </decoder>
-                </T>
-
 endmodule
-
diff --git a/decoder.k b/decoder.k
index 60e317e..4fca4ee 100644
--- a/decoder.k
+++ b/decoder.k
@@ -21,26 +21,33 @@ require "has_modrm.k"
 require "has_disp_regular.k"
 require "registers.k"
 require "decoder-syntax.k"
-require "generated_decoder_rules.k" // VERY slow
-//require "generated/generated-header.k"
+require "generated_decoder_rules.k"
+require "x86-syntax.k"
+
+module DECODER-INTERFACE
+  imports DOMAINS
+  
+  syntax Ints ::= List{Int, " "}
+
+  syntax K ::= Decode(Int, Ints)
+
+  syntax DecoderError
+                               //Len, DisassemblyString, x86-Semantics Instruction
+  syntax DecoderResult ::= DecoderResult(Int, String, Instruction) | DecoderError
+endmodule
 
 module DECODER
-  imports DECODER-SYNTAX
-  imports DECODER-CONVERSIONS
+  imports DECODER-INTERFACE
   imports HAS-MODRM-MAP
   imports HAS-DISP-REGULAR
   imports DOMAINS
   imports DECODER-CONFIGURATION
   imports GENERATED-DECODER-RULES
+  imports X86-SYNTAX
 
-  rule S:Stmts ; => S [structural]
-  rule S1 ; S2 => S1 ~> S2 [structural]
-  rule .Stmts => . [structural]
 
   syntax K ::= "SetMode" | "DecodePrefixes" | "ScanForVEX" | "ScanForEVEX" | "ScanForOpcode" | "ScanForMODRM" | "ScanForSIB" | "Disassemble" | "OutputDisassembly" | "IncrementInstruction"
 
-
-
   syntax Int ::= IntModeFromSymbol(K) [function]
 
   rule IntModeFromSymbol(mode16) => 0
@@ -75,9 +82,9 @@ module DECODER
   rule padIntsAux(Is, L) => 0 padIntsAux(Is, L -Int 1) requires L >Int 0
   rule padIntsAux(Is, 0) => Is
 
-  rule Disassemble(Addr:HexToken, Isn:HexToken) =>
+  rule Decode(Addr:Int, Bytes:Ints) =>
         ResetDecoder ~>
-        InitDecoder(HexTokenToInt(Addr), padInts(HexTokenToInts(Isn), 15)) ~>
+        InitDecoder(Addr, Bytes) ~>
         SetMode ~>
         DecodePrefixes ~> 
         ScanForVEX ~> 
@@ -532,7 +539,9 @@ module DECODER
   rule <k> ParseEVEX => DecoderOutOfBytes ... </k>
        <decoderBuffer> I1:Int I2:Int I3:Int I4:Int .Ints </decoderBuffer>
  
-  syntax K ::= "CheckUBIT" | "BadUBIT"
+  syntax K ::= "CheckUBIT"
+  
+  syntax DecoderError ::= "BadUBIT"
 
   rule <k> CheckUBIT => BadUBIT ... </k>
        <UBIT> 0 </UBIT> // We're not going to support KNC for the foreseeable future.
@@ -540,7 +549,9 @@ module DECODER
   rule <k> CheckUBIT => . ... </k>
        <UBIT> 1 </UBIT>
 
-  syntax K ::= "CheckVEXDEST4" | "BadVEXDEST4"
+  syntax K ::= "CheckVEXDEST4"
+  
+  syntax DecoderError ::= "BadVEXDEST4"
 
   rule <k> CheckVEXDEST4 => . ... </k>
        <VEXDEST4> V </VEXDEST4>
@@ -552,7 +563,9 @@ module DECODER
        <mode> M </mode>
        requires M =/=K mode64 andBool I:Int =/=Int 0
 
-  syntax K ::= "CheckMASK" | "BadMASK"
+  syntax K ::= "CheckMASK"
+  
+  syntax DecoderError ::= "BadMASK"
 
   rule <k> CheckMASK => . ... </k>
        <MASK> I:Int </MASK>
@@ -687,7 +700,7 @@ module DECODER
        <REG> _ => (I:Int >>Int 3) &Int 7  </REG>
        <RM> _ => (I:Int &Int 7) </RM>
 
-  syntax K ::= "BadLL"
+  syntax DecoderError ::= "BadLL"
 
   rule <k> CheckLL => BadLL ... </k>
        <LLRC> L </LLRC>
@@ -785,7 +798,9 @@ module DECODER
 
   syntax K ::= ReadLittleEndian(Int, Int, Int)
 
-  syntax K ::= ReadDisp(Int) | "SetDisp" | "InvalidDisp"
+  syntax K ::= ReadDisp(Int) | "SetDisp" 
+  
+  syntax DecoderError ::= "InvalidDisp"
 
   rule ReadDisp(0) => .
   rule ReadDisp(8) => ReadLittleEndian(1, 0, 0) ~> SetDisp
diff --git a/generator/build.py b/generator/build.py
new file mode 100644
index 0000000..e311a5e
--- /dev/null
+++ b/generator/build.py
@@ -0,0 +1,4 @@
+import sys
+from disasm_to_iclass import get_iclasses_from_disasms
+fromm
+
diff --git a/generator/disasm_to_iclass.py b/generator/disasm_to_iclass.py
index 282d134..39a74ab 100755
--- a/generator/disasm_to_iclass.py
+++ b/generator/disasm_to_iclass.py
@@ -11979,10 +11979,9 @@ lookup_table = {
     "vgf2p8mulb": ["VGF2P8MULB"],
 }
 
-result = set()
-for arg in sys.argv[1:]:
-    assert arg in lookup_table
-    result |= set(lookup_table[arg])
+def get_iclasses_from_disasms(disasms):
+    return list(set([lookup_table[disasm] for disasm in disasms]))
 
-for ret in result:
-    print(ret)
+if __name__ == "__main__":
+    for ret in get_iclasses_from_disasms(sys.argv[1:]):
+        print(ret)
diff --git a/generator/generate.py b/generator/generate.py
index aadda05..a18d2db 100755
--- a/generator/generate.py
+++ b/generator/generate.py
@@ -23,17 +23,8 @@
 import instructions
 import nonterminals
 import sys
-import os
-import shutil
 from kcodegen import kRewrite
 
-out_folder = "generated"
-
-if os.path.exists(out_folder): # https://stackoverflow.com/questions/273192/how-can-i-safely-create-a-nested-directory-in-python Is there a nicer way to do this?
-    shutil.rmtree(out_folder)
-
-os.makedirs(out_folder)
-
 class FreshVariableGenerator(object):
     def __init__(self, prefix="I"):
         self._prefix = prefix
@@ -127,45 +118,33 @@ def gen_from_inst(inst):
         ret.add_literal_match("VEXVALID", "0")
     return ret
 
-def make_outreg_rule(name):
-    return """syntax K ::= "OUTREGTo{0}"
-    rule <k> OUTREGTo{0} => . ... </k>
-         <OUTREG> M </OUTREG>
-         <{0}> _ => M </{0}>
-""".format(name)
-
-def write_to_file(name, contents):
-    with open(out_folder + "/" + name, "w") as f:
-        f.write(contents.replace("XED_", ""))
-
-generated_syntax_name = "generated-syntax.k"
-generated_syntax_contents = """// GENERATED CODE, DO NOT MODIFY.
-// Generated based on input data from Intel's XED disassembler (in particular, all_dec_instructions.txt)
-require "../decoder-syntax.k"
-module GENERATED-DECODER-RULES-COMMON
-    imports DOMAINS
-    imports COLLECTIONS
-    imports DECODER-SYNTAX
-    imports DECODER-CONFIGURATION
-
-    syntax K ::= "DecoderError"
-    
-    syntax K ::= "ScanForDisp"
-    
-    syntax K ::= "ScanForImmediate"
-    
-    syntax OperandVisibility ::= "SUPPRESSED" | "IMPLICIT" | "EXPLICIT"
-    syntax OperandWidth ::= Int | "AUTO" | "VECTOR" | "SSZ" | "ASZ" // Explicit bit count, AUTO for register arguments whose width is inferred from its value, and VECTOR for NELEM*ELEMSIZE
-    syntax KResult ::= OperandWidth
-    syntax KItem ::= OperandMetadata(KItem, Bool, OperandVisibility, KItem, OperandWidth, OperandWidth, OperandWidth) // Name, IsWriteMask, Visibility, C-Type, Wdith16, Width32, Width64
-"""
+def print_outreg_to(name):
+    print("syntax K ::= \"OUTREGTo" + name + "\"")
+    print("rule <k> OUTREGTo" + name + " => . ... </k>")
+    print("<OUTREG> M </OUTREG>")
+    print("<" + name + "> _ => M </" + name + ">")
+
+
+print("require \"decoder-syntax.k\"")
+print("module GENERATED-DECODER-RULES")
+print("imports DOMAINS")
+print("imports COLLECTIONS")
+print("imports DECODER-SYNTAX")
+print("imports DECODER-CONFIGURATION")
+print("syntax K ::= \"DecoderError\"")
+print("syntax K ::= \"ScanForDisp\"")
+print("syntax K ::= \"ScanForImmediate\"")
+print('syntax OperandVisibility ::= "SUPPRESSED" | "IMPLICIT" | "EXPLICIT"')
+print('syntax OperandWidth ::= Int | "AUTO" | "VECTOR" | "SSZ" | "ASZ"') # Explicit bit count, AUTO for register arguments whose width is inferred from its value, and VECTOR for NELEM*ELEMSIZE
+print('syntax KResult ::= OperandWidth')
+print("syntax KItem ::= OperandMetadata(KItem, Bool, OperandVisibility, KItem, OperandWidth, OperandWidth, OperandWidth)") # Name, IsWriteMask, Visibility, C-Type, Wdith16, Width32, Width64
 
 outregs_done = set()
 for name in nonterminals.nonterminals_map:
     for alternative in nonterminals.nonterminals_map[name]:
         for assign in alternative.consequent.get(nonterminals.ComplexAssignment.__name__, []):
             if assign.name != "OUTREG" and assign.name not in outregs_done:
-                generated_syntax_contents += make_outreg_rule(assign.name)
+                print_outreg_to(assign.name)
                 outregs_done.add(assign.name)
 
 attributes_done = set()
@@ -175,62 +154,33 @@ for inst in instructions.instruction_list:
     for operand in inst.operands:
         assign = operand[0]
         if assign.__class__.__name__ == "ComplexAssignment" and assign.name not in outregs_done:
-            generated_syntax_contents += make_outreg_rule(assign.name)
+            print_outreg_to(assign.name)
             outregs_done.add(assign.name)
     attributes_done |= set(inst.attributes)
     operand_metadata_ids |= set([id_ for (_, id_, _, _, _, _, _, _) in inst.operands])
     operand_sort_set |= set([sort for (_, _, _, _, sort, _, _, _) in inst.operands])
 
-generated_syntax_contents += "    syntax KItem ::= " + " | ".join(['"A_{0}"'.format(attribute) for attribute in attributes_done]) + "\n"
-generated_syntax_contents += "    syntax KItem ::= " + " | ".join(['"{0}"'.format(id_) for id_ in operand_metadata_ids]) + "\n"
-generated_syntax_contents += "    syntax KItem ::= " + " | ".join(['"{0}"'.format(sort) for sort in operand_sort_set]) + "\n"
+print("syntax KItem ::= " + " | ".join(['"A_{0}"'.format(attribute) for attribute in attributes_done]))
+print("syntax KItem ::= " + " | ".join(['"{0}"'.format(id_) for id_ in operand_metadata_ids]))
+print("syntax KItem ::= " + " | ".join(['"{0}"'.format(sort) for sort in operand_sort_set]))
 
 
-generated_syntax_contents += "    syntax K ::= \"Instruction\"\n"
-generated_syntax_contents += "    syntax IClass ::= " + " | ".join(list(set(["\"{0}\"".format(inst.iclass) for inst in instructions.instruction_list]))) + "\n"
+print("syntax K ::= \"Instruction\"")
+iclasses = list(set(["\"{0}\"".format(inst.iclass) for inst in instructions.instruction_list]))
+print("syntax IClass ::= " + " | ".join(iclasses))
+
+desired = set([n.upper() for n in sys.argv[1:]])
+
+for inst in instructions.instruction_list:
+    if len(desired) == 0 or inst.iclass in desired:
+        print("// UNAME: " + inst.uname)
+        print(gen_from_inst(inst).generate_rule().replace("XED_", ""))
 
 for name in nonterminals.nonterminals_map:
     if "SPLITTER" in name or "PREFIX" in name:
         continue
-    generated_syntax_contents += "    syntax K ::= \"" + name + "\"\n"
+    print("syntax K ::= \"" + name + "\"")
     for alternative in nonterminals.nonterminals_map[name]:
-        generated_syntax_contents += gen_from_nonterminal(alternative).generate_rule() + "\n"
+        print(gen_from_nonterminal(alternative).generate_rule().replace("XED_", ""))
 
-generated_syntax_contents += "endmodule\n"
-
-write_to_file(generated_syntax_name, generated_syntax_contents)
-
-definition_name = "{0}-definition.k"
-definition_contents = """require "{0}"
-module {1}-DEFINITION
-   imports GENERATED-DECODER-RULES-COMMON 
-{2}
-endmodule
-"""
-
-desired_iclasses = set([name.upper() for name in sys.argv[1:]])
-
-inst_map = {}
-for inst in instructions.instruction_list:
-    if len(desired_iclasses) == 0 or inst.iclass in desired_iclasses:
-        contents = inst_map.get(inst.iclass, "")
-        contents += gen_from_inst(inst).generate_rule()
-        contents += "\n"
-        inst_map[inst.iclass] = contents
-
-definition_modules = []
-for iclass in inst_map:
-    name = definition_name.format(iclass)
-    write_to_file(name, definition_contents.format(generated_syntax_name, iclass, inst_map[iclass]))
-    definition_modules.append((name, "{0}-DEFINITION".format(iclass)))
-
-imported_file_name = "generated-header.k"
-imported_file_contents = """
-require "{0}"
-{1}
-module GENERATED-DECODER-RULES
-{2}
-endmodule
-""".format(generated_syntax_name, "\n".join(["require \"{0}\"".format(filename) for (filename, _) in definition_modules]), "\n".join(["imports {0}".format(module_name) for (_, module_name) in definition_modules]))
-
-write_to_file(imported_file_name, imported_file_contents)
+print("endmodule")
diff --git a/generator/generate_all.py b/generator/generate_all.py
deleted file mode 100755
index a18d2db..0000000
--- a/generator/generate_all.py
+++ /dev/null
@@ -1,186 +0,0 @@
-#!/usr/bin/python3
-
-#BEGIN_LEGAL 
-# 
-# A Re-Implementation of Intels disassembler from XED in K semantics.
-#
-# Copyright (c) 2018 Intel Corporation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#                         
-# END_LEGAL
-
-import instructions
-import nonterminals
-import sys
-from kcodegen import kRewrite
-
-class FreshVariableGenerator(object):
-    def __init__(self, prefix="I"):
-        self._prefix = prefix
-        self._val = 0
-        self.next_variable()
-
-    def next_variable(self):
-        self._current = self._prefix + str(self._val)
-        self._val += 1
-        return self._current
-
-    def last_variable(self):
-        return self._current
-
-def gen_from_nonterminal(nonterm, additional = ""):
-    rewrite = kRewrite()
-    fresh_vars = FreshVariableGenerator()
-
-    pattern = nonterm.antecedent
-    assignments = nonterm.consequent
-
-    literal = " ".join([str(int(match.pattern, 16)) for match in pattern.get(nonterminals.NoncapturingMatch.__name__, [])]) 
-    if len(literal) > 0:
-        rewrite.add_literal_match("dynamicDecoderBuffer", literal + " _:Ints ")
-
-    reads = [eq for eq in pattern.get(nonterminals.Equation.__name__, [])]
-    writes = [assign for assign in assignments.get(nonterminals.SimpleAssignment.__name__, [])]
-
-    bound_names = {}
-    matches = []
-    for read in reads:
-        for write in writes:
-            if read.name == write.name:
-                rewrite.add_rewrite(read.name, read.val, write.val)
-                bound_names[read.name] = read.val
-
-    for cap in pattern.get(nonterminals.Capture.__name__, []):
-        assert len(cap.vars) > 0
-        name = cap.name
-        value = cap.vars[0].required_val
-        if value is not None:
-            bound_names[name] = value
-            rewrite.add_literal_match(name, value)
-
-    inequalities = []
-    for eq in pattern.get(nonterminals.Equation.__name__, []):
-        if eq.name in bound_names:
-            assert (bound_names[eq.name] == eq.val) == eq.is_equal # Either both equal, or both not equal.
-        else:
-            if eq.is_equal:
-                rewrite.add_literal_match(eq.name, eq.val)
-            else:
-                rewrite.add_variable(eq.name, fresh_vars.next_variable(), "Int")
-                inequalities.append((fresh_vars.last_variable(), eq.val))
-    if len(inequalities) > 0:
-        rewrite.set_condition(" andBool ".join(["{0} =/=Int {1}".format(name, value) for (name, value) in inequalities]))
-
-
-    if len(pattern.get(nonterminals.OtherwiseCondition.__name__, [])) > 0:
-        rewrite.add_attribute("owise")
-
-
-    for assign in assignments.get(nonterminals.SimpleAssignment.__name__, []):
-        if assign.name not in bound_names:
-            rewrite.add_rewrite(assign.name, "_", assign.val)
-
-    decode_nonterminals = " ~> ".join([nonterm.name for nonterm in pattern.get(nonterminals.NonterminalCondition.__name__, [])])
-
-    if len(additional) > 0:
-        decode_nonterminals += (" ~> " if len(decode_nonterminals) > 0 else "") + additional
-
-    for assign in assignments.get(nonterminals.ComplexAssignment.__name__, []):
-        decode_nonterminals += (" ~> " if len(decode_nonterminals) > 0 else "") + assign.func_name + (" ~> OUTREGTo" + assign.name if assign.name != "OUTREG" else "")
-
-    if len(assignments.get(nonterminals.DecoderError.__name__, [])) > 0:
-        rewrite.add_rewrite("k", nonterm.name, "DecoderError", False)
-    else:
-        rewrite.add_rewrite("k", nonterm.name, decode_nonterminals if len(decode_nonterminals) else ".", False)
-
-    return rewrite
-
-def gen_from_inst(inst): 
-    ret = gen_from_nonterminal(inst, "ScanForDisp ~> ScanForImmediate")
-    ret.add_rewrite("ICLASS", "_", inst.iclass)
-    ret.add_rewrite("INUM", "_", inst.id)
-    ret.add_rewrite("CATEGORY", "_", "\"CATEGORY_{0}\"".format(inst.category))
-    ret.add_rewrite("INAME", "_", "\"" + inst.iname + "\"")
-    ret.add_rewrite("ATTRIBUTES", "_", "{0}".format(" ".join(["ListItem(A_{0})".format(name) for name in inst.attributes])) if len(inst.attributes) > 0 else ".List")
-    ret.add_rewrite("OPERANDS", "_", " ".join(["ListItem(OperandMetadata({0},{1},{2},{3},{4},{5},{6}))".format(name, str(mask).lower(), vis, sort, width16, width32, width64) for (_, name, mask, vis, sort, width16, width32, width64) in inst.operands]) if len(inst.operands) > 0 else ".List")
-    if not inst.has_vexvalid:
-        ret.add_literal_match("VEXVALID", "0")
-    return ret
-
-def print_outreg_to(name):
-    print("syntax K ::= \"OUTREGTo" + name + "\"")
-    print("rule <k> OUTREGTo" + name + " => . ... </k>")
-    print("<OUTREG> M </OUTREG>")
-    print("<" + name + "> _ => M </" + name + ">")
-
-
-print("require \"decoder-syntax.k\"")
-print("module GENERATED-DECODER-RULES")
-print("imports DOMAINS")
-print("imports COLLECTIONS")
-print("imports DECODER-SYNTAX")
-print("imports DECODER-CONFIGURATION")
-print("syntax K ::= \"DecoderError\"")
-print("syntax K ::= \"ScanForDisp\"")
-print("syntax K ::= \"ScanForImmediate\"")
-print('syntax OperandVisibility ::= "SUPPRESSED" | "IMPLICIT" | "EXPLICIT"')
-print('syntax OperandWidth ::= Int | "AUTO" | "VECTOR" | "SSZ" | "ASZ"') # Explicit bit count, AUTO for register arguments whose width is inferred from its value, and VECTOR for NELEM*ELEMSIZE
-print('syntax KResult ::= OperandWidth')
-print("syntax KItem ::= OperandMetadata(KItem, Bool, OperandVisibility, KItem, OperandWidth, OperandWidth, OperandWidth)") # Name, IsWriteMask, Visibility, C-Type, Wdith16, Width32, Width64
-
-outregs_done = set()
-for name in nonterminals.nonterminals_map:
-    for alternative in nonterminals.nonterminals_map[name]:
-        for assign in alternative.consequent.get(nonterminals.ComplexAssignment.__name__, []):
-            if assign.name != "OUTREG" and assign.name not in outregs_done:
-                print_outreg_to(assign.name)
-                outregs_done.add(assign.name)
-
-attributes_done = set()
-operand_metadata_ids = set()
-operand_sort_set = set()
-for inst in instructions.instruction_list:
-    for operand in inst.operands:
-        assign = operand[0]
-        if assign.__class__.__name__ == "ComplexAssignment" and assign.name not in outregs_done:
-            print_outreg_to(assign.name)
-            outregs_done.add(assign.name)
-    attributes_done |= set(inst.attributes)
-    operand_metadata_ids |= set([id_ for (_, id_, _, _, _, _, _, _) in inst.operands])
-    operand_sort_set |= set([sort for (_, _, _, _, sort, _, _, _) in inst.operands])
-
-print("syntax KItem ::= " + " | ".join(['"A_{0}"'.format(attribute) for attribute in attributes_done]))
-print("syntax KItem ::= " + " | ".join(['"{0}"'.format(id_) for id_ in operand_metadata_ids]))
-print("syntax KItem ::= " + " | ".join(['"{0}"'.format(sort) for sort in operand_sort_set]))
-
-
-print("syntax K ::= \"Instruction\"")
-iclasses = list(set(["\"{0}\"".format(inst.iclass) for inst in instructions.instruction_list]))
-print("syntax IClass ::= " + " | ".join(iclasses))
-
-desired = set([n.upper() for n in sys.argv[1:]])
-
-for inst in instructions.instruction_list:
-    if len(desired) == 0 or inst.iclass in desired:
-        print("// UNAME: " + inst.uname)
-        print(gen_from_inst(inst).generate_rule().replace("XED_", ""))
-
-for name in nonterminals.nonterminals_map:
-    if "SPLITTER" in name or "PREFIX" in name:
-        continue
-    print("syntax K ::= \"" + name + "\"")
-    for alternative in nonterminals.nonterminals_map[name]:
-        print(gen_from_nonterminal(alternative).generate_rule().replace("XED_", ""))
-
-print("endmodule")
diff --git a/test-decoder.k b/test-decoder.k
new file mode 100644
index 0000000..4f60c32
--- /dev/null
+++ b/test-decoder.k
@@ -0,0 +1,57 @@
+/*BEGIN_LEGAL 
+ *
+ * Adapted from Intel's XED (Copyright (c) 2018 Intel Corporation)
+ *                         
+ * END_LEGAL */
+
+require "decoder.k"
+
+module TEST-DECODER-SYNTAX
+  imports DOMAINS-SYNTAX
+
+  syntax HexToken ::= r"0x[0-9a-fA-F]+" [token, prec(2)]
+
+  syntax Stmt ::= "Disassemble" "(" HexToken "," HexToken ")"
+  syntax Stmts ::= List{Stmt, ";"}
+
+  syntax Pgm ::= Stmts ";"
+endmodule
+
+module TEST-DECODER-CONVERSIONS
+  imports DECODER-INTERFACE
+  imports DOMAINS
+
+  syntax HexTokens ::= List{HexToken, " "}
+
+  syntax Int ::= HexStringToInt(String) [function]
+  rule HexStringToInt(S:String) => String2Base(S, 16)
+
+  syntax String ::= StringifyHexToken(HexToken) [function, hook(STRING.token2string)]
+
+  syntax String ::= removeFirstTwoChars(String) [function]
+  rule removeFirstTwoChars(S) => substrString(S, 2, lengthString(S))
+
+  syntax String ::= HexTokenToString(HexToken) [function]
+  rule HexTokenToString(H) => removeFirstTwoChars(StringifyHexToken(H))
+
+  syntax Ints ::= HexTokenToInts(HexToken) [function]
+  syntax Ints ::= ImplHexTokenToInts(String) [function]
+
+  rule HexTokenToInts(Ht) => ImplHexTokenToInts(HexTokenToString(Ht))
+
+  rule ImplHexTokenToInts("") => .Ints
+  rule ImplHexTokenToInts(S) => String2Base(substrString(S, 0, 2), 16) ImplHexTokenToInts(substrString(S, 2, lengthString(S))) requires 2 dividesInt lengthString(S) andBool lengthString(S) >Int 0
+
+  syntax Int ::= HexTokenToInt(HexToken) [function]
+  rule HexTokenToInt(H) => HexStringToInt(HexTokenToString(H))
+
+  syntax KResult ::= HexToken
+endmodule
+
+module TEST-DECODER
+  imports TEST-DECODER-SYNTAX
+  imports TEST-DECODER-CONVERSIONS
+
+  configuration <k> $PGM:Pgm </k>
+                <decoder/>
+endmodule
-- 
GitLab