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