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