Core commit. Compile and run on the OpenPandora
[mupen64plus-pandora.git] / source / mupen64plus-core / src / debugger / dbg_decoder.c
CommitLineData
451ab91e 1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Mupen64plus -- dbg_decoder.c *
3 * Copyright (c) 2010 Marshall B. Rogers <mbr@64.vg> *
4 * http://64.vg/ *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
20 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
21
22/*
23 * This is a heavily modified reentrant version of the MIPS disassembler found
24 * in the NetBSD operating system. I chose to use this as a base due to the
25 * small, compact, and easily manageable code.
26 *
27 * Original copyright/license information is contained below.
28 */
29
30/* $NetBSD: db_disasm.c,v 1.21 2009/12/14 00:46:06 matt Exp $ */
31
32/*-
33 * Copyright (c) 1991, 1993
34 * The Regents of the University of California. All rights reserved.
35 *
36 * This code is derived from software contributed to Berkeley by
37 * Ralph Campbell.
38 *
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
41 * are met:
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * SUCH DAMAGE.
62 *
63 * from: @(#)kadb.c 8.1 (Berkeley) 6/10/93
64 */
65#include <stdio.h>
66#include <stdarg.h>
67#include <string.h>
68#include <stdlib.h>
69#ifndef MIPS32
70 #define MIPS32
71#endif
72#include "dbg_decoder.h"
73#include "dbg_decoder_local.h"
74#include "osal/preproc.h"
75
76
77/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
78 Data types
79 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
80
81typedef uint32_t db_addr_t;
82
83
84
85/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
86 Local variables
87 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
88
89static const char * const r4k_str_op_name[64] =
90{
91/* 0 */ "spec", "bcond","j", "jal", "beq", "bne", "blez", "bgtz",
92/* 8 */ "addi", "addiu","slti", "sltiu","andi", "ori", "xori", "lui",
93/*16 */ "cop0", "cop1", "cop2", "cop3", "beql", "bnel", "blezl","bgtzl",
94/*24 */ "daddi","daddiu","ldl", "ldr", "op34", "op35", "op36", "op37",
95/*32 */ "lb", "lh", "lwl", "lw", "lbu", "lhu", "lwr", "lwu",
96/*40 */ "sb", "sh", "swl", "sw", "sdl", "sdr", "swr", "cache",
97/*48 */ "ll", "lwc1", "lwc2", "lwc3", "lld", "ldc1", "ldc2", "ld",
98/*56 */ "sc", "swc1", "swc2", "swc3", "scd", "sdc1", "sdc2", "sd"
99};
100
101static const char * const r4k_str_spec_name[64] =
102{
103/* 0 */ "sll", "spec01","srl", "sra", "sllv", "spec05","srlv","srav",
104/* 8 */ "jr", "jalr", "spec12","spec13","syscall","break","spec16","sync",
105/*16 */ "mfhi", "mthi", "mflo", "mtlo", "dsllv","spec25","dsrlv","dsrav",
106/*24 */ "mult", "multu","div", "divu", "dmult","dmultu","ddiv","ddivu",
107/*32 */ "add", "addu", "sub", "subu", "and", "or", "xor", "nor",
108/*40 */ "spec50","spec51","slt","sltu", "dadd","daddu","dsub","dsubu",
109/*48 */ "tge","tgeu","tlt","tltu","teq","spec65","tne","spec67",
110/*56 */ "dsll","spec71","dsrl","dsra","dsll32","spec75","dsrl32","dsra32"
111};
112
113static const char * const r4k_str_spec2_name[4] = /* QED RM4650, R5000, etc. */
114{
115/* 0 */ "mad", "madu", "mul", "spec3"
116};
117
118static const char * const r4k_str_bcond_name[32] =
119{
120/* 0 */ "bltz", "bgez", "bltzl", "bgezl", "?", "?", "?", "?",
121/* 8 */ "tgei", "tgeiu", "tlti", "tltiu", "teqi", "?", "tnei", "?",
122/*16 */ "bltzal", "bgezal", "bltzall", "bgezall", "?", "?", "?", "?",
123/*24 */ "?", "?", "?", "?", "?", "?", "?", "?",
124};
125
126static const char * const r4k_str_cop1_name[64] =
127{
128/* 0 */ "add", "sub", "mul", "div", "sqrt","abs", "mov", "neg",
129/* 8 */ "fop08", "trunc.l","fop0a","fop0b","fop0c","trunc.w","fop0e","fop0f",
130/*16 */ "fop10", "fop11","fop12","fop13","fop14","fop15","fop16","fop17",
131/*24 */ "fop18", "fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
132/*32 */ "cvt.s", "cvt.d","fop22","fop23","cvt.w","cvt.l","fop26","fop27",
133/*40 */ "fop28", "fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
134/*48 */ "c.f", "c.un","c.eq","c.ueq","c.olt","c.ult",
135 "c.ole", "c.ule",
136/*56 */ "c.sf", "c.ngle","c.seq","c.ngl","c.lt","c.nge",
137 "c.le", "c.ngt"
138};
139
140static const char * const r4k_str_fmt_name[16] =
141{
142
143 "s", "d", "e", "fmt3",
144 "w", "l", "fmt6", "fmt7",
145 "fmt8", "fmt9", "fmta", "fmtb",
146 "fmtc", "fmtd", "fmte", "fmtf"
147};
148
149
150static const char * const r4k_str_reg_name[32] =
151{
152 "$zero", "$at", "v0", "v1", "a0", "a1", "a2", "a3",
153 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
154 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
155 "t8", "t9", "k0", "k1", "$gp", "$sp", "s8", "$ra"
156};
157
158static const char * const r4k_str_c0_opname[64] =
159{
160 "c0op00","tlbr", "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07",
161 "tlbp", "c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17",
162 "rfe", "c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27",
163 "eret", "c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37",
164 "c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
165 "c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57",
166 "c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67",
167 "c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77",
168};
169
170static const char * const r4k_str_c0_reg[32] =
171{
172 "C0_INX", "C0_RAND", "C0_ENTRYLO0", "C0_ENTRYLO1",
173 "C0_CONTEXT", "C0_PAGEMASK", "C0_WIRED", "cp0r7",
174 "C0_BADVADDR", "C0_COUNT", "C0_ENTRYHI", "C0_COMPARE",
175 "C0_SR", "C0_CAUSE", "C0_EPC", "C0_PRID",
176 "C0_CONFIG", "C0_LLADDR", "C0_WATCHLO", "C0_WATCHHI",
177 "xcontext", "cp0r21", "cp0r22", "debug",
178 "depc", "perfcnt", "C0_ECC", "C0_CACHE_ERR",
179 "C0_TAGLO", "C0_TAGHI", "C0_ERROR_EPC", "desave"
180};
181
182
183
184/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
185 Local functions - lookup
186 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
187
188/* Look up a symbol */
189static char *
190lookup_sym ( struct r4k_dis_t * state,
191 uint32_t address )
192{
193 if( state->lookup_sym )
194 return state->lookup_sym( address, state->lookup_sym_d );
195
196 return NULL;
197}
198
199/* Look up an upper 16-bits relocation */
200static char *
201lookup_rel_hi16 ( struct r4k_dis_t * state,
202 uint32_t address )
203{
204 if( state->lookup_rel_hi16 )
205 return state->lookup_rel_hi16( address, state->lookup_rel_hi16_d );
206
207 return NULL;
208}
209
210/* Look up a lower 16-bits relocation */
211static char *
212lookup_rel_lo16 ( struct r4k_dis_t * state,
213 uint32_t address )
214{
215 if( state->lookup_rel_lo16 )
216 return state->lookup_rel_lo16( address, state->lookup_rel_lo16_d );
217
218 return NULL;
219}
220
221
222
223/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
224 Local functions - disassembler
225 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
226
227/* Print text into the destination buffer */
228static int
229db_printf ( struct r4k_dis_t * state,
230 char * fmt,
231 ... )
232{
233 int l;
234 va_list ap;
235 char buffer[1024];
236
237
238 /* Prepare user provided */
239 va_start( ap, fmt );
240 l = vsnprintf( buffer, sizeof(buffer), fmt, ap );
241 va_end( ap );
242
243 /* Add it to our string */
244 state->dest += sprintf(
245 state->dest,
246 "%s",
247 buffer
248 );
249 state->length += l;
250
251 return l;
252}
253
254
255/* Print an address to a string. If there's a symbol, the name will be printed */
256static int
257print_addr ( struct r4k_dis_t * state,
258 uint32_t address )
259{
260 int len;
261 char * sym;
262
263
264 /* Try to lookup symbol */
265 if( (sym = lookup_sym(state, address)) )
266 {
267 len = db_printf( state, "%s", sym );
268 }
269 else
270 {
271 len = db_printf( state, "0x%08X", address );
272 }
273
274 return len;
275}
276
277
278/* Disassemble an instruction */
279static db_addr_t
280db_disasm_insn ( struct r4k_dis_t * state,
281 int insn,
282 db_addr_t loc,
283 bool altfmt )
284{
285 char * rel;
286 InstFmt i;
287
288 i.word = insn;
289
290 switch (i.JType.op) {
291 case OP_SPECIAL:
292 if (i.word == 0) {
293 db_printf(state, "nop");
294 break;
295 }
296 /* XXX
297 * "addu" is a "move" only in 32-bit mode. What's the correct
298 * answer - never decode addu/daddu as "move"?
299 */
300 if (i.RType.func == OP_ADDU && i.RType.rt == 0) {
301 db_printf(state, "%-16s%s,%s",
302 "move",
303 r4k_str_reg_name[i.RType.rd],
304 r4k_str_reg_name[i.RType.rs]);
305 break;
306 }
307 db_printf(state, "%-16s", r4k_str_spec_name[i.RType.func]);
308 switch (i.RType.func) {
309 case OP_SLL:
310 case OP_SRL:
311 case OP_SRA:
312 case OP_DSLL:
313
314 case OP_DSRL:
315 case OP_DSRA:
316 case OP_DSLL32:
317 case OP_DSRL32:
318 case OP_DSRA32:
319 db_printf(state, "%s,%s,%d",
320 r4k_str_reg_name[i.RType.rd],
321 r4k_str_reg_name[i.RType.rt],
322 i.RType.shamt);
323 break;
324
325 case OP_SLLV:
326 case OP_SRLV:
327 case OP_SRAV:
328 case OP_DSLLV:
329 case OP_DSRLV:
330 case OP_DSRAV:
331 db_printf(state, "%s,%s,%s",
332 r4k_str_reg_name[i.RType.rd],
333 r4k_str_reg_name[i.RType.rt],
334 r4k_str_reg_name[i.RType.rs]);
335 break;
336
337 case OP_MFHI:
338 case OP_MFLO:
339 db_printf(state, "%s", r4k_str_reg_name[i.RType.rd]);
340 break;
341
342 case OP_JR:
343 case OP_JALR:
344 db_printf(state, "%s", r4k_str_reg_name[i.RType.rs]);
345 break;
346 case OP_MTLO:
347 case OP_MTHI:
348 db_printf(state, "%s", r4k_str_reg_name[i.RType.rs]);
349 break;
350
351 case OP_MULT:
352 case OP_MULTU:
353 case OP_DMULT:
354 case OP_DMULTU:
355 db_printf(state, "%s,%s",
356 r4k_str_reg_name[i.RType.rs],
357 r4k_str_reg_name[i.RType.rt]);
358 break;
359
360 case OP_DIV:
361 case OP_DIVU:
362 case OP_DDIV:
363 case OP_DDIVU:
364 db_printf(state, "$zero,%s,%s",
365 r4k_str_reg_name[i.RType.rs],
366 r4k_str_reg_name[i.RType.rt]);
367 break;
368
369
370 case OP_SYSCALL:
371 case OP_SYNC:
372 break;
373
374 case OP_BREAK:
375 db_printf(state, "%d", (i.RType.rs << 5) | i.RType.rt);
376 break;
377
378 default:
379 db_printf(state, "%s,%s,%s",
380 r4k_str_reg_name[i.RType.rd],
381 r4k_str_reg_name[i.RType.rs],
382 r4k_str_reg_name[i.RType.rt]);
383 }
384 break;
385
386 case OP_SPECIAL2:
387 if (i.RType.func == OP_MUL)
388 db_printf(state, "%s\t%s,%s,%s",
389 r4k_str_spec2_name[i.RType.func & 0x3],
390 r4k_str_reg_name[i.RType.rd],
391 r4k_str_reg_name[i.RType.rs],
392 r4k_str_reg_name[i.RType.rt]);
393 else
394 db_printf(state, "%s\t%s,%s",
395 r4k_str_spec2_name[i.RType.func & 0x3],
396 r4k_str_reg_name[i.RType.rs],
397 r4k_str_reg_name[i.RType.rt]);
398
399 break;
400
401 case OP_BCOND:
402 db_printf(state, "%-16s%s,", r4k_str_bcond_name[i.IType.rt],
403 r4k_str_reg_name[i.IType.rs]);
404 goto pr_displ;
405
406 case OP_BLEZ:
407 case OP_BLEZL:
408 case OP_BGTZ:
409 case OP_BGTZL:
410 db_printf(state, "%-16s%s,", r4k_str_op_name[i.IType.op],
411 r4k_str_reg_name[i.IType.rs]);
412 goto pr_displ;
413
414 case OP_BEQ:
415 case OP_BEQL:
416 if (i.IType.rs == 0 && i.IType.rt == 0) {
417 db_printf(state, "%-16s", "b");
418 goto pr_displ;
419 }
420 /* FALLTHROUGH */
421 case OP_BNE:
422 case OP_BNEL:
423 db_printf(state, "%-16s%s,%s,", r4k_str_op_name[i.IType.op],
424 r4k_str_reg_name[i.IType.rs],
425 r4k_str_reg_name[i.IType.rt]);
426 pr_displ:
427 print_addr( state, loc + 4 + ((short)i.IType.imm << 2) );
428 break;
429
430 case OP_COP0:
431 switch (i.RType.rs) {
432 case OP_BCx:
433 case OP_BCy:
434
435 db_printf(state, "bc0%c\t",
436 "ft"[i.RType.rt & COPz_BC_TF_MASK]);
437 goto pr_displ;
438
439 case OP_MT:
440 db_printf(state, "%-16s%s,%s",
441 "mtc0",
442 r4k_str_reg_name[i.RType.rt],
443 r4k_str_c0_reg[i.RType.rd]);
444 break;
445
446 case OP_DMT:
447 db_printf(state, "%-16s%s,%s",
448 "dmtc0",
449 r4k_str_reg_name[i.RType.rt],
450 r4k_str_c0_reg[i.RType.rd]);
451 break;
452
453 case OP_MF:
454 db_printf(state, "%-16s%s,%s", "mfc0",
455 r4k_str_reg_name[i.RType.rt],
456 r4k_str_c0_reg[i.RType.rd]);
457 break;
458
459 case OP_DMF:
460 db_printf(state, "%-16s%s,%s","dmfc0",
461 r4k_str_reg_name[i.RType.rt],
462 r4k_str_c0_reg[i.RType.rd]);
463 break;
464
465 default:
466 db_printf(state, "%s", r4k_str_c0_opname[i.FRType.func]);
467 }
468 break;
469
470 case OP_COP1:
471 switch (i.RType.rs) {
472 case OP_BCx:
473 case OP_BCy:
474 db_printf(state, "bc1%c%s\t\t",
475 "ft"[i.RType.rt & COPz_BC_TF_MASK],
476 (insn >> 16 & 0x1F) == 2 || (insn >> 16 & 0x1F) == 3 ? "l" : "");
477 goto pr_displ;
478
479 case OP_MT:
480 db_printf(state, "mtc1\t\t%s,$f%d",
481 r4k_str_reg_name[i.RType.rt],
482 i.RType.rd);
483 break;
484
485 case OP_MF:
486 db_printf(state, "mfc1\t\t%s,$f%d",
487 r4k_str_reg_name[i.RType.rt],
488 i.RType.rd);
489 break;
490
491 case OP_CT:
492 db_printf(state, "ctc1\t\t%s,$f%d",
493 r4k_str_reg_name[i.RType.rt],
494 i.RType.rd);
495 break;
496
497 case OP_CF:
498 db_printf(state, "cfc1\t\t%s,$f%d",
499 r4k_str_reg_name[i.RType.rt],
500 i.RType.rd);
501 break;
502
503 case OP_DMT:
504 db_printf(state, "dmtc1\t\t%s,$f%d",
505 r4k_str_reg_name[i.RType.rt],
506 i.RType.rd);
507 break;
508
509 case OP_DMF:
510 db_printf(state, "dmfc1\t\t%s,$f%d",
511 r4k_str_reg_name[i.RType.rt],
512 i.RType.rd);
513 break;
514
515 case OP_MTH:
516 db_printf(state, "mthc1\t\t%s,$f%d",
517 r4k_str_reg_name[i.RType.rt],
518 i.RType.rd);
519 break;
520
521 case OP_MFH:
522 db_printf(state, "mfhc1\t\t%s,$f%d",
523 r4k_str_reg_name[i.RType.rt],
524 i.RType.rd);
525 break;
526
527
528 default:
529
530 if( i.FRType.func == 0x21 || i.FRType.func == 0x20 || i.FRType.func == 0x24 || i.FRType.func == 0x25 ||
531 i.FRType.func == 7 || i.FRType.func == 6 || i.FRType.func == 0xd ||
532 i.FRType.func == 4 || i.FRType.func == 5 || i.FRType.func == 9 )
533 {/*NEG.fmt fd, fs*/
534
535 db_printf(state, "%s.%s\t\t$f%d,$f%d",
536 r4k_str_cop1_name[i.FRType.func],
537 r4k_str_fmt_name[i.FRType.fmt],
538 i.FRType.fd, i.FRType.fs);
539 }
540 else if( i.FRType.func != 1 && i.FRType.func != 2 && (insn & 0x3F) && !(insn >> 6 & 0x1F) ) /* C */
541 {
542 db_printf(state, "%s.%s\t\t$f%d,$f%d",
543 r4k_str_cop1_name[i.FRType.func],
544 r4k_str_fmt_name[i.FRType.fmt],
545 i.FRType.fs, i.FRType.ft);
546 }
547 else
548 {
549 db_printf(state, "%s.%s\t\t$f%d,$f%d,$f%d",
550 r4k_str_cop1_name[i.FRType.func],
551 r4k_str_fmt_name[i.FRType.fmt],
552 i.FRType.fd, i.FRType.fs, i.FRType.ft);
553 }
554 }
555 break;
556
557 case OP_J:
558 case OP_JAL:
559 db_printf(state, "%-16s", r4k_str_op_name[i.JType.op]);
560 print_addr(state, (loc & 0xF0000000) | (i.JType.target << 2));
561 break;
562
563 case OP_LDC1:
564 case OP_LWC1:
565 case OP_SWC1:
566 case OP_SDC1:
567 db_printf(state, "%-16s$f%d,", r4k_str_op_name[i.IType.op],
568 i.IType.rt);
569 goto loadstore;
570
571 case OP_LB:
572 case OP_LH:
573 case OP_LW:
574 case OP_LWL:
575 case OP_LWR:
576 case OP_LD:
577 case OP_LBU:
578 case OP_LHU:
579 case OP_LWU:
580 case OP_SB:
581 case OP_SH:
582 case OP_SW:
583 case OP_SWL:
584 case OP_SWR:
585 case OP_SD:
586 db_printf(state, "%-16s%s,", r4k_str_op_name[i.IType.op],
587 r4k_str_reg_name[i.IType.rt]);
588 loadstore:
589
590 /* Part of a relocation? */
591 if( (rel = lookup_rel_lo16(state, loc)) )
592 {
593 /* Yes. */
594 db_printf(state,
595 "%%lo(%s)(%s)",
596 rel,
597 r4k_str_reg_name[i.IType.rs]
598 );
599
600 break;
601 }
602
603
604 db_printf(state, "%d(%s)", (short)i.IType.imm,
605 r4k_str_reg_name[i.IType.rs]);
606 break;
607
608 case OP_ORI:
609 case OP_XORI:
610 if( i.IType.op == OP_ORI )
611 {
612 /* Part of a relocation? */
613 if( (rel = lookup_rel_lo16(state, loc)) )
614 {
615 /* Yes. */
616 db_printf(state,
617 "%-16s%s,%s,%%lo(%s)",
618 r4k_str_op_name[i.IType.op],
619 r4k_str_reg_name[i.IType.rt],
620 r4k_str_reg_name[i.IType.rs],
621 rel
622 );
623
624 break;
625 }
626 else
627 {
628 db_printf(state, "%-16s%s,%s,0x%x", r4k_str_op_name[i.IType.op],
629 r4k_str_reg_name[i.IType.rt],
630 r4k_str_reg_name[i.IType.rs],
631 i.IType.imm);
632
633 break;
634 }
635 }
636 else
637 if (i.IType.rs == 0) {
638 db_printf(state, "%-16s%s,0x%x",
639 "li",
640 r4k_str_reg_name[i.IType.rt],
641 i.IType.imm);
642 break;
643 }
644 /* FALLTHROUGH */
645 case OP_ANDI:
646 db_printf(state, "%-16s%s,%s,0x%x", r4k_str_op_name[i.IType.op],
647 r4k_str_reg_name[i.IType.rt],
648 r4k_str_reg_name[i.IType.rs],
649 i.IType.imm);
650 break;
651
652 case OP_LUI:
653 {
654 /* Part of a relocation? */
655 if( (rel = lookup_rel_hi16(state, loc)) )
656 {
657 /* Yes. */
658 db_printf(state,
659 "%-16s%s,%%hi(%s)",
660 r4k_str_op_name[i.IType.op],
661 r4k_str_reg_name[i.IType.rt],
662 rel
663 );
664 }
665 else
666 {
667 db_printf(state, "%-16s%s,0x%x", r4k_str_op_name[i.IType.op],
668 r4k_str_reg_name[i.IType.rt],
669 i.IType.imm);
670 }
671 }
672 break;
673
674 case OP_CACHE:
675 db_printf(state, "%-16s0x%x,0x%x(%s)",
676 r4k_str_op_name[i.IType.op],
677 i.IType.rt,
678 i.IType.imm,
679 r4k_str_reg_name[i.IType.rs]);
680 break;
681
682 case OP_ADDI:
683 case OP_DADDI:
684 case OP_ADDIU:
685 case OP_DADDIU:
686 {
687
688 /* Part of a relocation? */
689 if( (rel = lookup_rel_lo16(state, loc)) )
690 {
691 /* Yes. */
692 db_printf(state,
693 "%-16s%s,%s,%%lo(%s)",
694 r4k_str_op_name[i.IType.op],
695 r4k_str_reg_name[i.IType.rt],
696 r4k_str_reg_name[i.IType.rs],
697 rel
698 );
699
700 break;
701 }
702
703 if (i.IType.rs == 0) {
704 db_printf(state, "%-16s%s,%d", "li",
705 r4k_str_reg_name[i.IType.rt],
706 (short)i.IType.imm);
707 break;
708 }
709 /* FALLTHROUGH */
710
711 default:
712
713 db_printf(state, "%-16s%s,%s,%d", r4k_str_op_name[i.IType.op],
714 r4k_str_reg_name[i.IType.rt],
715 r4k_str_reg_name[i.IType.rs],
716 (short)i.IType.imm);
717 } }
718 /*db_printf(state, "\n");*/
719
720 return (loc + 4);
721}
722
723
724
725/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
726 Global functions
727 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
728
729/* Disassemble an instruction with state */
730static int
731r4k_disassemble ( struct r4k_dis_t * state,
732 uint32_t instruction,
733 uint32_t location,
734 char * dest )
735{
736 state->dest = dest;
737 db_disasm_insn( state, instruction, location, 0 );
738
739 return state->length;
740}
741
742
743
744/* Disassemble an instruction but split the opcode/operands into two char *'s */
745static int
746r4k_disassemble_split ( struct r4k_dis_t * state,
747 uint32_t instruction,
748 uint32_t location,
749 char ** opcode,
750 char ** operands )
751{
752 int v, i;
753 char buff[128], * dupd;
754
755 v = r4k_disassemble(
756 state,
757 instruction,
758 location,
759 buff
760 );
761
762 dupd = strdup( buff );
763 *opcode = &dupd[0];
764
765 for( i = 0; buff[i] && buff[i] != ' '; i++ );
766
767 dupd[i] = '\0';
768
769 for( ; buff[i] && buff[i] == ' '; i++ );
770
771 *operands = &dupd[i];
772
773 return v;
774}
775
776
777
778/* Disassemble an instruction with a blank state but split op/operands */
779static int
780r4k_disassemble_split_quick ( uint32_t instruction,
781 uint32_t location,
782 char ** opcode,
783 char ** operands )
784{
785 struct r4k_dis_t state;
786
787 /* Init state */
788 memset( &state, 0, sizeof(state) );
789
790 /* Perform */
791 return r4k_disassemble_split(
792 &state,
793 instruction,
794 location,
795 opcode,
796 operands
797 );
798}
799
800
801//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=[ DECODE_OP ]=-=-=-=-=-=-=-=-=-=-=-=-=-=-=[//
802
803void r4300_decode_op ( uint32 instr, char * opcode, char * arguments, int counter )
804{
805 char * _op, * _args;
806
807 _op = NULL;
808 _args = NULL;
809
810 r4k_disassemble_split_quick(
811 instr,
812 counter,
813 &_op,
814 &_args
815 );
816
817 strcpy( opcode, _op );
818 strcpy( arguments, _args );
819
820 free( _op );
821}
822