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

Subversion Repositories or1k

[/] [or1k/] [tags/] [final_interface/] [gdb-5.0/] [opcodes/] [mips-dis.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 106 markom
/* Print mips instructions for GDB, the GNU debugger, or for objdump.
2
   Copyright (c) 1989, 91-97, 1998 Free Software Foundation, Inc.
3
   Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
4
 
5
This file is part of GDB, GAS, and the GNU binutils.
6
 
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(at your option) any later version.
11
 
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
GNU General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
 
21
#include <ansidecl.h>
22
#include "sysdep.h"
23
#include "dis-asm.h"
24
#include "opcode/mips.h"
25
#include "opintl.h"
26
 
27
/* FIXME: These are needed to figure out if the code is mips16 or
28
   not. The low bit of the address is often a good indicator.  No
29
   symbol table is available when this code runs out in an embedded
30
   system as when it is used for disassembler support in a monitor. */
31
 
32
#if !defined(EMBEDDED_ENV)
33
#define SYMTAB_AVAILABLE 1
34
#include "elf-bfd.h"
35
#include "elf/mips.h"
36
#endif
37
 
38
static int print_insn_mips16 PARAMS ((bfd_vma, struct disassemble_info *));
39
static void print_mips16_insn_arg
40
  PARAMS ((int, const struct mips_opcode *, int, boolean, int, bfd_vma,
41
           struct disassemble_info *));
42
 
43
/* Mips instructions are never longer than this many bytes.  */
44
#define MAXLEN 4
45
 
46
static void print_insn_arg PARAMS ((const char *, unsigned long, bfd_vma,
47
                                    struct disassemble_info *));
48
static int _print_insn_mips PARAMS ((bfd_vma, unsigned long int,
49
                                     struct disassemble_info *));
50
 
51
 
52
/* FIXME: This should be shared with gdb somehow.  */
53
#define REGISTER_NAMES  \
54
    {   "zero", "at",   "v0",   "v1",   "a0",   "a1",   "a2",   "a3", \
55
        "t0",   "t1",   "t2",   "t3",   "t4",   "t5",   "t6",   "t7", \
56
        "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7", \
57
        "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra", \
58
        "sr",   "lo",   "hi",   "bad",  "cause","pc",    \
59
        "f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7", \
60
        "f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15", \
61
        "f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",\
62
        "f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31",\
63
        "fsr",  "fir",  "fp",   "inx",  "rand", "tlblo","ctxt", "tlbhi",\
64
        "epc",  "prid"\
65
    }
66
 
67
static CONST char * CONST reg_names[] = REGISTER_NAMES;
68
 
69
/* The mips16 register names.  */
70
static const char * const mips16_reg_names[] =
71
{
72
  "s0", "s1", "v0", "v1", "a0", "a1", "a2", "a3"
73
};
74
 
75
/* subroutine */
76
static void
77
print_insn_arg (d, l, pc, info)
78
     const char *d;
79
     register unsigned long int l;
80
     bfd_vma pc;
81
     struct disassemble_info *info;
82
{
83
  int delta;
84
 
85
  switch (*d)
86
    {
87
    case ',':
88
    case '(':
89
    case ')':
90
      (*info->fprintf_func) (info->stream, "%c", *d);
91
      break;
92
 
93
    case 's':
94
    case 'b':
95
    case 'r':
96
    case 'v':
97
      (*info->fprintf_func) (info->stream, "$%s",
98
                             reg_names[(l >> OP_SH_RS) & OP_MASK_RS]);
99
      break;
100
 
101
    case 't':
102
    case 'w':
103
      (*info->fprintf_func) (info->stream, "$%s",
104
                             reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
105
      break;
106
 
107
    case 'i':
108
    case 'u':
109
      (*info->fprintf_func) (info->stream, "0x%x",
110
                        (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
111
      break;
112
 
113
    case 'j': /* same as i, but sign-extended */
114
    case 'o':
115
      delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
116
      if (delta & 0x8000)
117
        delta |= ~0xffff;
118
      (*info->fprintf_func) (info->stream, "%d",
119
                             delta);
120
      break;
121
 
122
    case 'h':
123
      (*info->fprintf_func) (info->stream, "0x%x",
124
                             (unsigned int) ((l >> OP_SH_PREFX)
125
                                             & OP_MASK_PREFX));
126
      break;
127
 
128
    case 'k':
129
      (*info->fprintf_func) (info->stream, "0x%x",
130
                             (unsigned int) ((l >> OP_SH_CACHE)
131
                                             & OP_MASK_CACHE));
132
      break;
133
 
134
    case 'a':
135
      (*info->print_address_func)
136
        (((pc & 0xF0000000) | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
137
         info);
138
      break;
139
 
140
    case 'p':
141
      /* sign extend the displacement */
142
      delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
143
      if (delta & 0x8000)
144
        delta |= ~0xffff;
145
      (*info->print_address_func)
146
        ((delta << 2) + pc + 4,
147
         info);
148
      break;
149
 
150
    case 'd':
151
      (*info->fprintf_func) (info->stream, "$%s",
152
                             reg_names[(l >> OP_SH_RD) & OP_MASK_RD]);
153
      break;
154
 
155
    case 'z':
156
      (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
157
      break;
158
 
159
    case '<':
160
      (*info->fprintf_func) (info->stream, "0x%x",
161
                             (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
162
      break;
163
 
164
    case 'c':
165
      (*info->fprintf_func) (info->stream, "0x%x",
166
                             (l >> OP_SH_CODE) & OP_MASK_CODE);
167
      break;
168
 
169
 
170
    case 'q':
171
      (*info->fprintf_func) (info->stream, "0x%x",
172
                             (l >> OP_SH_CODE2) & OP_MASK_CODE2);
173
      break;
174
 
175
    case 'C':
176
      (*info->fprintf_func) (info->stream, "0x%x",
177
                             (l >> OP_SH_COPZ) & OP_MASK_COPZ);
178
      break;
179
 
180
    case 'B':
181
      (*info->fprintf_func) (info->stream, "0x%x",
182
                             (l >> OP_SH_SYSCALL) & OP_MASK_SYSCALL);
183
      break;
184
 
185
    case 'S':
186
    case 'V':
187
      (*info->fprintf_func) (info->stream, "$f%d",
188
                             (l >> OP_SH_FS) & OP_MASK_FS);
189
      break;
190
 
191
 
192
    case 'T':
193
    case 'W':
194
      (*info->fprintf_func) (info->stream, "$f%d",
195
                             (l >> OP_SH_FT) & OP_MASK_FT);
196
      break;
197
 
198
    case 'D':
199
      (*info->fprintf_func) (info->stream, "$f%d",
200
                             (l >> OP_SH_FD) & OP_MASK_FD);
201
      break;
202
 
203
    case 'R':
204
      (*info->fprintf_func) (info->stream, "$f%d",
205
                             (l >> OP_SH_FR) & OP_MASK_FR);
206
      break;
207
 
208
    case 'E':
209
      (*info->fprintf_func) (info->stream, "$%d",
210
                             (l >> OP_SH_RT) & OP_MASK_RT);
211
      break;
212
 
213
    case 'G':
214
      (*info->fprintf_func) (info->stream, "$%d",
215
                             (l >> OP_SH_RD) & OP_MASK_RD);
216
      break;
217
 
218
    case 'N':
219
      (*info->fprintf_func) (info->stream, "$fcc%d",
220
                             (l >> OP_SH_BCC) & OP_MASK_BCC);
221
      break;
222
 
223
    case 'M':
224
      (*info->fprintf_func) (info->stream, "$fcc%d",
225
                             (l >> OP_SH_CCC) & OP_MASK_CCC);
226
      break;
227
 
228
    case 'P':
229
      (*info->fprintf_func) (info->stream, "%d",
230
                             (l >> OP_SH_PERFREG) & OP_MASK_PERFREG);
231
      break;
232
 
233
 
234
    default:
235
      /* xgettext:c-format */
236
      (*info->fprintf_func) (info->stream,
237
                             _("# internal error, undefined modifier(%c)"),
238
                             *d);
239
      break;
240
    }
241
}
242
 
243
#if SYMTAB_AVAILABLE
244
 
245
/* Figure out the MIPS ISA and CPU based on the machine number.
246
   FIXME: What does this have to do with SYMTAB_AVAILABLE?  */
247
 
248
static void
249
set_mips_isa_type (mach, isa, cputype)
250
     int mach;
251
     int *isa;
252
     int *cputype;
253
{
254
  int target_processor = 0;
255
  int mips_isa = 0;
256
 
257
  switch (mach)
258
    {
259
      case bfd_mach_mips3000:
260
        target_processor = 3000;
261
        mips_isa = 1;
262
        break;
263
      case bfd_mach_mips3900:
264
        target_processor = 3900;
265
        mips_isa = 1;
266
        break;
267
      case bfd_mach_mips4000:
268
        target_processor = 4000;
269
        mips_isa = 3;
270
        break;
271
      case bfd_mach_mips4010:
272
        target_processor = 4010;
273
        mips_isa = 2;
274
        break;
275
      case bfd_mach_mips4100:
276
        target_processor = 4100;
277
        mips_isa = 3;
278
        break;
279
      case bfd_mach_mips4111:
280
        target_processor = 4100;
281
        mips_isa = 3;
282
        break;
283
      case bfd_mach_mips4300:
284
        target_processor = 4300;
285
        mips_isa = 3;
286
        break;
287
      case bfd_mach_mips4400:
288
        target_processor = 4400;
289
        mips_isa = 3;
290
        break;
291
      case bfd_mach_mips4600:
292
        target_processor = 4600;
293
        mips_isa = 3;
294
        break;
295
      case bfd_mach_mips4650:
296
        target_processor = 4650;
297
        mips_isa = 3;
298
        break;
299
      case bfd_mach_mips5000:
300
        target_processor = 5000;
301
        mips_isa = 4;
302
        break;
303
      case bfd_mach_mips6000:
304
        target_processor = 6000;
305
        mips_isa = 2;
306
        break;
307
      case bfd_mach_mips8000:
308
        target_processor = 8000;
309
        mips_isa = 4;
310
        break;
311
      case bfd_mach_mips10000:
312
        target_processor = 10000;
313
        mips_isa = 4;
314
        break;
315
      case bfd_mach_mips16:
316
        target_processor = 16;
317
        mips_isa = 3;
318
        break;
319
      default:
320
        target_processor = 3000;
321
        mips_isa = 3;
322
        break;
323
 
324
    }
325
 
326
  *isa = mips_isa;
327
  *cputype = target_processor;
328
}
329
 
330
#endif /* SYMTAB_AVAILABLE */
331
 
332
/* Print the mips instruction at address MEMADDR in debugged memory,
333
   on using INFO.  Returns length of the instruction, in bytes, which is
334
   always 4.  BIGENDIAN must be 1 if this is big-endian code, 0 if
335
   this is little-endian code.  */
336
 
337
static int
338
_print_insn_mips (memaddr, word, info)
339
     bfd_vma memaddr;
340
     unsigned long int word;
341
     struct disassemble_info *info;
342
{
343
  register const struct mips_opcode *op;
344
  int target_processor, mips_isa;
345
  static boolean init = 0;
346
  static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
347
 
348
  /* Build a hash table to shorten the search time.  */
349
  if (! init)
350
    {
351
      unsigned int i;
352
 
353
      for (i = 0; i <= OP_MASK_OP; i++)
354
        {
355
          for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
356
            {
357
              if (op->pinfo == INSN_MACRO)
358
                continue;
359
              if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP))
360
                {
361
                  mips_hash[i] = op;
362
                  break;
363
                }
364
            }
365
        }
366
 
367
      init = 1;
368
    }
369
 
370
#if ! SYMTAB_AVAILABLE
371
  /* This is running out on a target machine, not in a host tool.
372
     FIXME: Where does mips_target_info come from?  */
373
  target_processor = mips_target_info.processor;
374
  mips_isa = mips_target_info.isa;
375
#else  
376
  set_mips_isa_type (info->mach, &mips_isa, &target_processor);
377
#endif  
378
 
379
  info->bytes_per_chunk = 4;
380
  info->display_endian = info->endian;
381
 
382
  op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
383
  if (op != NULL)
384
    {
385
      for (; op < &mips_opcodes[NUMOPCODES]; op++)
386
        {
387
          if (op->pinfo != INSN_MACRO && (word & op->mask) == op->match)
388
            {
389
              register const char *d;
390
 
391
              if (! OPCODE_IS_MEMBER (op, mips_isa, target_processor, 0))
392
                continue;
393
 
394
              (*info->fprintf_func) (info->stream, "%s", op->name);
395
 
396
              d = op->args;
397
              if (d != NULL && *d != '\0')
398
                {
399
                    (*info->fprintf_func) (info->stream, "\t");
400
                  for (; *d != '\0'; d++)
401
                      print_insn_arg (d, word, memaddr, info);
402
                }
403
 
404
              return 4;
405
            }
406
        }
407
    }
408
 
409
  /* Handle undefined instructions.  */
410
  (*info->fprintf_func) (info->stream, "0x%x", word);
411
  return 4;
412
}
413
 
414
 
415
/* In an environment where we do not know the symbol type of the
416
   instruction we are forced to assume that the low order bit of the
417
   instructions' address may mark it as a mips16 instruction.  If we
418
   are single stepping, or the pc is within the disassembled function,
419
   this works.  Otherwise, we need a clue.  Sometimes.  */
420
 
421
int
422
print_insn_big_mips (memaddr, info)
423
     bfd_vma memaddr;
424
     struct disassemble_info *info;
425
{
426
  bfd_byte buffer[4];
427
  int status;
428
 
429
#if 1
430
  /* FIXME: If odd address, this is CLEARLY a mips 16 instruction.  */
431
  /* Only a few tools will work this way.  */
432
  if (memaddr & 0x01)
433
    return print_insn_mips16 (memaddr, info);
434
#endif  
435
 
436
#if SYMTAB_AVAILABLE
437
  if (info->mach == 16
438
      || (info->flavour == bfd_target_elf_flavour
439
          && info->symbols != NULL
440
          && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other
441
              == STO_MIPS16)))
442
    return print_insn_mips16 (memaddr, info);
443
#endif  
444
 
445
  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
446
  if (status == 0)
447
    return _print_insn_mips (memaddr, (unsigned long) bfd_getb32 (buffer),
448
                             info);
449
  else
450
    {
451
      (*info->memory_error_func) (status, memaddr, info);
452
      return -1;
453
    }
454
}
455
 
456
int
457
print_insn_little_mips (memaddr, info)
458
     bfd_vma memaddr;
459
     struct disassemble_info *info;
460
{
461
  bfd_byte buffer[4];
462
  int status;
463
 
464
 
465
#if 1
466
  if (memaddr & 0x01)
467
    return print_insn_mips16 (memaddr, info);
468
#endif  
469
 
470
#if SYMTAB_AVAILABLE
471
  if (info->mach == 16
472
      || (info->flavour == bfd_target_elf_flavour
473
          && info->symbols != NULL
474
          && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other
475
              == STO_MIPS16)))
476
    return print_insn_mips16 (memaddr, info);
477
#endif  
478
 
479
  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
480
  if (status == 0)
481
    return _print_insn_mips (memaddr, (unsigned long) bfd_getl32 (buffer),
482
                             info);
483
  else
484
    {
485
      (*info->memory_error_func) (status, memaddr, info);
486
      return -1;
487
    }
488
}
489
 
490
/* Disassemble mips16 instructions.  */
491
 
492
static int
493
print_insn_mips16 (memaddr, info)
494
     bfd_vma memaddr;
495
     struct disassemble_info *info;
496
{
497
  int status;
498
  bfd_byte buffer[2];
499
  int length;
500
  int insn;
501
  boolean use_extend;
502
  int extend = 0;
503
  const struct mips_opcode *op, *opend;
504
 
505
  info->bytes_per_chunk = 2;
506
  info->display_endian = info->endian;
507
 
508
  info->insn_info_valid = 1;
509
  info->branch_delay_insns = 0;
510
  info->data_size = 0;
511
  info->insn_type = dis_nonbranch;
512
  info->target = 0;
513
  info->target2 = 0;
514
 
515
  status = (*info->read_memory_func) (memaddr, buffer, 2, info);
516
  if (status != 0)
517
    {
518
      (*info->memory_error_func) (status, memaddr, info);
519
      return -1;
520
    }
521
 
522
  length = 2;
523
 
524
  if (info->endian == BFD_ENDIAN_BIG)
525
    insn = bfd_getb16 (buffer);
526
  else
527
    insn = bfd_getl16 (buffer);
528
 
529
  /* Handle the extend opcode specially.  */
530
  use_extend = false;
531
  if ((insn & 0xf800) == 0xf000)
532
    {
533
      use_extend = true;
534
      extend = insn & 0x7ff;
535
 
536
      memaddr += 2;
537
 
538
      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
539
      if (status != 0)
540
        {
541
          (*info->fprintf_func) (info->stream, "extend 0x%x",
542
                                 (unsigned int) extend);
543
          (*info->memory_error_func) (status, memaddr, info);
544
          return -1;
545
        }
546
 
547
      if (info->endian == BFD_ENDIAN_BIG)
548
        insn = bfd_getb16 (buffer);
549
      else
550
        insn = bfd_getl16 (buffer);
551
 
552
      /* Check for an extend opcode followed by an extend opcode.  */
553
      if ((insn & 0xf800) == 0xf000)
554
        {
555
          (*info->fprintf_func) (info->stream, "extend 0x%x",
556
                                 (unsigned int) extend);
557
          info->insn_type = dis_noninsn;
558
          return length;
559
        }
560
 
561
      length += 2;
562
    }
563
 
564
  /* FIXME: Should probably use a hash table on the major opcode here.  */
565
 
566
  opend = mips16_opcodes + bfd_mips16_num_opcodes;
567
  for (op = mips16_opcodes; op < opend; op++)
568
    {
569
      if (op->pinfo != INSN_MACRO && (insn & op->mask) == op->match)
570
        {
571
          const char *s;
572
 
573
          if (strchr (op->args, 'a') != NULL)
574
            {
575
              if (use_extend)
576
                {
577
                  (*info->fprintf_func) (info->stream, "extend 0x%x",
578
                                         (unsigned int) extend);
579
                  info->insn_type = dis_noninsn;
580
                  return length - 2;
581
                }
582
 
583
              use_extend = false;
584
 
585
              memaddr += 2;
586
 
587
              status = (*info->read_memory_func) (memaddr, buffer, 2,
588
                                                  info);
589
              if (status == 0)
590
                {
591
                  use_extend = true;
592
                  if (info->endian == BFD_ENDIAN_BIG)
593
                    extend = bfd_getb16 (buffer);
594
                  else
595
                    extend = bfd_getl16 (buffer);
596
                  length += 2;
597
                }
598
            }
599
 
600
          (*info->fprintf_func) (info->stream, "%s", op->name);
601
          if (op->args[0] != '\0')
602
            (*info->fprintf_func) (info->stream, "\t");
603
 
604
          for (s = op->args; *s != '\0'; s++)
605
            {
606
              if (*s == ','
607
                  && s[1] == 'w'
608
                  && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)
609
                      == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY)))
610
                {
611
                  /* Skip the register and the comma.  */
612
                  ++s;
613
                  continue;
614
                }
615
              if (*s == ','
616
                  && s[1] == 'v'
617
                  && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ)
618
                      == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)))
619
                {
620
                  /* Skip the register and the comma.  */
621
                  ++s;
622
                  continue;
623
                }
624
              print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr,
625
                                     info);
626
            }
