Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/opcodes/cr16-dis.c
Line
Count
Source (jump to first uncovered line)
1
/* Disassembler code for CR16.
2
   Copyright (C) 2007-2025 Free Software Foundation, Inc.
3
   Contributed by M R Swami Reddy (MR.Swami.Reddy@nsc.com).
4
5
   This file is part of GAS, GDB and the GNU binutils.
6
7
   This program is free software; you can redistribute it and/or modify it
8
   under the terms of the GNU General Public License as published by the
9
   Free Software Foundation; either version 3, or (at your option)
10
   any later version.
11
12
   This program is distributed in the hope that it will be useful, but WITHOUT
13
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15
   more details.
16
17
   You should have received a copy of the GNU General Public License
18
   along with this program; if not, write to the Free Software Foundation,
19
   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
20
21
#include "sysdep.h"
22
#include "disassemble.h"
23
#include "opcode/cr16.h"
24
#include "libiberty.h"
25
26
/* String to print when opcode was not matched.  */
27
16.0k
#define ILLEGAL  "illegal"
28
  /* Escape to 16-bit immediate.  */
29
#define ESCAPE_16_BIT  0xB
30
31
/* Extract 'n_bits' from 'a' starting from offset 'offs'.  */
32
#define EXTRACT(a, offs, n_bits) \
33
191k
  (((a) >> (offs)) & ((1ul << ((n_bits) - 1) << 1) - 1))
34
35
/* Set Bit Mask - a mask to set all bits in a 32-bit word starting
36
   from offset 'offs'.  */
37
18.2M
#define SBM(offs)  ((1ul << 31 << 1) - (1ul << (offs)))
38
39
/* Structure to map valid 'cinv' instruction options.  */
40
41
typedef struct
42
  {
43
    /* Cinv printed string.  */
44
    char *istr;
45
    /* Value corresponding to the string.  */
46
    char *ostr;
47
  }
48
cinv_entry;
49
50
/* CR16 'cinv' options mapping.  */
51
static const cinv_entry cr16_cinvs[] =
52
{
53
  {"cinv[i]",     "cinv    [i]"},
54
  {"cinv[i,u]",   "cinv    [i,u]"},
55
  {"cinv[d]",     "cinv    [d]"},
56
  {"cinv[d,u]",   "cinv    [d,u]"},
57
  {"cinv[d,i]",   "cinv    [d,i]"},
58
  {"cinv[d,i,u]", "cinv    [d,i,u]"}
59
};
60
61
/* Number of valid 'cinv' instruction options.  */
62
static int NUMCINVS = ARRAY_SIZE (cr16_cinvs);
63
64
/* Enum to distinguish different registers argument types.  */
65
typedef enum REG_ARG_TYPE
66
  {
67
    /* General purpose register (r<N>).  */
68
    REG_ARG = 0,
69
    /*Processor register   */
70
    P_ARG,
71
  }
72
REG_ARG_TYPE;
73
74
/* Current opcode table entry we're disassembling.  */
75
static const inst *instruction;
76
/* Current instruction we're disassembling.  */
77
static ins cr16_currInsn;
78
/* The current instruction is read into 3 consecutive words.  */
79
static wordU cr16_words[3];
80
/* Contains all words in appropriate order.  */
81
static ULONGLONG cr16_allWords;
82
/* Holds the current processed argument number.  */
83
static int processing_argument_number;
84
/* Nonzero means a IMM4 instruction.  */
85
static int imm4flag;
86
/* Nonzero means the instruction's original size is
87
   incremented (escape sequence is used).  */
