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)
6 This file is part of the GNU opcodes library.
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)
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.
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. */
27 #include "libiberty.h"
29 #include "opcode/xgate.h"
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
40 unsigned int operMask;
41 unsigned int operMasksRegisterBits;
42 struct xgate_opcode *opcodePTR;
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);
54 static struct decodeInfo *decodeTable;
55 static int initialized;
56 static char previousOpName[10];
57 static unsigned int perviousBin;
59 /* Disassemble one instruction at address 'memaddr'. Returns the number
60 of bytes used by that instruction. */
63 print_insn (bfd_vma memaddr, struct disassemble_info* info)
66 unsigned int raw_code;
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;
80 unsigned int operMaskReg = 0;
81 /* Initialize our array of opcode masks and check them against our constant
85 decodeTable = xmalloc (sizeof (struct decodeInfo) * xgate_num_opcodes);
86 for (i = 0, decodeTablePTR = decodeTable; i < xgate_num_opcodes;
87 i++, decodeTablePTR++, opcodePTR++)
90 unsigned int mask = 0;
91 for (s = opcodePTR->format; *s; s++)
95 operandRegisterBits <<= 1;
97 mask |= (*s == '0' || *s == '1');
98 operandRegisterBits |= (*s == 'r');
100 /* Asserting will uncover inconsistencies in our table. */
101 assert ((s - opcodePTR->format) == 16 || (s - opcodePTR->format) == 32);
102 assert (opcodePTR->bin_opcode == bin);
104 decodeTablePTR->operMask = mask;
105 decodeTablePTR->operMasksRegisterBits = operandRegisterBits;
106 decodeTablePTR->opcodePTR = opcodePTR;
112 bytesRead += XGATE_TWO_BYTES;
113 status = read_memory (memaddr, buffer, XGATE_TWO_BYTES, info);
116 raw_code = buffer[0];
118 raw_code += buffer[1];
120 decodePTR = find_match (raw_code);
123 operMaskReg = decodePTR->operMasksRegisterBits;
124 (*info->fprintf_func)(info->stream, "%s", decodePTR->opcodePTR->name);
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))
131 (*info->fprintf_func)(info->stream, " R%x, CCR",
132 (raw_code >> 8) & 0x7);
134 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON_C_R))
136 (*info->fprintf_func)(info->stream, " CCR, R%x",
137 (raw_code >> 8) & 0x7);
139 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON_R_P))
141 (*info->fprintf_func)(info->stream, " R%x, PC",
142 (raw_code >> 8) & 0x7);
144 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_TRI))
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);
150 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IDR))
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);
158 else if (raw_code & 0x02)
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);
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);
171 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_DYA))
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,
178 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IDO5))
180 (*info->fprintf_func)(info->stream, " R%x, (R%x, #0x%x)",
181 (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7, raw_code & 0x1f);
183 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON))
185 operandOne = ripBits (&operMaskReg, 3, decodePTR->opcodePTR,
187 (*info->fprintf_func)(info->stream, " R%x", operandOne);
189 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_REL9))
191 /* If address is negative handle it accordingly. */
192 if (raw_code & XGATE_NINE_SIGNBIT)
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. */
201 relAddr = raw_code & 0xff;
202 relAddr = (relAddr << 1) + 2;
204 (*info->fprintf_func)(info->stream, " *%d", relAddr);
205 (*info->fprintf_func)(info->stream, " Abs* 0x");
206 (*info->print_address_func)(memaddr + relAddr, info);
208 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_REL10))
210 /* If address is negative handle it accordingly. */
211 if (raw_code & XGATE_TEN_SIGNBIT)
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. */
220 relAddr = raw_code & 0x1FF;
221 relAddr = (relAddr << 1) + 2;
223 (*info->fprintf_func)(info->stream, " *%d", relAddr);
224 (*info->fprintf_func)(info->stream, " Abs* 0x");
225 (*info->print_address_func)(memaddr + relAddr, info);
227 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM4))
229 (*info->fprintf_func)(info->stream, " R%x, #0x%02x",
230 (raw_code >> 8) & 0x7, (raw_code >> 4) & 0xF);
232 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM8))
234 if (macro_search (decodePTR->opcodePTR->name, previousOpName) &&
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;
246 strcpy (previousOpName, decodePTR->opcodePTR->name);
247 (*info->fprintf_func)(info->stream, " R%x, #0x%02x",
248 (raw_code >> 8) & 0x7, raw_code & 0xff);
251 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM3))
253 (*info->fprintf_func)(info->stream, " #0x%x",
254 (raw_code >> 8) & 0x7);
256 else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_INH))
262 (*info->fprintf_func)(info->stream, " unhandled mode %s",
263 opcodePTR->constraints);
265 perviousBin = raw_code;
269 (*info->fprintf_func)(info->stream,
270 " unable to find opcode match #0%x", raw_code);
277 print_insn_xgate (bfd_vma memaddr, struct disassemble_info* info)
279 return print_insn (memaddr, info);
283 read_memory (bfd_vma memaddr, bfd_byte* buffer, int size,
284 struct disassemble_info* info)
287 status = (*info->read_memory_func) (memaddr, buffer, size, info);
290 (*info->memory_error_func) (status, memaddr, info);
297 ripBits (unsigned int *operandBitsRemaining,
298 int numBitsRequested,
299 struct xgate_opcode *opcodePTR,
302 unsigned int currentBit;
306 for (operand = 0, numBitsFound = 0, currentBit = 1
307 << ((opcodePTR->size * 8) - 1);
308 (numBitsFound < numBitsRequested) && currentBit; currentBit >>= 1)
310 if (currentBit & *operandBitsRemaining)
312 *operandBitsRemaining &= ~(currentBit); /* Consume the current bit. */
313 operand <<= 1; /* Make room for our next bit. */
315 operand |= (currentBit & memory) > 0;
322 macro_search (char *currentName, char *lastName)
328 for (i = 0; i < xgate_num_opcodes; i++)
330 where = strstr (xgate_opcodes[i].constraints, lastName);
334 length = strlen (where);
338 where = strstr (xgate_opcodes[i].constraints, currentName);
341 length = strlen (where);
349 static struct decodeInfo *
350 find_match (unsigned int raw_code)
352 struct decodeInfo *decodeTablePTR = 0;
355 for (i = 0, decodeTablePTR = decodeTable; i < xgate_num_opcodes;
356 i++, decodeTablePTR++)
358 if ((raw_code & decodeTablePTR->operMask)
359 == decodeTablePTR->opcodePTR->bin_opcode)
361 /* Make sure we didn't run into a macro or alias. */
362 if (decodeTablePTR->opcodePTR->cycles_min != 0)
364 return decodeTablePTR;