1 /* radare - LGPL - Copyright 2017-2019 - wargio */
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 #include <r_lib.h>
8 #include <r_util.h>
9 #include <r_flag.h>
10 #include <r_anal.h>
11 #include <r_parse.h>
12
replace(int argc,const char * argv[],char * newstr)13 static bool replace(int argc, const char *argv[], char *newstr) {
14 int i,j,k;
15 struct {
16 char *op;
17 char *str;
18 } ops[] = {
19 { "add", "A += B"},
20 { "adc", "A += B + carry"},
21 { "adiw", "A+1:A += B"},
22 { "sub", "A -= B"},
23 { "subi", "A -= B"},
24 { "sbc", "A -= (B + carry)"},
25 { "sbci", "A -= (B + carry)"},
26 { "sbiw", "A+1:A -= B"},
27 { "and", "A &= B"},
28 { "andi", "A &= B"},
29 { "or", "A |= B"},
30 { "ori", "A |= B"},
31 { "eor", "A ^= B"},
32 { "com", "A = 0xff - A"},
33 { "neg", "A = -A"},
34 { "sbr", "A |= B"},
35 { "cbr", "A &= (0xff - B)"},
36 { "inc", "A++"},
37 { "dec", "A--"},
38 { "tst", "A &= A"},
39 { "clr", "A ^= A"},
40 { "ser", "A = 0xff"},
41 { "mul", "r1:r0 = A * B"},
42 { "rjmp", "goto A"},
43 { "ijmp", "goto z"},
44 { "jmp", "goto A"},
45 { "rcall", "goto A"},
46 { "icall", "goto z"},
47 { "call", "goto A"},
48 { "ret", "return"},
49 { "iret", "return_interrupt()"},
50 { "cp", "var = A - B"},
51 { "cpc", "var = A - B - carry"},
52 { "cpi", "var = A - B"},
53 { "breq", "if(!var) goto A"},
54 { "brne", "if(var) goto A"},
55 { "brsh", "if(var >= 0) goto A"},
56 { "brlo", "if(var < 0) goto A"},
57 { "brmi", "if(var < 0) goto A"},
58 { "brpl", "if(var > 0) goto A"},
59 { "brge", "if(var >= 0) goto A"},
60 { "brlt", "if(var < 0) goto A"},
61 { "mov", "A = B"},
62 { "movw", "A+1:A = B+1:B"},
63 { "ldi", "A = B"},
64 { "lds", "A = *(B)"},
65 { "ld", "A = *(B)"},
66 { "ldd", "A = *(B)"},
67 { "lpm", "r0 = z"},
68 { "in", "A = B"},
69 { "out", "A = B"},
70 { "push", "push(A)"},
71 { "pop", "A = pop()"},
72 { "lsl", "A <<= 1"},
73 { "lsr", "A >>= 1"},
74 { "rol", "A = (A << 1) | (A >> 7)"},
75 { "ror", "A = (A << 7) | (A >> 1)"},
76 { "asr", "A >>= 1"},
77 { "swap", "A = ((A & 0xf0) >> 4) | ((A & 0x0f) << 4)"},
78 { "sec", "c = 1"},
79 { "clc", "c = 0"},
80 { "sen", "n = 1"},
81 { "cln", "n = 0"},
82 { "sez", "z = 1"},
83 { "clz", "z = 0"},
84 { "sei", "i = 1"},
85 { "cli", "i = 0"},
86 { "ses", "s = 1"},
87 { "cls", "s = 0"},
88 { "sev", "v = 1"},
89 { "clv", "v = 0"},
90 { "set", "t = 1"},
91 { "clt", "t = 0"},
92 { "seh", "h = 1"},
93 { "clh", "h = 0"},
94 { "nop", ""},
95 { "halt", "_halt()"},
96 { "wdr", "_watchdog_reset()"},
97 { "std", "*(A) = B"},
98 { "st", "*(A) = B"},
99 { "sts", "*(A) = B"},
100 { NULL }
101 };
102
103 for (i = 0; ops[i].op != NULL; i++) {
104 if (!strcmp (ops[i].op, argv[0])) {
105 if (newstr != NULL) {
106 for (j = k = 0; ops[i].str[j] != '\0'; j++, k++) {
107 if (ops[i].str[j] >= 'A' && ops[i].str[j] <= 'J') {
108 const char *w = argv[ops[i].str[j] - '@'];
109 if (w != NULL) {
110 strcpy (newstr + k, w);
111 k += strlen(w) - 1;
112 }
113 } else {
114 newstr[k] = ops[i].str[j];
115 }
116 }
117 newstr[k] = '\0';
118 }
119 return true;
120 }
121 }
122
123 /* TODO: this is slow */
124 if (newstr != NULL) {
125 newstr[0] = '\0';
126 for (i = 0; i < argc; i++) {
127 strcat (newstr, argv[i]);
128 strcat (newstr, (i == 0 || i == argc - 1) ? " ":", ");
129 }
130 }
131
132 return false;
133 }
134
135 #define WSZ 128
parse(RParse * p,const char * data,char * str)136 static int parse(RParse *p, const char *data, char *str) {
137 int i, len = strlen (data);
138 char w0[WSZ];
139 char w1[WSZ];
140 char w2[WSZ];
141 char w3[WSZ];
142 char w4[WSZ];
143 char *buf, *ptr, *optr;
144
145 // malloc can be slow here :?
146 if (!(buf = malloc (len + 1))) {
147 return false;
148 }
149 memcpy (buf, data, len + 1);
150
151 r_str_trim (buf);
152 if (*buf) {
153 w0[0] = '\0';
154 w1[0] = '\0';
155 w2[0] = '\0';
156 w3[0] = '\0';
157 w4[0] = '\0';
158 ptr = strchr (buf, ' ');
159 if (!ptr) {
160 ptr = strchr (buf, '\t');
161 }
162 if (ptr) {
163 *ptr = '\0';
164 for (++ptr; *ptr == ' '; ptr++) {
165 //nothing to see here
166 }
167 strncpy (w0, buf, WSZ - 1);
168 strncpy (w1, ptr, WSZ - 1);
169
170 optr = ptr;
171 ptr = strchr (ptr, ',');
172 if (ptr) {
173 *ptr = '\0';
174 for (++ptr; *ptr == ' '; ptr++) {
175 //nothing to see here
176 }
177 strncpy (w1, optr, WSZ - 1);
178 strncpy (w2, ptr, WSZ - 1);
179 optr = ptr;
180 ptr = strchr (ptr, ',');
181 if (ptr) {
182 *ptr = '\0';
183 for (++ptr; *ptr == ' '; ptr++) {
184 //nothing to see here
185 }
186 strncpy (w2, optr, WSZ - 1);
187 strncpy (w3, ptr, WSZ - 1);
188 optr = ptr;
189 // bonus
190 ptr = strchr (ptr, ',');
191 if (ptr) {
192 *ptr = '\0';
193 for (++ptr; *ptr == ' '; ptr++) {
194 //nothing to see here
195 }
196 strncpy (w3, optr, WSZ - 1);
197 strncpy (w4, ptr, WSZ - 1);
198 }
199 }
200 }
201 } else {
202 strncpy (w0, buf, WSZ - 1);
203 }
204 {
205 const char *wa[] = { w0, w1, w2, w3, w4 };
206 int nw = 0;
207 for (i = 0; i < 5; i++) {
208 if (wa[i][0] != '\0') {
209 nw++;
210 }
211 }
212 (void)replace (nw, wa, str);
213 }
214 }
215 free (buf);
216 return true;
217 }
218
219 RParsePlugin r_parse_plugin_avr_pseudo = {
220 .name = "avr.pseudo",
221 .desc = "AVR pseudo syntax",
222 .parse = parse
223 };
224
225 #ifndef R2_PLUGIN_INCORE
226 R_API RLibStruct radare_plugin = {
227 .type = R_LIB_TYPE_PARSE,
228 .data = &r_parse_plugin_avr_pseudo,
229 .version = R2_VERSION
230 };
231 #endif
232