1 /* Disassemble SH64 instructions.
2 Copyright 2000, 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
4 This file is part of the GNU opcodes library.
6 This library is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 It is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this file; see the file COPYING. If not, write to the
18 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
26 #include "libiberty.h"
27 /* We need to refer to the ELF header structure. */
30 #include "elf32-sh64.h"
32 #define ELF_MODE32_CODE_LABEL_P(SYM) \
33 (((elf_symbol_type *) (SYM))->internal_elf_sym.st_other & STO_SH5_ISA32)
35 #define SAVED_MOVI_R(INFO) \
36 (((struct sh64_disassemble_info *) ((INFO)->private_data))->address_reg)
38 #define SAVED_MOVI_IMM(INFO) \
39 (((struct sh64_disassemble_info *) ((INFO)->private_data))->built_address)
41 struct sh64_disassemble_info
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
;
48 /* This is the range decriptor for the current address. It is kept
49 around for the next call. */
50 sh64_elf_crange crange
;
53 /* Each item in the table is a mask to indicate which bits to be set
54 to determine an instruction's operator.
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. */
57 static unsigned long *shmedia_opcode_mask_table
;
59 /* Initialize the SH64 opcode mask table for each instruction in SHmedia
63 initialize_shmedia_opcode_mask_table (void)
68 /* Calculate number of opcodes. */
69 for (n_opc
= 0; shmedia_table
[n_opc
].name
!= NULL
; n_opc
++)
72 shmedia_opcode_mask_table
73 = xmalloc (sizeof (shmedia_opcode_mask_table
[0]) * n_opc
);
75 for (n
= 0; n
< n_opc
; n
++)
79 unsigned long mask
= 0;
81 for (i
= 0; shmedia_table
[n
].arg
[i
] != A_NONE
; i
++)
83 int offset
= shmedia_table
[n
].nibbles
[i
];
86 switch (shmedia_table
[n
].arg
[i
])
142 case A_PCIMMS16BY4_PT
:
153 mask
|= (0xffffffff >> (32 - length
)) << offset
;
155 shmedia_opcode_mask_table
[n
] = 0xffffffff & ~mask
;
159 /* Get a predefined control-register-name, or return NULL. */
162 creg_name (int cregno
)
164 const shmedia_creg_info
*cregp
;
166 /* If control register usage is common enough, change this to search a
168 for (cregp
= shmedia_creg_table
; cregp
->name
!= NULL
; cregp
++)
169 if (cregp
->cregno
== cregno
)
175 /* Main function to disassemble SHmedia instructions. */
178 print_insn_shmedia (bfd_vma memaddr
, struct disassemble_info
*info
)
180 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
181 void *stream
= info
->stream
;
182 unsigned char insn
[4];
183 unsigned long instruction
;
186 const shmedia_opcode_info
*op
;
190 bfd_vma disp_pc_addr
;
192 status
= info
->read_memory_func (memaddr
, insn
, 4, info
);
194 /* If we can't read four bytes, something is wrong. Display any data we
195 can get as .byte:s. */
200 for (i
= 0; i
< 3; i
++)
202 status
= info
->read_memory_func (memaddr
+ i
, insn
, 1, info
);
205 (*fprintf_fn
) (stream
, "%s0x%02x",
206 i
== 0 ? ".byte " : ", ",
213 /* Rearrange the bytes to make up an instruction. */
214 if (info
->endian
== BFD_ENDIAN_LITTLE
)
215 instruction
= bfd_getl32 (insn
);
217 instruction
= bfd_getb32 (insn
);
219 /* FIXME: Searching could be implemented using a hash on relevant
221 for (n
= 0, op
= shmedia_table
;
223 && ((instruction
& shmedia_opcode_mask_table
[n
]) != op
->opcode_base
);
227 /* FIXME: We should also check register number constraints. */
228 if (op
->name
== NULL
)
230 fprintf_fn (stream
, ".long 0x%08lx", instruction
);
234 fprintf_fn (stream
, "%s\t", op
->name
);
236 for (i
= 0; i
< 3 && op
->arg
[i
] != A_NONE
; i
++)
238 unsigned long temp
= instruction
>> op
->nibbles
[i
];
241 if (i
> 0 && op
->arg
[i
] != A_REUSE_PREV
)
242 fprintf_fn (stream
, ",");
253 fprintf_fn (stream
, "r%d", r
);
260 fprintf_fn (stream
, "fv%d", r
);
267 fprintf_fn (stream
, "fp%d", r
);
274 fprintf_fn (stream
, "mtrx%d", r
);
284 name
= creg_name (r
);
287 fprintf_fn (stream
, "%s", name
);
289 fprintf_fn (stream
, "cr%d", r
);
297 fprintf_fn (stream
, "fr%d", r
);
304 fprintf_fn (stream
, "dr%d", r
);
310 fprintf_fn (stream
, "tr%d", r
);
313 /* A signed 6-bit number. */
316 if (imm
& (unsigned long) 0x20)
317 imm
|= ~(unsigned long) 0x3f;
318 fprintf_fn (stream
, "%ld", imm
);
321 /* A signed 6-bit number, multiplied by 32 when used. */
324 if (imm
& (unsigned long) 0x20)
325 imm
|= ~(unsigned long) 0x3f;
326 fprintf_fn (stream
, "%ld", imm
* 32);
329 /* A signed 10-bit number, multiplied by 8 when used. */
334 /* A signed 10-bit number, multiplied by 4 when used. */
339 /* A signed 10-bit number, multiplied by 2 when used. */
344 /* A signed 10-bit number. */
348 if (imm
& (unsigned long) 0x200)
349 imm
|= ~(unsigned long) 0x3ff;
351 fprintf_fn (stream
, "%ld", imm
);
354 /* A signed 16-bit number. */
357 if (imm
& (unsigned long) 0x8000)
358 imm
|= ~((unsigned long) 0xffff);
359 fprintf_fn (stream
, "%ld", imm
);
362 /* A PC-relative signed 16-bit number, multiplied by 4 when
365 imm
= temp
& 0xffff; /* 16 bits */
366 if (imm
& (unsigned long) 0x8000)
367 imm
|= ~(unsigned long) 0xffff;
369 disp_pc_addr
= (bfd_vma
) imm
+ memaddr
;
370 (*info
->print_address_func
) (disp_pc_addr
, info
);
373 /* An unsigned 5-bit number. */
376 fprintf_fn (stream
, "%ld", imm
);
379 /* An unsigned 6-bit number. */
382 fprintf_fn (stream
, "%ld", imm
);
385 /* An unsigned 16-bit number. */
388 fprintf_fn (stream
, "%ld", imm
);
397 /* FIXME: Looks like 32-bit values only are handled.
398 FIXME: PC-relative numbers aren't handled correctly. */
399 if (op
->opcode_base
== (unsigned long) SHMEDIA_SHORI_OPC
400 && SAVED_MOVI_R (info
) == r
)
402 asection
*section
= info
->section
;
404 /* Most callers do not set the section field correctly yet. Revert
405 to getting the section from symbols, if any. */
407 && info
->symbols
!= NULL
408 && bfd_asymbol_flavour (info
->symbols
[0]) == bfd_target_elf_flavour
409 && ! bfd_is_und_section (bfd_get_section (info
->symbols
[0]))
410 && ! bfd_is_abs_section (bfd_get_section (info
->symbols
[0])))
411 section
= bfd_get_section (info
->symbols
[0]);
413 /* Only guess addresses when the contents of this section is fully
414 relocated. Otherwise, the value will be zero or perhaps even
417 || section
->owner
== NULL
418 || elf_elfheader (section
->owner
)->e_type
== ET_EXEC
)
420 bfd_signed_vma shori_addr
;
422 shori_addr
= SAVED_MOVI_IMM (info
) << 16;
425 fprintf_fn (stream
, "\t! 0x");
426 (*info
->print_address_func
) (shori_addr
, info
);
430 if (op
->opcode_base
== SHMEDIA_MOVI_OPC
)
432 SAVED_MOVI_IMM (info
) = imm
;
433 SAVED_MOVI_R (info
) = r
;
437 SAVED_MOVI_IMM (info
) = 0;
438 SAVED_MOVI_R (info
) = 255;
444 /* Check the type of contents about to be disassembled. This is like
445 sh64_get_contents_type (which may be called from here), except that it
446 takes the same arguments as print_insn_* and does what can be done if
447 no section is available. */
449 static enum sh64_elf_cr_type
450 sh64_get_contents_type_disasm (bfd_vma memaddr
, struct disassemble_info
*info
)
452 struct sh64_disassemble_info
*sh64_infop
= info
->private_data
;
454 /* Perhaps we have a region from a previous probe and it still counts
456 if (sh64_infop
->crange
.cr_type
!= CRT_NONE
457 && memaddr
>= sh64_infop
->crange
.cr_addr
458 && memaddr
< sh64_infop
->crange
.cr_addr
+ sh64_infop
->crange
.cr_size
)
459 return sh64_infop
->crange
.cr_type
;
461 /* If we have a section, try and use it. */
463 && bfd_get_flavour (info
->section
->owner
) == bfd_target_elf_flavour
)
465 enum sh64_elf_cr_type cr_type
466 = sh64_get_contents_type (info
->section
, memaddr
,
467 &sh64_infop
->crange
);
469 if (cr_type
!= CRT_NONE
)
473 /* If we have symbols, we can try and get at a section from *that*. */
474 if (info
->symbols
!= NULL
475 && bfd_asymbol_flavour (info
->symbols
[0]) == bfd_target_elf_flavour
476 && ! bfd_is_und_section (bfd_get_section (info
->symbols
[0]))
477 && ! bfd_is_abs_section (bfd_get_section (info
->symbols
[0])))
479 enum sh64_elf_cr_type cr_type
480 = sh64_get_contents_type (bfd_get_section (info
->symbols
[0]),
481 memaddr
, &sh64_infop
->crange
);
483 if (cr_type
!= CRT_NONE
)
487 /* We can make a reasonable guess based on the st_other field of a
488 symbol; for a BranchTarget this is marked as STO_SH5_ISA32 and then
489 it's most probably code there. */
491 && bfd_asymbol_flavour (info
->symbols
[0]) == bfd_target_elf_flavour
492 && elf_symbol_from (bfd_asymbol_bfd (info
->symbols
[0]),
493 info
->symbols
[0])->internal_elf_sym
.st_other
495 return CRT_SH5_ISA32
;
497 /* If all else fails, guess this is code and guess on the low bit set. */
498 return (memaddr
& 1) == 1 ? CRT_SH5_ISA32
: CRT_SH5_ISA16
;
501 /* Initialize static and dynamic disassembly state. */
504 init_sh64_disasm_info (struct disassemble_info
*info
)
506 struct sh64_disassemble_info
*sh64_infop
507 = calloc (sizeof (*sh64_infop
), 1);
509 if (sh64_infop
== NULL
)
512 info
->private_data
= sh64_infop
;
514 SAVED_MOVI_IMM (info
) = 0;
515 SAVED_MOVI_R (info
) = 255;
517 if (shmedia_opcode_mask_table
== NULL
)
518 initialize_shmedia_opcode_mask_table ();
523 /* Main entry to disassemble SHmedia instructions, given an endian set in
524 INFO. Note that the simulator uses this as the main entry and does not
525 use any of the functions further below. */
528 print_insn_sh64x_media (bfd_vma memaddr
, struct disassemble_info
*info
)
530 if (info
->private_data
== NULL
&& ! init_sh64_disasm_info (info
))
533 /* Make reasonable output. */
534 info
->bytes_per_line
= 4;
535 info
->bytes_per_chunk
= 4;
537 return print_insn_shmedia (memaddr
, info
);
540 /* Main entry to disassemble SHmedia insns.
541 If we see an SHcompact instruction, return -2. */
544 print_insn_sh64 (bfd_vma memaddr
, struct disassemble_info
*info
)
546 enum bfd_endian endian
= info
->endian
;
547 enum sh64_elf_cr_type cr_type
;
549 if (info
->private_data
== NULL
&& ! init_sh64_disasm_info (info
))
552 cr_type
= sh64_get_contents_type_disasm (memaddr
, info
);
553 if (cr_type
!= CRT_SH5_ISA16
)
555 int length
= 4 - (memaddr
% 4);
556 info
->display_endian
= endian
;
558 /* If we got an uneven address to indicate SHmedia, adjust it. */
559 if (cr_type
== CRT_SH5_ISA32
&& length
== 3)
560 memaddr
--, length
= 4;
562 /* Only disassemble on four-byte boundaries. Addresses that are not
563 a multiple of four can happen after a data region. */
564 if (cr_type
== CRT_SH5_ISA32
&& length
== 4)
565 return print_insn_sh64x_media (memaddr
, info
);
567 /* We get CRT_DATA *only* for data regions in a mixed-contents
568 section. For sections with data only, we get indication of one
569 of the ISA:s. You may think that we shouldn't disassemble
570 section with only data if we can figure that out. However, the
571 disassembly function is by default not called for data-only
572 sections, so if the user explicitly specified disassembly of a
573 data section, that's what we should do. */
574 if (cr_type
== CRT_DATA
|| length
!= 4)
577 unsigned char data
[4];
578 struct sh64_disassemble_info
*sh64_infop
= info
->private_data
;
581 && sh64_infop
->crange
.cr_type
!= CRT_NONE
582 && memaddr
>= sh64_infop
->crange
.cr_addr
583 && memaddr
< (sh64_infop
->crange
.cr_addr
584 + sh64_infop
->crange
.cr_size
))
586 = (sh64_infop
->crange
.cr_addr
587 + sh64_infop
->crange
.cr_size
- memaddr
);
590 = (*info
->read_memory_func
) (memaddr
, data
,
591 length
>= 4 ? 4 : length
, info
);
593 if (status
== 0 && length
>= 4)
595 (*info
->fprintf_func
) (info
->stream
, ".long 0x%08lx",
596 endian
== BFD_ENDIAN_BIG
597 ? (long) (bfd_getb32 (data
))
598 : (long) (bfd_getl32 (data
)));
605 for (i
= 0; i
< length
; i
++)
607 status
= info
->read_memory_func (memaddr
+ i
, data
, 1, info
);
610 (*info
->fprintf_func
) (info
->stream
, "%s0x%02x",
611 i
== 0 ? ".byte " : ", ",
620 /* SH1 .. SH4 instruction, let caller handle it. */