Coverage Report

Created: 2023-08-28 06:31

/src/binutils-gdb/opcodes/v850-dis.c
Line
Count
Source (jump to first uncovered line)
1
/* Disassemble V850 instructions.
2
   Copyright (C) 1996-2023 Free Software Foundation, Inc.
3
4
   This file is part of the GNU opcodes library.
5
6
   This library is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3, or (at your option)
9
   any later version.
10
11
   It is distributed in the hope that it will be useful, but WITHOUT
12
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14
   License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with this program; if not, write to the Free Software
18
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19
   MA 02110-1301, USA.  */
20
21
22
#include "sysdep.h"
23
#include <stdio.h>
24
#include <string.h>
25
#include "opcode/v850.h"
26
#include "disassemble.h"
27
#include "opintl.h"
28
#include "libiberty.h"
29
30
static const int v850_cacheop_codes[] =
31
{
32
  0x00, 0x20, 0x40, 0x60, 0x61, 0x04, 0x06,
33
  0x07, 0x24, 0x26, 0x27, 0x44, 0x64, 0x65, -1
34
};
35
36
static const int v850_prefop_codes[] =
37
{ 0x00, 0x04, -1};
38
39
static void
40
print_value (int flags,
41
       bfd_vma memaddr,
42
       struct disassemble_info *info,
43
       long value)
44
231k
{
45
231k
  if (flags & V850_PCREL)
46
24.2k
    {
47
24.2k
      bfd_vma addr = value + memaddr;
48
49
24.2k
      if (flags & V850_INVERSE_PCREL)
50
44
  addr = memaddr - value;
51
24.2k
      info->print_address_func (addr, info);
52
24.2k
    }
53
207k
  else if (flags & V850_OPERAND_DISP)
54
135k
    {
55
135k
      if (flags & V850_OPERAND_SIGNED)
56
43.8k
        {
57
43.8k
          info->fprintf_func (info->stream, "%ld", value);
58
43.8k
        }
59
91.4k
      else
60
91.4k
        {
61
91.4k
          info->fprintf_func (info->stream, "%lu", value);
62
91.4k
        }
63
135k
    }
64
72.1k
  else if ((flags & V850E_IMMEDIATE32)
65
72.1k
     || (flags & V850E_IMMEDIATE16HI))
66
223
    {
67
223
      info->fprintf_func (info->stream, "0x%lx", value);
68
223
    }
69
71.8k
  else
70
71.8k
    {
71
71.8k
      if (flags & V850_OPERAND_SIGNED)
72
42.7k
  {
73
42.7k
    info->fprintf_func (info->stream, "%ld", value);
74
42.7k
  }
75
29.1k
      else
76
29.1k
  {
77
29.1k
    info->fprintf_func (info->stream, "%lu", value);
78
29.1k
  }
79
71.8k
    }
80
231k
}
81
82
static long
83
get_operand_value (const struct v850_operand *operand,
84
       unsigned long insn,
85
       int bytes_read,
86
       bfd_vma memaddr,
87
       struct disassemble_info * info,
88
       bool noerror,
89
       int *invalid)
90
1.68M
{
91
1.68M
  unsigned long value;
92
1.68M
  bfd_byte buffer[4];
93
94
1.68M
  if ((operand->flags & V850E_IMMEDIATE16)
95
1.68M
      || (operand->flags & V850E_IMMEDIATE16HI))
96
598
    {
97
598
      int status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info);
98
99
598
      if (status == 0)
100
598
  {
101
598
    value = bfd_getl16 (buffer);
102
103
598
    if (operand->flags & V850E_IMMEDIATE16HI)
104
26
      value <<= 16;
105
572
    else if (value & 0x8000)
106
392
      value |= (-1UL << 16);
107
108
598
    return value;
109
598
  }
110
111
0
      if (!noerror)
112
0
  info->memory_error_func (status, memaddr + bytes_read, info);
113
114
0
      return 0;
115
598
    }
116
117
1.68M
  if (operand->flags & V850E_IMMEDIATE23)
