Coverage Report

Created: 2023-06-29 07:13

/src/binutils-gdb/opcodes/s12z-dis.c
Line
Count
Source (jump to first uncovered line)
1
/* s12z-dis.c -- Freescale S12Z disassembly
2
   Copyright (C) 2018-2023 Free Software Foundation, Inc.
3
4
   This file is part of the GNU opcodes library.
5
6
   This library is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3, or (at your option)
9
   any later version.
10
11
   It is distributed in the hope that it will be useful, but WITHOUT
12
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14
   License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with this program; if not, write to the Free Software
18
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19
   MA 02110-1301, USA.  */
20
21
#include "sysdep.h"
22
#include <stdio.h>
23
#include <stdint.h>
24
#include <stdbool.h>
25
#include <assert.h>
26
27
#include "opcode/s12z.h"
28
#include "bfd.h"
29
#include "dis-asm.h"
30
#include "disassemble.h"
31
#include "s12z-opc.h"
32
#include "opintl.h"
33
34
struct mem_read_abstraction
35
{
36
  struct mem_read_abstraction_base base;
37
  bfd_vma memaddr;
38
  struct disassemble_info* info;
39
};
40
41
static void
42
advance (struct mem_read_abstraction_base *b)
43
385k
{
44
385k
  struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
45
385k
  mra->memaddr ++;
46
385k
}
47
48
static bfd_vma
49
posn (struct mem_read_abstraction_base *b)
50
24.8k
{
51
24.8k
  struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
52
24.8k
  return mra->memaddr;
53
24.8k
}
54
55
static int
56
abstract_read_memory (struct mem_read_abstraction_base *b,
57
          int offset,
58
          size_t n, bfd_byte *bytes)
59
1.10M
{
60
1.10M
  struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
61
62
1.10M
  int status = (*mra->info->read_memory_func) (mra->memaddr + offset,
63
1.10M
                 bytes, n, mra->info);
64
1.10M
  if (status != 0)
65
668
    (*mra->info->memory_error_func) (status, mra->memaddr + offset,
66
668
                                     mra->info);
67
1.10M
  return status != 0 ? -1 : 0;
68
1.10M
}
69
70
/* Start of disassembly file.  */
71
const struct reg registers[S12Z_N_REGISTERS] =
72
  {
73
    {"d2", 2},
74
    {"d3", 2},
75
    {"d4", 2},
76
    {"d5", 2},
77
78
    {"d0", 1},
79
    {"d1", 1},
80
81
    {"d6", 4},
82
    {"d7", 4},
83
84
    {"x", 3},
85
    {"y", 3},
86
    {"s", 3},
87
    {"p", 3},
88
    {"cch", 1},
89
    {"ccl", 1},
90
    {"ccw", 2}
91
  };
92
93
static const char *mnemonics[] =
94
  {
95
    "!!invalid!!",
96
    "psh",
97
    "pul",
98
    "tbne", "tbeq", "tbpl", "tbmi", "tbgt", "tble",
99
    "dbne", "dbeq", "dbpl", "dbmi", "dbgt", "dble",
100
    "sex",
101
    "exg",
102
    "lsl", "lsr",
103
    "asl", "asr",
104
    "rol", "ror",
105
    "bfins", "bfext",
106
107
    "trap",
108
109
    "ld",
110
    "st",
111
    "cmp",
112
113
    "stop",
114
    "wai",
115
    "sys",
116
117
    "minu",
118
    "mins",
119
    "maxu",
120
    "maxs",
121
122
    "abs",
123
    "adc",
124
    "bit",
125
    "sbc",
126
    "rti",
127
    "clb",
128
    "eor",
129
130
    "sat",
131
132
    "nop",
133
    "bgnd",
134
    "brclr",
135
    "brset",
136
    "rts",
137
    "lea",
138
    "mov",
139
140
    "bra",
141
    "bsr",
142
    "bhi",
143
    "bls",
144
    "bcc",
145
    "bcs",
146
    "bne",
147
    "beq",
148
    "bvc",
149
    "bvs",
150
    "bpl",
151
    "bmi",
152
    "bge",
153
    "blt",
154
    "bgt",
155
    "ble",
156
    "inc",
157
    "clr",
158
    "dec",
159
160
    "add",
161
    "sub",
162
    "and",
163
    "or",
164
165
    "tfr",
166
    "jmp",
167
    "jsr",
168
    "com",
169
    "andcc",
170
    "neg",
171
    "orcc",
172
    "bclr",
173
    "bset",
174
    "btgl",
175
    "swi",
176
177
    "mulu",
178
    "divu",
179
    "modu",
180
    "macu",
181
    "qmulu",
182
183
    "muls",
184
    "divs",
185
    "mods",
186
    "macs",
187
    "qmuls",
188
189
    NULL
190
  };
