Mark symbol in executables if it matches dynamic_list
[platform/upstream/binutils.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           if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON_R_C))
130                 {
131                   (*info->fprintf_func)(info->stream, " R%x, CCR",
132                           (raw_code >> 8) & 0x7);
133                 }
134           else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON_C_R))
135             {
136                   (*info->fprintf_func)(info->stream, " CCR, R%x",
137                       (raw_code >> 8) & 0x7);
138             }
139           else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON_R_P))
140             {
141                   (*info->fprintf_func)(info->stream, " R%x, PC",
142                       (raw_code >> 8) & 0x7);
143             }
144           else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_TRI))
145             {
146                   (*info->fprintf_func)(info->stream, " R%x, R%x, R%x",
147                       (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7,
148                       (raw_code >> 2) & 0x7);
149             }
150           else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IDR))
151             {
152                   if (raw_code & 0x01)
153                     {
154                       (*info->fprintf_func)(info->stream, " R%x, (R%x, R%x+)",
155                           (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7,
156                           (raw_code >> 2) & 0x7);
157                     }
158                    else if (raw_code & 0x02)
159                           {
160                             (*info->fprintf_func)(info->stream, " R%x, (R%x, -R%x)",
161                                 (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7,
162                                 (raw_code >> 2) & 0x7);
163                           }
164                    else
165                      {
166                        (*info->fprintf_func)(info->stream, " R%x, (R%x, R%x)",
167                            (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7,
168                            (raw_code >> 2) & 0x7);
169                      }
170             }
171           else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_DYA))
172             {
173                   operandOne = ripBits (&operMaskReg, 3, opcodePTR, raw_code);
174                   operandTwo = ripBits (&operMaskReg, 3, opcodePTR, raw_code);
175                  ( *info->fprintf_func)(info->stream, " R%x, R%x", operandOne,
176                       operandTwo);
177             }
178           else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IDO5))
179             {
180                   (*info->fprintf_func)(info->stream, " R%x, (R%x, #0x%x)",
181                       (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7, raw_code & 0x1f);
182             }
183           else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON))
184             {
185                   operandOne = ripBits (&operMaskReg, 3, decodePTR->opcodePTR,
186                      raw_code);
187                  (*info->fprintf_func)(info->stream, " R%x", operandOne);
188             }
189           else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_REL9))
190             {
191               /* If address is negative handle it accordingly.  */
192               if (raw_code & XGATE_NINE_SIGNBIT)
193                 {
194                   relAddr = XGATE_NINE_BITS >> 1; /* Clip sign bit.  */
195                   relAddr = ~relAddr; /* Make signed.  */
196                   relAddr |= (raw_code & 0xFF) + 1; /* Apply our value.  */
197                   relAddr <<= 1; /* Multiply by two as per processor docs.  */
198                 }
199               else
200                 {
201                   relAddr = raw_code & 0xff;
202                   relAddr = (relAddr << 1) + 2;
203                 }
204              (*info->fprintf_func)(info->stream, " *%d", relAddr);
205              (*info->fprintf_func)(info->stream, "  Abs* 0x");
206              (*info->print_address_func)(memaddr + relAddr, info);
207            }
208           else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_REL10))
209             {
210               /* If address is negative handle it accordingly.  */
211               if (raw_code & XGATE_TEN_SIGNBIT)
212                 {
213                   relAddr = XGATE_TEN_BITS >> 1; /* Clip sign bit.  */
214                   relAddr = ~relAddr; /* Make signed.  */
215                   relAddr |= (raw_code & 0x1FF) + 1; /* Apply our value.  */
216                   relAddr <<= 1; /* Multiply by two as per processor docs.  */
217                 }
218               else
219                 {
220                   relAddr = raw_code & 0x1FF;
221                   relAddr = (relAddr << 1) + 2;
222                 }
223               (*info->fprintf_func)(info->stream, " *%d", relAddr);
224               (*info->fprintf_func)(info->stream, "  Abs* 0x");
225               (*info->print_address_func)(memaddr + relAddr, info);
226             }
227           else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM4))
228             {
229               (*info->fprintf_func)(info->stream, " R%x, #0x%02x",
230               (raw_code >> 8) & 0x7, (raw_code >> 4) & 0xF);
231             }
232           else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM8))
233             {
234               if (macro_search (decodePTR->opcodePTR->name, previousOpName) &&
235                  previousOpName[0])
236                {
237                  absAddress = (0xFF & raw_code) << 8;
238                  absAddress |= perviousBin & 0xFF;
239                  (*info->fprintf_func)(info->stream, " R%x, #0x%02x Abs* 0x",
240                      (raw_code >> 8) & 0x7, raw_code & 0xff);
241                  (*info->print_address_func)(absAddress, info);
242                  previousOpName[0] = 0;
243                }
244               else
245                {
246                  strcpy (previousOpName, decodePTR->opcodePTR->name);
247                  (*info->fprintf_func)(info->stream, " R%x, #0x%02x",
248                      (raw_code >> 8) & 0x7, raw_code & 0xff);
249                }
250             }
251           else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM3))
252             {
253                   (*info->fprintf_func)(info->stream, " #0x%x",
254                      (raw_code >> 8) & 0x7);
255             }
256           else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_INH))
257             {
258                   //
259             }
260           else
261             {
262               (*info->fprintf_func)(info->stream, " unhandled mode %s",
263                 opcodePTR->constraints);
264             }
265           perviousBin = raw_code;
266         }
267       else
268         {
269           (*info->fprintf_func)(info->stream,
270                                 " unable to find opcode match #0%x", raw_code);
271         }
272     }
273   return bytesRead;
274 }
275
276 int
277 print_insn_xgate (bfd_vma memaddr, struct disassemble_info* info)
278 {
279   return print_insn (memaddr, info);
280 }
281
282 static int
283 read_memory (bfd_vma memaddr, bfd_byte* buffer, int size,
284     struct disassemble_info* info)
285 {
286   int status;
287   status = (*info->read_memory_func) (memaddr, buffer, size, info);
288   if (status != 0)
289     {
290       (*info->memory_error_func) (status, memaddr, info);
291       return -1;
292     }
293   return 0;
294 }
295
296 static int
297 ripBits (unsigned int *operandBitsRemaining,
298          int numBitsRequested,
299          struct xgate_opcode *opcodePTR,
300          unsigned int memory)
301 {
302   unsigned int currentBit;
303   int operand;
304   int numBitsFound;
305
306   for (operand = 0, numBitsFound = 0, currentBit = 1
307          << ((opcodePTR->size * 8) - 1);
308        (numBitsFound < numBitsRequested) && currentBit; currentBit >>= 1)
309     {
310       if (currentBit & *operandBitsRemaining)
311         {
312           *operandBitsRemaining &= ~(currentBit); /* Consume the current bit.  */
313           operand <<= 1; /* Make room for our next bit.  */
314           numBitsFound++;
315           operand |= (currentBit & memory) > 0;
316         }
317     }
318   return operand;
319 }
320
321 static int
322 macro_search (char *currentName, char *lastName)
323 {
324   int i;
325   int length = 0;
326   char *where;
327
328   for (i = 0; i < xgate_num_opcodes; i++)
329     {
330       where = strstr (xgate_opcodes[i].constraints, lastName);
331
332       if (where)
333         {
334           length = strlen (where);
335         }
336       if (length)
337         {
338           where = strstr (xgate_opcodes[i].constraints, currentName);
339           if (where)
340             {
341               length = strlen (where);
342               return 1;
343             }
344         }
345     }
346   return 0;
347 }
348
349 static struct decodeInfo *
350 find_match (unsigned int raw_code)
351 {
352   struct decodeInfo *decodeTablePTR = 0;
353   int i;
354
355   for (i = 0, decodeTablePTR = decodeTable; i < xgate_num_opcodes;
356       i++, decodeTablePTR++)
357     {
358       if ((raw_code & decodeTablePTR->operMask)
359           == decodeTablePTR->opcodePTR->bin_opcode)
360         {
361           /* Make sure we didn't run into a macro or alias.  */
362           if (decodeTablePTR->opcodePTR->cycles_min != 0)
363             {
364               return decodeTablePTR;
365               break;
366             }
367           else
368             continue;
369         }
370     }
371   return 0;
372 }