1 1.6 christos /* ARC target-dependent stuff. Extension structure access functions 2 1.11 christos Copyright (C) 1995-2024 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.9 christos unsigned 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.7 christos break; 174 1.1 christos } 175 1.1 christos 176 1.1 christos case EXT_COND_CODE: 177 1.1 christos { 178 1.6 christos char *cc_name = xstrdup ((char *) (p + 3)); 179 1.6 christos 180 1.6 christos arc_extension_map. 181 1.6 christos condCodes[p[2] - FIRST_EXTENSION_CONDITION_CODE] 182 1.6 christos = cc_name; 183 1.6 christos break; 184 1.1 christos } 185 1.1 christos 186 1.1 christos case EXT_AUX_REGISTER: 187 1.1 christos { 188 1.6 christos /* Trickier -- need to store linked list of these. */ 189 1.6 christos struct ExtAuxRegister *newAuxRegister 190 1.6 christos = XNEW (struct ExtAuxRegister); 191 1.6 christos char *aux_name = xstrdup ((char *) (p + 6)); 192 1.1 christos 193 1.1 christos newAuxRegister->name = aux_name; 194 1.9 christos newAuxRegister->address = (((unsigned) p[2] << 24) | (p[3] << 16) 195 1.9 christos | (p[4] << 8) | p[5]); 196 1.1 christos newAuxRegister->next = arc_extension_map.auxRegisters; 197 1.1 christos arc_extension_map.auxRegisters = newAuxRegister; 198 1.6 christos break; 199 1.1 christos } 200 1.6 christos 201 1.6 christos default: 202 1.1 christos break; 203 1.6 christos } 204 1.6 christos 205 1.6 christos p += p[0]; /* Move on to next record. */ 206 1.6 christos } 207 1.6 christos } 208 1.6 christos 209 1.6 christos 210 1.6 christos /* Free memory that has been allocated for the extensions. */ 211 1.6 christos 212 1.6 christos static void 213 1.6 christos destroy_map (void) 214 1.6 christos { 215 1.6 christos struct ExtAuxRegister *r; 216 1.6 christos unsigned int i; 217 1.6 christos 218 1.6 christos /* Free auxiliary registers. */ 219 1.6 christos r = arc_extension_map.auxRegisters; 220 1.6 christos while (r) 221 1.6 christos { 222 1.6 christos /* N.B. after r has been freed, r->next is invalid! */ 223 1.6 christos struct ExtAuxRegister* next = r->next; 224 1.6 christos 225 1.6 christos free (r->name); 226 1.6 christos free (r); 227 1.6 christos r = next; 228 1.6 christos } 229 1.6 christos 230 1.6 christos /* Free instructions. */ 231 1.6 christos for (i = 0; i < INST_HASH_SIZE; i++) 232 1.6 christos { 233 1.6 christos struct ExtInstruction *insn = arc_extension_map.instructions[i]; 234 1.6 christos 235 1.6 christos while (insn) 236 1.6 christos { 237 1.6 christos /* N.B. after insn has been freed, insn->next is invalid! */ 238 1.6 christos struct ExtInstruction *next = insn->next; 239 1.6 christos 240 1.6 christos free (insn->name); 241 1.6 christos free (insn); 242 1.6 christos insn = next; 243 1.6 christos } 244 1.6 christos } 245 1.6 christos 246 1.6 christos /* Free core registers. */ 247 1.6 christos for (i = 0; i < NUM_EXT_CORE; i++) 248 1.9 christos free (arc_extension_map.coreRegisters[i].name); 249 1.6 christos 250 1.6 christos /* Free condition codes. */ 251 1.6 christos for (i = 0; i < NUM_EXT_COND; i++) 252 1.9 christos free (arc_extension_map.condCodes[i]); 253 1.6 christos 254 1.6 christos memset (&arc_extension_map, 0, sizeof (arc_extension_map)); 255 1.6 christos } 256 1.6 christos 257 1.6 christos 258 1.6 christos static const char * 259 1.6 christos ExtReadWrite_image (enum ExtReadWrite val) 260 1.6 christos { 261 1.6 christos switch (val) 262 1.6 christos { 263 1.6 christos case REG_INVALID : return "INVALID"; 264 1.6 christos case REG_READ : return "RO"; 265 1.6 christos case REG_WRITE : return "WO"; 266 1.6 christos case REG_READWRITE: return "R/W"; 267 1.6 christos default : return "???"; 268 1.6 christos } 269 1.6 christos } 270 1.6 christos 271 1.6 christos 272 1.6 christos /* Externally visible functions. */ 273 1.6 christos 274 1.6 christos /* Get the name of an extension instruction. */ 275 1.6 christos 276 1.6 christos const extInstruction_t * 277 1.7 christos arcExtMap_insn (int opcode, unsigned long long insn) 278 1.6 christos { 279 1.6 christos /* Here the following tasks need to be done. First of all, the 280 1.6 christos opcode stored in the Extension Map is the real opcode. However, 281 1.6 christos the subopcode stored in the instruction to be disassembled is 282 1.6 christos mangled. We pass (in minor opcode), the instruction word. Here 283 1.6 christos we will un-mangle it and get the real subopcode which we can look 284 1.6 christos for in the Extension Map. This function is used both for the 285 1.6 christos ARCTangent and the ARCompact, so we would also need some sort of 286 1.6 christos a way to distinguish between the two architectures. This is 287 1.6 christos because the ARCTangent does not do any of this mangling so we 288 1.6 christos have no issues there. */ 289 1.6 christos 290 1.6 christos /* If P[22:23] is 0 or 2 then un-mangle using iiiiiI. If it is 1 291 1.6 christos then use iiiiIi. Now, if P is 3 then check M[5:5] and if it is 0 292 1.6 christos then un-mangle using iiiiiI else iiiiii. */ 293 1.6 christos 294 1.6 christos unsigned char minor; 295 1.6 christos extInstruction_t *temp; 296 1.6 christos 297 1.6 christos /* 16-bit instructions. */ 298 1.6 christos if (0x08 <= opcode && opcode <= 0x0b) 299 1.6 christos { 300 1.6 christos unsigned char b, c, i; 301 1.6 christos 302 1.6 christos b = (insn & 0x0700) >> 8; 303 1.6 christos c = (insn & 0x00e0) >> 5; 304 1.6 christos i = (insn & 0x001f); 305 1.6 christos 306 1.6 christos if (i) 307 1.6 christos minor = i; 308 1.6 christos else 309 1.6 christos minor = (c == 0x07) ? b : c; 310 1.6 christos } 311 1.6 christos /* 32-bit instructions. */ 312 1.6 christos else 313 1.6 christos { 314 1.6 christos unsigned char I, A, B; 315 1.6 christos 316 1.6 christos I = (insn & 0x003f0000) >> 16; 317 1.6 christos A = (insn & 0x0000003f); 318 1.6 christos B = ((insn & 0x07000000) >> 24) | ((insn & 0x00007000) >> 9); 319 1.1 christos 320 1.6 christos if (I != 0x2f) 321 1.6 christos { 322 1.6 christos #ifndef UNMANGLED 323 1.6 christos switch (P) 324 1.6 christos { 325 1.6 christos case 3: 326 1.6 christos if (M) 327 1.6 christos { 328 1.6 christos minor = I; 329 1.6 christos break; 330 1.6 christos } 331 1.6 christos case 0: 332 1.6 christos case 2: 333 1.6 christos minor = (I >> 1) | ((I & 0x1) << 5); 334 1.6 christos break; 335 1.6 christos case 1: 336 1.6 christos minor = (I >> 1) | (I & 0x1) | ((I & 0x2) << 4); 337 1.6 christos } 338 1.6 christos #else 339 1.6 christos minor = I; 340 1.6 christos #endif 341 1.6 christos } 342 1.6 christos else 343 1.6 christos { 344 1.6 christos if (A != 0x3f) 345 1.6 christos minor = A; 346 1.6 christos else 347 1.6 christos minor = B; 348 1.6 christos } 349 1.6 christos } 350 1.1 christos 351 1.6 christos temp = arc_extension_map.instructions[INST_HASH (opcode, minor)]; 352 1.6 christos while (temp) 353 1.6 christos { 354 1.6 christos if ((temp->major == opcode) && (temp->minor == minor)) 355 1.6 christos { 356 1.6 christos return temp; 357 1.1 christos } 358 1.6 christos temp = temp->next; 359 1.1 christos } 360 1.1 christos 361 1.6 christos return NULL; 362 1.6 christos } 363 1.6 christos 364 1.6 christos /* Get the name of an extension core register. */ 365 1.6 christos 366 1.6 christos const char * 367 1.6 christos arcExtMap_coreRegName (int regnum) 368 1.6 christos { 369 1.6 christos if (regnum < FIRST_EXTENSION_CORE_REGISTER 370 1.6 christos || regnum > LAST_EXTENSION_CORE_REGISTER) 371 1.6 christos return NULL; 372 1.6 christos return arc_extension_map. 373 1.6 christos coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].name; 374 1.6 christos } 375 1.6 christos 376 1.6 christos /* Get the access mode of an extension core register. */ 377 1.6 christos 378 1.6 christos enum ExtReadWrite 379 1.6 christos arcExtMap_coreReadWrite (int regnum) 380 1.6 christos { 381 1.6 christos if (regnum < FIRST_EXTENSION_CORE_REGISTER 382 1.6 christos || regnum > LAST_EXTENSION_CORE_REGISTER) 383 1.6 christos return REG_INVALID; 384 1.6 christos return arc_extension_map. 385 1.6 christos coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].rw; 386 1.6 christos } 387 1.6 christos 388 1.6 christos /* Get the name of an extension condition code. */ 389 1.6 christos 390 1.6 christos const char * 391 1.6 christos arcExtMap_condCodeName (int code) 392 1.6 christos { 393 1.6 christos if (code < FIRST_EXTENSION_CONDITION_CODE 394 1.6 christos || code > LAST_EXTENSION_CONDITION_CODE) 395 1.6 christos return NULL; 396 1.6 christos return arc_extension_map. 397 1.6 christos condCodes[code - FIRST_EXTENSION_CONDITION_CODE]; 398 1.1 christos } 399 1.1 christos 400 1.6 christos /* Get the name of an extension auxiliary register. */ 401 1.6 christos 402 1.6 christos const char * 403 1.9 christos arcExtMap_auxRegName (unsigned address) 404 1.6 christos { 405 1.6 christos /* Walk the list of auxiliary register names and find the name. */ 406 1.6 christos struct ExtAuxRegister *r; 407 1.6 christos 408 1.6 christos for (r = arc_extension_map.auxRegisters; r; r = r->next) 409 1.6 christos { 410 1.6 christos if (r->address == address) 411 1.6 christos return (const char *)r->name; 412 1.6 christos } 413 1.6 christos return NULL; 414 1.6 christos } 415 1.6 christos 416 1.6 christos /* Load extensions described in .arcextmap and 417 1.6 christos .gnu.linkonce.arcextmap.* ELF section. */ 418 1.1 christos 419 1.1 christos void 420 1.6 christos build_ARC_extmap (bfd *text_bfd) 421 1.1 christos { 422 1.6 christos asection *sect; 423 1.1 christos 424 1.6 christos /* The map is built each time gdb loads an executable file - so free 425 1.6 christos any existing map, as the map defined by the new file may differ 426 1.6 christos from the old. */ 427 1.6 christos destroy_map (); 428 1.6 christos 429 1.6 christos for (sect = text_bfd->sections; sect != NULL; sect = sect->next) 430 1.6 christos if (!strncmp (sect->name, 431 1.6 christos ".gnu.linkonce.arcextmap.", 432 1.6 christos sizeof (".gnu.linkonce.arcextmap.") - 1) 433 1.6 christos || !strcmp (sect->name,".arcextmap")) 434 1.1 christos { 435 1.9 christos bfd_size_type count = bfd_section_size (sect); 436 1.6 christos unsigned char* buffer = xmalloc (count); 437 1.6 christos 438 1.6 christos if (buffer) 439 1.6 christos { 440 1.6 christos if (bfd_get_section_contents (text_bfd, sect, buffer, 0, count)) 441 1.6 christos create_map (buffer, count); 442 1.6 christos free (buffer); 443 1.6 christos } 444 1.1 christos } 445 1.1 christos } 446 1.6 christos 447 1.6 christos /* Debug function used to dump the ARC information fount in arcextmap 448 1.6 christos sections. */ 449 1.6 christos 450 1.6 christos void 451 1.6 christos dump_ARC_extmap (void) 452 1.6 christos { 453 1.6 christos struct ExtAuxRegister *r; 454 1.6 christos int i; 455 1.6 christos 456 1.6 christos r = arc_extension_map.auxRegisters; 457 1.6 christos 458 1.6 christos while (r) 459 1.6 christos { 460 1.9 christos printf ("AUX : %s %u\n", r->name, r->address); 461 1.6 christos r = r->next; 462 1.6 christos } 463 1.6 christos 464 1.6 christos for (i = 0; i < INST_HASH_SIZE; i++) 465 1.6 christos { 466 1.6 christos struct ExtInstruction *insn; 467 1.6 christos 468 1.6 christos for (insn = arc_extension_map.instructions[i]; 469 1.6 christos insn != NULL; insn = insn->next) 470 1.6 christos { 471 1.6 christos printf ("INST: 0x%02x 0x%02x ", insn->major, insn->minor); 472 1.6 christos switch (insn->flags & ARC_SYNTAX_MASK) 473 1.6 christos { 474 1.6 christos case ARC_SYNTAX_2OP: 475 1.6 christos printf ("SYNTAX_2OP"); 476 1.6 christos break; 477 1.6 christos case ARC_SYNTAX_3OP: 478 1.6 christos printf ("SYNTAX_3OP"); 479 1.6 christos break; 480 1.6 christos case ARC_SYNTAX_1OP: 481 1.6 christos printf ("SYNTAX_1OP"); 482 1.6 christos break; 483 1.6 christos case ARC_SYNTAX_NOP: 484 1.6 christos printf ("SYNTAX_NOP"); 485 1.6 christos break; 486 1.6 christos default: 487 1.6 christos printf ("SYNTAX_UNK"); 488 1.6 christos break; 489 1.6 christos } 490 1.6 christos 491 1.6 christos if (insn->flags & 0x10) 492 1.6 christos printf ("|MODIFIER"); 493 1.6 christos 494 1.6 christos printf (" %s\n", insn->name); 495 1.6 christos } 496 1.6 christos } 497 1.6 christos 498 1.6 christos for (i = 0; i < NUM_EXT_CORE; i++) 499 1.6 christos { 500 1.6 christos struct ExtCoreRegister reg = arc_extension_map.coreRegisters[i]; 501 1.6 christos 502 1.6 christos if (reg.name) 503 1.6 christos printf ("CORE: 0x%04x %s %s\n", reg.number, 504 1.6 christos ExtReadWrite_image (reg.rw), 505 1.6 christos reg.name); 506 1.6 christos } 507 1.6 christos 508 1.6 christos for (i = 0; i < NUM_EXT_COND; i++) 509 1.6 christos if (arc_extension_map.condCodes[i]) 510 1.6 christos printf ("COND: %s\n", arc_extension_map.condCodes[i]); 511 1.6 christos } 512 1.6 christos 513 1.6 christos /* For a given extension instruction generate the equivalent arc 514 1.6 christos opcode structure. */ 515 1.6 christos 516 1.6 christos struct arc_opcode * 517 1.6 christos arcExtMap_genOpcode (const extInstruction_t *einsn, 518 1.6 christos unsigned arc_target, 519 1.6 christos const char **errmsg) 520 1.6 christos { 521 1.6 christos struct arc_opcode *q, *arc_ext_opcodes = NULL; 522 1.6 christos const unsigned char *lflags_f; 523 1.6 christos const unsigned char *lflags_ccf; 524 1.6 christos int count; 525 1.6 christos 526 1.6 christos /* Check for the class to see how many instructions we generate. */ 527 1.6 christos switch (einsn->flags & ARC_SYNTAX_MASK) 528 1.6 christos { 529 1.6 christos case ARC_SYNTAX_3OP: 530 1.6 christos count = (einsn->modsyn & ARC_OP1_MUST_BE_IMM) ? 10 : 20; 531 1.6 christos break; 532 1.6 christos case ARC_SYNTAX_2OP: 533 1.6 christos count = (einsn->flags & 0x10) ? 7 : 6; 534 1.6 christos break; 535 1.6 christos case ARC_SYNTAX_1OP: 536 1.6 christos count = 3; 537 1.6 christos break; 538 1.6 christos case ARC_SYNTAX_NOP: 539 1.6 christos count = 1; 540 1.6 christos break; 541 1.6 christos default: 542 1.6 christos count = 0; 543 1.6 christos break; 544 1.6 christos } 545 1.6 christos 546 1.6 christos /* Allocate memory. */ 547 1.6 christos arc_ext_opcodes = (struct arc_opcode *) 548 1.6 christos xmalloc ((count + 1) * sizeof (*arc_ext_opcodes)); 549 1.6 christos 550 1.6 christos if (arc_ext_opcodes == NULL) 551 1.6 christos { 552 1.6 christos *errmsg = "Virtual memory exhausted"; 553 1.6 christos return NULL; 554 1.6 christos } 555 1.6 christos 556 1.6 christos /* Generate the patterns. */ 557 1.6 christos q = arc_ext_opcodes; 558 1.6 christos 559 1.6 christos if (einsn->suffix) 560 1.6 christos { 561 1.6 christos lflags_f = flags_none; 562 1.6 christos lflags_ccf = flags_none; 563 1.6 christos } 564 1.6 christos else 565 1.6 christos { 566 1.6 christos lflags_f = flags_f; 567 1.6 christos lflags_ccf = flags_ccf; 568 1.6 christos } 569 1.6 christos 570 1.6 christos if (einsn->suffix & ARC_SUFFIX_COND) 571 1.6 christos lflags_ccf = flags_cc; 572 1.6 christos if (einsn->suffix & ARC_SUFFIX_FLAG) 573 1.6 christos { 574 1.6 christos lflags_f = flags_f; 575 1.6 christos lflags_ccf = flags_f; 576 1.6 christos } 577 1.6 christos if (einsn->suffix & (ARC_SUFFIX_FLAG | ARC_SUFFIX_COND)) 578 1.6 christos lflags_ccf = flags_ccf; 579 1.6 christos 580 1.6 christos if (einsn->flags & ARC_SYNTAX_2OP 581 1.6 christos && !(einsn->flags & 0x10)) 582 1.6 christos { 583 1.6 christos /* Regular 2OP instruction. */ 584 1.6 christos if (einsn->suffix & ARC_SUFFIX_COND) 585 1.6 christos *errmsg = "Suffix SUFFIX_COND ignored"; 586 1.6 christos 587 1.6 christos INSERT_XOP (q, einsn->name, 588 1.6 christos INSN2OP_BC (einsn->major, einsn->minor), MINSN2OP_BC, 589 1.6 christos arc_target, arg_32bit_rbrc, lflags_f); 590 1.6 christos 591 1.6 christos INSERT_XOP (q, einsn->name, 592 1.6 christos INSN2OP_0C (einsn->major, einsn->minor), MINSN2OP_0C, 593 1.6 christos arc_target, arg_32bit_zarc, lflags_f); 594 1.6 christos 595 1.6 christos INSERT_XOP (q, einsn->name, 596 1.6 christos INSN2OP_BU (einsn->major, einsn->minor), MINSN2OP_BU, 597 1.6 christos arc_target, arg_32bit_rbu6, lflags_f); 598 1.6 christos 599 1.6 christos INSERT_XOP (q, einsn->name, 600 1.6 christos INSN2OP_0U (einsn->major, einsn->minor), MINSN2OP_0U, 601 1.6 christos arc_target, arg_32bit_zau6, lflags_f); 602 1.6 christos 603 1.6 christos INSERT_XOP (q, einsn->name, 604 1.6 christos INSN2OP_BL (einsn->major, einsn->minor), MINSN2OP_BL, 605 1.6 christos arc_target, arg_32bit_rblimm, lflags_f); 606 1.6 christos 607 1.6 christos INSERT_XOP (q, einsn->name, 608 1.6 christos INSN2OP_0L (einsn->major, einsn->minor), MINSN2OP_0L, 609 1.6 christos arc_target, arg_32bit_zalimm, lflags_f); 610 1.6 christos } 611 1.6 christos else if (einsn->flags & (0x10 | ARC_SYNTAX_2OP)) 612 1.6 christos { 613 1.6 christos /* This is actually a 3OP pattern. The first operand is 614 1.6 christos immplied and is set to zero. */ 615 1.6 christos INSERT_XOP (q, einsn->name, 616 1.6 christos INSN3OP_0BC (einsn->major, einsn->minor), MINSN3OP_0BC, 617 1.6 christos arc_target, arg_32bit_rbrc, lflags_f); 618 1.6 christos 619 1.6 christos INSERT_XOP (q, einsn->name, 620 1.6 christos INSN3OP_0BU (einsn->major, einsn->minor), MINSN3OP_0BU, 621 1.6 christos arc_target, arg_32bit_rbu6, lflags_f); 622 1.6 christos 623 1.6 christos INSERT_XOP (q, einsn->name, 624 1.6 christos INSN3OP_0BL (einsn->major, einsn->minor), MINSN3OP_0BL, 625 1.6 christos arc_target, arg_32bit_rblimm, lflags_f); 626 1.6 christos 627 1.6 christos INSERT_XOP (q, einsn->name, 628 1.6 christos INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC, 629 1.6 christos arc_target, arg_32bit_limmrc, lflags_ccf); 630 1.6 christos 631 1.6 christos INSERT_XOP (q, einsn->name, 632 1.6 christos INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU, 633 1.6 christos arc_target, arg_32bit_limmu6, lflags_ccf); 634 1.6 christos 635 1.6 christos INSERT_XOP (q, einsn->name, 636 1.6 christos INSN3OP_0LS (einsn->major, einsn->minor), MINSN3OP_0LS, 637 1.6 christos arc_target, arg_32bit_limms12, lflags_f); 638 1.6 christos 639 1.6 christos INSERT_XOP (q, einsn->name, 640 1.6 christos INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL, 641 1.6 christos arc_target, arg_32bit_limmlimm, lflags_ccf); 642 1.6 christos } 643 1.6 christos else if (einsn->flags & ARC_SYNTAX_3OP 644 1.6 christos && !(einsn->modsyn & ARC_OP1_MUST_BE_IMM)) 645 1.6 christos { 646 1.6 christos /* Regular 3OP instruction. */ 647 1.6 christos INSERT_XOP (q, einsn->name, 648 1.6 christos INSN3OP_ABC (einsn->major, einsn->minor), MINSN3OP_ABC, 649 1.6 christos arc_target, arg_32bit_rarbrc, lflags_f); 650 1.6 christos 651 1.6 christos INSERT_XOP (q, einsn->name, 652 1.6 christos INSN3OP_0BC (einsn->major, einsn->minor), MINSN3OP_0BC, 653 1.6 christos arc_target, arg_32bit_zarbrc, lflags_f); 654 1.6 christos 655 1.6 christos INSERT_XOP (q, einsn->name, 656 1.6 christos INSN3OP_CBBC (einsn->major, einsn->minor), MINSN3OP_CBBC, 657 1.6 christos arc_target, arg_32bit_rbrbrc, lflags_ccf); 658 1.6 christos 659 1.6 christos INSERT_XOP (q, einsn->name, 660 1.6 christos INSN3OP_ABU (einsn->major, einsn->minor), MINSN3OP_ABU, 661 1.6 christos arc_target, arg_32bit_rarbu6, lflags_f); 662 1.6 christos 663 1.6 christos INSERT_XOP (q, einsn->name, 664 1.6 christos INSN3OP_0BU (einsn->major, einsn->minor), MINSN3OP_0BU, 665 1.6 christos arc_target, arg_32bit_zarbu6, lflags_f); 666 1.6 christos 667 1.6 christos INSERT_XOP (q, einsn->name, 668 1.6 christos INSN3OP_CBBU (einsn->major, einsn->minor), MINSN3OP_CBBU, 669 1.6 christos arc_target, arg_32bit_rbrbu6, lflags_ccf); 670 1.6 christos 671 1.6 christos INSERT_XOP (q, einsn->name, 672 1.6 christos INSN3OP_BBS (einsn->major, einsn->minor), MINSN3OP_BBS, 673 1.6 christos arc_target, arg_32bit_rbrbs12, lflags_f); 674 1.6 christos 675 1.6 christos INSERT_XOP (q, einsn->name, 676 1.6 christos INSN3OP_ALC (einsn->major, einsn->minor), MINSN3OP_ALC, 677 1.6 christos arc_target, arg_32bit_ralimmrc, lflags_f); 678 1.6 christos 679 1.6 christos INSERT_XOP (q, einsn->name, 680 1.6 christos INSN3OP_ABL (einsn->major, einsn->minor), MINSN3OP_ABL, 681 1.6 christos arc_target, arg_32bit_rarblimm, lflags_f); 682 1.6 christos 683 1.6 christos INSERT_XOP (q, einsn->name, 684 1.6 christos INSN3OP_0LC (einsn->major, einsn->minor), MINSN3OP_0LC, 685 1.6 christos arc_target, arg_32bit_zalimmrc, lflags_f); 686 1.6 christos 687 1.6 christos INSERT_XOP (q, einsn->name, 688 1.6 christos INSN3OP_0BL (einsn->major, einsn->minor), MINSN3OP_0BL, 689 1.6 christos arc_target, arg_32bit_zarblimm, lflags_f); 690 1.6 christos 691 1.6 christos INSERT_XOP (q, einsn->name, 692 1.6 christos INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC, 693 1.6 christos arc_target, arg_32bit_zalimmrc, lflags_ccf); 694 1.6 christos 695 1.6 christos INSERT_XOP (q, einsn->name, 696 1.6 christos INSN3OP_CBBL (einsn->major, einsn->minor), MINSN3OP_CBBL, 697 1.6 christos arc_target, arg_32bit_rbrblimm, lflags_ccf); 698 1.6 christos 699 1.6 christos INSERT_XOP (q, einsn->name, 700 1.6 christos INSN3OP_ALU (einsn->major, einsn->minor), MINSN3OP_ALU, 701 1.6 christos arc_target, arg_32bit_ralimmu6, lflags_f); 702 1.6 christos 703 1.6 christos INSERT_XOP (q, einsn->name, 704 1.6 christos INSN3OP_0LU (einsn->major, einsn->minor), MINSN3OP_0LU, 705 1.6 christos arc_target, arg_32bit_zalimmu6, lflags_f); 706 1.6 christos 707 1.6 christos INSERT_XOP (q, einsn->name, 708 1.6 christos INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU, 709 1.6 christos arc_target, arg_32bit_zalimmu6, lflags_ccf); 710 1.6 christos 711 1.6 christos INSERT_XOP (q, einsn->name, 712 1.6 christos INSN3OP_0LS (einsn->major, einsn->minor), MINSN3OP_0LS, 713 1.6 christos arc_target, arg_32bit_zalimms12, lflags_f); 714 1.6 christos 715 1.6 christos INSERT_XOP (q, einsn->name, 716 1.6 christos INSN3OP_ALL (einsn->major, einsn->minor), MINSN3OP_ALL, 717 1.6 christos arc_target, arg_32bit_ralimmlimm, lflags_f); 718 1.6 christos 719 1.6 christos INSERT_XOP (q, einsn->name, 720 1.6 christos INSN3OP_0LL (einsn->major, einsn->minor), MINSN3OP_0LL, 721 1.6 christos arc_target, arg_32bit_zalimmlimm, lflags_f); 722 1.6 christos 723 1.6 christos INSERT_XOP (q, einsn->name, 724 1.6 christos INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL, 725 1.6 christos arc_target, arg_32bit_zalimmlimm, lflags_ccf); 726 1.6 christos } 727 1.6 christos else if (einsn->flags & ARC_SYNTAX_3OP) 728 1.6 christos { 729 1.6 christos /* 3OP instruction which accepts only zero as first 730 1.6 christos argument. */ 731 1.6 christos INSERT_XOP (q, einsn->name, 732 1.6 christos INSN3OP_0BC (einsn->major, einsn->minor), MINSN3OP_0BC, 733 1.6 christos arc_target, arg_32bit_zarbrc, lflags_f); 734 1.6 christos 735 1.6 christos INSERT_XOP (q, einsn->name, 736 1.6 christos INSN3OP_0BU (einsn->major, einsn->minor), MINSN3OP_0BU, 737 1.6 christos arc_target, arg_32bit_zarbu6, lflags_f); 738 1.6 christos 739 1.6 christos INSERT_XOP (q, einsn->name, 740 1.6 christos INSN3OP_0LC (einsn->major, einsn->minor), MINSN3OP_0LC, 741 1.6 christos arc_target, arg_32bit_zalimmrc, lflags_f); 742 1.6 christos 743 1.6 christos INSERT_XOP (q, einsn->name, 744 1.6 christos INSN3OP_0BL (einsn->major, einsn->minor), MINSN3OP_0BL, 745 1.6 christos arc_target, arg_32bit_zarblimm, lflags_f); 746 1.6 christos 747 1.6 christos INSERT_XOP (q, einsn->name, 748 1.6 christos INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC, 749 1.6 christos arc_target, arg_32bit_zalimmrc, lflags_ccf); 750 1.6 christos 751 1.6 christos INSERT_XOP (q, einsn->name, 752 1.6 christos INSN3OP_0LU (einsn->major, einsn->minor), MINSN3OP_0LU, 753 1.6 christos arc_target, arg_32bit_zalimmu6, lflags_f); 754 1.6 christos 755 1.6 christos INSERT_XOP (q, einsn->name, 756 1.6 christos INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU, 757 1.6 christos arc_target, arg_32bit_zalimmu6, lflags_ccf); 758 1.6 christos 759 1.6 christos INSERT_XOP (q, einsn->name, 760 1.6 christos INSN3OP_0LS (einsn->major, einsn->minor), MINSN3OP_0LS, 761 1.6 christos arc_target, arg_32bit_zalimms12, lflags_f); 762 1.6 christos 763 1.6 christos INSERT_XOP (q, einsn->name, 764 1.6 christos INSN3OP_0LL (einsn->major, einsn->minor), MINSN3OP_0LL, 765 1.6 christos arc_target, arg_32bit_zalimmlimm, lflags_f); 766 1.6 christos 767 1.6 christos INSERT_XOP (q, einsn->name, 768 1.6 christos INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL, 769 1.6 christos arc_target, arg_32bit_zalimmlimm, lflags_ccf); 770 1.6 christos } 771 1.6 christos else if (einsn->flags & ARC_SYNTAX_1OP) 772 1.6 christos { 773 1.6 christos if (einsn->suffix & ARC_SUFFIX_COND) 774 1.6 christos *errmsg = "Suffix SUFFIX_COND ignored"; 775 1.6 christos 776 1.6 christos INSERT_XOP (q, einsn->name, 777 1.6 christos INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor), 778 1.6 christos MINSN2OP_0C, arc_target, arg_32bit_rc, lflags_f); 779 1.6 christos 780 1.6 christos INSERT_XOP (q, einsn->name, 781 1.6 christos INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor) 782 1.6 christos | (0x01 << 22), MINSN2OP_0U, arc_target, arg_32bit_u6, 783 1.6 christos 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 | FIELDC (62), MINSN2OP_0L, arc_target, arg_32bit_limm, 788 1.6 christos lflags_f); 789 1.6 christos 790 1.6 christos } 791 1.6 christos else if (einsn->flags & ARC_SYNTAX_NOP) 792 1.6 christos { 793 1.6 christos if (einsn->suffix & ARC_SUFFIX_COND) 794 1.6 christos *errmsg = "Suffix SUFFIX_COND ignored"; 795 1.6 christos 796 1.6 christos INSERT_XOP (q, einsn->name, 797 1.6 christos INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor) 798 1.6 christos | (0x01 << 22), MINSN2OP_0L, arc_target, arg_none, lflags_f); 799 1.6 christos } 800 1.6 christos else 801 1.6 christos { 802 1.6 christos *errmsg = "Unknown syntax"; 803 1.6 christos return NULL; 804 1.6 christos } 805 1.6 christos 806 1.6 christos /* End marker. */ 807 1.6 christos memset (q, 0, sizeof (*arc_ext_opcodes)); 808 1.6 christos 809 1.6 christos return arc_ext_opcodes; 810 1.6 christos } 811