OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [opcodes/] [arm-dis.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* Instruction printing code for the ARM
2
   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
3
   Free Software Foundation, Inc.
4
   Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5
   Modification by James G. Smith (jsmith@cygnus.co.uk)
6
 
7
This file is part of libopcodes.
8
 
9
This program is free software; you can redistribute it and/or modify it under
10
the terms of the GNU General Public License as published by the Free
11
Software Foundation; either version 2 of the License, or (at your option)
12
any later version.
13
 
14
This program is distributed in the hope that it will be useful, but WITHOUT
15
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
17
more details.
18
 
19
You should have received a copy of the GNU General Public License
20
along with this program; if not, write to the Free Software
21
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
22
 
23
#include "sysdep.h"
24
#include "dis-asm.h"
25
#define DEFINE_TABLE
26
#include "arm-opc.h"
27
#include "coff/internal.h"
28
#include "libcoff.h"
29
#include "opintl.h"
30
 
31
/* FIXME: This shouldn't be done here */
32
#include "elf-bfd.h"
33
#include "elf/internal.h"
34
#include "elf/arm.h"
35
 
36
#ifndef streq
37
#define streq(a,b)      (strcmp ((a), (b)) == 0)
38
#endif
39
 
40
#ifndef strneq
41
#define strneq(a,b,n)   (strncmp ((a), (b), (n)) == 0)
42
#endif
43
 
44
#ifndef NUM_ELEM
45
#define NUM_ELEM(a)     (sizeof (a) / sizeof (a)[0])
46
#endif
47
 
48
static char * arm_conditional[] =
49
{"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
50
 "hi", "ls", "ge", "lt", "gt", "le", "", "nv"};
51
 
52
typedef struct
53
{
54
  const char * name;
55
  const char * description;
56
  const char * reg_names[16];
57
}
58
arm_regname;
59
 
60
static arm_regname regnames[] =
61
{
62
  { "raw" , "Select raw register names",
63
    { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}},
64
  { "gcc",  "Select register names used by GCC",
65
    { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl",  "fp",  "ip",  "sp",  "lr",  "pc" }},
66
  { "std",  "Select register names used in ARM's ISA documentation",
67
    { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp",  "lr",  "pc" }},
68
  { "apcs", "Select register names used in the APCS",
69
    { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl",  "fp",  "ip",  "sp",  "lr",  "pc" }},
70
  { "atpcs", "Select register names used in the ATPCS",
71
    { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7",  "v8",  "IP",  "SP",  "LR",  "PC" }},
72
  { "special-atpcs", "Select special register names used in the ATPCS",
73
    { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL",  "FP",  "IP",  "SP",  "LR",  "PC" }}
74
};
75
 
76
/* Default to GCC register name set.  */
77
static unsigned int regname_selected = 1;
78
 
79
#define NUM_ARM_REGNAMES  NUM_ELEM (regnames)
80
#define arm_regnames      regnames[regname_selected].reg_names
81
 
82
static boolean force_thumb = false;
83
 
84
static char * arm_fp_const[] =
85
{"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
86
 
87
static char * arm_shift[] =
88
{"lsl", "lsr", "asr", "ror"};
89
 
90
/* Forward declarations.  */
91
static void arm_decode_shift PARAMS ((long, fprintf_ftype, void *));
92
static int  print_insn_arm   PARAMS ((bfd_vma, struct disassemble_info *, long));
93
static int  print_insn_thumb PARAMS ((bfd_vma, struct disassemble_info *, long));
94
static void parse_disassembler_options PARAMS ((char *));
95
static int  print_insn       PARAMS ((bfd_vma, struct disassemble_info *, boolean));
96
int get_arm_regname_num_options (void);
97
int set_arm_regname_option (int option);
98
int get_arm_regnames (int option, const char **setname,
99
                      const char **setdescription,
100
                      const char ***register_names);
101
 
102
/* Functions. */
103
int
104
get_arm_regname_num_options (void)
105
{
106
  return NUM_ARM_REGNAMES;
107
}
108
 
109
int
110
set_arm_regname_option (int option)
111
{
112
  int old = regname_selected;
113
  regname_selected = option;
114
  return old;
115
}
116
 
117
int
118
get_arm_regnames (int option, const char **setname,
119
                  const char **setdescription,
120
                  const char ***register_names)
121
{
122
  *setname = regnames[option].name;
123
  *setdescription = regnames[option].description;
124
  *register_names = regnames[option].reg_names;
125
  return 16;
126
}
127
 
128
static void
129
arm_decode_shift (given, func, stream)
130
     long given;
131
     fprintf_ftype func;
132
     void * stream;
133
{
134
  func (stream, "%s", arm_regnames[given & 0xf]);
135
 
136
  if ((given & 0xff0) != 0)
137
    {
138
      if ((given & 0x10) == 0)
139
        {
140
          int amount = (given & 0xf80) >> 7;
141
          int shift = (given & 0x60) >> 5;
142
 
143
          if (amount == 0)
144
            {
145
              if (shift == 3)
146
                {
147
                  func (stream, ", rrx");
148
                  return;
149
                }
150
 
151
              amount = 32;
152
            }
153
 
154
          func (stream, ", %s #%d", arm_shift[shift], amount);
155
        }
156
      else
157
        func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5],
158
              arm_regnames[(given & 0xf00) >> 8]);
159
    }
160
}
161
 
162
/* Print one instruction from PC on INFO->STREAM.
163
   Return the size of the instruction (always 4 on ARM). */
164
static int
165
print_insn_arm (pc, info, given)
166
     bfd_vma                   pc;
167
     struct disassemble_info * info;
168
     long                      given;
169
{
170
  struct arm_opcode *  insn;
171
  void *               stream = info->stream;
172
  fprintf_ftype        func   = info->fprintf_func;
173
 
174
  for (insn = arm_opcodes; insn->assembler; insn++)
175
    {
176
      if ((given & insn->mask) == insn->value)
177
        {
178
          char * c;
179
 
180
          for (c = insn->assembler; *c; c++)
181
            {
182
              if (*c == '%')
183
                {
184
                  switch (*++c)
185
                    {
186
                    case '%':
187
                      func (stream, "%%");
188
                      break;
189
 
190
                    case 'a':
191
                      if (((given & 0x000f0000) == 0x000f0000)
192
                          && ((given & 0x02000000) == 0))
193
                        {
194
                          int offset = given & 0xfff;
195
 
196
                          func (stream, "[pc");
197
 
198
                          if (given & 0x01000000)
199
                            {
200
                              if ((given & 0x00800000) == 0)
201
                                offset = - offset;
202
 
203
                              /* pre-indexed */
204
                              func (stream, ", #%x]", offset);
205
 
206
                              offset += pc + 8;
207
 
208
                              /* Cope with the possibility of write-back
209
                                 being used.  Probably a very dangerous thing
210
                                 for the programmer to do, but who are we to
211
                                 argue ?  */
212
                              if (given & 0x00200000)
213
                                func (stream, "!");
214
                            }
215
                          else
216
                            {
217
                              /* Post indexed.  */
218
                              func (stream, "], #%x", offset);
219
 
220
                              offset = pc + 8;  /* ie ignore the offset.  */
221
                            }
222
 
223
                          func (stream, "\t; ");
224
                          info->print_address_func (offset, info);
225
                        }
226
                      else
227
                        {
228
                          func (stream, "[%s",
229
                                arm_regnames[(given >> 16) & 0xf]);
230
                          if ((given & 0x01000000) != 0)
231
                            {
232
                              if ((given & 0x02000000) == 0)
233
                                {
234
                                  int offset = given & 0xfff;
235
                                  if (offset)
236
                                    func (stream, ", %s#%d",
237
                                          (((given & 0x00800000) == 0)
238
                                           ? "-" : ""), offset);
239
                                }
240
                              else
241
                                {
242
                                  func (stream, ", %s",
243
                                        (((given & 0x00800000) == 0)
244
                                         ? "-" : ""));
245
                                  arm_decode_shift (given, func, stream);
246
                                }
247
 
248
                              func (stream, "]%s",
249
                                    ((given & 0x00200000) != 0) ? "!" : "");
250
                            }
251
                          else
252
                            {
253
                              if ((given & 0x02000000) == 0)
254
                                {
255
                                  int offset = given & 0xfff;
256
                                  if (offset)
257
                                    func (stream, "], %s#%d",
258
                                          (((given & 0x00800000) == 0)
259
                                           ? "-" : ""), offset);
260
                                  else
261
                                    func (stream, "]");
262
                                }
263
                              else
264
                                {
265
                                  func (stream, "], %s",
266
                                        (((given & 0x00800000) == 0)
267
                                         ? "-" : ""));
268
                                  arm_decode_shift (given, func, stream);
269
                                }
270
                            }
271
                        }
272
                      break;
273
 
274
                    case 's':
275
                      if ((given & 0x004f0000) == 0x004f0000)
276
                        {
277
                          /* PC relative with immediate offset.  */
278
                          int offset = ((given & 0xf00) >> 4) | (given & 0xf);
279
 
280
                          if ((given & 0x00800000) == 0)
281
                            offset = -offset;
282
 
283
                          func (stream, "[pc, #%x]\t; ", offset);
284
 
285
                          (*info->print_address_func)
286
                            (offset + pc + 8, info);
287
                        }
288
                      else
289
                        {
290
                          func (stream, "[%s",
291
                                arm_regnames[(given >> 16) & 0xf]);
292
                          if ((given & 0x01000000) != 0)
293
                            {
294
                              /* Pre-indexed.  */
295
                              if ((given & 0x00400000) == 0x00400000)
296
                                {
297
                                  /* Immediate.  */
298
                                  int offset = ((given & 0xf00) >> 4) | (given & 0xf);
299
                                  if (offset)
300
                                    func (stream, ", %s#%d",
301
                                          (((given & 0x00800000) == 0)
302
                                           ? "-" : ""), offset);
303
                                }
304
                              else
305
                                {
306
                                  /* Register.  */
307
                                  func (stream, ", %s%s",
308
                                        (((given & 0x00800000) == 0)
309
                                         ? "-" : ""),
310
                                        arm_regnames[given & 0xf]);
311
                                }
312
 
313
                              func (stream, "]%s",
314
                                    ((given & 0x00200000) != 0) ? "!" : "");
315
                            }
316
                          else
317
                            {
318
                              /* Post-indexed.  */
319
                              if ((given & 0x00400000) == 0x00400000)
320
                                {
321
                                  /* Immediate.  */
322
                                  int offset = ((given & 0xf00) >> 4) | (given & 0xf);
323
                                  if (offset)
324
                                    func (stream, "], %s#%d",
325
                                          (((given & 0x00800000) == 0)
326
                                           ? "-" : ""), offset);
327
                                  else
328
                                    func (stream, "]");
329
                                }
330
                              else
331
                                {
332
                                  /* Register.  */
333
                                  func (stream, "], %s%s",
334
                                        (((given & 0x00800000) == 0)
335
                                         ? "-" : ""),
336
                                        arm_regnames[given & 0xf]);
337
                                }
338
                            }
339
                        }
340
                      break;
341
 
342
                    case 'b':
343
                      (*info->print_address_func)
344
                        (BDISP (given) * 4 + pc + 8, info);
345
                      break;
346
 
347
                    case 'c':
348
                      func (stream, "%s",
349
                            arm_conditional [(given >> 28) & 0xf]);
350
                      break;
351
 
352
                    case 'm':
353
                      {
354
                        int started = 0;
355
                        int reg;
356
 
357
                        func (stream, "{");
358
                        for (reg = 0; reg < 16; reg++)
359
                          if ((given & (1 << reg)) != 0)
360
                            {
361
                              if (started)
362
                                func (stream, ", ");
363
                              started = 1;
364
                              func (stream, "%s", arm_regnames[reg]);
365
                            }
366
                        func (stream, "}");
367
                      }
368
                      break;
369
 
370
                    case 'o':
371
                      if ((given & 0x02000000) != 0)
372
                        {
373
                          int rotate = (given & 0xf00) >> 7;
374
                          int immed = (given & 0xff);
375
                          immed = (((immed << (32 - rotate))
376
                                    | (immed >> rotate)) & 0xffffffff);
377
                          func (stream, "#%d\t; 0x%x", immed, immed);
378
                        }
379
                      else
380
                        arm_decode_shift (given, func, stream);
381
                      break;
382
 
383
                    case 'p':
384
                      if ((given & 0x0000f000) == 0x0000f000)
385
                        func (stream, "p");
386
                      break;
387
 
388
                    case 't':
389
                      if ((given & 0x01200000) == 0x00200000)
390
                        func (stream, "t");
391
                      break;
392
 
393
                    case 'h':
394
                      if ((given & 0x00000020) == 0x00000020)
395
                        func (stream, "h");
396
                      else
397
                        func (stream, "b");
398
                      break;
399
 
400
                    case 'A':
401
                      func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
402
                      if ((given & 0x01000000) != 0)
403
                        {
404
                          int offset = given & 0xff;
405
                          if (offset)
406
                            func (stream, ", %s#%d]%s",
407
                                  ((given & 0x00800000) == 0 ? "-" : ""),
408
                                  offset * 4,
409
                                  ((given & 0x00200000) != 0 ? "!" : ""));
410
                          else
411
                            func (stream, "]");
412
                        }
413
                      else
414
                        {
415
                          int offset = given & 0xff;
416
                          if (offset)
417
                            func (stream, "], %s#%d",
418
                                  ((given & 0x00800000) == 0 ? "-" : ""),
419
                                  offset * 4);
420
                          else
421
                            func (stream, "]");
422
                        }
423
                      break;
424
 
425
                    case 'B':
426
                      /* Print ARM V5 BLX(1) address: pc+25 bits.  */
427
                      {
428
                        bfd_vma address;
429
                        bfd_vma offset = 0;
430
 
431
                        if (given & 0x00800000)
432
                          /* Is signed, hi bits should be ones.  */
433
                          offset = (-1) ^ 0x00ffffff;
434
 
435
                        /* Offset is (SignExtend(offset field)<<2).  */
436
                        offset += given & 0x00ffffff;
437
                        offset <<= 2;
438
                        address = offset + pc + 8;
439
 
440
                        if (given & 0x01000000)
441
                          /* H bit allows addressing to 2-byte boundaries.  */
442
                          address += 2;
443
 
444
                        info->print_address_func (address, info);
445
                      }
446
                      break;
447
 
448
                    case 'C':
449
                      func (stream, "_");
450
                      if (given & 0x80000)
451
                        func (stream, "f");
452
                      if (given & 0x40000)
453
                        func (stream, "s");
454
                      if (given & 0x20000)
455
                        func (stream, "x");
456
                      if (given & 0x10000)
457
                        func (stream, "c");
458
                      break;
459
 
460
                    case 'F':
461
                      switch (given & 0x00408000)
462
                        {
463
                        case 0:
464
                          func (stream, "4");
465
                          break;
466
                        case 0x8000:
467
                          func (stream, "1");
468
                          break;
469
                        case 0x00400000:
470
                          func (stream, "2");
471
                          break;
472
                        default:
473
                          func (stream, "3");
474
                        }
475
                      break;
476
 
477
                    case 'P':
478
                      switch (given & 0x00080080)
479
                        {
480
                        case 0:
481
                          func (stream, "s");
482
                          break;
483
                        case 0x80:
484
                          func (stream, "d");
485
                          break;
486
                        case 0x00080000:
487
                          func (stream, "e");
488
                          break;
489
                        default:
490
                          func (stream, _("<illegal precision>"));
491
                          break;
492
                        }
493
                      break;
494
                    case 'Q':
495
                      switch (given & 0x00408000)
496
                        {
497
                        case 0:
498
                          func (stream, "s");
499
                          break;
500
                        case 0x8000:
501
                          func (stream, "d");
502
                          break;
503
                        case 0x00400000:
504
                          func (stream, "e");
505
                          break;
506
                        default:
507
                          func (stream, "p");
508
                          break;
509
                        }
510
                      break;
511
                    case 'R':
512
                      switch (given & 0x60)
513
                        {
514
                        case 0:
515
                          break;
516
                        case 0x20:
517
                          func (stream, "p");
518
                          break;
519
                        case 0x40:
520
                          func (stream, "m");
521
                          break;
522
                        default:
523
                          func (stream, "z");
524
                          break;
525
                        }
526
                      break;
527
 
528
                    case '0': case '1': case '2': case '3': case '4':
529
                    case '5': case '6': case '7': case '8': case '9':
530
                      {
531
                        int bitstart = *c++ - '0';
532
                        int bitend = 0;
533
                        while (*c >= '0' && *c <= '9')
534
                          bitstart = (bitstart * 10) + *c++ - '0';
535
 
536
                        switch (*c)
537
                          {
538
                          case '-':
539
                            c++;
540
 
541
                            while (*c >= '0' && *c <= '9')
542
                              bitend = (bitend * 10) + *c++ - '0';
543
 
544
                            if (!bitend)
545
                              abort ();
546
 
547
                            switch (*c)
548
                              {
549
                              case 'r':
550
                                {
551
                                  long reg;
552
 
553
                                  reg = given >> bitstart;
554
                                  reg &= (2 << (bitend - bitstart)) - 1;
555
 
556
                                  func (stream, "%s", arm_regnames[reg]);
557
                                }
558
                                break;
559
                              case 'd':
560
                                {
561
                                  long reg;
562
 
563
                                  reg = given >> bitstart;
564
                                  reg &= (2 << (bitend - bitstart)) - 1;
565
 
566
                                  func (stream, "%d", reg);
567
                                }
568
                                break;
569
                              case 'x':
570
                                {
571
                                  long reg;
572
 
573
                                  reg = given >> bitstart;
574
                                  reg &= (2 << (bitend - bitstart)) - 1;
575
 
576
                                  func (stream, "0x%08x", reg);
577
 
578
                                  /* Some SWI instructions have special
579
                                     meanings.  */
580
                                  if ((given & 0x0fffffff) == 0x0FF00000)
581
                                    func (stream, "\t; IMB");
582
                                  else if ((given & 0x0fffffff) == 0x0FF00001)
583
                                    func (stream, "\t; IMBRange");
584
                                }
585
                                break;
586
                              case 'X':
587
                                {
588
                                  long reg;
589
 
590
                                  reg = given >> bitstart;
591
                                  reg &= (2 << (bitend - bitstart)) - 1;
592
 
593
                                  func (stream, "%01x", reg & 0xf);
594
                                }
595
                                break;
596
                              case 'f':
597
                                {
598
                                  long reg;
599
 
600
                                  reg = given >> bitstart;
601
                                  reg &= (2 << (bitend - bitstart)) - 1;
602
 
603
                                  if (reg > 7)
604
                                    func (stream, "#%s",
605
                                          arm_fp_const[reg & 7]);
606
                                  else
607
                                    func (stream, "f%d", reg);
608
                                }
609
                                break;
610
                              default:
611
                                abort ();
612
                              }
613
                            break;
614
 
615
                          case '`':
616
                            c++;
617
                            if ((given & (1 << bitstart)) == 0)
618
                              func (stream, "%c", *c);
619
                            break;
620
                          case '\'':
621
                            c++;
622
                            if ((given & (1 << bitstart)) != 0)
623
                              func (stream, "%c", *c);
624
                            break;
625
                          case '?':
626
                            ++c;
627
                            if ((given & (1 << bitstart)) != 0)
628
                              func (stream, "%c", *c++);
629
                            else
630
                              func (stream, "%c", *++c);
631
                            break;
632
                          default:
633
                            abort ();
634
                          }
635
                        break;
636
 
637
                      default:
638
                        abort ();
639
                      }
640
                    }
641
                }
642
              else
643
                func (stream, "%c", *c);
644
            }
645
          return 4;
646
        }
647
    }
648
  abort ();
649
}
650
 
651
/* Print one instruction from PC on INFO->STREAM.
652
   Return the size of the instruction. */
653
static int
654
print_insn_thumb (pc, info, given)
655
     bfd_vma                   pc;
656
     struct disassemble_info * info;
657
     long                      given;
658
{
659
  struct thumb_opcode * insn;
660
  void *                stream = info->stream;
661
  fprintf_ftype         func = info->fprintf_func;
662
 
663
  for (insn = thumb_opcodes; insn->assembler; insn++)
664
    {
665
      if ((given & insn->mask) == insn->value)
666
        {
667
          char * c = insn->assembler;
668
 
669
          /* Special processing for Thumb 2 instruction BL sequence:  */
670
          if (!*c) /* Check for empty (not NULL) assembler string.  */
671
            {
672
              long offset;
673
 
674
              info->bytes_per_chunk = 4;
675
              info->bytes_per_line  = 4;
676
 
677
              offset = BDISP23 (given);
678
 
679
              if ((given & 0x10000000) == 0)
680
                {
681
                  func (stream, "blx\t");
682
 
683
                  /* The spec says that bit 1 of the branch's destination
684
                     address comes from bit 1 of the instruction's
685
                     address and not from the offset in the instruction.  */
686
                  if (offset & 0x1)
687
                    {
688
                      /* func (stream, "*malformed!* "); */
689
                      offset &= ~ 0x1;
690
                    }
691
 
692
                  offset |= ((pc & 0x2) >> 1);
693
                }
694
              else
695
                func (stream, "bl\t");
696
 
697
              info->print_address_func (offset * 2 + pc + 4, info);
698
              return 4;
699
            }
700
          else
701
            {
702
              info->bytes_per_chunk = 2;
703
              info->bytes_per_line  = 4;
704
 
705
              given &= 0xffff;
706
 
707
              for (; *c; c++)
708
                {
709
                  if (*c == '%')
710
                    {
711
                      int domaskpc = 0;
712
                      int domasklr = 0;
713
 
714
                      switch (*++c)
715
                        {
716
                        case '%':
717
                          func (stream, "%%");
718
                          break;
719
 
720
                        case 'S':
721
                          {
722
                            long reg;
723
 
724
                            reg = (given >> 3) & 0x7;
725
                            if (given & (1 << 6))
726
                              reg += 8;
727
 
728
                            func (stream, "%s", arm_regnames[reg]);
729
                          }
730
                          break;
731
 
732
                        case 'D':
733
                          {
734
                            long reg;
735
 
736
                            reg = given & 0x7;
737
                            if (given & (1 << 7))
738
                             reg += 8;
739
 
740
                            func (stream, "%s", arm_regnames[reg]);
741
                          }
742
                          break;
743
 
744
                        case 'T':
745
                          func (stream, "%s",
746
                                arm_conditional [(given >> 8) & 0xf]);
747
                          break;
748
 
749
                        case 'N':
750
                          if (given & (1 << 8))
751
                            domasklr = 1;
752
                          /* Fall through.  */
753
                        case 'O':
754
                          if (*c == 'O' && (given & (1 << 8)))
755
                            domaskpc = 1;
756
                          /* Fall through.  */
757
                        case 'M':
758
                          {
759
                            int started = 0;
760
                            int reg;
761
 
762
                            func (stream, "{");
763
 
764
                            /* It would be nice if we could spot
765
                               ranges, and generate the rS-rE format: */
766
                            for (reg = 0; (reg < 8); reg++)
767
                              if ((given & (1 << reg)) != 0)
768
                                {
769
                                  if (started)
770
                                    func (stream, ", ");
771
                                  started = 1;
772
                                  func (stream, "%s", arm_regnames[reg]);
773
                                }
774
 
775
                            if (domasklr)
776
                              {
777
                                if (started)
778
                                  func (stream, ", ");
779
                                started = 1;
780
                                func (stream, arm_regnames[14] /* "lr" */);
781
                              }
782
 
783
                            if (domaskpc)
784
                              {
785
                                if (started)
786
                                  func (stream, ", ");
787
                                func (stream, arm_regnames[15] /* "pc" */);
788
                              }
789
 
790
                            func (stream, "}");
791
                          }
792
                          break;
793
 
794
 
795
                        case '0': case '1': case '2': case '3': case '4':
796
                        case '5': case '6': case '7': case '8': case '9':
797
                          {
798
                            int bitstart = *c++ - '0';
799
                            int bitend = 0;
800
 
801
                            while (*c >= '0' && *c <= '9')
802
                              bitstart = (bitstart * 10) + *c++ - '0';
803
 
804
                            switch (*c)
805
                              {
806
                              case '-':
807
                                {
808
                                  long reg;
809
 
810
                                  c++;
811
                                  while (*c >= '0' && *c <= '9')
812
                                    bitend = (bitend * 10) + *c++ - '0';
813
                                  if (!bitend)
814
                                    abort ();
815
                                  reg = given >> bitstart;
816
                                  reg &= (2 << (bitend - bitstart)) - 1;
817
                                  switch (*c)
818
                                    {
819
                                    case 'r':
820
                                      func (stream, "%s", arm_regnames[reg]);
821
                                      break;
822
 
823
                                    case 'd':
824
                                      func (stream, "%d", reg);
825
                                      break;
826
 
827
                                    case 'H':
828
                                      func (stream, "%d", reg << 1);
829
                                      break;
830
 
831
                                    case 'W':
832
                                      func (stream, "%d", reg << 2);
833
                                      break;
834
 
835
                                    case 'a':
836
                                      /* PC-relative address -- the bottom two
837
                                         bits of the address are dropped
838
                                         before the calculation.  */
839
                                      info->print_address_func
840
                                        (((pc + 4) & ~3) + (reg << 2), info);
841
                                      break;
842
 
843
                                    case 'x':
844
                                      func (stream, "0x%04x", reg);
845
                                      break;
846
 
847
                                    case 'I':
848
                                      reg = ((reg ^ (1 << bitend)) - (1 << bitend));
849
                                      func (stream, "%d", reg);
850
                                      break;
851
 
852
                                    case 'B':
853
                                      reg = ((reg ^ (1 << bitend)) - (1 << bitend));
854
                                      (*info->print_address_func)
855
                                        (reg * 2 + pc + 4, info);
856
                                      break;
857
 
858
                                    default:
859
                                      abort ();
860
                                    }
861
                                }
862
                                break;
863
 
864
                              case '\'':
865
                                c++;
866
                                if ((given & (1 << bitstart)) != 0)
867
                                  func (stream, "%c", *c);
868
                                break;
869
 
870
                              case '?':
871
                                ++c;
872
                                if ((given & (1 << bitstart)) != 0)
873
                                  func (stream, "%c", *c++);
874
                                else
875
                                  func (stream, "%c", *++c);
876
                                break;
877
 
878
                              default:
879
                                 abort ();
880
                              }
881
                          }
882
                          break;
883
 
884
                        default:
885
                          abort ();
886
                        }
887
                    }
888
                  else
889
                    func (stream, "%c", *c);
890
                }
891
             }
892
          return 2;
893
       }
894
    }
895
 
896
  /* No match.  */
897
  abort ();
898
}
899
 
900
/* Parse an individual disassembler option.  */
901
void
902
parse_arm_disassembler_option (option)
903
     char * option;
904
{
905
  if (option == NULL)
906
    return;
907
 
908
  if (strneq (option, "reg-names-", 10))
909
    {
910
      int i;
911
 
912
      option += 10;
913
 
914
      for (i = NUM_ARM_REGNAMES; i--;)
915
        if (streq (option, regnames[i].name))
916
          {
917
            regname_selected = i;
918
            break;
919
          }
920
 
921
      if (i < 0)
922
        fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
923
    }
924
  else if (streq (option, "force-thumb"))
925
    force_thumb = 1;
926
  else if (streq (option, "no-force-thumb"))
927
    force_thumb = 0;
928
  else
929
    fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
930
 
931
  return;
932
}
933
 
934
/* Parse the string of disassembler options, spliting it at whitespaces.  */
935
static void
936
parse_disassembler_options (options)
937
     char * options;
938
{
939
  char * space;
940
 
941
  if (options == NULL)
942
    return;
943
 
944
  do
945
    {
946
      space = strchr (options, ' ');
947
 
948
      if (space)
949
        {
950
          * space = '\0';
951
          parse_arm_disassembler_option (options);
952
          * space = ' ';
953
          options = space + 1;
954
        }
955
      else
956
        parse_arm_disassembler_option (options);
957
    }
958
  while (space);
959
}
960
 
961
/* NOTE: There are no checks in these routines that
962
   the relevant number of data bytes exist.  */
963
static int
964
print_insn (pc, info, little)
965
     bfd_vma pc;
966
     struct disassemble_info * info;
967
     boolean little;
968
{
969
  unsigned char      b[4];
970
  long               given;
971
  int                status;
972
  int                is_thumb;
973
 
974
  if (info->disassembler_options)
975
    {
976
      parse_disassembler_options (info->disassembler_options);
977
 
978
      /* To avoid repeated parsing of these options, we remove them here.  */
979
      info->disassembler_options = NULL;
980
    }
981
 
982
  is_thumb = force_thumb;
983
 
984
  if (!is_thumb && info->symbols != NULL)
985
    {
986
      if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
987
        {
988
          coff_symbol_type * cs;
989
 
990
          cs = coffsymbol (*info->symbols);
991
          is_thumb = (   cs->native->u.syment.n_sclass == C_THUMBEXT
992
                      || cs->native->u.syment.n_sclass == C_THUMBSTAT
993
                      || cs->native->u.syment.n_sclass == C_THUMBLABEL
994
                      || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
995
                      || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
996
        }
997
      else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
998
        {
999
          elf_symbol_type *  es;
1000
          unsigned int       type;
1001
 
1002
          es = *(elf_symbol_type **)(info->symbols);
1003
          type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
1004
 
1005
          is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
1006
        }
1007
    }
1008
 
1009
  info->bytes_per_chunk = 4;
1010
  info->display_endian  = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
1011
 
1012
  if (little)
1013
    {
1014
      status = info->read_memory_func (pc, (bfd_byte *) &b[0], 4, info);
1015
      if (status != 0 && is_thumb)
1016
        {
1017
          info->bytes_per_chunk = 2;
1018
 
1019
          status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
1020
          b[3] = b[2] = 0;
1021
        }
1022
 
1023
      if (status != 0)
1024
        {
1025
          info->memory_error_func (status, pc, info);
1026
          return -1;
1027
        }
1028
 
1029
      given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
1030
    }
1031
  else
1032
    {
1033
      status = info->read_memory_func
1034
        (pc & ~ 0x3, (bfd_byte *) &b[0], 4, info);
1035
      if (status != 0)
1036
        {
1037
          info->memory_error_func (status, pc, info);
1038
          return -1;
1039
        }
1040
 
1041
      if (is_thumb)
1042
        {
1043
          if (pc & 0x2)
1044
            {
1045
              given = (b[2] << 8) | b[3];
1046
 
1047
              status = info->read_memory_func
1048
                ((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
1049
              if (status != 0)
1050
                {
1051
                  info->memory_error_func (status, pc + 4, info);
1052
                  return -1;
1053
                }
1054
 
1055
              given |= (b[0] << 24) | (b[1] << 16);
1056
            }
1057
          else
1058
            given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16);
1059
        }
1060
      else
1061
        given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
1062
    }
1063
 
1064
  if (info->flags & INSN_HAS_RELOC)
1065
    /* If the instruction has a reloc associated with it, then
1066
       the offset field in the instruction will actually be the
1067
       addend for the reloc.  (We are using REL type relocs).
1068
       In such cases, we can ignore the pc when computing
1069
       addresses, since the addend is not currently pc-relative.  */
1070
    pc = 0;
1071
 
1072
  if (is_thumb)
1073
    status = print_insn_thumb (pc, info, given);
1074
  else
1075
    status = print_insn_arm (pc, info, given);
1076
 
1077
  return status;
1078
}
1079
 
1080
int
1081
print_insn_big_arm (pc, info)
1082
     bfd_vma pc;
1083
     struct disassemble_info * info;
1084
{
1085
  return print_insn (pc, info, false);
1086
}
1087
 
1088
int
1089
print_insn_little_arm (pc, info)
1090
     bfd_vma pc;
1091
     struct disassemble_info * info;
1092
{
1093
  return print_insn (pc, info, true);
1094
}
1095
 
1096
void
1097
print_arm_disassembler_options (FILE * stream)
1098
{
1099
  int i;
1100
 
1101
  fprintf (stream, _("\n\
1102
The following ARM specific disassembler options are supported for use with\n\
1103
the -M switch:\n"));
1104
 
1105
  for (i = NUM_ARM_REGNAMES; i--;)
1106
    fprintf (stream, "  reg-names-%s %*c%s\n",
1107
             regnames[i].name,
1108
             14 - strlen (regnames[i].name), ' ',
1109
             regnames[i].description);
1110
 
1111
  fprintf (stream, "  force-thumb              Assume all insns are Thumb insns\n");
1112
  fprintf (stream, "  no-force-thumb           Examine preceeding label to determine an insn's type\n\n");
1113
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.