Coverage Report

Created: 2024-05-21 06:29

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