Coverage Report

Created: 2023-08-28 06:31

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