Change source files over to GPLv3.
[deliverable/binutils-gdb.git] / opcodes / sh64-dis.c
CommitLineData
d28847ce 1/* Disassemble SH64 instructions.
9b201bb5 2 Copyright 2000, 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
d28847ce 3
9b201bb5
NC
4 This file is part of the GNU opcodes library.
5
6 This library is free software; you can redistribute it and/or modify
d28847ce 7 it under the terms of the GNU General Public License as published by
9b201bb5
NC
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
d28847ce 10
9b201bb5
NC
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.
d28847ce
AO
15
16 You should have received a copy of the GNU General Public License
9b201bb5
NC
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. */
d28847ce
AO
20
21#include <stdio.h>
22
23#include "dis-asm.h"
24#include "sysdep.h"
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 {
198 int i;
199
200 for (i = 0; i < 3; i++)
201 {
202 status = info->read_memory_func (memaddr + i, insn, 1, info);
203 if (status != 0)
204 break;
205 (*fprintf_fn) (stream, "%s0x%02x",
206 i == 0 ? ".byte " : ", ",
207 insn[0]);
208 }
209
210 return i ? i : -1;
211 }
212
213 /* Rearrange the bytes to make up an instruction. */
214 if (info->endian == BFD_ENDIAN_LITTLE)
215 instruction = bfd_getl32 (insn);
216 else
217 instruction = bfd_getb32 (insn);
218
219 /* FIXME: Searching could be implemented using a hash on relevant
220 fields. */
221 for (n = 0, op = shmedia_table;
222 op->name != NULL
223 && ((instruction & shmedia_opcode_mask_table[n]) != op->opcode_base);
224 n++, op++)
225 ;
226
227 /* FIXME: We should also check register number constraints. */
228 if (op->name == NULL)
229 {
0fd3a477 230 fprintf_fn (stream, ".long 0x%08lx", instruction);
d28847ce
AO
231 return 4;
232 }
233
234 fprintf_fn (stream, "%s\t", op->name);
235
236 for (i = 0; i < 3 && op->arg[i] != A_NONE; i++)
237 {
238 unsigned long temp = instruction >> op->nibbles[i];
239 int by_number = 0;
240
241 if (i > 0 && op->arg[i] != A_REUSE_PREV)
242 fprintf_fn (stream, ",");
243
244 switch (op->arg[i])
245 {
246 case A_REUSE_PREV:
247 continue;
248
249 case A_GREG_M:
250 case A_GREG_N:
251 case A_GREG_D:
252 r = temp & 0x3f;
253 fprintf_fn (stream, "r%d", r);
254 break;
255
256 case A_FVREG_F:
257 case A_FVREG_G:
258 case A_FVREG_H:
259 r = temp & 0x3f;
260 fprintf_fn (stream, "fv%d", r);
261 break;
262
263 case A_FPREG_F:
264 case A_FPREG_G:
265 case A_FPREG_H:
266 r = temp & 0x3f;
267 fprintf_fn (stream, "fp%d", r);
268 break;
269
270 case A_FMREG_F:
271 case A_FMREG_G:
272 case A_FMREG_H:
273 r = temp & 0x3f;
274 fprintf_fn (stream, "mtrx%d", r);
275 break;
276
277 case A_CREG_K:
278 case A_CREG_J:
279 {
280 const char *name;
47b0e7ad 281
d28847ce
AO
282 r = temp & 0x3f;
283
284 name = creg_name (r);
285
286 if (name != NULL)
287 fprintf_fn (stream, "%s", name);
288 else
289 fprintf_fn (stream, "cr%d", r);
290 }
291 break;
292
293 case A_FREG_G:
294 case A_FREG_H:
295 case A_FREG_F:
296 r = temp & 0x3f;
297 fprintf_fn (stream, "fr%d", r);
298 break;
299
300 case A_DREG_G:
301 case A_DREG_H:
302 case A_DREG_F:
303 r = temp & 0x3f;
304 fprintf_fn (stream, "dr%d", r);
305 break;
306
307 case A_TREG_A:
308 case A_TREG_B:
309 r = temp & 0x7;
310 fprintf_fn (stream, "tr%d", r);
311 break;
312
313 /* A signed 6-bit number. */
314 case A_IMMS6:
315 imm = temp & 0x3f;
316 if (imm & (unsigned long) 0x20)
317 imm |= ~(unsigned long) 0x3f;
0fd3a477 318 fprintf_fn (stream, "%ld", imm);
d28847ce
AO
319 break;
320
321 /* A signed 6-bit number, multiplied by 32 when used. */
322 case A_IMMS6BY32:
323 imm = temp & 0x3f;
324 if (imm & (unsigned long) 0x20)
325 imm |= ~(unsigned long) 0x3f;
0fd3a477 326 fprintf_fn (stream, "%ld", imm * 32);
d28847ce
AO
327 break;
328
329 /* A signed 10-bit number, multiplied by 8 when used. */
330 case A_IMMS10BY8:
331 by_number++;
332 /* Fall through. */
333
334 /* A signed 10-bit number, multiplied by 4 when used. */
335 case A_IMMS10BY4:
336 by_number++;
337 /* Fall through. */
338
339 /* A signed 10-bit number, multiplied by 2 when used. */
340 case A_IMMS10BY2:
341 by_number++;
342 /* Fall through. */
343
344 /* A signed 10-bit number. */
345 case A_IMMS10:
346 case A_IMMS10BY1:
347 imm = temp & 0x3ff;
348 if (imm & (unsigned long) 0x200)
349 imm |= ~(unsigned long) 0x3ff;
350 imm <<= by_number;
0fd3a477 351 fprintf_fn (stream, "%ld", imm);
d28847ce
AO
352 break;
353
354 /* A signed 16-bit number. */
355 case A_IMMS16:
356 imm = temp & 0xffff;
357 if (imm & (unsigned long) 0x8000)
358 imm |= ~((unsigned long) 0xffff);
0fd3a477 359 fprintf_fn (stream, "%ld", imm);
d28847ce
AO
360 break;
361
362 /* A PC-relative signed 16-bit number, multiplied by 4 when
363 used. */
364 case A_PCIMMS16BY4:
365 imm = temp & 0xffff; /* 16 bits */
366 if (imm & (unsigned long) 0x8000)
367 imm |= ~(unsigned long) 0xffff;
368 imm <<= 2;
369 disp_pc_addr = (bfd_vma) imm + memaddr;
370 (*info->print_address_func) (disp_pc_addr, info);
371 break;
372
373 /* An unsigned 5-bit number. */
374 case A_IMMU5:
375 imm = temp & 0x1f;
0fd3a477 376 fprintf_fn (stream, "%ld", imm);
d28847ce
AO
377 break;
378
379 /* An unsigned 6-bit number. */
380 case A_IMMU6:
381 imm = temp & 0x3f;
0fd3a477 382 fprintf_fn (stream, "%ld", imm);
d28847ce
AO
383 break;
384
385 /* An unsigned 16-bit number. */
386 case A_IMMU16:
387 imm = temp & 0xffff;
0fd3a477 388 fprintf_fn (stream, "%ld", imm);
d28847ce
AO
389 break;
390
391 default:
392 abort ();
393 break;
394 }
395 }
396
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)
401 {
402 asection *section = info->section;
403
404 /* Most callers do not set the section field correctly yet. Revert
405 to getting the section from symbols, if any. */
406 if (section == NULL
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]);
412
413 /* Only guess addresses when the contents of this section is fully
414 relocated. Otherwise, the value will be zero or perhaps even
415 bogus. */
416 if (section == NULL
417 || section->owner == NULL
418 || elf_elfheader (section->owner)->e_type == ET_EXEC)
419 {
420 bfd_signed_vma shori_addr;
421
422 shori_addr = SAVED_MOVI_IMM (info) << 16;
423 shori_addr |= imm;
424
425 fprintf_fn (stream, "\t! 0x");
426 (*info->print_address_func) (shori_addr, info);
427 }
428 }
429
430 if (op->opcode_base == SHMEDIA_MOVI_OPC)
431 {
432 SAVED_MOVI_IMM (info) = imm;
433 SAVED_MOVI_R (info) = r;
434 }
435 else
436 {
437 SAVED_MOVI_IMM (info) = 0;
438 SAVED_MOVI_R (info) = 255;
439 }
440
441 return 4;
442}
443
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. */
448
449static enum sh64_elf_cr_type
47b0e7ad 450sh64_get_contents_type_disasm (bfd_vma memaddr, struct disassemble_info *info)
d28847ce
AO
451{
452 struct sh64_disassemble_info *sh64_infop = info->private_data;
453
454 /* Perhaps we have a region from a previous probe and it still counts
455 for this address? */
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;
460
461 /* If we have a section, try and use it. */
462 if (info->section
463 && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour)
464 {
465 enum sh64_elf_cr_type cr_type
466 = sh64_get_contents_type (info->section, memaddr,
467 &sh64_infop->crange);
468
469 if (cr_type != CRT_NONE)
470 return cr_type;
471 }
472
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])))
478 {
479 enum sh64_elf_cr_type cr_type
480 = sh64_get_contents_type (bfd_get_section (info->symbols[0]),
481 memaddr, &sh64_infop->crange);
482
483 if (cr_type != CRT_NONE)
484 return cr_type;
485 }
486
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. */
490 if (info->symbols
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
494 == STO_SH5_ISA32)
495 return CRT_SH5_ISA32;
496
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;
499}
500
501/* Initialize static and dynamic disassembly state. */
502
b34976b6 503static bfd_boolean
47b0e7ad 504init_sh64_disasm_info (struct disassemble_info *info)
d28847ce
AO
505{
506 struct sh64_disassemble_info *sh64_infop
507 = calloc (sizeof (*sh64_infop), 1);
508
509 if (sh64_infop == NULL)
b34976b6 510 return FALSE;
d28847ce
AO
511
512 info->private_data = sh64_infop;
513
514 SAVED_MOVI_IMM (info) = 0;
515 SAVED_MOVI_R (info) = 255;
516
517 if (shmedia_opcode_mask_table == NULL)
518 initialize_shmedia_opcode_mask_table ();
519
b34976b6 520 return TRUE;
d28847ce
AO
521}
522
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. */
526
b34976b6 527int
47b0e7ad 528print_insn_sh64x_media (bfd_vma memaddr, struct disassemble_info *info)
d28847ce
AO
529{
530 if (info->private_data == NULL && ! init_sh64_disasm_info (info))
531 return -1;
532
533 /* Make reasonable output. */
534 info->bytes_per_line = 4;
535 info->bytes_per_chunk = 4;
536
537 return print_insn_shmedia (memaddr, info);
538}
539
1c509ca8
JR
540/* Main entry to disassemble SHmedia insns.
541 If we see an SHcompact instruction, return -2. */
d28847ce 542
b34976b6 543int
47b0e7ad 544print_insn_sh64 (bfd_vma memaddr, struct disassemble_info *info)
d28847ce 545{
1c509ca8 546 enum bfd_endian endian = info->endian;
d28847ce
AO
547 enum sh64_elf_cr_type cr_type;
548
549 if (info->private_data == NULL && ! init_sh64_disasm_info (info))
550 return -1;
551
552 cr_type = sh64_get_contents_type_disasm (memaddr, info);
553 if (cr_type != CRT_SH5_ISA16)
554 {
555 int length = 4 - (memaddr % 4);
556 info->display_endian = endian;
557
1c509ca8
JR
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;
561
d28847ce
AO
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);
566
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)
575 {
576 int status;
577 unsigned char data[4];
578 struct sh64_disassemble_info *sh64_infop = info->private_data;
579
580 if (length == 4
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))
585 length
586 = (sh64_infop->crange.cr_addr
587 + sh64_infop->crange.cr_size - memaddr);
588
589 status
590 = (*info->read_memory_func) (memaddr, data,
591 length >= 4 ? 4 : length, info);
592
593 if (status == 0 && length >= 4)
594 {
595 (*info->fprintf_func) (info->stream, ".long 0x%08lx",
596 endian == BFD_ENDIAN_BIG
597 ? (long) (bfd_getb32 (data))
598 : (long) (bfd_getl32 (data)));
599 return 4;
600 }
601 else
602 {
603 int i;
604
605 for (i = 0; i < length; i++)
606 {
607 status = info->read_memory_func (memaddr + i, data, 1, info);
608 if (status != 0)
609 break;
610 (*info->fprintf_func) (info->stream, "%s0x%02x",
611 i == 0 ? ".byte " : ", ",
612 data[0]);
613 }
614
615 return i ? i : -1;
616 }
617 }
618 }
619
1c509ca8
JR
620 /* SH1 .. SH4 instruction, let caller handle it. */
621 return -2;
d28847ce 622}
This page took 0.263889 seconds and 4 git commands to generate.