diff options
Diffstat (limited to 'miasm/arch/mep')
| -rw-r--r-- | miasm/arch/mep/__init__.py | 0 | ||||
| -rw-r--r-- | miasm/arch/mep/arch.py | 2080 | ||||
| -rw-r--r-- | miasm/arch/mep/disasm.py | 23 | ||||
| -rw-r--r-- | miasm/arch/mep/jit.py | 112 | ||||
| -rw-r--r-- | miasm/arch/mep/lifter_model_call.py | 45 | ||||
| -rw-r--r-- | miasm/arch/mep/regs.py | 91 | ||||
| -rw-r--r-- | miasm/arch/mep/sem.py | 1240 |
7 files changed, 0 insertions, 3591 deletions
diff --git a/miasm/arch/mep/__init__.py b/miasm/arch/mep/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/miasm/arch/mep/__init__.py +++ /dev/null diff --git a/miasm/arch/mep/arch.py b/miasm/arch/mep/arch.py deleted file mode 100644 index ed7813ca..00000000 --- a/miasm/arch/mep/arch.py +++ /dev/null @@ -1,2080 +0,0 @@ -# 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]) diff --git a/miasm/arch/mep/disasm.py b/miasm/arch/mep/disasm.py deleted file mode 100644 index 0260c01d..00000000 --- a/miasm/arch/mep/disasm.py +++ /dev/null @@ -1,23 +0,0 @@ -# Toshiba MeP-c4 - miasm disassembly engine -# Guillaume Valadon <guillaume@valadon.net> - -from miasm.core.asmblock import disasmEngine -from miasm.arch.mep.arch import mn_mep - - -class dis_mepb(disasmEngine): - """MeP miasm disassembly engine - Big Endian - - Notes: - - its is mandatory to call the miasm Machine - """ - - attrib = "b" - - def __init__(self, bs=None, **kwargs): - super(dis_mepb, self).__init__(mn_mep, self.attrib, bs, **kwargs) - - -class dis_mepl(dis_mepb): - """MeP miasm disassembly engine - Little Endian""" - attrib = "l" diff --git a/miasm/arch/mep/jit.py b/miasm/arch/mep/jit.py deleted file mode 100644 index 3fee2537..00000000 --- a/miasm/arch/mep/jit.py +++ /dev/null @@ -1,112 +0,0 @@ -# Toshiba MeP-c4 - miasm jitter -# Guillaume Valadon <guillaume@valadon.net> -# Note: inspiration from msp430/jit.py - -from miasm.jitter.jitload import Jitter -from miasm.core.utils import * -from miasm.jitter.codegen import CGen -from miasm.ir.translators.C import TranslatorC -from miasm.arch.mep.sem import Lifter_MEPl, Lifter_MEPb - -import logging - -log = logging.getLogger("jit_mep") -hnd = logging.StreamHandler() -hnd.setFormatter(logging.Formatter("[%(levelname)-8s]: %(message)s")) -log.addHandler(hnd) -log.setLevel(logging.CRITICAL) - - -class mep_CGen(CGen): - """ - Translate a block containing MeP instructions to C - - Note: it is used to emulate the *REPEAT instructions - """ - - def __init__(self, lifter): - self.lifter = lifter - self.PC = self.lifter.arch.regs.PC - self.translator = TranslatorC(self.lifter.loc_db) - self.init_arch_C() - - def gen_pre_code(self, attrib): - """Generate C code inserted before the current block""" - - # Call the base class method - out = super(mep_CGen, self).gen_pre_code(attrib) - - # Set the PC register value explicitly - out.append("mycpu->PC = 0x%X;" % attrib.instr.offset) - out.append("mycpu->last_addr = mycpu->PC;"); - - return out - - def gen_post_code(self, attrib, pc_value): - """Generate C code inserted after the current block""" - - # Call the base class method - out = super(mep_CGen, self).gen_post_code(attrib, pc_value) - - # Implement the *REPEAT instructions logics - tmp = r""" - /* *REPEAT instructions logic */ - { - uint32_t is_repeat_end = mycpu->is_repeat_end; - mycpu->is_repeat_end = !!(mycpu->last_addr == (mycpu->RPE&~0x1)); - - if (is_repeat_end && !mycpu->take_jmp && - (mycpu->in_erepeat || mycpu->RPC)) { - if (mycpu->RPC) - mycpu->RPC --; - - //printf("Go repeat %X\n", mycpu->RPB); - DST_value = mycpu->RPB; - BlockDst->address = mycpu->RPB; - return JIT_RET_NO_EXCEPTION; - } - } - """ - - out += tmp.split('`\n') - return out - - -class jitter_mepl(Jitter): - - C_Gen = mep_CGen - - def __init__(self, loc_db, *args, **kwargs): - Jitter.__init__(self, Lifter_MEPl(loc_db), *args, **kwargs) - self.vm.set_little_endian() - self.lifter.jit_pc = self.lifter.arch.regs.PC - - def push_uint16_t(self, v): - regs = self.cpu.get_gpreg() - regs["SP"] -= 2 - self.cpu.set_gpreg(regs) - self.vm.set_mem(regs["SP"], pck16(v)) - - def pop_uint16_t(self): - regs = self.cpu.get_gpreg() - x = self.vm.get_u16(regs["SP"]) - regs["SP"] += 2 - self.cpu.set_gpreg(regs) - return x - - def get_stack_arg(self, n): - regs = self.cpu.get_gpreg() - x = self.vm.get_u16(regs["SP"] + 2 * n) - return x - - def init_run(self, *args, **kwargs): - Jitter.init_run(self, *args, **kwargs) - self.cpu.PC = self.pc - - -class jitter_mepb(jitter_mepl): - - def __init__(self, loc_db, *args, **kwargs): - Jitter.__init__(self, Lifter_MEPb(loc_db), *args, **kwargs) - self.vm.set_big_endian() - self.lifter.jit_pc = self.lifter.arch.regs.PC diff --git a/miasm/arch/mep/lifter_model_call.py b/miasm/arch/mep/lifter_model_call.py deleted file mode 100644 index db729ba0..00000000 --- a/miasm/arch/mep/lifter_model_call.py +++ /dev/null @@ -1,45 +0,0 @@ -# Toshiba MeP-c4 - miasm IR analysis -# Guillaume Valadon <guillaume@valadon.net> - -from miasm.arch.mep.sem import Lifter_MEPb, Lifter_MEPl -from miasm.ir.analysis import LifterModelCall - - -class LifterModelCallMepb(Lifter_MEPb, LifterModelCall): - """MeP high level IR manipulations - Big Endian - - Notes: - - it is mandatory for symbolic execution. - """ - - def __init__(self, loc_db): - Lifter_MEPb.__init__(self, loc_db) - self.ret_reg = self.arch.regs.R0 - - # Note: the following are abstract method and must be implemented - def sizeof_char(self): - "Return the size of a char in bits" - return 8 - - def sizeof_short(self): - "Return the size of a short in bits" - return 16 - - def sizeof_int(self): - "Return the size of an int in bits" - return 32 - - def sizeof_long(self): - "Return the size of a long in bits" - return 32 - - def sizeof_pointer(self): - "Return the size of a void* in bits" - return 32 - - -class LifterModelCallMepl(Lifter_MEPl, LifterModelCallMepb): - """MeP high level IR manipulations - Little Endian""" - - def __init__(self, loc_db): - LifterModelCallMepb.__init__(self, loc_db) diff --git a/miasm/arch/mep/regs.py b/miasm/arch/mep/regs.py deleted file mode 100644 index be195b61..00000000 --- a/miasm/arch/mep/regs.py +++ /dev/null @@ -1,91 +0,0 @@ -# Toshiba MeP-c4 - miasm registers definition -# Guillaume Valadon <guillaume@valadon.net> - -from builtins import range -from miasm.expression.expression import ExprId -from miasm.core.cpu import reg_info, gen_reg, gen_regs - -# Used by internal miasm exceptions -exception_flags = ExprId("exception_flags", 32) -exception_flags_init = ExprId("exception_flags_init", 32) - -is_repeat_end = ExprId("is_repeat_end", 32) -is_repeat_end_init = ExprId("is_repeat_end_init", 32) -last_addr = ExprId("last_addr", 32) -last_addr_init = ExprId("last_addr_init", 32) -take_jmp = ExprId("take_jmp", 32) -take_jmp_init = ExprId("take_jmp_init", 32) -in_erepeat = ExprId("in_erepeat", 32) -in_erepeat_init = ExprId("take_jmp_init", 32) - - -# General-purpose registers (R0 to R15) names -gpr_names = ["R%d" % r for r in range(13)] # register names -gpr_names += ["TP", "GP", "SP"] # according to the manual GP does not exist -gpr_exprs, gpr_inits, gpr_infos = gen_regs(gpr_names, globals()) # sz=32 bits (default) - -# Notes: -# - gpr_exprs: register ExprIds on 32 bits. The size is important for -# symbolic execution. -# - gpr_inits: register initial values. -# - gpr_infos: object that binds names & ExprIds - -# Define aliases to general-purpose registers -TP = gpr_exprs[13] # Tiny data area Pointer -GP = gpr_exprs[14] # Global Pointer -SP = gpr_exprs[15] # Stack Pointer - - -# Control/special registers name -csr_names = ["PC", "LP", "SAR", "S3", "RPB", "RPE", "RPC", "HI", "LO", - "S9", "S10", "S11", "MB0", "ME0", "MB1", "ME1", "PSW", - "ID", "TMP", "EPC", "EXC", "CFG", "S22", "NPC", "DBG", - "DEPC", "OPT", "RCFG", "CCFG", "S29", "S30", "S31", "S32"] -csr_exprs, csr_inits, csr_infos = gen_regs(csr_names, globals()) - -# Define aliases to control/special registers -PC = csr_exprs[0] # Program Counter. On MeP, it is the special register R0 -LP = csr_exprs[1] # Link Pointer. On MeP, it is the special register R1 -SAR = csr_exprs[2] # Shift Amount Register. On MeP, it is the special register R2 -RPB = csr_exprs[4] # Repeat Begin. On MeP, it is the special register R4 -RPE = csr_exprs[5] # Repeat End. On MeP, it is the special register R5 -RPC = csr_exprs[6] # Repeat Counter. On MeP, it is the special register R6 - - -# Coprocesssor general-purpose registers (C0 to C15) names -# Note: a processor extension allows up to 32 coprocessor general-purpose registers -copro_gpr_names = ["C%d" % r for r in range(32)] # register names -copro_gpr_exprs, copro_gpr_inits, copro_gpr_infos = gen_regs(copro_gpr_names, globals()) - - -# Set registers initial values -all_regs_ids = gpr_exprs + csr_exprs + copro_gpr_exprs + [ - exception_flags, take_jmp, last_addr, is_repeat_end, - in_erepeat -] - -all_regs_ids_init = gpr_inits + csr_inits + copro_gpr_inits + [ - exception_flags_init, take_jmp_init, last_addr_init, is_repeat_end_init, - in_erepeat_init -] - -all_regs_ids_no_alias = all_regs_ids[:] # GV: not understood yet ! -all_regs_ids_byname = dict([(x.name, x) for x in all_regs_ids]) - - -float_st0 = ExprId("float_st0", 64) -float_st1 = ExprId("float_st1", 64) -float_st2 = ExprId("float_st2", 64) -float_st3 = ExprId("float_st3", 64) -float_st4 = ExprId("float_st4", 64) -float_st5 = ExprId("float_st5", 64) -float_st6 = ExprId("float_st6", 64) -float_st7 = ExprId("float_st7", 64) - -regs_flt_expr = [float_st0, float_st1, float_st2, float_st3, - float_st4, float_st5, float_st6, float_st7] - - -regs_init = dict() # mandatory name -for i, r in enumerate(all_regs_ids): - regs_init[r] = all_regs_ids_init[i] diff --git a/miasm/arch/mep/sem.py b/miasm/arch/mep/sem.py deleted file mode 100644 index 0ac50c58..00000000 --- a/miasm/arch/mep/sem.py +++ /dev/null @@ -1,1240 +0,0 @@ -# Toshiba MeP-c4 - miasm instructions side effects -# Guillaume Valadon <guillaume@valadon.net> - -from miasm.core.sembuilder import SemBuilder -from miasm.ir.ir import Lifter -from miasm.arch.mep.arch import mn_mep -from miasm.arch.mep.regs import PC, SP, LP, SAR, TP, RPB, RPE, RPC, EPC, NPC, \ - take_jmp, in_erepeat -from miasm.arch.mep.regs import EXC, HI, LO, PSW, DEPC, DBG -from miasm.expression.expression import ExprId, ExprInt, ExprOp, TOK_EQUAL -from miasm.expression.expression import ExprAssign, ExprCond, ExprMem -from miasm.core.cpu import sign_ext -from miasm.jitter.csts import EXCEPT_DIV_BY_ZERO - -from miasm.arch.mep.regs import exception_flags - - -def compute_s_inf(arg1, arg2): - """Signed comparison operator""" - return ((arg1 - arg2) ^ ((arg1 ^ arg2) & ((arg1 - arg2) ^ arg1))).msb() - -def compute_u_inf(x, y): - """Unsigned comparison operator""" - result = (((x - y) ^ ((x ^ y) & ((x - y) ^ x))) ^ x ^ y).msb() - return result - -def i8(value): - return ExprInt(value, 8) - -def i32(value): - return ExprInt(value, 32) - - -# SemBuilder context -ctx = {"PC": PC, "SP": SP, "LP": LP, "SAR": SAR, "TP": TP, - "RPB": RPB, "RPE": RPE, "RPC": RPC, "EPC": EPC, "NPC": NPC, - "EXC": EXC, "HI": HI, "LO": LO, "PSW": PSW, "DEPC": DEPC, "DBG": DBG, - "exception_flags": exception_flags, "compute_s_inf": compute_s_inf, - "compute_u_inf": compute_u_inf, "take_jmp": take_jmp, - "in_erepeat": in_erepeat, "EXCEPT_DIV_BY_ZERO": EXCEPT_DIV_BY_ZERO} -sbuild = SemBuilder(ctx) - - -# Functions used to get an instruction IR -manual_functions = dict() - - -@sbuild.parse -def mep_nop(): - """Dummy instruction""" - - -@sbuild.parse -def mep_nop_2_args(arg1, arg2): - """Dummy instruction with two arguments""" - - -### Load/Store instructions - -# Register indirect addressing mode - -def sb(ir, instr, reg_src, deref_dst): - """SB - Store Byte into memory""" - - # MemByte(Rm31..0) <- Rn7..0 - # MemByte((ZeroExt(disp7)+TP)31..0)) <- Rn7..0 - # MemByte((SignExt(disp16)+Rm)31..0) <- Rn7..0 - e = [] - e.append(ExprAssign(ExprMem(deref_dst.ptr, 8), reg_src[:8])) - return e, [] - -manual_functions["sb"] = sb - - -def sh(ir, instr, reg_src, deref_dst): - """SH - Store Halfword into memory""" - - # MemHword(Rm31..1||0) <- Rn15..0 - # MemHword((ZeroExt((disp7)6..1||0)+TP)31..1||0)) <- Rn15..0 - # MemHword((SignExt(disp16)+Rm)31..1||0) <- Rn15..0 - e = [] - e.append(ExprAssign(ExprMem(deref_dst.ptr & i32(0xFFFFFFFE), 16), reg_src[:16])) - return e, [] - -manual_functions["sh"] = sh - - -def sw(ir, instr, reg_src, deref_dst): - """SW - Store Word into memory""" - - # MemWord(Rm31..2||00) <- Rn31..0 - # MemWord((ZeroExt((disp7)6..2||00)+SP)31..2||00)) <- Rn31..0 - # MemWord((ZeroExt((disp7)6..2||00)+TP)31..2||00)) <- Rn31..0 - # MemWord((SignExt(disp16)+Rm)31..2||00) <- Rn31..0 - # MemWord(ZeroExt((abs24)23..2||00)) - Rn31..0 - e = [] - e.append(ExprAssign(ExprMem(deref_dst.ptr & i32(0xFFFFFFFC), 32), reg_src)) - return e, [] - -manual_functions["sw"] = sw - -# Without the sembuilder -#def sw(ir, instr, reg_src, deref_reg_or_imm, deref_reg=None): -# """SW - store Word into memory. -# -# Note: there are three variants to get the memory address: -# - from a register -# - relatively to SP -# - relatively to TP""" -# -# if isinstance(deref_reg_or_imm, ExprMem): -# # MemWord(Rm31..2||00) <- Rn31..0 -# dst = deref_reg_or_imm -# -# elif isinstance(deref_reg_or_imm, ExprInt) and deref_reg: -# # MemWord((ZeroExt((disp7)6..2||00)+SP)31..2||00)) <- Rn31..0 -# # MemWord((ZeroExt((disp7)6..2||00)+TP)31..2||00)) <- Rn31..0 -# -# imm = deref_reg_or_imm.zeroExtend(32) -# dst = ExprMem(ExprOp("+", imm, deref_reg.arg)) -# -# return [ExprAssign(dst, reg_src)], [] - - -def lb(ir, instr, reg_dst, deref_dst): - """LB - Load Byte from memory""" - - # Rn <- SignExt(MemByte(Rm31..0)) - # Rn <- SignExt(MemByte((ZeroExt(disp7)+TP)31..0)) - # Rn <- SignExt(MemByte((SignExt(disp16)+Rm)31..0) - e = [] - e.append(ExprAssign(reg_dst, ExprMem(deref_dst.ptr, 8).signExtend(32))) - return e, [] - -manual_functions["lb"] = lb - - -def lh(ir, instr, reg_dst, deref_dst): - """LH - Load Halfword from memory""" - - # Rn <- SignExt(MemHword(Rm31..1||0)) - # Rn <- SignExt(MemHword((ZeroExt((disp7)6..1||0)+TP)31..1||0) - # Rn <- SignExt(MemHword((SignExt(disp16)+Rm)31..1||0)) - e = [] - e.append(ExprAssign(reg_dst, ExprMem(deref_dst.ptr & i32(0xFFFFFFFE), 16).signExtend(32))) - return e, [] - -manual_functions["lh"] = lh - -def lw(ir, instr, reg_dst, deref_dst): - """LW - Load Word from memory""" - - # Rn <- MemWord(Rm31..2||00) - # Rn <- MemWord((ZeroExt((disp7)6..2||00)+TP)31..2||00) - # Rn <- MemWord((SignExt(disp16)+Rm)31..2||00) - # Rn <- MemWord(ZeroExt((abs24)23..2||00)) - e = [] - e.append(ExprAssign(reg_dst, ExprMem(deref_dst.ptr & i32(0xFFFFFFFC), 32))) - return e, [] - -manual_functions["lw"] = lw - - -def lbu(ir, instr, reg_dst, deref_dst): - """LBU - Load an unsigned Byte from memory""" - - # Rn <- ZeroExt(MemByte(Rm31..0)) - # Rn <- ZeroExt(MemByte((ZeroExt(disp7)+TP)31..0)) - # Rn <- ZeroExt(MemByte((SignExt(disp16)+Rm)31..0)) - e = [] - e.append(ExprAssign(reg_dst, ExprMem(deref_dst.ptr, 8).zeroExtend(32))) - return e, [] - -manual_functions["lbu"] = lbu - - -def lhu(ir, instr, reg_dst, deref_dst): - """LHU - Load an unsigned Halfword from memory""" - - # Rn <- ZeroExt(MemHword(Rm31..1||0)) - # Rn <- ZeroExt(MemHword((SignExt(disp16)+Rm)31..1||0)) - # Rn <- ZeroExt(MemHword((ZeroExt((disp7)6..1||0)+TP)31..1||0)) - e = [] - e.append(ExprAssign(reg_dst, ExprMem(deref_dst.ptr & i32(0xFFFFFFFE), 16).zeroExtend(32))) - return e, [] - -manual_functions["lhu"] = lhu - - - -### Byte/Halfword extension instructions - -@sbuild.parse -def extb(reg): - """EXTB - Sign extend a byte""" - - # Rn <- SignExt(Rn7..0) - reg = reg[:8].signExtend(32) - - -@sbuild.parse -def exth(reg): - """EXTH - Sign extend a word""" - - # Rn <- ZeroExt(Rn15..0) - reg = reg[:16].signExtend(32) - - -@sbuild.parse -def extub(reg): - """EXUTB - Zero extend a byte""" - - # Rn <- SignExt(Rn7..0) - reg = reg[:8].zeroExtend(32) - - -@sbuild.parse -def extuh(reg): - """EXTUH - Zero extend a word""" - - # Rn <- ZeroExt(Rn15..0) - reg = reg[:16].zeroExtend(32) - - -### Shift amount manipulation instructions - -#@sbuild.parse -#def ssarb(deref_reg): - - -### Move instructions - -@sbuild.parse -def mov(reg, value): - """MOV - Copy 'value' to a register. The three alternatives are handled.""" - - # Rn <- Rm - # Rn <- SignExt(imm8) - # Rn <- SignExt(imm16) - reg = value.signExtend(32) - - -@sbuild.parse -def movu(reg, value): - """MOV - Copy 'value' to a register. The two alternatives are handled.""" - - # Rn[0-7] <- ZeroExt(imm24) - # Rn <- ZeroExt(imm16) - reg = value.zeroExtend(32) - - -@sbuild.parse -def movh(reg, imm16): - """MOVH - Copy a shifted imm16 to a register.""" - - # Rn <- imm16 <<16 - reg = imm16.zeroExtend(32) << i32(16) - - -### Arithmetic instructions - -def add3(ir, instr, reg_dst, reg_src, reg_or_imm): - """ADD3 - Add two register and store the result to a register, or - add a register and an immediate and store the result to a register""" - - if isinstance(reg_or_imm, ExprId): - # Rl <- Rn + Rm - result = ExprOp("+", reg_src, reg_or_imm) - else: - # Rn <- Rm + SignExt(imm16) - value = int(reg_or_imm) - result = ExprOp("+", reg_src, ExprInt(value, 32)) - - return [ExprAssign(reg_dst, result)], [] - -manual_functions["add3"] = add3 - - -@sbuild.parse -def add(arg1, arg2): - """ADD - Add a register and an immediate.""" - - # Rn <- Rn + SignExt(imm6) - arg1 = arg1 + arg2.signExtend(32) - - -@sbuild.parse -def advck3(r0, rn, rm): - """ADVCK3 - Check addition overflow.""" - - # if(Overflow(Rn+Rm)) R0<-1 else R0<-0 (Signed) - r0 = i32(1) if compute_u_inf(i64(0xFFFFFFFF), rn.zeroExtend(64) + rm.zeroExtend(64)) else i32(0) - - -@sbuild.parse -def sub(reg1, reg2): - """SUB - Subtract one register to another.""" - - # Rn <- Rn - Rm - reg1 = reg1 - reg2 - - -def sbvck3(ir, instr, r0, rn, rm): - """SBVCK3 - Check subtraction overflow""" - - # if(Overflow(Rn-Rm)) R0<-1 else R0<-0 (Signed) - - # Subtract registers - reg_sub = ExprOp("+", rn, rm) - - # Get the register storing the highest value - max_rn_rm = ExprCond(ExprOp(">", rn, rm), rn, rm) - - # Check for an overflow - overflow_test = ExprOp(">", reg_sub, max_rn_rm) - - # Return the result - condition = ExprCond(overflow_test, ExprInt(1, 32), ExprInt(0, 32)) - return [ExprAssign(r0, condition)], [] - -manual_functions["sbvck3"] = sbvck3 - - -@sbuild.parse -def neg(reg1, reg2): - """NEG - Negate one register.""" - - # Rn <- - Rm - reg1 = - reg2 - - -@sbuild.parse -def slt3(r0, rn, rm_or_imm5): - """SLT3 - Set on less than (signed).""" - - # if (Rn<Rm) R0<-1 else R0<-0 (Signed) - # if (Rn<ZeroExt(imm5)) R0<-1 else R0<-0(Signed) - r0 = i32(1) if compute_s_inf(rn, rm_or_imm5.signExtend(32)) else i32(0) - -if False: - rm_ext = rm_or_imm5 - - # Mask sign bits - sign_mask = i32(0x80000000) - sign_rn = rn & sign_mask - sign_rm = rm_ext & sign_mask - - # Check if both numbers are positive or negative - are_both_neg = sign_rn & sign_rm - are_both_pos = ~(sign_rn & sign_rm) >> i32(31) - - # rn is positive and rm negative, return 1 - r0_mixed = i32(1) if sign_rn else i32(0) - - # rn & rm are both positives, test and return 1 or 0 - r0_pos = (i32(1) if "<"(rn, rm_ext) else i32(0)) if are_both_pos else r0_mixed - - # rn & rm are both negatives, test and return 0 or 1 - r0 = (i32(0) if "<"(rn, rm_ext) else i32(1)) if are_both_neg else r0_pos - - -@sbuild.parse -def sltu3(r0, rn, rm_or_imm5): - """SLTU3 - Set on less than (unsigned).""" - - # if (Rn<Rm) R0<-1 else R0<-0 (Unsigned) - # if (Rn<ZeroExt(imm5)) R0<-1 else R0<-0(Unsigned) - r0 = i32(1) if compute_u_inf(rn, rm_or_imm5) else i32(0) - - -@sbuild.parse -def sl1ad3(r0, rn, rm): - """SL1AD3 - Shift a register one bit left, then add another one.""" - - # R0 <- (Rn<<1) + Rm - r0 = (rn << i32(1)) + rm - - -@sbuild.parse -def sl2ad3(r0, rn, rm): - """SL2AD3 - Shift a register two bits left, then add another one.""" - - # R0 <- (Rn<<2) + Rm - r0 = (rn << i32(2)) + rm - - -### Logical instructions - -@sbuild.parse -def logical_or(rn, rm): - """OR - Logical OR between two registers.""" - - # Rn <- Rn or Rm - rn = rn | rm - -manual_functions["or"] = logical_or - - -@sbuild.parse -def logical_and(rn, rm): - """AND - Logical AND between two registers.""" - - # Rn <- Rn and Rm - rn = rn & rm - -manual_functions["and"] = logical_and - - -@sbuild.parse -def xor(rn, rm): - """XOR - Logical XOR between two registers.""" - - # Rn <- Rn xor Rm - rn = rn ^ rm - - -@sbuild.parse -def nor(rn, rm): - """NOR - Logical NOR between two registers.""" - - # Rn <- Rn nor Rm - rn = ~ (rn | rm) - - -@sbuild.parse -def or3(rn, rm, imm16): - """OR3 - Logical OR between a register and an immediate""" - - # Rn <- Rm or ZeroExt(imm16) - rn = rm | imm16 - - -@sbuild.parse -def and3(rn, rm, imm16): - """AND3 - Logical AND between a register and an immediate""" - - # Rn <- Rm and ZeroExt(imm16) - rn = rm & imm16 - - -@sbuild.parse -def xor3(rn, rm, imm16): - """XOR3 - Logical XOR between a register and an immediate""" - - # Rn <- Rm xor ZeroExt(imm16) - rn = rm ^ imm16 - - -### Shift instruction - -@sbuild.parse -def sra(rn, rm_or_imm5): - """SRA - Shift Right signed""" - - # Rn <- (Signed) Rn >> Rm4..0 - # Rn <- (Signed) Rn >> imm5 - - # Unsigned result - shift_u = rn >> rm_or_imm5 - - # Signed result - shift_mask = i32(32) - rm_or_imm5 - mask = (i32(0xFFFFFFFF) >> shift_mask) << shift_mask - shift_s = shift_u | mask - - rn = shift_s if rn.msb() else shift_u - - -@sbuild.parse -def srl(rn, rm_or_imm5): - """SRL - Shift Right unsigned.""" - - # Rn <- (Unsigned) Rn >> Rm4..0 - # Rn <- (Unsigned) Rn >> imm5 - rn = rn >> rm_or_imm5 - - -@sbuild.parse -def sll(rn, rm_or_imm5): - """SLL - Shift Left unsigned.""" - - # Rn <- (Unsigned) Rn >> Rm4..0 - # Rn <- (Unsigned) Rn << imm5 - rn = rn << rm_or_imm5 - - -@sbuild.parse -def sll3(r0, rn, imm5): - """SLL3 - Shift Left unsigned, with 3 arguments.""" - - # R0 <- (Unsigned) Rn << imm5 - r0 = rn << imm5 - - -@sbuild.parse -def fsft(rn, rm): - """FSFT - Funnel shift.""" - - # Rn <- ((Rn||Rm)<<SAR5..0)63..32 - # Note: lowest Rm bits are discarded - - sar = SAR[:5].zeroExtend(32) - tmp_rn = rn << sar # Shift Rn - tmp_rm = rm >> (i32(32) - sar) # Shift Rm in the reverse order - rn = tmp_rn | tmp_rm # Concatenate registers - - -## Branch/Jump instructions - -@sbuild.parse -def bra(disp12): - """BRA - Branch to an address.""" - - # PC <- PC + SignExt((disp12)11..1||0) - dst = disp12 - PC = dst - take_jmp = ExprInt(1, 32) - ir.IRDst = dst - - -@sbuild.parse -def beqz(reg_test, disp8): - """BEQZ - Branch if the register stores zero.""" - - # if(Rn==0) PC <- PC +SignExt((disp8)7..1||0) - dst = ExprLoc(ir.get_next_break_loc_key(instr), 32) if reg_test else disp8 - take_jmp = ExprInt(0, 32) if reg_test else ExprInt(1, 32) - PC = dst - ir.IRDst = dst - - -@sbuild.parse -def bnez(reg_test, disp8): - """BNEZ - Branch if the register does not store zero.""" - - # if(Rn!=0) PC <- PC + SignExt((disp8)7..1||0) - dst = disp8 if reg_test else ExprLoc(ir.get_next_break_loc_key(instr), 32) - take_jmp = ExprInt(1, 32) if reg_test else ExprInt(0, 32) - PC = dst - ir.IRDst = dst - - -@sbuild.parse -def beqi(reg_test, imm4, disp16): - """BEQI - Branch if the register stores imm4.""" - - # if(Rn==ZeroExt(imm4)) PC <- PC +SignExt((disp17)16..1||0) - dst = ExprLoc(ir.get_next_break_loc_key(instr), 32) if (reg_test - imm4) else disp16 - take_jmp = ExprInt(0, 32) if (reg_test - imm4) else ExprInt(1, 32) - PC = dst - ir.IRDst = dst - - -@sbuild.parse -def bnei(reg_test, imm4, disp16): - """BNEI - Branch if the register does not store imm4.""" - - # if(Rn!=ZeroExt(imm4)) PC <- PC+SignExt((disp17)16..1||0) - dst = disp16 if (reg_test - imm4) else ExprLoc(ir.get_next_break_loc_key(instr), 32) - take_jmp = ExprInt(1, 32) if (reg_test - imm4) else ExprInt(0, 32) - PC = dst - ir.IRDst = dst - - -@sbuild.parse -def blti(reg_test, imm4, disp16): - """BLTI - Branch if the register is lower than imm4.""" - - # if(Rn< ZeroExt(imm4)) PC <- PC +SignExt((disp17)16..1||0) - (Signed comparison) - dst = disp16 if compute_s_inf(reg_test, imm4) else ExprLoc(ir.get_next_break_loc_key(instr), 32) - take_jmp = ExprInt(1, 32) if compute_s_inf(reg_test, imm4) else ExprInt(0, 32) - PC = dst - ir.IRDst = dst - - -@sbuild.parse -def bgei(reg_test, imm4, disp16): - """BGEI - Branch if the register is greater or equal to imm4.""" - - # if(Rn>=ZeroExt(imm4)) PC <- PC +SignExt((disp17)16..1||0) - (Signed comparison) - cond = i32(1) if ExprOp(TOK_EQUAL, reg_test, imm4) else compute_s_inf(imm4, reg_test).zeroExtend(32) - dst = disp16 if cond else ExprLoc(ir.get_next_break_loc_key(instr), 32) - take_jmp = ExprInt(1, 32) if cond else ExprInt(0, 32) - PC = dst - ir.IRDst = dst - - -@sbuild.parse -def beq(rn, rm, disp16): - """BEQ - Branch if the two registers are equal.""" - - # if(Rn==Rm) PC <- PC +SignExt((disp17)16..1||0) - dst = ExprLoc(ir.get_next_break_loc_key(instr), 32) if (rn - rm) else disp16 - take_jmp = ExprInt(0, 32) if (rn - rm) else ExprInt(1, 32) - PC = dst - ir.IRDst = dst - - -@sbuild.parse -def bne(rn, rm, disp16): - """BNE - Branch if the two registers are not equal.""" - - # if(Rn!=Rm) PC <- PC +SignExt((disp17)16..1||0) - dst = disp16 if (rn - rm) else ExprLoc(ir.get_next_break_loc_key(instr), 32) - take_jmp = ExprInt(1, 32) if (rn - rm) else ExprInt(0, 32) - PC = dst - ir.IRDst = dst - - -@sbuild.parse -def bsr(disp): - """BSR - Branch to an address, and store the return address.""" - - # 16-bit variant: LP <- PC + 2; PC <- PC +SignExt((disp12)11..1||0) - # 32-bit variant: LP <- PC + 4; PC <- PC +SignExt((disp24)23..1||0) - - # Set LP - LP = ExprLoc(ir.get_next_break_loc_key(instr), 32) - take_jmp = ExprInt(1, 32) - - # Set PC according to the immediate size - dst = disp - PC = dst - ir.IRDst = dst - - -def jmp(ir, instr, reg_or_imm): - """JMP - Change PC to a register content or an immediate. - Note: the behavior in VLIW mode is not implemented""" - - take_jmp = ExprInt(1, 32) - - if isinstance(reg_or_imm, ExprId): - # PC <- Rm31..1||0 - new_PC = ExprAssign(PC, reg_or_imm) - else: - # PC <- PC31..28||0000||(target24)23..1||0 - new_PC = ExprAssign(PC, ExprOp("+", ExprOp("&", PC, ExprInt(0xF0000000, 32)), reg_or_imm)) - - return [new_PC, ExprAssign(ir.IRDst, new_PC)], [] - -manual_functions["jmp"] = jmp - - -@sbuild.parse -def jsr(reg): - """JSR - Jump to the register, and store the return address.""" - - # LP <- PC + 2; PC <- Rm31..1||0 - LP = ExprLoc(ir.get_next_break_loc_key(instr), 32) - take_jmp = ExprInt(1, 32) - PC = reg - ir.IRDst = reg - - -@sbuild.parse -def ret(): - """RET - Return from a function call. - Note: the behavior in VLIW mode is not implemented""" - - # PC <- LP31..1||0 - dst = LP - PC = dst - ir.IRDst = dst - - -# Repeat instructions - -@sbuild.parse -def repeat(rn, disp17): - """REPEAT - This instruction repeats an instruction block. It sets the RPB, - RPE and RPC control registers.""" - - # RPB <- pc+4 // Repeat Begin - RPB = PC + i32(4) - # RPE <- pc+SignExt((disp17)16..1||0)) // Repeat End - RPE = PC + i32(int(disp17) & 0xFFFFFFFE) - # RPC <- Rn - RPC = rn - in_erepeat = ExprInt(0, 32) - - -@sbuild.parse -def erepeat(disp17): - """EREPEAT - This instruction repeats an instruction block. It sets the RPB - and RPE control registers. To distinguish from the repeat instruction, - the least significant bit in the RPE register (ELR) is set to 1.""" - - # RPB <- pc+4 // Repeat Begin - RPB = PC + i32(4) - # RPE <- pc+SignExt((disp17)16..1||1)) (EREPEAT) - RPE = PC + i32(int(disp17) + 1) - # RPC <- undefined - in_erepeat = ExprInt(1, 32) - - -## Control Instructions - -@sbuild.parse -def stc(reg, control_reg): - """STC - Copy a general-purpose register into a control register.""" - - # ControlReg(imm5) <- Rn - control_reg = reg - - -@sbuild.parse -def ldc(reg, control_reg): - """LDC - Copy a control register into a general-purpose register.""" - - # Rn <- ControlReg(imm5) - reg = control_reg - - -@sbuild.parse -def di(): - """DI - Disable Interrupt""" - - # PSW.IEC<-0 - PSW = PSW & i32(0xFFFFFFFE) # PSW.IEC: bit 0 - - -@sbuild.parse -def ei(): - """EI - Enable Interrupt""" - - # PSW.IEC<-1 - PSW = PSW ^ i32(0b1) # PSW.IEC: bit 0 - - -@sbuild.parse -def reti(): - """RETI - Return from the exception/interrupt handler. - Note: the behavior in VLIW mode is not implemented""" - - #if (PSW.NMI==1) { - # PC <- NPC31..1 || 0; PSW.NMI<-0; - #} else { - # PC <- EPC31..1 || 0; - # PSW.UMC <- PSW.UMP; PSW.IEC <- PSW.IEP - #} - - # PSW.NMI == bit 9 - NMI_mask = i32(1 << 9) - - # PSW.UMP == bit 3 - # PSW.IEP == bit 1 - UMP_IEP_mask = i32((1 << 3) ^ (1 << 1)) - - # PSW.UMC == bit 2 - # PSW.IEC == bit 0 - UMC_IEC_mask = (PSW & UMP_IEP_mask) >> i32(1) - - # Get PSW.NMI - PSW_NMI = (PSW & NMI_mask) >> i32(9) - - # Set PC - dst = NPC & i32(0xFFFFFFFE) if PSW_NMI else EPC & i32(0xFFFFFFFE) - PC = dst - - # Set flags - PSW = PSW ^ NMI_mask if PSW_NMI else PSW ^ UMC_IEC_mask - - ir.IRDst = dst - - -@sbuild.parse -def swi(imm2): - """SWI - Software Interrupt""" - - # if(imm2==0) EXC.SIP0 <- 1 - # else if (imm2==1) EXC.SIP1 <- 1 - # else if (imm2==2) EXC.SIP2 <- 1 - # else if (imm2==3) EXC.SIP3 <- 1 - - # EXC.SIP0 == bit 4 - # EXC.SIP1 == bit 5 - # EXC.SIP2 == bit 6 - # EXC.SIP3 == bit 7 - - EXC = EXC ^ (i32(1) << (i32(4) + imm2)) - - -# Note: the following instructions can't be implemented -manual_functions["halt"] = mep_nop -manual_functions["sleep"] = mep_nop -manual_functions["break"] = mep_nop -manual_functions["syncm"] = mep_nop -manual_functions["stcb"] = mep_nop_2_args -manual_functions["ldcb"] = mep_nop_2_args - - -### Bit manipulation instruction option - -def bsetm(ir, instr, rm_deref, imm3): - """BSETM - Bit Set Memory""" - - # MemByte(Rm) <- MemByte(Rm) or (1<<imm3) - e = [] - e.append(ExprAssign(ExprMem(rm_deref.ptr, 8), ExprOp("|", ExprMem(rm_deref.ptr, 8), (i8(1) << imm3[:8])))) - return e, [] - -manual_functions["bsetm"] = bsetm - - -def bclrm(ir, instr, rm_deref, imm3): - """BCLRM - Bit Clear Memory""" - - # MemByte(Rm) <- MemByte(Rm) and ~(1<<imm3) - e = [] - shift = ExprOp("<<", i8(1), imm3[:8]) - e.append(ExprAssign(ExprMem(rm_deref.ptr, 8), ExprOp("&", ExprMem(rm_deref.ptr, 8), shift.__invert__()))) - return e, [] - -manual_functions["bclrm"] = bclrm - - -def bnotm(ir, instr, rm_deref, imm3): - """BNOTM - Bit Not Memory""" - - # MemByte(Rm) <- MemByte(Rm) xor (1<<imm3) - e = [] - e.append(ExprAssign(ExprMem(rm_deref.ptr, 8), ExprOp("^", ExprMem(rm_deref.ptr, 8), (i8(1) << imm3[:8])))) - return e, [] - -manual_functions["bnotm"] = bnotm - - -def btstm(ir, instr, r0, rm_deref, imm3): - """BTSTM - Bit Test Memory""" - - # R0 <- ZeroExt( MemByte(Rm) and (1<<imm3) ) - e = [] - e.append(ExprAssign(r0, ExprOp("&", ExprMem(rm_deref.ptr, 8), i8(1) << imm3[:8]).zeroExtend(32))) - return e, [] - -manual_functions["btstm"] = btstm - - -def tas(ir, instr, rn, rm_deref): - """TAS - Load And Set""" - - # temp <- Rm; Rn <- ZeroExt(MemByte(temp)); MemByte(temp) <- 1 - e = [] - temp = rm_deref - e.append(ExprAssign(rn, ExprMem(temp.ptr, 8).zeroExtend(32))) - e.append(ExprAssign(ExprMem(temp.ptr, 8), i8(1))) - return e, [] - -manual_functions["tas"] = tas - - -### Data cache option - -# Note: the following instruction can't be implemented -manual_functions["cache"] = mep_nop_2_args - - -### 32-bit multiply instruction option - -@sbuild.parse -def mul(rn, rm): - """MUL - Signed 32-bit multiplication""" - - # HI||LO <- Rn * Rm (Signed) - result = rn.signExtend(64) * rm.signExtend(64) # expand registers size - HI = result[32:64] - LO = result[:32] - - -@sbuild.parse -def mulu(rn, rm): - """MUL - Unsigned 32-bit multiplication""" - - # HI||LO <- Rn * Rm (Unsigned) - result = rn.zeroExtend(64) * rm.zeroExtend(64) # expand registers size - HI = result[32:64] - LO = result[0:32] - - -@sbuild.parse -def mulr(rn, rm): - """MULR - Signed 32-bit multiplication & store LO in Rn""" - - # HI||LO <- Rn * Rm; Rn <- LO (Signed) - result = rn.signExtend(64) * rm.signExtend(64) # expand registers size - HI = result[32:64] - LO = result[:32] - rn = result[:32] - - -@sbuild.parse -def mulru(rn, rm): - """MULRU - Unsigned 32-bit multiplication & store LO in Rn""" - - # HI||LO <- Rn * Rm; Rn <- LO (Unsigned) - result = rn.zeroExtend(64) * rm.zeroExtend(64) # expand registers size - HI = result[32:64] - LO = result[:32] - rn = result[:32] - - -@sbuild.parse -def madd(rn, rm): - """MADD - Signed 32-bit multiplication, adding results to HI & LO registers""" - - # HI||LO <- HI||LO + Rn*Rm (Signed) - result = (HI << i32(32)).signExtend(64) + LO.signExtend(64) + rn.signExtend(64) * rm.signExtend(64) # expand registers size - HI = result[32:64] - LO = result[:32] - - -@sbuild.parse -def maddu(rn, rm): - """MADDU - Unsigned 32-bit multiplication, adding results to HI & LO registers""" - - # HI||LO <- HI||LO + Rn*Rm (Unsigned) - result = (HI << i32(32)).zeroExtend(64) + LO.zeroExtend(64) + rn.zeroExtend(64) * rm.zeroExtend(64) # expand registers size - HI = result[32:64] - LO = result[:32] - - -@sbuild.parse -def maddr(rn, rm): - """MADDR - Signed 32-bit multiplication, adding results to HI & LO registers & storing LO in Rn""" - - # HI||LO <- HI||LO + Rn*Rm; Rn <- LO (Signed) - result = (HI << i32(32)).signExtend(64) + LO.signExtend(64) + rn.signExtend(64) * rm.signExtend(64) # expand registers size - HI = result[32:64] - LO = result[:32] - rn = result[:32] - - -@sbuild.parse -def maddru(rn, rm): - """MADDRU - Unsigned 32-bit multiplication, adding results to HI & LO registers & storing LO in Rn""" - - # HI||LO <- HI||LO + Rn*Rm; Rn <- LO (Unsigned) - result = (HI << i32(32)).zeroExtend(64) + LO.zeroExtend(64) + rn.zeroExtend(64) * rm.zeroExtend(64) # expand registers size - HI = result[32:64] - LO = result[:32] - rn = result[:32] - - -### 32-bit divide instruction option - -@sbuild.parse -def div(rn, rm): - """DIV - Signed division""" - - # LO <- Rn / Rm, HI <- Rn % Rm (Signed) - - # Mask sign bits - sign_mask = i32(0x80000000) - sign_rn = rn & sign_mask - sign_rm = rm & sign_mask - - # Check if both numbers are positive or negative - are_both_neg = sign_rn & sign_rm - are_both_pos = ExprCond( - are_both_neg - sign_mask, - ExprInt(0, are_both_neg.size), - ExprInt(1, are_both_neg.size) - ) - - - # Invert both numbers - rn_inv = ~rn + i32(1) - rm_inv = ~rm + i32(1) - - # Used to delay the arithmetic computations - tmp_rm = rm if rm else i32(1) - tmp_rm_inv = rm_inv if rm_inv else i32(1) - - # Results if only rn, or rm is negative - LO_rn_neg = (~(rn_inv // tmp_rm) + i32(1)) if sign_rn else (~(rn // tmp_rm_inv) + i32(1)) - HI_rn_neg = (~(rn_inv % tmp_rm) + i32(1)) if sign_rn else (~(rn % tmp_rm_inv) + i32(1)) - - # Results if both numbers are positive - LO_pos = rn // tmp_rm if are_both_pos else LO_rn_neg - HI_pos = rn % tmp_rm if are_both_pos else HI_rn_neg - - # Results if both numbers are negative - LO_neg = rn_inv // tmp_rm_inv if are_both_neg else LO_pos - HI_neg = rn_inv % tmp_rm_inv if are_both_neg else HI_pos - - # Results if rm is equal to zero - LO = LO_neg if rm else LO - HI = HI_neg if rm else HI - - exception_flags = i32(0) if rm else i32(EXCEPT_DIV_BY_ZERO) - - -@sbuild.parse -def divu(rn, rm): - """DIVU - Unsigned division""" - - # LO <- Rn / Rm, HI <- Rn % Rm (Unsigned) - - tmp_rm = rm if rm else i32(1) # used to delay the arithmetic computations - LO = rn // tmp_rm if rm else LO - HI = rn % tmp_rm if rm else HI - - exception_flags = i32(0) if rm else i32(EXCEPT_DIV_BY_ZERO) - - -### Debug function option - -@sbuild.parse -def dret(): - """DRET - Debug Exception Return""" - - # PC <- DEPC; DBG.DM <- 0 - PC = DEPC - DBG = DBG & i32(0xFFFFBFFF) # DBG.DM: bit 15 - - -@sbuild.parse -def dbreak(): - """DBREAK - Debug break""" - - # The DBG.DBP bit becomes 1 - DBG = DBG ^ i32(0b10) # DBG.DBP: bit 2 - - -### Leading zero instruction option - -@sbuild.parse -def ldz(rn, rm): - """LDZ - Count Leading Zeroes - - Note: this implementation is readable, yet slow. Each bit are tested - individually, and the results are propagated to other bits. - - Here is the commented implementation for 4-bit integers: - rm = 0b0001 - - # Invert the value - reversed_rm = ~rm - -> reversed_rm = 0b1110 - - # Test bits individually - b3 = (reversed_rm & i32(2**3)) >> i32(3) if reversed_rm else i32(0) - -> b3 = (0b1110 & 0b1000 >> 3) = 1 - - b2 = (reversed_rm & i32(2**2)) >> i32(2) if b3 else i32(0) - -> b2 = (0b1110 & 0b0100 >> 2) = 1 - - b1 = (reversed_rm & i32(2**1)) >> i32(1) if b2 else i32(0) - -> b1 = (0b1110 & 0b0010 >> 1) = 1 - - b0 = (reversed_rm & i32(2**0)) >> i32(0) if b1 else i32(0) - -> b0 = (0b1110 & 0b0001 >> 0) = 0 - - # Sum all partial results - rn = b3 + b2 + b1 + b0 - -> rn = 1 + 1 + 1 + 0 = 3 - """ - - # Rn <- LeadingZeroDetect(Rm) - - # Invert the value - reversed_rm = ~rm - - # Test bits individually - b31 = (reversed_rm & i32(2**31)) >> i32(31) if reversed_rm else i32(0) - b30 = (reversed_rm & i32(2**30)) >> i32(30) if b31 else i32(0) - b29 = (reversed_rm & i32(2**29)) >> i32(29) if b30 else i32(0) - b28 = (reversed_rm & i32(2**28)) >> i32(28) if b29 else i32(0) - b27 = (reversed_rm & i32(2**27)) >> i32(27) if b28 else i32(0) - b26 = (reversed_rm & i32(2**26)) >> i32(26) if b27 else i32(0) - b25 = (reversed_rm & i32(2**25)) >> i32(25) if b26 else i32(0) - b24 = (reversed_rm & i32(2**24)) >> i32(24) if b25 else i32(0) - b23 = (reversed_rm & i32(2**23)) >> i32(23) if b24 else i32(0) - b22 = (reversed_rm & i32(2**22)) >> i32(22) if b23 else i32(0) - b21 = (reversed_rm & i32(2**21)) >> i32(21) if b22 else i32(0) - b20 = (reversed_rm & i32(2**20)) >> i32(20) if b21 else i32(0) - b19 = (reversed_rm & i32(2**19)) >> i32(19) if b20 else i32(0) - b18 = (reversed_rm & i32(2**18)) >> i32(18) if b19 else i32(0) - b17 = (reversed_rm & i32(2**17)) >> i32(17) if b18 else i32(0) - b16 = (reversed_rm & i32(2**16)) >> i32(16) if b17 else i32(0) - b15 = (reversed_rm & i32(2**15)) >> i32(15) if b16 else i32(0) - b14 = (reversed_rm & i32(2**14)) >> i32(14) if b15 else i32(0) - b13 = (reversed_rm & i32(2**13)) >> i32(13) if b14 else i32(0) - b12 = (reversed_rm & i32(2**12)) >> i32(12) if b13 else i32(0) - b11 = (reversed_rm & i32(2**11)) >> i32(11) if b12 else i32(0) - b10 = (reversed_rm & i32(2**10)) >> i32(10) if b11 else i32(0) - b09 = (reversed_rm & i32(2 ** 9)) >> i32(9) if b10 else i32(0) - b08 = (reversed_rm & i32(2 ** 8)) >> i32(8) if b09 else i32(0) - b07 = (reversed_rm & i32(2 ** 7)) >> i32(7) if b08 else i32(0) - b06 = (reversed_rm & i32(2 ** 6)) >> i32(6) if b07 else i32(0) - b05 = (reversed_rm & i32(2 ** 5)) >> i32(5) if b06 else i32(0) - b04 = (reversed_rm & i32(2 ** 4)) >> i32(4) if b05 else i32(0) - b03 = (reversed_rm & i32(2 ** 3)) >> i32(3) if b04 else i32(0) - b02 = (reversed_rm & i32(2 ** 2)) >> i32(2) if b03 else i32(0) - b01 = (reversed_rm & i32(2 ** 1)) >> i32(1) if b02 else i32(0) - b00 = (reversed_rm & i32(2 ** 0)) >> i32(0) if b01 else i32(0) - - # Sum all partial results - rn = b31 + b30 + b29 + b28 + b27 + b26 + b25 + b24 + b23 + b22 + b21 + b20 \ - + b19 + b18 + b17 + b16 + b15 + b14 + b13 + b12 + b11 + b10 + b09 + b08 \ - + b07 + b06 + b05 + b04 + b03 + b02 + b01 + b00 - - -### Coprocessor option - -# Note: these instructions are implemented when needed - -# SWCP - Store Word to memory from a coprocessor register -# MemWord(Rm31..2||00) <- CRn 31..0 -manual_functions["swcp"] = sw - - -# LWCP - Load Word from memory to a coprocessor register -# CRn <- MemWord(Rm31..2||00) -manual_functions["lwcp"] = lw - - -def smcp(ir, instr, reg_src, deref_dst): - """SMCP - Store Word to memory from a coprocessor register""" - - # MemDword(Rm31..3||000) <- CRn - e = [] - e.append(ExprAssign(ExprMem(deref_dst.ptr & i32(0xFFFFFFF8), 32), reg_src)) - return e, [] - -manual_functions["smcp"] = smcp - - -def lmcp(ir, instr, reg_dst, deref_src): - """LMCP - Load Word from memory to a coprocessor register""" - - # CRn <- MemDword(Rm31..3||000) - e = [] - e.append(ExprAssign(reg_dst, ExprMem(deref_src.ptr & i32(0xFFFFFFF8), 32))) - return e, [] - -manual_functions["lmcp"] = lmcp - - -def swcpi(ir, instr, reg_src, deref_dst): - """SWCPI - Store Word to memory, and increment the address""" - - # MemWord(Rm31..2||00) <- CRn 31..0; Rm<-Rm+4 - e = [] - e.append(ExprAssign(ExprMem(deref_dst.ptr & i32(0xFFFFFFFC), 32), reg_src)) - e.append(ExprAssign(deref_dst.ptr, deref_dst.ptr + i32(4))) - return e, [] - -manual_functions["swcpi"] = swcpi - - -def lwcpi(ir, instr, reg_dst, deref_src): - """LWCPI - Load Word from memory, and increment the address""" - - # CRn <- MemWord(Rm31..2||00); Rm<-Rm+4 - e = [] - e.append(ExprAssign(reg_dst, ExprMem(deref_src.ptr & i32(0xFFFFFFFC), 32))) - e.append(ExprAssign(deref_src.ptr, deref_src.ptr + i32(4))) - return e, [] - -manual_functions["lwcpi"] = lwcpi - -def smcpi(ir, instr, reg_src, deref_dst): - """SMCPI - Store Word to memory, and increment the address""" - - # MemDword(Rm31..3||000) <- CRn; Rm<-Rm+8 - e = [] - e.append(ExprAssign(ExprMem(deref_dst.ptr & i32(0xFFFFFFF8), 32), reg_src)) - e.append(ExprAssign(deref_dst.ptr, deref_dst.ptr + i32(8))) - return e, [] - -manual_functions["smcpi"] = smcpi - - -def lmcpi(ir, instr, reg_dst, deref_src): - """LMCPI - Load Word from memory, and increment the address""" - - # CRn <- MemDword(Rm31..3||000); Rm<-Rm+8 - e = [] - e.append(ExprAssign(reg_dst, ExprMem(deref_src.ptr & i32(0xFFFFFFFC), 32))) - e.append(ExprAssign(deref_src.ptr, deref_src.ptr + i32(8))) - return e, [] - -manual_functions["lmcpi"] = lmcpi - - -### IR MeP definitions - -def get_mnemo_expr(ir, instr, *args): - """Simplify getting the IR from a miasm instruction.""" - - if instr.name.lower() in sbuild.functions: - mnemo_func = sbuild.functions[instr.name.lower()] - else: - mnemo_func = manual_functions[instr.name.lower()] - - ir, extra_ir = mnemo_func(ir, instr, *args) - return ir, extra_ir - - -class Lifter_MEPb(Lifter): - """Toshiba MeP miasm IR - Big Endian - - It transforms an instructon into an IR. - """ - - addrsize = 32 - - def __init__(self, loc_db): - Lifter.__init__(self, mn_mep, "b", loc_db) - self.pc = mn_mep.getpc() - self.sp = mn_mep.getsp() - self.IRDst = ExprId("IRDst", 32) - - def get_ir(self, instr): - """Get the IR from a miasm instruction.""" - - instr_ir, extra_ir = get_mnemo_expr(self, instr, *instr.args) - - return instr_ir, extra_ir - - def get_next_break_loc_key(self, instr): - """Returns a new label that identifies where the instruction is going. - - Note: it eases linking IR blocks - """ - - l = self.loc_db.get_or_create_offset_location(instr.offset + instr.l) - return l - - -class Lifter_MEPl(Lifter_MEPb): - """Toshiba MeP miasm IR - Little Endian""" - - def __init__(self, loc_db): - Lifter.__init__(self, mn_mep, "l", loc_db) - self.pc = mn_mep.getpc() - self.sp = mn_mep.getsp() - self.IRDst = ExprId("IRDst", 32) |