Coverage Report

Created: 2023-08-28 06:23

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