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 
39 struct 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.  */
55 static unsigned long *shmedia_opcode_mask_table;
56 
57 static void initialize_shmedia_opcode_mask_table PARAMS ((void));
58 static int print_insn_shmedia PARAMS ((bfd_vma, disassemble_info *));
59 static const char *creg_name PARAMS ((int));
60 static bfd_boolean init_sh64_disasm_info PARAMS ((struct disassemble_info *));
61 static 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 
67 static void
initialize_shmedia_opcode_mask_table()68 initialize_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 
166 const char *
creg_name(cregno)167 creg_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 
185 static int
print_insn_shmedia(memaddr,info)186 print_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 
459 static enum sh64_elf_cr_type
sh64_get_contents_type_disasm(memaddr,info)460 sh64_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 
515 static bfd_boolean
init_sh64_disasm_info(info)516 init_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 
540 int
print_insn_sh64x_media(memaddr,info)541 print_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 
558 int
print_insn_sh64(memaddr,info)559 print_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