Coverage Report

Created: 2025-07-08 11:15

/src/binutils-gdb/opcodes/xgate-dis.c
Line
Count
Source (jump to first uncovered line)
1
/* xgate-dis.c -- Freescale XGATE disassembly
2
   Copyright (C) 2009-2025 Free Software Foundation, Inc.
3
   Written by Sean Keys (skeys@ipdatasys.com)
4
5
   This file is part of the GNU opcodes library.
6
7
   This library is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3, or (at your option)
10
   any later version.
11
12
   It is distributed in the hope that it will be useful, but WITHOUT
13
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15
   License for more details.
16
17
   You should have received a copy of the GNU General Public License
18
   along with this program; if not, write to the Free Software
19
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20
   MA 02110-1301, USA.  */
21
22
#include "sysdep.h"
23
#include <assert.h>
24
#include "disassemble.h"
25
#include "opintl.h"
26
#include "libiberty.h"
27
#include "ansidecl.h"
28
#include "opcode/xgate.h"
29
30
140k
#define XGATE_TWO_BYTES      0x02
31
2.81k
#define XGATE_NINE_BITS      0x1FF
32
721
#define XGATE_TEN_BITS       0x3FF
33
5.50k
#define XGATE_NINE_SIGNBIT   0x100
34
1.23k
#define XGATE_TEN_SIGNBIT    0x200
35
36
/* Structures.  */
37
struct decodeInfo
38
{
39
  unsigned int operMask;
40
  unsigned int operMasksRegisterBits;
41
  struct xgate_opcode *opcodePTR;
42
};
43
44
/* Prototypes for local functions.  */
45
static int print_insn (bfd_vma, struct disassemble_info *);
46
static int read_memory (bfd_vma, bfd_byte*, int, struct disassemble_info *);
47
static int ripBits (unsigned int *, int,
48
        struct xgate_opcode *, unsigned int);
49
static int macro_search (char *, char *);
50
static struct decodeInfo * find_match (unsigned int);
51
52
/* Statics.  */
53
static struct decodeInfo *decodeTable;
54
static int initialized;
55
static char previousOpName[10];
56
static unsigned int perviousBin;
57
58
/* Disassemble one instruction at address 'memaddr'.  Returns the number
59
   of bytes used by that instruction.  */
60
61
static int
62
print_insn (bfd_vma memaddr, struct disassemble_info* info)
63
70.0k
{
64
70.0k
  int status;
65
70.0k
  unsigned int raw_code;
66
70.0k
  char *s = 0;
67
70.0k
  long bytesRead = 0;
68
70.0k
  int i = 0;
69
70.0k
  struct xgate_opcode *opcodePTR = (struct xgate_opcode*) xgate_opcodes;
70
70.0k
  struct decodeInfo *decodeTablePTR = 0;
71
70.0k
  struct decodeInfo *decodePTR = 0;
72
70.0k
  unsigned int operandRegisterBits = 0;
73
70.0k
  signed int relAddr = 0;
74
70.0k
  signed int operandOne = 0;
75
70.0k
  signed int operandTwo = 0;
76
70.0k
  bfd_byte buffer[4];
77
70.0k
  bfd_vma absAddress;
78
79
70.0k
  unsigned int operMaskReg = 0;
80
  /* Initialize our array of opcode masks and check them against our constant
81
     table.  */
82
70.0k
  if (!initialized)
83
2
    {
84
2
      decodeTable = xmalloc (sizeof (struct decodeInfo) * xgate_num_opcodes);
85
192
      for (i = 0, decodeTablePTR = decodeTable; i < xgate_num_opcodes;
86
190
          i++, decodeTablePTR++, opcodePTR++)
87
190
        {
88
190
          unsigned int bin = 0;
89
190
          unsigned int mask = 0;
90
3.23k
          for (s = opcodePTR->format; *s; s++)
91
3.04k
            {
92
3.04k
              bin <<= 1;
93
3.04k
              mask <<= 1;
94
3.04k
              operandRegisterBits <<= 1;
95
3.04k
              bin |= (*s == '1');
96
3.04k
              mask |= (*s == '0' || *s == '1');
97
3.04k
              operandRegisterBits |= (*s == 'r');
98
3.04k
            }
99
          /* Asserting will uncover inconsistencies in our table.  */
100
190
          assert ((s - opcodePTR->format) == 16 || (s - opcodePTR->format) == 32);
101
190
          assert (opcodePTR->bin_opcode == bin);
102
103
190
          decodeTablePTR->operMask = mask;
104
190
          decodeTablePTR->operMasksRegisterBits = operandRegisterBits;
105
190
          decodeTablePTR->opcodePTR = opcodePTR;
106
190
        }
107
2
      initialized = 1;
108
2
    }
109
110
  /* Read 16 bits.  */
111
70.0k
  bytesRead += XGATE_TWO_BYTES;
112
70.0k
  status = read_memory (memaddr, buffer, XGATE_TWO_BYTES, info);
113
70.0k
  if (status == 0)
114
70.0k
    {
115
70.0k
      raw_code = buffer[0];
116
70.0k
      raw_code <<= 8;
117
70.0k
      raw_code += buffer[1];
118
119
70.0k
      decodePTR = find_match (raw_code);
120
70.0k
      if (decodePTR)
121
62.7k
        {
122
62.7k
          operMaskReg = decodePTR->operMasksRegisterBits;
123
62.7k
          (*info->fprintf_func)(info->stream, "%s", decodePTR->opcodePTR->name);
124
125
          /* First we compare the shorthand format of the constraints. If we
126
        still are unable to pinpoint the operands
127
        we analyze the opcodes constraint string.  */
128
62.7k
          if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON_R_C))
129
111
          {
130
111
            (*info->fprintf_func)(info->stream, " R%x, CCR",
131
111
              (raw_code >> 8) & 0x7);
132
111
          }
133
62.6k
          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON_C_R))
