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