1/* xgate-dis.c -- Freescale XGATE disassembly
2   Copyright (C) 2009-2017 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 "dis-asm.h"
25#include "opintl.h"
26#include "libiberty.h"
27#include "ansidecl.h"
28#include "opcode/xgate.h"
29
30#define XGATE_TWO_BYTES      0x02
31#define XGATE_NINE_BITS      0x1FF
32#define XGATE_TEN_BITS       0x3FF
33#define XGATE_NINE_SIGNBIT   0x100
34#define XGATE_TEN_SIGNBIT    0x200
35
36/* Structures.  */
37struct decodeInfo
38{
39  unsigned int operMask;
40  unsigned int operMasksRegisterBits;
41  struct xgate_opcode *opcodePTR;
42};
43
44/* Prototypes for local functions.  */
45static int print_insn (bfd_vma, struct disassemble_info *);
46static int read_memory (bfd_vma, bfd_byte*, int, struct disassemble_info *);
47static int ripBits (unsigned int *, int,
48		    struct xgate_opcode *, unsigned int);
49static int macro_search (char *, char *);
50static struct decodeInfo * find_match (unsigned int);
51
52/* Statics.  */
53static struct decodeInfo *decodeTable;
54static int initialized;
55static char previousOpName[10];
56static unsigned int perviousBin;
57
58/* Disassemble one instruction at address 'memaddr'.  Returns the number
59   of bytes used by that instruction.  */
60
61static int
62print_insn (bfd_vma memaddr, struct disassemble_info* info)
63{
64  int status;
65  unsigned int raw_code;
66  char *s = 0;
67  long bytesRead = 0;
68  int i = 0;
69  struct xgate_opcode *opcodePTR = (struct xgate_opcode*) xgate_opcodes;
70  struct decodeInfo *decodeTablePTR = 0;
71  struct decodeInfo *decodePTR = 0;
72  unsigned int operandRegisterBits = 0;
73  signed int relAddr = 0;
74  signed int operandOne = 0;
75  signed int operandTwo = 0;
76  bfd_byte buffer[4];
77  bfd_vma absAddress;
78
79  unsigned int operMaskReg = 0;
80  /* Initialize our array of opcode masks and check them against our constant
81     table.  */
82  if (!initialized)
83    {
84      decodeTable = xmalloc (sizeof (struct decodeInfo) * xgate_num_opcodes);
85      for (i = 0, decodeTablePTR = decodeTable; i < xgate_num_opcodes;
86          i++, decodeTablePTR++, opcodePTR++)
87        {
88          unsigned int bin = 0;
89          unsigned int mask = 0;
90          for (s = opcodePTR->format; *s; s++)
91            {
92              bin <<= 1;
93              mask <<= 1;
94              operandRegisterBits <<= 1;
95              bin |= (*s == '1');
96              mask |= (*s == '0' || *s == '1');
97              operandRegisterBits |= (*s == 'r');
98            }
99          /* Asserting will uncover inconsistencies in our table.  */
100          assert ((s - opcodePTR->format) == 16 || (s - opcodePTR->format) == 32);
101          assert (opcodePTR->bin_opcode == bin);
102
103          decodeTablePTR->operMask = mask;
104          decodeTablePTR->operMasksRegisterBits = operandRegisterBits;
105          decodeTablePTR->opcodePTR = opcodePTR;
106        }
107      initialized = 1;
108    }
109
110  /* Read 16 bits.  */
111  bytesRead += XGATE_TWO_BYTES;
112  status = read_memory (memaddr, buffer, XGATE_TWO_BYTES, info);
113  if (status == 0)
114    {
115      raw_code = buffer[0];
116      raw_code <<= 8;
117      raw_code += buffer[1];
118
119      decodePTR = find_match (raw_code);
120      if (decodePTR)
121        {
122          operMaskReg = decodePTR->operMasksRegisterBits;
123          (*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          if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON_R_C))
129        	{
130        	  (*info->fprintf_func)(info->stream, " R%x, CCR",
131        		  (raw_code >> 8) & 0x7);
132        	}
133          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON_C_R))
134            {
135        	  (*info->fprintf_func)(info->stream, " CCR, R%x",
136        	      (raw_code >> 8) & 0x7);
137            }
138          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON_R_P))
139            {
140        	  (*info->fprintf_func)(info->stream, " R%x, PC",
141        	      (raw_code >> 8) & 0x7);
142            }
143          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_TRI))
144            {
145                  (*info->fprintf_func)(info->stream, " R%x, R%x, R%x",
146                      (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7,
147                      (raw_code >> 2) & 0x7);
148            }
149          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IDR))
150            {
151                  if (raw_code & 0x01)
152                    {
153                      (*info->fprintf_func)(info->stream, " R%x, (R%x, R%x+)",
154                          (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7,
155                          (raw_code >> 2) & 0x7);
156                    }
157                   else if (raw_code & 0x02)
158                          {
159                            (*info->fprintf_func)(info->stream, " R%x, (R%x, -R%x)",
160                                (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7,
161                                (raw_code >> 2) & 0x7);
162                          }
163                   else
164                     {
165                       (*info->fprintf_func)(info->stream, " R%x, (R%x, R%x)",
166                           (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7,
167                           (raw_code >> 2) & 0x7);
168                     }
169            }
170          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_DYA))
171            {
172        	  operandOne = ripBits (&operMaskReg, 3, opcodePTR, raw_code);
173        	  operandTwo = ripBits (&operMaskReg, 3, opcodePTR, raw_code);
174        	 ( *info->fprintf_func)(info->stream, " R%x, R%x", operandOne,
175        	      operandTwo);
176            }
177          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IDO5))
178            {
179        	  (*info->fprintf_func)(info->stream, " R%x, (R%x, #0x%x)",
180        	      (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7, raw_code & 0x1f);
181            }
182          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON))
183            {
184        	  operandOne = ripBits (&operMaskReg, 3, decodePTR->opcodePTR,
185        	     raw_code);
186        	 (*info->fprintf_func)(info->stream, " R%x", operandOne);
187            }
188          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_REL9))
189            {
190              /* If address is negative handle it accordingly.  */
191              if (raw_code & XGATE_NINE_SIGNBIT)
192                {
193                  relAddr = XGATE_NINE_BITS >> 1; /* Clip sign bit.  */
194                  relAddr = ~relAddr; /* Make signed.  */
195                  relAddr |= (raw_code & 0xFF) + 1; /* Apply our value.  */
196                  relAddr <<= 1; /* Multiply by two as per processor docs.  */
197                }
198              else
199                {
200                  relAddr = raw_code & 0xff;
201                  relAddr = (relAddr << 1) + 2;
202                }
203             (*info->fprintf_func)(info->stream, " *%d", relAddr);
204             (*info->fprintf_func)(info->stream, "  Abs* 0x");
205             (*info->print_address_func)(memaddr + relAddr, info);
206           }
207          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_REL10))
208            {
209              /* If address is negative handle it accordingly.  */
210              if (raw_code & XGATE_TEN_SIGNBIT)
211                {
212                  relAddr = XGATE_TEN_BITS >> 1; /* Clip sign bit.  */
213                  relAddr = ~relAddr; /* Make signed.  */
214                  relAddr |= (raw_code & 0x1FF) + 1; /* Apply our value.  */
215                  relAddr <<= 1; /* Multiply by two as per processor docs.  */
216                }
217              else
218                {
219                  relAddr = raw_code & 0x1FF;
220                  relAddr = (relAddr << 1) + 2;
221                }
222              (*info->fprintf_func)(info->stream, " *%d", relAddr);
223              (*info->fprintf_func)(info->stream, "  Abs* 0x");
224              (*info->print_address_func)(memaddr + relAddr, info);
225            }
226          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM4))
227            {
228              (*info->fprintf_func)(info->stream, " R%x, #0x%02x",
229              (raw_code >> 8) & 0x7, (raw_code >> 4) & 0xF);
230            }
231          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM8))
232            {
233              if (macro_search (decodePTR->opcodePTR->name, previousOpName) &&
234                 previousOpName[0])
235               {
236                 absAddress = (0xFF & raw_code) << 8;
237                 absAddress |= perviousBin & 0xFF;
238                 (*info->fprintf_func)(info->stream, " R%x, #0x%02x Abs* 0x",
239                     (raw_code >> 8) & 0x7, raw_code & 0xff);
240                 (*info->print_address_func)(absAddress, info);
241                 previousOpName[0] = 0;
242               }
243              else
244               {
245                 strcpy (previousOpName, decodePTR->opcodePTR->name);
246                 (*info->fprintf_func)(info->stream, " R%x, #0x%02x",
247                     (raw_code >> 8) & 0x7, raw_code & 0xff);
248               }
249            }
250          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM3))
251            {
252        	  (*info->fprintf_func)(info->stream, " #0x%x",
253        	     (raw_code >> 8) & 0x7);
254            }
255          else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_INH))
256            {
257        	  //
258            }
259          else
260            {
261              (*info->fprintf_func)(info->stream, " unhandled mode %s",
262                opcodePTR->constraints);
263            }
264          perviousBin = raw_code;
265        }
266      else
267        {
268          (*info->fprintf_func)(info->stream,
269				" unable to find opcode match #0%x", raw_code);
270        }
271    }
272  return bytesRead;
273}
274
275int
276print_insn_xgate (bfd_vma memaddr, struct disassemble_info* info)
277{
278  return print_insn (memaddr, info);
279}
280
281static int
282read_memory (bfd_vma memaddr, bfd_byte* buffer, int size,
283    struct disassemble_info* info)
284{
285  int status;
286  status = (*info->read_memory_func) (memaddr, buffer, size, info);
287  if (status != 0)
288    {
289      (*info->memory_error_func) (status, memaddr, info);
290      return -1;
291    }
292  return 0;
293}
294
295static int
296ripBits (unsigned int *operandBitsRemaining,
297	 int numBitsRequested,
298	 struct xgate_opcode *opcodePTR,
299	 unsigned int memory)
300{
301  unsigned int currentBit;
302  int operand;
303  int numBitsFound;
304
305  for (operand = 0, numBitsFound = 0, currentBit = 1
306	 << ((opcodePTR->size * 8) - 1);
307       (numBitsFound < numBitsRequested) && currentBit; currentBit >>= 1)
308    {
309      if (currentBit & *operandBitsRemaining)
310	{
311	  *operandBitsRemaining &= ~(currentBit); /* Consume the current bit.  */
312	  operand <<= 1; /* Make room for our next bit.  */
313	  numBitsFound++;
314	  operand |= (currentBit & memory) > 0;
315	}
316    }
317  return operand;
318}
319
320static int
321macro_search (char *currentName, char *lastName)
322{
323  int i;
324  int length = 0;
325  char *where;
326
327  for (i = 0; i < xgate_num_opcodes; i++)
328    {
329      where = strstr (xgate_opcodes[i].constraints, lastName);
330
331      if (where)
332        {
333          length = strlen (where);
334        }
335      if (length)
336        {
337          where = strstr (xgate_opcodes[i].constraints, currentName);
338          if (where)
339            {
340              length = strlen (where);
341              return 1;
342            }
343        }
344    }
345  return 0;
346}
347
348static struct decodeInfo *
349find_match (unsigned int raw_code)
350{
351  struct decodeInfo *decodeTablePTR = 0;
352  int i;
353
354  for (i = 0, decodeTablePTR = decodeTable; i < xgate_num_opcodes;
355      i++, decodeTablePTR++)
356    {
357      if ((raw_code & decodeTablePTR->operMask)
358          == decodeTablePTR->opcodePTR->bin_opcode)
359        {
360          /* Make sure we didn't run into a macro or alias.  */
361          if (decodeTablePTR->opcodePTR->cycles_min != 0)
362            {
363              return decodeTablePTR;
364              break;
365            }
366          else
367	    continue;
368        }
369    }
370  return 0;
371}
372