├── .gitignore ├── README.md ├── anal.py ├── asm.py ├── ba2r2.py ├── bin.py ├── bitstring.py ├── isa ├── __init__.py ├── decorators.py ├── exceptions.py ├── instructions.py └── types.py ├── test-disasm.py └── test-on-board.py /.gitignore: -------------------------------------------------------------------------------- 1 | .venv 2 | .vscode 3 | **/__pycache__/** 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pyba2: Python tools for Beyond Architecture 2 firmware analysis 2 | 3 | The project is intended for use with [radare2](https://www.radare.org/r/), but is structured in such a way that it should be useful in other Python-based environments (such as gdb). 4 | 5 | # Usage 6 | 7 | 1. Clone the project: `git clone https://github.com/alephsecurity/pyba2` 8 | 2. Change into its directory: `cd pyba2` 9 | 3. Make sure radare2 Python plugin is installed: `r2pm -i lang-python` 10 | 4. Run radare2 with `-I ba2r2.py`: `r2 -I ba2r2.py jn516x_ota_firmware_file.bin` 11 | 5. ... 12 | 6. Profit! 13 | 14 | # Requirements 15 | 16 | ## Python 3.6 17 | 18 | This project uses some modern features (e.g., f-strings) not available in prior Python versions. If using an older version of Python is a necessity, you're welcome to fork and change the project as needed. 19 | 20 | ## bitstring 21 | 22 | This isn't actually a requirement. Using virtual environments with radare2 plugins is tricky, so we just copied the module into our repository. However, they deserve the credit, so check [bitstring](https://pythonhosted.org/bitstring/index.html)! 23 | 24 | ## radare2 25 | 26 | To use the plugin with radare2, be sure to install the `lang-python` plugin first: `r2pm -i lang-python`. 27 | 28 | # Contributing 29 | 30 | The project is in development, and contributions are welcome! Go ahead and open issues (hopefully you don't find any :)), and use pull requests to improve the project! 31 | -------------------------------------------------------------------------------- /anal.py: -------------------------------------------------------------------------------- 1 | from r2lang import R 2 | from isa import instructions 3 | 4 | 5 | class BA2Analyzer: 6 | MIN_OP_SIZE = 2 7 | MAX_OP_SIZE = 6 8 | 9 | def __init__(self, a): 10 | if (a != 0): 11 | self._a = a 12 | print ("a", a) 13 | 14 | def archinfo(self, query): 15 | if query == 2: # R_ANAL_ARCHINFO_ALIGN 16 | return 0 17 | elif query == 1: # R_ANAL_ARCHINFO_MAX_OP_SIZE 18 | return self.MAX_OP_SIZE 19 | elif query == 0: # R_ANAL_ARCHINFO_MIN_OP_SIZE 20 | return self.MIN_OP_SIZE 21 | return 0 22 | 23 | def set_reg_profile(self): 24 | return """ 25 | =PC pc 26 | =SP r1 27 | =BP r2 28 | =A0 r0 29 | =A1 r1 30 | =A2 r2 31 | =A3 r3 32 | =A4 r4 33 | =A5 r5 34 | =A6 r6 35 | =A7 r7 36 | =A8 r8 37 | gpr r0 .32 0 0 38 | gpr r1 .32 4 0 39 | gpr r2 .32 8 0 40 | gpr r3 .32 12 0 41 | gpr r4 .32 16 0 42 | gpr r5 .32 20 0 43 | gpr r6 .32 24 0 44 | gpr r7 .32 28 0 45 | gpr r8 .32 32 0 46 | gpr r9 .32 36 0 47 | gpr r10 .32 40 0 48 | gpr r11 .32 44 0 49 | gpr r12 .32 48 0 50 | gpr r13 .32 52 0 51 | gpr r14 .32 56 0 52 | gpr r15 .32 60 0 53 | gpr r16 .32 64 0 54 | gpr r17 .32 68 0 55 | gpr r18 .32 72 0 56 | gpr r19 .32 76 0 57 | gpr r20 .32 80 0 58 | gpr r21 .32 84 0 59 | gpr r22 .32 88 0 60 | gpr r23 .32 92 0 61 | gpr r24 .32 96 0 62 | gpr r25 .32 100 0 63 | gpr r26 .32 104 0 64 | gpr r27 .32 108 0 65 | gpr r28 .32 112 0 66 | gpr r29 .32 116 0 67 | gpr r30 .32 120 0 68 | gpr r31 .32 124 0 69 | gpr sp .32 4 0 70 | gpr fp .32 8 0 71 | gpr lr .32 36 0 72 | gpr pc .32 128 0 73 | gpr fl .1 132 0 74 | gpr mac .64 136 0""" 75 | 76 | def op(self, memview, addr): 77 | op = { 78 | "type" : R.R_ANAL_OP_TYPE_NULL, 79 | "cycles" : 0, 80 | "stackop" : 0, 81 | "stackptr" : 0, 82 | "ptr" : -1, 83 | "jump" : -1, 84 | "addr" : addr, 85 | "eob" : False, 86 | "esil" : "", 87 | } 88 | 89 | try: 90 | insn, parsed_bytes = instructions.Instruction.lift(memview, addr) 91 | 92 | op['esil'] = insn.esil() 93 | 94 | if isinstance(insn, instructions.TrapInstruction): 95 | op['type'] = R.R_ANAL_OP_TYPE_TRAP 96 | 97 | elif isinstance(insn, instructions.ArithmeticInstruction): 98 | op['type'] = R.R_ANAL_OP_TYPE_ADD 99 | 100 | elif isinstance(insn, instructions.ShiftInstruction): 101 | op['type'] = R.R_ANAL_OP_TYPE_SHR 102 | 103 | elif isinstance(insn, instructions.CompareInstruction): 104 | op['type'] = R.R_ANAL_OP_TYPE_CMP 105 | 106 | elif isinstance(insn, instructions.BranchInstruction): 107 | op['type'] = R.R_ANAL_OP_TYPE_CJMP 108 | op['jump'] = insn.target_addr 109 | op['fail'] = insn.fail_addr 110 | 111 | elif isinstance(insn, instructions.JumpInstruction): 112 | if isinstance(insn, (instructions.BtJInstruction, 113 | instructions.BnJInstruction, 114 | instructions.BwJInstruction, 115 | instructions.BgJInstruction)): 116 | op['type'] = R.R_ANAL_OP_TYPE_JMP 117 | op['jump'] = insn.target_addr 118 | elif isinstance(insn, (instructions.BnJalInstruction, 119 | instructions.BwJalInstruction, 120 | instructions.BgJalInstruction)): 121 | op['type'] = R.R_ANAL_OP_TYPE_CALL 122 | op['jump'] = insn.target_addr 123 | elif isinstance(insn, instructions.BnJrInstruction): 124 | op['type'] = R.R_ANAL_OP_TYPE_IJMP 125 | elif isinstance(insn, instructions.BnJalrInstruction): 126 | op['type'] = R.R_ANAL_OP_TYPE_ICALL 127 | if insn.target_register == 9: # lr, Link Register 128 | op['type'] = R.R_ANAL_OP_TYPE_RET 129 | 130 | elif isinstance(insn, instructions.LoadInstruction): 131 | op['type'] = R.R_ANAL_OP_TYPE_LOAD 132 | if isinstance(insn, instructions.BnRetiInstruction): 133 | op['type'] = R.R_ANAL_OP_TYPE_POP 134 | op['stackop'] = R.R_ANAL_STACK_INC 135 | 136 | elif isinstance(insn, instructions.StoreInstruction): 137 | op['type'] = R.R_ANAL_OP_TYPE_STORE 138 | if isinstance(insn, instructions.BnEntriInstruction): 139 | op['type'] = R.R_ANAL_OP_TYPE_PUSH 140 | op['stackop'] = R.R_ANAL_STACK_INC 141 | 142 | elif isinstance(insn, instructions.MoveInstruction): 143 | op['type'] = R.R_ANAL_OP_TYPE_MOV 144 | 145 | elif isinstance(insn, instructions.NopInstruction): 146 | op['type'] = R.R_ANAL_OP_TYPE_NOP 147 | 148 | elif isinstance(insn, instructions.MacInstruction): 149 | op['type'] = R.R_ANAL_OP_TYPE_UNK 150 | 151 | elif isinstance(insn, instructions.FloatInstruction): 152 | op['type'] = R.R_ANAL_OP_TYPE_AND 153 | 154 | return [parsed_bytes, op] 155 | except KeyError as ke: 156 | # It's usually just a matter of unaligned block... 157 | pass 158 | except Exception as e: 159 | import traceback 160 | traceback.print_exc() 161 | 162 | return [0, op] 163 | 164 | def ba2anal(a): 165 | analyzer = BA2Analyzer(a) 166 | 167 | return { 168 | "name": "ba2", 169 | "arch": "ba2", 170 | "bits": 32, 171 | "esil": 1, 172 | "license": "BSD", 173 | "desc": "Beyond Architecture 2 analysis plugin", 174 | "set_reg_profile": analyzer.set_reg_profile, 175 | "op": analyzer.op, 176 | "archinfo": analyzer.archinfo, 177 | "esil": False, 178 | } 179 | -------------------------------------------------------------------------------- /asm.py: -------------------------------------------------------------------------------- 1 | import re 2 | from isa import instructions 3 | 4 | 5 | class BA2Assembler: 6 | def __init__(self, a=0): 7 | if (a != 0): 8 | self._a = a 9 | print ("a", a) 10 | 11 | def assemble(self, asm, addr): 12 | try: 13 | return instructions.Instruction.lower(asm, addr).encode() 14 | except Exception as e: 15 | import pdb 16 | pdb.set_trace() 17 | return [] 18 | 19 | def disassemble(self, memview, addr): 20 | try: 21 | insn, parsed_bytes = instructions.Instruction.lift(memview, addr) 22 | return [parsed_bytes, str(insn)] 23 | except Exception as e: 24 | import traceback 25 | print (e) 26 | traceback.print_exc() 27 | return [0, "invalid"] 28 | 29 | def ba2asm(a): 30 | assembler = BA2Assembler(a) 31 | 32 | return { 33 | "name": "ba2", 34 | "arch": "ba2", 35 | "bits": 32, 36 | "endian": 2, # R_SYS_ENDIAN_BIG 37 | "license": "BSD", 38 | "desc": "Beyond Architecture 2 (dis)assembly plugin", 39 | "assemble": assembler.assemble, 40 | "disassemble": assembler.disassemble, 41 | } 42 | -------------------------------------------------------------------------------- /ba2r2.py: -------------------------------------------------------------------------------- 1 | import r2lang 2 | 3 | from asm import ba2asm 4 | from anal import ba2anal 5 | from bin import jn5168bin 6 | 7 | 8 | r2lang.plugin("asm", ba2asm) 9 | r2lang.plugin("anal", ba2anal) 10 | r2lang.plugin("bin", jn5168bin) 11 | -------------------------------------------------------------------------------- /bin.py: -------------------------------------------------------------------------------- 1 | import struct 2 | from bitstring import ConstBitStream 3 | 4 | MAGIC = { 5 | bytes.fromhex('123456781122334455667788'): "jn516x", 6 | bytes.fromhex('123456782233445566778899'): "jn5178", 7 | } 8 | HEADER_SIZE = 0x38 9 | VERSION_SIZE = 0x4 10 | 11 | 12 | class FlashHeader: 13 | def __init__(self, binf): 14 | self._binf = binf 15 | if self._binf.buf[:0xc] in MAGIC: 16 | self._start = 0x0 17 | else: 18 | self._start = VERSION_SIZE 19 | 20 | @property 21 | def has_version(self): 22 | if self._binf.buf[:0xc] in MAGIC: 23 | return False 24 | else: 25 | return True 26 | 27 | def _slice(self, start, size=1): 28 | if self.has_version: 29 | start += 4 30 | 31 | return ConstBitStream(self._binf.buf[start:start + size].tobytes()) 32 | 33 | @property 34 | def version(self): 35 | if self._start: 36 | return self._slice(0, 4).uintbe 37 | else: 38 | return 0 39 | 40 | @property 41 | def magic(self): 42 | return self._slice(0, 12).bytes 43 | 44 | @property 45 | def config(self): 46 | return self._slice(0xc).uintbe 47 | 48 | @property 49 | def status(self): 50 | return self._slice(0xd).uintbe 51 | 52 | @property 53 | def app_id(self): 54 | return self._slice(0xe, 2).uintbe 55 | 56 | @property 57 | def encryption_init_vector(self): 58 | return self._slice(0x10, 4) 59 | 60 | @property 61 | def sw_conf(self): 62 | return self._slice(0xe, 2) 63 | 64 | @property 65 | def image_length(self): 66 | return self._slice(0x20, 4).uintbe 67 | 68 | @property 69 | def data_flash_start(self): 70 | return self._slice(0x24, 4).uintbe 71 | 72 | @property 73 | def data_load_address(self): 74 | return self._slice(0x28, 2).uintbe 75 | 76 | @property 77 | def data_length_in_words(self): 78 | return self._slice(0x2a, 2).uintbe 79 | 80 | @property 81 | def bss_start_address(self): 82 | return self._slice(0x2c, 2).uintbe 83 | 84 | @property 85 | def bss_length_in_words(self): 86 | return self._slice(0x2e, 2).uintbe 87 | 88 | @property 89 | def warm_start(self): 90 | return self._slice(0x30, 4).uintbe 91 | 92 | @property 93 | def cold_start(self): 94 | return self._slice(0x34, 4).uintbe 95 | 96 | class JennicLoader: 97 | RAM_BEGIN = 0x4000000 98 | 99 | def __init__(self, a): 100 | if (a != 0): 101 | self._a = a 102 | print ("a", a) 103 | 104 | def load_buffer(self, binf, buf, loadaddr): 105 | return [True] 106 | 107 | def baddr(self, binf): 108 | return [0x80000] 109 | 110 | def _check_bytes_versioned(self, buf): 111 | return len(buf) > (VERSION_SIZE + HEADER_SIZE) \ 112 | and buf[0x04:0x10] in MAGIC 113 | 114 | def _check_bytes_unversioned(self, buf): 115 | return len(buf) > (HEADER_SIZE) \ 116 | and buf[:0xc] in MAGIC 117 | 118 | def check_bytes(self, buf): 119 | return [self._check_bytes_versioned(buf) or self._check_bytes_unversioned(buf)] 120 | 121 | def sections(self, binf): 122 | fheader = FlashHeader(binf) 123 | offset = VERSION_SIZE if fheader.has_version else 0 124 | 125 | header = { 126 | "name": ".header", 127 | "size": HEADER_SIZE, 128 | "vsize": HEADER_SIZE, 129 | "paddr": offset, 130 | "vaddr": self.baddr(binf)[0], 131 | "perm": 4, # R_PERM_R 132 | "has_strings": False, 133 | "add": True, 134 | "is_data": True, 135 | } 136 | data = { 137 | "name": ".data", 138 | "size": HEADER_SIZE, 139 | "vsize": HEADER_SIZE, 140 | "paddr": offset + fheader.data_flash_start - self.baddr(binf)[0], 141 | "vaddr": self.RAM_BEGIN + 4 * fheader.data_load_address, 142 | "perm": 4|2, # R_PERM_R | R_PERM_W 143 | "has_strings": True, 144 | "add": True, 145 | "is_data": True, 146 | } 147 | text = { 148 | "name": ".text", 149 | "size": data['paddr'] - (offset + HEADER_SIZE), 150 | "vsize": data['paddr'] - (offset + HEADER_SIZE), 151 | "paddr": offset + HEADER_SIZE, 152 | "vaddr": self.baddr(binf)[0] + HEADER_SIZE, 153 | "perm": 4|1, # R_PERM_R | R_PERM_X 154 | "arch": "ba2", 155 | "bits": 32, 156 | "has_strings": False, 157 | "add": True, 158 | "is_data": False, 159 | } 160 | return [header, data, text] 161 | 162 | def entries(self, binf): 163 | return [ 164 | {"vaddr": FlashHeader(binf).cold_start}, 165 | {"vaddr": FlashHeader(binf).warm_start}, 166 | ] 167 | 168 | def info(self, binf): 169 | jntype = MAGIC[FlashHeader(binf).magic] 170 | return [{ 171 | "type" : jntype, 172 | #"bclass" : jntype, 173 | #"rclass" : jntype, 174 | "os" : "none", 175 | "subsystem" : "none", 176 | "machine" : jntype, 177 | "arch" : "ba2", 178 | "has_va" : 1, 179 | "bits" : 32, 180 | "big_endian" : 1, 181 | "dbg_info" : 0, 182 | }] 183 | 184 | def jn5168bin(a): 185 | loader = JennicLoader(a) 186 | 187 | return { 188 | "name": "jennic.fw", 189 | "desc": "JN516x/JN517x firmware loader plugin", 190 | "license": "BSD", 191 | "check_bytes": loader.check_bytes, 192 | "load_buffer": loader.load_buffer, 193 | "info": loader.info, 194 | "sections": loader.sections, 195 | "baddr": loader.baddr, 196 | "entries": loader.entries, 197 | } 198 | -------------------------------------------------------------------------------- /isa/__init__.py: -------------------------------------------------------------------------------- 1 | from .exceptions import InstructionMismatchException 2 | from .types import OperandType, InstructionType 3 | from .decorators import instruction 4 | -------------------------------------------------------------------------------- /isa/decorators.py: -------------------------------------------------------------------------------- 1 | from string import punctuation 2 | from bitstring import pack 3 | 4 | PunctuationToSpace = str.maketrans(punctuation, ' ' * len(punctuation)) 5 | 6 | 7 | class instruction: 8 | def __init__(self, mnemonic, op_args, encoding, esil="TODO"): 9 | self._mnemonic = mnemonic 10 | self._op_args_raw = op_args 11 | self._op_args = op_args.translate(PunctuationToSpace).split() 12 | self._encoding = pack('hex:4', encoding.split()[0]).bin + ''.join(encoding.split()[1:]) 13 | self._esil = esil 14 | 15 | def __call__(self, cls): 16 | cls.MNEMONIC = self._mnemonic 17 | cls.ARGS_RAW = self._op_args_raw 18 | cls.ARGS = self._op_args 19 | cls.ENCODING = self._encoding 20 | cls.ESIL = self._esil 21 | 22 | return cls 23 | -------------------------------------------------------------------------------- /isa/exceptions.py: -------------------------------------------------------------------------------- 1 | class InstructionMismatchException(Exception): 2 | pass 3 | -------------------------------------------------------------------------------- /isa/instructions.py: -------------------------------------------------------------------------------- 1 | from re import split 2 | from itertools import chain 3 | from bitstring import BitStream, ConstBitStream, CreationError 4 | 5 | from .exceptions import InstructionMismatchException 6 | from .types import OperandType, InstructionType, LetterCodes 7 | from .decorators import instruction 8 | 9 | 10 | class Instruction(object): 11 | MNEMONIC = "invalid" 12 | ARGS_RAW = "" 13 | ARGS = "" 14 | ENCODING = "" 15 | ESIL = "TODO" 16 | TYPE = InstructionType.UNKNOWN 17 | 18 | def __init__(self, operands, vma): 19 | self._operands = operands 20 | self._vma = vma 21 | 22 | @classmethod 23 | def parse(cls, bitstream, vma): 24 | data = {} 25 | 26 | for c, b in zip(cls.ENCODING, bitstream.bin): 27 | if c == '-': 28 | continue 29 | if c in '01': 30 | if b != c: 31 | raise InstructionMismatchException() 32 | continue 33 | if c not in data: 34 | data[c] = BitStream() 35 | data[c].append('bin:1=' + b) 36 | 37 | operands = {} 38 | 39 | for arg in cls.ARGS: 40 | letter = arg[-1] 41 | bits = data[letter] 42 | flags = LetterCodes[letter]['flags'] 43 | length = LetterCodes[letter]['length'] 44 | 45 | if flags & OperandType.LSB: 46 | bits.reverse() 47 | if flags & OperandType.DUNSIG: 48 | if bits.length % 8 != 0: 49 | bits.append(8 - (bits.length % 8)) 50 | 51 | if flags & OperandType.SIG: 52 | operands[letter] = bits.int 53 | else: 54 | operands[letter] = bits.uint 55 | 56 | return cls(operands, vma) 57 | 58 | @classmethod 59 | def assemble(cls, op_args, vma): 60 | op_args = split(r"[\(\),]+", op_args.lower()) 61 | if '' in op_args: 62 | op_args.remove('') 63 | operands = {} 64 | 65 | if len(set(op_args)) > len(cls.ARGS): 66 | raise InstructionMismatchException() 67 | 68 | for arg, val in zip(cls.ARGS, op_args): 69 | letter = arg[-1] 70 | flags = LetterCodes[letter]['flags'] 71 | length = LetterCodes[letter]['length'] 72 | 73 | if arg.startswith('r'): 74 | # Register expected 75 | if val.startswith('r'): 76 | # Register received 77 | val = int(val[1:]) 78 | 79 | if letter in operands and operands[letter] != val: 80 | raise InstructionMismatchException("These 2 registers should be the same!") 81 | 82 | operands[letter] = val 83 | else: 84 | # Immediate received 85 | raise ValueError("Register argument expected, got " + val) 86 | else: 87 | if val.startswith('r'): 88 | # Register received 89 | raise ValueError("Immediate argument expected, got " + val) 90 | else: 91 | # Immediate received 92 | negative = False 93 | 94 | if val.startswith('-'): 95 | negative = True 96 | val = val[1:] 97 | 98 | if val.startswith('0x'): 99 | operands[letter] = int(val[2:], base=16) 100 | elif val.endswith('h'): 101 | operands[letter] = int(val[:-1], base=16) 102 | elif val.startswith('0b'): 103 | operands[letter] = int(val[2:], base=2) 104 | else: 105 | operands[letter] = int(val, base=16) 106 | 107 | if negative: 108 | operands[letter] = -operands[letter] 109 | 110 | if flags & OperandType.REL: 111 | operands[letter] -= vma 112 | 113 | # Validate size 114 | prefix = "int" if flags & OperandType.SIG else "uint" 115 | if flags & OperandType.DUNSIG: 116 | BitStream(f"{prefix}:{8 * (length // 8 + 1)}={operands[letter]}") 117 | else: 118 | BitStream(f"{prefix}:{length}={operands[letter]}") 119 | 120 | return cls(operands, vma) 121 | 122 | @classmethod 123 | def lift(cls, buf, vma=0): 124 | stream = ConstBitStream(buf[:6].tobytes()) 125 | #stream = ConstBitStream(buf) 126 | 127 | group = stream.peek('uint:4') 128 | 129 | for insn_class in InstructionGroupLookup[group]: 130 | try: 131 | return [insn_class.parse(stream, vma), insn_class.size()] 132 | except InstructionMismatchException as ie: 133 | continue 134 | 135 | return [Instruction({}, vma), 0] 136 | 137 | @classmethod 138 | def lower(cls, asm, vma=0): 139 | parts = asm.split() 140 | mnemonic = parts[0].lower() 141 | op_args = "".join(parts[1:]) 142 | 143 | matching_instructions = [insn_class for insn_class in chain.from_iterable(InstructionGroupLookup.values()) if insn_class.MNEMONIC.split('.', 1)[-1] == mnemonic.split('.', 1)[-1]] 144 | matching_instructions.sort(key=lambda insn_class: len(insn_class.ENCODING)) 145 | 146 | for insn_class in matching_instructions: 147 | try: 148 | return insn_class.assemble(op_args, vma) 149 | except Exception as e: 150 | continue 151 | 152 | raise NotImplementedError("Not implemented instruction: " + mnemonic) 153 | 154 | @classmethod 155 | def size(cls): 156 | return int((len(cls.ENCODING) + 4) / 8) 157 | 158 | def esil(self): 159 | return self.ESIL.format(**self._operands) 160 | 161 | def encode(self): 162 | stream = BitStream() 163 | operands = {} 164 | 165 | for arg in self.ARGS: 166 | letter = arg[-1] 167 | flags = LetterCodes[letter]['flags'] 168 | length = LetterCodes[letter]['length'] 169 | prefix = "int" if flags & OperandType.SIG else "uint" 170 | extended = 8 * (length // 8 + 1) if length % 8 else length 171 | extra = extended - length 172 | rored = False 173 | 174 | try: 175 | operands[letter] = BitStream(f"{prefix}:{length}={self._operands[letter]}") 176 | except CreationError: 177 | operands[letter] = BitStream(f"{prefix}:{extended}={self._operands[letter]}") 178 | 179 | if flags & OperandType.LSB: 180 | if extra and operands[letter][-extra:].all(1) or operands[letter][-extra:].all(0): 181 | operands[letter] = operands[letter][:-extra] 182 | rored = True 183 | else: 184 | raise 185 | 186 | if flags & OperandType.LSB: 187 | if extra and flags & OperandType.DUNSIG and not rored: 188 | operands[letter] = operands[letter][:-extra] 189 | if operands[letter][0] and flags & OperandType.SIG: 190 | operands[letter].prepend('0b1' * extra) 191 | else: 192 | operands[letter].prepend('0b0' * extra) 193 | operands[letter].pos = 0 194 | operands[letter].reverse() 195 | 196 | try: 197 | for c in self.ENCODING: 198 | if c == '-': 199 | stream.append('bin:1=0') 200 | elif c in '01': 201 | stream.append('bin:1=' + c) 202 | else: 203 | stream.append('bin:1=' + operands[c].read('bin:1')) 204 | except Exception as e: 205 | import traceback 206 | traceback.print_exc() 207 | import pdb 208 | pdb.set_trace() 209 | 210 | return list(stream.bytes) 211 | 212 | def __str__(self): 213 | operands = self.ARGS_RAW 214 | table = {} 215 | 216 | for arg in self.ARGS: 217 | letter = arg[-1] 218 | if arg.startswith('r'): 219 | table[letter] = str(self._operands[letter]) 220 | else: 221 | value = self._operands[letter] 222 | 223 | if LetterCodes[letter]['flags'] & OperandType.REL: 224 | value += self._vma 225 | 226 | table[letter] = hex(value) 227 | 228 | return f"{self.MNEMONIC:11} {operands.translate(str.maketrans(table))}" 229 | 230 | ## Helpers 231 | 232 | class TrapInstruction(Instruction): 233 | TYPE = InstructionType.EXCEPTION 234 | 235 | class ArithmeticInstruction(Instruction): 236 | TYPE = InstructionType.ARITH 237 | 238 | class ShiftInstruction(Instruction): 239 | TYPE = InstructionType.SHIFT 240 | 241 | class CompareInstruction(Instruction): 242 | TYPE = InstructionType.COMPARE 243 | 244 | class LoadInstruction(Instruction): 245 | TYPE = InstructionType.LOAD 246 | 247 | class StoreInstruction(Instruction): 248 | TYPE = InstructionType.STORE 249 | 250 | class MoveInstruction(Instruction): 251 | TYPE = InstructionType.MOVE 252 | 253 | class ExtendInstruction(Instruction): 254 | TYPE = InstructionType.EXTEND 255 | 256 | class NopInstruction(Instruction): 257 | TYPE = InstructionType.NOP 258 | 259 | class MacInstruction(Instruction): 260 | TYPE = InstructionType.MAC 261 | 262 | class FloatInstruction(Instruction): 263 | TYPE = InstructionType.FLOAT 264 | 265 | class BranchInstruction(Instruction): 266 | TYPE = InstructionType.BRANCH 267 | 268 | @property 269 | def fail_addr(self): 270 | return self._vma + self.size() 271 | 272 | @property 273 | def target_addr(self): 274 | return self._vma + self._operands[self.ARGS[-1]] 275 | 276 | class JumpInstruction(Instruction): 277 | TYPE = InstructionType.JUMP 278 | 279 | @property 280 | def target_addr(self): 281 | return self._vma + self._operands[self.ARGS[-1]] 282 | 283 | @property 284 | def target_register(self): 285 | return self._operands[self.ARGS[-1][-1]] 286 | 287 | class BitwiseInstruction(ArithmeticInstruction): 288 | def __init__(self, operands, vma): 289 | if operands[self.ARGS[-1]] < 0: 290 | operands[self.ARGS[-1]] &= 0xffffffff 291 | super(BitwiseInstruction, self).__init__(operands, vma) 292 | 293 | ## Instructions 294 | 295 | @instruction("bt.movi", "rD,G", "0x0 00 DD DDD0 GGGG", "{G},r{D},=") 296 | class BtMoviInstruction(ArithmeticInstruction): 297 | def __init__(self, operands, vma): 298 | if operands['D'] == 0: 299 | raise InstructionMismatchException("This is bt.trap!") 300 | super().__init__(operands, vma) 301 | 302 | @instruction("bt.trap", "G", "0x0 0000 0000 GGGG") 303 | class BtTrapInstruction(TrapInstruction): 304 | pass 305 | 306 | @instruction("bt.addi", "rD,rD,G", "0x0 00 DD DDD1 GGGG", "{G},r{D},+,r{D},=") 307 | class BtAddiInstruction(ArithmeticInstruction): 308 | def __init__(self, operands, vma): 309 | if operands['D'] == 0: 310 | raise InstructionMismatchException("This is bt.nop!") 311 | super().__init__(operands, vma) 312 | 313 | @instruction("bt.nop", "G", "0x0 00 00 0001 GGGG") 314 | class BtNopInstruction(NopInstruction): 315 | pass 316 | 317 | @instruction("bt.mov", "rD,rA", "0x0 01 DD DDDA AAAA", "r{A},r{D},=") 318 | class BtMovInstruction(ArithmeticInstruction): 319 | def __init__(self, operands, vma): 320 | if operands['D'] == 0 and operands['A'] in (0, 1, 2, 3): 321 | raise InstructionMismatchException("This is bt.rfe/bt.ei/bt.di/bt.sys!") 322 | super().__init__(operands, vma) 323 | 324 | @instruction("bt.rfe", "", "0x0 01 00 0000 0000") 325 | class BtRfeInstruction(TrapInstruction): 326 | pass 327 | 328 | @instruction("bt.ei", "", "0x0 01 00 0000 0001") 329 | class BtEiInstruction(TrapInstruction): 330 | pass 331 | 332 | @instruction("bt.di", "", "0x0 01 00 0000 0010") 333 | class BtDiInstruction(TrapInstruction): 334 | pass 335 | 336 | @instruction("bt.sys", "", "0x0 01 00 0000 0011") 337 | class BtSysInstruction(TrapInstruction): 338 | pass 339 | 340 | @instruction("bt.add", "rD,rD,rA", "0x0 10 DD DDDA AAAA", "r{A},r{D},+,r{D},=") 341 | class BtAddInstruction(ArithmeticInstruction): 342 | pass 343 | 344 | @instruction("bt.j", "T", "0x0 11 TT TTTT TTTT", "2,{T},-,pc,+=") 345 | class BtJInstruction(JumpInstruction): 346 | pass 347 | 348 | @instruction("bn.sb", "N(rA),rB", "0x2 00 BB BBBA AAAA NNNN NNNN", "r{B},{N},r{A},+,=[1]") 349 | class BnSbInstruction(StoreInstruction): 350 | pass 351 | 352 | #TODO: zero extend 353 | @instruction("bn.lbz", "rD,N(rA)", "0x2 01 DD DDDA AAAA NNNN NNNN", "{N},r{A},+,[1],r{D},=") 354 | class BnLbzInstruction(LoadInstruction): 355 | pass 356 | 357 | @instruction("bn.sh", "M(rA),rB", "0x2 10 BB BBBA AAAA 0MMM MMMM", "r{B},{M},r{A},+,=[2]") 358 | class BnShInstruction(StoreInstruction): 359 | pass 360 | 361 | #TODO: zero extend 362 | @instruction("bn.lhz", "rD,M(rA)", "0x2 10 DD DDDA AAAA 1MMM MMMM", "{M},r{A},+,[2],r{D},=") 363 | class BnLhzInstruction(LoadInstruction): 364 | pass 365 | 366 | @instruction("bn.sw", "K(rA),rB", "0x2 11 BB BBBA AAAA 00KK KKKK", "r{B},{K},r{A},+,=[4]") 367 | class BnSwInstruction(StoreInstruction): 368 | pass 369 | 370 | #TODO: zero extend 371 | @instruction("bn.lwz", "rD,K(rA)", "0x2 11 DD DDDA AAAA 01KK KKKK", "{K},r{A},+,[4],r{D},=") 372 | class BnLwzInstruction(LoadInstruction): 373 | pass 374 | 375 | #TODO: sign extend 376 | @instruction("bn.lws", "rD,K(rA)", "0x2 11 DD DDDA AAAA 10KK KKKK", "{K},r{A},+,[4],r{D},=") 377 | class BnLwsInstruction(LoadInstruction): 378 | pass 379 | 380 | #TODO: Is this 64-bit? 381 | @instruction("bn.sd", "J(rA),rB", "0x2 11 BB BBBA AAAA 110J JJJJ") 382 | class BnSdInstruction(StoreInstruction): 383 | pass 384 | 385 | #TODO: Is this 64-bit? 386 | @instruction("bn.ld", "rD,J(rA)", "0x2 11 DD DDDA AAAA 111J JJJJ") 387 | class BnLdInstruction(LoadInstruction): 388 | pass 389 | 390 | @instruction("bn.addi", "rD,rA,O", "0x3 00 DD DDDA AAAA OOOO OOOO", "{O},r{A},+,r{D},=") 391 | class BnAddiInstruction(ArithmeticInstruction): 392 | pass 393 | 394 | @instruction("bn.andi", "rD,rA,N", "0x3 01 DD DDDA AAAA NNNN NNNN", "{N},r{A},&,r{D},=") 395 | class BnAndiInstruction(BitwiseInstruction): 396 | pass 397 | 398 | @instruction("bn.ori", "rD,rA,N", "0x3 10 DD DDDA AAAA NNNN NNNN", "{N},r{A},|,r{D},=") 399 | class BnOriInstruction(BitwiseInstruction): 400 | pass 401 | 402 | @instruction("bn.sfeqi", "rA,O", "0x3 11 00 000A AAAA OOOO OOOO", "0,fl,=,r{A},{O},==,$z,?{{,1,fl,}}") 403 | class BnSfeqiInstruction(CompareInstruction): 404 | pass 405 | 406 | @instruction("bn.sfnei", "rA,O", "0x3 11 00 001A AAAA OOOO OOOO", "0,fl,=,r{A},{O},==,$z,!,?{{,1,fl,}}") 407 | class BnSfneiInstruction(CompareInstruction): 408 | pass 409 | 410 | @instruction("bn.sfgesi", "rA,O", "0x3 11 00 010A AAAA OOOO OOOO", "0,fl,=,{O},r{A},>=,?{{,1,fl,}}") 411 | class BnSfgesiInstruction(CompareInstruction): 412 | pass 413 | 414 | #TODO: sign extend 415 | @instruction("bn.sfgeui", "rA,O", "0x3 11 00 011A AAAA OOOO OOOO", "0,fl,=,{O},r{A},>=,?{{,1,fl,}}") 416 | class BnSfgeuiInstruction(CompareInstruction): 417 | pass 418 | 419 | @instruction("bn.sfgtsi", "rA,O", "0x3 11 00 100A AAAA OOOO OOOO", "0,fl,=,{O},r{A},>,?{{,1,fl,}}") 420 | class BnSfgtsiInstruction(CompareInstruction): 421 | pass 422 | 423 | #TODO: sign extend 424 | @instruction("bn.sfgtui", "rA,O", "0x3 11 00 101A AAAA OOOO OOOO", "0,fl,=,{O},r{A},>,?{{,1,fl,}}") 425 | class BnSfgtuiInstruction(CompareInstruction): 426 | pass 427 | 428 | @instruction("bn.sflesi", "rA,O", "0x3 11 00 110A AAAA OOOO OOOO", "0,fl,=,{O},r{A},<=,?{{,1,fl,}}") 429 | class BnSflesiInstruction(CompareInstruction): 430 | pass 431 | 432 | #TODO: sign extend 433 | @instruction("bn.sfleui", "rA,O", "0x3 11 00 111A AAAA OOOO OOOO", "0,fl,=,{O},r{A},<=,?{{,1,fl,}}") 434 | class BnSfleuiInstruction(CompareInstruction): 435 | pass 436 | 437 | @instruction("bn.sfltsi", "rA,O", "0x3 11 01 000A AAAA OOOO OOOO", "0,fl,=,{O},r{A},<,?{{,1,fl,}}") 438 | class BnSfltsiInstruction(CompareInstruction): 439 | pass 440 | 441 | #TODO: sign extend 442 | @instruction("bn.sfltui", "rA,O", "0x3 11 01 001A AAAA OOOO OOOO", "0,fl,=,{O},r{A},<,?{{,1,fl,}}") 443 | class BnSfltuiInstruction(CompareInstruction): 444 | pass 445 | 446 | @instruction("bn.sfeq", "rA,rB", "0x3 11 01 010A AAAA BBBB B---", "0,fl,=,r{B},r{A},==,$z,?{{,1,fl,}}") 447 | class BnSfeqInstruction(CompareInstruction): 448 | pass 449 | 450 | @instruction("bn.sfne", "rA,rB", "0x3 11 01 011A AAAA BBBB B---", "0,fl,=,r{B},r{A},==,$z,!,?{{,1,fl,}}") 451 | class BnSfneInstruction(CompareInstruction): 452 | pass 453 | 454 | @instruction("bn.sfges", "rA,rB", "0x3 11 01 100A AAAA BBBB B---", "0,fl,=,r{B},r{A},>=,?{{,1,fl,}}") 455 | class BnSfgesInstruction(CompareInstruction): 456 | pass 457 | 458 | #TODO: sign extend 459 | @instruction("bn.sfgeu", "rA,rB", "0x3 11 01 101A AAAA BBBB B---", "0,fl,=,r{B},r{A},>=,?{{,1,fl,}}") 460 | class BnSfgeuInstruction(CompareInstruction): 461 | pass 462 | 463 | @instruction("bn.sfgts", "rA,rB", "0x3 11 01 110A AAAA BBBB B---", "0,fl,=,r{B},r{A},>,?{{,1,fl,}}") 464 | class BnSfgtsInstruction(CompareInstruction): 465 | pass 466 | 467 | #TODO: sign extend 468 | @instruction("bn.sfgtu", "rA,rB", "0x3 11 01 111A AAAA BBBB B---", "0,fl,=,r{B},r{A},>,?{{,1,fl,}}") 469 | class BnSfgtuInstruction(CompareInstruction): 470 | pass 471 | 472 | @instruction("bn.extbz", "rD,rA", "0x3 11 10 -00A AAAA DDDD D000", "0xff,r{A},&,r{D},=,") 473 | class BnExtbzInstruction(MoveInstruction): 474 | pass 475 | 476 | @instruction("bn.extbs", "rD,rA", "0x3 11 10 -00A AAAA DDDD D001", "0,r{D},=,r{A},0x80,&,0x80,==,?{{,0xffffff00,r{D},=,}},0xff,r{A},&,r{D},|=,") 477 | class BnExtbsInstruction(MoveInstruction): 478 | pass 479 | 480 | @instruction("bn.exthz", "rD,rA", "0x3 11 10 -00A AAAA DDDD D010", "0xffff,r{A},&,r{D},=,") 481 | class BnExthzInstruction(MoveInstruction): 482 | pass 483 | 484 | @instruction("bn.exths", "rD,rA", "0x3 11 10 -00A AAAA DDDD D011", "0,r{D},=,r{A},0x8000,&,0x8000,==,?{{,0xffff0000,r{D},=,}},0xffff,r{A},&,r{D},|=,") 485 | class BnExthsInstruction(MoveInstruction): 486 | pass 487 | 488 | #TODO: tricky, find index of first 1 bit, starting from LSB 489 | @instruction("bn.ff1", "rD,rA", "0x3 11 10 -00A AAAA DDDD D100") 490 | class BnFf1Instruction(ArithmeticInstruction): 491 | pass 492 | 493 | #TODO: count leading zeroes in rA, 0xffffffff if rA is 0 494 | @instruction("bn.clz", "rD,rA", "0x3 11 10 -00A AAAA DDDD D101") 495 | class BnClzInstruction(ArithmeticInstruction): 496 | pass 497 | 498 | #TODO: reverse bits of rA, store in rD 499 | @instruction("bn.bitrev", "rD,rA", "0x3 11 10 -00A AAAA DDDD D110") 500 | class BnBitrevInstruction(ArithmeticInstruction): 501 | pass 502 | 503 | #TODO: unknown 504 | @instruction("bn.swab", "rD,rA", "0x3 11 10 -00A AAAA DDDD D111") 505 | class BnSwabInstruction(ArithmeticInstruction): 506 | pass 507 | 508 | #TODO: tricky, ESIL doesn't support MSRs... 509 | @instruction("bn.mfspr", "rD,rA", "0x3 11 10 -01A AAAA DDDD D000") 510 | class BnMfsprInstruction(MoveInstruction): 511 | pass 512 | 513 | #TODO: tricky, ESIL doesn't support MSRs... 514 | @instruction("bn.mtspr", "rA,rB", "0x3 11 10 -01A AAAA BBBB B001") 515 | class BnMtsprInstruction(MoveInstruction): 516 | pass 517 | 518 | #TODO: rD <- least significant byte(rA) 519 | @instruction("bn.abs", "rD,rA", "0x3 11 10 -10A AAAA DDDD D000") 520 | class BnAbsInstruction(ArithmeticInstruction): 521 | pass 522 | 523 | #TODO: unknown... rD <- rA*rA? 524 | @instruction("bn.sqr", "rD,rA", "0x3 11 10 -10A AAAA DDDD D001") 525 | class BnSqrInstruction(ArithmeticInstruction): 526 | pass 527 | 528 | #TODO: unknown 529 | @instruction("bn.sqra", "rD,rA", "0x3 11 10 -10A AAAA DDDD D010") 530 | class BnSqraInstruction(ArithmeticInstruction): 531 | pass 532 | 533 | #TODO: unknown... some sort of jump? 534 | @instruction("bn.casei", "rA,N", "0x3 11 11 -00A AAAA NNNN NNNN") 535 | class BnCaseiInstruction(JumpInstruction): 536 | pass 537 | 538 | @instruction("bn.beqi", "rB,E,P", "0x4 00 00 EEEB BBBB PPPP PPPP", "{E},r{B},==,$z,?{{,3,{P},-,pc,+=,}}") 539 | class BnBeqiInstruction(BranchInstruction): 540 | pass 541 | 542 | @instruction("bn.bnei", "rB,E,P", "0x4 00 01 EEEB BBBB PPPP PPPP", "{E},r{B},==,$z,!,?{{,3,{P},-,pc,+=,}}") 543 | class BnBneiInstruction(BranchInstruction): 544 | pass 545 | 546 | @instruction("bn.bgesi", "rB,E,P", "0x4 00 10 EEEB BBBB PPPP PPPP", "{E},r{B},>=,?{{,3,{P},-,pc,+=,}}") 547 | class BnBgesiInstruction(BranchInstruction): 548 | pass 549 | 550 | @instruction("bn.bgtsi", "rB,E,P", "0x4 00 11 EEEB BBBB PPPP PPPP", "{E},r{B},>,?{{,3,{P},-,pc,+=,}}") 551 | class BnBgtsiInstruction(BranchInstruction): 552 | pass 553 | 554 | @instruction("bn.blesi", "rB,E,P", "0x4 01 00 EEEB BBBB PPPP PPPP", "{E},r{B},<=,?{{,3,{P},-,pc,+=,}}") 555 | class BnBlesiInstruction(BranchInstruction): 556 | pass 557 | 558 | @instruction("bn.bltsi", "rB,E,P", "0x4 01 01 EEEB BBBB PPPP PPPP", "{E},r{B},<,?{{,3,{P},-,pc,+=,}}") 559 | class BnBltsiInstruction(BranchInstruction): 560 | pass 561 | 562 | @instruction("bn.j", "Z", "0x4 01 10 ZZZZ ZZZZ ZZZZ ZZZZ", "{Z},pc,=") 563 | class BnJInstruction(JumpInstruction): 564 | pass 565 | 566 | @instruction("bn.bf", "S", "0x4 01 11 0010 SSSS SSSS SSSS", "fl,1,==,?{{,3,{S},-,pc,+=,}}") 567 | class BnBfInstruction(BranchInstruction): 568 | pass 569 | 570 | @instruction("bn.bnf", "S", "0x4 01 11 0011 SSSS SSSS SSSS", "fl,0,==,?{{,3,{S},-,pc,+=,}}") 571 | class BnBnfInstruction(BranchInstruction): 572 | pass 573 | 574 | @instruction("bn.bo", "S", "0x4 01 11 0100 SSSS SSSS SSSS", "$o,1,==,?{{,3,{S},-,pc,+=,}}") 575 | class BnBoInstruction(BranchInstruction): 576 | pass 577 | 578 | @instruction("bn.bno", "S", "0x4 01 11 0101 SSSS SSSS SSSS", "$o,0,==,?{{,3,{S},-,pc,+=,}}") 579 | class BnBnoInstruction(BranchInstruction): 580 | pass 581 | 582 | @instruction("bn.bc", "S", "0x4 01 11 0110 SSSS SSSS SSSS", "$c,1,==,?{{,3,{S},-,pc,+=,}}") 583 | class BnBcInstruction(BranchInstruction): 584 | pass 585 | 586 | @instruction("bn.bnc", "S", "0x4 01 11 0111 SSSS SSSS SSSS", "$c,0,==,?{{,3,{S},-,pc,+=,}}") 587 | class BnBncInstruction(BranchInstruction): 588 | pass 589 | 590 | #TODO: function prologue - frame construction 591 | # Push F GPRs (beginning with $lr/R9) onto the stack, then reduce the $sp/R1 by 592 | # an additional N 32-bit words. 593 | @instruction("bn.entri", "F,N", "0x4 01 11 1010 FFFF NNNN NNNN") 594 | class BnEntriInstruction(StoreInstruction): 595 | pass 596 | 597 | #TODO: function epilogue - frame deconstruction 598 | # Increase the $sp/R1 by N 32-bit words, then pop F GPRs (ending with $lr/R9) 599 | # Possibly returns, as well? (based on the fact that it's the final instruction of many functions) 600 | @instruction("bn.reti", "F,N", "0x4 01 11 1011 FFFF NNNN NNNN") 601 | class BnRetiInstruction(LoadInstruction): 602 | pass 603 | 604 | #TODO: unknown... function epilogue - stack ops 605 | @instruction("bn.rtnei", "F,N", "0x4 01 11 1100 FFFF NNNN NNNN") 606 | class BnRtneiInstruction(LoadInstruction): 607 | pass 608 | 609 | #TODO: unknown... same as 'jr lr'? 610 | @instruction("bn.return", "", "0x4 01 11 1101 --00 ---- ----") 611 | class BnReturnInstruction(JumpInstruction): 612 | pass 613 | 614 | @instruction("bn.jalr", "rA", "0x4 01 11 1101 --01 AAAA A---", "pc,lr,=,r{A},pc,=") 615 | class BnJalrInstruction(JumpInstruction): 616 | pass 617 | 618 | @instruction("bn.jr", "rA", "0x4 01 11 1101 --10 AAAA A---", "r{A},pc,=") 619 | class BnJrInstruction(JumpInstruction): 620 | pass 621 | 622 | @instruction("bn.jal", "s", "0x4 10 ss ssss ssss ssss ssss", "pc,lr,=,3,{s},-,pc,+=") 623 | class BnJalInstruction(JumpInstruction): 624 | pass 625 | 626 | #TODO: unknown 627 | @instruction("bn.mlwz", "rD,K(rA),C", "0x5 00 DD DDDA AAAA CCKK KKKK") 628 | class BnMlwzInstruction(LoadInstruction): 629 | pass 630 | 631 | #TODO: unknown 632 | @instruction("bn.msw", "K(rA),rB,C", "0x5 01 BB BBBA AAAA CCKK KKKK") 633 | class BnMswInstruction(StoreInstruction): 634 | pass 635 | 636 | #TODO: unknown 637 | @instruction("bn.mld", "rD,H(rA),C", "0x5 10 DD DDDA AAAA CC0H HHHH") 638 | class BnMldInstruction(LoadInstruction): 639 | pass 640 | 641 | #TODO: unknown 642 | @instruction("bn.msd", "H(rA),rB,C", "0x5 10 BB BBBA AAAA CC1H HHHH") 643 | class BnMsdInstruction(StoreInstruction): 644 | pass 645 | 646 | #TODO: unknown 647 | @instruction("bn.lwza", "rD,rA,L", "0x5 11 DD DDDA AAAA 1100 LLLL") 648 | class BnLwzaInstruction(LoadInstruction): 649 | pass 650 | 651 | #TODO: unknown 652 | @instruction("bn.swa", "rA,rB,L", "0x5 11 BB BBBA AAAA 1101 LLLL") 653 | class BnSwaInstruction(StoreInstruction): 654 | pass 655 | 656 | @instruction("bn.and", "rD,rA,rB", "0x6 00 DD DDDA AAAA BBBB B000", "r{B},r{A},&,r{D},=") 657 | class BnBitwiseInstruction(ArithmeticInstruction): 658 | pass 659 | 660 | @instruction("bn.or", "rD,rA,rB", "0x6 00 DD DDDA AAAA BBBB B001", "r{B},r{A},|,r{D},=") 661 | class BnOrInstruction(ArithmeticInstruction): 662 | pass 663 | 664 | @instruction("bn.xor", "rD,rA,rB", "0x6 00 DD DDDA AAAA BBBB B010", "r{B},r{A},^,r{D},=") 665 | class BnXorInstruction(ArithmeticInstruction): 666 | pass 667 | 668 | @instruction("bn.nand", "rD,rA,rB", "0x6 00 DD DDDA AAAA BBBB B011", "r{B},r{A},&,!,r{D},=") 669 | class BnNBitwiseInstruction(ArithmeticInstruction): 670 | pass 671 | 672 | #TODO: set carry/overflow 673 | @instruction("bn.add", "rD,rA,rB", "0x6 00 DD DDDA AAAA BBBB B100", "r{B},r{A},+,r{D},=") 674 | class BnAddInstruction(ArithmeticInstruction): 675 | pass 676 | 677 | #TODO: set carry/overflow 678 | @instruction("bn.sub", "rD,rA,rB", "0x6 00 DD DDDA AAAA BBBB B101", "r{B},r{A},-,r{D},=") 679 | class BnSubInstruction(ArithmeticInstruction): 680 | pass 681 | 682 | #TODO: should be logical 683 | @instruction("bn.sll", "rD,rA,rB", "0x6 00 DD DDDA AAAA BBBB B110", "r{B},r{A},<<,r{D},=") 684 | class BnSllInstruction(ShiftInstruction): 685 | pass 686 | 687 | #TODO: should be logical 688 | @instruction("bn.srl", "rD,rA,rB", "0x6 00 DD DDDA AAAA BBBB B111", "r{B},r{A},>>,r{D},=") 689 | class BnSrlInstruction(ShiftInstruction): 690 | pass 691 | 692 | #TODO: should be arithmetic 693 | @instruction("bn.sra", "rD,rA,rB", "0x6 01 DD DDDA AAAA BBBB B000", "r{B},r{A},>>,r{D},=") 694 | class BnSraInstruction(ShiftInstruction): 695 | pass 696 | 697 | @instruction("bn.ror", "rD,rA,rB", "0x6 01 DD DDDA AAAA BBBB B001", "r{B},r{A},>>>,r{D},=") 698 | class BnRorInstruction(ShiftInstruction): 699 | pass 700 | 701 | @instruction("bn.cmov", "rD,rA,rB", "0x6 01 DD DDDA AAAA BBBB B010", "r{B},r{D},=,fl,1,==,?{{,r{A},r{D},=,}}") 702 | class BnCmovInstruction(ArithmeticInstruction): 703 | pass 704 | 705 | #TODO: set overflow, treat as signed 706 | @instruction("bn.mul", "rD,rA,rB", "0x6 01 DD DDDA AAAA BBBB B011", "r{B},r{A},*,r{D},=") 707 | class BnMulInstruction(ArithmeticInstruction): 708 | pass 709 | 710 | #TODO: set overflow, treat as signed 711 | @instruction("bn.div", "rD,rA,rB", "0x6 01 DD DDDA AAAA BBBB B100", "r{B},r{A},/,r{D},=") 712 | class BnDivInstruction(ArithmeticInstruction): 713 | pass 714 | 715 | #TODO: set overflow, treat as unsigned 716 | @instruction("bn.divu", "rD,rA,rB", "0x6 01 DD DDDA AAAA BBBB B101", "r{B},r{A},/,r{D},=") 717 | class BnDivuInstruction(ArithmeticInstruction): 718 | pass 719 | 720 | @instruction("bn.mac", "rA,rB", "0x6 01 00 000A AAAA BBBB B110", "r{B},r{A},*,mac,+=") 721 | class BnMacInstruction(MacInstruction): 722 | pass 723 | 724 | #TODO: figure out signed/unsigned 725 | @instruction("bn.macs", "rA,rB", "0x6 01 00 001A AAAA BBBB B110", "r{B},r{A},*,mac,+=") 726 | class BnMacsInstruction(MacInstruction): 727 | pass 728 | 729 | #TODO: figure out signed/unsigned 730 | @instruction("bn.macsu", "rA,rB", "0x6 01 00 010A AAAA BBBB B110", "r{B},r{A},*,mac,+=") 731 | class BnMacsuInstruction(MacInstruction): 732 | pass 733 | 734 | #TODO: figure out signed/unsigned 735 | @instruction("bn.macuu", "rA,rB", "0x6 01 00 011A AAAA BBBB B110", "r{B},r{A},*,mac,+=") 736 | class BnMacuuInstruction(MacInstruction): 737 | pass 738 | 739 | #TODO: figure out signed/unsigned 740 | @instruction("bn.smactt", "rA,rB", "0x6 01 00 100A AAAA BBBB B110", "r{B},r{A},*,mac,+=") 741 | class BnSmacttInstruction(MacInstruction): 742 | pass 743 | 744 | #TODO: figure out signed/unsigned 745 | @instruction("bn.smacbb", "rA,rB", "0x6 01 00 101A AAAA BBBB B110", "r{B},r{A},*,mac,+=") 746 | class BnSmacbbInstruction(MacInstruction): 747 | pass 748 | 749 | #TODO: figure out signed/unsigned 750 | @instruction("bn.smactb", "rA,rB", "0x6 01 00 110A AAAA BBBB B110", "r{B},r{A},*,mac,+=") 751 | class BnSmactbInstruction(MacInstruction): 752 | pass 753 | 754 | #TODO: figure out signed/unsigned 755 | @instruction("bn.umactt", "rA,rB", "0x6 01 00 111A AAAA BBBB B110", "r{B},r{A},*,mac,+=") 756 | class BnUmacttInstruction(MacInstruction): 757 | pass 758 | 759 | #TODO: figure out signed/unsigned 760 | @instruction("bn.umacbb", "rA,rB", "0x6 01 01 000A AAAA BBBB B110", "r{B},r{A},*,mac,+=") 761 | class BnUmacbbInstruction(MacInstruction): 762 | pass 763 | 764 | #TODO: figure out signed/unsigned 765 | @instruction("bn.umactb", "rA,rB", "0x6 01 01 001A AAAA BBBB B110", "r{B},r{A},*,mac,+=") 766 | class BnUmactbInstruction(MacInstruction): 767 | pass 768 | 769 | #TODO: unknown 770 | @instruction("bn.msu", "rA,rB", "0x6 01 01 010A AAAA BBBB B110") 771 | class BnMsuInstruction(MacInstruction): 772 | pass 773 | 774 | #TODO: unknown 775 | @instruction("bn.msus", "rA,rB", "0x6 01 01 011A AAAA BBBB B110") 776 | class BnMsusInstruction(MacInstruction): 777 | pass 778 | 779 | #TODO: carry? 780 | @instruction("bn.addc", "rD,rA,rB", "0x6 01 DD DDDA AAAA BBBB B111", "$c,r{B}+,r{A},+,r{D},=") 781 | class BnAddcInstruction(ArithmeticInstruction): 782 | pass 783 | 784 | #TODO: borrow? 785 | @instruction("bn.subb", "rD,rA,rB", "0x6 10 DD DDDA AAAA BBBB B000", "$b,r{B}-,r{A},-,r{D},=") 786 | class BnSubbInstruction(ArithmeticInstruction): 787 | pass 788 | 789 | #TODO: unknown 790 | @instruction("bn.flb", "rD,rA,rB", "0x6 10 DD DDDA AAAA BBBB B001") 791 | class BnFlbInstruction(ArithmeticInstruction): 792 | pass 793 | 794 | #TODO: unknown - multiply half-words? 795 | @instruction("bn.mulhu", "rD,rA,rB", "0x6 10 DD DDDA AAAA BBBB B010") 796 | class BnMulhuInstruction(ArithmeticInstruction): 797 | pass 798 | 799 | #TODO: unknown - multiply half-words? 800 | @instruction("bn.mulh", "rD,rA,rB", "0x6 10 DD DDDA AAAA BBBB B011") 801 | class BnMulhInstruction(ArithmeticInstruction): 802 | pass 803 | 804 | #TODO: unknown - mod? 805 | @instruction("bn.mod", "rD,rA,rB", "0x6 10 DD DDDA AAAA BBBB B100") 806 | class BnModInstruction(ArithmeticInstruction): 807 | pass 808 | 809 | #TODO: unknown - mod unsigned? 810 | @instruction("bn.modu", "rD,rA,rB", "0x6 10 DD DDDA AAAA BBBB B101") 811 | class BnModuInstruction(ArithmeticInstruction): 812 | pass 813 | 814 | #TODO: unknown - add and what? 815 | @instruction("bn.aadd", "rD,rA,rB", "0x6 10 DD DDDA AAAA BBBB B110") 816 | class BnAaddInstruction(ArithmeticInstruction): 817 | pass 818 | 819 | #TODO: unknown - what's compared and what's exchanged? 820 | @instruction("bn.cmpxchg", "rD,rA,rB", "0x6 10 DD DDDA AAAA BBBB B111") 821 | class BnCmpxchgInstruction(ArithmeticInstruction): 822 | pass 823 | 824 | #TODO: should be logical 825 | @instruction("bn.slli", "rD,rA,H", "0x6 11 DD DDDA AAAA HHHH H-00", "{H},r{A},<<,r{D},=") 826 | class BnSlliInstruction(ShiftInstruction): 827 | pass 828 | 829 | #TODO: should be logical 830 | @instruction("bn.srli", "rD,rA,H", "0x6 11 DD DDDA AAAA HHHH H-01", "{H},r{A},>>,r{D},=") 831 | class BnSrliInstruction(ShiftInstruction): 832 | pass 833 | 834 | #TODO: should be arithmetic 835 | @instruction("bn.srai", "rD,rA,H", "0x6 11 DD DDDA AAAA HHHH H-10", "{H},r{A},>>,r{D},=") 836 | class BnSraiInstruction(ShiftInstruction): 837 | pass 838 | 839 | @instruction("bn.rori", "rD,rA,H", "0x6 11 DD DDDA AAAA HHHH H-11", "{H},r{A},>>>,r{D},=") 840 | class BnRoriInstruction(ShiftInstruction): 841 | pass 842 | 843 | #TODO: should be treated as floating point? 844 | @instruction("fn.add.s", "rD,rA,rB", "0x7 00 DD DDDA AAAA BBBB B000", "r{B},r{A},+,r{D},=") 845 | class FnAddSInstruction(FloatInstruction): 846 | pass 847 | 848 | #TODO: should be treated as floating point? 849 | @instruction("fn.sub.s", "rD,rA,rB", "0x7 00 DD DDDA AAAA BBBB B001", "r{B},r{A},-,r{D},=") 850 | class FnSubSInstruction(FloatInstruction): 851 | pass 852 | 853 | #TODO: should be treated as floating point? 854 | @instruction("fn.mul.s", "rD,rA,rB", "0x7 00 DD DDDA AAAA BBBB B010", "r{B},r{A},*,r{D},=") 855 | class FnMulSInstruction(FloatInstruction): 856 | pass 857 | 858 | #TODO: should be treated as floating point? 859 | @instruction("fn.div.s", "rD,rA,rB", "0x7 00 DD DDDA AAAA BBBB B011", "r{B},r{A},/,r{D},=") 860 | class FnDivSInstruction(FloatInstruction): 861 | pass 862 | 863 | #TODO: unknown - saturated? vectors? 864 | @instruction("bn.adds", "rD,rA,rB", "0x7 01 DD DDDA AAAA BBBB B000") 865 | class BnAddsInstruction(ArithmeticInstruction): 866 | pass 867 | 868 | #TODO: unknown - saturated? vectors? looks like signed subtraction... 869 | @instruction("bn.subs", "rD,rA,rB", "0x7 01 DD DDDA AAAA BBBB B001") 870 | class BnSubsInstruction(ArithmeticInstruction): 871 | def __init__ (self, operands, vma): 872 | if operands['A'] == 0: 873 | raise InstructionMismatchException("This is bn.neg!") 874 | super().__init__(operands, vma) 875 | 876 | @instruction("bn.neg", "rD,rB", "0x7 01 DD DDD0 0000 BBBB B001") 877 | class BnNegInstruction(ArithmeticInstruction): 878 | pass 879 | 880 | #TODO: unknown 881 | @instruction("bn.xaadd", "rD,rA,rB", "0x7 01 DD DDDA AAAA BBBB B010") 882 | class BnXaaddInstruction(ArithmeticInstruction): 883 | pass 884 | 885 | #TODO: unknown 886 | @instruction("bn.xcmpxchg","rD,rA,rB", "0x7 01 DD DDDA AAAA BBBB B011") 887 | class BnXcmpxchgInstruction(ArithmeticInstruction): 888 | pass 889 | 890 | #TODO: unknown - vectors? 891 | @instruction("bn.max", "rD,rA,rB", "0x7 01 DD DDDA AAAA BBBB B100") 892 | class BnMaxInstruction(ArithmeticInstruction): 893 | pass 894 | 895 | #TODO: unknown - vectors? 896 | @instruction("bn.min", "rD,rA,rB", "0x7 01 DD DDDA AAAA BBBB B101") 897 | class BnMinInstruction(ArithmeticInstruction): 898 | pass 899 | 900 | #TODO: unknown 901 | @instruction("bn.lim", "rD,rA,rB", "0x7 01 DD DDDA AAAA BBBB B110") 902 | class BnLimInstruction(ArithmeticInstruction): 903 | pass 904 | 905 | #TODO: should be logical; signed? 906 | @instruction("bn.slls", "rD,rA,rB", "0x7 10 DD DDDA AAAA BBBB B-00", "r{B},r{A},<<,r{D},=") 907 | class BnSllsInstruction(ShiftInstruction): 908 | pass 909 | 910 | #TODO: should be logical; signed? 911 | @instruction("bn.sllis", "rD,rA,H", "0x7 10 DD DDDA AAAA HHHH H-01", "{H},r{A},<<,r{D},=") 912 | class BnSllisInstruction(ShiftInstruction): 913 | pass 914 | 915 | #TODO: How to implement floating point in ESIL? 916 | @instruction("fn.ftoi.s", "rD,rA", "0x7 11 10 --0A AAAA DDDD D000") 917 | class FnFtoiSInstruction(FloatInstruction): 918 | pass 919 | 920 | #TODO: How to implement floating point in ESIL? 921 | @instruction("fn.itof.s", "rD,rA", "0x7 11 10 --0A AAAA DDDD D001") 922 | class FnItofSInstruction(FloatInstruction): 923 | pass 924 | 925 | @instruction("bw.sb", "h(rA),rB", "0x8 00 BB BBBA AAAA hhhh hhhh hhhh hhhh hhhh hhhh hhhh hhhh", "r{B},{h},r{A},+,=[1]") 926 | class BwSbInstruction(StoreInstruction): 927 | pass 928 | 929 | #TODO: zero extend 930 | @instruction("bw.lbz", "rD,h(rA)", "0x8 01 DD DDDA AAAA hhhh hhhh hhhh hhhh hhhh hhhh hhhh hhhh", "{h},r{A},+,[1],r{D},=") 931 | class BwLbzInstruction(LoadInstruction): 932 | pass 933 | 934 | @instruction("bw.sh", "i(rA),rB", "0x8 10 BB BBBA AAAA 0iii iiii iiii iiii iiii iiii iiii iiii", "r{B},{i},r{A},+,=[2]") 935 | class BwShInstruction(StoreInstruction): 936 | pass 937 | 938 | #TODO: zero extend 939 | @instruction("bw.lhz", "rD,i(rA)", "0x8 10 DD DDDA AAAA 1iii iiii iiii iiii iiii iiii iiii iiii", "{i},r{A},+,[2],r{D},=") 940 | class BwLhzInstruction(LoadInstruction): 941 | pass 942 | 943 | @instruction("bw.sw", "w(rA),rB", "0x8 11 BB BBBA AAAA 00ww wwww wwww wwww wwww wwww wwww wwww", "r{B},{w},r{A},+,=[4]") 944 | class BwSwInstruction(StoreInstruction): 945 | pass 946 | 947 | #TODO: zero extend 948 | @instruction("bw.lwz", "rD,w(rA)", "0x8 11 DD DDDA AAAA 01ww wwww wwww wwww wwww wwww wwww wwww", "{w},r{A},+,[4],r{D},=") 949 | class BwLwzInstruction(LoadInstruction): 950 | pass 951 | 952 | #TODO: sign extend 953 | @instruction("bw.lws", "rD,w(rA)", "0x8 11 DD DDDA AAAA 10ww wwww wwww wwww wwww wwww wwww wwww", "{w},r{A},+,[4],r{D},=") 954 | class BwLwsInstruction(LoadInstruction): 955 | pass 956 | 957 | #TODO: isn't this 64-bit? 958 | @instruction("bw.sd", "v(rA),rB", "0x8 11 BB BBBA AAAA 110v vvvv vvvv vvvv vvvv vvvv vvvv vvvv") 959 | class BwSdInstruction(StoreInstruction): 960 | pass 961 | 962 | #TODO: isn't this 64-bit? 963 | @instruction("bw.ld", "rD,v(rA)", "0x8 11 DD DDDA AAAA 111v vvvv vvvv vvvv vvvv vvvv vvvv vvvv") 964 | class BwLdInstruction(LoadInstruction): 965 | pass 966 | 967 | @instruction("bw.addi", "rD,rA,g", "0x9 00 DD DDDA AAAA gggg gggg gggg gggg gggg gggg gggg gggg", "{g},r{A},+,r{D},=") 968 | class BwAddiInstruction(ArithmeticInstruction): 969 | pass 970 | 971 | @instruction("bw.andi", "rD,rA,h", "0x9 01 DD DDDA AAAA hhhh hhhh hhhh hhhh hhhh hhhh hhhh hhhh", "{h},r{A},&,r{D},=") 972 | class BwAndiInstruction(BitwiseInstruction): 973 | def __init__(self, operands, vma): 974 | if operands['h'] == 0x7fffffff: 975 | raise InstructionMismatchException("This is f.abs.s!") 976 | super().__init__(operands, vma) 977 | 978 | @instruction("f.abs.s", "rD,rA", "0x9 01 DD DDDA AAAA 1111 1111 1111 1111 1111 1111 1111 1110", "0x7fffffff,r{A},&,r{D},=") 979 | class FAbsInstruction(ArithmeticInstruction): 980 | pass 981 | 982 | @instruction("bw.ori", "rD,rA,h", "0x9 10 DD DDDA AAAA hhhh hhhh hhhh hhhh hhhh hhhh hhhh hhhh", "{h},r{A},|,r{D},=") 983 | class BwOriInstruction(BitwiseInstruction): 984 | pass 985 | 986 | @instruction("bw.sfeqi", "rA,g", "0x9 11 01 10-A AAAA gggg gggg gggg gggg gggg gggg gggg gggg", "0,fl,=,r{A},{g},==,$z,?{{,1,fl,}}") 987 | class BwSfeqiInstruction(CompareInstruction): 988 | pass 989 | 990 | @instruction("bw.sfnei", "rA,g", "0x9 11 01 11-A AAAA gggg gggg gggg gggg gggg gggg gggg gggg", "0,fl,=,r{A},{g},==,$z,!,?{{,1,fl,}}") 991 | class BwSfneiInstruction(CompareInstruction): 992 | pass 993 | 994 | @instruction("bw.sfgesi", "rA,g", "0x9 11 10 00-A AAAA gggg gggg gggg gggg gggg gggg gggg gggg", "0,fl,=,{g},r{A},>=,?{{,1,fl,}}") 995 | class BwSfgesiInstruction(CompareInstruction): 996 | pass 997 | 998 | #TODO: sing extend 999 | @instruction("bw.sfgeui", "rA,g", "0x9 11 10 01-A AAAA gggg gggg gggg gggg gggg gggg gggg gggg", "0,fl,=,{g},r{A},>=,?{{,1,fl,}}") 1000 | class BwSfgeuiInstruction(CompareInstruction): 1001 | pass 1002 | 1003 | @instruction("bw.sfgtsi", "rA,g", "0x9 11 10 10-A AAAA gggg gggg gggg gggg gggg gggg gggg gggg", "0,fl,=,{g},r{A},>,?{{,1,fl,}}") 1004 | class BwSfgtsiInstruction(CompareInstruction): 1005 | pass 1006 | 1007 | #TODO: sign extend 1008 | @instruction("bw.sfgtui", "rA,g", "0x9 11 10 11-A AAAA gggg gggg gggg gggg gggg gggg gggg gggg", "0,fl,=,{g},r{A},>,?{{,1,fl,}}") 1009 | class BwSfgtuiInstruction(CompareInstruction): 1010 | pass 1011 | 1012 | @instruction("bw.sflesi", "rA,g", "0x9 11 11 00-A AAAA gggg gggg gggg gggg gggg gggg gggg gggg", "0,fl,=,{g},r{A},<=,?{{,1,fl,}}") 1013 | class BwSflesiInstruction(CompareInstruction): 1014 | pass 1015 | 1016 | #TODO: sign extend 1017 | @instruction("bw.sfleui", "rA,g", "0x9 11 11 01-A AAAA gggg gggg gggg gggg gggg gggg gggg gggg", "0,fl,=,{g},r{A},<=,?{{,1,fl,}}") 1018 | class BwSfleuiInstruction(CompareInstruction): 1019 | pass 1020 | 1021 | @instruction("bw.sfltsi", "rA,g", "0x9 11 11 10-A AAAA gggg gggg gggg gggg gggg gggg gggg gggg", "0,fl,=,{g},r{A},<,?{{,1,fl,}}") 1022 | class BwSfltsiInstruction(CompareInstruction): 1023 | pass 1024 | 1025 | #TODO: sign extend 1026 | @instruction("bw.sfltui", "rA,g", "0x9 11 11 11-A AAAA gggg gggg gggg gggg gggg gggg gggg gggg", "0,fl,=,{g},r{A},<,?{{,1,fl,}}") 1027 | class BwSfltuiInstruction(CompareInstruction): 1028 | pass 1029 | 1030 | @instruction("bw.beqi", "rB,I,u", "0xa 00 00 00II IIIB BBBB uuuu uuuu uuuu uuuu uuuu uuuu uuuu", "{I},r{B},==,$z,?{{,6,{u},-,pc,+=,}}") 1031 | class BwBeqiInstruction(BranchInstruction): 1032 | pass 1033 | 1034 | @instruction("bw.bnei", "rB,I,u", "0xa 00 00 01II IIIB BBBB uuuu uuuu uuuu uuuu uuuu uuuu uuuu", "{I},r{B},==,$z,!,?{{,6,{u},-,pc,+=,}}") 1035 | class BwBneiInstruction(BranchInstruction): 1036 | pass 1037 | 1038 | @instruction("bw.bgesi", "rB,I,u", "0xa 00 00 10II IIIB BBBB uuuu uuuu uuuu uuuu uuuu uuuu uuuu", "{I},r{B},>=,?{{,6,{u},-,pc,+=,}}") 1039 | class BwBgesiInstruction(BranchInstruction): 1040 | pass 1041 | 1042 | @instruction("bw.bgtsi", "rB,I,u", "0xa 00 00 11II IIIB BBBB uuuu uuuu uuuu uuuu uuuu uuuu uuuu", "{I},r{B},>,?{{,6,{u},-,pc,+=,}}") 1043 | class BwBgtsiInstruction(BranchInstruction): 1044 | pass 1045 | 1046 | @instruction("bw.blesi", "rB,I,u", "0xa 00 01 00II IIIB BBBB uuuu uuuu uuuu uuuu uuuu uuuu uuuu", "{I},r{B},<=,?{{,6,{u},-,pc,+=,}}") 1047 | class BwBlesiInstruction(BranchInstruction): 1048 | pass 1049 | 1050 | @instruction("bw.bltsi", "rB,I,u", "0xa 00 01 01II IIIB BBBB uuuu uuuu uuuu uuuu uuuu uuuu uuuu", "{I},r{B},<,?{{,6,{u},-,pc,+=,}}") 1051 | class BwBltsiInstruction(BranchInstruction): 1052 | pass 1053 | 1054 | #TODO: treat as unsigned 1055 | @instruction("bw.bgeui", "rB,I,u", "0xa 00 01 10II IIIB BBBB uuuu uuuu uuuu uuuu uuuu uuuu uuuu", "{I},r{B},>=,?{{,6,{u},-,pc,+=,}}") 1056 | class BwBgeuiInstruction(BranchInstruction): 1057 | pass 1058 | 1059 | #TODO: treat as unsigned 1060 | @instruction("bw.bgtui", "rB,I,u", "0xa 00 01 11II IIIB BBBB uuuu uuuu uuuu uuuu uuuu uuuu uuuu", "{I},r{B},>,?{{,6,{u},-,pc,+=,}}") 1061 | class BwBgtuiInstruction(BranchInstruction): 1062 | pass 1063 | 1064 | #TODO: treat as unsigned 1065 | @instruction("bw.bleui", "rB,I,u", "0xa 00 10 00II IIIB BBBB uuuu uuuu uuuu uuuu uuuu uuuu uuuu", "{I},r{B},<=,?{{,6,{u},-,pc,+=,}}") 1066 | class BwBleuiInstruction(BranchInstruction): 1067 | pass 1068 | 1069 | #TODO: treat as unsigned 1070 | @instruction("bw.bltui", "rB,I,u", "0xa 00 10 01II IIIB BBBB uuuu uuuu uuuu uuuu uuuu uuuu uuuu", "{I},r{B},<,?{{,6,{u},-,pc,+=,}}") 1071 | class BwBltuiInstruction(BranchInstruction): 1072 | pass 1073 | 1074 | @instruction("bw.beq", "rA,rB,u", "0xa 00 10 10AA AAAB BBBB uuuu uuuu uuuu uuuu uuuu uuuu uuuu", "r{B},r{A},==,$z,?{{,6,{u},-,pc,+=,}}") 1075 | class BwBeqInstruction(BranchInstruction): 1076 | pass 1077 | 1078 | @instruction("bw.bne", "rA,rB,u", "0xa 00 10 11AA AAAB BBBB uuuu uuuu uuuu uuuu uuuu uuuu uuuu", "r{B},r{A},==,$z,!,?{{,6,{u},-,pc,+=,}}") 1079 | class BwBneInstruction(BranchInstruction): 1080 | pass 1081 | 1082 | @instruction("bw.bges", "rA,rB,u", "0xa 00 11 00AA AAAB BBBB uuuu uuuu uuuu uuuu uuuu uuuu uuuu", "r{B},r{A},>=,?{{,6,{u},-,pc,+=,}}") 1083 | class BwBgesInstruction(BranchInstruction): 1084 | pass 1085 | 1086 | @instruction("bw.bgts", "rA,rB,u", "0xa 00 11 01AA AAAB BBBB uuuu uuuu uuuu uuuu uuuu uuuu uuuu", "r{B},r{A},>,?{{,6,{u},-,pc,+=,}}") 1087 | class BwBgtsInstruction(BranchInstruction): 1088 | pass 1089 | 1090 | #TODO: treat as unsigned 1091 | @instruction("bw.bgeu", "rA,rB,u", "0xa 00 11 10AA AAAB BBBB uuuu uuuu uuuu uuuu uuuu uuuu uuuu", "r{B},r{A},>=,?{{,6,{u},-,pc,+=,}}") 1092 | class BwBgeuInstruction(BranchInstruction): 1093 | pass 1094 | 1095 | #TODO: treat as unsigned 1096 | @instruction("bw.bgtu", "rA,rB,u", "0xa 00 11 11AA AAAB BBBB uuuu uuuu uuuu uuuu uuuu uuuu uuuu", "r{B},r{A},>,?{{,6,{u},-,pc,+=,}}") 1097 | class BwBgtuInstruction(BranchInstruction): 1098 | pass 1099 | 1100 | @instruction("bw.jal", "z", "0xa 01 00 00-- ---- zzzz zzzz zzzz zzzz zzzz zzzz zzzz zzzz", "pc,lr,=,6,{z},-,pc,+=") 1101 | class BwJalInstruction(JumpInstruction): 1102 | pass 1103 | 1104 | @instruction("bw.j", "z", "0xa 01 00 01-- ---- zzzz zzzz zzzz zzzz zzzz zzzz zzzz zzzz", "6,{z},-,pc,+=") 1105 | class BwJInstruction(JumpInstruction): 1106 | pass 1107 | 1108 | @instruction("bw.bf", "z", "0xa 01 00 10-- ---- zzzz zzzz zzzz zzzz zzzz zzzz zzzz zzzz", "fl,1,==,?{{,6,{z},-,pc,+=,}}") 1109 | class BwBfInstruction(BranchInstruction): 1110 | pass 1111 | 1112 | @instruction("bw.bnf", "z", "0xa 01 00 11-- ---- zzzz zzzz zzzz zzzz zzzz zzzz zzzz zzzz", "fl,0,==,?{{,6,{z},-,pc,+=,}}") 1113 | class BwBnfInstruction(BranchInstruction): 1114 | pass 1115 | 1116 | #TODO: jump absolute 1117 | @instruction("bw.ja", "g", "0xa 01 01 00-- ---- gggg gggg gggg gggg gggg gggg gggg gggg") 1118 | class BwJaInstruction(JumpInstruction): 1119 | pass 1120 | 1121 | #TODO: unknown - jump absolute? multiply? add? 1122 | @instruction("bw.jma", "rD,z", "0xa 01 01 01DD DDD0 zzzz zzzz zzzz zzzz zzzz zzzz zzzz zzzz") 1123 | class BwJmaInstruction(JumpInstruction): 1124 | pass 1125 | 1126 | #TODO: unknown - jump absolute? multiply? add? link? 1127 | @instruction("bw.jmal", "rD,z", "0xa 01 01 01DD DDD1 zzzz zzzz zzzz zzzz zzzz zzzz zzzz zzzz") 1128 | class BwJmalInstruction(JumpInstruction): 1129 | pass 1130 | 1131 | #TODO: unknown - multiply? add? 1132 | @instruction("bw.lma", "rD,z", "0xa 01 01 10DD DDD0 zzzz zzzz zzzz zzzz zzzz zzzz zzzz zzzz") 1133 | class BwLmaInstruction(LoadInstruction): 1134 | pass 1135 | 1136 | #TODO: unknown - multiply? add? 1137 | @instruction("bw.sma", "rB,z", "0xa 01 01 10BB BBB1 zzzz zzzz zzzz zzzz zzzz zzzz zzzz zzzz") 1138 | class BwSmaInstruction(StoreInstruction): 1139 | pass 1140 | 1141 | #TODO: unknown... some sort of jump? 1142 | @instruction("bw.casewi", "rB,z", "0xa 01 01 11BB BBB0 zzzz zzzz zzzz zzzz zzzz zzzz zzzz zzzz") 1143 | class BwCasewiInstruction(JumpInstruction): 1144 | pass 1145 | 1146 | #TODO: Treat as floating point 1147 | @instruction("fw.beq.s", "rA,rB,u", "0xa 01 10 00AA AAAB BBBB uuuu uuuu uuuu uuuu uuuu uuuu uuuu", "r{B},r{A},==,$z,?{{,6,{u},-,pc,+=,}}") 1148 | class FwBeqSInstruction(BranchInstruction): 1149 | pass 1150 | 1151 | #TODO: Treat as floating point 1152 | @instruction("fw.bne.s", "rA,rB,u", "0xa 01 10 01AA AAAB BBBB uuuu uuuu uuuu uuuu uuuu uuuu uuuu", "r{B},r{A},==,$z,!,?{{,6,{u},-,pc,+=,}}") 1153 | class FwBneSInstruction(BranchInstruction): 1154 | pass 1155 | 1156 | #TODO: Treat as floating point 1157 | @instruction("fw.bge.s", "rA,rB,u", "0xa 01 10 10AA AAAB BBBB uuuu uuuu uuuu uuuu uuuu uuuu uuuu", "r{B},r{A},>=,?{{,6,{u},-,pc,+=,}}") 1158 | class FwBgeSInstruction(BranchInstruction): 1159 | pass 1160 | 1161 | #TODO: Treat as floating point 1162 | @instruction("fw.bgt.s", "rA,rB,u", "0xa 01 10 11AA AAAB BBBB uuuu uuuu uuuu uuuu uuuu uuuu uuuu", "r{B},r{A},>,?{{,6,{u},-,pc,+=,}}") 1163 | class FwBgtSInstruction(BranchInstruction): 1164 | pass 1165 | 1166 | @instruction("bw.mfspr", "rD,rA,o", "0xa 10 DD DDDA AAAA oooo oooo oooo oooo oooo oooo ---- -000") 1167 | class BwMfsprInstruction(MoveInstruction): 1168 | pass 1169 | 1170 | @instruction("bw.mtspr", "rA,rB,o", "0xa 10 BB BBBA AAAA oooo oooo oooo oooo oooo oooo ---- -001") 1171 | class BwMtsprInstruction(MoveInstruction): 1172 | pass 1173 | 1174 | @instruction("bw.addci", "rD,rA,p", "0xa 10 DD DDDA AAAA pppp pppp pppp pppp pppp pppp ---- -010") 1175 | class BwAddciInstruction(ArithmeticInstruction): 1176 | pass 1177 | 1178 | @instruction("bw.divi", "rD,rA,p", "0xa 10 DD DDDA AAAA pppp pppp pppp pppp pppp pppp ---- -011") 1179 | class BwDiviInstruction(ArithmeticInstruction): 1180 | pass 1181 | 1182 | @instruction("bw.divui", "rD,rA,o", "0xa 10 DD DDDA AAAA oooo oooo oooo oooo oooo oooo ---- -100") 1183 | class BwDivuiInstruction(ArithmeticInstruction): 1184 | pass 1185 | 1186 | @instruction("bw.muli", "rD,rA,p", "0xa 10 DD DDDA AAAA pppp pppp pppp pppp pppp pppp ---- -101") 1187 | class BwMuliInstruction(ArithmeticInstruction): 1188 | pass 1189 | 1190 | @instruction("bw.xori", "rD,rA,p", "0xa 10 DD DDDA AAAA pppp pppp pppp pppp pppp pppp ---- -110") 1191 | class BwXoriInstruction(ArithmeticInstruction): 1192 | pass 1193 | 1194 | @instruction("bw.mulas", "rD,rA,rB,H", "0xa 11 DD DDDA AAAA BBBB BHHH HH-- ---- ---- ---- --00 0000") 1195 | class BwMulasInstruction(ArithmeticInstruction): 1196 | pass 1197 | 1198 | @instruction("bw.muluas", "rD,rA,rB,H", "0xa 11 DD DDDA AAAA BBBB BHHH HH-- ---- ---- ---- --00 0001") 1199 | class BwMuluasInstruction(ArithmeticInstruction): 1200 | pass 1201 | 1202 | @instruction("bw.mulras", "rD,rA,rB,H", "0xa 11 DD DDDA AAAA BBBB BHHH HH-- ---- ---- ---- --00 0010") 1203 | class BwMulrasInstruction(ArithmeticInstruction): 1204 | pass 1205 | 1206 | @instruction("bw.muluras", "rD,rA,rB,H", "0xa 11 DD DDDA AAAA BBBB BHHH HH-- ---- ---- ---- --00 0011") 1207 | class BwMulurasInstruction(ArithmeticInstruction): 1208 | pass 1209 | 1210 | @instruction("bw.mulsu", "rD,rA,rB", "0xa 11 DD DDDA AAAA BBBB B--- ---- ---- ---- ---- --00 0100") 1211 | class BwMulsuInstruction(ArithmeticInstruction): 1212 | pass 1213 | 1214 | @instruction("bw.mulhsu", "rD,rA,rB", "0xa 11 DD DDDA AAAA BBBB B--- ---- ---- ---- ---- --00 0101") 1215 | class BwMulhsuInstruction(ArithmeticInstruction): 1216 | pass 1217 | 1218 | @instruction("bw.mulhlsu", "rD,rQ,rA,rB", "0xa 11 DD DDDA AAAA BBBB BQQQ QQ-- ---- ---- ---- --00 0110") 1219 | class BwMulhlsuInstruction(ArithmeticInstruction): 1220 | pass 1221 | 1222 | @instruction("bw.smultt", "rD,rA,rB", "0xa 11 DD DDDA AAAA BBBB B--- ---- ---- ---- ---- --10 0000") 1223 | class BwSmulttInstruction(ArithmeticInstruction): 1224 | pass 1225 | 1226 | @instruction("bw.smultb", "rD,rA,rB", "0xa 11 DD DDDA AAAA BBBB B--- ---- ---- ---- ---- --10 0001") 1227 | class BwSmultbInstruction(ArithmeticInstruction): 1228 | pass 1229 | 1230 | @instruction("bw.smulbb", "rD,rA,rB", "0xa 11 DD DDDA AAAA BBBB B--- ---- ---- ---- ---- --10 0010") 1231 | class BwSmulbbInstruction(ArithmeticInstruction): 1232 | pass 1233 | 1234 | @instruction("bw.smulwb", "rD,rA,rB", "0xa 11 DD DDDA AAAA BBBB B--- ---- ---- ---- ---- --10 0011") 1235 | class BwSmulwbInstruction(ArithmeticInstruction): 1236 | pass 1237 | 1238 | @instruction("bw.smulwt", "rD,rA,rB", "0xa 11 DD DDDA AAAA BBBB B--- ---- ---- ---- ---- --10 0100") 1239 | class BwSmulwtInstruction(ArithmeticInstruction): 1240 | pass 1241 | 1242 | @instruction("bw.umultt", "rD,rA,rB", "0xa 11 DD DDDA AAAA BBBB B--- ---- ---- ---- ---- --10 1000") 1243 | class BwUmulttInstruction(ArithmeticInstruction): 1244 | pass 1245 | 1246 | @instruction("bw.umultb", "rD,rA,rB", "0xa 11 DD DDDA AAAA BBBB B--- ---- ---- ---- ---- --10 1001") 1247 | class BwUmultbInstruction(ArithmeticInstruction): 1248 | pass 1249 | 1250 | @instruction("bw.umulbb", "rD,rA,rB", "0xa 11 DD DDDA AAAA BBBB B--- ---- ---- ---- ---- --10 1010") 1251 | class BwUmulbbInstruction(ArithmeticInstruction): 1252 | pass 1253 | 1254 | @instruction("bw.umulwb", "rD,rA,rB", "0xa 11 DD DDDA AAAA BBBB B--- ---- ---- ---- ---- --10 1011") 1255 | class BwUmulwbInstruction(ArithmeticInstruction): 1256 | pass 1257 | 1258 | @instruction("bw.umulwt", "rD,rA,rB", "0xa 11 DD DDDA AAAA BBBB B--- ---- ---- ---- ---- --10 1100") 1259 | class BwUmulwtInstruction(ArithmeticInstruction): 1260 | pass 1261 | 1262 | @instruction("bw.smadtt", "rD,rA,rB,rR", "0xa 11 DD DDDA AAAA BBBB BRRR RR-- ---- ---- ---- --11 0000") 1263 | class BwSmadttInstruction(ArithmeticInstruction): 1264 | pass 1265 | 1266 | @instruction("bw.smadtb", "rD,rA,rB,rR", "0xa 11 DD DDDA AAAA BBBB BRRR RR-- ---- ---- ---- --11 0001") 1267 | class BwSmadtbInstruction(ArithmeticInstruction): 1268 | pass 1269 | 1270 | @instruction("bw.smadbb", "rD,rA,rB,rR", "0xa 11 DD DDDA AAAA BBBB BRRR RR-- ---- ---- ---- --11 0010") 1271 | class BwSmadbbInstruction(ArithmeticInstruction): 1272 | pass 1273 | 1274 | @instruction("bw.smadwb", "rD,rA,rB,rR", "0xa 11 DD DDDA AAAA BBBB BRRR RR-- ---- ---- ---- --11 0011") 1275 | class BwSmadwbInstruction(ArithmeticInstruction): 1276 | pass 1277 | 1278 | @instruction("bw.smadwt", "rD,rA,rB,rR", "0xa 11 DD DDDA AAAA BBBB BRRR RR-- ---- ---- ---- --11 0100") 1279 | class BwSmadwtInstruction(ArithmeticInstruction): 1280 | pass 1281 | 1282 | @instruction("bw.umadtt", "rD,rA,rB,rR", "0xa 11 DD DDDA AAAA BBBB BRRR RR-- ---- ---- ---- --11 1000") 1283 | class BwUmadttInstruction(ArithmeticInstruction): 1284 | pass 1285 | 1286 | @instruction("bw.umadtb", "rD,rA,rB,rR", "0xa 11 DD DDDA AAAA BBBB BRRR RR-- ---- ---- ---- --11 1001") 1287 | class BwUmadtbInstruction(ArithmeticInstruction): 1288 | pass 1289 | 1290 | @instruction("bw.umadbb", "rD,rA,rB,rR", "0xa 11 DD DDDA AAAA BBBB BRRR RR-- ---- ---- ---- --11 1010") 1291 | class BwUmadbbInstruction(ArithmeticInstruction): 1292 | pass 1293 | 1294 | @instruction("bw.umadwb", "rD,rA,rB,rR", "0xa 11 DD DDDA AAAA BBBB BRRR RR-- ---- ---- ---- --11 1011") 1295 | class BwUmadwbInstruction(ArithmeticInstruction): 1296 | pass 1297 | 1298 | @instruction("bw.umadwt", "rD,rA,rB,rR", "0xa 11 DD DDDA AAAA BBBB BRRR RR-- ---- ---- ---- --11 1100") 1299 | class BwUmadwtInstruction(ArithmeticInstruction): 1300 | pass 1301 | 1302 | @instruction("bw.copdss", "rD,rA,rB,y", "0xb 00 DD DDDA AAAA BBBB Byyy yyyy yyyy yyyy yyyy yyyy yyyy") 1303 | class BwCopdssInstruction(ArithmeticInstruction): 1304 | pass 1305 | 1306 | @instruction("bw.copd", "rD,g,H", "0xb 01 DD DDDH HHHH gggg gggg gggg gggg gggg gggg gggg gggg") 1307 | class BwCopdInstruction(ArithmeticInstruction): 1308 | pass 1309 | 1310 | @instruction("bw.cop", "g,x", "0xb 10 xx xxxx xxxx gggg gggg gggg gggg gggg gggg gggg gggg") 1311 | class BwCopInstruction(ArithmeticInstruction): 1312 | pass 1313 | 1314 | @instruction("bg.sb", "Y(rA),rB", "0xc 00 BB BBBA AAAA YYYY YYYY YYYY YYYY", "r{B},{Y},r{A},+,=[1]") 1315 | class BgSbInstruction(StoreInstruction): 1316 | pass 1317 | 1318 | @instruction("bg.lbz", "rD,Y(rA)", "0xc 01 DD DDDA AAAA YYYY YYYY YYYY YYYY", "{Y},r{A},+,[1],r{D},=") 1319 | class BgLbzInstruction(LoadInstruction): 1320 | pass 1321 | 1322 | @instruction("bg.sh", "X(rA),rB", "0xc 10 BB BBBA AAAA 0XXX XXXX XXXX XXXX", "r{B},{X},r{A},+,=[2]") 1323 | class BgShInstruction(StoreInstruction): 1324 | pass 1325 | 1326 | @instruction("bg.lhz", "rD,X(rA)", "0xc 10 DD DDDA AAAA 1XXX XXXX XXXX XXXX", "{X},r{A},+,[2],r{D},=") 1327 | class BgLhzInstruction(LoadInstruction): 1328 | pass 1329 | 1330 | @instruction("bg.sw", "W(rA),rB", "0xc 11 BB BBBA AAAA 00WW WWWW WWWW WWWW", "r{B},{W},r{A},+,=[4]") 1331 | class BgSwInstruction(StoreInstruction): 1332 | pass 1333 | 1334 | #TODO: zero extend 1335 | @instruction("bg.lwz", "rD,W(rA)", "0xc 11 DD DDDA AAAA 01WW WWWW WWWW WWWW", "{W},r{A},+,[4],r{D},=") 1336 | class BgLwzInstruction(LoadInstruction): 1337 | pass 1338 | 1339 | #TODO: sign extend 1340 | @instruction("bg.lws", "rD,W(rA)", "0xc 11 DD DDDA AAAA 10WW WWWW WWWW WWWW", "{W},r{A},+,[4],r{D},=") 1341 | class BgLwsInstruction(LoadInstruction): 1342 | pass 1343 | 1344 | #TODO: isn't this 64-bit? 1345 | @instruction("bg.sd", "V(rA),rB", "0xc 11 BB BBBA AAAA 110V VVVV VVVV VVVV") 1346 | class BgSdInstruction(StoreInstruction): 1347 | pass 1348 | 1349 | #TODO: isn't this 64-bit? 1350 | @instruction("bg.ld", "rD,V(rA)", "0xc 11 DD DDDA AAAA 111V VVVV VVVV VVVV") 1351 | class BgLdInstruction(LoadInstruction): 1352 | pass 1353 | 1354 | @instruction("bg.beqi", "rB,I,U", "0xd 00 00 00II IIIB BBBB UUUU UUUU UUUU", "{I},r{B},==,$z,?{{,4,{U},-,pc,+=,}}") 1355 | class BgBeqiInstruction(BranchInstruction): 1356 | pass 1357 | 1358 | @instruction("bg.bnei", "rB,I,U", "0xd 00 00 01II IIIB BBBB UUUU UUUU UUUU", "{I},r{B},==,$z,!,?{{,4,{U},-,pc,+=,}}") 1359 | class BgBneiInstruction(BranchInstruction): 1360 | pass 1361 | 1362 | @instruction("bg.bgesi", "rB,I,U", "0xd 00 00 10II IIIB BBBB UUUU UUUU UUUU", "{I},r{B},>=,?{{,4,{U},-,pc,+=,}}") 1363 | class BgBgesiInstruction(BranchInstruction): 1364 | pass 1365 | 1366 | @instruction("bg.bgtsi", "rB,I,U", "0xd 00 00 11II IIIB BBBB UUUU UUUU UUUU", "{I},r{B},>,?{{,4,{U},-,pc,+=,}}") 1367 | class BgBgtsiInstruction(BranchInstruction): 1368 | pass 1369 | 1370 | @instruction("bg.blesi", "rB,I,U", "0xd 00 01 00II IIIB BBBB UUUU UUUU UUUU", "{I},r{B},<=,?{{,4,{U},-,pc,+=,}}") 1371 | class BgBlesiInstruction(BranchInstruction): 1372 | pass 1373 | 1374 | @instruction("bg.bltsi", "rB,I,U", "0xd 00 01 01II IIIB BBBB UUUU UUUU UUUU", "{I},r{B},<,?{{,4,{U},-,pc,+=,}}") 1375 | class BgBltsiInstruction(BranchInstruction): 1376 | pass 1377 | 1378 | #TODO: sign extend 1379 | @instruction("bg.bgeui", "rB,I,U", "0xd 00 01 10II IIIB BBBB UUUU UUUU UUUU", "{I},r{B},>=,?{{,4,{U},-,pc,+=,}}") 1380 | class BgBgeuiInstruction(BranchInstruction): 1381 | pass 1382 | 1383 | #TODO: sign extend 1384 | @instruction("bg.bgtui", "rB,I,U", "0xd 00 01 11II IIIB BBBB UUUU UUUU UUUU", "{I},r{B},>,?{{,4,{U},-,pc,+=,}}") 1385 | class BgBgtuiInstruction(BranchInstruction): 1386 | pass 1387 | 1388 | #TODO: sign extend 1389 | @instruction("bg.bleui", "rB,I,U", "0xd 00 10 00II IIIB BBBB UUUU UUUU UUUU", "{I},r{B},<=,?{{,4,{U},-,pc,+=,}}") 1390 | class BgBleuiInstruction(BranchInstruction): 1391 | pass 1392 | 1393 | #TODO: sign extend 1394 | @instruction("bg.bltui", "rB,I,U", "0xd 00 10 01II IIIB BBBB UUUU UUUU UUUU", "{I},r{B},<,?{{,4,{U},-,pc,+=,}}") 1395 | class BgBltuiInstruction(BranchInstruction): 1396 | pass 1397 | 1398 | @instruction("bg.beq", "rA,rB,U", "0xd 00 10 10AA AAAB BBBB UUUU UUUU UUUU", "r{B},r{A},==,$z,?{{,4,{U},-,pc,+=,}}") 1399 | class BgBeqInstruction(BranchInstruction): 1400 | pass 1401 | 1402 | @instruction("bg.bne", "rA,rB,U", "0xd 00 10 11AA AAAB BBBB UUUU UUUU UUUU", "r{B},r{A},==,$z,!,?{{,4,{U},-,pc,+=,}}") 1403 | class BgBneInstruction(BranchInstruction): 1404 | pass 1405 | 1406 | @instruction("bg.bges", "rA,rB,U", "0xd 00 11 00AA AAAB BBBB UUUU UUUU UUUU", "r{B},r{A},>=,?{{,4,{U},-,pc,+=,}}") 1407 | class BgBgesInstruction(BranchInstruction): 1408 | pass 1409 | 1410 | @instruction("bg.bgts", "rA,rB,U", "0xd 00 11 01AA AAAB BBBB UUUU UUUU UUUU", "r{B},r{A},>,?{{,4,{U},-,pc,+=,}}") 1411 | class BgBgtsInstruction(BranchInstruction): 1412 | pass 1413 | 1414 | #TODO: sign extend 1415 | @instruction("bg.bgeu", "rA,rB,U", "0xd 00 11 10AA AAAB BBBB UUUU UUUU UUUU", "r{B},r{A},>=,?{{,4,{U},-,pc,+=,}}") 1416 | class BgBgeuInstruction(BranchInstruction): 1417 | pass 1418 | 1419 | #TODO: sign extend 1420 | @instruction("bg.bgtu", "rA,rB,U", "0xd 00 11 11AA AAAB BBBB UUUU UUUU UUUU", "r{B},r{A},>,?{{,4,{U},-,pc,+=,}}") 1421 | class BgBgtuInstruction(BranchInstruction): 1422 | pass 1423 | 1424 | @instruction("bg.jal", "t", "0xd 01 00 tttt tttt tttt tttt tttt tttt", "pc,lr,=,4,{t},-,pc,+=") 1425 | class BgJalInstruction(JumpInstruction): 1426 | pass 1427 | 1428 | @instruction("bg.j", "t", "0xd 01 01 tttt tttt tttt tttt tttt tttt", "4,{t},-,pc,+=") 1429 | class BgJInstruction(JumpInstruction): 1430 | pass 1431 | 1432 | @instruction("bg.bf", "t", "0xd 01 10 tttt tttt tttt tttt tttt tttt", "fl,1,==,?{{,4,{t},-,pc,+=,}}") 1433 | class BgBfInstruction(BranchInstruction): 1434 | pass 1435 | 1436 | @instruction("bg.bnf", "t", "0xd 01 11 tttt tttt tttt tttt tttt tttt", "fl,0,==,?{{,4,{t},-,pc,+=,}}") 1437 | class BgBnfInstruction(BranchInstruction): 1438 | pass 1439 | 1440 | @instruction("bg.addi", "rD,rA,Y", "0xd 10 DD DDDA AAAA YYYY YYYY YYYY YYYY", "{Y},r{A},+,r{D},=") 1441 | class BgAddiInstruction(ArithmeticInstruction): 1442 | pass 1443 | 1444 | #TODO: Treat as floating point 1445 | @instruction("fg.beq.s", "rA,rB,U", "0xd 11 00 00AA AAAB BBBB UUUU UUUU UUUU", "r{B},r{A},==,$z,?{{,4,{U},-,pc,+=,}}") 1446 | class FgBeqSInstruction(BranchInstruction): 1447 | pass 1448 | 1449 | #TODO: Treat as floating point 1450 | @instruction("fg.bne.s", "rA,rB,U", "0xd 11 00 01AA AAAB BBBB UUUU UUUU UUUU", "r{B},r{A},==,$z,!,?{{,4,{U},-,pc,+=,}}") 1451 | class FgBneSInstruction(BranchInstruction): 1452 | pass 1453 | 1454 | #TODO: Treat as floating point 1455 | @instruction("fg.bge.s", "rA,rB,U", "0xd 11 00 10AA AAAB BBBB UUUU UUUU UUUU", "r{B},r{A},>=,?{{,4,{U},-,pc,+=,}}") 1456 | class FgBgeSInstruction(BranchInstruction): 1457 | pass 1458 | 1459 | #TODO: Treat as floating point 1460 | @instruction("fg.bgt.s", "rA,rB,U", "0xd 11 00 11AA AAAB BBBB UUUU UUUU UUUU", "r{B},r{A},>,?{{,4,{U},-,pc,+=,}}") 1461 | class FgBgtSInstruction(BranchInstruction): 1462 | pass 1463 | 1464 | InstructionGroupLookup = { 1465 | 0: [BtMoviInstruction, 1466 | BtTrapInstruction, 1467 | BtAddiInstruction, 1468 | BtNopInstruction, 1469 | BtMovInstruction, 1470 | BtRfeInstruction, 1471 | BtEiInstruction, 1472 | BtDiInstruction, 1473 | BtSysInstruction, 1474 | BtAddInstruction, 1475 | BtJInstruction], 1476 | 2: [BnSbInstruction, 1477 | BnLbzInstruction, 1478 | BnShInstruction, 1479 | BnLhzInstruction, 1480 | BnSwInstruction, 1481 | BnLwzInstruction, 1482 | BnLwsInstruction, 1483 | BnSdInstruction, 1484 | BnLdInstruction], 1485 | 3: [BnAddiInstruction, 1486 | BnAndiInstruction, 1487 | BnOriInstruction, 1488 | BnSfeqiInstruction, 1489 | BnSfneiInstruction, 1490 | BnSfgesiInstruction, 1491 | BnSfgeuiInstruction, 1492 | BnSfgtsiInstruction, 1493 | BnSfgtuiInstruction, 1494 | BnSflesiInstruction, 1495 | BnSfleuiInstruction, 1496 | BnSfltsiInstruction, 1497 | BnSfltuiInstruction, 1498 | BnSfeqInstruction, 1499 | BnSfneInstruction, 1500 | BnSfgesInstruction, 1501 | BnSfgeuInstruction, 1502 | BnSfgtsInstruction, 1503 | BnSfgtuInstruction, 1504 | BnExtbzInstruction, 1505 | BnExtbsInstruction, 1506 | BnExthzInstruction, 1507 | BnExthsInstruction, 1508 | BnFf1Instruction, 1509 | BnClzInstruction, 1510 | BnBitrevInstruction, 1511 | BnSwabInstruction, 1512 | BnMfsprInstruction, 1513 | BnMtsprInstruction, 1514 | BnAbsInstruction, 1515 | BnSqrInstruction, 1516 | BnSqraInstruction, 1517 | BnCaseiInstruction], 1518 | 4: [BnBeqiInstruction, 1519 | BnBneiInstruction, 1520 | BnBgesiInstruction, 1521 | BnBgtsiInstruction, 1522 | BnBlesiInstruction, 1523 | BnBltsiInstruction, 1524 | BnJInstruction, 1525 | BnBfInstruction, 1526 | BnBnfInstruction, 1527 | BnBoInstruction, 1528 | BnBnoInstruction, 1529 | BnBcInstruction, 1530 | BnBncInstruction, 1531 | BnEntriInstruction, 1532 | BnRetiInstruction, 1533 | BnRtneiInstruction, 1534 | BnReturnInstruction, 1535 | BnJalrInstruction, 1536 | BnJrInstruction, 1537 | BnJalInstruction], 1538 | 5: [BnMlwzInstruction, 1539 | BnMswInstruction, 1540 | BnMldInstruction, 1541 | BnMsdInstruction, 1542 | BnLwzaInstruction, 1543 | BnSwaInstruction], 1544 | 6: [BnBitwiseInstruction, 1545 | BnOrInstruction, 1546 | BnXorInstruction, 1547 | BnNBitwiseInstruction, 1548 | BnAddInstruction, 1549 | BnSubInstruction, 1550 | BnSllInstruction, 1551 | BnSrlInstruction, 1552 | BnSraInstruction, 1553 | BnRorInstruction, 1554 | BnCmovInstruction, 1555 | BnMulInstruction, 1556 | BnDivInstruction, 1557 | BnDivuInstruction, 1558 | BnMacInstruction, 1559 | BnMacsInstruction, 1560 | BnMacsuInstruction, 1561 | BnMacuuInstruction, 1562 | BnSmacttInstruction, 1563 | BnSmacbbInstruction, 1564 | BnSmactbInstruction, 1565 | BnUmacttInstruction, 1566 | BnUmacbbInstruction, 1567 | BnUmactbInstruction, 1568 | BnMsuInstruction, 1569 | BnMsusInstruction, 1570 | BnAddcInstruction, 1571 | BnSubbInstruction, 1572 | BnFlbInstruction, 1573 | BnMulhuInstruction, 1574 | BnMulhInstruction, 1575 | BnModInstruction, 1576 | BnModuInstruction, 1577 | BnAaddInstruction, 1578 | BnCmpxchgInstruction, 1579 | BnSlliInstruction, 1580 | BnSrliInstruction, 1581 | BnSraiInstruction, 1582 | BnRoriInstruction], 1583 | 7: [FnAddSInstruction, 1584 | FnSubSInstruction, 1585 | FnMulSInstruction, 1586 | FnDivSInstruction, 1587 | BnAddsInstruction, 1588 | BnSubsInstruction, 1589 | BnNegInstruction, 1590 | BnXaaddInstruction, 1591 | BnXcmpxchgInstruction, 1592 | BnMaxInstruction, 1593 | BnMinInstruction, 1594 | BnLimInstruction, 1595 | BnSllsInstruction, 1596 | BnSllisInstruction, 1597 | FnFtoiSInstruction, 1598 | FnItofSInstruction], 1599 | 8: [BwSbInstruction, 1600 | BwLbzInstruction, 1601 | BwShInstruction, 1602 | BwLhzInstruction, 1603 | BwSwInstruction, 1604 | BwLwzInstruction, 1605 | BwLwsInstruction, 1606 | BwSdInstruction, 1607 | BwLdInstruction], 1608 | 9: [BwAddiInstruction, 1609 | BwAndiInstruction, 1610 | FAbsInstruction, 1611 | BwOriInstruction, 1612 | BwSfeqiInstruction, 1613 | BwSfneiInstruction, 1614 | BwSfgesiInstruction, 1615 | BwSfgeuiInstruction, 1616 | BwSfgtsiInstruction, 1617 | BwSfgtuiInstruction, 1618 | BwSflesiInstruction, 1619 | BwSfleuiInstruction, 1620 | BwSfltsiInstruction, 1621 | BwSfltuiInstruction], 1622 | 10: [BwBeqiInstruction, 1623 | BwBneiInstruction, 1624 | BwBgesiInstruction, 1625 | BwBgtsiInstruction, 1626 | BwBlesiInstruction, 1627 | BwBltsiInstruction, 1628 | BwBgeuiInstruction, 1629 | BwBgtuiInstruction, 1630 | BwBleuiInstruction, 1631 | BwBltuiInstruction, 1632 | BwBeqInstruction, 1633 | BwBneInstruction, 1634 | BwBgesInstruction, 1635 | BwBgtsInstruction, 1636 | BwBgeuInstruction, 1637 | BwBgtuInstruction, 1638 | BwJalInstruction, 1639 | BwJInstruction, 1640 | BwBfInstruction, 1641 | BwBnfInstruction, 1642 | BwJaInstruction, 1643 | BwJmaInstruction, 1644 | BwJmalInstruction, 1645 | BwLmaInstruction, 1646 | BwSmaInstruction, 1647 | BwCasewiInstruction, 1648 | FwBeqSInstruction, 1649 | FwBneSInstruction, 1650 | FwBgeSInstruction, 1651 | FwBgtSInstruction, 1652 | BwMfsprInstruction, 1653 | BwMtsprInstruction, 1654 | BwAddciInstruction, 1655 | BwDiviInstruction, 1656 | BwDivuiInstruction, 1657 | BwMuliInstruction, 1658 | BwXoriInstruction, 1659 | BwMulasInstruction, 1660 | BwMuluasInstruction, 1661 | BwMulrasInstruction, 1662 | BwMulurasInstruction, 1663 | BwMulsuInstruction, 1664 | BwMulhsuInstruction, 1665 | BwMulhlsuInstruction, 1666 | BwSmulttInstruction, 1667 | BwSmultbInstruction, 1668 | BwSmulbbInstruction, 1669 | BwSmulwbInstruction, 1670 | BwSmulwtInstruction, 1671 | BwUmulttInstruction, 1672 | BwUmultbInstruction, 1673 | BwUmulbbInstruction, 1674 | BwUmulwbInstruction, 1675 | BwUmulwtInstruction, 1676 | BwSmadttInstruction, 1677 | BwSmadtbInstruction, 1678 | BwSmadbbInstruction, 1679 | BwSmadwbInstruction, 1680 | BwSmadwtInstruction, 1681 | BwUmadttInstruction, 1682 | BwUmadtbInstruction, 1683 | BwUmadbbInstruction, 1684 | BwUmadwbInstruction, 1685 | BwUmadwtInstruction], 1686 | 11: [BwCopdssInstruction, 1687 | BwCopdInstruction, 1688 | BwCopInstruction], 1689 | 12: [BgSbInstruction, 1690 | BgLbzInstruction, 1691 | BgShInstruction, 1692 | BgLhzInstruction, 1693 | BgSwInstruction, 1694 | BgLwzInstruction, 1695 | BgLwsInstruction, 1696 | BgSdInstruction, 1697 | BgLdInstruction], 1698 | 13: [BgBeqiInstruction, 1699 | BgBneiInstruction, 1700 | BgBgesiInstruction, 1701 | BgBgtsiInstruction, 1702 | BgBlesiInstruction, 1703 | BgBltsiInstruction, 1704 | BgBgeuiInstruction, 1705 | BgBgtuiInstruction, 1706 | BgBleuiInstruction, 1707 | BgBltuiInstruction, 1708 | BgBeqInstruction, 1709 | BgBneInstruction, 1710 | BgBgesInstruction, 1711 | BgBgtsInstruction, 1712 | BgBgeuInstruction, 1713 | BgBgtuInstruction, 1714 | BgJalInstruction, 1715 | BgJInstruction, 1716 | BgBfInstruction, 1717 | BgBnfInstruction, 1718 | BgAddiInstruction, 1719 | FgBeqSInstruction, 1720 | FgBneSInstruction, 1721 | FgBgeSInstruction, 1722 | FgBgtSInstruction] 1723 | } 1724 | -------------------------------------------------------------------------------- /isa/types.py: -------------------------------------------------------------------------------- 1 | from enum import Flag, Enum, auto 2 | 3 | 4 | class OperandType(Flag): 5 | REG = 0x00000001 # The operand specifies a register index 6 | SIG = 0x00000002 # The operand must be sign extended 7 | DST = 0x00000004 # The operand is a destination 8 | REL = 0x00000008 # The operand is pc relative 9 | LSB = 0x00000010 # The operand is encoded LSB first 10 | DUNSIG = 0x00000020 # The operand will be disassembled as an unsigned value 11 | SYM = 0x00000040 # The letter is of pure symbolic value 12 | OP64BIT = 0x00000080 # This letter is used in instructions where the operation is carried out 13 | # in 64-bits (mostly meaning that the width of the registers involved are 14 | # 64-bits long) 15 | REGPRE = 0x00000100 # The letter is a prefix to a register. The letter should also be marked 16 | # as symbolic (SYM) 17 | 18 | class InstructionType(Enum): 19 | UNKNOWN = auto() 20 | EXCEPTION = auto() 21 | ARITH = auto() 22 | SHIFT = auto() 23 | COMPARE = auto() 24 | BRANCH = auto() 25 | JUMP = auto() 26 | LOAD = auto() 27 | STORE = auto() 28 | MOVIMM = auto() 29 | MOVE = auto() 30 | EXTEND = auto() 31 | NOP = auto() 32 | MAC = auto() 33 | FLOAT = auto() 34 | 35 | LetterCodes = { 36 | 'A': {'flags': OperandType.REG, 'length': 5}, 37 | 'B': {'flags': OperandType.REG, 'length': 5}, 38 | 'R': {'flags': OperandType.REG, 'length': 5}, 39 | 'D': {'flags': OperandType.REG | OperandType.DST, 'length': 5}, 40 | 'Q': {'flags': OperandType.REG | OperandType.DST, 'length': 5}, 41 | 'r': {'flags': OperandType.SYM | OperandType.REGPRE, 'length': 0}, 42 | 'C': {'flags': OperandType.LSB, 'length': 2}, 43 | 'E': {'flags': OperandType.LSB, 'length': 3}, 44 | 'F': {'flags': OperandType.LSB, 'length': 4}, 45 | 'G': {'flags': OperandType.SIG | OperandType.LSB, 'length': 4}, 46 | 'L': {'flags': OperandType.SIG | OperandType.LSB, 'length': 4}, # This actually doesn't seem to be LSB... 47 | 'H': {'flags': OperandType.LSB, 'length': 5}, 48 | 'I': {'flags': OperandType.SIG | OperandType.LSB, 'length': 5}, 49 | 'J': {'flags': OperandType.LSB | OperandType.DUNSIG, 'length': 5}, # Added DUNSIG to match binutils behavior 50 | 'K': {'flags': OperandType.LSB | OperandType.DUNSIG, 'length': 6}, # Added DUNSIG to match binutils behavior 51 | 'M': {'flags': OperandType.LSB | OperandType.DUNSIG, 'length': 7}, # Added DUNSIG to match binutils behavior 52 | 'N': {'flags': OperandType.LSB, 'length': 8}, 53 | 'O': {'flags': OperandType.SIG | OperandType.LSB, 'length': 8}, 54 | 'P': {'flags': OperandType.SIG | OperandType.REL | OperandType.LSB, 'length': 8}, 55 | 'T': {'flags': OperandType.SIG | OperandType.REL | OperandType.LSB, 'length': 10}, 56 | 'U': {'flags': OperandType.SIG | OperandType.REL | OperandType.LSB, 'length': 12}, 57 | 'S': {'flags': OperandType.SIG | OperandType.REL | OperandType.LSB, 'length': 12}, 58 | 'V': {'flags': OperandType.SIG | OperandType.LSB | OperandType.DUNSIG, 'length': 13}, # Added DUNSIG to match binutils behavior 59 | 'W': {'flags': OperandType.SIG | OperandType.LSB | OperandType.DUNSIG, 'length': 14}, # Added DUNSIG to match binutils behavior 60 | 'X': {'flags': OperandType.SIG | OperandType.LSB | OperandType.DUNSIG, 'length': 15}, # Added DUNSIG to match binutils behavior 61 | 'Y': {'flags': OperandType.SIG | OperandType.LSB, 'length': 16}, 62 | 'Z': {'flags': OperandType.SIG | OperandType.REL | OperandType.LSB, 'length': 16}, 63 | 's': {'flags': OperandType.SIG | OperandType.REL | OperandType.LSB, 'length': 18}, 64 | 'o': {'flags': OperandType.LSB, 'length': 24}, 65 | 'p': {'flags': OperandType.SIG | OperandType.LSB, 'length': 24}, 66 | 't': {'flags': OperandType.SIG | OperandType.REL | OperandType.LSB, 'length': 24}, 67 | 'u': {'flags': OperandType.SIG | OperandType.REL | OperandType.LSB, 'length': 28}, 68 | 'v': {'flags': OperandType.SIG | OperandType.LSB | OperandType.DUNSIG, 'length': 29}, 69 | 'w': {'flags': OperandType.LSB | OperandType.DUNSIG, 'length': 30}, # Removed SIG to match binutils behavior 70 | 'i': {'flags': OperandType.SIG | OperandType.LSB | OperandType.DUNSIG, 'length': 31}, 71 | 'g': {'flags': OperandType.SIG | OperandType.LSB, 'length': 32}, 72 | 'h': {'flags': OperandType.LSB | OperandType.DUNSIG, 'length': 32}, # Removed SIG to match binutils behavior 73 | 'z': {'flags': OperandType.SIG | OperandType.REL | OperandType.LSB, 'length': 32}, 74 | 'x': {'flags': OperandType.LSB, 'length': 10}, 75 | 'y': {'flags': OperandType.LSB, 'length': 27}, 76 | } -------------------------------------------------------------------------------- /test-disasm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import r2pipe 4 | import re 5 | import os 6 | import sys 7 | from pprint import pprint 8 | 9 | 10 | class SanityTester: 11 | def __init__(self, basefile): 12 | self._r2 = r2pipe.open() 13 | self._asmfile = open (basefile + '.asm', 'rt') 14 | 15 | if (os.path.exists (basefile + '.bin')): 16 | self._binfile = basefile + '.bin' 17 | else: 18 | self._binfile = basefile + '.elf' 19 | 20 | def __iter__(self): 21 | self._asmfile.seek (0) 22 | return self 23 | 24 | def __next__(self): 25 | for asmline in self._asmfile: 26 | try: 27 | # Code lines start with 3 spaces and have 2 tabs 28 | if not asmline.startswith(' ') or asmline.count('\t') < 2: 29 | continue 30 | 31 | # Split the code line into address, actual bytes, and assembly text 32 | addr, asmbytes, text = asmline.strip().split('\t') 33 | 34 | addr = int(addr[:-1], 16) 35 | asmbytes = bytes.fromhex(asmbytes) 36 | text = re.sub(r"<.*?>", "", text).strip() 37 | 38 | # literals are not instructions 39 | if text.startswith('.'): 40 | continue 41 | 42 | return [addr, asmbytes, text] 43 | except Exception as e: 44 | print (asmline, e) 45 | continue 46 | 47 | raise StopIteration 48 | 49 | def _asm_match(self, addr, text, r2disasm): 50 | # Split the assembly text into parts (mnemonic, arguments) 51 | actual_parts = [part for part in re.split(r"[\,\(\) ]+", r2disasm) if part != ''] 52 | text_parts = [part for part in re.split(r"[\,\(\) ]+", text) if part != ''] 53 | 54 | if len(actual_parts) != len(text_parts): 55 | print (f"{addr:x}: {r2disasm} != {text}") 56 | return False 57 | 58 | for actual, expected in zip(actual_parts, text_parts): 59 | if actual in self._symbols: 60 | actual = hex (self._symbols[actual]) 61 | if actual == expected: 62 | continue # Perfect match, continue 63 | if actual.split('.')[-1] == expected.split('.')[-1]: 64 | continue # The prefix doesn't match - but the opcode itself does, continue 65 | if actual[2:] == expected: 66 | continue # The hexadecimal values match, continue 67 | if int (actual, 16) - int (expected, 16) in (-0x100, -0x10000, -0x100000000): 68 | print (f"\033[0;33m {addr:x}: {r2disasm} != {text}") 69 | print (f" => {actual} != {expected}\033[00m") 70 | continue # The values match, but signed/unsigned disassembly is wrong 71 | 72 | print (f"\033[1;31m*** {addr:x}: {r2disasm} != {text}") 73 | print (f"*** => {actual} != {expected}\033[00m") 74 | 75 | return False 76 | 77 | return True 78 | 79 | 80 | def test_disassembly(self): 81 | print (f"Starting disassembly sanity test ({self._binfile})...") 82 | 83 | self._r2.cmd (f'o "{self._binfile}"') 84 | self._r2.cmd ("e asm.arch=ba2") 85 | 86 | self._symbols = {sym["name"]: sym["offset"] for sym in self._r2.cmdj ("fj")} 87 | self._r2.cmd ("fs strings") 88 | self._symbols.update ({sym["name"]: sym["offset"] for sym in self._r2.cmdj ("fj")}) 89 | 90 | skip_addresses = [] 91 | 92 | for addr, asmbytes, text in self: 93 | if addr in skip_addresses: 94 | continue 95 | 96 | # Get assembly text from radare2 97 | r2disasm = self._r2.cmdj(f'pdj 1@{addr}')[0]['disasm'] 98 | 99 | if not self._asm_match(addr, text, r2disasm): 100 | pass 101 | 102 | self._r2.cmd ("o--") 103 | 104 | def test_assembly(self): 105 | print (f"Starting assembly sanity test ({self._binfile})...") 106 | 107 | self._r2.cmd (f"o malloc://{os.stat(self._binfile).st_size} 0x80000") 108 | self._r2.cmd ("e asm.arch=ba2") 109 | self._symbols = {} 110 | 111 | skip_addresses = [] 112 | 113 | for addr, asmbytes, text in self: 114 | if addr in skip_addresses: 115 | continue 116 | 117 | self._r2.cmd (f"wa {text} @{addr}") 118 | writteninsn = self._r2.cmdj (f"pdj 1@{addr}")[0] 119 | writtenbytes = bytes.fromhex(writteninsn["bytes"]) 120 | writtentext = writteninsn["disasm"] 121 | if writtenbytes == asmbytes: 122 | continue 123 | else: 124 | print (' *** ') 125 | print (' *** ', hex(addr), ':', writtenbytes.hex(), asmbytes.hex(), writtentext, text) 126 | print (' *** ') 127 | if not self._asm_match (addr, text, writtentext): 128 | pass 129 | 130 | if __name__ == '__main__': 131 | if len (sys.argv) < 2: 132 | print (sys.argv) 133 | tester = SanityTester (sys.argv[-1]) 134 | tester.test_disassembly () 135 | tester.test_assembly () 136 | elif len (sys.argv) == 2: 137 | for filename in os.listdir (sys.argv[-1]): 138 | if not filename.endswith ('.elf'): 139 | continue 140 | 141 | tester = SanityTester (os.path.join (sys.argv[-1], filename[:-4])) 142 | # tester.test_disassembly () 143 | tester.test_assembly () 144 | else: 145 | print ("Usage: test-disasm.py [test-dir]") 146 | -------------------------------------------------------------------------------- /test-on-board.py: -------------------------------------------------------------------------------- 1 | from itertools import chain, filterfalse 2 | from asm import BA2Assembler 3 | from isa.instructions import InstructionGroupLookup 4 | from isa.types import LetterCodes, OperandType 5 | from pprint import pprint 6 | from random import randint 7 | 8 | 9 | class TestOpCode (gdb.Command): 10 | BASE_ADDRESS = 0x4000000 11 | REGISTERS = set([f"R{n}" for n in range(32)] + ["PC", "SR", "UR", "EPCR", "ESR", "EEAR"]) 12 | 13 | def __init__(self): 14 | super ().__init__ ("test-opcode", gdb.COMMAND_USER) 15 | self._assembler = BA2Assembler() 16 | self._reg_state_before = None 17 | self._reg_state_after = None 18 | self._mem_state_before = None 19 | self._mem_state_after = None 20 | 21 | def _dump_registers (self): 22 | return { 23 | register: gdb.parse_and_eval(f"${register}") for register in self.REGISTERS 24 | } 25 | 26 | def _dump_memory (self): 27 | return None 28 | 29 | def _pre (self): 30 | gdb.execute (f"set $PC={self.BASE_ADDRESS}") 31 | self._reg_state_before = self._dump_registers () 32 | self._mem_state_before = self._dump_memory () 33 | 34 | def _post (self): 35 | self._reg_state_after = self._dump_registers () 36 | self._mem_state_after = self._dump_memory () 37 | 38 | def _find_direct_sources (self, value): 39 | sources = {} 40 | 41 | for reg in self.REGISTERS: 42 | if self._reg_state_before[reg] == value: 43 | sources[reg] = value 44 | 45 | return sources 46 | 47 | def _test_insn (self, insn_class, args): 48 | insn = insn_class (args, self.BASE_ADDRESS) 49 | 50 | print (f"Testing '{insn}'...") 51 | 52 | gdb.selected_inferior ().write_memory (self.BASE_ADDRESS, bytes (0x100)) 53 | gdb.selected_inferior ().write_memory (self.BASE_ADDRESS, bytes (insn.encode ())) 54 | 55 | self._pre () 56 | gdb.execute ('si') 57 | self._post () 58 | 59 | if self._reg_state_after['PC'] == self.BASE_ADDRESS: 60 | print ("Execution failed - check your arguments!") 61 | else: 62 | changed_regs = filterfalse ( 63 | lambda reg: self._reg_state_before[reg] == self._reg_state_after[reg], 64 | self.REGISTERS) 65 | unchanged_regs = filterfalse ( 66 | lambda reg: self._reg_state_before[reg] != self._reg_state_after[reg], 67 | self.REGISTERS) 68 | 69 | for reg in changed_regs: 70 | sources = {} 71 | 72 | before = self._reg_state_before[reg] 73 | after = self._reg_state_after[reg] 74 | print (f" * {reg}: {before} -> {after}") 75 | 76 | sources.update (self._find_direct_sources (after)) 77 | 78 | for src, value in sources.items(): 79 | print (f" {src}: {value}") 80 | 81 | print (" ---") 82 | 83 | def _generate_args (self, insn_class): 84 | args = {} 85 | 86 | for arg in insn_class.ARGS: 87 | flags = LetterCodes[arg[-1]]['flags'] 88 | length = LetterCodes[arg[-1]]['length'] 89 | 90 | if flags & OperandType.SIG: 91 | value = randint (-2 ** (length - 1), 2 ** (length - 1) - 1) 92 | else: 93 | value = randint (0, 2 ** length - 1) 94 | 95 | args[arg[-1]] = value 96 | 97 | return args 98 | 99 | def invoke (self, arg, from_tty): 100 | for insn_class in chain.from_iterable (InstructionGroupLookup.values ()): 101 | if insn_class.MNEMONIC.split ('.', 1)[-1] == arg.split ()[0].split ('.', 1)[-1]: 102 | try: 103 | self._test_insn (insn_class, self._generate_args (insn_class)) 104 | except: 105 | import traceback 106 | traceback.print_exc () 107 | 108 | TestOpCode () --------------------------------------------------------------------------------