Coverage Report

Created: 2025-07-08 11:15

/src/binutils-gdb/opcodes/v850-dis.c
Line
Count
Source (jump to first uncovered line)
1
/* Disassemble V850 instructions.
2
   Copyright (C) 1996-2025 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
149k
{
45
149k
  if (flags & V850_PCREL)
46
16.0k
    {
47
16.0k
      bfd_vma addr = value + memaddr;
48
49
16.0k
      if (flags & V850_INVERSE_PCREL)
50
118
  addr = memaddr - value;
51
16.0k
      info->print_address_func (addr, info);
52
16.0k
    }
53
133k
  else if (flags & V850_OPERAND_DISP)
54
87.9k
    {
55
87.9k
      if (flags & V850_OPERAND_SIGNED)
56
31.2k
        {
57
31.2k
          info->fprintf_func (info->stream, "%ld", value);
58
31.2k
        }
59
56.6k
      else
60
56.6k
        {
61
56.6k
          info->fprintf_func (info->stream, "%lu", value);
62
56.6k
        }
63
87.9k
    }
64
45.4k
  else if ((flags & V850E_IMMEDIATE32)
65
45.4k
     || (flags & V850E_IMMEDIATE16HI))
66
452
    {
67
452
      info->fprintf_func (info->stream, "0x%lx", value);
68
452
    }
69
44.9k
  else
70
44.9k
    {
71
44.9k
      if (flags & V850_OPERAND_SIGNED)
72
28.7k
  {
73
28.7k
    info->fprintf_func (info->stream, "%ld", value);
74
28.7k
  }
75
16.2k
      else
76
16.2k
  {
77
16.2k
    info->fprintf_func (info->stream, "%lu", value);
78
16.2k
  }
79
44.9k
    }
80
149k
}
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.09M
{
91
1.09M
  unsigned long value;
92
1.09M
  bfd_byte buffer[4];
93
94
1.09M
  if ((operand->flags & V850E_IMMEDIATE16)
95
1.09M
      || (operand->flags & V850E_IMMEDIATE16HI))
96
750
    {
97
750
      int status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info);
98
99
750
      if (status == 0)
100
750
  {
101
750
    value = bfd_getl16 (buffer);
102
103
750
    if (operand->flags & V850E_IMMEDIATE16HI)
104
234
      value <<= 16;
105
516
    else if (value & 0x8000)
106
234
      value |= (-1UL << 16);
107
108
750
    return value;
109
750
  }
110
111
0
      if (!noerror)
112
0
  info->memory_error_func (status, memaddr + bytes_read, info);
113
114
0
      return 0;
115
750
    }
116
117
1.09M
  if (operand->flags & V850E_IMMEDIATE23)
118
2.90k
    {
119
2.90k
      int status = info->read_memory_func (memaddr + 2, buffer, 4, info);
120
121
2.90k
      if (status == 0)
122
2.90k
  {
123
2.90k
    value = bfd_getl32 (buffer);
124
125
2.90k
    value = (operand->extract) (value, invalid);
126
127
2.90k
    return value;
128
2.90k
  }
129
130
0
      if (!noerror)
131
0
  info->memory_error_func (status, memaddr + bytes_read, info);
132
133
0
      return 0;
134
2.90k
    }
135
136
1.08M
  if (operand->flags & V850E_IMMEDIATE32)
137
2.02k
    {
138
2.02k
      int status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info);
139
140
2.02k
      if (status == 0)
141
2.01k
  {
142
2.01k
    bytes_read += 4;
143
2.01k
    value = bfd_getl32 (buffer);
144
145
2.01k
    return value;
146
2.01k
  }
147
148
5
      if (!noerror)
149
2
  info->memory_error_func (status, memaddr + bytes_read, info);
150
151
5
      return 0;
152
2.02k
    }
153
154
1.08M
  if (operand->extract)
155
148k
    value = (operand->extract) (insn, invalid);
156
939k
  else
157
939k
    {
158
939k
      if (operand->bits == -1)
159
3.41k
  value = (insn & operand->shift);
160
935k
      else
161
935k
  value = (insn >> operand->shift) & ((1ul << operand->bits) - 1);
162
163
939k
      if (operand->flags & V850_OPERAND_SIGNED)
164
77.4k
  {
165
77.4k
    unsigned long sign = 1ul << (operand->bits - 1);
166
77.4k
    value = (value ^ sign) - sign;
167
77.4k
  }
168
939k
    }
169
170
1.08M
  return value;
171
1.08M
}
172
173
static const char *
174
get_v850_sreg_name (unsigned int reg)
175
145
{
176
145
  static const char *const v850_sreg_names[] =
177
145
    {
178
145
     "eipc/vip/mpm", "eipsw/mpc", "fepc/tid", "fepsw/ppa", "ecr/vmecr", "psw/vmtid",
179
145
     "sr6/fpsr/vmadr/dcc", "sr7/fpepc/dc0",
180
145
     "sr8/fpst/vpecr/dcv1", "sr9/fpcc/vptid", "sr10/fpcfg/vpadr/spal", "sr11/spau",
181
145
     "sr12/vdecr/ipa0l", "eiic/vdtid/ipa0u", "feic/ipa1l", "dbic/ipa1u",
182
145
     "ctpc/ipa2l", "ctpsw/ipa2u", "dbpc/ipa3l", "dbpsw/ipa3u", "ctbp/dpa0l",
183
145
     "dir/dpa0u", "bpc/dpa0u", "asid/dpa1l",
184
145
     "bpav/dpa1u", "bpam/dpa2l", "bpdv/dpa2u", "bpdm/dpa3l", "eiwr/dpa3u",
185
145
     "fewr", "dbwr", "bsel"
186
145
    };
187
188
145
  if (reg < ARRAY_SIZE (v850_sreg_names))
189
32
    return v850_sreg_names[reg];
190
113
  return _("<invalid s-reg number>");
191
145
}
192
193
static const char *
194
get_v850_reg_name (unsigned int reg)
195
294k
{
196
294k
  static const char *const v850_reg_names[] =
197
294k
    {
198
294k
     "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7",
199
294k
     "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
200
294k
     "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
201
294k
     "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp"
202
294k
    };
203
204
294k
  if (reg < ARRAY_SIZE (v850_reg_names))
205
294k
    return v850_reg_names[reg];
206
0
  return _("<invalid reg number>");
207
294k
}
208
209
static const char *
210
get_v850_vreg_name (unsigned int reg)
211
168
{
212
168
  static const char *const v850_vreg_names[] =
213
168
    {
214
168
     "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", "vr8", "vr9",
215
168
     "vr10", "vr11", "vr12", "vr13", "vr14", "vr15", "vr16", "vr17", "vr18",
216
168
     "vr19", "vr20", "vr21", "vr22", "vr23", "vr24", "vr25", "vr26", "vr27",
217
168
     "vr28", "vr29", "vr30", "vr31"
218
168
    };
219
220
168
  if (reg < ARRAY_SIZE (v850_vreg_names))
221
168
    return v850_vreg_names[reg];
222
0
  return _("<invalid v-reg number>");
223
168
}
224
225
static const char *
226
get_v850_cc_name (unsigned int reg)
227
450
{
228
450
  static const char *const v850_cc_names[] =
229
450
    {
230
450
     "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
231
450
     "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt"
232
450
    };
233
234
450
  if (reg < ARRAY_SIZE (v850_cc_names))
235
450
    return v850_cc_names[reg];
236
0
  return _("<invalid CC-reg number>");
237
450
}
238
239
static const char *
240
get_v850_float_cc_name (unsigned int reg)
241
40
{
242
40
  static const char *const v850_float_cc_names[] =
243
40
    {
244
40
     "f/t", "un/or", "eq/neq", "ueq/ogl", "olt/uge", "ult/oge", "ole/ugt", "ule/ogt",
245
40
     "sf/st", "ngle/gle", "seq/sne", "ngl/gl", "lt/nlt", "nge/ge", "le/nle", "ngt/gt"
246
40
    };
247
248
40
  if (reg < ARRAY_SIZE (v850_float_cc_names))
249
40
    return v850_float_cc_names[reg];
250
0
  return _("<invalid float-CC-reg number>");
251
40
}
252
253
static const char *
254
get_v850_cacheop_name (unsigned int reg)
255
48
{
256
48
  static const char *const v850_cacheop_names[] =
257
48
    {
258
48
     "chbii", "cibii", "cfali", "cisti", "cildi", "chbid", "chbiwbd",
259
48
     "chbwbd", "cibid", "cibiwbd", "cibwbd", "cfald", "cistd", "cildd"
260
48
    };
261
262
48
  if (reg < ARRAY_SIZE (v850_cacheop_names))
263
48
    return v850_cacheop_names[reg];
264
0
  return _("<invalid cacheop number>");
265
48
}
266
267
static const char *
268
get_v850_prefop_name (unsigned int reg)
269
83
{
270
83
  static const char *const v850_prefop_names[] =
271
83
    { "prefi", "prefd" };
272
273
83
  if (reg < ARRAY_SIZE (v850_prefop_names))
274
83
    return v850_prefop_names[reg];
275
0
  return _("<invalid prefop number>");
276
83
}
277
278
static int
279
disassemble (bfd_vma memaddr,
280
       struct disassemble_info *info,
281
       int bytes_read,
282
       unsigned long insn)
283
247k
{
284
247k
  struct v850_opcode *op = (struct v850_opcode *) v850_opcodes;
285
247k
  const struct v850_operand *operand;
286
247k
  int match = 0;
287
247k
  int target_processor;
288
289
247k
  switch (info->mach)
290
247k
    {
291
14.1k
    case 0:
292
14.1k
    default:
293
14.1k
      target_processor = PROCESSOR_V850;
294
14.1k
      break;
295
296
6.17k
    case bfd_mach_v850e:
297
6.17k
      target_processor = PROCESSOR_V850E;
298
6.17k
      break;
299
300
7.42k
    case bfd_mach_v850e1:
301
7.42k
      target_processor = PROCESSOR_V850E;
302
7.42k
      break;
303
304
990
    case bfd_mach_v850e2:
305
990
      target_processor = PROCESSOR_V850E2;
306
990
      break;
307
308
22.6k
    case bfd_mach_v850e2v3:
309
22.6k
      target_processor = PROCESSOR_V850E2V3;
310
22.6k
      break;
311
312
196k
    case bfd_mach_v850e3v5:
313
196k
      target_processor = PROCESSOR_V850E3V5;
314
196k
      break;
315
247k
    }
316
317
  /* If this is a two byte insn, then mask off the high bits.  */
