├── r2 ├── hexagon_anal.h ├── cc-hexagon-32.sdb.txt ├── asm_hexagon.c ├── Makefile ├── anal_hexagon.c ├── hexagon.c ├── hexagon.h └── hexagon_anal.c ├── README.md ├── LICENSE ├── const_extenders.txt └── importer.py /r2/hexagon_anal.h: -------------------------------------------------------------------------------- 1 | int hexagon_anal_instruction(HexInsn *hi, RAnalOp *op); 2 | 3 | -------------------------------------------------------------------------------- /r2/cc-hexagon-32.sdb.txt: -------------------------------------------------------------------------------- 1 | default.cc=hexagon 2 | 3 | hexagon=cc 4 | cc.hexagon.arg0=r0 5 | cc.hexagon.arg1=r1 6 | cc.hexagon.arg2=r2 7 | cc.hexagon.arg3=r3 8 | cc.hexagon.arg4=r4 9 | cc.hexagon.arg5=r5 10 | cc.hexagon.argn=stack_rev 11 | cc.hexagon.ret=r0 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | This is a Hexagon disassembly and analysis plugin generator for radare2. 4 | It uses text file of the specification as a source (recognized from PDF file), 5 | and some additional text files with some amendments. 6 | 7 | It processes the files and generate C code in `r2` directory. Just run `importer.py`. 8 | 9 | The parsing part based largely on [hexag00n](https://github.com/programa-stic/hexag00n) importer. 10 | 11 | # Contributors 12 | 13 | * Anton Kochkov 14 | 15 | * Lucas Molas 16 | 17 | * Iván Arce 18 | 19 | * Juan Heguiabehere 20 | 21 | * Christian Heitman 22 | 23 | * D.C. 24 | 25 | 26 | -------------------------------------------------------------------------------- /r2/asm_hexagon.c: -------------------------------------------------------------------------------- 1 | /* radare - LGPL - Copyright 2018 - xvilka */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "hexagon.h" 8 | #include "hexagon_insn.h" 9 | 10 | static int disassemble (RAsm *a, RAsmOp *op, const ut8 *buf, int l) { 11 | HexInsn hi = {0}; 12 | ut32 data = r_read_le32 (buf); 13 | op->size = hexagon_disasm_instruction (data, &hi, (ut32) a->pc); 14 | r_strbuf_set (&op->buf_asm, hi.mnem); 15 | return op->size; 16 | } 17 | 18 | RAsmPlugin r_asm_plugin_hexagon = { 19 | .name = "hexagon", 20 | .arch = "hexagon", 21 | .author = "xvilka", 22 | .license = "LGPL3", 23 | .bits = 32, 24 | .desc = "Qualcomm Hexagon (QDSP6) V6", 25 | .disassemble = &disassemble, 26 | }; 27 | 28 | #ifndef R2_PLUGIN_INCORE 29 | R_API RLibStruct radare_plugin = { 30 | .type = R_LIB_TYPE_ASM, 31 | .data = &r_asm_plugin_hexagon 32 | }; 33 | #endif 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Fundación Dr. Manuel Sadosky 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /r2/Makefile: -------------------------------------------------------------------------------- 1 | R2_PLUGIN_PATH=$(shell r2 -hh|grep USER_PLUGINS|awk '{print $$2}') 2 | SO_EXT=$(shell uname|grep -q Darwin && echo dylib || echo so) 3 | 4 | # RAsm plugin 5 | RASM_NAME=hexagon_asm 6 | RASM_CFLAGS=-g -fPIC $(shell pkg-config --cflags r_asm) 7 | RASM_LDFLAGS=-g -fPIC -shared $(shell pkg-config --libs r_asm) 8 | RASM_OBJS=asm_hexagon.o hexagon.o hexagon_disas.o 9 | RASM_SRC=$(pathsubst %.o, %.c, $(RASM_OBJS)) 10 | RASM_LIB=$(RASM_NAME).$(SO_EXT) 11 | 12 | # RAnal plugin 13 | RANAL_NAME=hexagon_anal 14 | RANAL_CFLAGS=-g -fPIC $(shell pkg-config --cflags r_anal) 15 | RANAL_LDFLAGS=-g -fPIC -shared $(shell pkg-config --libs r_anal) 16 | RANAL_OBJS=anal_hexagon.o hexagon.o hexagon_disas.o hexagon_anal.o 17 | RANAL_SRC=$(pathsubst %.o, %.c, $(RASM_OBJS)) 18 | RANAL_LIB=$(RANAL_NAME).$(SO_EXT) 19 | 20 | all: $(RASM_LIB) $(RANAL_LIB) 21 | 22 | clean: 23 | rm -f $(RASM_LIB) $(RANAL_LIB) $(RASM_OBJS) $(RANAL_OBJS) 24 | 25 | $(RASM_LIB): $(RASM_OBJS) 26 | $(CC) $(RASM_CFLAGS) $(RASM_LDFLAGS) $(RASM_OBJS) -o $(RASM_LIB) 27 | 28 | $(RANAL_LIB): $(RANAL_OBJS) 29 | $(CC) $(RANAL_CFLAGS) $(RANAL_LDFLAGS) $(RANAL_OBJS) -o $(RANAL_LIB) 30 | 31 | %.o: %.c 32 | $(CC) $(RASM_CFLAGS) $(RANAL_CFLAGS) -c $< -o $@ 33 | 34 | install: 35 | cp -f $(RASM_NAME).$(SO_EXT) $(R2_PLUGIN_PATH) 36 | cp -f $(RANAL_NAME).$(SO_EXT) $(R2_PLUGIN_PATH) 37 | 38 | uninstall: 39 | rm -f $(R2_PLUGIN_PATH)/$(RASM_NAME).$(SO_EXT) 40 | rm -f $(R2_PLUGIN_PATH)/$(RANAL_NAME).$(SO_EXT) 41 | 42 | -------------------------------------------------------------------------------- /r2/anal_hexagon.c: -------------------------------------------------------------------------------- 1 | /* radare - LGPL - Copyright 2018 - xvilka */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "hexagon.h" 9 | #include "hexagon_insn.h" 10 | #include "hexagon_anal.h" 11 | 12 | static int hexagon_v6_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len, RAnalOpMask mask) { 13 | HexInsn hi = {0};; 14 | ut32 data = 0; 15 | memset (op, 0, sizeof (RAnalOp)); 16 | data = r_read_le32 (buf); 17 | int size = hexagon_disasm_instruction (data, &hi, (ut32) addr); 18 | op->size = size; 19 | if (size <= 0) { 20 | return size; 21 | } 22 | 23 | op->addr = addr; 24 | op->jump = op->fail = -1; 25 | op->ptr = op->val = -1; 26 | return hexagon_anal_instruction (&hi, op); 27 | } 28 | 29 | static int set_reg_profile(RAnal *anal) { 30 | // TODO: Add missing registers 31 | const char *p = 32 | "=PC pc\n" 33 | "=SP r29\n" 34 | "=BP r30\n" 35 | "=LR r31\n" 36 | "=SN r6\n" 37 | "=ZF z\n" 38 | "=SF s\n" 39 | "=OF ov\n" 40 | "=CF cy\n" 41 | 42 | "gpr r0 .32 0 0\n" 43 | "gpr r1 .32 4 0\n" 44 | "gpr r2 .32 8 0\n" 45 | "gpr r3 .32 12 0\n" 46 | "gpr r4 .32 16 0\n" 47 | "gpr r5 .32 20 0\n" 48 | "gpr r6 .32 24 0\n" 49 | "gpr r7 .32 28 0\n" 50 | "gpr r8 .32 32 0\n" 51 | "gpr r9 .32 36 0\n" 52 | "gpr r10 .32 40 0\n" 53 | "gpr r11 .32 44 0\n" 54 | "gpr r12 .32 48 0\n" 55 | "gpr r13 .32 52 0\n" 56 | "gpr r14 .32 56 0\n" 57 | "gpr r15 .32 60 0\n" 58 | "gpr r16 .32 64 0\n" 59 | "gpr r17 .32 68 0\n" 60 | "gpr r18 .32 72 0\n" 61 | "gpr r19 .32 76 0\n" 62 | "gpr r20 .32 80 0\n" 63 | "gpr r21 .32 84 0\n" 64 | "gpr r22 .32 88 0\n" 65 | "gpr r23 .32 92 0\n" 66 | "gpr r24 .32 96 0\n" 67 | "gpr r25 .32 100 0\n" 68 | "gpr r26 .32 104 0\n" 69 | "gpr r27 .32 108 0\n" 70 | "gpr r28 .32 112 0\n" 71 | "gpr r29 .32 116 0\n" 72 | "gpr r30 .32 120 0\n" 73 | "gpr r31 .32 124 0\n" 74 | "gpr pc .32 128 0\n" 75 | 76 | "gpr psw .32 132 0\n" 77 | "gpr np .1 132.16 0\n" 78 | "gpr ep .1 132.17 0\n" 79 | "gpr ae .1 132.18 0\n" 80 | "gpr id .1 132.19 0\n" 81 | "flg cy .1 132.28 0\n" 82 | "flg ov .1 132.29 0\n" 83 | "flg s .1 132.30 0\n" 84 | "flg z .1 132.31 0\n"; 85 | 86 | return r_reg_set_profile_string (anal->reg, p); 87 | } 88 | 89 | RAnalPlugin r_anal_plugin_hexagon = { 90 | .name = "hexagon", 91 | .desc = "Qualcomm Hexagon (QDSP6) V6", 92 | .license = "LGPL3", 93 | .arch = "hexagon", 94 | .bits = 32, 95 | .op = hexagon_v6_op, 96 | .esil = true, 97 | .set_reg_profile = set_reg_profile, 98 | }; 99 | 100 | #ifndef R2_PLUGIN_INCORE 101 | R_API RLibStruct radare_plugin = { 102 | .type = R_LIB_TYPE_ANAL, 103 | .data = &r_anal_plugin_hexagon_v6, 104 | .version = R2_VERSION 105 | }; 106 | #endif 107 | -------------------------------------------------------------------------------- /r2/hexagon.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "hexagon.h" 8 | 9 | // TODO: Handle also control reg pairs 10 | char* hex_get_cntl_reg(int opreg){ 11 | switch (opreg) { 12 | case HEX_REG_SA0: 13 | return "SA0"; 14 | case HEX_REG_LC0: 15 | return "LC0"; 16 | case HEX_REG_SA1: 17 | return "SA1"; 18 | case HEX_REG_LC1: 19 | return "LC1"; 20 | case HEX_REG_P: 21 | return "P"; 22 | case HEX_REG_M0: 23 | return "M0"; 24 | case HEX_REG_M1: 25 | return "M1"; 26 | case HEX_REG_USR: 27 | return "USR"; 28 | case HEX_REG_PC: 29 | return "PC"; 30 | case HEX_REG_UGP: 31 | return "UGP"; 32 | case HEX_REG_GP: 33 | return "GP"; 34 | case HEX_REG_CS0: 35 | return "CS0"; 36 | case HEX_REG_CS1: 37 | return "CS1"; 38 | case HEX_REG_UPCYCLELO: 39 | return "UPCYCLELO"; 40 | case HEX_REG_UPCYCLEHI: 41 | return "UPCYCLEHI"; 42 | case HEX_REG_FRAMELIMIT: 43 | return "FRAMELIMIT"; 44 | case HEX_REG_FRAMEKEY: 45 | return "FRAMEKEY"; 46 | case HEX_REG_PKTCOUNTLO: 47 | return "PKTCOUNTLO"; 48 | case HEX_REG_PKTCOUNTHI: 49 | return "PKTCOUNTHI"; 50 | case HEX_REG_UTIMERLO: 51 | return "UTIMERLO"; 52 | case HEX_REG_UTIMERHI: 53 | return "UTIMERHI"; 54 | default: 55 | return ""; 56 | } 57 | } 58 | 59 | char* hex_get_sys_reg(int opreg) 60 | { 61 | static char tmp[5]; 62 | switch (opreg) { 63 | case HEX_REG_SGP0: 64 | return "SGP0"; 65 | case HEX_REG_SGP1: 66 | return "SGP1"; 67 | case HEX_REG_STID: 68 | return "STID"; 69 | case HEX_REG_ELR: 70 | return "ELR"; 71 | case HEX_REG_BADVA0: 72 | return "BADVA0"; 73 | case HEX_REG_BADVA1: 74 | return "BADVA1"; 75 | case HEX_REG_SSR: 76 | return "SSR"; 77 | case HEX_REG_CCR: 78 | return "CCR"; 79 | case HEX_REG_HTID: 80 | return "HTID"; 81 | case HEX_REG_BADVA: 82 | return "BADVA"; 83 | case HEX_REG_IMASK: 84 | return "IMASK"; 85 | case HEX_REG_EVB: 86 | return "EVB"; 87 | case HEX_REG_MODECTL: 88 | return "MODECTL"; 89 | case HEX_REG_SYSCFG: 90 | return "SYSCFG"; 91 | case HEX_REG_IPEND: 92 | return "IPEND"; 93 | case HEX_REG_VID: 94 | return "VID"; 95 | case HEX_REG_IAD: 96 | return "IAD"; 97 | case HEX_REG_IEL: 98 | return "IEL"; 99 | case HEX_REG_IAHL: 100 | return "IAHL"; 101 | case HEX_REG_CFGBASE: 102 | return "CFGBASE"; 103 | case HEX_REG_DIAG: 104 | return "DIAG"; 105 | case HEX_REG_REV: 106 | return "REV"; 107 | case HEX_REG_PCYCLELO: 108 | return "PCYCLELO"; 109 | case HEX_REG_PCYCLEHI: 110 | return "PCYCLEHI"; 111 | case HEX_REG_ISDBST: 112 | return "ISDBST"; 113 | case HEX_REG_ISDBCFG0: 114 | return "ISDBCFG0"; 115 | case HEX_REG_ISDBCFG1: 116 | return "ISDBCFG1"; 117 | case HEX_REG_BRKPTPC0: 118 | return "BRKPTPC0"; 119 | case HEX_REG_BRKPTCFG0: 120 | return "BRKPTCFG0"; 121 | case HEX_REG_BRKPTPC1: 122 | return "BRKPTPC1"; 123 | case HEX_REG_BRKPTCFG1: 124 | return "BRKPTCFG1"; 125 | case HEX_REG_ISDBMBXIN: 126 | return "ISDBMBXIN"; 127 | case HEX_REG_ISDBMBXOUT: 128 | return "ISDBMBXOUT"; 129 | case HEX_REG_ISDBEN: 130 | return "ISDBEN"; 131 | case HEX_REG_ISDBGPR: 132 | return "ISDBGPR"; 133 | case HEX_REG_PMUCNT0: 134 | return "PMUCNT0"; 135 | case HEX_REG_PMUCNT1: 136 | return "PMUCNT1"; 137 | case HEX_REG_PMUCNT2: 138 | return "PMUCNT2"; 139 | case HEX_REG_PMUCNT3: 140 | return "PMUCNT3"; 141 | case HEX_REG_PMUEVTCFG: 142 | return "PMUEVTCFG"; 143 | case HEX_REG_PMUCFG: 144 | return "PMUCFG"; 145 | default: 146 | sprintf(tmp, "S%d", opreg); 147 | return tmp; 148 | } 149 | } 150 | 151 | char* hex_get_sub_reg(int opreg) 152 | { 153 | switch (opreg) { 154 | case HEX_SUB_REG_R0: 155 | return "R0"; 156 | case HEX_SUB_REG_R1: 157 | return "R1"; 158 | case HEX_SUB_REG_R2: 159 | return "R2"; 160 | case HEX_SUB_REG_R3: 161 | return "R3"; 162 | case HEX_SUB_REG_R4: 163 | return "R4"; 164 | case HEX_SUB_REG_R5: 165 | return "R5"; 166 | case HEX_SUB_REG_R6: 167 | return "R6"; 168 | case HEX_SUB_REG_R7: 169 | return "R7"; 170 | case HEX_SUB_REG_R16: 171 | return "R16"; 172 | case HEX_SUB_REG_R17: 173 | return "R17"; 174 | case HEX_SUB_REG_R18: 175 | return "R18"; 176 | case HEX_SUB_REG_R19: 177 | return "R19"; 178 | case HEX_SUB_REG_R20: 179 | return "R20"; 180 | case HEX_SUB_REG_R21: 181 | return "R21"; 182 | case HEX_SUB_REG_R22: 183 | return "R22"; 184 | case HEX_SUB_REG_R23: 185 | return "R23"; 186 | default: 187 | return ""; 188 | } 189 | } 190 | 191 | char* hex_get_sub_regpair(int opreg) 192 | { 193 | switch (opreg) { 194 | case HEX_SUB_REGPAIR_R1_R0: 195 | return "R1:R0"; 196 | case HEX_SUB_REGPAIR_R3_R2: 197 | return "R3:R2"; 198 | case HEX_SUB_REGPAIR_R5_R4: 199 | return "R5:R4"; 200 | case HEX_SUB_REGPAIR_R7_R6: 201 | return "R7:R6"; 202 | case HEX_SUB_REGPAIR_R17_R16: 203 | return "R17:R16"; 204 | case HEX_SUB_REGPAIR_R19_R18: 205 | return "R19:R18"; 206 | case HEX_SUB_REGPAIR_R21_R20: 207 | return "R21:R20"; 208 | case HEX_SUB_REGPAIR_R23_R22: 209 | return "R23:R22"; 210 | default: 211 | return ""; 212 | } 213 | } 214 | 215 | inline bool hex_if_duplex(uint32_t insn_word) 216 | { 217 | if ((insn_word & (3 << 14)) == 0) { 218 | return true; 219 | } 220 | return false; 221 | } 222 | 223 | // Constant extender value 224 | ut32 constant_extender = 1; 225 | 226 | void hex_op_extend(HexOp *op) 227 | { 228 | if ((constant_extender != 1) && (op->type == HEX_OP_TYPE_IMM)) { 229 | op->op.imm = ((op->op.imm) & 0x3F) | (constant_extender); 230 | } 231 | constant_extender = 1; 232 | } 233 | 234 | void hex_op_extend_off(HexOp *op, int offset) 235 | { 236 | if ((constant_extender != 1) && (op->type == HEX_OP_TYPE_IMM)) { 237 | op->op.imm = (op->op.imm) >> offset; 238 | hex_op_extend(op); 239 | } 240 | } 241 | 242 | 243 | -------------------------------------------------------------------------------- /r2/hexagon.h: -------------------------------------------------------------------------------- 1 | // Predicates - declare the predicate state 2 | 3 | #ifndef HEXAGON_H 4 | #define HEXAGON_H 5 | 6 | typedef enum { 7 | HEX_NOPRED, // no conditional execution 8 | HEX_PRED_TRUE, // if (Pd) ... 9 | HEX_PRED_FALSE, // if (!Pd) ... 10 | HEX_PRED_TRUE_NEW, // if (Pd.new) ... 11 | HEX_PRED_FALSE_NEW, // if (!Pd.new) ... 12 | } HexPred; 13 | 14 | // Pre/post-fixes, different types 15 | typedef enum { 16 | HEX_PF_RND = 1, // :rnd 17 | HEX_PF_CRND = 1<<1, // :crnd 18 | HEX_PF_RAW = 1<<2, // :raw 19 | HEX_PF_CHOP = 1<<3, // :chop 20 | HEX_PF_SAT = 1<<4, // :sat 21 | HEX_PF_HI = 1<<5, // :hi 22 | HEX_PF_LO = 1<<6, // :lo 23 | HEX_PF_LSH1 = 1<<7, // :<<1 24 | HEX_PF_LSH16 = 1<<8, // :<<16 25 | HEX_PF_RSH1 = 1<<9, // :>>1 26 | HEX_PF_NEG = 1<<10, // :neg 27 | HEX_PF_POS = 1<<11, // :pos 28 | HEX_PF_SCALE = 1<<12, // :scale, for FMA instructions 29 | HEX_PF_DEPRECATED = 1<<15, // :deprecated 30 | } HexPf; 31 | 32 | typedef enum { 33 | HEX_OP_TYPE_IMM, 34 | HEX_OP_TYPE_REG, 35 | HEX_OP_TYPE_PREDICATE, 36 | HEX_OP_TYPE_CONTROL, 37 | HEX_OP_TYPE_SYSTEM, 38 | HEX_OP_TYPE_OPT, // Do not really use in the C code 39 | } HexOpType; 40 | 41 | // Attributes - .H/.L, const extender 42 | typedef enum { 43 | HEX_OP_CONST_EXT = 1 << 0, // Constant extender marker for Immediate 44 | HEX_OP_REG_HI = 1 << 1, // Rn.H marker 45 | HEX_OP_REG_LO = 1 << 2, // Rn.L marker 46 | HEX_OP_REG_PAIR = 1 << 3, // Is this a register pair? 47 | } HexOpAttr; 48 | 49 | typedef struct { 50 | ut8 type; 51 | union { 52 | ut8 reg; // + additional Hi or Lo selector // + additional shift // + additional :brev // 53 | ut32 imm; 54 | ut8 pred; // predicates - P0-P3 registers 55 | ut8 cr; // control register 56 | ut8 sys; // system control register 57 | } op; 58 | ut8 attr; 59 | } HexOp; 60 | 61 | typedef struct { 62 | int instruction; 63 | ut32 mask; 64 | HexPred predicate; // predicate set if set 65 | ut16 pf; // additional prefixes (bitmap) 66 | bool duplex; // is part of duplex container? 67 | bool compound; // is part of compound instruction? 68 | bool last; // is last in instruction packet? 69 | int shift; // Optional shift left is it true? 70 | ut8 op_count; 71 | HexOp ops[6]; 72 | char mnem[128]; // Instruction mnemonic 73 | } HexInsn; 74 | 75 | // Instruction container (currently only 2 instructions) 76 | // Can handle duplexes 77 | typedef struct { 78 | bool duplex; 79 | HexInsn ins[2]; // Or make it pointer + size? 80 | } HexInsnCont; 81 | 82 | // Instruction packet (Maximum - 4 instructions) 83 | // Can handle up to 4 instructions or 1 duplex + 2 instructions 84 | // Can have a loop marks 85 | typedef struct { 86 | bool loop0; // :endloop0 marker 87 | bool loop1; // :endloop1 marker 88 | int cont_cnt; 89 | HexInsnCont ins[4]; // Or make it pointer + size? 90 | } HexInsnPkt; 91 | 92 | typedef enum { 93 | HEX_INSN_CLASS_CEXT = 0, // Constant extender 94 | HEX_INSN_CLASS_J1 = 1, // Jump 95 | HEX_INSN_CLASS_J2 = 2, // Jump 96 | HEX_INSN_CLASS_LD_ST = 3, // Load/Store 97 | HEX_INSN_CLASS_LD_ST_COND_GP = 4, // Load/Store conditional or GP relative 98 | HEX_INSN_CLASS_J3 = 5, // Jump 99 | HEX_INSN_CLASS_CR = 6, // Control register instructions 100 | HEX_INSN_CLASS_ALU32 = 7, // ALU32 101 | HEX_INSN_CLASS_XTYPE = 8, // XTYPE 102 | HEX_INSN_CLASS_LD = 9, // Just load instructions 103 | HEX_INSN_CLASS_ST = 10, // Just store instructions 104 | HEX_INSN_CLASS_ALU32_1 = 11, // ALU32 105 | HEX_INSN_CLASS_XTYPE_1 = 12, // XTYPE again 106 | HEX_INSN_CLASS_XTYPE_2 = 13, // XTYPE one more time 107 | HEX_INSN_CLASS_XTYPE_3 = 14, // And again, XTYPE 108 | HEX_INSN_CLASS_ALU32_2 = 12, // ALU32 again 109 | } HEX_INSN_CLASS; 110 | 111 | typedef enum { 112 | HEX_REG_R0 = 0, 113 | HEX_REG_R1 = 1, 114 | HEX_REG_R2 = 2, 115 | HEX_REG_R3 = 3, 116 | HEX_REG_R4 = 4, 117 | HEX_REG_R5 = 5, 118 | HEX_REG_R6 = 6, 119 | HEX_REG_R7 = 7, 120 | HEX_REG_R8 = 8, 121 | HEX_REG_R9 = 9, 122 | HEX_REG_R10 = 10, 123 | HEX_REG_R11 = 11, 124 | HEX_REG_R12 = 12, 125 | HEX_REG_R13 = 13, 126 | HEX_REG_R14 = 14, 127 | HEX_REG_R15 = 15, 128 | HEX_REG_R16 = 16, 129 | HEX_REG_R17 = 17, 130 | HEX_REG_R18 = 18, 131 | HEX_REG_R19 = 19, 132 | HEX_REG_R20 = 20, 133 | HEX_REG_R21 = 21, 134 | HEX_REG_R22 = 22, 135 | HEX_REG_R23 = 23, 136 | HEX_REG_R24 = 24, 137 | HEX_REG_R25 = 25, 138 | HEX_REG_R26 = 26, 139 | HEX_REG_R27 = 27, 140 | HEX_REG_R28 = 28, 141 | HEX_REG_R29 = 29, 142 | HEX_REG_R30 = 30, 143 | HEX_REG_R31 = 31, 144 | } HEX_REG; 145 | 146 | // TODO: Also add regpair values 147 | 148 | // Control registers 149 | typedef enum { 150 | // Loop registers 151 | HEX_REG_SA0 = 0, // C0 152 | HEX_REG_LC0 = 1, // C1 153 | HEX_REG_SA1 = 2, // C2 154 | HEX_REG_LC1 = 3, // C3 155 | HEX_REG_P = 4, // C4 - 4 of 8bit registers 156 | // C5 is reserved 157 | // Modifier registers 158 | HEX_REG_M0 = 6, // C6 159 | HEX_REG_M1 = 7, // C7 160 | HEX_REG_USR = 8, // C8 // User Status Register 161 | HEX_REG_PC = 9, // C9 // Program counter 162 | HEX_REG_UGP = 10, // C10 // User General Pointer 163 | HEX_REG_GP = 11, // C11 // Global Pointer 164 | // Circular Start registers 165 | HEX_REG_CS0 = 12, // C12 166 | HEX_REG_CS1 = 13, // C13 167 | // Cycle Count registers 168 | HEX_REG_UPCYCLELO = 14, // C14 169 | HEX_REG_UPCYCLEHI = 15, // C15 170 | HEX_REG_FRAMELIMIT = 16, // C16 // Stack Bounds register 171 | HEX_REG_FRAMEKEY = 17, // C17 // Stack Smash register 172 | // Packet Count registers 173 | HEX_REG_PKTCOUNTLO = 18, // C18 174 | HEX_REG_PKTCOUNTHI = 19, // C19 175 | // C20 - C29 are reserved 176 | // Qtimer registers 177 | HEX_REG_UTIMERLO = 30, // C30 178 | HEX_REG_UTIMERHI = 31, // C31 179 | } HEX_CR_REG; 180 | 181 | // Supervisor control registers 182 | typedef enum { 183 | HEX_REG_SGP0 = 0, // S0 184 | HEX_REG_SGP1 = 1, // S1 185 | HEX_REG_STID = 2, // S2 186 | HEX_REG_ELR = 3, // S3 187 | HEX_REG_BADVA0 = 4, // S4 188 | HEX_REG_BADVA1 = 5, // S5 189 | HEX_REG_SSR = 6, // S6 190 | HEX_REG_CCR = 7, // S7 191 | HEX_REG_HTID = 8, // S8 192 | HEX_REG_BADVA = 9, // S9 193 | HEX_REG_IMASK = 10, // S10 194 | // S11 - S15 are reserved 195 | HEX_REG_EVB = 16, // S16 196 | HEX_REG_MODECTL = 17, // S17 197 | HEX_REG_SYSCFG = 18, // S18 198 | // S19 is reserved 199 | HEX_REG_IPEND = 20, // S20 200 | HEX_REG_VID = 21, // S21 201 | HEX_REG_IAD = 22, // S22 202 | // S23 is reserved 203 | HEX_REG_IEL = 24, // S24 204 | // S25 is reserved 205 | HEX_REG_IAHL = 26, // S26 206 | HEX_REG_CFGBASE = 27, // S27 207 | HEX_REG_DIAG = 28, // S28 208 | HEX_REG_REV = 29, // S29 209 | HEX_REG_PCYCLELO = 30, // S30 210 | HEX_REG_PCYCLEHI = 31, // S31 211 | HEX_REG_ISDBST = 32, // S32 212 | HEX_REG_ISDBCFG0 = 33, // S33 213 | HEX_REG_ISDBCFG1 = 34, // S34 214 | // S35 is reserved 215 | HEX_REG_BRKPTPC0 = 36, // S36 216 | HEX_REG_BRKPTCFG0 = 37, // S37 217 | HEX_REG_BRKPTPC1 = 38, // S38 218 | HEX_REG_BRKPTCFG1 = 39, // S39 219 | HEX_REG_ISDBMBXIN = 40, // S40 220 | HEX_REG_ISDBMBXOUT = 41, // S41 221 | HEX_REG_ISDBEN = 42, // S42 222 | HEX_REG_ISDBGPR = 43, // S43 223 | // S44 - S47 are reserved 224 | HEX_REG_PMUCNT0 = 48, // S48 225 | HEX_REG_PMUCNT1 = 49, // S49 226 | HEX_REG_PMUCNT2 = 50, // S50 227 | HEX_REG_PMUCNT3 = 51, // S51 228 | HEX_REG_PMUEVTCFG = 52, // S52 229 | HEX_REG_PMUCFG = 53, // S53 230 | // S54 - S63 are reserved 231 | } HEX_SYSCR_REG; 232 | 233 | // Here are the register field values for subinstructions 234 | 235 | typedef enum { 236 | HEX_SUB_REG_R0 = 0, // 0b0000 237 | HEX_SUB_REG_R1 = 1, // 0b0001 238 | HEX_SUB_REG_R2 = 2, // 0b0010 239 | HEX_SUB_REG_R3 = 3, // 0b0011 240 | HEX_SUB_REG_R4 = 4, // 0b0100 241 | HEX_SUB_REG_R5 = 5, // 0b0101 242 | HEX_SUB_REG_R6 = 6, // 0b0110 243 | HEX_SUB_REG_R7 = 7, // 0b0111 244 | HEX_SUB_REG_R16 = 8, // 0b1000 245 | HEX_SUB_REG_R17 = 9, // 0b1001 246 | HEX_SUB_REG_R18 = 10, // 0b1010 247 | HEX_SUB_REG_R19 = 11, // 0b1011 248 | HEX_SUB_REG_R20 = 12, // 0b1100 249 | HEX_SUB_REG_R21 = 13, // 0b1101 250 | HEX_SUB_REG_R22 = 14, // 0b1110 251 | HEX_SUB_REG_R23 = 15, // 0b1111 252 | } HEX_SUB_REG; 253 | 254 | 255 | typedef enum { 256 | HEX_SUB_REGPAIR_R1_R0 = 0, // 0b000 257 | HEX_SUB_REGPAIR_R3_R2 = 1, // 0b001 258 | HEX_SUB_REGPAIR_R5_R4 = 2, // 0b010 259 | HEX_SUB_REGPAIR_R7_R6 = 3, // 0b011 260 | HEX_SUB_REGPAIR_R17_R16 = 4, // 0b100 261 | HEX_SUB_REGPAIR_R19_R18 = 5, // 0b101 262 | HEX_SUB_REGPAIR_R21_R20 = 6, // 0b110 263 | HEX_SUB_REGPAIR_R23_R22 = 7, // 0b111 264 | } HEX_SUB_REGPAIR; 265 | 266 | 267 | #define BIT_MASK(len) (BIT(len)-1) 268 | #define BF_MASK(start, len) (BIT_MASK(len)<<(start)) 269 | #define BF_PREP(x, start, len) (((x)&BIT_MASK(len))<<(start)) 270 | #define BF_GET(y, start, len) (((y)>>(start)) & BIT_MASK(len)) 271 | #define BF_GETB(y, start, end) (BF_GET((y), (start), (end) - (start) + 1) 272 | 273 | char* hex_get_cntl_reg(int opreg); 274 | char* hex_get_sys_reg(int opreg); 275 | char* hex_get_sub_reg(int opreg); 276 | char* hex_get_sub_regpair(int opreg); 277 | bool hex_if_duplex(ut32 insn_word); 278 | void hex_op_extend(HexOp *op); 279 | void hex_op_extend_off(HexOp *op, int offset); 280 | int hexagon_disasm_instruction(ut32 hi_u32, HexInsn *hi, ut32 addr); 281 | 282 | #endif 283 | -------------------------------------------------------------------------------- /const_extenders.txt: -------------------------------------------------------------------------------- 1 | call #r22:2 // + 2 | if (!cmp.eq(Ns.new,#U5)) jump:nt #r9:2 // + 3 | if (cmp.eq(Ns.new,#U5)) jump:nt #r9:2 // + 4 | if (!cmp.eq(Ns.new,#U5)) jump:t #r9:2 // + 5 | if (cmp.eq(Ns.new,#U5)) jump:t #r9:2 // + 6 | if (!cmp.gt(Ns.new,#U5)) jump:nt #r9:2 // + 7 | if (cmp.gt(Ns.new,#U5)) jump:nt #r9:2 // + 8 | if (!cmp.gt(Ns.new,#U5)) jump:t #r9:2 // + 9 | if (cmp.gt(Ns.new,#U5)) jump:t #r9:2 // + 10 | if (!cmp.gtu(Ns.new,##U5)) jump:nt #r9:2 // + 11 | if (cmp.gtu(Ns.new,##U5)) jump:nt #r9:2 // + 12 | if (!cmp.gtu(Ns.new,##U5)) jump:t #r9:2 // + 13 | if (cmp.gtu(Ns.new,##U5)) jump:t #r9:2 // + 14 | if !Ps memw(Rs + #u6) = ##U32 // + 15 | if Ps memw(Rs + #u6) = ##U32 // + 16 | if (!Pt) memb(#u6) = Nt.new // + 17 | if (Pt) memb(#u6) = Nt.new // + 18 | if (!Pt) memb(#u6) = Rt // + 19 | if (Pt) memb(#u6) = Rt // + 20 | if (!Pt) memd(Rs + ##U32) = Ntt.new // + 21 | if (Pt) memd(Rs + ##U32) = Ntt.new // + 22 | if (!Pt) memd(#u6) = Rt.new // + 23 | if (Pt) memd(#u6) = Rt.new // + 24 | if (!Pt) memd(#u6) = Rtt // + 25 | if (Pt) memd(#u6) = Rtt // + 26 | if (!Pt) memh(#u6) = Nt.new // + 27 | if (Pt) memh(#u6) = Nt.new // + 28 | if (!Pt) memh(#u6) = Rt // + 29 | if (Pt) memh(#u6) = Rt // + 30 | if (!Pt) memw(Rs + ##U32) = Rt.new // + 31 | if (Pt) memw(Rs + ##U32) = Rt.new // + 32 | if (!Pt) memw(#u6) = Nt.new // + 33 | if (Pt) memw(#u6) = Nt.new // + 34 | if (!Pt) memw(#u6) = Rt // + 35 | if (Pt) memw(#u6) = Rt // + 36 | if (!Pt.new) memd(Rs + ##U32) = Ntt.new // + 37 | if (Pt.new) memd(Rs + ##U32) = Ntt.new // + 38 | if (!Pt.new) memw(Rs + ##U32) = Rt.new // + 39 | if (Pt.new) memw(Rs + ##U32) = Rt.new // + 40 | if (!Pt.new) memw(Rs + #u6:2) = Rt // + 41 | if (Pt.new) memw(Rs + #u6:2) = Rt // + 42 | if (!Pt.new) Rdd = memd (Rs + #u6:3) // + 43 | if (Pt.new) Rdd = memd (Rs + #u6:3) // + 44 | if (!Pt.new) Rdd = memd (#u6) // + 45 | if (Pt.new) Rdd = memd (#u6) // + 46 | if (!Pt.new) Rd = memb (Rs + #u6:0) // + 47 | if (Pt.new) Rd = memb (Rs + #u6:0) // + 48 | if (!Pt.new) Rd = memb (#u6) // + 49 | if (Pt.new) Rd = memb (#u6) // + 50 | if (!Pt.new) Rd = memh (Rs + #u6:1) // + 51 | if (Pt.new) Rd = memh (Rs + #u6:1) // + 52 | if (!Pt.new) Rd = memh (#u6) // + 53 | if (Pt.new) Rd = memh (#u6) // + 54 | if (!Pt.new) Rd = memub (Rs + #u6:0) // + 55 | if (Pt.new) Rd = memub (Rs + #u6:0) // + 56 | if (!Pt.new) Rd = memub (#u6) // + 57 | if (Pt.new) Rd = memub (#u6) // + 58 | if (!Pt.new) Rd = memuh (Rs + #u6:1) // + 59 | if (Pt.new) Rd = memuh (Rs + #u6:1) // + 60 | if (!Pt.new) Rd = memuh (#u6) // + 61 | if (Pt.new) Rd = memuh (#u6) // + 62 | if (!Pt.new) Rd = memw (Rs + #u6:2) // + 63 | if (Pt.new) Rd = memw (Rs + #u6:2) // + 64 | if (!Pt.new) Rd = memw (#u6) // + 65 | if (Pt.new) Rd = memw (#u6) // + 66 | if (!Pt) Rdd = memd (Rs + #u6:3) // + 67 | if (Pt) Rdd = memd (Rs + #u6:3) // + 68 | if (!Pt) Rdd = memd (#u6) // + 69 | if (Pt) Rdd = memd (#u6) // + 70 | if (!Pt) Rd = memb (Rs + #u6:0) // + 71 | if (Pt) Rd = memb (Rs + #u6:0) // + 72 | if (!Pt) Rd = memb (#u6) // + 73 | if (Pt) Rd = memb (#u6) // + 74 | if (!Pt) Rd = memh (Rs + #u6:1) // + 75 | if (Pt) Rd = memh (Rs + #u6:1) // + 76 | if (!Pt) Rd = memh (#u6) // + 77 | if (Pt) Rd = memh (#u6) // + 78 | if (!Pt) Rd = memub (Rs + #u6:0) // + 79 | if (Pt) Rd = memub (Rs + #u6:0) // + 80 | if (!Pt) Rd = memub (#u6) // + 81 | if (Pt) Rd = memub (#u6) // + 82 | if (!Pt) Rd = memuh (Rs + #u6:1) // + 83 | if (Pt) Rd = memuh (Rs + #u6:1) // + 84 | if (!Pt) Rd = memuh (#u6) // + 85 | if (Pt) Rd = memuh (#u6) // + 86 | if (!Pt) Rd = memw (Rs + #u6:2) // + 87 | if (Pt) Rd = memw (Rs + #u6:2) // + 88 | if (!Pt) Rd = memw (#u6) // + 89 | if (Pt) Rd = memw (#u6) // + 90 | if (!Pu) call #r15:2 // + 91 | if (Pu) call #r15:2 // + 92 | if (!Pu.new) Rd = add(Rs,#s8) // + 93 | if (Pu.new) Rd = add(Rs,#s8) // + 94 | if (!Pu.new) Rd = #s12 // + 95 | if (Pu.new) Rd = #s12 // + 96 | if (!Pu) Rd = add(Rs,#s8) // + 97 | if (Pu) Rd = add(Rs,#s8) // + 98 | if (!Pu) Rd = #s12 // + 99 | if (Pu) Rd = #s12 // + 100 | if (!Pv) memw(#u6) = Rt // + 101 | if (Pv) memw(#u6) = Rt // + 102 | if (!Pv) memw(#u6) = Nt.new // + 103 | if (Pv) memw(#u6) = Nt.new // + 104 | if (!Pv) memb(Rs + #u6:0) = Rt // + 105 | if (Pv) memb(Rs + #u6:0) = Rt // + 106 | if (!Pv) memb(Rs + #u6:0) = Rt.new // + 107 | if (Pv) memb(Rs + #u6:0) = Rt.new // + 108 | if (!Pv) memd(Rs + #u6:3) = Rtt // + 109 | if (Pv) memd(Rs + #u6:3) = Rtt // + 110 | if (!Pv) memh(Rs + #u6:1) = Rt // + 111 | if (Pv) memh(Rs + #u6:1) = Rt // + 112 | if (!Pv) memh(Rs + #u6:1) = Rt.new // + 113 | if (Pv) memh(Rs + #u6:1) = Rt.new // + 114 | if (!Pv) memw(Rs + #u6:2) = Rt // + 115 | if (Pv) memw(Rs + #u6:2) = Rt // + 116 | if (!Pv.new) memw(#u6) = Rt // + 117 | if (Pv.new) memw(#u6) = Rt // + 118 | if (!Pv.new) memw(#u6) = Nt.new // + 119 | if (Pv.new) memw(#u6) = Nt.new // + 120 | if (!Pv.new) memb(Rs + #u6:0) = Rt // + 121 | if (Pv.new) memb(Rs + #u6:0) = Rt // + 122 | if (!Pv.new) memb(Rs + #u6:0) = Rt.new // + 123 | if (Pv.new) memb(Rs + #u6:0) = Rt.new // + 124 | if (!Pv.new) memd(Rs + #u6:3) = Rtt // + 125 | if (Pv.new) memd(Rs + #u6:3) = Rtt // + 126 | if (!Pv.new) memh(Rs + #u6:1) = Rt // + 127 | if (Pv.new) memh(Rs + #u6:1) = Rt // + 128 | if (!Pv.new) memh(Rs + #u6:1) = Rt.new // + 129 | if (Pv.new) memh(Rs + #u6:1) = Rt.new // + 130 | if (!Pv.new) memw(Rs + #u6:2) = Rt // + 131 | if (Pv.new) memw(Rs + #u6:2) = Rt // + 132 | jump #r22:2 // + 133 | loop0 (#r7:2,Rs) // + 134 | loop0 (#r7:2,#U10) // + 135 | loop1 (#r7:2,Rs) // + 136 | loop1 (#r7:2,#U10) // + 137 | memb(gp+#u16:0) = Nt.new // + 138 | memb(gp+#u16:0) = Rt // + 139 | memb(Re=##U32) = Rt.new // + 140 | memb(Re=#U6) = Rt // + 141 | memb(Rs + #s11:0) = Nt.new // + 142 | memb(Rs + #s11:0) = Rt // + 143 | memb(Rs + #u6:0) = #S8 // + 144 | memb(Ru<<#u2 + #U6) = Nt.new // + 145 | memb(Ru<<#u2 + #U6) = Rt // + 146 | memd(gp+#u16:0) = Nt.new // + 147 | memd(gp+#u16:0) = Rtt // + 148 | memd(Re=##U32) = Rt.new // + 149 | memd(Re=#U6) = Rtt // + 150 | memd(Rs + #s11:3) = Ntt.new // + 151 | memd(Rs + #s11:3) = Rtt // + 152 | memd(Ru<<#u2 + #U6) = Nt.new // + 153 | memd(Ru<<#u2 + #U6) = Rtt // + 154 | memh(gp+#u16:0) = Nt.new // + 155 | memh(gp+#u16:0) = Rt // + 156 | memh(Re=##U32) = Rt.new // + 157 | memh(Re=#U6) = Rt // + 158 | memh(Rs + #s11:1) = Nt.new // + 159 | memh(Rs + #s11:1) = Rt // + 160 | memh(Rs + #u6:1) = #S8 // + 161 | memh(Ru<<#u2 + #U6) = Nt.new // + 162 | memh(Ru<<#u2 + #U6) = Rt // + 163 | memw(gp+#u16:0) = Nt.new // + 164 | memw(gp+#u16:0) = Rt // + 165 | memw(Re=##U32) = Rt.new // + 166 | memw(Re=#U6) = Rt // + 167 | memw(Rs + Rt<<#u2) = ##U32 // + 168 | memw(Rs + #s11:2) = Nt.new // + 169 | memw(Rs + #s11:2) = Rt // + 170 | memw(Rs + #u6:2) = #S8 // + 171 | memw(Rs + #u6) = ##U32 // + 172 | memw(Ru<<#u2 + #U6) = Nt.new // + 173 | memw(Ru<<#u2 + #U6) = Rt // + 174 | Pd = cmpb.eq (Rs,#u8) // + 175 | Pd = cmpb.gt (Rs,#s8) // + 176 | Pd = cmpb.gtu (Rs,#u7) // + 177 | Pd = !cmp.eq (Rs,#s10) // + 178 | Pd = cmp.eq (Rs,#s10) // + 179 | Pd = !cmp.gt (Rs,#s10) // + 180 | Pd = cmp.gt (Rs,#s10) // + 181 | Pd = !cmp.gtu (Rs,#u9) // + 182 | Pd = cmp.gtu (Rs,#u9) // + 183 | Pd = cmph.eq (Rs,#s8) // + 184 | Pd = cmph.gt (Rs,#s8) // + 185 | Pd = cmph.gtu (Rs,#u7) // + 186 | Pd = sp1loop0(#r7:2,Rs) // + 187 | Pd = sp1loop0(#r7:2,#U10) // + 188 | Pd = sp2loop0(#r7:2,Rs) // + 189 | Pd = sp2loop0(#r7:2,#U10) // + 190 | Pd = sp3loop0(#r7:2,Rs) // + 191 | Pd = sp3loop0(#r7:2,#U10) // + 192 | Rd = add(#6,mpyi(Rs,Rt)) // + 193 | Rd = add(pc,#u6) // + 194 | Rd = add(Rs,add(Ru,#s6)) // + 195 | Rd = add(Rs,#s16) // + 196 | Rd = add(Rs,sub(#s6,Ru)) // + 197 | Rd = add(#u6,mpyi(Rs,#u6)) // + 198 | Rd = and(Rs,#s10) // + 199 | Rd = !cmp.eq(Rs,#s8) // + 200 | Rd = cmp.eq(Rs,#s8) // + 201 | Rdd = combine(Rs,#s8) // + 202 | Rdd = combine(#s8,Rs) // + 203 | Rdd = combine(#s8,#s8) // + 204 | Rdd = combine (#s8,#S8) // + 205 | Rdd = combine(#s8,#U6) // + 206 | Rdd = memd (Re=#U6) // + 207 | Rdd = memd (Rs + #s11:3) // + 208 | Rdd = memd (Rt<<#u2 + #U6) // + 209 | Rd = memb (Re=#U6) // + 210 | Rd = memb (Rs + #s11:0) // + 211 | Rd = memb (Rt<<#u2 + #U6) // + 212 | Rd = memb(##U32) // + 213 | Rd = memd(##U32) // + 214 | Rd = memh (Re=#U6) // + 215 | Rd = memh (Rs + #s11:1) // + 216 | Rd = memh (Rt<<#u2 + #U6) // + 217 | Rd = memh(##U32) // + 218 | Rd = memub (Re=#U6) // + 219 | Rd = memub (Rs + #s11:0) // + 220 | Rd = memub (Rt<<#u2 + #U6) // + 221 | Rd = memub(##U32) // + 222 | Rd = memuh (Re=#U6) // + 223 | Rd = memuh (Rs + #s11:1) // + 224 | Rd = memuh (Rt<<#u2 + #U6) // + 225 | Rd = memuh(##U32) // + 226 | Rd = memw (Re=#U6) // + 227 | Rd = memw (Rs + #s11:2) // + 228 | Rd = memw (Rt<<#u2 + #U6) // + 229 | Rd = memw(##U32) // + 230 | Rd = memw (gp + #u16:2) // + 231 | Rd = memw (Re=#U6) // + 232 | Rd = memw (Rs + #s11:2) // + 233 | Rd = mpyi(Rs,#m9) // + 234 | Rd -= mpyi(Rs,#u8) // + 235 | Rd += mpyi(Rs,#u8) // + 236 | Rd = mux (Pu, Rs,#s8) // + 237 | Rd = mux (Pu, #s8, Rs) // + 238 | Rd = mux(Pu,#s8,#S8) // + 239 | Rd = or(Rs,#s10) // + 240 | Rd = #s16 // + 241 | Rd = sub(#s10,Rs) // + 242 | Rd = sub(##u32,add(Rs,Rt)) // Not in the manual 243 | Rx -= add(Rs,#s8) // + 244 | Rx += add(Rs,#s8) // + 245 | Rx = add (#u8,asl(Rs,Rx)) // + 246 | Rx = add (#u8,asl(Rx,Rs)) // Not in the manual 247 | Rx = add (#u8,asl(Rx,#U5)) // + 248 | Rx = add (#u8,asr(Rs,Rx)) // + 249 | Rx = add (#u8,asr(Rx,Rs)) // Not in the manual 250 | Rx = add (#u8,asr(Rx,#U5)) // + 251 | Rx = add (#u8,lsr(Rs,Rx)) // + 252 | Rx = add (#u8,lsr(Rx,Rs)) // Not in the manual 253 | Rx = add (#u8,lsr(Rx,#U5)) // + 254 | Rx = and (#u8,asl(Rs,Rx)) // + 255 | Rx = and (#u8,asl(Rx,Rs)) // Not in the manual 256 | Rx = and (#u8,asl(Rx,#U5)) // + 257 | Rx = and (#u8,asr(Rs,Rx)) // + 258 | Rx = and (#u8,asr(Rx,Rs)) // Not in the manual 259 | Rx = and (#u8,asr(Rx,#U5)) // + 260 | Rx = and (#u8,lsr(Rs,Rx)) // + 261 | Rx = and (#u8,lsr(Rx,Rs)) // Not in the manual 262 | Rx = and (#u8,lsr(Rx,#U5)) // + 263 | Rx = or(Rs,and(Rx,#s10)) // + 264 | Rx = or (#u8,asl(Rs,Rx)) // + 265 | Rx = or (#u8,asl(Rx,Rs)) // Not in the manual 266 | Rx = or (#u8,asl(Rx,#U5)) // + 267 | Rx = or (#u8,asr(Rs,Rx)) // + 268 | Rx = or (#u8,asr(Rx,Rs)) // Not in the manual 269 | Rx = or (#u8,asr(Rx,#U5)) // + 270 | Rx = or (#u8,lsr(Rs,Rx)) // + 271 | Rx = or (#u8,lsr(Rx,Rs)) // Not in the manual 272 | Rx = or (#u8,lsr(Rx,#U5)) // + 273 | Rx = sub (#u8,asl(Rs,Rx)) // + 274 | Rx = sub (#u8,asl(Rx,Rs)) // Not in the manual 275 | Rx = sub (#u8,asl(Rx,#U5)) // + 276 | Rx = sub (#u8,asr(Rs,Rx)) // Not in the manual 277 | Rx = sub (#u8,asr(Rx,Rs)) // + 278 | Rx = sub (#u8,asr(Rx,#U5)) // + 279 | Rx = sub (#u8,lsr(Rs,Rx)) // + 280 | Rx = sub (#u8,lsr(Rx,Rs)) // Not in the manual 281 | Rx = sub (#u8,lsr(Rx,#U5)) // + 282 | Rd = #u6 // Slot 1 duplex 283 | Rd = #U6 // Slot 1 duplex 284 | Re = #u6 // Slot 1 duplex 285 | Re = #U6 // Slot 1 duplex 286 | Rx = #u6 // Slot 1 duplex 287 | Rx = #U6 // Slot 1 duplex 288 | Rd = add (Rx, #s7) // Slot 1 duplex 289 | Rd = add (Rx, #S7) // Slot 1 duplex 290 | Re = add (Rx, #s7) // Slot 1 duplex 291 | Re = add (Rx, #S7) // Slot 1 duplex 292 | Rx = add (Rx, #s7) // Slot 1 duplex 293 | Rx = add (Rx, #S7) // Slot 1 duplex 294 | -------------------------------------------------------------------------------- /r2/hexagon_anal.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "hexagon.h" 8 | #include "hexagon_insn.h" 9 | 10 | int hexagon_anal_instruction(HexInsn *hi, RAnalOp *op) { 11 | switch (hi->instruction) { 12 | case HEX_INS_CALL__R22_2: { 13 | // call #r22:2 14 | op->type = R_ANAL_OP_TYPE_CALL; 15 | op->jump = op->addr + (st32) hi->ops[0].op.imm; 16 | break; 17 | } 18 | case HEX_INS_IF__PU__CALL__R15_2: { 19 | // if (Pu) call #r15:2 20 | op->type = R_ANAL_OP_TYPE_CALL; 21 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 22 | break; 23 | } 24 | case HEX_INS_IF__NOT_PU_CALL__R15_2: { 25 | // if !Pu call #r15:2 26 | op->type = R_ANAL_OP_TYPE_CALL; 27 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 28 | break; 29 | } 30 | case HEX_INS_MULT_P0___CMP_EQ__RS____1____IF__P0_NEW__JUMP_NT__R9_2: { 31 | // p0 = cmp.eq (Rs, #-1) ; if (p0.new) jump:nt #r9:2 32 | op->type = R_ANAL_OP_TYPE_CJMP; 33 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 34 | op->fail = op->addr + op->size; 35 | break; 36 | } 37 | case HEX_INS_MULT_P0___CMP_GT__RS____1____IF__P0_NEW__JUMP_NT__R9_2: { 38 | // p0 = cmp.gt (Rs, #-1) ; if (p0.new) jump:nt #r9:2 39 | op->type = R_ANAL_OP_TYPE_CJMP; 40 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 41 | op->fail = op->addr + op->size; 42 | break; 43 | } 44 | case HEX_INS_MULT_P0___TSTBIT__RS___0____IF__P0_NEW__JUMP_NT__R9_2: { 45 | // p0 = tstbit (Rs, #0) ; if (p0.new) jump:nt #r9:2 46 | op->type = R_ANAL_OP_TYPE_CJMP; 47 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 48 | op->fail = op->addr + op->size; 49 | break; 50 | } 51 | case HEX_INS_MULT_P0___CMP_EQ__RS____1____IF__P0_NEW__JUMP_T__R9_2: { 52 | // p0 = cmp.eq (Rs, #-1) ; if (p0.new) jump:t #r9:2 53 | op->type = R_ANAL_OP_TYPE_CJMP; 54 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 55 | op->fail = op->addr + op->size; 56 | break; 57 | } 58 | case HEX_INS_MULT_P0___CMP_GT__RS____1____IF__P0_NEW__JUMP_T__R9_2: { 59 | // p0 = cmp.gt (Rs, #-1) ; if (p0.new) jump:t #r9:2 60 | op->type = R_ANAL_OP_TYPE_CJMP; 61 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 62 | op->fail = op->addr + op->size; 63 | break; 64 | } 65 | case HEX_INS_MULT_P0___TSTBIT__RS___0____IF__P0_NEW__JUMP_T__R9_2: { 66 | // p0 = tstbit (Rs, #0) ; if (p0.new) jump:t #r9:2 67 | op->type = R_ANAL_OP_TYPE_CJMP; 68 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 69 | op->fail = op->addr + op->size; 70 | break; 71 | } 72 | case HEX_INS_MULT_P0___CMP_EQ__RS____1____IF___NOT_P0_NEW__JUMP_NT__R9_2: { 73 | // p0 = cmp.eq (Rs, #-1) ; if (!p0.new) jump:nt #r9:2 74 | op->type = R_ANAL_OP_TYPE_CJMP; 75 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 76 | op->fail = op->addr + op->size; 77 | break; 78 | } 79 | case HEX_INS_MULT_P0___CMP_GT__RS____1____IF___NOT_P0_NEW__JUMP_NT__R9_2: { 80 | // p0 = cmp.gt (Rs, #-1) ; if (!p0.new) jump:nt #r9:2 81 | op->type = R_ANAL_OP_TYPE_CJMP; 82 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 83 | op->fail = op->addr + op->size; 84 | break; 85 | } 86 | case HEX_INS_MULT_P0___TSTBIT__RS___0____IF___NOT_P0_NEW__JUMP_NT__R9_2: { 87 | // p0 = tstbit (Rs, #0) ; if (!p0.new) jump:nt #r9:2 88 | op->type = R_ANAL_OP_TYPE_CJMP; 89 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 90 | op->fail = op->addr + op->size; 91 | break; 92 | } 93 | case HEX_INS_MULT_P0___CMP_EQ__RS____1____IF___NOT_P0_NEW__JUMP_T__R9_2: { 94 | // p0 = cmp.eq (Rs, #-1) ; if (!p0.new) jump:t #r9:2 95 | op->type = R_ANAL_OP_TYPE_CJMP; 96 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 97 | op->fail = op->addr + op->size; 98 | break; 99 | } 100 | case HEX_INS_MULT_P0___CMP_GT__RS____1____IF___NOT_P0_NEW__JUMP_T__R9_2: { 101 | // p0 = cmp.gt (Rs, #-1) ; if (!p0.new) jump:t #r9:2 102 | op->type = R_ANAL_OP_TYPE_CJMP; 103 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 104 | op->fail = op->addr + op->size; 105 | break; 106 | } 107 | case HEX_INS_MULT_P0___TSTBIT__RS___0____IF___NOT_P0_NEW__JUMP_T__R9_2: { 108 | // p0 = tstbit (Rs, #0) ; if (!p0.new) jump:t #r9:2 109 | op->type = R_ANAL_OP_TYPE_CJMP; 110 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 111 | op->fail = op->addr + op->size; 112 | break; 113 | } 114 | case HEX_INS_MULT_P0___CMP_EQ__RS___U5____IF__P0_NEW__JUMP_NT__R9_2: { 115 | // p0 = cmp.eq (Rs, #U5) ; if (p0.new) jump:nt #r9:2 116 | op->type = R_ANAL_OP_TYPE_CJMP; 117 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 118 | op->fail = op->addr + op->size; 119 | break; 120 | } 121 | case HEX_INS_MULT_P0___CMP_EQ__RS___U5____IF__P0_NEW__JUMP_T__R9_2: { 122 | // p0 = cmp.eq (Rs, #U5) ; if (p0.new) jump:t #r9:2 123 | op->type = R_ANAL_OP_TYPE_CJMP; 124 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 125 | op->fail = op->addr + op->size; 126 | break; 127 | } 128 | case HEX_INS_MULT_P0___CMP_EQ__RS___U5____IF___NOT_P0_NEW__JUMP_NT__R9_2: { 129 | // p0 = cmp.eq (Rs, #U5) ; if (!p0.new) jump:nt #r9:2 130 | op->type = R_ANAL_OP_TYPE_CJMP; 131 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 132 | op->fail = op->addr + op->size; 133 | break; 134 | } 135 | case HEX_INS_MULT_P0___CMP_EQ__RS___U5____IF___NOT_P0_NEW__JUMP_T__R9_2: { 136 | // p0 = cmp.eq (Rs, #U5) ; if (!p0.new) jump:t #r9:2 137 | op->type = R_ANAL_OP_TYPE_CJMP; 138 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 139 | op->fail = op->addr + op->size; 140 | break; 141 | } 142 | case HEX_INS_MULT_P0___CMP_GT__RS___U5____IF__P0_NEW__JUMP_NT__R9_2: { 143 | // p0 = cmp.gt (Rs, #U5) ; if (p0.new) jump:nt #r9:2 144 | op->type = R_ANAL_OP_TYPE_CJMP; 145 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 146 | op->fail = op->addr + op->size; 147 | break; 148 | } 149 | case HEX_INS_MULT_P0___CMP_GT__RS___U5____IF__P0_NEW__JUMP_T__R9_2: { 150 | // p0 = cmp.gt (Rs, #U5) ; if (p0.new) jump:t #r9:2 151 | op->type = R_ANAL_OP_TYPE_CJMP; 152 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 153 | op->fail = op->addr + op->size; 154 | break; 155 | } 156 | case HEX_INS_MULT_P0___CMP_GT__RS___U5____IF___NOT_P0_NEW__JUMP_NT__R9_2: { 157 | // p0 = cmp.gt (Rs, #U5) ; if (!p0.new) jump:nt #r9:2 158 | op->type = R_ANAL_OP_TYPE_CJMP; 159 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 160 | op->fail = op->addr + op->size; 161 | break; 162 | } 163 | case HEX_INS_MULT_P0___CMP_GT__RS___U5____IF___NOT_P0_NEW__JUMP_T__R9_2: { 164 | // p0 = cmp.gt (Rs, #U5) ; if (!p0.new) jump:t #r9:2 165 | op->type = R_ANAL_OP_TYPE_CJMP; 166 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 167 | op->fail = op->addr + op->size; 168 | break; 169 | } 170 | case HEX_INS_MULT_P0___CMP_GTU__RS___U5____IF__P0_NEW__JUMP_NT__R9_2: { 171 | // p0 = cmp.gtu (Rs, #U5) ; if (p0.new) jump:nt #r9:2 172 | op->type = R_ANAL_OP_TYPE_CJMP; 173 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 174 | op->fail = op->addr + op->size; 175 | break; 176 | } 177 | case HEX_INS_MULT_P0___CMP_GTU__RS___U5____IF__P0_NEW__JUMP_T__R9_2: { 178 | // p0 = cmp.gtu (Rs, #U5) ; if (p0.new) jump:t #r9:2 179 | op->type = R_ANAL_OP_TYPE_CJMP; 180 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 181 | op->fail = op->addr + op->size; 182 | break; 183 | } 184 | case HEX_INS_MULT_P0___CMP_GTU__RS___U5____IF___NOT_P0_NEW__JUMP_NT__R9_2: { 185 | // p0 = cmp.gtu (Rs, #U5) ; if (!p0.new) jump:nt #r9:2 186 | op->type = R_ANAL_OP_TYPE_CJMP; 187 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 188 | op->fail = op->addr + op->size; 189 | break; 190 | } 191 | case HEX_INS_MULT_P0___CMP_GTU__RS___U5____IF___NOT_P0_NEW__JUMP_T__R9_2: { 192 | // p0 = cmp.gtu (Rs, #U5) ; if (!p0.new) jump:t #r9:2 193 | op->type = R_ANAL_OP_TYPE_CJMP; 194 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 195 | op->fail = op->addr + op->size; 196 | break; 197 | } 198 | case HEX_INS_MULT_P1___CMP_EQ__RS____1____IF__P1_NEW__JUMP_NT__R9_2: { 199 | // p1 = cmp.eq (Rs, #-1) ; if (p1.new) jump:nt #r9:2 200 | op->type = R_ANAL_OP_TYPE_CJMP; 201 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 202 | op->fail = op->addr + op->size; 203 | break; 204 | } 205 | case HEX_INS_MULT_P1___CMP_GT__RS____1____IF__P1_NEW__JUMP_NT__R9_2: { 206 | // p1 = cmp.gt (Rs, #-1) ; if (p1.new) jump:nt #r9:2 207 | op->type = R_ANAL_OP_TYPE_CJMP; 208 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 209 | op->fail = op->addr + op->size; 210 | break; 211 | } 212 | case HEX_INS_MULT_P1___TSTBIT__RS___0____IF__P1_NEW__JUMP_NT__R9_2: { 213 | // p1 = tstbit (Rs, #0) ; if (p1.new) jump:nt #r9:2 214 | op->type = R_ANAL_OP_TYPE_CJMP; 215 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 216 | op->fail = op->addr + op->size; 217 | break; 218 | } 219 | case HEX_INS_MULT_P1___CMP_EQ__RS____1____IF__P1_NEW__JUMP_T__R9_2: { 220 | // p1 = cmp.eq (Rs, #-1) ; if (p1.new) jump:t #r9:2 221 | op->type = R_ANAL_OP_TYPE_CJMP; 222 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 223 | op->fail = op->addr + op->size; 224 | break; 225 | } 226 | case HEX_INS_MULT_P1___CMP_GT__RS____1____IF__P1_NEW__JUMP_T__R9_2: { 227 | // p1 = cmp.gt (Rs, #-1) ; if (p1.new) jump:t #r9:2 228 | op->type = R_ANAL_OP_TYPE_CJMP; 229 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 230 | op->fail = op->addr + op->size; 231 | break; 232 | } 233 | case HEX_INS_MULT_P1___TSTBIT__RS___0____IF__P1_NEW__JUMP_T__R9_2: { 234 | // p1 = tstbit (Rs, #0) ; if (p1.new) jump:t #r9:2 235 | op->type = R_ANAL_OP_TYPE_CJMP; 236 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 237 | op->fail = op->addr + op->size; 238 | break; 239 | } 240 | case HEX_INS_MULT_P1___CMP_EQ__RS____1____IF___NOT_P1_NEW__JUMP_NT__R9_2: { 241 | // p1 = cmp.eq (Rs, #-1) ; if (!p1.new) jump:nt #r9:2 242 | op->type = R_ANAL_OP_TYPE_CJMP; 243 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 244 | op->fail = op->addr + op->size; 245 | break; 246 | } 247 | case HEX_INS_MULT_P1___CMP_GT__RS____1____IF___NOT_P1_NEW__JUMP_NT__R9_2: { 248 | // p1 = cmp.gt (Rs, #-1) ; if (!p1.new) jump:nt #r9:2 249 | op->type = R_ANAL_OP_TYPE_CJMP; 250 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 251 | op->fail = op->addr + op->size; 252 | break; 253 | } 254 | case HEX_INS_MULT_P1___TSTBIT__RS___0____IF___NOT_P1_NEW__JUMP_NT__R9_2: { 255 | // p1 = tstbit (Rs, #0) ; if (!p1.new) jump:nt #r9:2 256 | op->type = R_ANAL_OP_TYPE_CJMP; 257 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 258 | op->fail = op->addr + op->size; 259 | break; 260 | } 261 | case HEX_INS_MULT_P1___CMP_EQ__RS____1____IF___NOT_P1_NEW__JUMP_T__R9_2: { 262 | // p1 = cmp.eq (Rs, #-1) ; if (!p1.new) jump:t #r9:2 263 | op->type = R_ANAL_OP_TYPE_CJMP; 264 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 265 | op->fail = op->addr + op->size; 266 | break; 267 | } 268 | case HEX_INS_MULT_P1___CMP_GT__RS____1____IF___NOT_P1_NEW__JUMP_T__R9_2: { 269 | // p1 = cmp.gt (Rs, #-1) ; if (!p1.new) jump:t #r9:2 270 | op->type = R_ANAL_OP_TYPE_CJMP; 271 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 272 | op->fail = op->addr + op->size; 273 | break; 274 | } 275 | case HEX_INS_MULT_P1___TSTBIT__RS___0____IF___NOT_P1_NEW__JUMP_T__R9_2: { 276 | // p1 = tstbit (Rs, #0) ; if (!p1.new) jump:t #r9:2 277 | op->type = R_ANAL_OP_TYPE_CJMP; 278 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 279 | op->fail = op->addr + op->size; 280 | break; 281 | } 282 | case HEX_INS_MULT_P1___CMP_EQ__RS___U5____IF__P1_NEW__JUMP_NT__R9_2: { 283 | // p1 = cmp.eq (Rs, #U5) ; if (p1.new) jump:nt #r9:2 284 | op->type = R_ANAL_OP_TYPE_CJMP; 285 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 286 | op->fail = op->addr + op->size; 287 | break; 288 | } 289 | case HEX_INS_MULT_P1___CMP_EQ__RS___U5____IF__P1_NEW__JUMP_T__R9_2: { 290 | // p1 = cmp.eq (Rs, #U5) ; if (p1.new) jump:t #r9:2 291 | op->type = R_ANAL_OP_TYPE_CJMP; 292 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 293 | op->fail = op->addr + op->size; 294 | break; 295 | } 296 | case HEX_INS_MULT_P1___CMP_EQ__RS___U5____IF___NOT_P1_NEW__JUMP_NT__R9_2: { 297 | // p1 = cmp.eq (Rs, #U5) ; if (!p1.new) jump:nt #r9:2 298 | op->type = R_ANAL_OP_TYPE_CJMP; 299 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 300 | op->fail = op->addr + op->size; 301 | break; 302 | } 303 | case HEX_INS_MULT_P1___CMP_EQ__RS___U5____IF___NOT_P1_NEW__JUMP_T__R9_2: { 304 | // p1 = cmp.eq (Rs, #U5) ; if (!p1.new) jump:t #r9:2 305 | op->type = R_ANAL_OP_TYPE_CJMP; 306 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 307 | op->fail = op->addr + op->size; 308 | break; 309 | } 310 | case HEX_INS_MULT_P1___CMP_GT__RS___U5____IF__P1_NEW__JUMP_NT__R9_2: { 311 | // p1 = cmp.gt (Rs, #U5) ; if (p1.new) jump:nt #r9:2 312 | op->type = R_ANAL_OP_TYPE_CJMP; 313 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 314 | op->fail = op->addr + op->size; 315 | break; 316 | } 317 | case HEX_INS_MULT_P1___CMP_GT__RS___U5____IF__P1_NEW__JUMP_T__R9_2: { 318 | // p1 = cmp.gt (Rs, #U5) ; if (p1.new) jump:t #r9:2 319 | op->type = R_ANAL_OP_TYPE_CJMP; 320 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 321 | op->fail = op->addr + op->size; 322 | break; 323 | } 324 | case HEX_INS_MULT_P1___CMP_GT__RS___U5____IF___NOT_P1_NEW__JUMP_NT__R9_2: { 325 | // p1 = cmp.gt (Rs, #U5) ; if (!p1.new) jump:nt #r9:2 326 | op->type = R_ANAL_OP_TYPE_CJMP; 327 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 328 | op->fail = op->addr + op->size; 329 | break; 330 | } 331 | case HEX_INS_MULT_P1___CMP_GT__RS___U5____IF___NOT_P1_NEW__JUMP_T__R9_2: { 332 | // p1 = cmp.gt (Rs, #U5) ; if (!p1.new) jump:t #r9:2 333 | op->type = R_ANAL_OP_TYPE_CJMP; 334 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 335 | op->fail = op->addr + op->size; 336 | break; 337 | } 338 | case HEX_INS_MULT_P1___CMP_GTU__RS___U5____IF__P1_NEW__JUMP_NT__R9_2: { 339 | // p1 = cmp.gtu (Rs, #U5) ; if (p1.new) jump:nt #r9:2 340 | op->type = R_ANAL_OP_TYPE_CJMP; 341 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 342 | op->fail = op->addr + op->size; 343 | break; 344 | } 345 | case HEX_INS_MULT_P1___CMP_GTU__RS___U5____IF__P1_NEW__JUMP_T__R9_2: { 346 | // p1 = cmp.gtu (Rs, #U5) ; if (p1.new) jump:t #r9:2 347 | op->type = R_ANAL_OP_TYPE_CJMP; 348 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 349 | op->fail = op->addr + op->size; 350 | break; 351 | } 352 | case HEX_INS_MULT_P1___CMP_GTU__RS___U5____IF___NOT_P1_NEW__JUMP_NT__R9_2: { 353 | // p1 = cmp.gtu (Rs, #U5) ; if (!p1.new) jump:nt #r9:2 354 | op->type = R_ANAL_OP_TYPE_CJMP; 355 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 356 | op->fail = op->addr + op->size; 357 | break; 358 | } 359 | case HEX_INS_MULT_P1___CMP_GTU__RS___U5____IF___NOT_P1_NEW__JUMP_T__R9_2: { 360 | // p1 = cmp.gtu (Rs, #U5) ; if (!p1.new) jump:t #r9:2 361 | op->type = R_ANAL_OP_TYPE_CJMP; 362 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 363 | op->fail = op->addr + op->size; 364 | break; 365 | } 366 | case HEX_INS_MULT_P0___CMP_EQ__RS__RT____IF__P0_NEW__JUMP_NT__R9_2: { 367 | // p0 = cmp.eq (Rs, Rt) ; if (p0.new) jump:nt #r9:2 368 | op->type = R_ANAL_OP_TYPE_CJMP; 369 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 370 | op->fail = op->addr + op->size; 371 | break; 372 | } 373 | case HEX_INS_MULT_P1___CMP_EQ__RS__RT____IF__P1_NEW__JUMP_NT__R9_2: { 374 | // p1 = cmp.eq (Rs, Rt) ; if (p1.new) jump:nt #r9:2 375 | op->type = R_ANAL_OP_TYPE_CJMP; 376 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 377 | op->fail = op->addr + op->size; 378 | break; 379 | } 380 | case HEX_INS_MULT_P0___CMP_EQ__RS__RT____IF__P0_NEW__JUMP_T__R9_2: { 381 | // p0 = cmp.eq (Rs, Rt) ; if (p0.new) jump:t #r9:2 382 | op->type = R_ANAL_OP_TYPE_CJMP; 383 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 384 | op->fail = op->addr + op->size; 385 | break; 386 | } 387 | case HEX_INS_MULT_P1___CMP_EQ__RS__RT____IF__P1_NEW__JUMP_T__R9_2: { 388 | // p1 = cmp.eq (Rs, Rt) ; if (p1.new) jump:t #r9:2 389 | op->type = R_ANAL_OP_TYPE_CJMP; 390 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 391 | op->fail = op->addr + op->size; 392 | break; 393 | } 394 | case HEX_INS_MULT_P0___CMP_EQ__RS__RT____IF___NOT_P0_NEW__JUMP_NT__R9_2: { 395 | // p0 = cmp.eq (Rs, Rt) ; if (!p0.new) jump:nt #r9:2 396 | op->type = R_ANAL_OP_TYPE_CJMP; 397 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 398 | op->fail = op->addr + op->size; 399 | break; 400 | } 401 | case HEX_INS_MULT_P1___CMP_EQ__RS__RT____IF___NOT_P1_NEW__JUMP_NT__R9_2: { 402 | // p1 = cmp.eq (Rs, Rt) ; if (!p1.new) jump:nt #r9:2 403 | op->type = R_ANAL_OP_TYPE_CJMP; 404 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 405 | op->fail = op->addr + op->size; 406 | break; 407 | } 408 | case HEX_INS_MULT_P0___CMP_EQ__RS__RT____IF___NOT_P0_NEW__JUMP_T__R9_2: { 409 | // p0 = cmp.eq (Rs, Rt) ; if (!p0.new) jump:t #r9:2 410 | op->type = R_ANAL_OP_TYPE_CJMP; 411 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 412 | op->fail = op->addr + op->size; 413 | break; 414 | } 415 | case HEX_INS_MULT_P1___CMP_EQ__RS__RT____IF___NOT_P1_NEW__JUMP_T__R9_2: { 416 | // p1 = cmp.eq (Rs, Rt) ; if (!p1.new) jump:t #r9:2 417 | op->type = R_ANAL_OP_TYPE_CJMP; 418 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 419 | op->fail = op->addr + op->size; 420 | break; 421 | } 422 | case HEX_INS_MULT_P0___CMP_GT__RS__RT____IF__P0_NEW__JUMP_NT__R9_2: { 423 | // p0 = cmp.gt (Rs, Rt) ; if (p0.new) jump:nt #r9:2 424 | op->type = R_ANAL_OP_TYPE_CJMP; 425 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 426 | op->fail = op->addr + op->size; 427 | break; 428 | } 429 | case HEX_INS_MULT_P1___CMP_GT__RS__RT____IF__P1_NEW__JUMP_NT__R9_2: { 430 | // p1 = cmp.gt (Rs, Rt) ; if (p1.new) jump:nt #r9:2 431 | op->type = R_ANAL_OP_TYPE_CJMP; 432 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 433 | op->fail = op->addr + op->size; 434 | break; 435 | } 436 | case HEX_INS_MULT_P0___CMP_GT__RS__RT____IF__P0_NEW__JUMP_T__R9_2: { 437 | // p0 = cmp.gt (Rs, Rt) ; if (p0.new) jump:t #r9:2 438 | op->type = R_ANAL_OP_TYPE_CJMP; 439 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 440 | op->fail = op->addr + op->size; 441 | break; 442 | } 443 | case HEX_INS_MULT_P1___CMP_GT__RS__RT____IF__P1_NEW__JUMP_T__R9_2: { 444 | // p1 = cmp.gt (Rs, Rt) ; if (p1.new) jump:t #r9:2 445 | op->type = R_ANAL_OP_TYPE_CJMP; 446 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 447 | op->fail = op->addr + op->size; 448 | break; 449 | } 450 | case HEX_INS_MULT_P0___CMP_GT__RS__RT____IF___NOT_P0_NEW__JUMP_NT__R9_2: { 451 | // p0 = cmp.gt (Rs, Rt) ; if (!p0.new) jump:nt #r9:2 452 | op->type = R_ANAL_OP_TYPE_CJMP; 453 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 454 | op->fail = op->addr + op->size; 455 | break; 456 | } 457 | case HEX_INS_MULT_P1___CMP_GT__RS__RT____IF___NOT_P1_NEW__JUMP_NT__R9_2: { 458 | // p1 = cmp.gt (Rs, Rt) ; if (!p1.new) jump:nt #r9:2 459 | op->type = R_ANAL_OP_TYPE_CJMP; 460 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 461 | op->fail = op->addr + op->size; 462 | break; 463 | } 464 | case HEX_INS_MULT_P0___CMP_GT__RS__RT____IF___NOT_P0_NEW__JUMP_T__R9_2: { 465 | // p0 = cmp.gt (Rs, Rt) ; if (!p0.new) jump:t #r9:2 466 | op->type = R_ANAL_OP_TYPE_CJMP; 467 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 468 | op->fail = op->addr + op->size; 469 | break; 470 | } 471 | case HEX_INS_MULT_P1___CMP_GT__RS__RT____IF___NOT_P1_NEW__JUMP_T__R9_2: { 472 | // p1 = cmp.gt (Rs, Rt) ; if (!p1.new) jump:t #r9:2 473 | op->type = R_ANAL_OP_TYPE_CJMP; 474 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 475 | op->fail = op->addr + op->size; 476 | break; 477 | } 478 | case HEX_INS_MULT_P0___CMP_GTU__RS__RT____IF__P0_NEW__JUMP_NT__R9_2: { 479 | // p0 = cmp.gtu (Rs, Rt) ; if (p0.new) jump:nt #r9:2 480 | op->type = R_ANAL_OP_TYPE_CJMP; 481 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 482 | op->fail = op->addr + op->size; 483 | break; 484 | } 485 | case HEX_INS_MULT_P1___CMP_GTU__RS__RT____IF__P1_NEW__JUMP_NT__R9_2: { 486 | // p1 = cmp.gtu (Rs, Rt) ; if (p1.new) jump:nt #r9:2 487 | op->type = R_ANAL_OP_TYPE_CJMP; 488 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 489 | op->fail = op->addr + op->size; 490 | break; 491 | } 492 | case HEX_INS_MULT_P0___CMP_GTU__RS__RT____IF__P0_NEW__JUMP_T__R9_2: { 493 | // p0 = cmp.gtu (Rs, Rt) ; if (p0.new) jump:t #r9:2 494 | op->type = R_ANAL_OP_TYPE_CJMP; 495 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 496 | op->fail = op->addr + op->size; 497 | break; 498 | } 499 | case HEX_INS_MULT_P1___CMP_GTU__RS__RT____IF__P1_NEW__JUMP_T__R9_2: { 500 | // p1 = cmp.gtu (Rs, Rt) ; if (p1.new) jump:t #r9:2 501 | op->type = R_ANAL_OP_TYPE_CJMP; 502 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 503 | op->fail = op->addr + op->size; 504 | break; 505 | } 506 | case HEX_INS_MULT_P0___CMP_GTU__RS__RT____IF___NOT_P0_NEW__JUMP_NT__R9_2: { 507 | // p0 = cmp.gtu (Rs, Rt) ; if (!p0.new) jump:nt #r9:2 508 | op->type = R_ANAL_OP_TYPE_CJMP; 509 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 510 | op->fail = op->addr + op->size; 511 | break; 512 | } 513 | case HEX_INS_MULT_P1___CMP_GTU__RS__RT____IF___NOT_P1_NEW__JUMP_NT__R9_2: { 514 | // p1 = cmp.gtu (Rs, Rt) ; if (!p1.new) jump:nt #r9:2 515 | op->type = R_ANAL_OP_TYPE_CJMP; 516 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 517 | op->fail = op->addr + op->size; 518 | break; 519 | } 520 | case HEX_INS_MULT_P0___CMP_GTU__RS__RT____IF___NOT_P0_NEW__JUMP_T__R9_2: { 521 | // p0 = cmp.gtu (Rs, Rt) ; if (!p0.new) jump:t #r9:2 522 | op->type = R_ANAL_OP_TYPE_CJMP; 523 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 524 | op->fail = op->addr + op->size; 525 | break; 526 | } 527 | case HEX_INS_MULT_P1___CMP_GTU__RS__RT____IF___NOT_P1_NEW__JUMP_T__R9_2: { 528 | // p1 = cmp.gtu (Rs, Rt) ; if (!p1.new) jump:t #r9:2 529 | op->type = R_ANAL_OP_TYPE_CJMP; 530 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 531 | op->fail = op->addr + op->size; 532 | break; 533 | } 534 | case HEX_INS_JUMP__R22_2: { 535 | // jump #r22:2 536 | op->type = R_ANAL_OP_TYPE_JMP; 537 | op->jump = op->addr + (st32) hi->ops[0].op.imm; 538 | op->fail = op->addr + op->size; 539 | break; 540 | } 541 | case HEX_INS_IF__PU__JUMP_NT__R15_2: { 542 | // if (Pu) jump:nt #r15:2 543 | op->type = R_ANAL_OP_TYPE_CJMP; 544 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 545 | op->fail = op->addr + op->size; 546 | break; 547 | } 548 | case HEX_INS_IF__PU__JUMP_T__R15_2: { 549 | // if (Pu) jump:t #r15:2 550 | op->type = R_ANAL_OP_TYPE_CJMP; 551 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 552 | op->fail = op->addr + op->size; 553 | break; 554 | } 555 | case HEX_INS_IF__NOT_PU_JUMP_NT__R15_2: { 556 | // if !Pu jump:nt #r15:2 557 | op->type = R_ANAL_OP_TYPE_CJMP; 558 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 559 | op->fail = op->addr + op->size; 560 | break; 561 | } 562 | case HEX_INS_IF__NOT_PU_JUMP_T__R15_2: { 563 | // if !Pu jump:t #r15:2 564 | op->type = R_ANAL_OP_TYPE_CJMP; 565 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 566 | op->fail = op->addr + op->size; 567 | break; 568 | } 569 | case HEX_INS_IF__PU_NEW__JUMP_NT__R15_2: { 570 | // if (Pu.new) jump:nt #r15:2 571 | op->type = R_ANAL_OP_TYPE_CJMP; 572 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 573 | op->fail = op->addr + op->size; 574 | break; 575 | } 576 | case HEX_INS_IF__PU_NEW__JUMP_T__R15_2: { 577 | // if (Pu.new) jump:t #r15:2 578 | op->type = R_ANAL_OP_TYPE_CJMP; 579 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 580 | op->fail = op->addr + op->size; 581 | break; 582 | } 583 | case HEX_INS_IF__NOT_PU_NEW_JUMP_NT__R15_2: { 584 | // if !Pu.new jump:nt #r15:2 585 | op->type = R_ANAL_OP_TYPE_CJMP; 586 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 587 | op->fail = op->addr + op->size; 588 | break; 589 | } 590 | case HEX_INS_IF__NOT_PU_NEW_JUMP_T__R15_2: { 591 | // if !Pu.new jump:t #r15:2 592 | op->type = R_ANAL_OP_TYPE_CJMP; 593 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 594 | op->fail = op->addr + op->size; 595 | break; 596 | } 597 | case HEX_INS_IF__RS__NOT____0__JUMP_NT__R13_2: { 598 | // if (Rs != #0) jump:nt #r13:2 599 | op->type = R_ANAL_OP_TYPE_CJMP; 600 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 601 | op->fail = op->addr + op->size; 602 | break; 603 | } 604 | case HEX_INS_IF__RS__NOT____0__JUMP_T__R13_2: { 605 | // if (Rs != #0) jump:t #r13:2 606 | op->type = R_ANAL_OP_TYPE_CJMP; 607 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 608 | op->fail = op->addr + op->size; 609 | break; 610 | } 611 | case HEX_INS_IF__RS_GT_EQ___0__JUMP_NT__R13_2: { 612 | // if (Rs> = #0) jump:nt #r13:2 613 | op->type = R_ANAL_OP_TYPE_CJMP; 614 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 615 | op->fail = op->addr + op->size; 616 | break; 617 | } 618 | case HEX_INS_IF__RS_GT_EQ___0__JUMP_T__R13_2: { 619 | // if (Rs> = #0) jump:t #r13:2 620 | op->type = R_ANAL_OP_TYPE_CJMP; 621 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 622 | op->fail = op->addr + op->size; 623 | break; 624 | } 625 | case HEX_INS_IF__RS__EQ___0__JUMP_NT__R13_2: { 626 | // if (Rs == #0) jump:nt #r13:2 627 | op->type = R_ANAL_OP_TYPE_CJMP; 628 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 629 | op->fail = op->addr + op->size; 630 | break; 631 | } 632 | case HEX_INS_IF__RS__EQ___0__JUMP_T__R13_2: { 633 | // if (Rs == #0) jump:t #r13:2 634 | op->type = R_ANAL_OP_TYPE_CJMP; 635 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 636 | op->fail = op->addr + op->size; 637 | break; 638 | } 639 | case HEX_INS_IF__RS_LT_EQ___0__JUMP_NT__R13_2: { 640 | // if (Rs< = #0) jump:nt #r13:2 641 | op->type = R_ANAL_OP_TYPE_CJMP; 642 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 643 | op->fail = op->addr + op->size; 644 | break; 645 | } 646 | case HEX_INS_IF__RS_LT_EQ___0__JUMP_T__R13_2: { 647 | // if (Rs< = #0) jump:t #r13:2 648 | op->type = R_ANAL_OP_TYPE_CJMP; 649 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 650 | op->fail = op->addr + op->size; 651 | break; 652 | } 653 | case HEX_INS_MULT_RD____U6___JUMP__R9_2: { 654 | // Rd = #U6 ; jump #r9:2 655 | op->type = R_ANAL_OP_TYPE_JMP; 656 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 657 | op->fail = op->addr + op->size; 658 | break; 659 | } 660 | case HEX_INS_MULT_RD___RS___JUMP__R9_2: { 661 | // Rd = Rs ; jump #r9:2 662 | op->type = R_ANAL_OP_TYPE_JMP; 663 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 664 | op->fail = op->addr + op->size; 665 | break; 666 | } 667 | case HEX_INS_DEALLOC_RETURN: { 668 | // dealloc_return 669 | op->type = R_ANAL_OP_TYPE_RET; 670 | break; 671 | } 672 | case HEX_INS_IF__PS_NEW__DEALLOC_RETURN_NT: { 673 | // if (Ps.new) dealloc_return:nt 674 | op->type = R_ANAL_OP_TYPE_RET; 675 | break; 676 | } 677 | case HEX_INS_IF__PS__DEALLOC_RETURN: { 678 | // if (Ps) dealloc_return 679 | op->type = R_ANAL_OP_TYPE_RET; 680 | break; 681 | } 682 | case HEX_INS_IF__PS_NEW__DEALLOC_RETURN_T: { 683 | // if (Ps.new) dealloc_return:t 684 | op->type = R_ANAL_OP_TYPE_RET; 685 | break; 686 | } 687 | case HEX_INS_IF__NOT_PS_NEW_DEALLOC_RETURN_NT: { 688 | // if !Ps.new dealloc_return:nt 689 | op->type = R_ANAL_OP_TYPE_RET; 690 | break; 691 | } 692 | case HEX_INS_IF__NOT_PS_DEALLOC_RETURN: { 693 | // if !Ps dealloc_return 694 | op->type = R_ANAL_OP_TYPE_RET; 695 | break; 696 | } 697 | case HEX_INS_IF__NOT_PS_NEW_DEALLOC_RETURN_T: { 698 | // if !Ps.new dealloc_return:t 699 | op->type = R_ANAL_OP_TYPE_RET; 700 | break; 701 | } 702 | case HEX_INS_IF__CMP_EQ__NS_NEW__RT___JUMP_NT__R9_2: { 703 | // if (cmp.eq (Ns.new, Rt)) jump:nt #r9:2 704 | op->type = R_ANAL_OP_TYPE_CJMP; 705 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 706 | op->fail = op->addr + op->size; 707 | break; 708 | } 709 | case HEX_INS_IF__CMP_EQ__NS_NEW__RT___JUMP_T__R9_2: { 710 | // if (cmp.eq (Ns.new, Rt)) jump:t #r9:2 711 | op->type = R_ANAL_OP_TYPE_CJMP; 712 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 713 | op->fail = op->addr + op->size; 714 | break; 715 | } 716 | case HEX_INS_IF___NOT_CMP_EQ__NS_NEW__RT___JUMP_NT__R9_2: { 717 | // if (!cmp.eq (Ns.new, Rt)) jump:nt #r9:2 718 | op->type = R_ANAL_OP_TYPE_CJMP; 719 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 720 | op->fail = op->addr + op->size; 721 | break; 722 | } 723 | case HEX_INS_IF___NOT_CMP_EQ__NS_NEW__RT___JUMP_T__R9_2: { 724 | // if (!cmp.eq (Ns.new, Rt)) jump:t #r9:2 725 | op->type = R_ANAL_OP_TYPE_CJMP; 726 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 727 | op->fail = op->addr + op->size; 728 | break; 729 | } 730 | case HEX_INS_IF__CMP_GT__NS_NEW__RT___JUMP_NT__R9_2: { 731 | // if (cmp.gt (Ns.new, Rt)) jump:nt #r9:2 732 | op->type = R_ANAL_OP_TYPE_CJMP; 733 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 734 | op->fail = op->addr + op->size; 735 | break; 736 | } 737 | case HEX_INS_IF__CMP_GT__NS_NEW__RT___JUMP_T__R9_2: { 738 | // if (cmp.gt (Ns.new, Rt)) jump:t #r9:2 739 | op->type = R_ANAL_OP_TYPE_CJMP; 740 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 741 | op->fail = op->addr + op->size; 742 | break; 743 | } 744 | case HEX_INS_IF___NOT_CMP_GT__NS_NEW__RT___JUMP_NT__R9_2: { 745 | // if (!cmp.gt (Ns.new, Rt)) jump:nt #r9:2 746 | op->type = R_ANAL_OP_TYPE_CJMP; 747 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 748 | op->fail = op->addr + op->size; 749 | break; 750 | } 751 | case HEX_INS_IF___NOT_CMP_GT__NS_NEW__RT___JUMP_T__R9_2: { 752 | // if (!cmp.gt (Ns.new, Rt)) jump:t #r9:2 753 | op->type = R_ANAL_OP_TYPE_CJMP; 754 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 755 | op->fail = op->addr + op->size; 756 | break; 757 | } 758 | case HEX_INS_IF__CMP_GTU__NS_NEW__RT___JUMP_NT__R9_2: { 759 | // if (cmp.gtu (Ns.new, Rt)) jump:nt #r9:2 760 | op->type = R_ANAL_OP_TYPE_CJMP; 761 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 762 | op->fail = op->addr + op->size; 763 | break; 764 | } 765 | case HEX_INS_IF__CMP_GTU__NS_NEW__RT___JUMP_T__R9_2: { 766 | // if (cmp.gtu (Ns.new, Rt)) jump:t #r9:2 767 | op->type = R_ANAL_OP_TYPE_CJMP; 768 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 769 | op->fail = op->addr + op->size; 770 | break; 771 | } 772 | case HEX_INS_IF___NOT_CMP_GTU__NS_NEW__RT___JUMP_NT__R9_2: { 773 | // if (!cmp.gtu (Ns.new, Rt)) jump:nt #r9:2 774 | op->type = R_ANAL_OP_TYPE_CJMP; 775 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 776 | op->fail = op->addr + op->size; 777 | break; 778 | } 779 | case HEX_INS_IF___NOT_CMP_GTU__NS_NEW__RT___JUMP_T__R9_2: { 780 | // if (!cmp.gtu (Ns.new, Rt)) jump:t #r9:2 781 | op->type = R_ANAL_OP_TYPE_CJMP; 782 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 783 | op->fail = op->addr + op->size; 784 | break; 785 | } 786 | case HEX_INS_IF__CMP_GT__RT__NS_NEW___JUMP_NT__R9_2: { 787 | // if (cmp.gt (Rt, Ns.new)) jump:nt #r9:2 788 | op->type = R_ANAL_OP_TYPE_CJMP; 789 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 790 | op->fail = op->addr + op->size; 791 | break; 792 | } 793 | case HEX_INS_IF__CMP_GT__RT__NS_NEW___JUMP_T__R9_2: { 794 | // if (cmp.gt (Rt, Ns.new)) jump:t #r9:2 795 | op->type = R_ANAL_OP_TYPE_CJMP; 796 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 797 | op->fail = op->addr + op->size; 798 | break; 799 | } 800 | case HEX_INS_IF___NOT_CMP_GT__RT__NS_NEW___JUMP_NT__R9_2: { 801 | // if (!cmp.gt (Rt, Ns.new)) jump:nt #r9:2 802 | op->type = R_ANAL_OP_TYPE_CJMP; 803 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 804 | op->fail = op->addr + op->size; 805 | break; 806 | } 807 | case HEX_INS_IF___NOT_CMP_GT__RT__NS_NEW___JUMP_T__R9_2: { 808 | // if (!cmp.gt (Rt, Ns.new)) jump:t #r9:2 809 | op->type = R_ANAL_OP_TYPE_CJMP; 810 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 811 | op->fail = op->addr + op->size; 812 | break; 813 | } 814 | case HEX_INS_IF__CMP_GTU__RT__NS_NEW___JUMP_NT__R9_2: { 815 | // if (cmp.gtu (Rt, Ns.new)) jump:nt #r9:2 816 | op->type = R_ANAL_OP_TYPE_CJMP; 817 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 818 | op->fail = op->addr + op->size; 819 | break; 820 | } 821 | case HEX_INS_IF__CMP_GTU__RT__NS_NEW___JUMP_T__R9_2: { 822 | // if (cmp.gtu (Rt, Ns.new)) jump:t #r9:2 823 | op->type = R_ANAL_OP_TYPE_CJMP; 824 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 825 | op->fail = op->addr + op->size; 826 | break; 827 | } 828 | case HEX_INS_IF___NOT_CMP_GTU__RT__NS_NEW___JUMP_NT__R9_2: { 829 | // if (!cmp.gtu (Rt, Ns.new)) jump:nt #r9:2 830 | op->type = R_ANAL_OP_TYPE_CJMP; 831 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 832 | op->fail = op->addr + op->size; 833 | break; 834 | } 835 | case HEX_INS_IF___NOT_CMP_GTU__RT__NS_NEW___JUMP_T__R9_2: { 836 | // if (!cmp.gtu (Rt, Ns.new)) jump:t #r9:2 837 | op->type = R_ANAL_OP_TYPE_CJMP; 838 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 839 | op->fail = op->addr + op->size; 840 | break; 841 | } 842 | case HEX_INS_IF__CMP_EQ__NS_NEW___U5___JUMP_NT__R9_2: { 843 | // if (cmp.eq (Ns.new, #U5)) jump:nt #r9:2 844 | op->type = R_ANAL_OP_TYPE_CJMP; 845 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 846 | op->fail = op->addr + op->size; 847 | break; 848 | } 849 | case HEX_INS_IF__CMP_EQ__NS_NEW___U5___JUMP_T__R9_2: { 850 | // if (cmp.eq (Ns.new, #U5)) jump:t #r9:2 851 | op->type = R_ANAL_OP_TYPE_CJMP; 852 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 853 | op->fail = op->addr + op->size; 854 | break; 855 | } 856 | case HEX_INS_IF___NOT_CMP_EQ__NS_NEW___U5___JUMP_NT__R9_2: { 857 | // if (!cmp.eq (Ns.new, #U5)) jump:nt #r9:2 858 | op->type = R_ANAL_OP_TYPE_CJMP; 859 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 860 | op->fail = op->addr + op->size; 861 | break; 862 | } 863 | case HEX_INS_IF___NOT_CMP_EQ__NS_NEW___U5___JUMP_T__R9_2: { 864 | // if (!cmp.eq (Ns.new, #U5)) jump:t #r9:2 865 | op->type = R_ANAL_OP_TYPE_CJMP; 866 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 867 | op->fail = op->addr + op->size; 868 | break; 869 | } 870 | case HEX_INS_IF__CMP_GT__NS_NEW___U5___JUMP_NT__R9_2: { 871 | // if (cmp.gt (Ns.new, #U5)) jump:nt #r9:2 872 | op->type = R_ANAL_OP_TYPE_CJMP; 873 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 874 | op->fail = op->addr + op->size; 875 | break; 876 | } 877 | case HEX_INS_IF__CMP_GT__NS_NEW___U5___JUMP_T__R9_2: { 878 | // if (cmp.gt (Ns.new, #U5)) jump:t #r9:2 879 | op->type = R_ANAL_OP_TYPE_CJMP; 880 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 881 | op->fail = op->addr + op->size; 882 | break; 883 | } 884 | case HEX_INS_IF___NOT_CMP_GT__NS_NEW___U5___JUMP_NT__R9_2: { 885 | // if (!cmp.gt (Ns.new, #U5)) jump:nt #r9:2 886 | op->type = R_ANAL_OP_TYPE_CJMP; 887 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 888 | op->fail = op->addr + op->size; 889 | break; 890 | } 891 | case HEX_INS_IF___NOT_CMP_GT__NS_NEW___U5___JUMP_T__R9_2: { 892 | // if (!cmp.gt (Ns.new, #U5)) jump:t #r9:2 893 | op->type = R_ANAL_OP_TYPE_CJMP; 894 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 895 | op->fail = op->addr + op->size; 896 | break; 897 | } 898 | case HEX_INS_IF__CMP_GTU__NS_NEW___U5___JUMP_NT__R9_2: { 899 | // if (cmp.gtu (Ns.new, #U5)) jump:nt #r9:2 900 | op->type = R_ANAL_OP_TYPE_CJMP; 901 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 902 | op->fail = op->addr + op->size; 903 | break; 904 | } 905 | case HEX_INS_IF__CMP_GTU__NS_NEW___U5___JUMP_T__R9_2: { 906 | // if (cmp.gtu (Ns.new, #U5)) jump:t #r9:2 907 | op->type = R_ANAL_OP_TYPE_CJMP; 908 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 909 | op->fail = op->addr + op->size; 910 | break; 911 | } 912 | case HEX_INS_IF___NOT_CMP_GTU__NS_NEW___U5___JUMP_NT__R9_2: { 913 | // if (!cmp.gtu (Ns.new, #U5)) jump:nt #r9:2 914 | op->type = R_ANAL_OP_TYPE_CJMP; 915 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 916 | op->fail = op->addr + op->size; 917 | break; 918 | } 919 | case HEX_INS_IF___NOT_CMP_GTU__NS_NEW___U5___JUMP_T__R9_2: { 920 | // if (!cmp.gtu (Ns.new, #U5)) jump:t #r9:2 921 | op->type = R_ANAL_OP_TYPE_CJMP; 922 | op->jump = op->addr + (st32) hi->ops[2].op.imm; 923 | op->fail = op->addr + op->size; 924 | break; 925 | } 926 | case HEX_INS_IF__TSTBIT__NS_NEW___0___JUMP_NT__R9_2: { 927 | // if (tstbit (Ns.new, #0)) jump:nt #r9:2 928 | op->type = R_ANAL_OP_TYPE_CJMP; 929 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 930 | op->fail = op->addr + op->size; 931 | break; 932 | } 933 | case HEX_INS_IF__TSTBIT__NS_NEW___0___JUMP_T__R9_2: { 934 | // if (tstbit (Ns.new, #0)) jump:t #r9:2 935 | op->type = R_ANAL_OP_TYPE_CJMP; 936 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 937 | op->fail = op->addr + op->size; 938 | break; 939 | } 940 | case HEX_INS_IF___NOT_TSTBIT__NS_NEW___0___JUMP_NT__R9_2: { 941 | // if (!tstbit (Ns.new, #0)) jump:nt #r9:2 942 | op->type = R_ANAL_OP_TYPE_CJMP; 943 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 944 | op->fail = op->addr + op->size; 945 | break; 946 | } 947 | case HEX_INS_IF___NOT_TSTBIT__NS_NEW___0___JUMP_T__R9_2: { 948 | // if (!tstbit (Ns.new, #0)) jump:t #r9:2 949 | op->type = R_ANAL_OP_TYPE_CJMP; 950 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 951 | op->fail = op->addr + op->size; 952 | break; 953 | } 954 | case HEX_INS_IF__CMP_EQ__NS_NEW____1___JUMP_NT__R9_2: { 955 | // if (cmp.eq (Ns.new, #-1)) jump:nt #r9:2 956 | op->type = R_ANAL_OP_TYPE_CJMP; 957 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 958 | op->fail = op->addr + op->size; 959 | break; 960 | } 961 | case HEX_INS_IF__CMP_EQ__NS_NEW____1___JUMP_T__R9_2: { 962 | // if (cmp.eq (Ns.new, #-1)) jump:t #r9:2 963 | op->type = R_ANAL_OP_TYPE_CJMP; 964 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 965 | op->fail = op->addr + op->size; 966 | break; 967 | } 968 | case HEX_INS_IF___NOT_CMP_EQ__NS_NEW____1___JUMP_NT__R9_2: { 969 | // if (!cmp.eq (Ns.new, #-1)) jump:nt #r9:2 970 | op->type = R_ANAL_OP_TYPE_CJMP; 971 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 972 | op->fail = op->addr + op->size; 973 | break; 974 | } 975 | case HEX_INS_IF___NOT_CMP_EQ__NS_NEW____1___JUMP_T__R9_2: { 976 | // if (!cmp.eq (Ns.new, #-1)) jump:t #r9:2 977 | op->type = R_ANAL_OP_TYPE_CJMP; 978 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 979 | op->fail = op->addr + op->size; 980 | break; 981 | } 982 | case HEX_INS_IF__CMP_GT__NS_NEW____1___JUMP_NT__R9_2: { 983 | // if (cmp.gt (Ns.new, #-1)) jump:nt #r9:2 984 | op->type = R_ANAL_OP_TYPE_CJMP; 985 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 986 | op->fail = op->addr + op->size; 987 | break; 988 | } 989 | case HEX_INS_IF__CMP_GT__NS_NEW____1___JUMP_T__R9_2: { 990 | // if (cmp.gt (Ns.new, #-1)) jump:t #r9:2 991 | op->type = R_ANAL_OP_TYPE_CJMP; 992 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 993 | op->fail = op->addr + op->size; 994 | break; 995 | } 996 | case HEX_INS_IF___NOT_CMP_GT__NS_NEW____1___JUMP_NT__R9_2: { 997 | // if (!cmp.gt (Ns.new, #-1)) jump:nt #r9:2 998 | op->type = R_ANAL_OP_TYPE_CJMP; 999 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 1000 | op->fail = op->addr + op->size; 1001 | break; 1002 | } 1003 | case HEX_INS_IF___NOT_CMP_GT__NS_NEW____1___JUMP_T__R9_2: { 1004 | // if (!cmp.gt (Ns.new, #-1)) jump:t #r9:2 1005 | op->type = R_ANAL_OP_TYPE_CJMP; 1006 | op->jump = op->addr + (st32) hi->ops[1].op.imm; 1007 | op->fail = op->addr + op->size; 1008 | break; 1009 | } 1010 | case HEX_INS_DUPLEX_RD_____1___DEALLOC_RETURN: { 1011 | // Rd = #-1 ; dealloc_return 1012 | op->type = R_ANAL_OP_TYPE_RET; 1013 | break; 1014 | } 1015 | case HEX_INS_DUPLEX_RD_____1___IF___NOT__P0__DEALLOC_RETURN: { 1016 | // Rd = #-1 ; if (! p0) dealloc_return 1017 | op->type = R_ANAL_OP_TYPE_RET; 1018 | break; 1019 | } 1020 | case HEX_INS_DUPLEX_RD_____1___IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1021 | // Rd = #-1 ; if (! p0.new) dealloc_return:nt 1022 | op->type = R_ANAL_OP_TYPE_RET; 1023 | break; 1024 | } 1025 | case HEX_INS_DUPLEX_RD_____1___IF__P0__DEALLOC_RETURN: { 1026 | // Rd = #-1 ; if (p0) dealloc_return 1027 | op->type = R_ANAL_OP_TYPE_RET; 1028 | break; 1029 | } 1030 | case HEX_INS_DUPLEX_RD_____1___IF__P0_NEW__DEALLOC_RETURN_NT: { 1031 | // Rd = #-1 ; if (p0.new) dealloc_return:nt 1032 | op->type = R_ANAL_OP_TYPE_RET; 1033 | break; 1034 | } 1035 | case HEX_INS_DUPLEX_RD____U6___DEALLOC_RETURN: { 1036 | // Rd = #u6 ; dealloc_return 1037 | op->type = R_ANAL_OP_TYPE_RET; 1038 | break; 1039 | } 1040 | case HEX_INS_DUPLEX_RD____U6___IF___NOT__P0__DEALLOC_RETURN: { 1041 | // Rd = #u6 ; if (! p0) dealloc_return 1042 | op->type = R_ANAL_OP_TYPE_RET; 1043 | break; 1044 | } 1045 | case HEX_INS_DUPLEX_RD____U6___IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1046 | // Rd = #u6 ; if (! p0.new) dealloc_return:nt 1047 | op->type = R_ANAL_OP_TYPE_RET; 1048 | break; 1049 | } 1050 | case HEX_INS_DUPLEX_RD____U6___IF__P0__DEALLOC_RETURN: { 1051 | // Rd = #u6 ; if (p0) dealloc_return 1052 | op->type = R_ANAL_OP_TYPE_RET; 1053 | break; 1054 | } 1055 | case HEX_INS_DUPLEX_RD____U6___IF__P0_NEW__DEALLOC_RETURN_NT: { 1056 | // Rd = #u6 ; if (p0.new) dealloc_return:nt 1057 | op->type = R_ANAL_OP_TYPE_RET; 1058 | break; 1059 | } 1060 | case HEX_INS_DUPLEX_RD___RS___DEALLOC_RETURN: { 1061 | // Rd = Rs ; dealloc_return 1062 | op->type = R_ANAL_OP_TYPE_RET; 1063 | break; 1064 | } 1065 | case HEX_INS_DUPLEX_RD___RS___IF___NOT__P0__DEALLOC_RETURN: { 1066 | // Rd = Rs ; if (! p0) dealloc_return 1067 | op->type = R_ANAL_OP_TYPE_RET; 1068 | break; 1069 | } 1070 | case HEX_INS_DUPLEX_RD___RS___IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1071 | // Rd = Rs ; if (! p0.new) dealloc_return:nt 1072 | op->type = R_ANAL_OP_TYPE_RET; 1073 | break; 1074 | } 1075 | case HEX_INS_DUPLEX_RD___RS___IF__P0__DEALLOC_RETURN: { 1076 | // Rd = Rs ; if (p0) dealloc_return 1077 | op->type = R_ANAL_OP_TYPE_RET; 1078 | break; 1079 | } 1080 | case HEX_INS_DUPLEX_RD___RS___IF__P0_NEW__DEALLOC_RETURN_NT: { 1081 | // Rd = Rs ; if (p0.new) dealloc_return:nt 1082 | op->type = R_ANAL_OP_TYPE_RET; 1083 | break; 1084 | } 1085 | case HEX_INS_DUPLEX_RD___ADD__RS____1____DEALLOC_RETURN: { 1086 | // Rd = add (Rs, #-1) ; dealloc_return 1087 | op->type = R_ANAL_OP_TYPE_RET; 1088 | break; 1089 | } 1090 | case HEX_INS_DUPLEX_RD___ADD__RS____1____IF___NOT__P0__DEALLOC_RETURN: { 1091 | // Rd = add (Rs, #-1) ; if (! p0) dealloc_return 1092 | op->type = R_ANAL_OP_TYPE_RET; 1093 | break; 1094 | } 1095 | case HEX_INS_DUPLEX_RD___ADD__RS____1____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1096 | // Rd = add (Rs, #-1) ; if (! p0.new) dealloc_return:nt 1097 | op->type = R_ANAL_OP_TYPE_RET; 1098 | break; 1099 | } 1100 | case HEX_INS_DUPLEX_RD___ADD__RS____1____IF__P0__DEALLOC_RETURN: { 1101 | // Rd = add (Rs, #-1) ; if (p0) dealloc_return 1102 | op->type = R_ANAL_OP_TYPE_RET; 1103 | break; 1104 | } 1105 | case HEX_INS_DUPLEX_RD___ADD__RS____1____IF__P0_NEW__DEALLOC_RETURN_NT: { 1106 | // Rd = add (Rs, #-1) ; if (p0.new) dealloc_return:nt 1107 | op->type = R_ANAL_OP_TYPE_RET; 1108 | break; 1109 | } 1110 | case HEX_INS_DUPLEX_RD___ADD__RS___1____DEALLOC_RETURN: { 1111 | // Rd = add (Rs, #1) ; dealloc_return 1112 | op->type = R_ANAL_OP_TYPE_RET; 1113 | break; 1114 | } 1115 | case HEX_INS_DUPLEX_RD___ADD__RS___1____IF___NOT__P0__DEALLOC_RETURN: { 1116 | // Rd = add (Rs, #1) ; if (! p0) dealloc_return 1117 | op->type = R_ANAL_OP_TYPE_RET; 1118 | break; 1119 | } 1120 | case HEX_INS_DUPLEX_RD___ADD__RS___1____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1121 | // Rd = add (Rs, #1) ; if (! p0.new) dealloc_return:nt 1122 | op->type = R_ANAL_OP_TYPE_RET; 1123 | break; 1124 | } 1125 | case HEX_INS_DUPLEX_RD___ADD__RS___1____IF__P0__DEALLOC_RETURN: { 1126 | // Rd = add (Rs, #1) ; if (p0) dealloc_return 1127 | op->type = R_ANAL_OP_TYPE_RET; 1128 | break; 1129 | } 1130 | case HEX_INS_DUPLEX_RD___ADD__RS___1____IF__P0_NEW__DEALLOC_RETURN_NT: { 1131 | // Rd = add (Rs, #1) ; if (p0.new) dealloc_return:nt 1132 | op->type = R_ANAL_OP_TYPE_RET; 1133 | break; 1134 | } 1135 | case HEX_INS_DUPLEX_RD___ADD__SP___U6_2____DEALLOC_RETURN: { 1136 | // Rd = add (Sp, #u6:2) ; dealloc_return 1137 | op->type = R_ANAL_OP_TYPE_RET; 1138 | break; 1139 | } 1140 | case HEX_INS_DUPLEX_RD___ADD__SP___U6_2____IF___NOT__P0__DEALLOC_RETURN: { 1141 | // Rd = add (Sp, #u6:2) ; if (! p0) dealloc_return 1142 | op->type = R_ANAL_OP_TYPE_RET; 1143 | break; 1144 | } 1145 | case HEX_INS_DUPLEX_RD___ADD__SP___U6_2____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1146 | // Rd = add (Sp, #u6:2) ; if (! p0.new) dealloc_return:nt 1147 | op->type = R_ANAL_OP_TYPE_RET; 1148 | break; 1149 | } 1150 | case HEX_INS_DUPLEX_RD___ADD__SP___U6_2____IF__P0__DEALLOC_RETURN: { 1151 | // Rd = add (Sp, #u6:2) ; if (p0) dealloc_return 1152 | op->type = R_ANAL_OP_TYPE_RET; 1153 | break; 1154 | } 1155 | case HEX_INS_DUPLEX_RD___ADD__SP___U6_2____IF__P0_NEW__DEALLOC_RETURN_NT: { 1156 | // Rd = add (Sp, #u6:2) ; if (p0.new) dealloc_return:nt 1157 | op->type = R_ANAL_OP_TYPE_RET; 1158 | break; 1159 | } 1160 | case HEX_INS_DUPLEX_RD___AND__RS___1____DEALLOC_RETURN: { 1161 | // Rd = and (Rs, #1) ; dealloc_return 1162 | op->type = R_ANAL_OP_TYPE_RET; 1163 | break; 1164 | } 1165 | case HEX_INS_DUPLEX_RD___AND__RS___1____IF___NOT__P0__DEALLOC_RETURN: { 1166 | // Rd = and (Rs, #1) ; if (! p0) dealloc_return 1167 | op->type = R_ANAL_OP_TYPE_RET; 1168 | break; 1169 | } 1170 | case HEX_INS_DUPLEX_RD___AND__RS___1____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1171 | // Rd = and (Rs, #1) ; if (! p0.new) dealloc_return:nt 1172 | op->type = R_ANAL_OP_TYPE_RET; 1173 | break; 1174 | } 1175 | case HEX_INS_DUPLEX_RD___AND__RS___1____IF__P0__DEALLOC_RETURN: { 1176 | // Rd = and (Rs, #1) ; if (p0) dealloc_return 1177 | op->type = R_ANAL_OP_TYPE_RET; 1178 | break; 1179 | } 1180 | case HEX_INS_DUPLEX_RD___AND__RS___1____IF__P0_NEW__DEALLOC_RETURN_NT: { 1181 | // Rd = and (Rs, #1) ; if (p0.new) dealloc_return:nt 1182 | op->type = R_ANAL_OP_TYPE_RET; 1183 | break; 1184 | } 1185 | case HEX_INS_DUPLEX_RD___AND__RS___255____DEALLOC_RETURN: { 1186 | // Rd = and (Rs, #255) ; dealloc_return 1187 | op->type = R_ANAL_OP_TYPE_RET; 1188 | break; 1189 | } 1190 | case HEX_INS_DUPLEX_RD___AND__RS___255____IF___NOT__P0__DEALLOC_RETURN: { 1191 | // Rd = and (Rs, #255) ; if (! p0) dealloc_return 1192 | op->type = R_ANAL_OP_TYPE_RET; 1193 | break; 1194 | } 1195 | case HEX_INS_DUPLEX_RD___AND__RS___255____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1196 | // Rd = and (Rs, #255) ; if (! p0.new) dealloc_return:nt 1197 | op->type = R_ANAL_OP_TYPE_RET; 1198 | break; 1199 | } 1200 | case HEX_INS_DUPLEX_RD___AND__RS___255____IF__P0__DEALLOC_RETURN: { 1201 | // Rd = and (Rs, #255) ; if (p0) dealloc_return 1202 | op->type = R_ANAL_OP_TYPE_RET; 1203 | break; 1204 | } 1205 | case HEX_INS_DUPLEX_RD___AND__RS___255____IF__P0_NEW__DEALLOC_RETURN_NT: { 1206 | // Rd = and (Rs, #255) ; if (p0.new) dealloc_return:nt 1207 | op->type = R_ANAL_OP_TYPE_RET; 1208 | break; 1209 | } 1210 | case HEX_INS_DUPLEX_RD___MEMB__RS____U3_0____DEALLOC_RETURN: { 1211 | // Rd = memb (Rs + #u3:0) ; dealloc_return 1212 | op->type = R_ANAL_OP_TYPE_RET; 1213 | break; 1214 | } 1215 | case HEX_INS_DUPLEX_RD___MEMB__RS____U3_0____IF___NOT__P0__DEALLOC_RETURN: { 1216 | // Rd = memb (Rs + #u3:0) ; if (! p0) dealloc_return 1217 | op->type = R_ANAL_OP_TYPE_RET; 1218 | break; 1219 | } 1220 | case HEX_INS_DUPLEX_RD___MEMB__RS____U3_0____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1221 | // Rd = memb (Rs + #u3:0) ; if (! p0.new) dealloc_return:nt 1222 | op->type = R_ANAL_OP_TYPE_RET; 1223 | break; 1224 | } 1225 | case HEX_INS_DUPLEX_RD___MEMB__RS____U3_0____IF__P0__DEALLOC_RETURN: { 1226 | // Rd = memb (Rs + #u3:0) ; if (p0) dealloc_return 1227 | op->type = R_ANAL_OP_TYPE_RET; 1228 | break; 1229 | } 1230 | case HEX_INS_DUPLEX_RD___MEMB__RS____U3_0____IF__P0_NEW__DEALLOC_RETURN_NT: { 1231 | // Rd = memb (Rs + #u3:0) ; if (p0.new) dealloc_return:nt 1232 | op->type = R_ANAL_OP_TYPE_RET; 1233 | break; 1234 | } 1235 | case HEX_INS_DUPLEX_RD___MEMH__RS____U3_1____DEALLOC_RETURN: { 1236 | // Rd = memh (Rs + #u3:1) ; dealloc_return 1237 | op->type = R_ANAL_OP_TYPE_RET; 1238 | break; 1239 | } 1240 | case HEX_INS_DUPLEX_RD___MEMH__RS____U3_1____IF___NOT__P0__DEALLOC_RETURN: { 1241 | // Rd = memh (Rs + #u3:1) ; if (! p0) dealloc_return 1242 | op->type = R_ANAL_OP_TYPE_RET; 1243 | break; 1244 | } 1245 | case HEX_INS_DUPLEX_RD___MEMH__RS____U3_1____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1246 | // Rd = memh (Rs + #u3:1) ; if (! p0.new) dealloc_return:nt 1247 | op->type = R_ANAL_OP_TYPE_RET; 1248 | break; 1249 | } 1250 | case HEX_INS_DUPLEX_RD___MEMH__RS____U3_1____IF__P0__DEALLOC_RETURN: { 1251 | // Rd = memh (Rs + #u3:1) ; if (p0) dealloc_return 1252 | op->type = R_ANAL_OP_TYPE_RET; 1253 | break; 1254 | } 1255 | case HEX_INS_DUPLEX_RD___MEMH__RS____U3_1____IF__P0_NEW__DEALLOC_RETURN_NT: { 1256 | // Rd = memh (Rs + #u3:1) ; if (p0.new) dealloc_return:nt 1257 | op->type = R_ANAL_OP_TYPE_RET; 1258 | break; 1259 | } 1260 | case HEX_INS_DUPLEX_RD___MEMUB__RS____U4_0____DEALLOC_RETURN: { 1261 | // Rd = memub (Rs + #u4:0) ; dealloc_return 1262 | op->type = R_ANAL_OP_TYPE_RET; 1263 | break; 1264 | } 1265 | case HEX_INS_DUPLEX_RD___MEMUB__RS____U4_0____IF___NOT__P0__DEALLOC_RETURN: { 1266 | // Rd = memub (Rs + #u4:0) ; if (! p0) dealloc_return 1267 | op->type = R_ANAL_OP_TYPE_RET; 1268 | break; 1269 | } 1270 | case HEX_INS_DUPLEX_RD___MEMUB__RS____U4_0____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1271 | // Rd = memub (Rs + #u4:0) ; if (! p0.new) dealloc_return:nt 1272 | op->type = R_ANAL_OP_TYPE_RET; 1273 | break; 1274 | } 1275 | case HEX_INS_DUPLEX_RD___MEMUB__RS____U4_0____IF__P0__DEALLOC_RETURN: { 1276 | // Rd = memub (Rs + #u4:0) ; if (p0) dealloc_return 1277 | op->type = R_ANAL_OP_TYPE_RET; 1278 | break; 1279 | } 1280 | case HEX_INS_DUPLEX_RD___MEMUB__RS____U4_0____IF__P0_NEW__DEALLOC_RETURN_NT: { 1281 | // Rd = memub (Rs + #u4:0) ; if (p0.new) dealloc_return:nt 1282 | op->type = R_ANAL_OP_TYPE_RET; 1283 | break; 1284 | } 1285 | case HEX_INS_DUPLEX_RD___MEMUH__RS____U3_1____DEALLOC_RETURN: { 1286 | // Rd = memuh (Rs + #u3:1) ; dealloc_return 1287 | op->type = R_ANAL_OP_TYPE_RET; 1288 | break; 1289 | } 1290 | case HEX_INS_DUPLEX_RD___MEMUH__RS____U3_1____IF___NOT__P0__DEALLOC_RETURN: { 1291 | // Rd = memuh (Rs + #u3:1) ; if (! p0) dealloc_return 1292 | op->type = R_ANAL_OP_TYPE_RET; 1293 | break; 1294 | } 1295 | case HEX_INS_DUPLEX_RD___MEMUH__RS____U3_1____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1296 | // Rd = memuh (Rs + #u3:1) ; if (! p0.new) dealloc_return:nt 1297 | op->type = R_ANAL_OP_TYPE_RET; 1298 | break; 1299 | } 1300 | case HEX_INS_DUPLEX_RD___MEMUH__RS____U3_1____IF__P0__DEALLOC_RETURN: { 1301 | // Rd = memuh (Rs + #u3:1) ; if (p0) dealloc_return 1302 | op->type = R_ANAL_OP_TYPE_RET; 1303 | break; 1304 | } 1305 | case HEX_INS_DUPLEX_RD___MEMUH__RS____U3_1____IF__P0_NEW__DEALLOC_RETURN_NT: { 1306 | // Rd = memuh (Rs + #u3:1) ; if (p0.new) dealloc_return:nt 1307 | op->type = R_ANAL_OP_TYPE_RET; 1308 | break; 1309 | } 1310 | case HEX_INS_DUPLEX_RD___MEMW__RS____U4_2____DEALLOC_RETURN: { 1311 | // Rd = memw (Rs + #u4:2) ; dealloc_return 1312 | op->type = R_ANAL_OP_TYPE_RET; 1313 | break; 1314 | } 1315 | case HEX_INS_DUPLEX_RD___MEMW__RS____U4_2____IF___NOT__P0__DEALLOC_RETURN: { 1316 | // Rd = memw (Rs + #u4:2) ; if (! p0) dealloc_return 1317 | op->type = R_ANAL_OP_TYPE_RET; 1318 | break; 1319 | } 1320 | case HEX_INS_DUPLEX_RD___MEMW__RS____U4_2____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1321 | // Rd = memw (Rs + #u4:2) ; if (! p0.new) dealloc_return:nt 1322 | op->type = R_ANAL_OP_TYPE_RET; 1323 | break; 1324 | } 1325 | case HEX_INS_DUPLEX_RD___MEMW__RS____U4_2____IF__P0__DEALLOC_RETURN: { 1326 | // Rd = memw (Rs + #u4:2) ; if (p0) dealloc_return 1327 | op->type = R_ANAL_OP_TYPE_RET; 1328 | break; 1329 | } 1330 | case HEX_INS_DUPLEX_RD___MEMW__RS____U4_2____IF__P0_NEW__DEALLOC_RETURN_NT: { 1331 | // Rd = memw (Rs + #u4:2) ; if (p0.new) dealloc_return:nt 1332 | op->type = R_ANAL_OP_TYPE_RET; 1333 | break; 1334 | } 1335 | case HEX_INS_DUPLEX_RD___MEMW__SP____U5_2____DEALLOC_RETURN: { 1336 | // Rd = memw (Sp + #u5:2) ; dealloc_return 1337 | op->type = R_ANAL_OP_TYPE_RET; 1338 | break; 1339 | } 1340 | case HEX_INS_DUPLEX_RD___MEMW__SP____U5_2____IF___NOT__P0__DEALLOC_RETURN: { 1341 | // Rd = memw (Sp + #u5:2) ; if (! p0) dealloc_return 1342 | op->type = R_ANAL_OP_TYPE_RET; 1343 | break; 1344 | } 1345 | case HEX_INS_DUPLEX_RD___MEMW__SP____U5_2____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1346 | // Rd = memw (Sp + #u5:2) ; if (! p0.new) dealloc_return:nt 1347 | op->type = R_ANAL_OP_TYPE_RET; 1348 | break; 1349 | } 1350 | case HEX_INS_DUPLEX_RD___MEMW__SP____U5_2____IF__P0__DEALLOC_RETURN: { 1351 | // Rd = memw (Sp + #u5:2) ; if (p0) dealloc_return 1352 | op->type = R_ANAL_OP_TYPE_RET; 1353 | break; 1354 | } 1355 | case HEX_INS_DUPLEX_RD___MEMW__SP____U5_2____IF__P0_NEW__DEALLOC_RETURN_NT: { 1356 | // Rd = memw (Sp + #u5:2) ; if (p0.new) dealloc_return:nt 1357 | op->type = R_ANAL_OP_TYPE_RET; 1358 | break; 1359 | } 1360 | case HEX_INS_DUPLEX_RD___SXTB__RS____DEALLOC_RETURN: { 1361 | // Rd = sxtb (Rs) ; dealloc_return 1362 | op->type = R_ANAL_OP_TYPE_RET; 1363 | break; 1364 | } 1365 | case HEX_INS_DUPLEX_RD___SXTB__RS____IF___NOT__P0__DEALLOC_RETURN: { 1366 | // Rd = sxtb (Rs) ; if (! p0) dealloc_return 1367 | op->type = R_ANAL_OP_TYPE_RET; 1368 | break; 1369 | } 1370 | case HEX_INS_DUPLEX_RD___SXTB__RS____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1371 | // Rd = sxtb (Rs) ; if (! p0.new) dealloc_return:nt 1372 | op->type = R_ANAL_OP_TYPE_RET; 1373 | break; 1374 | } 1375 | case HEX_INS_DUPLEX_RD___SXTB__RS____IF__P0__DEALLOC_RETURN: { 1376 | // Rd = sxtb (Rs) ; if (p0) dealloc_return 1377 | op->type = R_ANAL_OP_TYPE_RET; 1378 | break; 1379 | } 1380 | case HEX_INS_DUPLEX_RD___SXTB__RS____IF__P0_NEW__DEALLOC_RETURN_NT: { 1381 | // Rd = sxtb (Rs) ; if (p0.new) dealloc_return:nt 1382 | op->type = R_ANAL_OP_TYPE_RET; 1383 | break; 1384 | } 1385 | case HEX_INS_DUPLEX_RD___SXTH__RS____DEALLOC_RETURN: { 1386 | // Rd = sxth (Rs) ; dealloc_return 1387 | op->type = R_ANAL_OP_TYPE_RET; 1388 | break; 1389 | } 1390 | case HEX_INS_DUPLEX_RD___SXTH__RS____IF___NOT__P0__DEALLOC_RETURN: { 1391 | // Rd = sxth (Rs) ; if (! p0) dealloc_return 1392 | op->type = R_ANAL_OP_TYPE_RET; 1393 | break; 1394 | } 1395 | case HEX_INS_DUPLEX_RD___SXTH__RS____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1396 | // Rd = sxth (Rs) ; if (! p0.new) dealloc_return:nt 1397 | op->type = R_ANAL_OP_TYPE_RET; 1398 | break; 1399 | } 1400 | case HEX_INS_DUPLEX_RD___SXTH__RS____IF__P0__DEALLOC_RETURN: { 1401 | // Rd = sxth (Rs) ; if (p0) dealloc_return 1402 | op->type = R_ANAL_OP_TYPE_RET; 1403 | break; 1404 | } 1405 | case HEX_INS_DUPLEX_RD___SXTH__RS____IF__P0_NEW__DEALLOC_RETURN_NT: { 1406 | // Rd = sxth (Rs) ; if (p0.new) dealloc_return:nt 1407 | op->type = R_ANAL_OP_TYPE_RET; 1408 | break; 1409 | } 1410 | case HEX_INS_DUPLEX_RD___ZXTH__RS____DEALLOC_RETURN: { 1411 | // Rd = zxth (Rs) ; dealloc_return 1412 | op->type = R_ANAL_OP_TYPE_RET; 1413 | break; 1414 | } 1415 | case HEX_INS_DUPLEX_RD___ZXTH__RS____IF___NOT__P0__DEALLOC_RETURN: { 1416 | // Rd = zxth (Rs) ; if (! p0) dealloc_return 1417 | op->type = R_ANAL_OP_TYPE_RET; 1418 | break; 1419 | } 1420 | case HEX_INS_DUPLEX_RD___ZXTH__RS____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1421 | // Rd = zxth (Rs) ; if (! p0.new) dealloc_return:nt 1422 | op->type = R_ANAL_OP_TYPE_RET; 1423 | break; 1424 | } 1425 | case HEX_INS_DUPLEX_RD___ZXTH__RS____IF__P0__DEALLOC_RETURN: { 1426 | // Rd = zxth (Rs) ; if (p0) dealloc_return 1427 | op->type = R_ANAL_OP_TYPE_RET; 1428 | break; 1429 | } 1430 | case HEX_INS_DUPLEX_RD___ZXTH__RS____IF__P0_NEW__DEALLOC_RETURN_NT: { 1431 | // Rd = zxth (Rs) ; if (p0.new) dealloc_return:nt 1432 | op->type = R_ANAL_OP_TYPE_RET; 1433 | break; 1434 | } 1435 | case HEX_INS_DUPLEX_RDD___COMBINE___0___U2____DEALLOC_RETURN: { 1436 | // Rdd = combine (#0, #u2) ; dealloc_return 1437 | op->type = R_ANAL_OP_TYPE_RET; 1438 | break; 1439 | } 1440 | case HEX_INS_DUPLEX_RDD___COMBINE___0___U2____IF___NOT__P0__DEALLOC_RETURN: { 1441 | // Rdd = combine (#0, #u2) ; if (! p0) dealloc_return 1442 | op->type = R_ANAL_OP_TYPE_RET; 1443 | break; 1444 | } 1445 | case HEX_INS_DUPLEX_RDD___COMBINE___0___U2____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1446 | // Rdd = combine (#0, #u2) ; if (! p0.new) dealloc_return:nt 1447 | op->type = R_ANAL_OP_TYPE_RET; 1448 | break; 1449 | } 1450 | case HEX_INS_DUPLEX_RDD___COMBINE___0___U2____IF__P0__DEALLOC_RETURN: { 1451 | // Rdd = combine (#0, #u2) ; if (p0) dealloc_return 1452 | op->type = R_ANAL_OP_TYPE_RET; 1453 | break; 1454 | } 1455 | case HEX_INS_DUPLEX_RDD___COMBINE___0___U2____IF__P0_NEW__DEALLOC_RETURN_NT: { 1456 | // Rdd = combine (#0, #u2) ; if (p0.new) dealloc_return:nt 1457 | op->type = R_ANAL_OP_TYPE_RET; 1458 | break; 1459 | } 1460 | case HEX_INS_DUPLEX_RDD___COMBINE___0__RS____DEALLOC_RETURN: { 1461 | // Rdd = combine (#0, Rs) ; dealloc_return 1462 | op->type = R_ANAL_OP_TYPE_RET; 1463 | break; 1464 | } 1465 | case HEX_INS_DUPLEX_RDD___COMBINE___0__RS____IF___NOT__P0__DEALLOC_RETURN: { 1466 | // Rdd = combine (#0, Rs) ; if (! p0) dealloc_return 1467 | op->type = R_ANAL_OP_TYPE_RET; 1468 | break; 1469 | } 1470 | case HEX_INS_DUPLEX_RDD___COMBINE___0__RS____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1471 | // Rdd = combine (#0, Rs) ; if (! p0.new) dealloc_return:nt 1472 | op->type = R_ANAL_OP_TYPE_RET; 1473 | break; 1474 | } 1475 | case HEX_INS_DUPLEX_RDD___COMBINE___0__RS____IF__P0__DEALLOC_RETURN: { 1476 | // Rdd = combine (#0, Rs) ; if (p0) dealloc_return 1477 | op->type = R_ANAL_OP_TYPE_RET; 1478 | break; 1479 | } 1480 | case HEX_INS_DUPLEX_RDD___COMBINE___0__RS____IF__P0_NEW__DEALLOC_RETURN_NT: { 1481 | // Rdd = combine (#0, Rs) ; if (p0.new) dealloc_return:nt 1482 | op->type = R_ANAL_OP_TYPE_RET; 1483 | break; 1484 | } 1485 | case HEX_INS_DUPLEX_RDD___COMBINE___1___U2____DEALLOC_RETURN: { 1486 | // Rdd = combine (#1, #u2) ; dealloc_return 1487 | op->type = R_ANAL_OP_TYPE_RET; 1488 | break; 1489 | } 1490 | case HEX_INS_DUPLEX_RDD___COMBINE___1___U2____IF___NOT__P0__DEALLOC_RETURN: { 1491 | // Rdd = combine (#1, #u2) ; if (! p0) dealloc_return 1492 | op->type = R_ANAL_OP_TYPE_RET; 1493 | break; 1494 | } 1495 | case HEX_INS_DUPLEX_RDD___COMBINE___1___U2____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1496 | // Rdd = combine (#1, #u2) ; if (! p0.new) dealloc_return:nt 1497 | op->type = R_ANAL_OP_TYPE_RET; 1498 | break; 1499 | } 1500 | case HEX_INS_DUPLEX_RDD___COMBINE___1___U2____IF__P0__DEALLOC_RETURN: { 1501 | // Rdd = combine (#1, #u2) ; if (p0) dealloc_return 1502 | op->type = R_ANAL_OP_TYPE_RET; 1503 | break; 1504 | } 1505 | case HEX_INS_DUPLEX_RDD___COMBINE___1___U2____IF__P0_NEW__DEALLOC_RETURN_NT: { 1506 | // Rdd = combine (#1, #u2) ; if (p0.new) dealloc_return:nt 1507 | op->type = R_ANAL_OP_TYPE_RET; 1508 | break; 1509 | } 1510 | case HEX_INS_DUPLEX_RDD___COMBINE___2___U2____DEALLOC_RETURN: { 1511 | // Rdd = combine (#2, #u2) ; dealloc_return 1512 | op->type = R_ANAL_OP_TYPE_RET; 1513 | break; 1514 | } 1515 | case HEX_INS_DUPLEX_RDD___COMBINE___2___U2____IF___NOT__P0__DEALLOC_RETURN: { 1516 | // Rdd = combine (#2, #u2) ; if (! p0) dealloc_return 1517 | op->type = R_ANAL_OP_TYPE_RET; 1518 | break; 1519 | } 1520 | case HEX_INS_DUPLEX_RDD___COMBINE___2___U2____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1521 | // Rdd = combine (#2, #u2) ; if (! p0.new) dealloc_return:nt 1522 | op->type = R_ANAL_OP_TYPE_RET; 1523 | break; 1524 | } 1525 | case HEX_INS_DUPLEX_RDD___COMBINE___2___U2____IF__P0__DEALLOC_RETURN: { 1526 | // Rdd = combine (#2, #u2) ; if (p0) dealloc_return 1527 | op->type = R_ANAL_OP_TYPE_RET; 1528 | break; 1529 | } 1530 | case HEX_INS_DUPLEX_RDD___COMBINE___2___U2____IF__P0_NEW__DEALLOC_RETURN_NT: { 1531 | // Rdd = combine (#2, #u2) ; if (p0.new) dealloc_return:nt 1532 | op->type = R_ANAL_OP_TYPE_RET; 1533 | break; 1534 | } 1535 | case HEX_INS_DUPLEX_RDD___COMBINE___3___U2____DEALLOC_RETURN: { 1536 | // Rdd = combine (#3, #u2) ; dealloc_return 1537 | op->type = R_ANAL_OP_TYPE_RET; 1538 | break; 1539 | } 1540 | case HEX_INS_DUPLEX_RDD___COMBINE___3___U2____IF___NOT__P0__DEALLOC_RETURN: { 1541 | // Rdd = combine (#3, #u2) ; if (! p0) dealloc_return 1542 | op->type = R_ANAL_OP_TYPE_RET; 1543 | break; 1544 | } 1545 | case HEX_INS_DUPLEX_RDD___COMBINE___3___U2____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1546 | // Rdd = combine (#3, #u2) ; if (! p0.new) dealloc_return:nt 1547 | op->type = R_ANAL_OP_TYPE_RET; 1548 | break; 1549 | } 1550 | case HEX_INS_DUPLEX_RDD___COMBINE___3___U2____IF__P0__DEALLOC_RETURN: { 1551 | // Rdd = combine (#3, #u2) ; if (p0) dealloc_return 1552 | op->type = R_ANAL_OP_TYPE_RET; 1553 | break; 1554 | } 1555 | case HEX_INS_DUPLEX_RDD___COMBINE___3___U2____IF__P0_NEW__DEALLOC_RETURN_NT: { 1556 | // Rdd = combine (#3, #u2) ; if (p0.new) dealloc_return:nt 1557 | op->type = R_ANAL_OP_TYPE_RET; 1558 | break; 1559 | } 1560 | case HEX_INS_DUPLEX_RDD___COMBINE__RS___0____DEALLOC_RETURN: { 1561 | // Rdd = combine (Rs, #0) ; dealloc_return 1562 | op->type = R_ANAL_OP_TYPE_RET; 1563 | break; 1564 | } 1565 | case HEX_INS_DUPLEX_RDD___COMBINE__RS___0____IF___NOT__P0__DEALLOC_RETURN: { 1566 | // Rdd = combine (Rs, #0) ; if (! p0) dealloc_return 1567 | op->type = R_ANAL_OP_TYPE_RET; 1568 | break; 1569 | } 1570 | case HEX_INS_DUPLEX_RDD___COMBINE__RS___0____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1571 | // Rdd = combine (Rs, #0) ; if (! p0.new) dealloc_return:nt 1572 | op->type = R_ANAL_OP_TYPE_RET; 1573 | break; 1574 | } 1575 | case HEX_INS_DUPLEX_RDD___COMBINE__RS___0____IF__P0__DEALLOC_RETURN: { 1576 | // Rdd = combine (Rs, #0) ; if (p0) dealloc_return 1577 | op->type = R_ANAL_OP_TYPE_RET; 1578 | break; 1579 | } 1580 | case HEX_INS_DUPLEX_RDD___COMBINE__RS___0____IF__P0_NEW__DEALLOC_RETURN_NT: { 1581 | // Rdd = combine (Rs, #0) ; if (p0.new) dealloc_return:nt 1582 | op->type = R_ANAL_OP_TYPE_RET; 1583 | break; 1584 | } 1585 | case HEX_INS_DUPLEX_RDD___MEMD__SP____U5_3____DEALLOC_RETURN: { 1586 | // Rdd = memd (Sp + #u5:3) ; dealloc_return 1587 | op->type = R_ANAL_OP_TYPE_RET; 1588 | break; 1589 | } 1590 | case HEX_INS_DUPLEX_RDD___MEMD__SP____U5_3____IF___NOT__P0__DEALLOC_RETURN: { 1591 | // Rdd = memd (Sp + #u5:3) ; if (! p0) dealloc_return 1592 | op->type = R_ANAL_OP_TYPE_RET; 1593 | break; 1594 | } 1595 | case HEX_INS_DUPLEX_RDD___MEMD__SP____U5_3____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1596 | // Rdd = memd (Sp + #u5:3) ; if (! p0.new) dealloc_return:nt 1597 | op->type = R_ANAL_OP_TYPE_RET; 1598 | break; 1599 | } 1600 | case HEX_INS_DUPLEX_RDD___MEMD__SP____U5_3____IF__P0__DEALLOC_RETURN: { 1601 | // Rdd = memd (Sp + #u5:3) ; if (p0) dealloc_return 1602 | op->type = R_ANAL_OP_TYPE_RET; 1603 | break; 1604 | } 1605 | case HEX_INS_DUPLEX_RDD___MEMD__SP____U5_3____IF__P0_NEW__DEALLOC_RETURN_NT: { 1606 | // Rdd = memd (Sp + #u5:3) ; if (p0.new) dealloc_return:nt 1607 | op->type = R_ANAL_OP_TYPE_RET; 1608 | break; 1609 | } 1610 | case HEX_INS_DUPLEX_RX___ADD__RS__RX____DEALLOC_RETURN: { 1611 | // Rx = add (Rs, Rx) ; dealloc_return 1612 | op->type = R_ANAL_OP_TYPE_RET; 1613 | break; 1614 | } 1615 | case HEX_INS_DUPLEX_RX___ADD__RS__RX____IF___NOT__P0__DEALLOC_RETURN: { 1616 | // Rx = add (Rs, Rx) ; if (! p0) dealloc_return 1617 | op->type = R_ANAL_OP_TYPE_RET; 1618 | break; 1619 | } 1620 | case HEX_INS_DUPLEX_RX___ADD__RS__RX____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1621 | // Rx = add (Rs, Rx) ; if (! p0.new) dealloc_return:nt 1622 | op->type = R_ANAL_OP_TYPE_RET; 1623 | break; 1624 | } 1625 | case HEX_INS_DUPLEX_RX___ADD__RS__RX____IF__P0__DEALLOC_RETURN: { 1626 | // Rx = add (Rs, Rx) ; if (p0) dealloc_return 1627 | op->type = R_ANAL_OP_TYPE_RET; 1628 | break; 1629 | } 1630 | case HEX_INS_DUPLEX_RX___ADD__RS__RX____IF__P0_NEW__DEALLOC_RETURN_NT: { 1631 | // Rx = add (Rs, Rx) ; if (p0.new) dealloc_return:nt 1632 | op->type = R_ANAL_OP_TYPE_RET; 1633 | break; 1634 | } 1635 | case HEX_INS_DUPLEX_RX___ADD__RX___S7____DEALLOC_RETURN: { 1636 | // Rx = add (Rx, #s7) ; dealloc_return 1637 | op->type = R_ANAL_OP_TYPE_RET; 1638 | break; 1639 | } 1640 | case HEX_INS_DUPLEX_RX___ADD__RX___S7____IF___NOT__P0__DEALLOC_RETURN: { 1641 | // Rx = add (Rx, #s7) ; if (! p0) dealloc_return 1642 | op->type = R_ANAL_OP_TYPE_RET; 1643 | break; 1644 | } 1645 | case HEX_INS_DUPLEX_RX___ADD__RX___S7____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1646 | // Rx = add (Rx, #s7) ; if (! p0.new) dealloc_return:nt 1647 | op->type = R_ANAL_OP_TYPE_RET; 1648 | break; 1649 | } 1650 | case HEX_INS_DUPLEX_RX___ADD__RX___S7____IF__P0__DEALLOC_RETURN: { 1651 | // Rx = add (Rx, #s7) ; if (p0) dealloc_return 1652 | op->type = R_ANAL_OP_TYPE_RET; 1653 | break; 1654 | } 1655 | case HEX_INS_DUPLEX_RX___ADD__RX___S7____IF__P0_NEW__DEALLOC_RETURN_NT: { 1656 | // Rx = add (Rx, #s7) ; if (p0.new) dealloc_return:nt 1657 | op->type = R_ANAL_OP_TYPE_RET; 1658 | break; 1659 | } 1660 | case HEX_INS_DUPLEX_RX___ADD__RX__RS____DEALLOC_RETURN: { 1661 | // Rx = add (Rx, Rs) ; dealloc_return 1662 | op->type = R_ANAL_OP_TYPE_RET; 1663 | break; 1664 | } 1665 | case HEX_INS_DUPLEX_RX___ADD__RX__RS____IF___NOT__P0__DEALLOC_RETURN: { 1666 | // Rx = add (Rx, Rs) ; if (! p0) dealloc_return 1667 | op->type = R_ANAL_OP_TYPE_RET; 1668 | break; 1669 | } 1670 | case HEX_INS_DUPLEX_RX___ADD__RX__RS____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1671 | // Rx = add (Rx, Rs) ; if (! p0.new) dealloc_return:nt 1672 | op->type = R_ANAL_OP_TYPE_RET; 1673 | break; 1674 | } 1675 | case HEX_INS_DUPLEX_RX___ADD__RX__RS____IF__P0__DEALLOC_RETURN: { 1676 | // Rx = add (Rx, Rs) ; if (p0) dealloc_return 1677 | op->type = R_ANAL_OP_TYPE_RET; 1678 | break; 1679 | } 1680 | case HEX_INS_DUPLEX_RX___ADD__RX__RS____IF__P0_NEW__DEALLOC_RETURN_NT: { 1681 | // Rx = add (Rx, Rs) ; if (p0.new) dealloc_return:nt 1682 | op->type = R_ANAL_OP_TYPE_RET; 1683 | break; 1684 | } 1685 | case HEX_INS_DUPLEX_IF___NOT__P0__RD____0___DEALLOC_RETURN: { 1686 | // if (! p0) Rd = #0 ; dealloc_return 1687 | op->type = R_ANAL_OP_TYPE_RET; 1688 | break; 1689 | } 1690 | case HEX_INS_DUPLEX_IF___NOT__P0__RD____0___IF___NOT__P0__DEALLOC_RETURN: { 1691 | // if (! p0) Rd = #0 ; if (! p0) dealloc_return 1692 | op->type = R_ANAL_OP_TYPE_RET; 1693 | break; 1694 | } 1695 | case HEX_INS_DUPLEX_IF___NOT__P0__RD____0___IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1696 | // if (! p0) Rd = #0 ; if (! p0.new) dealloc_return:nt 1697 | op->type = R_ANAL_OP_TYPE_RET; 1698 | break; 1699 | } 1700 | case HEX_INS_DUPLEX_IF___NOT__P0__RD____0___IF__P0__DEALLOC_RETURN: { 1701 | // if (! p0) Rd = #0 ; if (p0) dealloc_return 1702 | op->type = R_ANAL_OP_TYPE_RET; 1703 | break; 1704 | } 1705 | case HEX_INS_DUPLEX_IF___NOT__P0__RD____0___IF__P0_NEW__DEALLOC_RETURN_NT: { 1706 | // if (! p0) Rd = #0 ; if (p0.new) dealloc_return:nt 1707 | op->type = R_ANAL_OP_TYPE_RET; 1708 | break; 1709 | } 1710 | case HEX_INS_DUPLEX_IF___NOT__P0_NEW__RD____0___DEALLOC_RETURN: { 1711 | // if (! p0.new) Rd = #0 ; dealloc_return 1712 | op->type = R_ANAL_OP_TYPE_RET; 1713 | break; 1714 | } 1715 | case HEX_INS_DUPLEX_IF___NOT__P0_NEW__RD____0___IF___NOT__P0__DEALLOC_RETURN: { 1716 | // if (! p0.new) Rd = #0 ; if (! p0) dealloc_return 1717 | op->type = R_ANAL_OP_TYPE_RET; 1718 | break; 1719 | } 1720 | case HEX_INS_DUPLEX_IF___NOT__P0_NEW__RD____0___IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1721 | // if (! p0.new) Rd = #0 ; if (! p0.new) dealloc_return:nt 1722 | op->type = R_ANAL_OP_TYPE_RET; 1723 | break; 1724 | } 1725 | case HEX_INS_DUPLEX_IF___NOT__P0_NEW__RD____0___IF__P0__DEALLOC_RETURN: { 1726 | // if (! p0.new) Rd = #0 ; if (p0) dealloc_return 1727 | op->type = R_ANAL_OP_TYPE_RET; 1728 | break; 1729 | } 1730 | case HEX_INS_DUPLEX_IF___NOT__P0_NEW__RD____0___IF__P0_NEW__DEALLOC_RETURN_NT: { 1731 | // if (! p0.new) Rd = #0 ; if (p0.new) dealloc_return:nt 1732 | op->type = R_ANAL_OP_TYPE_RET; 1733 | break; 1734 | } 1735 | case HEX_INS_DUPLEX_IF__P0__RD____0___DEALLOC_RETURN: { 1736 | // if (p0) Rd = #0 ; dealloc_return 1737 | op->type = R_ANAL_OP_TYPE_RET; 1738 | break; 1739 | } 1740 | case HEX_INS_DUPLEX_IF__P0__RD____0___IF___NOT__P0__DEALLOC_RETURN: { 1741 | // if (p0) Rd = #0 ; if (! p0) dealloc_return 1742 | op->type = R_ANAL_OP_TYPE_RET; 1743 | break; 1744 | } 1745 | case HEX_INS_DUPLEX_IF__P0__RD____0___IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1746 | // if (p0) Rd = #0 ; if (! p0.new) dealloc_return:nt 1747 | op->type = R_ANAL_OP_TYPE_RET; 1748 | break; 1749 | } 1750 | case HEX_INS_DUPLEX_IF__P0__RD____0___IF__P0__DEALLOC_RETURN: { 1751 | // if (p0) Rd = #0 ; if (p0) dealloc_return 1752 | op->type = R_ANAL_OP_TYPE_RET; 1753 | break; 1754 | } 1755 | case HEX_INS_DUPLEX_IF__P0__RD____0___IF__P0_NEW__DEALLOC_RETURN_NT: { 1756 | // if (p0) Rd = #0 ; if (p0.new) dealloc_return:nt 1757 | op->type = R_ANAL_OP_TYPE_RET; 1758 | break; 1759 | } 1760 | case HEX_INS_DUPLEX_IF__P0_NEW__RD____0___DEALLOC_RETURN: { 1761 | // if (p0.new) Rd = #0 ; dealloc_return 1762 | op->type = R_ANAL_OP_TYPE_RET; 1763 | break; 1764 | } 1765 | case HEX_INS_DUPLEX_IF__P0_NEW__RD____0___IF___NOT__P0__DEALLOC_RETURN: { 1766 | // if (p0.new) Rd = #0 ; if (! p0) dealloc_return 1767 | op->type = R_ANAL_OP_TYPE_RET; 1768 | break; 1769 | } 1770 | case HEX_INS_DUPLEX_IF__P0_NEW__RD____0___IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1771 | // if (p0.new) Rd = #0 ; if (! p0.new) dealloc_return:nt 1772 | op->type = R_ANAL_OP_TYPE_RET; 1773 | break; 1774 | } 1775 | case HEX_INS_DUPLEX_IF__P0_NEW__RD____0___IF__P0__DEALLOC_RETURN: { 1776 | // if (p0.new) Rd = #0 ; if (p0) dealloc_return 1777 | op->type = R_ANAL_OP_TYPE_RET; 1778 | break; 1779 | } 1780 | case HEX_INS_DUPLEX_IF__P0_NEW__RD____0___IF__P0_NEW__DEALLOC_RETURN_NT: { 1781 | // if (p0.new) Rd = #0 ; if (p0.new) dealloc_return:nt 1782 | op->type = R_ANAL_OP_TYPE_RET; 1783 | break; 1784 | } 1785 | case HEX_INS_DUPLEX_P0___CMP_EQ__RS___U2____DEALLOC_RETURN: { 1786 | // p0 = cmp.eq (Rs, #u2) ; dealloc_return 1787 | op->type = R_ANAL_OP_TYPE_RET; 1788 | break; 1789 | } 1790 | case HEX_INS_DUPLEX_P0___CMP_EQ__RS___U2____IF___NOT__P0__DEALLOC_RETURN: { 1791 | // p0 = cmp.eq (Rs, #u2) ; if (! p0) dealloc_return 1792 | op->type = R_ANAL_OP_TYPE_RET; 1793 | break; 1794 | } 1795 | case HEX_INS_DUPLEX_P0___CMP_EQ__RS___U2____IF___NOT__P0_NEW__DEALLOC_RETURN_NT: { 1796 | // p0 = cmp.eq (Rs, #u2) ; if (! p0.new) dealloc_return:nt 1797 | op->type = R_ANAL_OP_TYPE_RET; 1798 | break; 1799 | } 1800 | case HEX_INS_DUPLEX_P0___CMP_EQ__RS___U2____IF__P0__DEALLOC_RETURN: { 1801 | // p0 = cmp.eq (Rs, #u2) ; if (p0) dealloc_return 1802 | op->type = R_ANAL_OP_TYPE_RET; 1803 | break; 1804 | } 1805 | case HEX_INS_DUPLEX_P0___CMP_EQ__RS___U2____IF__P0_NEW__DEALLOC_RETURN_NT: { 1806 | // p0 = cmp.eq (Rs, #u2) ; if (p0.new) dealloc_return:nt 1807 | op->type = R_ANAL_OP_TYPE_RET; 1808 | break; 1809 | } 1810 | } 1811 | return op->size; 1812 | } 1813 | -------------------------------------------------------------------------------- /importer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # pylint: disable=missing-docstring, invalid-name, line-too-long, too-many-lines, fixme 3 | # pylint: disable=too-few-public-methods 4 | 5 | from __future__ import (absolute_import, division, 6 | print_function, unicode_literals) 7 | 8 | import argparse 9 | import re 10 | import operator 11 | import collections 12 | import sys 13 | 14 | class UnexpectedException(Exception): 15 | def __init__(self, message): 16 | super().__init__(message) 17 | 18 | def standarize_syntax_objdump(syntax): 19 | """Change instruction syntax to match Qualcomm's objdump output. 20 | 21 | Args: 22 | syntax (str): instruction syntax, probably as was obtained from the parsed manual. 23 | 24 | Returns: 25 | str: matching objdump syntax (as close as possible). 26 | 27 | TODO: 28 | * Care should be taken not to modify the syntax patterns used in the decoder 29 | to recognize different attributes of the instruction, e.g., ``Rd`` can 30 | be splitted with a space like ``R d``. 31 | 32 | * Document the most complex regex. 33 | 34 | """ 35 | 36 | # Add spaces to certain chars like '=' and '()' 37 | 38 | both_spaces = ['=', '+', '-', '*', '/', '&', '|', '<<', '^'] 39 | left_space = ['(', '!'] 40 | rigth_space = [')', ','] 41 | for c in both_spaces: 42 | syntax = syntax.replace(c, ' ' + c + ' ') 43 | for c in left_space: 44 | syntax = syntax.replace(c, ' ' + c) 45 | for c in rigth_space: 46 | syntax = syntax.replace(c, c + ' ') 47 | 48 | syntax = re.sub(r'\s{2,}', ' ', syntax) 49 | 50 | # TODO: Special hack for the unary minus. 51 | syntax = re.sub(r'\#\s-\s', '#-', syntax) 52 | 53 | syntax = re.sub(r'\(\s*', '(', syntax) 54 | syntax = re.sub(r'\s*\)', ')', syntax) 55 | 56 | # Compound assingment 57 | syntax = re.sub(r'([\+\-\*\/\&\|\^\!]) =', r'\1=', syntax) 58 | 59 | syntax = syntax.replace(' ,', ',') 60 | syntax = syntax.replace(' .', '.') 61 | 62 | # Remove parenthesis from (!p0.new). just to match objdump, 63 | # but I prefer it with parenthesis. 64 | if ';' not in syntax: 65 | m = re.search(r'\( (\s* ! \s* [pP]\w(.new)? \s*) \)', syntax, re.X) 66 | 67 | if m: 68 | syntax = syntax.replace('(' + m.group(1) + ')', m.group(1)) 69 | # syntax = re.sub(r'\( (\s* ! \s* [pP]\w(.new)? \s*) \)', r'\1', syntax, re.X) 70 | # TODO: The re.sub is not working, don't know why.. 71 | 72 | 73 | syntax = syntax.replace('dfcmp', 'cmp') 74 | syntax = syntax.replace('sfcmp', 'cmp') 75 | 76 | # Special cases: ++, ==, != 77 | syntax = syntax.replace('+ +', '++') 78 | syntax = syntax.replace('= =', '==') 79 | syntax = syntax.replace('! =', '!=') 80 | 81 | # Special cases: <>1 82 | syntax = syntax.replace(': << N', ':<> 1', ':>>1') 85 | 86 | syntax = syntax.strip() 87 | 88 | return syntax 89 | 90 | 91 | class OperandTemplate(): 92 | # TODO: Document class. 93 | 94 | __slots__ = ['syntax_name'] 95 | # TODO: Change `syntax_name` to ``syntax``. 96 | 97 | def __init__(self, syntax_name): 98 | self.syntax_name = syntax_name 99 | 100 | 101 | class RegisterTemplate(OperandTemplate): 102 | # TODO: Document class. 103 | 104 | __slots__ = ['is_register_pair', 'is_predicate', 'is_control', 'is_system', 'is_newvalue', 'syntax', 'index'] 105 | 106 | def __init__(self, syntax_name): 107 | super(RegisterTemplate, self).__init__(syntax_name) 108 | self.syntax = syntax_name 109 | self.is_register_pair = False 110 | self.is_control = False 111 | self.is_system = False 112 | self.is_predicate = False 113 | self.is_newvalue = False 114 | self.index = 0 115 | 116 | # Register pair analysis. 117 | 118 | if self.syntax_name[0] == 'R': 119 | # General register. 120 | 121 | if len(self.syntax_name[1:]) == 2: 122 | self.is_register_pair = True 123 | 124 | if self.syntax_name[1] != self.syntax_name[2]: 125 | # the two chars of the register pair do not match 126 | raise UnexpectedException("The two chars of the register pair do not match:" 127 | "'{:s}' and '{:s}'".format(self.syntax_name[1], self.syntax_name[2])) 128 | 129 | if self.syntax_name[0] == 'P': 130 | # Predicate 131 | self.is_predicate = True 132 | 133 | if self.syntax_name[0] == 'C': 134 | # Control register 135 | self.is_control = True 136 | if len(self.syntax_name[1:]) == 2: 137 | self.is_register_pair = True 138 | 139 | if self.syntax_name[1] != self.syntax_name[2]: 140 | # the two chars of the register pair do not match 141 | raise UnexpectedException("The two chars of the register pair do not match:" 142 | "'{:s}' and '{:s}'".format(self.syntax_name[1], self.syntax_name[2])) 143 | 144 | if self.syntax_name[0] == 'S': 145 | # System control register 146 | self.is_system = True 147 | if len(self.syntax_name[1:]) == 2: 148 | self.is_register_pair = True 149 | 150 | if self.syntax_name[1] != self.syntax_name[2]: 151 | # the two chars of the register pair do not match 152 | raise UnexpectedException("The two chars of the register pair do not match:" 153 | "'{:s}' and '{:s}'".format(self.syntax_name[1], self.syntax_name[2])) 154 | 155 | 156 | if self.syntax_name[0] == 'N': 157 | # New value register 158 | self.is_newvalue = True 159 | 160 | 161 | # TODO: Check if the general purpose register is the only that uses reg. pairs. 162 | # (the control reg is also possible as reg. pair but they are usually rreferencedby their alias) 163 | 164 | 165 | 166 | class ImmediateTemplate(OperandTemplate): 167 | # TODO: Document class. Develop the notion of immediate type, e.g., r, m, s, etc. 168 | 169 | __slots__ = ['scaled', 'type', 'syntax', 'signed', 'index'] 170 | # TODO: Change `scaled` to ``scale`` (because it's used as an int, not a bool). 171 | 172 | def __init__(self, syntax_name, scaled=0): 173 | super(ImmediateTemplate, self).__init__(syntax_name) 174 | self.syntax = syntax_name 175 | self.scaled = scaled 176 | self.signed = False 177 | self.index = 0 178 | 179 | self.type = self.syntax_name[1].lower() 180 | if self.type == 's': 181 | self.signed = True 182 | 183 | if self.type not in ['s', 'u', 'm', 'r', 'g', 'n']: 184 | raise UnexpectedException("Unknown immediate type: {:s}".format(self.type)) 185 | 186 | class OptionalTemplate(OperandTemplate): 187 | __slots__ = ['syntax', 'index', 'syntax_pos'] 188 | 189 | def __init__(self, syntax_name): 190 | super(OptionalTemplate, self).__init__(syntax_name) 191 | self.syntax = syntax_name 192 | self.index = 0 193 | self.syntax_pos = 0 194 | 195 | class EncodingField(): 196 | """Hexagon instruction encoding field, as seen in the manual. 197 | 198 | An encoding field can be characterized with only a mask (int) with the 1's set 199 | to indicate the positions of the field chars in the encoding. E.g., in the encoding 200 | (str) ``1011iiiiiiisssssPPiiiiiiiiiddddd``, the field ``s5`` would have a mask 201 | (int) like ``0b00000000000111110000000000000000``. 202 | 203 | This mask is used to later extract the value of the field in the instruction 204 | being disassembled, which would be used to generate either an immediate or 205 | register operand. 206 | 207 | This value extraction (bit by bit) can be time consuming. To improve performance, 208 | and taking advantage of the fact that most encoding fields are unified, (i.e., 209 | all their field chars have consecutive order, like the example above), other 210 | (redundant) attributes are added to the class to reflect this. 211 | If a field is unified (``no_mask_split`` is True), the field value can 212 | be extracted just by applying a logical and operation, if the mask is split, 213 | after the logical and, the extracted bits need to be joined (which is time consumig 214 | for the disassembly process, as seen in the profiling results). 215 | 216 | Attributes: 217 | 218 | mask (int): resulting from setting to 1's the positions in the instruction encoding 219 | where the corresponding field char appears. 220 | mask_len (int): number of times the field char appears on the encoding field (i.e., 221 | number of 1's in the mask). 222 | no_mask_split (bool): indicates whether all the field chars have a consecutive 223 | bit ordering (i.e., if all the 1's in the mask are together). 224 | mask_lower_pos (int): lowest bit index in the encoding where the field char is found 225 | (i.e. position of the first 1 in the mask). 226 | index (int): the number of operand 227 | 228 | TODOs: 229 | * Improve this class explanation, its use is in the disassembler, maybe move 230 | some of the explanation there (to `extract_and_join_mask_bits` function). 231 | 232 | * Clearly differentiate between bit-by-bit processing vs manipulating all 233 | bits together (extract bits). 234 | 235 | * Change `mask_lower_pos` to ``field_lower_pos`` or ``field_start_pos``. 236 | 237 | * Change `no_mask_split` to ``mask_split`` and adjust logic, asking 238 | for ``if not no_mask_split`` is too cumbersome. 239 | 240 | """ 241 | __slots__ = ['mask', 'mask_len', 'no_mask_split', 'mask_lower_pos', 'index'] 242 | 243 | def __init__(self): 244 | self.mask = 0 245 | self.mask_len = 0 246 | # Used to determine the sign of immediates. 247 | # TODO: Is mask_len used just for that? 248 | self.index = 0 249 | 250 | 251 | class TemplateBranch(): 252 | """Hexagon instruction branch. 253 | 254 | Attribute that adds information to the InstructionTemplate, used mainly 255 | in the IDA processor module to perform branch analysis.. 256 | 257 | Attributes: 258 | 259 | type (str): of branch, useful for IDA analysis. 260 | target (OperandTemplate): operand template (register or immediate) in the instruction 261 | that contains the target of the branch. 262 | is_conditional (bool): True if conditional branch (there's an 'if' inside 263 | the syntax); False otherwise. 264 | 265 | TODOs: 266 | 267 | * Define the branch type inside a class or enum or somewhere unified, 268 | not as strings, and not inside the class. 269 | 270 | * Comment on each branch type separately, explaining the difference. 271 | 272 | * Change `all_branches` name to ``branch_syntax(es)``. 273 | 274 | * Change `all_branches` name to ``branch_syntax(es)``. 275 | 276 | * Document a branch as the union of hexagon jumps and calls. 277 | 278 | * The branch syntax is used like a regexp pattern, the spaces (added for readability) 279 | are ignored only if ``re.search`` is called with ``re.X`` argument 280 | (e.g., as `analyze_branch` does), enforce/specify this. 281 | 282 | * Once the branch types are unified give examples. 283 | 284 | """ 285 | __slots__ = ['target', 'is_conditional', 'type'] 286 | 287 | jump_reg_syntax = r'jumpr (?: :t | :nt)?' # ``?:`` don't capture group 288 | jump_imm_syntax = jump_reg_syntax.replace('jumpr', 'jump') 289 | call_reg_syntax = r'callr' 290 | call_imm_syntax = call_reg_syntax.replace('callr', 'call') 291 | dealloc_ret_syntax = r'dealloc_return' 292 | all_branches = [jump_reg_syntax, jump_imm_syntax, call_reg_syntax, call_imm_syntax, dealloc_ret_syntax] 293 | 294 | def __init__(self, type): 295 | self.type = type 296 | self.target = None 297 | self.is_conditional = False 298 | 299 | class TemplateToken(): 300 | """Hexagon instruction template token. 301 | 302 | Used mainly in the IDA processor module, to print some parts of the syntax (tokens) 303 | in a special manner, matching the strings (`s`) with their corresponding operand (`op`). 304 | 305 | Attributes: 306 | 307 | s (str): token string. 308 | op (Optional[OperandTemplate]): operand template (if any) that corresponds to the token. 309 | 310 | TODOs: 311 | * Change `s` name to something more descriptive, maybe also `op`, 312 | using more than 2 letters is allowed... 313 | 314 | """ 315 | __slots__ = ['s', 'op'] 316 | 317 | def __init__(self, s): 318 | self.s = s 319 | self.op = None 320 | 321 | 322 | class InstructionEncoding(): 323 | """Hexagon instruction encoding. 324 | 325 | Attributes: 326 | text (str): encoding chars, without spaces, of len 32, each char represents one bit of the 327 | instruction, e.g., the encoding of ``Rd=add(Rs,#s16)`` is ``1011iiiiiiisssssPPiiiiiiiiiddddd``, 328 | ``text[0]`` corresponds to bit 31 and ``text[31]`` to bit 0 (LSB) of the encoding. 329 | mask (int): resulting from setting to 1's all the instruction defining bits, used in the 330 | disassembly to determine the type of an instruction. 331 | value (int): resulting from extracting only the instruction defining bits, used in conjunction with 332 | the mask to determine the type of an instruction. 333 | fields (Dict[str, EncodingField]): instruction encoding fields, indexed by the field char, 334 | e.g. fields['d'] -> EncodingField(Rd). 335 | 336 | TODOs: 337 | * Change `text` attribute's name, so as not to be confused with an instruction text. 338 | * Fields is a redundant attribute, because the encodings fields are contained 339 | in the operands dict. key (of the instruction template), 340 | but it's clearer this way. Should it be eliminated? 341 | 342 | """ 343 | __slots__ = ['text', 'value', 'mask', 'fields'] 344 | 345 | def __init__(self, text): 346 | 347 | #if len(text) != 32: 348 | # raise UnexpectedException('There has been a problem during the instruction definition import process.') 349 | 350 | # TODO: Check also `text` for spaces. 351 | 352 | # TODO: check that ICLASS bits (31:28 and 31:29,13 for duplex) in `text` are always defined to 0/1. 353 | 354 | self.text = text 355 | 356 | self.fields = {} 357 | 358 | self.generate_mask_and_value() 359 | self.generate_fields() 360 | 361 | def generate_mask_and_value(self): 362 | """Generate the mask and value of the instruction encoding, from its text (str). 363 | 364 | There are no Args nor Return values, everything is done manipulating the 365 | object attributes: the input would be `self.text` and the output `self.mask` 366 | and `self.value`. 367 | 368 | """ 369 | self.mask = 0 370 | self.value = 0 371 | 372 | for text_pos in range(32): 373 | 374 | mask_pos = 31 - text_pos 375 | # The orders of mask bits (int) and text bits (str) are reversed. 376 | 377 | if self.text[text_pos] in ['0', '1']: 378 | self.mask |= (1 << mask_pos) 379 | self.value |= int(self.text[text_pos]) << mask_pos 380 | 381 | def generate_fields(self): 382 | """Generate instruction fields of the instruction encoding, from its text (str). 383 | 384 | Parse everything else that's not a instruction defining bit (0/1), like the ICLASS 385 | bits, and generate the corresponding fields from each different spotted char. 386 | The other type of chars ignored (besides 0/1) are '-' (irrelevant bit) 387 | and 'P' (parse bit). 388 | 389 | The fields created (EncodingField) do not differentiate between immediate or register, 390 | they are just a bit field at this stage. 391 | 392 | The generation of each field mask is pretty straight forward, but the process 393 | has been complicated with the fact that the generated mask is checked to see if 394 | bits are consecutive (no_mask_split), for performance reasons. See `EncodingField` 395 | description. 396 | 397 | There are no Args nor Return values, everything is done manipulating the 398 | object attributes: the input would be `self.text` and the output `self.fields`. 399 | 400 | TODOs: 401 | * Rethink this explanation. 'P' is a valid field, but I'm skipping it because it 402 | won't be a valid imm. o reg. operand. So even though this encoding fields 403 | are just bits their ultimate use will be for operands. 404 | 405 | * Use the terms "specific fields" (from "Instruction-specific fields") and 406 | Common fields (defined in section 10.2 of the manual). ICLASS and parse 407 | bits (common fields) are the ones I'm ignoring. 408 | 409 | * The rationale behind the `no_mask_split` is split between here and 410 | `EncodingField`. Unifiy. 411 | 412 | * Avoid skipping any field here, create all the bit fields from the instruction, 413 | and then skip them during reg./imm. ops. creation, to simplify the logic 414 | here (less coupling, this function is doing -or knowing- more than it should). 415 | 416 | """ 417 | field_last_seen_pos = {} # type: Dict[str, int]) 418 | # Used to detect a mask split. 419 | # TODO: Elaborate on this. 420 | 421 | # TODO: XXX: add the index of operand for each field 422 | for text_pos in range(32): 423 | 424 | mask_pos = 31 - text_pos 425 | # The orders of mask bits (int) and text bits (str) are reversed. 426 | 427 | if mask_pos in [14, 15]: # skip 'P', parse bits 428 | continue 429 | # TODO: Remove this check when this function is permitted to parse all fields 430 | # (and discard the P field later when generating the operands). 431 | 432 | c = self.text[text_pos] 433 | 434 | if c not in ['0', '1', '-']: 435 | # TODO: Change to a continue clause, to remove all the following indentation. 436 | 437 | if c not in self.fields: 438 | # Char seen for the first time, create a new field. 439 | 440 | self.fields[c] = EncodingField() 441 | self.fields[c].no_mask_split = True 442 | field_last_seen_pos[c] = (-1) 443 | # (-1): used to indicate that it's a new field, and there's 444 | # no last seen char before this one. 445 | 446 | self.fields[c].mask |= (1 << mask_pos) 447 | self.fields[c].mask_len += 1 448 | 449 | # Detect a split in the field (and if so, reflect it on the mask). 450 | 451 | if field_last_seen_pos[c] != -1: 452 | if mask_pos != (field_last_seen_pos[c] - 1): # mask_pos iteration is going ackwards 453 | self.fields[c].no_mask_split = False 454 | 455 | field_last_seen_pos[c] = mask_pos 456 | 457 | for c in self.fields: 458 | self.fields[c].mask_lower_pos = field_last_seen_pos[c] 459 | # The last seen position in the text (str) of each field is the 460 | # lowest position in the mask (int), as their orders are reversed. 461 | 462 | 463 | class InstructionDefinition(): 464 | """Definition of an instruction (like the manual): syntax, encoding, and beahvior. 465 | 466 | Instructions obtained by the importer (either from the manual or the objdump 467 | headers). It has the minimal processing, only on the instruction encoding, converted 468 | to `InstructionEncoding` (it has no use as a string), the major work is done in 469 | the `InstructionTemplate` through the decoder. 470 | 471 | The behavior attribute is optional, because the parser still doesn't support many of 472 | the manual's behavior strings. 473 | 474 | Attributes: 475 | syntax (str) 476 | encoding (InstructionEncoding) 477 | behavior (str) 478 | 479 | """ 480 | __slots__ = ['syntax', 'encoding', 'behavior'] 481 | 482 | def __init__(self, syntax, encoding, behavior): 483 | self.syntax = syntax 484 | self.encoding = InstructionEncoding(encoding) 485 | self.behavior = behavior 486 | 487 | # TODO: Handle also TAB characters 488 | 489 | class InstructionTemplate(): 490 | """Definition of the instruction with the maximum processing done before being used for disassembly. 491 | 492 | Created by the decoder from an `InstructionDefinition`. 493 | All the major attributes of the instruction are processed and 494 | stored here, e.g., operands, duplex, branches, tokens, etc. 495 | 496 | Attributes: 497 | encoding (InstructionEncoding): Hexagon instruction encoding, as seen in the manual. 498 | syntax (str): Hexagon instruction syntax, as seen in the manual, e.g. ``Rd=add(Rs,#s16)``. 499 | operands (Dict[str, InstructionOperand]): Operands (registers or immediates) indexed by their 500 | respective field char, e.g., operands['d'] -> InstructionOperand(Rd). 501 | mult_inst (bool): Has more than one atomic instruction, i.e., has a ';' in the syntax. 502 | is_duplex (bool): Indicates if this is a duplex instruction. 503 | imm_ops (List[ImmediateTemplate]): List of the instruction register operand templates. 504 | reg_ops (List[RegisterTemplate]): List of the instruction immediate operand templates. 505 | opt_ops (List[OptionalTemplate]): List of the instruction optional operand templates. 506 | branch (Optional[TemplateBranch]): If not None, has the branch being performed by the 507 | instruction, identified by the encoding analyzing the instruction syntax and not 508 | its behavior (as it should). 509 | behavior (str): Hexagon instruction behavior, as seen in the manual, e.g. ``Rd=Rs+#s;``. 510 | imm_ext_op (Optional[ImmediateTemplate]): "Pointer" to the immediate operand that can 511 | be extended in the instruction. It is just a hint for the disassembler, to let it 512 | know what immediate operand can be the target of a constant extension. "Pointer" 513 | here means that it has one of the imm. ops. in the `imm_ops` list. 514 | tokens (List[TemplateToken]): List of strings representing the tokenized behavior, where 515 | splits are done in the cases where part of the syntax can be linked to an operand, 516 | see `HexagonInstructionDecoder.tokenize_syntax`. 517 | name (str): Name. 518 | 519 | """ 520 | __slots__ = ['encoding', 'syntax', 'operands', 'mult_inst', 521 | 'is_duplex', 'imm_ops', 'reg_ops', 'opt_ops', 'branch', 'behavior', 522 | 'imm_ext_op', 'tokens', 'name'] 523 | 524 | 525 | register_operand_field_chars = ['t', 'd', 'x', 'u', 'e', 'y', 'v', 's'] 526 | # Seen on the manual 527 | 528 | # Added from the objdump headers, but not in the manual 529 | register_operand_field_chars.extend(['f', 'z']) 530 | 531 | immediate_operand_field_chars = ['i', 'I'] 532 | 533 | other_field_chars = ['-', 'P', 'E', 'N'] 534 | # 'E' added from the objdump header encodings (not in the manual) 535 | 536 | field_chars = register_operand_field_chars + \ 537 | immediate_operand_field_chars + \ 538 | other_field_chars 539 | # TODO: move all field char definitions inside `generate_operand` or in `common.py`. 540 | 541 | def __init__(self, inst_def): 542 | 543 | #print(inst_def) 544 | #if not isinstance(inst_def, InstructionTemplate): 545 | # pass 546 | 547 | self.encoding = inst_def.encoding 548 | self.syntax = standarize_syntax_objdump(inst_def.syntax) 549 | self.behavior = inst_def.behavior 550 | # TODO: Create an ``InstructionField`` that groups these 3 attributes. 551 | 552 | self.imm_ops = [] 553 | self.reg_ops = [] 554 | self.opt_ops = [] 555 | 556 | self.operands = {} 557 | # Contains the same info as imm_ops + reg_ops, only used inside 558 | # `generate_instruction_operands`. 559 | # TODO: Remove this attribute. 560 | 561 | self.branch = None 562 | self.imm_ext_op = None 563 | self.tokens = [] 564 | self.name = None 565 | 566 | self.mult_inst = (';' in self.syntax) 567 | 568 | self.is_duplex = (self.encoding.text[16:18] == '00') 569 | # PP (parity bits) set to '00' 570 | #print("is duplex? {0}".format(self.is_duplex)) 571 | 572 | for c in self.encoding.fields: 573 | #print(c) 574 | self.generate_operand(c) 575 | 576 | # Calculate operand indexes 577 | self.operand_calculate_indices() 578 | 579 | # C: char, ie: inst encoding 580 | def generate_operand(self, c): 581 | """Generate an operand from an instruction field. 582 | 583 | Args: 584 | c (str): Field char. 585 | 586 | Returns: 587 | None: the information is added to `reg_ops`/`imm_ops` and `operands` 588 | of the same InstructionTemplate. 589 | 590 | """ 591 | #print("syntax = \"{0}\" char = \"{1}\"".format(self.syntax, c)) 592 | if c not in InstructionTemplate.field_chars: 593 | print("Field char {:s} not recognized.".format(c)) 594 | raise UnexpectedException("Field char {:s} not recognized.".format(c)) 595 | 596 | if c in self.register_operand_field_chars: 597 | reg = self.match_register_in_syntax(self.syntax, c) 598 | if reg: 599 | self.operands[c] = reg 600 | self.reg_ops.append(reg) 601 | return 602 | print("not register operand match in syntax! [{0:s}]".format(c)) 603 | 604 | if c in self.immediate_operand_field_chars: 605 | imm = self.match_immediate_char_in_syntax(self.syntax, c) 606 | if imm: 607 | self.operands[c] = imm 608 | self.imm_ops.append(imm) 609 | 610 | return 611 | print("no immediate operand match in syntax! [{0:s}]".format(c)) 612 | 613 | # There is a pretty similar structure in both processings. 614 | # TODO: Can this be abstracted to a more general function? 615 | if c == 'N': 616 | # 'N' operand, it indicates an optional behavior in the instruction (which doesn't happen often). 617 | m = re.search(r"(\[\s*:\s*<<\s*N\s*\])", self.syntax) 618 | if m: 619 | opt = OptionalTemplate('[:< 0, tokens)) 831 | 832 | # Generate list of TemplateToken and match string tokens to operands. 833 | 834 | for str_token in tokens: 835 | 836 | #template_token = TemplateToken(str_token.lower()) 837 | template_token = TemplateToken(str_token) 838 | # TODO: Is it ok to convert to lowercase here? 839 | # The letter case of the operands text is useful (specially in IDA) to 840 | # identify them quickly in the visual analysis (from the rest of the instruction). 841 | 842 | for op in template.reg_ops + template.imm_ops + template.opt_ops: # type: InstructionOperand 843 | 844 | if str_token == op.syntax_name: 845 | # The string token names the operand, match them. 846 | 847 | template_token.op = op 848 | break 849 | 850 | template.tokens.append(template_token) 851 | 852 | return 853 | 854 | def resolve_constant_extender(self, template): 855 | """In case there are two imm. operands, indicate to which one would apply a constant extension. 856 | 857 | This is done for instructions that can be extended by a constant but have two 858 | immediate operands and it has to be indicated to which one the extension applies. 859 | 860 | The function ``apply_extension()`` in instruction behaviours is used as an indication 861 | that a constant extension can be applied, and the argument of the function specifies 862 | the syntax of which immediate operand it applies to. 863 | 864 | Args: 865 | template (InstructionTemplate): to be processed. 866 | 867 | Returns: 868 | None: the data is applied to the template itself. 869 | 870 | TODOs: 871 | * Add to the function description an example of an instruction where 872 | there are two imm. ops. and the ``apply_extension()`` resolves which one. 873 | 874 | """ 875 | if len(template.imm_ops) < 2: 876 | # There's no need to perform the check, there's (at most) only one 877 | # immediate operand to choose from. 878 | if template.imm_ops: 879 | template.imm_ext_op = template.imm_ops[0] 880 | return 881 | m = re.search(r""" 882 | # Looking for something like: "apply_extension(...);" 883 | 884 | apply_extension 885 | \( 886 | (.*?) # Capture group for the imm. op. name, e.g., ``#s``. 887 | \) 888 | """, template.behavior.replace(' ', ''), re.X) 889 | # The spaces are removed from the behavior string to simplify the regex. 890 | 891 | if m is None: 892 | # No constant extension found in the behavior. 893 | # But it has immediates -> assume imm_ops[0] 894 | template.imm_ext_op = template.imm_ops[0] 895 | return 896 | 897 | imm_op_ext_name = m.group(1) 898 | # Name of the imm. op. that is the argument of ``apply_extension()``. 899 | 900 | for imm_op in template.imm_ops: 901 | if imm_op_ext_name in imm_op.syntax_name: 902 | # An equal comparison is not made in the previous if because 903 | # the op. name in the apply_extension argument is usually a shorter 904 | # version of the name in the syntax (normally because the 905 | # operand's bit size was removed), e.g., ``#s16`` in 906 | # ``Rd=add(Rs,#s16)`` is referenced as ``apply_extension(#s);``. 907 | template.imm_ext_op = imm_op 908 | return 909 | 910 | raise UnexpectedException("Cannot parse constant extender") 911 | # If the regex matched, the operand should have been found in the previous loop. 912 | 913 | def analyze_branch(self, template): 914 | """Find a branch in the instruction syntax and generate the template info. 915 | 916 | Used in (IDA) static analysis. 917 | 918 | Args: 919 | template (InstructionTemplate): to be processed. 920 | 921 | Returns: 922 | None: the data is applied to the template itself. 923 | 924 | TODOs: 925 | * Change function name to something like 'find_branch(es)'. 926 | 927 | * This type of analysis should be done by studying the REIL translation 928 | of the instruction, which truly reflects its behaviour. When the REIL 929 | translation is added this function should be adapted. 930 | 931 | * Multiple branches in one instruction: is it possible? I think not, 932 | at most, two branches in one packet but separate. Check this. 933 | 934 | * The branch string itself is used to represent it, maybe some constants 935 | should be used instead. 936 | 937 | """ 938 | for branch_syntax in TemplateBranch.all_branches: # type: str 939 | # Find any of the possible branch syntaxes in the instruction 940 | # to detect a branch. 941 | m = re.search(branch_syntax, template.syntax, re.X) 942 | if m is None: 943 | continue 944 | 945 | if branch_syntax == TemplateBranch.dealloc_ret_syntax: 946 | # The instruction is a 'dealloc_return', a jump to the 947 | # LR as target. 948 | pass 949 | 950 | template.branch = TemplateBranch(branch_syntax) 951 | 952 | template.branch.is_conditional = ('if' in template.syntax) 953 | # TODO: The if could be applying to another sub-instruction. Improve detection. 954 | 955 | if branch_syntax in [TemplateBranch.jump_reg_syntax, TemplateBranch.call_reg_syntax]: 956 | # Branch type: jump/call register. 957 | 958 | # Find which register is the target of the branch. 959 | 960 | for reg in template.reg_ops: # type: RegisterTemplate 961 | m = re.search(branch_syntax + r'\s*' + reg.syntax_name, template.syntax, re.X) 962 | if m: 963 | template.branch.target = reg 964 | return 965 | 966 | # The target register operand was not found, this shouldn't happen, but 967 | # for now the case of register alias (specially the case of LR) is not 968 | # being handled, so an exception can't be raised, and this case is 969 | # tolerated (retuning instead). 970 | 971 | # raise UnexpectedException() 972 | return 973 | 974 | if branch_syntax in [TemplateBranch.jump_imm_syntax, TemplateBranch.call_imm_syntax]: 975 | # Branch type: jump/call immediate. 976 | 977 | for imm in template.imm_ops: # type: ImmediateTemplate 978 | m = re.search(branch_syntax + r'\s*' + imm.syntax_name.replace('#', r'\#'), template.syntax, re.X) 979 | # The '#' (used in imm. op. names) is escaped, as it is interpreted as 980 | # a comment in verbose regex (re.X), and verbose regex is used because 981 | # the branch syntax is written with spaces (verbose style) to improve 982 | # its readability. 983 | 984 | if m: 985 | template.branch.target = imm 986 | return 987 | 988 | raise UnexpectedException("Cannot find target immediate operand") 989 | # The target immediate operand should have been found. 990 | 991 | return 992 | 993 | class ManualParser: 994 | 995 | def __init__(self, manual_fn): 996 | self.manual = open(manual_fn, 'r', newline=None) # universal newlines, to get rid of '\r' when opening in linux 997 | self.lines = self.manual.read().splitlines() 998 | self.ln = 0 999 | self.current_line = self.lines[self.ln] 1000 | 1001 | # TODO: change the name, this are not yet instruction templates until the decoder process them 1002 | self.instructions = [] 1003 | 1004 | self.syntax_behavior_text = [] 1005 | 1006 | 1007 | self.current_inst_name = "" 1008 | self.total_encodings = 0 1009 | 1010 | def get_next_line(self): 1011 | self.ln += 1 1012 | 1013 | if self.ln == len(self.lines): 1014 | raise self.OutOfLinesException() 1015 | 1016 | return self.get_current_line() 1017 | 1018 | def peek_next_line(self): 1019 | if self.ln + 1 == len(self.lines): 1020 | raise self.OutOfLinesException() 1021 | 1022 | return self.lines[self.ln + 1] 1023 | 1024 | def peek_prev_line(self): 1025 | if self.ln - 1 == -1: 1026 | raise self.OutOfLinesException() 1027 | 1028 | return self.lines[self.ln - 1] 1029 | 1030 | def get_current_line(self): 1031 | self.current_line = self.lines[self.ln] 1032 | return self.current_line 1033 | 1034 | def get_prev_line(self): 1035 | self.ln -= 1 1036 | 1037 | if self.ln < 0: 1038 | raise self.UnexpectedException() 1039 | 1040 | return self.get_current_line() 1041 | 1042 | def go_to_instruction_set_start(self): 1043 | 1044 | try: 1045 | while True: 1046 | m = re.search(r"Hexagon V62 Programmer's Reference Manual\s*Instruction Set", self.current_line) 1047 | if m: 1048 | #print("Found start of Instruction Set at line: " + str(self.ln)) 1049 | #print(self.current_line) 1050 | break 1051 | 1052 | self.get_next_line() 1053 | 1054 | except self.OutOfLinesException: 1055 | raise self.UnexpectedException() 1056 | 1057 | def find_encondings(self): 1058 | try: 1059 | inside_encoding = False 1060 | inside_behavior = False 1061 | 1062 | last_syntax_found_ln = -1 1063 | last_behavior_found_ln = -1 1064 | while True: 1065 | 1066 | self.get_next_line() 1067 | #print(self.current_line) 1068 | 1069 | m = re.search(r"\s*Syntax\s*Behavior\s*", self.current_line) 1070 | if m: 1071 | #print("\nFound start of Syntax/Behavior at line: " + str(self.ln)) 1072 | #print(self.current_line) 1073 | inside_behavior = True 1074 | continue 1075 | 1076 | m = re.search(r"^\s*Class: .*", self.current_line) 1077 | if m: 1078 | #print("\nFound start of Class at line: " + str(self.ln)) 1079 | #print(self.current_line) 1080 | inside_behavior = False 1081 | continue 1082 | 1083 | m = re.search(r"\s*Encoding\s*", self.current_line) 1084 | if m: 1085 | #print("\nFound start of Encoding at line: " + str(self.ln)) 1086 | #print(self.current_line) 1087 | inside_encoding = True 1088 | inside_behavior = False 1089 | continue 1090 | 1091 | # The end of an econding section is typically signaled by the start of the "Field name" section. 1092 | m = re.search(r"Field name\s*Description", self.current_line) 1093 | if m: 1094 | #print("Found end of Encoding at line: " + str(self.ln) + '\n') 1095 | #print(self.current_line) 1096 | inside_encoding = False 1097 | inside_behavior = False 1098 | continue 1099 | 1100 | ''' 1101 | Syntax/Behavior extraction: 1102 | Organized in two columns. 1103 | ''' 1104 | if inside_behavior: 1105 | 1106 | 1107 | # Instructions without a clear separation of syntax and behavior are skipped 1108 | complicated_instructions = [ 1109 | "Vector", 1110 | "Floating", 1111 | "Complex add/sub halfwords", 1112 | "Multiply", 1113 | "Shift by register", 1114 | "Set/clear/toggle bit", 1115 | "Extract bitfield", 1116 | "Test bit", 1117 | "CABAC decode bin", 1118 | ] 1119 | if True in [ci.lower() in self.current_inst_name.lower() for ci in complicated_instructions]: 1120 | continue 1121 | 1122 | 1123 | #if self.current_line.strip().decode('utf-8') == '': 1124 | if self.current_line.strip() == '': 1125 | continue 1126 | 1127 | # Page header/footer skip 1128 | # TODO: maybe this should apply to more parts of the code, no just syntax/behavior 1129 | if ("Hexagon V62 Programmer's Reference Manual" in self.current_line or 1130 | "MAY CONTAIN U.S. AND INTERNATIONAL EXPORT" in self.current_line or 1131 | "80-N2040-36 B" in self.current_line): 1132 | continue 1133 | 1134 | 1135 | 1136 | 1137 | # Try to match the 2 column format, basically tryng to see the separation space between them (the 5 spaces min requirement) 1138 | m = re.search(r"^\s*(\S.+?\S)\s{5,}(\S.+)", self.current_line) 1139 | if m: 1140 | #print("Found pair of syntax/behavior") 1141 | #print("Group 1: " + m.group(1)) 1142 | #print("Group 2: " + m.group(2)) 1143 | behavior_1st_column_pos = m.start(1) 1144 | behavior_2nd_column_pos = m.start(2) 1145 | 1146 | # if self.current_line[0:behavior_2nd_column_pos].strip() != '': 1147 | # # Syntax column 1148 | # # TODO this if check should be include in the previous regex 1149 | 1150 | # Continuation syntax (in 2 consecutive lines) 1151 | if self.ln - 1 == last_syntax_found_ln: 1152 | #print("Cont Syntax: " + m.group(1)) 1153 | self.syntax_behavior_text[-1][0] += " " + m.group(1) 1154 | else: 1155 | #print("New Syntax: " + m.group(1)) 1156 | self.syntax_behavior_text.append([m.group(1), '']) 1157 | last_syntax_found_ln = self.ln 1158 | 1159 | #print("Behavior is: " + m.group(2)) 1160 | self.syntax_behavior_text[-1][1] += m.group(2) 1161 | last_behavior_found_ln = self.ln 1162 | 1163 | else: 1164 | # Can be a behavior continuation line 1165 | if self.current_line[behavior_2nd_column_pos:].strip() != '': 1166 | if self.ln - 1 == last_behavior_found_ln: 1167 | #print("Behavior cont is: " + self.current_line[behavior_2nd_column_pos:].strip()) 1168 | self.syntax_behavior_text[-1][1] += self.current_line[behavior_2nd_column_pos:].strip() 1169 | last_behavior_found_ln = self.ln 1170 | 1171 | 1172 | ''' 1173 | Start of a page of the "Instruction Set" section: if the first non empty line that appears 1174 | in the next 3 to 5 lines (usually its 3 blank lines and the title) 1175 | has text at the begining of the line, it's likely a new title, and hence a new instruction 1176 | name. I'm assuming the title has at least 3 chars. 1177 | 1178 | TODO: Double line titles 1179 | ''' 1180 | m = re.search(r"Hexagon V62 Programmer's Reference Manual\s*Instruction Set", self.current_line) 1181 | if m: 1182 | # print "Found start of Instruction Set page at line: " + str(self.ln) 1183 | start_ln = self.ln 1184 | title_found = False 1185 | for _ in range(5): 1186 | self.get_next_line() 1187 | # print self.current_line 1188 | m = re.search(r"^\w{3}", self.current_line) 1189 | if m: 1190 | #print("Found title at line: " + str(self.ln)) 1191 | #print(self.current_line) 1192 | self.current_inst_name = self.current_line.strip() 1193 | break 1194 | 1195 | # Just to be sure I return to where the search for a title began 1196 | if not title_found: 1197 | self.ln = start_ln 1198 | 1199 | continue 1200 | 1201 | # The first four bits (ICLASS) of an encoding are always set (either to 0 or 1), 1202 | # and are at the start of the line 1203 | m = re.search(r"^([01]\s*){4}", self.current_line) 1204 | if m: 1205 | # print "Found encoding at line: " + str(self.ln) 1206 | # print self.current_line 1207 | 1208 | # Bits not defined in the encoding are marked as "-", not left blank, 1209 | # so there is always 32 non-whites, particulary: 0/1, chars or "-". 1210 | m = re.search(r"^(([01a-zA-Z\-]\s*){32})(.*)$", self.current_line) 1211 | if m is None: 1212 | raise self.UnexpectedException() 1213 | 1214 | ie = m.group(1).replace(' ', '') 1215 | syntax = m.group(3) # My limited regex understanding doesn't get why this is the 3rd group and not the 2nd, but this works. 1216 | 1217 | # The syntax may be splitted in 2 lines, in this case the second line 1218 | # is all white spaces, until the position where the syntax started in the 1219 | # previous line, where the sytax string continues. Or can be the contrary, 1220 | # the second line of the syntax has the encoding and the first line is blank 1221 | next_line = self.peek_next_line() 1222 | prev_line = self.peek_prev_line() 1223 | 1224 | if len(next_line) > m.start(3) and re.search(r"^\s*$", next_line[0 : m.start(3)]): # all spaces up to the syntax string 1225 | # TODO: Change name m2. 1226 | m2 = re.search(r"^(\S.*)", next_line[m.start(3):]) # here has to be something (I can't specify what exactly besides a non space) 1227 | if m2: 1228 | #print("Found syntax continuation") 1229 | #print(("1st line: {:s}".format(syntax))) 1230 | #print(("2nd line: {:s}".format(m2.group(1)))) 1231 | 1232 | syntax += ' ' + m2.group(1) 1233 | 1234 | self.get_next_line() # To really pass over this continuation syntax line 1235 | 1236 | elif len(prev_line) > m.start(3) and re.search(r"^\s*$", prev_line[0 : m.start(3)]): 1237 | # TODO: Change name m2. 1238 | m2 = re.search(r"^(\S.*)", prev_line[m.start(3):]) # here has to be something (I can't specify what exactly besides a non space) 1239 | if m2: 1240 | #print("Found syntax continuation in prev line") 1241 | #print(("1st line: {:s}".format(m2.group(1)))) 1242 | #print(("2nd line: {:s}".format(syntax))) 1243 | 1244 | syntax = m2.group(1) + ' ' + syntax 1245 | 1246 | else: 1247 | # TODO: Tidy up. 1248 | # The same can happen but with a disalignment of the other syntax line (prev or next) by 1 char 1249 | if len(next_line) > (m.start(3) - 1) and re.search(r"^\s*$", next_line[0 : (m.start(3) - 1)]): # all spaces up to the syntax string 1250 | # TODO: Change name m2. 1251 | m2 = re.search(r"^(\S.*)", next_line[(m.start(3) - 1):]) # here has to be something (I can't specify what exactly besides a non space) 1252 | if m2: 1253 | #print("Found syntax continuation") 1254 | #print(("1st line: {:s}".format(syntax))) 1255 | #print(("2nd line: {:s}".format(m2.group(1)))) 1256 | 1257 | syntax += ' ' + m2.group(1) 1258 | 1259 | self.get_next_line() # To really pass over this continuation syntax line 1260 | 1261 | elif len(prev_line) > (m.start(3) - 1) and re.search(r"^\s*$", prev_line[0 : (m.start(3) - 1)]): 1262 | # TODO: Change name m2. 1263 | m2 = re.search(r"^(\S.*)", prev_line[(m.start(3) - 1):]) # here has to be something (I can't specify what exactly besides a non space) 1264 | if m2: 1265 | #print("Found syntax continuation in prev line") 1266 | #print(("1st line: {:s}".format(m2.group(1)))) 1267 | #print(("2nd line: {:s}".format(syntax))) 1268 | 1269 | syntax = m2.group(1) + ' ' + syntax 1270 | 1271 | 1272 | #print("Encoding: " + ie) 1273 | #print("syntax:" + syntax) 1274 | 1275 | # TODO: handle instruction name 1276 | # if self.current_inst_name not in self.instructions: 1277 | # self.instructions[self.current_inst_name] = [] 1278 | 1279 | self.instructions.append(InstructionDefinition(syntax, ie, self.syntax_behavior_text[-1][1])) 1280 | 1281 | self.total_encodings += 1 1282 | 1283 | continue 1284 | 1285 | 1286 | except ManualParser.OutOfLinesException: 1287 | pass 1288 | # print("End of scipt, out of lines") 1289 | 1290 | pass 1291 | 1292 | class OutOfLinesException(Exception): 1293 | pass 1294 | 1295 | class UnexpectedException(Exception): 1296 | pass 1297 | 1298 | 1299 | class HeaderParser: 1300 | def __init__(self, header_fn): 1301 | self.header = open(header_fn, 'r') 1302 | self.lines = self.header.read().splitlines() 1303 | 1304 | self.duplex_inst_encodings = [] 1305 | self.other_inst_encodings = [] 1306 | 1307 | def parse(self): 1308 | for l in self.lines: 1309 | 1310 | # TODO: check out HEXAGON_MAPPING 1311 | #m = re.search(r'^HEXAGON_OPCODE \s* \( \s* " (.*)? " \s* , \s* " (.*)? "', l, re.X) 1312 | m = re.search(r'^{\s* "(.*)?" \s* , \s* "(.*)?"', l, re.X) 1313 | if m: 1314 | syntax = m.group(1) 1315 | encoding = m.group(2).replace(' ', '') 1316 | 1317 | if len(encoding) != 32: 1318 | raise UnexpectedException 1319 | 1320 | # Split intructions: with subinsructions, marked with 1321 | # 'EE' in the 15:14 (from rigth to left) position of their encoding, which 1322 | # are going to be added to the database, and the rest, which only in the 1323 | # case they were not already added from the manual will be included (this is 1324 | # generally undocumented system instructions) 1325 | 1326 | if encoding[16:18].lower() == 'ee': 1327 | # I index the array from left to rigth, and just to be sure I'm converting to lower 1328 | encoding = (encoding[:16] + '00' + encoding[18:]) # '00' - duplex type 1329 | self.duplex_inst_encodings.append(InstructionDefinition(syntax, encoding, '')) 1330 | else: 1331 | self.other_inst_encodings.append(InstructionDefinition(syntax, encoding, '')) 1332 | # print("syntax: " + syntax) 1333 | # print("encoding: " + encoding) 1334 | 1335 | def standarize_syntax(self, encodings): 1336 | # To make it look like the manual 1337 | 1338 | for i in range(len(encodings)): 1339 | syntax = encodings[i].syntax 1340 | 1341 | # Remove registers size (I'm assuming) from their name: 1342 | # Rd16 -> Rd 1343 | # print("Before: " + syntax) 1344 | syntax = re.sub(r'\b ([RPNMCGS][a-z]{1,2}) \d{0,2} \b', r'\1', syntax, flags=re.X) # TODO: Register all possible register types, s,r,t,e etc. 1345 | # print("After: " + syntax) 1346 | 1347 | encodings[i].syntax = syntax 1348 | 1349 | # ------------------------------------------------------------------------------------- 1350 | 1351 | hex_insn_names = [] # For generating the instruction names header 1352 | 1353 | # TODO: add directions hint 1354 | # TODO: Add loop/endloop 1355 | # TODO: Support assignments 1356 | def generate_name(ins_syntax): 1357 | mname = "" 1358 | # Zero thing - "bla" 1359 | m = re.search(r'^\s*([_a-zA-Z\d]+)\s*$', ins_syntax) 1360 | if m: 1361 | mname = m.group(1) 1362 | # just copy as is 1363 | return mname.upper() 1364 | 1365 | # First thing - "bla bla insn (bla bla)" 1366 | # extract "insn"()a 1367 | m = re.search(r'([_a-zA-Z\d\.]+)\s*(\(.+\))+\s*.*$', ins_syntax) 1368 | if m: 1369 | mname = m.group(1) 1370 | return mname.upper() 1371 | 1372 | # HACK: just filter out the special characters and we're good to go 1373 | # TODO: Find a better way to generate names 1374 | def generate_dirtyname(ins_syntax): 1375 | #mname = "".join(e for e in ins_syntax if e.isalnum()) 1376 | mname = ins_syntax.replace("!", "_NOT_") 1377 | mname = mname.replace("-=", "_MINUS_EQ_") 1378 | mname = mname.replace("= -", "_EQ_MINUS_") 1379 | mname = mname.replace("+=", "_PLUS_EQ_") 1380 | mname = mname.replace("= +", "_EQ_PLUS_") 1381 | mname = mname.replace("&=", "_AND_EQ_") 1382 | mname = mname.replace("|=", "_OR_EQ_") 1383 | mname = mname.replace("< =", "_LT_EQ_") 1384 | mname = mname.replace("> =", "_GT_EQ_") 1385 | mname = mname.replace("==", "_EQ_") 1386 | mname = mname.translate({ord(c): "_" for c in " !@#$%^&*()[]{};:,./<>?\|`~-=+"}) 1387 | return mname.upper() 1388 | 1389 | def generate_insn(ins_tmpl): 1390 | iname = "HEX_INS" 1391 | if ins_tmpl.is_duplex: 1392 | iname += "_DUPLEX" 1393 | else: 1394 | if ins_tmpl.mult_inst: 1395 | iname += "_MULT" 1396 | # Split by ";" for multinstructions and duplexes 1397 | subs = ins_tmpl.syntax.split(";") 1398 | for sub in subs: 1399 | # Extract predicate 1400 | subname = generate_dirtyname(sub) 1401 | iname += "_" + subname 1402 | 1403 | # There is a weird case when two different instructions have the same syntax 1404 | if iname in hex_insn_names: 1405 | iname += "_" 1406 | 1407 | return iname 1408 | 1409 | # -------------------------------------------------------------------------------- 1410 | # Make a new C block (if/case/etc) 1411 | # TODO: support more syntax constructs 1412 | def make_C_block(lines, begin = None, end = None, ret = None, indent=True): 1413 | new = [] 1414 | ws = "\t" 1415 | if not indent: 1416 | ws = "" 1417 | if begin: 1418 | new += [begin + " {"] 1419 | else: 1420 | new += ["{"] 1421 | for l in lines: 1422 | new += [ws + l] 1423 | if ret: 1424 | new += [ws + ret] 1425 | if end: 1426 | new += ["} " + end] 1427 | else: 1428 | new += ["}"] 1429 | return new 1430 | 1431 | # -------------------------------------------------------------------------------- 1432 | # Associated bits of an instruction field are scattered over the encoding instruction in a whole. 1433 | # Here we assemble them by using the mask of the field. 1434 | # 1435 | # Simple example: 1436 | # Let the input mask of an immediate be: 0b1111111110011111111111110 1437 | # The bits of the actual immediate need to be concatenated ignoring bit 15:14 and bit 0 (the zeros in the mask). 1438 | # So this function returns C-code which shifts the bits of the immediate segments and ORs them to represent a valid value. 1439 | # 1440 | # hi_u32 is the raw instruction from which we want to concatenate bit 24:16 and bit 13:1 (bit 31:25 are ignored here) 1441 | # 10th 2 1 1442 | # bit # 432109876 54 3210987654321 0 1443 | 1444 | # Mask: 111111111|00|1111111111111|0 1445 | # hi_u32: 100111101|10|1010000010011|0 1446 | # | | 1447 | # | | 1448 | # +--+ >---------------|-------[shift bit 24:16] 1449 | # ____|____ | ((hi_u32 & 0x1ff0000) >> 3) 1450 | # 1001111010000000000000 | [shift bit 13:1] 1451 | # OR 1010000010011 >-+---------------------------------((hi_u32 & 0x3ffe) >> 1)) 1452 | # _______________________ 1453 | # imm = 1001111011010000010011 1454 | 1455 | # imm = ((hi_u32 & 0x1ff0000) >> 3) | ((hi_u32 & 0x3ffe) >> 1)) 1456 | 1457 | def make_sparse_mask(num, mask): 1458 | switch = False 1459 | ncount = 0 # counts how many bits were *not* set. 1460 | masks_count = 0 # How many masks we do have 1461 | masks = {} 1462 | bshift = {} 1463 | for i in range(0, 31): 1464 | if (mask >> i) & 1: 1465 | if not switch: 1466 | switch = True 1467 | masks_count += 1 1468 | bshift[masks_count] = ncount 1469 | if masks_count in masks: 1470 | masks[masks_count] |= 1 << i 1471 | else: 1472 | masks[masks_count] = 1 << i 1473 | #bcount -= 1 1474 | else: 1475 | switch = False 1476 | ncount += 1 1477 | 1478 | # print("MASK") # For grep 1479 | # print(bin(mask)) 1480 | # print(masks) 1481 | outstrings = [] 1482 | for i in range(masks_count, 0, -1): 1483 | outstrings += ["(({0:s} & 0x{1:x}) >> {2:d})".format(num, masks[i], bshift[i])] 1484 | # print(outstrings) 1485 | outstring = " | ".join(outstrings) 1486 | outstring = "({0:s})".format(outstring) 1487 | return outstring 1488 | 1489 | def find_common_bits(masks_list): 1490 | combits = 0 1491 | for mask in masks_list: 1492 | if combits: 1493 | combits &= mask 1494 | else: 1495 | combits = mask 1496 | return combits 1497 | 1498 | # -------------------------------------------------------------------------------- 1499 | # RADARE2 SPECIFIC CODE 1500 | 1501 | preds = { 1502 | "if (Pu)" : "HEX_PRED_TRUE", 1503 | "if (Pv)" : "HEX_PRED_TRUE", 1504 | "if (Pt)" : "HEX_PRED_TRUE", 1505 | "if !Pu " : "HEX_PRED_FALSE", 1506 | "if !Pv " : "HEX_PRED_FALSE", 1507 | "if !Pt " : "HEX_PRED_FALSE", 1508 | "if (Pu.new)" : "HEX_PRED_TRUE_NEW", 1509 | "if (Pv.new)" : "HEX_PRED_TRUE_NEW", 1510 | "if (Pt.new)" : "HEX_PRED_TRUE_NEW", 1511 | "if !Pu.new" : "HEX_PRED_FALSE_NEW", 1512 | "if !Pv.new" : "HEX_PRED_FALSE_NEW", 1513 | "if !Pt.new" : "HEX_PRED_FALSE_NEW", 1514 | } 1515 | 1516 | # TODO: How to handle duplex/combined instructions where is a predicate? 1517 | # TODO: Extract and set conditional flag based on the instruction 1518 | def extract_predicates_r2(ins_tmpl): 1519 | lines = [] 1520 | for k,v in preds.items(): 1521 | if ins_tmpl.syntax.startswith(k): 1522 | pred = "{0:s} = {1:s}; // {2:s}".format("hi->predicate", v, k) 1523 | lines = [pred] 1524 | if not lines: 1525 | lines = ["{0:s} = HEX_NOPRED;".format("hi->predicate")] 1526 | return lines 1527 | 1528 | pfs = { 1529 | ":rnd" : "HEX_PF_RND", 1530 | ":crnd" : "HEX_PF_CRND", 1531 | ":raw" : "HEX_PF_RAW", 1532 | ":chop" : "HEX_PF_CHOP", 1533 | ":sat" : "HEX_PF_SAT", 1534 | ":hi" : "HEX_PF_HI", 1535 | ":lo" : "HEX_PF_LO", 1536 | ":<<1" : "HEX_PF_LSH1", 1537 | ":<<16" : "HEX_PF_LSH16", 1538 | ":>>1" : "HEX_PF_RSH1", 1539 | ":neg" : "HEX_PF_NEG", 1540 | ":pos" : "HEX_PF_POS", 1541 | ":scale" : "HEX_PF_SCALE", 1542 | ":deprecated" : "HEX_PF_DEPRECATED" 1543 | } 1544 | 1545 | def extract_pf_r2(ins_tmpl): 1546 | lines = [] 1547 | pfssorted = collections.OrderedDict(sorted(pfs.items())) 1548 | for k,v in pfssorted.items(): 1549 | if k in ins_tmpl.syntax: 1550 | pf = "{0:s} |= {1:s}; // {2:s}".format("hi->pf", v, k) 1551 | lines += [pf] 1552 | return lines 1553 | 1554 | def extract_name_r2(ins_tmpl): 1555 | lines = [] 1556 | lines += ["hi->instruction = {0:s};".format(ins_tmpl.name)] 1557 | return lines 1558 | 1559 | def extract_fields_r2(ins_tmpl): 1560 | lines = [] 1561 | sortf = lambda c: ins_tmpl.operands[c].index 1562 | sortedfields = sorted(ins_tmpl.encoding.fields, key = sortf) 1563 | op_count = 0 1564 | # Set DUPLEX flag for those instructions 1565 | if ins_tmpl.is_duplex: 1566 | lines += ["hi->duplex = true;"] 1567 | # Handle branch specific fields 1568 | is_branch = False 1569 | if ins_tmpl.branch and ins_tmpl.branch.target: 1570 | is_branch = True 1571 | ti = ins_tmpl.branch.target.index # Target operand index 1572 | # if this is a loop, also mark it as a branch and get target 1573 | if "loop" in ins_tmpl.syntax: 1574 | is_branch = True 1575 | ti = 0 # Always 0 1576 | 1577 | for n in sortedfields: 1578 | f = ins_tmpl.encoding.fields[n] 1579 | i = ins_tmpl.operands[n].index 1580 | slines = [] 1581 | 1582 | if f.no_mask_split: 1583 | mask = "((({0:s}) & 0x{1:x}) >> {2:d})".format("hi_u32", f.mask, f.mask_lower_pos) 1584 | else: 1585 | # Merge bits into the groups first, for the sake of speed 1586 | mask = make_sparse_mask("hi_u32", f.mask) 1587 | 1588 | fieldtype = "HEX_OP_TYPE_IMM" 1589 | if isinstance(ins_tmpl.operands[n], RegisterTemplate): 1590 | fieldtype = "HEX_OP_TYPE_REG" 1591 | # 1. Check if predicate register 1592 | if ins_tmpl.operands[n].is_predicate: 1593 | fieldtype = "HEX_OP_TYPE_PREDICATE" 1594 | val = "hi->ops[{0:d}].op.pred = {1:s};".format(i, mask) 1595 | # 2. Check if control register 1596 | elif ins_tmpl.operands[n].is_control: 1597 | fieldtype = "HEX_OP_TYPE_CONTROL" 1598 | val = "hi->ops[{0:d}].op.cr = {1:s};".format(i, mask) 1599 | # 3. Check if system control register 1600 | elif ins_tmpl.operands[n].is_system: 1601 | fieldtype = "HEX_OP_TYPE_SYSTEM" 1602 | val = "hi->ops[{0:d}].op.sys = {1:s};".format(i, mask) 1603 | # 4. Usual register 1604 | else: 1605 | fieldtype = "HEX_OP_TYPE_REG" 1606 | if ins_tmpl.operands[n].is_register_pair: 1607 | # TODO: Handle additional attributes 1608 | val = "hi->ops[{0:d}].op.reg = {1:s};".format(i, mask) 1609 | else: 1610 | val = "hi->ops[{0:d}].op.reg = {1:s}; // {2:s}".format(i, mask, ins_tmpl.operands[n].syntax) 1611 | # Optional value 1612 | elif isinstance(ins_tmpl.operands[n], OptionalTemplate): 1613 | fieldtype = "HEX_OP_TYPE_OPT" 1614 | # Immediate value 1615 | else: 1616 | val = "hi->ops[{0:d}].op.imm = {1:s}".format(i, mask) 1617 | # Perform sign extension (also applies to jump targets...) 1618 | # Also applies to the loops 1619 | 1620 | if ins_tmpl.operands[n].signed or (is_branch and i == ti): 1621 | # The immediate is already scaled at this point. Therefore the most significant bit is bit 24 (if we assume #r22:2) 1622 | signmask = "hi->ops[{0:d}].op.imm & (1 << {1:d})".format(i, f.mask_len + ins_tmpl.operands[n].scaled - 1) 1623 | signext = "hi->ops[{0:d}].op.imm |= (0xFFFFFFFF << {1:d});".format(i, f.mask_len + ins_tmpl.operands[n].scaled - 1) 1624 | slines += make_C_block([signext], "if ({0:s})".format(signmask)) 1625 | # Handle scaled operands 1626 | if ins_tmpl.operands[n].scaled: 1627 | val += " << {0:d}; // scaled".format(ins_tmpl.operands[n].scaled) 1628 | else: 1629 | val += ";" 1630 | 1631 | # We do not have operand for optional, so handle it's differently 1632 | if fieldtype == "HEX_OP_TYPE_OPT": 1633 | # Add IF here, because optional 1634 | opsft = "{0:s} |= {1:s}; // {2:s}".format("hi->pf", "HEX_PF_LSH1", "[:<<1]") 1635 | lines += make_C_block([opsft], "if ({0:s})".format(mask)) 1636 | else: 1637 | field = "hi->ops[{0:d}].type = {1:s};".format(i, fieldtype) 1638 | opattrs = [] 1639 | if isinstance(ins_tmpl.operands[n], RegisterTemplate): 1640 | # Check if a register pair 1641 | if ins_tmpl.operands[n].is_register_pair: 1642 | opattrs += ["hi->ops[{0:d}].attr |= HEX_OP_REG_PAIR;".format(i)] 1643 | lines += [field] + opattrs + [val] 1644 | lines += slines 1645 | op_count += 1 # Count only non-optional operands 1646 | 1647 | lines = ["hi->op_count = {0:d};".format(op_count)] + lines 1648 | return lines 1649 | 1650 | def extend_immediates_r2(ins_tmpl): 1651 | elines = [] 1652 | # Note about duplex containers: 1653 | # In duplex containers only the second of two instructions (slot 1) can be expanded. 1654 | # Slot 1 are the high bits of an instruction, therefore: 1655 | # SLOT 1 ; SLOT 0 1656 | # Rd = #u6 ; allocframe(#u5) 1657 | # The manual speaks of only two specific instructions (Rx = add (Rx, #s7) and Rd = #u6) 1658 | # which are expandable (But there seem to be more) 1659 | # Reference: Programmers Manual V62-V67 Chapter 10.3 1660 | 1661 | if ins_tmpl.name in extendable_insn or (ins_tmpl.is_duplex \ 1662 | and ins_tmpl.syntax.split(';', 1)[0].strip() in extendable_duplex_syntax): 1663 | if ins_tmpl.imm_ops: 1664 | # Assume we only have one - it is clear in the list 1665 | op = ins_tmpl.imm_ext_op # imm_ext_op is by default set to imm_ops[0] 1666 | oi = op.index # Immediate operand index 1667 | # If there is an offset of the operand - apply it too 1668 | # Use "extend_offset(op, off)" function then 1669 | off = op.scaled 1670 | if off: 1671 | elines = ["hex_op_extend_off(&hi->ops[{0:d}], {1:d});".format(oi, off)] 1672 | else: 1673 | elines = ["hex_op_extend(&hi->ops[{0:d}]);".format(oi)] 1674 | return elines 1675 | 1676 | def extract_mnemonic_r2(ins_tmpl): 1677 | lines = [] 1678 | # field -> token 1679 | sortf = lambda c: ins_tmpl.operands[c].index 1680 | sortedops = sorted(ins_tmpl.operands, key = sortf) 1681 | fmt = {} 1682 | args = [] 1683 | fmtstr = ins_tmpl.syntax 1684 | for n in sortedops: 1685 | o = ins_tmpl.operands[n] 1686 | i = ins_tmpl.operands[n].index 1687 | if isinstance(o, RegisterTemplate): 1688 | if o.is_predicate: 1689 | fmt[o.syntax] = "P%d" # + number from mask 1690 | args += ["hi->ops[{0:d}].op.pred".format(i)] 1691 | elif o.is_control: 1692 | if o.is_register_pair: 1693 | fmt[o.syntax] = "%s:%s" 1694 | args += ["hex_get_cntl_reg(hi->ops[{0:d}].op.cr + 1)".format(i)] 1695 | args += ["hex_get_cntl_reg(hi->ops[{0:d}].op.cr)".format(i)] 1696 | else: 1697 | fmt[o.syntax] = "%s" 1698 | args += ["hex_get_cntl_reg(hi->ops[{0:d}].op.cr)".format(i)] 1699 | elif o.is_system: 1700 | if o.is_register_pair: 1701 | fmt[o.syntax] = "%s:%s" 1702 | args += ["hex_get_sys_reg(hi->ops[{0:d}].op.sys + 1)".format(i)] 1703 | args += ["hex_get_sys_reg(hi->ops[{0:d}].op.sys)".format(i)] 1704 | else: 1705 | fmt[o.syntax] = "%s" 1706 | args += ["hex_get_sys_reg(hi->ops[{0:d}].op.sys)".format(i)] 1707 | else: 1708 | # DUPLEX 1709 | if ins_tmpl.is_duplex: 1710 | if o.is_register_pair: 1711 | fmt[o.syntax] = "%s" # + number from mask 1712 | args += ["hex_get_sub_regpair(hi->ops[{0:d}].op.reg)".format(i)] 1713 | else: 1714 | fmt[o.syntax] = "%s" # + number from mask 1715 | args += ["hex_get_sub_reg(hi->ops[{0:d}].op.reg)".format(i)] 1716 | # NOT DUPLEX 1717 | else: 1718 | if o.is_register_pair: 1719 | fmt[o.syntax] = "R%d:R%d" # + number from mask 1720 | args += ["hi->ops[{0:d}].op.reg + 1".format(i)] 1721 | args += ["hi->ops[{0:d}].op.reg".format(i)] 1722 | else: 1723 | fmt[o.syntax] = "R%d" # + number from mask 1724 | args += ["hi->ops[{0:d}].op.reg".format(i)] 1725 | elif isinstance(o, OptionalTemplate): 1726 | fmt[o.syntax] = "%s" 1727 | args += ["((hi->pf & HEX_PF_LSH1) == HEX_PF_LSH1) ? \":<<1\" : \"\""] 1728 | elif isinstance(o, ImmediateTemplate): 1729 | fmt[o.syntax] = "0x%x" # TODO: Better representation, etc 1730 | # As soon as we extract the classes from the encoded instructions this should its info from it. 1731 | if ("JUMP_" in ins_tmpl.name or "CALL_" in ins_tmpl.name) and (i == len(ins_tmpl.operands)-1): 1732 | args += ["addr + (st32) hi->ops[{0:d}].op.imm".format(i)] 1733 | elif o.signed: 1734 | fmt[o.syntax] = "%d" 1735 | args += ["(st32) hi->ops[{0:d}].op.imm".format(i)] 1736 | else: 1737 | args += ["hi->ops[{0:d}].op.imm".format(i)] 1738 | else: 1739 | pass 1740 | 1741 | for k,v in fmt.items(): 1742 | fmtstr = fmtstr.replace(k,v,1) 1743 | if args: 1744 | mnem = "sprintf(hi->mnem, \"" + fmtstr + "\", " 1745 | mnem += ", ".join(args) 1746 | mnem += ");" 1747 | else: 1748 | mnem = "sprintf(hi->mnem, \"" + fmtstr + "\");" 1749 | 1750 | if mnem: 1751 | lines += [mnem] 1752 | 1753 | return lines 1754 | 1755 | def form_instruction_r2(category, instruction): 1756 | inlines = [] 1757 | inlines += ["// Instruction: {0}: {1} | {2}".format(category, instruction.encoding.text, instruction.syntax)] 1758 | inlines += extract_name_r2(instruction) 1759 | inlines += extract_fields_r2(instruction) 1760 | inlines += extract_predicates_r2(instruction) 1761 | inlines += extract_pf_r2(instruction) 1762 | inlines += extend_immediates_r2(instruction) 1763 | inlines += extract_mnemonic_r2(instruction) 1764 | return inlines 1765 | 1766 | def const_extender_r2(): 1767 | clines = ["// Handle constant extender"] 1768 | clines += ["hi->instruction = HEX_INS_IMMEXT;"] 1769 | clines += ["hi->op_count = 1;"] 1770 | clines += ["hi->ops[0].type = HEX_OP_TYPE_IMM;"] 1771 | clines += ["hi->ops[0].attr |= HEX_OP_CONST_EXT;"] 1772 | clines += ["hi->ops[0].op.imm = ((hi_u32 & 0x3FFF) | (((hi_u32 >> 16) & 0xFFF) << 14)) << 6;"] 1773 | clines += ["constant_extender = hi->ops[0].op.imm;"] 1774 | clines += ["sprintf(hi->mnem, \"immext(#0x%x)\", hi->ops[0].op.imm);"] 1775 | return clines 1776 | 1777 | def write_files_r2(ins_class, ins_duplex, hex_insn_names, extendable_insn): 1778 | HEX_DISAS_FILENAME = "r2/hexagon_disas.c" 1779 | HEX_INSN_FILENAME = "r2/hexagon_insn.h" 1780 | HEX_ANAL_FILENAME = "r2/hexagon_anal.c" 1781 | 1782 | # FIXME: Dirty hack but ENOTIME! 1783 | ins_enum = ["HEX_INS_UNKNOWN,"] # Unknown instruction 1784 | ins_enum += ["HEX_INS_IMMEXT,"] # Constant extender 1785 | for i in hex_insn_names: 1786 | ins_enum += [i + ","] 1787 | hlines = make_C_block(ins_enum, "enum HEX_INS") 1788 | hlines[-1] = hlines[-1] + ";" # Finish the enum with semicolon 1789 | with open(HEX_INSN_FILENAME, "w") as f: 1790 | for l in hlines: 1791 | f.write(l + "\n") 1792 | 1793 | # At first - generate code for parsing duplexes 1794 | # ----------------------------------------------------------------------------- 1795 | lines = ["// DUPLEXES"] 1796 | inlines = [] 1797 | cat_switch = "switch ((((hi_u32 >> 29) & 0xF) << 1) | ((hi_u32 >> 13) & 1))" 1798 | dupsorted = collections.OrderedDict(sorted(ins_duplex.items())) 1799 | for k,v in dupsorted.items(): 1800 | vlines = [] 1801 | # Match by category, in hex format 1802 | case_beg = "case 0x{0:x}:".format(k) 1803 | for i in v: 1804 | # TODO: Extract common markers, rebalance to switches 1805 | mask = i.encoding.mask 1806 | val = i.encoding.value 1807 | vlines += make_C_block(form_instruction_r2(k, i), "if ((hi_u32 & 0x{0:x}) == 0x{1:x})".format(mask, val), None, "break;") 1808 | inlines += make_C_block(vlines, case_beg, None, "break;") 1809 | inlines = make_C_block(inlines, cat_switch) 1810 | # Run duplexes only if parse bits are set 1811 | lines += make_C_block(inlines, "if (((hi_u32 >> 14) & 0x3) == 0)") 1812 | 1813 | # Now handle the non-compressed instructions 1814 | # ------------------------------------------------------------------------------- 1815 | inlines = [] 1816 | cat_switch = "switch ((hi_u32 >> 28) & 0xF)" 1817 | # At first - handle constant extender 1818 | const_case = "case 0x0:" 1819 | clines = const_extender_r2() 1820 | inlines += make_C_block(clines, const_case, None, "break;") 1821 | # Then generate code for usual instructions 1822 | classsorted = collections.OrderedDict(sorted(ins_class.items())) 1823 | for k,v in classsorted.items(): 1824 | vlines = [] 1825 | # Match by category, in hex format 1826 | case_beg = "case 0x{0:x}:".format(k) 1827 | for i in v: 1828 | # TODO: Extract common markers, rebalance to switches 1829 | mask = i.encoding.mask & ~(0xf << 28) 1830 | val = i.encoding.value & ~(0xf << 28) 1831 | vlines += make_C_block(form_instruction_r2(k, i), "if ((hi_u32 & 0x{0:x}) == 0x{1:x})".format(mask, val), None, "break;") 1832 | inlines += make_C_block(vlines, case_beg, None, "break;") 1833 | inlines = make_C_block(inlines, cat_switch) 1834 | lines += make_C_block(inlines, "else") # only run if non-duplex mode 1835 | 1836 | # Produce a RAsm plugin C file finally 1837 | # --------------------------------------------------------------------------------- 1838 | includes = ["#include "] 1839 | includes += ["#include "] 1840 | includes += ["#include "] 1841 | includes += ["#include "] 1842 | includes += ["#include "] 1843 | includes += ["#include \"hexagon.h\""] 1844 | includes += ["#include \"hexagon_insn.h\""] 1845 | includes += [""] # for the sake of beauty 1846 | 1847 | # Add constantExtender definition 1848 | includes += ["extern ut32 constant_extender;"] 1849 | includes += [""] # for the sake of beauty 1850 | 1851 | # Wrap everything into one function 1852 | lines = includes + make_C_block(lines, "int hexagon_disasm_instruction(ut32 hi_u32, HexInsn *hi, ut32 addr)", None, "return 4;") 1853 | with open(HEX_DISAS_FILENAME, "w") as f: 1854 | for l in lines: 1855 | f.write(l + "\n") 1856 | 1857 | # Generate analysis code 1858 | # --------------------------------------------------------------------------------- 1859 | 1860 | type_switch = "switch (hi->instruction)" 1861 | emulines = [] 1862 | for i in deco.inst_template_list: 1863 | ilines = [] 1864 | if i.branch: 1865 | if isinstance(i.branch.target, ImmediateTemplate): 1866 | ilines += ["// {0:s}".format(i.syntax)] 1867 | 1868 | if i.branch.type == "call": 1869 | ilines += ["op->type = R_ANAL_OP_TYPE_CALL;"] 1870 | ilines += ["op->jump = op->addr + (st32) hi->ops[{0:d}].op.imm;".format(i.branch.target.index)] 1871 | else: 1872 | if i.branch.is_conditional: 1873 | ilines += ["op->type = R_ANAL_OP_TYPE_CJMP;"] 1874 | else: 1875 | ilines += ["op->type = R_ANAL_OP_TYPE_JMP;"] 1876 | ilines += ["op->jump = op->addr + (st32) hi->ops[{0:d}].op.imm;".format(i.branch.target.index)] 1877 | ilines += ["op->fail = op->addr + op->size;"] 1878 | emulines += make_C_block(ilines, "case {0:s}:".format(i.name), None, "break;") 1879 | if i.branch.type == "dealloc_return": 1880 | ilines += ["// {0:s}".format(i.syntax)] 1881 | ilines += ["op->type = R_ANAL_OP_TYPE_RET;"]; 1882 | emulines += make_C_block(ilines, "case {0:s}:".format(i.name), None, "break;") 1883 | 1884 | emulines = make_C_block(emulines, type_switch, indent=False) 1885 | # Wrap everything into one function 1886 | lines = make_C_block(emulines, "int hexagon_anal_instruction(HexInsn *hi, RAnalOp *op)", None, "return op->size;") 1887 | 1888 | # Produce a RAsm plugin C file finally 1889 | # --------------------------------------------------------------------------------- 1890 | includes = ["#include "] 1891 | includes += ["#include "] 1892 | includes += ["#include "] 1893 | includes += ["#include "] 1894 | includes += ["#include "] 1895 | includes += ["#include "] 1896 | includes += ["#include \"hexagon.h\""] 1897 | includes += ["#include \"hexagon_insn.h\""] 1898 | includes += [""] # for the sake of beauty 1899 | lines = includes + lines 1900 | 1901 | with open(HEX_ANAL_FILENAME, "w") as f: 1902 | for l in lines: 1903 | f.write(l + "\n") 1904 | 1905 | 1906 | # TODO: Export the sources into r2 repository 1907 | 1908 | # ------------------------------------------------------------------------------------ 1909 | 1910 | if __name__ == "__main__": 1911 | if sys.version_info < (3, 7): 1912 | print("This script needs Python version 3.7 or higher") 1913 | sys.exit() 1914 | 1915 | parser = argparse.ArgumentParser(description="Hexagon C disassembly generator") 1916 | args = parser.parse_args() 1917 | mp = ManualParser('80-n2040-36_b_hexagon_v62_prog_ref_manual.txt') 1918 | mp.go_to_instruction_set_start() 1919 | mp.find_encondings() 1920 | 1921 | hp = HeaderParser('hexagon_iset_v5.h') 1922 | hp.parse() 1923 | # So here we have objects of parsed tokens 1924 | hp.standarize_syntax(hp.duplex_inst_encodings) 1925 | hp.standarize_syntax(hp.other_inst_encodings) 1926 | inst_def_list = mp.instructions 1927 | inst_def_list.extend(hp.duplex_inst_encodings) 1928 | #inst_def_list.extend(hp.other_inst_encodings) 1929 | #print(inst_def_list) 1930 | 1931 | deco = HexagonInstructionDecoder(inst_def_list) 1932 | ins_class = {} # We pre-sort our instructions by ICLASS value 1933 | ins_duplex = {} # We pre-sort our duplex instructions by ICLASS too 1934 | for ins_tmpl in deco.inst_template_list: 1935 | hex_inst_struc = {} 1936 | hex_inst_struc["mask"] = ins_tmpl.encoding.mask 1937 | hex_inst_struc["syntax"] = ins_tmpl.syntax 1938 | ins_tmpl.name = generate_insn(ins_tmpl) 1939 | hex_insn_names += [ins_tmpl.name] # for instructions header enum 1940 | # separate parsing duplex instructions into another thing 1941 | dupbits = ins_tmpl.encoding.text[16:18] 1942 | duplex = 1 1943 | if not dupbits == 'PP': 1944 | duplex = int(dupbits, 2) 1945 | 1946 | if not duplex == 0: 1947 | # for non-duplex instructions those are higher 4 bits 1948 | iclass = int(ins_tmpl.encoding.text[0:4], 2) 1949 | #print("{0} : {1} - {2}".format(iclass, ins_tmpl.encoding.text, ins_tmpl.syntax)) 1950 | #for tok in ins_tmpl.tokens: 1951 | # print("{0} : {1}".format(tok.s, tok.op)) 1952 | if iclass in ins_class: 1953 | ins_class[iclass] += [ins_tmpl] 1954 | else: 1955 | ins_class[iclass] = [ins_tmpl] 1956 | else: 1957 | # for duplex instructions those are high 3 bits + 13 bit 1958 | iclass = int(ins_tmpl.encoding.text[0:3] + ins_tmpl.encoding.text[18], 2) 1959 | if iclass in ins_duplex: 1960 | ins_duplex[iclass] += [ins_tmpl] 1961 | else: 1962 | ins_duplex[iclass] = [ins_tmpl] 1963 | 1964 | # ----------------------------------------------------------------------------------------------- 1965 | # Now parse the list of the instructions which are support the constant extender system 1966 | for i in deco.inst_template_list: 1967 | print(i.syntax) 1968 | extendable_insn = [] # The list of extendable instructions' names 1969 | extendable_duplex_syntax = [] 1970 | with open("const_extenders.txt") as f: 1971 | ext_ins = f.read().splitlines() 1972 | for ins_tmpl in deco.inst_template_list: 1973 | for ext_syntax in ext_ins: 1974 | normsyntax = standarize_syntax_objdump(ext_syntax.split('/', 1)[0]) 1975 | if ext_syntax.split('//')[-1].strip() == "Slot 1 duplex": 1976 | extendable_duplex_syntax += [normsyntax.strip()] 1977 | #print("{0:s} VS {1:s}".format(ins_tmpl.syntax, normsyntax)) 1978 | if ins_tmpl.syntax == normsyntax: 1979 | extendable_insn += [ins_tmpl.name] 1980 | print("{0:s} - {1:s}".format(ins_tmpl.name, ins_tmpl.syntax)) 1981 | 1982 | # ----------------------------------------------------------------------------------------------- 1983 | # TOOL SPECIFIC CODE 1984 | # R2 specifics 1985 | write_files_r2(ins_class, ins_duplex, hex_insn_names, extendable_insn) 1986 | print("Succesfully generated Radare2 disassembly plugin") 1987 | 1988 | --------------------------------------------------------------------------------