rizin/librz/analysis/p/analysis_6502_cs.c
Riccardo Schirone 53bf5c497f SPDX Copyright text for all files based on history
- Add LICENSES directory
- Download additional licenses used
- Add .reuse directory
- Add doc about SPDX/reuse

Co-authored-by: Florian Märkl <info@florianmaerkl.de>
2021-03-05 19:39:15 +08:00

230 lines
4.9 KiB
C

// SPDX-FileCopyrightText: 2018 pancake <pancake@nopcode.org>
// SPDX-License-Identifier: LGPL-3.0-only
#include <string.h>
#include <rz_types.h>
#include <rz_lib.h>
#include <rz_asm.h>
#include <rz_analysis.h>
#include <capstone.h>
#if CS_API_MAJOR >= 4 && CS_API_MINOR >= 1
#define CAPSTONE_HAS_MOS65XX 1
#else
#define CAPSTONE_HAS_MOS65XX 0
#endif
#if CAPSTONE_HAS_MOS65XX
#include <mos65xx.h>
static csh handle = 0;
static int analop(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, RzAnalysisOpMask mask) {
static int omode = 0;
#if USE_ITERZ_API
static
#endif
cs_insn *insn = NULL;
int mode = 0;
int n, ret;
if (handle && mode != omode) {
cs_close(&handle);
handle = 0;
}
omode = mode;
if (handle == 0) {
ret = cs_open(CS_ARCH_MOS65XX, mode, &handle);
if (ret != CS_ERR_OK) {
handle = 0;
return 0;
}
}
op->cycles = 1; // aprox
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
// capstone-next
#if USE_ITERZ_API
{
ut64 naddr = addr;
size_t size = len;
if (!insn) {
insn = cs_malloc(handle);
}
n = cs_disasm_iter(handle, (const uint8_t **)&buf,
&size, (uint64_t *)&naddr, insn);
}
#else
n = cs_disasm(handle, (const ut8 *)buf, len, addr, 1, &insn);
#endif
if (n < 1) {
op->type = RZ_ANALYSIS_OP_TYPE_ILL;
} else {
op->nopcode = 1;
op->size = insn->size;
op->id = insn->id;
op->family = RZ_ANALYSIS_OP_FAMILY_CPU; // almost everything is CPU
op->prefix = 0;
op->cond = 0;
switch (insn->id) {
case MOS65XX_INS_INVALID:
op->type = RZ_ANALYSIS_OP_TYPE_ILL;
break;
case MOS65XX_INS_ADC:
op->type = RZ_ANALYSIS_OP_TYPE_ADD;
break;
case MOS65XX_INS_AND:
op->type = RZ_ANALYSIS_OP_TYPE_AND;
break;
case MOS65XX_INS_ASL:
op->type = RZ_ANALYSIS_OP_TYPE_SHL;
break;
case MOS65XX_INS_BCC:
case MOS65XX_INS_BCS:
case MOS65XX_INS_BEQ:
case MOS65XX_INS_BIT:
case MOS65XX_INS_BMI:
case MOS65XX_INS_BNE:
case MOS65XX_INS_BPL:
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
break;
case MOS65XX_INS_BRK:
op->type = RZ_ANALYSIS_OP_TYPE_TRAP;
break;
case MOS65XX_INS_BVC:
case MOS65XX_INS_BVS:
case MOS65XX_INS_CLC:
case MOS65XX_INS_CLD:
case MOS65XX_INS_CLI:
case MOS65XX_INS_CLV:
case MOS65XX_INS_CPX:
case MOS65XX_INS_CPY:
break;
case MOS65XX_INS_CMP:
op->type = RZ_ANALYSIS_OP_TYPE_CMP;
break;
case MOS65XX_INS_DEC:
case MOS65XX_INS_DEX:
case MOS65XX_INS_DEY:
op->type = RZ_ANALYSIS_OP_TYPE_SUB;
break;
case MOS65XX_INS_EOR:
op->type = RZ_ANALYSIS_OP_TYPE_XOR;
break;
case MOS65XX_INS_INC:
case MOS65XX_INS_INX:
case MOS65XX_INS_INY:
op->type = RZ_ANALYSIS_OP_TYPE_ADD;
break;
case MOS65XX_INS_JMP:
op->type = RZ_ANALYSIS_OP_TYPE_JMP;
break;
case MOS65XX_INS_JSR:
op->type = RZ_ANALYSIS_OP_TYPE_RJMP;
break;
case MOS65XX_INS_LDA:
case MOS65XX_INS_LDX:
case MOS65XX_INS_LDY:
op->type = RZ_ANALYSIS_OP_TYPE_LOAD;
break;
case MOS65XX_INS_LSR:
case MOS65XX_INS_NOP:
op->type = RZ_ANALYSIS_OP_TYPE_NOP;
break;
case MOS65XX_INS_ORA:
op->type = RZ_ANALYSIS_OP_TYPE_OR;
break;
case MOS65XX_INS_PHA:
case MOS65XX_INS_PLA:
case MOS65XX_INS_PHP:
case MOS65XX_INS_PLP:
break;
case MOS65XX_INS_ROL:
op->type = RZ_ANALYSIS_OP_TYPE_SHR;
break;
case MOS65XX_INS_ROR:
op->type = RZ_ANALYSIS_OP_TYPE_ROR;
break;
case MOS65XX_INS_RTI:
case MOS65XX_INS_RTS:
case MOS65XX_INS_SBC:
case MOS65XX_INS_SEC:
case MOS65XX_INS_SED:
case MOS65XX_INS_SEI:
case MOS65XX_INS_STA:
case MOS65XX_INS_STX:
case MOS65XX_INS_STY:
case MOS65XX_INS_TAX:
case MOS65XX_INS_TAY:
case MOS65XX_INS_TSX:
case MOS65XX_INS_TXA:
case MOS65XX_INS_TXS:
case MOS65XX_INS_TYA:
break;
}
}
#if !USE_ITERZ_API
cs_free(insn, n);
#endif
//cs_close (&handle);
return op->size;
}
static bool set_reg_profile(RzAnalysis *analysis) {
char *p =
"=PC pc\n"
"=SP sp\n"
"=A0 y\n"
"=A1 x\n"
"gpr a .8 0 0\n"
"gpr x .8 1 0\n"
"gpr y .8 2 0\n"
"gpr flags .8 3 0\n"
"gpr C .1 .24 0\n"
"gpr Z .1 .25 0\n"
"gpr I .1 .26 0\n"
"gpr D .1 .27 0\n"
// bit 4 (.28) is NOT a real flag.
// "gpr B .1 .28 0\n"
// bit 5 (.29) is not used
"gpr V .1 .30 0\n"
"gpr N .1 .31 0\n"
"gpr sp .8 4 0\n"
"gpr pc .16 5 0\n";
return rz_reg_set_profile_string(analysis->reg, p);
}
RzAnalysisPlugin rz_analysis_plugin_6502_cs = {
.name = "6502.cs",
.desc = "Capstone mos65xx analysis plugin",
.license = "LGPL3",
.arch = "6502",
.bits = 8,
.op = &analop,
.set_reg_profile = &set_reg_profile,
};
#ifndef RZ_PLUGIN_INCORE
RZ_API RzLibStruct rizin_plugin = {
.type = RZ_LIB_TYPE_ANALYSIS,
.data = &rz_analysis_plugin_6502_cs,
.version = RZ_VERSION
};
#endif
#else
// empty plugin
RzAnalysisPlugin rz_analysis_plugin_6502_cs = {
.name = "6502.cs",
.desc = "Capstone mos65xx analysis plugin (not supported)",
.license = "LGPL3",
.arch = "6502",
.bits = 8,
};
#ifndef RZ_PLUGIN_INCORE
RZ_API RzLibStruct rizin_plugin = {
.type = RZ_LIB_TYPE_ANALYSIS,
.version = RZ_VERSION
};
#endif
#endif