1 /* radare2 - LGPL - Copyright 2019 - v3l0c1r4pt0r */
2
3 #include <r_asm.h>
4 #include <r_anal.h>
5 #include <r_lib.h>
6 #include <or1k_disas.h>
7
8 struct operands {
9 ut32 rd;
10 ut32 ra;
11 ut32 rb;
12 ut32 n;
13 ut32 k1;
14 ut32 k2;
15 ut32 k;
16 ut32 i;
17 ut32 l;
18 };
19
20 static ut32 cpu[32] = {0}; /* register contents */
21 static ut32 cpu_enable; /* allows to treat only registers with known value as
22 valid */
23
24 /**
25 * \brief Convert raw N operand to complete address
26 *
27 * \param n immediate, as appearing in instruction
28 * \param mask n operand mask
29 * \param addr address of current instruction
30 *
31 * \return 64-bit address
32 */
n_oper_to_addr(ut32 n,ut32 mask,ut64 addr)33 static ut64 n_oper_to_addr(ut32 n, ut32 mask, ut64 addr) {
34 /* sign extension returns 32b unsigned N, then it is multiplied by 4, made
35 * signed to support negative offsets, added to address and made unsigned
36 * again */
37 return (ut64) ((st64) ((st32) (sign_extend(n, mask) << 2)) + addr);
38 }
39
insn_to_op(RAnal * a,RAnalOp * op,ut64 addr,insn_t * descr,insn_extra_t * extra,ut32 insn)40 static int insn_to_op(RAnal *a, RAnalOp *op, ut64 addr, insn_t *descr, insn_extra_t *extra, ut32 insn) {
41 struct operands o = {0};
42 insn_type_t type = type_of_opcode(descr, extra);
43 insn_type_descr_t *type_descr = &types[INSN_X];
44
45 /* only use type descriptor if it has some useful data */
46 if (has_type_descriptor(type) && is_type_descriptor_defined(type)) {
47 type_descr = &types[type];
48 }
49
50 if (extra == NULL) {
51 op->type = descr->insn_type;
52 } else {
53 op->type = extra->insn_type;
54 }
55
56 switch ((insn & INSN_OPCODE_MASK) >> INSN_OPCODE_SHIFT) {
57 case 0x00: /* l.j */
58 o.n = get_operand_value(insn, type_descr, INSN_OPER_N);
59 op->eob = true;
60 op->jump = n_oper_to_addr(o.n, get_operand_mask(type_descr, INSN_OPER_N),
61 addr);
62 op->delay = 1;
63 break;
64 case 0x01: /* l.jal */
65 o.n = get_operand_value(insn, type_descr, INSN_OPER_N);
66 op->eob = true;
67 op->jump = n_oper_to_addr(o.n, get_operand_mask(type_descr, INSN_OPER_N),
68 addr);
69 op->delay = 1;
70 break;
71 case 0x03: /* l.bnf */
72 o.n = get_operand_value(insn, type_descr, INSN_OPER_N);
73 op->cond = R_ANAL_COND_NE;
74 op->jump = n_oper_to_addr(o.n, get_operand_mask(type_descr, INSN_OPER_N),
75 addr);
76 op->fail = addr + 8;
77 op->delay = 1;
78 break;
79 case 0x04: /* l.bf */
80 o.n = get_operand_value(insn, type_descr, INSN_OPER_N);
81 op->cond = R_ANAL_COND_EQ;
82 op->jump = n_oper_to_addr(o.n, get_operand_mask(type_descr, INSN_OPER_N),
83 addr);
84 op->fail = addr + 8;
85 op->delay = 1;
86 break;
87 case 0x11: /* l.jr */
88 o.rb = get_operand_value(insn, type_descr, INSN_OPER_B);
89 op->eob = true;
90 if (cpu_enable & (1 << o.rb)) {
91 op->jump = cpu[o.rb];
92 }
93 op->delay = 1;
94 break;
95 case 0x12: /* l.jalr */
96 o.rb = get_operand_value(insn, type_descr, INSN_OPER_B);
97 op->eob = true;
98 if (cpu_enable & (1 << o.rb)) {
99 op->jump = cpu[o.rb];
100 }
101 op->delay = 1;
102 break;
103 case 0x06: /* extended */
104 switch (insn & (1 << 16)) {
105 case 0: /* l.movhi */
106 o.rd = get_operand_value(insn, type_descr, INSN_OPER_D);
107 o.k = get_operand_value(insn, type_descr, INSN_OPER_K);
108 cpu[o.rd] = o.k << 16;
109 cpu_enable |= (1 << o.rd);
110 break;
111 case 1: /* l.macrc */
112 break;
113 }
114 break;
115 case 0x27: /* l.addi */
116 o.rd = get_operand_value(insn, type_descr, INSN_OPER_D);
117 o.ra = get_operand_value(insn, type_descr, INSN_OPER_A);
118 o.i = get_operand_value(insn, type_descr, INSN_OPER_I);
119 if (cpu_enable & (1 << o.ra) & cpu_enable & (1 << o.rd)) {
120 cpu[o.rd] = cpu[o.ra] | o.i;
121 cpu_enable |= (1 << o.rd);
122 op->ptr = cpu[o.rd];
123 op->direction = 8; /* reference */
124 }
125 break;
126 case 0x2a: /* l.ori */
127 o.rd = get_operand_value(insn, type_descr, INSN_OPER_D);
128 o.ra = get_operand_value(insn, type_descr, INSN_OPER_A);
129 o.i = get_operand_value(insn, type_descr, INSN_OPER_I);
130 if (cpu_enable & (1 << o.ra)) {
131 cpu[o.rd] = cpu[o.ra] | o.i;
132 cpu_enable |= (1 << o.rd);
133 op->ptr = cpu[o.rd];
134 op->direction = 8; /* reference */
135 }
136 break;
137 default:
138 /* if unknown instruction encountered, better forget state */
139 cpu_enable = 0;
140 }
141
142 /* temporary solution to prevent using wrong register values */
143 if ((op->type & R_ANAL_OP_TYPE_JMP) == R_ANAL_OP_TYPE_JMP) {
144 /* FIXME: handle delay slot after branches */
145 cpu_enable = 0;
146 }
147 return 4;
148 }
149
or1k_op(RAnal * a,RAnalOp * op,ut64 addr,const ut8 * data,int len,RAnalOpMask mask)150 static int or1k_op(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *data, int len, RAnalOpMask mask) {
151 ut32 insn, opcode;
152 ut8 opcode_idx;
153 insn_t *insn_descr;
154 insn_extra_t *extra_descr;
155
156 /* read instruction and basic opcode value */
157 insn = r_read_be32(data);
158 op->size = 4;
159 opcode = (insn & INSN_OPCODE_MASK);
160 opcode_idx = opcode >> INSN_OPCODE_SHIFT;
161
162 /* make sure instruction descriptor table is not overflowed */
163 if (opcode_idx >= insns_count) {
164 return op->size;
165 }
166
167 /* if instruction is marked as invalid finish processing now */
168 insn_descr = &or1k_insns[opcode_idx];
169 if (insn_descr->type == INSN_INVAL) {
170 return op->size;
171 }
172
173 /* if name is null, but extra is present, it means 6 most significant bits
174 * are not enough to decode instruction */
175 if ((insn_descr->name == NULL) && (insn_descr->extra != NULL)) {
176 extra_descr = find_extra_descriptor(insn_descr->extra, insn);
177 if (extra_descr != NULL) {
178 insn_to_op(a, op, addr, insn_descr, extra_descr, insn);
179 }
180 }
181 else {
182 /* otherwise basic descriptor is enough */
183 insn_to_op(a, op, addr, insn_descr, NULL, insn);
184 }
185
186 return op->size;
187 }
188
189 RAnalPlugin r_anal_plugin_or1k = {
190 .name = "or1k",
191 .desc = "OpenRISC 1000",
192 .license = "LGPL3",
193 .bits = 32,
194 .arch = "or1k",
195 .esil = false,
196 .op = &or1k_op,
197 };
198
199 #ifndef R2_PLUGIN_INCORE
200 R_API RLibStruct radare_plugin = {
201 .type = R_LIB_TYPE_ANAL,
202 .data = &r_anal_plugin_or1k,
203 .version = R2_VERSION
204 };
205 #endif
206