# Toshiba MeP-c4 - miasm architecture definition # Guillaume Valadon from miasm2.core.cpu import * from miasm2.core.utils import Disasm_Exception from miasm2.expression.expression import Expr, ExprId, ExprInt, ExprLoc, \ ExprMem, ExprOp from miasm2.core.asm_ast import AstId, AstMem from miasm2.arch.mep.regs import * import miasm2.arch.mep.regs as mep_regs_module # will be used to set mn_mep.regs # 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.arg) & 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 ! """ # Default delay slot # Note: # - mandatory for the miasm2 Machine delayslot = 0 @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 miasm2 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)" % (expr.ptr.args[1].arg, 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) 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 miasm2/core/cpu.py """ o = "%s" % self.name if self.name == "SSARB": # The first operand is displayed in decimal, not in hex o += " %d" % self.args[0].arg 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].arg) 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].arg) 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" % self.args[1].arg 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].arg, 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 isinstance(arg, Expr): 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 bloc.""" 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 bloc, 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 = self.args[num].arg 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 miasm2/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: """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: - theses 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 miasm2 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 miasm2/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 miasm2/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 miasm2/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].arg & 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.arg) # 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.arg) & 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.arg) 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.arg) 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.arg) & 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.arg) 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.arg) 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.arg) 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 ### # 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")]) ### # 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")]) ### # 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")]) ### # 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")]) ### # 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]) ### # MOV Rn,imm8 - 0101_nnnn_iiii_iiii addop("MOV", [bs("0101"), reg04, imm8]) ### # 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")]) ### # 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")]) ### # 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]) ### # ADD3 Rl,Rn,Rm - 1001_nnnn_mmmm_llll addop("ADD3", [bs("1001"), reg04_n, reg04_m, reg04_l], [reg04_l, reg04_n, reg04_m]) ### # 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")]) ### # 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")]) ### # 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]) ### # 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]) ### # 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]) ### # 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])