Coverage Report

Created: 2023-08-28 06:30

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