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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [opcodes/] [v850-dis.c] - Blame information for rev 53

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

Line No. Rev Author Line
1 18 khays
/* Disassemble V850 instructions.
2
   Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2007, 2010
3
   Free Software Foundation, Inc.
4
 
5
   This file is part of the GNU opcodes library.
6
 
7
   This library 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 3, or (at your option)
10
   any later version.
11
 
12
   It is distributed in the hope that it will be useful, but WITHOUT
13
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15
   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., 51 Franklin Street - Fifth Floor, Boston,
20
   MA 02110-1301, USA.  */
21
 
22
 
23
#include <stdio.h>
24
 
25
#include "sysdep.h"
26
#include "opcode/v850.h"
27
#include "dis-asm.h"
28
#include "opintl.h"
29
 
30
static const char *const v850_reg_names[] =
31
{
32
  "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7",
33
  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
34
  "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
35
  "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp"
36
};
37
 
38
static const char *const v850_sreg_names[] =
39
{
40
  "eipc/vip/mpm", "eipsw/mpc", "fepc/tid", "fepsw/ppa", "ecr/vmecr", "psw/vmtid",
41
  "sr6/fpsr/vmadr/dcc", "sr7/fpepc/dc0",
42
  "sr8/fpst/vpecr/dcv1", "sr9/fpcc/vptid", "sr10/fpcfg/vpadr/spal", "sr11/spau",
43
  "sr12/vdecr/ipa0l", "eiic/vdtid/ipa0u", "feic/ipa1l", "dbic/ipa1u",
44
  "ctpc/ipa2l", "ctpsw/ipa2u", "dbpc/ipa3l", "dbpsw/ipa3u", "ctbp/dpa0l",
45
  "dir/dpa0u", "bpc/dpa0u", "asid/dpa1l",
46
  "bpav/dpa1u", "bpam/dpa2l", "bpdv/dpa2u", "bpdm/dpa3l", "eiwr/dpa3u",
47
  "fewr", "dbwr", "bsel"
48
};
49
 
50
static const char *const v850_cc_names[] =
51
{
52
  "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
53
  "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt"
54
};
55
 
56
static const char *const v850_float_cc_names[] =
57
{
58
  "f/t", "un/or", "eq/neq", "ueq/ogl", "olt/uge", "ult/oge", "ole/ugt", "ule/ogt",
59
  "sf/st", "ngle/gle", "seq/sne", "ngl/gl", "lt/nlt", "nge/ge", "le/nle", "ngt/gt"
60
};
61
 
62
 
63
static void
64
print_value (int flags, bfd_vma memaddr, struct disassemble_info *info, long value)
65
{
66
  if (flags & V850_PCREL)
67
    {
68
      bfd_vma addr = value + memaddr;
69
      info->print_address_func (addr, info);
70
    }
71
  else if (flags & V850_OPERAND_DISP)
72
    {
73
      if (flags & V850_OPERAND_SIGNED)
74
        {
75
          info->fprintf_func (info->stream, "%ld", value);
76
        }
77
      else
78
        {
79
          info->fprintf_func (info->stream, "%lu", value);
80
        }
81
    }
82
  else if (flags & V850E_IMMEDIATE32)
83
    {
84
      info->fprintf_func (info->stream, "0x%lx", value);
85
    }
86
  else
87
    {
88
      if (flags & V850_OPERAND_SIGNED)
89
        {
90
          info->fprintf_func (info->stream, "%ld", value);
91
        }
92
      else
93
        {
94
          info->fprintf_func (info->stream, "%lu", value);
95
        }
96
    }
97
}
98
 
99
static long
100
get_operand_value (const struct v850_operand *operand,
101
                   unsigned long insn,
102
                   int bytes_read,
103
                   bfd_vma memaddr,
104
                   struct disassemble_info * info,
105
                   bfd_boolean noerror,
106
                   int *invalid)
107
{
108
  long value;
109
  bfd_byte buffer[4];
110
 
111
  if ((operand->flags & V850E_IMMEDIATE16)
112
      || (operand->flags & V850E_IMMEDIATE16HI))
113
    {
114
      int status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info);
115
 
116
      if (status == 0)
117
        {
118
          value = bfd_getl16 (buffer);
119
 
120
          if (operand->flags & V850E_IMMEDIATE16HI)
121
            value <<= 16;
122
 
123
          return value;
124
        }
125
 
126
      if (!noerror)
127
        info->memory_error_func (status, memaddr + bytes_read, info);
128
 
129
      return 0;
130
    }