134
223
            {
135
223
            (*info->fprintf_func)(info->stream, " CCR, R%x",
136
223
                (raw_code >> 8) & 0x7);
137
223
            }
138
62.4k
          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON_R_P))
139
259
            {
140
259
            (*info->fprintf_func)(info->stream, " R%x, PC",
141
259
                (raw_code >> 8) & 0x7);
142
259
            }
143
62.1k
          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_TRI))
144
3.51k
            {
145
3.51k
                  (*info->fprintf_func)(info->stream, " R%x, R%x, R%x",
146
3.51k
                      (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7,
147
3.51k
                      (raw_code >> 2) & 0x7);
148
3.51k
            }
149
58.6k
          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IDR))
150
6.03k
            {
151
6.03k
                  if (raw_code & 0x01)
152
1.87k
                    {
153
1.87k
                      (*info->fprintf_func)(info->stream, " R%x, (R%x, R%x+)",
154
1.87k
                          (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7,
155
1.87k
                          (raw_code >> 2) & 0x7);
156
1.87k
                    }
157
4.15k
                   else if (raw_code & 0x02)
158
1.85k
                          {
159
1.85k
                            (*info->fprintf_func)(info->stream, " R%x, (R%x, -R%x)",
160
1.85k
                                (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7,
161
1.85k
                                (raw_code >> 2) & 0x7);
162
1.85k
                          }
163
2.30k
                   else
164
2.30k
                     {
165
2.30k
                       (*info->fprintf_func)(info->stream, " R%x, (R%x, R%x)",
166
2.30k
                           (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7,
167
2.30k
                           (raw_code >> 2) & 0x7);
168
2.30k
                     }
169
6.03k
            }
170
52.6k
          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_DYA))
171
467
            {
172
467
            operandOne = ripBits (&operMaskReg, 3, decodePTR->opcodePTR, raw_code);
173
467
            operandTwo = ripBits (&operMaskReg, 3, decodePTR->opcodePTR, raw_code);
174
467
           ( *info->fprintf_func)(info->stream, " R%x, R%x", operandOne,
175
467
                operandTwo);
176
467
            }
177
52.1k
          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IDO5))
178
5.61k
            {
179
5.61k
            (*info->fprintf_func)(info->stream, " R%x, (R%x, #0x%x)",
180
5.61k
                (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7, raw_code & 0x1f);
181
5.61k
            }
182
46.5k
          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON))
