Coverage Report

Created: 2025-07-08 11:15

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