1/* Disassemble SH64 instructions.
2   Copyright 2000, 2001, 2002, 2003, 2005, 2007 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 <stdio.h>
22
23#include "dis-asm.h"
24#include "sysdep.h"
25#include "sh64-opc.h"
26#include "libiberty.h"
27/* We need to refer to the ELF header structure.  */
28#include "elf-bfd.h"
29#include "elf/sh.h"
30#include "elf32-sh64.h"
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
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.  */
57static unsigned long *shmedia_opcode_mask_table;
58
59/* Initialize the SH64 opcode mask table for each instruction in SHmedia
60   mode.  */
61
62static void
63initialize_shmedia_opcode_mask_table (void)
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;
85
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
117	    case A_IMMM:
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
161static const char *
162creg_name (int cregno)
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++)
169    if (cregp->cregno == cregno)
170      return cregp->name;
171
172  return NULL;
173}
174
175/* Main function to disassemble SHmedia instructions.  */
176
177static int
178print_insn_shmedia (bfd_vma memaddr, struct disassemble_info *info)
179{
180  fprintf_ftype fprintf_fn = info->fprintf_func;
181  void *stream = info->stream;
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    {
230      fprintf_fn (stream, ".long 0x%08lx", instruction);
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;
281
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;
318	  fprintf_fn (stream, "%ld", imm);
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;
326	  fprintf_fn (stream, "%ld", imm * 32);
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;
351	  fprintf_fn (stream, "%ld", imm);
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);
359	  fprintf_fn (stream, "%ld", imm);
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;
376	  fprintf_fn (stream, "%ld", imm);
377	  break;
378
379	  /* An unsigned 6-bit number.  */
380	case A_IMMU6:
381	  imm = temp & 0x3f;
382	  fprintf_fn (stream, "%ld", imm);
383	  break;
384
385	  /* An unsigned 16-bit number.  */
386	case A_IMMU16:
387	  imm = temp & 0xffff;
388	  fprintf_fn (stream, "%ld", imm);
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
450sh64_get_contents_type_disasm (bfd_vma memaddr, struct disassemble_info *info)
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
503static bfd_boolean
504init_sh64_disasm_info (struct disassemble_info *info)
505{
506  struct sh64_disassemble_info *sh64_infop
507    = calloc (sizeof (*sh64_infop), 1);
508
509  if (sh64_infop == NULL)
510    return FALSE;
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
520  return TRUE;
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
527int
528print_insn_sh64x_media (bfd_vma memaddr, struct disassemble_info *info)
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
540/* Main entry to disassemble SHmedia insns.
541   If we see an SHcompact instruction, return -2.  */
542
543int
544print_insn_sh64 (bfd_vma memaddr, struct disassemble_info *info)
545{
546  enum bfd_endian endian = info->endian;
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
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
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
620  /* SH1 .. SH4 instruction, let caller handle it.  */
621  return -2;
622}
623