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