131
 
132
  if (operand->flags & V850E_IMMEDIATE23)
133
    {
134
      int status = info->read_memory_func (memaddr + 2, buffer, 4, info);
135
 
136
      if (status == 0)
137
        {
138
          value = bfd_getl32 (buffer);
139
 
140
          value = (operand->extract) (value, invalid);
141
 
142
          return value;
143
        }
144
 
145
      if (!noerror)
146
        info->memory_error_func (status, memaddr + bytes_read, info);
147
 
148
      return 0;
149
    }
150
 
151
  if (operand->flags & V850E_IMMEDIATE32)
152
    {
153
      int status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info);
154
 
155
      if (status == 0)
156
        {
157
          bytes_read += 4;
158
          value = bfd_getl32 (buffer);
159
 
160
          return value;
161
        }
162
 
163
      if (!noerror)
164
        info->memory_error_func (status, memaddr + bytes_read, info);
165
 
166
      return 0;
167
    }
168
 
169
  if (operand->extract)
170
    value = (operand->extract) (insn, invalid);
171
  else
172
    {
173
      if (operand->bits == -1)
174
        value = (insn & operand->shift);
175
      else
176
        value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
177
 
178
      if (operand->flags & V850_OPERAND_SIGNED)
179
        value = ((long)(value << (sizeof (long)*8 - operand->bits))
180
                 >> (sizeof (long)*8 - operand->bits));
181
    }
182
 
183
  return value;
184
}
185
 
186
 
