1 /* Disassemble SH64 instructions.
2 Copyright (C) 2000, 2001 Free Software Foundation, Inc.
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.
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.
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. */
23 #include "libiberty.h"
25 /* We need to refer to the ELF header structure. */
29 #define ELF_MODE32_CODE_LABEL_P(SYM) \
30 (((elf_symbol_type *) (SYM))->internal_elf_sym.st_other & STO_SH5_ISA32)
32 #define SAVED_MOVI_R(INFO) \
33 (((struct sh64_disassemble_info *) ((INFO)->private_data))->address_reg)
35 #define SAVED_MOVI_IMM(INFO) \
36 (((struct sh64_disassemble_info *) ((INFO)->private_data))->built_address)
38 struct sh64_disassemble_info
40 /* When we see a MOVI, we save the register and the value, and merge a
41 subsequent SHORI and display the address, if there is one. */
42 unsigned int address_reg
;
43 bfd_signed_vma built_address
;
45 /* This is the range decriptor for the current address. It is kept
46 around for the next call. */
47 sh64_elf_crange crange
;
50 /* Each item in the table is a mask to indicate which bits to be set
51 to determine an instruction's operator.
52 The index is as same as the instruction in the opcode table.
53 Note that some archs have this as a field in the opcode table. */
54 static unsigned long *shmedia_opcode_mask_table
;
56 static void initialize_shmedia_opcode_mask_table
PARAMS ((void));
57 static int print_insn_shmedia
PARAMS ((bfd_vma
, disassemble_info
*));
58 static int print_insn_sh64x
59 PARAMS ((bfd_vma
, disassemble_info
*,
60 int (*) PARAMS ((bfd_vma
, struct disassemble_info
*)),
62 static const char *creg_name
PARAMS ((int));
63 static boolean init_sh64_disasm_info
PARAMS ((struct disassemble_info
*));
64 static enum sh64_elf_cr_type sh64_get_contents_type_disasm
65 PARAMS ((bfd_vma
, struct disassemble_info
*));
67 /* Initialize the SH64 opcode mask table for each instruction in SHmedia
71 initialize_shmedia_opcode_mask_table ()
76 /* Calculate number of opcodes. */
77 for (n_opc
= 0; shmedia_table
[n_opc
].name
!= NULL
; n_opc
++)
80 shmedia_opcode_mask_table
81 = xmalloc (sizeof (shmedia_opcode_mask_table
[0]) * n_opc
);
83 for (n
= 0; n
< n_opc
; n
++)
87 unsigned long mask
= 0;
89 for (i
= 0; shmedia_table
[n
].arg
[i
] != A_NONE
; i
++)
91 int offset
= shmedia_table
[n
].nibbles
[i
];
94 switch (shmedia_table
[n
].arg
[i
])
150 case A_PCIMMS16BY4_PT
:
161 mask
|= (0xffffffff >> (32 - length
)) << offset
;
163 shmedia_opcode_mask_table
[n
] = 0xffffffff & ~mask
;
167 /* Get a predefined control-register-name, or return NULL. */
173 const shmedia_creg_info
*cregp
;
175 /* If control register usage is common enough, change this to search a
177 for (cregp
= shmedia_creg_table
; cregp
->name
!= NULL
; cregp
++)
179 if (cregp
->cregno
== cregno
)
186 /* Main function to disassemble SHmedia instructions. */
189 print_insn_shmedia (memaddr
, info
)
191 struct disassemble_info
*info
;
193 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
194 void *stream
= info
->stream
;
196 unsigned char insn
[4];
197 unsigned long instruction
;
200 const shmedia_opcode_info
*op
;
204 bfd_vma disp_pc_addr
;
206 status
= info
->read_memory_func (memaddr
, insn
, 4, info
);
208 /* If we can't read four bytes, something is wrong. Display any data we
209 can get as .byte:s. */
214 for (i
= 0; i
< 3; i
++)
216 status
= info
->read_memory_func (memaddr
+ i
, insn
, 1, info
);
219 (*fprintf_fn
) (stream
, "%s0x%02x",
220 i
== 0 ? ".byte " : ", ",
227 /* Rearrange the bytes to make up an instruction. */
228 if (info
->endian
== BFD_ENDIAN_LITTLE
)
229 instruction
= bfd_getl32 (insn
);
231 instruction
= bfd_getb32 (insn
);
233 /* FIXME: Searching could be implemented using a hash on relevant
235 for (n
= 0, op
= shmedia_table
;
237 && ((instruction
& shmedia_opcode_mask_table
[n
]) != op
->opcode_base
);
241 /* FIXME: We should also check register number constraints. */
242 if (op
->name
== NULL
)
244 fprintf_fn (stream
, ".long 0x%08x", instruction
);
248 fprintf_fn (stream
, "%s\t", op
->name
);
250 for (i
= 0; i
< 3 && op
->arg
[i
] != A_NONE
; i
++)
252 unsigned long temp
= instruction
>> op
->nibbles
[i
];
255 if (i
> 0 && op
->arg
[i
] != A_REUSE_PREV
)
256 fprintf_fn (stream
, ",");
267 fprintf_fn (stream
, "r%d", r
);
274 fprintf_fn (stream
, "fv%d", r
);
281 fprintf_fn (stream
, "fp%d", r
);
288 fprintf_fn (stream
, "mtrx%d", r
);
297 name
= creg_name (r
);
300 fprintf_fn (stream
, "%s", name
);
302 fprintf_fn (stream
, "cr%d", r
);
310 fprintf_fn (stream
, "fr%d", r
);
317 fprintf_fn (stream
, "dr%d", r
);
323 fprintf_fn (stream
, "tr%d", r
);
326 /* A signed 6-bit number. */
329 if (imm
& (unsigned long) 0x20)
330 imm
|= ~(unsigned long) 0x3f;
331 fprintf_fn (stream
, "%d", imm
);
334 /* A signed 6-bit number, multiplied by 32 when used. */
337 if (imm
& (unsigned long) 0x20)
338 imm
|= ~(unsigned long) 0x3f;
339 fprintf_fn (stream
, "%d", imm
* 32);
342 /* A signed 10-bit number, multiplied by 8 when used. */
347 /* A signed 10-bit number, multiplied by 4 when used. */
352 /* A signed 10-bit number, multiplied by 2 when used. */
357 /* A signed 10-bit number. */
361 if (imm
& (unsigned long) 0x200)
362 imm
|= ~(unsigned long) 0x3ff;
364 fprintf_fn (stream
, "%d", imm
);
367 /* A signed 16-bit number. */
370 if (imm
& (unsigned long) 0x8000)
371 imm
|= ~((unsigned long) 0xffff);
372 fprintf_fn (stream
, "%d", imm
);
375 /* A PC-relative signed 16-bit number, multiplied by 4 when
378 imm
= temp
& 0xffff; /* 16 bits */
379 if (imm
& (unsigned long) 0x8000)
380 imm
|= ~(unsigned long) 0xffff;
382 disp_pc_addr
= (bfd_vma
) imm
+ memaddr
;
383 (*info
->print_address_func
) (disp_pc_addr
, info
);
386 /* An unsigned 5-bit number. */
389 fprintf_fn (stream
, "%d", imm
);
392 /* An unsigned 6-bit number. */
395 fprintf_fn (stream
, "%d", imm
);
398 /* An unsigned 16-bit number. */
401 fprintf_fn (stream
, "%d", imm
);
410 /* FIXME: Looks like 32-bit values only are handled.
411 FIXME: PC-relative numbers aren't handled correctly. */
412 if (op
->opcode_base
== (unsigned long) SHMEDIA_SHORI_OPC
413 && SAVED_MOVI_R (info
) == r
)
415 asection
*section
= info
->section
;
417 /* Most callers do not set the section field correctly yet. Revert
418 to getting the section from symbols, if any. */
420 && info
->symbols
!= NULL
421 && bfd_asymbol_flavour (info
->symbols
[0]) == bfd_target_elf_flavour
422 && ! bfd_is_und_section (bfd_get_section (info
->symbols
[0]))
423 && ! bfd_is_abs_section (bfd_get_section (info
->symbols
[0])))
424 section
= bfd_get_section (info
->symbols
[0]);
426 /* Only guess addresses when the contents of this section is fully
427 relocated. Otherwise, the value will be zero or perhaps even
430 || section
->owner
== NULL
431 || elf_elfheader (section
->owner
)->e_type
== ET_EXEC
)
433 bfd_signed_vma shori_addr
;
435 shori_addr
= SAVED_MOVI_IMM (info
) << 16;
438 fprintf_fn (stream
, "\t! 0x");
439 (*info
->print_address_func
) (shori_addr
, info
);
443 if (op
->opcode_base
== SHMEDIA_MOVI_OPC
)
445 SAVED_MOVI_IMM (info
) = imm
;
446 SAVED_MOVI_R (info
) = r
;
450 SAVED_MOVI_IMM (info
) = 0;
451 SAVED_MOVI_R (info
) = 255;
457 /* Check the type of contents about to be disassembled. This is like
458 sh64_get_contents_type (which may be called from here), except that it
459 takes the same arguments as print_insn_* and does what can be done if
460 no section is available. */
462 static enum sh64_elf_cr_type
463 sh64_get_contents_type_disasm (memaddr
, info
)
465 struct disassemble_info
*info
;
467 struct sh64_disassemble_info
*sh64_infop
= info
->private_data
;
469 /* Perhaps we have a region from a previous probe and it still counts
471 if (sh64_infop
->crange
.cr_type
!= CRT_NONE
472 && memaddr
>= sh64_infop
->crange
.cr_addr
473 && memaddr
< sh64_infop
->crange
.cr_addr
+ sh64_infop
->crange
.cr_size
)
474 return sh64_infop
->crange
.cr_type
;
476 /* If we have a section, try and use it. */
478 && bfd_get_flavour (info
->section
->owner
) == bfd_target_elf_flavour
)
480 enum sh64_elf_cr_type cr_type
481 = sh64_get_contents_type (info
->section
, memaddr
,
482 &sh64_infop
->crange
);
484 if (cr_type
!= CRT_NONE
)
488 /* If we have symbols, we can try and get at a section from *that*. */
489 if (info
->symbols
!= NULL
490 && bfd_asymbol_flavour (info
->symbols
[0]) == bfd_target_elf_flavour
491 && ! bfd_is_und_section (bfd_get_section (info
->symbols
[0]))
492 && ! bfd_is_abs_section (bfd_get_section (info
->symbols
[0])))
494 enum sh64_elf_cr_type cr_type
495 = sh64_get_contents_type (bfd_get_section (info
->symbols
[0]),
496 memaddr
, &sh64_infop
->crange
);
498 if (cr_type
!= CRT_NONE
)
502 /* We can make a reasonable guess based on the st_other field of a
503 symbol; for a BranchTarget this is marked as STO_SH5_ISA32 and then
504 it's most probably code there. */
506 && bfd_asymbol_flavour (info
->symbols
[0]) == bfd_target_elf_flavour
507 && elf_symbol_from (bfd_asymbol_bfd (info
->symbols
[0]),
508 info
->symbols
[0])->internal_elf_sym
.st_other
510 return CRT_SH5_ISA32
;
512 /* If all else fails, guess this is code and guess on the low bit set. */
513 return (memaddr
& 1) == 1 ? CRT_SH5_ISA32
: CRT_SH5_ISA16
;
516 /* Initialize static and dynamic disassembly state. */
519 init_sh64_disasm_info (info
)
520 struct disassemble_info
*info
;
522 struct sh64_disassemble_info
*sh64_infop
523 = calloc (sizeof (*sh64_infop
), 1);
525 if (sh64_infop
== NULL
)
528 info
->private_data
= sh64_infop
;
530 SAVED_MOVI_IMM (info
) = 0;
531 SAVED_MOVI_R (info
) = 255;
533 if (shmedia_opcode_mask_table
== NULL
)
534 initialize_shmedia_opcode_mask_table ();
539 /* Main entry to disassemble SHmedia instructions, given an endian set in
540 INFO. Note that the simulator uses this as the main entry and does not
541 use any of the functions further below. */
544 print_insn_sh64x_media (memaddr
, info
)
546 struct disassemble_info
*info
;
548 if (info
->private_data
== NULL
&& ! init_sh64_disasm_info (info
))
551 /* Make reasonable output. */
552 info
->bytes_per_line
= 4;
553 info
->bytes_per_chunk
= 4;
555 return print_insn_shmedia (memaddr
, info
);
558 /* Main entry to disassemble SHcompact or SHmedia insns. */
561 print_insn_sh64x (memaddr
, info
, pfun_compact
, endian
)
563 struct disassemble_info
*info
;
564 int (*pfun_compact
) PARAMS ((bfd_vma
, struct disassemble_info
*));
565 enum bfd_endian endian
;
567 enum sh64_elf_cr_type cr_type
;
569 if (info
->private_data
== NULL
&& ! init_sh64_disasm_info (info
))
572 cr_type
= sh64_get_contents_type_disasm (memaddr
, info
);
573 if (cr_type
!= CRT_SH5_ISA16
)
575 int length
= 4 - (memaddr
% 4);
576 info
->display_endian
= endian
;
578 /* Only disassemble on four-byte boundaries. Addresses that are not
579 a multiple of four can happen after a data region. */
580 if (cr_type
== CRT_SH5_ISA32
&& length
== 4)
581 return print_insn_sh64x_media (memaddr
, info
);
583 /* We get CRT_DATA *only* for data regions in a mixed-contents
584 section. For sections with data only, we get indication of one
585 of the ISA:s. You may think that we shouldn't disassemble
586 section with only data if we can figure that out. However, the
587 disassembly function is by default not called for data-only
588 sections, so if the user explicitly specified disassembly of a
589 data section, that's what we should do. */
590 if (cr_type
== CRT_DATA
|| length
!= 4)
593 unsigned char data
[4];
594 struct sh64_disassemble_info
*sh64_infop
= info
->private_data
;
597 && sh64_infop
->crange
.cr_type
!= CRT_NONE
598 && memaddr
>= sh64_infop
->crange
.cr_addr
599 && memaddr
< (sh64_infop
->crange
.cr_addr
600 + sh64_infop
->crange
.cr_size
))
602 = (sh64_infop
->crange
.cr_addr
603 + sh64_infop
->crange
.cr_size
- memaddr
);
606 = (*info
->read_memory_func
) (memaddr
, data
,
607 length
>= 4 ? 4 : length
, info
);
609 if (status
== 0 && length
>= 4)
611 (*info
->fprintf_func
) (info
->stream
, ".long 0x%08lx",
612 endian
== BFD_ENDIAN_BIG
613 ? (long) (bfd_getb32 (data
))
614 : (long) (bfd_getl32 (data
)));
621 for (i
= 0; i
< length
; i
++)
623 status
= info
->read_memory_func (memaddr
+ i
, data
, 1, info
);
626 (*info
->fprintf_func
) (info
->stream
, "%s0x%02x",
627 i
== 0 ? ".byte " : ", ",
636 return (*pfun_compact
) (memaddr
, info
);
639 /* Main entry to disassemble SHcompact or SHmedia insns, big endian. */
642 print_insn_sh64 (memaddr
, info
)
644 struct disassemble_info
*info
;
647 print_insn_sh64x (memaddr
, info
, print_insn_sh
, BFD_ENDIAN_BIG
);
650 /* Main entry to disassemble SHcompact or SHmedia insns, little endian. */
653 print_insn_sh64l (memaddr
, info
)
655 struct disassemble_info
*info
;
658 print_insn_sh64x (memaddr
, info
, print_insn_shl
, BFD_ENDIAN_LITTLE
);