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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [gdb-5.3/] [opcodes/] [arm-dis.c] - Blame information for rev 1765

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* Instruction printing code for the ARM
2
   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
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 ()
105
{
106
  return NUM_ARM_REGNAMES;
107
}
108
 
109
int
110
set_arm_regname_option (option)
111
     int option;
112
{
113
  int old = regname_selected;
114
  regname_selected = option;
115
  return old;
116
}
117
 
118
int
119
get_arm_regnames (option, setname, setdescription, register_names)
120
     int option;
121
     const char **setname;
122
     const char **setdescription;
123
     const char ***register_names;
124
{
125
  *setname = regnames[option].name;
126
  *setdescription = regnames[option].description;
127
  *register_names = regnames[option].reg_names;
128
  return 16;
129
}
130
 
131
static void
132
arm_decode_shift (given, func, stream)
133
     long given;
134
     fprintf_ftype func;
135
     void * stream;
136
{
137
  func (stream, "%s", arm_regnames[given & 0xf]);
138
 
139
  if ((given & 0xff0) != 0)
140
    {
141
      if ((given & 0x10) == 0)
142
        {
143
          int amount = (given & 0xf80) >> 7;
144
          int shift = (given & 0x60) >> 5;
145
 
146
          if (amount == 0)
147
            {
148
              if (shift == 3)
149
                {
150
                  func (stream, ", rrx");
151
                  return;
152
                }
153
 
154
              amount = 32;
155
            }
156
 
157
          func (stream, ", %s #%d", arm_shift[shift], amount);
158
        }
159
      else
160
        func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5],
161
              arm_regnames[(given & 0xf00) >> 8]);
162
    }
163
}
164
 
165
/* Print one instruction from PC on INFO->STREAM.
166
   Return the size of the instruction (always 4 on ARM). */
167
 
168
static int
169
print_insn_arm (pc, info, given)
170
     bfd_vma                   pc;
171
     struct disassemble_info * info;
172
     long                      given;
