Coverage Report

Created: 2026-04-04 08:16

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