Coverage Report

Created: 2024-05-21 06:29

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