rizin/librz/analysis/p/analysis_m680x_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

558 lines
12 KiB
C

// SPDX-FileCopyrightText: 2015-2019 pancake <pancake@nopcode.org>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_asm.h>
#include <rz_lib.h>
#include <capstone.h>
#if CS_API_MAJOR >= 4 && CS_API_MINOR >= 0
#define CAPSTONE_HAS_M680X 1
#else
#define CAPSTONE_HAS_M680X 0
#endif
#if !CAPSTONE_HAS_M680X
#ifdef _MSC_VER
#pragma message("Cannot find support for m680x in capstone")
#else
#warning Cannot find capstone-m680x support
#endif
#endif
#if CAPSTONE_HAS_M680X
#include <m680x.h>
static int m680xmode(const char *str) {
if (!str) {
return CS_MODE_M680X_6800;
}
// replace this with the asm.features?
if (str && strstr(str, "6800")) {
return CS_MODE_M680X_6800;
}
if (str && strstr(str, "6801")) {
return CS_MODE_M680X_6801;
} else if (str && strstr(str, "6805")) {
return CS_MODE_M680X_6805;
} else if (str && strstr(str, "6808")) {
return CS_MODE_M680X_6808;
} else if (str && strstr(str, "6809")) {
return CS_MODE_M680X_6809;
} else if (str && strstr(str, "6811")) {
return CS_MODE_M680X_6811;
}
//
if (str && strstr(str, "cpu12")) {
return CS_MODE_M680X_CPU12;
}
if (str && strstr(str, "6301")) {
return CS_MODE_M680X_6301;
}
if (str && strstr(str, "6309")) {
return CS_MODE_M680X_6309;
}
if (str && strstr(str, "hcs08")) {
return CS_MODE_M680X_HCS08;
}
return CS_MODE_M680X_6800;
}
#define IMM(x) insn->detail->m680x.operands[x].imm
#define REL(x) insn->detail->m680x.operands[x].rel
static int analop(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, RzAnalysisOpMask mask) {
int n, ret, opsize = -1;
static csh handle = 0;
static int omode = -1;
static int obits = 32;
cs_insn *insn;
int mode = m680xmode(a->cpu);
if (mode != omode || a->bits != obits) {
cs_close(&handle);
handle = 0;
omode = mode;
obits = a->bits;
}
op->size = 4;
if (handle == 0) {
ret = cs_open(CS_ARCH_M680X, mode, &handle);
if (ret != CS_ERR_OK) {
goto fin;
}
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
}
n = cs_disasm(handle, (ut8 *)buf, len, addr, 1, &insn);
if (n < 1 || insn->size < 1) {
op->type = RZ_ANALYSIS_OP_TYPE_ILL;
op->size = 2;
opsize = -1;
goto beach;
}
if (!memcmp(buf, "\xff\xff", RZ_MIN(len, 2))) {
op->type = RZ_ANALYSIS_OP_TYPE_ILL;
op->size = 2;
opsize = -1;
goto beach;
}
op->id = insn->id;
opsize = op->size = insn->size;
switch (insn->id) {
case M680X_INS_INVLD:
op->type = RZ_ANALYSIS_OP_TYPE_ILL;
break;
case M680X_INS_ABA: ///< M6800/1/2/3
case M680X_INS_ABX:
case M680X_INS_ABY:
break;
case M680X_INS_ADC:
case M680X_INS_ADCA:
case M680X_INS_ADCB:
case M680X_INS_ADCD:
case M680X_INS_ADCR:
case M680X_INS_ADD:
case M680X_INS_ADDA:
case M680X_INS_ADDB:
case M680X_INS_ADDD:
case M680X_INS_ADDE:
case M680X_INS_ADDF:
case M680X_INS_ADDR:
case M680X_INS_ADDW:
op->type = RZ_ANALYSIS_OP_TYPE_ADD;
break;
case M680X_INS_AIM:
case M680X_INS_AIS:
case M680X_INS_AIX:
case M680X_INS_AND:
case M680X_INS_ANDA:
case M680X_INS_ANDB:
case M680X_INS_ANDCC:
case M680X_INS_ANDD:
case M680X_INS_ANDR:
case M680X_INS_ASL:
case M680X_INS_ASLA:
case M680X_INS_ASLB:
case M680X_INS_ASLD: ///< or LSLD
case M680X_INS_ASR:
case M680X_INS_ASRA:
case M680X_INS_ASRB:
case M680X_INS_ASRD:
case M680X_INS_ASRX:
case M680X_INS_BAND:
case M680X_INS_BCC: ///< or BHS
case M680X_INS_BCLR:
case M680X_INS_BCS: ///< or BLO
case M680X_INS_BEOR:
break;
case M680X_INS_BIAND:
case M680X_INS_BIEOR:
case M680X_INS_BIH:
case M680X_INS_BIL:
case M680X_INS_BIOR:
case M680X_INS_BIT:
case M680X_INS_BITA:
case M680X_INS_BITB:
case M680X_INS_BITD:
case M680X_INS_BITMD:
break;
case M680X_INS_BRA:
op->type = RZ_ANALYSIS_OP_TYPE_JMP;
op->jump = addr + op->size + REL(0).offset;
op->fail = UT64_MAX;
break;
case M680X_INS_BEQ:
case M680X_INS_BGE:
case M680X_INS_BGND:
case M680X_INS_BGT:
case M680X_INS_BHCC:
case M680X_INS_BHCS:
case M680X_INS_BHI:
case M680X_INS_BLE:
case M680X_INS_BLS:
case M680X_INS_BLT:
case M680X_INS_BMC:
case M680X_INS_BMI:
case M680X_INS_BMS:
case M680X_INS_BNE:
case M680X_INS_BOR:
case M680X_INS_BPL:
case M680X_INS_BRCLR:
case M680X_INS_BRSET:
case M680X_INS_BRN:
case M680X_INS_BSET:
case M680X_INS_BSR:
case M680X_INS_BVC:
case M680X_INS_BVS:
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
op->jump = addr + op->size + REL(0).offset;
op->fail = addr + op->size;
break;
case M680X_INS_CALL:
case M680X_INS_CBA: ///< M6800/1/2/3
case M680X_INS_CBEQ:
case M680X_INS_CBEQA:
case M680X_INS_CBEQX:
case M680X_INS_CLC: ///< M6800/1/2/3
case M680X_INS_CLI: ///< M6800/1/2/3
case M680X_INS_CLR:
case M680X_INS_CLRA:
case M680X_INS_CLRB:
case M680X_INS_CLRD:
case M680X_INS_CLRE:
case M680X_INS_CLRF:
case M680X_INS_CLRH:
case M680X_INS_CLRW:
case M680X_INS_CLRX:
case M680X_INS_CLV: ///< M6800/1/2/3
break;
case M680X_INS_CMP:
case M680X_INS_CMPA:
case M680X_INS_CMPB:
case M680X_INS_CMPD:
case M680X_INS_CMPE:
case M680X_INS_CMPF:
case M680X_INS_CMPR:
case M680X_INS_CMPS:
case M680X_INS_CMPU:
case M680X_INS_CMPW:
case M680X_INS_CMPX:
case M680X_INS_CMPY:
op->type = RZ_ANALYSIS_OP_TYPE_CMP;
break;
case M680X_INS_COM:
case M680X_INS_COMA:
case M680X_INS_COMB:
case M680X_INS_COMD:
case M680X_INS_COME:
case M680X_INS_COMF:
case M680X_INS_COMW:
case M680X_INS_COMX:
case M680X_INS_CPD:
case M680X_INS_CPHX:
case M680X_INS_CPS:
case M680X_INS_CPX: ///< M6800/1/2/3
case M680X_INS_CPY:
case M680X_INS_CWAI:
case M680X_INS_DAA:
case M680X_INS_DBEQ:
case M680X_INS_DBNE:
case M680X_INS_DBNZ:
case M680X_INS_DBNZA:
case M680X_INS_DBNZX:
case M680X_INS_DEC:
case M680X_INS_DECA:
case M680X_INS_DECB:
case M680X_INS_DECD:
case M680X_INS_DECE:
case M680X_INS_DECF:
case M680X_INS_DECW:
case M680X_INS_DECX:
case M680X_INS_DES: ///< M6800/1/2/3
case M680X_INS_DEX: ///< M6800/1/2/3
case M680X_INS_DEY:
case M680X_INS_DIV:
case M680X_INS_DIVD:
case M680X_INS_DIVQ:
case M680X_INS_EDIV:
case M680X_INS_EDIVS:
case M680X_INS_EIM:
case M680X_INS_EMACS:
case M680X_INS_EMAXD:
case M680X_INS_EMAXM:
case M680X_INS_EMIND:
case M680X_INS_EMINM:
break;
case M680X_INS_EMUL:
case M680X_INS_EMULS:
op->type = RZ_ANALYSIS_OP_TYPE_MUL;
break;
case M680X_INS_EOR:
case M680X_INS_EORA:
case M680X_INS_EORB:
case M680X_INS_EORD:
case M680X_INS_EORR:
op->type = RZ_ANALYSIS_OP_TYPE_XOR;
break;
case M680X_INS_ETBL:
case M680X_INS_EXG:
case M680X_INS_FDIV:
case M680X_INS_IBEQ:
case M680X_INS_IBNE:
break;
case M680X_INS_IDIV:
case M680X_INS_IDIVS:
op->type = RZ_ANALYSIS_OP_TYPE_DIV;
break;
case M680X_INS_ILLGL:
break;
case M680X_INS_INC:
case M680X_INS_INCA:
case M680X_INS_INCB:
case M680X_INS_INCD:
case M680X_INS_INCE:
case M680X_INS_INCF:
case M680X_INS_INCW:
case M680X_INS_INCX:
op->type = RZ_ANALYSIS_OP_TYPE_ADD;
break;
case M680X_INS_INS: ///< M6800/1/2/3
case M680X_INS_INX: ///< M6800/1/2/3
case M680X_INS_INY:
break;
case M680X_INS_JMP:
op->type = RZ_ANALYSIS_OP_TYPE_JMP;
break;
case M680X_INS_JSR:
op->type = RZ_ANALYSIS_OP_TYPE_RJMP;
break;
case M680X_INS_LBCC: ///< or LBHS
case M680X_INS_LBCS: ///< or LBLO
case M680X_INS_LBEQ:
case M680X_INS_LBGE:
case M680X_INS_LBGT:
case M680X_INS_LBHI:
case M680X_INS_LBLE:
case M680X_INS_LBLS:
case M680X_INS_LBLT:
case M680X_INS_LBMI:
case M680X_INS_LBNE:
case M680X_INS_LBPL:
case M680X_INS_LBRA:
case M680X_INS_LBRN:
case M680X_INS_LBSR:
case M680X_INS_LBVC:
case M680X_INS_LBVS:
case M680X_INS_LDA:
case M680X_INS_LDAA: ///< M6800/1/2/3
case M680X_INS_LDAB: ///< M6800/1/2/3
case M680X_INS_LDB:
case M680X_INS_LDBT:
case M680X_INS_LDD:
case M680X_INS_LDE:
case M680X_INS_LDF:
case M680X_INS_LDHX:
case M680X_INS_LDMD:
case M680X_INS_LDQ:
case M680X_INS_LDS:
case M680X_INS_LDU:
case M680X_INS_LDW:
case M680X_INS_LDX:
case M680X_INS_LDY:
case M680X_INS_LEAS:
case M680X_INS_LEAU:
case M680X_INS_LEAX:
case M680X_INS_LEAY:
case M680X_INS_LSL:
case M680X_INS_LSLA:
case M680X_INS_LSLB:
case M680X_INS_LSLD:
case M680X_INS_LSLX:
case M680X_INS_LSR:
case M680X_INS_LSRA:
case M680X_INS_LSRB:
case M680X_INS_LSRD: ///< or ASRD
case M680X_INS_LSRW:
case M680X_INS_LSRX:
case M680X_INS_MAXA:
case M680X_INS_MAXM:
case M680X_INS_MEM:
case M680X_INS_MINA:
case M680X_INS_MINM:
break;
case M680X_INS_MOV:
case M680X_INS_MOVB:
case M680X_INS_MOVW:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
break;
case M680X_INS_MUL:
case M680X_INS_MULD:
op->type = RZ_ANALYSIS_OP_TYPE_MUL;
break;
case M680X_INS_NEG:
case M680X_INS_NEGA:
case M680X_INS_NEGB:
case M680X_INS_NEGD:
case M680X_INS_NEGX:
op->type = RZ_ANALYSIS_OP_TYPE_NOT;
break;
case M680X_INS_NOP:
op->type = RZ_ANALYSIS_OP_TYPE_NOP;
break;
case M680X_INS_NSA:
case M680X_INS_OIM:
case M680X_INS_ORA:
case M680X_INS_ORAA: ///< M6800/1/2/3
case M680X_INS_ORAB: ///< M6800/1/2/3
case M680X_INS_ORB:
case M680X_INS_ORCC:
case M680X_INS_ORD:
case M680X_INS_ORR:
case M680X_INS_PSHA: ///< M6800/1/2/3
case M680X_INS_PSHB: ///< M6800/1/2/3
case M680X_INS_PSHC:
case M680X_INS_PSHD:
case M680X_INS_PSHH:
case M680X_INS_PSHS:
case M680X_INS_PSHSW:
case M680X_INS_PSHU:
case M680X_INS_PSHUW:
case M680X_INS_PSHX: ///< M6800/1/2/3
case M680X_INS_PSHY:
case M680X_INS_PULA: ///< M6800/1/2/3
case M680X_INS_PULB: ///< M6800/1/2/3
case M680X_INS_PULC:
case M680X_INS_PULD:
case M680X_INS_PULH:
case M680X_INS_PULS:
case M680X_INS_PULSW:
case M680X_INS_PULU:
case M680X_INS_PULUW:
case M680X_INS_PULX: ///< M6800/1/2/3
case M680X_INS_PULY:
case M680X_INS_REV:
case M680X_INS_REVW:
case M680X_INS_ROL:
case M680X_INS_ROLA:
case M680X_INS_ROLB:
case M680X_INS_ROLD:
case M680X_INS_ROLW:
case M680X_INS_ROLX:
case M680X_INS_ROR:
case M680X_INS_RORA:
case M680X_INS_RORB:
case M680X_INS_RORD:
case M680X_INS_RORW:
case M680X_INS_RORX:
case M680X_INS_RSP:
case M680X_INS_RTC:
case M680X_INS_RTI:
case M680X_INS_RTS:
case M680X_INS_SBA: ///< M6800/1/2/3
case M680X_INS_SBC:
case M680X_INS_SBCA:
case M680X_INS_SBCB:
case M680X_INS_SBCD:
case M680X_INS_SBCR:
case M680X_INS_SEC:
case M680X_INS_SEI:
case M680X_INS_SEV:
case M680X_INS_SEX:
case M680X_INS_SEXW:
case M680X_INS_SLP:
case M680X_INS_STA:
case M680X_INS_STAA: ///< M6800/1/2/3
case M680X_INS_STAB: ///< M6800/1/2/3
case M680X_INS_STB:
case M680X_INS_STBT:
case M680X_INS_STD:
case M680X_INS_STE:
case M680X_INS_STF:
case M680X_INS_STOP:
case M680X_INS_STHX:
case M680X_INS_STQ:
case M680X_INS_STS:
case M680X_INS_STU:
case M680X_INS_STW:
case M680X_INS_STX:
case M680X_INS_STY:
case M680X_INS_SUB:
case M680X_INS_SUBA:
case M680X_INS_SUBB:
case M680X_INS_SUBD:
case M680X_INS_SUBE:
case M680X_INS_SUBF:
case M680X_INS_SUBR:
case M680X_INS_SUBW:
op->type = RZ_ANALYSIS_OP_TYPE_SUB;
break;
case M680X_INS_SWI:
case M680X_INS_SWI2:
case M680X_INS_SWI3:
op->type = RZ_ANALYSIS_OP_TYPE_SWI;
break;
case M680X_INS_SYNC:
case M680X_INS_TAB: ///< M6800/1/2/3
case M680X_INS_TAP: ///< M6800/1/2/3
case M680X_INS_TAX:
break;
case M680X_INS_TBA: ///< M6800/1/2/3
case M680X_INS_TBEQ:
case M680X_INS_TBL:
case M680X_INS_TBNE:
case M680X_INS_TEST:
case M680X_INS_TFM:
case M680X_INS_TFR:
case M680X_INS_TIM:
case M680X_INS_TPA: ///< M6800/1/2/3
case M680X_INS_TST:
case M680X_INS_TSTA:
case M680X_INS_TSTB:
case M680X_INS_TSTD:
case M680X_INS_TSTE:
case M680X_INS_TSTF:
case M680X_INS_TSTW:
case M680X_INS_TSTX:
op->type = RZ_ANALYSIS_OP_TYPE_CMP;
break;
case M680X_INS_TSX: ///< M6800/1/2/3
case M680X_INS_TSY:
case M680X_INS_TXA:
case M680X_INS_TXS: ///< M6800/1/2/3
case M680X_INS_TYS:
case M680X_INS_WAI: ///< M6800/1/2/3
case M680X_INS_WAIT:
case M680X_INS_WAV:
case M680X_INS_WAVR:
case M680X_INS_XGDX: ///< HD6301
case M680X_INS_XGDY:
break;
}
beach:
cs_free(insn, n);
//cs_close (&handle);
fin:
return opsize;
}
// XXX
static bool set_reg_profile(RzAnalysis *analysis) {
const char *p =
"=PC pc\n"
"=SP sp\n"
"=A0 a0\n"
"=A1 a1\n"
"gpr pc .16 48 0\n"
"gpr sp .16 48 0\n"
"gpr a0 .16 48 0\n"
"gpr a1 .16 48 0\n";
return rz_reg_set_profile_string(analysis->reg, p);
}
RzAnalysisPlugin rz_analysis_plugin_m680x_cs = {
.name = "m680x",
.desc = "Capstone M680X analysis plugin",
.license = "BSD",
.esil = false,
.arch = "m680x",
.set_reg_profile = &set_reg_profile,
.bits = 16 | 32,
.op = &analop,
};
#else
RzAnalysisPlugin rz_analysis_plugin_m680x_cs = {
.name = "m680x (unsupported)",
.desc = "Capstone M680X analyzer (unsupported)",
.license = "BSD",
.arch = "m680x",
.bits = 32,
};
#endif
#ifndef RZ_PLUGIN_INCORE
RZ_API RzLibStruct rizin_plugin = {
.type = RZ_LIB_TYPE_ANALYSIS,
.data = &rz_analysis_plugin_m680x_cs,
.version = RZ_VERSION
};
#endif