118
5.51k
    {
119
5.51k
      int status = info->read_memory_func (memaddr + 2, buffer, 4, info);
120
121
5.51k
      if (status == 0)
122
5.51k
  {
123
5.51k
    value = bfd_getl32 (buffer);
124
125
5.51k
    value = (operand->extract) (value, invalid);
126
127
5.51k
    return value;
128
5.51k
  }
129
130
0
      if (!noerror)
131
0
  info->memory_error_func (status, memaddr + bytes_read, info);
132
133
0
      return 0;
134
5.51k
    }
135
136
1.67M
  if (operand->flags & V850E_IMMEDIATE32)
137
1.76k
    {
138
1.76k
      int status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info);
139
140
1.76k
      if (status == 0)
141
1.76k
  {
142
1.76k
    bytes_read += 4;
143
1.76k
    value = bfd_getl32 (buffer);
144
145
1.76k
    return value;
146
1.76k
  }
147
148
2
      if (!noerror)
149
1
  info->memory_error_func (status, memaddr + bytes_read, info);
150
151
2
      return 0;
152
1.76k
    }
153
154
1.67M
  if (operand->extract)
155
216k
    value = (operand->extract) (insn, invalid);
156
1.45M
  else
157
1.45M
    {
158
1.45M
      if (operand->bits == -1)
159
4.95k
  value = (insn & operand->shift);
160
1.45M
      else
161
1.45M
  value = (insn >> operand->shift) & ((1ul << operand->bits) - 1);
162
163
1.45M
      if (operand->flags & V850_OPERAND_SIGNED)
164
114k
  {
165
114k
    unsigned long sign = 1ul << (operand->bits - 1);
166
114k
    value = (value ^ sign) - sign;
167
114k
  }
168
1.45M
    }
169
170
1.67M
  return value;
171
1.67M
}
172
173
static const char *
174
get_v850_sreg_name (unsigned int reg)
175
677
{
176
677
  static const char *const v850_sreg_names[] =
177
677
    {
178
677
     "eipc/vip/mpm", "eipsw/mpc", "fepc/tid", "fepsw/ppa", "ecr/vmecr", "psw/vmtid",
179
677
     "sr6/fpsr/vmadr/dcc", "sr7/fpepc/dc0",
180
677
     "sr8/fpst/vpecr/dcv1", "sr9/fpcc/vptid", "sr10/fpcfg/vpadr/spal", "sr11/spau",
181
677
     "sr12/vdecr/ipa0l", "eiic/vdtid/ipa0u", "feic/ipa1l", "dbic/ipa1u",
182
677
     "ctpc/ipa2l", "ctpsw/ipa2u", "dbpc/ipa3l", "dbpsw/ipa3u", "ctbp/dpa0l",
183
677
     "dir/dpa0u", "bpc/dpa0u", "asid/dpa1l",
184
677
     "bpav/dpa1u", "bpam/dpa2l", "bpdv/dpa2u", "bpdm/dpa3l", "eiwr/dpa3u",
185
677
     "fewr", "dbwr", "bsel"
186
677
    };
187
188
677
  if (reg < ARRAY_SIZE (v850_sreg_names))
189
83
    return v850_sreg_names[reg];
190
594
  return _("<invalid s-reg number>");
191
677
}
192
193
static const char *
194
get_v850_reg_name (unsigned int reg)
195
452k
{
196
452k
  static const char *const v850_reg_names[] =
197
452k
    {
198
452k
     "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7",
199
452k
     "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
200
452k
     "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
201
452k
     "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp"
202
452k
    };
203
204
452k
  if (reg < ARRAY_SIZE (v850_reg_names))
205
452k
    return v850_reg_names[reg];
206
0
  return _("<invalid reg number>");
207
452k
}
208
209
static const char *
210
get_v850_vreg_name (unsigned int reg)
211
303
{
212
303
  static const char *const v850_vreg_names[] =
213
303
    {
214
303
     "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", "vr8", "vr9",
215
303
     "vr10", "vr11", "vr12", "vr13", "vr14", "vr15", "vr16", "vr17", "vr18",
216
303
     "vr19", "vr20", "vr21", "vr22", "vr23", "vr24", "vr25", "vr26", "vr27",
217
303
     "vr28", "vr29", "vr30", "vr31"
218
303
    };
219
220
303
  if (reg < ARRAY_SIZE (v850_vreg_names))
221
303
    return v850_vreg_names[reg];
222
0
  return _("<invalid v-reg number>");
223
303
}
224
225
static const char *
226
get_v850_cc_name (unsigned int reg)
227
500
{
228
500
  static const char *const v850_cc_names[] =
229
500
    {
230
500
     "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
231
500
     "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt"
232
500
    };
233
234
500
  if (reg < ARRAY_SIZE (v850_cc_names))
235
500
    return v850_cc_names[reg];
236
0
  return _("<invalid CC-reg number>");
237
500
}
238
239
static const char *
240
get_v850_float_cc_name (unsigned int reg)
241
24
{
242
24
  static const char *const v850_float_cc_names[] =
243
24
    {
244
24
     "f/t", "un/or", "eq/neq", "ueq/ogl", "olt/uge", "ult/oge", "ole/ugt", "ule/ogt",
245
24
     "sf/st", "ngle/gle", "seq/sne", "ngl/gl", "lt/nlt", "nge/ge", "le/nle", "ngt/gt"
246
24
    };
247
248
24
  if (reg < ARRAY_SIZE (v850_float_cc_names))
249
24
    return v850_float_cc_names[reg];
250
0
  return _("<invalid float-CC-reg number>");
251
24
}
252
253
static const char *
254
get_v850_cacheop_name (unsigned int reg)
255
90
{
256
90
  static const char *const v850_cacheop_names[] =
257
90
    {
258
90
     "chbii", "cibii", "cfali", "cisti", "cildi", "chbid", "chbiwbd",
259
90
     "chbwbd", "cibid", "cibiwbd", "cibwbd", "cfald", "cistd", "cildd"
260
90
    };
261
262
90
  if (reg < ARRAY_SIZE (v850_cacheop_names))
263
90
    return v850_cacheop_names[reg];
264
0
  return _("<invalid cacheop number>");
265
90
}
266
267
static const char *
268
get_v850_prefop_name (unsigned int reg)
269
158
{
270
158
  static const char *const v850_prefop_names[] =
271
158
    { "prefi", "prefd" };
272
273
158
  if (reg < ARRAY_SIZE (v850_prefop_names))
274
158
    return v850_prefop_names[reg];
275
0
  return _("<invalid prefop number>");
276
158
}
277
278
static int
279
disassemble (bfd_vma memaddr,
280
       struct disassemble_info *info,
281
       int bytes_read,
282
       unsigned long insn)
