1/* Fujitsu FRV opcode support, for GNU Binutils. -*- C -*- 2 3 Copyright 2000, 2001, 2003, 2004 Free Software Foundation, Inc. 4 5 Contributed by Red Hat Inc; developed under contract from Fujitsu. 6 7 This file is part of the GNU Binutils. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 23*/ 24 25/* This file is an addendum to frv.cpu. Heavy use of C code isn't 26 appropriate in .cpu files, so it resides here. This especially applies 27 to assembly/disassembly where parsing/printing can be quite involved. 28 Such things aren't really part of the specification of the cpu, per se, 29 so .cpu files provide the general framework and .opc files handle the 30 nitty-gritty details as necessary. 31 32 Each section is delimited with start and end markers. 33 34 <arch>-opc.h additions use: "-- opc.h" 35 <arch>-opc.c additions use: "-- opc.c" 36 <arch>-asm.c additions use: "-- asm.c" 37 <arch>-dis.c additions use: "-- dis.c" 38 <arch>-ibd.h additions use: "-- ibd.h" 39*/ 40 41/* -- opc.h */ 42 43#undef CGEN_DIS_HASH_SIZE 44#define CGEN_DIS_HASH_SIZE 128 45#undef CGEN_DIS_HASH 46#define CGEN_DIS_HASH(buffer, value) (((value) >> 18) & 127) 47 48/* Allows reason codes to be output when assembler errors occur. */ 49#define CGEN_VERBOSE_ASSEMBLER_ERRORS 50 51/* Vliw support. */ 52#define FRV_VLIW_SIZE 8 /* fr550 has largest vliw size of 8. */ 53#define PAD_VLIW_COMBO ,UNIT_NIL,UNIT_NIL,UNIT_NIL,UNIT_NIL 54typedef CGEN_ATTR_VALUE_TYPE VLIW_COMBO[FRV_VLIW_SIZE]; 55 56typedef struct 57{ 58 int next_slot; 59 int constraint_violation; 60 unsigned long mach; 61 unsigned long elf_flags; 62 CGEN_ATTR_VALUE_TYPE *unit_mapping; 63 VLIW_COMBO *current_vliw; 64 CGEN_ATTR_VALUE_TYPE major[FRV_VLIW_SIZE]; 65 const CGEN_INSN* insn[FRV_VLIW_SIZE]; 66} FRV_VLIW; 67 68int frv_is_branch_major PARAMS ((CGEN_ATTR_VALUE_TYPE, unsigned long)); 69int frv_is_float_major PARAMS ((CGEN_ATTR_VALUE_TYPE, unsigned long)); 70int frv_is_media_major PARAMS ((CGEN_ATTR_VALUE_TYPE, unsigned long)); 71int frv_is_branch_insn PARAMS ((const CGEN_INSN *)); 72int frv_is_float_insn PARAMS ((const CGEN_INSN *)); 73int frv_is_media_insn PARAMS ((const CGEN_INSN *)); 74void frv_vliw_reset PARAMS ((FRV_VLIW *, unsigned long mach, unsigned long elf_flags)); 75int frv_vliw_add_insn PARAMS ((FRV_VLIW *, const CGEN_INSN *)); 76int spr_valid PARAMS ((long)); 77/* -- */ 78 79/* -- opc.c */ 80#include "elf/frv.h" 81#include <stdio.h> 82 83static int match_unit 84 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE, CGEN_ATTR_VALUE_TYPE)); 85static int match_vliw 86 PARAMS ((VLIW_COMBO *, VLIW_COMBO *, int)); 87static VLIW_COMBO * add_next_to_vliw 88 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE)); 89static int find_major_in_vliw 90 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE)); 91static int fr400_check_insn_major_constraints 92 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE)); 93static int fr500_check_insn_major_constraints 94 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE)); 95static int fr550_check_insn_major_constraints 96 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE, const CGEN_INSN *)); 97static int check_insn_major_constraints 98 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE, const CGEN_INSN *)); 99 100int 101frv_is_branch_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach) 102{ 103 switch (mach) 104 { 105 case bfd_mach_fr400: 106 if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6) 107 return 1; /* is a branch */ 108 break; 109 default: 110 if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6) 111 return 1; /* is a branch */ 112 break; 113 } 114 115 return 0; /* not a branch */ 116} 117 118int 119frv_is_float_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach) 120{ 121 switch (mach) 122 { 123 case bfd_mach_fr400: 124 return 0; /* No float insns */ 125 default: 126 if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8) 127 return 1; /* is a float insn */ 128 break; 129 } 130 131 return 0; /* not a branch */ 132} 133 134int 135frv_is_media_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach) 136{ 137 switch (mach) 138 { 139 case bfd_mach_fr400: 140 if (major >= FR400_MAJOR_M_1 && major <= FR400_MAJOR_M_2) 141 return 1; /* is a media insn */ 142 break; 143 default: 144 if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8) 145 return 1; /* is a media insn */ 146 break; 147 } 148 149 return 0; /* not a branch */ 150} 151 152int 153frv_is_branch_insn (const CGEN_INSN *insn) 154{ 155 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR), 156 bfd_mach_fr400)) 157 return 1; 158 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR), 159 bfd_mach_fr500)) 160 return 1; 161 162 return 0; 163} 164 165int 166frv_is_float_insn (const CGEN_INSN *insn) 167{ 168 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR), 169 bfd_mach_fr400)) 170 return 1; 171 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR), 172 bfd_mach_fr500)) 173 return 1; 174 175 return 0; 176} 177 178int 179frv_is_media_insn (const CGEN_INSN *insn) 180{ 181 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR), 182 bfd_mach_fr400)) 183 return 1; 184 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR), 185 bfd_mach_fr500)) 186 return 1; 187 188 return 0; 189} 190 191/* This table represents the allowable packing for vliw insns for the fr400. 192 The fr400 has only 2 vliw slots. Represent this by not allowing any insns 193 in the extra slots. 194 Subsets of any given row are also allowed. */ 195static VLIW_COMBO fr400_allowed_vliw[] = 196{ 197 /* slot0 slot1 slot2 slot3 */ 198 { UNIT_I0, UNIT_I1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 199 { UNIT_I0, UNIT_FM0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 200 { UNIT_I0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 201 { UNIT_FM0, UNIT_FM1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 202 { UNIT_FM0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 203 { UNIT_B0, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 204 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 205 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO } 206}; 207 208/* This table represents the allowable packing for vliw insns for the fr500. 209 The fr500 has only 4 vliw slots. Represent this by not allowing any insns 210 in the extra slots. 211 Subsets of any given row are also allowed. */ 212static VLIW_COMBO fr500_allowed_vliw[] = 213{ 214 /* slot0 slot1 slot2 slot3 */ 215 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1 PAD_VLIW_COMBO }, 216 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0 PAD_VLIW_COMBO }, 217 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0 PAD_VLIW_COMBO }, 218 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO }, 219 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO }, 220 { UNIT_I0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO }, 221 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO }, 222 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO }, 223 { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 224 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 225 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO } 226}; 227 228/* This table represents the allowable packing for vliw insns for the fr550. 229 Subsets of any given row are also allowed. */ 230static VLIW_COMBO fr550_allowed_vliw[] = 231{ 232 /* slot0 slot1 slot2 slot3 slot4 slot5 slot6 slot7 */ 233 { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL }, 234 { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL }, 235 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 236 { UNIT_I0, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 237 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_FM3 }, 238 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_B0 }, 239 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_FM3, UNIT_B0 }, 240 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_B0, UNIT_B1 }, 241 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 }, 242 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL }, 243 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 }, 244 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 }, 245 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL }, 246 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL }, 247 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1, UNIT_NIL }, 248 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL }, 249 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 250 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL }, 251 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL }, 252 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 253 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 254 { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 255 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 256 { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL }, 257 { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 258 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 259 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 260 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL } 261}; 262 263/* Some insns are assigned specialized implementation units which map to 264 different actual implementation units on different machines. These 265 tables perform that mapping. */ 266static CGEN_ATTR_VALUE_TYPE fr400_unit_mapping[] = 267{ 268/* unit in insn actual unit */ 269/* NIL */ UNIT_NIL, 270/* I0 */ UNIT_I0, 271/* I1 */ UNIT_I1, 272/* I01 */ UNIT_I01, 273/* I2 */ UNIT_NIL, /* no I2 or I3 unit */ 274/* I3 */ UNIT_NIL, 275/* IALL */ UNIT_I01, /* only I0 and I1 units */ 276/* FM0 */ UNIT_FM0, 277/* FM1 */ UNIT_FM1, 278/* FM01 */ UNIT_FM01, 279/* FM2 */ UNIT_NIL, /* no F2 or M2 units */ 280/* FM3 */ UNIT_NIL, /* no F3 or M3 units */ 281/* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */ 282/* FMLOW */ UNIT_FM0, /* Only F0,M0 units */ 283/* B0 */ UNIT_B0, /* branches only in B0 unit. */ 284/* B1 */ UNIT_B0, 285/* B01 */ UNIT_B0, 286/* C */ UNIT_C, 287/* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */ 288/* IACC */ UNIT_I01, /* iacc multiply in I0 or I1 unit. */ 289/* LOAD */ UNIT_I0, /* load only in I0 unit. */ 290/* STORE */ UNIT_I0, /* store only in I0 unit. */ 291/* SCAN */ UNIT_I0, /* scan only in I0 unit. */ 292/* DCPL */ UNIT_C, /* dcpl only in C unit. */ 293/* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */ 294/* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */ 295}; 296 297static CGEN_ATTR_VALUE_TYPE fr500_unit_mapping[] = 298{ 299/* unit in insn actual unit */ 300/* NIL */ UNIT_NIL, 301/* I0 */ UNIT_I0, 302/* I1 */ UNIT_I1, 303/* I01 */ UNIT_I01, 304/* I2 */ UNIT_NIL, /* no I2 or I3 unit */ 305/* I3 */ UNIT_NIL, 306/* IALL */ UNIT_I01, /* only I0 and I1 units */ 307/* FM0 */ UNIT_FM0, 308/* FM1 */ UNIT_FM1, 309/* FM01 */ UNIT_FM01, 310/* FM2 */ UNIT_NIL, /* no F2 or M2 units */ 311/* FM3 */ UNIT_NIL, /* no F3 or M2 units */ 312/* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */ 313/* FMLOW */ UNIT_FM0, /* Only F0,M0 units */ 314/* B0 */ UNIT_B0, 315/* B1 */ UNIT_B1, 316/* B01 */ UNIT_B01, 317/* C */ UNIT_C, 318/* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */ 319/* IACC */ UNIT_NIL, /* iacc multiply not implemented */ 320/* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */ 321/* STORE */ UNIT_I0, /* store only in I0 unit. */ 322/* SCAN */ UNIT_I01, /* scan in I0 or I1 unit. */ 323/* DCPL */ UNIT_C, /* dcpl only in C unit. */ 324/* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */ 325/* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */ 326}; 327 328static CGEN_ATTR_VALUE_TYPE fr550_unit_mapping[] = 329{ 330/* unit in insn actual unit */ 331/* NIL */ UNIT_NIL, 332/* I0 */ UNIT_I0, 333/* I1 */ UNIT_I1, 334/* I01 */ UNIT_I01, 335/* I2 */ UNIT_I2, 336/* I3 */ UNIT_I3, 337/* IALL */ UNIT_IALL, 338/* FM0 */ UNIT_FM0, 339/* FM1 */ UNIT_FM1, 340/* FM01 */ UNIT_FM01, 341/* FM2 */ UNIT_FM2, 342/* FM3 */ UNIT_FM3, 343/* FMALL */ UNIT_FMALL, 344/* FMLOW */ UNIT_FM01, /* Only F0,F1,M0,M1 units */ 345/* B0 */ UNIT_B0, 346/* B1 */ UNIT_B1, 347/* B01 */ UNIT_B01, 348/* C */ UNIT_C, 349/* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */ 350/* IACC */ UNIT_NIL, /* iacc multiply not implemented. */ 351/* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */ 352/* STORE */ UNIT_I01, /* store in I0 or I1 unit. */ 353/* SCAN */ UNIT_IALL, /* scan in any integer unit. */ 354/* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */ 355/* MDUALACC */ UNIT_FMALL,/* media dual acc insn in all media units */ 356/* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */ 357}; 358 359void 360frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags) 361{ 362 vliw->next_slot = 0; 363 vliw->constraint_violation = 0; 364 vliw->mach = mach; 365 vliw->elf_flags = elf_flags; 366 367 switch (mach) 368 { 369 case bfd_mach_fr400: 370 vliw->current_vliw = fr400_allowed_vliw; 371 vliw->unit_mapping = fr400_unit_mapping; 372 break; 373 case bfd_mach_fr550: 374 vliw->current_vliw = fr550_allowed_vliw; 375 vliw->unit_mapping = fr550_unit_mapping; 376 break; 377 default: 378 vliw->current_vliw = fr500_allowed_vliw; 379 vliw->unit_mapping = fr500_unit_mapping; 380 break; 381 } 382} 383 384/* Return 1 if unit1 is a match for unit2. 385 Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the 386 *_allowed_vliw tables above. */ 387static int 388match_unit (FRV_VLIW *vliw, 389 CGEN_ATTR_VALUE_TYPE unit1, CGEN_ATTR_VALUE_TYPE unit2) 390{ 391 /* Map any specialized implementation units to actual ones. */ 392 unit1 = vliw->unit_mapping[unit1]; 393 394 if (unit1 == unit2) 395 return 1; 396 if (unit1 < unit2) 397 return 0; 398 399 switch (unit1) 400 { 401 case UNIT_I01: 402 case UNIT_FM01: 403 case UNIT_B01: 404 /* The 01 versions of these units are within 2 enums of the 0 or 1 405 versions. */ 406 if (unit1 - unit2 <= 2) 407 return 1; 408 break; 409 case UNIT_IALL: 410 case UNIT_FMALL: 411 /* The ALL versions of these units are within 5 enums of the 0, 1, 2 or 3 412 versions. */ 413 if (unit1 - unit2 <= 5) 414 return 1; 415 break; 416 default: 417 break; 418 } 419 420 return 0; 421} 422 423/* Return 1 if the vliws match, 0 otherwise. */ 424 425static int 426match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size) 427{ 428 int i; 429 430 for (i = 0; i < vliw_size; ++i) 431 { 432 if ((*vliw1)[i] != (*vliw2)[i]) 433 return 0; 434 } 435 436 return 1; 437} 438 439/* Find the next vliw vliw in the table that can accomodate the new insn. 440 If one is found then return it. Otherwise return NULL. */ 441 442static VLIW_COMBO * 443add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit) 444{ 445 int next = vliw->next_slot; 446 VLIW_COMBO *current = vliw->current_vliw; 447 VLIW_COMBO *potential; 448 449 if (next <= 0) 450 { 451 fprintf (stderr, "frv-opc.c line %d: bad vliw->next_slot value.\n", 452 __LINE__); 453 abort (); /* Should never happen */ 454 } 455 456 /* The table is sorted by units allowed within slots, so vliws with 457 identical starting sequences are together. */ 458 potential = current; 459 do 460 { 461 if (match_unit (vliw, unit, (*potential)[next])) 462 return potential; 463 ++potential; 464 } 465 while (match_vliw (potential, current, next)); 466 467 return NULL; 468} 469 470/* Look for the given major insn type in the given vliw. Return 1 if found, 471 return 0 otherwise. */ 472 473static int 474find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major) 475{ 476 int i; 477 478 for (i = 0; i < vliw->next_slot; ++i) 479 if (vliw->major[i] == major) 480 return 1; 481 482 return 0; 483} 484 485/* Check for constraints between the insns in the vliw due to major insn 486 types. */ 487 488static int 489fr400_check_insn_major_constraints ( 490 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major 491) 492{ 493 /* In the cpu file, all media insns are represented as being allowed in 494 both media units. This makes it easier since this is the case for fr500. 495 Catch the invalid combinations here. Insns of major class FR400_MAJOR_M_2 496 cannot coexist with any other media insn in a vliw. */ 497 switch (major) 498 { 499 case FR400_MAJOR_M_2: 500 return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1) 501 && ! find_major_in_vliw (vliw, FR400_MAJOR_M_2); 502 default: 503 break; 504 } 505 return 1; 506} 507 508static int 509find_unit_in_vliw ( 510 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit 511) 512{ 513 int i; 514 for (i = 0; i < vliw->next_slot; ++i) 515 if (CGEN_INSN_ATTR_VALUE (vliw->insn[i], CGEN_INSN_UNIT) == unit) 516 return 1; 517 518 return 0; /* not found */ 519} 520 521static int 522find_major_in_slot ( 523 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major, CGEN_ATTR_VALUE_TYPE slot 524) 525{ 526 int i; 527 528 for (i = 0; i < vliw->next_slot; ++i) 529 if (vliw->major[i] == major && (*vliw->current_vliw)[i] == slot) 530 return 1; 531 532 return 0; 533} 534 535static int 536fr550_find_media_in_vliw (FRV_VLIW *vliw) 537{ 538 int i; 539 540 for (i = 0; i < vliw->next_slot; ++i) 541 { 542 if (vliw->major[i] < FR550_MAJOR_M_1 || vliw->major[i] > FR550_MAJOR_M_5) 543 continue; 544 545 /* Found a media insn, however, MNOP and MCLRACC don't count. */ 546 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MNOP 547 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_0 548 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_1) 549 continue; 550 551 return 1; /* found one */ 552 } 553 554 return 0; 555} 556 557static int 558fr550_find_float_in_vliw (FRV_VLIW *vliw) 559{ 560 int i; 561 562 for (i = 0; i < vliw->next_slot; ++i) 563 { 564 if (vliw->major[i] < FR550_MAJOR_F_1 || vliw->major[i] > FR550_MAJOR_F_4) 565 continue; 566 567 /* Found a floating point insn, however, FNOP doesn't count. */ 568 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_FNOP) 569 continue; 570 571 return 1; /* found one */ 572 } 573 574 return 0; 575} 576 577static int 578fr550_check_insn_major_constraints ( 579 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major, const CGEN_INSN *insn 580) 581{ 582 CGEN_ATTR_VALUE_TYPE unit; 583 CGEN_ATTR_VALUE_TYPE slot = (*vliw->current_vliw)[vliw->next_slot]; 584 switch (slot) 585 { 586 case UNIT_I2: 587 /* If it's a store, then there must be another store in I1 */ 588 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT); 589 if (unit == UNIT_STORE) 590 return find_unit_in_vliw (vliw, UNIT_STORE); 591 break; 592 case UNIT_FM2: 593 case UNIT_FM3: 594 /* Floating point insns other than FNOP in slot f2 or f3 cannot coexist with 595 media insns. */ 596 if (major >= FR550_MAJOR_F_1 && major <= FR550_MAJOR_F_4 597 && CGEN_INSN_NUM (insn) != FRV_INSN_FNOP) 598 return ! fr550_find_media_in_vliw (vliw); 599 /* Media insns other than MNOP in slot m2 or m3 cannot coexist with 600 floating point insns. */ 601 if (major >= FR550_MAJOR_M_1 && major <= FR550_MAJOR_M_5 602 && CGEN_INSN_NUM (insn) != FRV_INSN_MNOP) 603 return ! fr550_find_float_in_vliw (vliw); 604 /* F-2 in slot f2 or f3 cannot coexist with F-2 or F-4 in slot f1 or f2 605 respectively. 606 */ 607 if (major == FR550_MAJOR_F_2) 608 return ! find_major_in_slot (vliw, FR550_MAJOR_F_2, slot - (UNIT_FM2 - UNIT_FM0)) 609 && ! find_major_in_slot (vliw, FR550_MAJOR_F_4, slot - (UNIT_FM2 - UNIT_FM0)); 610 /* M-2 or M-5 in slot m2 or m3 cannot coexist with M-2 in slot m1 or m2 611 respectively. */ 612 if (major == FR550_MAJOR_M_2 || major == FR550_MAJOR_M_5) 613 return ! find_major_in_slot (vliw, FR550_MAJOR_M_2, slot - (UNIT_FM2 - UNIT_FM0)); 614 /* M-4 in slot m2 or m3 cannot coexist with M-4 in slot m1 or m2 615 respectively. */ 616 if (major == FR550_MAJOR_M_4) 617 return ! find_major_in_slot (vliw, FR550_MAJOR_M_4, slot - (UNIT_FM2 - UNIT_FM0)); 618 break; 619 default: 620 break; 621 } 622 return 1; /* all ok */ 623} 624 625static int 626fr500_check_insn_major_constraints ( 627 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major 628) 629{ 630 /* TODO: A table might be faster for some of the more complex instances 631 here. */ 632 switch (major) 633 { 634 case FR500_MAJOR_I_1: 635 case FR500_MAJOR_I_4: 636 case FR500_MAJOR_I_5: 637 case FR500_MAJOR_I_6: 638 case FR500_MAJOR_B_1: 639 case FR500_MAJOR_B_2: 640 case FR500_MAJOR_B_3: 641 case FR500_MAJOR_B_4: 642 case FR500_MAJOR_B_5: 643 case FR500_MAJOR_B_6: 644 case FR500_MAJOR_F_4: 645 case FR500_MAJOR_F_8: 646 case FR500_MAJOR_M_8: 647 return 1; /* OK */ 648 case FR500_MAJOR_I_2: 649 /* Cannot coexist with I-3 insn. */ 650 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3); 651 case FR500_MAJOR_I_3: 652 /* Cannot coexist with I-2 insn. */ 653 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2); 654 case FR500_MAJOR_F_1: 655 case FR500_MAJOR_F_2: 656 /* Cannot coexist with F-5, F-6, or M-7 insn. */ 657 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5) 658 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6) 659 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 660 case FR500_MAJOR_F_3: 661 /* Cannot coexist with F-7, or M-7 insn. */ 662 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7) 663 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 664 case FR500_MAJOR_F_5: 665 /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn. */ 666 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1) 667 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2) 668 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6) 669 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7) 670 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 671 case FR500_MAJOR_F_6: 672 /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn. */ 673 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1) 674 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2) 675 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5) 676 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6) 677 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 678 case FR500_MAJOR_F_7: 679 /* Cannot coexist with F-3, F-5, F-7, or M-7 insn. */ 680 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3) 681 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5) 682 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7) 683 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 684 case FR500_MAJOR_M_1: 685 /* Cannot coexist with M-7 insn. */ 686 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 687 case FR500_MAJOR_M_2: 688 case FR500_MAJOR_M_3: 689 /* Cannot coexist with M-5, M-6 or M-7 insn. */ 690 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5) 691 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6) 692 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 693 case FR500_MAJOR_M_4: 694 /* Cannot coexist with M-6 insn. */ 695 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6); 696 case FR500_MAJOR_M_5: 697 /* Cannot coexist with M-2, M-3, M-5, M-6 or M-7 insn. */ 698 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2) 699 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3) 700 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5) 701 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6) 702 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 703 case FR500_MAJOR_M_6: 704 /* Cannot coexist with M-2, M-3, M-4, M-5, M-6 or M-7 insn. */ 705 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2) 706 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3) 707 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_4) 708 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5) 709 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6) 710 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 711 case FR500_MAJOR_M_7: 712 /* Cannot coexist with M-1, M-2, M-3, M-5, M-6 or M-7 insn. */ 713 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1) 714 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_2) 715 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3) 716 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5) 717 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6) 718 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7) 719 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_1) 720 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2) 721 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_3) 722 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5) 723 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6) 724 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7); 725 default: 726 fprintf (stderr, "frv-opc.c, line %d: bad major code, aborting.\n", 727 __LINE__); 728 abort (); 729 break; 730 } 731 return 1; 732} 733 734static int 735check_insn_major_constraints ( 736 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major, const CGEN_INSN *insn 737) 738{ 739 int rc; 740 switch (vliw->mach) 741 { 742 case bfd_mach_fr400: 743 rc = fr400_check_insn_major_constraints (vliw, major); 744 break; 745 case bfd_mach_fr550: 746 rc = fr550_check_insn_major_constraints (vliw, major, insn); 747 break; 748 default: 749 rc = fr500_check_insn_major_constraints (vliw, major); 750 break; 751 } 752 return rc; 753} 754 755/* Add in insn to the VLIW vliw if possible. Return 0 if successful, 756 non-zero otherwise. */ 757int 758frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn) 759{ 760 int index; 761 CGEN_ATTR_VALUE_TYPE major; 762 CGEN_ATTR_VALUE_TYPE unit; 763 VLIW_COMBO *new_vliw; 764 765 if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn)) 766 return 1; 767 768 index = vliw->next_slot; 769 if (index >= FRV_VLIW_SIZE) 770 return 1; 771 772 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT); 773 if (unit == UNIT_NIL) 774 { 775 fprintf (stderr, "frv-opc.c line %d: bad insn unit.\n", 776 __LINE__); 777 abort (); /* no UNIT specified for this insn in frv.cpu */ 778 } 779 780 switch (vliw->mach) 781 { 782 case bfd_mach_fr400: 783 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR); 784 break; 785 case bfd_mach_fr550: 786 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR550_MAJOR); 787 break; 788 default: 789 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR); 790 break; 791 } 792 793 if (index <= 0) 794 { 795 /* Any insn can be added to slot 0. */ 796 while (! match_unit (vliw, unit, (*vliw->current_vliw)[0])) 797 ++vliw->current_vliw; 798 vliw->major[0] = major; 799 vliw->insn[0] = insn; 800 vliw->next_slot = 1; 801 return 0; 802 } 803 804 /* If there are already insns in the vliw(s) check to see that 805 this one can be added. Do this by finding an allowable vliw 806 combination that can accept the new insn. */ 807 if (! (vliw->elf_flags & EF_FRV_NOPACK)) 808 { 809 new_vliw = add_next_to_vliw (vliw, unit); 810 if (new_vliw && check_insn_major_constraints (vliw, major, insn)) 811 { 812 vliw->current_vliw = new_vliw; 813 vliw->major[index] = major; 814 vliw->insn[index] = insn; 815 vliw->next_slot++; 816 return 0; 817 } 818 819 /* The frv machine supports all packing conbinations. If we fail, 820 to add the insn, then it could not be handled as if it was the fr500. 821 Just return as if it was handled ok. */ 822 if (vliw->mach == bfd_mach_frv) 823 return 0; 824 } 825 826 vliw->constraint_violation = 1; 827 return 1; 828} 829 830int 831spr_valid (regno) 832 long regno; 833{ 834 if (regno < 0) return 0; 835 if (regno <= 4095) return 1; 836 return 0; 837} 838/* -- */ 839 840/* -- asm.c */ 841static const char * parse_ulo16 842 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *)); 843static const char * parse_uslo16 844 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *)); 845static const char * parse_uhi16 846 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *)); 847static long parse_register_number 848 PARAMS ((const char **)); 849static const char * parse_spr 850 PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *)); 851static const char * parse_d12 852 PARAMS ((CGEN_CPU_DESC, const char **, int, long *)); 853static const char * parse_s12 854 PARAMS ((CGEN_CPU_DESC, const char **, int, long *)); 855static const char * parse_u12 856 PARAMS ((CGEN_CPU_DESC, const char **, int, long *)); 857static const char * parse_even_register 858 PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *)); 859static const char * parse_A0 860 PARAMS ((CGEN_CPU_DESC, const char **, int, long *)); 861static const char * parse_A1 862 PARAMS ((CGEN_CPU_DESC, const char **, int, long *)); 863static const char * parse_A 864 PARAMS ((CGEN_CPU_DESC, const char **, int, long *, long)); 865 866static const char * 867parse_ulo16 (cd, strp, opindex, valuep) 868 CGEN_CPU_DESC cd; 869 const char **strp; 870 int opindex; 871 unsigned long *valuep; 872{ 873 const char *errmsg; 874 enum cgen_parse_operand_result result_type; 875 bfd_vma value; 876 877 if (**strp == '#' || **strp == '%') 878 { 879 if (strncasecmp (*strp + 1, "lo(", 3) == 0) 880 { 881 *strp += 4; 882 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16, 883 &result_type, &value); 884 if (**strp != ')') 885 return "missing `)'"; 886 ++*strp; 887 if (errmsg == NULL 888 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 889 value &= 0xffff; 890 *valuep = value; 891 return errmsg; 892 } 893 if (strncasecmp (*strp + 1, "gprello(", 8) == 0) 894 { 895 *strp += 9; 896 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO, 897 &result_type, &value); 898 if (**strp != ')') 899 return "missing ')'"; 900 ++*strp; 901 if (errmsg == NULL 902 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 903 value &= 0xffff; 904 *valuep = value; 905 return errmsg; 906 } 907 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0) 908 { 909 *strp += 7; 910 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTLO, 911 &result_type, &value); 912 if (**strp != ')') 913 return "missing ')'"; 914 ++*strp; 915 if (errmsg == NULL 916 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 917 value &= 0xffff; 918 *valuep = value; 919 return errmsg; 920 } 921 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0) 922 { 923 *strp += 15; 924 errmsg = cgen_parse_address (cd, strp, opindex, 925 BFD_RELOC_FRV_FUNCDESC_GOTLO, 926 &result_type, &value); 927 if (**strp != ')') 928 return "missing ')'"; 929 ++*strp; 930 if (errmsg == NULL 931 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 932 value &= 0xffff; 933 *valuep = value; 934 return errmsg; 935 } 936 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0) 937 { 938 *strp += 10; 939 errmsg = cgen_parse_address (cd, strp, opindex, 940 BFD_RELOC_FRV_GOTOFFLO, 941 &result_type, &value); 942 if (**strp != ')') 943 return "missing ')'"; 944 ++*strp; 945 if (errmsg == NULL 946 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 947 value &= 0xffff; 948 *valuep = value; 949 return errmsg; 950 } 951 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0) 952 { 953 *strp += 18; 954 errmsg = cgen_parse_address (cd, strp, opindex, 955 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO, 956 &result_type, &value); 957 if (**strp != ')') 958 return "missing ')'"; 959 ++*strp; 960 if (errmsg == NULL 961 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 962 value &= 0xffff; 963 *valuep = value; 964 return errmsg; 965 } 966 } 967 return cgen_parse_signed_integer (cd, strp, opindex, valuep); 968} 969 970static const char * 971parse_uslo16 (cd, strp, opindex, valuep) 972 CGEN_CPU_DESC cd; 973 const char **strp; 974 int opindex; 975 unsigned long *valuep; 976{ 977 const char *errmsg; 978 enum cgen_parse_operand_result result_type; 979 bfd_vma value; 980 981 if (**strp == '#' || **strp == '%') 982 { 983 if (strncasecmp (*strp + 1, "lo(", 3) == 0) 984 { 985 *strp += 4; 986 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16, 987 &result_type, &value); 988 if (**strp != ')') 989 return "missing `)'"; 990 ++*strp; 991 if (errmsg == NULL 992 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 993 value &= 0xffff; 994 *valuep = value; 995 return errmsg; 996 } 997 else if (strncasecmp (*strp + 1, "gprello(", 8) == 0) 998 { 999 *strp += 9; 1000 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO, 1001 &result_type, &value); 1002 if (**strp != ')') 1003 return "missing ')'"; 1004 ++*strp; 1005 if (errmsg == NULL 1006 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 1007 value &= 0xffff; 1008 *valuep = value; 1009 return errmsg; 1010 } 1011 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0) 1012 { 1013 *strp += 7; 1014 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTLO, 1015 &result_type, &value); 1016 if (**strp != ')') 1017 return "missing ')'"; 1018 ++*strp; 1019 if (errmsg == NULL 1020 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 1021 value &= 0xffff; 1022 *valuep = value; 1023 return errmsg; 1024 } 1025 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0) 1026 { 1027 *strp += 15; 1028 errmsg = cgen_parse_address (cd, strp, opindex, 1029 BFD_RELOC_FRV_FUNCDESC_GOTLO, 1030 &result_type, &value); 1031 if (**strp != ')') 1032 return "missing ')'"; 1033 ++*strp; 1034 if (errmsg == NULL 1035 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 1036 value &= 0xffff; 1037 *valuep = value; 1038 return errmsg; 1039 } 1040 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0) 1041 { 1042 *strp += 10; 1043 errmsg = cgen_parse_address (cd, strp, opindex, 1044 BFD_RELOC_FRV_GOTOFFLO, 1045 &result_type, &value); 1046 if (**strp != ')') 1047 return "missing ')'"; 1048 ++*strp; 1049 if (errmsg == NULL 1050 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 1051 value &= 0xffff; 1052 *valuep = value; 1053 return errmsg; 1054 } 1055 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0) 1056 { 1057 *strp += 18; 1058 errmsg = cgen_parse_address (cd, strp, opindex, 1059 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO, 1060 &result_type, &value); 1061 if (**strp != ')') 1062 return "missing ')'"; 1063 ++*strp; 1064 if (errmsg == NULL 1065 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 1066 value &= 0xffff; 1067 *valuep = value; 1068 return errmsg; 1069 } 1070 } 1071 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 1072} 1073 1074static const char * 1075parse_uhi16 (cd, strp, opindex, valuep) 1076 CGEN_CPU_DESC cd; 1077 const char **strp; 1078 int opindex; 1079 unsigned long *valuep; 1080{ 1081 const char *errmsg; 1082 enum cgen_parse_operand_result result_type; 1083 bfd_vma value; 1084 1085 if (**strp == '#' || **strp == '%') 1086 { 1087 if (strncasecmp (*strp + 1, "hi(", 3) == 0) 1088 { 1089 *strp += 4; 1090 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16, 1091 &result_type, &value); 1092 if (**strp != ')') 1093 return "missing `)'"; 1094 ++*strp; 1095 if (errmsg == NULL 1096 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 1097 value >>= 16; 1098 *valuep = value; 1099 return errmsg; 1100 } 1101 else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0) 1102 { 1103 *strp += 9; 1104 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELHI, 1105 &result_type, &value); 1106 if (**strp != ')') 1107 return "missing ')'"; 1108 ++*strp; 1109 if (errmsg == NULL 1110 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 1111 value >>= 16; 1112 *valuep = value; 1113 return errmsg; 1114 } 1115 else if (strncasecmp (*strp + 1, "gothi(", 6) == 0) 1116 { 1117 *strp += 7; 1118 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTHI, 1119 &result_type, &value); 1120 if (**strp != ')') 1121 return "missing ')'"; 1122 ++*strp; 1123 if (errmsg == NULL 1124 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 1125 value >>= 16; 1126 *valuep = value; 1127 return errmsg; 1128 } 1129 else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0) 1130 { 1131 *strp += 15; 1132 errmsg = cgen_parse_address (cd, strp, opindex, 1133 BFD_RELOC_FRV_FUNCDESC_GOTHI, 1134 &result_type, &value); 1135 if (**strp != ')') 1136 return "missing ')'"; 1137 ++*strp; 1138 if (errmsg == NULL 1139 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 1140 value >>= 16; 1141 *valuep = value; 1142 return errmsg; 1143 } 1144 else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0) 1145 { 1146 *strp += 10; 1147 errmsg = cgen_parse_address (cd, strp, opindex, 1148 BFD_RELOC_FRV_GOTOFFHI, 1149 &result_type, &value); 1150 if (**strp != ')') 1151 return "missing ')'"; 1152 ++*strp; 1153 if (errmsg == NULL 1154 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 1155 value >>= 16; 1156 *valuep = value; 1157 return errmsg; 1158 } 1159 else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0) 1160 { 1161 *strp += 18; 1162 errmsg = cgen_parse_address (cd, strp, opindex, 1163 BFD_RELOC_FRV_FUNCDESC_GOTOFFHI, 1164 &result_type, &value); 1165 if (**strp != ')') 1166 return "missing ')'"; 1167 ++*strp; 1168 if (errmsg == NULL 1169 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 1170 value >>= 16; 1171 *valuep = value; 1172 return errmsg; 1173 } 1174 } 1175 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 1176} 1177 1178static long 1179parse_register_number (strp) 1180 const char **strp; 1181{ 1182 int regno; 1183 if (**strp < '0' || **strp > '9') 1184 return -1; /* error */ 1185 1186 regno = **strp - '0'; 1187 for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp) 1188 regno = regno * 10 + (**strp - '0'); 1189 1190 return regno; 1191} 1192 1193static const char * 1194parse_spr (cd, strp, table, valuep) 1195 CGEN_CPU_DESC cd; 1196 const char **strp; 1197 CGEN_KEYWORD * table; 1198 long *valuep; 1199{ 1200 const char *save_strp; 1201 long regno; 1202 1203 /* Check for spr index notation. */ 1204 if (strncasecmp (*strp, "spr[", 4) == 0) 1205 { 1206 *strp += 4; 1207 regno = parse_register_number (strp); 1208 if (**strp != ']') 1209 return "missing `]'"; 1210 ++*strp; 1211 if (! spr_valid (regno)) 1212 return "Special purpose register number is out of range"; 1213 *valuep = regno; 1214 return NULL; 1215 } 1216 1217 save_strp = *strp; 1218 regno = parse_register_number (strp); 1219 if (regno != -1) 1220 { 1221 if (! spr_valid (regno)) 1222 return "Special purpose register number is out of range"; 1223 *valuep = regno; 1224 return NULL; 1225 } 1226 1227 *strp = save_strp; 1228 return cgen_parse_keyword (cd, strp, table, valuep); 1229} 1230 1231static const char * 1232parse_d12 (cd, strp, opindex, valuep) 1233 CGEN_CPU_DESC cd; 1234 const char **strp; 1235 int opindex; 1236 long *valuep; 1237{ 1238 const char *errmsg; 1239 enum cgen_parse_operand_result result_type; 1240 bfd_vma value; 1241 1242 /* Check for small data reference. */ 1243 if (**strp == '#' || **strp == '%') 1244 { 1245 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0) 1246 { 1247 *strp += 9; 1248 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12, 1249 &result_type, &value); 1250 if (**strp != ')') 1251 return "missing `)'"; 1252 ++*strp; 1253 *valuep = value; 1254 return errmsg; 1255 } 1256 else if (strncasecmp (*strp + 1, "got12(", 6) == 0) 1257 { 1258 *strp += 7; 1259 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOT12, 1260 &result_type, &value); 1261 if (**strp != ')') 1262 return "missing ')'"; 1263 ++*strp; 1264 *valuep = value; 1265 return errmsg; 1266 } 1267 else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0) 1268 { 1269 *strp += 15; 1270 errmsg = cgen_parse_address (cd, strp, opindex, 1271 BFD_RELOC_FRV_FUNCDESC_GOT12, 1272 &result_type, &value); 1273 if (**strp != ')') 1274 return "missing ')'"; 1275 ++*strp; 1276 *valuep = value; 1277 return errmsg; 1278 } 1279 else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0) 1280 { 1281 *strp += 10; 1282 errmsg = cgen_parse_address (cd, strp, opindex, 1283 BFD_RELOC_FRV_GOTOFF12, 1284 &result_type, &value); 1285 if (**strp != ')') 1286 return "missing ')'"; 1287 ++*strp; 1288 *valuep = value; 1289 return errmsg; 1290 } 1291 else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0) 1292 { 1293 *strp += 18; 1294 errmsg = cgen_parse_address (cd, strp, opindex, 1295 BFD_RELOC_FRV_FUNCDESC_GOTOFF12, 1296 &result_type, &value); 1297 if (**strp != ')') 1298 return "missing ')'"; 1299 ++*strp; 1300 *valuep = value; 1301 return errmsg; 1302 } 1303 } 1304 return cgen_parse_signed_integer (cd, strp, opindex, valuep); 1305} 1306 1307static const char * 1308parse_s12 (cd, strp, opindex, valuep) 1309 CGEN_CPU_DESC cd; 1310 const char **strp; 1311 int opindex; 1312 long *valuep; 1313{ 1314 const char *errmsg; 1315 enum cgen_parse_operand_result result_type; 1316 bfd_vma value; 1317 1318 /* Check for small data reference. */ 1319 if ((**strp == '#' || **strp == '%') 1320 && strncasecmp (*strp + 1, "gprel12(", 8) == 0) 1321 { 1322 *strp += 9; 1323 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12, 1324 &result_type, &value); 1325 if (**strp != ')') 1326 return "missing `)'"; 1327 ++*strp; 1328 *valuep = value; 1329 return errmsg; 1330 } 1331 else if ((**strp == '#' || **strp == '%') 1332 && strncasecmp (*strp + 1, "got12(", 6) == 0) 1333 { 1334 *strp += 7; 1335 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOT12, 1336 &result_type, &value); 1337 if (**strp != ')') 1338 return "missing ')'"; 1339 ++*strp; 1340 *valuep = value; 1341 return errmsg; 1342 } 1343 else if ((**strp == '#' || **strp == '%') 1344 && strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0) 1345 { 1346 *strp += 15; 1347 errmsg = cgen_parse_address (cd, strp, opindex, 1348 BFD_RELOC_FRV_FUNCDESC_GOT12, 1349 &result_type, &value); 1350 if (**strp != ')') 1351 return "missing ')'"; 1352 ++*strp; 1353 *valuep = value; 1354 return errmsg; 1355 } 1356 else if ((**strp == '#' || **strp == '%') 1357 && strncasecmp (*strp + 1, "gotoff12(", 9) == 0) 1358 { 1359 *strp += 10; 1360 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTOFF12, 1361 &result_type, &value); 1362 if (**strp != ')') 1363 return "missing ')'"; 1364 ++*strp; 1365 *valuep = value; 1366 return errmsg; 1367 } 1368 else if ((**strp == '#' || **strp == '%') 1369 && strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0) 1370 { 1371 *strp += 18; 1372 errmsg = cgen_parse_address (cd, strp, opindex, 1373 BFD_RELOC_FRV_FUNCDESC_GOTOFF12, 1374 &result_type, &value); 1375 if (**strp != ')') 1376 return "missing ')'"; 1377 ++*strp; 1378 *valuep = value; 1379 return errmsg; 1380 } 1381 else 1382 { 1383 if (**strp == '#') 1384 ++*strp; 1385 return cgen_parse_signed_integer (cd, strp, opindex, valuep); 1386 } 1387} 1388 1389static const char * 1390parse_u12 (cd, strp, opindex, valuep) 1391 CGEN_CPU_DESC cd; 1392 const char **strp; 1393 int opindex; 1394 long *valuep; 1395{ 1396 const char *errmsg; 1397 enum cgen_parse_operand_result result_type; 1398 bfd_vma value; 1399 1400 /* Check for small data reference. */ 1401 if ((**strp == '#' || **strp == '%') 1402 && strncasecmp (*strp + 1, "gprel12(", 8) == 0) 1403 { 1404 *strp += 9; 1405 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELU12, 1406 &result_type, &value); 1407 if (**strp != ')') 1408 return "missing `)'"; 1409 ++*strp; 1410 *valuep = value; 1411 return errmsg; 1412 } 1413 else 1414 { 1415 if (**strp == '#') 1416 ++*strp; 1417 return cgen_parse_signed_integer (cd, strp, opindex, valuep); 1418 } 1419} 1420 1421static const char * 1422parse_A (cd, strp, opindex, valuep, A) 1423 CGEN_CPU_DESC cd; 1424 const char **strp; 1425 int opindex; 1426 long *valuep; 1427 long A; 1428{ 1429 const char *errmsg; 1430 1431 if (**strp == '#') 1432 ++*strp; 1433 1434 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 1435 if (errmsg) 1436 return errmsg; 1437 1438 if (*valuep != A) 1439 return "Value of A operand must be 0 or 1"; 1440 1441 return NULL; 1442} 1443 1444static const char * 1445parse_A0 (cd, strp, opindex, valuep) 1446 CGEN_CPU_DESC cd; 1447 const char **strp; 1448 int opindex; 1449 long *valuep; 1450{ 1451 return parse_A (cd, strp, opindex, valuep, 0); 1452} 1453 1454static const char * 1455parse_A1 (cd, strp, opindex, valuep) 1456 CGEN_CPU_DESC cd; 1457 const char **strp; 1458 int opindex; 1459 long *valuep; 1460{ 1461 return parse_A (cd, strp, opindex, valuep, 1); 1462} 1463 1464static const char * 1465parse_even_register (cd, strP, tableP, valueP) 1466 CGEN_CPU_DESC cd; 1467 const char ** strP; 1468 CGEN_KEYWORD * tableP; 1469 long * valueP; 1470{ 1471 const char * errmsg; 1472 const char * saved_star_strP = * strP; 1473 1474 errmsg = cgen_parse_keyword (cd, strP, tableP, valueP); 1475 1476 if (errmsg == NULL && ((* valueP) & 1)) 1477 { 1478 errmsg = _("register number must be even"); 1479 * strP = saved_star_strP; 1480 } 1481 1482 return errmsg; 1483} 1484/* -- */ 1485 1486/* -- dis.c */ 1487static void print_spr 1488 PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned)); 1489static void print_hi 1490 PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int)); 1491static void print_lo 1492 PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int)); 1493 1494static void 1495print_spr (cd, dis_info, names, regno, attrs) 1496 CGEN_CPU_DESC cd; 1497 PTR dis_info; 1498 CGEN_KEYWORD *names; 1499 long regno; 1500 unsigned int attrs; 1501{ 1502 /* Use the register index format for any unnamed registers. */ 1503 if (cgen_keyword_lookup_value (names, regno) == NULL) 1504 { 1505 disassemble_info *info = (disassemble_info *) dis_info; 1506 (*info->fprintf_func) (info->stream, "spr[%ld]", regno); 1507 } 1508 else 1509 print_keyword (cd, dis_info, names, regno, attrs); 1510} 1511 1512static void 1513print_hi (cd, dis_info, value, attrs, pc, length) 1514 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED; 1515 PTR dis_info; 1516 long value; 1517 unsigned int attrs ATTRIBUTE_UNUSED; 1518 bfd_vma pc ATTRIBUTE_UNUSED; 1519 int length ATTRIBUTE_UNUSED; 1520{ 1521 disassemble_info *info = (disassemble_info *) dis_info; 1522 if (value) 1523 (*info->fprintf_func) (info->stream, "0x%lx", value); 1524 else 1525 (*info->fprintf_func) (info->stream, "hi(0x%lx)", value); 1526} 1527 1528static void 1529print_lo (cd, dis_info, value, attrs, pc, length) 1530 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED; 1531 PTR dis_info; 1532 long value; 1533 unsigned int attrs ATTRIBUTE_UNUSED; 1534 bfd_vma pc ATTRIBUTE_UNUSED; 1535 int length ATTRIBUTE_UNUSED; 1536{ 1537 disassemble_info *info = (disassemble_info *) dis_info; 1538 if (value) 1539 (*info->fprintf_func) (info->stream, "0x%lx", value); 1540 else 1541 (*info->fprintf_func) (info->stream, "lo(0x%lx)", value); 1542} 1543 1544/* -- */ 1545