ARM: plt_size functions need to read instructions in right byte order
[deliverable/binutils-gdb.git] / opcodes / nios2-dis.c
CommitLineData
36591ba1 1/* Altera Nios II disassemble routines
4b95cf5c 2 Copyright (C) 2012-2014 Free Software Foundation, Inc.
36591ba1
SL
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. */
42typedef struct _nios2_opcode_hash
43{
44 const struct nios2_opcode *opcode;
45 struct _nios2_opcode_hash *next;
46} nios2_opcode_hash;
47
48static bfd_boolean nios2_hash_init = 0;
49static nios2_opcode_hash *nios2_hash[(OP_MASK_OP) + 1];
50
51/* Separate hash table for pseudo-ops. */
52static nios2_opcode_hash *nios2_ps_hash[(OP_MASK_OP) + 1];
53
54/* Function to initialize the opcode hash table. */
55static void
56nios2_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. */
126const struct nios2_opcode *
127nios2_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. */
155static struct nios2_reg *
156nios2_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. */
175static struct nios2_reg *
176nios2_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. */
197static int
198nios2_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. */
313static int
314nios2_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
386static int
387print_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. */
413int
414print_insn_big_nios2 (bfd_vma address, disassemble_info *info)
415{
416 return print_insn_nios2 (address, info, BFD_ENDIAN_BIG);
417}
418
419int
420print_insn_little_nios2 (bfd_vma address, disassemble_info *info)
421{
422 return print_insn_nios2 (address, info, BFD_ENDIAN_LITTLE);
423}
This page took 0.117067 seconds and 4 git commands to generate.