183
1.48k
            {
184
1.48k
            operandOne = ripBits (&operMaskReg, 3, decodePTR->opcodePTR,
185
1.48k
               raw_code);
186
1.48k
           (*info->fprintf_func)(info->stream, " R%x", operandOne);
187
1.48k
            }
188
45.0k
          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_REL9))
189
5.50k
            {
190
              /* If address is negative handle it accordingly.  */
191
5.50k
              if (raw_code & XGATE_NINE_SIGNBIT)
192
2.81k
                {
193
2.81k
                  relAddr = XGATE_NINE_BITS >> 1; /* Clip sign bit.  */
194
2.81k
                  relAddr = ~relAddr; /* Make signed.  */
195
2.81k
                  relAddr |= (raw_code & 0xFF) + 1; /* Apply our value.  */
196
2.81k
                  relAddr *= 2; /* Multiply by two as per processor docs.  */
197
2.81k
                }
198
2.69k
              else
199
2.69k
                {
200
2.69k
                  relAddr = raw_code & 0xff;
201
2.69k
                  relAddr = relAddr * 2 + 2;
202
2.69k
                }
203
5.50k
             (*info->fprintf_func)(info->stream, " *%d", relAddr);
204
5.50k
             (*info->fprintf_func)(info->stream, "  Abs* 0x");
205
5.50k
             (*info->print_address_func)(memaddr + relAddr, info);
206
5.50k
           }
207
39.5k
          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_REL10))
208
1.23k
            {
209
              /* If address is negative handle it accordingly.  */
210
1.23k
              if (raw_code & XGATE_TEN_SIGNBIT)
211
721
                {
212
721
                  relAddr = XGATE_TEN_BITS >> 1; /* Clip sign bit.  */
213
721
                  relAddr = ~relAddr; /* Make signed.  */
214
721
                  relAddr |= (raw_code & 0x1FF) + 1; /* Apply our value.  */
215
721
                  relAddr *= 2; /* Multiply by two as per processor docs.  */
216
721
                }
217
512
              else
218
512
                {
219
512
                  relAddr = raw_code & 0x1FF;
220
512
                  relAddr = relAddr * 2 + 2;
221
512
                }
222
1.23k
              (*info->fprintf_func)(info->stream, " *%d", relAddr);
223
1.23k
              (*info->fprintf_func)(info->stream, "  Abs* 0x");
224
1.23k
              (*info->print_address_func)(memaddr + relAddr, info);
225
1.23k
            }
226
38.3k
          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM4))
227
1.71k
            {
228
1.71k
              (*info->fprintf_func)(info->stream, " R%x, #0x%02x",
229
1.71k
              (raw_code >> 8) & 0x7, (raw_code >> 4) & 0xF);
230
1.71k
            }
231
36.6k
          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM8))
232
27.1k
            {
233
27.1k
              if (macro_search (decodePTR->opcodePTR->name, previousOpName) &&
234
27.1k
                 previousOpName[0])
235
7.54k
               {
236
7.54k
                 absAddress = (0xFF & raw_code) << 8;
237
7.54k
                 absAddress |= perviousBin & 0xFF;
238
7.54k
                 (*info->fprintf_func)(info->stream, " R%x, #0x%02x Abs* 0x",
239
7.54k
                     (raw_code >> 8) & 0x7, raw_code & 0xff);
240
7.54k
                 (*info->print_address_func)(absAddress, info);
241
7.54k
                 previousOpName[0] = 0;
242
7.54k
               }
243
19.5k
              else
244
19.5k
               {
245
19.5k
                 strcpy (previousOpName, decodePTR->opcodePTR->name);
246
19.5k
                 (*info->fprintf_func)(info->stream, " R%x, #0x%02x",
247
19.5k
                     (raw_code >> 8) & 0x7, raw_code & 0xff);
248
19.5k
               }
249
27.1k
            }
250
9.49k
          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM3))
251
241
            {
252
241
            (*info->fprintf_func)(info->stream, " #0x%x",
253
241
               (raw_code >> 8) & 0x7);
254
241
            }
255
9.25k
          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_INH))
256
9.25k
            {
257
9.25k
            }
258
0
          else
