Coverage Report

Created: 2026-07-25 10:20

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