191
192
193
static void
194
operand_separator (struct disassemble_info *info)
195
437k
{
196
437k
  if ((info->flags & 0x2))
197
437k
    (*info->fprintf_func) (info->stream, ",");
198
199
437k
  (*info->fprintf_func) (info->stream, " ");
200
201
437k
  info->flags |= 0x2;
202
437k
}
203
204
/* Render the symbol name whose value is ADDR + BASE or the adddress itself if
205
   there is no symbol.  If BASE is non zero, then the a PC relative adddress is
206
   assumend (ie BASE is the value in the PC.  */
207
static void
208
decode_possible_symbol (bfd_signed_vma addr, bfd_vma base,
209
                        struct disassemble_info *info, bool relative)
210
69.5k
{
211
69.5k
  const char *fmt = relative ? "*%+" PRId64 : "%" PRId64;
212
69.5k
  asymbol *sym = info->symbol_at_address_func (addr + base, info);
213
214
69.5k
  if (!sym)
215
69.5k
    (*info->fprintf_func) (info->stream, fmt, (int64_t) addr);
216
0
  else
217
0
    (*info->fprintf_func) (info->stream, "%s", bfd_asymbol_name (sym));
218
69.5k
}
219
220
221
/* Emit the disassembled text for OPR */
222
static void
223
opr_emit_disassembly (const struct operand *opr,
224
          struct disassemble_info *info)
