Coverage Report

Created: 2026-10-02 09:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/binutils-gdb/opcodes/rx-dis.c
Line
Count
Source
1
/* Disassembler code for Renesas RX.
2
   Copyright (C) 2008-2026 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
57.4M
{
48
57.4M
  bfd_byte buf[1];
49
57.4M
  RX_Data *rx_data = (RX_Data *) vdata;
50
57.4M
  int status;
51
52
57.4M
  status = rx_data->dis->read_memory_func (rx_data->pc,
53
57.4M
             buf,
54
57.4M
             1,
55
57.4M
             rx_data->dis);
56
57.4M
  if (status != 0)
57
9.31k
    {
58
9.31k
      struct private *priv = (struct private *) rx_data->dis->private_data;
59
60
9.31k
      rx_data->dis->memory_error_func (status, rx_data->pc,
61
9.31k
               rx_data->dis);
62
9.31k
       OPCODES_SIGLONGJMP (priv->bailout, 1);
63
9.31k
    }
64
65
57.3M
  rx_data->pc ++;
66
57.3M
  return buf[0];
67
57.4M
}
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
21.0M
{
137
21.0M
  if (reg < ARRAY_SIZE (register_names))
138
21.0M
    return register_names[reg];
139
0
  return _("<invalid register number>");
140
21.0M
}
141
142
static inline const char *
143
get_condition_name (unsigned int cond)
144
3.21M
{
145
3.21M
  if (cond < ARRAY_SIZE (condition_names))
146
3.21M
    return condition_names[cond];
147
0
  return _("<invalid condition code>");
148
3.21M
}
149
150
static inline const char *
151
get_flag_name (unsigned int flag)
152
14.6k
{
153
14.6k
  if (flag < ARRAY_SIZE (flag_names))
154
14.6k
    return flag_names[flag];
155
0
  return _("<invalid flag>");
156
14.6k
}
157
158
static inline const char *
159
get_double_register_name (unsigned int reg)
160
156k
{
161
156k
  if (reg < ARRAY_SIZE (double_register_names))
162
155k
    return double_register_names[reg];
163
879
  return _("<invalid register number>");
164
156k
}
165
166
static inline const char *
167
get_double_register_high_name (unsigned int reg)
168
12.8k
{
169
12.8k
  if (reg < ARRAY_SIZE (double_register_high_names))
170
12.8k
    return double_register_high_names[reg];
171
0
  return _("<invalid register number>");
172
12.8k
}
173
174
static inline const char *
175
get_double_register_low_name (unsigned int reg)
176
11.5k
{
177
11.5k
  if (reg < ARRAY_SIZE (double_register_low_names))
178
11.5k
    return double_register_low_names[reg];
179
0
  return _("<invalid register number>");
180
11.5k
}
181
182
static inline const char *
183
get_double_control_register_name (unsigned int reg)
184
11.9k
{
185
11.9k
  if (reg < ARRAY_SIZE (double_control_register_names))
186
2.60k
    return double_control_register_names[reg];
187
9.37k
  return _("<invalid register number>");
188
11.9k
}
189
190
static inline const char *
191
get_double_condition_name (unsigned int cond)
192
4.20k
{
193
4.20k
  if (cond < ARRAY_SIZE (double_condition_names))
194
2.74k
    return double_condition_names[cond];
195
1.46k
  return _("<invalid condition code>");
196
4.20k
}
197
198
static inline const char *
199
get_opsize_name (unsigned int opsize)
200
6.43M
{
201
6.43M
  if (opsize < ARRAY_SIZE (opsize_names))
202
6.43M
    return opsize_names[opsize];
203
0
  return _("<invalid opsize>");
204
6.43M
}
205
206
static inline const char *
207
get_size_name (unsigned int size)
208
1.72M
{
209
1.72M
  if (size < ARRAY_SIZE (size_names))
210
1.72M
    return size_names[size];
211
0
  return _("<invalid size>");
212
1.72M
}
213
214
215
int
216
print_insn_rx (bfd_vma addr, disassemble_info * dis)
217
31.3M
{
218
31.3M
  int rv;
219
31.3M
  RX_Data rx_data;
220
31.3M
  RX_Opcode_Decoded opcode;
221
31.3M
  const char * s;
222
31.3M
  struct private priv;
223
224
31.3M
  dis->private_data = &priv;
225
31.3M
  rx_data.pc = addr;
226
31.3M
  rx_data.dis = dis;
227
228
31.3M
  if (OPCODES_SIGSETJMP (priv.bailout) != 0)
229
9.31k
    {
230
      /* Error return.  */
231
9.31k
      return -1;
232
9.31k
    }
233
234
31.3M
  rv = rx_decode_opcode (addr, &opcode, rx_get_byte, &rx_data);
235
236
31.3M
  dis->bytes_per_line = 10;
237
238
202M
#define PR (dis->fprintf_func)
239
202M
#define PS (dis->stream)
240
166M
#define PC(c) PR (PS, "%c", c)
241
242
  /* Detect illegal instructions.  */
243
31.3M
  if (opcode.op[0].size == RX_Bad_Size
244
31.2M
      || register_names [opcode.op[0].reg] == NULL
245
31.2M
      || register_names [opcode.op[1].reg] == NULL
246
31.2M
      || register_names [opcode.op[2].reg] == NULL)
247
82.9k
    {
248
82.9k
      bfd_byte buf[10];
249
82.9k
      int i;
250
251
82.9k
      PR (PS, ".byte ");
252
82.9k
      rx_data.dis->read_memory_func (rx_data.pc - rv, buf, rv, rx_data.dis);
253
      
254
430k
      for (i = 0 ; i < rv; i++)
255
347k
  PR (PS, "0x%02x ", buf[i]);
256
82.9k
      return rv;
257
82.9k
    }
