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