1 /* radare - LGPL - Copyright 2014 - montekki */
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 ut32 get_ins_len(ut8 opcode);
10 
tms320_c55x_plus_op(RAnal * anal,RAnalOp * op,ut64 addr,const ut8 * buf,int len)11 int tms320_c55x_plus_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len) {
12 	ut16 *ins = (ut16*)buf;
13 	ut32 ins_len;
14 
15 	if (!buf || len <= 0) {
16 		return 0;
17 	}
18 
19 	ins_len = get_ins_len(buf[0]);
20 	if (ins_len == 0) {
21 		return 0;
22 	}
23 
24 	op->addr = addr;
25 	op->size = ins_len;
26 
27 	if (ins_len == 1) {
28 		if (*ins == 0x20) {
29 			op->type = R_ANAL_OP_TYPE_NOP;
30 		} else if (*ins == 0x21) {
31 			op->type = R_ANAL_OP_TYPE_RET;
32 		}
33 	} else if (ins_len >= 4 && buf[0] == 0xD8) {
34 		//  BCC conditional absolute jump
35 		op->type = R_ANAL_OP_TYPE_CJMP;
36 		op->jump = (buf[1] << 16) | (buf[2] << 8) | buf[3];
37 	} else if (ins_len >= 2 && buf[0] == 0x6A) {
38 		//  BCC conditional relative jump
39 		op->type = R_ANAL_OP_TYPE_CJMP;
40 		op->jump = addr + ((st8)buf[1]) + ins_len;
41 	} else if (ins_len >= 3 && buf[0] == 0x9A) {
42 		// BCC conditional relative jump
43 		op->type = R_ANAL_OP_TYPE_CJMP;
44 		op->jump = addr + (st16)((buf[1] << 8) | buf[2]) + ins_len;
45 	} else if (ins_len >= 4 && buf[0] == 0x9C) {
46 		// B unconditional absolute jump
47 		op->type = R_ANAL_OP_TYPE_JMP;
48 		op->jump = (buf[1] << 16) | (buf[2] << 8) | buf[3];
49 	} else if (ins_len >= 3 && buf[0] == 0x68) {
50 		// B unconditional relative jump
51 		op->type = R_ANAL_OP_TYPE_JMP;
52 		op->jump = addr + (st16)((buf[1] << 8) | buf[2]) + ins_len;
53  	} else if (ins_len == 2 && buf[0] == 0x02) {
54 		// CALL unconditional absolute call with acumulator register ACx
55 
56 		op->type = R_ANAL_OP_TYPE_UCALL;
57 		op->fail = addr + ins_len;
58  	} else if (ins_len >= 3 && buf[0] == 0x69) {
59 		// CALL unconditional relative call
60 		op->type = R_ANAL_OP_TYPE_CALL;
61 		op->jump = addr + (st16)((buf[1] << 8) | buf[2]) + ins_len;
62  	} else if (ins_len >= 3 && buf[0] == 0x9D) {
63 		// CALL unconditional absolute call
64 		op->type = R_ANAL_OP_TYPE_CALL;
65 		op->jump = (buf[1] << 16) | (buf[2] << 8) | buf[3];
66  	} else if (ins_len >= 3 && buf[0] == 0x9B) {
67 		// CALLCC conditional relative call
68 		op->type = R_ANAL_OP_TYPE_CALL;
69 		op->jump = addr + (st16)((buf[1] << 8) | buf[2]) + ins_len;
70  	} else if (ins_len >= 4 && buf[0] == 0xD9) {
71 		// CALLCC conditional absolute call
72 		op->type = R_ANAL_OP_TYPE_CALL;
73 		op->jump = (buf[1] << 16) | (buf[2] << 8) | buf[3];
74 	} else {
75 		op->type = R_ANAL_OP_TYPE_UNK;
76 	}
77 	return op->size;
78 }
79