00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "sysdep.h"
00020 #include "dis-asm.h"
00021 #include "opcode/dlx.h"
00022
00023 #define R_ERROR 0x1
00024 #define R_TYPE 0x2
00025 #define ILD_TYPE 0x3
00026 #define IST_TYPE 0x4
00027 #define IAL_TYPE 0x5
00028 #define IBR_TYPE 0x6
00029 #define IJ_TYPE 0x7
00030 #define IJR_TYPE 0x8
00031 #define NIL 0x9
00032
00033 #define OPC(x) ((x >> 26) & 0x3F)
00034 #define FUNC(x) (x & 0x7FF)
00035
00036 unsigned char opc, rs1, rs2, rd;
00037 unsigned long imm26, imm16, func, current_insn_addr;
00038
00039 static unsigned char dlx_get_opcode PARAMS ((unsigned long));
00040 static unsigned char dlx_get_rs1 PARAMS ((unsigned long));
00041 static unsigned char dlx_get_rs2 PARAMS ((unsigned long));
00042 static unsigned char dlx_get_rdR PARAMS ((unsigned long));
00043 static unsigned long dlx_get_func PARAMS ((unsigned long));
00044 static unsigned long dlx_get_imm16 PARAMS ((unsigned long));
00045 static unsigned long dlx_get_imm26 PARAMS ((unsigned long));
00046 static void operand_deliminator PARAMS ((struct disassemble_info *, char *));
00047 static unsigned char dlx_r_type PARAMS ((struct disassemble_info *));
00048 static unsigned char dlx_load_type PARAMS ((struct disassemble_info *));
00049 static unsigned char dlx_store_type PARAMS ((struct disassemble_info *));
00050 static unsigned char dlx_aluI_type PARAMS ((struct disassemble_info *));
00051 static unsigned char dlx_br_type PARAMS ((struct disassemble_info *));
00052 static unsigned char dlx_jmp_type PARAMS ((struct disassemble_info *));
00053 static unsigned char dlx_jr_type PARAMS ((struct disassemble_info *));
00054
00055
00056
00057
00058 static unsigned char
00059 dlx_get_opcode (opcode)
00060 unsigned long opcode;
00061 {
00062 return (unsigned char) ((opcode >> 26) & 0x3F);
00063 }
00064
00065 static unsigned char
00066 dlx_get_rs1 (opcode)
00067 unsigned long opcode;
00068 {
00069 return (unsigned char) ((opcode >> 21) & 0x1F);
00070 }
00071
00072 static unsigned char
00073 dlx_get_rs2 (opcode)
00074 unsigned long opcode;
00075 {
00076 return (unsigned char) ((opcode >> 16) & 0x1F);
00077 }
00078
00079 static unsigned char
00080 dlx_get_rdR (opcode)
00081 unsigned long opcode;
00082 {
00083 return (unsigned char) ((opcode >> 11) & 0x1F);
00084 }
00085
00086 static unsigned long
00087 dlx_get_func (opcode)
00088 unsigned long opcode;
00089 {
00090 return (unsigned char) (opcode & 0x7FF);
00091 }
00092
00093 static unsigned long
00094 dlx_get_imm16 (opcode)
00095 unsigned long opcode;
00096 {
00097 return (unsigned long) (opcode & 0xFFFF);
00098 }
00099
00100 static unsigned long
00101 dlx_get_imm26 (opcode)
00102 unsigned long opcode;
00103 {
00104 return (unsigned long) (opcode & 0x03FFFFFF);
00105 }
00106
00107
00108 static void
00109 operand_deliminator (info, ptr)
00110 struct disassemble_info *info;
00111 char *ptr;
00112 {
00113 int difft = 8 - (int) strlen (ptr);
00114
00115 while (difft > 0)
00116 {
00117 (*info->fprintf_func) (info->stream, "%c", ' ');
00118 difft -= 1;
00119 }
00120 }
00121
00122
00123 static unsigned char
00124 dlx_r_type (info)
00125 struct disassemble_info *info;
00126 {
00127 unsigned char r_opc[] = { OPC(ALUOP) };
00128 int r_opc_num = (sizeof r_opc) / (sizeof (char));
00129 struct _r_opcode
00130 {
00131 unsigned long func;
00132 char *name;
00133 }
00134 dlx_r_opcode[] =
00135 {
00136 { NOPF, "nop" },
00137 { ADDF, "add" },
00138 { ADDUF, "addu" },
00139 { SUBF, "sub" },
00140 { SUBUF, "subu" },
00141 { MULTF, "mult" },
00142 { MULTUF, "multu" },
00143 { DIVF, "div" },
00144 { DIVUF, "divu" },
00145 { ANDF, "and" },
00146 { ORF, "or" },
00147 { XORF, "xor" },
00148 { SLLF, "sll" },
00149 { SRAF, "sra" },
00150 { SRLF, "srl" },
00151 { SEQF, "seq" },
00152 { SNEF, "sne" },
00153 { SLTF, "slt" },
00154 { SGTF, "sgt" },
00155 { SLEF, "sle" },
00156 { SGEF, "sge" },
00157 { SEQUF, "sequ" },
00158 { SNEUF, "sneu" },
00159 { SLTUF, "sltu" },
00160 { SGTUF, "sgtu" },
00161 { SLEUF, "sleu" },
00162 { SGEUF, "sgeu" },
00163 { MVTSF, "mvts" },
00164 { MVFSF, "mvfs" },
00165 { BSWAPF, "bswap" },
00166 { LUTF, "lut" }
00167 };
00168 int dlx_r_opcode_num = (sizeof dlx_r_opcode) / (sizeof dlx_r_opcode[0]);
00169 int idx;
00170
00171 for (idx = 0; idx < r_opc_num; idx++)
00172 {
00173 if (r_opc[idx] != opc)
00174 continue;
00175 else
00176 break;
00177 }
00178
00179 if (idx == r_opc_num)
00180 return NIL;
00181
00182 for (idx = 0 ; idx < dlx_r_opcode_num; idx++)
00183 if (dlx_r_opcode[idx].func == func)
00184 {
00185 (*info->fprintf_func) (info->stream, "%s", dlx_r_opcode[idx].name);
00186
00187 if (func != NOPF)
00188 {
00189
00190 operand_deliminator (info, dlx_r_opcode[idx].name);
00191 (*info->fprintf_func) (info->stream, "r%d,", (int)rd);
00192 (*info->fprintf_func) (info->stream, "r%d", (int)rs1);
00193 if (func != MVTSF && func != MVFSF)
00194 (*info->fprintf_func) (info->stream, ",r%d", (int)rs2);
00195 }
00196 return (unsigned char) R_TYPE;
00197 }
00198
00199 return (unsigned char) R_ERROR;
00200 }
00201
00202
00203
00204 static unsigned char
00205 dlx_load_type (info)
00206 struct disassemble_info* info;
00207 {
00208 struct _load_opcode
00209 {
00210 unsigned long opcode;
00211 char *name;
00212 }
00213 dlx_load_opcode[] =
00214 {
00215 { OPC(LHIOP), "lhi" },
00216 { OPC(LBOP), "lb" },
00217 { OPC(LBUOP), "lbu" },
00218 { OPC(LSBUOP),"ldstbu"},
00219 { OPC(LHOP), "lh" },
00220 { OPC(LHUOP), "lhu" },
00221 { OPC(LSHUOP),"ldsthu"},
00222 { OPC(LWOP), "lw" },
00223 { OPC(LSWOP), "ldstw" }
00224 };
00225 int dlx_load_opcode_num =
00226 (sizeof dlx_load_opcode) / (sizeof dlx_load_opcode[0]);
00227 int idx;
00228
00229 for (idx = 0 ; idx < dlx_load_opcode_num; idx++)
00230 if (dlx_load_opcode[idx].opcode == opc)
00231 {
00232 if (opc == OPC (LHIOP))
00233 {
00234 (*info->fprintf_func) (info->stream, "%s", dlx_load_opcode[idx].name);
00235 operand_deliminator (info, dlx_load_opcode[idx].name);
00236 (*info->fprintf_func) (info->stream, "r%d,", (int)rs2);
00237 (*info->fprintf_func) (info->stream, "0x%04x", (int)imm16);
00238 }
00239 else
00240 {
00241 (*info->fprintf_func) (info->stream, "%s", dlx_load_opcode[idx].name);
00242 operand_deliminator (info, dlx_load_opcode[idx].name);
00243 (*info->fprintf_func) (info->stream, "r%d,", (int)rs2);
00244 (*info->fprintf_func) (info->stream, "0x%04x[r%d]", (int)imm16, (int)rs1);
00245 }
00246
00247 return (unsigned char) ILD_TYPE;
00248 }
00249
00250 return (unsigned char) NIL;
00251 }
00252
00253
00254
00255 static unsigned char
00256 dlx_store_type (info)
00257 struct disassemble_info* info;
00258 {
00259 struct _store_opcode
00260 {
00261 unsigned long opcode;
00262 char *name;
00263 }
00264 dlx_store_opcode[] =
00265 {
00266 { OPC(SBOP), "sb" },
00267 { OPC(SHOP), "sh" },
00268 { OPC(SWOP), "sw" },
00269 };
00270 int dlx_store_opcode_num =
00271 (sizeof dlx_store_opcode) / (sizeof dlx_store_opcode[0]);
00272 int idx;
00273
00274 for (idx = 0 ; idx < dlx_store_opcode_num; idx++)
00275 if (dlx_store_opcode[idx].opcode == opc)
00276 {
00277 (*info->fprintf_func) (info->stream, "%s", dlx_store_opcode[idx].name);
00278 operand_deliminator (info, dlx_store_opcode[idx].name);
00279 (*info->fprintf_func) (info->stream, "0x%04x[r%d],", (int)imm16, (int)rs1);
00280 (*info->fprintf_func) (info->stream, "r%d", (int)rs2);
00281 return (unsigned char) IST_TYPE;
00282 }
00283
00284 return (unsigned char) NIL;
00285 }
00286
00287
00288
00289 static unsigned char
00290 dlx_aluI_type (info)
00291 struct disassemble_info* info;
00292 {
00293 struct _aluI_opcode
00294 {
00295 unsigned long opcode;
00296 char *name;
00297 }
00298 dlx_aluI_opcode[] =
00299 {
00300 { OPC(ADDIOP), "addi" },
00301 { OPC(ADDUIOP), "addui" },
00302 { OPC(SUBIOP), "subi" },
00303 { OPC(SUBUIOP), "subui" },
00304 { OPC(ANDIOP), "andi" },
00305 { OPC(ORIOP), "ori" },
00306 { OPC(XORIOP), "xori" },
00307 { OPC(SLLIOP), "slli" },
00308 { OPC(SRAIOP), "srai" },
00309 { OPC(SRLIOP), "srli" },
00310 { OPC(SEQIOP), "seqi" },
00311 { OPC(SNEIOP), "snei" },
00312 { OPC(SLTIOP), "slti" },
00313 { OPC(SGTIOP), "sgti" },
00314 { OPC(SLEIOP), "slei" },
00315 { OPC(SGEIOP), "sgei" },
00316 { OPC(SEQUIOP), "sequi" },
00317 { OPC(SNEUIOP), "sneui" },
00318 { OPC(SLTUIOP), "sltui" },
00319 { OPC(SGTUIOP), "sgtui" },
00320 { OPC(SLEUIOP), "sleui" },
00321 { OPC(SGEUIOP), "sgeui" },
00322 #if 0
00323 { OPC(MVTSOP), "mvts" },
00324 { OPC(MVFSOP), "mvfs" },
00325 #endif
00326 };
00327 int dlx_aluI_opcode_num =
00328 (sizeof dlx_aluI_opcode) / (sizeof dlx_aluI_opcode[0]);
00329 int idx;
00330
00331 for (idx = 0 ; idx < dlx_aluI_opcode_num; idx++)
00332 if (dlx_aluI_opcode[idx].opcode == opc)
00333 {
00334 (*info->fprintf_func) (info->stream, "%s", dlx_aluI_opcode[idx].name);
00335 operand_deliminator (info, dlx_aluI_opcode[idx].name);
00336 (*info->fprintf_func) (info->stream, "r%d,", (int)rs2);
00337 (*info->fprintf_func) (info->stream, "r%d,", (int)rs1);
00338 (*info->fprintf_func) (info->stream, "0x%04x", (int)imm16);
00339
00340 return (unsigned char) IAL_TYPE;
00341 }
00342
00343 return (unsigned char) NIL;
00344 }
00345
00346
00347
00348 static unsigned char
00349 dlx_br_type (info)
00350 struct disassemble_info* info;
00351 {
00352 struct _br_opcode
00353 {
00354 unsigned long opcode;
00355 char *name;
00356 }
00357 dlx_br_opcode[] =
00358 {
00359 { OPC(BEQOP), "beqz" },
00360 { OPC(BNEOP), "bnez" }
00361 };
00362 int dlx_br_opcode_num =
00363 (sizeof dlx_br_opcode) / (sizeof dlx_br_opcode[0]);
00364 int idx;
00365
00366 for (idx = 0 ; idx < dlx_br_opcode_num; idx++)
00367 if (dlx_br_opcode[idx].opcode == opc)
00368 {
00369 if (imm16 & 0x00008000)
00370 imm16 |= 0xFFFF0000;
00371
00372 imm16 += (current_insn_addr + 4);
00373 (*info->fprintf_func) (info->stream, "%s", dlx_br_opcode[idx].name);
00374 operand_deliminator (info, dlx_br_opcode[idx].name);
00375 (*info->fprintf_func) (info->stream, "r%d,", (int)rs1);
00376 (*info->fprintf_func) (info->stream, "0x%08x", (int)imm16);
00377
00378 return (unsigned char) IBR_TYPE;
00379 }
00380
00381 return (unsigned char) NIL;
00382 }
00383
00384
00385
00386 static unsigned char
00387 dlx_jmp_type (info)
00388 struct disassemble_info* info;
00389 {
00390 struct _jmp_opcode
00391 {
00392 unsigned long opcode;
00393 char *name;
00394 }
00395 dlx_jmp_opcode[] =
00396 {
00397 { OPC(JOP), "j" },
00398 { OPC(JALOP), "jal" },
00399 { OPC(BREAKOP), "break" },
00400 { OPC(TRAPOP), "trap" },
00401 { OPC(RFEOP), "rfe" }
00402 };
00403 int dlx_jmp_opcode_num =
00404 (sizeof dlx_jmp_opcode) / (sizeof dlx_jmp_opcode[0]);
00405 int idx;
00406
00407 for (idx = 0 ; idx < dlx_jmp_opcode_num; idx++)
00408 if (dlx_jmp_opcode[idx].opcode == opc)
00409 {
00410 if (imm26 & 0x02000000)
00411 imm26 |= 0xFC000000;
00412
00413 imm26 += (current_insn_addr + 4);
00414
00415 (*info->fprintf_func) (info->stream, "%s", dlx_jmp_opcode[idx].name);
00416 operand_deliminator (info, dlx_jmp_opcode[idx].name);
00417 (*info->fprintf_func) (info->stream, "0x%08x", (int)imm26);
00418
00419 return (unsigned char) IJ_TYPE;
00420 }
00421
00422 return (unsigned char) NIL;
00423 }
00424
00425
00426
00427 static unsigned char
00428 dlx_jr_type (info)
00429 struct disassemble_info* info;
00430 {
00431 struct _jr_opcode
00432 {
00433 unsigned long opcode;
00434 char *name;
00435 }
00436 dlx_jr_opcode[] = {
00437 { OPC(JROP), "jr" },
00438 { OPC(JALROP), "jalr" }
00439 };
00440 int dlx_jr_opcode_num =
00441 (sizeof dlx_jr_opcode) / (sizeof dlx_jr_opcode[0]);
00442 int idx;
00443
00444 for (idx = 0 ; idx < dlx_jr_opcode_num; idx++)
00445 if (dlx_jr_opcode[idx].opcode == opc)
00446 {
00447 (*info->fprintf_func) (info->stream, "%s", dlx_jr_opcode[idx].name);
00448 operand_deliminator (info, dlx_jr_opcode[idx].name);
00449 (*info->fprintf_func) (info->stream, "r%d", (int)rs1);
00450 return (unsigned char) IJR_TYPE;
00451 }
00452
00453 return (unsigned char) NIL;
00454 }
00455
00456 typedef unsigned char (* dlx_insn) PARAMS ((struct disassemble_info *));
00457
00458
00459
00460 int
00461 print_insn_dlx (memaddr, info)
00462 bfd_vma memaddr;
00463 struct disassemble_info* info;
00464 {
00465 bfd_byte buffer[4];
00466 int insn_idx;
00467 unsigned long insn_word;
00468 unsigned char rtn_code;
00469 unsigned long dlx_insn_type[] =
00470 {
00471 (unsigned long) dlx_r_type,
00472 (unsigned long) dlx_load_type,
00473 (unsigned long) dlx_store_type,
00474 (unsigned long) dlx_aluI_type,
00475 (unsigned long) dlx_br_type,
00476 (unsigned long) dlx_jmp_type,
00477 (unsigned long) dlx_jr_type,
00478 (unsigned long) NULL
00479 };
00480 int dlx_insn_type_num = ((sizeof dlx_insn_type) / (sizeof (unsigned long))) - 1;
00481 int status =
00482 (*info->read_memory_func) (memaddr, (bfd_byte *) &buffer[0], 4, info);
00483
00484 if (status != 0)
00485 {
00486 (*info->memory_error_func) (status, memaddr, info);
00487 return -1;
00488 }
00489
00490
00491 insn_word = bfd_getb32 (buffer);
00492 opc = dlx_get_opcode (insn_word);
00493 rs1 = dlx_get_rs1 (insn_word);
00494 rs2 = dlx_get_rs2 (insn_word);
00495 rd = dlx_get_rdR (insn_word);
00496 func = dlx_get_func (insn_word);
00497 imm16= dlx_get_imm16 (insn_word);
00498 imm26= dlx_get_imm26 (insn_word);
00499
00500 #if 0
00501 printf ("print_insn_big_dlx: opc = 0x%02x\n"
00502 " rs1 = 0x%02x\n"
00503 " rs2 = 0x%02x\n"
00504 " rd = 0x%02x\n"
00505 " func = 0x%08x\n"
00506 " imm16 = 0x%08x\n"
00507 " imm26 = 0x%08x\n",
00508 opc, rs1, rs2, rd, func, imm16, imm26);
00509 #endif
00510
00511
00512 rtn_code = 0;
00513 current_insn_addr = (unsigned long) memaddr;
00514
00515 for (insn_idx = 0; dlx_insn_type[insn_idx] != 0x0; insn_idx++)
00516 switch (((dlx_insn) (dlx_insn_type[insn_idx])) (info))
00517 {
00518
00519 case R_TYPE:
00520 case ILD_TYPE:
00521 case IST_TYPE:
00522 case IAL_TYPE:
00523 case IBR_TYPE:
00524 case IJ_TYPE:
00525 case IJR_TYPE:
00526 return 4;
00527
00528
00529 default:
00530 case NIL:
00531 continue;
00532
00533
00534
00535 case R_ERROR:
00536 return -1;
00537 }
00538
00539 if (insn_idx == dlx_insn_type_num)
00540
00541 (*info->fprintf_func) (info->stream, "<%s>", "Unrecognized Opcode");
00542
00543 return 4;
00544 }