1 /* radare - LGPL - Copyright 2010-2013 eloi<limited-entropy.com> */
2
3 #include <string.h>
4 #include <r_types.h>
5 #include <r_lib.h>
6 #include <r_asm.h>
7 #include <r_anal.h>
8
9 #define API static
10
11 #define LONG_SIZE 4
12 #define WORD_SIZE 2
13 #define BYTE_SIZE 1
14
15 /*
16 * all processor instructions are implemented, but all FPU are missing
17 * DIV1,MAC.W,MAC.L,rte,rts should be checked
18 * also tests are written, but still could be some issues, if I misunderstand instructions.
19 * If you found some bugs, please open an issue
20 */
21
22 #define BIT_32(x) x",0x80000000,&"
23 #define S16_EXT(x) x",DUP,0x8000,&,?{,0xFFFFFFFFFFFF0000,|,}"
24 #define S32_EXT(x) x",DUP,0x80000000,&,?{,0xFFFFFFFF00000000,|,}"
25 #define IS_T "sr,0x1,&,"
26 #define SET_T "0x1,sr,|="
27 #define CLR_T "0xFFFFFFFE,sr,&="
28 //Macros for different instruction types
29
30 #define IS_CLRT(x) x == 0x0008
31 #define IS_NOP(x) x == 0x0009
32 #define IS_RTS(x) x == 0x000b
33 #define IS_SETT(x) x == 0x0018
34 #define IS_DIV0U(x) x == 0x0019
35 #define IS_SLEEP(x) x == 0x001b
36 #define IS_CLRMAC(x) x == 0x0028
37 #define IS_RTE(x) x == 0x002b
38
39 #define IS_STCSR1(x) (((x) & 0xF0CF) == 0x0002) //mask stc Rn,{SR,gbr,VBR,SSR}
40 #define IS_BSRF(x) ((x) & 0xf0ff) == 0x0003
41 #define IS_BRAF(x) (((x) & 0xf0ff) == 0x0023)
42 #define IS_MOVB_REG_TO_R0REL(x) (((x) & 0xF00F) == 0x0004)
43 #define IS_MOVW_REG_TO_R0REL(x) (((x) & 0xF00F) == 0x0005)
44 #define IS_MOVL_REG_TO_R0REL(x) (((x) & 0xF00F) == 0x0006)
45 #define IS_MULL(x) (((x) & 0xF00F) == 0x0007)
46 #define IS_MOVB_R0REL_TO_REG(x) (((x) & 0xF00F) == 0x000C)
47 #define IS_MOVW_R0REL_TO_REG(x) (((x) & 0xF00F) == 0x000D)
48 #define IS_MOVL_R0REL_TO_REG(x) (((x) & 0xF00F) == 0x000E)
49 #define IS_MACL(x) (((x) & 0xF00F) == 0x000F)
50 #define IS_MOVT(x) (((x) & 0xF0FF) == 0x0029)
51 #define IS_STSMACH(x) (((x) & 0xF0FF) == 0x000A)
52 #define IS_STSMACL(x) (((x) & 0xF0FF) == 0x001A)
53 #define IS_STSPR(x) (((x) & 0xF0FF) == 0x002A)
54 //#define IS_STSFPUL(x) (((x) & 0xF0FF) == 0x005A) //FP*: todo maybe someday
55 //#define IS_STSFPSCR(x) (((x) & 0xF0FF) == 0x006A)
56 #define IS_MOVB_REG_TO_REGREF(x) (((x) & 0xF00F) == 0x2000)
57 #define IS_MOVW_REG_TO_REGREF(x) (((x) & 0xF00F) == 0x2001)
58 #define IS_MOVL_REG_TO_REGREF(x) (((x) & 0xF00F) == 0x2002)
59 //#define invalid?(x) (((x) & 0xF00F) == 0x2003) //illegal on sh2e
60 #define IS_PUSHB(x) (((x) & 0xF00F) == 0x2004)
61 #define IS_PUSHW(x) (((x) & 0xF00F) == 0x2005)
62 #define IS_PUSHL(x) (((x) & 0xF00F) == 0x2006)
63 #define IS_DIV0S(x) (((x) & 0xF00F) == 0x2007)
64 #define IS_TSTRR(x) (((x) & 0xF00F) == 0x2008)
65 #define IS_AND_REGS(x) (((x) & 0xF00F) == 0x2009)
66 #define IS_XOR_REGS(x) (((x) & 0xF00F) == 0x200A)
67 #define IS_OR_REGS(x) (((x) & 0xF00F) == 0x200B)
68 #define IS_CMPSTR(x) (((x) & 0xF00F) == 0x200C)
69 #define IS_XTRCT(x) (((x) & 0xF00F) == 0x200D)
70 #define IS_MULUW(x) (((x) & 0xF00F) == 0x200E)
71 #define IS_MULSW(x) (((x) & 0xF00F) == 0x200F)
72 #define IS_CMPEQ(x) (((x) & 0xF00F) == 0x3000)
73 //#define invalid?(x) (((x) & 0xF00F) == 0x3001)
74 #define IS_CMPHS(x) (((x) & 0xF00F) == 0x3002)
75 #define IS_CMPGE(x) (((x) & 0xF00F) == 0x3003)
76 #define IS_CMPHI(x) (((x) & 0xF00F) == 0x3006)
77 #define IS_CMPGT(x) (((x) & 0xF00F) == 0x3007)
78 #define IS_DIV1(x) (((x) & 0xF00F) == 0x3004)
79 #define IS_DMULU(x) (((x) & 0xF00F) == 0x3005)
80 #define IS_DMULS(x) (((x) & 0xF00F) == 0x300D)
81 #define IS_SUB(x) (((x) & 0xF00F) == 0x3008)
82 //#define invalid?(x) (((x) & 0xF00F) == 0x3009)
83 #define IS_SUBC(x) (((x) & 0xF00F) == 0x300A)
84 #define IS_SUBV(x) (((x) & 0xF00F) == 0x300B)
85 #define IS_ADD(x) (((x) & 0xF00F) == 0x300C)
86 #define IS_ADDC(x) (((x) & 0xF00F) == 0x300E)
87 #define IS_ADDV(x) (((x) & 0xF00F) == 0x300F)
88 #define IS_MACW(x) (((x) & 0xF00F) == 0x400F)
89 #define IS_JSR(x) (((x) & 0xf0ff) == 0x400b)
90 #define IS_JMP(x) (((x) & 0xf0ff) == 0x402b)
91 #define IS_CMPPL(x) (((x) & 0xf0ff) == 0x4015)
92 #define IS_CMPPZ(x) (((x) & 0xf0ff) == 0x4011)
93 #define IS_LDCSR(x) (((x) & 0xF0FF) == 0x400E)
94 #define IS_LDCGBR(x) (((x) & 0xF0FF) == 0x401E)
95 #define IS_LDCVBR(x) (((x) & 0xF0FF) == 0x402E)
96 #define IS_LDCLSR(x) (((x) & 0xF0FF) == 0x4007)
97 #define IS_LDCLSRGBR(x) (((x) & 0xF0FF) == 0x4017)
98 #define IS_LDCLSRVBR(x) (((x) & 0xF0FF) == 0x4027)
99 #define IS_LDSMACH(x) (((x) & 0xF0FF) == 0x400A)
100 #define IS_LDSMACL(x) (((x) & 0xF0FF) == 0x401A)
101 #define IS_LDSLMACH(x) (((x) & 0xF0FF) == 0x4006)
102 #define IS_LDSLMACL(x) (((x) & 0xF0FF) == 0x4016)
103 #define IS_LDSPR(x) (((x) & 0xF0FF) == 0x402A)
104 #define IS_LDSLPR(x) (((x) & 0xF0FF) == 0x4026)
105 //#define IS_LDSFPUL(x) (((x) & 0xF0FF) == 0x405A) //FP*: todo maybe someday
106 //#define IS_LDSFPSCR(x) (((x) & 0xF0FF) == 0x406A)
107 //#define IS_LDSLFPUL(x) (((x) & 0xF0FF) == 0x4066)
108 //#define IS_LDSLFPSCR(x) (((x) & 0xF0FF) == 0x4056)
109 #define IS_ROTCR(x) (((x) & 0xF0FF) == 0x4025)
110 #define IS_ROTCL(x) (((x) & 0xF0FF) == 0x4024)
111 #define IS_ROTL(x) (((x) & 0xF0FF) == 0x4004)
112 #define IS_ROTR(x) (((x) & 0xF0FF) == 0x4005)
113 //not on sh2e : shad, shld
114
115 //#define IS_SHIFT1(x) (((x) & 0xF0DE) == 0x4000) //unused (treated as switch-case)
116 //other shl{l,r}{,2,8,16} in switch case also.
117
118 #define IS_STSLMACL(x) (((x) & 0xF0FF) == 0x4012)
119 #define IS_STSLMACH(x) (((x) & 0xF0FF) == 0x4002)
120 #define IS_STCLSR(x) (((x) & 0xF0FF) == 0x4003)
121 #define IS_STCLGBR(x) (((x) & 0xF0FF) == 0x4013)
122 #define IS_STCLVBR(x) (((x) & 0xF0FF) == 0x4023)
123 //todo: other stc.l not on sh2e
124 #define IS_STSLPR(x) (((x) & 0xF0FF) == 0x4022)
125 //#define IS_STSLFPUL(x) (((x) & 0xF0FF) == 0x4052)
126 //#define IS_STSLFPSCR(x) (((x) & 0xF0FF) == 0x4062)
127 #define IS_TASB(x) (((x) & 0xF0FF) == 0x401B)
128 #define IS_DT(x) (((x) & 0xF0FF) == 0x4010)
129
130
131 #define IS_MOVB_REGREF_TO_REG(x) (((x) & 0xF00F) == 0x6000)
132 #define IS_MOVW_REGREF_TO_REG(x) (((x) & 0xF00F) == 0x6001)
133 #define IS_MOVL_REGREF_TO_REG(x) (((x) & 0xF00F) == 0x6002)
134 #define IS_MOV_REGS(x) (((x) & 0xf00f) == 0x6003)
135 #define IS_MOVB_POP(x) (((x) & 0xF00F) == 0x6004)
136 #define IS_MOVW_POP(x) (((x) & 0xF00F) == 0x6005)
137 #define IS_MOVL_POP(x) (((x) & 0xF00F) == 0x6006)
138 #define IS_NOT(x) (((x) & 0xF00F) == 0x6007)
139 #define IS_SWAPB(x) (((x) & 0xF00F) == 0x6008)
140 #define IS_SWAPW(x) (((x) & 0xF00F) == 0x6009)
141 #define IS_NEG(x) (((x) & 0xF00F) == 0x600B)
142 #define IS_NEGC(x) (((x) & 0xF00F) == 0x600A)
143 #define IS_EXT(x) (((x) & 0xF00C) == 0x600C) //match ext{s,u}.{b,w}
144
145
146 #define IS_MOVB_R0_REGDISP(x) (((x) & 0xFF00) == 0x8000)
147 #define IS_MOVW_R0_REGDISP(x) (((x) & 0xFF00) == 0x8100)
148 //#define illegal?(x) (((x) & 0xF900) == 0x8000) //match 8{2,3,6,7}00
149 #define IS_MOVB_REGDISP_R0(x) (((x) & 0xFF00) == 0x8400)
150 #define IS_MOVW_REGDISP_R0(x) (((x) & 0xFF00) == 0x8500)
151 #define IS_CMPIMM(x) (((x) & 0xFF00) == 0x8800)
152 //#define illegal?(x) (((x) & 0xFB00) == 0x8A00) //match 8{A,E}00
153 #define IS_BT(x) (((x) & 0xff00) == 0x8900)
154 #define IS_BF(x) (((x) & 0xff00) == 0x8B00)
155 #define IS_BTS(x) (((x) & 0xff00) == 0x8D00)
156 #define IS_BFS(x) (((x) & 0xff00) == 0x8F00)
157 #define IS_BT_OR_BF(x) IS_BT(x)||IS_BTS(x)||IS_BF(x)||IS_BFS(x)
158
159 #define IS_MOVB_R0_GBRREF(x) (((x) & 0xFF00) == 0xC000)
160 #define IS_MOVW_R0_GBRREF(x) (((x) & 0xFF00) == 0xC100)
161 #define IS_MOVL_R0_GBRREF(x) (((x) & 0xFF00) == 0xC200)
162 #define IS_TRAP(x) (((x) & 0xFF00) == 0xC300)
163 #define IS_MOVB_GBRREF_R0(x) (((x) & 0xFF00) == 0xC400)
164 #define IS_MOVW_GBRREF_R0(x) (((x) & 0xFF00) == 0xC500)
165 #define IS_MOVL_GBRREF_R0(x) (((x) & 0xFF00) == 0xC600)
166 #define IS_MOVA_PCREL_R0(x) (((x) & 0xFF00) == 0xC700)
167 #define IS_BINLOGIC_IMM_R0(x) (((x) & 0xFC00) == 0xC800) //match C{8,9,A,B}00
168 #define IS_BINLOGIC_IMM_GBR(x) (((x) & 0xFC00) == 0xCC00) //match C{C,D,E,F}00 : *.b #imm, @(R0,gbr)
169
170
171 /* Compute PC-relative displacement for branch instructions */
172 #define GET_BRA_OFFSET(x) ((x) & 0x0fff)
173 #define GET_BTF_OFFSET(x) ((x) & 0x00ff)
174
175 /* Compute reg nr for BRAF,BSR,BSRF,JMP,JSR */
176 #define GET_TARGET_REG(x) (((x) >> 8) & 0x0f)
177 #define GET_SOURCE_REG(x) (((x) >> 4) & 0x0f)
178
179 /* index of PC reg in regs[] array*/
180 #define PC_IDX 16
181
182 /* for {bra,bsr} only: (sign-extend 12bit offset)<<1 + PC +4 */
disarm_12bit_offset(RAnalOp * op,unsigned int insoff)183 static ut64 disarm_12bit_offset (RAnalOp *op, unsigned int insoff) {
184 ut64 off = insoff;
185 /* sign extend if higher bit is 1 (0x0800) */
186 if ((off & 0x0800) == 0x0800)
187 {
188 off |= ~0xFFF;
189 }
190 return (op->addr) + (off << 1) + 4;
191 }
192
193 /* for bt,bf sign-extended offsets : return PC+4+ (exts.b offset)<<1 */
disarm_8bit_offset(ut64 pc,ut32 offs)194 static ut64 disarm_8bit_offset (ut64 pc, ut32 offs) {
195 /* pc (really, op->addr) is 64 bits, so we need to sign-extend
196 * to 64 bits instead of the 32 the actual CPU does */
197 ut64 off = offs;
198 /* sign extend if higher bit is 1 (0x08) */
199 if ((off & 0x80) == 0x80)
200 {
201 off |= ~0xFF;
202 }
203 return (off << 1) + pc + 4;
204 }
205
206 static char *regs[]={"r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12","r13","r14","r15","pc"};
207
anal_fill_ai_rg(RAnal * anal,int idx)208 static RAnalValue *anal_fill_ai_rg(RAnal *anal, int idx) {
209 RAnalValue *ret = r_anal_value_new ();
210 ret->reg = r_reg_get (anal->reg, regs[idx], R_REG_TYPE_GPR);
211 return ret;
212 }
213
anal_fill_im(RAnal * anal,st32 v)214 static RAnalValue *anal_fill_im(RAnal *anal, st32 v) {
215 RAnalValue *ret = r_anal_value_new ();
216 ret->imm = v;
217 return ret;
218 }
219
220 /* Implements @(disp,Rn) , size=1 for .b, 2 for .w, 4 for .l */
anal_fill_reg_disp_mem(RAnal * anal,int reg,st64 delta,st64 size)221 static RAnalValue *anal_fill_reg_disp_mem(RAnal *anal, int reg, st64 delta, st64 size) {
222 RAnalValue *ret = anal_fill_ai_rg (anal, reg);
223 ret->memref = size;
224 ret->delta = delta*size;
225 return ret;
226 }
227
228 /* Rn */
anal_fill_reg_ref(RAnal * anal,int reg,st64 size)229 static RAnalValue *anal_fill_reg_ref(RAnal *anal, int reg, st64 size) {
230 RAnalValue *ret = anal_fill_ai_rg (anal, reg);
231 ret->memref = size;
232 return ret;
233 }
234
235 /* @(R0,Rx) references for all sizes */
anal_fill_r0_reg_ref(RAnal * anal,int reg,st64 size)236 static RAnalValue *anal_fill_r0_reg_ref(RAnal *anal, int reg, st64 size) {
237 RAnalValue *ret = anal_fill_ai_rg (anal, 0);
238 ret->regdelta = r_reg_get (anal->reg, regs[reg], R_REG_TYPE_GPR);
239 ret->memref = size;
240 return ret;
241 }
242
243 // @(disp,PC) for size=2(.w), size=4(.l). disp is 0-extended
anal_pcrel_disp_mov(RAnal * anal,RAnalOp * op,ut8 disp,int size)244 static RAnalValue *anal_pcrel_disp_mov(RAnal* anal, RAnalOp* op, ut8 disp, int size) {
245 RAnalValue *ret = r_anal_value_new ();
246 if (size==2) {
247 ret->base = op->addr + 4;
248 ret->delta = disp << 1;
249 } else {
250 ret->base = (op->addr + 4) & ~0x03;
251 ret->delta = disp << 2;
252 }
253
254 return ret;
255 }
256
257 //= PC+4+R<reg>
anal_regrel_jump(RAnal * anal,RAnalOp * op,ut8 reg)258 static RAnalValue *anal_regrel_jump(RAnal* anal, RAnalOp* op, ut8 reg) {
259 RAnalValue *ret = r_anal_value_new ();
260 ret->reg = r_reg_get (anal->reg, regs[reg], R_REG_TYPE_GPR);
261 ret->base = op->addr + 4;
262 return ret;
263 }
264
265 /* 16 decoder routines, based on 1st nibble value */
first_nibble_is_0(RAnal * anal,RAnalOp * op,ut16 code)266 static int first_nibble_is_0(RAnal* anal, RAnalOp* op, ut16 code) { //STOP
267 if (IS_BSRF (code)) {
268 /* Call 'far' subroutine Rn+PC+4 */
269 op->type = R_ANAL_OP_TYPE_UCALL;
270 op->delay = 1;
271 op->dst = anal_regrel_jump (anal, op, GET_TARGET_REG (code));
272 r_strbuf_setf (&op->esil, "1,SETD,pc,2,+,pr,=,r%d,2,+,pc,+=", GET_TARGET_REG (code));
273 } else if (IS_BRAF (code)) {
274 op->type = R_ANAL_OP_TYPE_UJMP;
275 op->dst = anal_regrel_jump (anal, op, GET_TARGET_REG (code));
276 op->eob = true;
277 op->delay = 1;
278 r_strbuf_setf (&op->esil, "1,SETD,r%d,2,+,pc,+=", GET_TARGET_REG (code));
279 } else if (IS_RTS (code)) {
280 op->type = R_ANAL_OP_TYPE_RET;
281 op->delay = 1;
282 op->eob = true;
283 r_strbuf_setf (&op->esil, "pr,pc,=");
284 } else if (IS_RTE (code)) {
285 op->type = R_ANAL_OP_TYPE_RET;
286 op->delay = 1;
287 op->eob = true;
288 //r_strbuf_setf (&op->esil, "1,SETD,r15,[4],4,+,pc,=,r15,4,+,[4],0xFFF0FFF,&,sr,=,8,r15,+=");
289 //not sure if should be added 4 to pc
290 r_strbuf_setf (&op->esil, "1,SETD,r15,[4],pc,=,r15,4,+,[4],0xFFF0FFF,&,sr,=,8,r15,+=");
291 } else if (IS_MOVB_REG_TO_R0REL (code)) { //0000nnnnmmmm0100 mov.b <REG_M>,@(R0,<REG_N>)
292 op->type = R_ANAL_OP_TYPE_STORE;
293 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
294 op->dst = anal_fill_r0_reg_ref (anal, GET_TARGET_REG (code), BYTE_SIZE);
295 r_strbuf_setf (&op->esil, "r%d,0xFF,&,r0,r%d,+,=[1]", GET_SOURCE_REG (code), GET_TARGET_REG (code));
296 } else if (IS_MOVW_REG_TO_R0REL (code)) {
297 op->type = R_ANAL_OP_TYPE_STORE;
298 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
299 op->dst = anal_fill_r0_reg_ref (anal, GET_TARGET_REG (code), WORD_SIZE);
300 r_strbuf_setf (&op->esil, "r%d,0xFFFF,&,r0,r%d,+,=[2]", GET_SOURCE_REG (code), GET_TARGET_REG (code));
301 } else if (IS_MOVL_REG_TO_R0REL (code)) {
302 op->type = R_ANAL_OP_TYPE_STORE;
303 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
304 op->dst = anal_fill_r0_reg_ref(anal, GET_TARGET_REG (code), LONG_SIZE);
305 r_strbuf_setf (&op->esil, "r%d,r0,r%d,+,=[4]", GET_SOURCE_REG (code), GET_TARGET_REG (code));
306 } else if (IS_MOVB_R0REL_TO_REG (code)) {
307 op->type = R_ANAL_OP_TYPE_LOAD;
308 op->src[0] = anal_fill_r0_reg_ref (anal, GET_SOURCE_REG (code), BYTE_SIZE);
309 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
310 r_strbuf_setf (&op->esil, "r0,r%d,+,[1],r%d,=,0x000000FF,r%d,&=,r%d,0x80,&,?{,0xFFFFFF00,r%d,|=,}", GET_SOURCE_REG (code), GET_TARGET_REG (code), GET_TARGET_REG (code), GET_TARGET_REG (code), GET_TARGET_REG (code));
311 } else if (IS_MOVW_R0REL_TO_REG (code)) {
312 op->type = R_ANAL_OP_TYPE_LOAD;
313 op->src[0] = anal_fill_r0_reg_ref (anal, GET_SOURCE_REG (code), WORD_SIZE);
314 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
315 r_strbuf_setf (&op->esil, "r0,r%d,+,[2],r%d,=,0x0000FFFF,r%d,&=,r%d,0x8000,&,?{,0xFFFF0000,r%d,|=,}", GET_SOURCE_REG (code), GET_TARGET_REG (code), GET_TARGET_REG (code), GET_TARGET_REG (code), GET_TARGET_REG (code));
316 } else if (IS_MOVL_R0REL_TO_REG (code)) {
317 op->type = R_ANAL_OP_TYPE_LOAD;
318 op->src[0] = anal_fill_r0_reg_ref (anal, GET_SOURCE_REG (code), LONG_SIZE);
319 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
320 r_strbuf_setf (&op->esil, "r0,r%d,+,[4],r%d,=", GET_SOURCE_REG (code), GET_TARGET_REG (code));
321 } else if (IS_NOP (code)) {
322 op->type = R_ANAL_OP_TYPE_NOP;
323 r_strbuf_setf (&op->esil, " ");
324 } else if (IS_CLRT (code)) {
325 op->type = R_ANAL_OP_TYPE_UNK;
326 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&=");
327 } else if (IS_SETT (code)) {
328 op->type = R_ANAL_OP_TYPE_UNK;
329 r_strbuf_setf (&op->esil, "0x1,sr,|=");
330 } else if (IS_CLRMAC (code)) {
331 op->type = R_ANAL_OP_TYPE_UNK;
332 r_strbuf_setf (&op->esil, "0,mach,=,0,macl,=");
333 } else if (IS_DIV0U (code)) {
334 op->type = R_ANAL_OP_TYPE_DIV;
335 r_strbuf_setf (&op->esil, "0xFFFFFCFE,sr,&=");
336 } else if (IS_MOVT (code)) {
337 op->type = R_ANAL_OP_TYPE_MOV;
338 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
339 r_strbuf_setf (&op->esil, "0x1,sr,&,r%d,=", GET_TARGET_REG (code));
340 } else if (IS_MULL (code)) { //multiply long
341 op->type = R_ANAL_OP_TYPE_MUL;
342 op->src[0] = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
343 op->src[1] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
344 r_strbuf_setf (&op->esil, "r%d,r%d,*,macl,=", GET_TARGET_REG (code), GET_SOURCE_REG (code));
345 } else if (IS_SLEEP (code)) {
346 op->type = R_ANAL_OP_TYPE_UNK;
347 r_strbuf_setf (&op->esil, "sleep_called,TRAP");
348 } else if (IS_STSMACH (code)) { //0000nnnn0000101_ sts MAC*,<REG_N>
349 op->type = R_ANAL_OP_TYPE_MOV;
350 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
351 r_strbuf_setf (&op->esil, "mach,r%d,=", GET_TARGET_REG (code));
352 } else if (IS_STSMACL (code)) { //0000nnnn0000101_ sts MAC*,<REG_N>
353 op->type = R_ANAL_OP_TYPE_MOV;
354 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
355 r_strbuf_setf (&op->esil, "macl,r%d,=", GET_TARGET_REG (code));
356 } else if (IS_STSLMACL (code)) {
357 op->type = R_ANAL_OP_TYPE_MOV;
358 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
359 r_strbuf_setf (&op->esil, "macl,r%d,=", GET_TARGET_REG (code));
360 } else if (IS_STCSR1 (code)) { //0000nnnn00010010 stc {sr,gbr,vbr,ssr},<REG_N>
361 op->type = R_ANAL_OP_TYPE_MOV;
362 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
363 //todo: plug in src
364 switch(GET_SOURCE_REG (code)) {
365 case 0:
366 r_strbuf_setf (&op->esil, "sr,r%d,=", GET_TARGET_REG (code));
367 break;
368 case 1:
369 r_strbuf_setf (&op->esil, "gbr,r%d,=", GET_TARGET_REG (code));
370 break;
371 case 2:
372 r_strbuf_setf (&op->esil, "vbr,r%d,=", GET_TARGET_REG (code));
373 break;
374 default:
375 r_strbuf_setf (&op->esil, "%s", "");
376 break;
377
378 }
379 } else if (IS_STSPR (code)) { //0000nnnn00101010 sts PR,<REG_N>
380 op->type = R_ANAL_OP_TYPE_MOV;
381 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
382 r_strbuf_setf (&op->esil, "pr,r%d,=", GET_TARGET_REG (code));
383 } else if (IS_MACL (code)) {
384 r_strbuf_setf (&op->esil,
385 "mach,0x80000000,&,!," //mach_old sign (0)
386 S32_EXT("r%d,[4]")"," //@Rn sign extended
387 S32_EXT("r%d,[4]")"," //@Rm sign extended
388 "*," //(1)
389 "macl,32,mach,<<,|," //macl | (mach << 32)
390 "+," //MAC+@Rm*@Rn
391 "32,"
392 S32_EXT("r%d,[4]")"," //@Rn sign extended
393 S32_EXT("r%d,[4]")"," //@Rm sign extended
394 "*,"
395 "4,r%d,+=," //Rn+=4
396 "4,r%d,+=," //Rm+=4
397 "0xffffffff00000000,&,>>,mach,=," //MACH > mach
398 "0xffffffff,&,macl,=,"
399 "0x2,sr,&,!,?{,BREAK,}," //if S==0 BREAK
400 "0x00007fff,mach,>,"
401 "0x80000000,mach,&,!,&,"
402 "?{,0x00007fff,mach,=,0xffffffff,macl,=,}," //if (mach>0x00007fff&&mach>0) mac=0x00007fffffffffff
403 "0xffff8000,mach,<,"
404 "0x80000000,mach,&,!,!,&,"
405 "?{,0xffff8000,mach,=,0x0,macl,=,}," //if (mach>0xffff8000&&mach<0) mac=0xffff800000000000
406 , GET_TARGET_REG (code), GET_SOURCE_REG (code),
407 GET_TARGET_REG (code), GET_SOURCE_REG (code),
408 GET_TARGET_REG (code), GET_SOURCE_REG (code));
409 op->type = R_ANAL_OP_TYPE_MUL;
410 }
411 return op->size;
412 }
413
414 //nibble=1; 0001nnnnmmmmi4*4 mov.l <REG_M>,@(<disp>,<REG_N>)
movl_reg_rdisp(RAnal * anal,RAnalOp * op,ut16 code)415 static int movl_reg_rdisp(RAnal* anal, RAnalOp* op, ut16 code) {
416 op->type = R_ANAL_OP_TYPE_STORE;
417 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
418 op->dst = anal_fill_reg_disp_mem (anal, GET_TARGET_REG (code), code & 0x0F, LONG_SIZE);
419 r_strbuf_setf (&op->esil, "r%d,r%d,0x%x,+,=[4]", GET_SOURCE_REG (code), GET_TARGET_REG (code), (code & 0xF) << 2);
420 return op->size;
421 }
422
first_nibble_is_2(RAnal * anal,RAnalOp * op,ut16 code)423 static int first_nibble_is_2(RAnal* anal, RAnalOp* op, ut16 code) {
424 if (IS_MOVB_REG_TO_REGREF (code)) { // 0010nnnnmmmm0000 mov.b <REG_M>,@<REG_N>
425 op->type = R_ANAL_OP_TYPE_STORE;
426 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
427 op->dst = anal_fill_reg_ref (anal, GET_TARGET_REG (code), BYTE_SIZE);
428 r_strbuf_setf (&op->esil, "r%d,r%d,=[1]", GET_SOURCE_REG (code), GET_TARGET_REG (code));
429 } else if (IS_MOVW_REG_TO_REGREF (code)) {
430 op->type = R_ANAL_OP_TYPE_STORE;
431 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
432 op->dst = anal_fill_reg_ref (anal, GET_TARGET_REG (code), WORD_SIZE);
433 r_strbuf_setf (&op->esil, "r%d,r%d,=[2]", GET_SOURCE_REG (code) & 0xFF, GET_TARGET_REG (code));
434 } else if (IS_MOVL_REG_TO_REGREF (code)) {
435 op->type = R_ANAL_OP_TYPE_STORE;
436 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
437 op->dst = anal_fill_reg_ref (anal, GET_TARGET_REG (code), LONG_SIZE);
438 r_strbuf_setf (&op->esil, "r%d,r%d,=[4]", GET_SOURCE_REG (code) & 0xFF, GET_TARGET_REG (code));
439 } else if (IS_AND_REGS (code)) {
440 op->type = R_ANAL_OP_TYPE_AND;
441 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
442 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
443 r_strbuf_setf (&op->esil, "r%d,r%d,&=", GET_SOURCE_REG (code), GET_TARGET_REG (code));
444 } else if (IS_XOR_REGS (code)) {
445 op->type = R_ANAL_OP_TYPE_XOR;
446 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
447 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
448 r_strbuf_setf (&op->esil, "r%d,r%d,^=", GET_SOURCE_REG (code), GET_TARGET_REG (code));
449 } else if (IS_OR_REGS (code)) {
450 op->type = R_ANAL_OP_TYPE_OR;
451 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
452 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
453 r_strbuf_setf (&op->esil, "r%d,r%d,|=", GET_SOURCE_REG (code), GET_TARGET_REG (code));
454 } else if (IS_PUSHB (code)) {
455 op->type = R_ANAL_OP_TYPE_PUSH;
456 r_strbuf_setf (&op->esil, "1,r%d,-=,r%d,r%d,=[1]", GET_TARGET_REG (code), GET_SOURCE_REG (code), GET_TARGET_REG (code));
457 } else if (IS_PUSHW (code)) {
458 op->type = R_ANAL_OP_TYPE_PUSH;
459 r_strbuf_setf (&op->esil, "2,r%d,-=,r%d,r%d,=[2]", GET_TARGET_REG (code), GET_SOURCE_REG (code), GET_TARGET_REG (code));
460 } else if (IS_PUSHL (code)) {
461 op->type = R_ANAL_OP_TYPE_PUSH;
462 r_strbuf_setf (&op->esil, "4,r%d,-=,r%d,r%d,=[4]", GET_TARGET_REG (code), GET_SOURCE_REG (code), GET_TARGET_REG (code));
463 } else if (IS_TSTRR (code)) {
464 op->type = R_ANAL_OP_TYPE_ACMP;
465 r_strbuf_setf (&op->esil, "1,sr,|=,r%d,r%d,&,?{,0xFFFFFFFE,sr,&=,}", GET_SOURCE_REG (code), GET_TARGET_REG (code));
466 } else if (IS_CMPSTR (code)) { //0010nnnnmmmm1100 cmp/str <REG_M>,<REG_N>
467 op->type = R_ANAL_OP_TYPE_ACMP; //maybe not?
468 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
469 op->src[1] = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
470 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&=,24,r%d,r%d,^,>>,0xFF,&,!,?{,1,sr,|=,},16,r%d,r%d,^,>>,0xFF,&,!,?{,1,sr,|=,},8,r%d,r%d,^,>>,0xFF,&,!,?{,1,sr,|=,},r%d,r%d,^,0xFF,&,!,?{,1,sr,|=,}", GET_SOURCE_REG (code), GET_TARGET_REG (code), GET_SOURCE_REG (code), GET_TARGET_REG (code), GET_SOURCE_REG (code), GET_TARGET_REG (code), GET_SOURCE_REG (code), GET_TARGET_REG (code));
471 } else if (IS_XTRCT (code)) { //0010nnnnmmmm1101 xtrct <REG_M>,<REG_N>
472 op->type = R_ANAL_OP_TYPE_MOV;
473 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
474 op->src[1] = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
475 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
476 r_strbuf_setf (&op->esil, "16,r%d,0xFFFF,&,<<,16,r%d,0xFFFF0000,&,>>,|,r%d,=", GET_SOURCE_REG (code), GET_TARGET_REG (code), GET_TARGET_REG (code));
477 } else if (IS_DIV0S (code)) {
478 op->type = R_ANAL_OP_TYPE_DIV;
479 r_strbuf_setf (&op->esil, "0xFFFFFCFE,sr,&=,r%d,0x80000000,&,?{,0x200,sr,|=,},r%d,0x80000000,&,?{,0x100,sr,|=,},sr,1,sr,<<,^,0x200,&,?{,1,sr,|=,}", GET_SOURCE_REG (code), GET_TARGET_REG (code));
480 } else if (IS_MULUW (code)) {
481 op->type = R_ANAL_OP_TYPE_MUL;
482 op->src[0] = anal_fill_ai_rg(anal, GET_SOURCE_REG (code));
483 op->src[1] = anal_fill_ai_rg(anal, GET_TARGET_REG (code));
484 r_strbuf_setf (&op->esil, "r%d,0xFFFF,&,r%d,0xFFFF,&,*,macl,=", GET_SOURCE_REG (code), GET_TARGET_REG (code));
485 } else if (IS_MULSW (code)) { //0010nnnnmmmm111_ mul{s,u}.w <REG_M>,<REG_N>
486 op->type = R_ANAL_OP_TYPE_MUL;
487 op->src[0] = anal_fill_ai_rg(anal, GET_SOURCE_REG (code));
488 op->src[1] = anal_fill_ai_rg(anal, GET_TARGET_REG (code));
489 r_strbuf_setf (&op->esil, S16_EXT("r%d") "," S16_EXT("r%d") ",*,macl,=", GET_SOURCE_REG (code), GET_TARGET_REG (code));
490 }
491
492 return op->size;
493 }
494
495
first_nibble_is_3(RAnal * anal,RAnalOp * op,ut16 code)496 static int first_nibble_is_3(RAnal* anal, RAnalOp* op, ut16 code) {
497 //TODO Handle carry/overflow , CMP/xx?
498 if (IS_ADD (code)) {
499 op->type = R_ANAL_OP_TYPE_ADD;
500 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
501 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
502 r_strbuf_setf (&op->esil, "r%d,r%d,+=", GET_SOURCE_REG (code), GET_TARGET_REG (code));
503 } else if (IS_ADDC (code)) {
504 op->type = R_ANAL_OP_TYPE_ADD;
505 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
506 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
507 r_strbuf_setf (&op->esil, "sr,0x1,&,0xFFFFFFFE,sr,&=,r%d,+=,31,$c,sr,|,sr,:=,r%d,r%d,+=,31,$c,sr,|,sr,:=", GET_TARGET_REG (code), GET_SOURCE_REG (code), GET_TARGET_REG (code));
508 } else if (IS_ADDV (code)) {
509 op->type = R_ANAL_OP_TYPE_ADD;
510 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
511 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
512 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&=,r%d,r%d,+=,31,$o,sr,|=", GET_SOURCE_REG (code), GET_TARGET_REG (code));
513 } else if (IS_SUB (code)) {
514 op->type = R_ANAL_OP_TYPE_SUB;
515 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
516 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
517 r_strbuf_setf (&op->esil, "r%d,r%d,-=", GET_SOURCE_REG (code), GET_TARGET_REG (code));
518 } else if (IS_SUBC (code)) {
519 op->type = R_ANAL_OP_TYPE_SUB;
520 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
521 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
522 r_strbuf_setf (&op->esil, "sr,1,&," CLR_T ",r%d,-=,31,$b,sr,|,sr,:=,r%d,r%d,-=,31,$b,sr,|,sr,:=", GET_TARGET_REG (code), GET_SOURCE_REG (code), GET_TARGET_REG (code));
523 } else if (IS_SUBV (code)) {
524 op->type = R_ANAL_OP_TYPE_SUB;
525 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
526 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
527 r_strbuf_setf (&op->esil, CLR_T ",r%d,r%d,-=,31,$o,sr,|,sr,:=", GET_SOURCE_REG(code), GET_TARGET_REG (code));
528 } else if (IS_CMPEQ (code)) {
529 op->type = R_ANAL_OP_TYPE_CMP;
530 op->src[0] = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
531 op->src[1] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
532 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&,r%d,r%d,^,!,|,sr,=", GET_SOURCE_REG (code), GET_TARGET_REG (code));
533 } else if (IS_CMPGE (code)) {
534 op->type = R_ANAL_OP_TYPE_CMP;
535 op->src[0] = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
536 op->src[1] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
537 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&=,r%d,r%d,>=,?{,0x1,sr,|=,}", GET_SOURCE_REG (code), GET_TARGET_REG (code));
538 } else if (IS_CMPGT (code)) {
539 op->type = R_ANAL_OP_TYPE_CMP;
540 op->src[0] = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
541 op->src[1] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
542 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&=,r%d,r%d,>,?{,0x1,sr,|=,}", GET_SOURCE_REG (code), GET_TARGET_REG (code));
543 } else if (IS_CMPHI (code)) {
544 op->type = R_ANAL_OP_TYPE_CMP;
545 op->src[0] = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
546 op->src[1] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
547 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&=,r%d,0x100000000,+,r%d,0x100000000,+,>,?{,0x1,sr,|=,}", GET_SOURCE_REG (code), GET_TARGET_REG (code));
548 } else if (IS_CMPHS (code)) {
549 op->type = R_ANAL_OP_TYPE_CMP;
550 op->src[0] = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
551 op->src[1] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
552 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&=,r%d,0x100000000,+,r%d,0x100000000,+,>=,?{,0x1,sr,|=,}", GET_SOURCE_REG (code), GET_TARGET_REG (code));
553 } else if (IS_DIV1 (code)) {
554 op->type = R_ANAL_OP_TYPE_DIV;
555 op->src[0] = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
556 op->src[1] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
557 r_strbuf_setf (&op->esil,
558 "1,sr,>>,sr,^,0x80,&," //old_Q^M
559 "0xFFFFFF7F,sr,&=,"
560 "1,r%d,DUP,0x80000000,&,?{,0x80,sr,|=,},<<,sr,0x1,&,|,r%d,=," //shift Q<-Rn<-T
561 "DUP,!,!,?{,"
562 "r%d,NUM,"//Rn_old (before subtract)
563 "r%d,r%d,+=,"
564 "r%d,<,}{," //tmp0
565 "r%d,NUM,"//Rn_old (before subtract)
566 "r%d,r%d,-=,"
567 "r%d,>,}," //tmp0
568 "sr,0x80,&,!,!,^," //Q^tmp0
569 "sr,0x100,&,?{,!,},"//if (M) !(Q^tmp0)
570 "0xFFFFFF7F,sr,&=," //Q==0
571 "?{,0x80,sr,|=,}," //Q=!(Q^tmp0)or(Q^tmp0)
572 CLR_T","
573 "1,sr,>>,sr,^,0x80,&,!,sr,|=", // sr=!Q^M
574 GET_TARGET_REG (code), GET_TARGET_REG (code),
575 GET_TARGET_REG (code),
576 GET_SOURCE_REG(code), GET_TARGET_REG (code),
577 GET_TARGET_REG (code),
578 GET_TARGET_REG (code),
579 GET_SOURCE_REG(code), GET_TARGET_REG (code),
580 GET_TARGET_REG (code));
581 } else if (IS_DMULU (code)) {
582 op->type = R_ANAL_OP_TYPE_MUL;
583 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
584 op->src[1] = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
585 r_strbuf_setf (&op->esil, "32,r%d,r%d,*,DUP,0xFFFFFFFF,&,macl,=,>>,mach,=", GET_SOURCE_REG (code), GET_TARGET_REG (code));
586 } else if (IS_DMULS (code)) {
587 op->type = R_ANAL_OP_TYPE_MUL;
588 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
589 op->src[1] = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
590 r_strbuf_setf (&op->esil, "32,r%d,r%d,0x80000000,&,?{,0xFFFFFFFF00000000,+,},r%d,r%d,0x80000000,&,?{,0xFFFFFFFF00000000,+,},*,DUP,0xFFFFFFFF,&,macl,=,>>,mach,=", GET_SOURCE_REG (code), GET_SOURCE_REG (code), GET_TARGET_REG (code), GET_TARGET_REG (code));
591 }
592 return op->size;
593 }
594
595
596
first_nibble_is_4(RAnal * anal,RAnalOp * op,ut16 code)597 static int first_nibble_is_4(RAnal* anal, RAnalOp* op, ut16 code) {
598 switch(code & 0xF0FF) { //TODO: change to common } else if construction
599 case 0x4020: //shal
600 op->type = R_ANAL_OP_TYPE_SAL;
601 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&=,r%d,0x80000000,&,?{,0x1,sr,|=,},1,r%d,<<=", GET_TARGET_REG (code), GET_TARGET_REG (code));
602 break;
603 case 0x4021: //shar
604 op->type = R_ANAL_OP_TYPE_SAR;
605 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&=,r%d,0x1,&,?{,0x1,sr,|=,},0,r%d,0x80000000,&,?{,0x80000000,+,},1,r%d,>>=,r%d,|=", GET_TARGET_REG (code), GET_TARGET_REG (code), GET_TARGET_REG (code), GET_TARGET_REG (code));
606 break;
607 case 0x4000: //shll
608 op->type = R_ANAL_OP_TYPE_SHL;
609 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&=,r%d,0x80000000,&,?{,0x1,sr,|=,},1,r%d,<<=", GET_TARGET_REG (code), GET_TARGET_REG (code));
610 break;
611 case 0x4008: //shll2
612 op->type = R_ANAL_OP_TYPE_SHL;
613 r_strbuf_setf (&op->esil, "2,r%d,<<=", GET_TARGET_REG (code));
614 break;
615 case 0x4018: //shll8
616 op->type = R_ANAL_OP_TYPE_SHL;
617 r_strbuf_setf (&op->esil, "8,r%d,<<=", GET_TARGET_REG (code));
618 break;
619 case 0x4028: //shll16
620 op->type = R_ANAL_OP_TYPE_SHL;
621 r_strbuf_setf (&op->esil, "16,r%d,<<=", GET_TARGET_REG (code));
622 break;
623 case 0x4001: //shlr
624 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&=,r%d,0x1,&,?{,0x1,sr,|=,},1,r%d,>>=", GET_TARGET_REG (code), GET_TARGET_REG (code));
625 op->type = R_ANAL_OP_TYPE_SHR;
626 break;
627 case 0x4009: //shlr2
628 r_strbuf_setf (&op->esil, "2,r%d,>>=", GET_TARGET_REG (code));
629 op->type = R_ANAL_OP_TYPE_SHR;
630 break;
631 case 0x4019: //shlr8
632 r_strbuf_setf (&op->esil, "8,r%d,>>=", GET_TARGET_REG (code));
633 op->type = R_ANAL_OP_TYPE_SHR;
634 break;
635 case 0x4029: //shlr16
636 r_strbuf_setf (&op->esil, "16,r%d,>>=", GET_TARGET_REG (code));
637 op->type = R_ANAL_OP_TYPE_SHR;
638 break;
639 default:
640 break;
641 }
642
643 if (IS_JSR (code)) {
644 // op->type = R_ANAL_OP_TYPE_UCALL; //call to reg
645 op->type = R_ANAL_OP_TYPE_RCALL; //call to reg
646 op->delay = 1;
647 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
648 r_strbuf_setf (&op->esil, "1,SETD,pc,2,+,pr,=,r%d,pc,=", GET_TARGET_REG (code));
649 } else if (IS_JMP (code)) {
650 op->type = R_ANAL_OP_TYPE_UJMP; //jmp to reg
651 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
652 op->delay = 1;
653 op->eob = true;
654 r_strbuf_setf (&op->esil, "1,SETD,r%d,pc,=", GET_TARGET_REG (code));
655 } else if (IS_CMPPL (code)) {
656 op->type = R_ANAL_OP_TYPE_CMP;
657 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&=,0,r%d,>,?{,0x1,sr,|=,}", GET_TARGET_REG (code));
658 } else if (IS_CMPPZ (code)) {
659 op->type = R_ANAL_OP_TYPE_CMP;
660 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&=,0,r%d,>=,?{,0x1,sr,|=,}", GET_TARGET_REG (code));
661 } else if (IS_LDCLSR (code)) {
662 op->type = R_ANAL_OP_TYPE_POP;
663 r_strbuf_setf (&op->esil, "r%d,[4],0x0FFF0FFF,&,sr,=,4,r%d,+=", GET_TARGET_REG (code), GET_TARGET_REG (code));
664 } else if (IS_LDCLSRGBR (code)) {
665 op->type = R_ANAL_OP_TYPE_POP;
666 r_strbuf_setf (&op->esil, "r%d,[4],gbr,=,4,r%d,+=", GET_TARGET_REG (code), GET_TARGET_REG (code));
667 } else if (IS_LDCLSRVBR (code)) {
668 op->type = R_ANAL_OP_TYPE_POP;
669 r_strbuf_setf (&op->esil, "r%d,[4],vbr,=,4,r%d,+=", GET_TARGET_REG (code), GET_TARGET_REG (code));
670 //todo ssr?
671 } else if (IS_LDSLMACH (code)) {
672 op->type = R_ANAL_OP_TYPE_POP;
673 r_strbuf_setf (&op->esil, "r%d,[4],mach,=,4,r%d,+=", GET_TARGET_REG (code), GET_TARGET_REG (code));
674 } else if (IS_LDSLMACL (code)) {
675 op->type = R_ANAL_OP_TYPE_POP;
676 r_strbuf_setf (&op->esil, "r%d,[4],macl,=,4,r%d,+=", GET_TARGET_REG (code), GET_TARGET_REG (code));
677 } else if (IS_LDSLPR (code)) {
678 op->type = R_ANAL_OP_TYPE_POP;
679 r_strbuf_setf (&op->esil, "r%d,[4],pr,=,4,r%d,+=", GET_TARGET_REG (code), GET_TARGET_REG (code));
680 } else if (IS_LDCSR (code)) {
681 r_strbuf_setf (&op->esil, "r%d,0x0FFF0FFF,&,sr,=", GET_TARGET_REG (code));
682 op->type = R_ANAL_OP_TYPE_MOV;
683 } else if (IS_LDCGBR (code)) {
684 r_strbuf_setf (&op->esil, "r%d,gbr,=", GET_TARGET_REG (code));
685 op->type = R_ANAL_OP_TYPE_MOV;
686 } else if (IS_LDCVBR (code)) {
687 r_strbuf_setf (&op->esil, "r%d,vbr,=", GET_TARGET_REG (code));
688 op->type = R_ANAL_OP_TYPE_MOV;
689 } else if (IS_LDSMACH (code)) {
690 r_strbuf_setf (&op->esil, "r%d,mach,=", GET_TARGET_REG (code));
691 op->type = R_ANAL_OP_TYPE_MOV;
692 } else if (IS_LDSMACL (code)) {
693 r_strbuf_setf (&op->esil, "r%d,macl,=", GET_TARGET_REG (code));
694 op->type = R_ANAL_OP_TYPE_MOV;
695 } else if (IS_LDSPR (code)) {
696 r_strbuf_setf (&op->esil, "r%d,pr,=", GET_TARGET_REG (code));
697 op->type = R_ANAL_OP_TYPE_MOV;
698 } else if (IS_ROTR (code)) {
699 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&=,r%d,0x1,&,sr,|=,0x1,r%d,>>>,r%d,=", GET_TARGET_REG (code), GET_TARGET_REG (code), GET_TARGET_REG (code));
700 op->type = (code & 1)? R_ANAL_OP_TYPE_ROR:R_ANAL_OP_TYPE_ROL;
701 } else if (IS_ROTL (code)) {
702 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&=,0x1,r%d,<<<,r%d,=,r%d,0x1,&,sr,|=", GET_TARGET_REG (code), GET_TARGET_REG (code), GET_TARGET_REG (code));
703 op->type = (code & 1)? R_ANAL_OP_TYPE_ROR:R_ANAL_OP_TYPE_ROL;
704 } else if (IS_ROTCR (code)) {
705 r_strbuf_setf (&op->esil, "0,sr,0x1,&,?{,0x80000000,},0xFFFFFFFE,sr,&=,r%d,1,&,sr,|=,1,r%d,>>=,r%d,|=", GET_TARGET_REG (code), GET_TARGET_REG (code), GET_TARGET_REG (code));
706 op->type = (code & 1)? R_ANAL_OP_TYPE_ROR:R_ANAL_OP_TYPE_ROL;
707 } else if (IS_ROTCL (code)) {
708 r_strbuf_setf (&op->esil, "sr,0x1,&,0xFFFFFFFE,sr,&=,r%d,0x80000000,&,?{,1,sr,|=,},1,r%d,<<=,r%d,|=", GET_TARGET_REG (code), GET_TARGET_REG (code), GET_TARGET_REG (code));
709 op->type = (code & 1)? R_ANAL_OP_TYPE_ROR:R_ANAL_OP_TYPE_ROL;
710 } else if (IS_STCLSR (code)) {
711 r_strbuf_setf (&op->esil, "4,r%d,-=,sr,r%d,=[4]", GET_TARGET_REG (code), GET_TARGET_REG (code));
712 op->type = R_ANAL_OP_TYPE_PUSH;
713 } else if (IS_STCLGBR (code)) {
714 r_strbuf_setf (&op->esil, "4,r%d,-=,gbr,r%d,=[4]", GET_TARGET_REG (code), GET_TARGET_REG (code));
715 op->type = R_ANAL_OP_TYPE_PUSH;
716 } else if (IS_STCLVBR (code)) {
717 r_strbuf_setf (&op->esil, "4,r%d,-=,vbr,r%d,=[4]", GET_TARGET_REG (code), GET_TARGET_REG (code));
718 op->type = R_ANAL_OP_TYPE_PUSH;
719 } else if (IS_STSLMACL (code)) {
720 r_strbuf_setf (&op->esil, "4,r%d,-=,macl,r%d,=[4]", GET_TARGET_REG (code), GET_TARGET_REG (code));
721 op->type = R_ANAL_OP_TYPE_PUSH;
722 } else if (IS_STSLMACH (code)) {
723 r_strbuf_setf (&op->esil, "4,r%d,-=,mach,r%d,=[4]", GET_TARGET_REG (code), GET_TARGET_REG (code));
724 op->type = R_ANAL_OP_TYPE_PUSH;
725 } else if (IS_STSLPR (code)) {
726 op->type = R_ANAL_OP_TYPE_PUSH;
727 r_strbuf_setf (&op->esil, "4,r%d,-=,pr,r%d,=[4]", GET_TARGET_REG (code), GET_TARGET_REG (code));
728 } else if (IS_TASB (code)) {
729 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&=,r%d,[1],!,?{,0x80,r%d,=[1],1,sr,|=,}", GET_TARGET_REG (code), GET_TARGET_REG (code));
730 op->type = R_ANAL_OP_TYPE_UNK;
731 } else if (IS_DT (code)) {
732 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&=,1,r%d,-=,$z,sr,|,sr,:=", GET_TARGET_REG (code));
733 op->type = R_ANAL_OP_TYPE_UNK;
734 } else if (IS_MACW(code)){
735 r_strbuf_setf (&op->esil,
736 "0x2,sr,&,!,?{," //if S==0
737 S16_EXT("r%d,[2]")"," //@Rn sign extended
738 S16_EXT("r%d,[2]")"," //@Rm sign extended
739 "*,"
740 "macl,32,mach,<<,|," //macl | (mach << 32)
741 "+," //MAC+@Rm*@Rn
742 "32,"
743 S16_EXT("r%d,[2]")"," //@Rn sign extended
744 S16_EXT("r%d,[2]")"," //@Rm sign extended
745 "*,"
746 "0xffffffff00000000,&,>>,mach,=," //MACH > mach
747 "0xffffffff,&,macl,=,"
748 "}{," //if S==1
749 S16_EXT("r%d,[2]")"," //@Rn sign extended
750 S16_EXT("r%d,[2]")"," //@Rm sign extended
751 "*"
752 "macl,+=," //macl+(@Rm+@Rm)
753 "31,$o,?{," //if overflow
754 "macl,0x80000000,&,?{,"
755 "0x7fffffff,macl,=,"
756 "}{,"
757 "0x80000000,macl,=,"
758 "},"
759 "},"
760 "},"
761 "2,r%d,+=," //Rn+=2
762 "2,r%d,+=,", //Rm+=2
763 GET_TARGET_REG (code), GET_SOURCE_REG (code),
764 GET_TARGET_REG (code), GET_SOURCE_REG (code),
765 GET_TARGET_REG (code), GET_SOURCE_REG (code),
766 GET_TARGET_REG (code), GET_SOURCE_REG (code));
767 op->type = R_ANAL_OP_TYPE_MUL;
768 }
769 return op->size;
770 }
771
772 //nibble=5; 0101nnnnmmmmi4*4 mov.l @(<disp>,<REG_M>),<REG_N>
movl_rdisp_reg(RAnal * anal,RAnalOp * op,ut16 code)773 static int movl_rdisp_reg(RAnal* anal, RAnalOp* op, ut16 code) {
774 op->type = R_ANAL_OP_TYPE_LOAD;
775 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
776 op->src[0] = anal_fill_reg_disp_mem (anal, GET_SOURCE_REG (code), code & 0x0F, LONG_SIZE);
777 r_strbuf_setf (&op->esil, "r%d,0x%x,+,[4],r%d,=", GET_SOURCE_REG (code), (code&0xF) * 4, GET_TARGET_REG (code));
778 return op->size;
779 }
780
781
first_nibble_is_6(RAnal * anal,RAnalOp * op,ut16 code)782 static int first_nibble_is_6(RAnal* anal, RAnalOp* op, ut16 code) {
783 if (IS_MOV_REGS (code)) {
784 op->type = R_ANAL_OP_TYPE_MOV;
785 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
786 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
787 r_strbuf_setf (&op->esil, "r%d,r%d,=", GET_SOURCE_REG (code), GET_TARGET_REG (code));
788 } else if (IS_MOVB_REGREF_TO_REG (code)) {
789 op->type = R_ANAL_OP_TYPE_LOAD;
790 op->src[0] = anal_fill_reg_ref (anal, GET_SOURCE_REG (code), BYTE_SIZE);
791 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
792 r_strbuf_setf (&op->esil, "0x000000FF,r%d,&=,r%d,[1],DUP,0x80,&,?{,0xFFFFFF00,|=,},r%d,=", GET_TARGET_REG (code), GET_SOURCE_REG (code), GET_TARGET_REG (code));
793 } else if (IS_MOVW_REGREF_TO_REG (code)) {
794 op->type = R_ANAL_OP_TYPE_LOAD;
795 op->src[0] = anal_fill_reg_ref (anal, GET_SOURCE_REG (code), WORD_SIZE);
796 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
797 r_strbuf_setf (&op->esil, "0x0000FFFF,r%d,&=,r%d,[2],DUP,0x8000,&,?{,0xFFFF0000,|=,},r%d,=", GET_TARGET_REG (code), GET_SOURCE_REG (code), GET_TARGET_REG (code));
798 } else if (IS_MOVL_REGREF_TO_REG (code)) {
799 op->type = R_ANAL_OP_TYPE_LOAD;
800 op->src[0] = anal_fill_reg_ref (anal, GET_SOURCE_REG (code), LONG_SIZE);
801 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
802 r_strbuf_setf (&op->esil, "r%d,[4],r%d,=", GET_SOURCE_REG (code), GET_TARGET_REG (code));
803 } else if (IS_EXT (code)) {
804 //ext{s,u}.{b,w} instructs. todo : more detail ?
805 op->type = R_ANAL_OP_TYPE_MOV;
806 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
807 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
808 switch(code & 0xF) {
809 case 0xC: //EXTU.B
810 r_strbuf_setf (&op->esil, "r%d,0xFF,&,r%d,=", GET_SOURCE_REG (code), GET_TARGET_REG (code));
811 break;
812 case 0xD: //EXTU.W
813 r_strbuf_setf (&op->esil, "r%d,0xFFFF,&,r%d,=", GET_SOURCE_REG (code), GET_TARGET_REG (code));
814 break;
815 case 0xE: //EXTS.B
816 r_strbuf_setf (&op->esil, "r%d,0xFF,&,DUP,0x80,&,?{,0xFFFFFF00,|,},r%d,=", GET_SOURCE_REG (code), GET_TARGET_REG (code));
817 break;
818 case 0xF: //EXTS.W
819 r_strbuf_setf (&op->esil, "r%d,0xFFFF,&,DUP,0x8000,&,?{,0xFFFF0000,|,},r%d,=", GET_SOURCE_REG (code), GET_TARGET_REG (code));
820 break;
821 default:
822 r_strbuf_setf (&op->esil, "TODO,NOT IMPLEMENTED");
823 break;
824 }
825 } else if (IS_MOVB_POP (code)) {
826 op->type = R_ANAL_OP_TYPE_POP;
827 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
828 r_strbuf_setf (&op->esil, "r%d,[1],DUP,0x80,&,?{,0xFFFFFF00,|,},r%d,=,1,r%d,+=", GET_SOURCE_REG (code), GET_TARGET_REG (code), GET_SOURCE_REG (code));
829 } else if (IS_MOVW_POP (code)) {
830 op->type = R_ANAL_OP_TYPE_POP;
831 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
832 r_strbuf_setf (&op->esil, "r%d,[2],DUP,0x8000,&,?{,0xFFFF0000,|,},r%d,=,2,r%d,+=", GET_SOURCE_REG (code), GET_TARGET_REG (code), GET_SOURCE_REG (code));
833 } else if (IS_MOVL_POP (code)) {
834 op->type = R_ANAL_OP_TYPE_POP;
835 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
836 r_strbuf_setf (&op->esil, "r%d,[4],r%d,=,4,r%d,+=", GET_SOURCE_REG (code), GET_TARGET_REG (code), GET_SOURCE_REG (code));
837 } else if (IS_NEG (code)) {
838 //todo: neg and negc details
839 op->type = R_ANAL_OP_TYPE_UNK;
840 r_strbuf_setf (&op->esil, "r%d,0,-,r%d,=", GET_SOURCE_REG (code), GET_TARGET_REG (code));
841 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
842 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
843 } else if (IS_NEGC (code)) {
844 op->type = R_ANAL_OP_TYPE_UNK;
845 r_strbuf_setf (&op->esil, "1,sr,&,0xFFFFFFFE,sr,&=,r%d,+,0,-,31,$b,sr,|,sr,=,r%d,=", GET_SOURCE_REG (code), GET_TARGET_REG (code));
846 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
847 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
848 } else if (IS_NOT (code)) {
849 //todo : details?
850 r_strbuf_setf (&op->esil, "0xFFFFFFFF,r%d,^,r%d,=", GET_SOURCE_REG (code), GET_TARGET_REG (code));
851 op->type = R_ANAL_OP_TYPE_NOT;
852 op->src[0] = anal_fill_ai_rg (anal, GET_SOURCE_REG (code));
853 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
854 } else if (IS_SWAPB (code)) {
855 r_strbuf_setf (&op->esil, "r%d,0xFFFF0000,&,8,r%d,0xFF,&,<<,|,8,r%d,0xFF00,&,>>,|,r%d,=", GET_SOURCE_REG (code), GET_SOURCE_REG (code), GET_SOURCE_REG (code), GET_TARGET_REG (code));
856 op->type = R_ANAL_OP_TYPE_MOV;
857 //todo : details
858 } else if (IS_SWAPW (code)) {
859 r_strbuf_setf (&op->esil, "16,r%d,0xFFFF,&,<<,16,r%d,0xFFFF0000,&,>>,|,r%d,=", GET_SOURCE_REG (code), GET_SOURCE_REG (code), GET_TARGET_REG (code));
860 op->type = R_ANAL_OP_TYPE_MOV;
861 }
862 return op->size;
863 }
864
865
866 //nibble=7; 0111nnnni8*1.... add #<imm>,<REG_N>
add_imm(RAnal * anal,RAnalOp * op,ut16 code)867 static int add_imm(RAnal* anal, RAnalOp* op, ut16 code) {
868 op->type = R_ANAL_OP_TYPE_ADD;
869 op->src[0] = anal_fill_im (anal, (st8)(code & 0xFF)); //Casting to (st8) forces sign-extension.
870 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
871 r_strbuf_setf (&op->esil, "0x%x,DUP,0x80,&,?{,0xFFFFFF00,|,},r%d,+=", code & 0xFF, GET_TARGET_REG (code));
872 return op->size;
873 }
874
first_nibble_is_8(RAnal * anal,RAnalOp * op,ut16 code)875 static int first_nibble_is_8(RAnal* anal, RAnalOp* op, ut16 code) {
876 if (IS_BT_OR_BF (code)) {
877 op->type = R_ANAL_OP_TYPE_CJMP; //Jump if true or jump if false insns
878 op->jump = disarm_8bit_offset (op->addr, GET_BTF_OFFSET (code));
879 op->fail = op->addr + 2 ;
880 op->eob = true;
881 if (IS_BT (code)) {
882 r_strbuf_setf (&op->esil, "sr,1,&,?{,0x%" PFMT64x ",pc,=,}", op->jump);
883 } else if (IS_BTS (code)) {
884 r_strbuf_setf (&op->esil, "1,SETD,sr,1,&,?{,0x%" PFMT64x ",pc,=,}", op->jump);
885 op->delay = 1; //Only /S versions have a delay slot
886 } else if (IS_BFS (code)) {
887 r_strbuf_setf (&op->esil, "1,SETD,sr,1,&,!,?{,0x%" PFMT64x ",pc,=,}",op->jump);
888 op->delay = 1; //Only /S versions have a delay slot
889 } else if (IS_BF (code)) {
890 r_strbuf_setf (&op->esil, "sr,1,&,!,?{,0x%" PFMT64x ",pc,=,}", op->jump);
891 }
892 } else if (IS_MOVB_REGDISP_R0 (code)) {
893 // 10000100mmmmi4*1 mov.b @(<disp>,<REG_M>),R0
894 op->type = R_ANAL_OP_TYPE_LOAD;
895 op->dst = anal_fill_ai_rg (anal, 0);
896 op->src[0] = anal_fill_reg_disp_mem (anal, GET_SOURCE_REG (code), code & 0x0F, BYTE_SIZE);
897 r_strbuf_setf (&op->esil, "r%d,0x%x,+,[1],DUP,0x80,&,?{,0xFFFFFF00,|,},r0,=", GET_SOURCE_REG (code), code & 0xF);
898 } else if (IS_MOVW_REGDISP_R0 (code)) {
899 // 10000101mmmmi4*2 mov.w @(<disp>,<REG_M>),R0
900 op->type = R_ANAL_OP_TYPE_LOAD;
901 op->dst = anal_fill_ai_rg (anal, 0);
902 op->src[0] = anal_fill_reg_disp_mem (anal, GET_SOURCE_REG (code), code & 0x0F, WORD_SIZE);
903 r_strbuf_setf (&op->esil, "r%d,0x%x,+,[2],DUP,0x8000,&,?{,0xFFFF0000,|,},r0,=", GET_SOURCE_REG (code), (code & 0xF) * 2);
904 } else if (IS_CMPIMM (code)) {
905 op->type = R_ANAL_OP_TYPE_CMP;
906 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&=,0x%x,DUP,0x80,&,?{,0xFFFFFF00,|,},r0,==,$z,sr,|,sr,:=", code & 0xFF);
907 } else if (IS_MOVB_R0_REGDISP (code)) {
908 /* 10000000mmmmi4*1 mov.b R0,@(<disp>,<REG_M>)*/
909 op->type = R_ANAL_OP_TYPE_STORE;
910 op->src[0] = anal_fill_ai_rg (anal, 0);
911 op->dst = anal_fill_reg_disp_mem (anal, GET_SOURCE_REG (code), code & 0x0F, BYTE_SIZE);
912 r_strbuf_setf (&op->esil, "r0,0xFF,&,0x%x,r%d,+,=[1]", code & 0xF, GET_SOURCE_REG (code));
913 } else if (IS_MOVW_R0_REGDISP (code)) {
914 // 10000001mmmmi4*2 mov.w R0,@(<disp>,<REG_M>))
915 op->type = R_ANAL_OP_TYPE_STORE;
916 op->src[0] = anal_fill_ai_rg (anal, 0);
917 op->dst = anal_fill_reg_disp_mem (anal, GET_SOURCE_REG (code), code & 0x0F, WORD_SIZE);
918 r_strbuf_setf (&op->esil, "r0,0xFFFF,&,0x%x,r%d,+,=[2]", (code & 0xF) * 2, GET_SOURCE_REG (code));
919 }
920 return op->size;
921 }
922
923 //nibble=9; 1001nnnni8p2.... mov.w @(<disp>,PC),<REG_N>
movw_pcdisp_reg(RAnal * anal,RAnalOp * op,ut16 code)924 static int movw_pcdisp_reg(RAnal* anal, RAnalOp* op, ut16 code) {
925 op->type = R_ANAL_OP_TYPE_LOAD;
926 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
927 op->src[0] = r_anal_value_new ();
928 op->src[0]->base = (code & 0xFF) * 2+op->addr + 4;
929 op->src[0]->memref=1;
930 r_strbuf_setf (&op->esil, "0x%" PFMT64x ",[2],r%d,=,r%d,0x8000,&,?{,0xFFFF0000,r%d,|=,}", op->src[0]->base, GET_TARGET_REG (code), GET_TARGET_REG (code), GET_TARGET_REG (code));
931 return op->size;
932 }
933
934 //nibble=A; 1010i12......... bra <bdisp12>
bra(RAnal * anal,RAnalOp * op,ut16 code)935 static int bra(RAnal* anal, RAnalOp* op, ut16 code) {
936 /* Unconditional branch, relative to PC */
937 op->type = R_ANAL_OP_TYPE_JMP;
938 op->delay = 1;
939 op->jump = disarm_12bit_offset (op, GET_BRA_OFFSET (code));
940 op->eob = true;
941 r_strbuf_setf (&op->esil, "1,SETD,0x%" PFMT64x ",pc,=", op->jump);
942 return op->size;
943 }
944
945 //nibble=B; 1011i12......... bsr <bdisp12>
bsr(RAnal * anal,RAnalOp * op,ut16 code)946 static int bsr(RAnal* anal, RAnalOp* op, ut16 code) {
947 /* Subroutine call, relative to PC */
948 op->type = R_ANAL_OP_TYPE_CALL;
949 op->jump = disarm_12bit_offset (op, GET_BRA_OFFSET (code));
950 op->delay = 1;
951 r_strbuf_setf (&op->esil, "1,SETD,pc,2,+,pr,=,0x%" PFMT64x ",pc,=", op->jump);
952 return op->size;
953 }
954
first_nibble_is_c(RAnal * anal,RAnalOp * op,ut16 code)955 static int first_nibble_is_c(RAnal* anal, RAnalOp* op, ut16 code) {
956 if (IS_TRAP (code)) {
957 op->type = R_ANAL_OP_TYPE_SWI;
958 op->val = (ut8)(code & 0xFF);
959 r_strbuf_setf (&op->esil, "4,r15,-=,sr,r15,=[4],4,r15,-=,2,pc,-,r15,=[4],2,0x%x,<<,4,+,vbr,+,pc,=", code & 0xFF);
960 } else if (IS_MOVA_PCREL_R0 (code)) {
961 // 11000111i8p4.... mova @(<disp>,PC),R0
962 op->type = R_ANAL_OP_TYPE_LEA;
963 op->src[0] = anal_pcrel_disp_mov (anal, op, code & 0xFF, LONG_SIZE); //this is wrong !
964 op->dst = anal_fill_ai_rg (anal, 0); //Always R0
965 r_strbuf_setf (&op->esil, "0x%x,pc,+,r0,=", (code & 0xFF) * 4);
966 } else if (IS_BINLOGIC_IMM_R0 (code)) { // 110010__i8 (binop) #imm, R0
967 op->src[0] = anal_fill_im (anal, code & 0xFF);
968 op->src[1] = anal_fill_ai_rg (anal, 0); //Always R0
969 op->dst = anal_fill_ai_rg (anal, 0); //Always R0 except tst #imm, R0
970 switch(code & 0xFF00) {
971 case 0xC800: //tst
972 //TODO : get correct op->dst ! (T flag)
973 op->type = R_ANAL_OP_TYPE_ACMP;
974 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&=,r0,0x%x,&,!,?{,1,sr,|=,}", code & 0xFF);
975 break;
976 case 0xC900: //and
977 op->type = R_ANAL_OP_TYPE_AND;
978 r_strbuf_setf (&op->esil, "0x%x,r0,&=", code & 0xFF);
979 break;
980 case 0xCA00: //xor
981 op->type = R_ANAL_OP_TYPE_XOR;
982 r_strbuf_setf (&op->esil, "0x%x,r0,^=", code & 0xFF);
983 break;
984 case 0xCB00: //or
985 op->type = R_ANAL_OP_TYPE_OR;
986 r_strbuf_setf (&op->esil, "0x%x,r0,|=", code & 0xFF);
987 break;
988 }
989 } else if (IS_BINLOGIC_IMM_GBR (code)) { //110011__i8 (binop).b #imm, @(R0,gbr)
990 op->src[0] = anal_fill_im (anal, code & 0xFF);
991 switch(code & 0xFF00) {
992 case 0xCC00: //tst
993 //TODO : get correct op->dst ! (T flag)
994 op->type = R_ANAL_OP_TYPE_ACMP;
995 r_strbuf_setf (&op->esil, "0xFFFFFFFE,sr,&=,r0,gbr,+,[1],0x%x,&,!,?{,1,sr,|=,}", code & 0xFF);
996 break;
997 case 0xCD00: //and
998 op->type = R_ANAL_OP_TYPE_AND;
999 r_strbuf_setf (&op->esil, "r0,gbr,+,[1],0x%x,&,r0,gbr,+,=[1]", code & 0xFF);
1000 break;
1001 case 0xCE00: //xor
1002 op->type = R_ANAL_OP_TYPE_XOR;
1003 r_strbuf_setf (&op->esil, "r0,gbr,+,[1],0x%x,^,r0,gbr,+,=[1]", code & 0xFF);
1004 break;
1005 case 0xCF00: //or
1006 op->type = R_ANAL_OP_TYPE_OR;
1007 r_strbuf_setf (&op->esil, "r0,gbr,+,[1],0x%x,|,r0,gbr,+,=[1]", code & 0xFF);
1008 break;
1009 }
1010 //TODO : implement @(R0,gbr) dest and src[1]
1011 } else if (IS_MOVB_R0_GBRREF (code)) {
1012 op->type = R_ANAL_OP_TYPE_STORE;
1013 op->src[0] = anal_fill_ai_rg (anal, 0);
1014 r_strbuf_setf (&op->esil, "r0,gbr,0x%x,+,=[1]", code & 0xFF);
1015 } else if (IS_MOVW_R0_GBRREF (code)) {
1016 op->type = R_ANAL_OP_TYPE_STORE;
1017 op->src[0] = anal_fill_ai_rg (anal, 0);
1018 r_strbuf_setf (&op->esil, "r0,gbr,0x%x,+,=[2]", (code & 0xFF) * 2);
1019 } else if (IS_MOVL_R0_GBRREF (code)) {
1020 op->type = R_ANAL_OP_TYPE_STORE;
1021 op->src[0] = anal_fill_ai_rg (anal, 0);
1022 r_strbuf_setf (&op->esil, "r0,gbr,0x%x,+,=[4]", (code & 0xFF) * 4);
1023 } else if (IS_MOVB_GBRREF_R0 (code)) {
1024 op->type = R_ANAL_OP_TYPE_LOAD;
1025 op->dst = anal_fill_ai_rg (anal, 0);
1026 r_strbuf_setf (&op->esil, "gbr,0x%x,+,[1],DUP,0x80,&,?{,0xFFFFFF00,|,},r0,=", (code & 0xFF));
1027 } else if (IS_MOVW_GBRREF_R0 (code)) {
1028 op->type = R_ANAL_OP_TYPE_LOAD;
1029 op->dst = anal_fill_ai_rg (anal, 0);
1030 r_strbuf_setf (&op->esil, "gbr,0x%x,+,[2],DUP,0x8000,&,?{,0xFFFF0000,|,},r0,=", (code & 0xFF)*2);
1031 } else if (IS_MOVL_GBRREF_R0 (code)) {
1032 op->type = R_ANAL_OP_TYPE_LOAD;
1033 op->dst = anal_fill_ai_rg (anal, 0);
1034 r_strbuf_setf (&op->esil, "gbr,0x%x,+,[4],r0,=", (code & 0xFF) * 4);
1035 }
1036
1037 return op->size;
1038 }
1039
1040 //nibble=d; 1101nnnni8 : mov.l @(<disp>,PC), Rn
movl_pcdisp_reg(RAnal * anal,RAnalOp * op,ut16 code)1041 static int movl_pcdisp_reg(RAnal* anal, RAnalOp* op, ut16 code) {
1042 op->type = R_ANAL_OP_TYPE_LOAD;
1043 op->src[0] = anal_pcrel_disp_mov (anal, op, code & 0xFF, LONG_SIZE);
1044 //TODO: check it
1045 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
1046 //r_strbuf_setf (&op->esil, "0x%x,[4],r%d,=", (code & 0xFF) * 4 + (op->addr & 0xfffffff3) + 4, GET_TARGET_REG (code));
1047 r_strbuf_setf (&op->esil, "0x%" PFMT64x ",[4],r%d,=", (code & 0xFF) * 4 + ((op->addr >> 2)<<2) + 4, GET_TARGET_REG (code));
1048 return op->size;
1049 }
1050
1051 //nibble=e; 1110nnnni8*1.... mov #<imm>,<REG_N>
mov_imm_reg(RAnal * anal,RAnalOp * op,ut16 code)1052 static int mov_imm_reg(RAnal* anal, RAnalOp* op, ut16 code) {
1053 op->type = R_ANAL_OP_TYPE_MOV;
1054 op->dst = anal_fill_ai_rg (anal, GET_TARGET_REG (code));
1055 op->src[0] = anal_fill_im (anal, (st8)(code & 0xFF));
1056 r_strbuf_setf (&op->esil, "0x%x,r%d,=,r%d,0x80,&,?{,0xFFFFFF00,r%d,|=,}", code & 0xFF, GET_TARGET_REG (code), GET_TARGET_REG (code), GET_TARGET_REG (code));
1057 return op->size;
1058 }
1059
1060 //nibble=f;
fpu_insn(RAnal * anal,RAnalOp * op,ut16 code)1061 static int fpu_insn(RAnal* anal, RAnalOp* op, ut16 code) {
1062 //Not interested on FPU stuff for now
1063 op->family = R_ANAL_OP_FAMILY_FPU;
1064 return op->size;
1065 }
1066
1067 /* Table of routines for further analysis based on 1st nibble */
1068 static int (*first_nibble_decode[])(RAnal*,RAnalOp*,ut16) = {
1069 first_nibble_is_0,
1070 movl_reg_rdisp,
1071 first_nibble_is_2,
1072 first_nibble_is_3,
1073 first_nibble_is_4,
1074 movl_rdisp_reg,
1075 first_nibble_is_6,
1076 add_imm,
1077 first_nibble_is_8,
1078 movw_pcdisp_reg,
1079 bra,
1080 bsr,
1081 first_nibble_is_c,
1082 movl_pcdisp_reg,
1083 mov_imm_reg,
1084 fpu_insn
1085 };
1086
1087
1088 /* This is the basic operation analysis. Just initialize and jump to
1089 * routines defined in first_nibble_decode table
1090 */
sh_op(RAnal * anal,RAnalOp * op,ut64 addr,const ut8 * data,int len,RAnalOpMask mask)1091 static int sh_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len, RAnalOpMask mask) {
1092 ut8 op_MSB, op_LSB;
1093 int ret;
1094 if (!data || len < 2) {
1095 return 0;
1096 }
1097 op->addr = addr;
1098 op->type = R_ANAL_OP_TYPE_UNK;
1099
1100 op->size = 2;
1101
1102 op_MSB = anal->big_endian? data[0]: data[1];
1103 op_LSB = anal->big_endian? data[1]: data[0];
1104 ret = first_nibble_decode[(op_MSB>>4) & 0x0F](anal, op, (ut16)(op_MSB<<8 | op_LSB));
1105
1106 return ret;
1107 }
1108
1109 /* Set the profile register */
sh_set_reg_profile(RAnal * anal)1110 static bool sh_set_reg_profile(RAnal* anal) {
1111 //TODO Add system ( ssr, spc ) + fpu regs
1112 const char *p =
1113 "=PC pc\n"
1114 "=SN r0\n"
1115 "=SP r15\n"
1116 "=BP r14\n"
1117 "=A0 r4\n"
1118 "=A1 r5\n"
1119 "=A2 r6\n"
1120 "=A3 r7\n"
1121 "=R0 r0\n"
1122 "gpr r0 .32 0 0\n"
1123 "gpr r1 .32 4 0\n"
1124 "gpr r2 .32 8 0\n"
1125 "gpr r3 .32 12 0\n"
1126 "gpr r4 .32 16 0\n"
1127 "gpr r5 .32 20 0\n"
1128 "gpr r6 .32 24 0\n"
1129 "gpr r7 .32 28 0\n"
1130 "gpr r8 .32 32 0\n"
1131 "gpr r9 .32 36 0\n"
1132 "gpr r10 .32 40 0\n"
1133 "gpr r11 .32 44 0\n"
1134 "gpr r12 .32 48 0\n"
1135 "gpr r13 .32 52 0\n"
1136 "gpr r14 .32 56 0\n"
1137 "gpr r15 .32 60 0\n"
1138 "gpr pc .32 64 0\n"
1139 "gpr pr .32 68 0\n"
1140 "gpr sr .32 72 0\n"
1141 "gpr gbr .32 76 0\n"
1142 "gpr vbr .32 80 0\n"
1143 "gpr mach .32 84 0\n"
1144 "gpr macl .32 88 0\n";
1145 return r_reg_set_profile_string(anal->reg, p);
1146 }
1147
archinfo(RAnal * anal,int q)1148 static int archinfo(RAnal *anal, int q) {
1149 #if 0
1150 if (q == R_ANAL_ARCHINFO_ALIGN) {
1151 return 4;
1152 }
1153 #endif
1154 return 2; /* :) */
1155 }
1156
1157
1158 RAnalPlugin r_anal_plugin_sh = {
1159 .name = "sh",
1160 .desc = "SH-4 code analysis plugin",
1161 .license = "LGPL3",
1162 .arch = "sh",
1163 .archinfo = archinfo,
1164 .bits = 32,
1165 .op = &sh_op,
1166 .set_reg_profile = &sh_set_reg_profile,
1167 .esil = true
1168 };
1169
1170 #ifndef R2_PLUGIN_INCORE
1171 R_API RLibStruct radare_plugin = {
1172 .type = R_LIB_TYPE_ANAL,
1173 .data = &r_anal_plugin_sh,
1174 .version = R2_VERSION
1175 };
1176 #endif
1177
1178