627
 
628
          if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
629
            {
630
              info->branch_delay_insns = 1;
631
              if (info->insn_type != dis_jsr)
632
                info->insn_type = dis_branch;
633
            }
634
 
635
          return length;
636
        }
637
    }
638
 
639
  if (use_extend)
640
    (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000);
641
  (*info->fprintf_func) (info->stream, "0x%x", insn);
642
  info->insn_type = dis_noninsn;
643
 
644
  return length;
645
}
646
 
647
/* Disassemble an operand for a mips16 instruction.  */
648
 
649
static void
650
print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info)
651
     int type;
652
     const struct mips_opcode *op;
653
     int l;
654
     boolean use_extend;
655
     int extend;
656
     bfd_vma memaddr;
657
     struct disassemble_info *info;
658
{
659
  switch (type)
660
    {
661
    case ',':
662
    case '(':
663
    case ')':
664
      (*info->fprintf_func) (info->stream, "%c", type);
665
      break;
666
 
667
    case 'y':
668
    case 'w':
669
      (*info->fprintf_func) (info->stream, "$%s",
670
                             mips16_reg_names[((l >> MIPS16OP_SH_RY)
671
                                               & MIPS16OP_MASK_RY)]);
672
      break;
673
 
674
    case 'x':
675
    case 'v':
676
      (*info->fprintf_func) (info->stream, "$%s",
677
                             mips16_reg_names[((l >> MIPS16OP_SH_RX)
678
                                               & MIPS16OP_MASK_RX)]);
679
      break;
680
 
681
    case 'z':
682
      (*info->fprintf_func) (info->stream, "$%s",
683
                             mips16_reg_names[((l >> MIPS16OP_SH_RZ)
684
                                               & MIPS16OP_MASK_RZ)]);
685
      break;
686
 
687
    case 'Z':
688
      (*info->fprintf_func) (info->stream, "$%s",
689
                             mips16_reg_names[((l >> MIPS16OP_SH_MOVE32Z)
690
                                               & MIPS16OP_MASK_MOVE32Z)]);
691
      break;
692
 
693
    case '0':
694
      (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
695
      break;
696
 
697
    case 'S':
698
      (*info->fprintf_func) (info->stream, "$%s", reg_names[29]);
699
      break;
700
 
701
    case 'P':
702
      (*info->fprintf_func) (info->stream, "$pc");
703
      break;
704
 
705
    case 'R':
706
      (*info->fprintf_func) (info->stream, "$%s", reg_names[31]);
707
      break;
708
 
709
    case 'X':
710
      (*info->fprintf_func) (info->stream, "$%s",
711
                             reg_names[((l >> MIPS16OP_SH_REGR32)
712
                                        & MIPS16OP_MASK_REGR32)]);
713
      break;
714
 
715
    case 'Y':
716
      (*info->fprintf_func) (info->stream, "$%s",
717
                             reg_names[MIPS16OP_EXTRACT_REG32R (l)]);
718
      break;
719
 
720
    case '<':
721
    case '>':
722
    case '[':
723
    case ']':
724
    case '4':
725
    case '5':
726
    case 'H':
727
    case 'W':
728
    case 'D':
729
    case 'j':
730
    case '6':
731
    case '8':
732
    case 'V':
733
    case 'C':
734
    case 'U':
735
    case 'k':
736
    case 'K':
737
    case 'p':
738
    case 'q':
739
    case 'A':
740
    case 'B':
741
    case 'E':
742
      {
743
        int immed, nbits, shift, signedp, extbits, pcrel, extu, branch;
744
 
745
        shift = 0;
746
        signedp = 0;
747
        extbits = 16;
748
        pcrel = 0;
749
        extu = 0;
750
        branch = 0;
751
        switch (type)
752
          {
753
          case '<':
754
            nbits = 3;
755
            immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
756
            extbits = 5;
757
            extu = 1;
758
            break;
759
          case '>':
760
            nbits = 3;
761
            immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
762
            extbits = 5;
763
            extu = 1;
764
            break;
765
          case '[':
766
            nbits = 3;
767
            immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
768
            extbits = 6;
769
            extu = 1;
770
            break;
771
          case ']':
772
            nbits = 3;
773
            immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
774
            extbits = 6;
775
            extu = 1;
776
            break;
777
          case '4':
778
            nbits = 4;
779
            immed = (l >> MIPS16OP_SH_IMM4) & MIPS16OP_MASK_IMM4;
780
            signedp = 1;
781
            extbits = 15;
782
            break;
783
          case '5':
784
            nbits = 5;
785
            immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
786
            info->insn_type = dis_dref;
787
            info->data_size = 1;
788
            break;
789
          case 'H':
790
            nbits = 5;
791
            shift = 1;
792
            immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
793
            info->insn_type = dis_dref;
794
            info->data_size = 2;
795
            break;
796
          case 'W':
797
            nbits = 5;
798
            shift = 2;
799
            immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
800
            if ((op->pinfo & MIPS16_INSN_READ_PC) == 0
801
                && (op->pinfo & MIPS16_INSN_READ_SP) == 0)
802
              {
803
                info->insn_type = dis_dref;
804
                info->data_size = 4;
805
              }
806
            break;
807
          case 'D':
808
            nbits = 5;
809
            shift = 3;
810
            immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
811
            info->insn_type = dis_dref;
812
            info->data_size = 8;
813
            break;
814
          case 'j':
815
            nbits = 5;
816
            immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
817
            signedp = 1;
818
            break;
819
          case '6':
820
            nbits = 6;
821
            immed = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
822
            break;
823
          case '8':
824
            nbits = 8;
825
            immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
826
            break;
827
          case 'V':
828
            nbits = 8;
829
            shift = 2;
830
            immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
831
            /* FIXME: This might be lw, or it might be addiu to $sp or
832
               $pc.  We assume it's load.  */
833
            info->insn_type = dis_dref;
834
            info->data_size = 4;
835
            break;
836
          case 'C':
837
            nbits = 8;
838
            shift = 3;
839
            immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
840
            info->insn_type = dis_dref;
841
            info->data_size = 8;
842
            break;
843
          case 'U':
844
            nbits = 8;
845
            immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
846
            extu = 1;
847
            break;
848
          case 'k':
849
            nbits = 8;
850
            immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
851
            signedp = 1;
852
            break;
853
          case 'K':
854
            nbits = 8;
855
            shift = 3;
856
            immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
857
            signedp = 1;
858
            break;
859
          case 'p':
860
            nbits = 8;
861
            immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
862
            signedp = 1;
863
            pcrel = 1;
864
            branch = 1;
865
            info->insn_type = dis_condbranch;
866
            break;
867
          case 'q':
868
            nbits = 11;
869
            immed = (l >> MIPS16OP_SH_IMM11) & MIPS16OP_MASK_IMM11;
870
            signedp = 1;
871
            pcrel = 1;
872
            branch = 1;
873
            info->insn_type = dis_branch;
874
            break;
875
          case 'A':
876
            nbits = 8;
877
            shift = 2;
878
            immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
879
            pcrel = 1;
880
            /* FIXME: This can be lw or la.  We assume it is lw.  */
881
            info->insn_type = dis_dref;
882
            info->data_size = 4;
883
            break;
884
          case 'B':
885
            nbits = 5;
886
            shift = 3;
887
            immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
888
            pcrel = 1;
889
            info->insn_type = dis_dref;
890
            info->data_size = 8;
891
            break;
892
          case 'E':
893
            nbits = 5;
894
            shift = 2;
895
            immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
896
            pcrel = 1;
897
            break;
898
          default:
899
            abort ();
900
          }
901
 
902
        if (! use_extend)
903
          {
904
            if (signedp && immed >= (1 << (nbits - 1)))
905
              immed -= 1 << nbits;
906
            immed <<= shift;
907
            if ((type == '<' || type == '>' || type == '[' || type == ']')
908
                && immed == 0)
909
              immed = 8;
910
          }
911
        else
912
          {
913
            if (extbits == 16)
914
              immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
915
            else if (extbits == 15)
916
              immed |= ((extend & 0xf) << 11) | (extend & 0x7f0);
917
            else
918
              immed = ((extend >> 6) & 0x1f) | (extend & 0x20);
919
            immed &= (1 << extbits) - 1;
920
            if (! extu && immed >= (1 << (extbits - 1)))
921
              immed -= 1 << extbits;
922
          }
923
 
924
        if (! pcrel)
925
          (*info->fprintf_func) (info->stream, "%d", immed);
926
        else
927
          {
928
            bfd_vma baseaddr;
929
            bfd_vma val;
930
 
931
            if (branch)
932
              {
933
                immed *= 2;
934
                baseaddr = memaddr + 2;
935
              }
936
            else if (use_extend)
937
              baseaddr = memaddr - 2;
938
            else
939
              {
940
                int status;
941
                bfd_byte buffer[2];
942
 
943
                baseaddr = memaddr;
944
 
945
                /* If this instruction is in the delay slot of a jr
946
                   instruction, the base address is the address of the
947
                   jr instruction.  If it is in the delay slot of jalr
948
                   instruction, the base address is the address of the
949
                   jalr instruction.  This test is unreliable: we have
950
                   no way of knowing whether the previous word is
951
                   instruction or data.  */
952
                status = (*info->read_memory_func) (memaddr - 4, buffer, 2,
953
                                                    info);
954
                if (status == 0
955
                    && (((info->endian == BFD_ENDIAN_BIG
956
                          ? bfd_getb16 (buffer)
957
                          : bfd_getl16 (buffer))
958
                         & 0xf800) == 0x1800))
959
                  baseaddr = memaddr - 4;
960
                else
961
                  {
962
                    status = (*info->read_memory_func) (memaddr - 2, buffer,
963
                                                        2, info);
964
                    if (status == 0
965
                        && (((info->endian == BFD_ENDIAN_BIG
966
                              ? bfd_getb16 (buffer)
967
                              : bfd_getl16 (buffer))
968
                             & 0xf81f) == 0xe800))
969
                      baseaddr = memaddr - 2;
970
                  }
971
              }
972
            val = (baseaddr & ~ ((1 << shift) - 1)) + immed;
973
            (*info->print_address_func) (val, info);
974
            info->target = val;
975
          }
976
      }
977
      break;
978
 
979
    case 'a':
980
      if (! use_extend)
981
        extend = 0;
982
      l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
983
      (*info->print_address_func) ((memaddr & 0xf0000000) | l, info);
984
      info->insn_type = dis_jsr;
985
      info->target = (memaddr & 0xf0000000) | l;
986
      info->branch_delay_insns = 1;
987
      break;
988
 
989
    case 'l':
990
    case 'L':
991
      {
992
        int need_comma, amask, smask;
993
 
994
        need_comma = 0;
995
 
996
        l = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
997
 
998
        amask = (l >> 3) & 7;
999
 
1000
        if (amask > 0 && amask < 5)
1001
          {
1002
            (*info->fprintf_func) (info->stream, "$%s", reg_names[4]);
1003
            if (amask > 1)
1004
              (*info->fprintf_func) (info->stream, "-$%s",
1005
                                     reg_names[amask + 3]);
1006
            need_comma = 1;
1007
          }
1008
 
1009
        smask = (l >> 1) & 3;
1010
        if (smask == 3)
1011
          {
1012
            (*info->fprintf_func) (info->stream, "%s??",
1013
                                   need_comma ? "," : "");
1014
            need_comma = 1;
1015
          }
1016
        else if (smask > 0)
1017
          {
1018
            (*info->fprintf_func) (info->stream, "%s$%s",
1019
                                   need_comma ? "," : "",
1020
                                   reg_names[16]);
1021
            if (smask > 1)
1022
              (*info->fprintf_func) (info->stream, "-$%s",
1023
                                     reg_names[smask + 15]);
1024
            need_comma = 1;
1025
          }
1026
 
1027
        if (l & 1)
1028
          {
1029
            (*info->fprintf_func) (info->stream, "%s$%s",
1030
                                   need_comma ? "," : "",
1031
                                   reg_names[31]);
1032
            need_comma = 1;
1033
          }
1034
 
1035
        if (amask == 5 || amask == 6)
1036
          {
1037
            (*info->fprintf_func) (info->stream, "%s$f0",
1038
                                   need_comma ? "," : "");
1039
            if (amask == 6)
1040
              (*info->fprintf_func) (info->stream, "-$f1");
1041
          }
1042
      }
1043
      break;
1044
 
1045
    default:
1046
      abort ();
1047
    }
1048
}

powered by: WebSVN 2.1.0

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