1 /* radare2 - LGPL - Copyright 2015-2018 - oddcoder, thestr4ng3r, courk */
2 
3 #include <r_types.h>
4 #include <r_anal.h>
5 #include <r_lib.h>
6 
7 #include "../../asm/arch/pic/pic_midrange.h"
8 
9 typedef struct _pic_midrange_op_args_val {
10 	ut16 f;
11 	ut16 k;
12 	ut8 d;
13 	ut8 m;
14 	ut8 n;
15 	ut8 b;
16 } PicMidrangeOpArgsVal;
17 
18 typedef void (*pic_midrange_inst_handler_t) (RAnal *anal, RAnalOp *op,
19 					     ut64 addr,
20 					     PicMidrangeOpArgsVal *args);
21 
22 typedef struct _pic_midrange_op_anal_info {
23 	PicMidrangeOpcode opcode;
24 	PicMidrangeOpArgs args;
25 	pic_midrange_inst_handler_t handler;
26 } PicMidrangeOpAnalInfo;
27 
28 #define INST_HANDLER(OPCODE_NAME)                                            \
29 	static void _inst__##OPCODE_NAME (RAnal *anal, RAnalOp *op,          \
30 					  ut64 addr,                         \
31 					  PicMidrangeOpArgsVal *args)
32 #define INST_DECL(NAME, ARGS)                                                \
33 	{                                                                    \
34 		PIC_MIDRANGE_OPCODE_##NAME, PIC_MIDRANGE_OP_ARGS_##ARGS,     \
35 			_inst__##NAME                                        \
36 	}
37 
38 #define e(frag) r_strbuf_append (&op->esil, frag)
39 #define ef(frag, ...) r_strbuf_appendf (&op->esil, frag, __VA_ARGS__)
40 
41 #define PIC_MIDRANGE_ESIL_SRAM_START (1 << 16)
42 #define PIC_MIDRANGE_ESIL_CSTACK_TOP ((1 << 16) + (1 << 12))
43 
44 #define PIC_MIDRANGE_ESIL_BSR_ADDR "bsr,0x80,*,0x%x,+,_sram,+"
45 
46 #define PIC_MIDRANGE_ESIL_OPTION_ADDR "0x95,_sram,+"
47 
48 #define PIC_MIDRANGE_ESIL_UPDATE_FLAGS                                       \
49 	"$z,z,:=,"                                                            \
50 	"7,$c,c,:=,"                                                           \
51 	"4,$c,dc,:=,"
52 
53 #define PIC_MIDRANGE_ESIL_LW_OP(O)                                           \
54 	"0x%x,wreg," #O "=," PIC_MIDRANGE_ESIL_UPDATE_FLAGS
55 
56 #define PIC_MIDRANGE_ESIL_FWF_OP(O)                                          \
57 	"wreg," PIC_MIDRANGE_ESIL_BSR_ADDR "," #O                            \
58 	"=[1]," PIC_MIDRANGE_ESIL_UPDATE_FLAGS
59 
60 #define PIC_MIDRANGE_ESIL_WWF_OP(O)                                          \
61 	PIC_MIDRANGE_ESIL_BSR_ADDR                                           \
62 	",[1],"                                                              \
63 	"wreg," #O "=," PIC_MIDRANGE_ESIL_UPDATE_FLAGS
64 
65 #define PIC_MIDRANGE_ESIL_FWF_OP_C(O)                                        \
66 	"c,wreg,"                                                            \
67 	"+," PIC_MIDRANGE_ESIL_BSR_ADDR "," #O                               \
68 	"=[1]," PIC_MIDRANGE_ESIL_UPDATE_FLAGS
69 
70 #define PIC_MIDRANGE_ESIL_WWF_OP_C(O)                                        \
71 	"c," PIC_MIDRANGE_ESIL_BSR_ADDR ",[1]," #O ","                       \
72 	"wreg," #O "=," PIC_MIDRANGE_ESIL_UPDATE_FLAGS
73 
INST_HANDLER(NOP)74 INST_HANDLER (NOP) {}
75 
INST_HANDLER(RETFIE)76 INST_HANDLER (RETFIE) {
77 	op->type = R_ANAL_OP_TYPE_RET;
78 }
79 
INST_HANDLER(OPTION)80 INST_HANDLER (OPTION) {
81 	op->type = R_ANAL_OP_TYPE_STORE;
82 }
83 
INST_HANDLER(TRIS)84 INST_HANDLER (TRIS) {
85 	op->type = R_ANAL_OP_TYPE_STORE;
86 }
87 
INST_HANDLER(RETURN)88 INST_HANDLER (RETURN) {
89 	op->type = R_ANAL_OP_TYPE_RET;
90 	e ("0x1f,stkptr,==,$z,?{,BREAK,},");
91 	e ("_stack,stkptr,2,*,+,[2],2,*,pc,=,");
92 	e ("0x01,stkptr,-=,");
93 	e ("0xff,stkptr,==,$z,?{,0x1f,stkptr,=,},");
94 }
95 
INST_HANDLER(CALL)96 INST_HANDLER (CALL) {
97 	ut64 pclath;
98 	op->type = R_ANAL_OP_TYPE_CALL;
99 	r_anal_esil_reg_read (anal->esil, "pclath", &pclath, NULL);
100 	op->jump = 2 * (((pclath & 0x78) << 8) + args->k);
101 	ef ("8,pclath,0x78,&,<<,0x%x,+,2,*,pc,=,", args->k);
102 	e ("0x1f,stkptr,==,$z,?{,0xff,stkptr,=,},");
103 	e ("0x0f,stkptr,==,$z,?{,0xff,stkptr,=,},");
104 	e ("0x01,stkptr,+=,");
105 	ef ("0x%" PFMT64x ",_stack,stkptr,2,*,+,=[2],", (addr + 2) / 2);
106 }
107 
INST_HANDLER(GOTO)108 INST_HANDLER (GOTO) {
109 	ut64 pclath;
110 	op->type = R_ANAL_OP_TYPE_JMP;
111 	r_anal_esil_reg_read (anal->esil, "pclath", &pclath, NULL);
112 	op->jump = 2 * (((pclath & 0x78) << 8) + args->k);
113 	ef ("8,pclath,0x78,&,<<,0x%x,+,2,*,pc,=,", args->k);
114 }
115 
INST_HANDLER(BCF)116 INST_HANDLER (BCF) {
117 	ut8 mask = ~(1 << args->b);
118 	ef (PIC_MIDRANGE_ESIL_BSR_ADDR
119 	    ",[1],0x%x,&," PIC_MIDRANGE_ESIL_BSR_ADDR ",=[1],",
120 	    args->f, mask, args->f);
121 }
122 
INST_HANDLER(BSF)123 INST_HANDLER (BSF) {
124 	ut8 mask = (1 << args->b);
125 	ef (PIC_MIDRANGE_ESIL_BSR_ADDR
126 	    ",[1],0x%x,|," PIC_MIDRANGE_ESIL_BSR_ADDR ",=[1],",
127 	    args->f, mask, args->f);
128 }
129 
INST_HANDLER(BTFSC)130 INST_HANDLER (BTFSC) {
131 	ut8 mask = (1 << args->b);
132 	op->type = R_ANAL_OP_TYPE_CJMP;
133 	op->jump = addr + 4;
134 	op->fail = addr + 2;
135 	ef (PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],0x%x,&,!,?{,0x%" PFMT64x ",pc,=,},",
136 	    args->f, mask, op->jump);
137 }
138 
INST_HANDLER(BTFSS)139 INST_HANDLER (BTFSS) {
140 	ut8 mask = (1 << args->b);
141 	op->type = R_ANAL_OP_TYPE_CJMP;
142 	op->jump = addr + 4;
143 	op->fail = addr + 2;
144 	ef (PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],0x%x,&,?{,0x%" PFMT64x ",pc,=,},", args->f,
145 	    mask, op->jump);
146 }
147 
INST_HANDLER(BRA)148 INST_HANDLER (BRA) {
149 	st16 branch = args->k;
150 	op->type = R_ANAL_OP_TYPE_JMP;
151 	branch |= ((branch & 0x100) ? 0xfe00 : 0);
152 	op->jump = addr + 2 * (branch + 1);
153 	ef ("%s0x%x,1,+,2,*,pc,+=,", branch < 0 ? "-" : "",
154 	    branch < 0 ? -branch : branch);
155 }
156 
INST_HANDLER(BRW)157 INST_HANDLER (BRW) {
158 	ut64 wreg;
159 	op->type = R_ANAL_OP_TYPE_UJMP;
160 	r_anal_esil_reg_read (anal->esil, "wreg", &wreg, NULL);
161 	op->jump = addr + 2 * (wreg + 1);
162 	e ("wreg,1,+,2,*,pc,+=,");
163 }
164 
INST_HANDLER(CLR)165 INST_HANDLER (CLR) {
166 	if (args->d) {
167 		ef ("0x00," PIC_MIDRANGE_ESIL_BSR_ADDR ",=[1],", args->f);
168 	} else {
169 		e ("0x00,wreg,=,");
170 	}
171 	e ("1,z,=,");
172 }
173 
INST_HANDLER(SUBWF)174 INST_HANDLER (SUBWF) {
175 	op->type = R_ANAL_OP_TYPE_SUB;
176 	if (args->d) {
177 		ef (PIC_MIDRANGE_ESIL_FWF_OP (-), args->f);
178 	} else {
179 		ef (PIC_MIDRANGE_ESIL_WWF_OP (-), args->f);
180 		e ("wreg,0x00,-,wreg,=,c,!=,dc,!=,");
181 	}
182 }
183 
INST_HANDLER(DECFSZ)184 INST_HANDLER (DECFSZ) {
185 	op->type = R_ANAL_OP_TYPE_CJMP;
186 	op->jump = addr + 4;
187 	op->fail = addr + 2;
188 	if (args->d) {
189 		ef ("0x01," PIC_MIDRANGE_ESIL_BSR_ADDR ",-=[1],", args->f);
190 	} else {
191 		ef ("0x01," PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],-,wreg,=,",
192 		    args->f);
193 	}
194 	ef (PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],!,?{,0x%" PFMT64x ",pc,=,},", args->f,
195 	    op->jump);
196 }
197 
INST_HANDLER(INCFSZ)198 INST_HANDLER (INCFSZ) {
199 	op->type = R_ANAL_OP_TYPE_CJMP;
200 	op->jump = addr + 4;
201 	op->fail = addr + 2;
202 	if (args->d) {
203 		ef ("0x01," PIC_MIDRANGE_ESIL_BSR_ADDR ",+=[1],", args->f);
204 	} else {
205 		ef ("0x01," PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],+,wreg,=,",
206 		    args->f);
207 	}
208 	ef (PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],!,?{,0x%" PFMT64x ",pc,=,},", args->f,
209 	    op->jump);
210 }
211 
INST_HANDLER(INCF)212 INST_HANDLER (INCF) {
213 	op->type = R_ANAL_OP_TYPE_ADD;
214 	if (args->d) {
215 		ef ("0x01," PIC_MIDRANGE_ESIL_BSR_ADDR ",+=[1],", args->f);
216 	} else {
217 		ef ("0x01," PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],+,wreg,=,",
218 		    args->f);
219 	}
220 	e ("$z,z,:=,");
221 }
222 
INST_HANDLER(DECF)223 INST_HANDLER (DECF) {
224 	op->type = R_ANAL_OP_TYPE_SUB;
225 	if (args->d) {
226 		ef ("0x01," PIC_MIDRANGE_ESIL_BSR_ADDR ",-=[1],", args->f);
227 	} else {
228 		ef ("0x01," PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],-,wreg,=,",
229 		    args->f);
230 	}
231 	e ("$z,z,:=,");
232 }
233 
INST_HANDLER(IORWF)234 INST_HANDLER (IORWF) {
235 	op->type = R_ANAL_OP_TYPE_OR;
236 	if (args->d) {
237 		ef (PIC_MIDRANGE_ESIL_FWF_OP (|), args->f);
238 	} else {
239 		ef (PIC_MIDRANGE_ESIL_WWF_OP (|), args->f);
240 	}
241 }
242 
INST_HANDLER(ANDWF)243 INST_HANDLER (ANDWF) {
244 	op->type = R_ANAL_OP_TYPE_AND;
245 	if (args->d) {
246 		ef (PIC_MIDRANGE_ESIL_FWF_OP (&), args->f);
247 	} else {
248 		ef (PIC_MIDRANGE_ESIL_WWF_OP (&), args->f);
249 	}
250 }
251 
INST_HANDLER(XORWF)252 INST_HANDLER (XORWF) {
253 	op->type = R_ANAL_OP_TYPE_XOR;
254 	if (args->d) {
255 		ef (PIC_MIDRANGE_ESIL_FWF_OP (^), args->f);
256 	} else {
257 		ef (PIC_MIDRANGE_ESIL_WWF_OP (^), args->f);
258 	}
259 }
260 
INST_HANDLER(ADDWF)261 INST_HANDLER (ADDWF) {
262 	op->type = R_ANAL_OP_TYPE_ADD;
263 	if (args->d) {
264 		ef (PIC_MIDRANGE_ESIL_FWF_OP (+), args->f);
265 	} else {
266 		ef (PIC_MIDRANGE_ESIL_WWF_OP (+), args->f);
267 	}
268 }
269 
INST_HANDLER(SUBLW)270 INST_HANDLER (SUBLW) {
271 	op->type = R_ANAL_OP_TYPE_SUB;
272 	ef (PIC_MIDRANGE_ESIL_LW_OP (-), args->k);
273 }
274 
INST_HANDLER(ADDLW)275 INST_HANDLER (ADDLW) {
276 	op->type = R_ANAL_OP_TYPE_ADD;
277 	ef (PIC_MIDRANGE_ESIL_LW_OP (+), args->k);
278 }
279 
INST_HANDLER(IORLW)280 INST_HANDLER (IORLW) {
281 	op->type = R_ANAL_OP_TYPE_OR;
282 	ef (PIC_MIDRANGE_ESIL_LW_OP (|), args->k);
283 }
284 
INST_HANDLER(ANDLW)285 INST_HANDLER (ANDLW) {
286 	op->type = R_ANAL_OP_TYPE_AND;
287 	ef (PIC_MIDRANGE_ESIL_LW_OP (&), args->k);
288 }
289 
INST_HANDLER(XORLW)290 INST_HANDLER (XORLW) {
291 	op->type = R_ANAL_OP_TYPE_XOR;
292 	ef (PIC_MIDRANGE_ESIL_LW_OP (^), args->k);
293 }
294 
INST_HANDLER(MOVLW)295 INST_HANDLER (MOVLW) {
296 	op->type = R_ANAL_OP_TYPE_LOAD;
297 	ef ("0x%x,wreg,=,", args->k);
298 }
299 
INST_HANDLER(RETLW)300 INST_HANDLER (RETLW) {
301 	op->type = R_ANAL_OP_TYPE_RET;
302 	ef ("0x%x,wreg,=,", args->k);
303 	e ("0x1f,stkptr,==,$z,?{,BREAK,},");
304 	e ("_stack,stkptr,2,*,+,[2],2,*,pc,=,");
305 	e ("0x01,stkptr,-=,");
306 	e ("0xff,stkptr,==,$z,?{,0x1f,stkptr,=,},");
307 }
308 
INST_HANDLER(MOVLP)309 INST_HANDLER (MOVLP) {
310 	op->type = R_ANAL_OP_TYPE_LOAD;
311 	ef ("0x%x,pclath,=,", args->f);
312 }
313 
INST_HANDLER(MOVLB)314 INST_HANDLER (MOVLB) {
315 	op->type = R_ANAL_OP_TYPE_LOAD;
316 	ef ("0x%x,bsr,=,", args->k);
317 }
318 
INST_HANDLER(CALLW)319 INST_HANDLER (CALLW) {
320 	op->type = R_ANAL_OP_TYPE_UCALL;
321 	e ("8,pclath,<<,0x%x,+,wreg,2,*,pc,=,");
322 	e ("0x1f,stkptr,==,$z,?{,0xff,stkptr,=,},");
323 	e ("0x0f,stkptr,==,$z,?{,0xff,stkptr,=,},");
324 	e ("0x01,stkptr,+=,");
325 	ef ("0x%" PFMT64x ",_stack,stkptr,2,*,+,=[2],", (addr + 2) / 2);
326 }
327 
INST_HANDLER(MOVWF)328 INST_HANDLER (MOVWF) {
329 	op->type = R_ANAL_OP_TYPE_STORE;
330 	ef ("wreg," PIC_MIDRANGE_ESIL_BSR_ADDR ",=[1],", args->f);
331 }
332 
INST_HANDLER(MOVF)333 INST_HANDLER (MOVF) {
334 	op->type = R_ANAL_OP_TYPE_LOAD;
335 	if (args->d) {
336 		ef (PIC_MIDRANGE_ESIL_BSR_ADDR
337 		    ",[1]," PIC_MIDRANGE_ESIL_BSR_ADDR ",=[1],",
338 		    args->f, args->f);
339 	} else {
340 		ef (PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],wreg,=,", args->f);
341 	}
342 	e ("$z,z,:=,");
343 }
344 
INST_HANDLER(SWAPF)345 INST_HANDLER (SWAPF) {
346 	ef ("4," PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],>>,0x0f,&,", args->f);
347 	ef ("4," PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],<<,0xf0,&,", args->f);
348 	e ("|,");
349 	ef (PIC_MIDRANGE_ESIL_BSR_ADDR ",=[1],", args->f);
350 }
351 
INST_HANDLER(LSLF)352 INST_HANDLER (LSLF) {
353 	op->type = R_ANAL_OP_TYPE_SHL;
354 	ef ("7," PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],>>,c,=,", args->f);
355 	if (args->d) {
356 		ef ("1," PIC_MIDRANGE_ESIL_BSR_ADDR ",<<=[1],", args->f);
357 	} else {
358 		ef ("1," PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],<<,wreg,=,",
359 		    args->f);
360 	}
361 	e ("$z,z,:=,");
362 }
363 
INST_HANDLER(LSRF)364 INST_HANDLER (LSRF) {
365 	op->type = R_ANAL_OP_TYPE_SHR;
366 	ef ("1," PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],&,c,=,", args->f);
367 	if (args->d) {
368 		ef ("1," PIC_MIDRANGE_ESIL_BSR_ADDR ",>>=[1],", args->f);
369 	} else {
370 		ef ("1," PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],>>,wreg,=,",
371 		    args->f);
372 	}
373 	e ("$z,z,:=,");
374 }
375 
INST_HANDLER(ASRF)376 INST_HANDLER (ASRF) {
377 	op->type = R_ANAL_OP_TYPE_SHR;
378 	ef ("1," PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],&,c,=,", args->f);
379 	ef ("1," PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],>>,", args->f);
380 	ef ("0x80," PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],&,", args->f);
381 	if (args->d) {
382 		ef ("|," PIC_MIDRANGE_ESIL_BSR_ADDR ",=[1],", args->f);
383 	} else {
384 		e ("|,wreg,=,");
385 	}
386 	e ("$z,z,:=,");
387 }
388 
INST_HANDLER(RRF)389 INST_HANDLER (RRF) {
390 	op->type = R_ANAL_OP_TYPE_ROR;
391 	ef ("1," PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],&,", args->f);
392 	if (args->d) {
393 		ef ("1," PIC_MIDRANGE_ESIL_BSR_ADDR ",>>=[1],"
394 		    "c," PIC_MIDRANGE_ESIL_BSR_ADDR ",|=[1],",
395 		    args->f, args->f);
396 	} else {
397 		ef ("1," PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],>>,wreg,=,"
398 		    "c,wreg,|=[1],",
399 		    args->f);
400 	}
401 	e ("c,=,");
402 }
403 
INST_HANDLER(RLF)404 INST_HANDLER (RLF) {
405 	op->type = R_ANAL_OP_TYPE_ROL;
406 	ef ("7," PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],>>,", args->f);
407 	if (args->d) {
408 		ef ("1," PIC_MIDRANGE_ESIL_BSR_ADDR ",<<=[1],"
409 		    "c," PIC_MIDRANGE_ESIL_BSR_ADDR ",|=[1],",
410 		    args->f, args->f);
411 	} else {
412 		ef ("1," PIC_MIDRANGE_ESIL_BSR_ADDR ",[1],<<,wreg,=,"
413 		    "c,wreg,|=[1],",
414 		    args->f);
415 	}
416 	e ("c,=,");
417 }
418 
INST_HANDLER(COMF)419 INST_HANDLER (COMF) {
420 	if (args->d) {
421 		ef ("0xff," PIC_MIDRANGE_ESIL_BSR_ADDR ",^=[1],", args->f);
422 	} else {
423 		ef ("0xff," PIC_MIDRANGE_ESIL_BSR_ADDR ",^,wreg,=,", args->f);
424 	}
425 	e ("$z,z,:=,");
426 }
427 
INST_HANDLER(RESET)428 INST_HANDLER (RESET) {
429 	op->type = R_ANAL_OP_TYPE_JMP;
430 	op->jump = 0;
431 	e ("0x0,pc,=,");
432 	e ("0x1f,stkptr,=,");
433 }
434 
INST_HANDLER(ADDFSR)435 INST_HANDLER (ADDFSR) {
436 	op->type = R_ANAL_OP_TYPE_ADD;
437 	if (args->n == 0) {
438 		ef ("0x%x,fsr0l,+=,", args->k);
439 		e ("7,$c,?{,0x01,fsr0h,+=,},");
440 	} else {
441 		ef ("0x%x,fsr1l,+=,", args->k);
442 		e ("7,$c,?{,0x01,fsr1h,+=,},");
443 	}
444 }
445 
INST_HANDLER(CLRWDT)446 INST_HANDLER (CLRWDT) {
447 	e ("1,to,=,");
448 	e ("1,pd,=,");
449 }
450 
INST_HANDLER(SLEEP)451 INST_HANDLER (SLEEP) {
452 	e ("1,to,=,");
453 	e ("0,pd,=,");
454 }
455 
INST_HANDLER(SUBWFB)456 INST_HANDLER (SUBWFB) {
457 	op->type = R_ANAL_OP_TYPE_SUB;
458 	e ("c,!=,");
459 	if (args->d) {
460 		ef (PIC_MIDRANGE_ESIL_FWF_OP_C (-), args->f);
461 	} else {
462 		ef (PIC_MIDRANGE_ESIL_WWF_OP_C (-), args->f);
463 		e ("wreg,0x00,-,wreg,=,c,!=,dc,!=,");
464 	}
465 }
466 
INST_HANDLER(ADDWFC)467 INST_HANDLER (ADDWFC) {
468 	op->type = R_ANAL_OP_TYPE_ADD;
469 	if (args->d) {
470 		ef (PIC_MIDRANGE_ESIL_FWF_OP_C (+), args->f);
471 	} else {
472 		ef (PIC_MIDRANGE_ESIL_WWF_OP_C (+), args->f);
473 	}
474 }
475 
INST_HANDLER(MOVIW_1)476 INST_HANDLER (MOVIW_1) {
477 	if (args->n == 0) {
478 		if (!(args->m & 2)) {
479 			ef ("1,fsr0l,%s=,", (args->m & 1) ? "-" : "+");
480 			ef ("7,$c%s,fsr0h,%s,", (args->m & 1) ? ",!" : "",
481 			    (args->m & 1) ? "-" : "+");
482 		}
483 		e ("indf0,wreg,=,");
484 		e ("$z,z,:=,");
485 		if (args->m & 2) {
486 			ef ("1,fsr0l,%s=,", (args->m & 1) ? "-" : "+");
487 			ef ("7,$c%s,fsr0h,%s,", (args->m & 1) ? ",!" : "",
488 			    (args->m & 1) ? "-" : "+");
489 		}
490 	} else {
491 		if (!(args->m & 2)) {
492 			ef ("1,fsr1l,%s=,", (args->m & 1) ? "-" : "+");
493 			ef ("7,$c%s,fsr1h,%s,", (args->m & 1) ? ",!" : "",
494 			    (args->m & 1) ? "-" : "+");
495 		}
496 		e ("indf1,wreg,=,");
497 		e ("$z,z,:=,");
498 		if (args->m & 2) {
499 			ef ("1,fsr1l,%s=,", (args->m & 1) ? "-" : "+");
500 			ef ("7,$c%s,fsr1h,%s,", (args->m & 1) ? ",!" : "",
501 			    (args->m & 1) ? "-" : "+");
502 		}
503 	}
504 }
505 
INST_HANDLER(MOVWI_1)506 INST_HANDLER (MOVWI_1) {
507 	if (args->n == 0) {
508 		if (!(args->m & 2)) {
509 			ef ("1,fsr0l,%s=,", (args->m & 1) ? "-" : "+");
510 			ef ("$c7%s,fsr0h,%s,", (args->m & 1) ? ",!" : "",
511 			    (args->m & 1) ? "-" : "+");
512 		}
513 		e ("wreg,indf0=,");
514 		e ("$z,z,:=,");
515 		if (args->m & 2) {
516 			ef ("1,fsr0l,%s=,", (args->m & 1) ? "-" : "+");
517 			ef ("$c7%s,fsr0h,%s,", (args->m & 1) ? ",!" : "",
518 			    (args->m & 1) ? "-" : "+");
519 		}
520 	} else {
521 		if (!(args->m & 2)) {
522 			ef ("1,fsr1l,%s=,", (args->m & 1) ? "-" : "+");
523 			ef ("$c7,fsr1h,%s,", (args->m & 1) ? ",!" : "");
524 		}
525 		e ("wreg,indf1=,");
526 		e ("$z,z,:=,");
527 		if (args->m & 2) {
528 			ef ("1,fsr1l,%s=,", (args->m & 1) ? "-" : "+");
529 			ef ("$c7%s,fsr1h,%s,", (args->m & 1) ? ",!" : "",
530 			    (args->m & 1) ? "-" : "+");
531 		}
532 	}
533 }
534 
INST_HANDLER(MOVIW_2)535 INST_HANDLER (MOVIW_2) {
536 	if (args->n == 0) {
537 		e ("fsr0l,8,fsr0h,<<,+,");
538 	} else {
539 		e ("fsr1l,8,fsr1h,<<,+,");
540 	}
541 	ef ("0x%x,+,[1],wreg,=,", args->k);
542 }
543 
INST_HANDLER(MOVWI_2)544 INST_HANDLER (MOVWI_2) {
545 	e ("wreg,");
546 	if (args->n == 0) {
547 		e ("fsr0l,8,fsr0h,<<,+,");
548 	} else {
549 		e ("fsr1l,8,fsr1h,<<,+,");
550 	}
551 	e ("=[1],");
552 }
553 
554 #define PIC_MIDRANGE_OPINFO_LEN 52
555 static const PicMidrangeOpAnalInfo pic_midrange_op_anal_info[PIC_MIDRANGE_OPINFO_LEN] = {
556 	INST_DECL (NOP, NONE),      INST_DECL (RETURN, NONE),
557 	INST_DECL (RETFIE, NONE),   INST_DECL (OPTION, NONE),
558 	INST_DECL (SLEEP, NONE),    INST_DECL (CLRWDT, NONE),
559 	INST_DECL (TRIS, 2F),       INST_DECL (MOVWF, 7F),
560 	INST_DECL (CLR, 1D_7F),     INST_DECL (SUBWF, 1D_7F),
561 	INST_DECL (DECF, 1D_7F),    INST_DECL (IORWF, 1D_7F),
562 	INST_DECL (ANDWF, 1D_7F),   INST_DECL (XORWF, 1D_7F),
563 	INST_DECL (ADDWF, 1D_7F),   INST_DECL (MOVF, 1D_7F),
564 	INST_DECL (COMF, 1D_7F),    INST_DECL (INCF, 1D_7F),
565 	INST_DECL (DECFSZ, 1D_7F),  INST_DECL (RRF, 1D_7F),
566 	INST_DECL (RLF, 1D_7F),     INST_DECL (SWAPF, 1D_7F),
567 	INST_DECL (INCFSZ, 1D_7F),  INST_DECL (BCF, 3B_7F),
568 	INST_DECL (BSF, 3B_7F),     INST_DECL (BTFSC, 3B_7F),
569 	INST_DECL (BTFSS, 3B_7F),   INST_DECL (CALL, 11K),
570 	INST_DECL (GOTO, 11K),      INST_DECL (MOVLW, 8K),
571 	INST_DECL (RETLW, 8K),      INST_DECL (IORLW, 8K),
572 	INST_DECL (ANDLW, 8K),      INST_DECL (XORLW, 8K),
573 	INST_DECL (SUBLW, 8K),      INST_DECL (ADDLW, 8K),
574 	INST_DECL (RESET, NONE),    INST_DECL (CALLW, NONE),
575 	INST_DECL (BRW, NONE),      INST_DECL (MOVIW_1, 1N_2M),
576 	INST_DECL (MOVWI_1, 1N_2M), INST_DECL (MOVLB, 4K),
577 	INST_DECL (LSLF, 1D_7F),    INST_DECL (LSRF, 1D_7F),
578 	INST_DECL (ASRF, 1D_7F),    INST_DECL (SUBWFB, 1D_7F),
579 	INST_DECL (ADDWFC, 1D_7F),  INST_DECL (ADDFSR, 1N_6K),
580 	INST_DECL (MOVLP, 7F),      INST_DECL (BRA, 9K),
581 	INST_DECL (MOVIW_2, 1N_6K), INST_DECL (MOVWI_2, 1N_6K)
582 };
583 
anal_pic_midrange_extract_args(ut16 instr,PicMidrangeOpArgs args,PicMidrangeOpArgsVal * args_val)584 static void anal_pic_midrange_extract_args (ut16 instr,
585 					    PicMidrangeOpArgs args,
586 					    PicMidrangeOpArgsVal *args_val) {
587 
588 	memset (args_val, 0, sizeof (PicMidrangeOpArgsVal));
589 
590 	switch (args) {
591 	case PIC_MIDRANGE_OP_ARGS_NONE: return;
592 	case PIC_MIDRANGE_OP_ARGS_2F:
593 		args_val->f = instr & PIC_MIDRANGE_OP_ARGS_2F_MASK_F;
594 		return;
595 	case PIC_MIDRANGE_OP_ARGS_7F:
596 		args_val->f = instr & PIC_MIDRANGE_OP_ARGS_7F_MASK_F;
597 		return;
598 	case PIC_MIDRANGE_OP_ARGS_1D_7F:
599 		args_val->f = instr & PIC_MIDRANGE_OP_ARGS_1D_7F_MASK_F;
600 		args_val->d =
601 			(instr & PIC_MIDRANGE_OP_ARGS_1D_7F_MASK_D) >> 7;
602 		return;
603 	case PIC_MIDRANGE_OP_ARGS_1N_6K:
604 		args_val->n =
605 			(instr & PIC_MIDRANGE_OP_ARGS_1N_6K_MASK_N) >> 6;
606 		args_val->k = instr & PIC_MIDRANGE_OP_ARGS_1N_6K_MASK_K;
607 		return;
608 	case PIC_MIDRANGE_OP_ARGS_3B_7F:
609 		args_val->b =
610 			(instr & PIC_MIDRANGE_OP_ARGS_3B_7F_MASK_B) >> 7;
611 		args_val->f = instr & PIC_MIDRANGE_OP_ARGS_3B_7F_MASK_F;
612 		return;
613 	case PIC_MIDRANGE_OP_ARGS_4K:
614 		args_val->k = instr & PIC_MIDRANGE_OP_ARGS_4K_MASK_K;
615 		return;
616 	case PIC_MIDRANGE_OP_ARGS_8K:
617 		args_val->k = instr & PIC_MIDRANGE_OP_ARGS_8K_MASK_K;
618 		return;
619 	case PIC_MIDRANGE_OP_ARGS_9K:
620 		args_val->k = instr & PIC_MIDRANGE_OP_ARGS_9K_MASK_K;
621 		return;
622 	case PIC_MIDRANGE_OP_ARGS_11K:
623 		args_val->k = instr & PIC_MIDRANGE_OP_ARGS_11K_MASK_K;
624 		return;
625 	case PIC_MIDRANGE_OP_ARGS_1N_2M:
626 		args_val->n =
627 			(instr & PIC_MIDRANGE_OP_ARGS_1N_2M_MASK_N) >> 2;
628 		args_val->m = instr & PIC_MIDRANGE_OP_ARGS_1N_2M_MASK_M;
629 		return;
630 	}
631 }
632 
633 static RIODesc *mem_sram = 0;
634 static RIODesc *mem_stack = 0;
635 
cpu_memory_map(RIOBind * iob,RIODesc * desc,ut32 addr,ut32 size)636 static RIODesc *cpu_memory_map (RIOBind *iob, RIODesc *desc, ut32 addr,
637 				ut32 size) {
638 	char *mstr = r_str_newf ("malloc://%d", size);
639 	if (desc && iob->fd_get_name (iob->io, desc->fd)) {
640 		iob->fd_remap (iob->io, desc->fd, addr);
641 	} else {
642 		desc = iob->open_at (iob->io, mstr, R_PERM_RW, 0, addr);
643 	}
644 	free (mstr);
645 	return desc;
646 }
647 
pic_midrange_reg_write(RReg * reg,const char * regname,ut32 num)648 static bool pic_midrange_reg_write (RReg *reg, const char *regname, ut32 num) {
649 	if (reg) {
650 		RRegItem *item = r_reg_get (reg, regname, R_REG_TYPE_GPR);
651 		if (item) {
652 			r_reg_set_value (reg, item, num);
653 			return true;
654 		}
655 	}
656 	return false;
657 }
658 
anal_pic_midrange_malloc(RAnal * anal,bool force)659 static void anal_pic_midrange_malloc (RAnal *anal, bool force) {
660 	static bool init_done = false;
661 
662 	if (!init_done || force) {
663 		// Allocate memory as needed.
664 		// We assume that code is already allocated with firmware
665 		// image
666 		mem_sram =
667 			cpu_memory_map (&anal->iob, mem_sram,
668 					PIC_MIDRANGE_ESIL_SRAM_START, 0x1000);
669 		mem_stack =
670 			cpu_memory_map (&anal->iob, mem_stack,
671 					PIC_MIDRANGE_ESIL_CSTACK_TOP, 0x20);
672 
673 		pic_midrange_reg_write (anal->reg, "_sram",
674 					PIC_MIDRANGE_ESIL_SRAM_START);
675 		pic_midrange_reg_write (anal->reg, "_stack",
676 					PIC_MIDRANGE_ESIL_CSTACK_TOP);
677 		pic_midrange_reg_write (anal->reg, "stkptr", 0x1f);
678 
679 		init_done = true;
680 	}
681 }
682 
anal_pic_midrange_op(RAnal * anal,RAnalOp * op,ut64 addr,const ut8 * buf,int len)683 static int anal_pic_midrange_op (RAnal *anal, RAnalOp *op, ut64 addr,
684 				 const ut8 *buf, int len) {
685 
686 	ut16 instr;
687 	int i;
688 
689 	anal_pic_midrange_malloc (anal, false);
690 
691 	if (!buf || len < 2) {
692 		op->type = R_ANAL_OP_TYPE_ILL;
693 		return op->size;
694 	}
695 
696 	instr = r_read_le16 (buf);
697 
698 	// Default op params
699 	op->size = 2;
700 	op->cycles = 1;
701 	op->type = R_ANAL_OP_TYPE_NOP;
702 
703 	PicMidrangeOpcode opcode = pic_midrange_get_opcode (instr);
704 	PicMidrangeOpArgsVal args_val;
705 
706 	for (i = 0; i < PIC_MIDRANGE_OPINFO_LEN; i++) {
707 		if (pic_midrange_op_anal_info[i].opcode == opcode) {
708 			anal_pic_midrange_extract_args (
709 				instr, pic_midrange_op_anal_info[i].args,
710 				&args_val);
711 			pic_midrange_op_anal_info[i].handler (anal, op, addr,
712 							      &args_val);
713 			break;
714 		}
715 	}
716 
717 	return op->size;
718 }
719 
pic18_cond_branch(RAnalOp * op,ut64 addr,const ut8 * buf,char * flag)720 static void pic18_cond_branch (RAnalOp *op, ut64 addr, const ut8 *buf, char *flag) {
721 	op->type = R_ANAL_OP_TYPE_CJMP;
722 	op->jump = addr + 2 + 2 * (*(ut16 *)buf & 0xff);
723 	op->fail = addr + op->size;
724 	op->cycles = 2;
725 	r_strbuf_setf (&op->esil, "%s,?,{,0x%" PFMT64x ",pc,=,}", flag, op->jump);
726 }
727 
anal_pic_pic18_op(RAnal * anal,RAnalOp * op,ut64 addr,const ut8 * buf,int len)728 static int anal_pic_pic18_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len) {
729 	//TODO code should be refactored and broken into smaller chunks!!
730 	//TODO complete the esil emitter
731 	if (len < 2) {
732 		op->size = len;
733 		goto beach; //pancake style :P
734 	}
735 	op->size = 2;
736 	ut16 b = *(ut16 *)buf;
737 	ut32 dword_instr = 0;
738 	memcpy (&dword_instr, buf, R_MIN (sizeof (dword_instr), len));
739 	switch (b >> 9) {
740 	case 0x76: //call
741 		if (len < 4) {
742 			goto beach;
743 		}
744 		if (dword_instr >> 28 != 0xf) {
745 			goto beach;
746 		}
747 		op->size = 4;
748 		op->type = R_ANAL_OP_TYPE_CALL;
749 		return op->size;
750 	};
751 	switch (b >> 11) { //NEX_T
752 	case 0x1b:	//rcall
753 		op->type = R_ANAL_OP_TYPE_CALL;
754 		return op->size;
755 	case 0x1a: //bra
756 		op->type = R_ANAL_OP_TYPE_JMP;
757 		op->cycles = 2;
758 		op->jump = addr + 2 + 2 * (*(ut16 *)buf & 0x7ff);
759 		r_strbuf_setf (&op->esil, "0x%" PFMT64x ",pc,=", op->jump);
760 		return op->size;
761 	}
762 	switch (b >> 12) { //NOP,movff,BAF_T
763 	case 0xf:	//nop
764 		op->type = R_ANAL_OP_TYPE_NOP;
765 		op->cycles = 1;
766 		r_strbuf_setf (&op->esil, ",");
767 		return op->size;
768 	case 0xc: //movff
769 		if (len < 4) {
770 			goto beach;
771 		}
772 		if (dword_instr >> 28 != 0xf) {
773 			goto beach;
774 		}
775 		op->size = 4;
776 		op->type = R_ANAL_OP_TYPE_MOV;
777 		return op->size;
778 	case 0xb: //btfsc
779 	case 0xa: //btfss
780 		op->type = R_ANAL_OP_TYPE_CJMP;
781 		return op->size;
782 	case 0x9: //bcf
783 	case 0x8: //bsf
784 	case 0x7: //btg
785 		op->type = R_ANAL_OP_TYPE_UNK;
786 		return op->size;
787 	};
788 
789 	switch (b >> 8) { //GOTO_T,N_T,K_T
790 	case 0xe0:	//bz
791 		pic18_cond_branch (op, addr, buf, "z");
792 		return op->size;
793 	case 0xe1: //bnz
794 		pic18_cond_branch (op, addr, buf, "z,!");
795 		return op->size;
796 	case 0xe3: //bnc
797 		pic18_cond_branch (op, addr, buf, "c,!");
798 		return op->size;
799 	case 0xe4: //bov
800 		pic18_cond_branch (op, addr, buf, "ov");
801 		return op->size;
802 	case 0xe5: //bnov
803 		pic18_cond_branch (op, addr, buf, "ov,!");
804 		return op->size;
805 	case 0xe6: //bn
806 		pic18_cond_branch (op, addr, buf, "n");
807 		return op->size;
808 	case 0xe7: //bnn
809 		pic18_cond_branch (op, addr, buf, "n,!");
810 		return op->size;
811 	case 0xe2: //bc
812 		pic18_cond_branch (op, addr, buf, "c");
813 		return op->size;
814 	case 0xef: //goto
815 		if (len < 4) {
816 			goto beach;
817 		}
818 		if (dword_instr >> 28 != 0xf) {
819 			goto beach;
820 		}
821 		op->size = 4;
822 		op->cycles = 2;
823 		op->jump = ((dword_instr & 0xff) | ((dword_instr & 0xfff0000) >> 8)) * 2;
824 		r_strbuf_setf (&op->esil, "0x%" PFMT64x ",pc,=", op->jump);
825 		op->type = R_ANAL_OP_TYPE_JMP;
826 		return op->size;
827 	case 0xf: //addlw
828 		op->type = R_ANAL_OP_TYPE_ADD;
829 		op->cycles = 1;
830 		//TODO add support for dc flag
831 		r_strbuf_setf (&op->esil, "0x%x,wreg,+=,$z,z,:=,7,$s,n,:=,7,$c,c,:=,7,$o,ov,:=,", *(ut16 *)buf & 0xff);
832 		return op->size;
833 	case 0xe: //movlw
834 		op->type = R_ANAL_OP_TYPE_LOAD;
835 		op->cycles = 1;
836 		r_strbuf_setf (&op->esil, "0x%x,wreg,=,", *(ut16* )buf & 0xff);
837 		return op->size;
838 	case 0xd: //mullw
839 		op->type = R_ANAL_OP_TYPE_MUL;
840 		op->cycles = 1;
841 		r_strbuf_setf (&op->esil, "0x%x,wreg,*,prod,=", *(ut16 *)buf & 0xff);
842 		return op->size;
843 	case 0xc: //retlw
844 		op->type = R_ANAL_OP_TYPE_RET;
845 		op->cycles = 2;
846 		r_strbuf_setf (&op->esil, "0x%x,wreg,=,tos,pc,=,", *(ut16 *)buf & 0xff);
847 		return op->size;
848 	case 0xb: //andlw
849 		op->type = R_ANAL_OP_TYPE_AND;
850 		op->cycles = 1;
851 		r_strbuf_setf (&op->esil, "0x%x,wreg,&=,$z,z,:=,7,$s,n,:=,", *(ut16 *)buf & 0xff);
852 		return op->size;
853 	case 0xa: //xorlw
854 		op->type = R_ANAL_OP_TYPE_XOR;
855 		op->cycles = 1;
856 		r_strbuf_setf (&op->esil, "0x%x,wreg,^=,$z,z,:=,7,$s,n,:=,", *(ut16 *)buf & 0xff);
857 		return op->size;
858 	case 0x9: //iorlw
859 		op->type = R_ANAL_OP_TYPE_OR;
860 		op->cycles = 1;
861 		r_strbuf_setf (&op->esil, "0x%x,wreg,^=,$z,z,:=,7,$s,n,:=,", *(ut16 *)buf & 0xff);
862 		return op->size;
863 	case 0x8: //sublw
864 		op->type = R_ANAL_OP_TYPE_SUB;
865 		op->cycles = 1;
866 		//TODO add support for dc flag
867 		r_strbuf_setf (&op->esil, "wreg,0x%x,-,wreg,=,$z,z,:=,7,$s,n,:=,7,$c,c,:=,7,$o,ov,:=,", *(ut16 *)buf & 0xff);
868 		return op->size;
869 	};
870 
871 	switch (b >> 6) { //LFSR
872 	case 0x3b8:       //lfsr
873 		if (len < 4) {
874 			goto beach;
875 		}
876 		if (dword_instr >> 28 != 0xf) {
877 			goto beach;
878 		}
879 		op->size = 4;
880 		op->type = R_ANAL_OP_TYPE_LOAD;
881 		return op->size;
882 	};
883 	switch (b >> 10) { //DAF_T
884 	case 0x17:	//subwf
885 	case 0x16:	//subwfb
886 	case 0x15:	//subfwb
887 	case 0x13:	//dcfsnz
888 	case 0xb:	//decfsz
889 	case 0x1:	//decf
890 		op->type = R_ANAL_OP_TYPE_SUB;
891 		return op->size;
892 	case 0x14: //movf
893 		op->type = R_ANAL_OP_TYPE_MOV;
894 		return op->size;
895 	case 0x12: //infsnz
896 	case 0xf:  //incfsz
897 	case 0xa:  //incf
898 	case 0x8:  //addwfc
899 		op->type = R_ANAL_OP_TYPE_ADD;
900 		return op->size;
901 	case 0x9: //addwf
902 		op->cycles = 1;
903 		op->type = R_ANAL_OP_TYPE_ADD;
904 		return op->size;
905 	case 0x11: //rlncf
906 	case 0xd:  //rlcf
907 		op->type = R_ANAL_OP_TYPE_ROL;
908 		return op->size;
909 	case 0x10: //rrncf
910 	case 0xc:  //rrcf
911 		op->type = R_ANAL_OP_TYPE_ROR;
912 		return op->size;
913 	case 0xe: //swapf
914 		op->type = R_ANAL_OP_TYPE_UNK;
915 		return op->size;
916 	case 0x7: //comf
917 		op->type = R_ANAL_OP_TYPE_CPL;
918 		return op->size;
919 	case 0x6: //xorwf
920 		op->type = R_ANAL_OP_TYPE_XOR;
921 		return op->size;
922 	case 0x5: //andwf
923 		op->type = R_ANAL_OP_TYPE_AND;
924 		return op->size;
925 	case 0x4: //iorwf
926 		op->type = R_ANAL_OP_TYPE_OR;
927 		return op->size;
928 	};
929 	switch (b >> 9) { //AF_T
930 	case 0x37:	//movwf
931 		op->type = R_ANAL_OP_TYPE_STORE;
932 		return op->size;
933 	case 0x36: //negf
934 	case 0x35: //clrf
935 	case 0x34: //setf
936 		op->type = R_ANAL_OP_TYPE_UNK;
937 		return op->size;
938 	case 0x33: //tstfsz
939 		op->type = R_ANAL_OP_TYPE_CJMP;
940 		return op->size;
941 	case 0x32: //cpfsgt
942 	case 0x31: //cpfseq
943 	case 0x30: //cpfslt
944 		op->type = R_ANAL_OP_TYPE_CMP;
945 		return op->size;
946 	case 0x1: //mulwf
947 		op->type = R_ANAL_OP_TYPE_MUL;
948 		return op->size;
949 	};
950 	switch (b >> 4) {
951 	case 0x10: //movlb
952 		op->type = R_ANAL_OP_TYPE_LOAD;
953 		op->cycles = 1;
954 		r_strbuf_setf (&op->esil, "0x%x,bsr,=,", *(ut16 *)buf & 0xf);
955 		return op->size;
956 	};
957 	switch (b) {
958 	case 0xff: //reset
959 	case 0x7:  //daw
960 	case 0x4:  //clwdt
961 	case 0x3:  //sleep
962 		op->type = R_ANAL_OP_TYPE_UNK;
963 		return op->size;
964 	case 0x13: //return
965 		op->type = R_ANAL_OP_TYPE_RET;
966 		op->cycles = 2;
967 		r_strbuf_setf (&op->esil, "tos,pc,=,");
968 		return op->size;
969 	case 0x12: //return
970 		op->type = R_ANAL_OP_TYPE_RET;
971 		op->cycles = 2;
972 		r_strbuf_setf (&op->esil, "tos,pc,=");
973 		return op->size;
974 	case 0x11: //retfie
975 	case 0x10: //retfie
976 		op->type = R_ANAL_OP_TYPE_RET;
977 		return op->size;
978 	case 0xf: //tblwt
979 	case 0xe: //tblwt
980 	case 0xd: //tblwt
981 	case 0xc: //tblwt
982 		op->type = R_ANAL_OP_TYPE_LOAD;
983 		return op->size;
984 	case 0xb: //tblrd
985 	case 0xa: //tblrd
986 	case 0x9: //tblrd
987 	case 0x8: //tblrd
988 		op->type = R_ANAL_OP_TYPE_STORE;
989 		return op->size;
990 	case 0x6: //pop
991 		op->type = R_ANAL_OP_TYPE_POP;
992 		return op->size;
993 	case 0x5: //push
994 		op->type = R_ANAL_OP_TYPE_PUSH;
995 		return op->size;
996 	case 0x0: //nop
997 		op->type = R_ANAL_OP_TYPE_NOP;
998 		op->cycles = 1;
999 		r_strbuf_setf (&op->esil, ",");
1000 		return op->size;
1001 	};
1002 beach:
1003 	op->type = R_ANAL_OP_TYPE_ILL;
1004 	return op->size;
1005 }
1006 
anal_pic_midrange_set_reg_profile(RAnal * esil)1007 static bool anal_pic_midrange_set_reg_profile (RAnal *esil) {
1008 	const char *p = \
1009 		"=PC	pc\n"
1010 		"=SP	stkptr\n"
1011 		"=A0	porta\n"
1012 		"=A1	portb\n"
1013 		"gpr	indf0	.8	0	0\n"
1014 		"gpr	indf1	.8	1	0\n"
1015 		"gpr	pcl		.8	2	0\n"
1016 		"gpr	status	.8	3	0\n"
1017 		"flg	c		.1	3.0	0\n"
1018 		"flg	dc		.1	3.1	0\n"
1019 		"flg	z		.1	3.2	0\n"
1020 		"flg	pd		.1	3.3	0\n"
1021 		"flg	to		.1	3.4	0\n"
1022 		"gpr	fsr0l	.8	4	0\n"
1023 		"gpr	fsr0h	.8	5	0\n"
1024 		"gpr	fsr1l	.8	6	0\n"
1025 		"gpr	fsr1h	.8	7	0\n"
1026 		"gpr	bsr		.8	8	0\n"
1027 		"gpr	wreg	.8	9	0\n"
1028 		"gpr	pclath	.8	10	0\n"
1029 		"gpr	intcon	.8	11	0\n"
1030 		"gpr	pc		.16	12	0\n"
1031 		"gpr	stkptr	.8	14	0\n"
1032 		"gpr	_sram	.32 15	0\n"
1033 		"gpr	_stack	.32 19	0\n";
1034 	return r_reg_set_profile_string (esil->reg, p);
1035 }
1036 
anal_pic_pic18_set_reg_profile(RAnal * esil)1037 static bool anal_pic_pic18_set_reg_profile(RAnal *esil) {
1038 	const char *p =
1039 		"#pc lives in nowhere actually"
1040 		"=PC	pc\n"
1041 		"=SP	tos\n"
1042 		"=A0	porta\n"
1043 		"=A1	portb\n"
1044 		"gpr	pc	.32	0	0\n"
1045 		"gpr	pcl	.8	0	0\n"
1046 		"gpr	pclath	.8	1	0\n"
1047 		"gpr	pclatu	.8	2	0\n"
1048 		"#bsr max is 0b111\n"
1049 		"gpr	bsr	.8	4	0\n"
1050 		"#tos doesn't exist\n"
1051 		"#general rule of thumb any register of size >8 bits has no existence\n"
1052 		"gpr	tos	.32	5	0\n"
1053 		"gpr	tosl	.8	5	0\n"
1054 		"gpr	tosh	.8	6	0\n"
1055 		"gpr	tosu	.8	7	0\n"
1056 
1057 		"gpr	indf0	.16	9	0\n"
1058 		"gpr	fsr0	.12	9	0\n"
1059 		"gpr	fsr0l	.8	9	0\n"
1060 		"gpr	fsr0h	.8	10	0\n"
1061 		"gpr	indf1	.16	11	0\n"
1062 		"gpr	fsr1	.12	11	0\n"
1063 		"gpr	fsr1l	.8	11	0\n"
1064 		"gpr	fsr1h	.8	12	0\n"
1065 		"gpr	indf2	.16	13	0\n"
1066 		"gpr	fsr2	.12	13	0\n"
1067 		"gpr	frs2l	.8	13	0\n"
1068 		"gpr	fsr2h	.8	14	0\n"
1069 		"gpr	tblptr	.22	15	0\n"
1070 		"gpr	tblptrl	.8	15	0\n"
1071 		"gpr	tblptrh	.8	16	0\n"
1072 		"gpr	tblptru	.8	17	0\n"
1073 		"gpr	rcon	.8	18	0\n"
1074 		"gpr	memcon	.8	19	0\n"
1075 		"gpr	intcon	.8	20	0\n"
1076 		"gpr	intcon2	.8	21	0\n"
1077 		"gpr	intcon3	.8	22	0\n"
1078 		"gpr	pie1	.8	23	0\n"
1079 		"gpr	porta	.7	29	0\n"
1080 		"gpr	trisa	.8	30	0\n"
1081 		"gpr	portb	.8	33	0\n"
1082 		"gpr	tisb	.8	34	0\n"
1083 		"gpr	latb	.8	35	0\n"
1084 		"gpr	portc	.8	36	0\n"
1085 		"gpr	trisc	.8	37	0\n"
1086 		"gpr	latc	.8	38	0\n"
1087 		"gpr	portd	.8	39	0\n"
1088 		"gpr	trisd	.8	40	0\n"
1089 		"gpr	latd	.8	41	0\n"
1090 		"gpr	pspcon	.8	42	0\n"
1091 		"gpr	porte	.8	43	0\n"
1092 		"gpr	trise	.8	44	0\n"
1093 		"gpr	late	.8	45	0\n"
1094 		"gpr	t0con	.8	46	0\n"
1095 		"gpr	t1con	.8	47	0\n"
1096 		"gpr	t2con	.8	48	0\n"
1097 		"gpr	tmr1h	.8	50	0\n"
1098 		"gpr	tmr0h	.8	51	0\n"
1099 		"gpr	tmr1l	.8	52	0\n"
1100 		"gpr	tmr2	.8	53	0\n"
1101 		"gpr	pr2	.8	54	0\n"
1102 		"gpr	ccpr1h	.8	55	0\n"
1103 		"gpr	postinc2 .8	56	0\n"
1104 		"gpr	ccpr1l	.8	57	0\n"
1105 		"gpr	postdec2 .8	58	0\n"
1106 		"gpr	ccp1con	.8	59	0\n"
1107 		"gpr	preinc2	.8	60	0\n"
1108 		"gpr	ccpr2h	.8	61	0\n"
1109 		"gpr	plusw2	.8	62	0\n"
1110 		"gpr	ccpr2l	.8	63	0\n"
1111 		"gpr	ccp2con	.8	64	0\n"
1112 		"gpr	status	.8	65	0\n"
1113 		"flg	c	.1	.520	0\n"
1114 		"flg	dc	.1	.521	0\n"
1115 		"flg	z	.1	.522	0\n"
1116 		"flg	ov	.1	.523	0\n"
1117 		"flg	n	.1	.524	0\n"
1118 		"gpr	prod	.16	66	0\n"
1119 		"gpr	prodl	.8	66	0\n"
1120 		"gpr	prodh	.8	67	0\n"
1121 		"gpr	osccon	.8	68	0\n"
1122 		"gpr	tmr3h	.8	69	0\n"
1123 		"gpr	lvdcon	.8	70	0\n"
1124 		"gpr	tmr3l	.8	71	0\n"
1125 		"gpr	wdtcon	.8	72	0\n"
1126 		"gpr	t3con	.8	73	0\n"
1127 		"gpr	spbrg	.8	74	0\n"
1128 		"gpr	postinc0 .8	75	0\n"
1129 		"gpr	rcreg	.8	76	0\n"
1130 		"gpr	postdec0 .8	77	0\n"
1131 		"gpr	txreg	.8	78	0\n"
1132 		"gpr	preinc0	.8	79	0\n"
1133 		"gpr	txsta	.8	80	0\n"
1134 		"gpr	plusw0	.8	81	0\n"
1135 		"gpr	rcsta	.8	82	0\n"
1136 		"gpr	sspbuf	.8	83	0\n"
1137 		"gpr	wreg	.8	84	0\n"
1138 		"gpr	sspadd	.8	85	0\n"
1139 		"gpr	sspstat	.8	86	0\n"
1140 		"gpr	postinc1 .8	87	0\n"
1141 		"gpr	sspcon1	.8	88	0\n"
1142 		"gpr	postdec1 .8	89	0\n"
1143 		"gpr	sspcon2	.8	90	0\n"
1144 		"gpr	preinc1	.8	91	0\n"
1145 		"gpr	adresh	.8	92	0\n"
1146 		"gpr	plusw1	.8	93	0\n"
1147 		"gpr	adresl	.8	94	0\n"
1148 		"gpr	adcon0	.8	95	0\n"
1149 		"#stkprt max is 0b11111\n"
1150 		"gpr	stkptr	.8	96	0\n"
1151 		"gpr	tablat	.8	14	0\n";
1152 
1153 	return r_reg_set_profile_string (esil->reg, p);
1154 }
1155 
1156 
anal_pic_op(RAnal * anal,RAnalOp * op,ut64 addr,const ut8 * buf,int len,RAnalOpMask mask)1157 static int anal_pic_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len, RAnalOpMask mask) {
1158 	if (anal->cpu && strcasecmp (anal->cpu, "baseline") == 0) {
1159 		// TODO: implement
1160 		return -1;
1161 	}
1162 	if (anal->cpu && strcasecmp (anal->cpu, "midrange") == 0) {
1163 		return anal_pic_midrange_op (anal, op, addr, buf, len);
1164 	}
1165 	if (anal->cpu && strcasecmp (anal->cpu, "pic18") == 0) {
1166 		return anal_pic_pic18_op (anal, op, addr, buf, len);
1167 	}
1168 	return -1;
1169 }
1170 
anal_pic_set_reg_profile(RAnal * anal)1171 static bool anal_pic_set_reg_profile(RAnal *anal) {
1172 	if (anal->cpu && strcasecmp (anal->cpu, "baseline") == 0) {
1173 		// TODO: We are using the midrange profile as the baseline
1174 		return anal_pic_midrange_set_reg_profile (anal);
1175 	}
1176 	if (anal->cpu && strcasecmp (anal->cpu, "midrange") == 0) {
1177 		return anal_pic_midrange_set_reg_profile (anal);
1178 	}
1179 	if (anal->cpu && strcasecmp (anal->cpu, "pic18") == 0) {
1180 		return anal_pic_pic18_set_reg_profile (anal);
1181 	}
1182 	return false;
1183 }
1184 
1185 RAnalPlugin r_anal_plugin_pic = {
1186 	.name = "pic",
1187 	.desc = "PIC analysis plugin",
1188 	.license = "LGPL3",
1189 	.arch = "pic",
1190 	.bits = 8,
1191 	.op = &anal_pic_op,
1192 	.set_reg_profile = &anal_pic_set_reg_profile,
1193 	.esil = true
1194 };
1195 
1196 #ifndef R2_PLUGIN_INCORE
1197 R_API RLibStruct radare_plugin = {
1198 	.type = R_LIB_TYPE_ANAL,
1199 	.data = &r_anal_plugin_pic,
1200 	.version = R2_VERSION
1201 };
1202 #endif
1203