Coverage Report

Created: 2025-06-24 06:45

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