258
      
259
238M
  for (s = opcode.syntax; *s; s++)
260
207M
    {
261
207M
      if (*s != '%')
262
166M
  {
263
166M
    PC (*s);
264
166M
  }
265
41.1M
      else
266
41.1M
  {
267
41.1M
    RX_Opcode_Operand * oper;
268
41.1M
    int do_size = 0;
269
41.1M
    int do_hex = 0;
270
41.1M
    int do_addr = 0;
271
272
41.1M
    s ++;
273
274
41.1M
    if (*s == 'S')
275
2.29M
      {
276
2.29M
        do_size = 1;
277
2.29M
        s++;
278
2.29M
      }
279
41.1M
    if (*s == 'x')
280
0
      {
281
0
        do_hex = 1;
282
0
        s++;
283
0
      }
284
41.1M
    if (*s == 'a')
285
4.92M
      {
286
4.92M
        do_addr = 1;
287
4.92M
        s++;
288
4.92M
      }
289
290
41.1M
    switch (*s)
291
41.1M
      {
292
0
      case '%':
293
0
        PC ('%');
294
0
        break;
295
296
6.43M
      case 's':
297
6.43M
        PR (PS, "%s", get_opsize_name (opcode.size));
298
6.43M
        break;
299
300
1.65k
      case 'b':
301
1.65k
        s ++;
302
1.65k
        if (*s == 'f')
303
1.65k
    {
304
1.65k
      int imm = opcode.op[2].addend;
305
1.65k
      int slsb, dlsb, width;
306
307
1.65k
      dlsb = (imm >> 5) & 0x1f;
308
1.65k
      slsb = (imm & 0x1f);
309
1.65k
      slsb = (slsb >= 0x10?(slsb ^ 0x1f) + 1:slsb);
310
1.65k
      slsb = dlsb - slsb;
311
1.65k
      slsb = (slsb < 0?-slsb:slsb);
312
1.65k
      width = ((imm >> 10) & 0x1f) - dlsb;
313
1.65k
      PR (PS, "#%d, #%d, #%d, %s, %s",
314
1.65k
          slsb, dlsb, width,
315
1.65k
          get_register_name (opcode.op[1].reg),
316
1.65k
          get_register_name (opcode.op[0].reg));
317
1.65k
    }
318
1.65k
        break;
319
15.5M
      case '0':
320
31.0M
      case '1':
321
34.7M
      case '2':
322
34.7M
        oper = opcode.op + (*s - '0');
323
34.7M
        if (do_size)
324
2.29M
    {
325
2.29M
      if (oper->type == RX_Operand_Indirect || oper->type == RX_Operand_Zero_Indirect)
326
1.72M
        PR (PS, "%s", get_size_name (oper->size));
327
2.29M
    }
328
32.4M
        else
329
32.4M
    switch (oper->type)
330
32.4M
      {
331
8.00M
      case RX_Operand_Immediate:
332
8.00M
        if (do_addr)
333
4.92M
          dis->print_address_func (oper->addend, dis);
334
3.08M
        else if (do_hex
335
3.08M
           || oper->addend > 999
336
2.73M
           || oper->addend < -999)
337
520k
          PR (PS, "%#x", oper->addend);
338
2.56M
        else
339
2.56M
          PR (PS, "%d", oper->addend);
340
8.00M
        break;
341
12.0M
      case RX_Operand_Register:
342
12.1M
      case RX_Operand_TwoReg:
343
12.1M
        PR (PS, "%s", get_register_name (oper->reg));
344
12.1M
        break;
345
6.64M
      case RX_Operand_Indirect:
346
6.64M
        PR (PS, "%d[%s]", oper->addend, get_register_name (oper->reg));
347
6.64M
        break;
348
2.20M
      case RX_Operand_Zero_Indirect:
349
2.20M
        PR (PS, "[%s]", get_register_name (oper->reg));
350
2.20M
        break;
351
6.19k
      case RX_Operand_Postinc:
352
6.19k
        PR (PS, "[%s+]", get_register_name (oper->reg));
353
6.19k
        break;
354
8.58k
      case RX_Operand_Predec:
355
8.58k
        PR (PS, "[-%s]", get_register_name (oper->reg));
356
8.58k
        break;
357
3.21M
      case RX_Operand_Condition:
358
3.21M
        PR (PS, "%s", get_condition_name (oper->reg));
359
3.21M
        break;
360
14.6k
      case RX_Operand_Flag:
361
14.6k
        PR (PS, "%s", get_flag_name (oper->reg));
362
14.6k
        break;
363
156k
      case RX_Operand_DoubleReg:
364
156k
        PR (PS, "%s", get_double_register_name (oper->reg));
365
156k
        break;
366
12.8k
      case RX_Operand_DoubleRegH:
367
12.8k
        PR (PS, "%s", get_double_register_high_name (oper->reg));
368
12.8k
        break;
369
11.5k
      case RX_Operand_DoubleRegL:
370
11.5k
        PR (PS, "%s", get_double_register_low_name (oper->reg));
371
11.5k
        break;
372
11.9k
      case RX_Operand_DoubleCReg:
373
11.9k
        PR (PS, "%s", get_double_control_register_name (oper->reg));
374
11.9k
        break;
375
4.20k
      case RX_Operand_DoubleCond:
376
4.20k
        PR (PS, "%s", get_double_condition_name (oper->reg));
377
4.20k
        break;
378
0
      default:
379
0
        PR (PS, "[???]");
380
0
        break;
381
32.4M
      }
382
41.1M
      }
383
41.1M
  }
384
207M
    }
385
386
31.2M
  return rv;
387
31.2M
}