1016e56d1Schristos /* xgate-dis.c -- Freescale XGATE disassembly
2*1424dfb3Schristos Copyright (C) 2009-2020 Free Software Foundation, Inc.
3016e56d1Schristos Written by Sean Keys (skeys@ipdatasys.com)
4016e56d1Schristos
5016e56d1Schristos This file is part of the GNU opcodes library.
6016e56d1Schristos
7016e56d1Schristos This library is free software; you can redistribute it and/or modify
8016e56d1Schristos it under the terms of the GNU General Public License as published by
9016e56d1Schristos the Free Software Foundation; either version 3, or (at your option)
10016e56d1Schristos any later version.
11016e56d1Schristos
12016e56d1Schristos It is distributed in the hope that it will be useful, but WITHOUT
13016e56d1Schristos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14016e56d1Schristos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15016e56d1Schristos License for more details.
16016e56d1Schristos
17016e56d1Schristos You should have received a copy of the GNU General Public License
18016e56d1Schristos along with this program; if not, write to the Free Software
19016e56d1Schristos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20016e56d1Schristos MA 02110-1301, USA. */
21016e56d1Schristos
22016e56d1Schristos #include "sysdep.h"
23016e56d1Schristos #include <assert.h>
2407163879Schristos #include "disassemble.h"
25016e56d1Schristos #include "opintl.h"
26016e56d1Schristos #include "libiberty.h"
27016e56d1Schristos #include "ansidecl.h"
28016e56d1Schristos #include "opcode/xgate.h"
29016e56d1Schristos
30016e56d1Schristos #define XGATE_TWO_BYTES 0x02
31016e56d1Schristos #define XGATE_NINE_BITS 0x1FF
32016e56d1Schristos #define XGATE_TEN_BITS 0x3FF
33016e56d1Schristos #define XGATE_NINE_SIGNBIT 0x100
34016e56d1Schristos #define XGATE_TEN_SIGNBIT 0x200
35016e56d1Schristos
36016e56d1Schristos /* Structures. */
37016e56d1Schristos struct decodeInfo
38016e56d1Schristos {
39016e56d1Schristos unsigned int operMask;
40016e56d1Schristos unsigned int operMasksRegisterBits;
41016e56d1Schristos struct xgate_opcode *opcodePTR;
42016e56d1Schristos };
43016e56d1Schristos
44016e56d1Schristos /* Prototypes for local functions. */
45016e56d1Schristos static int print_insn (bfd_vma, struct disassemble_info *);
46016e56d1Schristos static int read_memory (bfd_vma, bfd_byte*, int, struct disassemble_info *);
47016e56d1Schristos static int ripBits (unsigned int *, int,
48016e56d1Schristos struct xgate_opcode *, unsigned int);
49016e56d1Schristos static int macro_search (char *, char *);
50016e56d1Schristos static struct decodeInfo * find_match (unsigned int);
51016e56d1Schristos
52016e56d1Schristos /* Statics. */
53016e56d1Schristos static struct decodeInfo *decodeTable;
54016e56d1Schristos static int initialized;
55016e56d1Schristos static char previousOpName[10];
56016e56d1Schristos static unsigned int perviousBin;
57016e56d1Schristos
58016e56d1Schristos /* Disassemble one instruction at address 'memaddr'. Returns the number
59016e56d1Schristos of bytes used by that instruction. */
60016e56d1Schristos
61016e56d1Schristos static int
print_insn(bfd_vma memaddr,struct disassemble_info * info)62016e56d1Schristos print_insn (bfd_vma memaddr, struct disassemble_info* info)
63016e56d1Schristos {
64016e56d1Schristos int status;
65016e56d1Schristos unsigned int raw_code;
66016e56d1Schristos char *s = 0;
67016e56d1Schristos long bytesRead = 0;
68016e56d1Schristos int i = 0;
69016e56d1Schristos struct xgate_opcode *opcodePTR = (struct xgate_opcode*) xgate_opcodes;
70016e56d1Schristos struct decodeInfo *decodeTablePTR = 0;
71016e56d1Schristos struct decodeInfo *decodePTR = 0;
72016e56d1Schristos unsigned int operandRegisterBits = 0;
73016e56d1Schristos signed int relAddr = 0;
74016e56d1Schristos signed int operandOne = 0;
75016e56d1Schristos signed int operandTwo = 0;
76016e56d1Schristos bfd_byte buffer[4];
77016e56d1Schristos bfd_vma absAddress;
78016e56d1Schristos
79016e56d1Schristos unsigned int operMaskReg = 0;
80016e56d1Schristos /* Initialize our array of opcode masks and check them against our constant
81016e56d1Schristos table. */
82016e56d1Schristos if (!initialized)
83016e56d1Schristos {
84016e56d1Schristos decodeTable = xmalloc (sizeof (struct decodeInfo) * xgate_num_opcodes);
85016e56d1Schristos for (i = 0, decodeTablePTR = decodeTable; i < xgate_num_opcodes;
86016e56d1Schristos i++, decodeTablePTR++, opcodePTR++)
87016e56d1Schristos {
88016e56d1Schristos unsigned int bin = 0;
89016e56d1Schristos unsigned int mask = 0;
90016e56d1Schristos for (s = opcodePTR->format; *s; s++)
91016e56d1Schristos {
92016e56d1Schristos bin <<= 1;
93016e56d1Schristos mask <<= 1;
94016e56d1Schristos operandRegisterBits <<= 1;
95016e56d1Schristos bin |= (*s == '1');
96016e56d1Schristos mask |= (*s == '0' || *s == '1');
97016e56d1Schristos operandRegisterBits |= (*s == 'r');
98016e56d1Schristos }
99016e56d1Schristos /* Asserting will uncover inconsistencies in our table. */
100016e56d1Schristos assert ((s - opcodePTR->format) == 16 || (s - opcodePTR->format) == 32);
101016e56d1Schristos assert (opcodePTR->bin_opcode == bin);
102016e56d1Schristos
103016e56d1Schristos decodeTablePTR->operMask = mask;
104016e56d1Schristos decodeTablePTR->operMasksRegisterBits = operandRegisterBits;
105016e56d1Schristos decodeTablePTR->opcodePTR = opcodePTR;
106016e56d1Schristos }
107016e56d1Schristos initialized = 1;
108016e56d1Schristos }
109016e56d1Schristos
110016e56d1Schristos /* Read 16 bits. */
111016e56d1Schristos bytesRead += XGATE_TWO_BYTES;
112016e56d1Schristos status = read_memory (memaddr, buffer, XGATE_TWO_BYTES, info);
113016e56d1Schristos if (status == 0)
114016e56d1Schristos {
115016e56d1Schristos raw_code = buffer[0];
116016e56d1Schristos raw_code <<= 8;
117016e56d1Schristos raw_code += buffer[1];
118016e56d1Schristos
119016e56d1Schristos decodePTR = find_match (raw_code);
120016e56d1Schristos if (decodePTR)
121016e56d1Schristos {
122016e56d1Schristos operMaskReg = decodePTR->operMasksRegisterBits;
123016e56d1Schristos (*info->fprintf_func)(info->stream, "%s", decodePTR->opcodePTR->name);
124016e56d1Schristos
125016e56d1Schristos /* First we compare the shorthand format of the constraints. If we
126016e56d1Schristos still are unable to pinpoint the operands
127016e56d1Schristos we analyze the opcodes constraint string. */
1287af5a897Schristos if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON_R_C))
129016e56d1Schristos {
130016e56d1Schristos (*info->fprintf_func)(info->stream, " R%x, CCR",
131016e56d1Schristos (raw_code >> 8) & 0x7);
1327af5a897Schristos }
1337af5a897Schristos else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON_C_R))
1347af5a897Schristos {
135016e56d1Schristos (*info->fprintf_func)(info->stream, " CCR, R%x",
136016e56d1Schristos (raw_code >> 8) & 0x7);
1377af5a897Schristos }
1387af5a897Schristos else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON_R_P))
1397af5a897Schristos {
140016e56d1Schristos (*info->fprintf_func)(info->stream, " R%x, PC",
141016e56d1Schristos (raw_code >> 8) & 0x7);
1427af5a897Schristos }
1437af5a897Schristos else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_TRI))
144016e56d1Schristos {
145016e56d1Schristos (*info->fprintf_func)(info->stream, " R%x, R%x, R%x",
146016e56d1Schristos (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7,
147016e56d1Schristos (raw_code >> 2) & 0x7);
148016e56d1Schristos }
149016e56d1Schristos else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IDR))
150016e56d1Schristos {
151016e56d1Schristos if (raw_code & 0x01)
152016e56d1Schristos {
153016e56d1Schristos (*info->fprintf_func)(info->stream, " R%x, (R%x, R%x+)",
154016e56d1Schristos (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7,
155016e56d1Schristos (raw_code >> 2) & 0x7);
156016e56d1Schristos }
157016e56d1Schristos else if (raw_code & 0x02)
158016e56d1Schristos {
159016e56d1Schristos (*info->fprintf_func)(info->stream, " R%x, (R%x, -R%x)",
160016e56d1Schristos (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7,
161016e56d1Schristos (raw_code >> 2) & 0x7);
162016e56d1Schristos }
163016e56d1Schristos else
164016e56d1Schristos {
165016e56d1Schristos (*info->fprintf_func)(info->stream, " R%x, (R%x, R%x)",
166016e56d1Schristos (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7,
167016e56d1Schristos (raw_code >> 2) & 0x7);
168016e56d1Schristos }
169016e56d1Schristos }
1707af5a897Schristos else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_DYA))
171016e56d1Schristos {
172*1424dfb3Schristos operandOne = ripBits (&operMaskReg, 3, decodePTR->opcodePTR, raw_code);
173*1424dfb3Schristos operandTwo = ripBits (&operMaskReg, 3, decodePTR->opcodePTR, raw_code);
174016e56d1Schristos ( *info->fprintf_func)(info->stream, " R%x, R%x", operandOne,
175016e56d1Schristos operandTwo);
176016e56d1Schristos }
1777af5a897Schristos else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IDO5))
178016e56d1Schristos {
179016e56d1Schristos (*info->fprintf_func)(info->stream, " R%x, (R%x, #0x%x)",
180016e56d1Schristos (raw_code >> 8) & 0x7, (raw_code >> 5) & 0x7, raw_code & 0x1f);
1817af5a897Schristos }
1827af5a897Schristos else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_MON))
1837af5a897Schristos {
184016e56d1Schristos operandOne = ripBits (&operMaskReg, 3, decodePTR->opcodePTR,
185016e56d1Schristos raw_code);
186016e56d1Schristos (*info->fprintf_func)(info->stream, " R%x", operandOne);
1877af5a897Schristos }
1887af5a897Schristos else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_REL9))
189016e56d1Schristos {
190016e56d1Schristos /* If address is negative handle it accordingly. */
191016e56d1Schristos if (raw_code & XGATE_NINE_SIGNBIT)
192016e56d1Schristos {
193016e56d1Schristos relAddr = XGATE_NINE_BITS >> 1; /* Clip sign bit. */
194016e56d1Schristos relAddr = ~relAddr; /* Make signed. */
195016e56d1Schristos relAddr |= (raw_code & 0xFF) + 1; /* Apply our value. */
196*1424dfb3Schristos relAddr *= 2; /* Multiply by two as per processor docs. */
197016e56d1Schristos }
198016e56d1Schristos else
199016e56d1Schristos {
200016e56d1Schristos relAddr = raw_code & 0xff;
201*1424dfb3Schristos relAddr = relAddr * 2 + 2;
202016e56d1Schristos }
203016e56d1Schristos (*info->fprintf_func)(info->stream, " *%d", relAddr);
204016e56d1Schristos (*info->fprintf_func)(info->stream, " Abs* 0x");
205016e56d1Schristos (*info->print_address_func)(memaddr + relAddr, info);
206016e56d1Schristos }
207016e56d1Schristos else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_REL10))
208016e56d1Schristos {
209016e56d1Schristos /* If address is negative handle it accordingly. */
210016e56d1Schristos if (raw_code & XGATE_TEN_SIGNBIT)
211016e56d1Schristos {
212016e56d1Schristos relAddr = XGATE_TEN_BITS >> 1; /* Clip sign bit. */
213016e56d1Schristos relAddr = ~relAddr; /* Make signed. */
214016e56d1Schristos relAddr |= (raw_code & 0x1FF) + 1; /* Apply our value. */
215*1424dfb3Schristos relAddr *= 2; /* Multiply by two as per processor docs. */
216016e56d1Schristos }
217016e56d1Schristos else
218016e56d1Schristos {
219016e56d1Schristos relAddr = raw_code & 0x1FF;
220*1424dfb3Schristos relAddr = relAddr * 2 + 2;
221016e56d1Schristos }
222016e56d1Schristos (*info->fprintf_func)(info->stream, " *%d", relAddr);
223016e56d1Schristos (*info->fprintf_func)(info->stream, " Abs* 0x");
224016e56d1Schristos (*info->print_address_func)(memaddr + relAddr, info);
225016e56d1Schristos }
2267af5a897Schristos else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM4))
227016e56d1Schristos {
228016e56d1Schristos (*info->fprintf_func)(info->stream, " R%x, #0x%02x",
229016e56d1Schristos (raw_code >> 8) & 0x7, (raw_code >> 4) & 0xF);
230016e56d1Schristos }
231016e56d1Schristos else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM8))
232016e56d1Schristos {
233016e56d1Schristos if (macro_search (decodePTR->opcodePTR->name, previousOpName) &&
234016e56d1Schristos previousOpName[0])
235016e56d1Schristos {
236016e56d1Schristos absAddress = (0xFF & raw_code) << 8;
237016e56d1Schristos absAddress |= perviousBin & 0xFF;
238016e56d1Schristos (*info->fprintf_func)(info->stream, " R%x, #0x%02x Abs* 0x",
239016e56d1Schristos (raw_code >> 8) & 0x7, raw_code & 0xff);
240016e56d1Schristos (*info->print_address_func)(absAddress, info);
241016e56d1Schristos previousOpName[0] = 0;
242016e56d1Schristos }
243016e56d1Schristos else
244016e56d1Schristos {
245016e56d1Schristos strcpy (previousOpName, decodePTR->opcodePTR->name);
246016e56d1Schristos (*info->fprintf_func)(info->stream, " R%x, #0x%02x",
247016e56d1Schristos (raw_code >> 8) & 0x7, raw_code & 0xff);
248016e56d1Schristos }
249016e56d1Schristos }
2507af5a897Schristos else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_IMM3))
251016e56d1Schristos {
252016e56d1Schristos (*info->fprintf_func)(info->stream, " #0x%x",
253016e56d1Schristos (raw_code >> 8) & 0x7);
2547af5a897Schristos }
2557af5a897Schristos else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_INH))
2567af5a897Schristos {
2577af5a897Schristos }
2587af5a897Schristos else
2597af5a897Schristos {
2607af5a897Schristos (*info->fprintf_func)(info->stream, " unhandled mode %s",
261*1424dfb3Schristos decodePTR->opcodePTR->constraints);
262016e56d1Schristos }
263016e56d1Schristos perviousBin = raw_code;
264016e56d1Schristos }
265016e56d1Schristos else
266016e56d1Schristos {
267016e56d1Schristos (*info->fprintf_func)(info->stream,
268016e56d1Schristos " unable to find opcode match #0%x", raw_code);
269016e56d1Schristos }
270016e56d1Schristos }
271016e56d1Schristos return bytesRead;
272016e56d1Schristos }
273016e56d1Schristos
274016e56d1Schristos int
print_insn_xgate(bfd_vma memaddr,struct disassemble_info * info)275016e56d1Schristos print_insn_xgate (bfd_vma memaddr, struct disassemble_info* info)
276016e56d1Schristos {
277016e56d1Schristos return print_insn (memaddr, info);
278016e56d1Schristos }
279016e56d1Schristos
280016e56d1Schristos static int
read_memory(bfd_vma memaddr,bfd_byte * buffer,int size,struct disassemble_info * info)281016e56d1Schristos read_memory (bfd_vma memaddr, bfd_byte* buffer, int size,
282016e56d1Schristos struct disassemble_info* info)
283016e56d1Schristos {
284016e56d1Schristos int status;
285016e56d1Schristos status = (*info->read_memory_func) (memaddr, buffer, size, info);
286016e56d1Schristos if (status != 0)
287016e56d1Schristos {
288016e56d1Schristos (*info->memory_error_func) (status, memaddr, info);
289016e56d1Schristos return -1;
290016e56d1Schristos }
291016e56d1Schristos return 0;
292016e56d1Schristos }
293016e56d1Schristos
294016e56d1Schristos static int
ripBits(unsigned int * operandBitsRemaining,int numBitsRequested,struct xgate_opcode * opcodePTR,unsigned int memory)295016e56d1Schristos ripBits (unsigned int *operandBitsRemaining,
296016e56d1Schristos int numBitsRequested,
297016e56d1Schristos struct xgate_opcode *opcodePTR,
298016e56d1Schristos unsigned int memory)
299016e56d1Schristos {
300016e56d1Schristos unsigned int currentBit;
301*1424dfb3Schristos unsigned int operand = 0;
302016e56d1Schristos int numBitsFound;
303016e56d1Schristos
304*1424dfb3Schristos for (numBitsFound = 0, currentBit = 1u << ((opcodePTR->size * 8) - 1);
305*1424dfb3Schristos numBitsFound < numBitsRequested && currentBit != 0;
306*1424dfb3Schristos currentBit >>= 1)
307016e56d1Schristos {
308016e56d1Schristos if (currentBit & *operandBitsRemaining)
309016e56d1Schristos {
310016e56d1Schristos *operandBitsRemaining &= ~(currentBit); /* Consume the current bit. */
311016e56d1Schristos operand <<= 1; /* Make room for our next bit. */
312016e56d1Schristos numBitsFound++;
313016e56d1Schristos operand |= (currentBit & memory) > 0;
314016e56d1Schristos }
315016e56d1Schristos }
316016e56d1Schristos return operand;
317016e56d1Schristos }
318016e56d1Schristos
319016e56d1Schristos static int
macro_search(char * currentName,char * lastName)320016e56d1Schristos macro_search (char *currentName, char *lastName)
321016e56d1Schristos {
322016e56d1Schristos int i;
323016e56d1Schristos int length = 0;
324016e56d1Schristos char *where;
325016e56d1Schristos
326016e56d1Schristos for (i = 0; i < xgate_num_opcodes; i++)
327016e56d1Schristos {
328016e56d1Schristos where = strstr (xgate_opcodes[i].constraints, lastName);
329016e56d1Schristos
330016e56d1Schristos if (where)
331016e56d1Schristos {
332016e56d1Schristos length = strlen (where);
333016e56d1Schristos }
334016e56d1Schristos if (length)
335016e56d1Schristos {
336016e56d1Schristos where = strstr (xgate_opcodes[i].constraints, currentName);
337016e56d1Schristos if (where)
338016e56d1Schristos {
339016e56d1Schristos length = strlen (where);
340016e56d1Schristos return 1;
341016e56d1Schristos }
342016e56d1Schristos }
343016e56d1Schristos }
344016e56d1Schristos return 0;
345016e56d1Schristos }
346016e56d1Schristos
347016e56d1Schristos static struct decodeInfo *
find_match(unsigned int raw_code)348016e56d1Schristos find_match (unsigned int raw_code)
349016e56d1Schristos {
350016e56d1Schristos struct decodeInfo *decodeTablePTR = 0;
351016e56d1Schristos int i;
352016e56d1Schristos
353016e56d1Schristos for (i = 0, decodeTablePTR = decodeTable; i < xgate_num_opcodes;
354016e56d1Schristos i++, decodeTablePTR++)
355016e56d1Schristos {
356016e56d1Schristos if ((raw_code & decodeTablePTR->operMask)
357016e56d1Schristos == decodeTablePTR->opcodePTR->bin_opcode)
358016e56d1Schristos {
359016e56d1Schristos /* Make sure we didn't run into a macro or alias. */
360016e56d1Schristos if (decodeTablePTR->opcodePTR->cycles_min != 0)
361016e56d1Schristos {
362016e56d1Schristos return decodeTablePTR;
363016e56d1Schristos break;
364016e56d1Schristos }
365016e56d1Schristos else
366016e56d1Schristos continue;
367016e56d1Schristos }
368016e56d1Schristos }
369016e56d1Schristos return 0;
370016e56d1Schristos }
371