Coverage Report

Created: 2026-09-14 08:07

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
56.9M
{
48
56.9M
  bfd_byte buf[1];
49
56.9M
  RX_Data *rx_data = (RX_Data *) vdata;
50
56.9M
  int status;
51
52
56.9M
  status = rx_data->dis->read_memory_func (rx_data->pc,
53
56.9M
             buf,
54
56.9M
             1,
55
56.9M
             rx_data->dis);
56
56.9M
  if (status != 0)
57
9.07k
    {
58
9.07k
      struct private *priv = (struct private *) rx_data->dis->private_data;
59
60
9.07k
      rx_data->dis->memory_error_func (status, rx_data->pc,
61
9.07k
               rx_data->dis);
62
9.07k
       OPCODES_SIGLONGJMP (priv->bailout, 1);
63
9.07k
    }
64
65
56.9M
  rx_data->pc ++;
66
56.9M
  return buf[0];
67
56.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
20.8M
{
137
20.8M
  if (reg < ARRAY_SIZE (register_names))
138
20.8M
    return register_names[reg];
139
0
  return _("<invalid register number>");
140
20.8M
}
141
142
static inline const char *
143
get_condition_name (unsigned int cond)
144
3.18M
{
145
3.18M
  if (cond < ARRAY_SIZE (condition_names))
146
3.18M
    return condition_names[cond];
147
0
  return _("<invalid condition code>");
148
3.18M
}
149
150
static inline const char *
151
get_flag_name (unsigned int flag)
152
14.4k
{
153
14.4k
  if (flag < ARRAY_SIZE (flag_names))
154
14.4k
    return flag_names[flag];
155
0
  return _("<invalid flag>");
156
14.4k
}
157
158
static inline const char *
159
get_double_register_name (unsigned int reg)
160
153k
{
161
153k
  if (reg < ARRAY_SIZE (double_register_names))
162
152k
    return double_register_names[reg];
163
889
  return _("<invalid register number>");
164
153k
}
165
166
static inline const char *
167
get_double_register_high_name (unsigned int reg)
168
12.6k
{
169
12.6k
  if (reg < ARRAY_SIZE (double_register_high_names))
170
12.6k
    return double_register_high_names[reg];
171
0
  return _("<invalid register number>");
172
12.6k
}
173
174
static inline const char *
175
get_double_register_low_name (unsigned int reg)
176
10.8k
{
177
10.8k
  if (reg < ARRAY_SIZE (double_register_low_names))
178
10.8k
    return double_register_low_names[reg];
179
0
  return _("<invalid register number>");
180
10.8k
}
181
182
static inline const char *
183
get_double_control_register_name (unsigned int reg)
184
11.3k
{
185
11.3k
  if (reg < ARRAY_SIZE (double_control_register_names))
186
2.34k
    return double_control_register_names[reg];
187
8.99k
  return _("<invalid register number>");
188
11.3k
}
189
190
static inline const char *
191
get_double_condition_name (unsigned int cond)
192
4.06k
{
193
4.06k
  if (cond < ARRAY_SIZE (double_condition_names))
194
2.68k
    return double_condition_names[cond];
195
1.38k
  return _("<invalid condition code>");
196
4.06k
}
197
198
static inline const char *
199
get_opsize_name (unsigned int opsize)
200
6.38M
{
201
6.38M
  if (opsize < ARRAY_SIZE (opsize_names))
202
6.38M
    return opsize_names[opsize];
203
0
  return _("<invalid opsize>");
204
6.38M
}
205
206
static inline const char *
207
get_size_name (unsigned int size)
208
1.71M
{
209
1.71M
  if (size < ARRAY_SIZE (size_names))
210
1.71M
    return size_names[size];
211
0
  return _("<invalid size>");
212
1.71M
}
213
214
215
int
216
print_insn_rx (bfd_vma addr, disassemble_info * dis)
217
31.0M
{
218
31.0M
  int rv;
219
31.0M
  RX_Data rx_data;
220
31.0M
  RX_Opcode_Decoded opcode;
221
31.0M
  const char * s;
222
31.0M
  struct private priv;
223
224
31.0M
  dis->private_data = &priv;
225
31.0M
  rx_data.pc = addr;
226
31.0M
  rx_data.dis = dis;
227
228
31.0M
  if (OPCODES_SIGSETJMP (priv.bailout) != 0)
229
9.07k
    {
230
      /* Error return.  */
231
9.07k
      return -1;
232
9.07k
    }
233
234
31.0M
  rv = rx_decode_opcode (addr, &opcode, rx_get_byte, &rx_data);
235
236
31.0M
  dis->bytes_per_line = 10;
237
238
200M
#define PR (dis->fprintf_func)
239
200M
#define PS (dis->stream)
240
164M
#define PC(c) PR (PS, "%c", c)
241
242
  /* Detect illegal instructions.  */
243
31.0M
  if (opcode.op[0].size == RX_Bad_Size
244
31.0M
      || register_names [opcode.op[0].reg] == NULL
245
31.0M
      || register_names [opcode.op[1].reg] == NULL
246
30.9M
      || register_names [opcode.op[2].reg] == NULL)
247
82.1k
    {
248
82.1k
      bfd_byte buf[10];
249
82.1k
      int i;
250
251
82.1k
      PR (PS, ".byte ");
252
82.1k
      rx_data.dis->read_memory_func (rx_data.pc - rv, buf, rv, rx_data.dis);
253
      
254
426k
      for (i = 0 ; i < rv; i++)
255
344k
  PR (PS, "0x%02x ", buf[i]);
256
82.1k
      return rv;
257
82.1k
    }
258
      
259
236M
  for (s = opcode.syntax; *s; s++)
260
205M
    {
261
205M
      if (*s != '%')
262
164M
  {
263
164M
    PC (*s);
264
164M
  }
265
40.8M
      else
266
40.8M
  {
267
40.8M
    RX_Opcode_Operand * oper;
268
40.8M
    int do_size = 0;
269
40.8M
    int do_hex = 0;
270
40.8M
    int do_addr = 0;
271
272
40.8M
    s ++;
273
274
40.8M
    if (*s == 'S')
275
2.27M
      {
276
2.27M
        do_size = 1;
277
2.27M
        s++;
278
2.27M
      }
279
40.8M
    if (*s == 'x')
280
0
      {
281
0
        do_hex = 1;
282
0
        s++;
283
0
      }
284
40.8M
    if (*s == 'a')
285
4.87M
      {
286
4.87M
        do_addr = 1;
287
4.87M
        s++;
288
4.87M
      }
289
290
40.8M
    switch (*s)
291
40.8M
      {
292
0
      case '%':
293
0
        PC ('%');
294
0
        break;
295
296
6.38M
      case 's':
297
6.38M
        PR (PS, "%s", get_opsize_name (opcode.size));
298
6.38M
        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.4M
      case '0':
320
30.7M
      case '1':
321
34.4M
      case '2':
322
34.4M
        oper = opcode.op + (*s - '0');
323
34.4M
        if (do_size)
324
2.27M
    {
325
2.27M
      if (oper->type == RX_Operand_Indirect || oper->type == RX_Operand_Zero_Indirect)
326
1.71M
        PR (PS, "%s", get_size_name (oper->size));
327
2.27M
    }
328
32.1M
        else
329
32.1M
    switch (oper->type)
330
32.1M
      {
331
7.92M
      case RX_Operand_Immediate:
332
7.92M
        if (do_addr)
333
4.87M
          dis->print_address_func (oper->addend, dis);
334
3.04M
        else if (do_hex
335
3.04M
           || oper->addend > 999
336
2.70M
           || oper->addend < -999)
337
515k
          PR (PS, "%#x", oper->addend);
338
2.52M
        else
339
2.52M
          PR (PS, "%d", oper->addend);
340
7.92M
        break;
341
11.9M
      case RX_Operand_Register:
342
12.0M
      case RX_Operand_TwoReg:
343
12.0M
        PR (PS, "%s", get_register_name (oper->reg));
344
12.0M
        break;
345
6.59M
      case RX_Operand_Indirect:
346
6.59M
        PR (PS, "%d[%s]", oper->addend, get_register_name (oper->reg));
347
6.59M
        break;
348
2.18M
      case RX_Operand_Zero_Indirect:
349
2.18M
        PR (PS, "[%s]", get_register_name (oper->reg));
350
2.18M
        break;
351
6.02k
      case RX_Operand_Postinc:
352
6.02k
        PR (PS, "[%s+]", get_register_name (oper->reg));
353
6.02k
        break;
354
8.53k
      case RX_Operand_Predec:
355
8.53k
        PR (PS, "[-%s]", get_register_name (oper->reg));
356
8.53k
        break;
357
3.18M
      case RX_Operand_Condition:
358
3.18M
        PR (PS, "%s", get_condition_name (oper->reg));
359
3.18M
        break;
360
14.4k
      case RX_Operand_Flag:
361
14.4k
        PR (PS, "%s", get_flag_name (oper->reg));
362
14.4k
        break;
363
153k
      case RX_Operand_DoubleReg:
364
153k
        PR (PS, "%s", get_double_register_name (oper->reg));
365
153k
        break;
366
12.6k
      case RX_Operand_DoubleRegH:
367
12.6k
        PR (PS, "%s", get_double_register_high_name (oper->reg));
368
12.6k
        break;
369
10.8k
      case RX_Operand_DoubleRegL:
370
10.8k
        PR (PS, "%s", get_double_register_low_name (oper->reg));
371
10.8k
        break;
372
11.3k
      case RX_Operand_DoubleCReg:
373
11.3k
        PR (PS, "%s", get_double_control_register_name (oper->reg));
374
11.3k
        break;
375
4.06k
      case RX_Operand_DoubleCond:
376
4.06k
        PR (PS, "%s", get_double_condition_name (oper->reg));
377
4.06k
        break;
378
0
      default:
379
0
        PR (PS, "[???]");
380
0
        break;
381
32.1M
      }
382
40.8M
      }
383
40.8M
  }
384
205M
    }
385
386
30.9M
  return rv;
387
30.9M
}