Committed on the Free edition of March Hare Software CVSNT Server. Upgrade to CVS Suite for more features and support: http://march-hare.com/cvsnt/ git-svn-id: http://moon:8086/svn/vhdl/trunk@790 cc03376c-175c-47c8-b038-4cd826a8556b
652 lines
18 KiB
C
652 lines
18 KiB
C
/* +----------------------------------------------------------------+ */
|
|
/* | Copyright (c) 1994 Stanford University. | */
|
|
/* | All Rights Reserved. | */
|
|
/* | | */
|
|
/* | This software is distributed with *ABSOLUTELY NO SUPPORT* | */
|
|
/* | and *NO WARRANTY*. Use or reproduction of this code for | */
|
|
/* | commerical gains is strictly prohibited. Otherwise, you | */
|
|
/* | are given permission to use or modify this code as long | */
|
|
/* | as you do not remove this notice. | */
|
|
/* +----------------------------------------------------------------+ */
|
|
/* --------------------------------------------------- */
|
|
/* | Copyright (c) 1986 MIPS Computer Systems, Inc. | */
|
|
/* | All Rights Reserved. | */
|
|
/* --------------------------------------------------- */
|
|
|
|
/*
|
|
* Copyright 1985 by MIPS Computer Systems, Inc.
|
|
*/
|
|
|
|
/* TORCH disassembler */
|
|
/* derived from MIPS instruction dissassembler by PGL October 91 */
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "mipsdis.h"
|
|
|
|
#define false 0
|
|
#define true 1
|
|
typedef int boolean;
|
|
char *strcat();
|
|
|
|
#define ZERO 0
|
|
|
|
#define COMPILER_NAMES tdis_reg_names[0]
|
|
#define HARDWARE_NAMES tdis_reg_names[1]
|
|
#define ASSEMBLER_NAMES tdis_reg_names[2]
|
|
#define DIS_REG_NAMES(x) tdis_reg_names[x]
|
|
|
|
union extension_byte {
|
|
unsigned char byte;
|
|
struct { /* extension byte bits in little-endian order */
|
|
#if (defined __MIPSEB || defined _MIPSEB || defined MIPSEB)
|
|
unsigned reserved:1;
|
|
unsigned dyn_nop:1;
|
|
unsigned rs_boost:2;
|
|
unsigned rt_boost:2;
|
|
unsigned rd_boost:2;
|
|
#elif (defined __MIPSEL || defined _MIPSEL || defined MIPSEL)
|
|
unsigned rd_boost:2;
|
|
unsigned rt_boost:2;
|
|
unsigned rs_boost:2;
|
|
unsigned dyn_nop:1;
|
|
unsigned reserved:1;
|
|
#endif /*MIPSEB*/
|
|
} e;
|
|
};
|
|
|
|
#define blez_op_T blez_op
|
|
#define blez_op_N (blez_op | 0x10)
|
|
#define bgtz_op_T bgtz_op
|
|
#define bgtz_op_N (bgtz_op | 0x10)
|
|
#define beq_op_T beq_op
|
|
#define beq_op_N (beq_op | 0x10)
|
|
#define bne_op_T bne_op
|
|
#define bne_op_N (bne_op | 0x10)
|
|
#define bc_op_T bc_op
|
|
#define bc_op_N (bc_op | 0x02)
|
|
|
|
static char *op_name[64] = {
|
|
/* 0 */ "special", "regimm","j", "jal", "beq", "bne", "blez", "bgtz",
|
|
/* 8 */ "addi", "addiu","slti", "sltiu","andi", "ori", "xori", "lui",
|
|
/*16 */ "cop0", "cop1", "cop2", "cop3", "beql","bnel","blezl","bgtzl",
|
|
/*24 */ "op60", "op64", "op68", "op6c", "op70", "op74", "op78", "op7c",
|
|
/*32 */ "lb", "lh", "lwl", "lw", "lbu", "lhu", "lwr", "ld",
|
|
/*40 */ "sb", "sh", "swl", "sw", "opb0", "opb4", "swr", "sd",
|
|
/*48 */ "lwc0", "lwc1", "lwc2", "lwc3", "ldc0", "ldc1", "ldc2", "ldc3",
|
|
/*56 */ "swc0", "swc1", "swc2", "swc3", "sdc0", "sdc1", "sdc2", "sdc3"
|
|
};
|
|
|
|
static char *spec_name[64] = {
|
|
/* 0*/ "sll", "spec01","srl", "sra", "sllv", "spec05","srlv","srav",
|
|
/* 8*/ "jr", "jalr", "spec12","spec13","syscall","break","vcall","spec17",
|
|
/*16*/ "mfhi", "mthi", "mflo", "mtlo", "spec24","spec25","spec26","spec27",
|
|
/*24*/ "mult", "multu","div", "divu", "spec34","spec35","spec36","spec37",
|
|
/*32*/ "add", "addu", "sub", "subu", "and", "or", "xor", "nor",
|
|
/*40*/ "spec50","spec51","slt","sltu", "spec54","spec55","spec56","spec57",
|
|
/*48*/ "spec60","spec61","spec62","spec63","spec64","spec65","spec66","spec67",
|
|
/*56*/ "spec70","spec71","spec72","spec73","spec74","spec75","spec76","spec77"
|
|
};
|
|
|
|
static char *bcond_name[32] = {
|
|
"bltz",
|
|
"bgez",
|
|
"bltzl",
|
|
"bgezl",
|
|
"bcond04",
|
|
"bcond05",
|
|
"bcond06",
|
|
"bcond07",
|
|
"tgei",
|
|
"tgeiu",
|
|
"tlti",
|
|
"tltiu",
|
|
"teqi",
|
|
"bcond0d",
|
|
"tnei",
|
|
"bcond0f",
|
|
"bltzal",
|
|
"bgezal",
|
|
"bltzall",
|
|
"bgezall",
|
|
"bcond14",
|
|
"bcond15",
|
|
"bcond16",
|
|
"bcond17",
|
|
"bcond18",
|
|
"bcond19",
|
|
"bcond1a",
|
|
"bcond1b",
|
|
"bcond1c",
|
|
"bcond1d",
|
|
"bcond1e",
|
|
"bcond1f"
|
|
};
|
|
|
|
static char *cop1_name[64] = {
|
|
/* 0 */ "add", "sub", "mul", "div", "sqrt", "abs", "mov", "neg",
|
|
/* 8 */ "fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f",
|
|
/*16 */ "fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17",
|
|
/*24 */ "fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
|
|
/*32 */ "cvt.s","cvt.d","cvt.e","fop23","cvt.w","fop25","fop26","fop27",
|
|
/*40 */ "fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
|
|
/*48 */ "c.f", "c.un","c.eq","c.ueq","c.olt","c.ult","c.ole","c.ule",
|
|
/*56 */ "c.sf","c.ngle","c.seq","c.ngl","c.lt","c.nge","c.le","c.ngt"
|
|
};
|
|
|
|
static char *fmt_name[16] = {
|
|
"s", "d", "e", "q",
|
|
"w", "fmt5", "fmt6", "fmt7",
|
|
"fmt8", "fmt9", "fmta", "fmtb",
|
|
"fmtc", "fmtd", "fmte", "fmtf"
|
|
};
|
|
|
|
/* public */
|
|
/* Three sets of commonly used register names */
|
|
const char *tdis_reg_names[3][64] = {
|
|
{ /* compiler names */
|
|
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
|
|
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
|
|
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
|
|
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
|
|
"zero.B","at.B","v0.B", "v1.B", "a0.B", "a1.B", "a2.B", "a3.B",
|
|
"t0.B", "t1.B", "t2.B", "t3.B", "t4.B", "t5.B", "t6.B", "t7.B",
|
|
"s0.B", "s1.B", "s2.B", "s3.B", "s4.B", "s5.B", "s6.B", "s7.B",
|
|
"t8.B", "t9.B", "k0.B", "k1.B", "gp.B", "sp.B", "s8.B", "ra.B"
|
|
},
|
|
{ /* hardware names */
|
|
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
|
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
|
|
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
|
|
"r24", "r25", "r26", "r27", "gp", "sp", "r30", "r31",
|
|
"r0.B", "r1.B", "r2.B", "r3.B", "r4.B", "r5.B", "r6.B", "r7.B",
|
|
"r8.B", "r9.B", "r10.B","r11.B","r12.B","r13.B","r14.B","r15.B",
|
|
"r16.B","r17.B","r18.B","r19.B","r20.B","r21.B","r22.B","r23.B",
|
|
"r24.B","r25.B","r26.B","r27.B","gp.B", "sp.B", "r30.B","r31.B"
|
|
},
|
|
{ /* assembler names */
|
|
"$0", "$at", "$2", "$3", "$4", "$5", "$6", "$7",
|
|
"$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
|
|
"$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
|
|
"$24", "$25", "$26", "$27", "$gp", "$sp", "$30", "$31",
|
|
"$0.B", "$at.B","$2.B", "$3.B", "$4.B", "$5.B", "$6.B", "$7.B",
|
|
"$8.B", "$9.B", "$10.B","$11.B","$12.B","$13.B","$14.B","$15.B",
|
|
"$16.B","$17.B","$18.B","$19.B","$20.B","$21.B","$22.B","$23.B",
|
|
"$24.B","$25.B","$26.B","$27.B","$gp.B","$sp.B","$30.B","$31.B"
|
|
}
|
|
};
|
|
|
|
static char *c0_opname[64] = {
|
|
"c0op0","tlbr","tlbwi","c0op3","c0op4","c0op5","tlbwr","c0op7",
|
|
"tlbp","c0op9","c0op10","c0op11","c0op12","c0op13","c0op14","c0op15",
|
|
"rfe","c0op17","c0op18","c0op19","c0op20","c0op21","c0op22","c0op23",
|
|
"c0op24","c0op25","c0op26","c0op27","c0op28","c0op29","c0op30","c0op31",
|
|
"c0op32","c0op33","c0op34","c0op35","c0op36","c0op37","c0op38","c0op39",
|
|
"c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
|
|
"c0op48","c0op49","c0op50","c0op51","c0op52","c0op53","c0op54","c0op55",
|
|
"c0op56","c0op57","c0op58","c0op59","c0op60","c0op61","c0op62","c0op63"
|
|
};
|
|
|
|
static char *c0_reg[32] = {
|
|
"index","random","tlblo","c0r3","context","c0r5","c0r6","c0r7",
|
|
"badvaddr","c0r9","tlbhi","epcn","sr", "cause","epc", "c0r15",
|
|
"c0r16","c0r17","c0r18","c0r19","c0r20","c0r21","c0r22","c0r23",
|
|
"c0r24","c0r25","c0r26","c0r27","c0r28","c0r29","c0r30","c0r31"
|
|
};
|
|
|
|
/* Remember the options set by dis_init */
|
|
#define ADDR_DEFAULT 0
|
|
//#define ADDR_DEFAULT "%#010x:\t"
|
|
//#define VALUE_DEFAULT "%#010x\t"
|
|
#define VALUE_DEFAULT 0
|
|
#define NAME_DEFAULT COMPILER_NAMES
|
|
static struct {
|
|
char *addr_format;
|
|
char *value_format;
|
|
const char **reg_names;
|
|
int print_jal_targets;
|
|
} save = {
|
|
ADDR_DEFAULT,
|
|
VALUE_DEFAULT,
|
|
NAME_DEFAULT,
|
|
true
|
|
};
|
|
|
|
/* Update regmask to reflect the use of this general-purpose (not fp)
|
|
register, and return its name */
|
|
static const char *
|
|
register_name(ireg, boosted, regmask)
|
|
unsigned ireg, *regmask;
|
|
int boosted;
|
|
{
|
|
if (!boosted)
|
|
*regmask |= (1 << ireg);
|
|
return save.reg_names[boosted ? ireg + 32 : ireg];
|
|
}
|
|
|
|
/* public -- see dissassembler.h */
|
|
int
|
|
tdisasm(buffer, address, iword, ext, regmask, symbol_value, ls_register)
|
|
char *buffer;
|
|
unsigned char ext; /* extension byte */
|
|
unsigned address, iword, *regmask, *symbol_value, *ls_register;
|
|
{
|
|
int return_value = 0;
|
|
char *bufptr = buffer;
|
|
boolean do_b_displacement = false;
|
|
boolean do_loadstore = false;
|
|
union mips_instruction i;
|
|
union extension_byte e;
|
|
|
|
*bufptr = 0;
|
|
i.word = iword;
|
|
e.byte = ext;
|
|
*regmask = *symbol_value = *ls_register = 0;
|
|
|
|
/* Put out the address and hex value of the instruction,
|
|
leaving bufptr set at the end */
|
|
if (save.addr_format) {
|
|
sprintf(bufptr, save.addr_format, address);
|
|
bufptr += strlen(bufptr);
|
|
}
|
|
if (save.value_format) {
|
|
sprintf(bufptr, save.value_format, iword);
|
|
bufptr += strlen(bufptr);
|
|
}
|
|
|
|
/* check for dynamic NOP */
|
|
if (e.e.dyn_nop) {
|
|
strcat(bufptr, "D.");
|
|
bufptr += 2;
|
|
}
|
|
|
|
/* decode the instruction */
|
|
switch (i.j_format.opcode) {
|
|
|
|
case spec_op:
|
|
|
|
if (i.word == 0x20) {
|
|
strcat(bufptr, "nop");
|
|
if (e.e.rd_boost)
|
|
strcat(bufptr, ".B");
|
|
bufptr += strlen(bufptr);
|
|
break;
|
|
} else if (i.r_format.func == addu_op && i.r_format.rt == ZERO) {
|
|
sprintf(bufptr, "move%s\t%s,%s",
|
|
e.e.rd_boost ? ".B" : "",
|
|
register_name(i.r_format.rd, e.e.rd_boost, regmask),
|
|
register_name(i.r_format.rs, e.e.rs_boost, regmask));
|
|
bufptr += strlen(bufptr);
|
|
break;
|
|
}
|
|
strcat(bufptr, spec_name[i.r_format.func]);
|
|
if (e.e.rd_boost)
|
|
strcat(bufptr, ".B");
|
|
bufptr += strlen(bufptr);
|
|
|
|
switch (i.r_format.func) {
|
|
case sll_op:
|
|
case srl_op:
|
|
case sra_op:
|
|
sprintf(bufptr, "\t%s,%s,%d",
|
|
register_name(i.r_format.rd, e.e.rd_boost, regmask),
|
|
register_name(i.r_format.rt, e.e.rt_boost, regmask),
|
|
i.r_format.re);
|
|
break;
|
|
case sllv_op:
|
|
case srlv_op:
|
|
case srav_op:
|
|
sprintf(bufptr, "\t%s,%s,%s",
|
|
register_name(i.r_format.rd, e.e.rd_boost, regmask),
|
|
register_name(i.r_format.rt, e.e.rt_boost, regmask),
|
|
register_name(i.r_format.rs, e.e.rs_boost, regmask));
|
|
break;
|
|
case mfhi_op:
|
|
case mflo_op:
|
|
sprintf(bufptr, "\t%s",
|
|
register_name(i.r_format.rd, e.e.rd_boost, regmask));
|
|
break;
|
|
case jalr_op:
|
|
return_value = 2;
|
|
sprintf(bufptr, "\t%s,%s",
|
|
register_name(i.r_format.rd, e.e.rd_boost, regmask),
|
|
register_name(i.r_format.rs, e.e.rs_boost, regmask));
|
|
break;
|
|
case jr_op:
|
|
return_value = 2;
|
|
/* fall through */
|
|
case mtlo_op:
|
|
case mthi_op:
|
|
sprintf(bufptr, "\t%s",
|
|
register_name(i.r_format.rs, e.e.rs_boost, regmask));
|
|
break;
|
|
case mult_op:
|
|
case multu_op:
|
|
case div_op:
|
|
case divu_op:
|
|
sprintf(bufptr, "\t%s,%s",
|
|
register_name(i.r_format.rs, e.e.rs_boost, regmask),
|
|
register_name(i.r_format.rt, e.e.rt_boost, regmask));
|
|
break;
|
|
case syscall_op:
|
|
break;
|
|
case break_op:
|
|
case vcall_op:
|
|
{
|
|
char *format = "\t%d";
|
|
unsigned op2 = i.r_format.rd * 32 + i.r_format.re;
|
|
|
|
if (op2)
|
|
format = "\t%d,%d";
|
|
sprintf(bufptr, format, i.r_format.rs*32+i.r_format.rt,
|
|
op2);
|
|
}
|
|
break;
|
|
default:
|
|
sprintf(bufptr, "\t%s,%s,%s",
|
|
register_name(i.r_format.rd, e.e.rd_boost, regmask),
|
|
register_name(i.r_format.rs, e.e.rs_boost, regmask),
|
|
register_name(i.r_format.rt, e.e.rt_boost, regmask));
|
|
break;
|
|
};
|
|
break;
|
|
|
|
case bcond_op:
|
|
sprintf(bufptr, "%s%s\t%s,",
|
|
bcond_name[i.i_format.rt],
|
|
e.e.rd_boost ? ".B" : "",
|
|
register_name(i.i_format.rs, e.e.rs_boost, regmask));
|
|
do_b_displacement = true;
|
|
break;
|
|
|
|
case blez_op_T:
|
|
case bgtz_op_T:
|
|
case blez_op_N:
|
|
case bgtz_op_N:
|
|
sprintf(bufptr, "%s%s\t%s,", op_name[i.i_format.opcode],
|
|
e.e.rd_boost ? ".B" : "",
|
|
register_name(i.i_format.rs, e.e.rs_boost, regmask));
|
|
do_b_displacement = true;
|
|
break;
|
|
case beq_op_T:
|
|
case beq_op_N:
|
|
if (i.i_format.rs == ZERO && i.i_format.rt == ZERO) {
|
|
strcat(bufptr, "b");
|
|
if (i.j_format.opcode == beq_op_T)
|
|
strcat(bufptr, ".T");
|
|
else
|
|
strcat(bufptr, ".N");
|
|
if (e.e.rd_boost)
|
|
strcat(bufptr, ".B\t");
|
|
else
|
|
strcat(bufptr, "\t");
|
|
do_b_displacement = true;
|
|
break;
|
|
}
|
|
/* fall through */
|
|
case bne_op_T:
|
|
case bne_op_N:
|
|
sprintf(bufptr, "%s%s\t%s,%s,", op_name[i.i_format.opcode],
|
|
e.e.rd_boost ? ".B" : "",
|
|
register_name(i.i_format.rs, e.e.rs_boost, regmask),
|
|
register_name(i.i_format.rt, e.e.rt_boost, regmask));
|
|
do_b_displacement = true;
|
|
break;
|
|
|
|
case cop0_op:
|
|
case cop1_op:
|
|
case cop2_op:
|
|
case cop3_op:
|
|
{
|
|
unsigned which_cop = i.j_format.opcode - cop0_op;
|
|
char *f_or_r = "rf";
|
|
|
|
switch (i.r_format.rs) {
|
|
case bc_op_T:
|
|
sprintf(bufptr, "bc%d%c.T%s\t", which_cop,
|
|
"ft"[i.r_format.rt],
|
|
e.e.rd_boost ? ".B" : "");
|
|
do_b_displacement = true;
|
|
break;
|
|
case bc_op_N:
|
|
sprintf(bufptr, "bc%d%c.N%s\t", which_cop,
|
|
"ft"[i.r_format.rt],
|
|
e.e.rd_boost ? ".B" : "");
|
|
do_b_displacement = true;
|
|
break;
|
|
case mtc_op:
|
|
if (which_cop == 0)
|
|
sprintf(bufptr, "mtc%d%s\t%s,%s", which_cop,
|
|
e.e.rd_boost ? ".B" : "",
|
|
register_name(i.r_format.rt, e.e.rt_boost,regmask),
|
|
c0_reg[i.f_format.rd]);
|
|
else
|
|
sprintf(bufptr, "mtc%d%s\t%s,%c%d", which_cop,
|
|
e.e.rd_boost ? ".B" : "",
|
|
register_name(i.r_format.rt, e.e.rt_boost,regmask),
|
|
f_or_r[(which_cop == 1)],
|
|
i.f_format.rd);
|
|
break;
|
|
case mfc_op:
|
|
if (which_cop == 0)
|
|
sprintf(bufptr, "mfc%d%s\t%s,%s", which_cop,
|
|
e.e.rd_boost ? ".B" : "",
|
|
register_name(i.r_format.rt, e.e.rt_boost,regmask),
|
|
c0_reg[i.f_format.rd]);
|
|
else
|
|
sprintf(bufptr, "mfc%d%s\t%s,%c%d", which_cop,
|
|
e.e.rd_boost ? ".B" : "",
|
|
register_name(i.r_format.rt, e.e.rt_boost,regmask),
|
|
f_or_r[(which_cop == 1)],
|
|
i.f_format.rd);
|
|
break;
|
|
case cfc_op:
|
|
sprintf(bufptr, "cfc%d%s\t%s,%c%d", which_cop,
|
|
e.e.rd_boost ? ".B" : "",
|
|
register_name(i.r_format.rt, e.e.rt_boost, regmask),
|
|
f_or_r[(which_cop == 1)],
|
|
i.f_format.rd);
|
|
break;
|
|
case ctc_op:
|
|
sprintf(bufptr, "ctc%d%s\t%s,%c%d", which_cop,
|
|
e.e.rd_boost ? ".B" : "",
|
|
register_name(i.r_format.rt, e.e.rt_boost, regmask),
|
|
f_or_r[(which_cop == 1)],
|
|
i.f_format.rd);
|
|
break;
|
|
default:
|
|
if (which_cop != 1)
|
|
sprintf(bufptr, "c0%s\t%s", e.e.rd_boost ? ".B" : "",
|
|
c0_opname[i.f_format.func]);
|
|
else
|
|
{
|
|
sprintf(bufptr, "%s.%s%s\t",
|
|
cop1_name[i.f_format.func],
|
|
fmt_name[i.f_format.fmt],
|
|
e.e.rd_boost ? ".B" : "");
|
|
bufptr += strlen(bufptr);
|
|
switch (i.f_format.func) {
|
|
case fsqrt_op:
|
|
case fabs_op:
|
|
case fmov_op:
|
|
case fcvts_op:
|
|
case fcvtd_op:
|
|
case fcvte_op:
|
|
case fcvtw_op:
|
|
sprintf(bufptr, "f%d,f%d",
|
|
i.f_format.re,
|
|
i.f_format.rd);
|
|
break;
|
|
case fcmp_op+0x0:
|
|
case fcmp_op+0x1:
|
|
case fcmp_op+0x2:
|
|
case fcmp_op+0x3:
|
|
case fcmp_op+0x4:
|
|
case fcmp_op+0x5:
|
|
case fcmp_op+0x6:
|
|
case fcmp_op+0x7:
|
|
case fcmp_op+0x8:
|
|
case fcmp_op+0x9:
|
|
case fcmp_op+0xa:
|
|
case fcmp_op+0xb:
|
|
case fcmp_op+0xc:
|
|
case fcmp_op+0xd:
|
|
case fcmp_op+0xe:
|
|
case fcmp_op+0xf:
|
|
sprintf(bufptr, "f%d,f%d",
|
|
i.f_format.rd,
|
|
i.f_format.rt);
|
|
break;
|
|
default:
|
|
sprintf(bufptr, "f%d,f%d,f%d",
|
|
i.f_format.re,
|
|
i.f_format.rd,
|
|
i.f_format.rt);
|
|
break;
|
|
} /* switch on func */
|
|
}
|
|
break; /* End of default */
|
|
} /* switch on rs */
|
|
}
|
|
break; /* End of cop0, cop1, cop2, cop3 */
|
|
|
|
case jal_op:
|
|
case j_op:
|
|
sprintf(bufptr, "%s%s\t", op_name[i.j_format.opcode],
|
|
e.e.rd_boost ? ".B" : "");
|
|
*symbol_value = (address & 0xF0000000) | i.j_format.target << 2;
|
|
if (save.print_jal_targets)
|
|
{
|
|
bufptr += strlen(bufptr);
|
|
sprintf(bufptr, "%#x", *symbol_value);
|
|
}
|
|
return_value = 1;
|
|
break;
|
|
|
|
case swc1_op:
|
|
case sdc1_op:
|
|
case lwc1_op:
|
|
case ldc1_op:
|
|
sprintf(bufptr, "%s%s\tf%d,", op_name[i.i_format.opcode],
|
|
e.e.rd_boost ? ".B" : "",
|
|
i.i_format.rt);
|
|
do_loadstore = true;
|
|
break;
|
|
|
|
case lb_op:
|
|
case lh_op:
|
|
case lw_op:
|
|
case ld_op:
|
|
case lbu_op:
|
|
case lhu_op:
|
|
case sb_op:
|
|
case sh_op:
|
|
case sw_op:
|
|
case sd_op:
|
|
case lwl_op:
|
|
case lwr_op:
|
|
sprintf(bufptr, "%s%s\t%s,", op_name[i.i_format.opcode],
|
|
e.e.rd_boost ? ".B" : "",
|
|
register_name(i.i_format.rt, e.e.rt_boost, regmask));
|
|
do_loadstore = true;
|
|
break;
|
|
|
|
case ori_op:
|
|
case xori_op:
|
|
if (i.u_format.rs == ZERO) {
|
|
sprintf(bufptr, "li%s\t%s,%d",
|
|
e.e.rd_boost ? ".B" : "",
|
|
register_name(i.u_format.rt, e.e.rt_boost, regmask),
|
|
i.u_format.uimmediate);
|
|
break;
|
|
}
|
|
/* fall through */
|
|
case andi_op:
|
|
sprintf(bufptr, "%s%s\t%s,%s,%#x", op_name[i.u_format.opcode],
|
|
e.e.rd_boost ? ".B" : "",
|
|
register_name(i.u_format.rt, e.e.rt_boost, regmask),
|
|
register_name(i.u_format.rs, e.e.rs_boost, regmask),
|
|
i.u_format.uimmediate);
|
|
break;
|
|
case lui_op:
|
|
sprintf(bufptr, "%s%s\t%s,%#x", op_name[i.u_format.opcode],
|
|
e.e.rd_boost ? ".B" : "",
|
|
register_name(i.u_format.rt, e.e.rt_boost, regmask),
|
|
i.u_format.uimmediate);
|
|
break;
|
|
case addi_op:
|
|
case addiu_op:
|
|
if (i.i_format.rs == ZERO) {
|
|
short sign_extender = i.i_format.simmediate;
|
|
sprintf(bufptr, "li%s\t%s,%d",
|
|
e.e.rd_boost ? ".B" : "",
|
|
register_name(i.i_format.rt, e.e.rt_boost, regmask),
|
|
sign_extender);
|
|
break;
|
|
}
|
|
/* fall through */
|
|
default:
|
|
{
|
|
short sign_extender = i.i_format.simmediate;
|
|
sprintf(bufptr, "%s%s\t%s,%s,%d", op_name[i.i_format.opcode],
|
|
e.e.rd_boost ? ".B" : "",
|
|
register_name(i.i_format.rt, e.e.rt_boost, regmask),
|
|
register_name(i.i_format.rs, e.e.rs_boost, regmask),
|
|
sign_extender);
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* Some instructions require more than just registers */
|
|
|
|
if (do_loadstore)
|
|
{
|
|
short sign_extender = i.i_format.simmediate;
|
|
*symbol_value = sign_extender;
|
|
*ls_register = i.i_format.rs;
|
|
bufptr += strlen(bufptr);
|
|
sprintf(bufptr, "%d(%s)", sign_extender,
|
|
register_name(i.i_format.rs, e.e.rs_boost, regmask));
|
|
return_value = -1;
|
|
}
|
|
else if (do_b_displacement)
|
|
{
|
|
short sign_extender = i.i_format.simmediate;
|
|
bufptr += strlen(bufptr);
|
|
sprintf(bufptr, "%#x", 4 + address + ((((long)sign_extender & 0xFFFD0000) | (0x3FFFF & (sign_extender << 2)))));
|
|
// sprintf(bufptr, "%#x", (long)sign_extender);
|
|
return_value = 2;
|
|
}
|
|
|
|
return return_value;
|
|
}
|
|
|
|
static long instrs[10]={
|
|
0x0411000a,
|
|
0x03e0f021,
|
|
0x02feb023,
|
|
0x24010050,
|
|
0x10360044,
|
|
0x24010090,
|
|
0x10360046,
|
|
0x240100b8,
|
|
0x10360048,
|
|
0x240100d0
|
|
};
|
|
|
|
int main(void)
|
|
{
|
|
int i;
|
|
int junk;
|
|
char buf[80];
|
|
long *pInstr = (long*)instrs;
|
|
|
|
for (i=0; i < 10; i++)
|
|
{
|
|
tdisasm(buf, (long)&pInstr[i], pInstr[i], 0, &junk, &junk, &junk);
|
|
printf("%s\n", buf);
|
|
}
|
|
return 0;
|
|
|
|
}
|