00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #define _MAD_MSB 1
00043
00044 #include <stdio.h>
00045 #ifdef _BSD
00046 #include <machine/inst.h>
00047 #else
00048 #include <sys/inst.h>
00049 #endif
00050 #include "cmplrs/newinst.h"
00051 #include <disassembler.h>
00052 #include <string.h>
00053 #include "libelf.h"
00054 #if defined(BUILD_OS_DARWIN)
00055 #include "darwin_elf.h"
00056 #else
00057 #include <elf.h>
00058 #endif
00059
00060 extern int dis_asm(char *, unsigned long long int);
00061
00062 #ifdef _64BIT_OBJECTS
00063
00064 #define ELF_ADDR Elf64_Addr
00065 #define ELF_WORD Elf64_Word
00066 #define F_DIS_INIT __dis_init64
00067 #define F_REGISTER_NAME __register_name64
00068 #define F_FP_REGISTER_NAME __fp_register_name64
00069 #define F_C0_REGISTER_NAME __co_register_name64
00070 #define F_Vec_REGISTER_NAME __disassembler_vec_register_name64
00071 #define F_DISASM __disasm64
00072 #define F_DIS_REGS __dis_regs64
00073 #define F_DISASSEMBLER __disassembler64
00074 #define DIS_REG_NAMES dis_reg_names64
00075
00076 #define HEXREG "0x%llx"
00077
00078 #else
00079
00080 #define ELF_ADDR Elf32_Addr
00081 #define ELF_WORD Elf32_Word
00082 #define F_DIS_INIT __dis_init32
00083 #define F_REGISTER_NAME __register_name32
00084 #define F_FP_REGISTER_NAME __fp_register_name32
00085 #define F_C0_REGISTER_NAME __co_register_name32
00086 #define F_Vec_REGISTER_NAME __disassembler_vec_register_name32
00087 #define F_DISASM __disasm32
00088 #define F_DIS_REGS __dis_regs32
00089 #define F_DISASSEMBLER __disassembler32
00090 #define DIS_REG_NAMES dis_reg_names32
00091 #define HEXREG "0x%x"
00092
00093 #endif
00094
00095
00096 #define ZERO 0
00097 #define private static
00098
00099 typedef int boolean;
00100 #define true 1
00101 #define false 0
00102
00103 private char *c1fmt_name[16] = {
00104 "s", "d", "e", "q",
00105 "w", "l", "ps", "fmt7",
00106 "fmt8", "fmt9", "fmta", "fmtb",
00107 "fmtc", "fmtd", "fmte", "fmtf"
00108 };
00109
00110
00111 #ifdef _DIS_BUILD
00112 #define ADDR64_DEFAULT "%#llx\t"
00113 #define VALUE64_DEFAULT "%#llx\t"
00114 #define NAME64_DEFAULT COMPILER_NAMES
00115 #endif
00116 #define ADDR_DEFAULT "%#010x\t"
00117 #define VALUE_DEFAULT "%#010x\t"
00118 #define NAME_DEFAULT COMPILER_NAMES
00119
00120 private struct {
00121 char *addr_format;
00122 char *value_format;
00123 char **reg_names;
00124 int print_jal_targets;
00125 } save = {
00126 ADDR_DEFAULT,
00127 VALUE_DEFAULT,
00128 NAME_DEFAULT,
00129 true
00130 };
00131
00132
00133 static char *op_name[64] = {
00134 "spec", "bcond", "j", "jal", "beq", "bne", "blez", "bgtz",
00135 "addi", "addiu", "slti", "sltiu", "andi", "ori", "xori", "lui",
00136 "cop0", "cop1", "cop2", "op13", "beql", "bnel", "blezl", "bgtzl",
00137 "daddi", "daddiu","ldl", "ldr", "op1c", "op1d", "op1e", "op1f",
00138 "lb", "lh", "lwl", "lw", "lbu", "lhu", "lwr", "lwu",
00139 "sb", "sh", "swl", "sw", "sdl", "sdr", "swr", "cache",
00140 "ll", "lwc1", "lwc2", "pref", "lld", "ldc1", "ldc2", "ld",
00141 "sc", "swc1", "swc2", "op3b", "scd", "sdc1", "sdc2", "sd"
00142 };
00143
00144 static char *spec_name[64] = {
00145 "sll", "mov", "srl", "sra", "sllv", "spec05","srlv", "srav",
00146 "jr", "jalr", "movz", "movn", "syscall","break","spim", "sync",
00147 "mfhi", "mthi", "mflo", "mtlo", "dsllv","spec15","dsrlv", "dsrav",
00148 "mult", "multu", "div", "divu", "dmult", "dmultu","ddiv", "ddivu",
00149 "add", "addu", "sub", "subu", "and", "or", "xor", "nor",
00150 "spec28","spec29","slt", "sltu", "dadd", "daddu", "dsub", "dsubu",
00151 "tge", "tgeu", "tlt", "tltu", "teq", "spec35","tne", "spec37",
00152 "dsll", "spec39","dsrl", "dsra", "dsll32", "spec3d","dsrl32", "dsra32"
00153 };
00154
00155 static char *bcond_name[32] = {
00156 "bltz", "bgez", "bltzl", "bgezl",
00157 "spimi", "bcond05", "bcond06", "bcond07",
00158 "tgei", "tgeiu", "tlti", "tltiu",
00159 "teqi", "bcond0d", "tnei", "bcond0f",
00160 "bltzal", "bgezal", "bltzall", "bgezall",
00161 "bcond14", "bcond15", "bcond16", "bcond17",
00162 "bcond18", "bcond19", "bcond1a", "bcond1b",
00163 "bcond1c", "bcond1d", "bcond1e", "bcond1f"
00164 };
00165
00166 static char *cop1func_name[64] = {
00167 "add", "sub", "mul", "div", "sqrt", "abs", "mov", "neg",
00168 "round.l", "trunc.l", "ceil.l", "floor.l",
00169 "round.w", "trunc.w", "ceil.w", "floor.w",
00170 "fop10", "mov", "movz", "movn", "fop14", "recip", "rsqrt", "fop17",
00171 "fop18", "fop19", "fop1a", "fop1b", "fop1c", "fop1d", "fop1e", "fop1f",
00172 "cvt.s", "cvt.d", "cvt.e", "fop23", "cvt.w", "cvt.l", "cvt.ps", "fop27",
00173 "cvt.s.pu", "fop29", "fop2a", "fop2b", "pll", "plu", "pul", "puu",
00174 "c.f", "c.un", "c.eq", "c.ueq", "c.olt", "c.ult", "c.ole", "c.ule",
00175 "c.sf", "c.ngle","c.seq", "c.ngl", "c.lt", "c.nge", "c.le", "c.ngt"
00176 };
00177
00178 static char *bc_name[32] = {
00179 "f", "t", "fl", "tl",
00180 "x04", "x05", "x06", "x07",
00181 "x08", "x09", "x0a", "x0b",
00182 "x0c", "x0d", "x0e", "x0f",
00183 "x10", "x11", "x12", "x13",
00184 "x14", "x15", "x16", "x17",
00185 "x18", "x19", "x1a", "x1b",
00186 "x1c", "x1d", "x1e", "x1f"
00187 };
00188
00189 static char *c0func_name[64] = {
00190 "op00", "tlbr", "tlbwi","op03", "op04", "op05", "tlbwr","op07",
00191 "tlbp", "op9", "op10", "op11", "op12", "op13", "op14", "op15",
00192 "rfe", "op17", "op18", "op19", "op20", "op21", "op22", "op23",
00193 "eret", "op25", "op26", "op27", "op28", "op29", "op30", "op31",
00194 "op32", "op33", "op34", "op35", "op36", "op37", "op38", "op39",
00195 "op40", "op41", "op42", "op43", "op44", "op45", "op46", "op47",
00196 "op48", "op49", "op50", "op51", "op52", "op53", "op54", "op55",
00197 "op56", "op57", "op58", "op59", "op60", "op61", "op62", "op63"
00198 };
00199
00200 static char *c0mfunc_name[64] = {
00201 "c0m00", "tlbr1", "tlbw", "c0m03", "c0m04", "c0m05", "c0m06", "c0m07",
00202 "tlbp1", "dctr", "dctw", "c0m11", "c0m12", "c0m13", "c0m14", "c0m15",
00203 "c0m16", "c0m17", "c0m18", "c0m19", "c0m20", "c0m21", "c0m22", "c0m23",
00204 "c0m24", "c0m25", "c0m26", "c0m27", "c0m28", "c0m29", "c0m30", "c0m31",
00205 "c0m32", "c0m33", "c0m34", "c0m35", "c0m36", "c0m37", "c0m38", "c0m39",
00206 "c0m40", "c0m41", "c0m42", "c0m43", "c0m44", "c0m45", "c0m46", "c0m47",
00207 "c0m48", "c0m49", "c0m50", "c0m51", "c0m52", "c0m53", "c0m54", "c0m55",
00208 "c0m56", "c0m57", "c0m58", "c0m59", "c0m60", "c0m61", "c0m62", "c0m63"
00209 };
00210
00211 static char *c0reg_name[32] = {
00212 "index","random","tlblo","tlblo1","context","pagemask","wired","c0r7",
00213 "badvaddr","count","tlbhi","compare","sr", "cause","epc", "prid",
00214 "config","lladdr","watchlo","watchhi","c0r20","c0r21","c0r22","c0r23",
00215 "c0r24","c0r25","ecc","cacheerr","taglo","taghi","errorepc","c0r31"
00216 };
00217
00218 static char *cop1xfunc_name[64] = {
00219 "lwxc1", "ldxc1", "c1x02", "c1x03", "c1x04", "luxc1", "c1x06", "pfetch",
00220 "swxc1", "sdxc1", "c1x10", "c1x11", "c1x12", "suxc1", "c1x14", "prefx",
00221 "c1x16", "c1x17", "c1x18", "c1x19", "c1x20", "c1x21", "c1x22", "c1x23",
00222 "c1x24", "c1x25", "c1x26", "c1x27", "alnv.ps", "c1x29", "c1x30", "c1x31",
00223 "madd.s", "madd.d", "madd.e", "c1x35", "c1x36", "c1x37", "madd.ps", "c1x39",
00224 "msub.s", "msub.d", "msub.e", "c1x43", "c1x44", "c1x45", "msub.ps", "c1x47",
00225 "nmadd.s","nmadd.d","nmadd.e","c1x51", "c1x52", "c1x53", "nmadd.ps", "c1x55",
00226 "nmsub.s","nmsub.d","nmsub.e","c1x59", "c1x60", "c1x61", "nmsub.ps", "c1x63",
00227 };
00228
00229 static char *cop2func_name[64] = {
00230 "msgn", "c.eq", "pickf", "pickt", "c.lt", "c.le", "min", "max",
00231 "c2x8", "c2x9", "sub", "add", "and", "xor", "or", "nor",
00232 "sll", "c2x17", "srl", "sra", "c2x20", "c2x21", "c2x22", "c2x23",
00233 "alni.ob", "alnv.ob", "alni.qh", "alnv.qh", "c2x28", "c2x29", "c2x30", "shfl",
00234 "rzu", "rnau", "rneu", "c2x35", "rzs", "rnas", "rnes", "c2x39",
00235 "c2x40", "c2x41", "c2x42", "c2x43", "c2x44", "c2x45", "c2x46", "c2x47",
00236 "mul", "c2x49", "muls", "mul", "c2x52", "c2x53", "sub", "add",
00237 "c2x56", "c2x57","c2x58", "c2x59", "c2x60", "c2x61", "wac", "rac"
00238 };
00239
00240 #ifndef _64BIT_OBJECTS
00241
00242
00243 char *dis_reg_names[3][32] = {
00244 {
00245 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
00246 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
00247 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
00248 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
00249 },
00250 {
00251 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
00252 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
00253 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
00254 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
00255 },
00256 {
00257 "$0", "$at", "$2", "$3", "$4", "$5", "$6", "$7",
00258 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
00259 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
00260 "$24", "$25", "$26", "$27", "$gp", "$sp", "$30", "$31"
00261 }
00262 };
00263 #else
00264
00265
00266 char *dis_reg_names64[3][32] = {
00267 {
00268 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
00269 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
00270 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
00271 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
00272 },
00273 {
00274 "$0", "$at", "$2", "$3", "$4", "$5", "$6", "$7",
00275 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
00276 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
00277 "$24", "$25", "$26", "$27", "$gp", "$sp", "$30", "$31"
00278 }
00279 };
00280 #endif
00281
00282 #ifndef _64BIT_OBJECTS
00283 #pragma weak disasm = __disasm32
00284 #pragma weak disasm32 = __disasm32
00285 #pragma weak dis_init = __dis_init32
00286 #pragma weak dis_init32 = __dis_init32
00287 #pragma weak register_name = __register_name32
00288 #pragma weak co_register_name = __co_register_name32
00289 #pragma weak fp_register_name = __fp_register_name32
00290 #pragma weak disassembler = __disassembler32
00291 #pragma weak disassembler32 = __disassembler32
00292 #elif defined(BUILD_OS_DARWIN)
00293 #else
00294 #pragma weak disasm64 = __disasm64
00295 #pragma weak dis_init64 = __dis_init64
00296 #pragma weak register_name64 = __register_name64
00297 #pragma weak co_register_name64 = __co_register_name64
00298 #pragma weak fp_register_name64 = __fp_register_name64
00299 #pragma weak disassembler64 = __disassembler64
00300 #endif
00301
00302
00303 int F_DISASM(char *, ELF_ADDR,Elf32_Addr,Elf32_Addr *,ELF_ADDR *, Elf32_Addr *);
00304 void F_DIS_INIT ( char *, char *, char *[], int);
00305 char * F_REGISTER_NAME(unsigned, Elf32_Addr *);
00306 char * F_C0_REGISTER_NAME(unsigned);
00307 char * F_FP_REGISTER_NAME(unsigned);
00308 char * F_Vec_REGISTER_NAME (unsigned r);
00309 int F_DISASSEMBLER (ELF_ADDR ,int ,char *(*get_symname)(unsigned),int (*get_regvalue)(unsigned),long (*get_bytes)(void),void (*print_header)(unsigned,unsigned));
00310
00311 #ifdef _DIS_BUILD
00312 extern int Rel_data;
00313 extern int Rela_data;
00314 extern Elf32_Addr loc_val32;
00315 extern Elf64_Addr loc_val64;
00316 extern int is_64_bit;
00317 extern ELF_WORD dis_arch;
00318 extern int xflag;
00319 extern int zt5flag;
00320 #endif
00321
00322
00323 void
00324 F_DIS_INIT ( char *addr_format, char *value_format, char *reg_names[], int print_jal_targets)
00325 {
00326 if (addr_format) save.addr_format = addr_format;
00327 else {
00328 #ifdef _DIS_BUILD
00329 if (is_64_bit)
00330 save.addr_format = ADDR64_DEFAULT;
00331 else
00332 save.addr_format = ADDR_DEFAULT;
00333 #else
00334 save.addr_format = ADDR_DEFAULT;
00335 #endif
00336 }
00337 if (value_format) save.value_format = value_format;
00338 else {
00339 #ifdef _DIS_BUILD
00340 if (is_64_bit)
00341 save.value_format = VALUE64_DEFAULT;
00342 else
00343 save.value_format = VALUE_DEFAULT;
00344 #else
00345 save.value_format = VALUE_DEFAULT;
00346 #endif
00347 }
00348 if (reg_names) save.reg_names = reg_names;
00349 else {
00350 #ifdef _DIS_BUILD
00351 if (is_64_bit)
00352 save.reg_names = NAME64_DEFAULT;
00353 else
00354 save.reg_names = NAME_DEFAULT;
00355 #else
00356 save.reg_names = NAME_DEFAULT;
00357 #endif
00358 }
00359 save.print_jal_targets = print_jal_targets;
00360 }
00361
00362
00363
00364
00365 char *
00366 F_REGISTER_NAME ( unsigned ireg, Elf32_Addr *regmask)
00367 {
00368 *regmask |= (1 << ireg);
00369 return save.reg_names[ireg];
00370 }
00371
00372
00373 char *
00374 F_FP_REGISTER_NAME (unsigned r)
00375 {
00376 static char *name[32] = {
00377 "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
00378 "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
00379 "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
00380 "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"
00381 };
00382 return name[r];
00383 }
00384
00385
00386 char *
00387 F_C0_REGISTER_NAME(unsigned r)
00388 {
00389 return c0reg_name[r];
00390 }
00391
00392 char *
00393 F_Vec_REGISTER_NAME (unsigned r)
00394 {
00395 static char *name[32] = {
00396 "$v0", "$v1", "$v2", "$v3", "$v4", "$v5", "$v6", "$v7",
00397 "$v8", "$v9", "$v10", "$v11", "$v12", "$v13", "$v14", "$v15",
00398 "$v16", "$v17", "$v18", "$v19", "$v20", "$v21", "$v22", "$v23",
00399 "$v24", "$v25", "$v26", "$v27", "$v28", "$v29", "$v30", "$v31"
00400 };
00401 return name[r];
00402 }
00403
00404
00405 int
00406 F_DISASM(char *buffer, ELF_ADDR address, Elf32_Addr iword, Elf32_Addr *regmask, ELF_ADDR *symbol_value, Elf32_Addr *ls_register)
00407 {
00408 int return_value = 0;
00409 char *bufptr = buffer;
00410 boolean do_b_displacement = false;
00411 boolean do_loadstore = false;
00412 union mips_instruction i;
00413
00414 i.word = iword;
00415 *regmask = *symbol_value = *ls_register = 0;
00416
00417
00418
00419 #ifndef _DIS_BUILD
00420 if (save.addr_format) {
00421 sprintf(bufptr, save.addr_format, address);
00422 bufptr += strlen(bufptr);
00423 }
00424 if (save.value_format) {
00425 sprintf(bufptr, save.value_format, iword);
00426 bufptr += strlen(bufptr);
00427 }
00428 #endif
00429 #ifndef USE_TARG_INFO
00430 switch (i.j_format.opcode) {
00431
00432 case spec_op:
00433 if (i.word == 0) {
00434 strcat(bufptr, "nop");
00435 bufptr += strlen(bufptr);
00436 break;
00437 }
00438 else if ((i.r_format.func == addu_op ||
00439 i.r_format.func == daddu_op ||
00440 i.r_format.func == or_op) &&
00441 i.r_format.rt == ZERO)
00442 {
00443 if (i.r_format.func == addu_op &&
00444 i.r_format.rd == ZERO &&
00445 i.r_format.rs == ZERO )
00446 sprintf (bufptr, "nada");
00447 else {
00448 if (i.r_format.func == addu_op)
00449 {
00450 sprintf(bufptr, "%s\t%s,%s,%#x", "addu",
00451 F_REGISTER_NAME(i.r_format.rd, regmask),
00452 F_REGISTER_NAME(i.r_format.rs, regmask),
00453 i.r_format.re);
00454 } else if (i.r_format.func == or_op &&
00455 i.r_format.rt != ZERO)
00456 sprintf(bufptr, "%s\t%s,%s,%#x", "or",
00457 F_REGISTER_NAME(i.r_format.rd, regmask),
00458 F_REGISTER_NAME(i.r_format.rs, regmask),
00459 i.r_format.re);
00460 else
00461 sprintf(bufptr, "move\t%s,%s",
00462 F_REGISTER_NAME(i.r_format.rd, regmask),
00463 F_REGISTER_NAME(i.r_format.rs, regmask));
00464
00465 #if 0
00466 sprintf(bufptr, "move\t%s,%s",
00467 F_REGISTER_NAME(i.r_format.rd, regmask),
00468 F_REGISTER_NAME(i.r_format.rs, regmask));
00469 #endif
00470 }
00471 bufptr += strlen(bufptr);
00472 break;
00473 }
00474 else if ( ( i.r_format.func == sll_op )
00475 && ( i.r_format.rd == ZERO )
00476 && ( i.r_format.rs == ZERO )
00477 && ( i.r_format.re == 1 ) ) {
00478 sprintf (bufptr, "ssnop" );
00479 bufptr += strlen(bufptr);
00480 break;
00481 }
00482 strcat(bufptr, spec_name[i.r_format.func]);
00483 bufptr += strlen(bufptr);
00484
00485 switch (i.r_format.func) {
00486 case dsll_op:
00487 case dsrl_op:
00488 case dsra_op:
00489 case dsll32_op:
00490 case dsrl32_op:
00491 case dsra32_op:
00492 sprintf(bufptr, "\t%s,%s,%d",
00493 F_REGISTER_NAME(i.r_format.rd, regmask),
00494 F_REGISTER_NAME(i.r_format.rt, regmask),
00495 (int)(i.r_format.re + (i.r_format.rs << 5)));
00496 break;
00497 case sll_op:
00498 case srl_op:
00499 case sra_op:
00500 sprintf(bufptr, "\t%s,%s,%d",
00501 F_REGISTER_NAME(i.r_format.rd, regmask),
00502 F_REGISTER_NAME(i.r_format.rt, regmask),
00503 (int)i.r_format.re);
00504 break;
00505 case sllv_op:
00506 case srlv_op:
00507 case srav_op:
00508 case dsllv_op:
00509 case dsrlv_op:
00510 case dsrav_op:
00511 sprintf(bufptr, "\t%s,%s,%s",
00512 F_REGISTER_NAME(i.r_format.rd, regmask),
00513 F_REGISTER_NAME(i.r_format.rt, regmask),
00514 F_REGISTER_NAME(i.r_format.rs, regmask));
00515 break;
00516 case movc_op:
00517 sprintf(bufptr, "%c\t%s,%s,$fcc%d",
00518 (i.r_format.rt & 1) ? 't' : 'f',
00519 F_REGISTER_NAME(i.r_format.rd, regmask),
00520 F_REGISTER_NAME(i.r_format.rs, regmask),
00521 (int)(i.r_format.rt >> 2));
00522 break;
00523 case movz_op:
00524 case movn_op:
00525 sprintf(bufptr, "\t%s,%s,%s",
00526 F_REGISTER_NAME(i.r_format.rd, regmask),
00527 F_REGISTER_NAME(i.r_format.rs, regmask),
00528 F_REGISTER_NAME(i.r_format.rt, regmask));
00529 break;
00530 case mfhi_op:
00531 case mflo_op:
00532 sprintf(bufptr, "\t%s",
00533 F_REGISTER_NAME(i.r_format.rd, regmask));
00534 break;
00535 case jalr_op:
00536 return_value = 2;
00537 sprintf(bufptr, "\t%s,%s",
00538 F_REGISTER_NAME(i.r_format.rd, regmask),
00539 F_REGISTER_NAME(i.r_format.rs, regmask));
00540 break;
00541 case jr_op:
00542 return_value = 2;
00543 sprintf(bufptr, "\t%s",
00544 F_REGISTER_NAME(i.r_format.rs, regmask));
00545 break;
00546 case mtlo_op:
00547 case mthi_op:
00548 sprintf(bufptr, "\t%s",
00549 F_REGISTER_NAME(i.r_format.rs, regmask));
00550 break;
00551 case teq_op:
00552 {
00553 char *format = "\t%s,%s";
00554 ELF_ADDR op2 = i.r_format.rd * 32 + i.r_format.re;
00555
00556 if (op2)
00557 format = "\t%s,%s,%lx";
00558 sprintf(bufptr, format,
00559 F_REGISTER_NAME(i.r_format.rs, regmask),
00560 F_REGISTER_NAME(i.r_format.rt, regmask),
00561 op2);
00562 }
00563 break;
00564 case tge_op:
00565 case tlt_op:
00566 case tne_op:
00567 case div_op:
00568 sprintf(bufptr, "\t%s,%s",
00569 F_REGISTER_NAME(i.r_format.rs, regmask),
00570 F_REGISTER_NAME(i.r_format.rt, regmask));
00571 break;
00572 case tgeu_op:
00573 case tltu_op:
00574 case mult_op:
00575 case multu_op:
00576 case divu_op:
00577 case dmult_op:
00578 case dmultu_op:
00579 case ddiv_op:
00580 case ddivu_op:
00581 sprintf(bufptr, "\t%s,%s",
00582 F_REGISTER_NAME(i.r_format.rs, regmask),
00583 F_REGISTER_NAME(i.r_format.rt, regmask));
00584 break;
00585 case syscall_op:
00586 case sync_op:
00587 break;
00588 case break_op:
00589 {
00590 char *format = "\t%#x";
00591 ELF_ADDR op2 = i.r_format.rd * 32 + i.r_format.re;
00592
00593 if (op2)
00594 format = "\t%#x,%#x";
00595 sprintf(bufptr, format, i.r_format.rs*32+i.r_format.rt,
00596 op2);
00597 }
00598 break;
00599 default:
00600 sprintf(bufptr, bufptr-buffer<2?"\t\t%s,%s,%s":"\t%s,%s,%s",
00601 F_REGISTER_NAME(i.r_format.rd, regmask),
00602 F_REGISTER_NAME(i.r_format.rs, regmask),
00603 F_REGISTER_NAME(i.r_format.rt, regmask));
00604 break;
00605 }
00606 break;
00607
00608 case bcond_op:
00609 switch (i.i_format.rt) {
00610 case tgei_op:
00611 case tgeiu_op:
00612 case tlti_op:
00613 case tltiu_op:
00614 case teqi_op:
00615 case tnei_op:
00616 sprintf(bufptr, "%s\t%s,%d",
00617 bcond_name[i.i_format.rt],
00618 F_REGISTER_NAME(i.i_format.rs, regmask),
00619 i.i_format.simmediate);
00620 break;
00621 case blez_op:
00622 sprintf(bufptr, "%s\t%s,",
00623 bcond_name[i.i_format.rt],
00624 F_REGISTER_NAME(i.i_format.rs, regmask));
00625 do_b_displacement = true;
00626 break;
00627 case bltz_op:
00628 sprintf(bufptr, "%s\t%s,",
00629 bcond_name[i.i_format.rt],
00630 F_REGISTER_NAME(i.i_format.rs, regmask));
00631 do_b_displacement = true;
00632 break;
00633 default:
00634 sprintf(bufptr, "%s\t%s,",
00635 bcond_name[i.i_format.rt],
00636 F_REGISTER_NAME(i.i_format.rs, regmask));
00637 do_b_displacement = true;
00638 break;
00639 }
00640 break;
00641 case blez_op:
00642 case bgtz_op:
00643 case blezl_op:
00644 case bgtzl_op:
00645 sprintf(bufptr, "%s\t%s,", op_name[i.i_format.opcode],
00646 F_REGISTER_NAME(i.i_format.rs, regmask));
00647 do_b_displacement = true;
00648 break;
00649 case beq_op:
00650 if (i.i_format.rs == ZERO && i.i_format.rt == ZERO) {
00651 #ifdef _DIS_BUILD
00652 strcat(bufptr, "b\t\t");
00653 #else
00654 strcat(bufptr, "b\t");
00655 #endif
00656 do_b_displacement = true;
00657 break;
00658 }
00659
00660 case bne_op:
00661 sprintf(bufptr, "%s\t%s,%s,", op_name[i.i_format.opcode],
00662 F_REGISTER_NAME(i.i_format.rs, regmask),
00663 F_REGISTER_NAME(i.i_format.rt, regmask));
00664 do_b_displacement = true;
00665 break;
00666
00667 case beql_op:
00668 case bnel_op:
00669 sprintf(bufptr, "%s\t%s,%s,", op_name[i.i_format.opcode],
00670 F_REGISTER_NAME(i.i_format.rs, regmask),
00671 F_REGISTER_NAME(i.i_format.rt, regmask));
00672 do_b_displacement = true;
00673 break;
00674
00675 case jal_op:
00676 case j_op:
00677 sprintf(bufptr, "%s", op_name[i.j_format.opcode]);
00678 *symbol_value =
00679 ((address+4)&~((1<<28)-1)) + (i.j_format.target<<2);
00680 if (save.print_jal_targets) {
00681 bufptr += strlen(bufptr);
00682 #ifdef _DIS_BUILD
00683 if (i.r_format.opcode == j_op)
00684 sprintf(bufptr, "\t\t%#8llx", (unsigned long long)*symbol_value);
00685 else
00686 sprintf(bufptr, "\t%#8llx", (unsigned long long)*symbol_value);
00687 #else
00688
00689 #ifdef _64BIT_OBJECTS
00690 sprintf(bufptr, "\t%#llx", (unsigned long long)*symbol_value);
00691 #else
00692 sprintf(bufptr, "\t%#x", (unsigned)*symbol_value);
00693 #endif
00694
00695 #endif
00696 }
00697 return_value = 1;
00698 break;
00699
00700 case swc1_op:
00701 case sdc1_op:
00702 case lwc1_op:
00703 case ldc1_op:
00704 sprintf(bufptr, "%s\t%s,", op_name[i.i_format.opcode],
00705 F_FP_REGISTER_NAME(i.i_format.rt));
00706 do_loadstore = true;
00707 break;
00708
00709 case swc2_op:
00710 case sdc2_op:
00711 case lwc2_op:
00712 case ldc2_op:
00713 sprintf(bufptr, "%s\t$%#x,", op_name[i.i_format.opcode],
00714 i.i_format.rt);
00715 do_loadstore = true;
00716 break;
00717
00718 case lb_op:
00719 case lh_op:
00720 case lw_op:
00721 case ld_op:
00722 case sb_op:
00723 case sh_op:
00724 case sw_op:
00725 case sd_op:
00726 case ll_op:
00727 case sc_op:
00728 sprintf(bufptr, "%s\t%s,", op_name[i.i_format.opcode],
00729 F_REGISTER_NAME(i.i_format.rt, regmask));
00730 do_loadstore = true;
00731 break;
00732
00733 case lbu_op:
00734 case lhu_op:
00735 case swl_op:
00736 case swr_op:
00737 case lwl_op:
00738 case lwr_op:
00739 case scd_op:
00740 case lld_op:
00741 case lwu_op:
00742 case sdl_op:
00743 case sdr_op:
00744 case ldl_op:
00745 case ldr_op:
00746 sprintf(bufptr, "%s\t%s,", op_name[i.i_format.opcode],
00747 F_REGISTER_NAME(i.i_format.rt, regmask));
00748 do_loadstore = true;
00749 break;
00750
00751 case pref_op:
00752 sprintf(bufptr, "%s\t%d,", op_name[i.i_format.opcode],
00753 (int)i.i_format.rt);
00754 do_loadstore = true;
00755 break;
00756
00757 case cache_op:
00758 {
00759 ELF_ADDR code = i.c_format.c_op;
00760 ELF_ADDR caches = i.c_format.cache;
00761 char *operation;
00762 static char *cachename[4] = {"I", "D", "SI", "SD"};
00763 #ifdef _DIS_BUILD
00764 if (zt5flag) {
00765 cachename[2] = "RESERVED";
00766 cachename[3] = "S";
00767 }
00768 #endif
00769
00770 switch (code) {
00771 case 0:
00772 if (caches == 0 || caches == 2)
00773 operation = "Index_Invalidate";
00774 else
00775 operation = "Index_WriteBack_Invalidate";
00776 break;
00777 case 1:
00778 operation = "Index_Load_Tag";
00779 break;
00780 case 2:
00781 operation = "Index_Store_Tag";
00782 break;
00783 case 3:
00784 #ifdef _DIS_BUILD
00785 if (zt5flag) {
00786 operation = "Reserved";
00787 }
00788 else {
00789 #endif
00790 operation = "Create_Dirty_Exclusive";
00791 #ifdef _DIS_BUILD
00792 }
00793 #endif
00794 break;
00795 case 4:
00796 operation = "Hit_Invalidate";
00797 break;
00798 case 5:
00799 if (caches == 0)
00800 operation = "Fill";
00801 else
00802 operation = "Hit_WriteBack_Invalidate";
00803 break;
00804 case 6:
00805 #ifdef _DIS_BUILD
00806 if (zt5flag) {
00807 operation = "Index_Load_Data";
00808 }
00809 else {
00810 #endif
00811 operation = "Hit_WriteBack";
00812 #ifdef _DIS_BUILD
00813 }
00814 #endif
00815 break;
00816 case 7:
00817 #ifdef _DIS_BUILD
00818 if (zt5flag) {
00819 operation = "Index_Store_Data";
00820 }
00821 else {
00822 #endif
00823 operation = "Hit_Set_Virtual";
00824 #ifdef _DIS_BUILD
00825 }
00826 #endif
00827 break;
00828 }
00829 sprintf(bufptr, "%s\t%s[%s],", op_name[i.i_format.opcode],
00830 operation, cachename[caches]);
00831 do_loadstore = true;
00832 }
00833 break;
00834
00835 case ori_op:
00836 sprintf(bufptr, "%s\t%s,%s,%#x", op_name[i.u_format.opcode],
00837 F_REGISTER_NAME(i.u_format.rt, regmask),
00838 F_REGISTER_NAME(i.u_format.rs, regmask),
00839 i.u_format.uimmediate);
00840 break;
00841
00842 case xori_op:
00843 if (i.u_format.rs == ZERO) {
00844 sprintf(bufptr, "li\t\t%s,%d",
00845 F_REGISTER_NAME(i.u_format.rt, regmask),
00846 (int)i.u_format.uimmediate);
00847 break;
00848 }
00849
00850 case andi_op:
00851 sprintf(bufptr, "%s\t%s,%s,%#x", op_name[i.u_format.opcode],
00852 F_REGISTER_NAME(i.u_format.rt, regmask),
00853 F_REGISTER_NAME(i.u_format.rs, regmask),
00854 i.u_format.uimmediate);
00855 break;
00856 case lui_op:
00857 if (i.u_format.rs == ZERO)
00858 sprintf(bufptr, "%s\t%s,%#x", op_name[i.u_format.opcode],
00859 F_REGISTER_NAME(i.u_format.rt, regmask),
00860 i.u_format.uimmediate);
00861 else
00862 sprintf(bufptr, "%s\t%s,%s,%#x", op_name[i.u_format.opcode],
00863 F_REGISTER_NAME(i.u_format.rt, regmask),
00864 F_REGISTER_NAME(i.u_format.rs, regmask),
00865 i.u_format.uimmediate);
00866 #ifdef _DIS_BUILD
00867 if (Rel_data || Rela_data)
00868 return_value = 1;
00869 #endif
00870 break;
00871 case addi_op:
00872 case addiu_op:
00873 if (i.i_format.rs == ZERO) {
00874 short sign_extender = i.i_format.simmediate;
00875 #ifdef _DIS_BUILD
00876 sprintf(bufptr, "li\t");
00877 bufptr += 3;
00878 if (xflag) {
00879 if (sign_extender >= 0)
00880 sprintf(bufptr, "%s,%#x",
00881 F_REGISTER_NAME(i.i_format.rt, regmask),
00882 ((int)sign_extender));
00883 else
00884 sprintf(bufptr, "%s,-%#x",
00885 F_REGISTER_NAME(i.i_format.rt, regmask),
00886 -((int)sign_extender));
00887 }
00888 else {
00889 sprintf(bufptr, "%s,%d",
00890 F_REGISTER_NAME(i.i_format.rt, regmask),
00891 sign_extender);
00892 }
00893 #else
00894 sprintf(bufptr, "li\t%s,%d",
00895 F_REGISTER_NAME(i.i_format.rt, regmask),
00896 sign_extender);
00897 #endif
00898 break;
00899 }
00900
00901 default:
00902 {
00903 short sign_extender = i.i_format.simmediate;
00904 #ifdef _DIS_BUILD
00905 if (xflag) {
00906 if (sign_extender >= 0) {
00907 sprintf(bufptr, "%s\t%s,%s,%#x", op_name[i.i_format.opcode],
00908 F_REGISTER_NAME(i.i_format.rt, regmask),
00909 F_REGISTER_NAME(i.i_format.rs, regmask),
00910 ((int)sign_extender));
00911 }
00912 else {
00913 sprintf(bufptr, "%s\t%s,%s,-%#x", op_name[i.i_format.opcode],
00914 F_REGISTER_NAME(i.i_format.rt, regmask),
00915 F_REGISTER_NAME(i.i_format.rs, regmask),
00916 -((int)sign_extender));
00917 }
00918 }
00919 else {
00920 sprintf(bufptr, "%s\t%s,%s,%d", op_name[i.i_format.opcode],
00921 F_REGISTER_NAME(i.i_format.rt, regmask),
00922 F_REGISTER_NAME(i.i_format.rs, regmask),
00923 sign_extender);
00924 }
00925 #else
00926 sprintf(bufptr, "%s\t%s,%s,%d", op_name[i.i_format.opcode],
00927 F_REGISTER_NAME(i.i_format.rt, regmask),
00928 F_REGISTER_NAME(i.i_format.rs, regmask),
00929 sign_extender);
00930 #endif
00931 }
00932 #ifdef _DIS_BUILD
00933 if (Rel_data || Rela_data) return_value =1;
00934 #endif
00935 break;
00936
00937
00938 case cop0_op:
00939 switch (i.r_format.rs) {
00940 case bc_op:
00941 sprintf(bufptr, "bc0%s\t", bc_name[i.i_format.rt]);
00942 do_b_displacement = true;
00943 break;
00944 case dmtc_op:
00945 sprintf(bufptr, "d");
00946 bufptr++;
00947 case mtc_op:
00948 sprintf(bufptr, "mtc0\t%s,%s",
00949 F_REGISTER_NAME(i.r_format.rt, regmask),
00950 F_C0_REGISTER_NAME(i.r_format.rd));
00951 break;
00952 case dmfc_op:
00953 sprintf(bufptr, "d");
00954 bufptr++;
00955 case mfc_op:
00956 sprintf(bufptr, "mfc0\t%s,%s",
00957 F_REGISTER_NAME(i.r_format.rt, regmask),
00958 F_C0_REGISTER_NAME(i.r_format.rd));
00959 break;
00960 case cfc_op:
00961 sprintf(bufptr, "cfc0\t%s,$%d",
00962 F_REGISTER_NAME(i.r_format.rt, regmask),
00963 (int)i.r_format.rd);
00964 break;
00965 case ctc_op:
00966 sprintf(bufptr, "ctc0\t%s,$%d",
00967 F_REGISTER_NAME(i.r_format.rt, regmask),
00968 (int)i.r_format.rd);
00969 break;
00970 case copm_op:
00971 sprintf(bufptr, "c0\t%s", c0mfunc_name[i.r_format.func]);
00972 break;
00973 case cop_op:
00974 sprintf(bufptr, "c0\t%s", c0func_name[i.r_format.func]);
00975 break;
00976 default:
00977 sprintf(bufptr, "c0rs%d", (int)i.r_format.rs);
00978 break;
00979 }
00980 break;
00981
00982 case cop1_op:
00983 switch (i.r_format.rs) {
00984 case bc_op:
00985 if ( i.i_format.rt >> 2 )
00986 sprintf(bufptr, "bc1%s\t$fcc%d,", bc_name[i.i_format.rt & 3],
00987 (int)(i.r_format.rt >> 2));
00988 else
00989 sprintf(bufptr, "bc1%s\t", bc_name[i.i_format.rt]);
00990 do_b_displacement = true;
00991 break;
00992 case dmtc_op:
00993 sprintf(bufptr, "d");
00994 bufptr++;
00995 case mtc_op:
00996 sprintf(bufptr, "mtc1\t%s,%s",
00997 F_REGISTER_NAME(i.r_format.rt, regmask),
00998 F_FP_REGISTER_NAME(i.r_format.rd));
00999 break;
01000 case dmfc_op:
01001 sprintf(bufptr, "d");
01002 bufptr++;
01003 case mfc_op:
01004 sprintf(bufptr, "mfc1\t%s,%s",
01005 F_REGISTER_NAME(i.r_format.rt, regmask),
01006 F_FP_REGISTER_NAME(i.r_format.rd));
01007 break;
01008 case cfc_op:
01009 sprintf(bufptr, "cfc1\t%s,$%d",
01010 F_REGISTER_NAME(i.r_format.rt, regmask),
01011 (int)i.r_format.rd);
01012 break;
01013 case ctc_op:
01014 sprintf(bufptr, "ctc1\t%s,$%d",
01015 F_REGISTER_NAME(i.r_format.rt, regmask),
01016 (int)i.r_format.rd);
01017 break;
01018 case cop_op+s_fmt:
01019 case cop_op+d_fmt:
01020 case cop_op+e_fmt:
01021 case cop_op+w_fmt:
01022 case cop_op+q_fmt:
01023 case cop_op+l_fmt:
01024 case cop_op+ps_fmt:
01025 if (i.r_format.func == fmovc_op )
01026 sprintf(bufptr, "%s%c.%s\t",
01027 cop1func_name[i.r_format.func],
01028 (i.r_format.rt & 1) ? 't' : 'f',
01029 c1fmt_name[i.r_format.rs - cop_op]);
01030 else if ((i.r_format.rs == cop_op+ps_fmt) &&
01031 (i.r_format.func == fcvtspl_op ||
01032 i.r_format.func == fcvtspu_op))
01033 sprintf(bufptr, "%s%s\t",
01034 cop1func_name[i.r_format.func],
01035 (i.r_format.func == fcvtspu_op) ? "" : ".pl");
01036 else
01037 sprintf(bufptr, "%s.%s\t",
01038 cop1func_name[i.r_format.func],
01039 c1fmt_name[i.r_format.rs - cop_op]);
01040 bufptr += strlen(bufptr);
01041 switch (i.r_format.func) {
01042 case frecip_op:
01043 case frsqrt_op:
01044 case fsqrt_op:
01045 case fabs_op:
01046 case fmov_op:
01047 case fcvts_op:
01048 case fcvtspu_op:
01049 case fcvtd_op:
01050 case fcvte_op:
01051 case fcvtw_op:
01052 case fcvtl_op:
01053 case ftrunc_op:
01054 case ftruncl_op:
01055 case fround_op:
01056 case froundl_op:
01057 case ffloor_op:
01058 case ffloorl_op:
01059 case fceil_op:
01060 case fceill_op:
01061 case fneg_op:
01062 sprintf(bufptr, "%s,%s",
01063 F_FP_REGISTER_NAME(i.r_format.re),
01064 F_FP_REGISTER_NAME(i.r_format.rd));
01065 break;
01066 case fcmp_op+0x0:
01067 case fcmp_op+0x1:
01068 case fcmp_op+0x2:
01069 case fcmp_op+0x3:
01070 case fcmp_op+0x4:
01071 case fcmp_op+0x5:
01072 case fcmp_op+0x6:
01073 case fcmp_op+0x7:
01074 case fcmp_op+0x8:
01075 case fcmp_op+0x9:
01076 case fcmp_op+0xa:
01077 case fcmp_op+0xb:
01078 case fcmp_op+0xc:
01079 case fcmp_op+0xd:
01080 case fcmp_op+0xe:
01081 case fcmp_op+0xf:
01082 #ifdef _DIS_BUILD
01083
01084 if ( dis_arch == EF_MIPS_ARCH_4 || dis_arch == EF_MIPS_ARCH_5)
01085 #else
01086 if ( i.r_format.re >> 2 )
01087 #endif
01088 sprintf(bufptr, "$fcc%d,%s,%s",
01089 (int)(i.r_format.re >> 2),
01090 F_FP_REGISTER_NAME(i.r_format.rd),
01091 F_FP_REGISTER_NAME(i.r_format.rt));
01092 else
01093 sprintf(bufptr, "%s,%s",
01094 F_FP_REGISTER_NAME(i.r_format.rd),
01095 F_FP_REGISTER_NAME(i.r_format.rt));
01096 break;
01097 case fmovc_op:
01098 sprintf(bufptr, "%s,%s,$fcc%d",
01099 F_FP_REGISTER_NAME(i.r_format.re),
01100 F_FP_REGISTER_NAME(i.r_format.rd),
01101 (int)(i.r_format.rt >> 2));
01102 break;
01103 case fmovz_op:
01104 case fmovn_op:
01105 sprintf(bufptr, "%s,%s,%s",
01106 F_FP_REGISTER_NAME(i.r_format.re),
01107 F_FP_REGISTER_NAME(i.r_format.rd),
01108 F_REGISTER_NAME(i.r_format.rt, regmask));
01109 break;
01110 default:
01111
01112 sprintf(bufptr, "%s,%s,%s",
01113 F_FP_REGISTER_NAME(i.r_format.re),
01114 F_FP_REGISTER_NAME(i.r_format.rd),
01115 F_FP_REGISTER_NAME(i.r_format.rt));
01116 break;
01117 }
01118 break;
01119 }
01120 break;
01121
01122 case cop1x_op:
01123 {
01124 sprintf (bufptr, "%s\t", cop1xfunc_name[i.r_format.func]);
01125 bufptr += strlen(bufptr);
01126 switch (i.r_format.func) {
01127 case lwxc1_op:
01128 case ldxc1_op:
01129 case luxc1_op:
01130 sprintf(bufptr, "%s,%s(%s)",
01131 F_FP_REGISTER_NAME(i.ma_format.fd),
01132 F_REGISTER_NAME(i.ma_format.ft, regmask),
01133 F_REGISTER_NAME(i.ma_format.fr, regmask));
01134 break;
01135 case swxc1_op:
01136 case sdxc1_op:
01137 case suxc1_op:
01138 sprintf(bufptr, "%s,%s(%s)",
01139 F_FP_REGISTER_NAME(i.ma_format.fs),
01140 F_REGISTER_NAME(i.ma_format.ft, regmask),
01141 F_REGISTER_NAME(i.ma_format.fr, regmask));
01142 break;
01143 case pfetch_op:
01144 sprintf(bufptr, "%d,%s(%s)",
01145 (int)i.ma_format.fs,
01146 F_REGISTER_NAME(i.ma_format.ft, regmask),
01147 F_REGISTER_NAME(i.ma_format.fr, regmask));
01148 break;
01149 case madd_s_op:
01150 case madd_d_op:
01151 case madd_e_op:
01152 case madd_ps_op:
01153 case msub_s_op:
01154 case msub_d_op:
01155 case msub_e_op:
01156 case msub_ps_op:
01157 case nmadd_s_op:
01158 case nmadd_d_op:
01159 case nmadd_e_op:
01160 case nmadd_ps_op:
01161 case nmsub_s_op:
01162 case nmsub_d_op:
01163 case nmsub_e_op:
01164 case nmsub_ps_op:
01165 sprintf(bufptr, "%s,%s,%s,%s",
01166 F_FP_REGISTER_NAME(i.ma_format.fd),
01167 F_FP_REGISTER_NAME(i.ma_format.fr),
01168 F_FP_REGISTER_NAME(i.ma_format.fs),
01169 F_FP_REGISTER_NAME(i.ma_format.ft));
01170 break;
01171 case alnv_ps_op:
01172 sprintf(bufptr, "%s,%s,%s,%s",
01173 F_FP_REGISTER_NAME(i.r_format.re),
01174 F_FP_REGISTER_NAME(i.r_format.rd),
01175 F_FP_REGISTER_NAME(i.r_format.rt),
01176 F_REGISTER_NAME(i.r_format.rs,regmask));
01177 break;
01178 default:
01179 break;
01180 }
01181 }
01182 break;
01183
01184 case cop2_op:
01185 {
01186 #if 0
01187 The only form of cop2 ops supported are the SigProc Instructions.
01188 unsigned int which_cop = i.j_format.opcode - cop0_op;
01189
01190 switch (i.r_format.rs) {
01191 case bc_op:
01192 sprintf(bufptr, "bc%u%c\t", which_cop,
01193 bc_name[i.r_format.rt]);
01194 do_b_displacement = true;
01195 break;
01196 case dmtc_op:
01197 sprintf(bufptr, "d");
01198 bufptr++;
01199 case mtc_op:
01200 sprintf(bufptr, "mtc%u\t%s,$%d", which_cop,
01201 F_REGISTER_NAME(i.r_format.rt, regmask),
01202 i.r_format.rd);
01203 break;
01204 case dmfc_op:
01205 sprintf(bufptr, "d");
01206 bufptr++;
01207 case mfc_op:
01208 sprintf(bufptr, "mfc%u\t%s,$%d", which_cop,
01209 F_REGISTER_NAME(i.r_format.rt, regmask),
01210 i.r_format.rd);
01211 break;
01212 case cfc_op:
01213 sprintf(bufptr, "cfc%u\t%s,$%d", which_cop,
01214 F_REGISTER_NAME(i.r_format.rt, regmask),
01215 i.r_format.rd);
01216 break;
01217 case ctc_op:
01218 sprintf(bufptr, "ctc%u\t%s,$%d", which_cop,
01219 F_REGISTER_NAME(i.r_format.rt, regmask),
01220 i.r_format.rd);
01221 break;
01222 default:
01223 sprintf(bufptr, "c%u.%d\t%d", which_cop,i.r_format.rs, i.r_format.func);
01224 break;
01225 }
01226 #endif
01227 switch (i.v_format.func) {
01228 case valni_qh_op:
01229 case valni_ob_op:
01230 sprintf (bufptr, "%s\t", cop2func_name[i.v_format.func]);
01231 bufptr += strlen(bufptr);
01232 sprintf(bufptr, "%s,%s,%s,%d",
01233 F_Vec_REGISTER_NAME(i.v_format.vd),
01234 F_Vec_REGISTER_NAME(i.v_format.vs),
01235 F_Vec_REGISTER_NAME(i.v_format.vt),
01236 (int)i.r_format.rs);
01237 break;
01238 case valnv_qh_op:
01239 case valnv_ob_op:
01240 sprintf (bufptr, "%s\t", cop2func_name[i.v_format.func]);
01241 bufptr += strlen(bufptr);
01242 sprintf(bufptr, "%s,%s,%s,%s",
01243 F_Vec_REGISTER_NAME(i.v_format.vd),
01244 F_Vec_REGISTER_NAME(i.v_format.vs),
01245 F_Vec_REGISTER_NAME(i.v_format.vt),
01246 F_REGISTER_NAME(i.r_format.rs, regmask));
01247 break;
01248 case vshfl_op:
01249 sprintf (bufptr, "%s", cop2func_name[i.v_format.func]);
01250 bufptr += strlen(bufptr);
01251
01252
01253
01254 sprintf (bufptr,"%s\t",(i.v_format.fmt & qh_fmt) ? ".qh":".ob");
01255 bufptr += strlen(bufptr);
01256 sprintf(bufptr, "%s,%s,%s",
01257 F_Vec_REGISTER_NAME(i.v_format.vd),
01258 F_Vec_REGISTER_NAME(i.v_format.vs),
01259 F_Vec_REGISTER_NAME(i.v_format.vt));
01260 break;
01261 case vadd_op:
01262 case vsub_op:
01263 case vmul_op:
01264 case vsll_op:
01265 case vmin_op:
01266 case vmax_op:
01267 case vsrl_op:
01268 case vsra_op:
01269 case vand_op:
01270 case vor_op:
01271 case vnor_op:
01272 case vxor_op:
01273 case vmsgn_op:
01274 case vpickf_op:
01275 case vpickt_op:
01276 sprintf (bufptr, "%s", cop2func_name[i.v_format.func]);
01277 bufptr += strlen(bufptr);
01278
01279
01280
01281 sprintf (bufptr,"%s\t",(i.v_format.fmt & qh_fmt) ? ".qh":".ob");
01282 bufptr += strlen(bufptr);
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298 if ((i.v_format.sel >> 3) & 0x1)
01299 {
01300 if (i.v_format.sel == 10 ||
01301 i.v_format.sel == 11) {
01302
01303 sprintf(bufptr, "%s,%s,%s",
01304 F_Vec_REGISTER_NAME(i.v_format.vd),
01305 F_Vec_REGISTER_NAME(i.v_format.vs),
01306 F_Vec_REGISTER_NAME(i.v_format.vt));
01307 } else {
01308
01309 sprintf(bufptr, "%s,%s,%d",
01310 F_Vec_REGISTER_NAME(i.v_format.vd),
01311 F_Vec_REGISTER_NAME(i.v_format.vs),
01312 (int)i.v_format.vt);
01313 }
01314 } else {
01315
01316 sprintf(bufptr, "%s,%s,%s[%d]",
01317 F_Vec_REGISTER_NAME(i.v_format.vd),
01318 F_Vec_REGISTER_NAME(i.v_format.vs),
01319 F_Vec_REGISTER_NAME(i.v_format.vt),
01320 (int)(i.v_format.sel >>
01321 (i.v_format.fmt & 0x1)));
01322 }
01323 break;
01324 case vadda_op:
01325 case vmula_op:
01326 case vmuls_op:
01327 case vsuba_op:
01328 if (i.v_format.func == vmuls_op)
01329 sprintf (bufptr, "%s%s", cop2func_name[i.v_format.func],
01330 ((i.v_format.vd >> 4) & 0x1) ? "l" : "");
01331 else
01332 sprintf (bufptr, "%s%s", cop2func_name[i.v_format.func],
01333 ((i.v_format.vd >> 4) & 0x1) ? "l" : "a");
01334 bufptr += strlen(bufptr);
01335
01336
01337
01338 sprintf (bufptr,"%s\t",(i.v_format.fmt & qh_fmt) ? ".qh":".ob");
01339 bufptr += strlen(bufptr);
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355 if ((i.v_format.sel >> 3) & 0x1)
01356 {
01357 if (i.v_format.sel == 10 ||
01358 i.v_format.sel == 11) {
01359
01360 sprintf(bufptr, "%s,%s",
01361 F_Vec_REGISTER_NAME(i.v_format.vs),
01362 F_Vec_REGISTER_NAME(i.v_format.vt));
01363 } else {
01364
01365 sprintf(bufptr, "%s,%d",
01366 F_Vec_REGISTER_NAME(i.v_format.vs),
01367 (int)i.v_format.vt);
01368 }
01369 } else {
01370
01371 sprintf(bufptr, "%s,%s[%d]",
01372 F_Vec_REGISTER_NAME(i.v_format.vs),
01373 F_Vec_REGISTER_NAME(i.v_format.vt),
01374 (int)(i.v_format.sel >>
01375 (i.v_format.fmt & 0x1)));
01376 }
01377 break;
01378 case vrnd_zu_op:
01379 case vrnd_nau_op:
01380 case vrnd_neu_op:
01381 case vrnd_zs_op:
01382 case vrnd_nas_op:
01383 case vrnd_nes_op:
01384 sprintf (bufptr, "%s", cop2func_name[i.v_format.func]);
01385 bufptr += strlen(bufptr);
01386
01387
01388
01389 sprintf (bufptr,"%s\t",(i.v_format.fmt & qh_fmt) ? ".qh":".ob");
01390 bufptr += strlen(bufptr);
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406 if ((i.v_format.sel >> 3) & 0x1)
01407 {
01408 if (i.v_format.sel == 10 ||
01409 i.v_format.sel == 11) {
01410
01411 sprintf(bufptr, "%s,%s",
01412 F_Vec_REGISTER_NAME(i.v_format.vd),
01413 F_Vec_REGISTER_NAME(i.v_format.vt));
01414 } else {
01415
01416 sprintf(bufptr, "%s,%d",
01417 F_Vec_REGISTER_NAME(i.v_format.vd),
01418 (int)i.v_format.vt);
01419 }
01420 } else {
01421
01422 sprintf(bufptr, "%s,%s[%d]",
01423 F_Vec_REGISTER_NAME(i.v_format.vd),
01424 F_Vec_REGISTER_NAME(i.v_format.vt),
01425 (int)((i.v_format.sel >>
01426 (i.v_format.fmt & 0x1))));
01427 }
01428 break;
01429 case vrac_op:
01430 sprintf (bufptr, "%s", cop2func_name[i.v_format.func]);
01431 bufptr += strlen(bufptr);
01432
01433
01434
01435
01436
01437 sprintf (bufptr, "%s",(i.v_format.sel == 0) ? "l" :
01438 (i.v_format.sel == 4) ? "m" : "h");
01439 bufptr += strlen(bufptr);
01440
01441
01442
01443 sprintf (bufptr,"%s\t",(i.v_format.fmt & qh_fmt) ? ".qh":".ob");
01444 bufptr += strlen(bufptr);
01445 sprintf(bufptr, "%s", F_Vec_REGISTER_NAME(i.v_format.vd));
01446 break;
01447 case vwac_op:
01448 sprintf (bufptr, "%s", cop2func_name[i.v_format.func]);
01449 bufptr += strlen(bufptr);
01450
01451
01452
01453
01454 sprintf (bufptr, "%s",(i.v_format.sel == 0) ? "l" : "h");
01455 bufptr += strlen(bufptr);
01456
01457
01458
01459 sprintf (bufptr,"%s\t",(i.v_format.fmt & qh_fmt) ? ".qh":".ob");
01460 bufptr += strlen(bufptr);
01461 sprintf(bufptr, "%s", F_Vec_REGISTER_NAME(i.v_format.vs));
01462 if (i.v_format.sel == 0) {
01463 bufptr += strlen(bufptr);
01464 sprintf(bufptr, ",%s", F_Vec_REGISTER_NAME(i.v_format.vt));
01465 }
01466 break;
01467 case vcmp_lt_op:
01468 case vcmp_le_op:
01469 case vcmp_eq_op:
01470 sprintf (bufptr, "%s", cop2func_name[i.v_format.func]);
01471 bufptr += strlen(bufptr);
01472
01473
01474
01475 sprintf (bufptr,"%s\t",(i.v_format.fmt & qh_fmt) ? ".qh":".ob");
01476 bufptr += strlen(bufptr);
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492 if ((i.v_format.sel >> 3) & 0x1)
01493 {
01494 if (i.v_format.sel == 10 ||
01495 i.v_format.sel == 11) {
01496
01497 sprintf(bufptr, "%s,%s",
01498 F_Vec_REGISTER_NAME(i.v_format.vs),
01499 F_Vec_REGISTER_NAME(i.v_format.vt));
01500 } else {
01501
01502 sprintf(bufptr, "%s,%d",
01503 F_Vec_REGISTER_NAME(i.v_format.vs),
01504 (int)i.v_format.vt);
01505 }
01506 } else {
01507
01508 sprintf(bufptr, "%s,%s[%d]",
01509 F_Vec_REGISTER_NAME(i.v_format.vs),
01510 F_Vec_REGISTER_NAME(i.v_format.vt),
01511 (int)(i.v_format.sel >>
01512 (i.v_format.fmt & 0x1)));
01513 }
01514 break;
01515 default:
01516 break;
01517 }
01518 }
01519 break;
01520
01521 }
01522
01523
01524
01525 if (do_loadstore) {
01526 short sign_extender = i.i_format.simmediate;
01527 *symbol_value = sign_extender;
01528 *ls_register = i.i_format.rs;
01529 bufptr += strlen(bufptr);
01530 #ifdef _DIS_BUILD
01531 if (xflag) {
01532 if (sign_extender >= 0)
01533 sprintf(bufptr, "%#x(%s)",(int)sign_extender,F_REGISTER_NAME(i.i_format.rs, regmask));
01534 else
01535 sprintf(bufptr, "-%#x(%s)",-((int)sign_extender),F_REGISTER_NAME(i.i_format.rs, regmask));
01536 }
01537 else
01538 #endif
01539
01540 sprintf(bufptr, "%d(%s)",(int)sign_extender,F_REGISTER_NAME(i.i_format.rs, regmask));
01541 #ifdef _DIS_BUILD
01542 if (Rel_data || Rela_data)
01543 return_value = 1;
01544 else
01545 return_value = -1;
01546 #else
01547 return_value = -1;
01548 #endif
01549 }
01550 else if (do_b_displacement) {
01551 short sign_extender = i.i_format.simmediate;
01552 bufptr += strlen(bufptr);
01553 #ifdef _DIS_BUILD
01554 if (is_64_bit)
01555 {
01556 address = (ELF_ADDR)loc_val64;
01557 sprintf(bufptr, "%#llx",
01558 (unsigned long long)(address+4+(sign_extender<<2)));
01559 } else {
01560 address = loc_val32;
01561 sprintf(bufptr, "%#x",
01562 (unsigned)(address+4+(sign_extender<<2)));
01563 }
01564 #else
01565
01566 sprintf(bufptr, "%#llx",
01567 (unsigned long long)(address+4+(sign_extender<<2)));
01568
01569 #endif
01570 return_value = 2;
01571 }
01572 return return_value;
01573 #else
01574 bufptr += dis_asm(bufptr, iword);
01575
01576
01577
01578
01579
01580
01581 return 0;
01582 #endif
01583 }
01584
01585
01586
01587 void
01588 F_DIS_REGS ( char *buffer,unsigned regmask,ELF_ADDR reg_values[])
01589 {
01590 boolean first = true;
01591 ELF_ADDR i;
01592
01593 buffer += strlen(buffer);
01594 for (i = 0; regmask; i++, regmask >>= 1) {
01595 if (regmask & 1) {
01596 #ifdef _DIS_BUILD
01597 sprintf(buffer, "%s%s=%#llx", first ? "\t<" : ",",
01598 save.reg_names[i],
01599 (unsigned long long)reg_values[i]);
01600 #else
01601
01602 sprintf(buffer, "%s%s="
01603 HEXREG
01604 , first ? "\t<" : ",",
01605 save.reg_names[i], reg_values[i]);
01606 #endif
01607 buffer += strlen(buffer);
01608 first = false;
01609 }
01610 }
01611 if (!first)
01612 strcat(buffer, ">");
01613 }
01614
01615
01616 #include <errno.h>
01617 extern int errno;
01618
01619
01620
01621
01622
01623 int
01624 F_DISASSEMBLER (ELF_ADDR iadr,int regstyle,char *(*get_symname)(unsigned),int (*get_regvalue)(unsigned),long (*get_bytes)(void),void (*print_header)(unsigned,unsigned))
01625 {
01626 ELF_ADDR old_iadr = iadr;
01627
01628 if (!get_bytes) {
01629 errno = EINVAL;
01630 return -1;
01631 }
01632
01633
01634 F_DIS_INIT("", "", regstyle ? HARDWARE_NAMES : COMPILER_NAMES,
01635 ! (int) get_symname);
01636
01637 for (; ; iadr += 4) {
01638 int which;
01639 Elf32_Addr instr;
01640 Elf32_Addr regmask, ls_register;
01641 ELF_ADDR symbol_value;
01642 char buffer[1024], *symname;
01643
01644 instr = (Elf32_Addr) get_bytes();
01645 if (print_header)
01646 print_header(iadr, instr);
01647 which = F_DISASM(buffer,iadr,instr,®mask,&symbol_value,&ls_register);
01648
01649
01650 if ((which == 1) && get_symname)
01651 if (symname = get_symname(symbol_value))
01652 strcat(buffer, symname);
01653 else
01654 sprintf(buffer + strlen(buffer), "%#llx",
01655 (unsigned long long)symbol_value);
01656
01657
01658 else if ((which < 0) && get_regvalue)
01659 sprintf(buffer + strlen(buffer),
01660 " <0x%llx>",
01661 (unsigned long long)(get_regvalue(ls_register)
01662 + symbol_value));
01663
01664
01665 if (regmask && get_regvalue) {
01666 ELF_ADDR reg_values[32];
01667 ELF_ADDR reg_cnt, regtemp;
01668
01669 for (reg_cnt = 0, regtemp = regmask; regtemp;
01670 reg_cnt++, regtemp >>= 1)
01671 if (regtemp & 1)
01672 reg_values[reg_cnt] = get_regvalue(reg_cnt);
01673 F_DIS_REGS(buffer + strlen(buffer), regmask, reg_values);
01674 }
01675
01676 puts(buffer);
01677
01678
01679 if (which <= 0) {
01680 return (int)(iadr - old_iadr + 4);
01681 }
01682 }
01683 }