Change mode of gas/configure back to 0755
[deliverable/binutils-gdb.git] / opcodes / sh64-dis.c
CommitLineData
d28847ce 1/* Disassemble SH64 instructions.
df7b86aa
NC
2 Copyright 2000, 2001, 2002, 2003, 2005, 2007, 2012
3 Free Software Foundation, Inc.
d28847ce 4
9b201bb5
NC
5 This file is part of the GNU opcodes library.
6
7 This library is free software; you can redistribute it and/or modify
d28847ce 8 it under the terms of the GNU General Public License as published by
9b201bb5
NC
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
d28847ce 11
9b201bb5
NC
12 It is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
d28847ce
AO
16
17 You should have received a copy of the GNU General Public License
9b201bb5
NC
18 along with this file; see the file COPYING. If not, write to the
19 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
d28847ce 21
df7b86aa 22#include "sysdep.h"
d28847ce 23#include <stdio.h>
d28847ce 24#include "dis-asm.h"
d28847ce
AO
25#include "sh64-opc.h"
26#include "libiberty.h"
d28847ce
AO
27/* We need to refer to the ELF header structure. */
28#include "elf-bfd.h"
29#include "elf/sh.h"
f0abc2a1 30#include "elf32-sh64.h"
d28847ce
AO
31
32#define ELF_MODE32_CODE_LABEL_P(SYM) \
33 (((elf_symbol_type *) (SYM))->internal_elf_sym.st_other & STO_SH5_ISA32)
34
35#define SAVED_MOVI_R(INFO) \
36 (((struct sh64_disassemble_info *) ((INFO)->private_data))->address_reg)
37
38#define SAVED_MOVI_IMM(INFO) \
39 (((struct sh64_disassemble_info *) ((INFO)->private_data))->built_address)
40
41struct sh64_disassemble_info
42 {
43 /* When we see a MOVI, we save the register and the value, and merge a
44 subsequent SHORI and display the address, if there is one. */
45 unsigned int address_reg;
46 bfd_signed_vma built_address;
47
48 /* This is the range decriptor for the current address. It is kept
49 around for the next call. */
50 sh64_elf_crange crange;
51 };
52
53/* Each item in the table is a mask to indicate which bits to be set
b34976b6 54 to determine an instruction's operator.
d28847ce
AO
55 The index is as same as the instruction in the opcode table.
56 Note that some archs have this as a field in the opcode table. */
57static unsigned long *shmedia_opcode_mask_table;
58
d28847ce
AO
59/* Initialize the SH64 opcode mask table for each instruction in SHmedia
60 mode. */
61
62static void
47b0e7ad 63initialize_shmedia_opcode_mask_table (void)
d28847ce
AO
64{
65 int n_opc;
66 int n;
67
68 /* Calculate number of opcodes. */
69 for (n_opc = 0; shmedia_table[n_opc].name != NULL; n_opc++)
70 ;
71
72 shmedia_opcode_mask_table
73 = xmalloc (sizeof (shmedia_opcode_mask_table[0]) * n_opc);
74
75 for (n = 0; n < n_opc; n++)
76 {
77 int i;
78
79 unsigned long mask = 0;
80
81 for (i = 0; shmedia_table[n].arg[i] != A_NONE; i++)
82 {
83 int offset = shmedia_table[n].nibbles[i];
84 int length;
b34976b6 85
d28847ce
AO
86 switch (shmedia_table[n].arg[i])
87 {
88 case A_GREG_M:
89 case A_GREG_N:
90 case A_GREG_D:
91 case A_CREG_K:
92 case A_CREG_J:
93 case A_FREG_G:
94 case A_FREG_H:
95 case A_FREG_F:
96 case A_DREG_G:
97 case A_DREG_H:
98 case A_DREG_F:
99 case A_FMREG_G:
100 case A_FMREG_H:
101 case A_FMREG_F:
102 case A_FPREG_G:
103 case A_FPREG_H:
104 case A_FPREG_F:
105 case A_FVREG_G:
106 case A_FVREG_H:
107 case A_FVREG_F:
108 case A_REUSE_PREV:
109 length = 6;
110 break;
111
112 case A_TREG_A:
113 case A_TREG_B:
114 length = 3;
115 break;
116
b34976b6 117 case A_IMMM:
d28847ce
AO
118 abort ();
119 break;
120
121 case A_IMMU5:
122 length = 5;
123 break;
124
125 case A_IMMS6:
126 case A_IMMU6:
127 case A_IMMS6BY32:
128 length = 6;
129 break;
130
131 case A_IMMS10:
132 case A_IMMS10BY1:
133 case A_IMMS10BY2:
134 case A_IMMS10BY4:
135 case A_IMMS10BY8:
136 length = 10;
137 break;
138
139 case A_IMMU16:
140 case A_IMMS16:
141 case A_PCIMMS16BY4:
142 case A_PCIMMS16BY4_PT:
143 length = 16;
144 break;
145
146 default:
147 abort ();
148 length = 0;
149 break;
150 }
151
152 if (length != 0)
153 mask |= (0xffffffff >> (32 - length)) << offset;
154 }
155 shmedia_opcode_mask_table[n] = 0xffffffff & ~mask;
156 }
157}
158
159/* Get a predefined control-register-name, or return NULL. */
160
47b0e7ad
NC
161static const char *
162creg_name (int cregno)
d28847ce
AO
163{
164 const shmedia_creg_info *cregp;
165
166 /* If control register usage is common enough, change this to search a
167 hash-table. */
168 for (cregp = shmedia_creg_table; cregp->name != NULL; cregp++)
47b0e7ad
NC
169 if (cregp->cregno == cregno)
170 return cregp->name;
d28847ce
AO
171
172 return NULL;
173}
174
175/* Main function to disassemble SHmedia instructions. */
176
177static int
47b0e7ad 178print_insn_shmedia (bfd_vma memaddr, struct disassemble_info *info)
d28847ce
AO
179{
180 fprintf_ftype fprintf_fn = info->fprintf_func;
181 void *stream = info->stream;
d28847ce
AO
182 unsigned char insn[4];
183 unsigned long instruction;
184 int status;
185 int n;
186 const shmedia_opcode_info *op;
187 int i;
188 unsigned int r = 0;
189 long imm = 0;
190 bfd_vma disp_pc_addr;
191
192 status = info->read_memory_func (memaddr, insn, 4, info);
193
194 /* If we can't read four bytes, something is wrong. Display any data we
195 can get as .byte:s. */
196 if (status != 0)
197 {
d28847ce
AO
198 for (i = 0; i < 3; i++)
199 {
200 status = info->read_memory_func (memaddr + i, insn, 1, info);
201 if (status != 0)
202 break;
203 (*fprintf_fn) (stream, "%s0x%02x",
204 i == 0 ? ".byte " : ", ",
205 insn[0]);
206 }
207
208 return i ? i : -1;
209 }
210
211 /* Rearrange the bytes to make up an instruction. */
212 if (info->endian == BFD_ENDIAN_LITTLE)
213 instruction = bfd_getl32 (insn);
214 else
215 instruction = bfd_getb32 (insn);
216
217 /* FIXME: Searching could be implemented using a hash on relevant
218 fields. */
219 for (n = 0, op = shmedia_table;
220 op->name != NULL
221 && ((instruction & shmedia_opcode_mask_table[n]) != op->opcode_base);
222 n++, op++)
223 ;
224
225 /* FIXME: We should also check register number constraints. */
226 if (op->name == NULL)
227 {
0fd3a477 228 fprintf_fn (stream, ".long 0x%08lx", instruction);
d28847ce
AO
229 return 4;
230 }
231
232 fprintf_fn (stream, "%s\t", op->name);
233
234 for (i = 0; i < 3 && op->arg[i] != A_NONE; i++)
235 {
236 unsigned long temp = instruction >> op->nibbles[i];
237 int by_number = 0;
238
239 if (i > 0 && op->arg[i] != A_REUSE_PREV)
240 fprintf_fn (stream, ",");
241
242 switch (op->arg[i])
243 {
244 case A_REUSE_PREV:
245 continue;
246
247 case A_GREG_M:
248 case A_GREG_N:
249 case A_GREG_D:
250 r = temp & 0x3f;
251 fprintf_fn (stream, "r%d", r);
252 break;
253
254 case A_FVREG_F:
255 case A_FVREG_G:
256 case A_FVREG_H:
257 r = temp & 0x3f;
258 fprintf_fn (stream, "fv%d", r);
259 break;
260
261 case A_FPREG_F:
262 case A_FPREG_G:
263 case A_FPREG_H:
264 r = temp & 0x3f;
265 fprintf_fn (stream, "fp%d", r);
266 break;
267
268 case A_FMREG_F:
269 case A_FMREG_G:
270 case A_FMREG_H:
271 r = temp & 0x3f;
272 fprintf_fn (stream, "mtrx%d", r);
273 break;
274
275 case A_CREG_K:
276 case A_CREG_J:
277 {
278 const char *name;
47b0e7ad 279
d28847ce
AO
280 r = temp & 0x3f;
281
282 name = creg_name (r);
283
284 if (name != NULL)
285 fprintf_fn (stream, "%s", name);
286 else
287 fprintf_fn (stream, "cr%d", r);
288 }
289 break;
290
291 case A_FREG_G:
292 case A_FREG_H:
293 case A_FREG_F:
294 r = temp & 0x3f;
295 fprintf_fn (stream, "fr%d", r);
296 break;
297
298 case A_DREG_G:
299 case A_DREG_H:
300 case A_DREG_F:
301 r = temp & 0x3f;
302 fprintf_fn (stream, "dr%d", r);
303 break;
304
305 case A_TREG_A:
306 case A_TREG_B:
307 r = temp & 0x7;
308 fprintf_fn (stream, "tr%d", r);
309 break;
310
311 /* A signed 6-bit number. */
312 case A_IMMS6:
313 imm = temp & 0x3f;
314 if (imm & (unsigned long) 0x20)
315 imm |= ~(unsigned long) 0x3f;
0fd3a477 316 fprintf_fn (stream, "%ld", imm);
d28847ce
AO
317 break;
318
319 /* A signed 6-bit number, multiplied by 32 when used. */
320 case A_IMMS6BY32:
321 imm = temp & 0x3f;
322 if (imm & (unsigned long) 0x20)
323 imm |= ~(unsigned long) 0x3f;
0fd3a477 324 fprintf_fn (stream, "%ld", imm * 32);
d28847ce
AO
325 break;
326
327 /* A signed 10-bit number, multiplied by 8 when used. */
328 case A_IMMS10BY8:
329 by_number++;
330 /* Fall through. */
331
332 /* A signed 10-bit number, multiplied by 4 when used. */
333 case A_IMMS10BY4:
334 by_number++;
335 /* Fall through. */
336
337 /* A signed 10-bit number, multiplied by 2 when used. */
338 case A_IMMS10BY2:
339 by_number++;
340 /* Fall through. */
341
342 /* A signed 10-bit number. */
343 case A_IMMS10:
344 case A_IMMS10BY1:
345 imm = temp & 0x3ff;
346 if (imm & (unsigned long) 0x200)
347 imm |= ~(unsigned long) 0x3ff;
348 imm <<= by_number;
0fd3a477 349 fprintf_fn (stream, "%ld", imm);
d28847ce
AO
350 break;
351
352 /* A signed 16-bit number. */
353 case A_IMMS16:
354 imm = temp & 0xffff;
355 if (imm & (unsigned long) 0x8000)
356 imm |= ~((unsigned long) 0xffff);
0fd3a477 357 fprintf_fn (stream, "%ld", imm);
d28847ce
AO
358 break;
359
360 /* A PC-relative signed 16-bit number, multiplied by 4 when
361 used. */
362 case A_PCIMMS16BY4:
363 imm = temp & 0xffff; /* 16 bits */
364 if (imm & (unsigned long) 0x8000)
365 imm |= ~(unsigned long) 0xffff;
366 imm <<= 2;
367 disp_pc_addr = (bfd_vma) imm + memaddr;
368 (*info->print_address_func) (disp_pc_addr, info);
369 break;
370
371 /* An unsigned 5-bit number. */
372 case A_IMMU5:
373 imm = temp & 0x1f;
0fd3a477 374 fprintf_fn (stream, "%ld", imm);
d28847ce
AO
375 break;
376
377 /* An unsigned 6-bit number. */
378 case A_IMMU6:
379 imm = temp & 0x3f;
0fd3a477 380 fprintf_fn (stream, "%ld", imm);
d28847ce
AO
381 break;
382
383 /* An unsigned 16-bit number. */
384 case A_IMMU16:
385 imm = temp & 0xffff;
0fd3a477 386 fprintf_fn (stream, "%ld", imm);
d28847ce
AO
387 break;
388
389 default:
390 abort ();
391 break;
392 }
393 }
394
395 /* FIXME: Looks like 32-bit values only are handled.
396 FIXME: PC-relative numbers aren't handled correctly. */
397 if (op->opcode_base == (unsigned long) SHMEDIA_SHORI_OPC
398 && SAVED_MOVI_R (info) == r)
399 {
400 asection *section = info->section;
401
402 /* Most callers do not set the section field correctly yet. Revert
403 to getting the section from symbols, if any. */
404 if (section == NULL
405 && info->symbols != NULL
406 && bfd_asymbol_flavour (info->symbols[0]) == bfd_target_elf_flavour
407 && ! bfd_is_und_section (bfd_get_section (info->symbols[0]))
408 && ! bfd_is_abs_section (bfd_get_section (info->symbols[0])))
409 section = bfd_get_section (info->symbols[0]);
410
411 /* Only guess addresses when the contents of this section is fully
412 relocated. Otherwise, the value will be zero or perhaps even
413 bogus. */
414 if (section == NULL
415 || section->owner == NULL
416 || elf_elfheader (section->owner)->e_type == ET_EXEC)
417 {
418 bfd_signed_vma shori_addr;
419
420 shori_addr = SAVED_MOVI_IMM (info) << 16;
421 shori_addr |= imm;
422
423 fprintf_fn (stream, "\t! 0x");
424 (*info->print_address_func) (shori_addr, info);
425 }
426 }
427
428 if (op->opcode_base == SHMEDIA_MOVI_OPC)
429 {
430 SAVED_MOVI_IMM (info) = imm;
431 SAVED_MOVI_R (info) = r;
432 }
433 else
434 {
435 SAVED_MOVI_IMM (info) = 0;
436 SAVED_MOVI_R (info) = 255;
437 }
438
439 return 4;
440}
441
442/* Check the type of contents about to be disassembled. This is like
443 sh64_get_contents_type (which may be called from here), except that it
444 takes the same arguments as print_insn_* and does what can be done if
445 no section is available. */
446
447static enum sh64_elf_cr_type
47b0e7ad 448sh64_get_contents_type_disasm (bfd_vma memaddr, struct disassemble_info *info)
d28847ce
AO
449{
450 struct sh64_disassemble_info *sh64_infop = info->private_data;
451
452 /* Perhaps we have a region from a previous probe and it still counts
453 for this address? */
454 if (sh64_infop->crange.cr_type != CRT_NONE
455 && memaddr >= sh64_infop->crange.cr_addr
456 && memaddr < sh64_infop->crange.cr_addr + sh64_infop->crange.cr_size)
457 return sh64_infop->crange.cr_type;
458
459 /* If we have a section, try and use it. */
460 if (info->section
461 && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour)
462 {
463 enum sh64_elf_cr_type cr_type
464 = sh64_get_contents_type (info->section, memaddr,
465 &sh64_infop->crange);
466
467 if (cr_type != CRT_NONE)
468 return cr_type;
469 }
470
471 /* If we have symbols, we can try and get at a section from *that*. */
472 if (info->symbols != NULL
473 && bfd_asymbol_flavour (info->symbols[0]) == bfd_target_elf_flavour
474 && ! bfd_is_und_section (bfd_get_section (info->symbols[0]))
475 && ! bfd_is_abs_section (bfd_get_section (info->symbols[0])))
476 {
477 enum sh64_elf_cr_type cr_type
478 = sh64_get_contents_type (bfd_get_section (info->symbols[0]),
479 memaddr, &sh64_infop->crange);
480
481 if (cr_type != CRT_NONE)
482 return cr_type;
483 }
484
485 /* We can make a reasonable guess based on the st_other field of a
486 symbol; for a BranchTarget this is marked as STO_SH5_ISA32 and then
487 it's most probably code there. */
488 if (info->symbols
489 && bfd_asymbol_flavour (info->symbols[0]) == bfd_target_elf_flavour
490 && elf_symbol_from (bfd_asymbol_bfd (info->symbols[0]),
491 info->symbols[0])->internal_elf_sym.st_other
492 == STO_SH5_ISA32)
493 return CRT_SH5_ISA32;
494
495 /* If all else fails, guess this is code and guess on the low bit set. */
496 return (memaddr & 1) == 1 ? CRT_SH5_ISA32 : CRT_SH5_ISA16;
497}
498
499/* Initialize static and dynamic disassembly state. */
500
b34976b6 501static bfd_boolean
47b0e7ad 502init_sh64_disasm_info (struct disassemble_info *info)
d28847ce
AO
503{
504 struct sh64_disassemble_info *sh64_infop
505 = calloc (sizeof (*sh64_infop), 1);
506
507 if (sh64_infop == NULL)
b34976b6 508 return FALSE;
d28847ce
AO
509
510 info->private_data = sh64_infop;
511
512 SAVED_MOVI_IMM (info) = 0;
513 SAVED_MOVI_R (info) = 255;
514
515 if (shmedia_opcode_mask_table == NULL)
516 initialize_shmedia_opcode_mask_table ();
517
b34976b6 518 return TRUE;
d28847ce
AO
519}
520
521/* Main entry to disassemble SHmedia instructions, given an endian set in
522 INFO. Note that the simulator uses this as the main entry and does not
523 use any of the functions further below. */
524
b34976b6 525int
47b0e7ad 526print_insn_sh64x_media (bfd_vma memaddr, struct disassemble_info *info)
d28847ce
AO
527{
528 if (info->private_data == NULL && ! init_sh64_disasm_info (info))
529 return -1;
530
531 /* Make reasonable output. */
532 info->bytes_per_line = 4;
533 info->bytes_per_chunk = 4;
534
535 return print_insn_shmedia (memaddr, info);
536}
537
1c509ca8
JR
538/* Main entry to disassemble SHmedia insns.
539 If we see an SHcompact instruction, return -2. */
d28847ce 540
b34976b6 541int
47b0e7ad 542print_insn_sh64 (bfd_vma memaddr, struct disassemble_info *info)
d28847ce 543{
1c509ca8 544 enum bfd_endian endian = info->endian;
d28847ce
AO
545 enum sh64_elf_cr_type cr_type;
546
547 if (info->private_data == NULL && ! init_sh64_disasm_info (info))
548 return -1;
549
550 cr_type = sh64_get_contents_type_disasm (memaddr, info);
551 if (cr_type != CRT_SH5_ISA16)
552 {
553 int length = 4 - (memaddr % 4);
554 info->display_endian = endian;
555
1c509ca8
JR
556 /* If we got an uneven address to indicate SHmedia, adjust it. */
557 if (cr_type == CRT_SH5_ISA32 && length == 3)
558 memaddr--, length = 4;
559
d28847ce
AO
560 /* Only disassemble on four-byte boundaries. Addresses that are not
561 a multiple of four can happen after a data region. */
562 if (cr_type == CRT_SH5_ISA32 && length == 4)
563 return print_insn_sh64x_media (memaddr, info);
564
565 /* We get CRT_DATA *only* for data regions in a mixed-contents
566 section. For sections with data only, we get indication of one
567 of the ISA:s. You may think that we shouldn't disassemble
568 section with only data if we can figure that out. However, the
569 disassembly function is by default not called for data-only
570 sections, so if the user explicitly specified disassembly of a
571 data section, that's what we should do. */
572 if (cr_type == CRT_DATA || length != 4)
573 {
574 int status;
575 unsigned char data[4];
576 struct sh64_disassemble_info *sh64_infop = info->private_data;
577
578 if (length == 4
579 && sh64_infop->crange.cr_type != CRT_NONE
580 && memaddr >= sh64_infop->crange.cr_addr
581 && memaddr < (sh64_infop->crange.cr_addr
582 + sh64_infop->crange.cr_size))
583 length
584 = (sh64_infop->crange.cr_addr
585 + sh64_infop->crange.cr_size - memaddr);
586
587 status
588 = (*info->read_memory_func) (memaddr, data,
589 length >= 4 ? 4 : length, info);
590
591 if (status == 0 && length >= 4)
592 {
593 (*info->fprintf_func) (info->stream, ".long 0x%08lx",
594 endian == BFD_ENDIAN_BIG
595 ? (long) (bfd_getb32 (data))
596 : (long) (bfd_getl32 (data)));
597 return 4;
598 }
599 else
600 {
601 int i;
602
603 for (i = 0; i < length; i++)
604 {
605 status = info->read_memory_func (memaddr + i, data, 1, info);
606 if (status != 0)
607 break;
608 (*info->fprintf_func) (info->stream, "%s0x%02x",
609 i == 0 ? ".byte " : ", ",
610 data[0]);
611 }
612
613 return i ? i : -1;
614 }
615 }
616 }
617
1c509ca8
JR
618 /* SH1 .. SH4 instruction, let caller handle it. */
619 return -2;
d28847ce 620}
This page took 0.526431 seconds and 4 git commands to generate.