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