Coverage Report

Created: 2026-05-11 07:54

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