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