88
static int size_changed;
89
90
91
/* Print the constant expression length.  */
92
93
static char *
94
print_exp_len (int size)
95
47.0k
{
96
47.0k
  switch (size)
97
47.0k
    {
98
0
    case 4:
99
0
    case 5:
100
0
    case 6:
101
0
    case 8:
102
0
    case 14:
103
29.2k
    case 16:
104
29.2k
      return ":s";
105
0
    case 20:
106
0
    case 24:
107
16.5k
    case 32:
108
16.5k
      return ":m";
109
1.19k
    case 48:
110
1.19k
      return ":l";
111
0
    default:
112
0
      return "";
113
47.0k
    }
114
47.0k
}
115
116
117
/* Retrieve the number of operands for the current assembled instruction.  */
118
119
static int
120
get_number_of_operands (void)
121
80.9k
{
122
80.9k
  int i;
123
124
237k
  for (i = 0; instruction->operands[i].op_type && i < MAX_OPERANDS; i++)
125
157k
    ;
126
127
80.9k
  return i;
128
80.9k
}
129
130
/* Return the bit size for a given operand.  */
131
132
static int
133
getbits (operand_type op)
134
157k
{
135
157k
  if (op < MAX_OPRD)
136
157k
    return cr16_optab[op].bit_size;
137
138
0
  return 0;
139
157k
}
140
141
/* Return the argument type of a given operand.  */
142
143
static argtype
144
getargtype (operand_type op)
145
157k
{
146
157k
  if (op < MAX_OPRD)
147
157k
    return cr16_optab[op].arg_type;
148
149
0
  return nullargs;
150
157k
}
151
152
/* Given a 'CC' instruction constant operand, return its corresponding
153
   string. This routine is used when disassembling the 'CC' instruction.  */
154
155
static char *
156
getccstring (unsigned cc_insn)
157
5.70k
{
158
5.70k
  return (char *) cr16_b_cond_tab[cc_insn];
159
5.70k
}
160
161
162
/* Given a 'cinv' instruction constant operand, return its corresponding
163
   string. This routine is used when disassembling the 'cinv' instruction. */
164
165
static char *
166
getcinvstring (const char *str)
167
375
{
168
375
  const cinv_entry *cinv;
169
170
1.14k
  for (cinv = cr16_cinvs; cinv < (cr16_cinvs + NUMCINVS); cinv++)
171
1.14k
    if (strcmp (cinv->istr, str) == 0)
172
375
      return cinv->ostr;
173
174
0
  return ILLEGAL;
175
375
}
176
177
/* Given the trap index in dispatch table, return its name.
178
   This routine is used when disassembling the 'excp' instruction.  */
179
180
static char *
181
gettrapstring (unsigned int trap_index)
182
613
{
183
613
  const trap_entry *trap;
184
185
4.84k
  for (trap = cr16_traps; trap < cr16_traps + NUMTRAPS; trap++)
186
4.60k
    if (trap->entry == trap_index)
187
379
      return trap->name;
188
189
234
  return ILLEGAL;
190
613
}
191
192
/* Given a register enum value, retrieve its name.  */
193
194
static char *
195
getregname (reg r)
196
57.0k
{
197
57.0k
  const reg_entry * regentry = cr16_regtab + r;
198
199
57.0k
  if (regentry->type != CR16_R_REGTYPE)
200
0
    return ILLEGAL;
201
202
57.0k
  return regentry->name;
203
57.0k
}
204
205
/* Given a register pair enum value, retrieve its name.  */
206
207
static char *
208
getregpname (reg r)
209
44.1k
{
210
44.1k
  const reg_entry * regentry = cr16_regptab + r;
211
212
44.1k
  if (regentry->type != CR16_RP_REGTYPE)
213
0
    return ILLEGAL;
214
215
44.1k
  return regentry->name;
216
44.1k
}
217
218
/* Given a index register pair enum value, retrieve its name.  */
219
220
static char *
221
getidxregpname (reg r)
222
2.81k
{
223
2.81k
  const reg_entry * regentry;
224
225
2.81k
  switch (r)
226
2.81k
   {
227
350
   case 0: r = 0; break;
228
105
   case 1: r = 2; break;
229
443
   case 2: r = 4; break;
230
289
   case 3: r = 6; break;
231
200
   case 4: r = 8; break;
232
69
   case 5: r = 10; break;
233
1.20k
   case 6: r = 3; break;
234
160
   case 7: r = 5; break;
235
0
   default:
236
0
     break;
237
2.81k
   }
238
239
2.81k
  regentry = cr16_regptab + r;
240
241
2.81k
  if (regentry->type != CR16_RP_REGTYPE)
242
0
    return ILLEGAL;
243
244
2.81k
  return regentry->name;
245
2.81k
}
246
247
/* Getting a processor register name.  */
248
249
static char *
250
getprocregname (int reg_index)
251
99
{
252
99
  const reg_entry *r;
253
254
442
  for (r = cr16_pregtab; r < cr16_pregtab + NUMPREGS; r++)
255
442
    if (r->image == reg_index)
256
99
      return r->name;
257
258
0
  return "ILLEGAL REGISTER";
259
99
}
260
261
/* Getting a processor register name - 32 bit size.  */
262
263
static char *
264
getprocpregname (int reg_index)
265
141
{
266
141
  const reg_entry *r;
267
268
1.05k
  for (r = cr16_pregptab; r < cr16_pregptab + NUMPREGPS; r++)
269
991
    if (r->image == reg_index)
270
81
      return r->name;
271
272
60
  return "ILLEGAL REGISTER";
273
141
}
274
275
/* START and END are relating 'cr16_allWords' struct, which is 48 bits size.
276
277
                          START|--------|END
278
             +---------+---------+---------+---------+
279
             |         |   V    |     A    |   L     |
280
             +---------+---------+---------+---------+
281
                       0         16        32        48
282
    words                  [0]       [1]       [2]      */
