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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [opcodes/] [mips-dis.c] - Blame information for rev 1776

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

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

powered by: WebSVN 2.1.0

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