283
377k
{
284
377k
  struct v850_opcode *op = (struct v850_opcode *) v850_opcodes;
285
377k
  const struct v850_operand *operand;
286
377k
  int match = 0;
287
377k
  int target_processor;
288
289
377k
  switch (info->mach)
290
377k
    {
291
4.84k
    case 0:
292
4.84k
    default:
293
4.84k
      target_processor = PROCESSOR_V850;
294
4.84k
      break;
295
296
2.15k
    case bfd_mach_v850e:
297
2.15k
      target_processor = PROCESSOR_V850E;
298
2.15k
      break;
299
300
4.09k
    case bfd_mach_v850e1:
301
4.09k
      target_processor = PROCESSOR_V850E;
302
4.09k
      break;
303
304
18.5k
    case bfd_mach_v850e2:
305
18.5k
      target_processor = PROCESSOR_V850E2;
306
18.5k
      break;
307
308
34.8k
    case bfd_mach_v850e2v3:
309
34.8k
      target_processor = PROCESSOR_V850E2V3;
310
34.8k
      break;
311
312
313k
    case bfd_mach_v850e3v5:
313
313k
      target_processor = PROCESSOR_V850E3V5;
314
313k
      break;
315
377k
    }
316
317
  /* If this is a two byte insn, then mask off the high bits.  */
318
377k
  if (bytes_read == 2)
319
290k
    insn &= 0xffff;
320
321
  /* Find the opcode.  */
322
77.7M
  while (op->name)
323
77.7M
    {
324
77.7M
      if ((op->mask & insn) == op->opcode
325
77.7M
    && (op->processors & target_processor)
326
77.7M
    && !(op->processors & PROCESSOR_OPTION_ALIAS))
327
436k
  {
328
    /* Code check start.  */
329
436k
    const unsigned char *opindex_ptr;
330
436k
    unsigned int opnum;
331
436k
    unsigned int memop;
332
333
436k
    for (opindex_ptr = op->operands, opnum = 1;
334
1.27M
         *opindex_ptr != 0;
335
842k
         opindex_ptr++, opnum++)
336
913k
      {
337
913k
        int invalid = 0;
338
913k
        long value;
339
340
913k
        operand = &v850_operands[*opindex_ptr];
341
342
913k
        value = get_operand_value (operand, insn, bytes_read, memaddr,
343
913k
           info, 1, &invalid);
344
345
913k
        if (invalid)
346
28
    goto next_opcode;
347
348
913k
              if ((operand->flags & V850_NOT_R0) && value == 0 && (op->memop) <=2)
349
70.1k
    goto next_opcode;
350
351
842k
        if ((operand->flags & V850_NOT_SA) && value == 0xd)
352
91
    goto next_opcode;
353
354
842k
        if ((operand->flags & V850_NOT_IMM0) && value == 0)
355
209
    goto next_opcode;
356
842k
      }
357
358
    /* Code check end.  */
359
360
366k
    match = 1;
361
366k
    (*info->fprintf_func) (info->stream, "%s\t", op->name);
362
#if 0
363
    fprintf (stderr, "match: insn: %lx, mask: %lx, opcode: %lx, name: %s\n",
364
       insn, op->mask, op->opcode, op->name );
365
#endif
366
367
366k
    memop = op->memop;
368
    /* Now print the operands.
369
370
       MEMOP is the operand number at which a memory
371
       address specification starts, or zero if this
372
       instruction has no memory addresses.
373
374
       A memory address is always two arguments.
375
376
       This information allows us to determine when to
377
       insert commas into the output stream as well as
378
       when to insert disp[reg] expressions onto the
379
       output stream.  */
380
381
366k
    for (opindex_ptr = op->operands, opnum = 1;
382
1.13M
         *opindex_ptr != 0;
383
770k
         opindex_ptr++, opnum++)
384
770k
      {
385
770k
        bool square = false;
386
770k
        long value;
387
770k
        int flag;
388
770k
        char *prefix;
389
390
770k
        operand = &v850_operands[*opindex_ptr];
391
392
770k
        value = get_operand_value (operand, insn, bytes_read, memaddr,
393
770k
           info, 0, 0);
394
395
        /* The first operand is always output without any
396
     special handling.
397
398
     For the following arguments:
399
400
       If memop && opnum == memop + 1, then we need '[' since
401
       we're about to output the register used in a memory
402
       reference.
403
404
       If memop && opnum == memop + 2, then we need ']' since
405
       we just finished the register in a memory reference.  We
406
       also need a ',' before this operand.
407
408
       Else we just need a comma.
409
410
       We may need to output a trailing ']' if the last operand
411
       in an instruction is the register for a memory address.
412
413
       The exception (and there's always an exception) are the
414
       "jmp" insn which needs square brackets around it's only
415
       register argument, and the clr1/not1/set1/tst1 insns
416
       which [...] around their second register argument.  */
417
418
770k
        prefix = "";
419
770k
        if (operand->flags & V850_OPERAND_BANG)
420
0
    {
421
0
      prefix = "!";
422
0
    }
423
770k
        else if (operand->flags & V850_OPERAND_PERCENT)
424
0
    {
425
0
      prefix = "%";
426
0
    }
427
428
770k
        if (opnum == 1 && opnum == memop)
429
2.88k
    {
430
2.88k
      info->fprintf_func (info->stream, "%s[", prefix);
431
2.88k
      square = true;
432
2.88k
    }
433
767k
        else if (   (strcmp ("stc.w", op->name) == 0
434
767k
      || strcmp ("cache", op->name) == 0
435
767k
      || strcmp ("pref",  op->name) == 0)
436
767k
           && opnum == 2 && opnum == memop)
437
894
    {
438
894
      info->fprintf_func (info->stream, ", [");
439
894
      square = true;
440
894
    }
441
767k
        else if (   (strcmp (op->name, "pushsp") == 0
442
767k
      || strcmp (op->name, "popsp") == 0
443
767k
      || strcmp (op->name, "dbpush" ) == 0)
444
767k
           && opnum == 2)
445
115
    {
446
115
      info->fprintf_func (info->stream, "-");
447
115
    }
448
766k
        else if (opnum > 1
449
766k
           && (v850_operands[*(opindex_ptr - 1)].flags
450
451k
         & V850_OPERAND_DISP) != 0
451
766k
           && opnum == memop)
452
135k
    {
453
135k
      info->fprintf_func (info->stream, "%s[", prefix);
454
135k
      square = true;
455
135k
    }
456
631k
        else if (opnum == 2
457
631k
           && (   op->opcode == 0x00e407e0 /* clr1 */
458
195k
         || op->opcode == 0x00e207e0 /* not1 */
459
195k
         || op->opcode == 0x00e007e0 /* set1 */
460
195k
         || op->opcode == 0x00e607e0 /* tst1 */
461
195k
         ))
462
267
    {
463
267
      info->fprintf_func (info->stream, ", %s[", prefix);
464
267
      square = true;
465
267
    }
466
631k
        else if (opnum > 1)
467
315k
    info->fprintf_func (info->stream, ", %s", prefix);
468
469
        /* Extract the flags, ignoring ones which do not
470
     effect disassembly output.  */
471
770k
        flag = operand->flags & (V850_OPERAND_REG
472
770k
               | V850_REG_EVEN
473
770k
               | V850_OPERAND_EP
474
770k
               | V850_OPERAND_SRG
475
770k
               | V850E_OPERAND_REG_LIST
476
770k
               | V850_OPERAND_CC
477
770k
               | V850_OPERAND_VREG
478
770k
               | V850_OPERAND_CACHEOP
479
770k
               | V850_OPERAND_PREFOP
480
770k
               | V850_OPERAND_FLOAT_CC);
481
482
770k
        switch (flag)
483
770k
    {
484
442k
    case V850_OPERAND_REG:
485
442k
      info->fprintf_func (info->stream, "%s", get_v850_reg_name (value));
486
442k
      break;
487
183
    case (V850_OPERAND_REG|V850_REG_EVEN):
488
183
      info->fprintf_func (info->stream, "%s", get_v850_reg_name (value * 2));
489
183
      break;
490
91.4k
    case V850_OPERAND_EP:
491
91.4k
      info->fprintf_func (info->stream, "ep");
492
91.4k
      break;
493
677
    case V850_OPERAND_SRG:
494
677
      info->fprintf_func (info->stream, "%s", get_v850_sreg_name (value));
495
677
      break;
496
2.47k
    case V850E_OPERAND_REG_LIST:
497
2.47k
      {
498
2.47k
        static int list12_regs[32]   = { 30, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
499
2.47k
                 0,  0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
500
2.47k
        int *regs;
501
2.47k
        int i;
502
2.47k
        unsigned int mask = 0;
503
2.47k
        int pc = 0;
504
505
2.47k
        switch (operand->shift)
506
2.47k
          {
507
2.47k
          case 0xffe00001: regs = list12_regs; break;
508
0
          default:
509
      /* xgettext:c-format */
510
0
      opcodes_error_handler (_("unknown operand shift: %x"),
511
0
                 operand->shift);
512
0
      abort ();
513
2.47k
          }
514
515
81.8k
        for (i = 0; i < 32; i++)
516
79.3k
          {
517
79.3k
      if (value & (1u << i))
518
12.8k
        {
519
12.8k
          switch (regs[ i ])
520
12.8k
            {
521
12.8k
            default:
522
12.8k
        mask |= (1u << regs[ i ]);
523
12.8k
        break;
524
0
            case 0:
525
        /* xgettext:c-format */
526
0
        opcodes_error_handler (_("unknown reg: %d"), i);
527
0
        abort ();
528
0
        break;
529
0
            case -1:
530
0
        pc = 1;
531
0
        break;
532
12.8k
            }
533
12.8k
        }
534
79.3k
          }
535
536
2.47k
        info->fprintf_func (info->stream, "{");
537
538
2.47k
        if (mask || pc)
539
2.38k
          {
540
2.38k
      if (mask)
541
2.38k
        {
542
2.38k
          unsigned int bit;
543
2.38k
          int shown_one = 0;
544
545
66.8k
          for (bit = 0; bit < 32; bit++)
546
64.4k
            if (mask & (1u << bit))
547
7.16k
        {
548
7.16k
          unsigned int first = bit;
549
7.16k
          unsigned int last;
550
551
7.16k
          if (shown_one)
552
4.77k
            info->fprintf_func (info->stream, ", ");
553
2.38k
          else
554
2.38k
            shown_one = 1;
555
556
7.16k
          info->fprintf_func (info->stream, "%s", get_v850_reg_name (first));
557
558
12.8k
          for (bit++; bit < 32; bit++)
559
11.8k
            if ((mask & (1u << bit)) == 0)
560
6.17k
              break;
561
562
7.16k
          last = bit;
563
564
7.16k
          if (last > first + 1)
565
3.02k
            {
566
3.02k
              info->fprintf_func (info->stream, " - %s", get_v850_reg_name (last - 1));
567
3.02k
            }
568
7.16k
        }
569
2.38k
        }
570
571
2.38k
      if (pc)
572
0
        info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
573
2.38k
          }
574
575
2.47k
        info->fprintf_func (info->stream, "}");
576
2.47k
      }
577
0
      break;
578
579
500
    case V850_OPERAND_CC:
580
500
      info->fprintf_func (info->stream, "%s", get_v850_cc_name (value));
581
500
      break;
582
583
24
    case V850_OPERAND_FLOAT_CC:
584
24
      info->fprintf_func (info->stream, "%s", get_v850_float_cc_name (value));
585
24
      break;
586
587
326
    case V850_OPERAND_CACHEOP:
588
326
      {
589
326
        int idx;
590
591
4.44k
        for (idx = 0; v850_cacheop_codes[idx] != -1; idx++)
592
4.20k
          {
593
4.20k
      if (value == v850_cacheop_codes[idx])
594
90
        {
595
90
          info->fprintf_func (info->stream, "%s",
596
90
            get_v850_cacheop_name (idx));
597
90
          goto MATCH_CACHEOP_CODE;
598
90
        }
599
4.20k
          }
600
236
        info->fprintf_func (info->stream, "%d", (int) value);
601
236
      }
602
326
    MATCH_CACHEOP_CODE:
603
326
      break;
604
605
568
    case V850_OPERAND_PREFOP:
606
568
      {
607
568
        int idx;
608
609
1.41k
        for (idx = 0; v850_prefop_codes[idx] != -1; idx++)
610
1.00k
          {
611
1.00k
      if (value == v850_prefop_codes[idx])
612
158
        {
613
158
          info->fprintf_func (info->stream, "%s",
614
158
            get_v850_prefop_name (idx));
615
158
          goto MATCH_PREFOP_CODE;
616
158
        }
617
1.00k
          }
618
410
        info->fprintf_func (info->stream, "%d", (int) value);
619
410
      }
620
568
    MATCH_PREFOP_CODE:
621
568
      break;
622
623
303
    case V850_OPERAND_VREG:
624
303
      info->fprintf_func (info->stream, "%s", get_v850_vreg_name (value));
625
303
      break;
626
627
231k
    default:
628
231k
      print_value (operand->flags, memaddr, info, value);
629
231k
      break;
630
770k
    }
631
632
770k
        if (square)
633
139k
    (*info->fprintf_func) (info->stream, "]");
634
770k
      }
635
636
    /* All done. */
637
366k
    break;
638
366k
  }
639
77.4M
    next_opcode:
640
77.4M
      op++;
641
77.4M
    }
642
643
377k
  return match;
644
377k
}
645
646
int
647
print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
648
378k
{
649
378k
  int status, status2, match;
650
378k
  bfd_byte buffer[8];
651
378k
  int length = 0, code_length = 0;
652
378k
  unsigned long insn = 0, insn2 = 0;
653
378k
  int target_processor;
654
655
378k
  switch (info->mach)
656
378k
    {
657
4.86k
    case 0:
658
4.86k
    default:
659
4.86k
      target_processor = PROCESSOR_V850;
660
4.86k
      break;
661
662
2.16k
    case bfd_mach_v850e:
663
2.16k
      target_processor = PROCESSOR_V850E;
664
2.16k
      break;
665
666
4.09k
    case bfd_mach_v850e1:
667
4.09k
      target_processor = PROCESSOR_V850E;
668
4.09k
      break;
669
670
18.5k
    case bfd_mach_v850e2:
671
18.5k
      target_processor = PROCESSOR_V850E2;
672
18.5k
      break;
673
674
34.8k
    case bfd_mach_v850e2v3:
675
34.8k
      target_processor = PROCESSOR_V850E2V3;
676
34.8k
      break;
677
678
313k
    case bfd_mach_v850e3v5:
679
313k
      target_processor = PROCESSOR_V850E3V5;
680
313k
      break;
681
378k
    }
682
683
378k
  status = info->read_memory_func (memaddr, buffer, 2, info);
684
685
378k
  if (status)
686
120
    {
687
120
      info->memory_error_func (status, memaddr, info);
688
120
      return -1;
689
120
    }
690
691
377k
  insn = bfd_getl16 (buffer);
692
693
377k
  status2 = info->read_memory_func (memaddr+2, buffer, 2 , info);
694
695
377k
  if (!status2)
696
377k
    {
697
377k
      insn2 = bfd_getl16 (buffer);
698
      /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
699
377k
    }
700
701
  /* Special case.  */
702
377k
  if (length == 0
703
377k
      && ((target_processor & PROCESSOR_V850E2_UP) != 0))
704
366k
    {
705
366k
      if ((insn & 0xffff) == 0x02e0    /* jr 32bit */
706
366k
    && !status2 && (insn2 & 0x1) == 0)
707
5
  {
708
5
    length = 2;
709
5
    code_length = 6;
710
5
  }
711
366k
      else if ((insn & 0xffe0) == 0x02e0  /* jarl 32bit */
712
366k
         && !status2 && (insn2 & 0x1) == 0)
713
387
  {
714
387
    length = 2;
715
387
    code_length = 6;
716
387
  }
717
366k
      else if ((insn & 0xffe0) == 0x06e0  /* jmp 32bit */
718
366k
         && !status2 && (insn2 & 0x1) == 0)
719
217
  {
720
217
    length = 2;
721
217
    code_length = 6;
722
217
  }
723
366k
    }
724
725
377k
  if (length == 0
726
377k
      && ((target_processor & PROCESSOR_V850E3V5_UP) != 0))
727
313k
    {
728
313k
      if (   ((insn & 0xffe0) == 0x07a0    /* ld.dw 23bit (v850e3v5) */
729
313k
        && !status2 && (insn2 & 0x000f) == 0x0009)
730
313k
    || ((insn & 0xffe0) == 0x07a0    /* st.dw 23bit (v850e3v5) */
731
313k
        && !status2 && (insn2 & 0x000f) == 0x000f))
732
655
  {
733
655
    length = 4;
734
655
    code_length = 6;
735
655
  }
736
313k
    }
737
738
377k
  if (length == 0
739
377k
      && ((target_processor & PROCESSOR_V850E2V3_UP) != 0))
740
347k
    {
741
347k
      if (((insn & 0xffe0) == 0x0780    /* ld.b 23bit */
742
347k
     && !status2 && (insn2 & 0x000f) == 0x0005)
743
347k
    || ((insn & 0xffe0) == 0x07a0    /* ld.bu 23bit */
744
346k
        && !status2 && (insn2 & 0x000f) == 0x0005)
745
347k
    || ((insn & 0xffe0) == 0x0780    /* ld.h 23bit */
746
346k
        && !status2 && (insn2 & 0x000f) == 0x0007)
747
347k
    || ((insn & 0xffe0) == 0x07a0    /* ld.hu 23bit */
748
346k
        && !status2 && (insn2 & 0x000f) == 0x0007)
749
347k
    || ((insn & 0xffe0) == 0x0780    /* ld.w 23bit */
750
345k
        && !status2 && (insn2 & 0x000f) == 0x0009))
751
1.40k
  {
752
1.40k
    length = 4;
753
1.40k
    code_length = 6;
754
1.40k
  }
755
345k
      else if (((insn & 0xffe0) == 0x0780  /* st.b 23bit */
756
345k
         && !status2 && (insn2 & 0x000f) == 0x000d)
757
345k
        || ((insn & 0xffe0) == 0x07a0  /* st.h 23bit */
758
345k
      && !status2 && (insn2 & 0x000f) == 0x000d)
759
345k
        || ((insn & 0xffe0) == 0x0780  /* st.w 23bit */
760
344k
      && !status2 && (insn2 & 0x000f) == 0x000f))
761
1.28k
  {
762
1.28k
    length = 4;
763
1.28k
    code_length = 6;
764
1.28k
  }
765
347k
    }
766
767
377k
  if (length == 0
768
377k
      && target_processor != PROCESSOR_V850)
769
369k
    {
770
369k
      if ((insn & 0xffe0) == 0x0620)    /* 32 bit MOV */
771
129
  {
772
129
    length = 2;
773
129
    code_length = 6;
774
129
  }
775
369k
      else if ((insn & 0xffc0) == 0x0780  /* prepare {list}, imm5, imm16<<16 */
776
369k
         && !status2 && (insn2 & 0x001f) == 0x0013)
777
13
  {
778
13
    length = 4;
779
13
    code_length = 6;
780
13
  }
781
369k
      else if ((insn & 0xffc0) == 0x0780  /* prepare {list}, imm5, imm16 */
782
369k
         && !status2 && (insn2 & 0x001f) == 0x000b)
783
286
  {
784
286
    length = 4;
785
286
    code_length = 6;
786
286
  }
787
368k
      else if ((insn & 0xffc0) == 0x0780  /* prepare {list}, imm5, imm32 */
788
368k
         && !status2 && (insn2 & 0x001f) == 0x001b)
789
86
  {
790
86
    length = 4;
791
86
    code_length = 8;
792
86
  }
793
369k
    }
794
795
377k
  if (length == 4
796
377k
      || (length == 0
797
374k
    && (insn & 0x0600) == 0x0600))
798
87.5k
    {
799
      /* This is a 4 byte insn.  */
800
87.5k
      status = info->read_memory_func (memaddr, buffer, 4, info);
801
87.5k
      if (!status)
802
87.4k
  {
803
87.4k
    insn = bfd_getl32 (buffer);
804
805
87.4k
    if (!length)
806
83.7k
      length = code_length = 4;
807
87.4k
  }
808
87.5k
    }
809
810
377k
  if (code_length > length)
811
4.47k
    {
812
4.47k
      status = info->read_memory_func (memaddr + length, buffer, code_length - length, info);
813
4.47k
      if (status)
814
5
  length = 0;
815
4.47k
    }
816
817
377k
  if (length == 0 && !status)
818
289k
    length = code_length = 2;
819
820
377k
  if (length == 2)
821
290k
    insn &= 0xffff;
822
823
  /* when the last 2 bytes of section is 0xffff, length will be 0 and cause infinitive loop */
824
377k
  if (length == 0)
825
14
    return -1;
826
827
377k
  match = disassemble (memaddr, info, length, insn);
828
829
377k
  if (!match)
830
11.7k
    {
831
11.7k
      int l = 0;
832
833
11.7k
      status = info->read_memory_func (memaddr, buffer, code_length, info);
834
835
24.2k
      while (l < code_length)
836
12.4k
  {
837
12.4k
    if (code_length - l == 2)
838
7.70k
      {
839
7.70k
        insn = bfd_getl16 (buffer + l) & 0xffff;
840
7.70k
        info->fprintf_func (info->stream, ".short\t0x%04lx", insn);
841
7.70k
        l += 2;
842
7.70k
      }
843
4.74k
    else
844
4.74k
      {
845
4.74k
        insn = bfd_getl32 (buffer + l);
846
4.74k
        info->fprintf_func (info->stream, ".long\t0x%08lx", insn);
847
4.74k
        l += 4;
848
4.74k
      }
849
12.4k
  }
850
11.7k
    }
851
852
377k
  return code_length;
853
377k
}