Rizin
unix-like reverse engineering framework and cli tools
8051_ass.c File Reference
#include "8051_ass.h"
#include <rz_util.h>
#include <string.h>

Go to the source code of this file.

Classes

struct  ftable
 

Macros

#define mnem(n, mn)   { #mn " ", &mnem_##mn, n },
 
#define zeroarg_mnem(mn)   { #mn, &mnem_##mn, 0 },
 

Typedefs

typedef bool(* parse_mnem_args) (char const *const *, ut16, ut8 **)
 

Functions

static bool parse_hexadecimal (char const *hexstr, ut16 *out)
 
static bool get_arg (char const *multi, int n, char *dest)
 
static int get_arguments (char **arg, char const *arguments)
 
static bool terminates_asm_line (char c)
 
static int str_iwhitecasecmp (char const *a, char const *b)
 
static bool pattern_match (char const *str, char const *pattern)
 
static parse_mnem_args match_prefix_f (int *args, char const *str, ftable const tbl)
 
static bool is_indirect_reg (char const *str)
 
static bool is_reg (char const *str)
 
static bool relative_address (ut16 pc, ut16 address, ut8 *out)
 
static bool resolve_immediate (char const *imm_str, ut16 *imm_out)
 
static bool to_address (char const *addr_str, ut16 *addr_out)
 
static bool address_direct (char const *addr_str, ut8 *addr_out)
 
static bool address_bit (char const *addr_str, ut8 *addr_out)
 
static int register_number (char const *reg)
 
static bool single_byte_instr (ut8 const instr, ut8 **out)
 
static bool singlearg_bit (ut8 const firstbyte, char const *arg, ut8 **out)
 
static bool singlearg_reladdr (ut8 const firstbyte, char const *arg, ut16 const pc, ut8 **out)
 
static bool singlearg_direct (ut8 const firstbyte, char const *arg, ut8 **out)
 
static bool singlearg_immediate (ut8 firstbyte, char const *imm_str, ut8 **out)
 
static bool singlearg_register (ut8 firstbyte, char const *reg, ut8 **out)
 
static bool single_a_arg_instr (ut8 const firstbyte, char const *arg, ut8 **out)
 
