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