Coverage Report

Created: 2023-06-29 07:13

/src/binutils-gdb/opcodes/rx-dis.c
Line
Count
Source (jump to first uncovered line)
1
/* Disassembler code for Renesas RX.
2
   Copyright (C) 2008-2023 Free Software Foundation, Inc.
3
   Contributed by Red Hat.
4
   Written by DJ Delorie.
5
6
   This file is part of the GNU opcodes library.
7
8
   This library is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3, or (at your option)
11
   any later version.
12
13
   It is distributed in the hope that it will be useful, but WITHOUT
14
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16
   License for more details.
17
18
   You should have received a copy of the GNU General Public License
19
   along with this program; if not, write to the Free Software
20
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21
   MA 02110-1301, USA.  */
22
23
#include "sysdep.h"
24
#include <stdio.h>
25
26
#include "bfd.h"
27
#include "dis-asm.h"
28
#include "opcode/rx.h"
29
#include "libiberty.h"
30
#include "opintl.h"
31
32
#include <setjmp.h>
33
34
typedef struct
35
{
36
  bfd_vma pc;
37
  disassemble_info * dis;
38
} RX_Data;
39
40
struct private
41
{
42
  OPCODES_SIGJMP_BUF bailout;
43
};
44
45
static int
46
rx_get_byte (void * vdata)
47
58.1M
{
48
58.1M
  bfd_byte buf[1];
49
58.1M
  RX_Data *rx_data = (RX_Data *) vdata;
50
58.1M
  int status;
51
52
58.1M
  status = rx_data->dis->read_memory_func (rx_data->pc,
53
58.1M
             buf,
54
58.1M
             1,
55
58.1M
             rx_data->dis);
56
58.1M
  if (status != 0)
57
5.03k
    {
58
5.03k
      struct private *priv = (struct private *) rx_data->dis->private_data;
59
60
5.03k
      rx_data->dis->memory_error_func (status, rx_data->pc,
61
5.03k
               rx_data->dis);
62
5.03k
       OPCODES_SIGLONGJMP (priv->bailout, 1);
63
5.03k
    }
64
65
58.1M
  rx_data->pc ++;
66
58.1M
  return buf[0];
67
58.1M
}
68
69
static char const * size_names[RX_MAX_SIZE] =
70
{
71
  "", ".b", ".ub", ".b", ".w", ".uw", ".w", ".a", ".l", "", "<error>"
72
};
73
74
static char const * opsize_names[RX_MAX_SIZE] =
75
{
76
  "", ".b", ".b", ".b", ".w", ".w", ".w", ".a", ".l", ".d", "<error>"
77
};
78
79
static char const * register_names[] =
80
{
81
  /* General registers.  */
82
  "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
83
  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
84
  /* Control registers.  */
85
  "psw", "pc", "usp", "fpsw", NULL, NULL, NULL, NULL,
86
  "bpsw", "bpc", "isp", "fintv", "intb", "extb", NULL, NULL,
87
  "a0", "a1", NULL, NULL, NULL, NULL, NULL, NULL,
88
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
89
};
90
91
static char const * condition_names[] =
92
{
93
  /* Condition codes.  */
94
  "eq", "ne", "c", "nc", "gtu", "leu", "pz", "n",
95
  "ge", "lt", "gt", "le", "o", "no", "<invalid>", "<invalid>"
96
};
97
98
static const char * flag_names[] =
99
{
100
  "c", "z", "s", "o", "", "", "", "",
101
  "", "", "", "", "", "", "", "",
102
  "i", "u", "", "", "", "", "", "",
103
  "", "", "", "", "", "", "", ""
104
};
105
106
static const char * double_register_names[] =
107
{
108
  "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7",
109
  "dr8", "dr9", "dr10", "dr11", "dr12", "dr13", "dr14", "dr15"
110
};
111
112
static const char * double_register_high_names[] =
113
{
114
  "drh0", "drh1", "drh2", "drh3", "drh4", "drh5", "drh6", "drh7",
115
  "drh8", "drh9", "drh10", "drh11", "drh12", "drh13", "drh14", "drh15"
116
};
117
118
static const char * double_register_low_names[] =
119
{
120
  "drl0", "drl1", "drl2", "drl3", "drl4", "drl5", "drl6", "drl7",
121
  "drl8", "drl9", "drl10", "drl11", "drl12", "drl13", "drl14", "drl15"
122
};
123
124
static const char * double_control_register_names[] =
125
{
126
  "dpsw", "dcmr", "decnt", "depc"
127
};
128
129
static const char * double_condition_names[] =
130
{
131
  "", "un", "eq", "", "lt", "", "le"
132
};
133
134
static inline const char *
135
get_register_name (unsigned int reg)
136
24.2M
{
137
24.2M
  if (reg < ARRAY_SIZE (register_names))
138
24.2M
    return register_names[reg];
139
0
  return _("<invalid register number>");
140
24.2M
}
141
142
static inline const char *
143
get_condition_name (unsigned int cond)
144
3.40M
{
145
3.40M
  if (cond < ARRAY_SIZE (condition_names))
146
3.40M
    return condition_names[cond];
147
0
  return _("<invalid condition code>");
148
3.40M
}
149
150
static inline const char *
151
get_flag_name (unsigned int flag)
152
9.26k
{
153
9.26k
  if (flag < ARRAY_SIZE (flag_names))
154
9.26k
    return flag_names[flag];
155
0
  return _("<invalid flag>");
156
9.26k
}
157
158
static inline const char *
159
get_double_register_name (unsigned int reg)
160
106k
{
161
106k
  if (reg < ARRAY_SIZE (double_register_names))
162
105k
    return double_register_names[reg];
163
765
  return _("<invalid register number>");
164
106k
}
165
166
static inline const char *
167
get_double_register_high_name (unsigned int reg)
168
3.90k
{
169
3.90k
  if (reg < ARRAY_SIZE (double_register_high_names))
170
3.90k
    return double_register_high_names[reg];
171
0
  return _("<invalid register number>");
172
3.90k
}
173
174
static inline const char *
175
get_double_register_low_name (unsigned int reg)
176
5.30k
{
177
5.30k
  if (reg < ARRAY_SIZE (double_register_low_names))
178
5.30k
    return double_register_low_names[reg];
179
0
  return _("<invalid register number>");
180
5.30k
}
181
182
static inline const char *
183
get_double_control_register_name (unsigned int reg)
184
6.60k
{
185
6.60k
  if (reg < ARRAY_SIZE (double_control_register_names))
186
1.14k
    return double_control_register_names[reg];
187
5.46k
  return _("<invalid register number>");
188
6.60k
}
189
190
static inline const char *
191
get_double_condition_name (unsigned int cond)
192
5.54k
{
193
5.54k
  if (cond < ARRAY_SIZE (double_condition_names))
194
2.92k
    return double_condition_names[cond];
195
2.62k
  return _("<invalid condition code>");
196
5.54k
}
197
198
static inline const char *
199
get_opsize_name (unsigned int opsize)
200
8.06M
{
201
8.06M
  if (opsize < ARRAY_SIZE (opsize_names))
202
8.06M
    return opsize_names[opsize];
203
0
  return _("<invalid opsize>");
204
8.06M
}
205
206
static inline const char *
207
get_size_name (unsigned int size)
208
2.01M
{
209
2.01M
  if (size < ARRAY_SIZE (size_names))
210
2.01M
    return size_names[size];
211
0
  return _("<invalid size>");
212
2.01M
}
213
214
215
int
216
print_insn_rx (bfd_vma addr, disassemble_info * dis)
217
29.9M
{
218
29.9M
  int rv;
219
29.9M
  RX_Data rx_data;
220
29.9M
  RX_Opcode_Decoded opcode;
221
29.9M
  const char * s;
222
29.9M
  struct private priv;
223
224
29.9M
  dis->private_data = &priv;
225
29.9M
  rx_data.pc = addr;
226
29.9M
  rx_data.dis = dis;
227
228
29.9M
  if (OPCODES_SIGSETJMP (priv.bailout) != 0)
229
5.03k
    {
230
      /* Error return.  */
231
5.03k
      return -1;
232
5.03k
    }
233
234
29.9M
  rv = rx_decode_opcode (addr, &opcode, rx_get_byte, &rx_data);
235
236
29.9M
  dis->bytes_per_line = 10;
237
238
205M
#define PR (dis->fprintf_func)
239
205M
#define PS (dis->stream)
240
162M
#define PC(c) PR (PS, "%c", c)
241
242
  /* Detect illegal instructions.  */
243
29.9M
  if (opcode.op[0].size == RX_Bad_Size
244
29.9M
      || register_names [opcode.op[0].reg] == NULL
245
29.9M
      || register_names [opcode.op[1].reg] == NULL
246
29.9M
      || register_names [opcode.op[2].reg] == NULL)
247
240k
    {
248
240k
      bfd_byte buf[10];
249
240k
      int i;
250
251
240k
      PR (PS, ".byte ");
252
240k
      rx_data.dis->read_memory_func (rx_data.pc - rv, buf, rv, rx_data.dis);
253
      
254
1.20M
      for (i = 0 ; i < rv; i++)
255
964k
  PR (PS, "0x%02x ", buf[i]);
256
240k
      return rv;
257
240k
    }
258
      
259
239M
  for (s = opcode.syntax; *s; s++)
260
209M
    {
261
209M
      if (*s != '%')
262
162M
  {
263
162M
    PC (*s);
264
162M
  }
265
46.5M
      else
266
46.5M
  {
267
46.5M
    RX_Opcode_Operand * oper;
268
46.5M
    int do_size = 0;
269
46.5M
    int do_hex = 0;
270
46.5M
    int do_addr = 0;
271
272
46.5M
    s ++;
273
274
46.5M
    if (*s == 'S')
275
2.63M
      {
276
2.63M
        do_size = 1;
277
2.63M
        s++;
278
2.63M
      }
279
46.5M
    if (*s == 'x')
280
0
      {
281
0
        do_hex = 1;
282
0
        s++;
283
0
      }
284
46.5M
    if (*s == 'a')
285
4.86M
      {
286
4.86M
        do_addr = 1;
287
4.86M
        s++;
288
4.86M
      }
289
290
46.5M
    switch (*s)
291
46.5M
      {
292
0
      case '%':
293
0
        PC ('%');
294
0
        break;
295
296
8.06M
      case 's':
297
8.06M
        PR (PS, "%s", get_opsize_name (opcode.size));
298
8.06M
        break;
299
300
948
      case 'b':
301
948
        s ++;
302
948
        if (*s == 'f')
303
948
    {
304
948
      int imm = opcode.op[2].addend;
305
948
      int slsb, dlsb, width;
306
307
948
      dlsb = (imm >> 5) & 0x1f;
308
948
      slsb = (imm & 0x1f);
309
948
      slsb = (slsb >= 0x10?(slsb ^ 0x1f) + 1:slsb);
310
948
      slsb = dlsb - slsb;
311
948
      slsb = (slsb < 0?-slsb:slsb);
312
948
      width = ((imm >> 10) & 0x1f) - dlsb;
313
948
      PR (PS, "#%d, #%d, #%d, %s, %s",
314
948
          slsb, dlsb, width,
315
948
          get_register_name (opcode.op[1].reg),
316
948
          get_register_name (opcode.op[0].reg));
317
948
    }
318
948
        break;
319
17.2M
      case '0':
320
34.8M
      case '1':
321
38.5M
      case '2':
322
38.5M
        oper = opcode.op + (*s - '0');
323
38.5M
        if (do_size)
324
2.63M
    {
325
2.63M
      if (oper->type == RX_Operand_Indirect || oper->type == RX_Operand_Zero_Indirect)
326
2.01M
        PR (PS, "%s", get_size_name (oper->size));
327
2.63M
    }
328
35.8M
        else
329
35.8M
    switch (oper->type)
330
35.8M
      {
331
8.12M
      case RX_Operand_Immediate:
332
8.12M
        if (do_addr)
333
4.86M
          dis->print_address_func (oper->addend, dis);
334
3.25M
        else if (do_hex
335
3.25M
           || oper->addend > 999
336
3.25M
           || oper->addend < -999)
337
477k
          PR (PS, "%#x", oper->addend);
338
2.77M
        else
339
2.77M
          PR (PS, "%d", oper->addend);
340
8.12M
        break;
341
13.0M
      case RX_Operand_Register:
342
13.1M
      case RX_Operand_TwoReg:
343
13.1M
        PR (PS, "%s", get_register_name (oper->reg));
344
13.1M
        break;
345
8.46M
      case RX_Operand_Indirect:
346
8.46M
        PR (PS, "%d[%s]", oper->addend, get_register_name (oper->reg));
347
8.46M
        break;
348
2.60M
      case RX_Operand_Zero_Indirect:
349
2.60M
        PR (PS, "[%s]", get_register_name (oper->reg));
350
2.60M
        break;
351
1.64k
      case RX_Operand_Postinc:
352
1.64k
        PR (PS, "[%s+]", get_register_name (oper->reg));
353
1.64k
        break;
354
4.08k
      case RX_Operand_Predec:
355
4.08k
        PR (PS, "[-%s]", get_register_name (oper->reg));
356
4.08k
        break;
357
3.40M
      case RX_Operand_Condition:
358
3.40M
        PR (PS, "%s", get_condition_name (oper->reg));
359
3.40M
        break;
360
9.26k
      case RX_Operand_Flag:
361
9.26k
        PR (PS, "%s", get_flag_name (oper->reg));
362
9.26k
        break;
363
106k
      case RX_Operand_DoubleReg:
364
106k
        PR (PS, "%s", get_double_register_name (oper->reg));
365
106k
        break;
366
3.90k
      case RX_Operand_DoubleRegH:
367
3.90k
        PR (PS, "%s", get_double_register_high_name (oper->reg));
368
3.90k
        break;
369
5.30k
      case RX_Operand_DoubleRegL:
370
5.30k
        PR (PS, "%s", get_double_register_low_name (oper->reg));
371
5.30k
        break;
372
6.60k
      case RX_Operand_DoubleCReg:
373
6.60k
        PR (PS, "%s", get_double_control_register_name (oper->reg));
374
6.60k
        break;
375
5.54k
      case RX_Operand_DoubleCond:
376
5.54k
        PR (PS, "%s", get_double_condition_name (oper->reg));
377
5.54k
        break;
378
0
      default:
379
0
        PR (PS, "[???]");
380
0
        break;
381
35.8M
      }
382
46.5M
      }
383
46.5M
  }
384
209M
    }
385
386
29.6M
  return rv;
387
29.6M
}