173
{
174
  struct arm_opcode *  insn;
175
  void *               stream = info->stream;
176
  fprintf_ftype        func   = info->fprintf_func;
177
 
178
  for (insn = arm_opcodes; insn->assembler; insn++)
179
    {
180
      if ((given & insn->mask) == insn->value)
181
        {
182
          char * c;
183
 
184
          for (c = insn->assembler; *c; c++)
185
            {
186
              if (*c == '%')
187
                {
188
                  switch (*++c)
189
                    {
190
                    case '%':
191
                      func (stream, "%%");
192
                      break;
193
 
194
                    case 'a':
195
                      if (((given & 0x000f0000) == 0x000f0000)
196
                          && ((given & 0x02000000) == 0))
197
                        {
198
                          int offset = given & 0xfff;
199
 
200
                          func (stream, "[pc");
201
 
202
                          if (given & 0x01000000)
203
                            {
204
                              if ((given & 0x00800000) == 0)
205
                                offset = - offset;
206
 
207
                              /* Pre-indexed.  */
208
                              func (stream, ", #%d]", offset);
209
 
210
                              offset += pc + 8;
211
 
212
                              /* Cope with the possibility of write-back
213
                                 being used.  Probably a very dangerous thing
214
                                 for the programmer to do, but who are we to
215
                                 argue ?  */
216
                              if (given & 0x00200000)
217
                                func (stream, "!");
218
                            }
219
                          else
220
                            {
221
                              /* Post indexed.  */
222
                              func (stream, "], #%d", offset);
223
 
224
                              /* ie ignore the offset.  */
225
                              offset = pc + 8;
226
                            }
227
 
228
                          func (stream, "\t; ");
229
                          info->print_address_func (offset, info);
230
                        }
231
                      else
232
                        {
233
                          func (stream, "[%s",
234
                                arm_regnames[(given >> 16) & 0xf]);
235
                          if ((given & 0x01000000) != 0)
236
                            {
237
                              if ((given & 0x02000000) == 0)
238
                                {
239
                                  int offset = given & 0xfff;
240
                                  if (offset)
241
                                    func (stream, ", %s#%d",
242
                                          (((given & 0x00800000) == 0)
243
                                           ? "-" : ""), offset);
244
                                }
245
                              else
246
                                {
247
                                  func (stream, ", %s",
248
                                        (((given & 0x00800000) == 0)
249
                                         ? "-" : ""));
250
                                  arm_decode_shift (given, func, stream);
251
                                }
252
 
253
                              func (stream, "]%s",
254
                                    ((given & 0x00200000) != 0) ? "!" : "");
255
                            }
256
                          else
257
                            {
258
                              if ((given & 0x02000000) == 0)
259
                                {
260
                                  int offset = given & 0xfff;
261
                                  if (offset)
262
                                    func (stream, "], %s#%d",
263
                                          (((given & 0x00800000) == 0)
264
                                           ? "-" : ""), offset);
265
                                  else
266
                                    func (stream, "]");
267
                                }
268
                              else
269
                                {
270
                                  func (stream, "], %s",
271
                                        (((given & 0x00800000) == 0)
272
                                         ? "-" : ""));
273
                                  arm_decode_shift (given, func, stream);
274
                                }
275
                            }
276
                        }
277
                      break;
278
 
279
                    case 's':
280
                      if ((given & 0x004f0000) == 0x004f0000)
281
                        {
282
                          /* PC relative with immediate offset.  */
283
                          int offset = ((given & 0xf00) >> 4) | (given & 0xf);
284
 
285
                          if ((given & 0x00800000) == 0)
286
                            offset = -offset;
287
 
288
                          func (stream, "[pc, #%d]\t; ", offset);
289
 
290
                          (*info->print_address_func)
291
                            (offset + pc + 8, info);
292
                        }
293
                      else
294
                        {
295
                          func (stream, "[%s",
296
                                arm_regnames[(given >> 16) & 0xf]);
297
                          if ((given & 0x01000000) != 0)
298
                            {
299
                              /* Pre-indexed.  */
300
                              if ((given & 0x00400000) == 0x00400000)
301
                                {
302
                                  /* Immediate.  */
303
                                  int offset = ((given & 0xf00) >> 4) | (given & 0xf);
304
                                  if (offset)
305
                                    func (stream, ", %s#%d",
306
                                          (((given & 0x00800000) == 0)
307
                                           ? "-" : ""), offset);
308
                                }
309
                              else
310
                                {
311
                                  /* Register.  */
312
                                  func (stream, ", %s%s",
313
                                        (((given & 0x00800000) == 0)
314
                                         ? "-" : ""),
315
                                        arm_regnames[given & 0xf]);
316
                                }
317
 
318
                              func (stream, "]%s",
319
                                    ((given & 0x00200000) != 0) ? "!" : "");
320
                            }
321
                          else
322
                            {
323
                              /* Post-indexed.  */
324
                              if ((given & 0x00400000) == 0x00400000)
325
                                {
326
                                  /* Immediate.  */
327
                                  int offset = ((given & 0xf00) >> 4) | (given & 0xf);
328
                                  if (offset)
329
                                    func (stream, "], %s#%d",
330
                                          (((given & 0x00800000) == 0)
331
                                           ? "-" : ""), offset);
332
                                  else
333
                                    func (stream, "]");
334
                                }
335
                              else
336
                                {
337
                                  /* Register.  */
338
                                  func (stream, "], %s%s",
339
                                        (((given & 0x00800000) == 0)
340
                                         ? "-" : ""),
341
                                        arm_regnames[given & 0xf]);
342
                                }
343
                            }
344
                        }
345
                      break;
346
 
347
                    case 'b':
348
                      (*info->print_address_func)
349
                        (BDISP (given) * 4 + pc + 8, info);
350
                      break;
351
 
352
                    case 'c':
353
                      func (stream, "%s",
354
                            arm_conditional [(given >> 28) & 0xf]);
355
                      break;
356
 
357
                    case 'm':
358
                      {
359
                        int started = 0;
360
                        int reg;
361
 
362
                        func (stream, "{");
363
                        for (reg = 0; reg < 16; reg++)
364
                          if ((given & (1 << reg)) != 0)
365
                            {
366
                              if (started)
367
                                func (stream, ", ");
368
                              started = 1;
369
                              func (stream, "%s", arm_regnames[reg]);
370
                            }
371
                        func (stream, "}");
372
                      }
373
                      break;
374
 
375
                    case 'o':
376
                      if ((given & 0x02000000) != 0)
377
                        {
378
                          int rotate = (given & 0xf00) >> 7;
379
                          int immed = (given & 0xff);
380
                          immed = (((immed << (32 - rotate))
381
                                    | (immed >> rotate)) & 0xffffffff);
382
                          func (stream, "#%d\t; 0x%x", immed, immed);
383
                        }
384
                      else
385
                        arm_decode_shift (given, func, stream);
386
                      break;
387
 
388
                    case 'p':
389
                      if ((given & 0x0000f000) == 0x0000f000)
390
                        func (stream, "p");
391
                      break;
392
 
393
                    case 't':
394
                      if ((given & 0x01200000) == 0x00200000)
395
                        func (stream, "t");
396
                      break;
397
 
398
                    case 'A':
399
                      func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
400
                      if ((given & 0x01000000) != 0)
401
                        {
402
                          int offset = given & 0xff;
403
                          if (offset)
404
                            func (stream, ", %s#%d]%s",
405
                                  ((given & 0x00800000) == 0 ? "-" : ""),
406
                                  offset * 4,
407
                                  ((given & 0x00200000) != 0 ? "!" : ""));
408
                          else
409
                            func (stream, "]");
410
                        }
411
                      else
412
                        {
413
                          int offset = given & 0xff;
414
                          if (offset)
415
                            func (stream, "], %s#%d",
416
                                  ((given & 0x00800000) == 0 ? "-" : ""),
417
                                  offset * 4);
418
                          else
419
                            func (stream, "]");
420
                        }
421
                      break;
422
 
423
                    case 'B':
424
                      /* Print ARM V5 BLX(1) address: pc+25 bits.  */
425
                      {
426
                        bfd_vma address;
427
                        bfd_vma offset = 0;
428
 
429
                        if (given & 0x00800000)
430
                          /* Is signed, hi bits should be ones.  */
431
                          offset = (-1) ^ 0x00ffffff;
432
 
433
                        /* Offset is (SignExtend(offset field)<<2).  */
434
                        offset += given & 0x00ffffff;
435
                        offset <<= 2;
436
                        address = offset + pc + 8;
437
 
438
                        if (given & 0x01000000)
439
                          /* H bit allows addressing to 2-byte boundaries.  */
440
                          address += 2;
441
 
442
                        info->print_address_func (address, info);
443
                      }
444
                      break;
445
 
446
                    case 'I':
447
                      /* Print a Cirrus/DSP shift immediate.  */
448
                      /* Immediates are 7bit signed ints with bits 0..3 in
449
                         bits 0..3 of opcode and bits 4..6 in bits 5..7
450
                         of opcode.  */
451
                      {
452
                        int imm;
453
 
454
                        imm = (given & 0xf) | ((given & 0xe0) >> 1);
455
 
456
                        /* Is ``imm'' a negative number?  */
457
                        if (imm & 0x40)
458
                          imm |= (-1 << 7);
459
 
460
                        func (stream, "%d", imm);
461
                      }
462
 
463
                      break;
464
 
465
                    case 'C':
466
                      func (stream, "_");
467
                      if (given & 0x80000)
468
                        func (stream, "f");
469
                      if (given & 0x40000)
470
                        func (stream, "s");
471
                      if (given & 0x20000)
472
                        func (stream, "x");
473
                      if (given & 0x10000)
474
                        func (stream, "c");
475
                      break;
476
 
477
                    case 'F':
478
                      switch (given & 0x00408000)
479
                        {
480
                        case 0:
481
                          func (stream, "4");
482
                          break;
483
                        case 0x8000:
484
                          func (stream, "1");
485
                          break;
486
                        case 0x00400000:
487
                          func (stream, "2");
488
                          break;
489
                        default:
490
                          func (stream, "3");
491
                        }
492
                      break;
493
 
494
                    case 'P':
495
                      switch (given & 0x00080080)
496
                        {
497
                        case 0:
498
                          func (stream, "s");
499
                          break;
500
                        case 0x80:
501
                          func (stream, "d");
502
                          break;
503
                        case 0x00080000:
504
                          func (stream, "e");
505
                          break;
506
                        default:
507
                          func (stream, _("<illegal precision>"));
508
                          break;
509
                        }
510
                      break;
511
                    case 'Q':
512
                      switch (given & 0x00408000)
513
                        {
514
                        case 0:
515
                          func (stream, "s");
516
                          break;
517
                        case 0x8000:
518
                          func (stream, "d");
519
                          break;
520
                        case 0x00400000:
521
                          func (stream, "e");
522
                          break;
523
                        default:
524
                          func (stream, "p");
525
                          break;
526
                        }
527
                      break;
528
                    case 'R':
529
                      switch (given & 0x60)
530
                        {
531
                        case 0:
532
                          break;
533
                        case 0x20:
534
                          func (stream, "p");
535
                          break;
536
                        case 0x40:
537
                          func (stream, "m");
538
                          break;
539
                        default:
540
                          func (stream, "z");
541
                          break;
542
                        }
543
                      break;
544
 
545
                    case '0': case '1': case '2': case '3': case '4':
546
                    case '5': case '6': case '7': case '8': case '9':
547
                      {
548
                        int bitstart = *c++ - '0';
549
                        int bitend = 0;
550
                        while (*c >= '0' && *c <= '9')
551
                          bitstart = (bitstart * 10) + *c++ - '0';
552
 
553
                        switch (*c)
554
                          {
555
                          case '-':
556
                            c++;
557
 
558
                            while (*c >= '0' && *c <= '9')
559
                              bitend = (bitend * 10) + *c++ - '0';
560
 
561
                            if (!bitend)
562
                              abort ();
563
 
564
                            switch (*c)
565
                              {
566
                              case 'r':
567
                                {
568
                                  long reg;
569
 
570
                                  reg = given >> bitstart;
571
                                  reg &= (2 << (bitend - bitstart)) - 1;
572
 
573
                                  func (stream, "%s", arm_regnames[reg]);
574
                                }
575
                                break;
576
                              case 'd':
577
                                {
578
                                  long reg;
579
 
580
                                  reg = given >> bitstart;
581
                                  reg &= (2 << (bitend - bitstart)) - 1;
582
 
583
                                  func (stream, "%d", reg);
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, "0x%08x", reg);
594
 
595
                                  /* Some SWI instructions have special
596
                                     meanings.  */
597
                                  if ((given & 0x0fffffff) == 0x0FF00000)
598
                                    func (stream, "\t; IMB");
599
                                  else if ((given & 0x0fffffff) == 0x0FF00001)
600
                                    func (stream, "\t; IMBRange");
601
                                }
602
                                break;
603
                              case 'X':
604
                                {
605
                                  long reg;
606
 
607
                                  reg = given >> bitstart;
608
                                  reg &= (2 << (bitend - bitstart)) - 1;
609
 
610
                                  func (stream, "%01x", reg & 0xf);
611
                                }
612
                                break;
613
                              case 'f':
614
                                {
615
                                  long reg;
616
 
617
                                  reg = given >> bitstart;
618
                                  reg &= (2 << (bitend - bitstart)) - 1;
619
 
620
                                  if (reg > 7)
621
                                    func (stream, "#%s",
622
                                          arm_fp_const[reg & 7]);
623
                                  else
624
                                    func (stream, "f%d", reg);
625
                                }
626
                                break;
627
                              default:
628
                                abort ();
629
                              }
630
                            break;
631
 
632
                          case 'y':
633
                          case 'z':
634
                            {
635
                              int single = *c == 'y';
636
                              int regno;
637
 
638
                              switch (bitstart)
639
                                {
640
                                case 4: /* Sm pair */
641
                                  func (stream, "{");
642
                                  /* Fall through.  */
643
                                case 0: /* Sm, Dm */
644
                                  regno = given & 0x0000000f;
645
                                  if (single)
646
                                    {
647
                                      regno <<= 1;
648
                                      regno += (given >> 5) & 1;
649
                                    }
650
                                  break;
651
 
652
                                case 1: /* Sd, Dd */
653
                                  regno = (given >> 12) & 0x0000000f;
654
                                  if (single)
655
                                    {
656
                                      regno <<= 1;
657
                                      regno += (given >> 22) & 1;
658
                                    }
659
                                  break;
660
 
661
                                case 2: /* Sn, Dn */
662
                                  regno = (given >> 16) & 0x0000000f;
663
                                  if (single)
664
                                    {
665
                                      regno <<= 1;
666
                                      regno += (given >> 7) & 1;
667
                                    }
668
                                  break;
669
 
670
                                case 3: /* List */
671
                                  func (stream, "{");
672
                                  regno = (given >> 12) & 0x0000000f;
673
                                  if (single)
674
                                    {
675
                                      regno <<= 1;
676
                                      regno += (given >> 22) & 1;
677
                                    }
678
                                  break;
679
 
680
 
681
                                default:
682
                                  abort ();
683
                                }
684
 
685
                              func (stream, "%c%d", single ? 's' : 'd', regno);
686
 
687
                              if (bitstart == 3)
688
                                {
689
                                  int count = given & 0xff;
690
 
691
                                  if (single == 0)
692
                                    count >>= 1;
693
 
694
                                  if (--count)
695
                                    {
696
                                      func (stream, "-%c%d",
697
                                            single ? 's' : 'd',
698
                                            regno + count);
699
                                    }
700
 
701
                                  func (stream, "}");
702
                                }
703
                              else if (bitstart == 4)
704
                                func (stream, ", %c%d}", single ? 's' : 'd',
705
                                      regno + 1);
706
 
707
                              break;
708
                            }
709
 
710
                          case '`':
711
                            c++;
712
                            if ((given & (1 << bitstart)) == 0)
713
                              func (stream, "%c", *c);
714
                            break;
715
                          case '\'':
716
                            c++;
717
                            if ((given & (1 << bitstart)) != 0)
718
                              func (stream, "%c", *c);
719
                            break;
720
                          case '?':
721
                            ++c;
722
                            if ((given & (1 << bitstart)) != 0)
723
                              func (stream, "%c", *c++);
724
                            else
725
                              func (stream, "%c", *++c);
726
                            break;
727
                          default:
728
                            abort ();
729
                          }
730
                        break;
731
 
732
                      default:
733
                        abort ();
734
                      }
735
                    }
736
                }
737
              else
738
                func (stream, "%c", *c);
739
            }
740
          return 4;
741
        }
742
    }
