diff options
| author | Guillaume Valadon <guillaume@valadon.net> | 2018-06-15 12:10:10 +0200 |
|---|---|---|
| committer | Guillaume Valadon <guillaume@valadon.net> | 2018-07-12 22:50:51 +0200 |
| commit | b8e5038798b0dece628846acb5ad25d9d4e60395 (patch) | |
| tree | 932dd2676afcf0c4ba6bf0c57d3b574954461ad2 | |
| parent | 82eb5f6eb197fc59d2e9ae21cfda05a1868e462e (diff) | |
| download | miasm-b8e5038798b0dece628846acb5ad25d9d4e60395.tar.gz miasm-b8e5038798b0dece628846acb5ad25d9d4e60395.zip | |
Toshiba MeP support
56 files changed, 8914 insertions, 2 deletions
diff --git a/miasm2/analysis/machine.py b/miasm2/analysis/machine.py index 73b90aef..03d19503 100644 --- a/miasm2/analysis/machine.py +++ b/miasm2/analysis/machine.py @@ -12,7 +12,7 @@ class Machine(object): __available = ["arml", "armb", "armtl", "armtb", "sh4", "x86_16", "x86_32", "x86_64", "msp430", "mips32b", "mips32l", - "aarch64l", "aarch64b", "ppc32b"] + "aarch64l", "aarch64b", "ppc32b", "mepl", "mepb"] def __init__(self, machine_name): @@ -178,6 +178,20 @@ class Machine(object): mn = arch.mn_ppc from miasm2.arch.ppc.ira import ir_a_ppc32b as ira from miasm2.arch.ppc.sem import ir_ppc32b as ir + elif machine_name == "mepb": + from miasm2.arch.mep.disasm import dis_mepb as dis_engine + from miasm2.arch.mep import arch, jit + mn = arch.mn_mep + jitter = jit.jitter_mepb + from miasm2.arch.mep.ira import ir_a_mepb as ira + from miasm2.arch.mep.sem import ir_mepb as ir + elif machine_name == "mepl": + from miasm2.arch.mep.disasm import dis_mepl as dis_engine + from miasm2.arch.mep import arch, jit + mn = arch.mn_mep + jitter = jit.jitter_mepl + from miasm2.arch.mep.ira import ir_a_mepl as ira + from miasm2.arch.mep.sem import ir_mepl as ir else: raise ValueError('Unknown machine: %s' % machine_name) diff --git a/miasm2/arch/mep/__init__.py b/miasm2/arch/mep/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/miasm2/arch/mep/__init__.py diff --git a/miasm2/arch/mep/arch.py b/miasm2/arch/mep/arch.py new file mode 100644 index 00000000..3f844c06 --- /dev/null +++ b/miasm2/arch/mep/arch.py @@ -0,0 +1,2049 @@ +# Toshiba MeP-c4 - miasm architecture definition +# Guillaume Valadon <guillaume@valadon.net> + +from miasm2.core.cpu import * +from miasm2.core.utils import Disasm_Exception +from miasm2.expression.expression import * +from miasm2.core.asm_ast import AstId, AstMem + +from miasm2.arch.mep.regs import * +import miasm2.arch.mep.regs as mep_regs_module # will be used to set mn_mep.regs + + +# Note: pyparsing is used to alter the way special operands are parsed +from pyparsing import Literal, Group, Word, hexnums + + +# These definitions will help parsing dereferencing instructions (i.e. that uses +# parenthesis) with pyparsing +LPARENTHESIS = Literal("(") +RPARENTHESIS = Literal(")") +PLUSSIGN = Literal("+") +HEX_INTEGER = str_int_pos | str_int_neg + + +def ExprInt2SignedString(expr, pos_fmt="%d", neg_fmt="%d", size=None, offset=0): + """Return the signed string corresponding to an ExprInt + + Note: this function is only useful to mimic objdump output""" + + # Apply a mask to the integer + if size is None: + mask_length = expr.size + else: + mask_length = size + mask = (1 << mask_length) - 1 + value = int(expr.arg) & mask + + # Return a signed integer if necessary + if (value >> mask_length - 1) == 1: + value = offset - ((value ^ mask) + 1) + if value < 0: + return "-" + neg_fmt % -value + else: + value += offset + + return pos_fmt % value + + +class instruction_mep(instruction): + """Generic MeP-c4 instruction + + Notes: + - this object is used to build internal miasm instructions based + on mnemonics + - it must be implemented ! + """ + + # Default delay slot + # Note: + # - mandatory for the miasm2 Machine + delayslot = 0 + + @staticmethod + def arg2str(expr, pos=None, loc_db=None): + """Convert mnemonics arguments into readable strings according to the + MeP-c4 architecture manual and their internal types + + Notes: + - it must be implemented ! However, a simple 'return str(expr)' + could do the trick. + - it is used to mimic objdump output + + Args: + expr: argument as a miasm2 expression + pos: position index in the arguments list + """ + + if isinstance(expr, ExprId) or isinstance(expr, ExprInt): + return str(expr) + + elif isinstance(expr, ExprLoc): + if loc_db is not None: + return loc_db.pretty_str(expr.loc_key) + else: + return str(expr) + + elif isinstance(expr, ExprMem) and (isinstance(expr.arg, ExprId) or isinstance(expr.arg, ExprInt)): + return "(%s)" % expr.arg + + elif isinstance(expr, ExprMem) and isinstance(expr.arg, ExprOp): + return "0x%X(%s)" % (expr.arg.args[1].arg, expr.arg.args[0]) + + # Raise an exception if the expression type was not processed + message = "instruction_mep.arg2str(): don't know what \ + to do with a '%s' instance." % type(expr) + raise Disasm_Exception(message) + + def __str__(self): + """Return the mnemonic as a string. + + Note: + - it is not mandatory as the instruction class already implement + it. It used to get rid of the padding between the opcode and the + arguments. + - most of this code is copied from miasm2/core/cpu.py + """ + + o = "%s" % self.name + + if self.name == "SSARB": + # The first operand is displayed in decimal, not in hex + o += " %d" % self.args[0].arg + o += self.arg2str(self.args[1]) + + elif self.name in ["MOV", "ADD"] and isinstance(self.args[1], ExprInt): + # The second operand is displayed in decimal, not in hex + o += " " + self.arg2str(self.args[0]) + o += ", %s" % ExprInt2SignedString(self.args[1].arg) + + elif "CPI" in self.name: + # The second operand ends with the '+' sign + o += " " + self.arg2str(self.args[0]) + deref_reg_str = self.arg2str(self.args[1]) + o += ", %s+)" % deref_reg_str[:-1] # GV: looks ugly + + elif self.name[0] in ["S", "L"] and self.name[-3:] in ["CPA", "PM0", "PM1"]: + # The second operand ends with the '+' sign + o += " " + self.arg2str(self.args[0]) + deref_reg_str = self.arg2str(self.args[1]) + o += ", %s+)" % deref_reg_str[:-1] # GV: looks ugly + # The third operand is displayed in decimal, not in hex + o += ", %s" % ExprInt2SignedString(self.args[2].arg) + + elif len(self.args) == 2 and self.name in ["SB", "SH", "LBU", "LB", "LH", "LW"] and \ + isinstance(self.args[1], ExprMem) and isinstance(self.args[1].arg, 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].arg.args[1], "0x%X") + o += "(%s)" % self.arg2str(self.args[1].arg.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].arg, 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].arg.args[1]) + o += "(%s)" % self.arg2str(self.args[1].arg.args[0]) + + elif self.name == "SLL" and isinstance(self.args[1], ExprInt): # Major Opcodes #6 + # The second operand is displayed in hex, not in decimal + o += " " + self.arg2str(self.args[0]) + o += ", 0x%X" % self.args[1].arg + + elif self.name in ["ADD3", "SLT3"] and isinstance(self.args[2], ExprInt): + o += " %s" % self.arg2str(self.args[0]) + o += ", %s" % self.arg2str(self.args[1]) + # The third operand is displayed in decimal, not in hex + o += ", %s" % ExprInt2SignedString(self.args[2].arg, pos_fmt="0x%X") + + elif self.name == "(RI)": + return o + + else: + args = [] + if self.args: + o += " " + for i, arg in enumerate(self.args): + if not isinstance(arg, Expr): + raise ValueError('zarb arg type') + x = self.arg2str(arg, pos=i) + args.append(x) + o += self.gen_args(args) + + return o + + def breakflow(self): + """Instructions that stop a basic bloc.""" + + if self.name in ["BRA", "BEQZ", "BNEZ", "BEQI", "BNEI", "BLTI", "BGEI", "BEQ", "BNE", "BSR"]: + return True + + if self.name in ["JMP", "JSR", "RET"]: + return True + + if self.name in ["RETI", "HALT", "SLEEP"]: + return True + + return False + + def splitflow(self): + """Instructions that splits a basic bloc, i.e. the CPU can go somewhere else.""" + + if self.name in ["BEQZ", "BNEZ", "BEQI", "BNEI", "BLTI", "BGEI", "BEQ", "BNE", "BSR"]: + return True + + return False + + def dstflow(self): + """Instructions that explicitly provide the destination.""" + + if self.name in ["BRA", "BEQZ", "BNEZ", "BEQI", "BNEI", "BLTI", "BGEI", "BEQ", "BNE", "BSR"]: + return True + + if self.name in ["JMP"]: + return True + + return False + + def dstflow2label(self, loc_db): + """Set the label for the current destination. + + Note: it is used at disassembly""" + + if self.name == "JMP" and isinstance(self.args[0], ExprId): + # 'JMP RM' does not provide the destination + return + + # Compute the correct address + num = self.get_dst_num() + addr = self.args[num].arg + if not self.name == "JMP": + addr += self.offset + + # Get a new label at the address + label = loc_db.get_or_create_offset_location(addr) + + # Assign the label to the correct instruction argument + self.args[num] = ExprLoc(label, self.args[num].size) + + def get_dst_num(self): + """Get the index of the argument that points to the instruction destination.""" + + if self.name[-1] == "Z": + num = 1 + elif self.name in ["BEQI", "BNEI", "BLTI", "BGEI", "BEQ", "BNE"]: + num = 2 + else: + num = 0 + + return num + + def getdstflow(self, loc_db): + """Get the argument that points to the instruction destination.""" + + num = self.get_dst_num() + return [self.args[num]] + + def is_subcall(self): + """Instructions used to call sub functions.""" + + return self.name in ["JSR", "BSR"] + + def fixDstOffset(self): + """Fix/correct the instruction immediate according to the current offset + + Note: - it is used at assembly + - code inspired by miasm2/arch/mips32/arch.py""" + + if self.name == "JMP" and isinstance(self.args[0], ExprInt): + # 'JMP IMMEDIATE' does not need to be fixed + return + + # Get the argument that needs to be fixed + if not len(self.args): + return + num = self.get_dst_num() + expr = self.args[num] + + # Check that the argument can be fixed + if self.offset is None: + raise ValueError("Symbol not resolved %s" % self.l) + if not isinstance(expr, ExprInt): + return + + # Adjust the immediate according to the current instruction offset + off = expr.arg - self.offset + if int(off % 2): + raise ValueError("Strange offset! %r" % off) + self.args[num] = ExprInt(off, 32) + + +class mep_additional_info: + """Additional MeP instructions information + """ + + def __init__(self): + self.except_on_instr = False + + +class mn_mep(cls_mn): + """Toshiba MeP-c4 disassembler & assembler + """ + + # Define variables that stores information used to disassemble & assemble + # Notes: - theses variables are mandatory + # - they could be moved to the cls_mn class + + num = 0 # holds the number of mnemonics + + all_mn = list() # list of mnenomnics, converted to metamn objects + + all_mn_mode = defaultdict(list) # mneomnics, converted to metamn objects + # Note: + # - the key is the mode # GV: what is it ? + # - the data is a list of mnemonics + + all_mn_name = defaultdict(list) # mnenomnics strings + # Note: + # - the key is the mnemonic string + # - the data is the corresponding + # metamn object + + all_mn_inst = defaultdict(list) # mnemonics objects + # Note: + # - the key is the mnemonic Python class + # - the data is an instanciated 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 informations + regs = mep_regs_module + + # Default delay slot + # Note: + # - mandatory for the miasm2 Machine + delayslot = 0 + + # Architecture name + name = "mep" + + # PC name depending on architecture attributes (here, l or b) + pc = {'l': PC, 'b': PC} + + def additional_info(self): + """Define instruction side effects # GV: not fully understood yet + + When used, it must return an object that implements specific + variables, such as except_on_instr. + + Notes: + - it must be implemented ! + - it could be moved to the cls_mn class + """ + + return mep_additional_info() + + @classmethod + def gen_modes(cls, subcls, name, bases, dct, fields): + """Ease populating internal variables used to disassemble & assemble, such + as self.all_mn_mode, self.all_mn_name and self.all_mn_inst + + Notes: + - it must be implemented ! + - it could be moved to the cls_mn class. All miasm architectures + use the same code + + Args: + cls: ? + sublcs: + name: mnemonic name + bases: ? + dct: ? + fields: ? + + Returns: + a list of ? + + """ + + dct["mode"] = None + return [(subcls, name, bases, dct, fields)] + + @classmethod + def getmn(cls, name): + """Get the mnemonic name + + Notes: + - it must be implemented ! + - it could be moved to the cls_mn class. Most miasm architectures + use the same code + + Args: + cls: the mnemonic class + name: the mnemonic string + """ + + return name.upper() + + @classmethod + def getpc(cls, attrib=None): + """"Return the ExprId that represents the Program Counter. + + Notes: + - mandatory for the symbolic execution + - PC is defined in regs.py + + Args: + attrib: architecture dependent attributes (here, l or b) + """ + + return PC + + @classmethod + def getsp(cls, attrib=None): + """"Return the ExprId that represents the Stack Pointer. + + Notes: + - mandatory for the symbolic execution + - SP is defined in regs.py + + Args: + attrib: architecture dependent attributes (here, l or b) + """ + + return SP + + @classmethod + def getbits(cls, bitstream, attrib, start, n): + """Return an integer of n bits at the 'start' offset + + Note: code from miasm2/arch/mips32/arch.py + """ + + # Return zero if zero bits are requested + if not n: + return 0 + + o = 0 # the returned value + while n: + # Get a byte, the offset is adjusted according to the endianness + offset = start / 8 # the offset in bytes + n_offset = cls.endian_offset(attrib, offset) # the adjusted offset + c = cls.getbytes(bitstream, n_offset, 1) + if not c: + raise IOError + + # Extract the bits value + c = ord(c) + r = 8 - start % 8 + c &= (1 << r) - 1 + l = min(r, n) + c >>= (r - l) + o <<= l + o |= c + n -= l + start += l + + return o + + @classmethod + def endian_offset(cls, attrib, offset): + """Adjust the byte offset according to the endianness""" + + if attrib == "l": # Little Endian + if offset % 2: + return offset - 1 + else: + return offset + 1 + + elif attrib == "b": # Big Endian + return offset + + else: + raise NotImplementedError("Bad MeP endianness") + + def value(self, mode): + """Adjust the assembled instruction based on the endianness + + Note: code inspired by miasm2/arch/mips32/arch.py + """ + + # Get the candidated + candidates = super(mn_mep, self).value(mode) + + if mode == "l": + # Invert bytes per 16-bits + for i in range(len(candidates)): + tmp = candidates[i][1] + candidates[i][0] + if len(candidates[i]) == 4: + tmp += candidates[i][3] + candidates[i][2] + candidates[i] = tmp + return candidates + + elif mode == "b": + return candidates + + else: + raise NotImplementedError("Bad MeP endianness (%s)" % mode) + + +def addop(name, fields, args=None, alias=False): + """Dynamically create the "name" object + + Notes: + - it could be moved to a generic function such as: + addop(name, fields, cls_mn, args=None, alias=False). + - most architectures use the same code + + Args: + name: the mnemonic name + fields: used to fill the object.__dict__'fields' attribute # GV: not understood yet + args: used to fill the object.__dict__'fields' attribute # GV: not understood yet + alias: used to fill the object.__dict__'fields' attribute # GV: not understood yet + """ + + namespace = {"fields": fields, "alias": alias} + + if args is not None: + namespace["args"] = args + + # Dynamically create the "name" object + type(name, (mn_mep,), namespace) + + +# Define specific operand parsers & converters + +def deref2expr(s, l, parse_results): + """Convert a parsed dereferenced register to an ExprMem""" + + # Only use the first results + parse_results = parse_results[0] + + if type(parse_results[0]) == AstInt and isinstance(parse_results[2], AstId): + return AstMem(parse_results[2] + parse_results[0], 32) # 1 == "(" and 3 == ")" + + elif type(parse_results[0]) == int and isinstance(parse_results[2], AstId): + return AstMem(parse_results[2] + AstOp('-', AstInt(-parse_results[0])), 32) # 1 == "(" and 3 == ")" + + else: + return AstMem(parse_results[1], 32) # 0 == "(" and 2 == ")" + + +deref_reg_parser = Group(LPARENTHESIS + gpr_infos.parser + RPARENTHESIS).setParseAction(deref2expr) +deref_inc_reg_parser = Group(LPARENTHESIS + gpr_infos.parser + PLUSSIGN + RPARENTHESIS).setParseAction(deref2expr) +abs24_deref_parser = Group(LPARENTHESIS + HEX_INTEGER + RPARENTHESIS).setParseAction(deref2expr) +offset_deref_reg_parser = Group(HEX_INTEGER + LPARENTHESIS + gpr_infos.parser + RPARENTHESIS).setParseAction(deref2expr) + +# Define registers decoders and encoders + +class mep_arg(m_arg): + def asm_ast_to_expr(self, arg, loc_db): + """Convert AST to expressions + + Note: - code inspired by miasm2/arch/mips32/arch.py""" + + if isinstance(arg, AstId): + if isinstance(arg.name, ExprId): + return arg.name + if isinstance(arg.name, str) and arg.name in gpr_names: + return None # GV: why? + loc_key = loc_db.get_or_create_name_location(arg.name) + return ExprLoc(loc_key, 32) + + elif isinstance(arg, AstMem): + addr = self.asm_ast_to_expr(arg.ptr, loc_db) + if addr is None: + return None + return ExprMem(addr, 32) + + elif isinstance(arg, AstInt): + return ExprInt(arg.value, 32) + + elif isinstance(arg, AstOp): + args = [self.asm_ast_to_expr(tmp, loc_db) for tmp in arg.args] + if None in args: + return None + return ExprOp(arg.op, *args) + + # Raise an exception if the argument was not processed + message = "mep_arg.asm_ast_to_expr(): don't know what \ + to do with a '%s' instance." % type(arg) + raise Exception(message) + +class mep_reg(reg_noarg, mep_arg): + """Generic Toshiba MeP-c4 register + + Note: + - the register size will be set using bs() + """ + reg_info = gpr_infos # the list of MeP-c4 registers defined in regs.py + parser = reg_info.parser # GV: not understood yet + + +class mep_deref_reg(mep_arg): + """Generic Toshiba MeP-c4 dereferenced register + + Note: + - the arg2str() method could be defined to change the output string + """ + parser = deref_reg_parser + + def decode(self, v): + """Transform the decoded value to a ExprMem(ExprId()) expression""" + r = gpr_infos.expr[v] # get the ExprId, i.e. the register expression + self.expr = ExprMem(r, 32) + return True + + def encode(self): + """Ensure that we have a ExprMem(ExprId()) expression, and return the + register value.""" + + if not isinstance(self.expr, ExprMem): + return False + if not isinstance(self.expr.arg, ExprId): + return False + + # Get the ExprId index, i.e. its value + self.value = gpr_exprs.index(self.expr.arg) + 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.arg, ExprOp): + return False + + # Get the integer and check the upper bound + v = int(self.expr.arg.args[1].arg & 0xFFFF) + + # Encode the values + self.parent.reg04_deref.value = gpr_exprs.index(self.expr.arg.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.arg, ExprOp): + return False + if self.expr.arg.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.arg.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.arg.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.arg.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 registe + """ + parser = deref_inc_reg_parser + + +# Immediate decoders and encoders + +class mep_int32_noarg(int32_noarg): + """Generic Toshiba MeP-c4 signed immediate + + Note: encode() is copied from int32_noarg.encode() and modified to allow + small (< 32 bits) signed immediate to be manipulated. + + """ + + def encode(self): + if not isinstance(self.expr, ExprInt): + return False + v = int(self.expr.arg) + # Note: the following lines were commented on purpose + #if sign_ext(v & self.lmask, self.l, self.intsize) != v: + # return False + v = self.encodeval(v & self.lmask) + self.value = v & self.lmask + return True + + +class mep_imm(imm_noarg, mep_arg): + """Generic Toshiba MeP-c4 immediate + + Note: + - the immediate size will be set using bs() + """ + parser = base_expr + + +class mep_imm6(mep_int32_noarg): + """Toshiba MeP-c4 signed 6 bits immediate.""" + parser = base_expr + intsize = 6 + intmask = (1 << intsize) - 1 + int2expr = lambda self, x: ExprInt(sign_ext(x, self.l, 32), 32) + + +class mep_imm8(mep_int32_noarg): + """Toshiba MeP-c4 signed 8 bits immediate.""" + parser = base_expr + intsize = 8 + intmask = (1 << intsize) - 1 + int2expr = lambda self, x: ExprInt(sign_ext(x, self.l, 32), 32) + + +class mep_imm16(mep_int32_noarg): + """Toshiba MeP-c4 16 bits immediate.""" + parser = base_expr + intsize = 16 + intmask = (1 << intsize) - 1 + int2expr = lambda self, x: ExprInt(x, 32) + + +class mep_imm16_signed(mep_int32_noarg): + """Toshiba MeP-c4 signed 16 bits immediate.""" + parser = base_expr + intsize = 16 + intmask = (1 << intsize) - 1 + int2expr = lambda self, x: ExprInt(sign_ext(x, self.l, 32), 32) + + +class mep_target24(mep_imm): + """Toshiba MeP-c4 target24 immediate, as used in JMP + """ + + def decode(self, v): + """Modify the decoded value using the previously decoded imm7. + """ + + # Apply the immediate mask + v = v & self.lmask + + # Shift values such as: + # target24=tttt_tttt_tttt_tttt||TTT_TTTT||0 + target24 = (v << 8) + ((self.parent.imm7.value & 0x7F) << 1) + + # Build the internal expression + self.expr = ExprInt(target24, 32) + return True + + def encode(self): + """Modify the encoded value. One part is stored in this object, and + the other one in imm7. + """ + + if not isinstance(self.expr, ExprInt): + return False + + # Get the integer and apply a mask + v = int(self.expr.arg) & 0x00FFFFFF + + # Encode the value into two parts + self.parent.imm7.value = (v & 0xFF) >> 1 + self.value = v >> 8 + return True + + +class mep_target24_signed(mep_target24): + """Toshiba MeP-c4 target24 signed immediate, as used in BSR + """ + + def decode(self, v): + """Perform sign extension + """ + + mep_target24.decode(self, v) + v = int(self.expr.arg) + self.expr = ExprInt(v, 24).signExtend(32) + return True + + +class mep_code20(mep_imm): + """Toshiba MeP-c4 code20 immediate, as used in DSP1 + """ + + def decode(self, v): + """Modify the decoded value using the previously decoded imm4_noarg. + """ + + # Apply the immediate mask + v = v & self.lmask + + # Shift values such as: + # code20=mmmm_cccc_cccc_cccc_cccc + code20 = v + ((self.parent.imm4.value & 0xFF) << 16) + + # Build the internal expression + self.expr = ExprInt(code20, 32) + return True + + def encode(self): + """Modify the encoded value. One part is stored in this object, and + the other one in imm4_noarg. + """ + + if not isinstance(self.expr, ExprInt): + return False + + # Get the integer and check the upper bound + v = int(self.expr.arg) + if v > 0xffffff: + return False + + # Encode the value into two parts + self.parent.imm4 = ((v >> 16) & 0xFF) + self.value = v + return True + + +class mep_code24(mep_imm): + """Toshiba MeP-c4 code24 immediate, as used in CP + """ + + def decode(self, v): + """Modify the decoded value using the previously decoded imm8_CCCC_CCCC. + """ + + # Shift values such as: + # code24=CCCC_CCCC||cccc_cccc_cccc_cccc + code24 = v + ((self.parent.imm8_CCCC_CCCC.value & 0xFF) << 16) + + # Build the internal expression + self.expr = ExprInt(code24, 32) + return True + + def encode(self): + """Modify the encoded value. One part is stored in this object, and + the other one in imm8_CCCC_CCCC. + """ + + if not isinstance(self.expr, ExprInt): + return False + + # Get the integer and check the upper bound + v = int(self.expr.arg) + if v > 0xFFFFFF: + return False + + # Encode the value into two parts + self.parent.imm8_CCCC_CCCC.value = ((v >> 16) & 0xFF) + self.value = v & 0xFFFF + return True + + +class mep_imm7_align4(mep_imm): + """Toshiba MeP-c4 imm7.align4 immediate, as used in Major #4 opcodes + """ + + def decode(self, v): + """Modify the decoded value. + """ + + # Apply the immediate mask + v = v & self.lmask + + # Shift value such as: + # imm7=iii_ii||00 + imm7_align4 = v << 2 + + # Build the internal expression + self.expr = ExprInt(imm7_align4, 32) + return True + + def encode(self): + """Modify the encoded value. + """ + + if not isinstance(self.expr, ExprInt): + return False + + # Get the integer and check the upper bound + v = int(self.expr.arg) + if v > 0x80: + return False + + # Encode the value + self.value = v >> 2 + return True + + +class mep_imm5_Iiiii (mep_imm): + """Toshiba MeP-c4 imm5 immediate, as used in STC & LDC. It encodes a + control/special register. + """ + + reg_info = csr_infos # the list of MeP-c4 control/special registers defined in regs.py + parser = reg_info.parser # GV: not understood yet + + def decode(self, v): + """Modify the decoded value using the previously decoded imm4_iiii + """ + + # Apply the immediate mask + I = v & self.lmask + + # Shift values such as: + # imm5=I||iiii + imm5 = (I << 4) + (self.parent.imm4_iiii.value & 0xF) + + # Build the internal register expression + self.expr = ExprId(csr_names[imm5], 32) + return True + + def encode(self): + """Modify the encoded value. One part is stored in this object, and + the other one in imm4_iiii. + """ + + if not isinstance(self.expr, ExprId): + return False + + # Get the register number and check the upper bound + v = csr_names.index(self.expr.name) + if v > 0x1F: + return False + + # Encode the value into two parts + self.parent.imm4_iiii.value = v & 0xF # iiii + self.value = (v >> 4) & 0b1 # I + return True + + +class mep_disp7_align2(mep_imm): + """Toshiba MeP-c4 disp7.align2 immediate, as used in Major #8 opcodes + """ + upper_bound = 0x7F + bits_shift = 1 + + def decode(self, v): + """Modify the decoded value. + """ + + # Apply the immediate mask + v = v & self.lmask + + # Shift value such as: + # disp7 = ddd_ddd||0 + disp7_align2 = (v << self.bits_shift) + + # Sign extension + disp7_align2 = sign_ext(disp7_align2, self.l + self.bits_shift, 32) + + # Build the internal expression + self.expr = ExprInt(disp7_align2, 32) + return True + + def encode(self): + """Modify the encoded value. + """ + + if not isinstance(self.expr, ExprInt): + return False + + # Get the integer + v = int(self.expr.arg) & self.upper_bound + + # Encode the value + self.value = (v >> self.bits_shift) & self.upper_bound + self.value = (v & self.upper_bound) >> self.bits_shift + return True + + +class mep_disp8_align2(mep_disp7_align2): + upper_bound = 0xFF + + +class mep_disp8_align4(mep_disp7_align2): + upper_bound = 0xFF + bits_shift = 2 + + +class mep_imm8_align8(mep_disp7_align2): + upper_bound = 0xFF + bits_shift = 3 + + +class mep_disp12_align2(mep_disp7_align2): + upper_bound = 0xFFF + + +class mep_disp12_align2_signed(mep_disp12_align2): + + def decode(self, v): + """Perform sign extension. + """ + mep_disp12_align2.decode(self, v) + v = int(self.expr.arg) + + self.expr = ExprInt(v, 12).signExtend(32) + return True + + +class mep_disp17(mep_disp7_align2): + upper_bound = 0x1FFFF + + +class mep_imm24(mep_imm): + """Toshiba MeP-c4 imm24 immediate, as used in MOVU + """ + + def decode(self, v): + """Modify the decoded value. + """ + + # Apply the immediate mask + v = v & self.lmask + + # Shift values such as: + # imm24=iiii_iiii_iiii_iiii||IIII_IIIII + imm24 = ((v & 0xFFFF) << 8) + ((v & 0xFF0000) >> 16) + + # Build the internal expression + self.expr = ExprInt(imm24, 32) + return True + + def encode(self): + """Modify the encoded value. + """ + + if not isinstance(self.expr, ExprInt): + return False + + # Get the integer and check the upper bound + v = int(self.expr.arg) + if v > 0xFFFFFF: + return False + + # Encode the value + self.value = ((v & 0xFFFF00) >> 8) + ((v & 0xFF) << 16) + return True + + +class mep_abs24(mep_imm): + """Toshiba MeP-c4 abs24 immediate + """ + parser = abs24_deref_parser + + def decode(self, v): + """Modify the decoded value using the previously decoded imm6. + """ + + # Apply the immediate mask + v = v & self.lmask + + # Shift values such as: + # abs24=dddd_dddd_dddd_dddd||DDDD_DD||00 + abs24 = (v << 8) + ((self.parent.imm6.value & 0x3F) << 2) + + # Build the internal expression + self.expr = ExprMem(ExprInt(abs24, 32), 32) + return True + + def encode(self): + """Modify the encoded value. One part is stored in this object, and + the other one in imm6. + """ + + if not (isinstance(self.expr, ExprMem) and isinstance(self.expr.arg, ExprInt)): + return False + + # Get the integer and check the upper bound + v = int(self.expr.arg.arg) + if v > 0xffffff: + return False + + # Encode the value into two parts + self.parent.imm6.value = (v & 0xFF) >> 2 + self.value = v >> 8 + return True + + +# Define MeP-c4 assembly operands + +reg04 = bs(l=4, # length in bits + cls=(mep_reg, )) # class implementing decoding & encoding + +reg04_l = bs(l=4, cls=(mep_reg, )) + +reg04_m = bs(l=4, cls=(mep_reg, )) + +reg04_n = bs(l=4, cls=(mep_reg, )) + +reg00 = bs(l=0, cls=(mep_reg, )) + +reg00_sp = bs(l=0, cls=(mep_reg_sp, )) + +reg00_tp = bs(l=0, cls=(mep_reg_tp, )) + +reg00_deref_sp = bs(l=0, cls=(mep_deref_sp_offset, )) + +reg00_deref_tp = bs(l=0, cls=(mep_deref_tp_offset, )) + +reg03 = bs(l=3, cls=(mep_reg, )) + +reg04_deref = bs(l=4, cls=(mep_deref_reg,)) + +reg04_deref_noarg = bs(l=4, fname="reg04_deref") + +reg04_inc_deref = bs(l=4, cls=(mep_deref_inc_reg,)) + +copro_reg04 = bs(l=4, cls=(mep_copro_reg,)) + +copro_reg05 = bs(l=1, cls=(mep_copro_reg_split,)) + +copro_reg06 = bs(l=2, cls=(mep_copro_reg_split,)) + +disp2 = bs(l=2, cls=(mep_imm, )) + +imm2 = disp2 + +imm3 = bs(l=3, cls=(mep_imm, )) + +imm4 = bs(l=4, cls=(mep_imm, )) + +imm4_noarg = bs(l=4, fname="imm4") + +imm4_iiii_noarg = bs(l=4, fname="imm4_iiii") + +imm5 = bs(l=5, cls=(mep_imm, )) + +imm5_Iiiii = bs(l=1, cls=(mep_imm5_Iiiii, )) # it is not an immediate, but a + # control/special register. + +imm6 = bs(l=6, cls=(mep_imm6, mep_arg)) + +imm6_noarg = bs(l=6, fname="imm6") + +imm7 = bs(l=7, cls=(mep_imm, )) + +imm7_noarg = bs(l=7, fname="imm7") # Note: + # - will be decoded as a 7 bits immediate + # - fname is used to set the operand name + # used in mep_target24 to merge operands + # values. By default, the bs class fills + # fname with an hex string compute from + # arguments passed to __init__ + +imm7_align4 = bs(l=5, cls=(mep_imm7_align4,)) + +imm7_align4_noarg = bs(l=5, fname="imm7_align4") + +disp7_align2 = bs(l=6, cls=(mep_disp7_align2,)) + +disp7_align2_noarg = bs(l=6, fname="disp7_align2") + +imm8 = bs(l=8, cls=(mep_imm8, mep_arg)) + +imm8_noarg = bs(l=8, fname="imm8_CCCC_CCCC") + +disp8 = bs(l=7, cls=(mep_disp8_align2, )) + +imm8_align2 = bs(l=7, cls=(mep_disp8_align2, )) + +imm8_align4 = bs(l=6, cls=(mep_disp8_align4, )) + +imm8_align8 = bs(l=5, cls=(mep_imm8_align8, )) + +imm12 = bs(l=12, cls=(mep_imm, )) + +disp12_signed = bs(l=11, cls=(mep_disp12_align2_signed, )) + +imm16 = bs(l=16, cls=(mep_imm16, mep_arg)) +imm16_signed = bs(l=16, cls=(mep_imm16_signed, mep_arg)) + +disp16_reg_deref = bs(l=16, cls=(mep_deref_reg_offset,)) + +disp17 = bs(l=16, cls=(mep_disp17, )) + +imm18 = bs(l=19, cls=(mep_imm, )) + +imm_code20 = bs(l=16, cls=(mep_code20, )) + +imm24 = bs(l=24, cls=(mep_imm24, )) + +imm_target24 = bs(l=16, cls=(mep_target24, )) +imm_target24_signed = bs(l=16, cls=(mep_target24_signed, )) + +imm_code24 = bs(l=16, cls=(mep_code24, )) + +abs24 = bs(l=16, cls=(mep_abs24, )) + + +# MeP-c4 mnemonics objects + +### <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/miasm2/arch/mep/disasm.py b/miasm2/arch/mep/disasm.py new file mode 100644 index 00000000..2ad73036 --- /dev/null +++ b/miasm2/arch/mep/disasm.py @@ -0,0 +1,23 @@ +# Toshiba MeP-c4 - miasm disassembly engine +# Guillaume Valadon <guillaume@valadon.net> + +from miasm2.core.asmblock import disasmEngine +from miasm2.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/miasm2/arch/mep/ira.py b/miasm2/arch/mep/ira.py new file mode 100644 index 00000000..34808656 --- /dev/null +++ b/miasm2/arch/mep/ira.py @@ -0,0 +1,45 @@ +# Toshiba MeP-c4 - miasm IR analysis +# Guillaume Valadon <guillaume@valadon.net> + +from miasm2.arch.mep.sem import ir_mepb, ir_mepl +from miasm2.ir.analysis import ira + + +class ir_a_mepb(ir_mepb, ira): + """MeP high level IR manipulations - Big Endian + + Notes: + - it is mandatory for symbolic execution. + """ + + def __init__(self, loc_db=None): + ir_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 ir_a_mepl(ir_mepl, ir_a_mepb): + """MeP high level IR manipulations - Little Endian""" + + def __init__(self, loc_db=None): + ir_a_mepb.__init__(self, loc_db) diff --git a/miasm2/arch/mep/jit.py b/miasm2/arch/mep/jit.py new file mode 100644 index 00000000..33eb5c3c --- /dev/null +++ b/miasm2/arch/mep/jit.py @@ -0,0 +1,115 @@ +# Toshiba MeP-c4 - miasm jitter +# Guillaume Valadon <guillaume@valadon.net> +# Note: inspiration from msp430/jit.py + +from miasm2.jitter.jitload import Jitter +from miasm2.core.locationdb import LocationDB +from miasm2.core.utils import * +from miasm2.jitter.codegen import CGen +from miasm2.ir.translators.C import TranslatorC +from miasm2.arch.mep.sem import ir_mepl, ir_mepb + +import logging + +log = logging.getLogger("jit_mep") +hnd = logging.StreamHandler() +hnd.setFormatter(logging.Formatter("[%(levelname)s]: %(message)s")) +log.addHandler(hnd) +log.setLevel(logging.CRITICAL) + + +class mep_CGen(CGen): + """ + Translate a bloc containing MeP instructions to C + + Note: it is used to emulate the *REPEAT instructions + """ + + def __init__(self, ir_arch): + self.ir_arch = ir_arch + self.PC = self.ir_arch.arch.regs.PC + self.translator = TranslatorC(self.ir_arch.loc_db) + self.init_arch_C() + + def gen_pre_code(self, attrib): + """Generate C code inserted before the current bloc""" + + # 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): + """Generate C code inserted after the current bloc""" + + # Call the base class method + out = super(mep_CGen, self).gen_post_code(attrib) + + # 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, *args, **kwargs): + sp = LocationDB() + Jitter.__init__(self, ir_mepl(sp), *args, **kwargs) + self.vm.set_little_endian() + self.ir_arch.jit_pc = self.ir_arch.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 = upck16(self.vm.get_mem(regs["SP"], 2)) + regs["SP"] += 2 + self.cpu.set_gpreg(regs) + return x + + def get_stack_arg(self, n): + regs = self.cpu.get_gpreg() + x = upck16(self.vm.get_mem(regs["SP"] + 2 * n, 2)) + 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, *args, **kwargs): + sp = LocationDB() + Jitter.__init__(self, ir_mepb(sp), *args, **kwargs) + self.vm.set_big_endian() + self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC diff --git a/miasm2/arch/mep/regs.py b/miasm2/arch/mep/regs.py new file mode 100644 index 00000000..9564d026 --- /dev/null +++ b/miasm2/arch/mep/regs.py @@ -0,0 +1,90 @@ +# Toshiba MeP-c4 - miasm registers definition +# Guillaume Valadon <guillaume@valadon.net> + +from miasm2.expression.expression import * +from miasm2.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 xrange(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 Conter. 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 xrange(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/miasm2/arch/mep/sem.py b/miasm2/arch/mep/sem.py new file mode 100644 index 00000000..32a3270d --- /dev/null +++ b/miasm2/arch/mep/sem.py @@ -0,0 +1,1172 @@ +# Toshiba MeP-c4 - miasm instructions side effects +# Guillaume Valadon <guillaume@valadon.net> + +from miasm2.core.sembuilder import SemBuilder +from miasm2.ir.ir import IntermediateRepresentation +from miasm2.arch.mep.arch import mn_mep +from miasm2.arch.mep.regs import PC, SP, LP, SAR, TP, RPB, RPE, RPC, EPC, NPC, \ + take_jmp, in_erepeat +from miasm2.arch.mep.regs import EXC, HI, LO, PSW, DEPC, DBG +from miasm2.expression.expression import ExprId, ExprInt, ExprOp +from miasm2.expression.expression import ExprAff, ExprCond, ExprMem +from miasm2.core.cpu import sign_ext +from miasm2.jitter.csts import EXCEPT_DIV_BY_ZERO + +from miasm2.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 + + +# 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 + +@sbuild.parse +def sb(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 + mem8[deref_dst.arg] = reg_src[:8] + + +@sbuild.parse +def sh(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 + mem16[deref_dst.arg & i32(0xFFFFFFFE)] = reg_src[:16] + + +@sbuild.parse +def sw(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 + + mem32[deref_dst.arg & i32(0xFFFFFFFC)] = reg_src + +# 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 [ExprAff(dst, reg_src)], [] + + +@sbuild.parse +def lb(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) + reg_dst = mem8[deref_dst.arg].signExtend(32) + + +@sbuild.parse +def lh(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)) + reg_dst = mem16[deref_dst.arg & i32(0xFFFFFFFE)].signExtend(32) + + +@sbuild.parse +def lw(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)) + reg_dst = mem32[deref_dst.arg & i32(0xFFFFFFFC)] + + +@sbuild.parse +def lbu(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)) + reg_dst = mem8[deref_dst.arg].zeroExtend(32) + + +@sbuild.parse +def lhu(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)) + reg_dst = mem16[deref_dst.arg & i32(0xFFFFFFFE)].zeroExtend(32) + + +### 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.arg) + result = ExprOp("+", reg_src, ExprInt(value, 32)) + + return [ExprAff(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 - Substract one register to another.""" + + # Rn <- Rn - Rm + reg1 = reg1 - reg2 + + +def sbvck3(ir, instr, r0, rn, rm): + """SBVCK3 - Check substraction overflow""" + + # if(Overflow(Rn-Rm)) R0<-1 else R0<-0 (Signed) + + # Substract 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 [ExprAff(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 (Unigned) + # 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, i32(0)) else ExprLoc(ir.get_next_break_loc_key(instr), 32) + take_jmp = ExprInt(1, 32) if "-"(reg_test, i32(0)) 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) + 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 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 = ExprAff(PC, reg_or_imm) + else: + # PC <- PC31..28||0000||(target24)23..1||0 + new_PC = ExprAff(PC, ExprOp("+", ExprOp("&", PC, ExprInt(0xF0000000, 32)), reg_or_imm)) + + return [new_PC, ExprAff(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(disp17.arg & 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(disp17.arg + 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 + +@sbuild.parse +def bsetm(rm_deref, imm3): + """BSETM - Bit Set Memory""" + + # MemByte(Rm) <- MemByte(Rm) or (1<<imm3) + mem8[rm_deref.arg] = ExprOp("|", mem8[rm_deref.arg], (i8(1) << imm3[:8])) + + +@sbuild.parse +def bclrm(rm_deref, imm3): + """BCLRM - Bit Clear Memory""" + + # MemByte(Rm) <- MemByte(Rm) and ~(1<<imm3) + shift = ExprOp("<<", i8(1), imm3[:8]) + mem8[rm_deref.arg] = ExprOp("&", mem8[rm_deref.arg], shift.__invert__()) + + +@sbuild.parse +def bnotm(rm_deref, imm3): + """BNOTM - Bit Not Memory""" + + # MemByte(Rm) <- MemByte(Rm) xor (1<<imm3) + mem8[rm_deref.arg] = ExprOp("^", mem8[rm_deref.arg], (i8(1) << imm3[:8])) + + +@sbuild.parse +def btstm(r0, rm_deref, imm3): + """BTSTM - Bit Test Memory""" + + # R0 <- ZeroExt( MemByte(Rm) and (1<<imm3) ) + r0 = ExprOp("&", mem8[rm_deref.arg], i8(1) << imm3[:8]).zeroExtend(32) + + +@sbuild.parse +def tas(rn, rm_deref): + """TAS - Load And Set""" + + # temp <- Rm; Rn <- ZeroExt(MemByte(temp)); MemByte(temp) <- 1 + temp = rm_deref + rn = mem8[temp.arg].zeroExtend(32) + mem8[temp.arg] = i8(1) + + +### 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 = "=="(are_both_neg, sign_mask) + + # 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 + + +@sbuild.parse +def smcp(reg_src, deref_dst): + """SMCP - Store Word to memory from a coprocessor register""" + + # MemDword(Rm31..3||000) <- CRn + mem32[deref_dst.arg & i32(0xFFFFFFF8)] = reg_src + + +@sbuild.parse +def lmcp(reg_dst, deref_src): + """LMCP - Load Word from memory to a coprocessor register""" + + # CRn <- MemDword(Rm31..3||000) + reg_dst = mem32[deref_src.arg & i32(0xFFFFFFF8)] + + +@sbuild.parse +def swcpi(reg_src, deref_dst): + """SWCPI - Store Word to memory, and increment the address""" + + # MemWord(Rm31..2||00) <- CRn 31..0; Rm<-Rm+4 + mem32[deref_dst.arg & i32(0xFFFFFFFC)] = reg_src + deref_dst.arg = deref_dst.arg + i32(4) + + +@sbuild.parse +def lwcpi(reg_dst, deref_src): + """LWCPI - Load Word from memory, and increment the address""" + + # CRn <- MemWord(Rm31..2||00); Rm<-Rm+4 + reg_dst = mem32[deref_src.arg & i32(0xFFFFFFFC)] + deref_src.arg = deref_src.arg + i32(4) + + +@sbuild.parse +def smcpi(reg_src, deref_dst): + """SMCPI - Store Word to memory, and increment the address""" + + # MemDword(Rm31..3||000) <- CRn; Rm<-Rm+8 + mem32[deref_dst.arg & i32(0xFFFFFFF8)] = reg_src + deref_dst.arg = deref_dst.arg + i32(8) + + +@sbuild.parse +def lmcpi(reg_dst, deref_src): + """LMCPI - Load Word from memory, and increment the address""" + + # CRn <- MemDword(Rm31..3||000); Rm<-Rm+8 + reg_dst = mem32[deref_src.arg & i32(0xFFFFFFFC)] + deref_src.arg = deref_src.arg + i32(8) + + +### 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 ir_mepb(IntermediateRepresentation): + """Toshiba MeP miasm IR - Big Endian + + It transforms an instructon into an IR. + """ + + def __init__(self, loc_db=None): + IntermediateRepresentation.__init__(self, mn_mep, "b", loc_db) + self.pc = mn_mep.getpc() + self.sp = mn_mep.getsp() + self.IRDst = ExprId("IRDst", 32) + self.addrsize = 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 instuction is going. + + Note: it eases linking IR blocs + """ + + l = self.loc_db.get_or_create_offset_location(instr.offset + instr.l) + return l + + +class ir_mepl(ir_mepb): + """Toshiba MeP miasm IR - Little Endian""" + + def __init__(self, loc_db=None): + IntermediateRepresentation.__init__(self, mn_mep, "l", loc_db) + self.pc = mn_mep.getpc() + self.sp = mn_mep.getsp() + self.IRDst = ExprId("IRDst", 32) diff --git a/miasm2/jitter/arch/JitCore_mep.c b/miasm2/jitter/arch/JitCore_mep.c new file mode 100644 index 00000000..e63fa97b --- /dev/null +++ b/miasm2/jitter/arch/JitCore_mep.c @@ -0,0 +1,618 @@ +// Inspired from JitCore_mep.c + +#include <Python.h> +#include "structmember.h" +#include <stdint.h> + +#include <inttypes.h> +#include "../queue.h" +#include "../vm_mngr.h" +#include "../vm_mngr_py.h" +#include "../JitCore.h" +#include "JitCore_mep.h" + + +reg_dict gpreg_dict[] = { + {.name = "R0", .offset = offsetof(vm_cpu_t, R0)}, + {.name = "R1", .offset = offsetof(vm_cpu_t, R1)}, + {.name = "R2", .offset = offsetof(vm_cpu_t, R2)}, + {.name = "R3", .offset = offsetof(vm_cpu_t, R3)}, + {.name = "R4", .offset = offsetof(vm_cpu_t, R4)}, + {.name = "R5", .offset = offsetof(vm_cpu_t, R5)}, + {.name = "R6", .offset = offsetof(vm_cpu_t, R6)}, + {.name = "R7", .offset = offsetof(vm_cpu_t, R7)}, + {.name = "R8", .offset = offsetof(vm_cpu_t, R8)}, + {.name = "R9", .offset = offsetof(vm_cpu_t, R9)}, + {.name = "R10", .offset = offsetof(vm_cpu_t, R10)}, + {.name = "R11", .offset = offsetof(vm_cpu_t, R11)}, + {.name = "R12", .offset = offsetof(vm_cpu_t, R12)}, + {.name = "TP", .offset = offsetof(vm_cpu_t, TP)}, + {.name = "GP", .offset = offsetof(vm_cpu_t, GP)}, + {.name = "SP", .offset = offsetof(vm_cpu_t, SP)}, + + {.name = "PC", .offset = offsetof(vm_cpu_t, PC)}, + {.name = "LP", .offset = offsetof(vm_cpu_t, LP)}, + {.name = "SAR", .offset = offsetof(vm_cpu_t, SAR)}, + {.name = "S3", .offset = offsetof(vm_cpu_t, S3)}, + {.name = "RPB", .offset = offsetof(vm_cpu_t, RPB)}, + {.name = "RPE", .offset = offsetof(vm_cpu_t, RPE)}, + {.name = "RPC", .offset = offsetof(vm_cpu_t, RPC)}, + {.name = "HI", .offset = offsetof(vm_cpu_t, HI)}, + {.name = "LO", .offset = offsetof(vm_cpu_t, LO)}, + {.name = "S9", .offset = offsetof(vm_cpu_t, S9)}, + {.name = "S10", .offset = offsetof(vm_cpu_t, S10)}, + {.name = "S11", .offset = offsetof(vm_cpu_t, S11)}, + {.name = "MB0", .offset = offsetof(vm_cpu_t, MB0)}, + {.name = "ME0", .offset = offsetof(vm_cpu_t, ME0)}, + {.name = "MB1", .offset = offsetof(vm_cpu_t, MB1)}, + {.name = "ME1", .offset = offsetof(vm_cpu_t, ME1)}, + {.name = "PSW", .offset = offsetof(vm_cpu_t, PSW)}, + {.name = "ID", .offset = offsetof(vm_cpu_t, ID)}, + {.name = "TMP", .offset = offsetof(vm_cpu_t, TMP)}, + {.name = "EPC", .offset = offsetof(vm_cpu_t, EPC)}, + {.name = "EXC", .offset = offsetof(vm_cpu_t, EXC)}, + {.name = "CFG", .offset = offsetof(vm_cpu_t, CFG)}, + {.name = "S22", .offset = offsetof(vm_cpu_t, S22)}, + {.name = "NPC", .offset = offsetof(vm_cpu_t, NPC)}, + {.name = "DBG", .offset = offsetof(vm_cpu_t, DBG)}, + {.name = "DEPC", .offset = offsetof(vm_cpu_t, DEPC)}, + {.name = "OPT", .offset = offsetof(vm_cpu_t, OPT)}, + {.name = "RCFG", .offset = offsetof(vm_cpu_t, RCFG)}, + {.name = "CCFG", .offset = offsetof(vm_cpu_t, CCFG)}, + {.name = "S29", .offset = offsetof(vm_cpu_t, S29)}, + {.name = "S30", .offset = offsetof(vm_cpu_t, S30)}, + {.name = "S31", .offset = offsetof(vm_cpu_t, S31)}, + {.name = "S32", .offset = offsetof(vm_cpu_t, S32)}, + {.name = "take_jmp", .offset = offsetof(vm_cpu_t, take_jmp)}, + {.name = "last_addr", .offset = offsetof(vm_cpu_t, last_addr)}, + {.name = "is_repeat_end", .offset = offsetof(vm_cpu_t, is_repeat_end)}, + + {.name = "PC_end", .offset = offsetof(vm_cpu_t, PC_end)}, + {.name = "RPE_instr_count", .offset = offsetof(vm_cpu_t, RPE_instr_count)}, + {.name = "RPC_current", .offset = offsetof(vm_cpu_t, RPC_current)}, + +}; + +/************************** JitCpu object **************************/ + + + +PyObject* cpu_get_gpreg(JitCpu* self) +{ + PyObject *dict = PyDict_New(); + PyObject *o; + + get_reg(R0); + get_reg(R1); + get_reg(R2); + get_reg(R3); + get_reg(R4); + get_reg(R5); + get_reg(R6); + get_reg(R7); + get_reg(R8); + get_reg(R9); + get_reg(R10); + get_reg(R11); + get_reg(R12); + get_reg(TP); + get_reg(GP); + get_reg(SP); + + get_reg(PC); + get_reg(LP); + get_reg(SAR); + get_reg(S3); + get_reg(RPB); + get_reg(RPE); + get_reg(RPC); + get_reg(HI); + get_reg(LO); + get_reg(S9); + get_reg(S10); + get_reg(S11); + get_reg(MB0); + get_reg(ME0); + get_reg(MB1); + get_reg(ME1); + get_reg(PSW); + get_reg(ID); + get_reg(TMP); + get_reg(EPC); + get_reg(EXC); + get_reg(CFG); + get_reg(S22); + get_reg(NPC); + get_reg(DBG); + get_reg(DEPC); + get_reg(OPT); + get_reg(RCFG); + get_reg(CCFG); + get_reg(S29); + get_reg(S30); + get_reg(S31); + get_reg(S32); + + get_reg(PC_end); + get_reg(RPE_instr_count); + get_reg(RPC_current); + + + return dict; +} + + +PyObject* cpu_set_gpreg(JitCpu* self, PyObject *args) +{ + PyObject* dict; + PyObject *d_key, *d_value = NULL; + Py_ssize_t pos = 0; + uint64_t val; + unsigned int i, found; + + if (!PyArg_ParseTuple(args, "O", &dict)) + return NULL; + if(!PyDict_Check(dict)) + RAISE(PyExc_TypeError, "arg must be dict"); + while(PyDict_Next(dict, &pos, &d_key, &d_value)){ + if(!PyString_Check(d_key)) + RAISE(PyExc_TypeError, "key must be str"); + + PyGetInt(d_value, val); + + found = 0; + for (i=0; i < sizeof(gpreg_dict)/sizeof(reg_dict); i++){ + if (strcmp(PyString_AsString(d_key), gpreg_dict[i].name)) + continue; + *((uint32_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val; + found = 1; + break; + } + + if (found) + continue; + fprintf(stderr, "unkown key: %s\n", PyString_AsString(d_key)); + RAISE(PyExc_ValueError, "unkown reg"); + } + Py_INCREF(Py_None); + return Py_None; +} + + + + +PyObject * cpu_init_regs(JitCpu* self) +{ + memset(self->cpu, 0, sizeof(vm_cpu_t)); + + Py_INCREF(Py_None); + return Py_None; + +} + +void dump_gpregs(vm_cpu_t* vmcpu) +{ + printf("R0 %.4"PRIX32" ", vmcpu->R0); + printf("R1 %.4"PRIX32" ", vmcpu->R1); + printf("R2 %.4"PRIX32" ", vmcpu->R2); + printf("R3 %.4"PRIX32" ", vmcpu->R3); + printf("R4 %.4"PRIX32" ", vmcpu->R4); + printf("R5 %.4"PRIX32" ", vmcpu->R5); + printf("R6 %.4"PRIX32" ", vmcpu->R6); + printf("R7 %.4"PRIX32" ", vmcpu->R7); + printf("R8 %.4"PRIX32" ", vmcpu->R8); + printf("R9 %.4"PRIX32" ", vmcpu->R9); + printf("R10 %.4"PRIX32" ", vmcpu->R10); + printf("R11 %.4"PRIX32" ", vmcpu->R11); + printf("R12 %.4"PRIX32" ", vmcpu->R12); + printf("TP %.4"PRIX32" ", vmcpu->TP); + printf("GP %.4"PRIX32" ", vmcpu->GP); + printf("SP %.4"PRIX32" ", vmcpu->SP); + printf("\n"); +} + + +PyObject * cpu_dump_gpregs(JitCpu* self, PyObject* args) +{ + vm_cpu_t* vmcpu; + + vmcpu = self->cpu; + dump_gpregs(vmcpu); + Py_INCREF(Py_None); + return Py_None; +} + + +PyObject* cpu_set_exception(JitCpu* self, PyObject* args) +{ + PyObject *item1; + uint64_t i; + + if (!PyArg_ParseTuple(args, "O", &item1)) + return NULL; + + PyGetInt(item1, i); + + ((vm_cpu_t*)self->cpu)->exception_flags = i; + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* cpu_get_exception(JitCpu* self, PyObject* args) +{ + return PyLong_FromUnsignedLongLong((uint64_t)(((vm_cpu_t*)self->cpu)->exception_flags)); +} + + + + + +void check_automod(JitCpu* jitcpu, uint64_t addr, uint64_t size) +{ + PyObject *result; + + if (!(((VmMngr*)jitcpu->pyvm)->vm_mngr.exception_flags & EXCEPT_CODE_AUTOMOD)) + return; + result = PyObject_CallMethod(jitcpu->jitter, "automod_cb", "LL", addr, size); + Py_DECREF(result); + +} + +void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src) +{ + vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); + check_automod(jitcpu, addr, 8); +} + +void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src) +{ + vm_MEM_WRITE_16(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); + check_automod(jitcpu, addr, 16); +} + +void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src) +{ + vm_MEM_WRITE_32(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); + check_automod(jitcpu, addr, 32); +} + +void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src) +{ + vm_MEM_WRITE_64(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); + check_automod(jitcpu, addr, 64); +} + + +PyObject* vm_set_mem(JitCpu *self, PyObject* args) +{ + PyObject *py_addr; + PyObject *py_buffer; + Py_ssize_t py_length; + + char * buffer; + uint64_t size; + uint64_t addr; + int ret = 0x1337; + + if (!PyArg_ParseTuple(args, "OO", &py_addr, &py_buffer)) + return NULL; + + PyGetInt(py_addr, addr); + + if(!PyString_Check(py_buffer)) + RAISE(PyExc_TypeError,"arg must be str"); + + size = PyString_Size(py_buffer); + PyString_AsStringAndSize(py_buffer, &buffer, &py_length); + + ret = vm_write_mem(&(((VmMngr*)self->pyvm)->vm_mngr), addr, buffer, size); + if (ret < 0) + RAISE(PyExc_TypeError,"arg must be str"); + check_automod(self, addr, size*8); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyMemberDef JitCpu_members[] = { + {NULL} /* Sentinel */ +}; + +static PyMethodDef JitCpu_methods[] = { + {"init_regs", (PyCFunction)cpu_init_regs, METH_NOARGS, "X"}, + {"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS, "X"}, + {"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS, "X"}, + {"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS, "X"}, + {"get_exception", (PyCFunction)cpu_get_exception, METH_VARARGS, "X"}, + {"set_exception", (PyCFunction)cpu_set_exception, METH_VARARGS, "X"}, + {"set_mem", (PyCFunction)vm_set_mem, METH_VARARGS, "X"}, + {"get_mem", (PyCFunction)vm_get_mem, METH_VARARGS, "X"}, + {NULL} /* Sentinel */ +}; + +static int +JitCpu_init(JitCpu *self, PyObject *args, PyObject *kwds) +{ + self->cpu = malloc(sizeof(vm_cpu_t)); + if (self->cpu == NULL) { + fprintf(stderr, "cannot alloc vm_cpu_t\n"); + exit(0); + } + return 0; +} + +getset_reg_u32(R0); +getset_reg_u32(R1); +getset_reg_u32(R2); +getset_reg_u32(R3); +getset_reg_u32(R4); +getset_reg_u32(R5); +getset_reg_u32(R6); +getset_reg_u32(R7); +getset_reg_u32(R8); +getset_reg_u32(R9); +getset_reg_u32(R10); +getset_reg_u32(R11); +getset_reg_u32(R12); +getset_reg_u32(TP); +getset_reg_u32(GP); +getset_reg_u32(SP); + +getset_reg_u32(PC); +getset_reg_u32(LP); +getset_reg_u32(SAR); +getset_reg_u32(S3); +getset_reg_u32(RPB); +getset_reg_u32(RPE); +getset_reg_u32(RPC); +getset_reg_u32(HI); +getset_reg_u32(LO); +getset_reg_u32(S9); +getset_reg_u32(S10); +getset_reg_u32(S11); +getset_reg_u32(MB0); +getset_reg_u32(ME0); +getset_reg_u32(MB1); +getset_reg_u32(ME1); +getset_reg_u32(PSW); +getset_reg_u32(ID); +getset_reg_u32(TMP); +getset_reg_u32(EPC); +getset_reg_u32(EXC); +getset_reg_u32(CFG); +getset_reg_u32(S22); +getset_reg_u32(NPC); +getset_reg_u32(DBG); +getset_reg_u32(DEPC); +getset_reg_u32(OPT); +getset_reg_u32(RCFG); +getset_reg_u32(CCFG); +getset_reg_u32(S29); +getset_reg_u32(S30); +getset_reg_u32(S31); +getset_reg_u32(S32); + +getset_reg_u32(PC_end); +getset_reg_u32(RPE_instr_count); +getset_reg_u32(RPC_current); + + + +PyObject* get_gpreg_offset_all(void) +{ + PyObject *dict = PyDict_New(); + PyObject *o; + get_reg_off(exception_flags); + + get_reg_off(R0); + get_reg_off(R1); + get_reg_off(R2); + get_reg_off(R3); + get_reg_off(R4); + get_reg_off(R5); + get_reg_off(R6); + get_reg_off(R7); + get_reg_off(R8); + get_reg_off(R9); + get_reg_off(R10); + get_reg_off(R11); + get_reg_off(R12); + get_reg_off(TP); + get_reg_off(GP); + get_reg_off(SP); + + get_reg_off(PC); + get_reg_off(LP); + get_reg_off(SAR); + get_reg_off(S3); + get_reg_off(RPB); + get_reg_off(RPE); + get_reg_off(RPC); + get_reg_off(HI); + get_reg_off(LO); + get_reg_off(S9); + get_reg_off(S10); + get_reg_off(S11); + get_reg_off(MB0); + get_reg_off(ME0); + get_reg_off(MB1); + get_reg_off(ME1); + get_reg_off(PSW); + get_reg_off(ID); + get_reg_off(TMP); + get_reg_off(EPC); + get_reg_off(EXC); + get_reg_off(CFG); + get_reg_off(S22); + get_reg_off(NPC); + get_reg_off(DBG); + get_reg_off(DEPC); + get_reg_off(OPT); + get_reg_off(RCFG); + get_reg_off(CCFG); + get_reg_off(S29); + get_reg_off(S30); + get_reg_off(S31); + get_reg_off(S32); + + get_reg_off(PC_end); + get_reg_off(RPE_instr_count); + get_reg_off(RPC_current); + + + return dict; +} + + + + +static PyGetSetDef JitCpu_getseters[] = { + {"vmmngr", + (getter)JitCpu_get_vmmngr, (setter)JitCpu_set_vmmngr, + "vmmngr", + NULL}, + + {"jitter", + (getter)JitCpu_get_jitter, (setter)JitCpu_set_jitter, + "jitter", + NULL}, + + + {"R0" , (getter)JitCpu_get_R0 , (setter)JitCpu_set_R0 , "R0" , NULL}, + {"R1" , (getter)JitCpu_get_R1 , (setter)JitCpu_set_R1 , "R1" , NULL}, + {"R2" , (getter)JitCpu_get_R2 , (setter)JitCpu_set_R2 , "R2" , NULL}, + {"R3" , (getter)JitCpu_get_R3 , (setter)JitCpu_set_R3 , "R3" , NULL}, + {"R4" , (getter)JitCpu_get_R4 , (setter)JitCpu_set_R4 , "R4" , NULL}, + {"R5" , (getter)JitCpu_get_R5 , (setter)JitCpu_set_R5 , "R5" , NULL}, + {"R6" , (getter)JitCpu_get_R6 , (setter)JitCpu_set_R6 , "R6" , NULL}, + {"R7" , (getter)JitCpu_get_R7 , (setter)JitCpu_set_R7 , "R7" , NULL}, + {"R8" , (getter)JitCpu_get_R8 , (setter)JitCpu_set_R8 , "R8" , NULL}, + {"R9" , (getter)JitCpu_get_R9 , (setter)JitCpu_set_R9 , "R9" , NULL}, + {"R10" , (getter)JitCpu_get_R10 , (setter)JitCpu_set_R10 , "R10" , NULL}, + {"R11" , (getter)JitCpu_get_R11 , (setter)JitCpu_set_R11 , "R11" , NULL}, + {"R12" , (getter)JitCpu_get_R12 , (setter)JitCpu_set_R12 , "R12" , NULL}, + {"TP" , (getter)JitCpu_get_TP , (setter)JitCpu_set_TP , "TP" , NULL}, + {"GP" , (getter)JitCpu_get_GP , (setter)JitCpu_set_GP , "GP" , NULL}, + {"SP" , (getter)JitCpu_get_SP , (setter)JitCpu_set_SP , "SP" , NULL}, + + {"PC" , (getter)JitCpu_get_PC , (setter)JitCpu_set_PC , "PC" , NULL}, + {"LP" , (getter)JitCpu_get_LP , (setter)JitCpu_set_LP , "LP" , NULL}, + {"SAR" , (getter)JitCpu_get_SAR , (setter)JitCpu_set_SAR , "SAR" , NULL}, + {"S3" , (getter)JitCpu_get_S3 , (setter)JitCpu_set_S3 , "S3" , NULL}, + {"RPB" , (getter)JitCpu_get_RPB , (setter)JitCpu_set_RPB , "RPB" , NULL}, + {"RPE" , (getter)JitCpu_get_RPE , (setter)JitCpu_set_RPE , "RPE" , NULL}, + {"RPC" , (getter)JitCpu_get_RPC , (setter)JitCpu_set_RPC , "RPC" , NULL}, + {"HI" , (getter)JitCpu_get_HI , (setter)JitCpu_set_HI , "HI" , NULL}, + {"LO" , (getter)JitCpu_get_LO , (setter)JitCpu_set_LO , "LO" , NULL}, + {"S9" , (getter)JitCpu_get_S9 , (setter)JitCpu_set_S9 , "S9" , NULL}, + {"S10" , (getter)JitCpu_get_S10 , (setter)JitCpu_set_S10 , "S10" , NULL}, + {"S11" , (getter)JitCpu_get_S11 , (setter)JitCpu_set_S11 , "S11" , NULL}, + {"MB0" , (getter)JitCpu_get_MB0 , (setter)JitCpu_set_MB0 , "MB0" , NULL}, + {"ME0" , (getter)JitCpu_get_ME0 , (setter)JitCpu_set_ME0 , "ME0" , NULL}, + {"MB1" , (getter)JitCpu_get_MB1 , (setter)JitCpu_set_MB1 , "MB1" , NULL}, + {"ME1" , (getter)JitCpu_get_ME1 , (setter)JitCpu_set_ME1 , "ME1" , NULL}, + {"PSW" , (getter)JitCpu_get_PSW , (setter)JitCpu_set_PSW , "PSW" , NULL}, + {"ID" , (getter)JitCpu_get_ID , (setter)JitCpu_set_ID , "ID" , NULL}, + {"TMP" , (getter)JitCpu_get_TMP , (setter)JitCpu_set_TMP , "TMP" , NULL}, + {"EPC" , (getter)JitCpu_get_EPC , (setter)JitCpu_set_EPC , "EPC" , NULL}, + {"EXC" , (getter)JitCpu_get_EXC , (setter)JitCpu_set_EXC , "EXC" , NULL}, + {"CFG" , (getter)JitCpu_get_CFG , (setter)JitCpu_set_CFG , "CFG" , NULL}, + {"S22" , (getter)JitCpu_get_S22 , (setter)JitCpu_set_S22 , "S22" , NULL}, + {"NPC" , (getter)JitCpu_get_NPC , (setter)JitCpu_set_NPC , "NPC" , NULL}, + {"DBG" , (getter)JitCpu_get_DBG , (setter)JitCpu_set_DBG , "DBG" , NULL}, + {"DEPC" , (getter)JitCpu_get_DEPC , (setter)JitCpu_set_DEPC , "DEPC" , NULL}, + {"OPT" , (getter)JitCpu_get_OPT , (setter)JitCpu_set_OPT , "OPT" , NULL}, + {"RCFG" , (getter)JitCpu_get_RCFG , (setter)JitCpu_set_RCFG , "RCFG" , NULL}, + {"CCFG" , (getter)JitCpu_get_CCFG , (setter)JitCpu_set_CCFG , "CCFG" , NULL}, + {"S29" , (getter)JitCpu_get_S29 , (setter)JitCpu_set_S29 , "S29" , NULL}, + {"S30" , (getter)JitCpu_get_S30 , (setter)JitCpu_set_S30 , "S30" , NULL}, + {"S31" , (getter)JitCpu_get_S31 , (setter)JitCpu_set_S31 , "S31" , NULL}, + {"S32" , (getter)JitCpu_get_S32 , (setter)JitCpu_set_S32 , "S32" , NULL}, + + {"PC_end" , (getter)JitCpu_get_PC_end , (setter)JitCpu_set_PC_end , "PC_end" , NULL}, + {"RPE_instr_count" , (getter)JitCpu_get_RPE_instr_count , (setter)JitCpu_set_RPE_instr_count , "RPE_instr_count" , NULL}, + {"RPC_current" , (getter)JitCpu_get_RPC_current , (setter)JitCpu_set_RPC_current , "RPC_current" , NULL}, + + + + {NULL} /* Sentinel */ +}; + + + +static PyTypeObject JitCpuType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "JitCore_mep.JitCpu", /*tp_name*/ + sizeof(JitCpu), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)JitCpu_dealloc,/*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "JitCpu objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + JitCpu_methods, /* tp_methods */ + JitCpu_members, /* tp_members */ + JitCpu_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)JitCpu_init, /* tp_init */ + 0, /* tp_alloc */ + JitCpu_new, /* tp_new */ +}; + + + +static PyMethodDef JitCore_mep_Methods[] = { + + /* + + */ + {"get_gpreg_offset_all", (PyCFunction)get_gpreg_offset_all, METH_NOARGS}, + {NULL, NULL, 0, NULL} /* Sentinel */ + +}; + +static PyObject *JitCore_mep_Error; + +PyMODINIT_FUNC +initJitCore_mep(void) +{ + PyObject *m; + + if (PyType_Ready(&JitCpuType) < 0) + return; + + m = Py_InitModule("JitCore_mep", JitCore_mep_Methods); + if (m == NULL) + return; + + JitCore_mep_Error = PyErr_NewException("JitCore_mep.error", NULL, NULL); + Py_INCREF(JitCore_mep_Error); + PyModule_AddObject(m, "error", JitCore_mep_Error); + + Py_INCREF(&JitCpuType); + PyModule_AddObject(m, "JitCpu", (PyObject *)&JitCpuType); + +} diff --git a/miasm2/jitter/arch/JitCore_mep.h b/miasm2/jitter/arch/JitCore_mep.h new file mode 100644 index 00000000..47075ba5 --- /dev/null +++ b/miasm2/jitter/arch/JitCore_mep.h @@ -0,0 +1,77 @@ +// Inspired from JitCore_msp430.h + +typedef struct { + /* miasm2 flags */ + uint32_t exception_flags; + + /* gpregs */ + uint32_t R0; + uint32_t R1; + uint32_t R2; + uint32_t R3; + uint32_t R4; + uint32_t R5; + uint32_t R6; + uint32_t R7; + uint32_t R8; + uint32_t R9; + uint32_t R10; + uint32_t R11; + uint32_t R12; + uint32_t TP; + uint32_t GP; + uint32_t SP; + + /* csregs */ + uint32_t PC; + uint32_t LP; + uint32_t SAR; + uint32_t S3; + uint32_t RPB; + uint32_t RPE; + uint32_t RPC; + uint32_t HI; + uint32_t LO; + uint32_t S9; + uint32_t S10; + uint32_t S11; + uint32_t MB0; + uint32_t ME0; + uint32_t MB1; + uint32_t ME1; + uint32_t PSW; + uint32_t ID; + uint32_t TMP; + uint32_t EPC; + uint32_t EXC; + uint32_t CFG; + uint32_t S22; + uint32_t NPC; + uint32_t DBG; + uint32_t DEPC; + uint32_t OPT; + uint32_t RCFG; + uint32_t CCFG; + uint32_t S29; + uint32_t S30; + uint32_t S31; + uint32_t S32; + + /* miasm2 specific regs */ + uint32_t PC_end; + uint32_t RPE_instr_count; + uint32_t RPC_current; + + + uint32_t take_jmp; + uint32_t last_addr; + uint32_t is_repeat_end; + uint32_t in_erepeat; + + /* flags */ + +} vm_cpu_t; + +void dump_gpregs(vm_cpu_t* vmcpu); + +#define RETURN_PC return BlockDst; diff --git a/miasm2/jitter/codegen.py b/miasm2/jitter/codegen.py index 10140fd2..a709d5ec 100644 --- a/miasm2/jitter/codegen.py +++ b/miasm2/jitter/codegen.py @@ -132,7 +132,8 @@ class CGen(object): @dst2index: LocKey -> uniq value @loc_key: LocKey istance""" - dst2index[loc_key] = len(dst2index) + if loc_key not in dst2index: + dst2index[loc_key] = len(dst2index) def assignblk_to_irbloc(self, instr, assignblk): """ diff --git a/miasm2/jitter/jitload.py b/miasm2/jitter/jitload.py index 288e737a..39ca3d56 100644 --- a/miasm2/jitter/jitload.py +++ b/miasm2/jitter/jitload.py @@ -196,6 +196,8 @@ class Jitter(object): from miasm2.jitter.arch import JitCore_mips32 as jcore elif arch_name == "ppc32": from miasm2.jitter.arch import JitCore_ppc32 as jcore + elif arch_name == "mep": + from miasm2.jitter.arch import JitCore_mep as jcore else: raise ValueError("unknown jit arch: %s" % arch_name) except ImportError: diff --git a/setup.py b/setup.py index 0a1acc00..1985a52e 100755 --- a/setup.py +++ b/setup.py @@ -12,6 +12,7 @@ def buil_all(): 'miasm2/arch/arm', 'miasm2/arch/aarch64', 'miasm2/arch/msp430', + 'miasm2/arch/mep', 'miasm2/arch/sh4', 'miasm2/arch/mips32', 'miasm2/arch/ppc', @@ -49,6 +50,10 @@ def buil_all(): "miasm2/jitter/vm_mngr.c", "miasm2/jitter/op_semantics.c", "miasm2/jitter/arch/JitCore_msp430.c"]), + Extension("miasm2.jitter.arch.JitCore_mep", + ["miasm2/jitter/JitCore.c", + "miasm2/jitter/vm_mngr.c", + "miasm2/jitter/arch/JitCore_mep.c"]), Extension("miasm2.jitter.arch.JitCore_mips32", ["miasm2/jitter/JitCore.c", "miasm2/jitter/vm_mngr.c", diff --git a/test/arch/mep/asm/launch.py b/test/arch/mep/asm/launch.py new file mode 100644 index 00000000..ed8d9f27 --- /dev/null +++ b/test/arch/mep/asm/launch.py @@ -0,0 +1,22 @@ +# Toshiba MeP-c4 - pytest unit tests wrapper +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_asm import launch_tests + +from test_major_opcode_0 import TestMajor0; launch_tests(TestMajor0()) +from test_major_opcode_1 import TestMajor1; launch_tests(TestMajor1()) +from test_major_opcode_2 import TestMajor2; launch_tests(TestMajor2()) +from test_major_opcode_3 import TestMajor3; launch_tests(TestMajor3()) +from test_major_opcode_4 import TestMajor4; launch_tests(TestMajor4()) +from test_major_opcode_5 import TestMajor5; launch_tests(TestMajor5()) +from test_major_opcode_6 import TestMajor6; launch_tests(TestMajor6()) +from test_major_opcode_7 import TestMajor7; launch_tests(TestMajor7()) +from test_major_opcode_8 import TestMajor8; launch_tests(TestMajor8()) +from test_major_opcode_9 import TestMajor9; launch_tests(TestMajor9()) +from test_major_opcode_10 import TestMajor10; launch_tests(TestMajor10()) +from test_major_opcode_11 import TestMajor11; launch_tests(TestMajor11()) +from test_major_opcode_12 import TestMajor12; launch_tests(TestMajor12()) +from test_major_opcode_13 import TestMajor13; launch_tests(TestMajor13()) +from test_major_opcode_14 import TestMajor14; launch_tests(TestMajor14()) +from test_major_opcode_15 import TestMajor15; launch_tests(TestMajor15()) +from test_asm import TestMisc; launch_tests(TestMisc()) diff --git a/test/arch/mep/asm/test_asm.py b/test/arch/mep/asm/test_asm.py new file mode 100644 index 00000000..ddf91ed6 --- /dev/null +++ b/test/arch/mep/asm/test_asm.py @@ -0,0 +1,38 @@ +# Toshiba MeP-c4 - Misc unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from miasm2.arch.mep.arch import mn_mep + +class TestMisc: + + def test(self): + + # Disassemble & assemble unit tests + unit_tests = [("ADD R1, 2", "6108")] + unit_tests += [("JMP 0xC3FA38", "d9c8c3fa")] + unit_tests += [("SLT3 R0, R8, R10", "08a2")] + unit_tests += [("SB R9, (R4)", "0948")] + unit_tests += [("SSARB 3(GP)", "13ec")] + unit_tests += [("SWCPI C13, (R2+)", "3d20")] + unit_tests += [("ADD3 R2, SP, 0x1C", "421c")] + unit_tests += [("SW R7, 0x50(SP)", "4752")] + + for mn_str, mn_hex in unit_tests: + print "-" * 49 # Tests separation + + # Dissassemble + mn_bin = mn_hex.decode("hex") + mn = mn_mep.dis(mn_bin, "b") + + print "dis: %s -> %s" % (mn_hex.rjust(20), str(mn).rjust(20)) + assert(str(mn) == mn_str) # dissassemble assertion + + # Assemble and return all possible candidates + instr = mn_mep.fromstring(str(mn), "b") + instr.mode = "b" + asm_list = [i.encode("hex") for i in mn_mep.asm(instr)] + + # Print the results + print "asm: %s -> %s" % (mn_str.rjust(20), + ", ".join(asm_list).rjust(20)) + assert(mn_hex in asm_list) # assemble assertion diff --git a/test/arch/mep/asm/test_major_opcode_0.py b/test/arch/mep/asm/test_major_opcode_0.py new file mode 100644 index 00000000..d517850a --- /dev/null +++ b/test/arch/mep/asm/test_major_opcode_0.py @@ -0,0 +1,268 @@ +# Toshiba MeP-c4 - Major Opcode #0 unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_asm import check_instruction + + +class TestMajor0: + + def test_MOV(self): + """Test the MOV instruction""" + + # Top instructions + check_instruction("MOV $0, $4", "0040") + check_instruction("MOV $TP, $1", "0d10") + check_instruction("MOV $1, $7", "0170") + check_instruction("MOV $1, $8", "0180") + check_instruction("MOV $1, $TP", "01d0") + + # Randomly choosen instructions + check_instruction("MOV $3, $7", "0370") + check_instruction("MOV $0, $SP", "00f0") + check_instruction("MOV $5, $SP", "05f0") + check_instruction("MOV $2, $10", "02a0") + check_instruction("MOV $GP, $12", "0ec0") + + def test_NEG(self): + """Test the NEG instruction""" + + # Top instructions + check_instruction("NEG $0, $12", "00c1") + check_instruction("NEG $1, $0", "0101") + check_instruction("NEG $0, $1", "0011") + check_instruction("NEG $0, $0", "0001") + check_instruction("NEG $0, $8", "0081") + + # Randomly choosen instructions + check_instruction("NEG $6, $6", "0661") + check_instruction("NEG $9, $5", "0951") + check_instruction("NEG $11, $12", "0bc1") + check_instruction("NEG $2, $6", "0261") + check_instruction("NEG $4, $9", "0491") + + def test_SLT3(self): + """Test the SLT3 instruction""" + + # Top instructions + check_instruction("SLT3 $0, $1, $0", "0102") + check_instruction("SLT3 $0, $4, $12", "04c2") + check_instruction("SLT3 $0, $0, $12", "00c2") + check_instruction("SLT3 $0, $0, $0", "0002") + check_instruction("SLT3 $0, $0, $8", "0082") + + # Randomly choosen instructions + check_instruction("SLT3 $0, $2, $4", "0242") + check_instruction("SLT3 $0, $SP, $2", "0f22") + check_instruction("SLT3 $0, $5, $9", "0592") + check_instruction("SLT3 $0, $6, $4", "0642") + check_instruction("SLT3 $0, $12, $6", "0c62") + + def test_SLTU3(self): + """Test the SLTU3 instruction""" + + # Top instructions + check_instruction("SLTU3 $0, $6, $8", "0683") + check_instruction("SLTU3 $0, $0, $0", "0003") + check_instruction("SLTU3 $0, $10, $11", "0ab3") + check_instruction("SLTU3 $0, $12, $0", "0c03") + check_instruction("SLTU3 $0, $4, $3", "0433") + + # Randomly choosen instructions + check_instruction("SLTU3 $0, $5, $TP", "05d3") + check_instruction("SLTU3 $0, $2, $5", "0253") + check_instruction("SLTU3 $0, $SP, $TP", "0fd3") + check_instruction("SLTU3 $0, $11, $10", "0ba3") + check_instruction("SLTU3 $0, $4, $7", "0473") + + def test_SUB(self): + """Test the SUB instruction""" + + # Top instructions + check_instruction("SUB $0, $6", "0064") + check_instruction("SUB $0, $0", "0004") + check_instruction("SUB $12, $4", "0c44") + check_instruction("SUB $4, $3", "0434") + check_instruction("SUB $0, $8", "0084") + + # Randomly choosen instructions + check_instruction("SUB $11, $9", "0b94") + check_instruction("SUB $9, $9", "0994") + check_instruction("SUB $TP, $2", "0d24") + check_instruction("SUB $1, $9", "0194") + check_instruction("SUB $SP, $11", "0fb4") + + def test_SBVCK3(self): + """Test the SBVCK3 instruction""" + + # Top instructions + check_instruction("SBVCK3 $0, $0, $4", "0045") + check_instruction("SBVCK3 $0, $5, $0", "0505") + check_instruction("SBVCK3 $0, $0, $0", "0005") + check_instruction("SBVCK3 $0, $0, $6", "0065") + check_instruction("SBVCK3 $0, $0, $12", "00c5") + + # Randomly choosen instructions + check_instruction("SBVCK3 $0, $0, $5", "0055") + check_instruction("SBVCK3 $0, $4, $8", "0485") + check_instruction("SBVCK3 $0, $4, $1", "0415") + check_instruction("SBVCK3 $0, $TP, $4", "0d45") + check_instruction("SBVCK3 $0, $1, $7", "0175") + + def test_RI(self): + """Test the (RI) instruction""" + + # No samples were found + assert(True) + + def test_ADVCK3(self): + """Test the ADVCK3 instruction""" + + # Top instructions + check_instruction("ADVCK3 $0, $0, $6", "0067") + check_instruction("ADVCK3 $0, $0, $4", "0047") + check_instruction("ADVCK3 $0, $8, $9", "0897") + check_instruction("ADVCK3 $0, $0, $0", "0007") + check_instruction("ADVCK3 $0, $0, $12", "00c7") + + # Randomly choosen instructions + check_instruction("ADVCK3 $0, $3, $9", "0397") + check_instruction("ADVCK3 $0, $10, $7", "0a77") + check_instruction("ADVCK3 $0, $1, $5", "0157") + check_instruction("ADVCK3 $0, $0, $9", "0097") + check_instruction("ADVCK3 $0, $0, $2", "0027") + + def test_SB(self): + """Test the SB instruction""" + + # Top instructions + check_instruction("SB $10, ($12)", "0ac8") + check_instruction("SB $8, ($0)", "0808") + check_instruction("SB $12, ($10)", "0ca8") + check_instruction("SB $12, ($4)", "0c48") + check_instruction("SB $12, ($11)", "0cb8") + + # Randomly choosen instructions + check_instruction("SB $4, ($4)", "0448") + check_instruction("SB $10, ($8)", "0a88") + check_instruction("SB $7, ($6)", "0768") + check_instruction("SB $8, ($11)", "08b8") + check_instruction("SB $2, ($GP)", "02e8") + + def test_SH(self): + """Test the SH instruction""" + + # Top instructions + check_instruction("SH $12, ($11)", "0cb9") + check_instruction("SH $12, ($0)", "0c09") + check_instruction("SH $12, ($4)", "0c49") + check_instruction("SH $0, ($2)", "0029") + check_instruction("SH $0, ($12)", "00c9") + + # Randomly choosen instructions + check_instruction("SH $GP, ($12)", "0ec9") + check_instruction("SH $6, ($10)", "06a9") + check_instruction("SH $10, ($11)", "0ab9") + check_instruction("SH $9, ($4)", "0949") + check_instruction("SH $1, ($5)", "0159") + + def test_SW(self): + """Test the SW instruction""" + + # Top instructions + check_instruction("SW $10, ($12)", "0aca") + check_instruction("SW $0, ($12)", "00ca") + check_instruction("SW $0, ($0)", "000a") + check_instruction("SW $12, ($SP)", "0cfa") + check_instruction("SW $0, ($SP)", "00fa") + + # Randomly choosen instructions + check_instruction("SW $0, ($7)", "007a") + check_instruction("SW $4, ($12)", "04ca") + check_instruction("SW $12, ($7)", "0c7a") + check_instruction("SW $9, ($12)", "09ca") + check_instruction("SW $TP, ($1)", "0d1a") + + def test_LBU(self): + """Test the LBU instruction""" + + # Top instructions + check_instruction("LBU $12, ($TP)", "0cdb") + check_instruction("LBU $12, ($10)", "0cab") + check_instruction("LBU $12, ($11)", "0cbb") + check_instruction("LBU $12, ($4)", "0c4b") + check_instruction("LBU $0, ($4)", "004b") + + # Randomly choosen instructions + check_instruction("LBU $6, ($TP)", "06db") + check_instruction("LBU $11, ($SP)", "0bfb") + check_instruction("LBU $10, ($10)", "0aab") + check_instruction("LBU $1, ($9)", "019b") + check_instruction("LBU $12, ($1)", "0c1b") + + def test_LB(self): + """Test the LB instruction""" + + # Top instructions + check_instruction("LB $11, ($TP)", "0bdc") + check_instruction("LB $11, ($12)", "0bcc") + check_instruction("LB $11, ($4)", "0b4c") + check_instruction("LB $10, ($4)", "0a4c") + check_instruction("LB $12, ($TP)", "0cdc") + + # Randomly choosen instructions + check_instruction("LB $0, ($12)", "00cc") + check_instruction("LB $2, ($7)", "027c") + check_instruction("LB $5, ($7)", "057c") + check_instruction("LB $10, ($1)", "0a1c") + check_instruction("LB $12, ($12)", "0ccc") + + def test_LH(self): + """Test the LH instruction""" + + # Top instructions + check_instruction("LH $0, ($4)", "004d") + check_instruction("LH $0, ($0)", "000d") + check_instruction("LH $12, ($4)", "0c4d") + check_instruction("LH $0, ($12)", "00cd") + check_instruction("LH $10, ($0)", "0a0d") + + # Randomly choosen instructions + check_instruction("LH $0, ($GP)", "00ed") + check_instruction("LH $12, ($5)", "0c5d") + check_instruction("LH $0, ($3)", "003d") + check_instruction("LH $10, ($SP)", "0afd") + check_instruction("LH $3, ($6)", "036d") + + def test_LW(self): + """Test the LW instruction""" + + # Top instructions + check_instruction("LW $0, ($SP)", "00fe") + check_instruction("LW $12, ($4)", "0c4e") + check_instruction("LW $12, ($SP)", "0cfe") + check_instruction("LW $0, ($12)", "00ce") + check_instruction("LW $1, ($SP)", "01fe") + + # Randomly choosen instructions + check_instruction("LW $1, ($0)", "010e") + check_instruction("LW $7, ($12)", "07ce") + check_instruction("LW $TP, ($2)", "0d2e") + check_instruction("LW $5, ($2)", "052e") + check_instruction("LW $10, ($2)", "0a2e") + + def test_LHU(self): + """Test the LHU instruction""" + + # Top instructions + check_instruction("LHU $12, ($1)", "0c1f") + check_instruction("LHU $11, ($4)", "0b4f") + check_instruction("LHU $11, ($3)", "0b3f") + check_instruction("LHU $12, ($8)", "0c8f") + check_instruction("LHU $12, ($4)", "0c4f") + + # Randomly choosen instructions + check_instruction("LHU $5, ($11)", "05bf") + check_instruction("LHU $12, ($3)", "0c3f") + check_instruction("LHU $9, ($8)", "098f") + check_instruction("LHU $10, ($3)", "0a3f") + check_instruction("LHU $5, ($8)", "058f") diff --git a/test/arch/mep/asm/test_major_opcode_1.py b/test/arch/mep/asm/test_major_opcode_1.py new file mode 100644 index 00000000..acdb9ca2 --- /dev/null +++ b/test/arch/mep/asm/test_major_opcode_1.py @@ -0,0 +1,294 @@ +# Toshiba MeP-c4 - Major Opcode #1 unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_asm import check_instruction + + +class TestMajor1: + + def test_OR(self): + """Test the OR instruction""" + + # Top instructions + check_instruction("OR $0, $4", "1040") + check_instruction("OR $12, $10", "1ca0") + check_instruction("OR $11, $12", "1bc0") + check_instruction("OR $0, $11", "10b0") + check_instruction("OR $0, $12", "10c0") + + # Randomly choosen instructions + check_instruction("OR $1, $12", "11c0") + check_instruction("OR $6, $11", "16b0") + check_instruction("OR $10, $9", "1a90") + check_instruction("OR $2, $10", "12a0") + check_instruction("OR $11, $4", "1b40") + + def test_AND(self): + """Test the AND instruction""" + + # Top instructions + check_instruction("AND $11, $12", "1bc1") + check_instruction("AND $12, $10", "1ca1") + check_instruction("AND $4, $12", "14c1") + check_instruction("AND $12, $11", "1cb1") + check_instruction("AND $0, $0", "1001") + + # Randomly choosen instructions + check_instruction("AND $6, $12", "16c1") + check_instruction("AND $8, $6", "1861") + check_instruction("AND $1, $12", "11c1") + check_instruction("AND $11, $2", "1b21") + check_instruction("AND $2, $4", "1241") + + def test_XOR(self): + """Test the XOR instruction""" + + # Top instructions + check_instruction("XOR $0, $2", "1022") + check_instruction("XOR $6, $10", "16a2") + check_instruction("XOR $2, $2", "1222") + check_instruction("XOR $4, $0", "1402") + check_instruction("XOR $11, $12", "1bc2") + + # Randomly choosen instructions + check_instruction("XOR $0, $12", "10c2") + check_instruction("XOR $12, $1", "1c12") + check_instruction("XOR $SP, $10", "1fa2") + check_instruction("XOR $3, $11", "13b2") + check_instruction("XOR $1, $8", "1182") + + def test_NOR(self): + """Test the NOR instruction""" + + # Top instructions + check_instruction("NOR $9, $2", "1923") + check_instruction("NOR $12, $12", "1cc3") + check_instruction("NOR $4, $4", "1443") + check_instruction("NOR $11, $0", "1b03") + check_instruction("NOR $0, $0", "1003") + + # Randomly choosen instructions + check_instruction("NOR $4, $1", "1413") + check_instruction("NOR $11, $11", "1bb3") + check_instruction("NOR $9, $9", "1993") + check_instruction("NOR $11, $2", "1b23") + check_instruction("NOR $0, $5", "1053") + + def test_MUL(self): + """Test the MUL instruction""" + + # Top instructions + check_instruction("MUL $9, $SP", "19f4") + check_instruction("MUL $0, $8", "1084") + check_instruction("MUL $8, $12", "18c4") + check_instruction("MUL $10, $9", "1a94") + check_instruction("MUL $10, $3", "1a34") + + # Randomly choosen instructions + check_instruction("MUL $2, $2", "1224") + check_instruction("MUL $4, $12", "14c4") + check_instruction("MUL $9, $3", "1934") + check_instruction("MUL $4, $11", "14b4") + check_instruction("MUL $6, $0", "1604") + + def test_MULU(self): + """Test the MULU instruction""" + + # Top instructions + check_instruction("MULU $4, $2", "1425") + check_instruction("MULU $8, $9", "1895") + check_instruction("MULU $7, $12", "17c5") + check_instruction("MULU $5, $12", "15c5") + check_instruction("MULU $1, $8", "1185") + + # Randomly choosen instructions + check_instruction("MULU $9, $6", "1965") + check_instruction("MULU $5, $1", "1515") + check_instruction("MULU $5, $11", "15b5") + check_instruction("MULU $1, $10", "11a5") + check_instruction("MULU $0, $4", "1045") + + def test_MULR(self): + """Test the MULR instruction""" + + # Top instructions + check_instruction("MULR $SP, $0", "1f06") + check_instruction("MULR $8, $3", "1836") + check_instruction("MULR $SP, $6", "1f66") + check_instruction("MULR $12, $1", "1c16") + check_instruction("MULR $6, $1", "1616") + + # Randomly choosen instructions + check_instruction("MULR $7, $1", "1716") + check_instruction("MULR $10, $8", "1a86") + check_instruction("MULR $4, $1", "1416") + check_instruction("MULR $12, $11", "1cb6") + check_instruction("MULR $12, $4", "1c46") + + def test_MULRU(self): + """Test the MULRU instruction""" + + # Top instructions + check_instruction("MULRU $12, $2", "1c27") + check_instruction("MULRU $0, $4", "1047") + check_instruction("MULRU $2, $1", "1217") + check_instruction("MULRU $7, $1", "1717") + check_instruction("MULRU $GP, $6", "1e67") + + # Randomly choosen instructions + check_instruction("MULRU $3, $12", "13c7") + check_instruction("MULRU $2, $TP", "12d7") + check_instruction("MULRU $3, $TP", "13d7") + check_instruction("MULRU $2, $12", "12c7") + check_instruction("MULRU $TP, $2", "1d27") + + def test_DIV(self): + """Test the DIV instruction""" + + # Top instructions + check_instruction("DIV $1, $12", "11c8") + check_instruction("DIV $8, $1", "1818") + check_instruction("DIV $GP, $0", "1e08") + check_instruction("DIV $9, $12", "19c8") + check_instruction("DIV $12, $11", "1cb8") + + # Randomly choosen instructions + check_instruction("DIV $6, $1", "1618") + check_instruction("DIV $5, $11", "15b8") + check_instruction("DIV $1, $9", "1198") + check_instruction("DIV $GP, $GP", "1ee8") + check_instruction("DIV $0, $1", "1018") + + def test_DIVU(self): + """Test the DIVU instruction""" + + # Top instructions + check_instruction("DIVU $1, $TP", "11d9") + check_instruction("DIVU $4, $12", "14c9") + check_instruction("DIVU $9, $1", "1919") + check_instruction("DIVU $0, $10", "10a9") + check_instruction("DIVU $11, $10", "1ba9") + + # Randomly choosen instructions + check_instruction("DIVU $3, $9", "1399") + check_instruction("DIVU $SP, $4", "1f49") + check_instruction("DIVU $12, $5", "1c59") + check_instruction("DIVU $8, $4", "1849") + check_instruction("DIVU $8, $11", "18b9") + + def test_RI(self): + """Test the (RI) instruction""" + + # No samples were found + assert(True) + + def test_SSARB(self): + """Test the SSARB instruction""" + + # Top instructions + check_instruction("SSARB 0($8)", "108c") + check_instruction("SSARB 3($GP)", "13ec") + check_instruction("SSARB 0($3)", "103c") + check_instruction("SSARB 0($TP)", "10dc") + check_instruction("SSARB 3($0)", "130c") + + def test_EXTB(self): + """Test the EXTB instruction""" + + # Top instructions + check_instruction("EXTB $8", "180d") + check_instruction("EXTB $0", "100d") + check_instruction("EXTB $4", "140d") + check_instruction("EXTB $11", "1b0d") + check_instruction("EXTB $12", "1c0d") + + # Randomly choosen instructions + check_instruction("EXTB $6", "160d") + check_instruction("EXTB $10", "1a0d") + check_instruction("EXTB $9", "190d") + check_instruction("EXTB $7", "170d") + check_instruction("EXTB $3", "130d") + + def test_EXTH(self): + """Test the EXTH instruction""" + + # Top instructions + check_instruction("EXTH $0", "102d") + check_instruction("EXTH $11", "1b2d") + check_instruction("EXTH $2", "122d") + check_instruction("EXTH $6", "162d") + check_instruction("EXTH $12", "1c2d") + + def test_EXTUB(self): + """Test the EXTUB instruction""" + + # Top instructions + check_instruction("EXTUB $2", "128d") + check_instruction("EXTUB $11", "1b8d") + check_instruction("EXTUB $12", "1c8d") + check_instruction("EXTUB $0", "108d") + check_instruction("EXTUB $4", "148d") + + # Randomly choosen instructions + check_instruction("EXTUB $7", "178d") + check_instruction("EXTUB $1", "118d") + check_instruction("EXTUB $6", "168d") + check_instruction("EXTUB $9", "198d") + check_instruction("EXTUB $10", "1a8d") + + def test_EXTUH(self): + """Test the EXTUH instruction""" + + # Top instructions + check_instruction("EXTUH $4", "14ad") + check_instruction("EXTUH $1", "11ad") + check_instruction("EXTUH $12", "1cad") + check_instruction("EXTUH $3", "13ad") + check_instruction("EXTUH $0", "10ad") + + # Randomly choosen instructions + check_instruction("EXTUH $7", "17ad") + check_instruction("EXTUH $5", "15ad") + check_instruction("EXTUH $2", "12ad") + check_instruction("EXTUH $GP", "1ead") + check_instruction("EXTUH $8", "18ad") + + def test_JMP(self): + """Test the JMP instruction""" + + # Top instructions + check_instruction("JMP $11", "10be") + check_instruction("JMP $2", "102e") + check_instruction("JMP $4", "104e") + check_instruction("JMP $12", "10ce") + check_instruction("JMP $1", "101e") + + # Randomly choosen instructions + check_instruction("JMP $7", "107e") + check_instruction("JMP $8", "108e") + check_instruction("JMP $10", "10ae") + check_instruction("JMP $9", "109e") + check_instruction("JMP $3", "103e") + + def test_JSR(self): + """Test the JSR instruction""" + + # Top instructions + check_instruction("JSR $11", "10bf") + check_instruction("JSR $0", "100f") + check_instruction("JSR $3", "103f") + check_instruction("JSR $12", "10cf") + check_instruction("JSR $4", "104f") + + # Randomly choosen instructions + check_instruction("JSR $9", "109f") + check_instruction("JSR $10", "10af") + check_instruction("JSR $6", "106f") + check_instruction("JSR $5", "105f") + check_instruction("JSR $7", "107f") + + def test_JSRV(self): + """Test the JSRV instruction""" + + # Top instructions + check_instruction("JSRV $GP", "18ef") diff --git a/test/arch/mep/asm/test_major_opcode_10.py b/test/arch/mep/asm/test_major_opcode_10.py new file mode 100644 index 00000000..6c8d0cf4 --- /dev/null +++ b/test/arch/mep/asm/test_major_opcode_10.py @@ -0,0 +1,41 @@ +# Toshiba MeP-c4 - Major Opcode #10 unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_asm import check_instruction + + +class TestMajor10: + + def test_BEQZ(self): + """Test the BEQZ instruction""" + + # Top instructions + check_instruction("BEQZ $11, 0xFFFFFF8C", "ab8c") + check_instruction("BEQZ $4, 0x6", "a406") + check_instruction("BEQZ $TP, 0x4", "ad04") + check_instruction("BEQZ $11, 0x4", "ab04") + check_instruction("BEQZ $12, 0xA", "ac0a") + + # Randomly choosen instructions + check_instruction("BEQZ $0, 0x42", "a042") + check_instruction("BEQZ $10, 0x6", "aa06") + check_instruction("BEQZ $0, 0x8", "a008") + check_instruction("BEQZ $12, 0x4", "ac04") + check_instruction("BEQZ $1, 0x70", "a170") + + def test_BNEZ(self): + """Test the BNEZ instruction""" + + # Top instructions + check_instruction("BNEZ $7, 0x46", "a747") + check_instruction("BNEZ $0, 0x40", "a041") + check_instruction("BNEZ $9, 0x1C", "a91d") + check_instruction("BNEZ $0, 0xFFFFFFF6", "a0f7") + check_instruction("BNEZ $4, 0xA", "a40b") + + # Randomly choosen instructions + check_instruction("BNEZ $7, 0xE", "a70f") + check_instruction("BNEZ $11, 0xE", "ab0f") + check_instruction("BNEZ $10, 0x28", "aa29") + check_instruction("BNEZ $9, 0xFFFFFFAE", "a9af") + check_instruction("BNEZ $9, 0xE", "a90f") diff --git a/test/arch/mep/asm/test_major_opcode_11.py b/test/arch/mep/asm/test_major_opcode_11.py new file mode 100644 index 00000000..7876a968 --- /dev/null +++ b/test/arch/mep/asm/test_major_opcode_11.py @@ -0,0 +1,44 @@ +# Toshiba MeP-c4 - Major Opcode #11 unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_asm import check_instruction + + +class TestMajor11: + + def test_BRA(self): + """Test the BRA instruction""" + + # Top instructions + check_instruction("BRA 0xFFFFF9B4", "b9b4") + check_instruction("BRA 0x34", "b034") + check_instruction("BRA 0x16", "b016") + check_instruction("BRA 0x46", "b046") + check_instruction("BRA 0xFFFFFF98", "bf98") + + # Randomly choosen instructions + check_instruction("BRA 0x2AA", "b2aa") + check_instruction("BRA 0x22", "b022") + check_instruction("BRA 0x12", "b012") + check_instruction("BRA 0x7FE", "b7fe") + check_instruction("BRA 0x34", "b034") + + def test_BSR(self): + """Test the BSR instruction""" + + # Top instructions + check_instruction("BSR 0xFFFFFF22", "bf23", multi=2) + check_instruction("BSR 0x716", "b717", multi=2) + check_instruction("BSR 0xFFFFFE36", "be37", multi=2) + check_instruction("BSR 0xFFFFFBB2", "bbb3", multi=2) + check_instruction("BSR 0xFFFFFCCE", "bccf", multi=2) + + # Randomly choosen instructions + check_instruction("BSR 0xFFFFFED4", "bed5", multi=2) + check_instruction("BSR 0xFFFFFF62", "bf63", multi=2) + check_instruction("BSR 0xFFFFFF36", "bf37", multi=2) + check_instruction("BSR 0xFFFFFBD0", "bbd1", multi=2) + check_instruction("BSR 0x5AA", "b5ab", multi=2) + + # Manually crafted + check_instruction("BSR 0xC67BFA", "bfa3", offset=0xc67c58) diff --git a/test/arch/mep/asm/test_major_opcode_12.py b/test/arch/mep/asm/test_major_opcode_12.py new file mode 100644 index 00000000..c9a0be79 --- /dev/null +++ b/test/arch/mep/asm/test_major_opcode_12.py @@ -0,0 +1,300 @@ +# Toshiba MeP-c4 - Major Opcode #12 unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_asm import check_instruction + + +class TestMajor12: + + def test_ADD3(self): + """Test the ADD3 instruction""" + + # Top instructions + check_instruction("ADD3 $SP, $SP, -64", "cff0ffc0") + check_instruction("ADD3 $SP, $SP, -44", "cff0ffd4") + check_instruction("ADD3 $SP, $SP, -36", "cff0ffdc") + check_instruction("ADD3 $12, $4, 0x48", "cc400048") + check_instruction("ADD3 $SP, $SP, -68", "cff0ffbc") + + # Randomly choosen instructions + check_instruction("ADD3 $12, $SP, 0x6", "ccf00006") + check_instruction("ADD3 $12, $12, 0x3E4", "ccc003e4") + check_instruction("ADD3 $7, $5, -31912", "c7508358") + check_instruction("ADD3 $1, $8, 0x54", "c1800054") + check_instruction("ADD3 $2, $8, 0x28", "c2800028") + + def test_MOV(self): + """Test the MOV instruction""" + + # Top instructions + check_instruction("MOV $11, 136", "cb010088", multi=2) + check_instruction("MOV $10, 170", "ca0100aa", multi=2) + check_instruction("MOV $2, 130", "c2010082", multi=2) + check_instruction("MOV $2, 139", "c201008b", multi=2) + check_instruction("MOV $0, 194", "c00100c2", multi=2) + + # Randomly choosen instructions + check_instruction("MOV $12, 239", "cc0100ef", multi=2) + check_instruction("MOV $1, 136", "c1010088", multi=2) + check_instruction("MOV $3, 168", "c30100a8", multi=2) + check_instruction("MOV $10, 133", "ca010085", multi=2) + check_instruction("MOV $11, 32640", "cb017f80", multi=2) + + def test_MOVU(self): + """Test the MOVU instruction""" + + # Top instructions + check_instruction("MOVU $2, 0x0", "c2110000", multi=2) + check_instruction("MOVU $2, 0x8002", "c2118002") + check_instruction("MOVU $10, 0x8106", "ca118106") + check_instruction("MOVU $11, 0x8105", "cb118105") + check_instruction("MOVU $11, 0x8106", "cb118106") + + # Randomly choosen instructions + check_instruction("MOVU $9, 0x8126", "c9118126") + check_instruction("MOVU $7, 0xFF00", "c711ff00") + check_instruction("MOVU $2, 0xE200", "c211e200") + check_instruction("MOVU $10, 0xE102", "ca11e102") + check_instruction("MOVU $11, 0xD6D8", "cb11d6d8") + + def test_MOVH(self): + """Test the MOVH instruction""" + + # Top instructions + check_instruction("MOVH $11, 0x8000", "cb218000") + check_instruction("MOVH $11, 0x1000", "cb211000") + check_instruction("MOVH $11, 0x100", "cb210100") + check_instruction("MOVH $1, 0x101", "c1210101") + check_instruction("MOVH $12, 0x81", "cc210081") + + # Randomly choosen instructions + check_instruction("MOVH $4, 0xF4D5", "c421f4d5") + check_instruction("MOVH $10, 0xFC00", "ca21fc00") + check_instruction("MOVH $12, 0xC003", "cc21c003") + check_instruction("MOVH $TP, 0x400", "cd210400") + check_instruction("MOVH $7, 0x8000", "c7218000") + + def test_SLT3(self): + """Test the SLT3 instruction""" + + # Top instructions + check_instruction("SLT3 $0, $2, 0x908", "c0220908") + check_instruction("SLT3 $0, $1, 0x90F", "c012090f") + check_instruction("SLT3 $0, $1, 0x1CE", "c01201ce") + check_instruction("SLT3 $0, $12, 0x801", "c0c20801") + check_instruction("SLT3 $0, $4, 0x800", "c0420800") + + # Randomly choosen instructions + check_instruction("SLT3 $2, $4, 0x6A18", "c2426a18") + check_instruction("SLT3 $2, $11, -31153", "c2b2864f") + check_instruction("SLT3 $11, $12, 0x5BFA", "cbc25bfa") + check_instruction("SLT3 $SP, $4, -30809", "cf4287a7") + check_instruction("SLT3 $0, $12, 0x21", "c0c20021") + + def test_SLTU3(self): + """Test the SLTU3 instruction""" + + # Top instructions + check_instruction("SLTU3 $11, $8, 0x8813", "cb838813") + check_instruction("SLTU3 $12, $11, 0x2711", "ccb32711") + check_instruction("SLTU3 $0, $11, 0x941", "c0b30941") + check_instruction("SLTU3 $0, $12, 0x941", "c0c30941") + check_instruction("SLTU3 $12, $8, 0x1001", "cc831001") + + # Randomly choosen instructions + check_instruction("SLTU3 $8, $12, 0x8BA9", "c8c38ba9") + check_instruction("SLTU3 $12, $11, 0x1E", "ccb3001e") + check_instruction("SLTU3 $6, $GP, 0x6C90", "c6e36c90") + check_instruction("SLTU3 $TP, $7, 0x86C3", "cd7386c3") + check_instruction("SLTU3 $12, $10, 0x1", "cca30001") + + def test_OR3(self): + """Test the OR3 instruction""" + + # Top instructions + check_instruction("OR3 $1, $1, 0x1", "c1140001") + check_instruction("OR3 $11, $11, 0x8", "cbb40008") + check_instruction("OR3 $4, $4, 0x20", "c4440020") + check_instruction("OR3 $12, $12, 0x1", "ccc40001") + check_instruction("OR3 $12, $12, 0x2", "ccc40002") + + # Randomly choosen instructions + check_instruction("OR3 $12, $GP, 0xC7", "cce400c7") + check_instruction("OR3 $10, $3, 0x40", "ca340040") + check_instruction("OR3 $3, $3, 0xFF97", "c334ff97") + check_instruction("OR3 $9, $TP, 0x7A0D", "c9d47a0d") + check_instruction("OR3 $1, $1, 0x1122", "c1141122") + + def test_AND3(self): + """Test the AND3 instruction""" + + # Top instructions + check_instruction("AND3 $10, $12, 0x1", "cac50001") + check_instruction("AND3 $11, $4, 0x8", "cb450008") + check_instruction("AND3 $12, $4, 0x1", "cc450001") + check_instruction("AND3 $11, $12, 0x8", "cbc50008") + check_instruction("AND3 $11, $12, 0x1", "cbc50001") + + # Randomly choosen instructions + check_instruction("AND3 $12, $7, 0x1FF", "cc7501ff") + check_instruction("AND3 $9, $10, 0x4E27", "c9a54e27") + check_instruction("AND3 $4, $4, 0xFB", "c44500fb") + check_instruction("AND3 $10, $7, 0x10", "ca750010") + check_instruction("AND3 $8, $9, 0xCE", "c89500ce") + + def test_XOR3(self): + """Test the XOR3 instruction""" + + # Top instructions + check_instruction("XOR3 $GP, $0, 0x9D72", "ce069d72") + check_instruction("XOR3 $10, $9, 0xDB3C", "ca96db3c") + check_instruction("XOR3 $7, $7, 0x6060", "c7766060") + check_instruction("XOR3 $12, $11, 0x4", "ccb60004") + check_instruction("XOR3 $4, $4, 0x1", "c4460001") + + # Randomly choosen instructions + check_instruction("XOR3 $TP, $9, 0x8704", "cd968704") + check_instruction("XOR3 $11, $SP, 0x7411", "cbf67411") + check_instruction("XOR3 $SP, $8, 0x8801", "cf868801") + check_instruction("XOR3 $12, $8, 0x8648", "cc868648") + check_instruction("XOR3 $5, $8, 0xC5", "c58600c5") + + def test_SB(self): + """Test the SB instruction""" + + # Top instructions + check_instruction("SB $12, 0x14($SP)", "ccf80014") + check_instruction("SB $4, 0x4($SP)", "c4f80004") + check_instruction("SB $4, 0x3($3)", "c4380003") + check_instruction("SB $11, 0x17($SP)", "cbf80017") + check_instruction("SB $12, 0x16($SP)", "ccf80016") + + # Randomly choosen instructions + check_instruction("SB $TP, -31053($6)", "cd6886b3") + check_instruction("SB $3, 0x6E($8)", "c388006e") + check_instruction("SB $7, 0x81($8)", "c7880081") + check_instruction("SB $11, 0x1FE($7)", "cb7801fe") + check_instruction("SB $11, 0x7B($4)", "cb48007b") + + def test_SH(self): + """Test the SH instruction""" + + # Top instructions + check_instruction("SH $11, 0x8($12)", "cbc90008") + check_instruction("SH $11, 0x2($4)", "cb490002") + check_instruction("SH $4, 0xE($SP)", "c4f9000e") + check_instruction("SH $4, 0xC($SP)", "c4f9000c") + check_instruction("SH $11, 0x1E($4)", "cb49001e") + + # Randomly choosen instructions + check_instruction("SH $SP, -30753($6)", "cf6987df") + check_instruction("SH $12, 0x6C4($TP)", "ccd906c4") + check_instruction("SH $4, 0x38($3)", "c4390038") + check_instruction("SH $TP, 0x8($2)", "cd290008") + check_instruction("SH $11, 0x62F5($10)", "cba962f5") + + # Manually generated instruction + check_instruction("SH $0, 0x7FFF($1)", "c0197fff") + check_instruction("SH $0, -32767($1)", "c0198001") + + def test_SW(self): + """Test the SW instruction""" + + # Top instructions + check_instruction("SW $12, 0x4($1)", "cc1a0004") + check_instruction("SW $9, 0x4($6)", "c96a0004") + check_instruction("SW $12, 0x10($4)", "cc4a0010") + check_instruction("SW $10, 0xC($12)", "caca000c") + check_instruction("SW $10, 0x4($12)", "caca0004") + + # Randomly choosen instructions + check_instruction("SW $12, 0x100($1)", "cc1a0100") + check_instruction("SW $10, 0x88($6)", "ca6a0088") + check_instruction("SW $0, 0x188($SP)", "c0fa0188") + check_instruction("SW $10, 0x22C($SP)", "cafa022c") + check_instruction("SW $4, 0x60A9($SP)", "c4fa60a9") + + def test_LBU(self): + """Test the LBU instruction""" + + # Top instructions + check_instruction("LBU $10, 0x3($12)", "cacb0003") + check_instruction("LBU $12, 0x2($0)", "cc0b0002") + check_instruction("LBU $4, 0x2($7)", "c47b0002") + check_instruction("LBU $12, 0x16($SP)", "ccfb0016") + check_instruction("LBU $11, 0x2($4)", "cb4b0002") + + # Randomly choosen instructions + check_instruction("LBU $12, 0x16($4)", "cc4b0016") + check_instruction("LBU $2, 0x3($11)", "c2bb0003") + check_instruction("LBU $7, 0x5($2)", "c72b0005") + check_instruction("LBU $12, 0x1E1($1)", "cc1b01e1") + check_instruction("LBU $10, -31425($6)", "ca6b853f") + + def test_LB(self): + """Test the LB instruction""" + + # Top instructions + check_instruction("LB $9, 0x26($1)", "c91c0026") + check_instruction("LB $4, 0x5($7)", "c47c0005") + check_instruction("LB $12, 0x14($SP)", "ccfc0014") + check_instruction("LB $9, 0x2($12)", "c9cc0002") + check_instruction("LB $12, 0x16($SP)", "ccfc0016") + + # Randomly choosen instructions + check_instruction("LB $0, 0x5784($10)", "c0ac5784") + check_instruction("LB $11, -31243($9)", "cb9c85f5") + check_instruction("LB $5, 0x11($6)", "c56c0011") + check_instruction("LB $4, 0x154($7)", "c47c0154") + check_instruction("LB $12, 0x18($SP)", "ccfc0018") + + def test_LH(self): + """Test the LH instruction""" + + # Top instructions + check_instruction("LH $4, 0x14($SP)", "c4fd0014") + check_instruction("LH $4, 0x6($8)", "c48d0006") + check_instruction("LH $4, 0x10($7)", "c47d0010") + check_instruction("LH $4, 0x4($8)", "c48d0004") + check_instruction("LH $9, 0x10($1)", "c91d0010") + + # Randomly choosen instructions + check_instruction("LH $4, 0x8($8)", "c48d0008") + check_instruction("LH $12, 0x8($10)", "ccad0008") + check_instruction("LH $6, -32042($6)", "c66d82d6") + check_instruction("LH $9, -31509($8)", "c98d84eb") + check_instruction("LH $0, 0x7E8D($6)", "c06d7e8d") + + def test_LW(self): + """Test the LW instruction""" + + # Top instructions + check_instruction("LW $4, 0x1C($8)", "c48e001c") + check_instruction("LW $12, 0x4($11)", "ccbe0004") + check_instruction("LW $7, 0x18($3)", "c73e0018") + check_instruction("LW $2, 0x8($8)", "c28e0008") + check_instruction("LW $4, 0x14($8)", "c48e0014") + + # Randomly choosen instructions + check_instruction("LW $12, 0x1D48($7)", "cc7e1d48") + check_instruction("LW $8, 0x58($1)", "c81e0058") + check_instruction("LW $12, 0xB0($7)", "cc7e00b0") + check_instruction("LW $SP, 0x6653($SP)", "cffe6653") + check_instruction("LW $12, -8($10)", "ccaefff8") + + def test_LHU(self): + """Test the LHU instruction""" + + # Top instructions + check_instruction("LHU $3, 0x10($8)", "c38f0010") + check_instruction("LHU $12, 0x10($1)", "cc1f0010") + check_instruction("LHU $4, 0x2($8)", "c48f0002") + check_instruction("LHU $4, 0x18($8)", "c48f0018") + check_instruction("LHU $2, 0x10($8)", "c28f0010") + + # Randomly choosen instructions + check_instruction("LHU $12, 0x94($8)", "cc8f0094") + check_instruction("LHU $4, 0xE($6)", "c46f000e") + check_instruction("LHU $11, 0x5B59($GP)", "cbef5b59") + check_instruction("LHU $1, 0x601D($10)", "c1af601d") + check_instruction("LHU $6, 0x74F6($11)", "c6bf74f6") diff --git a/test/arch/mep/asm/test_major_opcode_13.py b/test/arch/mep/asm/test_major_opcode_13.py new file mode 100644 index 00000000..b6e99dd5 --- /dev/null +++ b/test/arch/mep/asm/test_major_opcode_13.py @@ -0,0 +1,143 @@ +# Toshiba MeP-c4 - Major Opcode #13 unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_asm import check_instruction + + +class TestMajor13: + + def test_MOVU(self): + """Test the MOVU instruction""" + + # Top instructions + check_instruction("MOVU $0, 0xC901", "d00100c9", multi=2) + check_instruction("MOVU $4, 0xC7C708", "d408c7c7", multi=2) + check_instruction("MOVU $4, 0x202EFE", "d4fe202e", multi=2) + check_instruction("MOVU $4, 0x202EE0", "d4e0202e", multi=2) + check_instruction("MOVU $4, 0xC12A8E", "d48ec12a", multi=2) + + # Randomly choosen instructions + check_instruction("MOVU $4, 0x1D7100", "d4001d71", multi=2) + check_instruction("MOVU $4, 0x8A395B", "d45b8a39", multi=2) + check_instruction("MOVU $4, 0x67A3E6", "d4e667a3", multi=2) + check_instruction("MOVU $2, 0xCA2D02", "d202ca2d", multi=2) + check_instruction("MOVU $1, 0xCE820C", "d10cce82", multi=2) + + def test_BCPEQ(self): + """Test the BCPEQ instruction""" + + # Top instructions + check_instruction("BCPEQ 0xE, 0xA504", "d8e45282") + check_instruction("BCPEQ 0x4, 0xD5F4", "d8446afa") + check_instruction("BCPEQ 0xC, 0xAADA", "d8c4556d") + check_instruction("BCPEQ 0x7, 0xFFFF18F6", "d8748c7b") + + # Randomly choosen instructions + check_instruction("BCPEQ 0x6, 0xFFFF18CA", "d8648c65") + + def test_BCPNE(self): + """Test the BCPNE instruction""" + + # Top instructions + check_instruction("BCPNE 0xF, 0x9DEA", "d8f54ef5") + check_instruction("BCPNE 0x5, 0xFFFF18A4", "d8558c52") + check_instruction("BCPNE 0x7, 0xFFFF18FA", "d8758c7d") + check_instruction("BCPNE 0x1, 0x674E", "d81533a7") + + # Randomly choosen instructions + check_instruction("BCPNE 0xB, 0xD820", "d8b56c10") + check_instruction("BCPNE 0x8, 0xFFFF1922", "d8858c91") + check_instruction("BCPNE 0xD, 0xA6C8", "d8d55364") + check_instruction("BCPNE 0xA, 0xBDFE", "d8a55eff") + check_instruction("BCPNE 0x8, 0xFFFF1920", "d8858c90") + + def test_BCPAT(self): + """Test the BCPAT instruction""" + + # Top instructions + check_instruction("BCPAT 0xE, 0xA526", "d8e65293") + check_instruction("BCPAT 0xF, 0x9E4A", "d8f64f25") + check_instruction("BCPAT 0x8, 0xFFFF1922", "d8868c91") + check_instruction("BCPAT 0xC, 0x9D88", "d8c64ec4") + check_instruction("BCPAT 0x7, 0xFFFF18FA", "d8768c7d") + + # Randomly choosen instructions + check_instruction("BCPAT 0x6, 0xFFFF18D0", "d8668c68") + check_instruction("BCPAT 0x7, 0xFFFF18FC", "d8768c7e") + check_instruction("BCPAT 0x6, 0xFFFF18CE", "d8668c67") + check_instruction("BCPAT 0x5, 0xFFFF18A8", "d8568c54") + check_instruction("BCPAT 0xB, 0xADBE", "d8b656df") + + def test_BCPAF(self): + """Test the BCPAF instruction""" + + # Top instructions + check_instruction("BCPAF 0xE, 0xA304", "d8e75182") + check_instruction("BCPAF 0x5, 0xFFFF18AA", "d8578c55") + check_instruction("BCPAF 0xB, 0xFFFF01C8", "d8b780e4") + check_instruction("BCPAF 0xF, 0x9E4E", "d8f74f27") + check_instruction("BCPAF 0xD, 0xA412", "d8d75209") + + # Randomly choosen instructions + check_instruction("BCPAF 0xB, 0xFFFF01CA", "d8b780e5") + check_instruction("BCPAF 0xA, 0x9C2A", "d8a74e15") + check_instruction("BCPAF 0x8, 0xFFFF1924", "d8878c92") + check_instruction("BCPAF 0x6, 0xFFFF18D2", "d8678c69") + check_instruction("BCPAF 0xC, 0xA71A", "d8c7538d") + + def test_JMP(self): + """Test the JMP instruction""" + + # Top instructions + check_instruction("JMP 0xC9706A", "db58c970") + check_instruction("JMP 0xC7517A", "dbd8c751") + check_instruction("JMP 0x4", "d8280000") + check_instruction("JMP 0x80FF2C", "d96880ff") + check_instruction("JMP 0x814174", "dba88141") + + # Randomly choosen instructions + check_instruction("JMP 0xC3F782", "dc18c3f7") + check_instruction("JMP 0xC814", "d8a800c8") + check_instruction("JMP 0x9079EE", "df789079") + check_instruction("JMP 0xC6982A", "d958c698") + check_instruction("JMP 0xC3986C", "db68c398") + + # Manually crafted + check_instruction("JMP 0xC3F782", "dc18c3f7", offset=0x1024) + + def test_BSR(self): + """Test the BSR instruction""" + + # Top instructions + check_instruction("BSR 0xFFFEFB20", "d909fefb", multi=2) + check_instruction("BSR 0x603A92", "dc99603a", multi=2) + check_instruction("BSR 0xAF64", "db2900af", multi=2) + check_instruction("BSR 0x36C4", "de290036", multi=2) + check_instruction("BSR 0xFFFC6AC4", "de29fc6a", multi=2) + + # Randomly choosen instructions + check_instruction("BSR 0x22C", "d9690002", multi=2) + check_instruction("BSR 0x5FEE6A", "db595fee", multi=2) + check_instruction("BSR 0x4AFF4", "dfa904af", multi=2) + check_instruction("BSR 0x1B126", "d93901b1", multi=2) + check_instruction("BSR 0xFFFB3F76", "dbb9fb3f", multi=2) + + # Manually crafted + check_instruction("BSR 0xC7FB84", "d869017f", offset=0xc67c78) + + def test_BSRV(self): + """Test the BSRV instruction""" + + # Top instructions + check_instruction("BSRV 0x8E8488", "dc4b8e84") + check_instruction("BSRV 0x8E396E", "db7b8e39") + check_instruction("BSRV 0xF785CE", "de7bf785") + check_instruction("BSRV 0x6509F4", "dfab6509") + check_instruction("BSRV 0x8F50C8", "de4b8f50") + + # Randomly choosen instructions + check_instruction("BSRV 0x544BF6", "dfbb544b") + check_instruction("BSRV 0x8CCA2A", "d95b8cca") + check_instruction("BSRV 0x4F681E", "d8fb4f68") + check_instruction("BSRV 0x8EAA8C", "dc6b8eaa") + check_instruction("BSRV 0x30A030", "d98b30a0") diff --git a/test/arch/mep/asm/test_major_opcode_14.py b/test/arch/mep/asm/test_major_opcode_14.py new file mode 100644 index 00000000..1c2ac466 --- /dev/null +++ b/test/arch/mep/asm/test_major_opcode_14.py @@ -0,0 +1,179 @@ +# Toshiba MeP-c4 - Major Opcode #14 unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_asm import check_instruction + + +class TestMajor14: + + def test_BEQI(self): + """Test the BEQI instruction""" + + # Top instructions + check_instruction("BEQI $0, 0x5, 0x32", "e0500019") + check_instruction("BEQI $4, 0x3, 0x3C", "e430001e") + check_instruction("BEQI $4, 0x3, 0x20", "e4300010") + check_instruction("BEQI $0, 0xA, 0x8", "e0a00004") + check_instruction("BEQI $0, 0x0, 0xC4", "e0000062") + + # Randomly choosen instructions + check_instruction("BEQI $0, 0x1, 0xFFFFFF6A", "e010ffb5") + check_instruction("BEQI $1, 0x2, 0x20", "e1200010") + check_instruction("BEQI $9, 0x0, 0xE0", "e9000070") + check_instruction("BEQI $5, 0x8, 0xFFFF2696", "e580934b") + check_instruction("BEQI $4, 0xA, 0x0", "e4a00000") + + def test_BEQ(self): + """Test the BEQ instruction""" + + # Top instructions + check_instruction("BEQ $12, $9, 0x3A", "ec91001d") + check_instruction("BEQ $11, $10, 0x34", "eba1001a") + check_instruction("BEQ $11, $12, 0x1E", "ebc1000f") + check_instruction("BEQ $0, $0, 0x102", "e0010081") + check_instruction("BEQ $7, $11, 0x56", "e7b1002b") + + # Randomly choosen instructions + check_instruction("BEQ $11, $9, 0x26", "eb910013") + check_instruction("BEQ $12, $11, 0x28", "ecb10014") + check_instruction("BEQ $0, $0, 0xA12", "e0010509") + check_instruction("BEQ $12, $3, 0x24", "ec310012") + check_instruction("BEQ $10, $TP, 0xE", "ead10007") + + # Manually crafted + check_instruction("BEQ $0, $12, 0xC67CA4", "e0c10024", offset=0xc67c5c) + + def test_BNEI(self): + """Test the BNEI instruction""" + + # Top instructions + check_instruction("BNEI $0, 0x1, 0x16", "e014000b") + check_instruction("BNEI $11, 0x1, 0x1E", "eb14000f") + check_instruction("BNEI $0, 0x1, 0xFFFFFFB4", "e014ffda") + check_instruction("BNEI $4, 0x2, 0xDA", "e424006d") + check_instruction("BNEI $12, 0x1, 0x8", "ec140004") + + # Randomly choosen instructions + check_instruction("BNEI $12, 0x2, 0x6", "ec240003") + check_instruction("BNEI $3, 0xC, 0xFFFF2D68", "e3c496b4") + check_instruction("BNEI $4, 0x1, 0x10", "e4140008") + check_instruction("BNEI $4, 0x1, 0x2A", "e4140015") + check_instruction("BNEI $TP, 0xC, 0xF040", "edc47820") + + def test_BNE(self): + """Test the BNE instruction""" + + # Top instructions + check_instruction("BNE $TP, $7, 0xFFFFFFCC", "ed75ffe6") + check_instruction("BNE $12, $TP, 0x6", "ecd50003") + check_instruction("BNE $10, $11, 0x1C", "eab5000e") + check_instruction("BNE $3, $0, 0xFFFF35A8", "e3059ad4") + check_instruction("BNE $10, $3, 0xA", "ea350005") + + # Randomly choosen instructions + check_instruction("BNE $4, $12, 0x8", "e4c50004") + check_instruction("BNE $4, $1, 0x10", "e4150008") + check_instruction("BNE $4, $12, 0x34", "e4c5001a") + check_instruction("BNE $10, $11, 0x1C", "eab5000e") + check_instruction("BNE $2, $11, 0xFFFFFFD8", "e2b5ffec") + + def test_BGEI(self): + """Test the BGEI instruction""" + + # Top instructions + check_instruction("BGEI $4, 0x3, 0xE", "e4380007") + check_instruction("BGEI $11, 0x3, 0xFFFFFFF2", "eb38fff9") + check_instruction("BGEI $TP, 0x0, 0x12", "ed080009") + check_instruction("BGEI $12, 0x0, 0x22", "ec080011") + check_instruction("BGEI $GP, 0xE, 0xFFFF2996", "eee894cb") + + # Randomly choosen instructions + check_instruction("BGEI $4, 0x5, 0x52", "e4580029") + check_instruction("BGEI $1, 0x4, 0xA", "e1480005") + check_instruction("BGEI $8, 0x0, 0x10", "e8080008") + check_instruction("BGEI $11, 0x3, 0xFFFFFFF2", "eb38fff9") + + def test_REPEAT(self): + """Test the REPEAT instruction""" + + # Top instructions + check_instruction("REPEAT $2, 0x2A", "e2090015") + check_instruction("REPEAT $10, 0x16", "ea09000b") + check_instruction("REPEAT $12, 0x6", "ec090003") + check_instruction("REPEAT $11, 0x8", "eb090004") + check_instruction("REPEAT $11, 0x6", "eb090003") + + # Randomly choosen instructions + check_instruction("REPEAT $12, 0x24", "ec090012") + check_instruction("REPEAT $9, 0x8", "e9090004") + check_instruction("REPEAT $12, 0x14", "ec09000a") + check_instruction("REPEAT $10, 0x6", "ea090003") + check_instruction("REPEAT $10, 0x8", "ea090004") + + def test_EREPEAT(self): + """Test the EREPEAT instruction""" + + # Top instructions + check_instruction("EREPEAT 0xA", "e0190005") + check_instruction("EREPEAT 0x24", "e0190012") + check_instruction("EREPEAT 0x18", "e019000c") + check_instruction("EREPEAT 0x12", "e0190009") + check_instruction("EREPEAT 0x1C", "e019000e") + + # Randomly choosen instructions + check_instruction("EREPEAT 0x12", "e0190009") + check_instruction("EREPEAT 0x7E", "e019003f") + check_instruction("EREPEAT 0x8", "e0190004") + check_instruction("EREPEAT 0x1A", "e019000d") + check_instruction("EREPEAT 0xC", "e0190006") + + def test_BLTI(self): + """Test the BLTI instruction""" + + # Top instructions + check_instruction("BLTI $12, 0x1, 0x26", "ec1c0013") + check_instruction("BLTI $2, 0x2, 0xC", "e22c0006") + check_instruction("BLTI $8, 0x0, 0x10", "e80c0008") + check_instruction("BLTI $7, 0x1, 0x1A", "e71c000d") + check_instruction("BLTI $12, 0x9, 0xEA52", "ec9c7529") + + # Randomly choosen instructions + check_instruction("BLTI $4, 0x6, 0xFFFF25AE", "e46c92d7") + check_instruction("BLTI $12, 0x1, 0x24", "ec1c0012") + check_instruction("BLTI $9, 0xF, 0xFFFF1F0A", "e9fc8f85") + check_instruction("BLTI $2, 0x2, 0x2A", "e22c0015") + check_instruction("BLTI $12, 0x8, 0xFFFFFFCE", "ec8cffe7") + + def test_SW(self): + """Test the SW instruction""" + + # Top instructions + check_instruction("SW $4, (0x825BE0)", "e4e2825b") + check_instruction("SW $4, (0x816834)", "e4368168") + check_instruction("SW $4, (0x817318)", "e41a8173") + check_instruction("SW $4, (0x826864)", "e4668268") + check_instruction("SW $4, (0x826994)", "e4968269") + + # Randomly choosen instructions + check_instruction("SW $1, (0x815864)", "e1668158") + check_instruction("SW $1, (0x825BD8)", "e1da825b") + check_instruction("SW $10, (0x6225AC)", "eaae6225") + check_instruction("SW $GP, (0x9497CC)", "eece9497") + check_instruction("SW $3, (0x6CEEF8)", "e3fa6cee") + + def test_LW(self): + """Test the LW instruction""" + + # Top instructions + check_instruction("LW $0, (0x8200)", "e0030082") + check_instruction("LW $4, (0x816820)", "e4238168") + check_instruction("LW $0, (0x8500)", "e0030085") + check_instruction("LW $3, (0x816820)", "e3238168") + check_instruction("LW $4, (0x81F0F0)", "e4f381f0") + + # Randomly choosen instructions + check_instruction("LW $GP, (0x94CEE8)", "eeeb94ce") + check_instruction("LW $4, (0x823608)", "e40b8236") + check_instruction("LW $0, (0x815E40)", "e043815e") + check_instruction("LW $0, (0x814D50)", "e053814d") + check_instruction("LW $0, (0x8269C4)", "e0c78269") diff --git a/test/arch/mep/asm/test_major_opcode_15.py b/test/arch/mep/asm/test_major_opcode_15.py new file mode 100644 index 00000000..8eeb2eff --- /dev/null +++ b/test/arch/mep/asm/test_major_opcode_15.py @@ -0,0 +1,583 @@ +# Toshiba MeP-c4 - Major Opcode #15 unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_asm import check_instruction + + +class TestMajor15: + + def test_DSP(self): + """Test the DSP instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("DSP $1, $2, 0x3", "f1200003") + + def test_DSP0(self): + """Test the DSP0 instruction""" + + # No samples were found + assert(True) + + def test_DSP1(self): + """Test the DSP1 instruction""" + + # No samples were found + assert(True) + + def test_LDZ(self): + """Test the LDZ instruction""" + + # Top instructions + check_instruction("LDZ $10, $9", "fa910000") + check_instruction("LDZ $SP, $12", "ffc10000") + + def test_AVE(self): + """Test the AVE instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("AVE $1, $2", "f1210002") + + def test_ABS(self): + """Test the ABS instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("ABS $1, $2", "f1210003") + + def test_MIN(self): + """Test the MIN instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("MIN $1, $2", "f1210004") + + def test_MAX(self): + """Test the MAX instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("MAX $1, $2", "f1210005") + + def test_MINU(self): + """Test the MINU instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("MINU $1, $2", "f1210006") + + def test_MAXU(self): + """Test the MAXU instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("MAXU $1, $2", "f1210007") + + def test_SADD(self): + """Test the SADD instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("SADD $1, $2", "f1210008") + + def test_SADDU(self): + """Test the SADDU instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("SADDU $1, $2", "f1210009") + + def test_SSUB(self): + """Test the SSUB instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("SSUB $1, $2", "f121000a") + + def test_SSUBU(self): + """Test the SSUBU instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("SSUBU $1, $2", "f121000b") + + def test_CLIP(self): + """Test the CLIP instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("CLIP $1, 0x2", "f1011010") + + def test_CLIPU(self): + """Test the CLIPU instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("CLIPU $1, 0x2", "f1011011") + + def test_MADD(self): + """Test the MADD instruction""" + + # Top instructions + check_instruction("MADD $3, $12", "f3c13004") + check_instruction("MADD $11, $1", "fb113004") + check_instruction("MADD $9, $1", "f9113004") + check_instruction("MADD $10, $4", "fa413004") + check_instruction("MADD $4, $11", "f4b13004") + + # Randomly choosen instructions + check_instruction("MADD $7, $10", "f7a13004") + check_instruction("MADD $0, $10", "f0a13004") + check_instruction("MADD $12, $9", "fc913004") + check_instruction("MADD $5, $TP", "f5d13004") + check_instruction("MADD $10, $12", "fac13004") + + def test_MADDU(self): + """Test the MADDU instruction""" + + # Top instructions + check_instruction("MADDU $12, $11", "fcb13005") + check_instruction("MADDU $6, $12", "f6c13005") + check_instruction("MADDU $6, $11", "f6b13005") + check_instruction("MADDU $6, $9", "f6913005") + check_instruction("MADDU $6, $10", "f6a13005") + + # Randomly choosen instructions + check_instruction("MADDU $10, $12", "fac13005") + check_instruction("MADDU $10, $2", "fa213005") + check_instruction("MADDU $1, $12", "f1c13005") + check_instruction("MADDU $11, $10", "fba13005") + check_instruction("MADDU $8, $12", "f8c13005") + + def test_MADDR(self): + """Test the MADDR instruction""" + + # Top instructions + check_instruction("MADDR $12, $3", "fc313006") + check_instruction("MADDR $10, $2", "fa213006") + check_instruction("MADDR $6, $12", "f6c13006") + check_instruction("MADDR $11, $10", "fba13006") + + def test_MADDRU(self): + """Test the MADDRU instruction""" + + # Top instructions + check_instruction("MADDRU $11, $2", "fb213007") + check_instruction("MADDRU $10, $9", "fa913007") + check_instruction("MADDRU $12, $10", "fca13007") + check_instruction("MADDRU $11, $1", "fb113007") + check_instruction("MADDRU $12, $1", "fc113007") + + # Randomly choosen instructions + check_instruction("MADDRU $1, $0", "f1013007") + check_instruction("MADDRU $10, $3", "fa313007") + check_instruction("MADDRU $12, $11", "fcb13007") + check_instruction("MADDRU $12, $9", "fc913007") + check_instruction("MADDRU $3, $1", "f3113007") + + def test_UCI(self): + """Test the UCI instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("UCI $1, $2, 0x3", "f1220003") + + def test_STCB(self): + """Test the STCB instruction""" + + # Top instructions + check_instruction("STCB $11, 0x1000", "fb041000") + check_instruction("STCB $3, 0x1005", "f3041005") + check_instruction("STCB $1, 0x1004", "f1041004") + check_instruction("STCB $11, 0x0", "fb040000") + check_instruction("STCB $12, 0x4100", "fc044100") + + # Randomly choosen instructions + check_instruction("STCB $2, 0x4007", "f2044007") + check_instruction("STCB $10, 0x4002", "fa044002") + check_instruction("STCB $11, 0x2", "fb040002") + check_instruction("STCB $10, 0x420", "fa040420") + check_instruction("STCB $4, 0x405", "f4040405") + + def test_LDCB(self): + """Test the LDCB instruction""" + + # Top instructions + check_instruction("LDCB $12, 0x3", "fc140003") + check_instruction("LDCB $12, 0x1001", "fc141001") + check_instruction("LDCB $11, 0x1000", "fb141000") + check_instruction("LDCB $12, 0x1000", "fc141000") + check_instruction("LDCB $12, 0x0", "fc140000") + + # Randomly choosen instructions + check_instruction("LDCB $12, 0x420", "fc140420") + check_instruction("LDCB $10, 0x1", "fa140001") + check_instruction("LDCB $11, 0x5", "fb140005") + check_instruction("LDCB $2, 0x4002", "f2144002") + check_instruction("LDCB $1, 0x4005", "f1144005") + + def test_SBCPA(self): + """Test the SBCPA instruction""" + + # Top instructions + check_instruction("SBCPA $C5, ($GP+), -50", "f5e500ce") + check_instruction("SBCPA $C5, ($GP+), -55", "f5e500c9") + check_instruction("SBCPA $C6, ($9+), -50", "f69500ce") + check_instruction("SBCPA $C4, ($TP+), -52", "f4d500cc") + check_instruction("SBCPA $C6, ($4+), -55", "f64500c9") + + # Randomly choosen instructions + check_instruction("SBCPA $C2, ($SP+), -51", "f2f500cd") + check_instruction("SBCPA $C13, ($8+), -52", "fd8500cc") + check_instruction("SBCPA $C2, ($TP+), -51", "f2d500cd") + check_instruction("SBCPA $C6, ($6+), -55", "f66500c9") + check_instruction("SBCPA $C2, ($10+), -51", "f2a500cd") + + def test_SHCPA(self): + """Test the SHCPA instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("SHCPA $C1, ($2+), 6", "f1251006") + + def test_SWCPA(self): + """Test the SWCPA instruction""" + + # Top instructions + check_instruction("SWCPA $C10, ($5+), 48", "fa552030") + + # Manually generated instruction + check_instruction("SWCPA $C1, ($2+), 4", "f1252004") + + def test_SMCPA(self): + """Test the SMCPA instruction""" + + # Top instructions + check_instruction("SMCPA $C15, ($0+), -16", "ff0530f0") + check_instruction("SMCPA $C15, ($0+), 32", "ff053020") + + # Manually generated instruction + check_instruction("SMCPA $C1, ($2+), 8", "f1253008") + + def test_LBCPA(self): + """Test the LBCPA instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("LBCPA $C1, ($2+), 8", "f1254008") + + def test_LHCPA(self): + """Test the LHCPA instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("LHCPA $C1, ($2+), 8", "f1255008") + + def test_LWCPA(self): + """Test the LWCPA instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("LWCPA $C1, ($2+), 8", "f1256008") + + def test_LMCPA(self): + """Test the LMCPA instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("LMCPA $C1, ($2+), 8", "f1257008") + + def test_SBCPM0(self): + """Test the SBCPM0 instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("SBCPM0 $C1, ($2+), 8", "f1250808") + + def test_SHCPM0(self): + """Test the SHCPM0 instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("SHCPM0 $C1, ($2+), 8", "f1251808") + + def test_SWCPM0(self): + """Test the SWCPM0 instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("SWCPM0 $C1, ($2+), 8", "f1252808") + + def test_SMCPM0(self): + """Test the SMCPM0 instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("SMCPM0 $C1, ($2+), 8", "f1253808") + + def test_LBCPM0(self): + """Test the LBCPM0 instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("LBCPM0 $C1, ($2+), 8", "f1254808") + + def test_LHCPM0(self): + """Test the LHCPM0 instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("LHCPM0 $C1, ($2+), 8", "f1255808") + + def test_LWCPM0(self): + """Test the LWCPM0 instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("LWCPM0 $C1, ($2+), 8", "f1256808") + + def test_LMCPM0(self): + """Test the LMCPM0 instruction""" + + # Top instructions + check_instruction("LMCPM0 $C3, ($12+), 8", "f3c57808") + check_instruction("LMCPM0 $C1, ($11+), -32", "f1b578e0") + check_instruction("LMCPM0 $C3, ($TP+), 48", "f3d57830") + check_instruction("LMCPM0 $C3, ($GP+), -96", "f3e578a0") + check_instruction("LMCPM0 $C3, ($SP+), -40", "f3f578d8") + + def test_SBCPM1(self): + """Test the SBCPM1 instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("SBCPM1 $C1, ($2+), 8", "f1250c08") + + def test_SHCPM1(self): + """Test the SHCPM1 instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("SHCPM1 $C1, ($2+), 8", "f1251c08") + + def test_SWCPM1(self): + """Test the SWCPM1 instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("SWCPM1 $C1, ($2+), 8", "f1252c08") + + def test_SMCPM1(self): + """Test the SMCPM1 instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("SMCPM1 $C1, ($2+), 8", "f1253c08") + + def test_LBCPM1(self): + """Test the LBCPM1 instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("LBCPM1 $C1, ($2+), 8", "f1254c08") + + def test_LHCPM1(self): + """Test the LHCPM1 instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("LHCPM1 $C1, ($2+), 8", "f1255c08") + + def test_LWCPM1(self): + """Test the LWCPM1 instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("LWCPM1 $C1, ($2+), 8", "f1256c08") + + def test_LMCPM1(self): + """Test the LMCPM1 instruction""" + + # Top instructions + check_instruction("LMCPM1 $C9, ($4+), 48", "f9457c30") + check_instruction("LMCPM1 $C4, ($10+), 64", "f4a57c40") + check_instruction("LMCPM1 $C4, ($TP+), -72", "f4d57cb8") + check_instruction("LMCPM1 $C4, ($GP+), -32", "f4e57ce0") + + def test_CP(self): + """Test the CP instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + #check_instruction("CP 0x280780", "f2870780") + + def test_CMOV(self): + """Test the CMOV instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("CMOV $C0, $1", "f017f000") + check_instruction("CMOV $1, $C0", "f017f001") + check_instruction("CMOV $C28, $1", "fc17f008") + check_instruction("CMOV $1, $C28", "fc17f009") + + def test_CMOVC(self): + """Test the CMOVC instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("CMOVC $C0, $1", "f017f002") + check_instruction("CMOVC $2, $C3", "f327f003") + + def test_CMOVH(self): + """Test the CMOVH instruction""" + + # No samples were found + assert(True) + + # Manually generated instruction + check_instruction("CMOVH $C0, $1", "f017f100") + check_instruction("CMOVH $2, $C3", "f327f101") + check_instruction("CMOVH $C29, $12", "fdc7f108") + check_instruction("CMOVH $SP, $C30", "fef7f109") + + def test_SWCP(self): + """Test the SWCP instruction""" + + # Top instructions + check_instruction("SWCP $C7, 197($12)", "f7cc00c5") + check_instruction("SWCP $C1, 194($7)", "f17c00c2") + check_instruction("SWCP $C14, -16690($10)", "feacbece") + check_instruction("SWCP $C2, 24658($5)", "f25c6052") + check_instruction("SWCP $C0, 27132($9)", "f09c69fc") + + # Randomly choosen instructions + check_instruction("SWCP $C9, 195($10)", "f9ac00c3") + check_instruction("SWCP $C5, -25704($5)", "f55c9b98") + check_instruction("SWCP $C2, -31068($11)", "f2bc86a4") + check_instruction("SWCP $C6, -27760($12)", "f6cc9390") + check_instruction("SWCP $C4, -28337($SP)", "f4fc914f") + + def test_LWCP(self): + """Test the LWCP instruction""" + + # Top instructions + check_instruction("LWCP $C9, 9890($1)", "f91d26a2") + check_instruction("LWCP $C1, 10757($6)", "f16d2a05") + check_instruction("LWCP $C4, -14058($8)", "f48dc916") + check_instruction("LWCP $C15, -26720($8)", "ff8d97a0") + check_instruction("LWCP $C15, 26934($4)", "ff4d6936") + + # Randomly choosen instructions + check_instruction("LWCP $C11, -25049($5)", "fb5d9e27") + check_instruction("LWCP $C6, -25560($8)", "f68d9c28") + check_instruction("LWCP $C7, -24867($GP)", "f7ed9edd") + check_instruction("LWCP $C0, 30229($SP)", "f0fd7615") + check_instruction("LWCP $C7, -25527($4)", "f74d9c49") + + def test_SMCP(self): + """Test the SMCP instruction""" + + # Top instructions + check_instruction("SMCP $C15, 2047($SP)", "fffe07ff") + check_instruction("SMCP $C15, -1($SP)", "fffeffff") + check_instruction("SMCP $C4, 17362($9)", "f49e43d2") + check_instruction("SMCP $C3, 6490($4)", "f34e195a") + check_instruction("SMCP $C2, -11232($10)", "f2aed420") + + # Randomly choosen instructions + check_instruction("SMCP $C6, 201($7)", "f67e00c9") + check_instruction("SMCP $C3, -25912($6)", "f36e9ac8") + check_instruction("SMCP $C9, -25215($7)", "f97e9d81") + check_instruction("SMCP $C0, -26294($7)", "f07e994a") + check_instruction("SMCP $C3, 32566($11)", "f3be7f36") + + def test_LMCP(self): + """Test the LMCP instruction""" + + # Top instructions + check_instruction("LMCP $C9, 6994($11)", "f9bf1b52") + check_instruction("LMCP $C12, -8368($3)", "fc3fdf50") + check_instruction("LMCP $C4, -13277($GP)", "f4efcc23") + check_instruction("LMCP $C15, 4095($SP)", "ffff0fff") + check_instruction("LMCP $C15, -1($SP)", "ffffffff") + + # Randomly choosen instructions + check_instruction("LMCP $C7, -24863($GP)", "f7ef9ee1") + check_instruction("LMCP $C14, 16674($SP)", "feff4122") + check_instruction("LMCP $C13, 1023($SP)", "fdff03ff") + check_instruction("LMCP $C1, -32729($GP)", "f1ef8027") + check_instruction("LMCP $C15, 30719($SP)", "ffff77ff") diff --git a/test/arch/mep/asm/test_major_opcode_2.py b/test/arch/mep/asm/test_major_opcode_2.py new file mode 100644 index 00000000..913d8756 --- /dev/null +++ b/test/arch/mep/asm/test_major_opcode_2.py @@ -0,0 +1,194 @@ +# Toshiba MeP-c4 - Major Opcode #2 unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_asm import check_instruction + + +class TestMajor2: + + def test_BSETM(self): + """Test the BSETM instruction""" + + # Top instructions + check_instruction("BSETM ($0), 0x0", "2000") + check_instruction("BSETM ($0), 0x5", "2500") + check_instruction("BSETM ($3), 0x0", "2030") + check_instruction("BSETM ($2), 0x5", "2520") + check_instruction("BSETM ($2), 0x0", "2020") + + # Randomly choosen instructions + check_instruction("BSETM ($8), 0x4", "2480") + check_instruction("BSETM ($5), 0x5", "2550") + check_instruction("BSETM ($5), 0x0", "2050") + check_instruction("BSETM ($0), 0x7", "2700") + check_instruction("BSETM ($TP), 0x0", "20d0") + + def test_BCLRM(self): + """Test the BCLRM instruction""" + + # Top instructions + check_instruction("BCLRM ($3), 0x0", "2031") + check_instruction("BCLRM ($2), 0x0", "2021") + check_instruction("BCLRM ($1), 0x2", "2211") + check_instruction("BCLRM ($2), 0x1", "2121") + check_instruction("BCLRM ($0), 0x0", "2001") + + # Randomly choosen instructions + check_instruction("BCLRM ($6), 0x4", "2461") + check_instruction("BCLRM ($7), 0x4", "2471") + check_instruction("BCLRM ($6), 0x5", "2561") + check_instruction("BCLRM ($0), 0x2", "2201") + check_instruction("BCLRM ($0), 0x1", "2101") + + def test_BNOTM(self): + """Test the BNOTM instruction""" + + # Top instructions + check_instruction("BNOTM ($7), 0x1", "2172") + check_instruction("BNOTM ($2), 0x1", "2122") + check_instruction("BNOTM ($SP), 0x0", "20f2") + check_instruction("BNOTM ($3), 0x0", "2032") + check_instruction("BNOTM ($7), 0x0", "2072") + + # Randomly choosen instructions + check_instruction("BNOTM ($6), 0x4", "2462") + check_instruction("BNOTM ($2), 0x2", "2222") + check_instruction("BNOTM ($0), 0x1", "2102") + check_instruction("BNOTM ($2), 0x0", "2022") + check_instruction("BNOTM ($1), 0x2", "2212") + + def test_BTSTM(self): + """Test the BTSTM instruction""" + + # Top instructions + check_instruction("BTSTM $0, ($12), 0x3", "23c3") + check_instruction("BTSTM $0, ($6), 0x0", "2063") + check_instruction("BTSTM $0, ($3), 0x0", "2033") + check_instruction("BTSTM $0, ($0), 0x0", "2003") + check_instruction("BTSTM $0, ($7), 0x0", "2073") + + # Randomly choosen instructions + check_instruction("BTSTM $0, ($2), 0x4", "2423") + check_instruction("BTSTM $0, ($12), 0x6", "26c3") + check_instruction("BTSTM $0, ($4), 0x5", "2543") + check_instruction("BTSTM $0, ($9), 0x1", "2193") + check_instruction("BTSTM $0, ($0), 0x4", "2403") + + def test_TAS(self): + """Test the TAS instruction""" + + # Top instructions + check_instruction("TAS $GP, ($6)", "2e64") + check_instruction("TAS $12, ($TP)", "2cd4") + check_instruction("TAS $9, ($6)", "2964") + check_instruction("TAS $0, ($7)", "2074") + check_instruction("TAS $0, ($6)", "2064") + + # Randomly choosen instructions + check_instruction("TAS $1, ($6)", "2164") + check_instruction("TAS $11, ($3)", "2b34") + check_instruction("TAS $1, ($0)", "2104") + check_instruction("TAS $8, ($7)", "2874") + check_instruction("TAS $8, ($4)", "2844") + + def test_SL1AD3(self): + """Test the SL1AD3 instruction""" + + # Top instructions + check_instruction("SL1AD3 $0, $1, $4", "2146") + check_instruction("SL1AD3 $0, $11, $11", "2bb6") + check_instruction("SL1AD3 $0, $4, $4", "2446") + check_instruction("SL1AD3 $0, $3, $3", "2336") + check_instruction("SL1AD3 $0, $12, $12", "2cc6") + + # Randomly choosen instructions + check_instruction("SL1AD3 $0, $5, $4", "2546") + check_instruction("SL1AD3 $0, $11, $4", "2b46") + check_instruction("SL1AD3 $0, $GP, $3", "2e36") + check_instruction("SL1AD3 $0, $6, $3", "2636") + check_instruction("SL1AD3 $0, $3, $4", "2346") + + def test_SL2AD3(self): + """Test the SL2AD3 instruction""" + + # Top instructions + check_instruction("SL2AD3 $0, $0, $4", "2047") + check_instruction("SL2AD3 $0, $12, $7", "2c77") + check_instruction("SL2AD3 $0, $7, $4", "2747") + check_instruction("SL2AD3 $0, $12, $0", "2c07") + check_instruction("SL2AD3 $0, $11, $4", "2b47") + + # Randomly choosen instructions + check_instruction("SL2AD3 $0, $10, $SP", "2af7") + check_instruction("SL2AD3 $0, $4, $8", "2487") + check_instruction("SL2AD3 $0, $10, $12", "2ac7") + check_instruction("SL2AD3 $0, $9, $TP", "29d7") + check_instruction("SL2AD3 $0, $5, $10", "25a7") + + def test_SRL(self): + """Test the SRL instruction""" + + # Top instructions + check_instruction("SRL $0, $4", "204c") + check_instruction("SRL $3, $7", "237c") + check_instruction("SRL $0, $2", "202c") + check_instruction("SRL $0, $6", "206c") + check_instruction("SRL $SP, $3", "2f3c") + + # Randomly choosen instructions + check_instruction("SRL $9, $6", "296c") + check_instruction("SRL $2, $7", "227c") + check_instruction("SRL $9, $12", "29cc") + check_instruction("SRL $12, $9", "2c9c") + check_instruction("SRL $12, $2", "2c2c") + + def test_SRA(self): + """Test the SRA instruction""" + + # Top instructions + check_instruction("SRA $0, $6", "206d") + check_instruction("SRA $TP, $1", "2d1d") + check_instruction("SRA $5, $3", "253d") + check_instruction("SRA $0, $3", "203d") + check_instruction("SRA $0, $5", "205d") + + # Randomly choosen instructions + check_instruction("SRA $11, $2", "2b2d") + check_instruction("SRA $9, $6", "296d") + check_instruction("SRA $4, $8", "248d") + check_instruction("SRA $8, $3", "283d") + check_instruction("SRA $3, $0", "230d") + + def test_SLL(self): + """Test the SLL instruction""" + + # Top instructions + check_instruction("SLL $10, $1", "2a1e") + check_instruction("SLL $12, $9", "2c9e") + check_instruction("SLL $0, $3", "203e") + check_instruction("SLL $5, $2", "252e") + check_instruction("SLL $0, $6", "206e") + + # Randomly choosen instructions + check_instruction("SLL $4, $0", "240e") + check_instruction("SLL $SP, $10", "2fae") + check_instruction("SLL $0, $4", "204e") + check_instruction("SLL $7, $2", "272e") + check_instruction("SLL $3, $2", "232e") + + def test_FSFT(self): + """Test the FSFT instruction""" + + # Top instructions + check_instruction("FSFT $0, $2", "202f") + check_instruction("FSFT $0, $1", "201f") + check_instruction("FSFT $9, $SP", "29ff") + check_instruction("FSFT $SP, $2", "2f2f") + check_instruction("FSFT $0, $6", "206f") + + # Randomly choosen instructions + check_instruction("FSFT $SP, $6", "2f6f") + check_instruction("FSFT $0, $9", "209f") + check_instruction("FSFT $5, $9", "259f") + check_instruction("FSFT $0, $TP", "20df") + check_instruction("FSFT $0, $GP", "20ef") diff --git a/test/arch/mep/asm/test_major_opcode_3.py b/test/arch/mep/asm/test_major_opcode_3.py new file mode 100644 index 00000000..6802e752 --- /dev/null +++ b/test/arch/mep/asm/test_major_opcode_3.py @@ -0,0 +1,143 @@ +# Toshiba MeP-c4 - Major Opcode #3 unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_asm import check_instruction + + +class TestMajor3: + + def test_SWCPI(self): + """Test the SWCPI instruction""" + + # Top instructions + check_instruction("SWCPI $C0, ($2+)", "3020") + check_instruction("SWCPI $C3, ($2+)", "3320") + check_instruction("SWCPI $C3, ($3+)", "3330") + check_instruction("SWCPI $C2, ($3+)", "3230") + check_instruction("SWCPI $C0, ($3+)", "3030") + + # Randomly choosen instructions + check_instruction("SWCPI $C2, ($2+)", "3220") + check_instruction("SWCPI $C6, ($10+)", "36a0") + check_instruction("SWCPI $C15, ($SP+)", "3ff0") + check_instruction("SWCPI $C15, ($9+)", "3f90") + check_instruction("SWCPI $C10, ($3+)", "3a30") + + def test_LWCPI(self): + """Test the LWCPI instruction""" + + # Top instructions + check_instruction("LWCPI $C10, ($3+)", "3a31") + check_instruction("LWCPI $C7, ($2+)", "3721") + check_instruction("LWCPI $C15, ($12+)", "3fc1") + check_instruction("LWCPI $C1, ($3+)", "3131") + check_instruction("LWCPI $C10, ($4+)", "3a41") + + # Randomly choosen instructions + check_instruction("LWCPI $C0, ($1+)", "3011") + check_instruction("LWCPI $C0, ($11+)", "30b1") + check_instruction("LWCPI $C3, ($10+)", "33a1") + check_instruction("LWCPI $C0, ($5+)", "3051") + check_instruction("LWCPI $C2, ($3+)", "3231") + + def test_SMCPI(self): + """Test the SMCPI instruction""" + + # Top instructions + check_instruction("SMCPI $C10, ($SP+)", "3af2") + check_instruction("SMCPI $C14, ($7+)", "3e72") + check_instruction("SMCPI $C3, ($3+)", "3332") + check_instruction("SMCPI $C8, ($10+)", "38a2") + check_instruction("SMCPI $C0, ($3+)", "3032") + + # Randomly choosen instructions + check_instruction("SMCPI $C5, ($10+)", "35a2") + check_instruction("SMCPI $C9, ($3+)", "3932") + check_instruction("SMCPI $C11, ($5+)", "3b52") + check_instruction("SMCPI $C0, ($9+)", "3092") + check_instruction("SMCPI $C10, ($5+)", "3a52") + + def test_LMCPI(self): + """Test the LMCPI instruction""" + + # Top instructions + check_instruction("LMCPI $C2, ($3+)", "3233") + check_instruction("LMCPI $C0, ($3+)", "3033") + check_instruction("LMCPI $C10, ($7+)", "3a73") + check_instruction("LMCPI $C3, ($3+)", "3333") + check_instruction("LMCPI $C0, ($0+)", "3003") + + # Randomly choosen instructions + check_instruction("LMCPI $C0, ($SP+)", "30f3") + check_instruction("LMCPI $C1, ($1+)", "3113") + check_instruction("LMCPI $C3, ($0+)", "3303") + check_instruction("LMCPI $C3, ($2+)", "3323") + check_instruction("LMCPI $C13, ($9+)", "3d93") + + def test_SWCP(self): + """Test the SWCP instruction""" + + # Top instructions + check_instruction("SWCP $C1, ($4)", "3148") + check_instruction("SWCP $C13, ($1)", "3d18") + check_instruction("SWCP $C0, ($6)", "3068") + check_instruction("SWCP $C10, ($7)", "3a78") + check_instruction("SWCP $C0, ($10)", "30a8") + + # Randomly choosen instructions + check_instruction("SWCP $C7, ($12)", "37c8") + check_instruction("SWCP $C1, ($1)", "3118") + check_instruction("SWCP $C10, ($5)", "3a58") + check_instruction("SWCP $C8, ($11)", "38b8") + check_instruction("SWCP $C11, ($3)", "3b38") + + def test_LWCP(self): + """Test the LWCP instruction""" + + # Top instructions + check_instruction("LWCP $C14, ($7)", "3e79") + check_instruction("LWCP $C2, ($3)", "3239") + check_instruction("LWCP $C14, ($5)", "3e59") + check_instruction("LWCP $C6, ($10)", "36a9") + check_instruction("LWCP $C6, ($TP)", "36d9") + + # Randomly choosen instructions + check_instruction("LWCP $C11, ($9)", "3b99") + check_instruction("LWCP $C1, ($1)", "3119") + check_instruction("LWCP $C7, ($3)", "3739") + check_instruction("LWCP $C2, ($4)", "3249") + check_instruction("LWCP $C2, ($6)", "3269") + + def test_SMCP(self): + """Test the SMCP instruction""" + + # Top instructions + check_instruction("SMCP $C14, ($11)", "3eba") + check_instruction("SMCP $C12, ($GP)", "3cea") + check_instruction("SMCP $C4, ($GP)", "34ea") + check_instruction("SMCP $C0, ($GP)", "30ea") + check_instruction("SMCP $C12, ($0)", "3c0a") + + # Randomly choosen instructions + check_instruction("SMCP $C3, ($4)", "334a") + check_instruction("SMCP $C13, ($0)", "3d0a") + check_instruction("SMCP $C3, ($3)", "333a") + check_instruction("SMCP $C15, ($1)", "3f1a") + check_instruction("SMCP $C13, ($SP)", "3dfa") + + def test_LMCP(self): + """Test the LMCP instruction""" + + # Top instructions + check_instruction("LMCP $C14, ($6)", "3e6b") + check_instruction("LMCP $C14, ($4)", "3e4b") + check_instruction("LMCP $C5, ($6)", "356b") + check_instruction("LMCP $C9, ($4)", "394b") + check_instruction("LMCP $C15, ($6)", "3f6b") + + # Randomly choosen instructions + check_instruction("LMCP $C0, ($4)", "304b") + check_instruction("LMCP $C0, ($GP)", "30eb") + check_instruction("LMCP $C13, ($6)", "3d6b") + check_instruction("LMCP $C11, ($6)", "3b6b") + check_instruction("LMCP $C0, ($SP)", "30fb") diff --git a/test/arch/mep/asm/test_major_opcode_4.py b/test/arch/mep/asm/test_major_opcode_4.py new file mode 100644 index 00000000..c5de257e --- /dev/null +++ b/test/arch/mep/asm/test_major_opcode_4.py @@ -0,0 +1,118 @@ +# Toshiba MeP-c4 - Major Opcode #4 unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_asm import check_instruction + + +class TestMajor4: + + def test_ADD3(self): + """Test the ADD3 instruction""" + + # Top instructions + check_instruction("ADD3 $2, $SP, 0x20", "4220", multi=2) + check_instruction("ADD3 $1, $SP, 0x14", "4114", multi=2) + check_instruction("ADD3 $SP, $SP, 0x2C", "4f2c", multi=2) + check_instruction("ADD3 $1, $SP, 0x20", "4120", multi=2) + check_instruction("ADD3 $SP, $SP, 0x24", "4f24", multi=2) + check_instruction("ADD3 $2, $SP, 0x4", "4204", multi=2) + check_instruction("ADD3 $2, $SP, 0x8", "4208", multi=2) + check_instruction("ADD3 $1, $SP, 0x8", "4108", multi=2) + check_instruction("ADD3 $SP, $SP, 0x20", "4f20", multi=2) + check_instruction("ADD3 $1, $SP, 0x4", "4104", multi=2) + + # Randomly choosen instructions + check_instruction("ADD3 $11, $SP, 0x38", "4b38", multi=2) + check_instruction("ADD3 $5, $SP, 0x30", "4530", multi=2) + check_instruction("ADD3 $TP, $SP, 0x38", "4d38", multi=2) + check_instruction("ADD3 $4, $SP, 0x70", "4470", multi=2) + check_instruction("ADD3 $SP, $SP, 0xC", "4f0c", multi=2) + check_instruction("ADD3 $10, $SP, 0x10", "4a10", multi=2) + check_instruction("ADD3 $6, $SP, 0x7C", "467c", multi=2) + check_instruction("ADD3 $11, $SP, 0x14", "4b14", multi=2) + check_instruction("ADD3 $7, $SP, 0x3C", "473c", multi=2) + check_instruction("ADD3 $SP, $SP, 0x48", "4f48", multi=2) + + def test_SW(self): + """Test the SW instruction""" + + # Top instructions + check_instruction("SW $6, 0x4($SP)", "4606", multi=2) + check_instruction("SW $0, 0x4($SP)", "4006", multi=2) + check_instruction("SW $8, 0x10($SP)", "4812", multi=2) + check_instruction("SW $7, 0x8($SP)", "470a", multi=2) + check_instruction("SW $8, 0x8($SP)", "480a", multi=2) + check_instruction("SW $7, 0x4($SP)", "4706", multi=2) + check_instruction("SW $8, 0xC($SP)", "480e", multi=2) + check_instruction("SW $TP, 0x4($SP)", "4d06", multi=2) + check_instruction("SW $8, 0x4($SP)", "4806", multi=2) + check_instruction("SW $4, 0x40($SP)", "4442", multi=2) + + # Randomly choosen instructions + check_instruction("SW $4, 0x30($SP)", "4432", multi=2) + check_instruction("SW $9, 0x3C($SP)", "493e", multi=2) + check_instruction("SW $6, 0x68($SP)", "466a", multi=2) + check_instruction("SW $0, 0x40($TP)", "40c2", multi=2) + check_instruction("SW $9, 0x68($SP)", "496a", multi=2) + check_instruction("SW $4, 0x4($SP)", "4406", multi=2) + check_instruction("SW $2, 0x18($SP)", "421a", multi=2) + check_instruction("SW $10, 0x60($SP)", "4a62", multi=2) + check_instruction("SW $GP, 0x14($SP)", "4e16", multi=2) + check_instruction("SW $1, 0x20($SP)", "4122", multi=2) + + def test_LW(self): + """Test the LW instruction""" + + # Top instructions + check_instruction("LW $1, 0x8($SP)", "410b", multi=2) + check_instruction("LW $6, 0x4($SP)", "4607", multi=2) + check_instruction("LW $8, 0x10($SP)", "4813", multi=2) + check_instruction("LW $1, 0x4($SP)", "4107", multi=2) + check_instruction("LW $7, 0x8($SP)", "470b", multi=2) + check_instruction("LW $8, 0x8($SP)", "480b", multi=2) + check_instruction("LW $7, 0x4($SP)", "4707", multi=2) + check_instruction("LW $8, 0xC($SP)", "480f", multi=2) + check_instruction("LW $TP, 0x4($SP)", "4d07", multi=2) + check_instruction("LW $8, 0x4($SP)", "4807", multi=2) + + # Randomly choosen instructions + check_instruction("LW $9, 0x4C($SP)", "494f", multi=2) + check_instruction("LW $2, 0x44($TP)", "42c7", multi=2) + check_instruction("LW $6, 0x58($SP)", "465b", multi=2) + check_instruction("LW $SP, 0x74($SP)", "4f77", multi=2) + check_instruction("LW $4, 0x68($TP)", "44eb", multi=2) + check_instruction("LW $3, 0x34($TP)", "43b7", multi=2) + check_instruction("LW $6, 0x28($SP)", "462b", multi=2) + check_instruction("LW $1, 0x68($TP)", "41eb", multi=2) + check_instruction("LW $9, 0x28($SP)", "492b", multi=2) + check_instruction("LW $12, 0x30($SP)", "4c33", multi=2) + + def test_LBU(self): + """Test the LBU instruction""" + + # Top instructions + check_instruction("LBU $1, 0x3F($TP)", "49bf", multi=2) + check_instruction("LBU $2, 0x3F($TP)", "4abf", multi=2) + check_instruction("LBU $4, 0x3F($TP)", "4cbf", multi=2) + check_instruction("LBU $4, 0x9($TP)", "4c89", multi=2) + check_instruction("LBU $4, 0x25($TP)", "4ca5", multi=2) + check_instruction("LBU $4, 0xA($TP)", "4c8a", multi=2) + check_instruction("LBU $4, 0x2($TP)", "4c82", multi=2) + check_instruction("LBU $4, 0x1($TP)", "4c81", multi=2) + check_instruction("LBU $4, 0x5($TP)", "4c85", multi=2) + check_instruction("LBU $4, 0x6($TP)", "4c86", multi=2) + + # Randomly choosen instructions + check_instruction("LBU $4, 0x21($TP)", "4ca1", multi=2) + check_instruction("LBU $4, 0x22($TP)", "4ca2", multi=2) + # Note: the following instruction can not be easily manipulated due to + # expressions simplifications performed by miasm at assembly and + # dissassembly, i.e. ExprMem($TP + 0) is simplified into ExprMem($TP) + #check_instruction("LBU $6, 0x0($TP)", "4e80", multi=2) + check_instruction("LBU $7, 0x3C($TP)", "4fbc", multi=2) + check_instruction("LBU $2, 0x4($TP)", "4a84", multi=2) + check_instruction("LBU $7, 0x57($TP)", "4fd7", multi=2) + check_instruction("LBU $3, 0x66($TP)", "4be6", multi=2) + check_instruction("LBU $4, 0x31($TP)", "4cb1", multi=2) + check_instruction("LBU $6, 0x59($TP)", "4ed9", multi=2) + check_instruction("LBU $5, 0x66($TP)", "4de6", multi=2) diff --git a/test/arch/mep/asm/test_major_opcode_5.py b/test/arch/mep/asm/test_major_opcode_5.py new file mode 100644 index 00000000..dc984420 --- /dev/null +++ b/test/arch/mep/asm/test_major_opcode_5.py @@ -0,0 +1,24 @@ +# Toshiba MeP-c4 - Major Opcode #5 unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_asm import check_instruction + + +class TestMajor5: + + def test_MOV(self): + """Test the MOV instruction""" + + # Top instructions + check_instruction("MOV $2, 0", "5200", multi=2) + check_instruction("MOV $12, 0", "5c00", multi=2) + check_instruction("MOV $4, 0", "5400", multi=2) + check_instruction("MOV $0, 0", "5000", multi=2) + check_instruction("MOV $0, 3", "5003", multi=2) + + # Randomly choosen instructions + check_instruction("MOV $8, 84", "5854", multi=2) + check_instruction("MOV $SP, 108", "5f6c", multi=2) + check_instruction("MOV $12, 80", "5c50", multi=2) + check_instruction("MOV $TP, 59", "5d3b", multi=2) + check_instruction("MOV $9, 89", "5959", multi=2) diff --git a/test/arch/mep/asm/test_major_opcode_6.py b/test/arch/mep/asm/test_major_opcode_6.py new file mode 100644 index 00000000..be7858b5 --- /dev/null +++ b/test/arch/mep/asm/test_major_opcode_6.py @@ -0,0 +1,126 @@ +# Toshiba MeP-c4 - Major Opcode #6 unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_asm import check_instruction + + +class TestMajor6: + + def test_ADD(self): + """Test the ADD instruction""" + + # Top instructions + check_instruction("ADD $SP, 12", "6f30") + check_instruction("ADD $SP, -12", "6fd0") + check_instruction("ADD $SP, 8", "6f20") + check_instruction("ADD $SP, -8", "6fe0") + check_instruction("ADD $4, 1", "6404") + + # Randomly choosen instructions + check_instruction("ADD $2, -26", "6298") + check_instruction("ADD $TP, 7", "6d1c") + check_instruction("ADD $SP, 26", "6f68") + check_instruction("ADD $8, -9", "68dc") + check_instruction("ADD $6, 16", "6640") + + def test_SLT3(self): + """Test the SLT3 instruction""" + + # Top instructions + check_instruction("SLT3 $0, $4, 0xC", "6461", multi=2) + check_instruction("SLT3 $0, $9, 0xC", "6961", multi=2) + check_instruction("SLT3 $0, $12, 0xC", "6c61", multi=2) + check_instruction("SLT3 $0, $GP, 0xC", "6e61", multi=2) + check_instruction("SLT3 $0, $GP, 0xD", "6e69", multi=2) + + # Randomly choosen instructions + check_instruction("SLT3 $0, $8, 0x14", "68a1", multi=2) + check_instruction("SLT3 $0, $6, 0x0", "6601", multi=2) + check_instruction("SLT3 $0, $2, 0xB", "6259", multi=2) + check_instruction("SLT3 $0, $SP, 0x15", "6fa9", multi=2) + check_instruction("SLT3 $0, $7, 0x14", "67a1", multi=2) + + def test_SRL(self): + """Test the SRL instruction""" + + # Top instructions + check_instruction("SRL $SP, 0xE", "6f72") + check_instruction("SRL $12, 0x4", "6c22") + check_instruction("SRL $12, 0x8", "6c42") + check_instruction("SRL $12, 0x2", "6c12") + check_instruction("SRL $5, 0xE", "6572") + + # Randomly choosen instructions + check_instruction("SRL $3, 0x16", "63b2") + check_instruction("SRL $0, 0x1F", "60fa") + check_instruction("SRL $5, 0xF", "657a") + check_instruction("SRL $6, 0xE", "6672") + check_instruction("SRL $6, 0x1B", "66da") + + def test_SRA(self): + """Test the SRA instruction""" + + # Top instructions + check_instruction("SRA $1, 0xC", "6163") + check_instruction("SRA $SP, 0xC", "6f63") + check_instruction("SRA $5, 0xE", "6573") + check_instruction("SRA $4, 0x1", "640b") + check_instruction("SRA $12, 0x8", "6c43") + + # Randomly choosen instructions + check_instruction("SRA $0, 0x1B", "60db") + check_instruction("SRA $10, 0x17", "6abb") + check_instruction("SRA $GP, 0xB", "6e5b") + check_instruction("SRA $SP, 0x17", "6fbb") + check_instruction("SRA $7, 0x17", "67bb") + + def test_SLTU3(self): + """Test the SLTU3 instruction""" + + # Top instructions + check_instruction("SLTU3 $0, $0, 0x1", "600d", multi=2) + check_instruction("SLTU3 $0, $5, 0xD", "656d", multi=2) + check_instruction("SLTU3 $0, $12, 0x1", "6c0d", multi=2) + check_instruction("SLTU3 $0, $GP, 0xC", "6e65", multi=2) + check_instruction("SLTU3 $0, $4, 0x4", "6425", multi=2) + + # Randomly choosen instructions + check_instruction("SLTU3 $0, $9, 0x9", "694d", multi=2) + check_instruction("SLTU3 $0, $TP, 0xF", "6d7d", multi=2) + check_instruction("SLTU3 $0, $10, 0x1D", "6aed", multi=2) + check_instruction("SLTU3 $0, $6, 0x10", "6685", multi=2) + check_instruction("SLTU3 $0, $10, 0x1C", "6ae5", multi=2) + + def test_SLL(self): + """Test the SLL instruction""" + + # Top instructions + check_instruction("SLL $6, 0xC", "6666") + check_instruction("SLL $SP, 0xD", "6f6e") + check_instruction("SLL $0, 0x5", "602e") + check_instruction("SLL $0, 0x2", "6016") + check_instruction("SLL $0, 0x3", "601e") + + # Randomly choosen instructions + check_instruction("SLL $8, 0x16", "68b6") + check_instruction("SLL $SP, 0x4", "6f26") + check_instruction("SLL $4, 0x19", "64ce") + check_instruction("SLL $12, 0xA", "6c56") + check_instruction("SLL $12, 0x17", "6cbe") + + def test_SLL3(self): + """Test the SLL3 instruction""" + + # Top instructions + check_instruction("SLL3 $0, $4, 0x5", "642f") + check_instruction("SLL3 $0, $4, 0x3", "641f") + check_instruction("SLL3 $0, $10, 0x8", "6a47") + check_instruction("SLL3 $0, $GP, 0xD", "6e6f") + check_instruction("SLL3 $0, $1, 0x3", "611f") + + # Randomly choosen instructions + check_instruction("SLL3 $0, $11, 0x16", "6bb7") + check_instruction("SLL3 $0, $TP, 0xD", "6d6f") + check_instruction("SLL3 $0, $10, 0xB", "6a5f") + check_instruction("SLL3 $0, $7, 0x6", "6737") + check_instruction("SLL3 $0, $2, 0xF", "627f") diff --git a/test/arch/mep/asm/test_major_opcode_7.py b/test/arch/mep/asm/test_major_opcode_7.py new file mode 100644 index 00000000..fcd5e1f9 --- /dev/null +++ b/test/arch/mep/asm/test_major_opcode_7.py @@ -0,0 +1,133 @@ +# Toshiba MeP-c4 - Major Opcode #7 unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_asm import check_instruction + + +class TestMajor7: + + def test_DI(self): + """Test the DI instruction""" + + # Top instructions + check_instruction("DI", "7000") + + def test_EI(self): + """Test the EI instruction""" + + # Top instructions + check_instruction("EI", "7010") + + def test_SYNCM(self): + """Test the SYNCM instruction""" + + # Top instructions + check_instruction("SYNCM", "7011") + + def test_SYNCCP(self): + """Test the SYNCCP instruction""" + + # Top instructions + check_instruction("SYNCCP", "7021") + + def test_RET(self): + """Test the RET instruction""" + + # Top instructions + check_instruction("RET", "7002") + + def test_RETI(self): + """Test the RETI instruction""" + + # Top instructions + check_instruction("RETI", "7012") + + def test_HALT(self): + """Test the HALT instruction""" + + # Top instructions + check_instruction("HALT", "7022") + + def test_BREAK(self): + """Test the BREAK instruction""" + + # Top instructions + check_instruction("BREAK", "7032") + + def test_SLEEP(self): + """Test the SLEEP instruction""" + + # Top instructions + check_instruction("SLEEP", "7062") + + def test_DRET(self): + """Test the DRET instruction""" + + # Top instructions + check_instruction("DRET", "7013") + + def test_DBREAK(self): + """Test the DBREAK instruction""" + + # Top instructions + check_instruction("DBREAK", "7033") + + def test_CACHE(self): + """Test the CACHE instruction""" + + # Top instructions + check_instruction("CACHE 0x0, ($11)", "70b4") + check_instruction("CACHE 0x2, ($7)", "7274") + check_instruction("CACHE 0x4, ($7)", "7474") + check_instruction("CACHE 0x9, ($7)", "7974") + check_instruction("CACHE 0x2, ($6)", "7264") + + # Randomly choosen instructions + check_instruction("CACHE 0x5, ($8)", "7584") + check_instruction("CACHE 0xC, ($6)", "7c64") + check_instruction("CACHE 0x2, ($1)", "7214") + check_instruction("CACHE 0x3, ($1)", "7314") + check_instruction("CACHE 0x1, ($8)", "7184") + + def test_SWI(self): + """Test the SWI instruction""" + + # Top instructions + check_instruction("SWI 0x0", "7006") + check_instruction("SWI 0x2", "7026") + check_instruction("SWI 0x1", "7016") + check_instruction("SWI 0x3", "7036") + + def test_STC(self): + """Test the STC instruction""" + + # Top instructions + check_instruction("STC $4, $S22", "7469") # the documentation & objsdump disagree + check_instruction("STC $3, $S22", "7369") # the documentation & objsdump disagree + check_instruction("STC $1, $CFG", "7159") + check_instruction("STC $8, $LO", "7888") + check_instruction("STC $0, $LP", "7018") + + # Randomly choosen instructions + check_instruction("STC $9, $DBG", "7989") + check_instruction("STC $2, $DBG", "7289") + check_instruction("STC $9, $LO", "7988") + check_instruction("STC $11, $DEPC", "7b99") + check_instruction("STC $1, $S29", "71d9") + + def test_LDC(self): + """Test the LDC instruction""" + + # Top instructions + check_instruction("LDC $1, $CFG", "715b") + check_instruction("LDC $9, $HI", "797a") + check_instruction("LDC $11, $LO", "7b8a") + check_instruction("LDC $12, $LO", "7c8a") + check_instruction("LDC $0, $LP", "701a") + + # Randomly choosen instructions + check_instruction("LDC $11, $RPC", "7b6a") + check_instruction("LDC $10, $CFG", "7a5b") + check_instruction("LDC $2, $NPC", "727b") + check_instruction("LDC $6, $MB1", "76ea") + check_instruction("LDC $TP, $RPC", "7d6a") diff --git a/test/arch/mep/asm/test_major_opcode_8.py b/test/arch/mep/asm/test_major_opcode_8.py new file mode 100644 index 00000000..c4a8505f --- /dev/null +++ b/test/arch/mep/asm/test_major_opcode_8.py @@ -0,0 +1,92 @@ +# Toshiba MeP-c4 - Major Opcode #8 unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_asm import check_instruction + + +class TestMajor8: + + def test_SB(self): + """Test the SB instruction""" + + # Top instructions + check_instruction("SB $4, 0x2($TP)", "8402", multi=2) + check_instruction("SB $4, 0x4B($TP)", "844b", multi=2) + check_instruction("SB $4, 0x3($TP)", "8403", multi=2) + check_instruction("SB $4, 0x1($TP)", "8401", multi=2) + check_instruction("SB $0, 0x3($TP)", "8003", multi=2) + + # Randomly choosen instructions + check_instruction("SB $2, 0x65($TP)", "8265", multi=2) + check_instruction("SB $5, 0x48($TP)", "8548", multi=2) + check_instruction("SB $7, 0x77($TP)", "8777", multi=2) + check_instruction("SB $1, 0x49($TP)", "8149", multi=2) + check_instruction("SB $4, 0x20($TP)", "8420", multi=2) + + def test_SH(self): + """Test the SH instruction""" + + # Top instructions + check_instruction("SH $0, 0x18($TP)", "8098", multi=2) + check_instruction("SH $4, 0x10($TP)", "8490", multi=2) + check_instruction("SH $4, 0xE($TP)", "848e", multi=2) + check_instruction("SH $4, 0x4($TP)", "8484", multi=2) + check_instruction("SH $4, 0xC($TP)", "848c", multi=2) + + # Randomly choosen instructions + check_instruction("SH $7, 0x3A($TP)", "87ba", multi=2) + check_instruction("SH $2, 0x36($TP)", "82b6", multi=2) + check_instruction("SH $1, 0x76($TP)", "81f6", multi=2) + check_instruction("SH $7, 0x74($TP)", "87f4", multi=2) + check_instruction("SH $7, 0x7E($TP)", "87fe", multi=2) + + def test_LB(self): + """Test the LB instruction""" + + # Top instructions + check_instruction("LB $4, 0x1($TP)", "8c01", multi=2) + check_instruction("LB $4, 0x27($TP)", "8c27", multi=2) + check_instruction("LB $4, 0x4($TP)", "8c04", multi=2) + check_instruction("LB $4, 0x1A($TP)", "8c1a", multi=2) + check_instruction("LB $4, 0x6($TP)", "8c06", multi=2) + + # Randomly choosen instructions + check_instruction("LB $4, 0x59($TP)", "8c59", multi=2) + check_instruction("LB $7, 0x53($TP)", "8f53", multi=2) + check_instruction("LB $6, 0x62($TP)", "8e62", multi=2) + check_instruction("LB $6, 0x53($TP)", "8e53", multi=2) + check_instruction("LB $0, 0x34($TP)", "8834", multi=2) + + def test_LH(self): + """Test the LH instruction""" + + # Top instructions + check_instruction("LH $4, 0x18($TP)", "8c98", multi=2) + check_instruction("LH $4, 0x10($TP)", "8c90", multi=2) + check_instruction("LH $4, 0x28($TP)", "8ca8", multi=2) + check_instruction("LH $4, 0x6($TP)", "8c86", multi=2) + check_instruction("LH $4, 0x4($TP)", "8c84", multi=2) + + # Randomly choosen instructions + check_instruction("LH $7, 0x28($TP)", "8fa8", multi=2) + check_instruction("LH $4, 0x16($TP)", "8c96", multi=2) + check_instruction("LH $0, 0x56($TP)", "88d6", multi=2) + check_instruction("LH $4, 0x40($TP)", "8cc0", multi=2) + check_instruction("LH $7, 0x2A($TP)", "8faa", multi=2) + + def test_LHU(self): + """Test the LHU instruction""" + + # Top instructions + check_instruction("LHU $4, 0x4($TP)", "8c85", multi=2) + check_instruction("LHU $4, 0x28($TP)", "8ca9", multi=2) + check_instruction("LHU $4, 0xC($TP)", "8c8d", multi=2) + check_instruction("LHU $4, 0x10($TP)", "8c91", multi=2) + check_instruction("LHU $3, 0xC($TP)", "8b8d", multi=2) + + # Randomly choosen instructions + check_instruction("LHU $3, 0x54($TP)", "8bd5", multi=2) + check_instruction("LHU $7, 0x66($TP)", "8fe7", multi=2) + check_instruction("LHU $2, 0x6E($TP)", "8aef", multi=2) + check_instruction("LHU $2, 0x36($TP)", "8ab7", multi=2) + check_instruction("LHU $3, 0x78($TP)", "8bf9", multi=2) diff --git a/test/arch/mep/asm/test_major_opcode_9.py b/test/arch/mep/asm/test_major_opcode_9.py new file mode 100644 index 00000000..822f3b6a --- /dev/null +++ b/test/arch/mep/asm/test_major_opcode_9.py @@ -0,0 +1,24 @@ +# Toshiba MeP-c4 - Major Opcode #9 unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_asm import check_instruction + + +class TestMajor9: + + def test_ADD3(self): + """Test the ADD3 instruction""" + + # Top instructions + check_instruction("ADD3 $10, $4, $0", "940a") + check_instruction("ADD3 $3, $0, $0", "9003") + check_instruction("ADD3 $12, $4, $0", "940c") + check_instruction("ADD3 $7, $12, $0", "9c07") + check_instruction("ADD3 $TP, $4, $0", "940d") + + # Randomly choosen instructions + check_instruction("ADD3 $4, $1, $9", "9194") + check_instruction("ADD3 $7, $12, $9", "9c97") + check_instruction("ADD3 $12, $9, $SP", "99fc") + check_instruction("ADD3 $12, $TP, $7", "9d7c") + check_instruction("ADD3 $4, $8, $SP", "98f4") diff --git a/test/arch/mep/asm/ut_helpers_asm.py b/test/arch/mep/asm/ut_helpers_asm.py new file mode 100644 index 00000000..af010afc --- /dev/null +++ b/test/arch/mep/asm/ut_helpers_asm.py @@ -0,0 +1,92 @@ +# Toshiba MeP-c4 - unit tests helpers +# Guillaume Valadon <guillaume@valadon.net> + +from miasm2.arch.mep.arch import mn_mep +from miasm2.core.cpu import Disasm_Exception +from miasm2.core.locationdb import LocationDB +from miasm2.expression.expression import ExprId, ExprInt, ExprLoc + +import re + + +def dis(mn_hex): + """Disassembly helper""" + mn_bin = mn_hex.decode("hex") + try: + return mn_mep.dis(mn_bin, "b") + except Disasm_Exception: + assert(False) # miasm don't know what to do + + +def check_instruction(mn_str, mn_hex, multi=None, offset=0): + """Try to disassemble and assemble this instruction""" + + # Rename objdump registers names + mn_str = re.sub("\$([0-9]+)", lambda m: "R"+m.group(1), mn_str) + mn_str = mn_str.replace("$", "") + + # Disassemble + mn = dis(mn_hex) + mn.offset = offset + if mn.dstflow(): + + # Remember ExprInt arguments sizes + args_size = list() + for i in range(len(mn.args)): + if isinstance(mn.args[i], ExprInt): + args_size.append(mn.args[i].size) + else: + args_size.append(None) + + # Adjust arguments values using the instruction offset + loc_db = LocationDB() + mn.dstflow2label(loc_db) + + # Convert ExprLoc to ExprInt + for i in range(len(mn.args)): + if args_size[i] is None: + continue + if isinstance(mn.args[i], ExprLoc): + addr = loc_db.get_location_offset(mn.args[i].loc_key) + mn.args[i] = ExprInt(addr, args_size[i]) + + print "dis: %s -> %s" % (mn_hex.rjust(20), str(mn).rjust(20)) + assert(str(mn) == mn_str) # disassemble assertion + + # Assemble and return all possible candidates + instr = mn_mep.fromstring(mn_str, "b") + instr.offset = offset + instr.mode = "b" + if instr.offset: + instr.fixDstOffset() + asm_list = [i.encode("hex") for i in mn_mep.asm(instr)] + + # Check instructions variants + if multi: + print "Instructions count:", len(asm_list) + assert(len(asm_list) == multi) + + # Ensure that variants correspond to the same disassembled instruction + for mn_hex in asm_list: + mn = dis(mn_hex) + print "dis: %s -> %s" % (mn_hex.rjust(20), str(mn).rjust(20)) + + # Check the assembly result + print "asm: %s -> %s" % (mn_str.rjust(20), + ", ".join(asm_list).rjust(20)) + assert(mn_hex in asm_list) # assemble assertion + + +def launch_tests(obj): + """Call test methods by name""" + + test_methods = [name for name in dir(obj) if name.startswith("test")] + + for method in test_methods: + print method + try: + getattr(obj, method)() + except AttributeError as e: + print "Method not found: %s" % method + assert(False) + print '-' * 42 diff --git a/test/arch/mep/ir/launch.py b/test/arch/mep/ir/launch.py new file mode 100644 index 00000000..44a8db52 --- /dev/null +++ b/test/arch/mep/ir/launch.py @@ -0,0 +1,22 @@ +# Toshiba MeP-c4 - pytest unit tests wrapper +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_ir import launch_tests + +from test_arithmetic import TestArithmetic; launch_tests(TestArithmetic()) +from test_bitmanipulation import TestBitManipulation; launch_tests(TestBitManipulation()) +from test_branchjump import TestBranchJump; launch_tests(TestBranchJump()) +from test_control import TestControl; launch_tests(TestControl()) +from test_coprocessor import TestCoprocessor; launch_tests(TestCoprocessor()) +from test_datacache import TestDataCache; launch_tests(TestDataCache()) +from test_debug import TestDebug; launch_tests(TestDebug()) +from test_divide import TestDivide; launch_tests(TestDivide()) +from test_extension import TestExtension; launch_tests(TestExtension()) +from test_ldz import TestLdz; launch_tests(TestLdz()) +from test_loadstore import TestLoadStore; launch_tests(TestLoadStore()) +from test_logical import TestLogical; launch_tests(TestLogical()) +from test_move import TestMove; launch_tests(TestMove()) +from test_multiply import TestMultiply; launch_tests(TestMultiply()) +from test_repeat import TestRepeat; launch_tests(TestRepeat()) +from test_shift import TestShift; launch_tests(TestShift()) +from test_ir import TestMisc; launch_tests(TestMisc()) diff --git a/test/arch/mep/ir/test_arithmetic.py b/test/arch/mep/ir/test_arithmetic.py new file mode 100644 index 00000000..6da938e9 --- /dev/null +++ b/test/arch/mep/ir/test_arithmetic.py @@ -0,0 +1,185 @@ +# Toshiba MeP-c4 - Arithmetic instructions unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_ir import exec_instruction + +from miasm2.expression.expression import ExprId, ExprInt, ExprCond, ExprOp + + +class TestArithmetic: + + def test_add3(self): + """Test ADD3 execution""" + + # ADD3 Rl,Rn,Rm + exec_instruction("ADD3 R1, R2, R3", + [(ExprId("R2", 32), ExprInt(0x40, 32)), (ExprId("R3", 32), ExprInt(0x2, 32))], + [(ExprId("R1", 32), ExprInt(0x42, 32))]) + + # ADD3 Rn,SP,imm7.align4 + exec_instruction("ADD3 R1, SP, 0x8", + [(ExprId("SP", 32), ExprInt(0x20, 32))], + [(ExprId("R1", 32), ExprInt(0x28, 32))]) + + # ADD3 Rn,Rm,imm16 + exec_instruction("ADD3 R7, R5, -31912", + [(ExprId("R5", 32), ExprInt(0x20, 32))], + [(ExprId("R7", 32), ExprInt(-31880, 32))]) + + def test_add(self): + """Test ADD execution""" + + # ADD Rn,imm6 + exec_instruction("ADD R1, 0x10", + [(ExprId("R1", 32), ExprInt(0x32, 32))], + [(ExprId("R1", 32), ExprInt(0x42, 32))]) + + exec_instruction("ADD R1, -5", + [(ExprId("R1", 32), ExprInt(0x32, 32))], + [(ExprId("R1", 32), ExprInt(45, 32))]) + + exec_instruction("ADD R1, -16", + [(ExprId("R1", 32), ExprInt(0xFFFF, 32))], + [(ExprId("R1", 32), ExprInt(0xFFEF, 32))]) + + exec_instruction("ADD R1, -28", + [(ExprId("R1", 32), ExprInt(0, 32))], + [(ExprId("R1", 32), ExprInt(0xFFFFFFE4, 32))]) + + def test_advck3(self): + """Test ADVCK3 execution""" + + # ADVCK3 R0,Rn,Rm + exec_instruction("ADVCK3 R0, R1, R2", + [(ExprId("R1", 32), ExprInt(1, 32)), + (ExprId("R2", 32), ExprInt(2, 32))], + [(ExprId("R0", 32), ExprInt(0, 32))]) + + exec_instruction("ADVCK3 R0, R1, R2", + [(ExprId("R1", 32), ExprInt(1, 32)), + (ExprId("R2", 32), ExprInt(0xFFFFFFFF, 32))], + [(ExprId("R0", 32), ExprInt(1, 32))]) + + def test_sub(self): + """Test SUB execution""" + + # SUB Rn,Rm + exec_instruction("SUB R1, R2", + [(ExprId("R1", 32), ExprInt(0x28, 32)), + (ExprId("R2", 32), ExprInt(0x7, 32))], + [(ExprId("R1", 32), ExprInt(0x21, 32))]) + + def test_sbvck3(self): + """Test SBVCK3 execution""" + + # SBVCK3 R0,Rn,Rm + exec_instruction("SBVCK3 R0, R1, R2", + [(ExprId("R1", 32), ExprInt(2, 32)), + (ExprId("R2", 32), ExprInt(1, 32))], + [(ExprId("R0", 32), ExprCond(ExprOp(">", + ExprInt(3, 32), + ExprCond(ExprOp(">", ExprInt(0x2, 32), ExprInt(0x1, 32)), + ExprInt(0x2, 32), + ExprInt(0x1, 32))), + ExprInt(1, 32), + ExprInt(0, 32)))]) + + exec_instruction("SBVCK3 R0, R1, R2", + [(ExprId("R1", 32), ExprInt(0, 32)), + (ExprId("R2", 32), ExprInt(1, 32))], + [(ExprId("R0", 32), ExprCond(ExprOp(">", + ExprInt(1, 32), + ExprCond(ExprOp(">", ExprInt(0, 32), ExprInt(1, 32)), + ExprInt(0, 32), + ExprInt(1, 32))), + ExprInt(1, 32), + ExprInt(0, 32)))]) + + def test_neg(self): + """Test NEG execution""" + + # NEG Rn,Rm + exec_instruction("NEG R1, R2", + [(ExprId("R2", 32), ExprInt(1, 32))], + [(ExprId("R1", 32), ExprInt(0xFFFFFFFF, 32))]) + + exec_instruction("NEG R1, R2", + [(ExprId("R2", 32), ExprInt(0x42, 32))], + [(ExprId("R1", 32), ExprInt(0xFFFFFFBE, 32))]) + + def test_slt3(self): + """Test SLT3 execution""" + + # SLT3 R0,Rn,Rm + exec_instruction("SLT3 R0, R1, R2", + [(ExprId("R1", 32), ExprInt(0x2, 32)), + (ExprId("R2", 32), ExprInt(0x1, 32))], + [(ExprId("R0", 32), ExprInt(0, 32))]) + + r1 = 0x80000000 + r2 = 0x80000001 + exec_instruction("SLT3 R0, R1, R2", + [(ExprId("R1", 32), ExprInt(r1, 32)), + (ExprId("R2", 32), ExprInt(r2, 32))], + [(ExprId("R0", 32), ExprInt(1, 32))]) + + r1 = 0x80000000 + r2 = 0x00000001 + exec_instruction("SLT3 R0, R1, R2", + [(ExprId("R1", 32), ExprInt(r1, 32)), + (ExprId("R2", 32), ExprInt(r2, 32))], + [(ExprId("R0", 32), ExprInt(1, 32))]) + + r1 = 0x00000001 + r2 = 0x80000000 + exec_instruction("SLT3 R0, R1, R2", + [(ExprId("R1", 32), ExprInt(r1, 32)), + (ExprId("R2", 32), ExprInt(r2, 32))], + [(ExprId("R0", 32), ExprInt(0, 32))]) + + # SLT3 R0,Rn,imm5 + exec_instruction("SLT3 R0, R1, 12", + [(ExprId("R1", 32), ExprInt(0x1, 32))], + [(ExprId("R0", 32), ExprInt(1, 32))]) + + r1 = 0x80000000 + exec_instruction("SLT3 R0, R1, 12", + [(ExprId("R1", 32), ExprInt(0x80000000, 32))], + [(ExprId("R0", 32), ExprInt(1, 32))]) + + def test_sltu3(self): + """Test SLTU3 execution""" + + # SLTU3 R0,Rn,Rm + exec_instruction("SLTU3 R0, R1, R2", + [(ExprId("R1", 32), ExprInt(0x1, 32)), + (ExprId("R2", 32), ExprInt(0x2, 32))], + [(ExprId("R0", 32), ExprInt(1, 32))]) + + exec_instruction("SLTU3 R0, R1, R2", + [(ExprId("R1", 32), ExprInt(0x2, 32)), + (ExprId("R2", 32), ExprInt(0x1, 32))], + [(ExprId("R0", 32), ExprInt(0, 32))]) + + # SLTU3 R0,Rn,imm5 + exec_instruction("SLTU3 R0, R1, 12", + [(ExprId("R1", 32), ExprInt(0x1, 32))], + [(ExprId("R0", 32), ExprInt(1, 32))]) + + def test_sl1ad3(self): + """Test SL2AD3 execution""" + + # SL1AD3 R0,Rn,Rm + exec_instruction("SL1AD3 R0, R1, R2", + [(ExprId("R1", 32), ExprInt(0x2, 32)), + (ExprId("R2", 32), ExprInt(0x20, 32))], + [(ExprId("R0", 32), ExprInt(0x24, 32))]) + + def test_sl2ad3(self): + """Test SL2AD3 execution""" + + # SL2AD3 R0,Rn,Rm + exec_instruction("SL2AD3 R0, R1, R2", + [(ExprId("R1", 32), ExprInt(0x2, 32)), + (ExprId("R2", 32), ExprInt(0x20, 32))], + [(ExprId("R0", 32), ExprInt(0x28, 32))]) diff --git a/test/arch/mep/ir/test_bitmanipulation.py b/test/arch/mep/ir/test_bitmanipulation.py new file mode 100644 index 00000000..06466f9d --- /dev/null +++ b/test/arch/mep/ir/test_bitmanipulation.py @@ -0,0 +1,55 @@ +# Toshiba MeP-c4 - Bit manipulation instructions unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_ir import exec_instruction + +from miasm2.expression.expression import ExprId, ExprInt, ExprMem + + +class TestBitManipulation: + + def test_bsetm(self): + """Test BSETM execution""" + + # BSETM (Rm),imm3 + exec_instruction("BSETM (R1), 1", + [(ExprId("R1", 32), ExprInt(0x28, 32)), + (ExprMem(ExprInt(0x28, 32), 8), ExprInt(0x1, 8))], + [(ExprMem(ExprInt(0x28, 32), 8), ExprInt(0x3, 8))]) + + def test_bclrm(self): + """Test BCLRM execution""" + + # BCLRM (Rm),imm3 + exec_instruction("BCLRM (R1), 1", + [(ExprId("R1", 32), ExprInt(0x28, 32)), + (ExprMem(ExprInt(0x28, 32), 8), ExprInt(0x3, 8))], + [(ExprMem(ExprInt(0x28, 32), 8), ExprInt(0x1, 8))]) + + def test_bnotm(self): + """Test BNOTM execution""" + + # BNOTM (Rm),imm3 + exec_instruction("BNOTM (R1), 1", + [(ExprId("R1", 32), ExprInt(0x28, 32)), + (ExprMem(ExprInt(0x28, 32), 8), ExprInt(0x1, 8))], + [(ExprMem(ExprInt(0x28, 32), 8), ExprInt(0x3, 8))]) + + def test_btstm(self): + """Test BTSTM execution""" + + # BTSTM R0,(Rm),imm3 + exec_instruction("BTSTM R0, (R1), 1", + [(ExprId("R1", 32), ExprInt(0x28, 32)), + (ExprMem(ExprInt(0x28, 32), 8), ExprInt(0x2, 8))], + [(ExprId("R0", 32), ExprInt(0x2, 32))]) + + def test_tas(self): + """Test TAS execution""" + + # TAS Rn,(Rm) + exec_instruction("TAS R0, (R1)", + [(ExprId("R1", 32), ExprInt(0x28, 32)), + (ExprMem(ExprInt(0x28, 32), 8), ExprInt(0x2, 8))], + [(ExprId("R0", 32), ExprInt(0x2, 32)), + (ExprMem(ExprInt(0x28, 32), 8), ExprInt(0x1, 8))]) diff --git a/test/arch/mep/ir/test_branchjump.py b/test/arch/mep/ir/test_branchjump.py new file mode 100644 index 00000000..48feb54d --- /dev/null +++ b/test/arch/mep/ir/test_branchjump.py @@ -0,0 +1,191 @@ +# Toshiba MeP-c4 - Branch/Jump instructions unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_ir import exec_instruction + +from miasm2.expression.expression import ExprId, ExprCond, ExprOp, ExprInt + + +class TestBranchJump: + + def test_bra(self): + """Test BRA execution""" + + # BRA disp12.align2 + exec_instruction("BRA 0x28", + [], + [(ExprId("PC", 32), ExprInt(0x28, 32))]) + + exec_instruction("BRA 0x800", + [], + [(ExprId("PC", 32), ExprInt(0xFFFFF800, 32))]) + + exec_instruction("BRA 0x28", + [], + [(ExprId("PC", 32), ExprInt(0x1028, 32))], offset=0x1000) + + def test_beqz(self): + """Test BEQZ execution""" + + # BEQZ Rn,disp8.align2 + exec_instruction("BEQZ R1, 0x10", + [(ExprId("R1", 32), ExprInt(0, 32))], + [(ExprId("PC", 32), ExprInt(0x20, 32))], offset=0x10) + + exec_instruction("BEQZ R1, 0x10", + [(ExprId("R1", 32), ExprInt(1, 32))], + [(ExprId("PC", 32), ExprInt(0x2, 32))]) + + exec_instruction("BEQZ R1, 0x80", + [(ExprId("R1", 32), ExprInt(0, 32))], + [(ExprId("PC", 32), ExprInt(0xFFFFFF90, 32))], offset=0x10) + + def test_bnez(self): + """Test BNEZ execution""" + + # BNEZ Rn,disp8.align2 + exec_instruction("BNEZ R1, 0x10", + [(ExprId("R1", 32), ExprInt(0, 32))], + [(ExprId("PC", 32), ExprInt(0x2, 32))]) + + exec_instruction("BNEZ R1, 0x10", + [(ExprId("R1", 32), ExprInt(1, 32))], + [(ExprId("PC", 32), ExprInt(0x20, 32))], offset=0x10) + + exec_instruction("BNEZ R1, 0x80", + [(ExprId("R1", 32), ExprInt(0, 32))], + [(ExprId("PC", 32), ExprInt(0x2, 32))]) + + def test_beqi(self): + """Test BEQI execution""" + + # BEQI Rn,imm4,disp17.align2 + exec_instruction("BEQI R1, 0x8, 0x28", + [(ExprId("R1", 32), ExprInt(0, 32))], + [(ExprId("PC", 32), ExprInt(0x4, 32))]) + + exec_instruction("BEQI R1, 0x1, 0x28", + [(ExprId("R1", 32), ExprInt(1, 32))], + [(ExprId("PC", 32), ExprInt(0x38, 32))], offset=0x10) + + exec_instruction("BEQI R1, 0x6, 0x10000", + [(ExprId("R1", 32), ExprInt(6, 32))], + [(ExprId("PC", 32), ExprInt(0xFFFF0010, 32))], offset=0x10) + + def test_bnei(self): + """Test BNEI execution""" + + # BNEI Rn,imm4,disp17.align2 + exec_instruction("BNEI R1, 0x5, 0x28", + [(ExprId("R1", 32), ExprInt(0, 32))], + [(ExprId("PC", 32), ExprInt(0x38, 32))], offset=0x10) + + exec_instruction("BNEI R1, 0x7, 0xFF00", + [(ExprId("R1", 32), ExprInt(7, 32)), + (ExprId("PC", 32), ExprInt(0x1, 32))], + [(ExprId("PC", 32), ExprInt(0x4, 32))]) + + def test_blti(self): + """Test BLTI execution""" + + # BLTI Rn,imm4,disp17.align2 + exec_instruction("BLTI R1, 0x5, 0x10000", + [(ExprId("R1", 32), ExprInt(0x10, 32))], + [(ExprId("PC", 32), ExprInt(0x14, 32))], + offset=0x10) + + exec_instruction("BLTI R1, 0x5, 0x10000", + [(ExprId("R1", 32), ExprInt(0x1, 32))], + [(ExprId("PC", 32), ExprInt(0xFFFF0010, 32))], + offset=0x10) + + def test_bgei(self): + """Test BGEI execution""" + + # BGEI Rn,imm4,disp17.align2 + exec_instruction("BGEI R1, 0x5, 0x10000", + [(ExprId("R1", 32), ExprInt(0x10, 32))], + [(ExprId("PC", 32), ExprCond(ExprOp(">=", ExprInt(0x10, 32), ExprInt(0x5, 32)), ExprInt(0xFFFF0010, 32), ExprInt(0x14, 32)))], + offset=0x10) + + def test_beq(self): + """Test BEQ execution""" + + # BEQ Rn,Rm,disp17.align2 + exec_instruction("BEQ R1, R2, 0x10000", + [(ExprId("R1", 32), ExprInt(0x10, 32)), + (ExprId("R2", 32), ExprInt(0x10, 32))], + [(ExprId("PC", 32), ExprInt(0xFFFF0010, 32))], offset=0x10) + + exec_instruction("BEQ R1, R2, 0x8000", + [(ExprId("R1", 32), ExprInt(0x09, 32)), + (ExprId("R2", 32), ExprInt(0x10, 32)), + (ExprId("PC", 32), ExprInt(0x10, 32))], + [(ExprId("PC", 32), ExprInt(0x4, 32))]) + + def test_bne(self): + """Test BNE execution""" + + # BNE Rn,Rm,disp17.align2 + exec_instruction("BNE R1, R2, 0x8000", + [(ExprId("R1", 32), ExprInt(0x10, 32)), + (ExprId("R2", 32), ExprInt(0x10, 32))], + [(ExprId("PC", 32), ExprInt(0x4, 32))]) + + exec_instruction("BNE R1, R2, 0x8000", + [(ExprId("R1", 32), ExprInt(0x09, 32)), + (ExprId("R2", 32), ExprInt(0x10, 32))], + [(ExprId("PC", 32), ExprInt(0x8010, 32))], offset=0x10) + + exec_instruction("BNE R1, R2, 0x10000", + [(ExprId("R1", 32), ExprInt(0x09, 32)), + (ExprId("R2", 32), ExprInt(0x10, 32))], + [(ExprId("PC", 32), ExprInt(0xFFFF0010, 32))], offset=0x10) + + def test_bsr(self): + """Test BSR execution""" + + # BSR disp12.align2 + exec_instruction("BSR 0x800", + [(ExprId("PC", 32), ExprInt(2, 32))], + [(ExprId("PC", 32), ExprInt(0xFFFFF800, 32)), + (ExprId("LP", 32), ExprInt(2, 32))], index=0) + + # BSR disp24.align2 + exec_instruction("BSR 0x101015", + [(ExprId("PC", 32), ExprInt(4, 32))], + [(ExprId("PC", 32), ExprInt(0x101014, 32)), + (ExprId("LP", 32), ExprInt(4, 32))], index=1) + + def test_jmp(self): + """Test JMP execution""" + + # JMP Rm + exec_instruction("JMP R1", + [(ExprId("R1", 32), ExprInt(0x101015, 32))], + [(ExprId("PC", 32), ExprInt(0x101015, 32))]) + + # JMP target24.align2 + exec_instruction("JMP 0x2807", + [(ExprId("PC", 32), ExprInt(0, 32))], + [(ExprId("PC", 32), ExprInt(0x2806, 32))], offset=0x42) + exec_instruction("JMP 0x2807", + [(ExprId("PC", 32), ExprInt(0xB0000000, 32))], + [(ExprId("PC", 32), ExprInt(0xB0002806, 32))], offset=0xB0000000) + + def test_jsr(self): + """Test JSR execution""" + + # JSR Rm + exec_instruction("JSR R1", + [(ExprId("R1", 32), ExprInt(0x2807, 32))], + [(ExprId("PC", 32), ExprInt(0x2807, 32)), + (ExprId("LP", 32), ExprInt(0x2, 32))]) + + def test_ret(self): + """Test RET execution""" + + # RET + exec_instruction("RET", + [(ExprId("LP", 32), ExprInt(0x28, 32))], + [(ExprId("PC", 32), ExprInt(0x28, 32))]) diff --git a/test/arch/mep/ir/test_control.py b/test/arch/mep/ir/test_control.py new file mode 100644 index 00000000..a1b3c7c7 --- /dev/null +++ b/test/arch/mep/ir/test_control.py @@ -0,0 +1,105 @@ +# Toshiba MeP-c4 - Control instructions unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_ir import exec_instruction + +from miasm2.expression.expression import ExprId, ExprInt, ExprCond, ExprOp + + +class TestControl: + + def test_stc(self): + """Test STC execution""" + + # STC Rn,imm5 + exec_instruction("STC R1, SAR", + [(ExprId("R1", 32), ExprInt(0x28, 32))], + [(ExprId("SAR", 32), ExprInt(0x28, 32))]) + + def test_ldc(self): + """Test LDC execution""" + + # LDC Rn,imm5 + exec_instruction("LDC R1, SAR", + [(ExprId("SAR", 32), ExprInt(0x28, 32))], + [(ExprId("R1", 32), ExprInt(0x28, 32))]) + + def test_di(self): + """Test DI execution""" + + # DI + exec_instruction("DI", + [(ExprId("PSW", 32), ExprInt(1, 32))], + [(ExprId("PSW", 32), ExprInt(0, 32))]) + + def test_ei(self): + """Test EI execution""" + + # EI + exec_instruction("EI", + [(ExprId("PSW", 32), ExprInt(0, 32))], + [(ExprId("PSW", 32), ExprInt(1, 32))]) + + def test_reti(self): + """Test RETI execution""" + + # RETI + exec_instruction("RETI", + [(ExprId("PSW", 32), ExprInt(0xF0000201, 32)), # PSW_NMI = 1 + (ExprId("NPC", 32), ExprInt(0x43, 32))], + [(ExprId("PSW", 32), ExprInt(0xF0000001, 32)), + (ExprId("PC", 32), ExprInt(0x42, 32))]) + + exec_instruction("RETI", + [(ExprId("PSW", 32), ExprInt(0b1010, 32)), # PSW_UMP = 1 & PSW_IEP = 1 + (ExprId("EPC", 32), ExprInt(0x29, 32))], + [(ExprId("PSW", 32), ExprInt(0b1111, 32)), # PSW_UMC = 1 & PSW_IEC = 1 + (ExprId("PC", 32), ExprInt(0x28, 32))]) + + def test_swi(self): + """Test SWI execution""" + + # SWI + exec_instruction("SWI 0", + [(ExprId("EXC", 32), ExprInt(0xF0000001, 32))], + [(ExprId("EXC", 32), ExprInt(0xF0000001 + (1 << 4), 32))]) + + exec_instruction("SWI 1", + [(ExprId("EXC", 32), ExprInt(0xF0000001, 32))], + [(ExprId("EXC", 32), ExprInt(0xF0000001 + (1 << 5), 32))]) + + def test_halt(self): + """Test HALT execution""" + + # HALT + exec_instruction("HALT", [], []) + + def test_sleep(self): + """Test SLEEP execution""" + + # SLEEP + exec_instruction("SLEEP", [], []) + + def test_break(self): + """Test BREAK execution""" + + # BREAK + exec_instruction("BREAK", [], []) + + def test_syncm(self): + """Test SYNCM execution""" + + # SYNCM + exec_instruction("SYNCM", [], []) + + def test_stcb(self): + """Test STCB execution""" + + # STCB Rn,abs16 + exec_instruction("STCB R0, 0x0", [], []) + + def test_ldcb(self): + """Test LDCB execution""" + + # LDCB Rn,abs16 + exec_instruction("LDCB R0, 0x0", [], []) diff --git a/test/arch/mep/ir/test_coprocessor.py b/test/arch/mep/ir/test_coprocessor.py new file mode 100644 index 00000000..e9b745ff --- /dev/null +++ b/test/arch/mep/ir/test_coprocessor.py @@ -0,0 +1,109 @@ +# Toshiba MeP-c4 - Coprocessor instructions unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_ir import exec_instruction + +from miasm2.expression.expression import ExprId, ExprMem, ExprInt + + +class TestCoprocessor: + + def test_swcp(self): + """Test SWCP execution""" + + # SWCP CRn,(Rm) + exec_instruction("SWCP C1, (R2)", + [(ExprId("C1", 32), ExprInt(0x28071010, 32)), + (ExprId("R2", 32), ExprInt(0x11, 32))], + [(ExprMem(ExprInt(0x10, 32), 32), ExprInt(0x28071010, 32))]) + + # SWCP CRn,disp16(Rm) + exec_instruction("SWCP C10, 0xF800(R2)", + [(ExprId("C10", 32), ExprInt(0xABC7, 32)), + (ExprId("R2", 32), ExprInt(0x11, 32))], + [(ExprMem(ExprInt(0xFFFFF810, 32), 32), ExprInt(0xABC7, 32))]) + + def test_lwcp(self): + """Test LWCP execution""" + + # LWCP CRn[0-15],(Rm) + exec_instruction("LWCP C1, (R2)", + [(ExprId("R2", 32), ExprInt(0x11, 32)), + (ExprMem(ExprInt(0x10, 32), 32), ExprInt(0xABCD, 32))], + [(ExprId("C1", 32), ExprInt(0xABCD, 32))]) + + # LWCP CRn[0-15],disp16(Rm) + exec_instruction("LWCP C9, 0xF000(R2)", + [(ExprId("R2", 32), ExprInt(0x42, 32)), + (ExprMem(ExprInt(0xFFFFF040, 32), 32), ExprInt(0x10, 32))], + [(ExprId("C9", 32), ExprInt(0x10, 32))]) + + def test_smcp(self): + """Test SMCP execution""" + + # SMCP CRn,(Rm) + exec_instruction("SMCP C1, (R2)", + [(ExprId("C1", 32), ExprInt(0x28071010, 32)), + (ExprId("R2", 32), ExprInt(0x17, 32))], + [(ExprMem(ExprInt(0x10, 32), 32), ExprInt(0x28071010, 32))]) + + # SMCP CRn,disp16(Rm) + exec_instruction("SMCP C10, 0xF800(R2)", + [(ExprId("C10", 32), ExprInt(0xABC7, 32)), + (ExprId("R2", 32), ExprInt(0x17, 32))], + [(ExprMem(ExprInt(0xFFFFF810, 32), 32), ExprInt(0xABC7, 32))]) + + def test_lmcp(self): + """Test LMCP execution""" + + # LMCP CRn[0-15],(Rm) + exec_instruction("LMCP C1, (R2)", + [(ExprId("R2", 32), ExprInt(0x10, 32)), + (ExprMem(ExprInt(0x10, 32), 32), ExprInt(0xABCD, 32))], + [(ExprId("C1", 32), ExprInt(0xABCD, 32))]) + + # LMCP CRn[0-15],disp16(Rm) + exec_instruction("LMCP C9, 0xF000(R2)", + [(ExprId("R2", 32), ExprInt(0x17, 32)), + (ExprMem(ExprInt(0xFFFFF010, 32), 32), ExprInt(0x10, 32))], + [(ExprId("C9", 32), ExprInt(0x10, 32))]) + + def test_swcpi(self): + """Test SWCPI execution""" + + # SWCPI CRn[0-15],(Rm+) + exec_instruction("SWCPI C1, (R2+)", + [(ExprId("C1", 32), ExprInt(0x28071010, 32)), + (ExprId("R2", 32), ExprInt(0x11, 32))], + [(ExprMem(ExprInt(0x10, 32), 32), ExprInt(0x28071010, 32)), + (ExprId("R2", 32), ExprInt(0x15, 32))]) + + def test_lwcpi(self): + """Test LWCPI execution""" + + # LWCPI CRn[0-15],(Rm+) + exec_instruction("LWCPI C1, (R2+)", + [(ExprId("R2", 32), ExprInt(0x11, 32)), + (ExprMem(ExprInt(0x10, 32), 32), ExprInt(0xABCD, 32))], + [(ExprId("C1", 32), ExprInt(0xABCD, 32)), + (ExprId("R2", 32), ExprInt(0x15, 32))]) + + def test_smcpi(self): + """Test SMCPI execution""" + + # SMCPI CRn[0-15],(Rm+) + exec_instruction("SMCPI C1, (R2+)", + [(ExprId("C1", 32), ExprInt(0x28071010, 32)), + (ExprId("R2", 32), ExprInt(0x17, 32))], + [(ExprMem(ExprInt(0x10, 32), 32), ExprInt(0x28071010, 32)), + (ExprId("R2", 32), ExprInt(0x1F, 32))]) + + def test_lmcpi(self): + """Test LMCPI execution""" + + # LMCPI CRn[0-15],(Rm+) + exec_instruction("LMCPI C1, (R2+)", + [(ExprId("R2", 32), ExprInt(0x11, 32)), + (ExprMem(ExprInt(0x10, 32), 32), ExprInt(0xABCD, 32))], + [(ExprId("C1", 32), ExprInt(0xABCD, 32)), + (ExprId("R2", 32), ExprInt(0x19, 32))]) diff --git a/test/arch/mep/ir/test_datacache.py b/test/arch/mep/ir/test_datacache.py new file mode 100644 index 00000000..a462315d --- /dev/null +++ b/test/arch/mep/ir/test_datacache.py @@ -0,0 +1,13 @@ +# Toshiba MeP-c4 - Data cache instructions unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_ir import exec_instruction + + +class TestDataCache: + + def test_cache(self): + """Test CACHE execution""" + + # CACHE imm4, (Rm) + exec_instruction("CACHE 0x0, (R0)", [], []) diff --git a/test/arch/mep/ir/test_debug.py b/test/arch/mep/ir/test_debug.py new file mode 100644 index 00000000..53f4064d --- /dev/null +++ b/test/arch/mep/ir/test_debug.py @@ -0,0 +1,33 @@ +# Toshiba MeP-c4 - Debug instructions unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_ir import exec_instruction + +from miasm2.expression.expression import ExprId, ExprInt, ExprCond, ExprOp + + +class TestDebug: + + def test_dret(self): + """Test DRET execution""" + + # DRET + exec_instruction("DRET", + [(ExprId("DEPC", 32), ExprInt(2, 32)), + (ExprId("DBG", 32), ExprInt(0xFFFFFFFF, 32))], + [(ExprId("PC", 32), ExprInt(2, 32)), + (ExprId("DBG", 32), ExprInt(0xFFFFBFFF, 32))]) + + exec_instruction("DRET", + [(ExprId("DEPC", 32), ExprInt(2, 32)), + (ExprId("DBG", 32), ExprInt(2**15, 32))], + [(ExprId("PC", 32), ExprInt(2, 32)), + (ExprId("DBG", 32), ExprInt(2**15, 32))]) + + def test_dbreak(self): + """Test DBREAK execution""" + + # DBREAK + exec_instruction("DBREAK", + [(ExprId("DBG", 32), ExprInt(0, 32))], + [(ExprId("DBG", 32), ExprInt(0b10, 32))]) diff --git a/test/arch/mep/ir/test_divide.py b/test/arch/mep/ir/test_divide.py new file mode 100644 index 00000000..04d5f6c5 --- /dev/null +++ b/test/arch/mep/ir/test_divide.py @@ -0,0 +1,99 @@ +# Toshiba MeP-c4 - Divide instructions unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_ir import exec_instruction + +from miasm2.expression.expression import ExprId, ExprInt, ExprCond, ExprOp +from miasm2.jitter.csts import EXCEPT_DIV_BY_ZERO + + +class TestDivide: + + def test_div(self): + """Test DIV execution""" + + # DIV Rn,Rm + exec_instruction("DIV R0, R1", + [(ExprId("R0", 32), ExprInt(0x80, 32)), + (ExprId("R1", 32), ExprInt(0x0, 32)), + (ExprId("HI", 32), ExprInt(0, 32)), + (ExprId("LO", 32), ExprInt(0, 32))], + [(ExprId("HI", 32), ExprInt(0, 32)), + (ExprId("LO", 32), ExprInt(0, 32)), + (ExprId("exception_flags", 32), ExprInt(EXCEPT_DIV_BY_ZERO, 32))]) + + # Negative numbers + exec_instruction("DIV R0, R1", + [(ExprId("R0", 32), ExprInt(-4, 32)), + (ExprId("R1", 32), ExprInt(-2, 32))], + [(ExprId("HI", 32), ExprInt(0, 32)), + (ExprId("LO", 32), ExprInt(2, 32))]) + + exec_instruction("DIV R0, R1", + [(ExprId("R0", 32), ExprInt(-5, 32)), + (ExprId("R1", 32), ExprInt(-2, 32))], + [(ExprId("HI", 32), ExprInt(1, 32)), + (ExprId("LO", 32), ExprInt(2, 32))]) + + # Positive numbers + exec_instruction("DIV R0, R1", + [(ExprId("R0", 32), ExprInt(4, 32)), + (ExprId("R1", 32), ExprInt(2, 32))], + [(ExprId("HI", 32), ExprCond(ExprOp("==", + ExprInt(0, 32), + ExprInt(0x80000000, 32)), + ExprInt(0, 32), + ExprInt(0xFFFFFFFC, 32))), + (ExprId("LO", 32), ExprCond(ExprOp("==", + ExprInt(0, 32), + ExprInt(0x80000000, 32)), + ExprInt(2, 32), + ExprInt(0, 32)))]) + + # Negative & positive numbers + exec_instruction("DIV R0, R1", + [(ExprId("R0", 32), ExprInt(-5, 32)), + (ExprId("R1", 32), ExprInt(2, 32))], + [(ExprId("HI", 32), ExprCond(ExprOp("==", ExprInt(0, 32), ExprInt(0x80000000, 32)), + ExprInt(1, 32), ExprInt(0xFFFFFFFF, 32))), + (ExprId("LO", 32), ExprCond(ExprOp("==", ExprInt(0, 32), ExprInt(0x80000000, 32)), + ExprInt(0x7FFFFFFD, 32), ExprInt(0xFFFFFFFE, 32)))]) + + exec_instruction("DIV R0, R1", + [(ExprId("R0", 32), ExprInt(5, 32)), + (ExprId("R1", 32), ExprInt(-2, 32))], + [(ExprId("HI", 32), ExprCond(ExprOp("==", ExprInt(0, 32), ExprInt(0x80000000, 32)), + ExprInt(5, 32), ExprInt(0xFFFFFFFF, 32))), + (ExprId("LO", 32), ExprCond(ExprOp("==", ExprInt(0, 32), ExprInt(0x80000000, 32)), + ExprInt(0, 32), ExprInt(0xFFFFFFFE, 32)))]) + + def test_divu(self): + """Test DIVU execution""" + + # DIVU Rn,Rm + exec_instruction("DIVU R0, R1", + [(ExprId("R0", 32), ExprInt(0x80, 32)), + (ExprId("R1", 32), ExprInt(0x0, 32)), + (ExprId("HI", 32), ExprInt(0, 32)), + (ExprId("LO", 32), ExprInt(0, 32))], + [(ExprId("HI", 32), ExprInt(0, 32)), + (ExprId("LO", 32), ExprInt(0, 32)), + (ExprId("exception_flags", 32), ExprInt(EXCEPT_DIV_BY_ZERO, 32))]) + + exec_instruction("DIVU R0, R1", + [(ExprId("R0", 32), ExprInt(0x80, 32)), + (ExprId("R1", 32), ExprInt(0x2, 32))], + [(ExprId("HI", 32), ExprInt(0x0, 32)), + (ExprId("LO", 32), ExprInt(0x40, 32))]) + + exec_instruction("DIVU R0, R1", + [(ExprId("R0", 32), ExprInt(0x83, 32)), + (ExprId("R1", 32), ExprInt(0x2, 32))], + [(ExprId("HI", 32), ExprInt(0x1, 32)), + (ExprId("LO", 32), ExprInt(0x41, 32))]) + + exec_instruction("DIVU R0, R1", + [(ExprId("R0", 32), ExprInt(0x80000000, 32)), + (ExprId("R1", 32), ExprInt(-1, 32))], + [(ExprId("HI", 32), ExprInt(0x80000000, 32)), + (ExprId("LO", 32), ExprInt(0x0, 32))]) diff --git a/test/arch/mep/ir/test_extension.py b/test/arch/mep/ir/test_extension.py new file mode 100644 index 00000000..72423220 --- /dev/null +++ b/test/arch/mep/ir/test_extension.py @@ -0,0 +1,57 @@ +# Toshiba MeP-c4 - Byte/Halfword extension instructions unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_ir import exec_instruction + +from miasm2.expression.expression import ExprId, ExprMem, ExprInt + + +class TestExtension: + + def test_extb(self): + """Test EXTB execution""" + + # EXTB Rn + exec_instruction("EXTB R1", + [(ExprId("R1", 32), ExprInt(0xFE, 32))], + [(ExprId("R1", 32), ExprInt(0xFFFFFFFE, 32))]) + + exec_instruction("EXTB R2", + [(ExprId("R2", 32), ExprInt(0x80, 32))], + [(ExprId("R2", 32), ExprInt(0xFFFFFF80, 32))]) + + def test_exth(self): + """Test EXTH execution""" + + # EXTH Rn + exec_instruction("EXTH R1", + [(ExprId("R1", 32), ExprInt(0xFFFE, 32))], + [(ExprId("R1", 32), ExprInt(0xFFFFFFFE, 32))]) + + exec_instruction("EXTH R2", + [(ExprId("R2", 32), ExprInt(0x8000, 32))], + [(ExprId("R2", 32), ExprInt(0xFFFF8000, 32))]) + + def test_extub(self): + """Test EXTUB execution""" + + # EXTUB Rn + exec_instruction("EXTUB R1", + [(ExprId("R1", 32), ExprInt(0xFFFFFFFE, 32))], + [(ExprId("R1", 32), ExprInt(0xFE, 32))]) + + exec_instruction("EXTUB R2", + [(ExprId("R2", 32), ExprInt(0xFFFFFF80, 32))], + [(ExprId("R2", 32), ExprInt(0x80, 32))]) + + def test_extuh(self): + """Test EXTUH execution""" + + # EXTUH Rn + exec_instruction("EXTUH R1", + [(ExprId("R1", 32), ExprInt(0xFFFFFFFE, 32))], + [(ExprId("R1", 32), ExprInt(0xFFFE, 32))]) + + exec_instruction("EXTUH R2", + [(ExprId("R2", 32), ExprInt(0xFFFF8000, 32))], + [(ExprId("R2", 32), ExprInt(0x8000, 32))]) diff --git a/test/arch/mep/ir/test_ir.py b/test/arch/mep/ir/test_ir.py new file mode 100644 index 00000000..3fec9ec9 --- /dev/null +++ b/test/arch/mep/ir/test_ir.py @@ -0,0 +1,56 @@ +# Toshiba MeP-c4 - Misc unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from miasm2.arch.mep.arch import mn_mep +from miasm2.arch.mep.regs import regs_init +from miasm2.arch.mep.ira import ir_mepb, ir_a_mepb +from miasm2.expression.expression import ExprId, ExprInt, ExprMem +from miasm2.ir.symbexec import SymbolicExecutionEngine +from miasm2.core.locationdb import LocationDB + + +class TestMisc: + + def test(self): + + """Simple symbolic execution examples""" + + def exec_instruction(hex_asm, init_values): + """Symbolically execute an instruction""" + + print "Hex:", hex_asm + + # Disassemble an instruction + mn = mn_mep.dis(hex_asm.decode("hex"), "b") + print "Dis:", mn + + # Get the IR + im = ir_mepb() + iir, eiir, = im.get_ir(mn) + print "\nInternal representation:", iir + + # Symbolic execution + loc_db = LocationDB() + sb = SymbolicExecutionEngine(ir_a_mepb(loc_db), regs_init) + + # Assign register values before symbolic evaluation + for reg_expr_id, reg_expr_value in init_values: + sb.symbols[reg_expr_id] = reg_expr_value + + print "\nModified registers:", [reg for reg in sb.modified(mems=False)] + print "Modified memories:", [mem for mem in sb.modified()] + + print "\nFinal registers:" + sb.dump(mems=False) + + print "\nFinal mems:" + sb.dump() + + for hex_asm, init_values in [("6108", [(ExprId("R1", 32), ExprInt(0x40, 32))]), + ("08a2", [(ExprId("R8", 32), ExprInt(0x40, 32)), + (ExprId("R10", 32), ExprInt(0x41, 32))]), + ("0948", [(ExprId("R4", 32), ExprInt(0x41, 32)), + (ExprId("R9", 32), ExprInt(0x28, 32)), + (ExprMem(ExprInt(0x41, 32), 8), ExprInt(0, 8))])]: + print "-" * 49 # Tests separation + exec_instruction(hex_asm, init_values) diff --git a/test/arch/mep/ir/test_ldz.py b/test/arch/mep/ir/test_ldz.py new file mode 100644 index 00000000..02960b60 --- /dev/null +++ b/test/arch/mep/ir/test_ldz.py @@ -0,0 +1,41 @@ +# Toshiba MeP-c4 - Leading zero instructions unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_ir import exec_instruction + +from miasm2.expression.expression import ExprId, ExprInt, ExprCond, ExprOp + + +class TestLdz: + + def test_ldz(self): + """Test LDZ execution""" + + # LDZ Rn,Rm + exec_instruction("LDZ R0, R1", + [(ExprId("R1", 32), ExprInt(0x80000000, 32))], + [(ExprId("R0", 32), ExprInt(0, 32))]) + + exec_instruction("LDZ R0, R1", + [(ExprId("R1", 32), ExprInt(0x40000000, 32))], + [(ExprId("R0", 32), ExprInt(1, 32))]) + + exec_instruction("LDZ R0, R1", + [(ExprId("R1", 32), ExprInt(0b1111, 32))], + [(ExprId("R0", 32), ExprInt(28, 32))]) + + exec_instruction("LDZ R0, R1", + [(ExprId("R1", 32), ExprInt(0b0100, 32))], + [(ExprId("R0", 32), ExprInt(29, 32))]) + + exec_instruction("LDZ R0, R1", + [(ExprId("R1", 32), ExprInt(0b0010, 32))], + [(ExprId("R0", 32), ExprInt(30, 32))]) + + exec_instruction("LDZ R0, R1", + [(ExprId("R1", 32), ExprInt(0b0001, 32))], + [(ExprId("R0", 32), ExprInt(31, 32))]) + + exec_instruction("LDZ R0, R1", + [(ExprId("R1", 32), ExprInt(0b0000, 32))], + [(ExprId("R0", 32), ExprInt(32, 32))]) diff --git a/test/arch/mep/ir/test_loadstore.py b/test/arch/mep/ir/test_loadstore.py new file mode 100644 index 00000000..c6b40d55 --- /dev/null +++ b/test/arch/mep/ir/test_loadstore.py @@ -0,0 +1,209 @@ +# Toshiba MeP-c4 - Load/Store instructions unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_ir import exec_instruction + +from miasm2.expression.expression import ExprId, ExprMem, ExprInt + + +class TestLoadStore: + + def test_sb(self): + """Test SB execution""" + + # SB Rn,(Rm) + exec_instruction("SB R1, (R2)", + [(ExprId("R1", 32), ExprInt(0x28, 32)), + (ExprId("R2", 32), ExprInt(0x10, 32))], + [(ExprMem(ExprInt(0x10, 32), 8), ExprInt(0x28, 8))]) + + # SB Rn[0-7], disp7(TP) + exec_instruction("SB R1, 0x18(R2)", + [(ExprId("R1", 32), ExprInt(0xABC7, 32)), + (ExprId("R2", 32), ExprInt(0x10, 32))], + [(ExprMem(ExprInt(0x28, 32), 8), ExprInt(0xC7, 8))]) + + # SB Rn,disp16(Rm) + exec_instruction("SB R10, 0xF800(R2)", + [(ExprId("R10", 32), ExprInt(0xABC7, 32)), + (ExprId("R2", 32), ExprInt(0x10, 32))], + [(ExprMem(ExprInt(0xFFFFF810, 32), 8), ExprInt(0xC7, 8))]) + + def test_sh(self): + """Test SH execution""" + + # SH Rn,(Rm) + exec_instruction("SH R1, (R2)", + [(ExprId("R1", 32), ExprInt(0x2807, 32)), + (ExprId("R2", 32), ExprInt(0x10, 32))], + [(ExprMem(ExprInt(0x10, 32), 16), ExprInt(0x2807, 16))]) + + # SH Rn[0-7],disp7.align2(TP) + exec_instruction("SH R1, 0x18(R2)", + [(ExprId("R1", 32), ExprInt(0xABC7, 32)), + (ExprId("R2", 32), ExprInt(0x10, 32))], + [(ExprMem(ExprInt(0x28, 32), 16), ExprInt(0xABC7, 16))]) + + # SH Rn,disp16(Rm) + exec_instruction("SH R10, 0xF800(R2)", + [(ExprId("R10", 32), ExprInt(0xABC7, 32)), + (ExprId("R2", 32), ExprInt(0x10, 32))], + [(ExprMem(ExprInt(0xFFFFF810, 32), 16), ExprInt(0xABC7, 16))]) + + def test_sw(self): + """Test SW execution""" + + # SW Rn,(Rm) + exec_instruction("SW R1, (R2)", + [(ExprId("R1", 32), ExprInt(0x28071010, 32)), + (ExprId("R2", 32), ExprInt(0x10, 32))], + [(ExprMem(ExprInt(0x10, 32), 32), ExprInt(0x28071010, 32))]) + + # SW Rn,disp7.align4(SP) + exec_instruction("SW R1, 4(SP)", + [(ExprId("R1", 32), ExprInt(0x28071010, 32)), + (ExprId("SP", 32), ExprInt(0x10, 32))], + [(ExprMem(ExprInt(0x14, 32), 32), ExprInt(0x28071010, 32))]) + + # SW Rn,disp7.align4(TP) + exec_instruction("SW R1, 12(TP)", + [(ExprId("R1", 32), ExprInt(0x28071010, 32)), + (ExprId("TP", 32), ExprInt(0x10, 32))], + [(ExprMem(ExprInt(0x1c, 32), 32), ExprInt(0x28071010, 32))]) + + # SW Rn,disp16(Rm) + exec_instruction("SW R10, 0xF800(R2)", + [(ExprId("R10", 32), ExprInt(0xABC7, 32)), + (ExprId("R2", 32), ExprInt(0x10, 32))], + [(ExprMem(ExprInt(0xFFFFF810, 32), 32), ExprInt(0xABC7, 32))]) + + # SW Rn,(abs24.align4) + exec_instruction("SW R10, (0x1010)", + [(ExprId("R10", 32), ExprInt(0xABC7, 32))], + [(ExprMem(ExprInt(0x1010, 32), 32), ExprInt(0xABC7, 32))]) + + def test_lb(self): + """Test LB executon""" + + # LB Rn,(Rm) + exec_instruction("LB R1, (R2)", + [(ExprId("R2", 32), ExprInt(0x10, 32)), + (ExprMem(ExprInt(0x10, 32), 8), ExprInt(0xF0, 8))], + [(ExprId("R1", 32), ExprInt(0xFFFFFFF0, 32))]) + + # LB Rn[0-7],disp7(TP) + exec_instruction("LB R7, 0x3(TP)", + [(ExprId("TP", 32), ExprInt(0x10, 32)), + (ExprMem(ExprInt(0x13, 32), 8), ExprInt(0xF0, 8))], + [(ExprId("R7", 32), ExprInt(0xFFFFFFF0, 32))]) + + # LB Rn,disp16(Rm) + exec_instruction("LB R10, 0xF800(R2)", + [(ExprId("R2", 32), ExprInt(0x10, 32)), + (ExprMem(ExprInt(0xFFFFF810, 32), 8), ExprInt(0x4, 8))], + [(ExprId("R10", 32), ExprInt(0x4, 32))]) + + exec_instruction("LB R10, 0xF800(R2)", + [(ExprId("R2", 32), ExprInt(0x10, 32)), + (ExprMem(ExprInt(0xFFFFF810, 32), 8), ExprInt(0xFE, 8))], + [(ExprId("R10", 32), ExprInt(0xFFFFFFFE, 32))]) + + def test_lh(self): + """Test lh execution""" + + # LH Rn,(Rm) + exec_instruction("LH R1, (R2)", + [(ExprId("R2", 32), ExprInt(0x10, 32)), + (ExprMem(ExprInt(0x10, 32), 16), ExprInt(0xF517, 16))], + [(ExprId("R1", 32), ExprInt(0xFFFFF517, 32))]) + + # LH Rn[0-7],disp7.align2(TP) + exec_instruction("LH R1, 0x18(R2)", + [(ExprId("R2", 32), ExprInt(0x10, 32)), + (ExprMem(ExprInt(0x28, 32), 16), ExprInt(0xF517, 16))], + [(ExprId("R1", 32), ExprInt(0xFFFFF517, 32))]) + + # LH Rn,disp16(Rm) + exec_instruction("LH R9, 0xF000(R2)", + [(ExprId("R2", 32), ExprInt(0x42, 32)), + (ExprMem(ExprInt(0xFFFFF042, 32), 16), ExprInt(0x10, 16))], + [(ExprId("R9", 32), ExprInt(0x10, 32))]) + + exec_instruction("LH R9, 0xF000(R2)", + [(ExprId("R2", 32), ExprInt(0x42, 32)), + (ExprMem(ExprInt(0xFFFFF042, 32), 16), ExprInt(0xABCD, 16))], + [(ExprId("R9", 32), ExprInt(0xFFFFABCD, 32))]) + + def test_lw(self): + """Test SW execution""" + + # LW Rn,(Rm) + exec_instruction("LW R1, (R2)", + [(ExprId("R2", 32), ExprInt(0x10, 32)), + (ExprMem(ExprInt(0x10, 32), 32), ExprInt(0xABCD, 32))], + [(ExprId("R1", 32), ExprInt(0xABCD, 32))]) + + # LW Rn,disp7.align4(SP) + exec_instruction("LW R1, 0x18(SP)", + [(ExprId("SP", 32), ExprInt(0x10, 32)), + (ExprMem(ExprInt(0x28, 32), 32), ExprInt(0x01234567, 32))], + [(ExprId("R1", 32), ExprInt(0x01234567, 32))]) + + # LW Rn[0-7],disp7.align4(TP) + exec_instruction("LW R1, 0x18(TP)", + [(ExprId("TP", 32), ExprInt(0x10, 32)), + (ExprMem(ExprInt(0x28, 32), 32), ExprInt(0x1010, 32))], + [(ExprId("R1", 32), ExprInt(0x1010, 32))]) + + # LW Rn,disp16(Rm) + exec_instruction("LW R9, 0xF000(R2)", + [(ExprId("R2", 32), ExprInt(0x42, 32)), + (ExprMem(ExprInt(0xFFFFF040, 32), 32), ExprInt(0x10, 32))], + [(ExprId("R9", 32), ExprInt(0x10, 32))]) + + # LW Rn,(abs24.align4) + exec_instruction("LW R10, (0x1010)", + [(ExprMem(ExprInt(0x1010, 32), 32), ExprInt(0xABC7, 32))], + [(ExprId("R10", 32), ExprInt(0xABC7, 32))]) + + def test_lbu(self): + """Test LBU execution""" + + # LBU Rn,(Rm) + exec_instruction("LBU R1, (R2)", + [(ExprId("R2", 32), ExprInt(0x10, 32)), + (ExprMem(ExprInt(0x10, 32), 8), ExprInt(0xA, 8))], + [(ExprId("R1", 32), ExprInt(0xA, 32))]) + + # LBU Rn[0-7],disp7(TP) + exec_instruction("LBU R1, 0x22(R3)", + [(ExprId("R3", 32), ExprInt(0x10, 32)), + (ExprMem(ExprInt(0x32, 32), 8), ExprInt(0xA, 8))], + [(ExprId("R1", 32), ExprInt(0xA, 32))]) + + # LBU Rn,disp16(Rm) + exec_instruction("LBU R10, 0xF000(R2)", + [(ExprId("R2", 32), ExprInt(0x42, 32)), + (ExprMem(ExprInt(0xFFFFF042, 32), 32), ExprInt(0x10, 32))], + [(ExprId("R10", 32), ExprInt(0x10, 32))]) + + def test_lhu(self): + """Test LHU execution""" + + # LHU Rn,(Rm) + exec_instruction("LHU R1, (R2)", + [(ExprId("R2", 32), ExprInt(0x10, 32)), + (ExprMem(ExprInt(0x10, 32), 16), ExprInt(0xEF, 16))], + [(ExprId("R1", 32), ExprInt(0xEF, 32))]) + + # LHU Rn[0-7],disp7.align2(TP) + exec_instruction("LHU R1, 0x22(R3)", + [(ExprId("R3", 32), ExprInt(0x10, 32)), + (ExprMem(ExprInt(0x32, 32), 16), ExprInt(0xFEDC, 16))], + [(ExprId("R1", 32), ExprInt(0xFEDC, 32))]) + + # LHU Rn,disp16(Rm) + exec_instruction("LHU R10, 0xF000(R2)", + [(ExprId("R2", 32), ExprInt(0x42, 32)), + (ExprMem(ExprInt(0xFFFFF042, 32), 16), ExprInt(0x1234, 16))], + [(ExprId("R10", 32), ExprInt(0x1234, 32))]) diff --git a/test/arch/mep/ir/test_logical.py b/test/arch/mep/ir/test_logical.py new file mode 100644 index 00000000..61cbbf0a --- /dev/null +++ b/test/arch/mep/ir/test_logical.py @@ -0,0 +1,65 @@ +# Toshiba MeP-c4 - Logical instructions unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_ir import exec_instruction + +from miasm2.expression.expression import ExprId, ExprInt, ExprCond, ExprOp + + +class TestLogical: + + def test_or(self): + """Test OR execution""" + + # OR Rn, Rm + exec_instruction("OR R1, R2", + [(ExprId("R1", 32), ExprInt(1, 32)), (ExprId("R2", 32), ExprInt(1, 32))], + [(ExprId("R1", 32), ExprInt(1, 32))]) + + def test_or3(self): + """Test OR3 execution""" + + # OR3 Rn,Rm,imm16 + exec_instruction("OR3 R1, R2, 1", + [(ExprId("R2", 32), ExprInt(1, 32))], + [(ExprId("R1", 32), ExprInt(1, 32))]) + + def test_and(self): + """Test AND execution""" + + # AND Rn, Rm + exec_instruction("AND R1, R2", + [(ExprId("R1", 32), ExprInt(1, 32)), (ExprId("R2", 32), ExprInt(0, 32))], + [(ExprId("R1", 32), ExprInt(0, 32))]) + + def test_and3(self): + """Test AND3 execution""" + + # AND3 Rn,Rm,imm16 + exec_instruction("AND3 R1, R2, 0", + [(ExprId("R2", 32), ExprInt(1, 32))], + [(ExprId("R1", 32), ExprInt(0, 32))]) + + def test_xor(self): + """Test XOR execution""" + + # XOR Rn, Rm + exec_instruction("XOR R1, R2", + [(ExprId("R1", 32), ExprInt(1, 32)), (ExprId("R2", 32), ExprInt(0, 32))], + [(ExprId("R1", 32), ExprInt(1, 32))]) + + def test_xor3(self): + """Test XOR3 execution""" + + # XOR3 Rn,Rm,imm16 + exec_instruction("XOR3 R1, R2, 1", + [(ExprId("R2", 32), ExprInt(0, 32))], + [(ExprId("R1", 32), ExprInt(1, 32))]) + + def test_nor(self): + """Test NOR execution""" + + # NOR Rn, Rm + exec_instruction("NOR R1, R2", + [(ExprId("R1", 32), ExprInt(1, 32)), (ExprId("R2", 32), ExprInt(0, 32))], + [(ExprId("R1", 32), ExprInt(0xFFFFFFFE, 32))]) diff --git a/test/arch/mep/ir/test_move.py b/test/arch/mep/ir/test_move.py new file mode 100644 index 00000000..56a4225e --- /dev/null +++ b/test/arch/mep/ir/test_move.py @@ -0,0 +1,58 @@ +# Toshiba MeP-c4 - Move instructions unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_ir import exec_instruction + +from miasm2.expression.expression import ExprId, ExprMem, ExprInt + + +class TestMove: + + def test_mov(self): + """Test MOV execution""" + + # MOV Rn,Rm + exec_instruction("MOV R1, R2", + [(ExprId("R2", 32), ExprInt(0x2807, 32))], + [(ExprId("R1", 32), ExprInt(0x2807, 32))]) + + # MOV Rn,imm8 + exec_instruction("MOV R1, 0x28", + [], + [(ExprId("R1", 32), ExprInt(0x28, 32))]) + + exec_instruction("MOV R1, 0x80", + [], + [(ExprId("R1", 32), ExprInt(0xFFFFFF80, 32))]) + + # MOV Rn,imm16 + exec_instruction("MOV R1, 0x2807", + [], + [(ExprId("R1", 32), ExprInt(0x2807, 32))], + index=1) + + def test_movu(self): + """Test MOVU execution""" + + # MOVU Rn[0-7],imm24 + exec_instruction("MOVU R1, 0xFF2807", + [], + [(ExprId("R1", 32), ExprInt(0xFF2807, 32))], + index=1) + + # MOVU Rn,imm16 + exec_instruction("MOVU R10, 0x2807", + [], + [(ExprId("R10", 32), ExprInt(0x2807, 32))]) + + def test_movh(self): + """Test MOVH execution""" + + # MOVH Rn,imm16 + exec_instruction("MOVH R1, 1", + [], + [(ExprId("R1", 32), ExprInt(0x10000, 32))]) + + exec_instruction("MOVH R1, 0xFFFF", + [], + [(ExprId("R1", 32), ExprInt(0xFFFF0000, 32))]) diff --git a/test/arch/mep/ir/test_multiply.py b/test/arch/mep/ir/test_multiply.py new file mode 100644 index 00000000..0618f69f --- /dev/null +++ b/test/arch/mep/ir/test_multiply.py @@ -0,0 +1,138 @@ +# Toshiba MeP-c4 - Multiply instructions unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_ir import exec_instruction + +from miasm2.expression.expression import ExprId, ExprInt, ExprCond, ExprOp + + +class TestMultiply: + + def test_mul(self): + """Test MUL execution""" + + # MUL Rn,Rm + exec_instruction("MUL R0, R1", + [(ExprId("R0", 32), ExprInt(0x80, 32)), + (ExprId("R1", 32), ExprInt(0xFFFFFFFF, 32))], + [(ExprId("HI", 32), ExprInt(0xFFFFFFFF, 32)), + (ExprId("LO", 32), ExprInt(0xFFFFFF80, 32))]) + + exec_instruction("MUL R0, R1", + [(ExprId("R0", 32), ExprInt(0x80000000, 32)), + (ExprId("R1", 32), ExprInt(0xFFFFFFFF, 32))], + [(ExprId("HI", 32), ExprInt(0x00000000, 32)), + (ExprId("LO", 32), ExprInt(0x80000000, 32))]) + + def test_mulu(self): + """Test MULU execution""" + + # MULU Rn,Rm + exec_instruction("MULU R0, R1", + [(ExprId("R0", 32), ExprInt(0x2, 32)), + (ExprId("R1", 32), ExprInt(0xFFFFFFFF, 32))], + [(ExprId("HI", 32), ExprInt(0x1, 32)), + (ExprId("LO", 32), ExprInt(0xFFFFFFFE, 32))]) + + exec_instruction("MULU R0, R1", + [(ExprId("R0", 32), ExprInt(0x80000000, 32)), + (ExprId("R1", 32), ExprInt(0xFFFFFFFF, 32))], + [(ExprId("HI", 32), ExprInt(0x7FFFFFFF, 32)), + (ExprId("LO", 32), ExprInt(0x80000000, 32))]) + + def test_mulr(self): + """Test MULR execution""" + + # MULR Rn,Rm + exec_instruction("MULR R0, R1", + [(ExprId("R0", 32), ExprInt(0x80, 32)), + (ExprId("R1", 32), ExprInt(0xFFFFFFFF, 32))], + [(ExprId("HI", 32), ExprInt(0xFFFFFFFF, 32)), + (ExprId("LO", 32), ExprInt(0xFFFFFF80, 32)), + (ExprId("R0", 32), ExprInt(0xFFFFFF80, 32))]) + + def test_mulru(self): + """Test MULRU execution""" + + # MULRU Rn,Rm + exec_instruction("MULRU R0, R1", + [(ExprId("R0", 32), ExprInt(0x2, 32)), + (ExprId("R1", 32), ExprInt(0xFFFFFFFF, 32))], + [(ExprId("HI", 32), ExprInt(0x1, 32)), + (ExprId("LO", 32), ExprInt(0xFFFFFFFE, 32)), + (ExprId("R0", 32), ExprInt(0xFFFFFFFE, 32))]) + + def test_madd(self): + """Test MADD execution""" + + # MADD Rn,Rm + exec_instruction("MADD R0, R1", + [(ExprId("R0", 32), ExprInt(0x80, 32)), + (ExprId("R1", 32), ExprInt(0xFFFFFFFF, 32)), + (ExprId("HI", 32), ExprInt(0, 32)), + (ExprId("LO", 32), ExprInt(0, 32))], + [(ExprId("HI", 32), ExprInt(0xFFFFFFFF, 32)), + (ExprId("LO", 32), ExprInt(0xFFFFFF80, 32))]) + + exec_instruction("MADD R0, R1", + [(ExprId("R0", 32), ExprInt(0x80, 32)), + (ExprId("R1", 32), ExprInt(0xFFFFFFFF, 32)), + (ExprId("HI", 32), ExprInt(1, 32)), + (ExprId("LO", 32), ExprInt(1, 32))], + [(ExprId("HI", 32), ExprInt(0xFFFFFFFF, 32)), + (ExprId("LO", 32), ExprInt(0xFFFFFF81, 32))]) + + def test_maddu(self): + """Test MADDU execution""" + + # MADDU Rn,Rm + exec_instruction("MADDU R0, R1", + [(ExprId("R0", 32), ExprInt(0x2, 32)), + (ExprId("R1", 32), ExprInt(0xFFFFFFFF, 32)), + (ExprId("HI", 32), ExprInt(0, 32)), + (ExprId("LO", 32), ExprInt(0, 32))], + [(ExprId("HI", 32), ExprInt(0x1, 32)), + (ExprId("LO", 32), ExprInt(0xFFFFFFFE, 32))]) + + exec_instruction("MADDU R0, R1", + [(ExprId("R0", 32), ExprInt(0x2, 32)), + (ExprId("R1", 32), ExprInt(0xFFFFFFFF, 32)), + (ExprId("HI", 32), ExprInt(1, 32)), + (ExprId("LO", 32), ExprInt(1, 32))], + [(ExprId("HI", 32), ExprInt(0x1, 32)), + (ExprId("LO", 32), ExprInt(0xFFFFFFFF, 32))]) + + def test_maddr(self): + """Test MADDR execution""" + + # MADDR Rn,Rm + exec_instruction("MADDR R0, R1", + [(ExprId("R0", 32), ExprInt(0x80, 32)), + (ExprId("R1", 32), ExprInt(0xFFFFFFFF, 32)), + (ExprId("HI", 32), ExprInt(0, 32)), + (ExprId("LO", 32), ExprInt(0, 32))], + [(ExprId("HI", 32), ExprInt(0xFFFFFFFF, 32)), + (ExprId("LO", 32), ExprInt(0xFFFFFF80, 32)), + (ExprId("R0", 32), ExprInt(0xFFFFFF80, 32))]) + + exec_instruction("MADDR R0, R1", + [(ExprId("R0", 32), ExprInt(0x80, 32)), + (ExprId("R1", 32), ExprInt(0xFFFFFFFF, 32)), + (ExprId("HI", 32), ExprInt(1, 32)), + (ExprId("LO", 32), ExprInt(1, 32))], + [(ExprId("HI", 32), ExprInt(0xFFFFFFFF, 32)), + (ExprId("LO", 32), ExprInt(0xFFFFFF81, 32)), + (ExprId("R0", 32), ExprInt(0xFFFFFF81, 32))]) + + def test_maddru(self): + """Test MADDRU execution""" + + # MADDRU Rn,Rm + exec_instruction("MADDRU R0, R1", + [(ExprId("R0", 32), ExprInt(0x2, 32)), + (ExprId("R1", 32), ExprInt(0xFFFFFFFF, 32)), + (ExprId("HI", 32), ExprInt(0, 32)), + (ExprId("LO", 32), ExprInt(0, 32))], + [(ExprId("HI", 32), ExprInt(0x1, 32)), + (ExprId("LO", 32), ExprInt(0xFFFFFFFE, 32)), + (ExprId("R0", 32), ExprInt(0xFFFFFFFE, 32))]) diff --git a/test/arch/mep/ir/test_repeat.py b/test/arch/mep/ir/test_repeat.py new file mode 100644 index 00000000..252764b1 --- /dev/null +++ b/test/arch/mep/ir/test_repeat.py @@ -0,0 +1,29 @@ +# Toshiba MeP-c4 - Repeat instructions unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_ir import exec_instruction + +from miasm2.expression.expression import ExprId, ExprInt, ExprCond, ExprOp + + +class TestRepeat: + + def test_repeat(self): + """Test REPEAT execution""" + + # REPEAT Rn, disp17.align2 + exec_instruction("REPEAT R0, 0x42", + [(ExprId("PC", 32), ExprInt(2, 32)), + (ExprId("R0", 32), ExprInt(0x28, 32))], + [(ExprId("RPB", 32), ExprInt(6, 32)), + (ExprId("RPE", 32), ExprInt(0x44, 32)), + (ExprId("RPC", 32), ExprInt(0x28, 32))]) + + def test_erepeat(self): + """Test EREPEAT execution""" + + # EREPEAT disp17.align2 + exec_instruction("EREPEAT 0x42", + [(ExprId("PC", 32), ExprInt(0, 32))], + [(ExprId("RPB", 32), ExprInt(4, 32)), + (ExprId("RPE", 32), ExprInt(0x43, 32))]) diff --git a/test/arch/mep/ir/test_shift.py b/test/arch/mep/ir/test_shift.py new file mode 100644 index 00000000..b63f9ed7 --- /dev/null +++ b/test/arch/mep/ir/test_shift.py @@ -0,0 +1,108 @@ +# Toshiba MeP-c4 - Shift instructions unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_ir import exec_instruction + +from miasm2.expression.expression import ExprId, ExprInt, ExprCond, ExprOp +from miasm2.core.cpu import sign_ext + + +class TestShift: + + def test_sra(self): + """Test SRA execution""" + + # SRA Rn, Rm + exec_instruction("SRA R1, R2", + [(ExprId("R1", 32), ExprInt(4, 32)), (ExprId("R2", 32), ExprInt(1, 32))], + [(ExprId("R1", 32), ExprInt(2, 32))]) + + exec_instruction("SRA R1, R2", + [(ExprId("R1", 32), ExprInt(sign_ext(4, 3, 32), 32)), (ExprId("R2", 32), ExprInt(1, 32))], + [(ExprId("R1", 32), ExprInt(0xFFFFFFFE, 32))]) + + exec_instruction("SRA R1, R2", + [(ExprId("R1", 32), ExprInt(0xF0000000, 32)), (ExprId("R2", 32), ExprInt(4, 32))], + [(ExprId("R1", 32), ExprInt(0xFF000000, 32))]) + + # SRA Rn,imm5 + exec_instruction("SRA R1, 1", + [(ExprId("R1", 32), ExprInt(4, 32))], + [(ExprId("R1", 32), ExprInt(2, 32))]) + + # SRA Rn,imm5 + exec_instruction("SRA R1, 1", + [(ExprId("R1", 32), ExprInt(0x80000000, 32))], + [(ExprId("R1", 32), ExprInt(0xC0000000, 32))]) + + exec_instruction("SRA R1, 1", + [(ExprId("R1", 32), ExprInt(1, 32))], + [(ExprId("R1", 32), ExprInt(0, 32))]) + + def test_srl(self): + """Test SRL execution""" + + # SRL Rn, Rm + exec_instruction("SRL R1, R2", + [(ExprId("R1", 32), ExprInt(4, 32)), (ExprId("R2", 32), ExprInt(1, 32))], + [(ExprId("R1", 32), ExprInt(2, 32))]) + + # SRL Rn,imm5 + exec_instruction("SRL R1, 1", + [(ExprId("R1", 32), ExprInt(4, 32))], + [(ExprId("R1", 32), ExprInt(2, 32))]) + + exec_instruction("SRL R1, 1", + [(ExprId("R1", 32), ExprInt(1, 32))], + [(ExprId("R1", 32), ExprInt(0, 32))]) + + def test_sll(self): + """Test SLL execution""" + + # SLL Rn, Rm + exec_instruction("SLL R1, R2", + [(ExprId("R1", 32), ExprInt(4, 32)), (ExprId("R2", 32), ExprInt(1, 32))], + [(ExprId("R1", 32), ExprInt(8, 32))]) + + exec_instruction("SLL R1, R2", + [(ExprId("R1", 32), ExprInt(0x80000000, 32)), (ExprId("R2", 32), ExprInt(1, 32))], + [(ExprId("R1", 32), ExprInt(0, 32))]) + + # SLL Rn,imm5 + exec_instruction("SLL R1, 1", + [(ExprId("R1", 32), ExprInt(4, 32))], + [(ExprId("R1", 32), ExprInt(8, 32))]) + + def test_sll3(self): + """Test SLL3 execution""" + + # SLL3 R0,Rn,imm5 + exec_instruction("SLL3 R0, R1, 2", + [(ExprId("R1", 32), ExprInt(4, 32))], + [(ExprId("R0", 32), ExprInt(16, 32))]) + + exec_instruction("SLL3 R0, R1, 2", + [(ExprId("R1", 32), ExprInt(0xC0000000, 32))], + [(ExprId("R0", 32), ExprInt(0, 32))]) + + def test_fsft(self): + """Test FSFT execution""" + + # FSFT Rn,Rm + exec_instruction("FSFT R0, R1", + [(ExprId("SAR", 32), ExprInt(0x00000001, 32)), + (ExprId("R0", 32), ExprInt(0x00000001, 32)), + (ExprId("R1", 32), ExprInt(0x80000000, 32))], + [(ExprId("R0", 32), ExprInt(0x00000003, 32))]) + + exec_instruction("FSFT R0, R1", + [(ExprId("SAR", 32), ExprInt(0x00000004, 32)), + (ExprId("R0", 32), ExprInt(0xFFFFFFFF, 32)), + (ExprId("R1", 32), ExprInt(0xF0000000, 32))], + [(ExprId("R0", 32), ExprInt(0xFFFFFFFF, 32))]) + + exec_instruction("FSFT R0, R1", + [(ExprId("SAR", 32), ExprInt(0x00000004, 32)), + (ExprId("R0", 32), ExprInt(0xF0000000, 32)), + (ExprId("R1", 32), ExprInt(0x0F000000, 32))], + [(ExprId("R0", 32), ExprInt(0, 32))]) diff --git a/test/arch/mep/ir/ut_helpers_ir.py b/test/arch/mep/ir/ut_helpers_ir.py new file mode 100644 index 00000000..fcf31764 --- /dev/null +++ b/test/arch/mep/ir/ut_helpers_ir.py @@ -0,0 +1,87 @@ +# Toshiba MeP-c4 - unit tests helpers +# Guillaume Valadon <guillaume@valadon.net> + +from miasm2.arch.mep.arch import mn_mep +from miasm2.arch.mep.sem import ir_mepb +from miasm2.arch.mep.regs import regs_init + +from miasm2.ir.symbexec import SymbolicExecutionEngine +from miasm2.core.locationdb import LocationDB +from miasm2.core.utils import Disasm_Exception +from miasm2.ir.ir import AssignBlock +from miasm2.arch.mep.ira import ir_a_mepb +from miasm2.expression.expression import ExprId, ExprInt, ExprOp, ExprMem, ExprAff, ExprLoc + + +def exec_instruction(mn_str, init_values, results, index=0, offset=0): + """Symbolically execute an instruction and check the expected results.""" + + # Assemble and disassemble the instruction + instr = mn_mep.fromstring(mn_str, "b") + instr.mode = "b" + mn_bin = mn_mep.asm(instr)[index] + try: + instr = mn_mep.dis(mn_bin, "b") + except Disasm_Exception: + assert(False) # miasm don't know what to do + + # Specify the instruction offset and compute the destination label + instr.offset = offset + loc_db = LocationDB() + if instr.dstflow(): + instr.dstflow2label(loc_db) + + # Get the IR + im = ir_mepb(loc_db) + iir, eiir = im.get_ir(instr) + + # Filter out IRDst + iir = [ir for ir in iir if not (isinstance(ir, ExprAff) and + isinstance(ir.dst, ExprId) and + ir.dst.name == "IRDst")] + + # Prepare symbolic execution + sb = SymbolicExecutionEngine(ir_a_mepb(loc_db), regs_init) + + # Assign int values before symbolic evaluation + for expr_id, expr_value in init_values: + sb.symbols[expr_id] = expr_value + + # Execute the IR + ab = AssignBlock(iir) + sb.eval_updt_assignblk(ab) + + # Check if expected expr_id were modified + matched_results = 0 + for expr_id, expr_value in results: + + result = sb.eval_expr(expr_id) + if isinstance(result, ExprLoc): + addr = loc_db.get_location_offset(result.loc_key) + if expr_value.arg == addr: + matched_results += 1 + continue + elif result == expr_value: + matched_results += 1 + continue + + # Ensure that all expected results were verified + if len(results) is not matched_results: + print "Expected:", results + print "Modified:", [r for r in sb.modified(mems=False)] + assert(False) + + +def launch_tests(obj): + """Call test methods by name""" + + test_methods = [name for name in dir(obj) if name.startswith("test")] + + for method in test_methods: + print method + try: + getattr(obj, method)() + except AttributeError as e: + print "Method not found: %s" % method + assert(False) + print '-' * 42 diff --git a/test/arch/mep/jit/launch.py b/test/arch/mep/jit/launch.py new file mode 100644 index 00000000..8c67e072 --- /dev/null +++ b/test/arch/mep/jit/launch.py @@ -0,0 +1,7 @@ +# Toshiba MeP-c4 - pytest unit tests wrapper +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_jit import launch_tests + +from test_jit_branchjump import TestBranchJump; launch_tests(TestBranchJump()) +from test_jit_repeat import TestRepeat; launch_tests(TestRepeat()) diff --git a/test/arch/mep/jit/test_jit_branchjump.py b/test/arch/mep/jit/test_jit_branchjump.py new file mode 100644 index 00000000..baf602d8 --- /dev/null +++ b/test/arch/mep/jit/test_jit_branchjump.py @@ -0,0 +1,23 @@ +# Toshiba MeP-c4 - Branch/Jump instructions JIT unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_jit import jit_instructions + + +class TestBranchJump: + + def test_blti(self): + """Test BLTI jit""" + + # Instructions that will be jitted + instructions = "MOV R0, 1\n" + instructions += "BLTI R0, 0x2, 0x6\n" + instructions += "MOV R0, 0\n" + instructions += "MOV R1, 1" + + # Jit + jitter = jit_instructions(instructions) + + # Check expected results + assert(jitter.cpu.R0 == 1) + assert(jitter.cpu.R1 == 1) diff --git a/test/arch/mep/jit/test_jit_repeat.py b/test/arch/mep/jit/test_jit_repeat.py new file mode 100644 index 00000000..9fa64fa5 --- /dev/null +++ b/test/arch/mep/jit/test_jit_repeat.py @@ -0,0 +1,99 @@ +# Toshiba MeP-c4 - *REPEAT instructions JIT unit tests +# Guillaume Valadon <guillaume@valadon.net> + +from ut_helpers_jit import jit_instructions + + +class TestRepeat: + def test_repeat(self): + """Test REPEAT jit""" + + # Instructions that will be jitted + instructions = "MOV R0, 8\n" + instructions += "REPEAT R0, 0x6\n" + instructions += "ADD R1, 1\n" + instructions += "ADD R2, 1\n" # <-RPE + instructions += "ADD R3, 1" + + # Jit + jitter = jit_instructions(instructions) + + # Check expected results + assert(jitter.cpu.R0 == 8) + assert(jitter.cpu.R1 == 8) + assert(jitter.cpu.R2 == 8) + assert(jitter.cpu.R3 == 8) + + def test_erepeat_0(self): + """Test EREPEAT jit""" + + # Instructions that will be jitted + instructions = "EREPEAT 0xA\n" + instructions += "ADD R1, 1\n" + instructions += "BEQI R1, 0x6, 0x8\n" + instructions += "ADD R2, 1\n" + instructions += "ADD R3, 1" # <- RPE + + # Jit + jitter = jit_instructions(instructions) + + # Check expected results + assert(jitter.cpu.R1 == 6) + assert(jitter.cpu.R2 == 5) + assert(jitter.cpu.R3 == 5) + + def test_erepeat_1(self): + """Test EREPEAT jit""" + + # Instructions that will be jitted + instructions = "EREPEAT 0x8\n" + instructions += "ADD R1, 1\n" + instructions += "ADD R2, 1\n" + instructions += "ADD R3, 1\n" + instructions += "BEQI R1, 0x6, 0x4\n" # <- RPE + instructions += "ADD R2, 1\n" + instructions += "ADD R3, 1" + + # Jit + jitter = jit_instructions(instructions) + + # Check expected results + assert(jitter.cpu.R1 == 6) + assert(jitter.cpu.R2 == 7) + assert(jitter.cpu.R3 == 7) + + def test_erepeat_2(self): + """Test EREPEAT jit""" + + # Instructions that will be jitted + instructions = "EREPEAT 0x8\n" + instructions += "ADD R1, 1\n" + instructions += "ADD R2, 1\n" + instructions += "ADD R3, 1\n" # <- RPE + instructions += "BEQI R3, 0x6, 0x4" + + # Jit + jitter = jit_instructions(instructions) + + # Check expected results + assert(jitter.cpu.R1 == 6) + assert(jitter.cpu.R2 == 6) + assert(jitter.cpu.R3 == 6) + + def test_erepeat_3(self): + """Test EREPEAT jit""" + + # Instructions that will be jitted + instructions = "EREPEAT 0x8\n" + instructions += "ADD R1, 1\n" + instructions += "ADD R2, 1\n" + instructions += "BEQI R1, 0x6, 0x6\n" # <- RPE + instructions += "ADD R3, 1" + + # Jit + jitter = jit_instructions(instructions) + + # Check expected results + assert(jitter.cpu.R1 == 6) + assert(jitter.cpu.R2 == 6) + assert(jitter.cpu.R3 == 5) diff --git a/test/arch/mep/jit/ut_helpers_jit.py b/test/arch/mep/jit/ut_helpers_jit.py new file mode 100644 index 00000000..590c534f --- /dev/null +++ b/test/arch/mep/jit/ut_helpers_jit.py @@ -0,0 +1,49 @@ +# Toshiba MeP-c4 - unit tests helpers +# Guillaume Valadon <guillaume@valadon.net> + +from miasm2.analysis.machine import Machine +from miasm2.jitter.csts import PAGE_READ, PAGE_WRITE + + +def jit_instructions(mn_str): + """JIT instructions and return the jitter object.""" + + # Get the miasm2 Machine + machine = Machine("mepb") + mn_mep = machine.mn() + + # Assemble the instructions + asm = "" + for instr_str in mn_str.split("\n"): + instr = mn_mep.fromstring(instr_str, "b") + instr.mode = "b" + asm += mn_mep.asm(instr)[0] + + # Init the jitter and add the assembled instructions to memory + jitter = machine.jitter(jit_type="gcc") + jitter.vm.add_memory_page(0, PAGE_READ | PAGE_WRITE, asm) + + # Set the breakpoint + jitter.add_breakpoint(len(asm), lambda x: False) + + # Jit the instructions + #jitter.init_stack() + jitter.init_run(0) + jitter.continue_run() + + return jitter + + +def launch_tests(obj): + """Call test methods by name""" + + test_methods = [name for name in dir(obj) if name.startswith("test")] + + for method in test_methods: + print method + try: + getattr(obj, method)() + except AttributeError as e: + print "Method not found: %s" % method + assert(False) + print '-' * 42 diff --git a/test/test_all.py b/test/test_all.py index 665fc3a5..07210f01 100755 --- a/test/test_all.py +++ b/test/test_all.py @@ -724,6 +724,11 @@ testset += ExampleJitter(["example_types.py"]) testset += ExampleJitter(["trace.py", Example.get_sample("md5_arm"), "-a", "0xA684"]) +## Toshiba MeP +testset = TestSet("../") +testset += RegressionTest(["launch.py"], base_dir="arch/mep/asm") +testset += RegressionTest(["launch.py"], base_dir="arch/mep/ir") +testset += RegressionTest(["launch.py"], base_dir="arch/mep/jit") if __name__ == "__main__": # Argument parsing |