arc-ext.c revision 1.6 1 1.6 christos /* ARC target-dependent stuff. Extension structure access functions
2 1.6 christos Copyright (C) 1995-2016 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos This file is part of libopcodes.
5 1.1 christos
6 1.1 christos This library is free software; you can redistribute it and/or modify
7 1.1 christos it under the terms of the GNU General Public License as published by
8 1.1 christos the Free Software Foundation; either version 3, or (at your option)
9 1.1 christos any later version.
10 1.1 christos
11 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT
12 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 1.1 christos License for more details.
15 1.1 christos
16 1.1 christos You should have received a copy of the GNU General Public License
17 1.1 christos along with this program; if not, write to the Free Software
18 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 1.1 christos MA 02110-1301, USA. */
20 1.1 christos
21 1.1 christos #include "sysdep.h"
22 1.1 christos #include <stdlib.h>
23 1.1 christos #include <stdio.h>
24 1.6 christos
25 1.1 christos #include "bfd.h"
26 1.1 christos #include "arc-ext.h"
27 1.6 christos #include "elf/arc.h"
28 1.1 christos #include "libiberty.h"
29 1.1 christos
30 1.6 christos /* This module provides support for extensions to the ARC processor
31 1.6 christos architecture. */
32 1.1 christos
33 1.1 christos
34 1.6 christos /* Local constants. */
35 1.1 christos
36 1.6 christos #define FIRST_EXTENSION_CORE_REGISTER 32
37 1.6 christos #define LAST_EXTENSION_CORE_REGISTER 59
38 1.6 christos #define FIRST_EXTENSION_CONDITION_CODE 0x10
39 1.6 christos #define LAST_EXTENSION_CONDITION_CODE 0x1f
40 1.1 christos
41 1.6 christos #define NUM_EXT_CORE \
42 1.6 christos (LAST_EXTENSION_CORE_REGISTER - FIRST_EXTENSION_CORE_REGISTER + 1)
43 1.6 christos #define NUM_EXT_COND \
44 1.6 christos (LAST_EXTENSION_CONDITION_CODE - FIRST_EXTENSION_CONDITION_CODE + 1)
45 1.6 christos #define INST_HASH_BITS 6
46 1.6 christos #define INST_HASH_SIZE (1 << INST_HASH_BITS)
47 1.6 christos #define INST_HASH_MASK (INST_HASH_SIZE - 1)
48 1.1 christos
49 1.1 christos
50 1.6 christos /* Local types. */
51 1.1 christos
52 1.6 christos /* These types define the information stored in the table. */
53 1.1 christos
54 1.6 christos struct ExtAuxRegister
55 1.1 christos {
56 1.6 christos long address;
57 1.6 christos char * name;
58 1.6 christos struct ExtAuxRegister * next;
59 1.6 christos };
60 1.1 christos
61 1.6 christos struct ExtCoreRegister
62 1.6 christos {
63 1.6 christos short number;
64 1.6 christos enum ExtReadWrite rw;
65 1.6 christos char * name;
66 1.6 christos };
67 1.1 christos
68 1.6 christos struct arcExtMap
69 1.6 christos {
70 1.6 christos struct ExtAuxRegister* auxRegisters;
71 1.6 christos struct ExtInstruction* instructions[INST_HASH_SIZE];
72 1.6 christos struct ExtCoreRegister coreRegisters[NUM_EXT_CORE];
73 1.6 christos char * condCodes[NUM_EXT_COND];
74 1.6 christos };
75 1.1 christos
76 1.1 christos
77 1.6 christos /* Local data. */
78 1.1 christos
79 1.6 christos /* Extension table. */
80 1.6 christos static struct arcExtMap arc_extension_map;
81 1.1 christos
82 1.1 christos
83 1.6 christos /* Local macros. */
84 1.1 christos
85 1.6 christos /* A hash function used to map instructions into the table. */
86 1.6 christos #define INST_HASH(MAJOR, MINOR) ((((MAJOR) << 3) ^ (MINOR)) & INST_HASH_MASK)
87 1.1 christos
88 1.1 christos
89 1.6 christos /* Local functions. */
90 1.1 christos
91 1.6 christos static void
92 1.6 christos create_map (unsigned char *block,
93 1.6 christos unsigned long length)
94 1.1 christos {
95 1.6 christos unsigned char *p = block;
96 1.1 christos
97 1.1 christos while (p && p < (block + length))
98 1.1 christos {
99 1.1 christos /* p[0] == length of record
100 1.1 christos p[1] == type of record
101 1.1 christos For instructions:
102 1.1 christos p[2] = opcode
103 1.1 christos p[3] = minor opcode (if opcode == 3)
104 1.1 christos p[4] = flags
105 1.1 christos p[5]+ = name
106 1.1 christos For core regs and condition codes:
107 1.1 christos p[2] = value
108 1.1 christos p[3]+ = name
109 1.6 christos For auxiliary regs:
110 1.1 christos p[2..5] = value
111 1.1 christos p[6]+ = name
112 1.6 christos (value is p[2]<<24|p[3]<<16|p[4]<<8|p[5]). */
113 1.1 christos
114 1.6 christos /* The sequence of records is temrinated by an "empty"
115 1.6 christos record. */
116 1.1 christos if (p[0] == 0)
117 1.6 christos break;
118 1.1 christos
119 1.1 christos switch (p[1])
120 1.1 christos {
121 1.1 christos case EXT_INSTRUCTION:
122 1.1 christos {
123 1.6 christos struct ExtInstruction *insn = XNEW (struct ExtInstruction);
124 1.6 christos int major = p[2];
125 1.6 christos int minor = p[3];
126 1.6 christos struct ExtInstruction **bucket =
127 1.6 christos &arc_extension_map.instructions[INST_HASH (major, minor)];
128 1.6 christos
129 1.6 christos insn->name = xstrdup ((char *) (p + 5));
130 1.6 christos insn->major = major;
131 1.6 christos insn->minor = minor;
132 1.6 christos insn->flags = p[4];
133 1.6 christos insn->next = *bucket;
134 1.6 christos insn->suffix = 0;
135 1.6 christos insn->syntax = 0;
136 1.6 christos insn->modsyn = 0;
137 1.6 christos *bucket = insn;
138 1.6 christos break;
139 1.1 christos }
140 1.1 christos
141 1.1 christos case EXT_CORE_REGISTER:
142 1.1 christos {
143 1.6 christos unsigned char number = p[2];
144 1.6 christos char* name = (char *) (p + 3);
145 1.6 christos
146 1.6 christos arc_extension_map.
147 1.6 christos coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].number
148 1.6 christos = number;
149 1.6 christos arc_extension_map.
150 1.6 christos coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].rw
151 1.6 christos = REG_READWRITE;
152 1.6 christos arc_extension_map.
153 1.6 christos coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].name
154 1.6 christos = xstrdup (name);
155 1.6 christos break;
156 1.6 christos }
157 1.1 christos
158 1.6 christos case EXT_LONG_CORE_REGISTER:
159 1.6 christos {
160 1.6 christos unsigned char number = p[2];
161 1.6 christos char* name = (char *) (p + 7);
162 1.6 christos enum ExtReadWrite rw = p[6];
163 1.6 christos
164 1.6 christos arc_extension_map.
165 1.6 christos coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].number
166 1.6 christos = number;
167 1.6 christos arc_extension_map.
168 1.6 christos coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].rw
169 1.6 christos = rw;
170 1.6 christos arc_extension_map.
171 1.6 christos coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].name
172 1.6 christos = xstrdup (name);
173 1.1 christos }
174 1.1 christos
175 1.1 christos case EXT_COND_CODE:
176 1.1 christos {
177 1.6 christos char *cc_name = xstrdup ((char *) (p + 3));
178 1.6 christos
179 1.6 christos arc_extension_map.
180 1.6 christos condCodes[p[2] - FIRST_EXTENSION_CONDITION_CODE]
181 1.6 christos = cc_name;
182 1.6 christos break;
183 1.1 christos }
184 1.1 christos
185 1.1 christos case EXT_AUX_REGISTER:
186 1.1 christos {
187 1.6 christos /* Trickier -- need to store linked list of these. */
188 1.6 christos struct ExtAuxRegister *newAuxRegister
189 1.6 christos = XNEW (struct ExtAuxRegister);
190 1.6 christos char *aux_name = xstrdup ((char *) (p + 6));
191 1.1 christos
192 1.1 christos newAuxRegister->name = aux_name;
193 1.6 christos newAuxRegister->address = (p[2] << 24) | (p[3] << 16)
194 1.6 christos | (p[4] << 8) | p[5];
195 1.1 christos newAuxRegister->next = arc_extension_map.auxRegisters;
196 1.1 christos arc_extension_map.auxRegisters = newAuxRegister;
197 1.6 christos break;
198 1.1 christos }
199 1.6 christos
200 1.6 christos default:
201 1.1 christos break;
202 1.6 christos }
203 1.6 christos
204 1.6 christos p += p[0]; /* Move on to next record. */
205 1.6 christos }
206 1.6 christos }
207 1.6 christos
208 1.6 christos
209 1.6 christos /* Free memory that has been allocated for the extensions. */
210 1.6 christos
211 1.6 christos static void
212 1.6 christos destroy_map (void)
213 1.6 christos {
214 1.6 christos struct ExtAuxRegister *r;
215 1.6 christos unsigned int i;
216 1.6 christos
217 1.6 christos /* Free auxiliary registers. */
218 1.6 christos r = arc_extension_map.auxRegisters;
219 1.6 christos while (r)
220 1.6 christos {
221 1.6 christos /* N.B. after r has been freed, r->next is invalid! */
222 1.6 christos struct ExtAuxRegister* next = r->next;
223 1.6 christos
224 1.6 christos free (r->name);
225 1.6 christos free (r);
226 1.6 christos r = next;
227 1.6 christos }
228 1.6 christos
229 1.6 christos /* Free instructions. */
230 1.6 christos for (i = 0; i < INST_HASH_SIZE; i++)
231 1.6 christos {
232 1.6 christos struct ExtInstruction *insn = arc_extension_map.instructions[i];
233 1.6 christos
234 1.6 christos while (insn)
235 1.6 christos {
236 1.6 christos /* N.B. after insn has been freed, insn->next is invalid! */
237 1.6 christos struct ExtInstruction *next = insn->next;
238 1.6 christos
239 1.6 christos free (insn->name);
240 1.6 christos free (insn);
241 1.6 christos insn = next;
242 1.6 christos }
243 1.6 christos }
244 1.6 christos
245 1.6 christos /* Free core registers. */
246 1.6 christos for (i = 0; i < NUM_EXT_CORE; i++)
247 1.6 christos {
248 1.6 christos if (arc_extension_map.coreRegisters[i].name)
249 1.6 christos free (arc_extension_map.coreRegisters[i].name);
250 1.6 christos }
251 1.6 christos
252 1.6 christos /* Free condition codes. */
253 1.6 christos for (i = 0; i < NUM_EXT_COND; i++)
254 1.6 christos {
255 1.6 christos if (arc_extension_map.condCodes[i])
256 1.6 christos free (arc_extension_map.condCodes[i]);
257 1.6 christos }
258 1.6 christos
259 1.6 christos memset (&arc_extension_map, 0, sizeof (arc_extension_map));
260 1.6 christos }
261 1.6 christos
262 1.6 christos
263 1.6 christos static const char *
264 1.6 christos ExtReadWrite_image (enum ExtReadWrite val)
265 1.6 christos {
266 1.6 christos switch (val)
267 1.6 christos {
268 1.6 christos case REG_INVALID : return "INVALID";
269 1.6 christos case REG_READ : return "RO";
270 1.6 christos case REG_WRITE : return "WO";
271 1.6 christos case REG_READWRITE: return "R/W";
272 1.6 christos default : return "???";
273 1.6 christos }
274 1.6 christos }
275 1.6 christos
276 1.6 christos
277 1.6 christos /* Externally visible functions. */
278 1.6 christos
279 1.6 christos /* Get the name of an extension instruction. */
280 1.6 christos
281 1.6 christos const extInstruction_t *
282 1.6 christos arcExtMap_insn (int opcode, int insn)
283 1.6 christos {
284 1.6 christos /* Here the following tasks need to be done. First of all, the
285 1.6 christos opcode stored in the Extension Map is the real opcode. However,
286 1.6 christos the subopcode stored in the instruction to be disassembled is
287 1.6 christos mangled. We pass (in minor opcode), the instruction word. Here
288 1.6 christos we will un-mangle it and get the real subopcode which we can look
289 1.6 christos for in the Extension Map. This function is used both for the
290 1.6 christos ARCTangent and the ARCompact, so we would also need some sort of
291 1.6 christos a way to distinguish between the two architectures. This is
292 1.6 christos because the ARCTangent does not do any of this mangling so we
293 1.6 christos have no issues there. */
294 1.6 christos
295 1.6 christos /* If P[22:23] is 0 or 2 then un-mangle using iiiiiI. If it is 1
296 1.6 christos then use iiiiIi. Now, if P is 3 then check M[5:5] and if it is 0
297 1.6 christos then un-mangle using iiiiiI else iiiiii. */
298 1.6 christos
299 1.6 christos unsigned char minor;
300 1.6 christos extInstruction_t *temp;
301 1.6 christos
302 1.6 christos /* 16-bit instructions. */
303 1.6 christos if (0x08 <= opcode && opcode <= 0x0b)
304 1.6 christos {
305 1.6 christos unsigned char b, c, i;
306 1.6 christos
307 1.6 christos b = (insn & 0x0700) >> 8;
308 1.6 christos c = (insn & 0x00e0) >> 5;
309 1.6 christos i = (insn & 0x001f);
310 1.6 christos
311 1.6 christos if (i)
312 1.6 christos minor = i;
313 1.6 christos else
314 1.6 christos minor = (c == 0x07) ? b : c;
315 1.6 christos }
316 1.6 christos /* 32-bit instructions. */
317 1.6 christos else
318 1.6 christos {
319 1.6 christos unsigned char I, A, B;
320 1.6 christos
321 1.6 christos I = (insn & 0x003f0000) >> 16;
322 1.6 christos A = (insn & 0x0000003f);
323 1.6 christos B = ((insn & 0x07000000) >> 24) | ((insn & 0x00007000) >> 9);
324 1.1 christos
325 1.6 christos if (I != 0x2f)
326 1.6 christos {
327 1.6 christos #ifndef UNMANGLED
328 1.6 christos switch (P)
329 1.6 christos {
330 1.6 christos case 3:
331 1.6 christos if (M)
332 1.6 christos {
333 1.6 christos minor = I;
334 1.6 christos break;
335 1.6 christos }
336 1.6 christos case 0:
337 1.6 christos case 2:
338 1.6 christos minor = (I >> 1) | ((I & 0x1) << 5);
339 1.6 christos break;
340 1.6 christos case 1:
341 1.6 christos minor = (I >> 1) | (I & 0x1) | ((I & 0x2) << 4);
342 1.6 christos }
343 1.6 christos #else
344 1.6 christos minor = I;
345 1.6 christos #endif
346 1.6 christos }
347 1.6 christos else
348 1.6 christos {
349 1.6 christos if (A != 0x3f)
350 1.6 christos minor = A;
351 1.6 christos else
352 1.6 christos minor = B;
353 1.6 christos }
354 1.6 christos }
355 1.1 christos
356 1.6 christos temp = arc_extension_map.instructions[INST_HASH (opcode, minor)];
357 1.6 christos while (temp)
358 1.6 christos {
359 1.6 christos if ((temp->major == opcode) && (temp->minor == minor))
360 1.6 christos {
361 1.6 christos return temp;
362 1.1 christos }
363 1.6 christos temp = temp->next;
364 1.1 christos }
365 1.1 christos
366 1.6 christos return NULL;
367 1.6 christos }
368 1.6 christos
369 1.6 christos /* Get the name of an extension core register. */
370 1.6 christos
371 1.6 christos const char *
372 1.6 christos arcExtMap_coreRegName (int regnum)
373 1.6 christos {
374 1.6 christos if (regnum < FIRST_EXTENSION_CORE_REGISTER
375 1.6 christos || regnum > LAST_EXTENSION_CORE_REGISTER)
376 1.6 christos return NULL;
377 1.6 christos return arc_extension_map.
378 1.6 christos coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].name;
379 1.6 christos }
380 1.6 christos
381 1.6 christos /* Get the access mode of an extension core register. */
382 1.6 christos
383 1.6 christos enum ExtReadWrite
384 1.6 christos arcExtMap_coreReadWrite (int regnum)
385 1.6 christos {
386 1.6 christos if (regnum < FIRST_EXTENSION_CORE_REGISTER
387 1.6 christos || regnum > LAST_EXTENSION_CORE_REGISTER)
388 1.6 christos return REG_INVALID;
389 1.6 christos return arc_extension_map.
390 1.6 christos coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].rw;
391 1.6 christos }
392 1.6 christos
393 1.6 christos /* Get the name of an extension condition code. */
394 1.6 christos
395 1.6 christos const char *
396 1.6 christos arcExtMap_condCodeName (int code)
397 1.6 christos {
398 1.6 christos if (code < FIRST_EXTENSION_CONDITION_CODE
399 1.6 christos || code > LAST_EXTENSION_CONDITION_CODE)
400 1.6 christos return NULL;
401 1.6 christos return arc_extension_map.
402 1.6 christos condCodes[code - FIRST_EXTENSION_CONDITION_CODE];
403 1.1 christos }
404 1.1 christos
405 1.6 christos /* Get the name of an extension auxiliary register. */
406 1.6 christos
407 1.6 christos const char *
408 1.6 christos arcExtMap_auxRegName (long address)
409 1.6 christos {
410 1.6 christos /* Walk the list of auxiliary register names and find the name. */
411 1.6 christos struct ExtAuxRegister *r;
412 1.6 christos
413 1.6 christos for (r = arc_extension_map.auxRegisters; r; r = r->next)
414 1.6 christos {
415 1.6 christos if (r->address == address)
416 1.6 christos return (const char *)r->name;
417 1.6 christos }
418 1.6 christos return NULL;
419 1.6 christos }
420 1.6 christos
421 1.6 christos /* Load extensions described in .arcextmap and
422 1.6 christos .gnu.linkonce.arcextmap.* ELF section. */
423 1.1 christos
424 1.1 christos void
425 1.6 christos build_ARC_extmap (bfd *text_bfd)
426 1.1 christos {
427 1.6 christos asection *sect;
428 1.1 christos
429 1.6 christos /* The map is built each time gdb loads an executable file - so free
430 1.6 christos any existing map, as the map defined by the new file may differ
431 1.6 christos from the old. */
432 1.6 christos destroy_map ();
433 1.6 christos
434 1.6 christos for (sect = text_bfd->sections; sect != NULL; sect = sect->next)
435 1.6 christos if (!strncmp (sect->name,
436 1.6 christos ".gnu.linkonce.arcextmap.",
437 1.6 christos sizeof (".gnu.linkonce.arcextmap.") - 1)
438 1.6 christos || !strcmp (sect->name,".arcextmap"))
439 1.1 christos {
440 1.6 christos bfd_size_type count = bfd_get_section_size (sect);
441 1.6 christos unsigned char* buffer = xmalloc (count);
442 1.6 christos
443 1.6 christos if (buffer)
444 1.6 christos {
445 1.6 christos if (bfd_get_section_contents (text_bfd, sect, buffer, 0, count))
446 1.6 christos create_map (buffer, count);
447 1.6 christos free (buffer);
448 1.6 christos }
449 1.1 christos }
450 1.1 christos }
451 1.6 christos
452 1.6 christos /* Debug function used to dump the ARC information fount in arcextmap
453 1.6 christos sections. */
454 1.6 christos
455 1.6 christos void
456 1.6 christos dump_ARC_extmap (void)
457 1.6 christos {
458 1.6 christos struct ExtAuxRegister *r;
459 1.6 christos int i;
460 1.6 christos
461 1.6 christos r = arc_extension_map.auxRegisters;
462 1.6 christos
463 1.6 christos while (r)
464 1.6 christos {
465 1.6 christos printf ("AUX : %s %ld\n", r->name, r->address);
466 1.6 christos r = r->next;
467 1.6 christos }
468 1.6 christos
469 1.6 christos for (i = 0; i < INST_HASH_SIZE; i++)
470 1.6 christos {
471 1.6 christos struct ExtInstruction *insn;
472 1.6 christos
473 1.6 christos for (insn = arc_extension_map.instructions[i];
474 1.6 christos insn != NULL; insn = insn->next)
475 1.6 christos {
476 1.6 christos printf ("INST: 0x%02x 0x%02x ", insn->major, insn->minor);
477 1.6 christos switch (insn->flags & ARC_SYNTAX_MASK)
478 1.6 christos {
479 1.6 christos case ARC_SYNTAX_2OP:
480 1.6 christos printf ("SYNTAX_2OP");
481 1.6 christos break;
482 1.6 christos case ARC_SYNTAX_3OP:
483 1.6 christos printf ("SYNTAX_3OP");
484 1.6 christos break;
485 1.6 christos case ARC_SYNTAX_1OP:
486 1.6 christos printf ("SYNTAX_1OP");
487 1.6 christos break;
488 1.6 christos case ARC_SYNTAX_NOP:
489 1.6 christos printf ("SYNTAX_NOP");
490 1.6 christos break;
491 1.6 christos default:
492 1.6 christos printf ("SYNTAX_UNK");
493 1.6 christos break;
494 1.6 christos }
495 1.6 christos
496 1.6 christos if (insn->flags & 0x10)
497 1.6 christos printf ("|MODIFIER");
498 1.6 christos
499 1.6 christos printf (" %s\n", insn->name);
500 1.6 christos }
501 1.6 christos }
502 1.6 christos
503 1.6 christos for (i = 0; i < NUM_EXT_CORE; i++)
504 1.6 christos {
505 1.6 christos struct ExtCoreRegister reg = arc_extension_map.coreRegisters[i];
506 1.6 christos
507 1.6 christos if (reg.name)
508 1.6 christos printf ("CORE: 0x%04x %s %s\n", reg.number,
509 1.6 christos ExtReadWrite_image (reg.rw),
510 1.6 christos reg.name);
511 1.6 christos }
512 1.6 christos
513 1.6 christos for (i = 0; i < NUM_EXT_COND; i++)
514 1.6 christos if (arc_extension_map.condCodes[i])
515 1.6 christos printf ("COND: %s\n", arc_extension_map.condCodes[i]);
516 1.6 christos }
517 1.6 christos
518 1.6 christos /* For a given extension instruction generate the equivalent arc
519 1.6 christos opcode structure. */
520 1.6 christos
521 1.6 christos struct arc_opcode *
522 1.6 christos arcExtMap_genOpcode (const extInstruction_t *einsn,
523 1.6 christos unsigned arc_target,
524 1.6 christos const char **errmsg)
525 1.6 christos {
526 1.6 christos struct arc_opcode *q, *arc_ext_opcodes = NULL;
527 1.6 christos const unsigned char *lflags_f;
528 1.6 christos const unsigned char *lflags_ccf;
529 1.6 christos int count;
530 1.6 christos
531 1.6 christos /* Check for the class to see how many instructions we generate. */
532 1.6 christos switch (einsn->flags & ARC_SYNTAX_MASK)
533 1.6 christos {
534 1.6 christos case ARC_SYNTAX_3OP:
535 1.6 christos count = (einsn->modsyn & ARC_OP1_MUST_BE_IMM) ? 10 : 20;
536 1.6 christos break;
537 1.6 christos case ARC_SYNTAX_2OP:
538 1.6 christos count = (einsn->flags & 0x10) ? 7 : 6;
539 1.6 christos break;
540 1.6 christos case ARC_SYNTAX_1OP:
541 1.6 christos count = 3;
542 1.6 christos break;
543 1.6 christos case ARC_SYNTAX_NOP:
544 1.6 christos count = 1;
545 1.6 christos break;
546 1.6 christos default:
547 1.6 christos count = 0;
548 1.6 christos break;
549 1.6 christos }
550 1.6 christos
551 1.6 christos /* Allocate memory. */
552 1.6 christos arc_ext_opcodes = (struct arc_opcode *)
553 1.6 christos xmalloc ((count + 1) * sizeof (*arc_ext_opcodes));
554 1.6 christos
555 1.6 christos if (arc_ext_opcodes == NULL)
556 1.6 christos {
557 1.6 christos *errmsg = "Virtual memory exhausted";
558 1.6 christos return NULL;
559 1.6 christos }
560 1.6 christos
561 1.6 christos /* Generate the patterns. */
562 1.6 christos q = arc_ext_opcodes;
563 1.6 christos
564 1.6 christos if (einsn->suffix)
565 1.6 christos {
566 1.6 christos lflags_f = flags_none;
567 1.6 christos lflags_ccf = flags_none;
568 1.6 christos }
569 1.6 christos else
570 1.6 christos {
571 1.6 christos lflags_f = flags_f;
572 1.6 christos lflags_ccf = flags_ccf;
573 1.6 christos }
574 1.6 christos
575 1.6 christos if (einsn->suffix & ARC_SUFFIX_COND)
576 1.6 christos lflags_ccf = flags_cc;
577 1.6 christos if (einsn->suffix & ARC_SUFFIX_FLAG)
578 1.6 christos {
579 1.6 christos lflags_f = flags_f;
580 1.6 christos lflags_ccf = flags_f;
581 1.6 christos }
582 1.6 christos if (einsn->suffix & (ARC_SUFFIX_FLAG | ARC_SUFFIX_COND))
583 1.6 christos lflags_ccf = flags_ccf;
584 1.6 christos
585 1.6 christos if (einsn->flags & ARC_SYNTAX_2OP
586 1.6 christos && !(einsn->flags & 0x10))
587 1.6 christos {
588 1.6 christos /* Regular 2OP instruction. */
589 1.6 christos if (einsn->suffix & ARC_SUFFIX_COND)
590 1.6 christos *errmsg = "Suffix SUFFIX_COND ignored";
591 1.6 christos
592 1.6 christos INSERT_XOP (q, einsn->name,
593 1.6 christos INSN2OP_BC (einsn->major, einsn->minor), MINSN2OP_BC,
594 1.6 christos arc_target, arg_32bit_rbrc, lflags_f);
595 1.6 christos
596 1.6 christos INSERT_XOP (q, einsn->name,
597 1.6 christos INSN2OP_0C (einsn->major, einsn->minor), MINSN2OP_0C,
598 1.6 christos arc_target, arg_32bit_zarc, lflags_f);
599 1.6 christos
600 1.6 christos INSERT_XOP (q, einsn->name,
601 1.6 christos INSN2OP_BU (einsn->major, einsn->minor), MINSN2OP_BU,
602 1.6 christos arc_target, arg_32bit_rbu6, lflags_f);
603 1.6 christos
604 1.6 christos INSERT_XOP (q, einsn->name,
605 1.6 christos INSN2OP_0U (einsn->major, einsn->minor), MINSN2OP_0U,
606 1.6 christos arc_target, arg_32bit_zau6, lflags_f);
607 1.6 christos
608 1.6 christos INSERT_XOP (q, einsn->name,
609 1.6 christos INSN2OP_BL (einsn->major, einsn->minor), MINSN2OP_BL,
610 1.6 christos arc_target, arg_32bit_rblimm, lflags_f);
611 1.6 christos
612 1.6 christos INSERT_XOP (q, einsn->name,
613 1.6 christos INSN2OP_0L (einsn->major, einsn->minor), MINSN2OP_0L,
614 1.6 christos arc_target, arg_32bit_zalimm, lflags_f);
615 1.6 christos }
616 1.6 christos else if (einsn->flags & (0x10 | ARC_SYNTAX_2OP))
617 1.6 christos {
618 1.6 christos /* This is actually a 3OP pattern. The first operand is
619 1.6 christos immplied and is set to zero. */
620 1.6 christos INSERT_XOP (q, einsn->name,
621 1.6 christos INSN3OP_0BC (einsn->major, einsn->minor), MINSN3OP_0BC,
622 1.6 christos arc_target, arg_32bit_rbrc, lflags_f);
623 1.6 christos
624 1.6 christos INSERT_XOP (q, einsn->name,
625 1.6 christos INSN3OP_0BU (einsn->major, einsn->minor), MINSN3OP_0BU,
626 1.6 christos arc_target, arg_32bit_rbu6, lflags_f);
627 1.6 christos
628 1.6 christos INSERT_XOP (q, einsn->name,
629 1.6 christos INSN3OP_0BL (einsn->major, einsn->minor), MINSN3OP_0BL,
630 1.6 christos arc_target, arg_32bit_rblimm, lflags_f);
631 1.6 christos
632 1.6 christos INSERT_XOP (q, einsn->name,
633 1.6 christos INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
634 1.6 christos arc_target, arg_32bit_limmrc, lflags_ccf);
635 1.6 christos
636 1.6 christos INSERT_XOP (q, einsn->name,
637 1.6 christos INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
638 1.6 christos arc_target, arg_32bit_limmu6, lflags_ccf);
639 1.6 christos
640 1.6 christos INSERT_XOP (q, einsn->name,
641 1.6 christos INSN3OP_0LS (einsn->major, einsn->minor), MINSN3OP_0LS,
642 1.6 christos arc_target, arg_32bit_limms12, lflags_f);
643 1.6 christos
644 1.6 christos INSERT_XOP (q, einsn->name,
645 1.6 christos INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
646 1.6 christos arc_target, arg_32bit_limmlimm, lflags_ccf);
647 1.6 christos }
648 1.6 christos else if (einsn->flags & ARC_SYNTAX_3OP
649 1.6 christos && !(einsn->modsyn & ARC_OP1_MUST_BE_IMM))
650 1.6 christos {
651 1.6 christos /* Regular 3OP instruction. */
652 1.6 christos INSERT_XOP (q, einsn->name,
653 1.6 christos INSN3OP_ABC (einsn->major, einsn->minor), MINSN3OP_ABC,
654 1.6 christos arc_target, arg_32bit_rarbrc, lflags_f);
655 1.6 christos
656 1.6 christos INSERT_XOP (q, einsn->name,
657 1.6 christos INSN3OP_0BC (einsn->major, einsn->minor), MINSN3OP_0BC,
658 1.6 christos arc_target, arg_32bit_zarbrc, lflags_f);
659 1.6 christos
660 1.6 christos INSERT_XOP (q, einsn->name,
661 1.6 christos INSN3OP_CBBC (einsn->major, einsn->minor), MINSN3OP_CBBC,
662 1.6 christos arc_target, arg_32bit_rbrbrc, lflags_ccf);
663 1.6 christos
664 1.6 christos INSERT_XOP (q, einsn->name,
665 1.6 christos INSN3OP_ABU (einsn->major, einsn->minor), MINSN3OP_ABU,
666 1.6 christos arc_target, arg_32bit_rarbu6, lflags_f);
667 1.6 christos
668 1.6 christos INSERT_XOP (q, einsn->name,
669 1.6 christos INSN3OP_0BU (einsn->major, einsn->minor), MINSN3OP_0BU,
670 1.6 christos arc_target, arg_32bit_zarbu6, lflags_f);
671 1.6 christos
672 1.6 christos INSERT_XOP (q, einsn->name,
673 1.6 christos INSN3OP_CBBU (einsn->major, einsn->minor), MINSN3OP_CBBU,
674 1.6 christos arc_target, arg_32bit_rbrbu6, lflags_ccf);
675 1.6 christos
676 1.6 christos INSERT_XOP (q, einsn->name,
677 1.6 christos INSN3OP_BBS (einsn->major, einsn->minor), MINSN3OP_BBS,
678 1.6 christos arc_target, arg_32bit_rbrbs12, lflags_f);
679 1.6 christos
680 1.6 christos INSERT_XOP (q, einsn->name,
681 1.6 christos INSN3OP_ALC (einsn->major, einsn->minor), MINSN3OP_ALC,
682 1.6 christos arc_target, arg_32bit_ralimmrc, lflags_f);
683 1.6 christos
684 1.6 christos INSERT_XOP (q, einsn->name,
685 1.6 christos INSN3OP_ABL (einsn->major, einsn->minor), MINSN3OP_ABL,
686 1.6 christos arc_target, arg_32bit_rarblimm, lflags_f);
687 1.6 christos
688 1.6 christos INSERT_XOP (q, einsn->name,
689 1.6 christos INSN3OP_0LC (einsn->major, einsn->minor), MINSN3OP_0LC,
690 1.6 christos arc_target, arg_32bit_zalimmrc, lflags_f);
691 1.6 christos
692 1.6 christos INSERT_XOP (q, einsn->name,
693 1.6 christos INSN3OP_0BL (einsn->major, einsn->minor), MINSN3OP_0BL,
694 1.6 christos arc_target, arg_32bit_zarblimm, lflags_f);
695 1.6 christos
696 1.6 christos INSERT_XOP (q, einsn->name,
697 1.6 christos INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
698 1.6 christos arc_target, arg_32bit_zalimmrc, lflags_ccf);
699 1.6 christos
700 1.6 christos INSERT_XOP (q, einsn->name,
701 1.6 christos INSN3OP_CBBL (einsn->major, einsn->minor), MINSN3OP_CBBL,
702 1.6 christos arc_target, arg_32bit_rbrblimm, lflags_ccf);
703 1.6 christos
704 1.6 christos INSERT_XOP (q, einsn->name,
705 1.6 christos INSN3OP_ALU (einsn->major, einsn->minor), MINSN3OP_ALU,
706 1.6 christos arc_target, arg_32bit_ralimmu6, lflags_f);
707 1.6 christos
708 1.6 christos INSERT_XOP (q, einsn->name,
709 1.6 christos INSN3OP_0LU (einsn->major, einsn->minor), MINSN3OP_0LU,
710 1.6 christos arc_target, arg_32bit_zalimmu6, lflags_f);
711 1.6 christos
712 1.6 christos INSERT_XOP (q, einsn->name,
713 1.6 christos INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
714 1.6 christos arc_target, arg_32bit_zalimmu6, lflags_ccf);
715 1.6 christos
716 1.6 christos INSERT_XOP (q, einsn->name,
717 1.6 christos INSN3OP_0LS (einsn->major, einsn->minor), MINSN3OP_0LS,
718 1.6 christos arc_target, arg_32bit_zalimms12, lflags_f);
719 1.6 christos
720 1.6 christos INSERT_XOP (q, einsn->name,
721 1.6 christos INSN3OP_ALL (einsn->major, einsn->minor), MINSN3OP_ALL,
722 1.6 christos arc_target, arg_32bit_ralimmlimm, lflags_f);
723 1.6 christos
724 1.6 christos INSERT_XOP (q, einsn->name,
725 1.6 christos INSN3OP_0LL (einsn->major, einsn->minor), MINSN3OP_0LL,
726 1.6 christos arc_target, arg_32bit_zalimmlimm, lflags_f);
727 1.6 christos
728 1.6 christos INSERT_XOP (q, einsn->name,
729 1.6 christos INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
730 1.6 christos arc_target, arg_32bit_zalimmlimm, lflags_ccf);
731 1.6 christos }
732 1.6 christos else if (einsn->flags & ARC_SYNTAX_3OP)
733 1.6 christos {
734 1.6 christos /* 3OP instruction which accepts only zero as first
735 1.6 christos argument. */
736 1.6 christos INSERT_XOP (q, einsn->name,
737 1.6 christos INSN3OP_0BC (einsn->major, einsn->minor), MINSN3OP_0BC,
738 1.6 christos arc_target, arg_32bit_zarbrc, lflags_f);
739 1.6 christos
740 1.6 christos INSERT_XOP (q, einsn->name,
741 1.6 christos INSN3OP_0BU (einsn->major, einsn->minor), MINSN3OP_0BU,
742 1.6 christos arc_target, arg_32bit_zarbu6, lflags_f);
743 1.6 christos
744 1.6 christos INSERT_XOP (q, einsn->name,
745 1.6 christos INSN3OP_0LC (einsn->major, einsn->minor), MINSN3OP_0LC,
746 1.6 christos arc_target, arg_32bit_zalimmrc, lflags_f);
747 1.6 christos
748 1.6 christos INSERT_XOP (q, einsn->name,
749 1.6 christos INSN3OP_0BL (einsn->major, einsn->minor), MINSN3OP_0BL,
750 1.6 christos arc_target, arg_32bit_zarblimm, lflags_f);
751 1.6 christos
752 1.6 christos INSERT_XOP (q, einsn->name,
753 1.6 christos INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
754 1.6 christos arc_target, arg_32bit_zalimmrc, lflags_ccf);
755 1.6 christos
756 1.6 christos INSERT_XOP (q, einsn->name,
757 1.6 christos INSN3OP_0LU (einsn->major, einsn->minor), MINSN3OP_0LU,
758 1.6 christos arc_target, arg_32bit_zalimmu6, lflags_f);
759 1.6 christos
760 1.6 christos INSERT_XOP (q, einsn->name,
761 1.6 christos INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
762 1.6 christos arc_target, arg_32bit_zalimmu6, lflags_ccf);
763 1.6 christos
764 1.6 christos INSERT_XOP (q, einsn->name,
765 1.6 christos INSN3OP_0LS (einsn->major, einsn->minor), MINSN3OP_0LS,
766 1.6 christos arc_target, arg_32bit_zalimms12, lflags_f);
767 1.6 christos
768 1.6 christos INSERT_XOP (q, einsn->name,
769 1.6 christos INSN3OP_0LL (einsn->major, einsn->minor), MINSN3OP_0LL,
770 1.6 christos arc_target, arg_32bit_zalimmlimm, lflags_f);
771 1.6 christos
772 1.6 christos INSERT_XOP (q, einsn->name,
773 1.6 christos INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
774 1.6 christos arc_target, arg_32bit_zalimmlimm, lflags_ccf);
775 1.6 christos }
776 1.6 christos else if (einsn->flags & ARC_SYNTAX_1OP)
777 1.6 christos {
778 1.6 christos if (einsn->suffix & ARC_SUFFIX_COND)
779 1.6 christos *errmsg = "Suffix SUFFIX_COND ignored";
780 1.6 christos
781 1.6 christos INSERT_XOP (q, einsn->name,
782 1.6 christos INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor),
783 1.6 christos MINSN2OP_0C, arc_target, arg_32bit_rc, lflags_f);
784 1.6 christos
785 1.6 christos INSERT_XOP (q, einsn->name,
786 1.6 christos INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
787 1.6 christos | (0x01 << 22), MINSN2OP_0U, arc_target, arg_32bit_u6,
788 1.6 christos lflags_f);
789 1.6 christos
790 1.6 christos INSERT_XOP (q, einsn->name,
791 1.6 christos INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
792 1.6 christos | FIELDC (62), MINSN2OP_0L, arc_target, arg_32bit_limm,
793 1.6 christos lflags_f);
794 1.6 christos
795 1.6 christos }
796 1.6 christos else if (einsn->flags & ARC_SYNTAX_NOP)
797 1.6 christos {
798 1.6 christos if (einsn->suffix & ARC_SUFFIX_COND)
799 1.6 christos *errmsg = "Suffix SUFFIX_COND ignored";
800 1.6 christos
801 1.6 christos INSERT_XOP (q, einsn->name,
802 1.6 christos INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
803 1.6 christos | (0x01 << 22), MINSN2OP_0L, arc_target, arg_none, lflags_f);
804 1.6 christos }
805 1.6 christos else
806 1.6 christos {
807 1.6 christos *errmsg = "Unknown syntax";
808 1.6 christos return NULL;
809 1.6 christos }
810 1.6 christos
811 1.6 christos /* End marker. */
812 1.6 christos memset (q, 0, sizeof (*arc_ext_opcodes));
813 1.6 christos
814 1.6 christos return arc_ext_opcodes;
815 1.6 christos }
816