Coverage Report

Created: 2026-07-12 09:22

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