1 /* radare - LGPL - Copyright 2014-2019 - pancake */
2
3 #include <r_reg.h>
4
5 #undef Z
6 #undef S
7 #undef C
8 #undef O
9 #undef P
10 #define Z f->z
11 #define S f->s
12 #define C f->c
13 #define O f->o
14 #define P f->p
15
r_reg_cond_get(RReg * reg,const char * name)16 R_API RRegItem *r_reg_cond_get(RReg *reg, const char *name) {
17 int i = R_REG_TYPE_GPR;
18 RListIter *iter;
19 RRegItem *r;
20 r_return_val_if_fail (reg && name, NULL);
21
22 r_list_foreach (reg->regset[i].regs, iter, r) {
23 if (r->flags && !strcmp (name, r->flags)) {
24 return r;
25 }
26 }
27 return NULL;
28 }
29
r_reg_cond_get_value(RReg * r,const char * name)30 R_API int r_reg_cond_get_value(RReg *r, const char *name) {
31 return (int)r_reg_get_value (r, r_reg_cond_get (r, name)) ? 1 : 0;
32 }
33
r_reg_cond_set(RReg * r,const char * name,bool val)34 R_API bool r_reg_cond_set(RReg *r, const char *name, bool val) {
35 RRegItem *item = r_reg_cond_get (r, name);
36 if (item) {
37 r_reg_set_value (r, item, val);
38 return true;
39 }
40 // eprintf ("Cannot find '%s'\n", name);
41 return false;
42 }
43
r_reg_cond_to_string(int n)44 R_API const char *r_reg_cond_to_string(int n) {
45 const char *cs[] = {
46 "eq", "ne", "cf", "neg", "of", "hi", "he",
47 "lo", "loe", "ge", "gt", "lt", "le"
48 };
49 if (n < 0 || (n > (sizeof (cs) / sizeof (*cs)) - 1)) {
50 return NULL;
51 }
52 return cs[n];
53 }
54
r_reg_cond_from_string(const char * str)55 R_API int r_reg_cond_from_string(const char *str) {
56 if (!strcmp (str, "eq")) {
57 return R_REG_COND_EQ;
58 }
59 if (!strcmp (str, "ne")) {
60 return R_REG_COND_NE;
61 }
62 if (!strcmp (str, "cf")) {
63 return R_REG_COND_CF;
64 }
65 if (!strcmp (str, "neg")) {
66 return R_REG_COND_NEG;
67 }
68 if (!strcmp (str, "of")) {
69 return R_REG_COND_OF;
70 }
71 if (!strcmp (str, "hi")) {
72 return R_REG_COND_HI;
73 }
74 if (!strcmp (str, "he")) {
75 return R_REG_COND_HE;
76 }
77 if (!strcmp (str, "lo")) {
78 return R_REG_COND_LO;
79 }
80 if (!strcmp (str, "loe")) {
81 return R_REG_COND_LOE;
82 }
83 if (!strcmp (str, "ge")) {
84 return R_REG_COND_GE;
85 }
86 if (!strcmp (str, "gt")) {
87 return R_REG_COND_GT;
88 }
89 if (!strcmp (str, "lt")) {
90 return R_REG_COND_LT;
91 }
92 if (!strcmp (str, "le")) {
93 return R_REG_COND_LE;
94 }
95 // TODO: move this into core
96 eprintf ("| Usage: drc[=] [condition](=1,0)\n"
97 "| eq equal\n"
98 "| ne not equal\n"
99 "| cf carry flag set\n"
100 "| neg negative value (has sign)\n"
101 "| of overflow\n"
102 "|unsigned:\n"
103 "| hi higher\n"
104 "| he higher or equal\n"
105 "| lo lower\n"
106 "| loe lower or equal\n"
107 "|signed:\n"
108 "| ge greater or equal\n"
109 "| gt greater than\n"
110 "| le less or equal\n"
111 "| lt less than\n");
112 return -1;
113 }
114
r_reg_cond_bits(RReg * r,int type,RRegFlags * f)115 R_API int r_reg_cond_bits(RReg *r, int type, RRegFlags *f) {
116 switch (type) {
117 case R_REG_COND_EQ: return Z;
118 case R_REG_COND_NE: return !Z;
119 case R_REG_COND_CF: return C;
120 case R_REG_COND_NEG: return S;
121 case R_REG_COND_OF:
122 return O;
123 // unsigned
124 case R_REG_COND_HI: return (!Z && C); // HIGHER
125 case R_REG_COND_HE: return Z || (!Z && C); // HIGHER OR EQUAL
126 case R_REG_COND_LO: return (Z || !C); // LOWER
127 case R_REG_COND_LOE:
128 return (Z || !C); // LOWER OR EQUAL
129 // signed
130 case R_REG_COND_GE: return ((S && O) || (!S && !O));
131 case R_REG_COND_GT: return ((S && !Z && O) || (!S && !Z && !O));
132 case R_REG_COND_LT: return ((S && !O) || (!S && O));
133 case R_REG_COND_LE: return (Z || (S && !O) || (!S && O));
134 }
135 return false;
136 }
137
r_reg_cond_bits_set(RReg * r,int type,RRegFlags * f,bool v)138 R_API bool r_reg_cond_bits_set(RReg *r, int type, RRegFlags *f, bool v) {
139 switch (type) {
140 case R_REG_COND_EQ: Z = v; break;
141 case R_REG_COND_NE: Z = !v; break;
142 case R_REG_COND_CF: C = v; break;
143 case R_REG_COND_NEG: S = v; break;
144 case R_REG_COND_OF: O = v; break;
145 case R_REG_COND_HI:
146 if (v) {
147 Z = 0;
148 C = 1;
149 } else {
150 Z = 1;
151 C = 0;
152 }
153 break;
154 case R_REG_COND_HE:
155 if (v) {
156 Z = 1;
157 } else {
158 Z = 0;
159 C = 1;
160 }
161 break;
162 case R_REG_COND_LO:
163 if (v) {
164 Z = 1;
165 C = 0;
166 } else {
167 Z = 0;
168 C = 1;
169 }
170 break;
171 case R_REG_COND_LOE:
172 if (v) {
173 Z = 1;
174 C = 0;
175 } else {
176 Z = 0;
177 C = 1;
178 }
179 break;
180 // signed
181 case R_REG_COND_GE:
182 if (v) {
183 S = O = 1;
184 } else {
185 S = 1;
186 O = 0;
187 }
188 break;
189 case R_REG_COND_GT:
190 if (v) {
191 S = 1;
192 Z = 0;
193 O = 1;
194 } else {
195 S = 0;
196 Z = 1;
197 O = 0;
198 }
199 break;
200 case R_REG_COND_LT:
201 if (v) {
202 S = 1;
203 O = 0;
204 } else {
205 S = 1;
206 O = 1;
207 }
208 break;
209 case R_REG_COND_LE:
210 if (v) {
211 S = 0;
212 Z = 1;
213 O = 0;
214 } else {
215 S = 1;
216 Z = 0;
217 O = 1;
218 }
219 break;
220 default:
221 return false;
222 }
223 return true;
224 }
225
r_reg_cond(RReg * r,int type)226 R_API int r_reg_cond(RReg *r, int type) {
227 RRegFlags f = { 0 };
228 r_reg_cond_retrieve (r, &f);
229 return r_reg_cond_bits (r, type, &f);
230 }
231
r_reg_cond_retrieve(RReg * r,RRegFlags * f)232 R_API RRegFlags *r_reg_cond_retrieve(RReg *r, RRegFlags *f) {
233 if (!f) {
234 f = R_NEW0 (RRegFlags);
235 }
236 if (!f) {
237 return NULL;
238 }
239 f->s = r_reg_cond_get_value (r, "sign"); // sign, negate flag, less than zero
240 f->z = r_reg_cond_get_value (r, "zero"); // zero flag
241 f->c = r_reg_cond_get_value (r, "carry"); // carry flag
242 f->o = r_reg_cond_get_value (r, "overflow"); // overflow flag
243 f->p = r_reg_cond_get_value (r, "parity"); // parity // intel only
244 return f;
245 }
246
r_reg_cond_apply(RReg * r,RRegFlags * f)247 R_API void r_reg_cond_apply(RReg *r, RRegFlags *f) {
248 r_return_if_fail (r && f);
249 r_reg_cond_set (r, "sign", f->s);
250 r_reg_cond_set (r, "zero", f->z);
251 r_reg_cond_set (r, "carry", f->c);
252 r_reg_cond_set (r, "overflow", f->o);
253 r_reg_cond_set (r, "parity", f->p);
254 }
255