743
  abort ();
744
}
745
 
746
/* Print one instruction from PC on INFO->STREAM.
747
   Return the size of the instruction. */
748
 
749
static int
750
print_insn_thumb (pc, info, given)
751
     bfd_vma                   pc;
752
     struct disassemble_info * info;
753
     long                      given;
754
{
755
  struct thumb_opcode * insn;
756
  void *                stream = info->stream;
757
  fprintf_ftype         func = info->fprintf_func;
758
 
759
  for (insn = thumb_opcodes; insn->assembler; insn++)
760
    {
761
      if ((given & insn->mask) == insn->value)
762
        {
763
          char * c = insn->assembler;
764
 
765
          /* Special processing for Thumb 2 instruction BL sequence:  */
766
          if (!*c) /* Check for empty (not NULL) assembler string.  */
767
            {
768
              long offset;
769
 
770
              info->bytes_per_chunk = 4;
771
              info->bytes_per_line  = 4;
772
 
773
              offset = BDISP23 (given);
774
              offset = offset * 2 + pc + 4;
775
 
776
              if ((given & 0x10000000) == 0)
777
                {
778
                  func (stream, "blx\t");
779
                  offset &= 0xfffffffc;
780
                }
781
              else
782
                func (stream, "bl\t");
783
 
784
              info->print_address_func (offset, info);
785
              return 4;
786
            }
787
          else
788
            {
789
              info->bytes_per_chunk = 2;
790
              info->bytes_per_line  = 4;
791
 
792
              given &= 0xffff;
793
 
794
              for (; *c; c++)
795
                {
796
                  if (*c == '%')
797
                    {
798
                      int domaskpc = 0;
799
                      int domasklr = 0;
800
 
801
                      switch (*++c)
802
                        {
803
                        case '%':
804
                          func (stream, "%%");
805
                          break;
806
 
807
                        case 'S':
808
                          {
809
                            long reg;
810
 
811
                            reg = (given >> 3) & 0x7;
812
                            if (given & (1 << 6))
813
                              reg += 8;
814
 
815
                            func (stream, "%s", arm_regnames[reg]);
816
                          }
817
                          break;
818
 
819
                        case 'D':
820
                          {
821
                            long reg;
822
 
823
                            reg = given & 0x7;
824
                            if (given & (1 << 7))
825
                             reg += 8;
826
 
827
                            func (stream, "%s", arm_regnames[reg]);
828
                          }
829
                          break;
830
 
831
                        case 'T':
832
                          func (stream, "%s",
833
                                arm_conditional [(given >> 8) & 0xf]);
834
                          break;
835
 
836
                        case 'N':
837
                          if (given & (1 << 8))
838
                            domasklr = 1;
839
                          /* Fall through.  */
840
                        case 'O':
841
                          if (*c == 'O' && (given & (1 << 8)))
842
                            domaskpc = 1;
843
                          /* Fall through.  */
844
                        case 'M':
845
                          {
846
                            int started = 0;
847
                            int reg;
848
 
849
                            func (stream, "{");
850
 
851
                            /* It would be nice if we could spot
852
                               ranges, and generate the rS-rE format: */
853
                            for (reg = 0; (reg < 8); reg++)
854
                              if ((given & (1 << reg)) != 0)
855
                                {
856
                                  if (started)
857
                                    func (stream, ", ");
858
                                  started = 1;
859
                                  func (stream, "%s", arm_regnames[reg]);
860
                                }
861
 
862
                            if (domasklr)
863
                              {
864
                                if (started)
865
                                  func (stream, ", ");
866
                                started = 1;
867
                                func (stream, arm_regnames[14] /* "lr" */);
868
                              }
869
 
870
                            if (domaskpc)
871
                              {
872
                                if (started)
873
                                  func (stream, ", ");
874
                                func (stream, arm_regnames[15] /* "pc" */);
875
                              }
876
 
877
                            func (stream, "}");
878
                          }
879
                          break;
880
 
881
 
882
                        case '0': case '1': case '2': case '3': case '4':
883
                        case '5': case '6': case '7': case '8': case '9':
884
                          {
885
                            int bitstart = *c++ - '0';
886
                            int bitend = 0;
887
 
888
                            while (*c >= '0' && *c <= '9')
889
                              bitstart = (bitstart * 10) + *c++ - '0';
890
 
891
                            switch (*c)
892
                              {
893
                              case '-':
894
                                {
895
                                  long reg;
896
 
897
                                  c++;
898
                                  while (*c >= '0' && *c <= '9')
899
                                    bitend = (bitend * 10) + *c++ - '0';
900
                                  if (!bitend)
901
                                    abort ();
902
                                  reg = given >> bitstart;
903
                                  reg &= (2 << (bitend - bitstart)) - 1;
904
                                  switch (*c)
905
                                    {
906
                                    case 'r':
907
                                      func (stream, "%s", arm_regnames[reg]);
908
                                      break;
909
 
910
                                    case 'd':
911
                                      func (stream, "%d", reg);
912
                                      break;
913
 
914
                                    case 'H':
915
                                      func (stream, "%d", reg << 1);
916
                                      break;
917
 
918
                                    case 'W':
919
                                      func (stream, "%d", reg << 2);
920
                                      break;
921
 
922
                                    case 'a':
923
                                      /* PC-relative address -- the bottom two
924
                                         bits of the address are dropped
925
                                         before the calculation.  */
926
                                      info->print_address_func
927
                                        (((pc + 4) & ~3) + (reg << 2), info);
928
                                      break;
929
 
930
                                    case 'x':
931
                                      func (stream, "0x%04x", reg);
932
                                      break;
933
 
934
                                    case 'I':
935
                                      reg = ((reg ^ (1 << bitend)) - (1 << bitend));
936
                                      func (stream, "%d", reg);
937
                                      break;
938
 
939
                                    case 'B':
940
                                      reg = ((reg ^ (1 << bitend)) - (1 << bitend));
941
                                      (*info->print_address_func)
942
                                        (reg * 2 + pc + 4, info);
943
                                      break;
944
 
945
                                    default:
946
                                      abort ();
947
                                    }
948
                                }
949
                                break;
950
 
951
                              case '\'':
952
                                c++;
953
                                if ((given & (1 << bitstart)) != 0)
954
                                  func (stream, "%c", *c);
955
                                break;
956
 
957
                              case '?':
958
                                ++c;
959
                                if ((given & (1 << bitstart)) != 0)
960
                                  func (stream, "%c", *c++);
961
                                else
962
                                  func (stream, "%c", *++c);
963
                                break;
964
 
965
                              default:
966
                                 abort ();
967
                              }
968
                          }
969
                          break;
970
 
971
                        default:
972
                          abort ();
973
                        }
974
                    }
975
                  else
976
                    func (stream, "%c", *c);
977
                }
978
             }
979
          return 2;
980
       }
981
    }
982
 
983
  /* No match.  */
984
  abort ();
985
}
986
 
