about summary refs log tree commit diff stats
path: root/src/miasm/arch/mep/arch.py
diff options
context:
space:
mode:
authorTheofilos Augoustis <theofilos.augoustis@gmail.com>2025-10-14 09:09:29 +0000
committerTheofilos Augoustis <theofilos.augoustis@gmail.com>2025-10-14 09:09:29 +0000
commit579cf1d03fb932083e6317967d1613d5c2587fb6 (patch)
tree629f039935382a2a7391bce9253f6c9968159049 /src/miasm/arch/mep/arch.py
parent51c15d3ea2e16d4fc5f0f01a3b9befc66b1f982e (diff)
downloadfocaccia-miasm-ta/nix.tar.gz
focaccia-miasm-ta/nix.zip
Convert to src-layout ta/nix
Diffstat (limited to 'src/miasm/arch/mep/arch.py')
-rw-r--r--src/miasm/arch/mep/arch.py2080
1 files changed, 2080 insertions, 0 deletions
diff --git a/src/miasm/arch/mep/arch.py b/src/miasm/arch/mep/arch.py
new file mode 100644
index 00000000..ed7813ca
--- /dev/null
+++ b/src/miasm/arch/mep/arch.py
@@ -0,0 +1,2080 @@
+# Toshiba MeP-c4 - miasm architecture definition
+# Guillaume Valadon <guillaume@valadon.net>
+
+from builtins import range
+from miasm.core.cpu import *
+from miasm.core.utils import Disasm_Exception
+from miasm.expression.expression import ExprId, ExprInt, ExprLoc, \
+    ExprMem, ExprOp, is_expr
+from miasm.core.asm_ast import AstId, AstMem
+
+from miasm.arch.mep.regs import *
+import miasm.arch.mep.regs as mep_regs_module  # will be used to set mn_mep.regs
+from miasm.ir.ir import color_expr_html
+
+
+# Note: pyparsing is used to alter the way special operands are parsed
+from pyparsing import Literal, Group, Word, hexnums
+
+
+# These definitions will help parsing dereferencing instructions (i.e. that uses
+# parenthesis) with pyparsing
+LPARENTHESIS = Literal("(")
+RPARENTHESIS = Literal(")")
+PLUSSIGN = Literal("+")
+HEX_INTEGER = str_int_pos | str_int_neg
+
+
+def ExprInt2SignedString(expr, pos_fmt="%d", neg_fmt="%d", size=None, offset=0):
+    """Return the signed string corresponding to an ExprInt
+
+       Note: this function is only useful to mimic objdump output"""
+
+    # Apply a mask to the integer
+    if size is None:
+        mask_length = expr.size
+    else:
+        mask_length = size
+    mask = (1 << mask_length) - 1
+    value = int(expr) & mask
+
+    # Return a signed integer if necessary
+    if (value >> mask_length - 1) == 1:
+        value = offset - ((value ^ mask) + 1)
+        if value < 0:
+            return "-" + neg_fmt % -value
+    else:
+        value += offset
+
+    return pos_fmt % value
+
+
+class instruction_mep(instruction):
+    """Generic MeP-c4 instruction
+
+    Notes:
+        - this object is used to build internal miasm instructions based
+          on mnemonics
+        - it must be implemented !
+    """
+
+    @staticmethod
+    def arg2str(expr, pos=None, loc_db=None):
+        """Convert mnemonics arguments into readable strings according to the
+        MeP-c4 architecture manual and their internal types
+
+        Notes:
+            - it must be implemented ! However, a simple 'return str(expr)'
+              could do the trick.
+            - it is used to mimic objdump output
+
+        Args:
+            expr: argument as a miasm expression
+            pos: position index in the arguments list
+        """
+
+        if isinstance(expr, ExprId) or isinstance(expr, ExprInt):
+            return str(expr)
+
+        elif isinstance(expr, ExprLoc):
+            if loc_db is not None:
+                return loc_db.pretty_str(expr.loc_key)
+            else:
+                return str(expr)
+
+        elif isinstance(expr, ExprMem) and (isinstance(expr.ptr, ExprId) or isinstance(expr.ptr, ExprInt)):
+            return "(%s)" % expr.ptr
+
+        elif isinstance(expr, ExprMem) and isinstance(expr.ptr, ExprOp):
+            return "0x%X(%s)" % (int(expr.ptr.args[1]), expr.ptr.args[0])
+
+        # Raise an exception if the expression type was not processed
+        message = "instruction_mep.arg2str(): don't know what \
+                   to do with a '%s' instance." % type(expr)
+        raise Disasm_Exception(message)
+
+    @staticmethod
+    def arg2html(expr, pos=None, loc_db=None):
+        """Convert mnemonics arguments into readable html strings according to the
+        MeP-c4 architecture manual and their internal types
+
+        Notes:
+            - it must be implemented ! However, a simple 'return str(expr)'
+              could do the trick.
+            - it is used to mimic objdump output
+
+        Args:
+            expr: argument as a miasm expression
+            pos: position index in the arguments list
+        """
+
+        if isinstance(expr, ExprId) or isinstance(expr, ExprInt) or isinstance(expr, ExprLoc):
+            return color_expr_html(expr, loc_db)
+
+        elif isinstance(expr, ExprMem) and (isinstance(expr.ptr, ExprId) or isinstance(expr.ptr, ExprInt)):
+            return "(%s)" % color_expr_html(expr.ptr, loc_db)
+
+        elif isinstance(expr, ExprMem) and isinstance(expr.ptr, ExprOp):
+            return "%s(%s)" % (
+                color_expr_html(expr.ptr.args[1], loc_db),
+                color_expr_html(expr.ptr.args[0], loc_db)
+            )
+
+        # Raise an exception if the expression type was not processed
+        message = "instruction_mep.arg2str(): don't know what \
+                   to do with a '%s' instance." % type(expr)
+        raise Disasm_Exception(message)
+
+    def __str__(self):
+        """Return the mnemonic as a string.
+
+        Note:
+            - it is not mandatory as the instruction class already implement
+              it. It used to get rid of the padding between the opcode and the
+              arguments.
+            - most of this code is copied from miasm/core/cpu.py
+        """
+
+        o = "%s" % self.name
+
+        if self.name == "SSARB":
+            # The first operand is displayed in decimal, not in hex
+            o += " %d" % int(self.args[0])
+            o += self.arg2str(self.args[1])
+
+        elif self.name in ["MOV", "ADD"] and isinstance(self.args[1], ExprInt):
+            # The second operand is displayed in decimal, not in hex
+            o += " " + self.arg2str(self.args[0])
+            o += ", %s" % ExprInt2SignedString(self.args[1])
+
+        elif "CPI" in self.name:
+            # The second operand ends with the '+' sign
+            o += " " + self.arg2str(self.args[0])
+            deref_reg_str = self.arg2str(self.args[1])
+            o += ", %s+)" % deref_reg_str[:-1]  # GV: looks ugly
+
+        elif self.name[0] in ["S", "L"] and self.name[-3:] in ["CPA", "PM0", "PM1"]:
+            # The second operand ends with the '+' sign
+            o += " " + self.arg2str(self.args[0])
+            deref_reg_str = self.arg2str(self.args[1])
+            o += ", %s+)" % deref_reg_str[:-1]  # GV: looks ugly
+            # The third operand is displayed in decimal, not in hex
+            o += ", %s" % ExprInt2SignedString(self.args[2])
+
+        elif len(self.args) == 2 and self.name in ["SB", "SH", "LBU", "LB", "LH", "LW"] and \
+                isinstance(self.args[1], ExprMem) and isinstance(self.args[1].ptr, ExprOp):  # Major Opcodes #12
+            # The second operand is an offset to a register
+            o += " " + self.arg2str(self.args[0])
+            o += ", %s" % ExprInt2SignedString(self.args[1].ptr.args[1], "0x%X")
+            o += "(%s)" % self.arg2str(self.args[1].ptr.args[0])
+
+        elif len(self.args) == 2 and self.name in ["SWCP", "LWCP", "SMCP", "LMCP"] \
+                and isinstance(self.args[1], ExprMem) and isinstance(self.args[1].ptr, ExprOp):  # Major Opcodes #12
+            # The second operand is an offset to a register
+            o += " " + self.arg2str(self.args[0])
+            o += ", %s" % ExprInt2SignedString(self.args[1].ptr.args[1])
+            o += "(%s)" % self.arg2str(self.args[1].ptr.args[0])
+
+        elif self.name == "SLL" and isinstance(self.args[1], ExprInt):  # Major Opcodes #6
+            # The second operand is displayed in hex, not in decimal
+            o += " " + self.arg2str(self.args[0])
+            o += ", 0x%X" % int(self.args[1])
+
+        elif self.name in ["ADD3", "SLT3"] and isinstance(self.args[2], ExprInt):
+            o += " %s" % self.arg2str(self.args[0])
+            o += ", %s" % self.arg2str(self.args[1])
+            # The third operand is displayed in decimal, not in hex
+            o += ", %s" % ExprInt2SignedString(self.args[2], pos_fmt="0x%X")
+
+        elif self.name == "(RI)":
+            return o
+
+        else:
+            args = []
+            if self.args:
+                o += " "
+            for i, arg in enumerate(self.args):
+                if not is_expr(arg):
+                    raise ValueError('zarb arg type')
+                x = self.arg2str(arg, pos=i)
+                args.append(x)
+            o += self.gen_args(args)
+
+        return o
+
+    def breakflow(self):
+        """Instructions that stop a basic block."""
+
+        if self.name in ["BRA", "BEQZ", "BNEZ", "BEQI", "BNEI", "BLTI", "BGEI", "BEQ", "BNE", "BSR"]:
+            return True
+
+        if self.name in ["JMP", "JSR", "RET"]:
+            return True
+
+        if self.name in ["RETI", "HALT", "SLEEP"]:
+            return True
+
+        return False
+
+    def splitflow(self):
+        """Instructions that splits a basic block, i.e. the CPU can go somewhere else."""
+
+        if self.name in ["BEQZ", "BNEZ", "BEQI", "BNEI", "BLTI", "BGEI", "BEQ", "BNE", "BSR"]:
+            return True
+
+        return False
+
+    def dstflow(self):
+        """Instructions that explicitly provide the destination."""
+
+        if self.name in ["BRA", "BEQZ", "BNEZ", "BEQI", "BNEI", "BLTI", "BGEI", "BEQ", "BNE", "BSR"]:
+            return True
+
+        if self.name in ["JMP"]:
+            return True
+
+        return False
+
+    def dstflow2label(self, loc_db):
+        """Set the label for the current destination.
+
+           Note: it is used at disassembly"""
+
+        if self.name == "JMP" and isinstance(self.args[0], ExprId):
+            # 'JMP RM' does not provide the destination
+            return
+
+        # Compute the correct address
+        num = self.get_dst_num()
+        addr = int(self.args[num])
+        if not self.name == "JMP":
+            addr += self.offset
+
+        # Get a new label at the address
+        label = loc_db.get_or_create_offset_location(addr)
+
+        # Assign the label to the correct instruction argument
+        self.args[num] = ExprLoc(label, self.args[num].size)
+
+    def get_dst_num(self):
+        """Get the index of the argument that points to the instruction destination."""
+
+        if self.name[-1] == "Z":
+            num = 1
+        elif self.name in ["BEQI", "BNEI", "BLTI", "BGEI", "BEQ", "BNE"]:
+            num = 2
+        else:
+            num = 0
+
+        return num
+
+    def getdstflow(self, loc_db):
+        """Get the argument that points to the instruction destination."""
+
+        num = self.get_dst_num()
+        return [self.args[num]]
+
+    def is_subcall(self):
+        """Instructions used to call sub functions."""
+
+        return self.name in ["JSR", "BSR"]
+
+    def fixDstOffset(self):
+        """Fix/correct the instruction immediate according to the current offset
+
+           Note: - it is used at assembly
+                 - code inspired by miasm/arch/mips32/arch.py"""
+
+        if self.name == "JMP" and isinstance(self.args[0], ExprInt):
+            # 'JMP IMMEDIATE' does not need to be fixed
+            return
+
+        # Get the argument that needs to be fixed
+        if not len(self.args):
+            return
+        num = self.get_dst_num()
+        expr = self.args[num]
+
+        # Check that the argument can be fixed
+        if self.offset is None:
+            raise ValueError("Symbol not resolved %s" % self.l)
+        if not isinstance(expr, ExprInt):
+            return
+
+        # Adjust the immediate according to the current instruction offset
+        off = expr.arg - self.offset
+        if int(off % 2):
+            raise ValueError("Strange offset! %r" % off)
+        self.args[num] = ExprInt(off, 32)
+
+
+class mep_additional_info(object):
+    """Additional MeP instructions information
+    """
+
+    def __init__(self):
+        self.except_on_instr = False
+
+
+class mn_mep(cls_mn):
+    """Toshiba MeP-c4 disassembler & assembler
+    """
+
+    # Define variables that stores information used to disassemble & assemble
+    # Notes: - these variables are mandatory
+    #        - they could be moved to the cls_mn class
+
+    num = 0  # holds the number of mnemonics
+
+    all_mn = list()  # list of mnenomnics, converted to metamn objects
+
+    all_mn_mode = defaultdict(list)  # mneomnics, converted to metamn objects
+                                     # Note:
+                                     #   - the key is the mode # GV: what is it ?
+                                     #   - the data is a list of mnemonics
+
+    all_mn_name = defaultdict(list)  # mnenomnics strings
+                                     # Note:
+                                     #   - the key is the mnemonic string
+                                     #   - the data is the corresponding
+                                     #     metamn object
+
+    all_mn_inst = defaultdict(list)  # mnemonics objects
+                                     # Note:
+                                     #   - the key is the mnemonic Python class
+                                     #   - the data is an instantiated object
+
+    bintree = dict()  # Variable storing internal values used to guess a
+                      # mnemonic during disassembly
+
+    # Defines the instruction set that will be used
+    instruction = instruction_mep
+
+    # Python module that stores registers information
+    regs = mep_regs_module
+
+    # Default delay slot
+    # Note:
+    #   - mandatory for the miasm Machine
+    delayslot = 0
+
+    # Architecture name
+    name = "mep"
+
+    # PC name depending on architecture attributes (here, l or b)
+    pc = {'l': PC, 'b': PC}
+
+    def additional_info(self):
+        """Define instruction side effects # GV: not fully understood yet
+
+        When used, it must return an object that implements specific
+        variables, such as except_on_instr.
+
+        Notes:
+            - it must be implemented !
+            - it could be moved to the cls_mn class
+        """
+
+        return mep_additional_info()
+
+    @classmethod
+    def gen_modes(cls, subcls, name, bases, dct, fields):
+        """Ease populating internal variables used to disassemble & assemble, such
+        as self.all_mn_mode, self.all_mn_name and self.all_mn_inst
+
+        Notes:
+            - it must be implemented !
+            - it could be moved to the cls_mn class. All miasm architectures
+              use the same code
+
+        Args:
+            cls: ?
+            sublcs:
+            name: mnemonic name
+            bases: ?
+            dct: ?
+            fields: ?
+
+        Returns:
+            a list of ?
+
+        """
+
+        dct["mode"] = None
+        return [(subcls, name, bases, dct, fields)]
+
+    @classmethod
+    def getmn(cls, name):
+        """Get the mnemonic name
+
+        Notes:
+            - it must be implemented !
+            - it could be moved to the cls_mn class. Most miasm architectures
+              use the same code
+
+        Args:
+            cls:  the mnemonic class
+            name: the mnemonic string
+        """
+
+        return name.upper()
+
+    @classmethod
+    def getpc(cls, attrib=None):
+        """"Return the ExprId that represents the Program Counter.
+
+        Notes:
+            - mandatory for the symbolic execution
+            - PC is defined in regs.py
+
+        Args:
+           attrib: architecture dependent attributes (here, l or b)
+        """
+
+        return PC
+
+    @classmethod
+    def getsp(cls, attrib=None):
+        """"Return the ExprId that represents the Stack Pointer.
+
+        Notes:
+            - mandatory for the symbolic execution
+            - SP is defined in regs.py
+
+        Args:
+           attrib: architecture dependent attributes (here, l or b)
+        """
+
+        return SP
+
+    @classmethod
+    def getbits(cls, bitstream, attrib, start, n):
+        """Return an integer of n bits at the 'start' offset
+
+           Note: code from miasm/arch/mips32/arch.py
+        """
+
+        # Return zero if zero bits are requested
+        if not n:
+            return 0
+
+        o = 0  # the returned value
+        while n:
+            # Get a byte, the offset is adjusted according to the endianness
+            offset = start // 8  # the offset in bytes
+            n_offset = cls.endian_offset(attrib, offset)  # the adjusted offset
+            c = cls.getbytes(bitstream, n_offset, 1)
+            if not c:
+                raise IOError
+
+            # Extract the bits value
+            c = ord(c)
+            r = 8 - start % 8
+            c &= (1 << r) - 1
+            l = min(r, n)
+            c >>= (r - l)
+            o <<= l
+            o |= c
+            n -= l
+            start += l
+
+        return o
+
+    @classmethod
+    def endian_offset(cls, attrib, offset):
+        """Adjust the byte offset according to the endianness"""
+
+        if attrib == "l":  # Little Endian
+            if offset % 2:
+                return offset - 1
+            else:
+                return offset + 1
+
+        elif attrib == "b":  # Big Endian
+            return offset
+
+        else:
+            raise NotImplementedError("Bad MeP endianness")
+
+    def value(self, mode):
+        """Adjust the assembled instruction based on the endianness
+
+           Note: code inspired by miasm/arch/mips32/arch.py
+        """
+
+        # Get the candidated
+        candidates = super(mn_mep, self).value(mode)
+
+        if mode == "l":
+            # Invert bytes per 16-bits
+            for i in range(len(candidates)):
+                tmp = candidates[i][1] + candidates[i][0]
+                if len(candidates[i]) == 4:
+                    tmp += candidates[i][3] + candidates[i][2]
+                candidates[i] = tmp
+            return candidates
+
+        elif mode == "b":
+            return candidates
+
+        else:
+            raise NotImplementedError("Bad MeP endianness (%s)" % mode)
+
+
+def addop(name, fields, args=None, alias=False):
+    """Dynamically create the "name" object
+
+    Notes:
+        - it could be moved to a generic function such as:
+          addop(name, fields, cls_mn, args=None, alias=False).
+        - most architectures use the same code
+
+    Args:
+        name:   the mnemonic name
+        fields: used to fill the object.__dict__'fields' attribute # GV: not understood yet
+        args:   used to fill the object.__dict__'fields' attribute # GV: not understood yet
+        alias:  used to fill the object.__dict__'fields' attribute # GV: not understood yet
+    """
+
+    namespace = {"fields": fields, "alias": alias}
+
+    if args is not None:
+        namespace["args"] = args
+
+    # Dynamically create the "name" object
+    type(name, (mn_mep,), namespace)
+
+
+# Define specific operand parsers & converters
+
+def deref2expr(s, l, parse_results):
+    """Convert a parsed dereferenced register to an ExprMem"""
+
+    # Only use the first results
+    parse_results = parse_results[0]
+
+    if type(parse_results[0]) == AstInt and isinstance(parse_results[2], AstId):
+        return AstMem(parse_results[2] + parse_results[0], 32)  # 1 == "(" and 3 == ")"
+
+    elif type(parse_results[0]) == int and isinstance(parse_results[2], AstId):
+        return AstMem(parse_results[2] + AstOp('-', AstInt(-parse_results[0])), 32)  # 1 == "(" and 3 == ")"
+
+    else:
+        return AstMem(parse_results[1], 32)  # 0 == "(" and 2 == ")"
+
+
+deref_reg_parser = Group(LPARENTHESIS + gpr_infos.parser + RPARENTHESIS).setParseAction(deref2expr)
+deref_inc_reg_parser = Group(LPARENTHESIS + gpr_infos.parser + PLUSSIGN + RPARENTHESIS).setParseAction(deref2expr)
+abs24_deref_parser = Group(LPARENTHESIS + HEX_INTEGER + RPARENTHESIS).setParseAction(deref2expr)
+offset_deref_reg_parser = Group(HEX_INTEGER + LPARENTHESIS + gpr_infos.parser + RPARENTHESIS).setParseAction(deref2expr)
+
+# Define registers decoders and encoders
+
+class mep_arg(m_arg):
+    def asm_ast_to_expr(self, arg, loc_db):
+        """Convert AST to expressions
+
+           Note: - code inspired by miasm/arch/mips32/arch.py"""
+
+        if isinstance(arg, AstId):
+            if isinstance(arg.name, ExprId):
+                return arg.name
+            if isinstance(arg.name, str) and arg.name in gpr_names:
+                return None  # GV: why?
+            loc_key = loc_db.get_or_create_name_location(arg.name)
+            return ExprLoc(loc_key, 32)
+
+        elif isinstance(arg, AstMem):
+            addr = self.asm_ast_to_expr(arg.ptr, loc_db)
+            if addr is None:
+                return None
+            return ExprMem(addr, 32)
+
+        elif isinstance(arg, AstInt):
+            return ExprInt(arg.value, 32)
+
+        elif isinstance(arg, AstOp):
+            args = [self.asm_ast_to_expr(tmp, loc_db) for tmp in arg.args]
+            if None in args:
+                return None
+            return ExprOp(arg.op, *args)
+
+        # Raise an exception if the argument was not processed
+        message = "mep_arg.asm_ast_to_expr(): don't know what \
+                   to do with a '%s' instance." % type(arg)
+        raise Exception(message)
+
+class mep_reg(reg_noarg, mep_arg):
+    """Generic Toshiba MeP-c4 register
+
+    Note:
+        - the register size will be set using bs()
+    """
+    reg_info = gpr_infos  # the list of MeP-c4 registers defined in regs.py
+    parser = reg_info.parser  # GV: not understood yet
+
+
+class mep_deref_reg(mep_arg):
+    """Generic Toshiba MeP-c4 dereferenced register
+
+    Note:
+        - the arg2str() method could be defined to change the output string
+    """
+    parser = deref_reg_parser
+
+    def decode(self, v):
+        """Transform the decoded value to a ExprMem(ExprId()) expression"""
+        r = gpr_infos.expr[v]  # get the ExprId, i.e. the register expression
+        self.expr = ExprMem(r, 32)
+        return True
+
+    def encode(self):
+        """Ensure that we have a ExprMem(ExprId()) expression, and return the
+        register value."""
+
+        if not isinstance(self.expr, ExprMem):
+            return False
+        if not isinstance(self.expr.ptr, ExprId):
+            return False
+
+        # Get the ExprId index, i.e. its value
+        self.value = gpr_exprs.index(self.expr.ptr)
+        return True
+
+
+class mep_reg_sp(mep_reg):
+    """Dummy Toshiba MeP-c4 register that represents SP. It is used in
+    instructions that implicitly use SP, such as ADD3.
+    """
+    implicit_reg = SP
+
+    def decode(self, v):
+        """Always return 'implicit_reg."""
+        self.expr = self.implicit_reg
+        return True
+
+    def encode(self):
+        """Do nothing"""
+        return True
+
+
+class mep_reg_tp(mep_reg_sp):
+    """Dummy Toshiba MeP-c4 register that represents TP.
+    """
+    implicit_reg = TP
+
+
+class mep_deref_reg_offset(mep_arg):
+    """Toshiba MeP-c4 dereferenced register that represents SP, plus an
+    offset.
+    """
+    parser = offset_deref_reg_parser
+
+    def decode(self, v):
+        """Modify the decoded value using the previously decoded
+        register id.
+        """
+
+        # Apply the immediate mask
+        se = sign_ext(v & 0xFFFF, 16, 32)  # GV: might not belong here
+        int_id = ExprInt(se, 32)
+
+        # Get the register expression
+        reg_id = gpr_infos.expr[self.parent.reg04_deref.value]
+
+        # Build the internal expression
+        self.expr = ExprMem(reg_id + int_id, 32)
+
+        return True
+
+    def encode(self):
+        """Modify the encoded value. One part is stored in this object, and
+        the other one in reg04_deref.
+        """
+
+        # Verify the expression
+        if not isinstance(self.expr, ExprMem):
+            return False
+        if not isinstance(self.expr.ptr, ExprOp):
+            return False
+
+        # Get the integer and check the upper bound
+        v = int(self.expr.ptr.args[1]) & 0xFFFF
+
+        # Encode the values
+        self.parent.reg04_deref.value = gpr_exprs.index(self.expr.ptr.args[0])
+        self.value = v & 0xFFFF
+        return True
+
+
+class mep_deref_sp_offset(mep_deref_reg):
+    """Dummy Toshiba MeP-c4 dereferenced register that represents SP, plus an
+    offset.
+    Note: it is as generic as possible to ease its use in different instructions
+    """
+    implicit_reg = SP
+    parser = offset_deref_reg_parser
+
+    def decode(self, v):
+        """Modify the decoded value using the previously decoded
+        immediate.
+        """
+
+        immediate = None
+        if getattr(self.parent, "imm7_align4", False):
+            # Apply the immediate mask
+            v = self.parent.imm7_align4.value & 0x1F
+
+            # Shift value such as:
+            #   imm7=iii_ii||00
+            immediate = v << 2
+
+        elif getattr(self.parent, "imm7", False):
+            # Apply the immediate mask
+            immediate = self.parent.imm7.value & 0x7F
+
+        elif getattr(self.parent, "disp7_align2", False):
+            # Apply the immediate mask
+            disp7_align2 = self.parent.disp7_align2.value & 0x3F
+
+            # Shift value such as:
+            #   disp7 = ddd_ddd||0
+            immediate = disp7_align2 << 1
+
+        if immediate is not None:
+            self.expr = ExprMem(self.implicit_reg + ExprInt(immediate, 32), 32)
+            return True
+        else:
+            return False
+
+    def encode(self):
+        """Modify the encoded value. One part is stored in this object, and
+        the other one in a parent immediate.
+        """
+
+        # Verify the expression
+        if not isinstance(self.expr, ExprMem):
+            return False
+        if not isinstance(self.expr.ptr, ExprOp):
+            return False
+        if self.expr.ptr.args[0] != self.implicit_reg:
+            return False
+
+        if getattr(self.parent, "imm7_align4", False):
+
+            # Get the integer and check the upper bound
+            v = int(self.expr.ptr.args[1].arg)
+            if v > 0x80:
+                return False
+
+            # Encode the value
+            self.parent.imm7_align4.value = v >> 2
+
+            return True
+
+        elif getattr(self.parent, "imm7", False):
+
+            # Get the integer and check the upper bound
+            v = int(self.expr.ptr.args[1].arg)
+            if v > 0x80:
+                return False
+
+            # Encode the value
+            self.parent.imm7.value = v
+
+            return True
+
+        elif getattr(self.parent, "disp7_align2", False):
+
+            # Get the integer and check the upper bound
+            v = int(self.expr.ptr.args[1].arg)
+            if v > 0x80:
+                return False
+
+            # Encode the value
+            self.parent.disp7_align2.value = v >> 1
+
+            return True
+
+        return False
+
+
+class mep_deref_tp_offset(mep_deref_sp_offset):
+    """Dummy Toshiba MeP-c4 dereferenced register that represents TP, plus an
+    offset.
+    """
+    implicit_reg = TP
+
+
+class mep_copro_reg(reg_noarg, mep_arg):
+    """Generic Toshiba MeP-c4 coprocessor register
+    """
+    reg_info = copro_gpr_infos  # the list of MeP-c4 coprocessor registers defined in regs.py
+    parser = reg_info.parser  # GV: not understood yet
+
+
+class mep_copro_reg_split(mep_copro_reg):
+    """Generic Toshiba MeP-c4 coprocessor register encode into different fields
+    """
+
+    def decode(self, v):
+        """Modify the decoded value using the previously decoded imm4_noarg.
+        """
+
+        # Apply the immediate mask
+        v = v & self.lmask
+
+        # Shift values such as:
+        #   CRn=NNnnnn
+        crn = (v << 4) + (self.parent.imm4.value & 0xF)
+
+        # Build the internal expression
+        self.expr = ExprId("C%d" % crn, 32)
+        return True
+
+    def encode(self):
+        """Modify the encoded value. One part is stored in this object, and
+        the other one in imm4_noarg.
+        """
+
+        if not isinstance(self.expr, ExprId):
+            return False
+
+        # Get the register and check the upper bound
+        reg_name = self.expr.name
+        if reg_name[0] != "C":
+            return False
+        reg_value = copro_gpr_names.index(reg_name)
+        if reg_value > 0x3f:
+            return False
+
+        # Encode the value into two parts
+        self.parent.imm4.value = (reg_value & 0xF)
+        self.value = (reg_value >> 4) & 0x3
+        return True
+
+
+class mep_deref_inc_reg(mep_deref_reg):
+    """Generic Toshiba MeP-c4 coprocess dereferenced & incremented register
+    """
+    parser = deref_inc_reg_parser
+
+
+# Immediate decoders and encoders
+
+class mep_int32_noarg(int32_noarg):
+    """Generic Toshiba MeP-c4 signed immediate
+
+       Note: encode() is copied from int32_noarg.encode() and modified to allow
+             small (< 32 bits) signed immediate to be manipulated.
+
+    """
+
+    def encode(self):
+        if not isinstance(self.expr, ExprInt):
+            return False
+        v = int(self.expr)
+        # Note: the following lines were commented on purpose
+        #if sign_ext(v & self.lmask, self.l, self.intsize) != v:
+        #    return False
+        v = self.encodeval(v & self.lmask)
+        self.value = v & self.lmask
+        return True
+
+
+class mep_imm(imm_noarg, mep_arg):
+    """Generic Toshiba MeP-c4 immediate
+
+    Note:
+        - the immediate size will be set using bs()
+    """
+    parser = base_expr
+
+
+class mep_imm6(mep_int32_noarg):
+    """Toshiba MeP-c4 signed 6 bits immediate."""
+    parser = base_expr
+    intsize = 6
+    intmask = (1 << intsize) - 1
+    int2expr = lambda self, x: ExprInt(sign_ext(x, self.l, 32), 32)
+
+
+class mep_imm8(mep_int32_noarg):
+    """Toshiba MeP-c4 signed 8 bits immediate."""
+    parser = base_expr
+    intsize = 8
+    intmask = (1 << intsize) - 1
+    int2expr = lambda self, x: ExprInt(sign_ext(x, self.l, 32), 32)
+
+
+class mep_imm16(mep_int32_noarg):
+    """Toshiba MeP-c4 16 bits immediate."""
+    parser = base_expr
+    intsize = 16
+    intmask = (1 << intsize) - 1
+    int2expr = lambda self, x: ExprInt(x, 32)
+
+
+class mep_imm16_signed(mep_int32_noarg):
+    """Toshiba MeP-c4 signed 16 bits immediate."""
+    parser = base_expr
+    intsize = 16
+    intmask = (1 << intsize) - 1
+    int2expr = lambda self, x: ExprInt(sign_ext(x, self.l, 32), 32)
+
+
+class mep_target24(mep_imm):
+    """Toshiba MeP-c4 target24 immediate, as used in JMP
+    """
+
+    def decode(self, v):
+        """Modify the decoded value using the previously decoded imm7.
+        """
+
+        # Apply the immediate mask
+        v = v & self.lmask
+
+        # Shift values such as:
+        #   target24=tttt_tttt_tttt_tttt||TTT_TTTT||0
+        target24 = (v << 8) + ((self.parent.imm7.value & 0x7F) << 1)
+
+        # Build the internal expression
+        self.expr = ExprInt(target24, 32)
+        return True
+
+    def encode(self):
+        """Modify the encoded value. One part is stored in this object, and
+        the other one in imm7.
+        """
+
+        if not isinstance(self.expr, ExprInt):
+            return False
+
+        # Get the integer and apply a mask
+        v = int(self.expr) & 0x00FFFFFF
+
+        # Encode the value into two parts
+        self.parent.imm7.value = (v & 0xFF) >> 1
+        self.value = v >> 8
+        return True
+
+
+class mep_target24_signed(mep_target24):
+    """Toshiba MeP-c4 target24 signed immediate, as used in BSR
+    """
+
+    def decode(self, v):
+        """Perform sign extension
+        """
+
+        mep_target24.decode(self, v)
+        v = int(self.expr)
+        self.expr = ExprInt(sign_ext(v, 24, 32), 32)
+
+        return True
+
+
+class mep_code20(mep_imm):
+    """Toshiba MeP-c4 code20 immediate, as used in DSP1
+    """
+
+    def decode(self, v):
+        """Modify the decoded value using the previously decoded imm4_noarg.
+        """
+
+        # Apply the immediate mask
+        v = v & self.lmask
+
+        # Shift values such as:
+        #   code20=mmmm_cccc_cccc_cccc_cccc
+        code20 = v + ((self.parent.imm4.value & 0xFF) << 16)
+
+        # Build the internal expression
+        self.expr = ExprInt(code20, 32)
+        return True
+
+    def encode(self):
+        """Modify the encoded value. One part is stored in this object, and
+        the other one in imm4_noarg.
+        """
+
+        if not isinstance(self.expr, ExprInt):
+            return False
+
+        # Get the integer and check the upper bound
+        v = int(self.expr.arg)
+        if v > 0xffffff:
+            return False
+
+        # Encode the value into two parts
+        self.parent.imm4 = ((v >> 16) & 0xFF)
+        self.value = v
+        return True
+
+
+class mep_code24(mep_imm):
+    """Toshiba MeP-c4 code24 immediate, as used in CP
+    """
+
+    def decode(self, v):
+        """Modify the decoded value using the previously decoded imm8_CCCC_CCCC.
+        """
+
+        # Shift values such as:
+        #   code24=CCCC_CCCC||cccc_cccc_cccc_cccc
+        code24 = v + ((self.parent.imm8_CCCC_CCCC.value & 0xFF) << 16)
+
+        # Build the internal expression
+        self.expr = ExprInt(code24, 32)
+        return True
+
+    def encode(self):
+        """Modify the encoded value. One part is stored in this object, and
+        the other one in imm8_CCCC_CCCC.
+        """
+
+        if not isinstance(self.expr, ExprInt):
+            return False
+
+        # Get the integer and check the upper bound
+        v = int(self.expr.arg)
+        if v > 0xFFFFFF:
+            return False
+
+        # Encode the value into two parts
+        self.parent.imm8_CCCC_CCCC.value = ((v >> 16) & 0xFF)
+        self.value = v & 0xFFFF
+        return True
+
+
+class mep_imm7_align4(mep_imm):
+    """Toshiba MeP-c4 imm7.align4 immediate, as used in Major #4 opcodes
+    """
+
+    def decode(self, v):
+        """Modify the decoded value.
+        """
+
+        # Apply the immediate mask
+        v = v & self.lmask
+
+        # Shift value such as:
+        #   imm7=iii_ii||00
+        imm7_align4 = v << 2
+
+        # Build the internal expression
+        self.expr = ExprInt(imm7_align4, 32)
+        return True
+
+    def encode(self):
+        """Modify the encoded value.
+        """
+
+        if not isinstance(self.expr, ExprInt):
+            return False
+
+        # Get the integer and check the upper bound
+        v = int(self.expr)
+        if v > 0x80:
+            return False
+
+        # Encode the value
+        self.value = v >> 2
+        return True
+
+
+class mep_imm5_Iiiii (mep_imm):
+    """Toshiba MeP-c4 imm5 immediate, as used in STC & LDC. It encodes a
+    control/special register.
+    """
+
+    reg_info = csr_infos  # the list of MeP-c4 control/special registers defined in regs.py
+    parser = reg_info.parser  # GV: not understood yet
+
+    def decode(self, v):
+        """Modify the decoded value using the previously decoded imm4_iiii
+        """
+
+        # Apply the immediate mask
+        I = v & self.lmask
+
+        # Shift values such as:
+        #   imm5=I||iiii
+        imm5 = (I << 4) + (self.parent.imm4_iiii.value & 0xF)
+
+        # Build the internal register expression
+        self.expr = ExprId(csr_names[imm5], 32)
+        return True
+
+    def encode(self):
+        """Modify the encoded value. One part is stored in this object, and
+        the other one in imm4_iiii.
+        """
+
+        if not isinstance(self.expr, ExprId):
+            return False
+
+        # Get the register number and check the upper bound
+        v = csr_names.index(self.expr.name)
+        if v > 0x1F:
+            return False
+
+        # Encode the value into two parts
+        self.parent.imm4_iiii.value = v & 0xF  # iiii
+        self.value = (v >> 4) & 0b1  # I
+        return True
+
+
+class mep_disp7_align2(mep_imm):
+    """Toshiba MeP-c4 disp7.align2 immediate, as used in Major #8 opcodes
+    """
+    upper_bound = 0x7F
+    bits_shift = 1
+
+    def decode(self, v):
+        """Modify the decoded value.
+        """
+
+        # Apply the immediate mask
+        v = v & self.lmask
+
+        # Shift value such as:
+        #   disp7 = ddd_ddd||0
+        disp7_align2 = (v << self.bits_shift)
+
+        # Sign extension
+        disp7_align2 = sign_ext(disp7_align2, self.l + self.bits_shift, 32)
+
+        # Build the internal expression
+        self.expr = ExprInt(disp7_align2, 32)
+        return True
+
+    def encode(self):
+        """Modify the encoded value.
+        """
+
+        if not isinstance(self.expr, ExprInt):
+            return False
+
+        # Get the integer
+        v = int(self.expr) & self.upper_bound
+
+        # Encode the value
+        self.value = (v >> self.bits_shift) & self.upper_bound
+        self.value = (v & self.upper_bound) >> self.bits_shift
+        return True
+
+
+class mep_disp8_align2(mep_disp7_align2):
+    upper_bound = 0xFF
+
+
+class mep_disp8_align4(mep_disp7_align2):
+    upper_bound = 0xFF
+    bits_shift = 2
+
+
+class mep_imm8_align8(mep_disp7_align2):
+    upper_bound = 0xFF
+    bits_shift = 3
+
+
+class mep_disp12_align2(mep_disp7_align2):
+    upper_bound = 0xFFF
+
+
+class mep_disp12_align2_signed(mep_disp12_align2):
+
+    def decode(self, v):
+        """Perform sign extension.
+        """
+        mep_disp12_align2.decode(self, v)
+        v = int(self.expr)
+
+        self.expr = ExprInt(sign_ext(v, 12, 32), 32)
+        return True
+
+
+class mep_disp17(mep_disp7_align2):
+    upper_bound = 0x1FFFF
+
+
+class mep_imm24(mep_imm):
+    """Toshiba MeP-c4 imm24 immediate, as used in MOVU
+    """
+
+    def decode(self, v):
+        """Modify the decoded value.
+        """
+
+        # Apply the immediate mask
+        v = v & self.lmask
+
+        # Shift values such as:
+        #   imm24=iiii_iiii_iiii_iiii||IIII_IIIII
+        imm24 = ((v & 0xFFFF) << 8) + ((v & 0xFF0000) >> 16)
+
+        # Build the internal expression
+        self.expr = ExprInt(imm24, 32)
+        return True
+
+    def encode(self):
+        """Modify the encoded value.
+        """
+
+        if not isinstance(self.expr, ExprInt):
+            return False
+
+        # Get the integer and check the upper bound
+        v = int(self.expr)
+        if v > 0xFFFFFF:
+            return False
+
+        # Encode the value
+        self.value = ((v & 0xFFFF00) >> 8) + ((v & 0xFF) << 16)
+        return True
+
+
+class mep_abs24(mep_imm):
+    """Toshiba MeP-c4 abs24 immediate
+    """
+    parser = abs24_deref_parser
+
+    def decode(self, v):
+        """Modify the decoded value using the previously decoded imm6.
+        """
+
+        # Apply the immediate mask
+        v = v & self.lmask
+
+        # Shift values such as:
+        #   abs24=dddd_dddd_dddd_dddd||DDDD_DD||00
+        abs24 = (v << 8) + ((self.parent.imm6.value & 0x3F) << 2)
+
+        # Build the internal expression
+        self.expr = ExprMem(ExprInt(abs24, 32), 32)
+        return True
+
+    def encode(self):
+        """Modify the encoded value. One part is stored in this object, and
+        the other one in imm6.
+        """
+
+        if not (isinstance(self.expr, ExprMem) and isinstance(self.expr.ptr, ExprInt)):
+            return False
+
+        # Get the integer and check the upper bound
+        v = int(self.expr.ptr)
+        if v > 0xffffff:
+            return False
+
+        # Encode the value into two parts
+        self.parent.imm6.value = (v & 0xFF) >> 2
+        self.value = v >> 8
+        return True
+
+
+# Define MeP-c4 assembly operands
+
+reg04 = bs(l=4,  # length in bits
+           cls=(mep_reg, ))  # class implementing decoding & encoding
+
+reg04_l = bs(l=4, cls=(mep_reg, ))
+
+reg04_m = bs(l=4, cls=(mep_reg, ))
+
+reg04_n = bs(l=4, cls=(mep_reg, ))
+
+reg00 = bs(l=0, cls=(mep_reg, ))
+
+reg00_sp = bs(l=0, cls=(mep_reg_sp, ))
+
+reg00_tp = bs(l=0, cls=(mep_reg_tp, ))
+
+reg00_deref_sp = bs(l=0, cls=(mep_deref_sp_offset, ))
+
+reg00_deref_tp = bs(l=0, cls=(mep_deref_tp_offset, ))
+
+reg03 = bs(l=3, cls=(mep_reg, ))
+
+reg04_deref = bs(l=4, cls=(mep_deref_reg,))
+
+reg04_deref_noarg = bs(l=4, fname="reg04_deref")
+
+reg04_inc_deref = bs(l=4, cls=(mep_deref_inc_reg,))
+
+copro_reg04 = bs(l=4, cls=(mep_copro_reg,))
+
+copro_reg05 = bs(l=1, cls=(mep_copro_reg_split,))
+
+copro_reg06 = bs(l=2, cls=(mep_copro_reg_split,))
+
+disp2 = bs(l=2, cls=(mep_imm, ))
+
+imm2 = disp2
+
+imm3 = bs(l=3, cls=(mep_imm, ))
+
+imm4 = bs(l=4, cls=(mep_imm, ))
+
+imm4_noarg = bs(l=4, fname="imm4")
+
+imm4_iiii_noarg = bs(l=4, fname="imm4_iiii")
+
+imm5 = bs(l=5, cls=(mep_imm, ))
+
+imm5_Iiiii = bs(l=1, cls=(mep_imm5_Iiiii, ))  # it is not an immediate, but a
+                                              # control/special register.
+
+imm6 = bs(l=6, cls=(mep_imm6, mep_arg))
+
+imm6_noarg = bs(l=6, fname="imm6")
+
+imm7 = bs(l=7, cls=(mep_imm, ))
+
+imm7_noarg = bs(l=7, fname="imm7")  # Note:
+                                    #   - will be decoded as a 7 bits immediate
+                                    #   - fname is used to set the operand name
+                                    #     used in mep_target24 to merge operands
+                                    #     values. By default, the bs class fills
+                                    #     fname with an hex string compute from
+                                    #     arguments passed to __init__
+
+imm7_align4 = bs(l=5, cls=(mep_imm7_align4,))
+
+imm7_align4_noarg = bs(l=5, fname="imm7_align4")
+
+disp7_align2 = bs(l=6, cls=(mep_disp7_align2,))
+
+disp7_align2_noarg = bs(l=6, fname="disp7_align2")
+
+imm8 = bs(l=8, cls=(mep_imm8, mep_arg))
+
+imm8_noarg = bs(l=8, fname="imm8_CCCC_CCCC")
+
+disp8 = bs(l=7, cls=(mep_disp8_align2, ))
+
+imm8_align2 = bs(l=7, cls=(mep_disp8_align2, ))
+
+imm8_align4 = bs(l=6, cls=(mep_disp8_align4, ))
+
+imm8_align8 = bs(l=5, cls=(mep_imm8_align8, ))
+
+imm12 = bs(l=12, cls=(mep_imm, ))
+
+disp12_signed = bs(l=11, cls=(mep_disp12_align2_signed, ))
+
+imm16 = bs(l=16, cls=(mep_imm16, mep_arg))
+imm16_signed = bs(l=16, cls=(mep_imm16_signed, mep_arg))
+
+disp16_reg_deref = bs(l=16, cls=(mep_deref_reg_offset,))
+
+disp17 = bs(l=16, cls=(mep_disp17, ))
+
+imm18 = bs(l=19, cls=(mep_imm, ))
+
+imm_code20 = bs(l=16, cls=(mep_code20, ))
+
+imm24 = bs(l=24, cls=(mep_imm24, ))
+
+imm_target24 = bs(l=16, cls=(mep_target24, ))
+imm_target24_signed = bs(l=16, cls=(mep_target24_signed, ))
+
+imm_code24 = bs(l=16, cls=(mep_code24, ))
+
+abs24 = bs(l=16, cls=(mep_abs24, ))
+
+
+# MeP-c4 mnemonics objects
+
+### <Major Opcode #0>
+
+# MOV Rn,Rm - 0000_nnnn_mmmm_0000
+addop("MOV", [bs("0000"), reg04, reg04, bs("0000")])
+
+# NEG Rn,Rm - 0000_nnnn_mmmm_0001
+addop("NEG", [bs("0000"), reg04, reg04, bs("0001")])
+
+# SLT3 R0,Rn,Rm - 0000_nnnn_mmmm_0010
+addop("SLT3", [bs("0000"), reg00, reg04, reg04, bs("0010")])
+
+# SLTU3 R0,Rn,Rm - 0000_nnnn_mmmm_0011
+addop("SLTU3", [bs("0000"), reg00, reg04, reg04, bs("0011")])
+
+# SUB Rn,Rm - 0000_nnnn_mmmm_0100
+addop("SUB", [bs("0000"), reg04, reg04, bs("0100")])
+
+# SBVCK3 R0,Rn,Rm - 0000_nnnn_mmmm_0101
+addop("SBVCK3", [bs("0000"), reg00, reg04, reg04, bs("0101")])
+
+# (RI) - 0000_xxxx_xxxx_0110
+addop("(RI)", [bs("0000"), reg04, reg04, bs("0110")])
+
+# ADVCK3 R0,Rn,Rm - 0000_nnnn_mmmm_0111
+addop("ADVCK3", [bs("0000"), reg00, reg04, reg04, bs("0111")])
+
+# SB Rn,(Rm) - 0000_nnnn_mmmm_1000
+addop("SB", [bs("0000"), reg04, reg04_deref, bs("1000")])
+
+# SH Rn,(Rm) - 0000_nnnn_mmmm_1001
+addop("SH", [bs("0000"), reg04, reg04_deref, bs("1001")])
+
+# SW Rn,(Rm) - 0000_nnnn_mmmm_1010
+addop("SW", [bs("0000"), reg04, reg04_deref, bs("1010")])
+
+# LBU Rn,(Rm) - 0000_nnnn_mmmm_1011
+addop("LBU", [bs("0000"), reg04, reg04_deref, bs("1011")])
+
+# LB Rn,(Rm) - 0000_nnnn_mmmm_1100
+addop("LB", [bs("0000"), reg04, reg04_deref, bs("1100")])
+
+# LH Rn,(Rm) - 0000_nnnn_mmmm_1101
+addop("LH", [bs("0000"), reg04, reg04_deref, bs("1101")])
+
+# LW Rn,(Rm) - 0000_nnnn_mmmm_1110
+addop("LW", [bs("0000"), reg04, reg04_deref, bs("1110")])
+
+# LHU Rn,(Rm) - 0000_nnnn_mmmm_1111
+addop("LHU", [bs("0000"), reg04, reg04_deref, bs("1111")])
+
+
+### <Major Opcode #1>
+
+# OR Rn,Rm - 0001_nnnn_mmmm_0000
+addop("OR", [bs("0001"), reg04, reg04, bs("0000")])
+
+# AND Rn,Rm - 0001_nnnn_mmmm_0001
+addop("AND", [bs("0001"), reg04, reg04, bs("0001")])
+
+# XOR Rn,Rm - 0001_nnnn_mmmm_0010
+addop("XOR", [bs("0001"), reg04, reg04, bs("0010")])
+
+# NOR Rn,Rm - 0001_nnnn_mmmm_0011
+addop("NOR", [bs("0001"), reg04, reg04, bs("0011")])
+
+# MUL Rn,Rm - 0001_nnnn_mmmm_0100
+addop("MUL", [bs("0001"), reg04, reg04, bs("0100")])
+
+# MULU Rn,Rm - 0001_nnnn_mmmm_0101
+addop("MULU", [bs("0001"), reg04, reg04, bs("0101")])
+
+# MULR Rn,Rm - 0001_nnnn_mmmm_0110
+addop("MULR", [bs("0001"), reg04, reg04, bs("0110")])
+
+# MULRU Rn,Rm - 0001_nnnn_mmmm_0111
+addop("MULRU", [bs("0001"), reg04, reg04, bs("0111")])
+
+# DIV Rn,Rm - 0001_nnnn_mmmm_1000
+addop("DIV", [bs("0001"), reg04, reg04, bs("1000")])
+
+# DIVU Rn,Rm - 0001_nnnn_mmmm_1001
+addop("DIVU", [bs("0001"), reg04, reg04, bs("1001")])
+
+# (RI) - 0001_xxxx_xxxx_1010
+addop("(RI)", [bs("0001"), reg04, reg04, bs("1010")])
+
+# (RI) - 0001_xxxx_xxxx_1011
+addop("(RI)", [bs("0001"), reg04, reg04, bs("1011")])
+
+# SSARB disp2(Rm) - 0001_00dd_mmmm_1100
+addop("SSARB", [bs("000100"), disp2, reg04_deref, bs("1100")])
+
+# EXTB Rn - 0001_nnnn_0000_1101
+addop("EXTB", [bs("0001"), reg04, bs("00001101")])
+
+# EXTH Rn - 0001_nnnn_0010_1101
+addop("EXTH", [bs("0001"), reg04, bs("00101101")])
+
+# EXTUB Rn - 0001_nnnn_1000_1101
+addop("EXTUB", [bs("0001"), reg04, bs("10001101")])
+
+# EXTUH Rn - 0001_nnnn_1010_1101
+addop("EXTUH", [bs("0001"), reg04, bs("10101101")])
+
+# JMP Rm - 0001_0000_mmmm_1110
+addop("JMP", [bs("00010000"), reg04, bs("1110")])
+
+# JSR Rm - 0001_0000_mmmm_1111
+addop("JSR", [bs("00010000"), reg04, bs("1111")])
+
+# JSRV Rm - 0001_1000_mmmm_1111
+addop("JSRV", [bs("00011000"), reg04, bs("1111")])
+
+
+### <Major Opcode #2>
+
+# BSETM (Rm),imm3 - 0010_0iii_mmmm_0000
+addop("BSETM", [bs("00100"), imm3, reg04_deref, bs("0000")], [reg04_deref, imm3])
+
+# BCLRM (Rn),imm3 - 0010_0iii_mmmm_0001
+addop("BCLRM", [bs("00100"), imm3, reg04_deref, bs("0001")], [reg04_deref, imm3])
+
+# BNOTM (Rm),imm3 - 0010_0iii_mmmm_0010
+addop("BNOTM", [bs("00100"), imm3, reg04_deref, bs("0010")], [reg04_deref, imm3])
+
+# BTSTM R0,(Rm),imm3 - 0010_0iii_mmmm_0011
+addop("BTSTM", [bs("00100"), reg00, imm3, reg04_deref, bs("0011")], [reg00, reg04_deref, imm3])
+
+# TAS Rn,(Rm) - 0010_nnnn_mmmm_0100
+addop("TAS", [bs("0010"), reg04, reg04_deref, bs("0100")])
+
+# (RI) - 0010_xxxx_xxxx_0101
+addop("(RI)", [bs("0010"), reg04, reg04, bs("0101")])
+
+# SL1AD3 R0,Rn,Rm - 0010_nnnn_mmmm_0110
+addop("SL1AD3", [bs("0010"), reg00, reg04, reg04, bs("0110")])
+
+# SL2AD3 R0,Rn,Rm - 0010_nnnn_mmmm_0111
+addop("SL2AD3", [bs("0010"), reg00, reg04, reg04, bs("0111")])
+
+# (RI) - 0010_xxxx_xxxx_1000
+addop("(RI)", [bs("0010"), reg04, reg04, bs("1000")])
+
+# (RI) - 0010_xxxx_xxxx_1001
+addop("(RI)", [bs("0010"), reg04, reg04, bs("1001")])
+
+# (RI) - 0010_xxxx_xxxx_1010
+addop("(RI)", [bs("0010"), reg04, reg04, bs("1010")])
+
+# (RI) - 0010_xxxx_xxxx_1011
+addop("(RI)", [bs("0010"), reg04, reg04, bs("1011")])
+
+# SRL Rn,Rm - 0010_nnnn_mmmm_1100
+addop("SRL", [bs("0010"), reg04, reg04, bs("1100")])
+
+# SRA Rn,Rm - 0010_nnnn_mmmm_1101
+addop("SRA", [bs("0010"), reg04, reg04, bs("1101")])
+
+# SLL Rn,Rm - 0010_nnnn_mmmm_1110
+addop("SLL", [bs("0010"), reg04, reg04, bs("1110")])
+
+# FSFT Rn,Rm - 0010_nnnn_mmmm_1111
+addop("FSFT", [bs("0010"), reg04, reg04, bs("1111")])
+
+
+### <Major Opcode #3>
+
+# SWCPI CRn,(Rm+) - 0011_nnnn_mmmm_0000
+addop("SWCPI", [bs("0011"), copro_reg04, reg04_inc_deref, bs("0000")])
+
+# LWCPI CRn,(Rm+) - 0011_nnnn_mmmm_0001
+addop("LWCPI", [bs("0011"), copro_reg04, reg04_inc_deref, bs("0001")])
+
+# SMCPI CRn,(Rm+) - 0011_nnnn_mmmm_0010
+addop("SMCPI", [bs("0011"), copro_reg04, reg04_inc_deref, bs("0010")])
+
+# LMCPI CRn,(Rm+) - 0011_nnnn_mmmm_0011
+addop("LMCPI", [bs("0011"), copro_reg04, reg04_inc_deref, bs("0011")])
+
+# SWCP CRn,(Rm) - 0011_nnnn_mmmm_1000
+addop("SWCP", [bs("0011"), copro_reg04, reg04_deref, bs("1000")])
+
+# LWCP CRn,(Rm) - 0011_nnnn_mmmm_1001
+addop("LWCP", [bs("0011"), copro_reg04, reg04_deref, bs("1001")])
+
+# SMCP CRn,(Rm) - 0011_nnnn_mmmm_1010
+addop("SMCP", [bs("0011"), copro_reg04, reg04_deref, bs("1010")])
+
+# LMCP CRn,(Rm) - 0011_nnnn_mmmm_1011
+addop("LMCP", [bs("0011"), copro_reg04, reg04_deref, bs("1011")])
+
+
+### <Major Opcode #4>
+
+# ADD3 Rn,SP,imm7.align4 - 0100_nnnn_0iii_ii00
+addop("ADD3", [bs("0100"), reg04, reg00_sp, bs("0"), imm7_align4, bs("00")])
+
+# SW Rn,disp7.align4(SP) - 0100_nnnn_0ddd_dd10
+# Note: disp7.align4 is the same as imm7.align4
+addop("SW", [bs("0100"), reg04, bs("0"), imm7_align4_noarg, reg00_deref_sp, bs("10")])
+
+# LW Rn,disp7.align4(SP) - 0100_nnnn_0ddd_dd11
+addop("LW", [bs("0100"), reg04, bs("0"), imm7_align4_noarg, reg00_deref_sp, bs("11")])
+
+# SW Rn[0-7],disp7.align4(TP) - 0100_0nnn_1ddd_dd10
+addop("SW", [bs("01000"), reg03, bs("1"), imm7_align4_noarg, reg00_deref_tp, bs("10")])
+
+# LW Rn[0-7],disp7.align4(TP) - 0100_0nnn_1ddd_dd11
+addop("LW", [bs("01000"), reg03, bs("1"), imm7_align4_noarg, reg00_deref_tp, bs("11")])
+
+# LBU Rn[0-7],disp7(TP) - 0100_1nnn_1ddd_dddd
+addop("LBU", [bs("01001"), reg03, bs("1"), imm7_noarg, reg00_deref_tp], [reg03, reg00_deref_tp])
+
+### <Major Opcode #5>
+
+# MOV Rn,imm8 - 0101_nnnn_iiii_iiii
+addop("MOV", [bs("0101"), reg04, imm8])
+
+
+### <Major Opcode #6>
+
+# ADD Rn,imm6 - 0110_nnnn_iiii_ii00
+addop("ADD",  # mnemonic name
+      [bs("0110"), reg04, imm6, bs("00")])  # mnemonic description
+
+# SLT3 R0,Rn,imm5 - 0110_nnnn_iiii_i001
+addop("SLT3", [bs("0110"), reg00, reg04, imm5, bs("001")])
+
+# SRL Rn,imm5 - 0110_nnnn_iiii_i010
+addop("SRL", [bs("0110"), reg04, imm5, bs("010")])
+
+# SRA Rn,imm5 - 0110_nnnn_iiii_i011
+addop("SRA", [bs("0110"), reg04, imm5, bs("011")])
+
+# SLTU3 R0,Rn,imm5 - 0110_nnnn_iiii_i101
+addop("SLTU3", [bs("0110"), reg00, reg04, imm5, bs("101")])
+
+# SLL Rn,imm5 - 0110_nnnn_iiii_i110
+addop("SLL", [bs("0110"), reg04, imm5, bs("110")])
+
+# SLL3 R0,Rn,imm5 - 0110_nnnn_iiii_i111
+addop("SLL3", [bs("0110"), reg00, reg04, imm5, bs("111")])
+
+
+### <Major Opcode #7>
+
+# DI - 0111_0000_0000_0000
+addop("DI", [bs("0111000000000000")])
+
+# EI - 0111_0000_0001_0000
+addop("EI", [bs("0111000000010000")])
+
+# SYNCM - 0111_0000_0001_0001
+addop("SYNCM", [bs("0111000000010001")])
+
+# SYNCCP - 0111_0000_0010_0001
+addop("SYNCCP", [bs("0111000000100001")])
+
+# RET - 0111_0000_0000_0010
+addop("RET", [bs("0111000000000010")])
+
+# RETI - 0111_0000_0001_0010
+addop("RETI", [bs("0111000000010010")])
+
+# HALT - 0111_0000_0010_0010
+addop("HALT", [bs("0111000000100010")])
+
+# BREAK - 0111_0000_0011_0010
+addop("BREAK", [bs("0111000000110010")])
+
+# SLEEP - 0111_0000_0110_0010
+addop("SLEEP", [bs("0111000001100010")])
+
+# DRET - 0111_0000_0001_0011
+addop("DRET", [bs("0111000000010011")])
+
+# DBREAK - 0111_0000_0011_0011
+addop("DBREAK", [bs("0111000000110011")])
+
+# CACHE imm4,(Rm) - 0111_iiii_mmmm_0100
+addop("CACHE", [bs("0111"), imm4, reg04_deref, bs("0100")])
+
+# (RI) - 0111_xxxx_xxxx_0101
+addop("(RI)", [bs("0111"), reg04, reg04, bs("0101")])
+
+# SWI imm2 - 0111_0000_00ii_0110
+addop("SWI", [bs("0111000000"), imm2, bs("0110")])
+
+# (RI) - 0111_xxxx_xxxx_0111
+addop("(RI)", [bs("0111"), reg04, reg04, bs("0111")])
+
+# STC Rn,imm5 - 0111_nnnn_iiii_100I
+addop("STC", [bs("0111"), reg04, imm4_iiii_noarg, bs("100"), imm5_Iiiii])
+
+# LDC Rn,imm5 - 0111_nnnn_iiii_101I
+addop("LDC", [bs("0111"), reg04, imm4_iiii_noarg, bs("101"), imm5_Iiiii])
+
+# (RI) - 0111_xxxx_xxxx_1100
+addop("(RI)", [bs("0111"), reg04, reg04, bs("1100")])
+
+# (RI) - 0111_xxxx_xxxx_1101
+addop("(RI)", [bs("0111"), reg04, reg04, bs("1101")])
+
+# (RI) - 0111_xxxx_xxxx_1110
+addop("(RI)", [bs("0111"), reg04, reg04, bs("1110")])
+
+# (RI) - 0111_xxxx_xxxx_1111
+addop("(RI)", [bs("0111"), reg04, reg04, bs("1111")])
+
+
+### <Major Opcode #8>
+
+# SB Rn[0-7],disp7(TP) - 1000_0nnn_0ddd_dddd
+addop("SB", [bs("10000"), reg03, bs("0"), imm7_noarg, reg00_deref_tp])
+
+# SH Rn[0-7],disp7.align2(TP) - 1000_0nnn_1ddd_ddd0
+# (disp7.align2 = ddd_ddd||0)
+addop("SH", [bs("10000"), reg03, bs("1"), disp7_align2_noarg, bs("0"), reg00_deref_tp])
+
+# LB Rn[0-7],disp7(TP) - 1000_1nnn_0ddd_dddd
+addop("LB", [bs("10001"), reg03, bs("0"), imm7_noarg, reg00_deref_tp])
+
+# LH Rn[0-7],disp7.align2(TP) - 1000_1nnn_1ddd_ddd0
+addop("LH", [bs("10001"), reg03, bs("1"), disp7_align2_noarg, bs("0"), reg00_deref_tp])
+
+# LHU Rn[0-7],disp7.align2(TP) - 1000_1nnn_1ddd_ddd1
+addop("LHU", [bs("10001"), reg03, bs("1"), disp7_align2_noarg, bs("1"), reg00_deref_tp])
+
+
+### <Major Opcode #9>
+
+# ADD3 Rl,Rn,Rm - 1001_nnnn_mmmm_llll
+addop("ADD3", [bs("1001"), reg04_n, reg04_m, reg04_l], [reg04_l, reg04_n, reg04_m])
+
+
+### <Major Opcode #10>
+
+# BEQZ Rn,disp8.align2 - 1010_nnnn_dddd_ddd0
+# (disp8=dddd_ddd||0)
+addop("BEQZ", [bs("1010"), reg04, disp8, bs("0")])
+
+# BNEZ Rn,disp8.align2 - 1010_nnnn_dddd_ddd1
+addop("BNEZ", [bs("1010"), reg04, disp8, bs("1")])
+
+
+### <Major Opcode #11>
+
+# BRA disp12.align2 - 1011_dddd_dddd_ddd0
+# (disp12=dddd_dddd_ddd||0)
+addop("BRA", [bs("1011"), disp12_signed, bs("0")])
+
+# BSR disp12.align2 - 1011_dddd_dddd_ddd1
+addop("BSR", [bs("1011"), disp12_signed, bs("1")])
+
+
+### <Major Opcode #12>
+
+# ADD3 Rn,Rm,imm16 - 1100_nnnn_mmmm_0000 iiii_iiii_iiii_iiii
+addop("ADD3", [bs("1100"), reg04, reg04, bs("0000"), imm16_signed])
+
+# MOV Rn,imm16 - 1100_nnnn_0000_0001 iiii_iiii_iiii_iiii
+addop("MOV", [bs("1100"), reg04, bs("00000001"), imm16])
+
+# MOVU Rn,imm16 - 1100_nnnn_0001_0001 iiii_iiii_iiii_iiii
+addop("MOVU", [bs("1100"), reg04, bs("00010001"), imm16])
+
+# MOVH Rn,imm16 - 1100_nnnn_0010_0001 iiii_iiii_iiii_iiii
+addop("MOVH", [bs("1100"), reg04, bs("00100001"), imm16])
+
+# SLT3 Rn,Rm,imm16 - 1100_nnnn_mmmm_0010 iiii_iiii_iiii_iiii
+addop("SLT3", [bs("1100"), reg04, reg04, bs("0010"), imm16_signed])
+
+# SLTU3 Rn,Rm,imm16 - 1100_nnnn_mmmm_0011 iiii_iiii_iiii_iiii
+addop("SLTU3", [bs("1100"), reg04, reg04, bs("0011"), imm16])
+
+# OR3 Rn,Rm,imm16 - 1100_nnnn_mmmm_0100 iiii_iiii_iiii_iiii
+addop("OR3", [bs("1100"), reg04, reg04, bs("0100"), imm16])
+
+# AND3 Rn,Rm,imm16 - 1100_nnnn_mmmm_0101 iiii_iiii_iiii_iiii
+addop("AND3", [bs("1100"), reg04, reg04, bs("0101"), imm16])
+
+# XOR3 Rn,Rm,imm16 - 1100_nnnn_mmmm_0110 iiii_iiii_iiii_iiii
+addop("XOR3", [bs("1100"), reg04, reg04, bs("0110"), imm16])
+
+# (RI) - 1100_xxxx_xxxx_0111 xxxx_xxxx_xxxx_xxxx
+addop("(RI)", [bs("1100"), imm8, bs("0111"), imm16])
+
+# SB Rn,disp16(Rm) - 1100_nnnn_mmmm_1000 dddd_dddd_dddd_dddd
+addop("SB", [bs("1100"), reg04, reg04_deref_noarg, bs("1000"), disp16_reg_deref], [reg04, disp16_reg_deref])
+
+# SH Rn,disp16(Rm) - 1100_nnnn_mmmm_1001 dddd_dddd_dddd_dddd
+addop("SH", [bs("1100"), reg04, reg04_deref_noarg, bs("1001"), disp16_reg_deref], [reg04, disp16_reg_deref])
+
+# SW Rn,disp16(Rm) - 1100_nnnn_mmmm_1010 dddd_dddd_dddd_dddd
+addop("SW", [bs("1100"), reg04, reg04_deref_noarg, bs("1010"), disp16_reg_deref], [reg04, disp16_reg_deref])
+
+# LBU Rn,disp16(Rm) - 1100_nnnn_mmmm_1011 dddd_dddd_dddd_dddd
+addop("LBU", [bs("1100"), reg04, reg04_deref_noarg, bs("1011"), disp16_reg_deref], [reg04, disp16_reg_deref])
+
+# LB Rn,disp16(Rm) - 1100_nnnn_mmmm_1100 dddd_dddd_dddd_dddd
+addop("LB", [bs("1100"), reg04, reg04_deref_noarg, bs("1100"), disp16_reg_deref], [reg04, disp16_reg_deref])
+
+# LH Rn,disp16(Rm) - 1100_nnnn_mmmm_1101 dddd_dddd_dddd_dddd
+addop("LH", [bs("1100"), reg04, reg04_deref_noarg, bs("1101"), disp16_reg_deref], [reg04, disp16_reg_deref])
+
+# LW Rn,disp16(Rm) - 1100_nnnn_mmmm_1110 dddd_dddd_dddd_dddd
+addop("LW", [bs("1100"), reg04, reg04_deref_noarg, bs("1110"), disp16_reg_deref], [reg04, disp16_reg_deref])
+
+# LHU Rn,disp16(Rm) - 1100_nnnn_mmmm_1111 dddd_dddd_dddd_dddd
+addop("LHU", [bs("1100"), reg04, reg04_deref_noarg, bs("1111"), disp16_reg_deref], [reg04, disp16_reg_deref])
+
+
+### <Major Opcode #13>
+
+# MOVU Rn[0-7],imm24 - 1101_0nnn_IIII_IIII iiii_iiii_iiii_iiii
+addop("MOVU", [bs("11010"), reg03, imm24])
+
+# BCPEQ cccc,disp17 - 1101_1000_cccc_0100 dddd_dddd_dddd_dddd
+addop("BCPEQ", [bs("11011000"), imm4, bs("0100"), disp17])
+
+# BCPNE cccc,disp17 - 1101_1000_cccc_0101 dddd_dddd_dddd_dddd
+addop("BCPNE", [bs("11011000"), imm4, bs("0101"), disp17])
+
+# BCPAT cccc,disp17 - 1101_1000_cccc_0110 dddd_dddd_dddd_dddd
+addop("BCPAT", [bs("11011000"), imm4, bs("0110"), disp17])
+
+# BCPAF cccc,disp17 - 1101_1000_cccc_0111 dddd_dddd_dddd_dddd
+addop("BCPAF", [bs("11011000"), imm4, bs("0111"), disp17])
+
+# JMP target24 - 1101_1TTT_TTTT_1000 tttt_tttt_tttt_tttt
+addop("JMP", [bs("11011"), imm7_noarg, bs("1000"), imm_target24],
+      [imm_target24])  # the only interesting operand is imm_target24
+
+# BSR disp24 - 1101_1DDD_DDDD_1001 dddd_dddd_dddd_dddd
+addop("BSR", [bs("11011"), imm7_noarg, bs("1001"), imm_target24_signed], [imm_target24_signed])
+
+# BSRV disp24 1101_1DDD_DDDD_1011 dddd_dddd_dddd_dddd
+addop("BSRV", [bs("11011"), imm7_noarg, bs("1011"), imm_target24], [imm_target24])
+
+
+### <Major Opcode #14>
+
+# BEQI Rn,imm4,disp17 - 1110_nnnn_iiii_0000 dddd_dddd_dddd_dddd
+addop("BEQI", [bs("1110"), reg04, imm4, bs("0000"), disp17])
+
+# BEQ Rn,Rm,disp17 - 1110_nnnn_mmmm_0001 dddd_dddd_dddd_dddd
+addop("BEQ", [bs("1110"), reg04, reg04, bs("0001"), disp17])
+
+# BNEI Rn,imm4,disp17 - 1110_nnnn_iiii_0100 dddd_dddd_dddd_dddd
+addop("BNEI", [bs("1110"), reg04, imm4, bs("0100"), disp17])
+
+# BNE Rn,Rm,disp17 - 1110_nnnn_mmmm_0101 dddd_dddd_dddd_dddd
+addop("BNE", [bs("1110"), reg04, reg04, bs("0101"), disp17])
+
+# BGEI Rn,imm4,disp17 - 1110_nnnn_iiii_1000 dddd_dddd_dddd_dddd
+addop("BGEI", [bs("1110"), reg04, imm4, bs("1000"), disp17])
+
+# REPEAT Rn,disp17 - 1110_nnnn_0000_1001 dddd_dddd_dddd_dddd
+addop("REPEAT", [bs("1110"), reg04, bs("00001001"), disp17])
+
+# EREPEAT disp17 - 1110_0000_0001_1001 dddd_dddd_dddd_dddd
+addop("EREPEAT", [bs("1110000000011001"), disp17])
+
+# BLTI Rn,imm4,disp17 - 1110_nnnn_iiii_1100 dddd_dddd_dddd_dddd
+addop("BLTI", [bs("1110"), reg04, imm4, bs("1100"), disp17])
+
+# (RI) - 1110_xxxx_xxxx_1101 xxxx_xxxx_xxxx_xxxx
+addop("(RI)", [bs("1110"), imm8, bs("1101"), imm16])
+
+# SW Rn,(abs24) - 1110_nnnn_DDDD_DD10 dddd_dddd_dddd_dddd
+addop("SW", [bs("1110"), reg04, imm6_noarg, bs("10"), abs24])
+
+# LW Rn,(abs24) - 1110_nnnn_DDDD_DD11 dddd_dddd_dddd_dddd
+addop("LW", [bs("1110"), reg04, imm6_noarg, bs("11"), abs24])
+
+
+### <Major Opcode #15>
+
+# DSP Rn,Rm,code16 - 1111_nnnn_mmmm_0000 cccc_cccc_cccc_cccc
+addop("DSP", [bs("1111"), reg04, reg04, bs("0000"), imm16])
+
+# Note: DSP, DSP0 & DSP1 look exactly the same. This is ambiguous, and prevent
+#       them for being correctly disassembled. DSP0 & DSP1 are arbitrarily
+#       disabled.
+
+# DSP0 code24 - 1111_nnnn_mmmm_0000 cccc_cccc_cccc_cccc
+#addop("DSP0", [bs("1111"), imm8_noarg, bs("0000"), imm_code24], [imm_code24])
+
+# DSP1 Rn,code20 - 1111_nnnn_mmmm_0000 cccc_cccc_cccc_cccc
+#addop("DSP1", [bs("1111"), reg04, imm4_noarg, bs("0000"), imm_code20])
+
+# LDZ Rn,Rm - 1111_nnnn_mmmm_0001 0000_0000_0000_0000
+addop("LDZ", [bs("1111"), reg04, reg04, bs("00010000000000000000")])
+
+# AVE Rn,Rm - 1111_nnnn_mmmm_0001 0000_0000_0000_0010
+addop("AVE", [bs("1111"), reg04, reg04, bs("00010000000000000010")])
+
+# ABS Rn,Rm - 1111_nnnn_mmmm_0001 0000_0000_0000_0011
+addop("ABS", [bs("1111"), reg04, reg04, bs("00010000000000000011")])
+
+# MIN Rn,Rm - 1111_nnnn_mmmm_0001 0000_0000_0000_0100
+addop("MIN", [bs("1111"), reg04, reg04, bs("00010000000000000100")])
+
+# MAX Rn,Rm - 1111_nnnn_mmmm_0001 0000_0000_0000_0101
+addop("MAX", [bs("1111"), reg04, reg04, bs("00010000000000000101")])
+
+# MINU Rn,Rm - 1111_nnnn_mmmm_0001 0000_0000_0000_0110
+addop("MINU", [bs("1111"), reg04, reg04, bs("00010000000000000110")])
+
+# MAXU Rn,Rm - 1111_nnnn_mmmm_0001 0000_0000_0000_0111
+addop("MAXU", [bs("1111"), reg04, reg04, bs("00010000000000000111")])
+
+# SADD Rn,Rm - 1111_nnnn_mmmm_0001 0000_0000_0000_1000
+addop("SADD", [bs("1111"), reg04, reg04, bs("00010000000000001000")])
+
+# SADDU Rn,Rm - 1111_nnnn_mmmm_0001 0000_0000_0000_1001
+addop("SADDU", [bs("1111"), reg04, reg04, bs("00010000000000001001")])
+
+# SSUB Rn,Rm - 1111_nnnn_mmmm_0001 0000_0000_0000_1010
+addop("SSUB", [bs("1111"), reg04, reg04, bs("00010000000000001010")])
+
+# SSUBU Rn,Rm - 1111_nnnn_mmmm_0001 0000_0000_0000_1011
+addop("SSUBU", [bs("1111"), reg04, reg04, bs("00010000000000001011")])
+
+# CLIP Rn,imm5 - 1111_nnnn_0000_0001 0001_0000_iiii_i000
+addop("CLIP", [bs("1111"), reg04, bs("0000000100010000"), imm5, bs("000")])
+
+# CLIPU Rn,imm5 - 1111_nnnn_0000_0001 0001_0000_iiii_i001
+addop("CLIPU", [bs("1111"), reg04, bs("0000000100010000"), imm5, bs("001")])
+
+# (RI) - 1111_xxxx_xxxx_0001 0010_xxxx_xxxx_xxxx
+addop("(RI)", [bs("1111"), imm8, bs("00010010"), imm12])
+
+# MADD Rn,Rm - 1111_nnnn_mmmm_0001 0011_0000_0000_0100
+addop("MADD", [bs("1111"), reg04, reg04, bs("00010011000000000100")])
+
+# MADDU Rn,Rm - 1111_nnnn_mmmm_0001 0011_0000_0000_0101
+addop("MADDU", [bs("1111"), reg04, reg04, bs("00010011000000000101")])
+
+# MADDR Rn,Rm - 1111_nnnn_mmmm_0001 0011_0000_0000_0110
+addop("MADDR", [bs("1111"), reg04, reg04, bs("00010011000000000110")])
+
+# MADDRU Rn,Rm - 1111_nnnn_mmmm_0001 0011_0000_0000_0111
+addop("MADDRU", [bs("1111"), reg04, reg04, bs("00010011000000000111")])
+
+# UCI Rn,Rm,code16 - 1111_nnnn_mmmm_0010 cccc_cccc_cccc_cccc
+addop("UCI", [bs("1111"), reg04, reg04, bs("0010"), imm16])
+
+# (RI) - 1111_xxxx_xxxx_0011 xxxx_xxxx_xxxx_xxxx
+addop("(RI)", [bs("1111"), imm8, bs("0011"), imm16])
+
+# STCB Rn,abs16 - 1111_nnnn_0000_0100 aaaa_aaaa_aaaa_aaaa
+addop("STCB", [bs("1111"), reg04, bs("00000100"), imm16])
+
+# LDCB Rn,abs16 - 1111_nnnn_0001_0100 aaaa_aaaa_aaaa_aaaa
+addop("LDCB", [bs("1111"), reg04, bs("00010100"), imm16])
+
+# SBCPA CRn,(Rm+),imm8 - 1111_nnnn_mmmm_0101 0000_0000_iiii_iiii
+addop("SBCPA", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010100000000"), imm8])
+
+# SHCPA CRn,(Rm+),imm8.align2 - 1111_nnnn_mmmm_0101 0001_0000_iiii_iii0
+addop("SHCPA", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010100010000"), imm8_align2, bs("0")])
+
+# SWCPA CRn,(Rm+),imm8.align4 - 1111_nnnn_mmmm_0101 0010_0000_iiii_ii00
+addop("SWCPA", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010100100000"), imm8_align4, bs("00")])
+
+# SMCPA CRn,(Rm+),imm8.align8 - 1111_nnnn_mmmm_0101 0011_0000_iiii_i000
+addop("SMCPA", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010100110000"), imm8_align8, bs("000")])
+
+# LBCPA CRn,(Rm+),imm8 - 1111_nnnn_mmmm_0101 0100_0000_iiii_iiii
+addop("LBCPA", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010101000000"), imm8])
+
+# LHCPA CRn,(Rm+),imm8.align2 - 1111_nnnn_mmmm_0101 0101_0000_iiii_iii0
+addop("LHCPA", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010101010000"), imm8_align2, bs("0")])
+
+# LWCPA CRn,(Rm+),imm8.align4 - 1111_nnnn_mmmm_0101 0110_0000_iiii_ii00
+addop("LWCPA", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010101100000"), imm8_align4, bs("00")])
+
+# LMCPA CRn,(Rm+),imm8.align8 - 1111_nnnn_mmmm_0101 0111_0000_iiii_i000
+addop("LMCPA", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010101110000"), imm8_align8, bs("000")])
+
+# SBCPM0 CRn,(Rm+),imm8 - 1111_nnnn_mmmm_0101 0000_1000_iiii_iiii
+addop("SBCPM0", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010100001000"), imm8])
+
+# SHCPM0 CRn,(Rm+),imm8.align2 - 1111_nnnn_mmmm_0101 0001_1000_iiii_iii0
+addop("SHCPM0", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010100011000"), imm8_align2, bs("0")])
+
+# SWCPM0 CRn,(Rm+),imm8.align4 - 1111_nnnn_mmmm_0101 0010_1000_iiii_ii00
+addop("SWCPM0", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010100101000"), imm8_align4, bs("00")])
+
+# SMCPM0 CRn,(Rm+),imm8.align8 - 1111_nnnn_mmmm_0101 0011_1000_iiii_i000
+addop("SMCPM0", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010100111000"), imm8_align8, bs("000")])
+
+# LBCPM0 CRn,(Rm+),imm8 - 1111_nnnn_mmmm_0101 0100_1000_iiii_iiii
+addop("LBCPM0", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010101001000"), imm8])
+
+# LHCPM0 CRn,(Rm+),imm8.align2 - 1111_nnnn_mmmm_0101 0101_1000_iiii_iii0
+addop("LHCPM0", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010101011000"), imm8_align2, bs("0")])
+
+# LWCPM0 CRn,(Rm+),imm8.align4 - 1111_nnnn_mmmm_0101 0110_1000_iiii_ii00
+addop("LWCPM0", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010101101000"), imm8_align4, bs("00")])
+
+# LMCPM0 CRn,(Rm+),imm8.align8 - 1111_nnnn_mmmm_0101 0111_1000_iiii_i000
+addop("LMCPM0", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010101111000"), imm8_align8, bs("000")])
+
+# SBCPM1 CRn,(Rm+),imm8 - 1111_nnnn_mmmm_0101 0000_1100_iiii_iiii
+addop("SBCPM1", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010100001100"), imm8])
+
+# SHCPM1 CRn,(Rm+),imm8.align2 - 1111_nnnn_mmmm_0101 0001_1100_iiii_iii0
+addop("SHCPM1", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010100011100"), imm8_align2, bs("0")])
+
+# SWCPM1 CRn,(Rm+),imm8.align4 - 1111_nnnn_mmmm_0101 0010_1100_iiii_ii00
+addop("SWCPM1", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010100101100"), imm8_align4, bs("00")])
+
+# SMCPM1 CRn,(Rm+),imm8.align8 - 1111_nnnn_mmmm_0101 0011_1100_iiii_i000
+addop("SMCPM1", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010100111100"), imm8_align8, bs("000")])
+
+# LBCPM1 CRn,(Rm+),imm8 - 1111_nnnn_mmmm_0101 0100_1100_iiii_iiii
+addop("LBCPM1", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010101001100"), imm8])
+
+# LHCPM1 CRn,(Rm+),imm8.align2 - 1111_nnnn_mmmm_0101 0101_1100_iiii_iii0
+addop("LHCPM1", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010101011100"), imm8_align2, bs("0")])
+
+# LWCPM1 CRn,(Rm+),imm8.align4 - 1111_nnnn_mmmm_0101 0110_1100_iiii_ii00
+addop("LWCPM1", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010101101100"), imm8_align4, bs("00")])
+
+# LMCPM1 CRn,(Rm+),imm8.align8 - 1111_nnnn_mmmm_0101 0111_1100_iiii_i000
+addop("LMCPM1", [bs("1111"), copro_reg04, reg04_inc_deref, bs("010101111100"), imm8_align8, bs("000")])
+
+# (RI) - 1111_xxxx_xxxx_0110 xxxx_xxxx_xxxx_xxxx
+addop("(RI)", [bs("1111"), imm8, bs("0110"), imm16])
+
+# CP code24 - 1111_CCCC_CCCC_0111 cccc_cccc_cccc_cccc
+#addop("CP", [bs("1111"), imm8_noarg, bs("0111"), imm_code24], [imm_code24])
+# Note: CP & CMOV* look exactly the same. This is ambiguous, and prevent
+#       them for being correctly disassembled. CP was arbitrarily disabled.
+
+# CP code56 - 1111_CCCC_CCCC_0111 cccc_cccc_cccc_cccc cccc_cccc_cccc_cccc
+# 64-bit VLIW operation mode - not implemented
+
+# CMOV CRn,Rm - 1111_nnnn_mmmm_0111 1111_0000_0000_0000
+#addop("CMOV", [bs("1111"), copro_reg04, reg04, bs("01111111000000000000")])
+
+# CMOV Rm,CRn - 1111_nnnn_mmmm_0111 1111_0000_0000_0001
+#addop("CMOV", [bs("1111"), copro_reg04, reg04, bs("01111111000000000001")], [reg04, copro_reg04])
+
+# CMOVC CCRn,Rm - 1111_nnnn_mmmm_0111 1111_0000_0000_NN10
+# CRn=NNnnnn
+addop("CMOVC", [bs("1111"), imm4_noarg, reg04, bs("0111111100000000"), copro_reg06, bs("10")], [copro_reg06, reg04])
+
+# CMOVC Rm,CCRn - 1111_nnnn_mmmm_0111 1111_0000_0000_NN11
+# CRn=NNnnnn
+addop("CMOVC", [bs("1111"), imm4_noarg, reg04, bs("0111111100000000"), copro_reg06, bs("11")], [reg04, copro_reg06])
+
+# CMOVH CRn,Rm - 1111_nnnn_mmmm_0111 1111_0001_0000_0000
+#addop("CMOVH", [bs("1111"), copro_reg04, reg04, bs("01111111000100000000")])
+
+# CMOVH Rm,CRn - 1111_nnnn_mmmm_0111 1111_0001_0000_0001
+#addop("CMOVH", [bs("1111"), copro_reg04, reg04, bs("01111111000100000001")], [reg04, copro_reg04])
+
+# Note: the following CMOV* instructions are extensions used when the processor
+#       has more than 16 coprocessor general-purpose registers. They can be
+#       used to assemble and disassemble both CMOV* instructuons sets.
+
+# CMOV CRn,Rm - 1111_nnnn_mmmm_0111 1111_0000_0000_N000
+# CRn=Nnnnn
+addop("CMOV", [bs("1111"), imm4_noarg, reg04, bs("0111111100000000"), copro_reg05, bs("000")], [copro_reg05, reg04])
+
+# CMOV Rm,CRn - 1111_nnnn_mmmm_0111 1111_0000_0000_N001
+addop("CMOV", [bs("1111"), imm4_noarg, reg04, bs("0111111100000000"), copro_reg05, bs("001")], [reg04, copro_reg05])
+
+# CMOVH CRn,Rm - 1111_nnnn_mmmm_0111 1111_0001_0000_N000
+addop("CMOVH", [bs("1111"), imm4_noarg, reg04, bs("0111111100010000"), copro_reg05, bs("000")], [copro_reg05, reg04])
+
+# CMOVH Rm,CRn - 1111_nnnn_mmmm_0111 1111_0001_0000_N001
+addop("CMOVH", [bs("1111"), imm4_noarg, reg04, bs("0111111100010000"), copro_reg05, bs("001")], [reg04, copro_reg05])
+
+# (RI) - 1111_xxxx_xxxx_10xx xxxx_xxxx_xxxx_xxxx
+addop("(RI)", [bs("1111"), imm8, bs("10"), imm18])
+
+# SWCP CRn,disp16(Rm) - 1111_nnnn_mmmm_1100 dddd_dddd_dddd_dddd
+addop("SWCP", [bs("1111"), copro_reg04, reg04_deref_noarg, bs("1100"), disp16_reg_deref], [copro_reg04, disp16_reg_deref])
+
+# LWCP CRn,disp16(Rm) - 1111_nnnn_mmmm_1101 dddd_dddd_dddd_dddd
+addop("LWCP", [bs("1111"), copro_reg04, reg04_deref_noarg, bs("1101"), disp16_reg_deref], [copro_reg04, disp16_reg_deref, reg04_deref])
+
+# SMCP CRn,disp16(Rm) - 1111_nnnn_mmmm_1110 dddd_dddd_dddd_dddd
+addop("SMCP", [bs("1111"), copro_reg04, reg04_deref_noarg, bs("1110"), disp16_reg_deref], [copro_reg04, disp16_reg_deref, reg04_deref])
+
+# LMCP CRn,disp16(Rm) - 1111_nnnn_mmmm_1111 dddd_dddd_dddd_dddd
+addop("LMCP", [bs("1111"), copro_reg04, reg04_deref_noarg, bs("1111"), disp16_reg_deref], [copro_reg04, disp16_reg_deref])