static bool mnem_acall (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_add (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_addc (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_ajmp (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_anl (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_cjne (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_clr (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_cpl (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_da (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_dec (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_div (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_djnz (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_inc (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_jb (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_jbc (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_jc (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_jnb (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_jnc (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_jnz (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_jz (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_lcall (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_ljmp (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_mov_c (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_mov (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_movc (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_movx (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_mul (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_nop (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_orl (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_pop (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_push (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_ret (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_reti (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_rl (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_rlc (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_rr (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_rrc (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_setb (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_sjmp (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_jmp (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_subb (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_swap (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_xrl (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_xch (char const *const *arg, ut16 pc, ut8 **out)
 
static bool mnem_xchd (char const *const *arg, ut16 pc, ut8 **out)
 
static parse_mnem_args mnemonic (char const *user_asm, int *nargs)
 
int assemble_8051 (RzAsm *a, RzAsmOp *op, char const *user_asm)
 

Macro Definition Documentation

◆ mnem

#define mnem (   n,
  mn 
)    { #mn " ", &mnem_##mn, n },

◆ zeroarg_mnem

#define zeroarg_mnem (   mn)    { #mn, &mnem_##mn, 0 },

Typedef Documentation

◆ parse_mnem_args

typedef bool(* parse_mnem_args) (char const *const *, ut16, ut8 **)

Definition at line 278 of file 8051_ass.c.

Function Documentation

◆ address_bit()

static bool address_bit ( char const addr_str,
ut8 addr_out 
)
static

attempts to parse the given string as a bit-address

Definition at line 399 of file 8051_ass.c.

399  {
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 }
static bool address_direct(char const *addr_str, ut8 *addr_out)
Definition: 8051_ass.c:385
RzCryptoSelector bit
Definition: crypto.c:16
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
uint8_t ut8
Definition: lh5801.h:11
void * malloc(size_t size)
Definition: malloc.c:123
RZ_API const char * rz_str_lchr(const char *str, char chr)
Definition: str.c:669
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

References address_direct(), bit, test_evm::end, free(), malloc(), rz_str_lchr(), and rz_str_ncpy().

Referenced by mnem_jb(), mnem_jbc(), mnem_jnb(), and singlearg_bit().

◆ address_direct()

static bool address_direct ( char const addr_str,
ut8 addr_out 
)
static

attempts to parse the given string as an 8bit-wide address

Definition at line 385 of file 8051_ass.c.

385  {
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 }
static bool parse_hexadecimal(char const *hexstr, ut16 *out)
Definition: 8051_ass.c:92
uint16_t ut16

References parse_hexadecimal().

Referenced by address_bit(), mnem_anl(), mnem_cjne(), mnem_djnz(), mnem_mov(), mnem_orl(), mnem_xrl(), and singlearg_direct().

◆ assemble_8051()

int assemble_8051 ( RzAsm a,
RzAsmOp op,
char const user_asm 
)

Definition at line 1183 of file 8051_ass.c.

1183  {
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
#define mnem(n, mn)
bool(* parse_mnem_args)(char const *const *, ut16, ut8 **)
Definition: 8051_ass.c:278
static int get_arguments(char **arg, char const *arguments)
Definition: 8051_ass.c:189
static parse_mnem_args mnemonic(char const *user_asm, int *nargs)
Definition: 8051_ass.c:1162
static bool terminates_asm_line(char c)
Definition: 8051_ass.c:238
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 a(i)
Definition: sha256.c:41
Definition: dis.c:32

References a, free(), get_arguments(), len, mnem, mnemonic(), rz_strbuf_set(), rz_strbuf_setbin(), and terminates_asm_line().

◆ get_arg()

static bool get_arg ( char const multi,
int  n,
char *  dest 
)
static

splits up the given string into multiple chucks, separated by unquoted commas. It will then copy chunk n-1 into dest, with the leading and trailing whitespace stripped.

if chunk n-1 does not exist or is empty, it will return false;

only text before newlines, NUL, and unquoted semicolons is chunked.

any text after a single-quote and before the next single-quote is considered quoted. There is no escaping.

Definition at line 126 of file 8051_ass.c.

126  {
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 }
char * dest
Definition: lz4.h:697
int n
Definition: mipsasm.c:19

References dest, and n.

Referenced by get_arguments().

◆ get_arguments()

static int get_arguments ( char **  arg,
char const arguments 
)
static

tokenizes the argument list arg parameter must be 3 char pointers wide. TODO: merge with get_arg, as this is now the only user

Definition at line 189 of file 8051_ass.c.

189  {
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 }
static bool get_arg(char const *multi, int n, char *dest)
Definition: 8051_ass.c:126
void * realloc(void *ptr, size_t size)
Definition: malloc.c:144

References free(), get_arg(), malloc(), realloc(), and autogen_x86imm::tmp.

Referenced by assemble_8051().

◆ is_indirect_reg()

static bool is_indirect_reg ( char const str)
static

matches registers r0 and r1 when they are indirectly-addressed. 8051-style syntax @r0, but also r2 defacto [r0]

Definition at line 333 of file 8051_ass.c.

333  {
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 }
RZ_API size_t rz_str_ansi_nlen(const char *str, size_t len)
Definition: str.c:1923
#define tolower(c)
Definition: safe-ctype.h:149

References rz_str_ansi_nlen(), cmd_descs_generate::str, and tolower.

Referenced by mnem_addc(), mnem_anl(), mnem_cjne(), mnem_dec(), mnem_inc(), mnem_mov(), mnem_movx(), mnem_orl(), mnem_subb(), mnem_xch(), mnem_xchd(), mnem_xrl(), and register_number().

◆ is_reg()

static bool is_reg ( char const str)
static

returns true if the given string denotes an 'r'-register

Definition at line 352 of file 8051_ass.c.

352  {
353  return str && tolower(str[0]) == 'r' && rz_str_ansi_nlen(str, 3) == 2 && '0' <= str[1] && str[1] <= '7';
354 }

References rz_str_ansi_nlen(), cmd_descs_generate::str, and tolower.

Referenced by mnem_add(), mnem_addc(), mnem_anl(), mnem_cjne(), mnem_dec(), mnem_djnz(), mnem_inc(), mnem_mov(), mnem_orl(), mnem_subb(), mnem_xch(), mnem_xrl(), and register_number().

◆ match_prefix_f()

static parse_mnem_args match_prefix_f ( int args,
char const str,
ftable const  tbl 
)
static

Definition at line 311 of file 8051_ass.c.

311  {
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 }
static bool pattern_match(char const *str, char const *pattern)
Definition: 8051_ass.c:286
int args
Definition: mipsasm.c:18

References ftable::args, args, pattern_match(), ftable::res, and cmd_descs_generate::str.

Referenced by mnemonic().

◆ mnem_acall()

static bool mnem_acall ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 522 of file 8051_ass.c.

522  {
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 }
static bool to_address(char const *addr_str, ut16 *addr_out)
Definition: 8051_ass.c:376
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528

References out, and to_address().

◆ mnem_add()

static bool mnem_add ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 533 of file 8051_ass.c.

533  {
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 }
static bool is_reg(char const *str)
Definition: 8051_ass.c:352
static bool singlearg_immediate(ut8 firstbyte, char const *imm_str, ut8 **out)
Definition: 8051_ass.c:496
static bool singlearg_register(ut8 firstbyte, char const *reg, ut8 **out)
Definition: 8051_ass.c:507
static bool singlearg_direct(ut8 const firstbyte, char const *arg, ut8 **out)
Definition: 8051_ass.c:485
RZ_API int rz_str_casecmp(const char *dst, const char *orig)
Definition: str.c:121

References is_reg(), out, rz_str_casecmp(), singlearg_direct(), singlearg_immediate(), and singlearg_register().

◆ mnem_addc()

static bool mnem_addc ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 552 of file 8051_ass.c.

552  {
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 }
static bool is_indirect_reg(char const *str)
Definition: 8051_ass.c:333

References is_indirect_reg(), is_reg(), out, rz_str_casecmp(), singlearg_direct(), singlearg_immediate(), and singlearg_register().

◆ mnem_ajmp()

static bool mnem_ajmp ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 568 of file 8051_ass.c.

568  {
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 }

References out, and to_address().

Referenced by mnem_jmp().

◆ mnem_anl()

static bool mnem_anl ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 579 of file 8051_ass.c.

579  {
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 }
static bool resolve_immediate(char const *imm_str, ut16 *imm_out)
Definition: 8051_ass.c:370
static bool singlearg_bit(ut8 const firstbyte, char const *arg, ut8 **out)
Definition: 8051_ass.c:464
#define imm

References address_direct(), imm, is_indirect_reg(), is_reg(), out, resolve_immediate(), rz_str_casecmp(), singlearg_bit(), singlearg_direct(), singlearg_immediate(), and singlearg_register().

◆ mnem_cjne()

static bool mnem_cjne ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 617 of file 8051_ass.c.

617  {
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 }
static bool relative_address(ut16 pc, ut16 address, ut8 *out)
Definition: 8051_ass.c:360
static int register_number(char const *reg)
Definition: 8051_ass.c:444

References address_direct(), imm, is_indirect_reg(), is_reg(), out, pc, register_number(), relative_address(), resolve_immediate(), rz_str_casecmp(), and to_address().

◆ mnem_clr()

static bool mnem_clr ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 669 of file 8051_ass.c.

669  {
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 }
static bool single_byte_instr(ut8 const instr, ut8 **out)
Definition: 8051_ass.c:458

References out, rz_str_casecmp(), single_byte_instr(), and singlearg_bit().

◆ mnem_cpl()

static bool mnem_cpl ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 679 of file 8051_ass.c.

679  {
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 }

References out, rz_str_casecmp(), single_byte_instr(), and singlearg_bit().

◆ mnem_da()

static bool mnem_da ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 689 of file 8051_ass.c.

689  {
690  return single_a_arg_instr(0xd4, arg[0], out);
691 }
static bool single_a_arg_instr(ut8 const firstbyte, char const *arg, ut8 **out)
Definition: 8051_ass.c:511

References out, and single_a_arg_instr().

◆ mnem_dec()

static bool mnem_dec ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 693 of file 8051_ass.c.

693  {
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 }

References is_indirect_reg(), is_reg(), out, rz_str_casecmp(), single_byte_instr(), singlearg_direct(), and singlearg_register().

◆ mnem_div()

static bool mnem_div ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 706 of file 8051_ass.c.

706  {
707  if (rz_str_casecmp("ab", arg[0])) {
708  return false;
709  }
710  return single_byte_instr(0x84, out);
711 }

References out, rz_str_casecmp(), and single_byte_instr().

◆ mnem_djnz()

static bool mnem_djnz ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 713 of file 8051_ass.c.

713  {
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 }

References address_direct(), is_reg(), out, pc, register_number(), relative_address(), and to_address().

◆ mnem_inc()

static bool mnem_inc ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 739 of file 8051_ass.c.

739  {
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 }

References is_indirect_reg(), is_reg(), out, rz_str_casecmp(), single_byte_instr(), singlearg_direct(), and singlearg_register().

◆ mnem_jb()

static bool mnem_jb ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 755 of file 8051_ass.c.

755  {
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 }
static bool address_bit(char const *addr_str, ut8 *addr_out)
Definition: 8051_ass.c:399

References address_bit(), out, pc, relative_address(), and to_address().

◆ mnem_jbc()

static bool mnem_jbc ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 771 of file 8051_ass.c.

771  {
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 }

References address_bit(), out, pc, relative_address(), and to_address().

◆ mnem_jc()

static bool mnem_jc ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 787 of file 8051_ass.c.

787  {
788  return singlearg_reladdr(0x40, arg[0], pc, out);
789 }
static bool singlearg_reladdr(ut8 const firstbyte, char const *arg, ut16 const pc, ut8 **out)
Definition: 8051_ass.c:475

References out, pc, and singlearg_reladdr().

◆ mnem_jmp()

static bool mnem_jmp ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 1056 of file 8051_ass.c.

1056  {
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 }
static int str_iwhitecasecmp(char const *a, char const *b)
Definition: 8051_ass.c:245
static bool mnem_ljmp(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:831
static bool mnem_ajmp(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:568
static bool mnem_sjmp(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:1052

References mnem_ajmp(), mnem_ljmp(), mnem_sjmp(), out, pc, single_byte_instr(), str_iwhitecasecmp(), and to_address().

◆ mnem_jnb()

static bool mnem_jnb ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 791 of file 8051_ass.c.

791  {
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 }

References address_bit(), out, pc, relative_address(), and to_address().

◆ mnem_jnc()

static bool mnem_jnc ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 807 of file 8051_ass.c.

807  {
808  return singlearg_reladdr(0x50, arg[0], pc, out);
809 }

References out, pc, and singlearg_reladdr().

◆ mnem_jnz()

static bool mnem_jnz ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 811 of file 8051_ass.c.

811  {
812  return singlearg_reladdr(0x70, arg[0], pc, out);
813 }

References out, pc, and singlearg_reladdr().

◆ mnem_jz()

static bool mnem_jz ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 815 of file 8051_ass.c.

815  {
816  return singlearg_reladdr(0x60, arg[0], pc, out);
817 }

References out, pc, and singlearg_reladdr().

◆ mnem_lcall()

static bool mnem_lcall ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 819 of file 8051_ass.c.

819  {
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 }

References out, and to_address().

◆ mnem_ljmp()

static bool mnem_ljmp ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 831 of file 8051_ass.c.

831  {
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 }

References out, and to_address().

Referenced by mnem_jmp().

◆ mnem_mov()

static bool mnem_mov ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 847 of file 8051_ass.c.

847  {
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 }

References address_direct(), imm, is_indirect_reg(), is_reg(), out, register_number(), resolve_immediate(), rz_str_casecmp(), singlearg_bit(), singlearg_direct(), singlearg_immediate(), and singlearg_register().

◆ mnem_mov_c()

static bool mnem_mov_c ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 843 of file 8051_ass.c.

843  {
844  return singlearg_bit(0xa2, arg[1], out);
845 }

References out, and singlearg_bit().

Referenced by mnemonic().

◆ mnem_movc()

static bool mnem_movc ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 929 of file 8051_ass.c.

929  {
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 }

References out, rz_str_casecmp(), single_byte_instr(), and str_iwhitecasecmp().

◆ mnem_movx()

static bool mnem_movx ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 942 of file 8051_ass.c.

942  {
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 }

References is_indirect_reg(), out, rz_str_casecmp(), single_byte_instr(), singlearg_register(), and str_iwhitecasecmp().

◆ mnem_mul()

static bool mnem_mul ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 963 of file 8051_ass.c.

963  {
964  if (rz_str_ncasecmp("ab", arg[0], 3)) {
965  return false;
966  }
967  return single_byte_instr(0xa4, out);
968 }
RZ_API int rz_str_ncasecmp(const char *dst, const char *orig, size_t n)
Definition: str.c:129

References out, rz_str_ncasecmp(), and single_byte_instr().

◆ mnem_nop()

static bool mnem_nop ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 970 of file 8051_ass.c.

970  {
971  return single_byte_instr(0x00, out);
972 }

References out, and single_byte_instr().

◆ mnem_orl()

static bool mnem_orl ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 974 of file 8051_ass.c.

974  {
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 }

References address_direct(), imm, is_indirect_reg(), is_reg(), out, resolve_immediate(), rz_str_casecmp(), singlearg_bit(), singlearg_direct(), singlearg_immediate(), and singlearg_register().

◆ mnem_pop()

static bool mnem_pop ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 1013 of file 8051_ass.c.

1013  {
1014  return singlearg_direct(0xd0, arg[0], out);
1015 }

References out, and singlearg_direct().

◆ mnem_push()

static bool mnem_push ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 1017 of file 8051_ass.c.

1017  {
1018  return singlearg_direct(0xc0, arg[0], out);
1019 }

References out, and singlearg_direct().

◆ mnem_ret()

static bool mnem_ret ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 1021 of file 8051_ass.c.

1021  {
1022  return single_byte_instr(0x22, out);
1023 }

References out, and single_byte_instr().

◆ mnem_reti()

static bool mnem_reti ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 1025 of file 8051_ass.c.

1025  {
1026  return single_byte_instr(0x32, out);
1027 }

References out, and single_byte_instr().

◆ mnem_rl()

static bool mnem_rl ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 1029 of file 8051_ass.c.

1029  {
1030  return single_a_arg_instr(0x23, arg[0], out);
1031 }

References out, and single_a_arg_instr().

◆ mnem_rlc()

static bool mnem_rlc ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 1033 of file 8051_ass.c.

1033  {
1034  return single_a_arg_instr(0x33, arg[0], out);
1035 }

References out, and single_a_arg_instr().

◆ mnem_rr()

static bool mnem_rr ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 1037 of file 8051_ass.c.

1037  {
1038  return single_a_arg_instr(0x03, arg[0], out);
1039 }

References out, and single_a_arg_instr().

◆ mnem_rrc()

static bool mnem_rrc ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 1041 of file 8051_ass.c.

1041  {
1042  return single_a_arg_instr(0x13, arg[0], out);
1043 }

References out, and single_a_arg_instr().

◆ mnem_setb()

static bool mnem_setb ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 1045 of file 8051_ass.c.

1045  {
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 }

References out, rz_str_casecmp(), single_byte_instr(), and singlearg_bit().

◆ mnem_sjmp()

static bool mnem_sjmp ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 1052 of file 8051_ass.c.

1052  {
1053  return singlearg_reladdr(0x80, arg[0], pc, out);
1054 }

References out, pc, and singlearg_reladdr().

Referenced by mnem_jmp().

◆ mnem_subb()

static bool mnem_subb ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 1081 of file 8051_ass.c.

1081  {
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 }

References is_indirect_reg(), is_reg(), out, rz_str_casecmp(), singlearg_direct(), singlearg_immediate(), and singlearg_register().

◆ mnem_swap()

static bool mnem_swap ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 1097 of file 8051_ass.c.

1097  {
1098  return single_a_arg_instr(0xc4, arg[0], out);
1099 }

References out, and single_a_arg_instr().

◆ mnem_xch()

static bool mnem_xch ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 1135 of file 8051_ass.c.

1135  {
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 }

References is_indirect_reg(), is_reg(), out, rz_str_casecmp(), singlearg_direct(), and singlearg_register().

◆ mnem_xchd()

static bool mnem_xchd ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 1148 of file 8051_ass.c.

1148  {
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 }

References is_indirect_reg(), out, rz_str_casecmp(), and singlearg_register().

◆ mnem_xrl()

static bool mnem_xrl ( char const *const arg,
ut16  pc,
ut8 **  out 
)
static

Definition at line 1101 of file 8051_ass.c.

1101  {
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 }

References address_direct(), imm, is_indirect_reg(), is_reg(), out, resolve_immediate(), rz_str_casecmp(), singlearg_direct(), singlearg_immediate(), and singlearg_register().

◆ mnemonic()

static parse_mnem_args mnemonic ( char const user_asm,
int nargs 
)
static

Definition at line 1162 of file 8051_ass.c.

1162  {
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 }
static parse_mnem_args match_prefix_f(int *args, char const *str, ftable const tbl)
Definition: 8051_ass.c:311
static bool mnem_mov_c(char const *const *arg, ut16 pc, ut8 **out)
Definition: 8051_ass.c:843
#define zeroarg_mnem(mn)
#define jmp
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
#define swap(a, b)
Definition: qsort.h:111
Definition: mybfd.h:285
static int add(char *argv[])
Definition: ziptool.c:84

References add(), jmp, match_prefix_f(), mnem, mnem_mov_c(), mov(), mul(), cmd_descs_generate::nargs, swap, and zeroarg_mnem.

Referenced by assemble_8051().

◆ parse_hexadecimal()

static bool parse_hexadecimal ( char const hexstr,
ut16 out 
)
static

Definition at line 92 of file 8051_ass.c.

92  {
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 }
void * p
Definition: libc.cpp:67

References out, and p.

Referenced by address_direct(), resolve_immediate(), and to_address().

◆ pattern_match()

static bool pattern_match ( char const str,
char const pattern 
)
static

Definition at line 286 of file 8051_ass.c.

286  {
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 }
si
#define isspace(c)
Definition: safe-ctype.h:141

References isspace, si, cmd_descs_generate::str, and tolower.

Referenced by match_prefix_f().

◆ register_number()

static int register_number ( char const reg)
static

figures out which register is denoted by the given string returns 8 if invalid

Definition at line 444 of file 8051_ass.c.

444  {
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 }
#define reg(n)

References is_indirect_reg(), is_reg(), and reg.

Referenced by mnem_cjne(), mnem_djnz(), mnem_mov(), and singlearg_register().

◆ relative_address()

static bool relative_address ( ut16  pc,
ut16  address,
ut8 out 
)
static

returns true if the given number is a valid relative address from the given pc, the relative address is stored in the *out parameter.

Definition at line 360 of file 8051_ass.c.

360  {
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 }
#define st16
Definition: rz_types_base.h:14
#define INT8_MIN
#define INT8_MAX

References INT8_MAX, INT8_MIN, out, pc, and st16.

Referenced by mnem_cjne(), mnem_djnz(), mnem_jb(), mnem_jbc(), mnem_jnb(), and singlearg_reladdr().

◆ resolve_immediate()

static bool resolve_immediate ( char const imm_str,
ut16 imm_out 
)
static

Definition at line 370 of file 8051_ass.c.

370  {
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 }

References parse_hexadecimal().

Referenced by mnem_anl(), mnem_cjne(), mnem_mov(), mnem_orl(), mnem_xrl(), and singlearg_immediate().

◆ single_a_arg_instr()

static bool single_a_arg_instr ( ut8 const  firstbyte,
char const arg,
ut8 **  out 
)
static

Definition at line 511 of file 8051_ass.c.

511  {
512  if (rz_str_casecmp("a", arg)) {
513  return false;
514  }
515  return single_byte_instr(firstbyte, out);
516 }

References out, rz_str_casecmp(), and single_byte_instr().

Referenced by mnem_da(), mnem_rl(), mnem_rlc(), mnem_rr(), mnem_rrc(), and mnem_swap().

◆ single_byte_instr()

static bool single_byte_instr ( ut8 const  instr,
ut8 **  out 
)
static

Definition at line 458 of file 8051_ass.c.

458  {
459  (*out)[0] = instr;
460  *out += 1;
461  return true;
462 }

References out.

Referenced by mnem_clr(), mnem_cpl(), mnem_dec(), mnem_div(), mnem_inc(), mnem_jmp(), mnem_movc(), mnem_movx(), mnem_mul(), mnem_nop(), mnem_ret(), mnem_reti(), mnem_setb(), single_a_arg_instr(), and singlearg_register().

◆ singlearg_bit()

static bool singlearg_bit ( ut8 const  firstbyte,
char const arg,
ut8 **  out 
)
static

Definition at line 464 of file 8051_ass.c.

464  {
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 }

References address_bit(), and out.

Referenced by mnem_anl(), mnem_clr(), mnem_cpl(), mnem_mov(), mnem_mov_c(), mnem_orl(), and mnem_setb().

◆ singlearg_direct()

static bool singlearg_direct ( ut8 const  firstbyte,
char const arg,
ut8 **  out 
)
static

Definition at line 485 of file 8051_ass.c.

485  {
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 }

References address_direct(), and out.

Referenced by mnem_add(), mnem_addc(), mnem_anl(), mnem_dec(), mnem_inc(), mnem_mov(), mnem_orl(), mnem_pop(), mnem_push(), mnem_subb(), mnem_xch(), and mnem_xrl().

◆ singlearg_immediate()

static bool singlearg_immediate ( ut8  firstbyte,
char const imm_str,
ut8 **  out 
)
static

Definition at line 496 of file 8051_ass.c.

496  {
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 }

References imm, out, and resolve_immediate().

Referenced by mnem_add(), mnem_addc(), mnem_anl(), mnem_mov(), mnem_orl(), mnem_subb(), and mnem_xrl().

◆ singlearg_register()

static bool singlearg_register ( ut8  firstbyte,
char const reg,
ut8 **  out 
)
static

◆ singlearg_reladdr()

static bool singlearg_reladdr ( ut8 const  firstbyte,
char const arg,
ut16 const  pc,
ut8 **  out 
)
static

Definition at line 475 of file 8051_ass.c.

475  {
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 }

References out, pc, relative_address(), and to_address().

Referenced by mnem_jc(), mnem_jnc(), mnem_jnz(), mnem_jz(), and mnem_sjmp().

◆ str_iwhitecasecmp()

static int str_iwhitecasecmp ( char const a,
char const b 
)
static

Like rz_str_casecmp, but ignores all isspace characters

Definition at line 245 of file 8051_ass.c.

245  {
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 }
#define b(i)
Definition: sha256.c:42

References a, b, isspace, and tolower.

Referenced by mnem_jmp(), mnem_movc(), and mnem_movx().

◆ terminates_asm_line()

static bool terminates_asm_line ( char  c)
static

returns true if there is no more valid assembly code after this character

Definition at line 238 of file 8051_ass.c.

238  {
239  return c == '\0' || c == '\n' || c == '\r' || c == ';';
240 }
#define c(i)
Definition: sha256.c:43

References c.

Referenced by assemble_8051().

◆ to_address()

static bool to_address ( char const addr_str,
ut16 addr_out 
)
static

Definition at line 376 of file 8051_ass.c.

376  {
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 }

References parse_hexadecimal().

Referenced by mnem_acall(), mnem_ajmp(), mnem_cjne(), mnem_djnz(), mnem_jb(), mnem_jbc(), mnem_jmp(), mnem_jnb(), mnem_lcall(), mnem_ljmp(), and singlearg_reladdr().