Coverage Report

Created: 2023-08-28 06:31

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