987
/* Parse an individual disassembler option.  */
988
 
989
void
990
parse_arm_disassembler_option (option)
991
     char * option;
992
{
993
  if (option == NULL)
994
    return;
995
 
996
  if (strneq (option, "reg-names-", 10))
997
    {
998
      int i;
999
 
1000
      option += 10;
1001
 
1002
      for (i = NUM_ARM_REGNAMES; i--;)
1003
        if (streq (option, regnames[i].name))
1004
          {
1005
            regname_selected = i;
1006
            break;
1007
          }
1008
 
1009
      if (i < 0)
1010
        fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
1011
    }
1012
  else if (streq (option, "force-thumb"))
1013
    force_thumb = 1;
1014
  else if (streq (option, "no-force-thumb"))
1015
    force_thumb = 0;
1016
  else
1017
    fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
1018
 
1019
  return;
1020
}
1021
 
1022
/* Parse the string of disassembler options, spliting it at whitespaces.  */
1023
 
1024
static void
1025
parse_disassembler_options (options)
1026
     char * options;
1027
{
1028
  char * space;
1029
 
1030
  if (options == NULL)
1031
    return;
1032
 
1033
  do
1034
    {
1035
      space = strchr (options, ' ');
1036
 
1037
      if (space)
1038
        {
1039
          * space = '\0';
1040
          parse_arm_disassembler_option (options);
1041
          * space = ' ';
1042
          options = space + 1;
1043
        }
1044
      else
1045
        parse_arm_disassembler_option (options);
1046
    }
1047
  while (space);
1048
}
1049
 
