Coverage Report

Created: 2023-08-28 06:30

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