1 /* xgate-dis.c -- Freescale XGATE disassembly
2    Copyright (C) 2009-2020 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 #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.  */
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
print_insn(bfd_vma memaddr,struct disassemble_info * info)62 print_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, decodePTR->opcodePTR, raw_code);
173         	  operandTwo = ripBits (&operMaskReg, 3, decodePTR->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 *= 2; /* Multiply by two as per processor docs.  */
197                 }
198               else
199                 {
200                   relAddr = raw_code & 0xff;
201                   relAddr = relAddr * 2 + 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 *= 2; /* Multiply by two as per processor docs.  */
216                 }
217               else
218                 {
219                   relAddr = raw_code & 0x1FF;
220                   relAddr = relAddr * 2 + 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           else
259             {
260               (*info->fprintf_func)(info->stream, " unhandled mode %s",
261 				    decodePTR->opcodePTR->constraints);
262             }
263           perviousBin = raw_code;
264         }
265       else
266         {
267           (*info->fprintf_func)(info->stream,
268 				" unable to find opcode match #0%x", raw_code);
269         }
270     }
271   return bytesRead;
272 }
273 
274 int
print_insn_xgate(bfd_vma memaddr,struct disassemble_info * info)275 print_insn_xgate (bfd_vma memaddr, struct disassemble_info* info)
276 {
277   return print_insn (memaddr, info);
278 }
279 
280 static int
read_memory(bfd_vma memaddr,bfd_byte * buffer,int size,struct disassemble_info * info)281 read_memory (bfd_vma memaddr, bfd_byte* buffer, int size,
282     struct disassemble_info* info)
283 {
284   int status;
285   status = (*info->read_memory_func) (memaddr, buffer, size, info);
286   if (status != 0)
287     {
288       (*info->memory_error_func) (status, memaddr, info);
289       return -1;
290     }
291   return 0;
292 }
293 
294 static int
ripBits(unsigned int * operandBitsRemaining,int numBitsRequested,struct xgate_opcode * opcodePTR,unsigned int memory)295 ripBits (unsigned int *operandBitsRemaining,
296 	 int numBitsRequested,
297 	 struct xgate_opcode *opcodePTR,
298 	 unsigned int memory)
299 {
300   unsigned int currentBit;
301   unsigned int operand = 0;
302   int numBitsFound;
303 
304   for (numBitsFound = 0, currentBit = 1u << ((opcodePTR->size * 8) - 1);
305        numBitsFound < numBitsRequested && currentBit != 0;
306        currentBit >>= 1)
307     {
308       if (currentBit & *operandBitsRemaining)
309 	{
310 	  *operandBitsRemaining &= ~(currentBit); /* Consume the current bit.  */
311 	  operand <<= 1; /* Make room for our next bit.  */
312 	  numBitsFound++;
313 	  operand |= (currentBit & memory) > 0;
314 	}
315     }
316   return operand;
317 }
318 
319 static int
macro_search(char * currentName,char * lastName)320 macro_search (char *currentName, char *lastName)
321 {
322   int i;
323   int length = 0;
324   char *where;
325 
326   for (i = 0; i < xgate_num_opcodes; i++)
327     {
328       where = strstr (xgate_opcodes[i].constraints, lastName);
329 
330       if (where)
331         {
332           length = strlen (where);
333         }
334       if (length)
335         {
336           where = strstr (xgate_opcodes[i].constraints, currentName);
337           if (where)
338             {
339               length = strlen (where);
340               return 1;
341             }
342         }
343     }
344   return 0;
345 }
346 
347 static struct decodeInfo *
find_match(unsigned int raw_code)348 find_match (unsigned int raw_code)
349 {
350   struct decodeInfo *decodeTablePTR = 0;
351   int i;
352 
353   for (i = 0, decodeTablePTR = decodeTable; i < xgate_num_opcodes;
354       i++, decodeTablePTR++)
355     {
356       if ((raw_code & decodeTablePTR->operMask)
357           == decodeTablePTR->opcodePTR->bin_opcode)
358         {
359           /* Make sure we didn't run into a macro or alias.  */
360           if (decodeTablePTR->opcodePTR->cycles_min != 0)
361             {
362               return decodeTablePTR;
363               break;
364             }
365           else
366 	    continue;
367         }
368     }
369   return 0;
370 }
371