1 /* Altera Nios II disassemble routines 2 Copyright (C) 2012, 2013 Free Software Foundation, Inc. 3 Contributed by Nigel Gray (ngray@altera.com). 4 Contributed by Mentor Graphics, Inc. 5 6 This file is part of the GNU opcodes library. 7 8 This library is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3, or (at your option) 11 any later version. 12 13 It is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 16 License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this file; see the file COPYING. If not, write to the 20 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, 21 MA 02110-1301, USA. */ 22 23 #include "sysdep.h" 24 #include "dis-asm.h" 25 #include "opcode/nios2.h" 26 #include "libiberty.h" 27 #include <string.h> 28 #include <assert.h> 29 30 /* No symbol table is available when this code runs out in an embedded 31 system as when it is used for disassembler support in a monitor. */ 32 #if !defined(EMBEDDED_ENV) 33 #define SYMTAB_AVAILABLE 1 34 #include "elf-bfd.h" 35 #include "elf/nios2.h" 36 #endif 37 38 /* Length of Nios II instruction in bytes. */ 39 #define INSNLEN 4 40 41 /* Data structures used by the opcode hash table. */ 42 typedef struct _nios2_opcode_hash 43 { 44 const struct nios2_opcode *opcode; 45 struct _nios2_opcode_hash *next; 46 } nios2_opcode_hash; 47 48 static bfd_boolean nios2_hash_init = 0; 49 static nios2_opcode_hash *nios2_hash[(OP_MASK_OP) + 1]; 50 51 /* Separate hash table for pseudo-ops. */ 52 static nios2_opcode_hash *nios2_ps_hash[(OP_MASK_OP) + 1]; 53 54 /* Function to initialize the opcode hash table. */ 55 static void 56 nios2_init_opcode_hash (void) 57 { 58 unsigned int i; 59 register const struct nios2_opcode *op; 60 61 for (i = 0; i <= OP_MASK_OP; ++i) 62 nios2_hash[0] = NULL; 63 for (i = 0; i <= OP_MASK_OP; i++) 64 for (op = nios2_opcodes; op < &nios2_opcodes[NUMOPCODES]; op++) 65 { 66 nios2_opcode_hash *new_hash; 67 nios2_opcode_hash **bucket = NULL; 68 69 if ((op->pinfo & NIOS2_INSN_MACRO) == NIOS2_INSN_MACRO) 70 { 71 if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP) 72 && (op->pinfo & (NIOS2_INSN_MACRO_MOV | NIOS2_INSN_MACRO_MOVI) 73 & 0x7fffffff)) 74 bucket = &(nios2_ps_hash[i]); 75 } 76 else if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP)) 77 bucket = &(nios2_hash[i]); 78 79 if (bucket) 80 { 81 new_hash = 82 (nios2_opcode_hash *) malloc (sizeof (nios2_opcode_hash)); 83 if (new_hash == NULL) 84 { 85 fprintf (stderr, 86 "error allocating memory...broken disassembler\n"); 87 abort (); 88 } 89 new_hash->opcode = op; 90 new_hash->next = NULL; 91 while (*bucket) 92 bucket = &((*bucket)->next); 93 *bucket = new_hash; 94 } 95 } 96 nios2_hash_init = 1; 97 #ifdef DEBUG_HASHTABLE 98 for (i = 0; i <= OP_MASK_OP; ++i) 99 { 100 nios2_opcode_hash *tmp_hash = nios2_hash[i]; 101 printf ("index: 0x%02X ops: ", i); 102 while (tmp_hash != NULL) 103 { 104 printf ("%s ", tmp_hash->opcode->name); 105 tmp_hash = tmp_hash->next; 106 } 107 printf ("\n"); 108 } 109 110 for (i = 0; i <= OP_MASK_OP; ++i) 111 { 112 nios2_opcode_hash *tmp_hash = nios2_ps_hash[i]; 113 printf ("index: 0x%02X ops: ", i); 114 while (tmp_hash != NULL) 115 { 116 printf ("%s ", tmp_hash->opcode->name); 117 tmp_hash = tmp_hash->next; 118 } 119 printf ("\n"); 120 } 121 #endif /* DEBUG_HASHTABLE */ 122 } 123 124 /* Return a pointer to an nios2_opcode struct for a given instruction 125 opcode, or NULL if there is an error. */ 126 const struct nios2_opcode * 127 nios2_find_opcode_hash (unsigned long opcode) 128 { 129 nios2_opcode_hash *entry; 130 131 /* Build a hash table to shorten the search time. */ 132 if (!nios2_hash_init) 133 nios2_init_opcode_hash (); 134 135 /* First look in the pseudo-op hashtable. */ 136 for (entry = nios2_ps_hash[(opcode >> OP_SH_OP) & OP_MASK_OP]; 137 entry; entry = entry->next) 138 if (entry->opcode->match == (opcode & entry->opcode->mask)) 139 return entry->opcode; 140 141 /* Otherwise look in the main hashtable. */ 142 for (entry = nios2_hash[(opcode >> OP_SH_OP) & OP_MASK_OP]; 143 entry; entry = entry->next) 144 if (entry->opcode->match == (opcode & entry->opcode->mask)) 145 return entry->opcode; 146 147 return NULL; 148 } 149 150 /* There are 32 regular registers, 32 coprocessor registers, 151 and 32 control registers. */ 152 #define NUMREGNAMES 32 153 154 /* Return a pointer to the base of the coprocessor register name array. */ 155 static struct nios2_reg * 156 nios2_coprocessor_regs (void) 157 { 158 static struct nios2_reg *cached = NULL; 159 160 if (!cached) 161 { 162 int i; 163 for (i = NUMREGNAMES; i < nios2_num_regs; i++) 164 if (!strcmp (nios2_regs[i].name, "c0")) 165 { 166 cached = nios2_regs + i; 167 break; 168 } 169 assert (cached); 170 } 171 return cached; 172 } 173 174 /* Return a pointer to the base of the control register name array. */ 175 static struct nios2_reg * 176 nios2_control_regs (void) 177 { 178 static struct nios2_reg *cached = NULL; 179 180 if (!cached) 181 { 182 int i; 183 for (i = NUMREGNAMES; i < nios2_num_regs; i++) 184 if (!strcmp (nios2_regs[i].name, "status")) 185 { 186 cached = nios2_regs + i; 187 break; 188 } 189 assert (cached); 190 } 191 return cached; 192 } 193 194 /* The function nios2_print_insn_arg uses the character pointed 195 to by ARGPTR to determine how it print the next token or separator 196 character in the arguments to an instruction. */ 197 static int 198 nios2_print_insn_arg (const char *argptr, 199 unsigned long opcode, bfd_vma address, 200 disassemble_info *info) 201 { 202 unsigned long i = 0; 203 struct nios2_reg *reg_base; 204 205 switch (*argptr) 206 { 207 case ',': 208 case '(': 209 case ')': 210 (*info->fprintf_func) (info->stream, "%c", *argptr); 211 break; 212 case 'd': 213 i = GET_INSN_FIELD (RRD, opcode); 214 215 if (GET_INSN_FIELD (OP, opcode) == OP_MATCH_CUSTOM 216 && GET_INSN_FIELD (CUSTOM_C, opcode) == 0) 217 reg_base = nios2_coprocessor_regs (); 218 else 219 reg_base = nios2_regs; 220 221 if (i < NUMREGNAMES) 222 (*info->fprintf_func) (info->stream, "%s", reg_base[i].name); 223 else 224 (*info->fprintf_func) (info->stream, "unknown"); 225 break; 226 case 's': 227 i = GET_INSN_FIELD (RRS, opcode); 228 229 if (GET_INSN_FIELD (OP, opcode) == OP_MATCH_CUSTOM 230 && GET_INSN_FIELD (CUSTOM_A, opcode) == 0) 231 reg_base = nios2_coprocessor_regs (); 232 else 233 reg_base = nios2_regs; 234 235 if (i < NUMREGNAMES) 236 (*info->fprintf_func) (info->stream, "%s", reg_base[i].name); 237 else 238 (*info->fprintf_func) (info->stream, "unknown"); 239 break; 240 case 't': 241 i = GET_INSN_FIELD (RRT, opcode); 242 243 if (GET_INSN_FIELD (OP, opcode) == OP_MATCH_CUSTOM 244 && GET_INSN_FIELD (CUSTOM_B, opcode) == 0) 245 reg_base = nios2_coprocessor_regs (); 246 else 247 reg_base = nios2_regs; 248 249 if (i < NUMREGNAMES) 250 (*info->fprintf_func) (info->stream, "%s", reg_base[i].name); 251 else 252 (*info->fprintf_func) (info->stream, "unknown"); 253 break; 254 case 'i': 255 /* 16-bit signed immediate. */ 256 i = (signed) (GET_INSN_FIELD (IMM16, opcode) << 16) >> 16; 257 (*info->fprintf_func) (info->stream, "%ld", i); 258 break; 259 case 'u': 260 /* 16-bit unsigned immediate. */ 261 i = GET_INSN_FIELD (IMM16, opcode); 262 (*info->fprintf_func) (info->stream, "%ld", i); 263 break; 264 case 'o': 265 /* 16-bit signed immediate address offset. */ 266 i = (signed) (GET_INSN_FIELD (IMM16, opcode) << 16) >> 16; 267 address = address + 4 + i; 268 (*info->print_address_func) (address, info); 269 break; 270 case 'p': 271 /* 5-bit unsigned immediate. */ 272 i = GET_INSN_FIELD (CACHE_OPX, opcode); 273 (*info->fprintf_func) (info->stream, "%ld", i); 274 break; 275 case 'j': 276 /* 5-bit unsigned immediate. */ 277 i = GET_INSN_FIELD (IMM5, opcode); 278 (*info->fprintf_func) (info->stream, "%ld", i); 279 break; 280 case 'l': 281 /* 8-bit unsigned immediate. */ 282 /* FIXME - not yet implemented */ 283 i = GET_INSN_FIELD (CUSTOM_N, opcode); 284 (*info->fprintf_func) (info->stream, "%lu", i); 285 break; 286 case 'm': 287 /* 26-bit unsigned immediate. */ 288 i = GET_INSN_FIELD (IMM26, opcode); 289 /* This translates to an address because it's only used in call 290 instructions. */ 291 address = (address & 0xf0000000) | (i << 2); 292 (*info->print_address_func) (address, info); 293 break; 294 case 'c': 295 /* Control register index. */ 296 i = GET_INSN_FIELD (IMM5, opcode); 297 reg_base = nios2_control_regs (); 298 (*info->fprintf_func) (info->stream, "%s", reg_base[i].name); 299 break; 300 case 'b': 301 i = GET_INSN_FIELD (IMM5, opcode); 302 (*info->fprintf_func) (info->stream, "%ld", i); 303 break; 304 default: 305 (*info->fprintf_func) (info->stream, "unknown"); 306 break; 307 } 308 return 0; 309 } 310 311 /* nios2_disassemble does all the work of disassembling a Nios II 312 instruction opcode. */ 313 static int 314 nios2_disassemble (bfd_vma address, unsigned long opcode, 315 disassemble_info *info) 316 { 317 const struct nios2_opcode *op; 318 319 info->bytes_per_line = INSNLEN; 320 info->bytes_per_chunk = INSNLEN; 321 info->display_endian = info->endian; 322 info->insn_info_valid = 1; 323 info->branch_delay_insns = 0; 324 info->data_size = 0; 325 info->insn_type = dis_nonbranch; 326 info->target = 0; 327 info->target2 = 0; 328 329 /* Find the major opcode and use this to disassemble 330 the instruction and its arguments. */ 331 op = nios2_find_opcode_hash (opcode); 332 333 if (op != NULL) 334 { 335 bfd_boolean is_nop = FALSE; 336 if (op->pinfo == NIOS2_INSN_MACRO_MOV) 337 { 338 /* Check for mov r0, r0 and change to nop. */ 339 int dst, src; 340 dst = GET_INSN_FIELD (RRD, opcode); 341 src = GET_INSN_FIELD (RRS, opcode); 342 if (dst == 0 && src == 0) 343 { 344 (*info->fprintf_func) (info->stream, "nop"); 345 is_nop = TRUE; 346 } 347 else 348 (*info->fprintf_func) (info->stream, "%s", op->name); 349 } 350 else 351 (*info->fprintf_func) (info->stream, "%s", op->name); 352 353 if (!is_nop) 354 { 355 const char *argstr = op->args; 356 if (argstr != NULL && *argstr != '\0') 357 { 358 (*info->fprintf_func) (info->stream, "\t"); 359 while (*argstr != '\0') 360 { 361 nios2_print_insn_arg (argstr, opcode, address, info); 362 ++argstr; 363 } 364 } 365 } 366 } 367 else 368 { 369 /* Handle undefined instructions. */ 370 info->insn_type = dis_noninsn; 371 (*info->fprintf_func) (info->stream, "0x%lx", opcode); 372 } 373 /* Tell the caller how far to advance the program counter. */ 374 return INSNLEN; 375 } 376 377 378 /* print_insn_nios2 is the main disassemble function for Nios II. 379 The function diassembler(abfd) (source in disassemble.c) returns a 380 pointer to this either print_insn_big_nios2 or 381 print_insn_little_nios2, which in turn call this function when the 382 bfd machine type is Nios II. print_insn_nios2 reads the 383 instruction word at the address given, and prints the disassembled 384 instruction on the stream info->stream using info->fprintf_func. */ 385 386 static int 387 print_insn_nios2 (bfd_vma address, disassemble_info *info, 388 enum bfd_endian endianness) 389 { 390 bfd_byte buffer[INSNLEN]; 391 int status; 392 393 status = (*info->read_memory_func) (address, buffer, INSNLEN, info); 394 if (status == 0) 395 { 396 unsigned long insn; 397 if (endianness == BFD_ENDIAN_BIG) 398 insn = (unsigned long) bfd_getb32 (buffer); 399 else 400 insn = (unsigned long) bfd_getl32 (buffer); 401 status = nios2_disassemble (address, insn, info); 402 } 403 else 404 { 405 (*info->memory_error_func) (status, address, info); 406 status = -1; 407 } 408 return status; 409 } 410 411 /* These two functions are the main entry points, accessed from 412 disassemble.c. */ 413 int 414 print_insn_big_nios2 (bfd_vma address, disassemble_info *info) 415 { 416 return print_insn_nios2 (address, info, BFD_ENDIAN_BIG); 417 } 418 419 int 420 print_insn_little_nios2 (bfd_vma address, disassemble_info *info) 421 { 422 return print_insn_nios2 (address, info, BFD_ENDIAN_LITTLE); 423 } 424