OSDN Git Service

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