Coverage Report

Created: 2023-08-28 06:30

/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
0
{
44
0
  struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
45
0
  mra->memaddr ++;
46
0
}
47
48
static bfd_vma
49
posn (struct mem_read_abstraction_base *b)
50
0
{
51
0
  struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
52
0
  return mra->memaddr;
53
0
}
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
0
{
60
0
  struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
61
62
0
  int status = (*mra->info->read_memory_func) (mra->memaddr + offset,
63
0
                 bytes, n, mra->info);
64
0
  if (status != 0)
65
0
    (*mra->info->memory_error_func) (status, mra->memaddr + offset,
66
0
                                     mra->info);
67
0
  return status != 0 ? -1 : 0;
68
0
}
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
0
{
196
0
  if ((info->flags & 0x2))
197
0
    (*info->fprintf_func) (info->stream, ",");
198
199
0
  (*info->fprintf_func) (info->stream, " ");
200
201
0
  info->flags |= 0x2;
202
0
}
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
0
{
211
0
  const char *fmt = relative ? "*%+" PRId64 : "%" PRId64;
212
0
  asymbol *sym = info->symbol_at_address_func (addr + base, info);
213
214
0
  if (!sym)
215
0
    (*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
0
}
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
0
{
226
0
  operand_separator (info);
227
228
0
  switch (opr->cl)
229
0
    {
230
0
    case OPND_CL_IMMEDIATE:
231
0
      (*info->fprintf_func) (info->stream, "#%d",
232
0
           ((struct immediate_operand *) opr)->value);
233
0
      break;
234
0
    case OPND_CL_REGISTER:
235
0
      {
236
0
        int r = ((struct register_operand*) opr)->reg;
237
238
0
  if (r < 0 || r >= S12Z_N_REGISTERS)
239
0
    (*info->fprintf_func) (info->stream, _("<illegal reg num>"));
240
0
  else
241
0
    (*info->fprintf_func) (info->stream, "%s", registers[r].name);
242
0
      }
243
0
      break;
244
0
    case OPND_CL_REGISTER_ALL16:
245
0
      (*info->fprintf_func) (info->stream, "%s", "ALL16b");
246
0
      break;
247
0
    case OPND_CL_REGISTER_ALL:
248
0
      (*info->fprintf_func) (info->stream, "%s", "ALL");
249
0
      break;
250
0
    case OPND_CL_BIT_FIELD:
251
0
      (*info->fprintf_func) (info->stream, "#%d:%d",
252
0
                             ((struct bitfield_operand*)opr)->width,
253
0
                             ((struct bitfield_operand*)opr)->offset);
254
0
      break;
255
0
    case OPND_CL_SIMPLE_MEMORY:
256
0
      {
257
0
        struct simple_memory_operand *mo =
258
0
    (struct simple_memory_operand *) opr;
259
0
  decode_possible_symbol (mo->addr, mo->base, info, mo->relative);
260
0
      }
261
0
      break;
262
0
    case OPND_CL_MEMORY:
263
0
      {
264
0
        int used_reg = 0;
265
0
        struct memory_operand *mo = (struct memory_operand *) opr;
266
0
  (*info->fprintf_func) (info->stream, "%c", mo->indirect ? '[' : '(');
267
268
0
  const char *fmt;
269
0
  assert (mo->mutation == OPND_RM_NONE || mo->n_regs == 1);
270
0
  switch (mo->mutation)
271
0
    {
272
0
    case OPND_RM_PRE_DEC:
273
0
      fmt = "-%s";
274
0
      break;
275
0
    case OPND_RM_PRE_INC:
276
0
      fmt = "+%s";
277
0
      break;
278
0
    case OPND_RM_POST_DEC:
279
0
      fmt = "%s-";
280
0
      break;
281
0
    case OPND_RM_POST_INC:
282
0
      fmt = "%s+";
283
0
      break;
284
0
    case OPND_RM_NONE:
285
0
    default:
286
0
      if (mo->n_regs < 2)
287
0
        (*info->fprintf_func) (info->stream, (mo->n_regs == 0) ? "%d" : "%d,", mo->base_offset);
288
0
      fmt = "%s";
289
0
      break;
290
0
    }
291
0
  if (mo->n_regs > 0)
292
0
    {
293
0
      int r = mo->regs[0];
294
295
0
      if (r < 0 || r >= S12Z_N_REGISTERS)
296
0
        (*info->fprintf_func) (info->stream, fmt, _("<illegal reg num>"));
297
0
      else
298
0
        (*info->fprintf_func) (info->stream, fmt, registers[r].name);
299
0
    }
300
0
  used_reg = 1;
301
302
0
        if (mo->n_regs > used_reg)
303
0
          {
304
0
      int r = mo->regs[used_reg];
305
306
0
      if (r < 0 || r >= S12Z_N_REGISTERS)
307
0
        (*info->fprintf_func) (info->stream, _("<illegal reg num>"));
308
0
      else
309
0
        (*info->fprintf_func) (info->stream, ",%s",
310
0
             registers[r].name);
311
0
          }
312
313
0
  (*info->fprintf_func) (info->stream, "%c",
314
0
             mo->indirect ? ']' : ')');
315
0
      }
316
0
      break;
317
0
    };
318
0
}
319
320
0
#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
0
{
329
0
  int o;
330
0
  enum optr operator = OP_INVALID;
331
0
  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
0
  struct operand *operands[6];
336
337
0
  struct mem_read_abstraction mra;
338
0
  mra.base.read = (void *) abstract_read_memory ;
339
0
  mra.base.advance = advance ;
340
0
  mra.base.posn = posn;
341
0
  mra.memaddr = memaddr;
342
0
  mra.info = info;
343
344
0
  short osize = -1;
345
0
  int n_bytes =
346
0
    decode_s12z (&operator, &osize, &n_operands, operands,
347
0
     (struct mem_read_abstraction_base *) &mra);
348
349
0
  (info->fprintf_func) (info->stream, "%s", mnemonics[(long)operator]);
350
351
  /* Ship out size sufficies for those instructions which
352
     need them.  */
353
0
  if (osize == -1)
354
0
    {
355
0
      bool suffix = false;
356
357
0
      for (o = 0; o < n_operands; ++o)
358
0
  {
359
0
    if (operands[o] && operands[o]->osize != -1)
360
0
      {
361
0
        if (!suffix)
362
0
    {
363
0
      (*mra.info->fprintf_func) (mra.info->stream, "%c", '.');
364
0
      suffix = true;
365
0
    }
366
367
0
        osize = operands[o]->osize;
368
369
0
        if (osize < 0 || osize >= S12Z_N_SIZES)
370
0
    (*mra.info->fprintf_func) (mra.info->stream, _("<bad>"));
371
0
        else
372
0
    (*mra.info->fprintf_func) (mra.info->stream, "%c",
373
0
             shift_size_table[osize]);
374
0
      }
375
0
  }
376
0
    }
377
0
  else
378
0
    {
379
0
      if (osize < 0 || osize >= S12Z_N_SIZES)
380
0
  (*mra.info->fprintf_func) (mra.info->stream, _(".<bad>"));
381
0
      else
382
0
  (*mra.info->fprintf_func) (mra.info->stream, ".%c",
383
0
           shift_size_table[osize]);
384
0
    }
385
386
  /* Ship out the operands.  */
387
0
  for (o = 0; o < n_operands; ++o)
388
0
    {
389
0
      if (operands[o])
390
0
  opr_emit_disassembly (operands[o], mra.info);
391
0
      free (operands[o]);
392
0
    }
393
394
0
  return n_bytes;
395
0
}