318
247k
  if (bytes_read == 2)
319
187k
    insn &= 0xffff;
320
321
  /* Find the opcode.  */
322
51.0M
  while (op->name)
323
51.0M
    {
324
51.0M
      if ((op->mask & insn) == op->opcode
325
51.0M
    && (op->processors & target_processor)
326
51.0M
    && !(op->processors & PROCESSOR_OPTION_ALIAS))
327
289k
  {
328
    /* Code check start.  */
329
289k
    const unsigned char *opindex_ptr;
330
289k
    unsigned int opnum;
331
289k
    unsigned int memop;
332
333
289k
    for (opindex_ptr = op->operands, opnum = 1;
334
836k
         *opindex_ptr != 0;
335
547k
         opindex_ptr++, opnum++)
336
597k
      {
337
597k
        int invalid = 0;
338
597k
        long value;
339
340
597k
        operand = &v850_operands[*opindex_ptr];
341
342
597k
        value = get_operand_value (operand, insn, bytes_read, memaddr,
343
597k
           info, 1, &invalid);
344
345
597k
        if (invalid)
346
50
    goto next_opcode;
347
348
597k
              if ((operand->flags & V850_NOT_R0) && value == 0 && (op->memop) <=2)
349
50.1k
    goto next_opcode;
350
351
547k
        if ((operand->flags & V850_NOT_SA) && value == 0xd)
352
27
    goto next_opcode;
353
354
547k
        if ((operand->flags & V850_NOT_IMM0) && value == 0)
355
171
    goto next_opcode;
356
547k
      }
357
358
    /* Code check end.  */
359
360
239k
    match = 1;
361
239k
    (*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
239k
    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
239k
    for (opindex_ptr = op->operands, opnum = 1;
382
734k
         *opindex_ptr != 0;
383
495k
         opindex_ptr++, opnum++)
384
495k
      {
385
495k
        bool square = false;
386
495k
        long value;
387
495k
        int flag;
388
495k
        char *prefix;
389
390
495k
        operand = &v850_operands[*opindex_ptr];
391
392
495k
        value = get_operand_value (operand, insn, bytes_read, memaddr,
393
495k
           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
495k
        prefix = "";
419
495k
        if (operand->flags & V850_OPERAND_BANG)
420
0
    {
421
0
      prefix = "!";
422
0
    }
423
495k
        else if (operand->flags & V850_OPERAND_PERCENT)
424
0
    {
425
0
      prefix = "%";
426
0
    }
427
428
495k
        if (opnum == 1 && opnum == memop)
429
1.98k
    {
430
1.98k
      info->fprintf_func (info->stream, "%s[", prefix);
431
1.98k
      square = true;
432
1.98k
    }
433
493k
        else if (   (strcmp ("stc.w", op->name) == 0
434
493k
      || strcmp ("cache", op->name) == 0
435
493k
      || strcmp ("pref",  op->name) == 0)
436
493k
           && opnum == 2 && opnum == memop)
437
467
    {
438
467
      info->fprintf_func (info->stream, ", [");
439
467
      square = true;
440
467
    }
441
493k
        else if (   (strcmp (op->name, "pushsp") == 0
442
493k
      || strcmp (op->name, "popsp") == 0
443
493k
      || strcmp (op->name, "dbpush" ) == 0)
444
493k
           && opnum == 2)
445
101
    {
446
101
      info->fprintf_func (info->stream, "-");
447
101
    }
448
493k
        else if (opnum > 1
449
493k
           && (v850_operands[*(opindex_ptr - 1)].flags
450
289k
         & V850_OPERAND_DISP) != 0
451
493k
           && opnum == memop)
452
87.9k
    {
453
87.9k
      info->fprintf_func (info->stream, "%s[", prefix);
454
87.9k
      square = true;
455
87.9k
    }
456
405k
        else if (opnum == 2
457
405k
           && (   op->opcode == 0x00e407e0 /* clr1 */
458
123k
         || op->opcode == 0x00e207e0 /* not1 */
459
123k
         || op->opcode == 0x00e007e0 /* set1 */
460
123k
         || op->opcode == 0x00e607e0 /* tst1 */
461
123k
         ))
462
394
    {
463
394
      info->fprintf_func (info->stream, ", %s[", prefix);
464
394
      square = true;
465
394
    }
466
404k
        else if (opnum > 1)
467
201k
    info->fprintf_func (info->stream, ", %s", prefix);
468
469
        /* Extract the flags, ignoring ones which do not
470
     effect disassembly output.  */
471
495k
        flag = operand->flags & (V850_OPERAND_REG
472
495k
               | V850_REG_EVEN
473
495k
               | V850_OPERAND_EP
474
495k
               | V850_OPERAND_SRG
475
495k
               | V850E_OPERAND_REG_LIST
476
495k
               | V850_OPERAND_CC
477
495k
               | V850_OPERAND_VREG
478
495k
               | V850_OPERAND_CACHEOP
479
495k
               | V850_OPERAND_PREFOP
480
495k
               | V850_OPERAND_FLOAT_CC);
481
482
495k
        switch (flag)
483
495k
    {
484
286k
    case V850_OPERAND_REG:
485
286k
      info->fprintf_func (info->stream, "%s", get_v850_reg_name (value));
486
286k
      break;
487
215
    case (V850_OPERAND_REG|V850_REG_EVEN):
488
215
      info->fprintf_func (info->stream, "%s", get_v850_reg_name (value * 2));
489
215
      break;
490
56.6k
    case V850_OPERAND_EP:
491
56.6k
      info->fprintf_func (info->stream, "ep");
492
56.6k
      break;
493
145
    case V850_OPERAND_SRG:
494
145
      info->fprintf_func (info->stream, "%s", get_v850_sreg_name (value));
495
145
      break;
496
1.70k
    case V850E_OPERAND_REG_LIST:
497
1.70k
      {
498
1.70k
        static int list12_regs[32]   = { 30, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
499
1.70k
                 0,  0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
500
1.70k
        int *regs;
501
1.70k
        int i;
502
1.70k
        unsigned int mask = 0;
503
1.70k
        int pc = 0;
504
505
1.70k
        switch (operand->shift)
506
1.70k
          {
507
1.70k
          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
1.70k
          }
514
515
56.2k
        for (i = 0; i < 32; i++)
516
54.5k
          {
517
54.5k
      if (value & (1u << i))
518
10.7k
        {
519
10.7k
          switch (regs[ i ])
520
10.7k
            {
521
10.7k
            default:
522
10.7k
        mask |= (1u << regs[ i ]);
523
10.7k
        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
10.7k
            }
533
10.7k
        }
534
54.5k
          }
535
536
1.70k
        info->fprintf_func (info->stream, "{");
537
538
1.70k
        if (mask || pc)
539
1.68k
          {
540
1.68k
      if (mask)
541
1.68k
        {
542
1.68k
          unsigned int bit;
543
1.68k
          int shown_one = 0;
544
545
46.0k
          for (bit = 0; bit < 32; bit++)
546
44.3k
            if (mask & (1u << bit))
547
5.51k
        {
548
5.51k
          unsigned int first = bit;
549
5.51k
          unsigned int last;
550
551
5.51k
          if (shown_one)
552
3.83k
            info->fprintf_func (info->stream, ", ");
553
1.68k
          else
554
1.68k
            shown_one = 1;
555
556
5.51k
          info->fprintf_func (info->stream, "%s", get_v850_reg_name (first));
557
558
10.7k
          for (bit++; bit < 32; bit++)
559
9.53k
            if ((mask & (1u << bit)) == 0)
560
4.33k
              break;
561
562
5.51k
          last = bit;
563
564
5.51k
          if (last > first + 1)
565
2.50k
            {
566
2.50k
              info->fprintf_func (info->stream, " - %s", get_v850_reg_name (last - 1));
567
2.50k
            }
568
5.51k
        }
569
1.68k
        }
570
571
1.68k
      if (pc)
572
0
        info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
573
1.68k
          }
574
575
1.70k
        info->fprintf_func (info->stream, "}");
576
1.70k
      }
577
0
      break;
578
579
450
    case V850_OPERAND_CC:
580
450
      info->fprintf_func (info->stream, "%s", get_v850_cc_name (value));
581
450
      break;
582
583
40
    case V850_OPERAND_FLOAT_CC:
584
40
      info->fprintf_func (info->stream, "%s", get_v850_float_cc_name (value));
585
40
      break;
586
587
237
    case V850_OPERAND_CACHEOP:
588
237
      {
589
237
        int idx;
590
591
3.27k
        for (idx = 0; v850_cacheop_codes[idx] != -1; idx++)
592
3.08k
          {
593
3.08k
      if (value == v850_cacheop_codes[idx])
594
48
        {
595
48
          info->fprintf_func (info->stream, "%s",
596
48
            get_v850_cacheop_name (idx));
597
48
          goto MATCH_CACHEOP_CODE;
598
48
        }
599
3.08k
          }
600
189
        info->fprintf_func (info->stream, "%d", (int) value);
601
189
      }
602
237
    MATCH_CACHEOP_CODE:
603
237
      break;
604
605
211
    case V850_OPERAND_PREFOP:
606
211
      {
607
211
        int idx;
608
609
469
        for (idx = 0; v850_prefop_codes[idx] != -1; idx++)
610
341
          {
611
341
      if (value == v850_prefop_codes[idx])
612
83
        {
613
83
          info->fprintf_func (info->stream, "%s",
614
83
            get_v850_prefop_name (idx));
615
83
          goto MATCH_PREFOP_CODE;
616
83
        }
617
341
          }
618
128
        info->fprintf_func (info->stream, "%d", (int) value);
619
128
      }
620
211
    MATCH_PREFOP_CODE:
621
211
      break;
622
623
168
    case V850_OPERAND_VREG:
624
168
      info->fprintf_func (info->stream, "%s", get_v850_vreg_name (value));
625
168
      break;
626
627
149k
    default:
628
149k
      print_value (operand->flags, memaddr, info, value);
629
149k
      break;
630
495k
    }
631
632
495k
        if (square)
633
90.7k
    (*info->fprintf_func) (info->stream, "]");
634
495k
      }
635
636
    /* All done. */
637
239k
    break;
638
239k
  }
639
50.8M
    next_opcode:
640
50.8M
      op++;
641
50.8M
    }
642
643
247k
  return match;
644
247k
}
645
646
int
647
print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
648
247k
{
649
247k
  int status, status2, match;
650
247k
  bfd_byte buffer[8];
651
247k
  int length = 0, code_length = 0;
652
247k
  unsigned long insn = 0, insn2 = 0;
653
247k
  int target_processor;
654
655
247k
  switch (info->mach)
656
247k
    {
657
14.1k
    case 0:
658
14.1k
    default:
659
14.1k
      target_processor = PROCESSOR_V850;
660
14.1k
      break;
661
662
6.19k
    case bfd_mach_v850e:
663
6.19k
      target_processor = PROCESSOR_V850E;
664
6.19k
      break;
665
666
7.44k
    case bfd_mach_v850e1:
667
7.44k
      target_processor = PROCESSOR_V850E;
668
7.44k
      break;
669
670
1.00k
    case bfd_mach_v850e2:
671
1.00k
      target_processor = PROCESSOR_V850E2;
672
1.00k
      break;
673
674
22.6k
    case bfd_mach_v850e2v3:
675
22.6k
      target_processor = PROCESSOR_V850E2V3;
676
22.6k
      break;
677
678
196k
    case bfd_mach_v850e3v5:
679
196k
      target_processor = PROCESSOR_V850E3V5;
680
196k
      break;
681
247k
    }
682
683
247k
  status = info->read_memory_func (memaddr, buffer, 2, info);
684
685
247k
  if (status)
686
162
    {
687
162
      info->memory_error_func (status, memaddr, info);
688
162
      return -1;
689
162
    }
690
691
247k
  insn = bfd_getl16 (buffer);
692
693
247k
  status2 = info->read_memory_func (memaddr+2, buffer, 2 , info);
694
695
247k
  if (!status2)
696
247k
    {
697
247k
      insn2 = bfd_getl16 (buffer);
698
      /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
699
247k
    }
700
701
  /* Special case.  */
702
247k
  if (length == 0
703
247k
      && ((target_processor & PROCESSOR_V850E2_UP) != 0))
704
219k
    {
705
219k
      if ((insn & 0xffff) == 0x02e0    /* jr 32bit */
706
219k
    && !status2 && (insn2 & 0x1) == 0)
707
21
  {
708
21
    length = 2;
709
21
    code_length = 6;
710
21
  }
711
219k
      else if ((insn & 0xffe0) == 0x02e0  /* jarl 32bit */
712
219k
         && !status2 && (insn2 & 0x1) == 0)
713
286
  {
714
286
    length = 2;
715
286
    code_length = 6;
716
286
  }
717
219k
      else if ((insn & 0xffe0) == 0x06e0  /* jmp 32bit */
718
219k
         && !status2 && (insn2 & 0x1) == 0)
719
311
  {
720
311
    length = 2;
721
311
    code_length = 6;
722
311
  }
723
219k
    }
724
725
247k
  if (length == 0
726
247k
      && ((target_processor & PROCESSOR_V850E3V5_UP) != 0))
727
195k
    {
728
195k
      if (   ((insn & 0xffe0) == 0x07a0    /* ld.dw 23bit (v850e3v5) */
729
195k
        && !status2 && (insn2 & 0x000f) == 0x0009)
730
195k
    || ((insn & 0xffe0) == 0x07a0    /* st.dw 23bit (v850e3v5) */
731
195k
        && !status2 && (insn2 & 0x000f) == 0x000f))
732
327
  {
733
327
    length = 4;
734
327
    code_length = 6;
735
327
  }
736
195k
    }
737
738
247k
  if (length == 0
739
247k
      && ((target_processor & PROCESSOR_V850E2V3_UP) != 0))
740
217k
    {
741
217k
      if (((insn & 0xffe0) == 0x0780    /* ld.b 23bit */
742
217k
     && !status2 && (insn2 & 0x000f) == 0x0005)
743
217k
    || ((insn & 0xffe0) == 0x07a0    /* ld.bu 23bit */
744
217k
        && !status2 && (insn2 & 0x000f) == 0x0005)
745
217k
    || ((insn & 0xffe0) == 0x0780    /* ld.h 23bit */
746
217k
        && !status2 && (insn2 & 0x000f) == 0x0007)
747
217k
    || ((insn & 0xffe0) == 0x07a0    /* ld.hu 23bit */
748
217k
        && !status2 && (insn2 & 0x000f) == 0x0007)
749
217k
    || ((insn & 0xffe0) == 0x0780    /* ld.w 23bit */
750
217k
        && !status2 && (insn2 & 0x000f) == 0x0009))
751
637
  {
752
637
    length = 4;
753
637
    code_length = 6;
754
637
  }
755
217k
      else if (((insn & 0xffe0) == 0x0780  /* st.b 23bit */
756
217k
         && !status2 && (insn2 & 0x000f) == 0x000d)
757
217k
        || ((insn & 0xffe0) == 0x07a0  /* st.h 23bit */
758
217k
      && !status2 && (insn2 & 0x000f) == 0x000d)
759
217k
        || ((insn & 0xffe0) == 0x0780  /* st.w 23bit */
760
216k
      && !status2 && (insn2 & 0x000f) == 0x000f))
761
774
  {
762
774
    length = 4;
763
774
    code_length = 6;
764
774
  }
765
217k
    }
766
767
247k
  if (length == 0
768
247k
      && target_processor != PROCESSOR_V850)
769
231k
    {
770
231k
      if ((insn & 0xffe0) == 0x0620)    /* 32 bit MOV */
771
24
  {
772
24
    length = 2;
773
24
    code_length = 6;
774
24
  }
775
231k
      else if ((insn & 0xffc0) == 0x0780  /* prepare {list}, imm5, imm16<<16 */
776
231k
         && !status2 && (insn2 & 0x001f) == 0x0013)
777
117
  {
778
117
    length = 4;
779
117
    code_length = 6;
780
117
  }
781
230k
      else if ((insn & 0xffc0) == 0x0780  /* prepare {list}, imm5, imm16 */
782
230k
         && !status2 && (insn2 & 0x001f) == 0x000b)
783
258
  {
784
258
    length = 4;
785
258
    code_length = 6;
786
258
  }
787
230k
      else if ((insn & 0xffc0) == 0x0780  /* prepare {list}, imm5, imm32 */
788
230k
         && !status2 && (insn2 & 0x001f) == 0x001b)
789
311
  {
790
311
    length = 4;
791
311
    code_length = 8;
792
311
  }
793
231k
    }
794
795
247k
  if (length == 4
796
247k
      || (length == 0
797
245k
    && (insn & 0x0600) == 0x0600))
798
60.4k
    {
799
      /* This is a 4 byte insn.  */
800
60.4k
      status = info->read_memory_func (memaddr, buffer, 4, info);
801
60.4k
      if (!status)
802
60.4k
  {
803
60.4k
    insn = bfd_getl32 (buffer);
804
805
60.4k
    if (!length)
806
57.9k
      length = code_length = 4;
807
60.4k
  }
808
60.4k
    }
809
810
247k
  if (code_length > length)
811
3.06k
    {
812
3.06k
      status = info->read_memory_func (memaddr + length, buffer, code_length - length, info);
813
3.06k
      if (status)
814
0
  length = 0;
815
3.06k
    }
816
817
247k
  if (length == 0 && !status)
818
186k
    length = code_length = 2;
819
820
247k
  if (length == 2)
821
187k
    insn &= 0xffff;
822
823
  /* when the last 2 bytes of section is 0xffff, length will be 0 and cause infinitive loop */
824
247k
  if (length == 0)
825
48
    return -1;
826
827
247k
  match = disassemble (memaddr, info, length, insn);
828
829
247k
  if (!match)
830
8.33k
    {
831
8.33k
      int l = 0;
832
833
8.33k
      status = info->read_memory_func (memaddr, buffer, code_length, info);
834
835
16.9k
      while (l < code_length)
836
8.62k
  {
837
8.62k
    if (code_length - l == 2)
838
4.95k
      {
839
4.95k
        insn = bfd_getl16 (buffer + l) & 0xffff;
840
4.95k
        info->fprintf_func (info->stream, ".short\t0x%04lx", insn);
841
4.95k
        l += 2;
842
4.95k
      }
843
3.66k
    else
844
3.66k
      {
845
3.66k
        insn = bfd_getl32 (buffer + l);
846
3.66k
        info->fprintf_func (info->stream, ".long\t0x%08lx", insn);
847
3.66k
        l += 4;
848
3.66k
      }
849
8.62k
  }
850
8.33k
    }
851
852
247k
  return code_length;
853
247k
}