187
static int
188
disassemble (bfd_vma memaddr, struct disassemble_info *info, int bytes_read, unsigned long insn)
189
{
190
  struct v850_opcode *op = (struct v850_opcode *)v850_opcodes;
191
  const struct v850_operand *operand;
192
  int match = 0;
193
  int target_processor;
194
 
195
  switch (info->mach)
196
    {
197
    case 0:
198
    default:
199
      target_processor = PROCESSOR_V850;
200
      break;
201
 
202
    case bfd_mach_v850e:
203
      target_processor = PROCESSOR_V850E;
204
      break;
205
 
206
    case bfd_mach_v850e1:
207
      target_processor = PROCESSOR_V850E;
208
      break;
209
 
210
    case bfd_mach_v850e2:
211
      target_processor = PROCESSOR_V850E2;
212
      break;
213
 
214
    case bfd_mach_v850e2v3:
215
      target_processor = PROCESSOR_V850E2V3;
216
      break;
217
    }
218
 
219
  /* If this is a two byte insn, then mask off the high bits.  */
220
  if (bytes_read == 2)
221
    insn &= 0xffff;
222
 
223
  /* Find the opcode.  */
224
  while (op->name)
225
    {
226
      if ((op->mask & insn) == op->opcode
227
          && (op->processors & target_processor)
228
          && !(op->processors & PROCESSOR_OPTION_ALIAS))
229
        {
230
          /* Code check start.  */
231
          const unsigned char *opindex_ptr;
232
          unsigned int opnum;
233
          unsigned int memop;
234
 
235
          for (opindex_ptr = op->operands, opnum = 1;
236
               *opindex_ptr != 0;
237
               opindex_ptr++, opnum++)
238
            {
239
              int invalid = 0;
240
              long value;
241
 
242
              operand = &v850_operands[*opindex_ptr];
243
 
244
              value = get_operand_value (operand, insn, bytes_read, memaddr, info, 1, &invalid);
245
 
246
              if (invalid)
247
                goto next_opcode;
248
 
249
              if ((operand->flags & V850_NOT_R0) && value == 0 && (op->memop) <=2)
250
                goto next_opcode;
251
 
252
              if ((operand->flags & V850_NOT_SA) && value == 0xd)
253
                goto next_opcode;
254
 
255
              if ((operand->flags & V850_NOT_IMM0) && value == 0)
256
                goto next_opcode;
257
            }
258
 
259
          /* Code check end.  */
260
 
261
          match = 1;
262
          (*info->fprintf_func) (info->stream, "%s\t", op->name);
263
#if 0
264
          fprintf (stderr, "match: insn: %lx, mask: %lx, opcode: %lx, name: %s\n",
265
                   insn, op->mask, op->opcode, op->name );
266
#endif
267
 
268
          memop = op->memop;
269
          /* Now print the operands.
270
 
271
             MEMOP is the operand number at which a memory
272
             address specification starts, or zero if this
273
             instruction has no memory addresses.
274
 
275
             A memory address is always two arguments.
276
 
277
             This information allows us to determine when to
278
             insert commas into the output stream as well as
279
             when to insert disp[reg] expressions onto the
280
             output stream.  */
281
 
282
          for (opindex_ptr = op->operands, opnum = 1;
283
               *opindex_ptr != 0;
284
               opindex_ptr++, opnum++)
285
            {
286
              bfd_boolean square = FALSE;
287
              long value;
288
              int flag;
289
              char *prefix;
290
 
291
              operand = &v850_operands[*opindex_ptr];
292
 
293
              value = get_operand_value (operand, insn, bytes_read, memaddr, info, 0, 0);
294
 
295
              /* The first operand is always output without any
296
                 special handling.
297
 
298
                 For the following arguments:
299
 
300
                   If memop && opnum == memop + 1, then we need '[' since
301
                   we're about to output the register used in a memory
302
                   reference.
303
 
304
                   If memop && opnum == memop + 2, then we need ']' since
305
                   we just finished the register in a memory reference.  We
306
                   also need a ',' before this operand.
307
 
308
                   Else we just need a comma.
309
 
310
                   We may need to output a trailing ']' if the last operand
311
                   in an instruction is the register for a memory address.
312
 
313
                   The exception (and there's always an exception) is the
314
                   "jmp" insn which needs square brackets around it's only
315
                   register argument.  */
316
              prefix = "";
317
              if (operand->flags & V850_OPERAND_BANG)
318
                {
319
                  prefix = "!";
320
                }
321
              else if (operand->flags & V850_OPERAND_PERCENT)
322
                {
323
                  prefix = "%";
324
                }
325
 
326
              if (opnum == 1 && opnum == memop)
327
                {
328
                  info->fprintf_func (info->stream, "%s[", prefix);
329
                  square = TRUE;
330
                }
331
              else if (opnum > 1
332
                       && (v850_operands[*(opindex_ptr - 1)].flags & V850_OPERAND_DISP) != 0
333
                       && opnum == memop)
334
                {
335
                  info->fprintf_func (info->stream, "%s[", prefix);
336
                  square = TRUE;
337
                }
338
              else if (opnum > 1)
339
                info->fprintf_func (info->stream, ", %s", prefix);
340
 
341
              /* Extract the flags, ignoring ones which do not effect disassembly output.  */
342
              flag = operand->flags & (V850_OPERAND_REG
343
                                       | V850_REG_EVEN
344
                                       | V850_OPERAND_EP
345
                                       | V850_OPERAND_SRG
346
                                       | V850E_OPERAND_REG_LIST
347
                                       | V850_OPERAND_CC
348
                                       | V850_OPERAND_FLOAT_CC);
349
 
350
              switch (flag)
351
                {
352
                case V850_OPERAND_REG:  info->fprintf_func (info->stream, "%s", v850_reg_names[value]); break;
353
                case (V850_OPERAND_REG|V850_REG_EVEN):  info->fprintf_func (info->stream, "%s", v850_reg_names[value*2]); break;
354
                case V850_OPERAND_EP:   info->fprintf_func (info->stream, "ep"); break;
355
                case V850_OPERAND_SRG:  info->fprintf_func (info->stream, "%s", v850_sreg_names[value]); break;
356
 
357
                case V850E_OPERAND_REG_LIST:
358
                  {
359
                    static int list12_regs[32]   = { 30, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
360
                                                     0,  0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
361
                    int *regs;
362
                    int i;
363
                    unsigned long int mask = 0;
364
                    int pc = 0;
365
 
366
 
367
                    switch (operand->shift)
368
                      {
369
                      case 0xffe00001: regs = list12_regs; break;
370
                      default:
371
                        /* xgettext:c-format */
372
                        fprintf (stderr, _("unknown operand shift: %x\n"), operand->shift );
373
                        abort ();
374
                      }
375
 
376
                    for (i = 0; i < 32; i++)
377
                      {
378
                        if (value & (1 << i))
379
                          {
380
                            switch (regs[ i ])
381
                              {
382
                              default: mask |= (1 << regs[ i ]); break;
383
                                /* xgettext:c-format */
384
                              case 0:  fprintf (stderr, _("unknown reg: %d\n"), i ); abort ();
385
                              case -1: pc = 1; break;
386
                              }
387
                          }
388
                      }
389
 
390
                    info->fprintf_func (info->stream, "{");
391
 
392
                    if (mask || pc)
393
                      {
394
                        if (mask)
395
                          {
396
                            unsigned int bit;
397
                            int shown_one = 0;
398
 
399
                            for (bit = 0; bit < 32; bit++)
400
                              if (mask & (1 << bit))
401
                                {
402
                                  unsigned long int first = bit;
403
                                  unsigned long int last;
404
 
405
                                  if (shown_one)
406
                                    info->fprintf_func (info->stream, ", ");
407
                                  else
408
                                    shown_one = 1;
409
 
410
                                  info->fprintf_func (info->stream, v850_reg_names[first]);
411
 
412
                                  for (bit++; bit < 32; bit++)
413
                                    if ((mask & (1 << bit)) == 0)
414
                                      break;
415
 
416
                                  last = bit;
417
 
418
                                  if (last > first + 1)
419
                                    {
420
                                      info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]);
421
                                    }
422
                                }
423
                          }
424
 
425
                        if (pc)
426
                          info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
427
                      }
428
 
429
                    info->fprintf_func (info->stream, "}");
430
                  }
431
                  break;
432
 
433
                case V850_OPERAND_CC:   info->fprintf_func (info->stream, "%s", v850_cc_names[value]); break;
434
                case V850_OPERAND_FLOAT_CC:   info->fprintf_func (info->stream, "%s", v850_float_cc_names[value]); break;
435
 
436
                default:
437
                  print_value (operand->flags, memaddr, info, value);
438
                  break;
439
                }
440
 
441
              if (square)
442
                (*info->fprintf_func) (info->stream, "]");
443
            }
444
 
445
          /* All done. */
446
          break;
447
        }
448
    next_opcode:
449
      op++;
450
    }