259
0
            {
260
0
              (*info->fprintf_func)(info->stream, " unhandled mode %s",
261
0
            decodePTR->opcodePTR->constraints);
262
0
            }
263
62.7k
          perviousBin = raw_code;
264
62.7k
        }
265
7.23k
      else
266
7.23k
        {
267
7.23k
          (*info->fprintf_func)(info->stream,
268
7.23k
        " unable to find opcode match #0%x", raw_code);
269
7.23k
        }
270
70.0k
    }
271
70.0k
  return bytesRead;
272
70.0k
}
273
274
int
275
print_insn_xgate (bfd_vma memaddr, struct disassemble_info* info)
276
70.0k
{
277
70.0k
  return print_insn (memaddr, info);
278
70.0k
}
279
280
static int
281
read_memory (bfd_vma memaddr, bfd_byte* buffer, int size,
282
    struct disassemble_info* info)
283
70.0k
{
284
70.0k
  int status;
285
70.0k
  status = (*info->read_memory_func) (memaddr, buffer, size, info);
286
70.0k
  if (status != 0)
287
68
    {
288
68
      (*info->memory_error_func) (status, memaddr, info);
289
68
      return -1;
290
68
    }
291
70.0k
  return 0;
292
70.0k
}
293
294
static int
295
ripBits (unsigned int *operandBitsRemaining,
296
   int numBitsRequested,
297
   struct xgate_opcode *opcodePTR,
298
   unsigned int memory)
299
2.41k
{
300
2.41k
  unsigned int currentBit;
301
2.41k
  unsigned int operand = 0;
302
2.41k
  int numBitsFound;
303
304
2.41k
  for (numBitsFound = 0, currentBit = 1u << ((opcodePTR->size * 8) - 1);
305
23.1k
       numBitsFound < numBitsRequested && currentBit != 0;
306
20.7k
       currentBit >>= 1)
307
20.7k
    {
308
20.7k
      if (currentBit & *operandBitsRemaining)
309
7.24k
  {
310
7.24k
    *operandBitsRemaining &= ~(currentBit); /* Consume the current bit.  */
311
7.24k
    operand <<= 1; /* Make room for our next bit.  */
312
7.24k
    numBitsFound++;
313
7.24k
    operand |= (currentBit & memory) > 0;
314
7.24k
  }
315
20.7k
    }
316
2.41k
  return operand;
317
2.41k
}
318
319
static int
320
macro_search (char *currentName, char *lastName)
321
27.1k
{
322
27.1k
  int i;
323
27.1k
  int length = 0;
324
27.1k
  char *where;
325
326
2.49M
  for (i = 0; i < xgate_num_opcodes; i++)
327
2.48M
    {
328
2.48M
      where = strstr (xgate_opcodes[i].constraints, lastName);
329
330
2.48M
      if (where)
331
684k
        {
332
684k
          length = strlen (where);
333
684k
        }
334
2.48M
      if (length)
335
688k
        {
336
688k
          where = strstr (xgate_opcodes[i].constraints, currentName);
337
688k
          if (where)
338
14.0k
            {
339
14.0k
              length = strlen (where);
340
14.0k
              return 1;
341
14.0k
            }
342
688k
        }
343
2.48M
    }
344
13.1k
  return 0;
345
27.1k
}
346
347
static struct decodeInfo *
348
find_match (unsigned int raw_code)
349
70.0k
{
350
70.0k
  struct decodeInfo *decodeTablePTR = 0;
351
70.0k
  int i;
352
353
3.18M
  for (i = 0, decodeTablePTR = decodeTable; i < xgate_num_opcodes;
354
3.11M
      i++, decodeTablePTR++)
355
3.18M
    {
356
3.18M
      if ((raw_code & decodeTablePTR->operMask)
357
3.18M
          == decodeTablePTR->opcodePTR->bin_opcode)
358
106k
        {
359
          /* Make sure we didn't run into a macro or alias.  */
360
106k
          if (decodeTablePTR->opcodePTR->cycles_min != 0)
361
62.7k
            {
362
62.7k
              return decodeTablePTR;
363
0
              break;
364
62.7k
            }
365
43.3k
          else
366
43.3k
      continue;
367
106k
        }
368
3.18M
    }
369
7.23k
  return 0;
370
70.0k
}