1050
/* NOTE: There are no checks in these routines that
1051
   the relevant number of data bytes exist.  */
1052
 
1053
static int
1054
print_insn (pc, info, little)
1055
     bfd_vma pc;
1056
     struct disassemble_info * info;
1057
     boolean little;
1058
{
1059
  unsigned char      b[4];
1060
  long               given;
1061
  int                status;
1062
  int                is_thumb;
1063
 
1064
  if (info->disassembler_options)
1065
    {
1066
      parse_disassembler_options (info->disassembler_options);
1067
 
1068
      /* To avoid repeated parsing of these options, we remove them here.  */
1069
      info->disassembler_options = NULL;
1070
    }
1071
 
1072
  is_thumb = force_thumb;
1073
 
1074
  if (!is_thumb && info->symbols != NULL)
1075
    {
1076
      if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
1077
        {
1078
          coff_symbol_type * cs;
1079
 
1080
          cs = coffsymbol (*info->symbols);
1081
          is_thumb = (   cs->native->u.syment.n_sclass == C_THUMBEXT
1082
                      || cs->native->u.syment.n_sclass == C_THUMBSTAT
1083
                      || cs->native->u.syment.n_sclass == C_THUMBLABEL
1084
                      || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
1085
                      || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
1086
        }
1087
      else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
1088
        {
1089
          elf_symbol_type *  es;
1090
          unsigned int       type;
1091
 
1092
          es = *(elf_symbol_type **)(info->symbols);
1093
          type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
1094
 
1095
          is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
1096
        }
1097
    }
1098
 
1099
  info->bytes_per_chunk = 4;
1100
  info->display_endian  = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
1101
 
1102
  if (little)
1103
    {
1104
      status = info->read_memory_func (pc, (bfd_byte *) &b[0], 4, info);
1105
      if (status != 0 && is_thumb)
1106
        {
1107
          info->bytes_per_chunk = 2;
1108
 
1109
          status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
1110
          b[3] = b[2] = 0;
1111
        }
1112
 
1113
      if (status != 0)
1114
        {
1115
          info->memory_error_func (status, pc, info);
1116
          return -1;
1117
        }
1118
 
1119
      given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
1120
    }
1121
  else
1122
    {
1123
      status = info->read_memory_func
1124
        (pc & ~ 0x3, (bfd_byte *) &b[0], 4, info);
1125
      if (status != 0)
1126
        {
1127
          info->memory_error_func (status, pc, info);
1128
          return -1;
1129
        }
1130
 
1131
      if (is_thumb)
1132
        {
1133
          if (pc & 0x2)
1134
            {
1135
              given = (b[2] << 8) | b[3];
1136
 
1137
              status = info->read_memory_func
1138
                ((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
1139
              if (status != 0)
1140
                {
1141
                  info->memory_error_func (status, pc + 4, info);
1142
                  return -1;
1143
                }
1144
 
1145
              given |= (b[0] << 24) | (b[1] << 16);
1146
            }
1147
          else
1148
            given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16);
1149
        }
1150
      else
1151
        given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
1152
    }
1153
 
1154
  if (info->flags & INSN_HAS_RELOC)
1155
    /* If the instruction has a reloc associated with it, then
1156
       the offset field in the instruction will actually be the
1157
       addend for the reloc.  (We are using REL type relocs).
1158
       In such cases, we can ignore the pc when computing
1159
       addresses, since the addend is not currently pc-relative.  */
1160
    pc = 0;
1161
 
1162
  if (is_thumb)
1163
    status = print_insn_thumb (pc, info, given);
1164
  else
1165
    status = print_insn_arm (pc, info, given);
1166
 
1167
  return status;
1168
}
1169
 
1170
int
1171
print_insn_big_arm (pc, info)
1172
     bfd_vma pc;
1173
     struct disassemble_info * info;
1174
{
1175
  return print_insn (pc, info, false);
1176
}
1177
 
1178
int
1179
print_insn_little_arm (pc, info)
1180
     bfd_vma pc;
1181
     struct disassemble_info * info;
1182
{
1183
  return print_insn (pc, info, true);
1184
}
1185
 
1186
void
1187
print_arm_disassembler_options (FILE * stream)
1188
{
1189
  int i;
1190
 
1191
  fprintf (stream, _("\n\
1192
The following ARM specific disassembler options are supported for use with\n\
1193
the -M switch:\n"));
1194
 
1195
  for (i = NUM_ARM_REGNAMES; i--;)
1196
    fprintf (stream, "  reg-names-%s %*c%s\n",
1197
             regnames[i].name,
1198
             (int)(14 - strlen (regnames[i].name)), ' ',
1199
             regnames[i].description);
1200
 
1201
  fprintf (stream, "  force-thumb              Assume all insns are Thumb insns\n");
1202
  fprintf (stream, "  no-force-thumb           Examine preceeding label to determine an insn's type\n\n");
1203
}

powered by: WebSVN 2.1.0

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