451
 
452
  return match;
453
}
454
 
455
int
456
print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
457
{
458
  int status, status2, match;
459
  bfd_byte buffer[8];
460
  int length = 0, code_length = 0;
461
  unsigned long insn = 0, insn2 = 0;
462
  int target_processor;
463
 
464
  switch (info->mach)
465
    {
466
    case 0:
467
    default:
468
      target_processor = PROCESSOR_V850;
469
      break;
470
 
471
    case bfd_mach_v850e:
472
      target_processor = PROCESSOR_V850E;
473
      break;
474
 
475
    case bfd_mach_v850e1:
476
      target_processor = PROCESSOR_V850E;
477
      break;
478
 
479
    case bfd_mach_v850e2:
480
      target_processor = PROCESSOR_V850E2;
481
      break;
482
 
483
    case bfd_mach_v850e2v3:
484
      target_processor = PROCESSOR_V850E2V3;
485
      break;
486
    }
487
 
488
  status = info->read_memory_func (memaddr, buffer, 2, info);
489
 
490
  if (status)
491
    {
492
      info->memory_error_func (status, memaddr, info);
493
      return -1;
494
    }
495
 
496
  insn = bfd_getl16 (buffer);
497
 
498
  status2 = info->read_memory_func (memaddr+2, buffer, 2 , info);
499
 
500
  if (!status2)
501
    {
502
      insn2 = bfd_getl16 (buffer);
503
      /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
504
    }
505
 
506
  /* Special case.  */
507
  if (length == 0
508
      && (target_processor == PROCESSOR_V850E2
509
          || target_processor == PROCESSOR_V850E2V3))
510
    {
511
      if ((insn & 0xffff) == 0x02e0             /* jr 32bit */
512
          && !status2 && (insn2 & 0x1) == 0)
513
        {
514
          length = 2;
515
          code_length = 6;
516
        }
517
      else if ((insn & 0xffe0) == 0x02e0        /* jarl 32bit */
518
               && !status2 && (insn2 & 0x1) == 0)
519
        {
520
          length = 2;
521
          code_length = 6;
522
        }
523
      else if ((insn & 0xffe0) == 0x06e0        /* jmp 32bit */
524
               && !status2 && (insn2 & 0x1) == 0)
525
        {
526
          length = 2;
527
          code_length = 6;
528
        }
529
    }
530
 
531
  if (length == 0
532
      && target_processor == PROCESSOR_V850E2V3)
533
    {
534
      if (((insn & 0xffe0) == 0x0780            /* ld.b 23bit */
535
           && !status2 && (insn2 & 0x000f) == 0x0005)
536
          || ((insn & 0xffe0) == 0x07a0         /* ld.bu 23bit */
537
              && !status2 && (insn2 & 0x000f) == 0x0005)
538
          || ((insn & 0xffe0) == 0x0780         /* ld.h 23bit */
539
              && !status2 && (insn2 & 0x000f) == 0x0007)
540
          || ((insn & 0xffe0) == 0x07a0         /* ld.hu 23bit */
541
              && !status2 && (insn2 & 0x000f) == 0x0007)
542
          || ((insn & 0xffe0) == 0x0780         /* ld.w 23bit */
543
              && !status2 && (insn2 & 0x000f) == 0x0009))
544
        {
545
          length = 4;
546
          code_length = 6;
547
        }
548
      else if (((insn & 0xffe0) == 0x0780       /* st.b 23bit */
549
               && !status2 && (insn2 & 0x000f) == 0x000d)
550
              || ((insn & 0xffe0) == 0x07a0     /* st.h 23bit */
551
                  && !status2 && (insn2 & 0x000f) == 0x000d)
552
              || ((insn & 0xffe0) == 0x0780     /* st.w 23bit */
553
                  && !status2 && (insn2 & 0x000f) == 0x000f))
554
        {
555
          length = 4;
556
          code_length = 6;
557
        }
558
    }
559
 
560
  if (length == 0
561
      && target_processor != PROCESSOR_V850)
562
    {
563
      if ((insn & 0xffe0) == 0x0620)            /* 32 bit MOV */
564
        {
565
          length = 2;
566
          code_length = 6;
567
        }
568
      else if ((insn & 0xffc0) == 0x0780        /* prepare {list}, imm5, imm16<<16 */
569
               && !status2 && (insn2 & 0x001f) == 0x0013)
570
        {
571
          length = 4;
572
          code_length = 6;
573
        }
574
      else if ((insn & 0xffc0) == 0x0780        /* prepare {list}, imm5, imm16 */
575
               && !status2 && (insn2 & 0x001f) == 0x000b)
576
        {
577
          length = 4;
578
          code_length = 6;
579
        }
580
      else if ((insn & 0xffc0) == 0x0780        /* prepare {list}, imm5, imm32 */
581
               && !status2 && (insn2 & 0x001f) == 0x001b)
582
        {
583
          length = 4;
584
          code_length = 8;
585
        }
586
    }
587
 
588
  if (length == 4
589
      || (length == 0
590
          && (insn & 0x0600) == 0x0600))
591
    {
592
      /* This is a 4 byte insn.  */
593
      status = info->read_memory_func (memaddr, buffer, 4, info);
594
      if (!status)
595
        {
596
          insn = bfd_getl32 (buffer);
597
 
598
          if (!length)
599
            length = code_length = 4;
600
        }
601
    }
602
 
603
  if (code_length > length)
604
    {
605
      status = info->read_memory_func (memaddr + length, buffer, code_length - length, info);
606
      if (status)
607
        length = 0;
608
    }
609
 
610
  if (length == 0 && !status)
611
    length = code_length = 2;
612
 
613
  if (length == 2)
614
    insn &= 0xffff;
615
 
616
  match = disassemble (memaddr, info, length, insn);
617
 
618
  if (!match)
619
    {
620
      int l = 0;
621
 
622
      status = info->read_memory_func (memaddr, buffer, code_length, info);
623
 
624
      while (l < code_length)
625
        {
626
          if (code_length - l == 2)
627
            {
628
              insn = bfd_getl16 (buffer + l) & 0xffff;
629
              info->fprintf_func (info->stream, ".short\t0x%04lx", insn);
630
              l += 2;
631
            }
632
          else
633
            {
634
              insn = bfd_getl32 (buffer + l);
635
              info->fprintf_func (info->stream, ".long\t0x%08lx", insn);
636
              l += 4;
637
            }
638
        }
639
    }
640
 
641
  return code_length;
642
}

powered by: WebSVN 2.1.0

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