PR 14072
[deliverable/binutils-gdb.git] / opcodes / xgate-dis.c
CommitLineData
f6c1a2d5 1/* xgate-dis.c -- Freescale XGATE disassembly
df7b86aa 2 Copyright 2009, 2010, 2011, 2012
f6c1a2d5
NC
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,
df7b86aa 21 MA 02110-1301, USA. */
f6c1a2d5 22
f6c1a2d5 23#include "sysdep.h"
df7b86aa 24#include <assert.h>
f6c1a2d5
NC
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
df7b86aa
NC
37/* Structures. */
38struct decodeInfo
39{
f6c1a2d5
NC
40 unsigned int operMask;
41 unsigned int operMasksRegisterBits;
42 struct xgate_opcode *opcodePTR;
43};
44
45/* Prototypes for local functions. */
df7b86aa
NC
46static int print_insn (bfd_vma, struct disassemble_info *);
47static int read_memory (bfd_vma, bfd_byte*, int, struct disassemble_info *);
48static int ripBits (unsigned int *, int,
49 struct xgate_opcode *, unsigned int);
50static int macro_search (char *, char *);
51static struct decodeInfo * find_match (unsigned int);
f6c1a2d5 52
df7b86aa 53/* Statics. */
f6c1a2d5
NC
54static struct decodeInfo *decodeTable;
55static int initialized;
56static char previousOpName[10];
57static unsigned int perviousBin;
58
59/* Disassemble one instruction at address 'memaddr'. Returns the number
df7b86aa
NC
60 of bytes used by that instruction. */
61
f6c1a2d5
NC
62static int
63print_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;
df7b86aa
NC
81 /* Initialize our array of opcode masks and check them against our constant
82 table. */
f6c1a2d5
NC
83 if (!initialized)
84 {
df7b86aa 85 decodeTable = xmalloc (sizeof (struct decodeInfo) * xgate_num_opcodes);
f6c1a2d5
NC
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 }
df7b86aa
NC
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
f6c1a2d5
NC
104 decodeTablePTR->operMask = mask;
105 decodeTablePTR->operMasksRegisterBits = operandRegisterBits;
106 decodeTablePTR->opcodePTR = opcodePTR;
107 }
108 initialized = 1;
109 }
df7b86aa
NC
110
111 /* Read 16 bits. */
f6c1a2d5 112 bytesRead += XGATE_TWO_BYTES;
df7b86aa 113 status = read_memory (memaddr, buffer, XGATE_TWO_BYTES, info);
f6c1a2d5
NC
114 if (status == 0)
115 {
116 raw_code = buffer[0];
117 raw_code <<= 8;
118 raw_code += buffer[1];
119
df7b86aa 120 decodePTR = find_match (raw_code);
f6c1a2d5
NC
121 if (decodePTR)
122 {
123 operMaskReg = decodePTR->operMasksRegisterBits;
124 (*info->fprintf_func)(info->stream, "%s", decodePTR->opcodePTR->name);
df7b86aa 125
f6c1a2d5 126 /* First we compare the shorthand format of the constraints. If we
df7b86aa
NC
127 still are unable to pinpoint the operands
128 we analyze the opcodes constraint string. */
f6c1a2d5
NC
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:
df7b86aa 146 if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_TRI))
f6c1a2d5
NC
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 }
df7b86aa 152 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IDR))
f6c1a2d5
NC
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:
df7b86aa 180 if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_DYA_MON))
f6c1a2d5 181 {
df7b86aa 182 operandOne = ripBits (&operMaskReg, 3, decodePTR->opcodePTR,
f6c1a2d5 183 raw_code);
df7b86aa 184 operandTwo = ripBits (&operMaskReg, 3, decodePTR->opcodePTR,
f6c1a2d5
NC
185 raw_code);
186 (*info->fprintf_func)(info->stream, " R%x, R%x", operandOne,
187 operandTwo);
188 }
df7b86aa 189 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_DYA))
f6c1a2d5 190 {
df7b86aa
NC
191 operandOne = ripBits (&operMaskReg, 3, opcodePTR, raw_code);
192 operandTwo = ripBits (&operMaskReg, 3, opcodePTR, raw_code);
f6c1a2d5
NC
193 (*info->fprintf_func)(info->stream, " R%x, R%x", operandOne,
194 operandTwo);
195 }
196 else
197 {
198 (*info->fprintf_func)(info->stream, " unhandled mode %s",
199 opcodePTR->constraints);
200 }
201 break;
202 case XG_R_R_I:
203 (*info->fprintf_func)(info->stream, " R%x, (R%x, #0x%x)",
204 (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7, raw_code & 0x1f);
205 break;
206 case XG_R:
df7b86aa 207 operandOne = ripBits (&operMaskReg, 3, decodePTR->opcodePTR,
f6c1a2d5
NC
208 raw_code);
209 (*info->fprintf_func)(info->stream, " R%x", operandOne);
210 break;
211 case XG_I | XG_PCREL:
df7b86aa 212 if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_REL9))
f6c1a2d5 213 {
df7b86aa 214 /* If address is negative handle it accordingly. */
f6c1a2d5
NC
215 if (raw_code & XGATE_NINE_SIGNBIT)
216 {
df7b86aa
NC
217 relAddr = XGATE_NINE_BITS >> 1; /* Clip sign bit. */
218 relAddr = ~relAddr; /* Make signed. */
219 relAddr |= (raw_code & 0xFF) + 1; /* Apply our value. */
220 relAddr <<= 1; /* Multiply by two as per processor docs. */
f6c1a2d5
NC
221 }
222 else
223 {
224 relAddr = raw_code & 0xff;
225 relAddr = (relAddr << 1) + 2;
226 }
227 (*info->fprintf_func)(info->stream, " *%d", relAddr);
228 (*info->fprintf_func)(info->stream, " Abs* 0x");
229 (*info->print_address_func)(memaddr + relAddr, info);
230 }
df7b86aa 231 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_REL10))
f6c1a2d5 232 {
df7b86aa 233 /* If address is negative handle it accordingly. */
f6c1a2d5
NC
234 if (raw_code & XGATE_TEN_SIGNBIT)
235 {
df7b86aa
NC
236 relAddr = XGATE_TEN_BITS >> 1; /* Clip sign bit. */
237 relAddr = ~relAddr; /* Make signed. */
238 relAddr |= (raw_code & 0x1FF) + 1; /* Apply our value. */
239 relAddr <<= 1; /* Multiply by two as per processor docs. */
f6c1a2d5
NC
240 }
241 else
242 {
243 relAddr = raw_code & 0x1FF;
244 relAddr = (relAddr << 1) + 2;
245 }
246 (*info->fprintf_func)(info->stream, " *%d", relAddr);
247 (*info->fprintf_func)(info->stream, " Abs* 0x");
248 (*info->print_address_func)(memaddr + relAddr, info);
249 }
250 else
251 {
252 (*info->fprintf_func)(info->stream,
253 " Can't disassemble for mode) %s",
254 decodePTR->opcodePTR->constraints);
255 }
256 break;
257 case XG_R_I:
df7b86aa 258 if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM4))
f6c1a2d5
NC
259 {
260 (*info->fprintf_func)(info->stream, " R%x, #0x%02x",
261 (raw_code >> 8) & 0x7, (raw_code >> 4) & 0xF);
262 }
df7b86aa 263 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM8))
f6c1a2d5 264 {
df7b86aa 265 if (macro_search (decodePTR->opcodePTR->name, previousOpName) &&
f6c1a2d5
NC
266 previousOpName[0])
267 {
268 absAddress = (0xFF & raw_code) << 8;
269 absAddress |= perviousBin & 0xFF;
270 (*info->fprintf_func)(info->stream, " R%x, #0x%02x Abs* 0x",
271 (raw_code >> 8) & 0x7, raw_code & 0xff);
272 (*info->print_address_func)(absAddress, info);
273 previousOpName[0] = 0;
274 }
275 else
276 {
df7b86aa 277 strcpy (previousOpName, decodePTR->opcodePTR->name);
f6c1a2d5
NC
278 (*info->fprintf_func)(info->stream, " R%x, #0x%02x",
279 (raw_code >> 8) & 0x7, raw_code & 0xff);
280 }
281 }
282 else
283 {
284 (*info->fprintf_func)(info->stream,
285 " Can't disassemble for mode %s",
286 decodePTR->opcodePTR->constraints);
287 }
288 break;
289 case XG_I:
290 (*info->fprintf_func)(info->stream, " #0x%x",
291 (raw_code >> 8) & 0x7);
292 break;
293 default:
294 (*info->fprintf_func)(info->stream, "address mode not found\t %x",
295 opcodePTR->bin_opcode);
296 break;
297 }
298 perviousBin = raw_code;
299 }
300 else
301 {
302 (*info->fprintf_func)(info->stream,
df7b86aa 303 " unable to find opcode match #0%x", raw_code);
f6c1a2d5
NC
304 }
305 }
306 return bytesRead;
307}
308
309int
310print_insn_xgate (bfd_vma memaddr, struct disassemble_info* info)
311{
312 return print_insn (memaddr, info);
313}
314
315static int
316read_memory (bfd_vma memaddr, bfd_byte* buffer, int size,
317 struct disassemble_info* info)
318{
319 int status;
320 status = (*info->read_memory_func) (memaddr, buffer, size, info);
321 if (status != 0)
322 {
323 (*info->memory_error_func) (status, memaddr, info);
324 return -1;
325 }
326 return 0;
327}
328
329static int
df7b86aa
NC
330ripBits (unsigned int *operandBitsRemaining,
331 int numBitsRequested,
332 struct xgate_opcode *opcodePTR,
333 unsigned int memory)
f6c1a2d5
NC
334{
335 unsigned int currentBit;
336 int operand;
337 int numBitsFound;
df7b86aa 338
f6c1a2d5 339 for (operand = 0, numBitsFound = 0, currentBit = 1
df7b86aa
NC
340 << ((opcodePTR->size * 8) - 1);
341 (numBitsFound < numBitsRequested) && currentBit; currentBit >>= 1)
f6c1a2d5 342 {
df7b86aa
NC
343 if (currentBit & *operandBitsRemaining)
344 {
345 *operandBitsRemaining &= ~(currentBit); /* Consume the current bit. */
346 operand <<= 1; /* Make room for our next bit. */
347 numBitsFound++;
348 operand |= (currentBit & memory) > 0;
349 }
350 }
f6c1a2d5
NC
351 return operand;
352}
353
df7b86aa
NC
354static int
355macro_search (char *currentName, char *lastName)
f6c1a2d5
NC
356{
357 int i;
358 int length = 0;
359 char *where;
df7b86aa 360
f6c1a2d5
NC
361 for (i = 0; i < xgate_num_opcodes; i++)
362 {
df7b86aa
NC
363 where = strstr (xgate_opcodes[i].constraints, lastName);
364
f6c1a2d5
NC
365 if (where)
366 {
df7b86aa 367 length = strlen (where);
f6c1a2d5
NC
368 }
369 if (length)
370 {
df7b86aa 371 where = strstr (xgate_opcodes[i].constraints, currentName);
f6c1a2d5
NC
372 if (where)
373 {
df7b86aa 374 length = strlen (where);
f6c1a2d5
NC
375 return 1;
376 }
377 }
378 }
379 return 0;
380}
381
df7b86aa
NC
382static struct decodeInfo *
383find_match (unsigned int raw_code)
f6c1a2d5
NC
384{
385 struct decodeInfo *decodeTablePTR = 0;
386 int i;
387
388 for (i = 0, decodeTablePTR = decodeTable; i < xgate_num_opcodes;
389 i++, decodeTablePTR++)
390 {
391 if ((raw_code & decodeTablePTR->operMask)
392 == decodeTablePTR->opcodePTR->bin_opcode)
393 {
df7b86aa 394 /* Make sure we didn't run into a macro or alias. */
f6c1a2d5
NC
395 if (decodeTablePTR->opcodePTR->cycles_min != 0)
396 {
397 return decodeTablePTR;
398 break;
399 }
400 else
df7b86aa 401 continue;
f6c1a2d5
NC
402 }
403 }
404 return 0;
405}
This page took 0.044085 seconds and 4 git commands to generate.