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