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