- Add LICENSES directory - Download additional licenses used - Add .reuse directory - Add doc about SPDX/reuse Co-authored-by: Florian Märkl <info@florianmaerkl.de>
414 lines
7.1 KiB
C
414 lines
7.1 KiB
C
// SPDX-FileCopyrightText: 2015 condret <condr3t@protonmail.com>
|
|
// 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 "../../asm/arch/snes/snes_op_table.h"
|
|
#include "../../asm/p/asm_snes.h"
|
|
|
|
static struct snes_asm_flags *snesflags = NULL;
|
|
|
|
static int snes_anop(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask) {
|
|
op->size = snes_op_get_size(snesflags->M, snesflags->X, &snes_op[data[0]]);
|
|
if (op->size > len) {
|
|
return op->size = 0;
|
|
}
|
|
op->nopcode = 1;
|
|
op->addr = addr;
|
|
op->type = RZ_ANALYSIS_OP_TYPE_UNK;
|
|
switch (data[0]) {
|
|
case 0xea: // nop
|
|
op->type = RZ_ANALYSIS_OP_TYPE_NOP;
|
|
break;
|
|
case 0xfb: // xce
|
|
op->type = RZ_ANALYSIS_OP_TYPE_XCHG;
|
|
break;
|
|
case 0x00: // brk
|
|
case 0x02: // cop
|
|
op->type = RZ_ANALYSIS_OP_TYPE_SWI;
|
|
break;
|
|
case 0x1b: // tcs
|
|
case 0x3b: // tsc
|
|
case 0x5b: // tcd
|
|
case 0x7b: // tdc
|
|
case 0x8a: // txa
|
|
case 0x98: // tya
|
|
case 0x9a: // txs
|
|
case 0x9b: // txy
|
|
case 0xa8: // tay
|
|
case 0xaa: // tax
|
|
case 0xba: // tsx
|
|
case 0xbb: // tyx
|
|
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
|
|
break;
|
|
case 0x48: // pha
|
|
case 0x8b: // phb
|
|
case 0x0b: // phd
|
|
case 0x4b: // phk
|
|
case 0x08: // php
|
|
case 0xda: // phx
|
|
case 0x5a: // phy
|
|
op->type = RZ_ANALYSIS_OP_TYPE_PUSH;
|
|
break;
|
|
case 0x68: // pla
|
|
case 0xab: // plb
|
|
case 0x2b: // pld
|
|
case 0x28: // plp
|
|
case 0xfa: // plx
|
|
case 0x7a: // ply
|
|
op->type = RZ_ANALYSIS_OP_TYPE_POP;
|
|
break;
|
|
// adc
|
|
case 0x61:
|
|
case 0x63:
|
|
case 0x65:
|
|
case 0x67:
|
|
case 0x69:
|
|
case 0x6d:
|
|
case 0x6f:
|
|
case 0x71:
|
|
case 0x72:
|
|
case 0x73:
|
|
case 0x75:
|
|
case 0x77:
|
|
case 0x79:
|
|
case 0x7d:
|
|
case 0x7f:
|
|
// inc
|
|
case 0x1a:
|
|
case 0xe6:
|
|
case 0xee:
|
|
case 0xf6:
|
|
case 0xfe:
|
|
case 0xe8: // inx
|
|
case 0xc8: // iny
|
|
op->type = RZ_ANALYSIS_OP_TYPE_ADD;
|
|
break;
|
|
// and
|
|
case 0x23:
|
|
case 0x25:
|
|
case 0x27:
|
|
case 0x29:
|
|
case 0x2d:
|
|
case 0x2f:
|
|
case 0x31:
|
|
case 0x32:
|
|
case 0x33:
|
|
case 0x35:
|
|
case 0x37:
|
|
case 0x39:
|
|
case 0x3d:
|
|
case 0x3f:
|
|
op->type = RZ_ANALYSIS_OP_TYPE_AND;
|
|
break;
|
|
// bit
|
|
case 0x24:
|
|
case 0x2c:
|
|
case 0x34:
|
|
case 0x3c:
|
|
case 0x89:
|
|
op->type = RZ_ANALYSIS_OP_TYPE_ACMP;
|
|
break;
|
|
// cmp
|
|
case 0xc1:
|
|
case 0xc3:
|
|
case 0xc5:
|
|
case 0xc7:
|
|
case 0xc9:
|
|
case 0xcd:
|
|
case 0xcf:
|
|
case 0xd1:
|
|
case 0xd2:
|
|
case 0xd3:
|
|
case 0xd5:
|
|
case 0xd7:
|
|
case 0xd9:
|
|
case 0xdd:
|
|
case 0xdf:
|
|
// cpx
|
|
case 0xe0:
|
|
case 0xe4:
|
|
case 0xec:
|
|
// cpy
|
|
case 0xc0:
|
|
case 0xc4:
|
|
case 0xcc:
|
|
op->type = RZ_ANALYSIS_OP_TYPE_CMP;
|
|
break;
|
|
// ora
|
|
case 0x01:
|
|
case 0x03:
|
|
case 0x05:
|
|
case 0x07:
|
|
case 0x09:
|
|
case 0x0d:
|
|
case 0x0f:
|
|
case 0x11:
|
|
case 0x12:
|
|
case 0x13:
|
|
case 0x15:
|
|
case 0x17:
|
|
case 0x19:
|
|
case 0x1d:
|
|
case 0x1f:
|
|
op->type = RZ_ANALYSIS_OP_TYPE_OR;
|
|
break;
|
|
// eor
|
|
case 0x41:
|
|
case 0x43:
|
|
case 0x45:
|
|
case 0x47:
|
|
case 0x49:
|
|
case 0x4d:
|
|
case 0x4f:
|
|
case 0x51:
|
|
case 0x52:
|
|
case 0x53:
|
|
case 0x55:
|
|
case 0x57:
|
|
case 0x59:
|
|
case 0x5d:
|
|
case 0x5f:
|
|
op->type = RZ_ANALYSIS_OP_TYPE_XOR;
|
|
break;
|
|
// asl
|
|
case 0x06:
|
|
case 0x0a:
|
|
case 0x0e:
|
|
case 0x16:
|
|
case 0x1e:
|
|
op->type = RZ_ANALYSIS_OP_TYPE_SAL;
|
|
break;
|
|
// lsr
|
|
case 0x46:
|
|
case 0x4a:
|
|
case 0x4e:
|
|
case 0x56:
|
|
case 0x5e:
|
|
op->type = RZ_ANALYSIS_OP_TYPE_SHR;
|
|
break;
|
|
// rol
|
|
case 0x26:
|
|
case 0x2a:
|
|
case 0x2e:
|
|
case 0x36:
|
|
case 0x3e:
|
|
op->type = RZ_ANALYSIS_OP_TYPE_ROL;
|
|
break;
|
|
// ror
|
|
case 0x66:
|
|
case 0x6a:
|
|
case 0x6e:
|
|
case 0x76:
|
|
case 0x7e:
|
|
op->type = RZ_ANALYSIS_OP_TYPE_ROR;
|
|
break;
|
|
// sbc
|
|
case 0xe1:
|
|
case 0xe3:
|
|
case 0xe5:
|
|
case 0xe7:
|
|
case 0xe9:
|
|
case 0xed:
|
|
case 0xef:
|
|
case 0xf1:
|
|
case 0xf2:
|
|
case 0xf3:
|
|
case 0xf5:
|
|
case 0xf7:
|
|
case 0xf9:
|
|
case 0xfd:
|
|
case 0xff:
|
|
// dec
|
|
case 0x3a:
|
|
case 0xc6:
|
|
case 0xce:
|
|
case 0xd6:
|
|
case 0xde:
|
|
case 0xca: // dex
|
|
case 0x88: // dey
|
|
op->type = RZ_ANALYSIS_OP_TYPE_SUB;
|
|
break;
|
|
// sta
|
|
case 0x81:
|
|
case 0x83:
|
|
case 0x85:
|
|
case 0x87:
|
|
case 0x8d:
|
|
case 0x8f:
|
|
case 0x91:
|
|
case 0x92:
|
|
case 0x93:
|
|
case 0x95:
|
|
case 0x97:
|
|
case 0x99:
|
|
case 0x9d:
|
|
case 0x9f:
|
|
// stx
|
|
case 0x86:
|
|
case 0x8e:
|
|
case 0x96:
|
|
// sty
|
|
case 0x84:
|
|
case 0x8c:
|
|
case 0x94:
|
|
// stz
|
|
case 0x64:
|
|
case 0x74:
|
|
case 0x9c:
|
|
case 0x9e:
|
|
op->type = RZ_ANALYSIS_OP_TYPE_STORE;
|
|
break;
|
|
// lda
|
|
case 0xa1:
|
|
case 0xa3:
|
|
case 0xa5:
|
|
case 0xa7:
|
|
case 0xa9:
|
|
case 0xad:
|
|
case 0xaf:
|
|
case 0xb1:
|
|
case 0xb2:
|
|
case 0xb3:
|
|
case 0xb5:
|
|
case 0xb7:
|
|
case 0xb9:
|
|
case 0xbd:
|
|
case 0xbf:
|
|
// ldx
|
|
case 0xa2:
|
|
case 0xa6:
|
|
case 0xae:
|
|
case 0xb6:
|
|
case 0xbe:
|
|
// ldy
|
|
case 0xa0:
|
|
case 0xa4:
|
|
case 0xac:
|
|
case 0xb4:
|
|
case 0xbc:
|
|
op->type = RZ_ANALYSIS_OP_TYPE_LOAD;
|
|
break;
|
|
case 0x4c: // jmp addr
|
|
op->eob = true;
|
|
op->jump = (addr & 0xFF0000) | ut8p_bw(data + 1);
|
|
op->type = RZ_ANALYSIS_OP_TYPE_JMP;
|
|
break;
|
|
case 0x5c: // jmp long
|
|
op->eob = true;
|
|
op->jump = data[1] | data[2] << 8 | data[3] << 16;
|
|
op->type = RZ_ANALYSIS_OP_TYPE_JMP;
|
|
break;
|
|
case 0x80: // bra
|
|
op->eob = true;
|
|
op->jump = addr + 2 + (st8)data[1];
|
|
op->type = RZ_ANALYSIS_OP_TYPE_JMP;
|
|
break;
|
|
case 0x82: // brl
|
|
op->eob = true;
|
|
op->jump = addr + 3 + (st16)ut8p_bw(data + 1);
|
|
op->type = RZ_ANALYSIS_OP_TYPE_JMP;
|
|
break;
|
|
case 0x6c: // jmp (addr)
|
|
case 0x7c: // jmp (addr,X)
|
|
case 0xdc: // jmp [addr]
|
|
op->eob = true;
|
|
op->type = RZ_ANALYSIS_OP_TYPE_UJMP;
|
|
break;
|
|
case 0x10: // bpl
|
|
case 0x30: // bmi
|
|
case 0x50: // bvc
|
|
case 0x70: // bvs
|
|
case 0x90: // bcc
|
|
case 0xb0: // bcs
|
|
op->eob = true;
|
|
op->jump = addr + 2 + (st8)data[1];
|
|
op->fail = addr + 2;
|
|
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
|
|
break;
|
|
case 0xd0: // bne
|
|
op->eob = true;
|
|
op->cond = RZ_ANALYSIS_COND_NE;
|
|
op->jump = addr + 2 + (st8)data[1];
|
|
op->fail = addr + 2;
|
|
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
|
|
break;
|
|
case 0xf0: // beq
|
|
op->eob = true;
|
|
op->cond = RZ_ANALYSIS_COND_EQ;
|
|
op->jump = addr + 2 + (st8)data[1];
|
|
op->fail = addr + 2;
|
|
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
|
|
break;
|
|
case 0x20: // jsr addr
|
|
op->jump = (addr & 0xFF0000) | ut8p_bw(data + 1);
|
|
op->type = RZ_ANALYSIS_OP_TYPE_CALL;
|
|
break;
|
|
case 0x22: // jsr long
|
|
op->jump = data[1] | data[2] << 8 | data[3] << 16;
|
|
op->type = RZ_ANALYSIS_OP_TYPE_CALL;
|
|
break;
|
|
case 0xfc: // jsr (addr,X)
|
|
op->type = RZ_ANALYSIS_OP_TYPE_UCALL;
|
|
break;
|
|
case 0x40: // rti
|
|
case 0x60: // rts
|
|
case 0x6b: // rtl
|
|
op->eob = true;
|
|
op->type = RZ_ANALYSIS_OP_TYPE_RET;
|
|
break;
|
|
case 0xc2: // rep
|
|
if (((st8)data[1]) & 0x10) {
|
|
snesflags->X = 0;
|
|
}
|
|
if (((st8)data[1]) & 0x20) {
|
|
snesflags->M = 0;
|
|
}
|
|
break;
|
|
case 0xe2: // sep
|
|
if (((st8)data[1]) & 0x10) {
|
|
snesflags->X = 1;
|
|
}
|
|
if (((st8)data[1]) & 0x20) {
|
|
snesflags->M = 1;
|
|
}
|
|
break;
|
|
}
|
|
return op->size;
|
|
}
|
|
|
|
static int snes_analysis_init(void *user) {
|
|
if (!snesflags) {
|
|
snesflags = malloc(sizeof(struct snes_asm_flags));
|
|
}
|
|
memset(snesflags, 0, sizeof(struct snes_asm_flags));
|
|
return 0;
|
|
}
|
|
|
|
static int snes_analysis_fini(void *user) {
|
|
free(snesflags);
|
|
snesflags = NULL;
|
|
return 0;
|
|
}
|
|
|
|
RzAnalysisPlugin rz_analysis_plugin_snes = {
|
|
.name = "snes",
|
|
.desc = "SNES analysis plugin",
|
|
.license = "LGPL3",
|
|
.arch = "snes",
|
|
.bits = 16,
|
|
.init = snes_analysis_init,
|
|
.fini = snes_analysis_fini,
|
|
.op = &snes_anop,
|
|
};
|
|
|
|
#ifndef RZ_PLUGIN_INCORE
|
|
RZ_API RzLibStruct rizin_plugin = {
|
|
.type = RZ_LIB_TYPE_ANALYSIS,
|
|
.data = &rz_analysis_plugin_snes,
|
|
.version = RZ_VERSION
|
|
};
|
|
#endif
|