Coverage Report

Created: 2026-05-11 07:54

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