283
284
static inline dwordU
285
makelongparameter (ULONGLONG val, int start, int end)
286
191k
{
287
191k
  return EXTRACT (val, 48 - end, end - start);
288
191k
}
289
290
/* Build a mask of the instruction's 'constant' opcode,
291
   based on the instruction's printing flags.  */
292
293
static unsigned long
294
build_mask (void)
295
18.2M
{
296
18.2M
  unsigned long mask = SBM (instruction->match_bits);
297
298
  /* Adjust mask for bcond with 32-bit size instruction.  */
299
18.2M
  if ((IS_INSN_MNEMONIC("b") && instruction->size == 2))
300
46.3k
    mask = 0xff0f0000;
301
302
18.2M
  return mask;
303
18.2M
}
304
305
/* Search for a matching opcode. Return 1 for success, 0 for failure.  */
306
307
int
308
cr16_match_opcode (void)
309
96.7k
{
310
96.7k
  unsigned long mask;
311
  /* The instruction 'constant' opcode doesn't exceed 32 bits.  */
312
96.7k
  unsigned long doubleWord = cr16_words[1] + ((unsigned) cr16_words[0] << 16);
313
314
  /* Start searching from end of instruction table.  */
315
96.7k
  instruction = &cr16_instruction[NUMOPCODES - 2];
316
317
  /* Loop over instruction table until a full match is found.  */
318
18.2M
  while (instruction >= cr16_instruction)
319
18.2M
    {
320
18.2M
      mask = build_mask ();
321
322
18.2M
      if ((doubleWord & mask) == BIN (instruction->match,
323
18.2M
              instruction->match_bits))
324
80.9k
  return 1;
325
18.1M
      else
326
18.1M
  instruction--;
327
18.2M
    }
328
15.8k
  return 0;
329
96.7k
}
330
331
/* Set the proper parameter value for different type of arguments.  */
332
333
static void
334
make_argument (argument * a, int start_bits)
335
157k
{
336
157k
  int inst_bit_size;
337
157k
  dwordU p;
338
339
157k
  if ((instruction->size == 3) && a->size >= 16)
340
3.55k
    inst_bit_size = 48;
341
153k
  else
342
153k
    inst_bit_size = 32;
343
344
157k
  switch (a->type)
345
157k
    {
346
56.6k
    case arg_r:
347
56.6k
      p = makelongparameter (cr16_allWords,
348
56.6k
           inst_bit_size - (start_bits + a->size),
349
56.6k
           inst_bit_size - start_bits);
350
56.6k
      a->r = p;
351
56.6k
      break;
352
353
17.9k
    case arg_rp:
354
17.9k
      p = makelongparameter (cr16_allWords,
355
17.9k
           inst_bit_size - (start_bits + a->size),
356
17.9k
           inst_bit_size - start_bits);
357
17.9k
      a->rp = p;
358
17.9k
      break;
359
360
99
    case arg_pr:
361
99
      p = makelongparameter (cr16_allWords,
362
99
           inst_bit_size - (start_bits + a->size),
363
99
           inst_bit_size - start_bits);
364
99
      a->pr = p;
365
99
      break;
366
367
126
    case arg_prp:
368
126
      p = makelongparameter (cr16_allWords,
369
126
           inst_bit_size - (start_bits + a->size),
370
126
           inst_bit_size - start_bits);
371
126
      a->prp = p;
372
126
      break;
373
374
29.7k
    case arg_ic:
375
29.7k
      p = makelongparameter (cr16_allWords,
376
29.7k
           inst_bit_size - (start_bits + a->size),
377
29.7k
           inst_bit_size - start_bits);
378
29.7k
      a->constant = p;
379
29.7k
      break;
380
381
5.70k
    case arg_cc:
382
5.70k
      p = makelongparameter (cr16_allWords,
383
5.70k
           inst_bit_size - (start_bits + a->size),
384
5.70k
           inst_bit_size - start_bits);
385
5.70k
      a->cc = p;
386
5.70k
      break;
387
388
5.65k
    case arg_idxr:
389
5.65k
      if (IS_INSN_TYPE (CSTBIT_INS) && instruction->mnemonic[4] == 'b')
390
939
  p = makelongparameter (cr16_allWords, 8, 9);
391
4.71k
      else
392
4.71k
  p = makelongparameter (cr16_allWords, 9, 10);
393
5.65k
      a->i_r = p;
394
5.65k
      p = makelongparameter (cr16_allWords,
395
5.65k
           inst_bit_size - a->size, inst_bit_size);
396
5.65k
      a->constant = p;
397
5.65k
      break;
398
399
2.80k
    case arg_idxrp:
400
2.80k
      p = makelongparameter (cr16_allWords, start_bits + 12, start_bits + 13);
401
2.80k
      a->i_r = p;
402
2.80k
      p = makelongparameter (cr16_allWords, start_bits + 13, start_bits + 16);
403
2.80k
      a->rp = p;
404
2.80k
      if (inst_bit_size > 32)
405
263
  {
406
263
    p = makelongparameter (cr16_allWords, inst_bit_size - start_bits - 12,
407
263
         inst_bit_size);
408
263
    a->constant = (p & 0xffff) | (p >> 8 & 0xf0000);
409
263
  }
410
2.53k
      else if (instruction->size == 2)
411
781
  {
412
781
    p = makelongparameter (cr16_allWords, inst_bit_size - 22,
413
781
         inst_bit_size);
414
781
    a->constant = ((p & 0xf) | (((p >> 20) & 0x3) << 4)
415
781
       | ((p >> 14 & 0x3) << 6) | (((p >>7) & 0x1f) << 7));
416
781
  }
417
1.75k
      else if (instruction->size == 1 && a->size == 0)
418
1.75k
  a->constant = 0;
419
420
2.80k
      break;
421
422
0
    case arg_rbase:
423
0
      p = makelongparameter (cr16_allWords, inst_bit_size, inst_bit_size);
424
0
      a->constant = p;
425
0
      p = makelongparameter (cr16_allWords, inst_bit_size - (start_bits + 4),
426
0
           inst_bit_size - start_bits);
427
0
      a->r = p;
428
0
      break;
429
430
275
    case arg_cr:
431
275
      p = makelongparameter (cr16_allWords, start_bits + 12, start_bits + 16);
432
275
      a->r = p;
433
275
      p = makelongparameter (cr16_allWords, inst_bit_size - 28, inst_bit_size);
434
275
      a->constant = ((p >> 8) & 0xf0000) | (p & 0xffff);
435
275
      break;
436
437
26.6k
    case arg_crp:
438
26.6k
      if (instruction->size == 1)
439
19.9k
  p = makelongparameter (cr16_allWords, 12, 16);
440
6.73k
      else
441
6.73k
  p = makelongparameter (cr16_allWords, start_bits + 12, start_bits + 16);
442
26.6k
      a->rp = p;
443
444
26.6k
      if (inst_bit_size > 32)
445
111
  {
446
111
    p = makelongparameter (cr16_allWords, inst_bit_size - start_bits - 12,
447
111
         inst_bit_size);
448
111
    a->constant = ((p & 0xffff) | (p >> 8 & 0xf0000));
449
111
  }
450
26.5k
      else if (instruction->size == 2)
451
6.62k
  {
452
6.62k
    p = makelongparameter (cr16_allWords, inst_bit_size - 16,
453
6.62k
         inst_bit_size);
454
6.62k
    a->constant = p;
455
6.62k
  }
456
19.9k
      else if (instruction->size == 1 && a->size != 0)
457
18.1k
  {
458
18.1k
    p = makelongparameter (cr16_allWords, 4, 8);
459
18.1k
    if (IS_INSN_MNEMONIC ("loadw")
460
18.1k
        || IS_INSN_MNEMONIC ("loadd")
461
18.1k
        || IS_INSN_MNEMONIC ("storw")
462
18.1k
        || IS_INSN_MNEMONIC ("stord"))
463
11.3k
      a->constant = p * 2;
464
6.81k
    else
465
6.81k
      a->constant = p;
466
18.1k
  }
467
1.78k
      else /* below case for 0x0(reg pair) */
468
1.78k
  a->constant = 0;
469
470
26.6k
      break;
471
472
11.3k
    case arg_c:
473
474
11.3k
      if ((IS_INSN_TYPE (BRANCH_INS))
475
11.3k
    || (IS_INSN_MNEMONIC ("bal"))
476
11.3k
    || (IS_INSN_TYPE (CSTBIT_INS))
477
11.3k
    || (IS_INSN_TYPE (LD_STOR_INS)))
478
9.27k
  {
479
9.27k
    switch (a->size)
480
9.27k
      {
481
5.18k
      case 8 :
482
5.18k
        p = makelongparameter (cr16_allWords, 0, start_bits);
483
5.18k
        a->constant = ((p & 0xf00) >> 4) | (p & 0xf);
484
5.18k
        break;
485
486
1.29k
      case 24:
487
1.29k
        if (instruction->size == 3)
488
550
    {
489
550
      p = makelongparameter (cr16_allWords, 16, inst_bit_size);
490
550
      a->constant = ((((p >> 16) & 0xf) << 20)
491
550
         | (((p >> 24) & 0xf) << 16)
492
550
         | (p & 0xffff));
493
550
    }
494
740
        else if (instruction->size == 2)
495
740
    {
496
740
      p = makelongparameter (cr16_allWords, 8, inst_bit_size);
497
740
      a->constant = p;
498
740
    }
499
1.29k
        break;
500
501
2.79k
      default:
502
2.79k
        p = makelongparameter (cr16_allWords,
503
2.79k
             inst_bit_size - (start_bits + a->size),
504
2.79k
             inst_bit_size - start_bits);
505
2.79k
        a->constant = p;
506
2.79k
        break;
507
9.27k
      }
508
9.27k
  }
509
2.10k
      else
510
2.10k
  {
511
2.10k
    p = makelongparameter (cr16_allWords,
512
2.10k
         inst_bit_size - (start_bits + a->size),
513
2.10k
         inst_bit_size - start_bits);
514
2.10k
    a->constant = p;
515
2.10k
  }
516
11.3k
      break;
517
518
11.3k
    default:
519
0
      break;
520
157k
    }
521
157k
}
522
523
/*  Print a single argument.  */
524
525
static void
526
print_arg (argument *a, bfd_vma memaddr, struct disassemble_info *info)
527
156k
{
528
156k
  LONGLONG longdisp, mask;
529
156k
  int sign_flag = 0;
530
156k
  int relative = 0;
531
156k
  bfd_vma number;
532
156k
  void *stream = info->stream;
533
156k
  fprintf_ftype func = info->fprintf_func;
534
535
156k
  switch (a->type)
536
156k
    {
537
56.7k
    case arg_r:
538
56.7k
      func (stream, "%s", getregname (a->r));
539
56.7k
      break;
540
541
17.3k
    case arg_rp:
542
17.3k
      func (stream, "%s", getregpname (a->rp));
543
17.3k
      break;
544
545
99
    case arg_pr:
546
99
      func (stream, "%s", getprocregname (a->pr));
547
99
      break;
548
549
141
    case arg_prp:
550
141
      func (stream, "%s", getprocpregname (a->prp));
551
141
      break;
552
553
5.70k
    case arg_cc:
554
5.70k
      func (stream, "%s", getccstring (a->cc));
555
5.70k
      func (stream, "%s", "\t");
556
5.70k
      break;
557
558
29.7k
    case arg_ic:
559
29.7k
      if (IS_INSN_MNEMONIC ("excp"))
560
613
  {
561
613
    func (stream, "%s", gettrapstring (a->constant));
562
613
    break;
563
613
  }
564
29.1k
      else if ((IS_INSN_TYPE (ARITH_INS) || IS_INSN_TYPE (ARITH_BYTE_INS))
565
29.1k
         && ((instruction->size == 1) && (a->constant == 9)))
566
333
  func (stream, "$%d", -1);
567
28.7k
      else if (INST_HAS_REG_LIST)
568
4.75k
  func (stream, "$0x%lx", a->constant +1);
569
24.0k
      else if (IS_INSN_TYPE (SHIFT_INS))
570
3.45k
  {
571
3.45k
    longdisp = a->constant;
572
3.45k
    mask = ((LONGLONG)1 << a->size) - 1;
573
3.45k
    if (longdisp & ((LONGLONG)1 << (a->size -1)))
574
2.15k
      {
575
2.15k
        sign_flag = 1;
576
2.15k
        longdisp = ~(longdisp) + 1;
577
2.15k
      }
578
3.45k
    a->constant = (unsigned long int) (longdisp & mask);
579
3.45k
    func (stream, "$%d", ((int)(sign_flag ? -a->constant :
580
3.45k
              a->constant)));
581
3.45k
  }
582
20.5k
      else
583
20.5k
  func (stream, "$0x%lx", a->constant);
584
29.1k
      switch (a->size)
585
29.1k
  {
586
18.3k
  case 4  : case 5  : case 6  : case 8  :
587
18.3k
    func (stream, "%s", ":s"); break;
588
1.30k
  case 16 : case 20 : func (stream, "%s", ":m"); break;
589
2.35k
  case 24 : case 32 : func (stream, "%s", ":l"); break;
590
7.14k
  default: break;
591
29.1k
  }
592
29.1k
      break;
593
594
29.1k
    case arg_idxr:
595
5.69k
      if (a->i_r == 0) func (stream, "[r12]");
596
5.69k
      if (a->i_r == 1) func (stream, "[r13]");
597
5.69k
      func (stream, "0x%lx", a->constant);
598
5.69k
      func (stream, "%s", print_exp_len (instruction->size * 16));
599
5.69k
      break;
600
601
2.81k
    case arg_idxrp:
602
2.81k
      if (a->i_r == 0) func (stream, "[r12]");
603
2.81k
      if (a->i_r == 1) func (stream, "[r13]");
604
2.81k
      func (stream, "0x%lx", a->constant);
605
2.81k
      func (stream, "%s", print_exp_len (instruction->size * 16));
606
2.81k
      func (stream, "%s", getidxregpname (a->rp));
607
2.81k
      break;
608
609
0
    case arg_rbase:
610
0
      func (stream, "(%s)", getregname (a->r));
611
0
      break;
612
613
277
    case arg_cr:
614
277
      func (stream, "0x%lx", a->constant);
615
277
      func (stream, "%s", print_exp_len (instruction->size * 16));
616
277
      func (stream, "(%s)", getregname (a->r));
617
277
      break;
618
619
26.8k
    case arg_crp:
620
26.8k
      func (stream, "0x%lx", a->constant);
621
26.8k
      func (stream, "%s", print_exp_len (instruction->size * 16));
622
26.8k
      func (stream, "%s", getregpname (a->rp));
623
26.8k
      break;
624
625
11.4k
    case arg_c:
626
      /*Removed the *2 part as because implicit zeros are no more required.
627
  Have to fix this as this needs a bit of extension in terms of branch
628
  instructions. */
629
11.4k
      if (IS_INSN_TYPE (BRANCH_INS) || IS_INSN_MNEMONIC ("bal"))
630
6.68k
  {
631
6.68k
    relative = 1;
632
6.68k
    longdisp = a->constant;
633
    /* REVISIT: To sync with WinIDEA and CR16 4.1tools, the below
634
       line commented */
635
    /* longdisp <<= 1; */
636
6.68k
    mask = ((LONGLONG)1 << a->size) - 1;
637
6.68k
    switch (a->size)
638
6.68k
      {
639
5.18k
      case 8  :
640
5.18k
        {
641
5.18k
    longdisp <<= 1;
642
5.18k
    if (longdisp & ((LONGLONG)1 << a->size))
643
2.22k
      {
644
2.22k
        sign_flag = 1;
645
2.22k
        longdisp = ~(longdisp) + 1;
646
2.22k
      }
647
5.18k
    break;
648
0
        }
649
237
      case 16 :
650
1.50k
      case 24 :
651
1.50k
        {
652
1.50k
    if (longdisp & 1)
653
318
      {
654
318
        sign_flag = 1;
655
318
        longdisp = ~(longdisp) + 1;
656
318
      }
657
1.50k
    break;
658
237
        }
659
0
      default:
660
0
        func (stream, "Wrong offset used in branch/bal instruction");
661
0
        break;
662
6.68k
      }
663
6.68k
    a->constant = (unsigned long int) (longdisp & mask);
664
6.68k
  }
665
      /* For branch Neq instruction it is 2*offset + 2.  */
666
4.75k
      else if (IS_INSN_TYPE (BRANCH_NEQ_INS))
667
2.10k
  a->constant = 2 * a->constant + 2;
668
669
11.4k
      if ((!IS_INSN_TYPE (CSTBIT_INS)) && (!IS_INSN_TYPE (LD_STOR_INS)))
670
8.86k
  (sign_flag) ? func (stream, "%s", "*-"): func (stream, "%s","*+");
671
672
      /* PR 10173: Avoid printing the 0x prefix twice.  */
673
11.4k
      if (info->symtab_size > 0)
674
0
  func (stream, "%s", "0x");
675
11.4k
      number = ((relative ? memaddr : 0) +
676
11.4k
    (sign_flag ? ((- a->constant) & 0xffffffe) : a->constant));
677
678
11.4k
      (*info->print_address_func) ((number & ((1 << 24) - 1)), info);
679
680
11.4k
      func (stream, "%s", print_exp_len (instruction->size * 16));
681
11.4k
      break;
682
683
0
    default:
684
0
      break;
685
156k
    }
686
156k
}
687
688
/* Print all the arguments of CURRINSN instruction.  */
689
690
static void
691
print_arguments (ins *currentInsn, bfd_vma memaddr, struct disassemble_info *info)
692
80.9k
{
693
80.9k
  int i;
694
695
  /* For "pop/push/popret RA instruction only.  */
696
80.9k
  if ((IS_INSN_MNEMONIC ("pop")
697
80.9k
       || (IS_INSN_MNEMONIC ("popret")
698
80.0k
     || (IS_INSN_MNEMONIC ("push"))))
699
80.9k
      && currentInsn->nargs == 1)
700
41
    {
701
41
      info->fprintf_func (info->stream, "RA");
702
41
      return;
703
41
    }
704
705
239k
  for (i = 0; i < currentInsn->nargs; i++)
706
158k
    {
707
158k
      processing_argument_number = i;
708
709
      /* For "bal (ra), disp17" instruction only.  */
710
158k
      if ((IS_INSN_MNEMONIC ("bal")) && (i == 0) && instruction->size == 2)
711
740
  {
712
740
    info->fprintf_func (info->stream, "(ra),");
713
740
    continue;
714
740
  }
715
716
157k
      if ((INST_HAS_REG_LIST) && (i == 2))
717
857
  info->fprintf_func (info->stream, "RA");
718
156k
      else
719
156k
  print_arg (&currentInsn->arg[i], memaddr, info);
720
721
157k
      if ((i != currentInsn->nargs - 1) && (!IS_INSN_MNEMONIC ("b")))
722
72.3k
  info->fprintf_func (info->stream, ",");
723
157k
    }
724
80.8k
}
725
726
/* Build the instruction's arguments.  */
727
728
void
729
cr16_make_instruction (void)
730
80.9k
{
731
80.9k
  int i;
732
80.9k
  unsigned int shift;
733
734
237k
  for (i = 0; i < cr16_currInsn.nargs; i++)
735
157k
    {
736
157k
      argument a;
737
738
157k
      memset (&a, 0, sizeof (a));
739
157k
      a.type = getargtype (instruction->operands[i].op_type);
740
157k
      a.size = getbits (instruction->operands[i].op_type);
741
157k
      shift = instruction->operands[i].shift;
742
743
157k
      make_argument (&a, shift);
744
157k
      cr16_currInsn.arg[i] = a;
745
157k
    }
746
747
  /* Calculate instruction size (in bytes).  */
748
80.9k
  cr16_currInsn.size = instruction->size + (size_changed ? 1 : 0);
749
  /* Now in bits.  */
750
80.9k
  cr16_currInsn.size *= 2;
751
80.9k
}
752
753
/* Retrieve a single word from a given memory address.  */
754
755
static wordU
756
get_word_at_PC (bfd_vma memaddr, struct disassemble_info *info)
757
290k
{
758
290k
  bfd_byte buffer[4];
759
290k
  int status;
760
290k
  wordU insn = 0;
761
762
290k
  status = info->read_memory_func (memaddr, buffer, 2, info);
763
764
290k
  if (status == 0)
765
289k
    insn = (wordU) bfd_getl16 (buffer);
766
767
290k
  return insn;
768
290k
}
769
770
/* Retrieve multiple words (3) from a given memory address.  */
771
772
static void
773
get_words_at_PC (bfd_vma memaddr, struct disassemble_info *info)
774
96.7k
{
775
96.7k
  int i;
776
96.7k
  bfd_vma mem;
777
778
387k
  for (i = 0, mem = memaddr; i < 3; i++, mem += 2)
779
290k
    cr16_words[i] = get_word_at_PC (mem, info);
780
781
96.7k
  cr16_allWords =  ((ULONGLONG) cr16_words[0] << 32)
782
96.7k
       + ((unsigned long) cr16_words[1] << 16) + cr16_words[2];
783
96.7k
}
784
785
/* Prints the instruction by calling print_arguments after proper matching.  */
786
787
int
788
print_insn_cr16 (bfd_vma memaddr, struct disassemble_info *info)
789
96.7k
{
790
96.7k
  int is_decoded;     /* Nonzero means instruction has a match.  */
791
792
  /* Initialize global variables.  */
793
96.7k
  imm4flag = 0;
794
96.7k
  size_changed = 0;
795
796
  /* Retrieve the encoding from current memory location.  */
797
96.7k
  get_words_at_PC (memaddr, info);
798
  /* Find a matching opcode in table.  */
799
96.7k
  is_decoded = cr16_match_opcode ();
800
  /* If found, print the instruction's mnemonic and arguments.  */
801
96.7k
  if (is_decoded > 0 && (cr16_words[0] != 0 || cr16_words[1] != 0))
802
80.9k
    {
803
80.9k
      if (startswith (instruction->mnemonic, "cinv"))
804
375
  info->fprintf_func (info->stream,"%s",
805
375
          getcinvstring (instruction->mnemonic));
806
80.5k
      else
807
80.5k
  info->fprintf_func (info->stream, "%s", instruction->mnemonic);
808
809
80.9k
      if (((cr16_currInsn.nargs = get_number_of_operands ()) != 0)
810
80.9k
    && ! (IS_INSN_MNEMONIC ("b")))
811
73.9k
  info->fprintf_func (info->stream, "\t");
812
80.9k
      cr16_make_instruction ();
813
      /* For push/pop/pushrtn with RA instructions.  */
814
80.9k
      if ((INST_HAS_REG_LIST) && ((cr16_words[0] >> 7) & 0x1))
815
1.43k
  cr16_currInsn.nargs +=1;
816
80.9k
      print_arguments (&cr16_currInsn, memaddr, info);
817
80.9k
      return cr16_currInsn.size;
818
80.9k
    }
819
820
  /* No match found.  */
821
15.8k
  info->fprintf_func (info->stream,"%s ",ILLEGAL);
822
15.8k
  return 2;
823
96.7k
}