2004-04-30 Andrew Cagney <cagney@redhat.com>
[platform/upstream/binutils.git] / opcodes / sh64-dis.c
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
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 *
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
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
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
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
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
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 }