static int i8051_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { op->delay = 0; int i = 0; while (_8051_ops[i].string && _8051_ops[i].op != (buf[0] & ~_8051_ops[i].mask)) { i++; } op->size = _8051_ops[i].len; op->jump = op->fail = -1; op->ptr = op->val = -1; ut8 arg1 = _8051_ops[i].arg1; ut8 arg2 = _8051_ops[i].arg2; switch (arg1) { case A_DIRECT: op->ptr = buf[1]; break; case A_BIT: op->ptr = arg_bit (buf[1]); break; case A_IMMEDIATE: op->val = buf[1]; break; case A_IMM16: op->val = buf[1] * 256 + buf[2]; break; default: break; } switch (arg2) { case A_DIRECT: op->ptr = (arg1 == A_RI || arg1 == A_RN) ? buf[1] : buf[2]; break; case A_BIT: op->ptr = arg_bit ((arg1 == A_RI || arg1 == A_RN) ? buf[1] : buf[2]); break; case A_IMMEDIATE: op->val = (arg1 == A_RI || arg1 == A_RN) ? buf[1] : buf[2]; break; default: break; } switch(_8051_ops[i].instr) { case OP_PUSH: op->type = R_ANAL_OP_TYPE_PUSH; op->ptr = 0; op->stackop = R_ANAL_STACK_INC; op->stackptr = 1; break; case OP_POP: op->type = R_ANAL_OP_TYPE_POP; op->ptr = 0; op->stackop = R_ANAL_STACK_INC; op->stackptr = -1; break; case OP_RET: op->type = R_ANAL_OP_TYPE_RET; op->stackop = R_ANAL_STACK_INC; op->stackptr = -2; break; case OP_NOP: op->type = R_ANAL_OP_TYPE_NOP; break; case OP_INC: case OP_ADD: case OP_ADDC: op->type = R_ANAL_OP_TYPE_ADD; break; case OP_DEC: case OP_SUBB: op->type = R_ANAL_OP_TYPE_SUB; break; case OP_ANL: op->type = R_ANAL_OP_TYPE_AND; break; case OP_ORL: op->type = R_ANAL_OP_TYPE_OR; break; case OP_XRL: op->type = R_ANAL_OP_TYPE_XOR; break; case OP_CPL: op->type = R_ANAL_OP_TYPE_CPL; break; case OP_XCH: op->type = R_ANAL_OP_TYPE_XCHG; break; case OP_MOV: op->type = R_ANAL_OP_TYPE_MOV; break; case OP_MUL: op->type = R_ANAL_OP_TYPE_MUL; break; case OP_DIV: op->type = R_ANAL_OP_TYPE_DIV; break; case OP_CALL: op->type = R_ANAL_OP_TYPE_CALL; if (arg1 == A_ADDR11) { op->jump = arg_addr11 (addr + op->size, buf); op->fail = addr + op->size; } else if (arg1 == A_ADDR16) { op->jump = 0x100 * buf[1] + buf[2]; op->fail = addr + op->size; } break; case OP_JMP: op->type = R_ANAL_OP_TYPE_JMP; if (arg1 == A_ADDR11) { op->jump = arg_addr11 (addr + op->size, buf); op->fail = addr + op->size; } else if (arg1 == A_ADDR16) { op->jump = 0x100 * buf[1] + buf[2]; op->fail = addr + op->size; } else if (arg1 == A_OFFSET) { op->jump = arg_offset (addr + op->size, buf[1]); op->fail = addr + op->size; } break; case OP_CJNE: case OP_DJNZ: case OP_JC: case OP_JNC: case OP_JZ: case OP_JNZ: case OP_JB: case OP_JBC: case OP_JNB: op->type = R_ANAL_OP_TYPE_CJMP; if (op->size == 2) { op->jump = arg_offset (addr + 2, buf[1]); op->fail = addr + 2; } else if (op->size == 3) { op->jump = arg_offset (addr + 3, buf[2]); op->fail = addr + 3; } break; case OP_INVALID: op->type = R_ANAL_OP_TYPE_ILL; break; default: op->type = R_ANAL_OP_TYPE_UNK; break; } if (op->ptr != -1 && op->refptr == 0) { op->refptr = 1; } if (anal->decode) { ut8 copy[3] = {0, 0, 0}; memcpy (copy, buf, len >= 3 ? 3 : len); analop_esil (anal, op, addr, copy); } return op->size; }
int _8051_disas (ut64 pc, RAsmOp *op, const ut8 *buf, ut64 len) { int i = 0; while (_8051_ops[i].string && _8051_ops[i].op != (buf[0] & ~_8051_ops[i].mask)) { i++; } if (_8051_ops[i].string) { // valid opcodes const char* name = _8051_ops[i].string; ut8 mask = _8051_ops[i].mask; ut8 arg1 = _8051_ops[i].arg1; ut8 arg2 = _8051_ops[i].arg2; ut8 arg3 = _8051_ops[i].arg3; ut8 oplen = _8051_ops[i].len; switch (oplen) { case 1: if ((arg1 == A_RI) || (arg1 == A_RN)) { // op @Ri; op Rn sprintf (op->buf_asm, name, buf[0] & mask); } else { sprintf (op->buf_asm, "%s", name); } break; case 2: if (len>1) { if (arg1 == A_OFFSET) { sprintf (op->buf_asm, name, arg_offset (pc + 2, buf[1])); } else if (arg1 == A_ADDR11) { sprintf (op->buf_asm, name, arg_addr11 (pc + 2, buf)); } else if ((arg1 == A_RI) || (arg1 == A_RN)) { // op @Ri, arg; op Rn, arg if (arg2 == A_OFFSET) { sprintf (op->buf_asm, name, buf[0] & mask, arg_offset (pc + 2, buf[1])); } else { sprintf (op->buf_asm, name, buf[0] & mask, buf[1]); } } else if ((arg2 == A_RI) || (arg2 == A_RN)) { // op arg, @Ri; op arg, Rn sprintf (op->buf_asm, name, buf[1], buf[0] & mask); } else if (arg1 == A_BIT) { // bit addressing mode sprintf (op->buf_asm, name, arg_bit (buf[1]), buf[1] & 0x07); } else { // direct, immediate, bit sprintf (op->buf_asm, name, buf[1]); } } else { strcpy (op->buf_asm, "truncated"); return -1; } break; case 3: if (len>2) { if ((arg1 == A_ADDR16) || (arg1 == A_IMM16)) { sprintf (op->buf_asm, name, 0x100 * buf[1] + buf[2]); } else if (arg1 == A_IMM16) { sprintf (op->buf_asm, name, 0x100 * buf[1] + buf[2]); } else if (arg2 == A_OFFSET) { if (mask != A_NONE) { // @Ri, immediate, offset; Rn, immediate, offset sprintf (op->buf_asm, name, buf[0] & mask, buf[1], arg_offset (pc + 3, buf[1])); } else if (arg1 == A_BIT) { // bit, offset sprintf (op->buf_asm, name, arg_bit (buf[1]), buf[1] & 0x07, arg_offset (pc + 3, buf[2])); } else { // direct, offset; a, immediate, offset sprintf (op->buf_asm, name, buf[1], arg_offset (pc + 3, buf[2])); } } else if (arg3 == A_OFFSET) { // @Ri/Rn, direct, offset sprintf (op->buf_asm, name, buf[0] & mask, buf[1], arg_offset (pc + 3, buf[2])); } else if (arg1 == A_DIRECT && arg2 == A_DIRECT) { // op direct, direct has src and dest swapped sprintf (op->buf_asm, name, buf[2], buf[1]); } else { // direct, immediate sprintf (op->buf_asm, name, buf[1], buf[2]); } } else { strcpy (op->buf_asm, "truncated"); return -1; } break; default: // if we get here something is wrong return 0; } return oplen; } // invalid op-code return 0; }