1 /* radare - LGPL - Copyright 2015 - condret */
2 
3 #include <string.h>
4 #include <r_types.h>
5 #include <r_lib.h>
6 #include <r_asm.h>
7 #include <r_anal.h>
8 #include "../../asm/arch/snes/snes_op_table.h"
9 #include "../../asm/p/asm_snes.h"
10 
11 static struct snes_asm_flags* snesflags = NULL;
12 
snes_anop(RAnal * anal,RAnalOp * op,ut64 addr,const ut8 * data,int len,RAnalOpMask mask)13 static int snes_anop(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len, RAnalOpMask mask) {
14 	op->size = snes_op_get_size(snesflags->M, snesflags->X, &snes_op[data[0]]);
15 	if (op->size > len) {
16 		return op->size = 0;
17 	}
18 	op->nopcode = 1;
19 	op->addr = addr;
20 	op->type = R_ANAL_OP_TYPE_UNK;
21 	switch (data[0]) {
22 	case 0xea: // nop
23 		op->type = R_ANAL_OP_TYPE_NOP;
24 		break;
25 	case 0xfb: // xce
26 		op->type = R_ANAL_OP_TYPE_XCHG;
27 		break;
28 	case 0x00: // brk
29 	case 0x02: // cop
30 		op->type = R_ANAL_OP_TYPE_SWI;
31 		break;
32 	case 0x1b: // tcs
33 	case 0x3b: // tsc
34 	case 0x5b: // tcd
35 	case 0x7b: // tdc
36 	case 0x8a: // txa
37 	case 0x98: // tya
38 	case 0x9a: // txs
39 	case 0x9b: // txy
40 	case 0xa8: // tay
41 	case 0xaa: // tax
42 	case 0xba: // tsx
43 	case 0xbb: // tyx
44 		op->type = R_ANAL_OP_TYPE_MOV;
45 		break;
46 	case 0x48: // pha
47 	case 0x8b: // phb
48 	case 0x0b: // phd
49 	case 0x4b: // phk
50 	case 0x08: // php
51 	case 0xda: // phx
52 	case 0x5a: // phy
53 		op->type = R_ANAL_OP_TYPE_PUSH;
54 		break;
55 	case 0x68: // pla
56 	case 0xab: // plb
57 	case 0x2b: // pld
58 	case 0x28: // plp
59 	case 0xfa: // plx
60 	case 0x7a: // ply
61 		op->type = R_ANAL_OP_TYPE_POP;
62 		break;
63 	// adc
64 	case 0x61: case 0x63: case 0x65: case 0x67: case 0x69: case 0x6d:
65 	case 0x6f: case 0x71: case 0x72: case 0x73: case 0x75: case 0x77:
66 	case 0x79: case 0x7d: case 0x7f:
67 	// inc
68 	case 0x1a: case 0xe6: case 0xee: case 0xf6: case 0xfe:
69 	case 0xe8: // inx
70 	case 0xc8: // iny
71 		op->type = R_ANAL_OP_TYPE_ADD;
72 		break;
73 	// and
74 	case 0x23: case 0x25: case 0x27: case 0x29: case 0x2d: case 0x2f:
75 	case 0x31: case 0x32: case 0x33: case 0x35: case 0x37: case 0x39:
76 	case 0x3d: case 0x3f:
77 		op->type = R_ANAL_OP_TYPE_AND;
78 		break;
79 	// bit
80 	case 0x24: case 0x2c: case 0x34: case 0x3c: case 0x89:
81 		op->type = R_ANAL_OP_TYPE_ACMP;
82 		break;
83 	// cmp
84 	case 0xc1: case 0xc3: case 0xc5: case 0xc7: case 0xc9: case 0xcd:
85 	case 0xcf: case 0xd1: case 0xd2: case 0xd3: case 0xd5: case 0xd7:
86 	case 0xd9: case 0xdd: case 0xdf:
87 	// cpx
88 	case 0xe0: case 0xe4: case 0xec:
89 	// cpy
90 	case 0xc0: case 0xc4: case 0xcc:
91 		op->type = R_ANAL_OP_TYPE_CMP;
92 		break;
93 	// ora
94 	case 0x01: case 0x03: case 0x05: case 0x07: case 0x09: case 0x0d:
95 	case 0x0f: case 0x11: case 0x12: case 0x13: case 0x15: case 0x17:
96 	case 0x19: case 0x1d: case 0x1f:
97 		op->type = R_ANAL_OP_TYPE_OR;
98 		break;
99 	// eor
100 	case 0x41: case 0x43: case 0x45: case 0x47: case 0x49: case 0x4d:
101 	case 0x4f: case 0x51: case 0x52: case 0x53: case 0x55: case 0x57:
102 	case 0x59: case 0x5d: case 0x5f:
103 		op->type = R_ANAL_OP_TYPE_XOR;
104 		break;
105 	// asl
106 	case 0x06: case 0x0a: case 0x0e: case 0x16: case 0x1e:
107 		op->type = R_ANAL_OP_TYPE_SAL;
108 		break;
109 	// lsr
110 	case 0x46: case 0x4a: case 0x4e: case 0x56: case 0x5e:
111 		op->type = R_ANAL_OP_TYPE_SHR;
112 		break;
113 	// rol
114 	case 0x26: case 0x2a: case 0x2e: case 0x36: case 0x3e:
115 		op->type = R_ANAL_OP_TYPE_ROL;
116 		break;
117 	// ror
118 	case 0x66: case 0x6a: case 0x6e: case 0x76: case 0x7e:
119 		op->type = R_ANAL_OP_TYPE_ROR;
120 		break;
121 	// sbc
122 	case 0xe1: case 0xe3: case 0xe5: case 0xe7: case 0xe9: case 0xed:
123 	case 0xef: case 0xf1: case 0xf2: case 0xf3: case 0xf5: case 0xf7:
124 	case 0xf9: case 0xfd: case 0xff:
125 	// dec
126 	case 0x3a: case 0xc6: case 0xce: case 0xd6: case 0xde:
127 	case 0xca: // dex
128 	case 0x88: // dey
129 		op->type = R_ANAL_OP_TYPE_SUB;
130 		break;
131 	// sta
132 	case 0x81: case 0x83: case 0x85: case 0x87: case 0x8d: case 0x8f:
133 	case 0x91: case 0x92: case 0x93: case 0x95: case 0x97: case 0x99:
134 	case 0x9d: case 0x9f:
135 	// stx
136 	case 0x86: case 0x8e: case 0x96:
137 	// sty
138 	case 0x84: case 0x8c: case 0x94:
139 	// stz
140 	case 0x64: case 0x74: case 0x9c: case 0x9e:
141 		op->type = R_ANAL_OP_TYPE_STORE;
142 		break;
143 	// lda
144 	case 0xa1: case 0xa3: case 0xa5: case 0xa7: case 0xa9: case 0xad:
145 	case 0xaf: case 0xb1: case 0xb2: case 0xb3: case 0xb5: case 0xb7:
146 	case 0xb9: case 0xbd: case 0xbf:
147 	// ldx
148 	case 0xa2: case 0xa6: case 0xae: case 0xb6: case 0xbe:
149 	// ldy
150 	case 0xa0: case 0xa4: case 0xac: case 0xb4: case 0xbc:
151 		op->type = R_ANAL_OP_TYPE_LOAD;
152 		break;
153 	case 0x4c: // jmp addr
154 		op->eob = true;
155 		op->jump = (addr & 0xFF0000) | ut8p_bw (data + 1);
156 		op->type = R_ANAL_OP_TYPE_JMP;
157 		break;
158 	case 0x5c: // jmp long
159 		op->eob = true;
160 		op->jump = data[1] | data[2] << 8 | data[3] << 16;
161 		op->type = R_ANAL_OP_TYPE_JMP;
162 		break;
163 	case 0x80: // bra
164 		op->eob = true;
165 		op->jump = addr + 2 + (st8)data[1];
166 		op->type = R_ANAL_OP_TYPE_JMP;
167 		break;
168 	case 0x82: // brl
169 		op->eob = true;
170 		op->jump = addr + 3 + (st16)ut8p_bw (data + 1);
171 		op->type = R_ANAL_OP_TYPE_JMP;
172 		break;
173 	case 0x6c: // jmp (addr)
174 	case 0x7c: // jmp (addr,X)
175 	case 0xdc: // jmp [addr]
176 		op->eob = true;
177 		op->type = R_ANAL_OP_TYPE_UJMP;
178 		break;
179 	case 0x10: // bpl
180 	case 0x30: // bmi
181 	case 0x50: // bvc
182 	case 0x70: // bvs
183 	case 0x90: // bcc
184 	case 0xb0: // bcs
185 		op->eob = true;
186 		op->jump = addr + 2 + (st8)data[1];
187 		op->fail = addr + 2;
188 		op->type = R_ANAL_OP_TYPE_CJMP;
189 		break;
190 	case 0xd0: // bne
191 		op->eob = true;
192 		op->cond = R_ANAL_COND_NE;
193 		op->jump = addr + 2 + (st8)data[1];
194 		op->fail = addr + 2;
195 		op->type = R_ANAL_OP_TYPE_CJMP;
196 		break;
197 	case 0xf0: // beq
198 		op->eob = true;
199 		op->cond = R_ANAL_COND_EQ;
200 		op->jump = addr + 2 + (st8)data[1];
201 		op->fail = addr + 2;
202 		op->type = R_ANAL_OP_TYPE_CJMP;
203 		break;
204 	case 0x20: // jsr addr
205 		op->jump = (addr & 0xFF0000) | ut8p_bw (data+1);
206 		op->type = R_ANAL_OP_TYPE_CALL;
207 		break;
208 	case 0x22: // jsr long
209 		op->jump = data[1] | data[2] << 8 | data[3] << 16;
210 		op->type = R_ANAL_OP_TYPE_CALL;
211 		break;
212 	case 0xfc: // jsr (addr,X)
213 		op->type = R_ANAL_OP_TYPE_UCALL;
214 		break;
215 	case 0x40: // rti
216 	case 0x60: // rts
217 	case 0x6b: // rtl
218 		op->eob = true;
219 		op->type = R_ANAL_OP_TYPE_RET;
220 		break;
221 	case 0xc2: // rep
222 		if (((st8)data[1]) & 0x10) {
223 			snesflags->X = 0;
224 		}
225 		if (((st8)data[1]) & 0x20) {
226 			snesflags->M = 0;
227 		}
228 		break;
229 	case 0xe2: // sep
230 		if (((st8)data[1]) & 0x10) {
231 			snesflags->X = 1;
232 		}
233 		if (((st8)data[1]) & 0x20) {
234 			snesflags->M = 1;
235 		}
236 		break;
237 	}
238 	return op->size;
239 }
240 
snes_anal_init(void * user)241 static int snes_anal_init (void* user) {
242 	if (!snesflags) {
243 		snesflags = malloc (sizeof (struct snes_asm_flags));
244 	}
245 	memset(snesflags,0,sizeof (struct snes_asm_flags));
246 	return 0;
247 }
248 
snes_anal_fini(void * user)249 static int snes_anal_fini (void* user) {
250 	free(snesflags);
251 	snesflags = NULL;
252 	return 0;
253 }
254 
255 RAnalPlugin r_anal_plugin_snes = {
256 	.name = "snes",
257 	.desc = "SNES analysis plugin",
258 	.license = "LGPL3",
259 	.arch = "snes",
260 	.bits = 16,
261 	.init = snes_anal_init,
262 	.fini = snes_anal_fini,
263 	.op = &snes_anop,
264 };
265 
266 #ifndef R2_PLUGIN_INCORE
267 R_API RLibStruct radare_plugin = {
268 	.type = R_LIB_TYPE_ANAL,
269 	.data = &r_anal_plugin_snes,
270 	.version = R2_VERSION
271 };
272 #endif
273