225
437k
{
226
437k
  operand_separator (info);
227
228
437k
  switch (opr->cl)
229
437k
    {
230
68.0k
    case OPND_CL_IMMEDIATE:
231
68.0k
      (*info->fprintf_func) (info->stream, "#%d",
232
68.0k
           ((struct immediate_operand *) opr)->value);
233
68.0k
      break;
234
236k
    case OPND_CL_REGISTER:
235
236k
      {
236
236k
        int r = ((struct register_operand*) opr)->reg;
237
238
236k
  if (r < 0 || r >= S12Z_N_REGISTERS)
239
248
    (*info->fprintf_func) (info->stream, _("<illegal reg num>"));
240
235k
  else
241
235k
    (*info->fprintf_func) (info->stream, "%s", registers[r].name);
242
236k
      }
243
236k
      break;
244
23
    case OPND_CL_REGISTER_ALL16:
245
23
      (*info->fprintf_func) (info->stream, "%s", "ALL16b");
246
23
      break;
247
296
    case OPND_CL_REGISTER_ALL:
248
296
      (*info->fprintf_func) (info->stream, "%s", "ALL");
249
296
      break;
250
80
    case OPND_CL_BIT_FIELD:
251
80
      (*info->fprintf_func) (info->stream, "#%d:%d",
252
80
                             ((struct bitfield_operand*)opr)->width,
253
80
                             ((struct bitfield_operand*)opr)->offset);
254
80
      break;
255
69.5k
    case OPND_CL_SIMPLE_MEMORY:
256
69.5k
      {
257
69.5k
        struct simple_memory_operand *mo =
258
69.5k
    (struct simple_memory_operand *) opr;
259
69.5k
  decode_possible_symbol (mo->addr, mo->base, info, mo->relative);
260
69.5k
      }
261
69.5k
      break;
262
63.8k
    case OPND_CL_MEMORY:
263
63.8k
      {
264
63.8k
        int used_reg = 0;
265
63.8k
        struct memory_operand *mo = (struct memory_operand *) opr;
266
63.8k
  (*info->fprintf_func) (info->stream, "%c", mo->indirect ? '[' : '(');
267
268
63.8k
  const char *fmt;
269
63.8k
  assert (mo->mutation == OPND_RM_NONE || mo->n_regs == 1);
270
63.8k
  switch (mo->mutation)
271
63.8k
    {
272
1.78k
    case OPND_RM_PRE_DEC:
273
1.78k
      fmt = "-%s";
274
1.78k
      break;
275
1.34k
    case OPND_RM_PRE_INC:
276
1.34k
      fmt = "+%s";
277
1.34k
      break;
278
1.06k
    case OPND_RM_POST_DEC:
279
1.06k
      fmt = "%s-";
280
1.06k
      break;
281
6.06k
    case OPND_RM_POST_INC:
282
6.06k
      fmt = "%s+";
283
6.06k
      break;
284
53.6k
    case OPND_RM_NONE:
285
53.6k
    default:
286
53.6k
      if (mo->n_regs < 2)
287
43.3k
        (*info->fprintf_func) (info->stream, (mo->n_regs == 0) ? "%d" : "%d,", mo->base_offset);
288
53.6k
      fmt = "%s";
289
53.6k
      break;
290
63.8k
    }
291
63.8k
  if (mo->n_regs > 0)
292
63.0k
    {
293
63.0k
      int r = mo->regs[0];
294
295
63.0k
      if (r < 0 || r >= S12Z_N_REGISTERS)
296
0
        (*info->fprintf_func) (info->stream, fmt, _("<illegal reg num>"));
297
63.0k
      else
298
63.0k
        (*info->fprintf_func) (info->stream, fmt, registers[r].name);
299
63.0k
    }
300
63.8k
  used_reg = 1;
301
302
63.8k
        if (mo->n_regs > used_reg)
303
10.3k
          {
304
10.3k
      int r = mo->regs[used_reg];
305
306
10.3k
      if (r < 0 || r >= S12Z_N_REGISTERS)
307
0
        (*info->fprintf_func) (info->stream, _("<illegal reg num>"));
308
10.3k
      else
309
10.3k
        (*info->fprintf_func) (info->stream, ",%s",
310
10.3k
             registers[r].name);
311
10.3k
          }
312
313
63.8k
  (*info->fprintf_func) (info->stream, "%c",
314
63.8k
             mo->indirect ? ']' : ')');
315
63.8k
      }
316
0
      break;
317
437k
    };
318
437k
}
319
320
28.3k
#define S12Z_N_SIZES 4
321
static const char shift_size_table[S12Z_N_SIZES] =
322
{
323
  'b', 'w', 'p', 'l'
324
};
325
326
int
327
print_insn_s12z (bfd_vma memaddr, struct disassemble_info* info)
328
381k
{
329
381k
  int o;
330
381k
  enum optr operator = OP_INVALID;
331
381k
  int n_operands = 0;
332
333
  /* The longest instruction in S12Z can have 6 operands.
334
     (Most have 3 or less.  Only PSH and PUL have so many.  */
335
381k
  struct operand *operands[6];
336
337
381k
  struct mem_read_abstraction mra;
338
381k
  mra.base.read = (void *) abstract_read_memory ;
339
381k
  mra.base.advance = advance ;
340
381k
  mra.base.posn = posn;
341
381k
  mra.memaddr = memaddr;
342
381k
  mra.info = info;
343
344
381k
  short osize = -1;
345
381k
  int n_bytes =
346
381k
    decode_s12z (&operator, &osize, &n_operands, operands,
347
381k
     (struct mem_read_abstraction_base *) &mra);
348
349
381k
  (info->fprintf_func) (info->stream, "%s", mnemonics[(long)operator]);
350
351
  /* Ship out size sufficies for those instructions which
352
     need them.  */
353
381k
  if (osize == -1)
354
367k
    {
355
367k
      bool suffix = false;
356
357
786k
      for (o = 0; o < n_operands; ++o)
358
418k
  {
359
418k
    if (operands[o] && operands[o]->osize != -1)
360
14.3k
      {
361
14.3k
        if (!suffix)
362
13.3k
    {
363
13.3k
      (*mra.info->fprintf_func) (mra.info->stream, "%c", '.');
364
13.3k
      suffix = true;
365
13.3k
    }
366
367
14.3k
        osize = operands[o]->osize;
368
369
14.3k
        if (osize < 0 || osize >= S12Z_N_SIZES)
370
0
    (*mra.info->fprintf_func) (mra.info->stream, _("<bad>"));
371
14.3k
        else
372
14.3k
    (*mra.info->fprintf_func) (mra.info->stream, "%c",
373
14.3k
             shift_size_table[osize]);
374
14.3k
      }
375
418k
  }
376
367k
    }
377
13.9k
  else
378
13.9k
    {
379
13.9k
      if (osize < 0 || osize >= S12Z_N_SIZES)
380
0
  (*mra.info->fprintf_func) (mra.info->stream, _(".<bad>"));
381
13.9k
      else
382
13.9k
  (*mra.info->fprintf_func) (mra.info->stream, ".%c",
383
13.9k
           shift_size_table[osize]);
384
13.9k
    }
385
386
  /* Ship out the operands.  */
387
819k
  for (o = 0; o < n_operands; ++o)
388
437k
    {
389
437k
      if (operands[o])
390
437k
  opr_emit_disassembly (operands[o], mra.info);
391
437k
      free (operands[o]);
392
437k
    }
393
394
381k
  return n_bytes;
395
381k
}