Rizin
unix-like reverse engineering framework and cli tools
8051_ass.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2009-2019 hmht
2 // SPDX-License-Identifier: LGPL-3.0-only
3 #include "8051_ass.h"
4 
5 /*****************************************************************************\
6  * Architecture
7  *
8  * File Contents:
9  * ## Section 1. Token parsers
10  * ## Section 2: some weird datastructure
11  * ## Section 3: token classifiers
12  * ## Section 4: Generic instruction emitters
13  * ## Section 5: Specific instruction parsing
14  * ## Section 6: mnemonic token dispatcher
15  * ## Section 7: rizin glue and mnemonic tokenization
16  *
17  * documentation date: 2019-10-04
18  * documentation date: 2019-10-14
19  *
20  * 1. Token parsers
21  *
22  * I'm sure most of this is re-inventing the wheel, (poorly, too), this is
23  * because I didn't take enough time to find a proper implementation.
24  * If you know a r2lib function that does the job it should be used instead.
25  *
26  *
27  * 2. Some weird datastructure
28  *
29  * Started out for matching strings whitespace-independently, and uses c99s
30  * (struct literal){} notation and is zero-terminated.
31  * I wrote this thing in the late hours of r2con2019 while jetlagged.
32  *
33  * Currently the last place it's used in is mnemonic matching, since I hacked
34  * in a nr-of-arguments field into the table. Whitespace-independence is
35  * currently a bug since it'll accept "n o p" as "nop"... also functions need
36  * to be renamed.
37  *
38  * One pitfall is that the match is lazy (non-greedy?) in other words, "reti"
39  * is matched by "ret", but not the other way around, so the most-specific match
40  * must come first in the list.
41  *
42  *
43  * 3. token classifiers
44  *
45  * right now mostly has functions to distinguish between argument types, and
46  * parses their data. (Some argument types, such as relative addresses and bits,
47  * require parsing to asses their validity.)
48  *
49  *
50  * 4. Generic instruction parsing
51  *
52  * I started out just writing specific parser for each
53  * mnemonic(-variant), and halfway through I started noticing a lot of
54  * code duplication, so extracted some of it.
55  * Their basic operation is simple: dump whatever you're given into the out
56  * parameter, and move the write pointer forward.
57  *
58  *
59  * 5. Specific instruction parsing
60  *
61  * Of course, in the very beginning I started out with the idea to
62  * completely generalize everything, but there were more edge cases than
63  * my small brain could handle, so I scrapped that and started punching
64  * out special parsers for each instruction variant mindlessly.
65  * The result of this approach is really glaring. Lots of duplication.
66  * There's lots of easy deduplication opportunity, and now that it's finished I
67  * have some ideas on how to do it better, but eh.
68  *
69  *
70  * 6. mnemonic token dispatcher
71  *
72  * The weird datastructure returns! with macros! it's basically just a jump
73  * table with one bit of validation.
74  *
75  *
76  * 7. Radare2 glue and mnemonic tokenization
77  *
78  * Had one look at the gb glue code and copied the lot of it without really
79  * understanding what I'm doing.
80  *
81  * also splits out the first word (asserted mnemonic) for the token dispatcher,
82  * and splits up the arguments
83  *
84 \*****************************************************************************/
85 #include <rz_util.h>
86 #include <string.h>
87 
88 /******************************************************************************
89  * ## Section 1. Generic Token parsers
90  * ------- -------------*/
91 
92 static bool parse_hexadecimal(char const *hexstr, ut16 *out) {
93  if (!hexstr || hexstr[0] != '0' || !(hexstr[1] == 'x' || hexstr[1] == 'X')) {
94  return false;
95  }
96  *out = 0;
97  char const *p;
98  for (p = hexstr + 2; p < hexstr + 6 && *p; p += 1) {
99  *out <<= 4;
100  if ('0' <= *p && *p <= '9') {
101  *out |= *p - '0';
102  } else if ('a' <= *p && *p <= 'f') {
103  *out |= *p - 'a' + 10;
104  } else if ('A' <= *p && *p <= 'F') {
105  *out |= *p - 'A' + 10;
106  } else {
107  return false;
108  }
109  }
110  return !*p;
111 }
112 
113 // FIXME: may write outside buffer
126 static bool get_arg(char const *multi, int n, char *dest) {
127  char *lastnonws = dest;
128  bool anynonws = false;
129  bool in_string = false;
130  n -= 1;
131  if (!multi)
132  return false;
133  while (n && *multi && *multi != '\n' && *multi != '\r') {
134  if (*multi == '\'')
135  in_string = !in_string;
136  if (!in_string) {
137  if (*multi == ';') {
138  return false;
139  }
140  if (*multi == ',') {
141  multi += 1;
142  n -= 1;
143  continue;
144  }
145  }
146  multi += 1;
147  }
148  if (!*multi || *multi == '\n' || *multi == '\r' || in_string) {
149  return false;
150  }
151 
152  while (*multi && (*multi == ' ' || *multi == '\t')) {
153  multi += 1;
154  }
155 
156  while (*multi && *multi != '\n' && *multi != '\r') {
157  if (*multi == '\'')
158  in_string = !in_string;
159  if (!in_string) {
160  if (*multi == ';' || *multi == ',') {
161  break;
162  }
163  if (*multi != ' ' && *multi != '\t') {
164  lastnonws = dest;
165  anynonws = true;
166  }
167  *dest = *multi;
168  dest += 1;
169  multi += 1;
170  }
171  }
172 
173  if (in_string)
174  return false;
175 
176  if (!anynonws) {
177  *dest = '\0';
178  return false;
179  }
180  *(lastnonws + 1) = '\0';
181  return true;
182 }
183 
189 static int get_arguments(char **arg, char const *arguments) {
190  size_t arglen = strlen(arguments) + 1;
191  char *tmp = malloc(arglen);
192  if (!get_arg(arguments, 1, tmp)) {
193  free(tmp);
194  tmp = 0;
195  return 0;
196  } else {
197  arg[0] = realloc(tmp, strlen(tmp) + 1);
198  tmp = 0;
199  tmp = malloc(arglen);
200  if (!get_arg(arguments, 2, tmp)) {
201  free(tmp);
202  tmp = 0;
203  return 1;
204  } else {
205  arg[1] = realloc(tmp, strlen(tmp) + 1);
206  tmp = 0;
207  tmp = malloc(arglen + 1);
208  if (!get_arg(arguments, 3, tmp)) {
209  free(tmp);
210  tmp = 0;
211  return 2;
212  } else {
213  arg[2] = realloc(tmp, strlen(tmp) + 1);
214  tmp = 0;
215  tmp = malloc(arglen + 1);
216  if (get_arg(arguments, 4, tmp)) {
217  free(tmp);
218  tmp = 0;
219  free(arg[0]);
220  arg[0] = 0;
221  free(arg[1]);
222  arg[1] = 0;
223  free(arg[2]);
224  arg[2] = 0;
225  return 4;
226  }
227  free(tmp);
228  tmp = 0;
229  return 3;
230  }
231  }
232  }
233 }
234 
238 static bool terminates_asm_line(char c) {
239  return c == '\0' || c == '\n' || c == '\r' || c == ';';
240 }
241 
245 static int str_iwhitecasecmp(char const *a, char const *b) {
246  if (!a && !b) {
247  return *a - *b;
248  }
249  while (a && b) {
250  if (!*a && !*b) {
251  break;
252  }
253  if (!*a || !*b) {
254  break;
255  }
256  if (isspace(*a)) {
257  a += 1;
258  continue;
259  }
260  if (isspace(*b)) {
261  b += 1;
262  continue;
263  }
264  if (tolower(*a) == tolower(*b)) {
265  a += 1;
266  b += 1;
267  continue;
268  }
269  break;
270  }
271  return *a - *b;
272 }
273 
274 /******************************************************************************
275  * ## Section 2: some weird datastructure
276  ------------------------*/
277 
278 typedef bool (*parse_mnem_args)(char const *const *, ut16, ut8 **);
279 
280 typedef struct {
281  char const *const pattern;
283  int args;
284 } ftable[];
285 
286 static bool pattern_match(char const *str, char const *pattern) {
287  int si = 0;
288  int ti = 0;
289  if (!pattern) {
290  return true;
291  }
292 
293  while (pattern[ti] != '\0') {
294  while (isspace(str[si]) && !isspace(pattern[ti])) {
295  si += 1;
296  }
297  if (isspace(pattern[ti])) {
298  ti += 1;
299  continue;
300  }
301  if (tolower(pattern[ti]) == tolower(str[si])) {
302  si += 1;
303  ti += 1;
304  } else {
305  return false;
306  }
307  }
308  return true;
309 }
310 
311 static parse_mnem_args match_prefix_f(int *args, char const *str, ftable const tbl) {
312  int row = 0;
313  while (tbl[row].pattern) {
314  if (pattern_match(str, tbl[row].pattern)) {
315  *args = tbl[row].args;
316  return tbl[row].res;
317  } else {
318  row += 1;
319  }
320  }
321  *args = tbl[row].args;
322  return tbl[row].res;
323 }
324 
325 /******************************************************************************
326  * ## Section 3: token classifiers
327  -----------------*/
328 
333 static bool is_indirect_reg(char const *str) {
334  if (!str) {
335  return false;
336  }
337 
338  if (str[0] == '@') {
339  return rz_str_ansi_nlen(str, 4) == 3 && tolower(str[1]) == 'r' && (str[2] == '0' || str[2] == '1');
340  }
341 
342  if (str[0] == '[') {
343  return rz_str_ansi_nlen(str, 5) == 4 && tolower(str[1]) == 'r' && (str[2] == '0' || str[2] == '1') && str[3] == ']';
344  }
345 
346  return false;
347 }
348 
352 static bool is_reg(char const *str) {
353  return str && tolower(str[0]) == 'r' && rz_str_ansi_nlen(str, 3) == 2 && '0' <= str[1] && str[1] <= '7';
354 }
355 
360 static bool relative_address(ut16 pc, ut16 address, ut8 *out) {
361  st16 diff = address - (pc + 2);
362  if (diff < INT8_MIN || INT8_MAX < diff) {
363  return false;
364  } else {
365  *out = diff;
366  return true;
367  }
368 }
369 
370 static bool resolve_immediate(char const *imm_str, ut16 *imm_out) {
371  // rz_asm resolves symbols, so does this really only need to parse hex?
372  // maybe TODO: skip leading '#' if exists?
373  return parse_hexadecimal(imm_str, imm_out);
374 }
375 
376 static bool to_address(char const *addr_str, ut16 *addr_out) {
377  // rz_asm resolves symbols, so does this really only need to parse hex?
378  // maybe TODO: check address bounds?
379  return parse_hexadecimal(addr_str, addr_out);
380 }
381 
385 static bool address_direct(char const *addr_str, ut8 *addr_out) {
386  ut16 addr_big;
387  // rz_asm resolves symbols, so does this really only need to parse hex?
388  // maybe TODO: check address bounds?
389  if (!parse_hexadecimal(addr_str, &addr_big) || (0xFF < addr_big)) {
390  return false;
391  }
392  *addr_out = addr_big;
393  return true;
394 }
395 
399 static bool address_bit(char const *addr_str, ut8 *addr_out) {
400  char *bitpart = malloc(strlen(addr_str) + 1);
401  char *bytepart = malloc(strlen(addr_str) + 1);
402  char const *separator = rz_str_lchr(addr_str, '.');
403  ut8 byte;
404  int bit;
405  bool ret = false;
406  // TODO: check if symbols are resolved properly in all cases:
407  // - symbol.2
408  // - 0x25.symbol
409  // - symbol.symbol
410  // - symbol
411  if (!separator) {
412  goto end;
413  }
414  rz_str_ncpy(bytepart, addr_str, separator - addr_str + 1);
415  bytepart[separator - addr_str + 1] = '\0';
416  rz_str_ncpy(bitpart, separator + 1, strlen(separator));
417  if (!address_direct(bytepart, &byte)) {
418  goto end;
419  }
420  if (1 < strlen(bitpart) || bitpart[0] < '0' || '7' < bitpart[0]) {
421  ret = false;
422  goto end;
423  }
424  bit = bitpart[0] - '0';
425  if (0x20 <= byte && byte < 0x30) {
426  *addr_out = (byte - 0x20) * 8 + bit;
427  ret = true;
428  } else if (0x80 <= byte && !(byte % 8)) {
429  *addr_out = byte + bit;
430  ret = true;
431  }
432 end:
433  free(bitpart);
434  bitpart = 0;
435  free(bytepart);
436  bytepart = 0;
437  return ret;
438 }
439 
444 static int register_number(char const *reg) {
445  if (is_reg(reg)) {
446  return reg[1] - '0';
447  }
448  if (is_indirect_reg(reg)) {
449  return reg[2] - '0';
450  }
451  return 8; // not register 0-7, so...
452 }
453 
454 /******************************************************************************
455  * ## Section 4: Generic instruction emmiters
456  ----------------------------*/
457 
458 static bool single_byte_instr(ut8 const instr, ut8 **out) {
459  (*out)[0] = instr;
460  *out += 1;
461  return true;
462 }
463 
464 static bool singlearg_bit(ut8 const firstbyte, char const *arg, ut8 **out) {
465  ut8 address;
466  if (!address_bit(arg, &address)) {
467  return false;
468  }
469  (*out)[0] = firstbyte;
470  (*out)[1] = address;
471  *out += 2;
472  return true;
473 }
474 
475 static bool singlearg_reladdr(ut8 const firstbyte, char const *arg, ut16 const pc, ut8 **out) {
476  ut16 address;
477  if (!to_address(arg, &address) || !relative_address(pc, address, (*out) + 1)) {
478  return false;
479  }
480  (*out)[0] = firstbyte;
481  *out += 2;
482  return true;
483 }
484 
485 static bool singlearg_direct(ut8 const firstbyte, char const *arg, ut8 **out) {
486  ut8 address;
487  if (!address_direct(arg, &address)) {
488  return false;
489  }
490  (*out)[0] = firstbyte;
491  (*out)[1] = address;
492  *out += 2;
493  return true;
494 }
495 
496 static bool singlearg_immediate(ut8 firstbyte, char const *imm_str, ut8 **out) {
497  ut16 imm;
498  if (imm_str[0] != '#' || !resolve_immediate(imm_str + 1, &imm)) {
499  return false;
500  }
501  (*out)[0] = firstbyte;
502  (*out)[1] = imm & 0x00FF;
503  *out += 2;
504  return true;
505 }
506 
507 static bool singlearg_register(ut8 firstbyte, char const *reg, ut8 **out) {
508  return single_byte_instr(firstbyte | register_number(reg), out);
509 }
510 
511 static bool single_a_arg_instr(ut8 const firstbyte, char const *arg, ut8 **out) {
512  if (rz_str_casecmp("a", arg)) {
513  return false;
514  }
515  return single_byte_instr(firstbyte, out);
516 }
517 
518 /******************************************************************************
519  * ## Section 5: Specific instruction parsing
520  ----------------------------*/
521 
522 static bool mnem_acall(char const *const *arg, ut16 pc, ut8 **out) {
523  ut16 address;
524  if (!to_address(arg[0], &address)) {
525  return false;
526  }
527  (*out)[0] = ((address & 0x0700) >> 3) | 0x11;
528  (*out)[1] = address & 0x00FF;
529  *out += 2;
530  return true;
531 }
532 
533 static bool mnem_add(char const *const *arg, ut16 pc, ut8 **out) {
534  if (rz_str_casecmp(arg[0], "a")) {
535  return false;
536  }
537  switch (arg[1][0]) {
538  case '@':
539  case '[':
540  return singlearg_register(0x26, arg[1], out);
541  break;
542  case '#':
543  return singlearg_immediate(0x24, arg[1], out);
544  }
545  if (is_reg(arg[1])) {
546  return singlearg_register(0x28, arg[1], out);
547  } else {
548  return singlearg_direct(0x25, arg[1], out);
549  }
550 }
551 
552 static bool mnem_addc(char const *const *arg, ut16 pc, ut8 **out) {
553  if (rz_str_casecmp(arg[0], "a")) {
554  return false;
555  }
556  if (is_indirect_reg(arg[1])) {
557  return singlearg_register(0x36, arg[1], out);
558  }
559  if (arg[1][0] == '#') {
560  return singlearg_immediate(0x34, arg[1], out);
561  }
562  if (is_reg(arg[1])) {
563  return singlearg_register(0x38, arg[1], out);
564  }
565  return singlearg_direct(0x35, arg[1], out);
566 }
567 
568 static bool mnem_ajmp(char const *const *arg, ut16 pc, ut8 **out) {
569  ut16 address;
570  if (!to_address(arg[0], &address)) {
571  return false;
572  }
573  (*out)[0] = ((address & 0x0700) >> 3) | 0x01;
574  (*out)[1] = address & 0x00FF;
575  *out += 2;
576  return true;
577 }
578 
579 static bool mnem_anl(char const *const *arg, ut16 pc, ut8 **out) {
580  if (!strcmp(arg[0], "c")) {
581  if (arg[1][0] == '/') {
582  return singlearg_bit(0xb0, arg[1] + 1, out);
583  }
584  return singlearg_bit(0x82, arg[1], out);
585  }
586  if (!strcmp(arg[0], "a")) {
587  if (is_indirect_reg(arg[1])) {
588  return singlearg_register(0x56, arg[1], out);
589  }
590  if (arg[1][0] == '#') {
591  return singlearg_immediate(0x54, arg[1], out);
592  }
593  if (is_reg(arg[1])) {
594  return singlearg_register(0x58, arg[1], out);
595  }
596  return singlearg_direct(0x55, arg[1], out);
597  }
598 
599  ut8 address;
600  if (!address_direct(arg[0], &address)) {
601  return false;
602  }
603  if (!rz_str_casecmp(arg[1], "a")) {
604  return singlearg_direct(0x52, arg[0], out);
605  }
606  ut16 imm;
607  if (arg[1][0] != '#' || !resolve_immediate(arg[1] + 1, &imm)) {
608  return false;
609  }
610  (*out)[0] = 0x53;
611  (*out)[1] = address;
612  (*out)[2] = imm & 0x00FF;
613  *out += 3;
614  return true;
615 }
616 
617 static bool mnem_cjne(char const *const *arg, ut16 pc, ut8 **out) {
618  ut16 address;
619  if (!to_address(arg[2], &address) || !relative_address(pc + 1, address, (*out) + 2)) {
620  return false;
621  }
622  if (!rz_str_casecmp(arg[0], "a")) {
623  if (arg[1][0] == '#') {
624  ut16 imm;
625  if (!resolve_immediate(arg[1] + 1, &imm)) {
626  return false;
627  }
628  (*out)[0] = 0xb4;
629  (*out)[1] = imm & 0x00FF;
630  // out[2] set earlier
631  *out += 3;
632  return true;
633  }
634  ut8 address;
635  if (!address_direct(arg[1], &address)) {
636  return false;
637  }
638  (*out)[0] = 0xb5;
639  (*out)[1] = address;
640  // out[2] set earlier
641  *out += 3;
642  return true;
643  }
644  if (is_reg(arg[0])) {
645  ut16 imm;
646  if (!resolve_immediate(arg[1] + 1, &imm)) {
647  return false;
648  }
649  (*out)[0] = 0xbf | register_number(arg[0]);
650  (*out)[1] = imm & 0x00FF;
651  // out[2] set earlier
652  *out += 3;
653  return true;
654  }
655  if (is_indirect_reg(arg[0])) {
656  ut16 imm;
657  if (!resolve_immediate(arg[1] + 1, &imm)) {
658  return false;
659  }
660  (*out)[0] = 0xb6 | register_number(arg[0]);
661  (*out)[1] = imm & 0x00FF;
662  // out[2] set earlier
663  *out += 3;
664  return true;
665  }
666  return false;
667 }
668 
669 static bool mnem_clr(char const *const *arg, ut16 pc, ut8 **out) {
670  if (!rz_str_casecmp("a", arg[0])) {
671  return single_byte_instr(0xe4, out);
672  }
673  if (!rz_str_casecmp("c", arg[0])) {
674  return single_byte_instr(0xc3, out);
675  }
676  return singlearg_bit(0xc2, arg[0], out);
677 }
678 
679 static bool mnem_cpl(char const *const *arg, ut16 pc, ut8 **out) {
680  if (!rz_str_casecmp("a", arg[0])) {
681  return single_byte_instr(0xf4, out);
682  }
683  if (!rz_str_casecmp("c", arg[0])) {
684  return single_byte_instr(0xb3, out);
685  }
686  return singlearg_bit(0xb2, arg[0], out);
687 }
688 
689 static bool mnem_da(char const *const *arg, ut16 pc, ut8 **out) {
690  return single_a_arg_instr(0xd4, arg[0], out);
691 }
692 
693 static bool mnem_dec(char const *const *arg, ut16 pc, ut8 **out) {
694  if (is_indirect_reg(arg[0])) {
695  return singlearg_register(0x16, arg[0], out);
696  }
697  if (is_reg(arg[0])) {
698  return singlearg_register(0x18, arg[0], out);
699  }
700  if (!rz_str_casecmp("a", arg[0])) {
701  return single_byte_instr(0x14, out);
702  }
703  return singlearg_direct(0x15, arg[0], out);
704 }
705 
706 static bool mnem_div(char const *const *arg, ut16 pc, ut8 **out) {
707  if (rz_str_casecmp("ab", arg[0])) {
708  return false;
709  }
710  return single_byte_instr(0x84, out);
711 }
712 
713 static bool mnem_djnz(char const *const *arg, ut16 pc, ut8 **out) {
714  ut16 jmp_address;
715  if (!to_address(arg[1], &jmp_address)) {
716  return false;
717  }
718  if (!relative_address(pc, jmp_address, (*out) + 2)) {
719  return false;
720  }
721 
722  if (is_reg(arg[0])) {
723  (*out)[0] = 0xd8 | register_number(arg[0]);
724  (*out)[1] = (*out)[2];
725  *out += 2;
726  return true;
727  }
728  ut8 dec_address;
729  if (!address_direct(arg[0], &dec_address)) {
730  return false;
731  }
732  (*out)[0] = 0xd5;
733  (*out)[1] = dec_address;
734  (*out)[2] -= 1;
735  *out += 3;
736  return true;
737 }
738 
739 static bool mnem_inc(char const *const *arg, ut16 pc, ut8 **out) {
740  if (is_reg(arg[0])) {
741  return singlearg_register(0x08, arg[0], out);
742  }
743  if (is_indirect_reg(arg[0])) {
744  return singlearg_register(0x06, arg[0], out);
745  }
746  if (!rz_str_casecmp("a", arg[0])) {
747  return single_byte_instr(0x04, out);
748  }
749  if (!rz_str_casecmp("dptr", arg[0])) {
750  return single_byte_instr(0xa3, out);
751  }
752  return singlearg_direct(0x05, arg[0], out);
753 }
754 
755 static bool mnem_jb(char const *const *arg, ut16 pc, ut8 **out) {
756  ut8 cmp_addr;
757  if (!address_bit(arg[0], &cmp_addr)) {
758  return false;
759  }
760  ut16 jmp_addr;
761  if (!to_address(arg[1], &jmp_addr) || !relative_address(pc + 1, jmp_addr, (*out) + 2)) {
762  return false;
763  }
764  (*out)[0] = 0x20;
765  (*out)[1] = cmp_addr;
766  // out[2] set earlier
767  *out += 3;
768  return true;
769 }
770 
771 static bool mnem_jbc(char const *const *arg, ut16 pc, ut8 **out) {
772  ut8 cmp_addr;
773  if (!address_bit(arg[0], &cmp_addr)) {
774  return false;
775  }
776  ut16 jmp_addr;
777  if (!to_address(arg[1], &jmp_addr) || !relative_address(pc + 1, jmp_addr, (*out) + 2)) {
778  return false;
779  }
780  (*out)[0] = 0x10;
781  (*out)[1] = cmp_addr;
782  // out[2] set earlier
783  *out += 3;
784  return true;
785 }
786 
787 static bool mnem_jc(char const *const *arg, ut16 pc, ut8 **out) {
788  return singlearg_reladdr(0x40, arg[0], pc, out);
789 }
790 
791 static bool mnem_jnb(char const *const *arg, ut16 pc, ut8 **out) {
792  ut8 cmp_addr;
793  if (!address_bit(arg[0], &cmp_addr)) {
794  return false;
795  }
796  ut16 jmp_addr;
797  if (!to_address(arg[1], &jmp_addr) || !relative_address(pc + 1, jmp_addr, (*out) + 2)) {
798  return false;
799  }
800  (*out)[0] = 0x30;
801  (*out)[1] = cmp_addr;
802  // out[2] set earlier
803  *out += 3;
804  return true;
805 }
806 
807 static bool mnem_jnc(char const *const *arg, ut16 pc, ut8 **out) {
808  return singlearg_reladdr(0x50, arg[0], pc, out);
809 }
810 
811 static bool mnem_jnz(char const *const *arg, ut16 pc, ut8 **out) {
812  return singlearg_reladdr(0x70, arg[0], pc, out);
813 }
814 
815 static bool mnem_jz(char const *const *arg, ut16 pc, ut8 **out) {
816  return singlearg_reladdr(0x60, arg[0], pc, out);
817 }
818 
819 static bool mnem_lcall(char const *const *arg, ut16 pc, ut8 **out) {
820  ut16 address;
821  if (!to_address(arg[0], &address)) {
822  return false;
823  }
824  (*out)[0] = 0x12;
825  (*out)[1] = ((address & 0xFF00) >> 8) & 0x00FF;
826  (*out)[2] = address & 0x00FF;
827  *out += 3;
828  return true;
829 }
830 
831 static bool mnem_ljmp(char const *const *arg, ut16 pc, ut8 **out) {
832  ut16 address;
833  if (!to_address(arg[0], &address)) {
834  return false;
835  }
836  (*out)[0] = 0x02;
837  (*out)[1] = ((address & 0xFF00) >> 8) & 0x00FF;
838  (*out)[2] = address & 0x00FF;
839  *out += 3;
840  return true;
841 }
842 
843 static bool mnem_mov_c(char const *const *arg, ut16 pc, ut8 **out) {
844  return singlearg_bit(0xa2, arg[1], out);
845 }
846 
847 static bool mnem_mov(char const *const *arg, ut16 pc, ut8 **out) {
848  if (!rz_str_casecmp(arg[0], "dptr")) {
849  ut16 imm;
850  if (!resolve_immediate(arg[1] + 1, &imm)) {
851  return false;
852  }
853  (*out)[0] = 0x90;
854  (*out)[1] = imm >> 8;
855  (*out)[2] = imm;
856  *out += 3;
857  return true;
858  }
859  if (is_indirect_reg(arg[0])) {
860  if (!rz_str_casecmp(arg[1], "a")) {
861  return singlearg_register(0xf6, arg[0], out);
862  }
863  if (arg[1][0] != '#') {
864  return singlearg_direct(
865  0xa6 | register_number(arg[0]), arg[1], out);
866  }
867  return singlearg_immediate(0x76 | register_number(arg[0]), arg[1], out);
868  }
869  if (!rz_str_casecmp(arg[0], "a")) {
870  if (is_indirect_reg(arg[1])) {
871  return singlearg_register(0xe6, arg[1], out);
872  }
873  if (is_reg(arg[1])) {
874  return singlearg_register(0xe8, arg[1], out);
875  }
876  if (arg[1][0] == '#') {
877  return singlearg_immediate(0x74, arg[1], out);
878  }
879  return singlearg_direct(0xe5, arg[1], out);
880  }
881  if (is_reg(arg[0])) {
882  if (!rz_str_casecmp(arg[1], "a")) {
883  return singlearg_register(0xf8, arg[0], out);
884  }
885  if (arg[1][0] == '#') {
886  return singlearg_immediate(
887  0x78 | register_number(arg[0]), arg[1], out);
888  }
889  return singlearg_direct(0xa8 | register_number(arg[0]), arg[1], out);
890  }
891  if (!rz_str_casecmp(arg[1], "c")) {
892  return singlearg_bit(0x92, arg[0], out);
893  }
894  if (!rz_str_casecmp(arg[1], "a")) {
895  return singlearg_direct(0xf5, arg[0], out);
896  }
897  if (is_reg(arg[1])) {
898  return singlearg_direct(0x88 | register_number(arg[1]), arg[0], out);
899  }
900  if (is_indirect_reg(arg[1])) {
901  return singlearg_direct(0x86 | register_number(arg[1]), arg[0], out);
902  }
903  ut8 dest_addr;
904  if (!address_direct(arg[0], &dest_addr)) {
905  return false;
906  }
907  if (arg[1][0] == '#') {
908  ut16 imm;
909  if (!resolve_immediate(arg[1] + 1, &imm)) {
910  return false;
911  }
912  (*out)[0] = 0x75;
913  (*out)[1] = dest_addr;
914  (*out)[2] = imm & 0x00FF;
915  *out += 3;
916  return true;
917  }
918  ut8 src_addr;
919  if (!address_direct(arg[1], &src_addr)) {
920  return false;
921  }
922  (*out)[0] = 0x85;
923  (*out)[1] = src_addr;
924  (*out)[2] = dest_addr;
925  *out += 3;
926  return true;
927 }
928 
929 static bool mnem_movc(char const *const *arg, ut16 pc, ut8 **out) {
930  if (rz_str_casecmp(arg[0], "a")) {
931  return false;
932  }
933  if (!str_iwhitecasecmp(arg[1], "@a+dptr") || !str_iwhitecasecmp(arg[1], "[a+dptr]")) {
934  return single_byte_instr(0x93, out);
935  }
936  if (!str_iwhitecasecmp(arg[1], "@a+pc") || !str_iwhitecasecmp(arg[1], "[a+pc]")) {
937  return single_byte_instr(0x83, out);
938  }
939  return false;
940 }
941 
942 static bool mnem_movx(char const *const *arg, ut16 pc, ut8 **out) {
943  if (!rz_str_casecmp(arg[0], "a")) {
944  if (is_indirect_reg(arg[1])) {
945  return singlearg_register(0xe2, arg[1], out);
946  }
947  if (!str_iwhitecasecmp(arg[1], "@dptr") || !str_iwhitecasecmp(arg[1], "[dptr]")) {
948  return single_byte_instr(0xe0, out);
949  }
950  }
951  if (rz_str_casecmp(arg[1], "a")) {
952  return false;
953  }
954  if (is_indirect_reg(arg[0])) {
955  return singlearg_register(0xf2, arg[0], out);
956  }
957  if (!str_iwhitecasecmp(arg[0], "@dptr") || !str_iwhitecasecmp(arg[0], "[dptr]")) {
958  return single_byte_instr(0xf0, out);
959  }
960  return false;
961 }
962 
963 static bool mnem_mul(char const *const *arg, ut16 pc, ut8 **out) {
964  if (rz_str_ncasecmp("ab", arg[0], 3)) {
965  return false;
966  }
967  return single_byte_instr(0xa4, out);
968 }
969 
970 static bool mnem_nop(char const *const *arg, ut16 pc, ut8 **out) {
971  return single_byte_instr(0x00, out);
972 }
973 
974 static bool mnem_orl(char const *const *arg, ut16 pc, ut8 **out) {
975  if (!rz_str_casecmp(arg[0], "c")) {
976  if (arg[1][0] == '/') {
977  return singlearg_bit(0xa0, arg[1] + 1, out);
978  }
979  return singlearg_bit(0x72, arg[1], out);
980  }
981  if (!rz_str_casecmp(arg[0], "a")) {
982  if (is_indirect_reg(arg[1])) {
983  return singlearg_register(0x46, arg[1], out);
984  }
985  if (arg[1][0] == '#') {
986  return singlearg_immediate(0x44, arg[1], out);
987  }
988  if (is_reg(arg[1])) {
989  return singlearg_register(0x48, arg[1], out);
990  }
991  return singlearg_direct(0x45, arg[1], out);
992  }
993 
994  if (arg[1][0] != '#') {
995  return singlearg_direct(0x42, arg[0], out);
996  }
997 
998  ut8 dest_addr;
999  if (!address_direct(arg[0], &dest_addr)) {
1000  return false;
1001  }
1002  ut16 imm;
1003  if (!resolve_immediate(arg[1] + 1, &imm)) {
1004  return false;
1005  }
1006  (*out)[0] = 0x43;
1007  (*out)[1] = dest_addr;
1008  (*out)[2] = imm & 0x00FF;
1009  *out += 3;
1010  return true;
1011 }
1012 
1013 static bool mnem_pop(char const *const *arg, ut16 pc, ut8 **out) {
1014  return singlearg_direct(0xd0, arg[0], out);
1015 }
1016 
1017 static bool mnem_push(char const *const *arg, ut16 pc, ut8 **out) {
1018  return singlearg_direct(0xc0, arg[0], out);
1019 }
1020 
1021 static bool mnem_ret(char const *const *arg, ut16 pc, ut8 **out) {
1022  return single_byte_instr(0x22, out);
1023 }
1024 
1025 static bool mnem_reti(char const *const *arg, ut16 pc, ut8 **out) {
1026  return single_byte_instr(0x32, out);
1027 }
1028 
1029 static bool mnem_rl(char const *const *arg, ut16 pc, ut8 **out) {
1030  return single_a_arg_instr(0x23, arg[0], out);
1031 }
1032 
1033 static bool mnem_rlc(char const *const *arg, ut16 pc, ut8 **out) {
1034  return single_a_arg_instr(0x33, arg[0], out);
1035 }
1036 
1037 static bool mnem_rr(char const *const *arg, ut16 pc, ut8 **out) {
1038  return single_a_arg_instr(0x03, arg[0], out);
1039 }
1040 
1041 static bool mnem_rrc(char const *const *arg, ut16 pc, ut8 **out) {
1042  return single_a_arg_instr(0x13, arg[0], out);
1043 }
1044 
1045 static bool mnem_setb(char const *const *arg, ut16 pc, ut8 **out) {
1046  if (!rz_str_casecmp("c", arg[0])) {
1047  return single_byte_instr(0xd3, out);
1048  }
1049  return singlearg_bit(0xd2, arg[0], out);
1050 }
1051 
1052 static bool mnem_sjmp(char const *const *arg, ut16 pc, ut8 **out) {
1053  return singlearg_reladdr(0x80, arg[0], pc, out);
1054 }
1055 
1056 static bool mnem_jmp(char const *const *arg, ut16 pc, ut8 **out) {
1057  if (!str_iwhitecasecmp(arg[0], "@a+dptr") || !str_iwhitecasecmp(arg[0], "[a+dptr]")) {
1058  return single_byte_instr(0x73, out);
1059  }
1060 
1061  ut16 address;
1062  if (!to_address(arg[0], &address)) {
1063  return false;
1064  }
1065  ut16 reladdr;
1066  if (pc < address) {
1067  reladdr = address - pc;
1068  } else {
1069  reladdr = pc - address;
1070  }
1071 
1072  if (reladdr < 0x100) {
1073  return mnem_sjmp(arg, pc, out);
1074  } else if (reladdr < 0x08FF) {
1075  return mnem_ajmp(arg, pc, out);
1076  } else {
1077  return mnem_ljmp(arg, pc, out);
1078  }
1079 }
1080 
1081 static bool mnem_subb(char const *const *arg, ut16 pc, ut8 **out) {
1082  if (rz_str_casecmp(arg[0], "a")) {
1083  return false;
1084  }
1085  if (is_indirect_reg(arg[1])) {
1086  return singlearg_register(0x96, arg[1], out);
1087  }
1088  if (arg[1][0] == '#') {
1089  return singlearg_immediate(0x94, arg[1], out);
1090  }
1091  if (is_reg(arg[1])) {
1092  return singlearg_register(0x98, arg[1], out);
1093  }
1094  return singlearg_direct(0x95, arg[1], out);
1095 }
1096 
1097 static bool mnem_swap(char const *const *arg, ut16 pc, ut8 **out) {
1098  return single_a_arg_instr(0xc4, arg[0], out);
1099 }
1100 
1101 static bool mnem_xrl(char const *const *arg, ut16 pc, ut8 **out) {
1102  if (!rz_str_casecmp(arg[0], "a")) {
1103  if (is_indirect_reg(arg[1])) {
1104  return singlearg_register(0x66, arg[1], out);
1105  }
1106  if (arg[1][0] == '#') {
1107  return singlearg_immediate(0x64, arg[1], out);
1108  }
1109  if (is_reg(arg[1])) {
1110  return singlearg_register(0x68, arg[1], out);
1111  }
1112  return singlearg_direct(0x65, arg[1], out);
1113  }
1114  if (arg[1][0] != '#') {
1115  if (rz_str_casecmp(arg[1], "a")) {
1116  return false;
1117  }
1118  return singlearg_direct(0x62, arg[0], out);
1119  }
1120  ut8 dest_addr;
1121  if (!address_direct(arg[0], &dest_addr)) {
1122  return false;
1123  }
1124  ut16 imm;
1125  if (!resolve_immediate(arg[1] + 1, &imm)) {
1126  return false;
1127  }
1128  (*out)[0] = 0x63;
1129  (*out)[1] = dest_addr;
1130  (*out)[2] = imm & 0x00FF;
1131  *out += 3;
1132  return true;
1133 }
1134 
1135 static bool mnem_xch(char const *const *arg, ut16 pc, ut8 **out) {
1136  if (rz_str_casecmp(arg[0], "a")) {
1137  return false;
1138  }
1139  if (is_indirect_reg(arg[1])) {
1140  return singlearg_register(0xc6, arg[1], out);
1141  }
1142  if (is_reg(arg[1])) {
1143  return singlearg_register(0xc8, arg[1], out);
1144  }
1145  return singlearg_direct(0xc5, arg[1], out);
1146 }
1147 
1148 static bool mnem_xchd(char const *const *arg, ut16 pc, ut8 **out) {
1149  if (rz_str_casecmp(arg[0], "a")) {
1150  return false;
1151  }
1152  if (!is_indirect_reg(arg[1])) {
1153  return false;
1154  }
1155  return singlearg_register(0xd6, arg[1], out);
1156 }
1157 
1158 /******************************************************************************
1159  * ## Section 6: mnemonic token dispatcher
1160  -------------------------*/
1161 
1162 static parse_mnem_args mnemonic(char const *user_asm, int *nargs) {
1163  return match_prefix_f(nargs, user_asm, (ftable){
1164 #define mnem(n, mn) { #mn " ", &mnem_##mn, n },
1165 #define zeroarg_mnem(mn) { #mn, &mnem_##mn, 0 },
1166  mnem(1, acall) mnem(2, addc) mnem(2, add) mnem(1, ajmp) mnem(2, anl) mnem(3, cjne) mnem(1, clr) mnem(1, cpl) mnem(1, da) mnem(1, dec) mnem(1, div) mnem(2, djnz) mnem(1, inc) mnem(2, jbc) mnem(2, jb) mnem(1, jc) mnem(1, jmp) mnem(2, jnb) mnem(1, jnc) mnem(1, jz) mnem(1, jnz) mnem(1, lcall) mnem(1, ljmp)
1167  /* so uh, the whitespace-independent matching sees movc and mov c as the same
1168  * thing...
1169  * My first thought was to add an exception for mov c, but later I saw that it'd
1170  * be better to match the space after each instruction, but the exception is
1171  * still here
1172  */
1173  { "mov c,", &mnem_mov_c, 2 },
1174  mnem(2, movc) mnem(2, movx) mnem(2, mov) mnem(1, mul) mnem(2, orl) mnem(1, pop) mnem(1, push) mnem(2, xchd) mnem(2, xch) mnem(2, xrl) mnem(1, rlc) mnem(1, rl) mnem(1, rrc) mnem(1, rr) mnem(1, setb) mnem(1, sjmp) mnem(2, subb) mnem(1, swap) zeroarg_mnem(nop) zeroarg_mnem(reti) zeroarg_mnem(ret)
1175 #undef mnem
1176  { 0 } });
1177 }
1178 
1179 /******************************************************************************
1180  * ## Section 7: rizin glue and mnemonic tokenization
1181  --------------------------------------*/
1182 
1183 int assemble_8051(RzAsm *a, RzAsmOp *op, char const *user_asm) {
1184  if (!a || !op || !user_asm) {
1185  return 0;
1186  }
1187  rz_strbuf_set(&op->buf_asm, user_asm);
1188  while (!terminates_asm_line(*user_asm) && (*user_asm == ' ' || *user_asm == '\t')) {
1189  user_asm += 1;
1190  }
1191  char const *arguments = user_asm;
1192  while (!terminates_asm_line(*arguments) && (('a' <= *arguments && *arguments <= 'z') || ('A' <= *arguments && *arguments <= 'Z'))) {
1193  arguments += 1;
1194  }
1195  while (!terminates_asm_line(*arguments) && (*arguments == ' ' || *arguments == '\t')) {
1196  arguments += 1;
1197  }
1198  char *arg[3] = { 0 };
1199  int nr_of_arguments = get_arguments(arg, arguments);
1200  char const *carg[3] = { arg[0], arg[1], arg[2] }; /* aliasing pointers...
1201  I need to pass char const *s, but I can't free char const *s
1202  not without compiler warnings, at least */
1203  int wants_arguments;
1204  parse_mnem_args mnem = mnemonic(user_asm, &wants_arguments);
1205  if (!mnem || nr_of_arguments != wants_arguments) {
1206  free(arg[2]);
1207  arg[2] = 0;
1208  carg[2] = 0;
1209  free(arg[1]);
1210  arg[1] = 0;
1211  carg[1] = 0;
1212  free(arg[0]);
1213  arg[0] = 0;
1214  carg[0] = 0;
1215  return 0;
1216  }
1217  ut8 instr[4] = { 0 };
1218  ut8 *binp = instr;
1219  if (!mnem(carg, a->pc, &binp)) {
1220  free(arg[0]);
1221  arg[0] = 0;
1222  carg[2] = 0;
1223  free(arg[1]);
1224  arg[1] = 0;
1225  carg[1] = 0;
1226  free(arg[2]);
1227  arg[2] = 0;
1228  carg[0] = 0;
1229  return 0;
1230  } else {
1231  free(arg[0]);
1232  arg[0] = 0;
1233  carg[2] = 0;
1234  free(arg[1]);
1235  arg[1] = 0;
1236  carg[1] = 0;
1237  free(arg[2]);
1238  arg[2] = 0;
1239  carg[0] = 0;
1240  size_t len = binp - instr;
1241  rz_strbuf_setbin(&op->buf, instr, len);
1242  return binp - instr;
1243  }
1244 }
size_t len
Definition: 6502dis.c:15
static bool mnem_push(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:1017
static int str_iwhitecasecmp(char const *a, char const *b)
Definition: 8051_ass.c:245
static bool pattern_match(char const *str, char const *pattern)
Definition: 8051_ass.c:286
static bool mnem_reti(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:1025
static bool mnem_nop(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:970
static bool parse_hexadecimal(char const *hexstr, ut16 *out)
Definition: 8051_ass.c:92
static bool to_address(char const *addr_str, ut16 *addr_out)
Definition: 8051_ass.c:376
#define mnem(n, mn)
int assemble_8051(RzAsm *a, RzAsmOp *op, char const *user_asm)
Definition: 8051_ass.c:1183
static bool mnem_ljmp(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:831
static bool singlearg_reladdr(ut8 const firstbyte, char const *arg, ut16 const pc, ut8 **out)
Definition: 8051_ass.c:475
bool(* parse_mnem_args)(char const *const *, ut16, ut8 **)
Definition: 8051_ass.c:278
static bool mnem_ajmp(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:568
static bool mnem_orl(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:974
static bool is_reg(char const *str)
Definition: 8051_ass.c:352
static bool mnem_rl(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:1029
static bool mnem_mul(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:963
static bool mnem_sjmp(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:1052
static bool get_arg(char const *multi, int n, char *dest)
Definition: 8051_ass.c:126
static bool mnem_xrl(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:1101
static bool address_bit(char const *addr_str, ut8 *addr_out)
Definition: 8051_ass.c:399
static bool mnem_acall(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:522
static bool mnem_jnz(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:811
static bool is_indirect_reg(char const *str)
Definition: 8051_ass.c:333
static int get_arguments(char **arg, char const *arguments)
Definition: 8051_ass.c:189
static bool mnem_anl(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:579
static bool relative_address(ut16 pc, ut16 address, ut8 *out)
Definition: 8051_ass.c:360
static bool mnem_jb(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:755
static bool mnem_ret(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:1021
static bool mnem_xchd(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:1148
static bool resolve_immediate(char const *imm_str, ut16 *imm_out)
Definition: 8051_ass.c:370
static bool single_a_arg_instr(ut8 const firstbyte, char const *arg, ut8 **out)
Definition: 8051_ass.c:511
static bool mnem_subb(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:1081
static bool mnem_rlc(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:1033
static bool mnem_dec(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:693
static bool mnem_cpl(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:679
static bool mnem_jz(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:815
static bool address_direct(char const *addr_str, ut8 *addr_out)
Definition: 8051_ass.c:385
static bool mnem_jnc(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:807
static int register_number(char const *reg)
Definition: 8051_ass.c:444
static bool mnem_div(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:706
static bool mnem_addc(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:552
static bool singlearg_bit(ut8 const firstbyte, char const *arg, ut8 **out)
Definition: 8051_ass.c:464
static bool mnem_inc(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:739
static bool mnem_add(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:533
static bool singlearg_immediate(ut8 firstbyte, char const *imm_str, ut8 **out)
Definition: 8051_ass.c:496
static bool mnem_djnz(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:713
static parse_mnem_args match_prefix_f(int *args, char const *str, ftable const tbl)
Definition: 8051_ass.c:311
static bool singlearg_register(ut8 firstbyte, char const *reg, ut8 **out)
Definition: 8051_ass.c:507
static bool mnem_pop(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:1013
static bool mnem_rr(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:1037
static parse_mnem_args mnemonic(char const *user_asm, int *nargs)
Definition: 8051_ass.c:1162
static bool mnem_da(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:689
static bool mnem_setb(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:1045
static bool mnem_jnb(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:791
static bool mnem_lcall(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:819
static bool mnem_jc(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:787
static bool mnem_movx(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:942
static bool terminates_asm_line(char c)
Definition: 8051_ass.c:238
static bool mnem_mov_c(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:843
static bool single_byte_instr(ut8 const instr, ut8 **out)
Definition: 8051_ass.c:458
static bool mnem_movc(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:929
static bool mnem_clr(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:669
static bool mnem_xch(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:1135
static bool mnem_rrc(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:1041
static bool singlearg_direct(ut8 const firstbyte, char const *arg, ut8 **out)
Definition: 8051_ass.c:485
static bool mnem_jbc(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:771
static bool mnem_mov(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:847
#define zeroarg_mnem(mn)
static bool mnem_jmp(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:1056
static bool mnem_cjne(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:617
static bool mnem_swap(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:1097
si
#define jmp
#define imm
static RzILOpEffect * mov(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:351
static RzILOpEffect * mul(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:539
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
RzCryptoSelector bit
Definition: crypto.c:16
uint16_t ut16
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
#define reg(n)
uint8_t ut8
Definition: lh5801.h:11
void * p
Definition: libc.cpp:67
void * realloc(void *ptr, size_t size)
Definition: malloc.c:144
void * malloc(size_t size)
Definition: malloc.c:123
char * dest
Definition: lz4.h:697
int args
Definition: mipsasm.c:18
int n
Definition: mipsasm.c:19
#define swap(a, b)
Definition: qsort.h:111
RZ_API const char * rz_str_lchr(const char *str, char chr)
Definition: str.c:669
RZ_API int rz_str_casecmp(const char *dst, const char *orig)
Definition: str.c:121
RZ_API size_t rz_str_ncpy(char *dst, const char *src, size_t n)
Secure string copy with null terminator.
Definition: str.c:923
RZ_API size_t rz_str_ansi_nlen(const char *str, size_t len)
Definition: str.c:1923
RZ_API int rz_str_ncasecmp(const char *dst, const char *orig, size_t n)
Definition: str.c:129
RZ_API const char * rz_strbuf_set(RzStrBuf *sb, const char *s)
Definition: strbuf.c:153
RZ_API bool rz_strbuf_setbin(RzStrBuf *sb, const ut8 *s, size_t len)
Definition: strbuf.c:85
#define st16
Definition: rz_types_base.h:14
#define isspace(c)
Definition: safe-ctype.h:141
#define tolower(c)
Definition: safe-ctype.h:149
#define b(i)
Definition: sha256.c:42
#define c(i)
Definition: sha256.c:43
#define a(i)
Definition: sha256.c:41
#define INT8_MIN
#define INT8_MAX
parse_mnem_args res
Definition: 8051_ass.c:282
char const *const pattern
Definition: 8051_ass.c:281
int args
Definition: 8051_ass.c:283
Definition: mybfd.h:285
#define bool
Definition: sysdefs.h:146
Definition: dis.c:32
static int add(char *argv[])
Definition: ziptool.c:84