1/* Fujitsu FRV opcode support, for GNU Binutils. -*- C -*- 2 3 Copyright 2000, 2001, 2003, 2004, 2005, 2007 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 3 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., 51 Franklin Street - Fifth Floor, Boston, 22 MA 02110-1301, USA. */ 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/* -- opc.h */ 41 42#undef CGEN_DIS_HASH_SIZE 43#define CGEN_DIS_HASH_SIZE 128 44#undef CGEN_DIS_HASH 45#define CGEN_DIS_HASH(buffer, value) (((value) >> 18) & 127) 46 47/* Allows reason codes to be output when assembler errors occur. */ 48#define CGEN_VERBOSE_ASSEMBLER_ERRORS 49 50/* Vliw support. */ 51#define FRV_VLIW_SIZE 8 /* fr550 has largest vliw size of 8. */ 52#define PAD_VLIW_COMBO ,UNIT_NIL,UNIT_NIL,UNIT_NIL,UNIT_NIL 53 54typedef CGEN_ATTR_VALUE_ENUM_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_ENUM_TYPE * unit_mapping; 63 VLIW_COMBO * current_vliw; 64 CGEN_ATTR_VALUE_ENUM_TYPE major[FRV_VLIW_SIZE]; 65 const CGEN_INSN * insn[FRV_VLIW_SIZE]; 66} FRV_VLIW; 67 68int frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long); 69int frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long); 70int frv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long); 71int frv_is_branch_insn (const CGEN_INSN *); 72int frv_is_float_insn (const CGEN_INSN *); 73int frv_is_media_insn (const CGEN_INSN *); 74void frv_vliw_reset (FRV_VLIW *, unsigned long, unsigned long); 75int frv_vliw_add_insn (FRV_VLIW *, const CGEN_INSN *); 76int spr_valid (long); 77/* -- */ 78 79/* -- opc.c */ 80#include "elf/frv.h" 81#include <stdio.h> 82 83/* Returns TRUE if {MAJOR,MACH} is a major branch of the FRV 84 development tree. */ 85 86bfd_boolean 87frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach) 88{ 89 switch (mach) 90 { 91 case bfd_mach_fr400: 92 if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6) 93 return TRUE; 94 break; 95 case bfd_mach_fr450: 96 if (major >= FR450_MAJOR_B_1 && major <= FR450_MAJOR_B_6) 97 return TRUE; 98 break; 99 default: 100 if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6) 101 return TRUE; 102 break; 103 } 104 105 return FALSE; 106} 107 108/* Returns TRUE if {MAJOR,MACH} supports floating point insns. */ 109 110bfd_boolean 111frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach) 112{ 113 switch (mach) 114 { 115 case bfd_mach_fr400: 116 case bfd_mach_fr450: 117 return FALSE; 118 default: 119 if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8) 120 return TRUE; 121 break; 122 } 123 124 return FALSE; 125} 126 127/* Returns TRUE if {MAJOR,MACH} supports media insns. */ 128 129bfd_boolean 130frv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach) 131{ 132 switch (mach) 133 { 134 case bfd_mach_fr400: 135 if (major >= FR400_MAJOR_M_1 && major <= FR400_MAJOR_M_2) 136 return TRUE; 137 break; 138 case bfd_mach_fr450: 139 if (major >= FR450_MAJOR_M_1 && major <= FR450_MAJOR_M_6) 140 return TRUE; 141 break; 142 default: 143 if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8) 144 return TRUE; 145 break; 146 } 147 148 return FALSE; 149} 150 151bfd_boolean 152frv_is_branch_insn (const CGEN_INSN *insn) 153{ 154 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR), 155 bfd_mach_fr400)) 156 return TRUE; 157 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR), 158 bfd_mach_fr450)) 159 return TRUE; 160 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR), 161 bfd_mach_fr500)) 162 return TRUE; 163 164 return FALSE; 165} 166 167bfd_boolean 168frv_is_float_insn (const CGEN_INSN *insn) 169{ 170 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR), 171 bfd_mach_fr400)) 172 return TRUE; 173 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR), 174 bfd_mach_fr450)) 175 return TRUE; 176 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR), 177 bfd_mach_fr500)) 178 return TRUE; 179 180 return FALSE; 181} 182 183bfd_boolean 184frv_is_media_insn (const CGEN_INSN *insn) 185{ 186 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR), 187 bfd_mach_fr400)) 188 return TRUE; 189 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR), 190 bfd_mach_fr450)) 191 return TRUE; 192 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR), 193 bfd_mach_fr500)) 194 return TRUE; 195 196 return FALSE; 197} 198 199/* This table represents the allowable packing for vliw insns for the fr400. 200 The fr400 has only 2 vliw slots. Represent this by not allowing any insns 201 in the extra slots. 202 Subsets of any given row are also allowed. */ 203static VLIW_COMBO fr400_allowed_vliw[] = 204{ 205 /* slot0 slot1 slot2 slot3 */ 206 { UNIT_I0, UNIT_I1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 207 { UNIT_I0, UNIT_FM0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 208 { UNIT_I0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 209 { UNIT_FM0, UNIT_FM1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 210 { UNIT_FM0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 211 { UNIT_B0, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 212 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 213 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO } 214}; 215 216/* This table represents the allowable packing for vliw insns for the fr500. 217 The fr500 has only 4 vliw slots. Represent this by not allowing any insns 218 in the extra slots. 219 Subsets of any given row are also allowed. */ 220static VLIW_COMBO fr500_allowed_vliw[] = 221{ 222 /* slot0 slot1 slot2 slot3 */ 223 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1 PAD_VLIW_COMBO }, 224 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0 PAD_VLIW_COMBO }, 225 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0 PAD_VLIW_COMBO }, 226 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO }, 227 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO }, 228 { UNIT_I0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO }, 229 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO }, 230 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO }, 231 { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 232 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 233 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO } 234}; 235 236/* This table represents the allowable packing for vliw insns for the fr550. 237 Subsets of any given row are also allowed. */ 238static VLIW_COMBO fr550_allowed_vliw[] = 239{ 240 /* slot0 slot1 slot2 slot3 slot4 slot5 slot6 slot7 */ 241 { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL }, 242 { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL }, 243 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 244 { UNIT_I0, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 245 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_FM3 }, 246 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_B0 }, 247 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_FM3, UNIT_B0 }, 248 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_B0, UNIT_B1 }, 249 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 }, 250 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL }, 251 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 }, 252 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 }, 253 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL }, 254 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL }, 255 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1, UNIT_NIL }, 256 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL }, 257 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 258 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL }, 259 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL }, 260 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 261 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 262 { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 263 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 264 { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL }, 265 { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 266 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 267 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 268 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL } 269}; 270 271/* Some insns are assigned specialized implementation units which map to 272 different actual implementation units on different machines. These 273 tables perform that mapping. */ 274static CGEN_ATTR_VALUE_ENUM_TYPE fr400_unit_mapping[] = 275{ 276/* unit in insn actual unit */ 277/* NIL */ UNIT_NIL, 278/* I0 */ UNIT_I0, 279/* I1 */ UNIT_I1, 280/* I01 */ UNIT_I01, 281/* I2 */ UNIT_NIL, /* no I2 or I3 unit */ 282/* I3 */ UNIT_NIL, 283/* IALL */ UNIT_I01, /* only I0 and I1 units */ 284/* FM0 */ UNIT_FM0, 285/* FM1 */ UNIT_FM1, 286/* FM01 */ UNIT_FM01, 287/* FM2 */ UNIT_NIL, /* no F2 or M2 units */ 288/* FM3 */ UNIT_NIL, /* no F3 or M3 units */ 289/* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */ 290/* FMLOW */ UNIT_FM0, /* Only F0,M0 units */ 291/* B0 */ UNIT_B0, /* branches only in B0 unit. */ 292/* B1 */ UNIT_B0, 293/* B01 */ UNIT_B0, 294/* C */ UNIT_C, 295/* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */ 296/* IACC */ UNIT_I01, /* iacc multiply in I0 or I1 unit. */ 297/* LOAD */ UNIT_I0, /* load only in I0 unit. */ 298/* STORE */ UNIT_I0, /* store only in I0 unit. */ 299/* SCAN */ UNIT_I0, /* scan only in I0 unit. */ 300/* DCPL */ UNIT_C, /* dcpl only in C unit. */ 301/* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */ 302/* MDCUTSSI */ UNIT_FM0, /* mdcutssi only in FM0 unit. */ 303/* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */ 304}; 305 306/* Some insns are assigned specialized implementation units which map to 307 different actual implementation units on different machines. These 308 tables perform that mapping. */ 309static CGEN_ATTR_VALUE_ENUM_TYPE fr450_unit_mapping[] = 310{ 311/* unit in insn actual unit */ 312/* NIL */ UNIT_NIL, 313/* I0 */ UNIT_I0, 314/* I1 */ UNIT_I1, 315/* I01 */ UNIT_I01, 316/* I2 */ UNIT_NIL, /* no I2 or I3 unit */ 317/* I3 */ UNIT_NIL, 318/* IALL */ UNIT_I01, /* only I0 and I1 units */ 319/* FM0 */ UNIT_FM0, 320/* FM1 */ UNIT_FM1, 321/* FM01 */ UNIT_FM01, 322/* FM2 */ UNIT_NIL, /* no F2 or M2 units */ 323/* FM3 */ UNIT_NIL, /* no F3 or M3 units */ 324/* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */ 325/* FMLOW */ UNIT_FM0, /* Only F0,M0 units */ 326/* B0 */ UNIT_B0, /* branches only in B0 unit. */ 327/* B1 */ UNIT_B0, 328/* B01 */ UNIT_B0, 329/* C */ UNIT_C, 330/* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */ 331/* IACC */ UNIT_I01, /* iacc multiply in I0 or I1 unit. */ 332/* LOAD */ UNIT_I0, /* load only in I0 unit. */ 333/* STORE */ UNIT_I0, /* store only in I0 unit. */ 334/* SCAN */ UNIT_I0, /* scan only in I0 unit. */ 335/* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */ 336/* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */ 337/* MDCUTSSI */ UNIT_FM01, /* mdcutssi in FM0 or FM1. */ 338/* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */ 339}; 340 341static CGEN_ATTR_VALUE_ENUM_TYPE fr500_unit_mapping[] = 342{ 343/* unit in insn actual unit */ 344/* NIL */ UNIT_NIL, 345/* I0 */ UNIT_I0, 346/* I1 */ UNIT_I1, 347/* I01 */ UNIT_I01, 348/* I2 */ UNIT_NIL, /* no I2 or I3 unit */ 349/* I3 */ UNIT_NIL, 350/* IALL */ UNIT_I01, /* only I0 and I1 units */ 351/* FM0 */ UNIT_FM0, 352/* FM1 */ UNIT_FM1, 353/* FM01 */ UNIT_FM01, 354/* FM2 */ UNIT_NIL, /* no F2 or M2 units */ 355/* FM3 */ UNIT_NIL, /* no F3 or M2 units */ 356/* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */ 357/* FMLOW */ UNIT_FM0, /* Only F0,M0 units */ 358/* B0 */ UNIT_B0, 359/* B1 */ UNIT_B1, 360/* B01 */ UNIT_B01, 361/* C */ UNIT_C, 362/* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */ 363/* IACC */ UNIT_NIL, /* iacc multiply not implemented */ 364/* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */ 365/* STORE */ UNIT_I0, /* store only in I0 unit. */ 366/* SCAN */ UNIT_I01, /* scan in I0 or I1 unit. */ 367/* DCPL */ UNIT_C, /* dcpl only in C unit. */ 368/* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */ 369/* MDCUTSSI */ UNIT_FM0, /* mdcutssi only in FM0 unit. */ 370/* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */ 371}; 372 373static CGEN_ATTR_VALUE_ENUM_TYPE fr550_unit_mapping[] = 374{ 375/* unit in insn actual unit */ 376/* NIL */ UNIT_NIL, 377/* I0 */ UNIT_I0, 378/* I1 */ UNIT_I1, 379/* I01 */ UNIT_I01, 380/* I2 */ UNIT_I2, 381/* I3 */ UNIT_I3, 382/* IALL */ UNIT_IALL, 383/* FM0 */ UNIT_FM0, 384/* FM1 */ UNIT_FM1, 385/* FM01 */ UNIT_FM01, 386/* FM2 */ UNIT_FM2, 387/* FM3 */ UNIT_FM3, 388/* FMALL */ UNIT_FMALL, 389/* FMLOW */ UNIT_FM01, /* Only F0,F1,M0,M1 units */ 390/* B0 */ UNIT_B0, 391/* B1 */ UNIT_B1, 392/* B01 */ UNIT_B01, 393/* C */ UNIT_C, 394/* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */ 395/* IACC */ UNIT_NIL, /* iacc multiply not implemented. */ 396/* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */ 397/* STORE */ UNIT_I01, /* store in I0 or I1 unit. */ 398/* SCAN */ UNIT_IALL, /* scan in any integer unit. */ 399/* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */ 400/* MDUALACC */ UNIT_FMALL,/* media dual acc insn in all media units */ 401/* MDCUTSSI */ UNIT_FM01, /* mdcutssi in FM0 or FM1 unit. */ 402/* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */ 403}; 404 405void 406frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags) 407{ 408 vliw->next_slot = 0; 409 vliw->constraint_violation = 0; 410 vliw->mach = mach; 411 vliw->elf_flags = elf_flags; 412 413 switch (mach) 414 { 415 case bfd_mach_fr400: 416 vliw->current_vliw = fr400_allowed_vliw; 417 vliw->unit_mapping = fr400_unit_mapping; 418 break; 419 case bfd_mach_fr450: 420 vliw->current_vliw = fr400_allowed_vliw; 421 vliw->unit_mapping = fr450_unit_mapping; 422 break; 423 case bfd_mach_fr550: 424 vliw->current_vliw = fr550_allowed_vliw; 425 vliw->unit_mapping = fr550_unit_mapping; 426 break; 427 default: 428 vliw->current_vliw = fr500_allowed_vliw; 429 vliw->unit_mapping = fr500_unit_mapping; 430 break; 431 } 432} 433 434/* Return TRUE if unit1 is a match for unit2. 435 Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the 436 *_allowed_vliw tables above. */ 437static bfd_boolean 438match_unit (FRV_VLIW *vliw, 439 CGEN_ATTR_VALUE_ENUM_TYPE unit1, CGEN_ATTR_VALUE_ENUM_TYPE unit2) 440{ 441 /* Map any specialized implementation units to actual ones. */ 442 unit1 = vliw->unit_mapping[unit1]; 443 444 if (unit1 == unit2) 445 return TRUE; 446 if (unit1 < unit2) 447 return FALSE; 448 449 switch (unit1) 450 { 451 case UNIT_I01: 452 case UNIT_FM01: 453 case UNIT_B01: 454 /* The 01 versions of these units are within 2 enums of the 0 or 1 455 versions. */ 456 if (unit1 - unit2 <= 2) 457 return TRUE; 458 break; 459 case UNIT_IALL: 460 case UNIT_FMALL: 461 /* The ALL versions of these units are within 5 enums of the 0, 1, 2 or 3 462 versions. */ 463 if (unit1 - unit2 <= 5) 464 return TRUE; 465 break; 466 default: 467 break; 468 } 469 470 return FALSE; 471} 472 473/* Return TRUE if the vliws match, FALSE otherwise. */ 474 475static bfd_boolean 476match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size) 477{ 478 int i; 479 480 for (i = 0; i < vliw_size; ++i) 481 if ((*vliw1)[i] != (*vliw2)[i]) 482 return FALSE; 483 484 return TRUE; 485} 486 487/* Find the next vliw vliw in the table that can accomodate the new insn. 488 If one is found then return it. Otherwise return NULL. */ 489 490static VLIW_COMBO * 491add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit) 492{ 493 int next = vliw->next_slot; 494 VLIW_COMBO *current = vliw->current_vliw; 495 VLIW_COMBO *potential; 496 497 if (next <= 0) 498 { 499 fprintf (stderr, "frv-opc.c line %d: bad vliw->next_slot value.\n", 500 __LINE__); 501 abort (); /* Should never happen. */ 502 } 503 504 /* The table is sorted by units allowed within slots, so vliws with 505 identical starting sequences are together. */ 506 potential = current; 507 do 508 { 509 if (match_unit (vliw, unit, (*potential)[next])) 510 return potential; 511 ++potential; 512 } 513 while (match_vliw (potential, current, next)); 514 515 return NULL; 516} 517 518/* Look for the given major insn type in the given vliw. 519 Returns TRUE if found, FALSE otherwise. */ 520 521static bfd_boolean 522find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major) 523{ 524 int i; 525 526 for (i = 0; i < vliw->next_slot; ++i) 527 if (vliw->major[i] == major) 528 return TRUE; 529 530 return FALSE; 531} 532 533/* Check for constraints between the insns in the vliw due to major insn 534 types. */ 535 536static bfd_boolean 537fr400_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major) 538{ 539 /* In the cpu file, all media insns are represented as being allowed in 540 both media units. This makes it easier since this is the case for fr500. 541 Catch the invalid combinations here. Insns of major class FR400_MAJOR_M_2 542 cannot coexist with any other media insn in a vliw. */ 543 switch (major) 544 { 545 case FR400_MAJOR_M_2: 546 return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1) 547 && ! find_major_in_vliw (vliw, FR400_MAJOR_M_2); 548 case FR400_MAJOR_M_1: 549 return ! find_major_in_vliw (vliw, FR400_MAJOR_M_2); 550 default: 551 break; 552 } 553 return TRUE; 554} 555 556static bfd_boolean 557fr450_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major) 558{ 559 CGEN_ATTR_VALUE_ENUM_TYPE other_major; 560 561 /* Our caller guarantees there's at least one other instruction. */ 562 other_major = CGEN_INSN_ATTR_VALUE (vliw->insn[0], CGEN_INSN_FR450_MAJOR); 563 564 /* (M4, M5) and (M4, M6) are allowed. */ 565 if (other_major == FR450_MAJOR_M_4) 566 if (major == FR450_MAJOR_M_5 || major == FR450_MAJOR_M_6) 567 return TRUE; 568 569 /* Otherwise, instructions in even-numbered media categories cannot be 570 executed in parallel with other media instructions. */ 571 switch (major) 572 { 573 case FR450_MAJOR_M_2: 574 case FR450_MAJOR_M_4: 575 case FR450_MAJOR_M_6: 576 return !(other_major >= FR450_MAJOR_M_1 577 && other_major <= FR450_MAJOR_M_6); 578 579 case FR450_MAJOR_M_1: 580 case FR450_MAJOR_M_3: 581 case FR450_MAJOR_M_5: 582 return !(other_major == FR450_MAJOR_M_2 583 || other_major == FR450_MAJOR_M_4 584 || other_major == FR450_MAJOR_M_6); 585 586 default: 587 return TRUE; 588 } 589} 590 591static bfd_boolean 592find_unit_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit) 593{ 594 int i; 595 596 for (i = 0; i < vliw->next_slot; ++i) 597 if (CGEN_INSN_ATTR_VALUE (vliw->insn[i], CGEN_INSN_UNIT) == unit) 598 return TRUE; 599 600 return FALSE; /* Not found. */ 601} 602 603static bfd_boolean 604find_major_in_slot (FRV_VLIW *vliw, 605 CGEN_ATTR_VALUE_ENUM_TYPE major, 606 CGEN_ATTR_VALUE_ENUM_TYPE slot) 607{ 608 int i; 609 610 for (i = 0; i < vliw->next_slot; ++i) 611 if (vliw->major[i] == major && (*vliw->current_vliw)[i] == slot) 612 return TRUE; 613 614 return FALSE; 615} 616 617static bfd_boolean 618fr550_find_media_in_vliw (FRV_VLIW *vliw) 619{ 620 int i; 621 622 for (i = 0; i < vliw->next_slot; ++i) 623 { 624 if (vliw->major[i] < FR550_MAJOR_M_1 || vliw->major[i] > FR550_MAJOR_M_5) 625 continue; 626 627 /* Found a media insn, however, MNOP and MCLRACC don't count. */ 628 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MNOP 629 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_0 630 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_1) 631 continue; 632 633 return TRUE; /* Found one. */ 634 } 635 636 return FALSE; 637} 638 639static bfd_boolean 640fr550_find_float_in_vliw (FRV_VLIW *vliw) 641{ 642 int i; 643 644 for (i = 0; i < vliw->next_slot; ++i) 645 { 646 if (vliw->major[i] < FR550_MAJOR_F_1 || vliw->major[i] > FR550_MAJOR_F_4) 647 continue; 648 649 /* Found a floating point insn, however, FNOP doesn't count. */ 650 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_FNOP) 651 continue; 652 653 return TRUE; /* Found one. */ 654 } 655 656 return FALSE; 657} 658 659static bfd_boolean 660fr550_check_insn_major_constraints (FRV_VLIW *vliw, 661 CGEN_ATTR_VALUE_ENUM_TYPE major, 662 const CGEN_INSN *insn) 663{ 664 CGEN_ATTR_VALUE_ENUM_TYPE unit; 665 CGEN_ATTR_VALUE_ENUM_TYPE slot = (*vliw->current_vliw)[vliw->next_slot]; 666 switch (slot) 667 { 668 case UNIT_I2: 669 /* If it's a store, then there must be another store in I1 */ 670 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT); 671 if (unit == UNIT_STORE) 672 return find_unit_in_vliw (vliw, UNIT_STORE); 673 break; 674 case UNIT_FM2: 675 case UNIT_FM3: 676 /* Floating point insns other than FNOP in slot f2 or f3 cannot coexist 677 with media insns. */ 678 if (major >= FR550_MAJOR_F_1 && major <= FR550_MAJOR_F_4 679 && CGEN_INSN_NUM (insn) != FRV_INSN_FNOP) 680 return ! fr550_find_media_in_vliw (vliw); 681 /* Media insns other than MNOP in slot m2 or m3 cannot coexist with 682 floating point insns. */ 683 if (major >= FR550_MAJOR_M_1 && major <= FR550_MAJOR_M_5 684 && CGEN_INSN_NUM (insn) != FRV_INSN_MNOP) 685 return ! fr550_find_float_in_vliw (vliw); 686 /* F-2 in slot f2 or f3 cannot coexist with F-2 or F-4 in slot f1 or f2 687 respectively. */ 688 if (major == FR550_MAJOR_F_2) 689 return ! find_major_in_slot (vliw, FR550_MAJOR_F_2, 690 slot - (UNIT_FM2 - UNIT_FM0)) 691 && ! find_major_in_slot (vliw, FR550_MAJOR_F_4, 692 slot - (UNIT_FM2 - UNIT_FM0)); 693 /* M-2 or M-5 in slot m2 or m3 cannot coexist with M-2 in slot m1 or m2 694 respectively. */ 695 if (major == FR550_MAJOR_M_2 || major == FR550_MAJOR_M_5) 696 return ! find_major_in_slot (vliw, FR550_MAJOR_M_2, 697 slot - (UNIT_FM2 - UNIT_FM0)); 698 /* M-4 in slot m2 or m3 cannot coexist with M-4 in slot m1 or m2 699 respectively. */ 700 if (major == FR550_MAJOR_M_4) 701 return ! find_major_in_slot (vliw, FR550_MAJOR_M_4, 702 slot - (UNIT_FM2 - UNIT_FM0)); 703 break; 704 default: 705 break; 706 } 707 return TRUE; /* All OK. */ 708} 709 710static bfd_boolean 711fr500_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major) 712{ 713 /* TODO: A table might be faster for some of the more complex instances 714 here. */ 715 switch (major) 716 { 717 case FR500_MAJOR_I_1: 718 case FR500_MAJOR_I_4: 719 case FR500_MAJOR_I_5: 720 case FR500_MAJOR_I_6: 721 case FR500_MAJOR_B_1: 722 case FR500_MAJOR_B_2: 723 case FR500_MAJOR_B_3: 724 case FR500_MAJOR_B_4: 725 case FR500_MAJOR_B_5: 726 case FR500_MAJOR_B_6: 727 case FR500_MAJOR_F_4: 728 case FR500_MAJOR_F_8: 729 case FR500_MAJOR_M_8: 730 return TRUE; /* OK */ 731 case FR500_MAJOR_I_2: 732 /* Cannot coexist with I-3 insn. */ 733 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3); 734 case FR500_MAJOR_I_3: 735 /* Cannot coexist with I-2 insn. */ 736 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2); 737 case FR500_MAJOR_F_1: 738 case FR500_MAJOR_F_2: 739 /* Cannot coexist with F-5, F-6, or M-7 insn. */ 740 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5) 741 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6) 742 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 743 case FR500_MAJOR_F_3: 744 /* Cannot coexist with F-7, or M-7 insn. */ 745 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7) 746 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 747 case FR500_MAJOR_F_5: 748 /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn. */ 749 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1) 750 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2) 751 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6) 752 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7) 753 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 754 case FR500_MAJOR_F_6: 755 /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn. */ 756 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1) 757 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2) 758 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5) 759 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6) 760 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 761 case FR500_MAJOR_F_7: 762 /* Cannot coexist with F-3, F-5, F-7, or M-7 insn. */ 763 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3) 764 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5) 765 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7) 766 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 767 case FR500_MAJOR_M_1: 768 /* Cannot coexist with M-7 insn. */ 769 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 770 case FR500_MAJOR_M_2: 771 case FR500_MAJOR_M_3: 772 /* Cannot coexist with M-5, M-6 or M-7 insn. */ 773 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5) 774 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6) 775 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 776 case FR500_MAJOR_M_4: 777 /* Cannot coexist with M-6 insn. */ 778 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6); 779 case FR500_MAJOR_M_5: 780 /* Cannot coexist with M-2, M-3, M-5, M-6 or M-7 insn. */ 781 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2) 782 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3) 783 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5) 784 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6) 785 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 786 case FR500_MAJOR_M_6: 787 /* Cannot coexist with M-2, M-3, M-4, M-5, M-6 or M-7 insn. */ 788 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2) 789 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3) 790 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_4) 791 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5) 792 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6) 793 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 794 case FR500_MAJOR_M_7: 795 /* Cannot coexist with M-1, M-2, M-3, M-5, M-6 or M-7 insn. */ 796 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1) 797 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_2) 798 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3) 799 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5) 800 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6) 801 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7) 802 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_1) 803 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2) 804 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_3) 805 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5) 806 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6) 807 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7); 808 default: 809 fprintf (stderr, "frv-opc.c, line %d: bad major code, aborting.\n", 810 __LINE__); 811 abort (); 812 break; 813 } 814 return TRUE; 815} 816 817static bfd_boolean 818check_insn_major_constraints (FRV_VLIW *vliw, 819 CGEN_ATTR_VALUE_ENUM_TYPE major, 820 const CGEN_INSN *insn) 821{ 822 switch (vliw->mach) 823 { 824 case bfd_mach_fr400: 825 return fr400_check_insn_major_constraints (vliw, major); 826 827 case bfd_mach_fr450: 828 return fr450_check_insn_major_constraints (vliw, major); 829 830 case bfd_mach_fr550: 831 return fr550_check_insn_major_constraints (vliw, major, insn); 832 833 default: 834 return fr500_check_insn_major_constraints (vliw, major); 835 } 836} 837 838/* Add in insn to the VLIW vliw if possible. 839 Return 0 if successful, non-zero otherwise. */ 840 841int 842frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn) 843{ 844 int index; 845 CGEN_ATTR_VALUE_ENUM_TYPE major; 846 CGEN_ATTR_VALUE_ENUM_TYPE unit; 847 VLIW_COMBO *new_vliw; 848 849 if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn)) 850 return 1; 851 852 index = vliw->next_slot; 853 if (index >= FRV_VLIW_SIZE) 854 return 1; 855 856 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT); 857 if (unit == UNIT_NIL) 858 { 859 fprintf (stderr, "frv-opc.c line %d: bad insn unit.\n", 860 __LINE__); 861 abort (); /* No UNIT specified for this insn in frv.cpu. */ 862 } 863 864 switch (vliw->mach) 865 { 866 case bfd_mach_fr400: 867 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR); 868 break; 869 case bfd_mach_fr450: 870 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR); 871 break; 872 case bfd_mach_fr550: 873 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR550_MAJOR); 874 break; 875 default: 876 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR); 877 break; 878 } 879 880 if (index <= 0) 881 { 882 /* Any insn can be added to slot 0. */ 883 while (! match_unit (vliw, unit, (*vliw->current_vliw)[0])) 884 ++vliw->current_vliw; 885 vliw->major[0] = major; 886 vliw->insn[0] = insn; 887 vliw->next_slot = 1; 888 return 0; 889 } 890 891 /* If there are already insns in the vliw(s) check to see that 892 this one can be added. Do this by finding an allowable vliw 893 combination that can accept the new insn. */ 894 if (! (vliw->elf_flags & EF_FRV_NOPACK)) 895 { 896 new_vliw = add_next_to_vliw (vliw, unit); 897 if (new_vliw && check_insn_major_constraints (vliw, major, insn)) 898 { 899 vliw->current_vliw = new_vliw; 900 vliw->major[index] = major; 901 vliw->insn[index] = insn; 902 vliw->next_slot++; 903 return 0; 904 } 905 906 /* The frv machine supports all packing conbinations. If we fail, 907 to add the insn, then it could not be handled as if it was the fr500. 908 Just return as if it was handled ok. */ 909 if (vliw->mach == bfd_mach_frv) 910 return 0; 911 } 912 913 vliw->constraint_violation = 1; 914 return 1; 915} 916 917bfd_boolean 918spr_valid (long regno) 919{ 920 if (regno < 0) return FALSE; 921 if (regno <= 4095) return TRUE; 922 return FALSE; 923} 924/* -- */ 925 926/* -- asm.c */ 927inline static const char * 928parse_symbolic_address (CGEN_CPU_DESC cd, 929 const char **strp, 930 int opindex, 931 int opinfo, 932 enum cgen_parse_operand_result *resultp, 933 bfd_vma *valuep) 934{ 935 enum cgen_parse_operand_result result_type; 936 const char *errmsg = (* cd->parse_operand_fn) 937 (cd, CGEN_PARSE_OPERAND_SYMBOLIC, strp, opindex, opinfo, 938 &result_type, valuep); 939 940 if (errmsg == NULL 941 && result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED) 942 return "symbolic expression required"; 943 944 if (resultp) 945 *resultp = result_type; 946 947 return errmsg; 948} 949 950static const char * 951parse_ldd_annotation (CGEN_CPU_DESC cd, 952 const char **strp, 953 int opindex, 954 unsigned long *valuep) 955{ 956 const char *errmsg; 957 enum cgen_parse_operand_result result_type; 958 bfd_vma value; 959 960 if (**strp == '#' || **strp == '%') 961 { 962 if (strncasecmp (*strp + 1, "tlsdesc(", 8) == 0) 963 { 964 *strp += 9; 965 errmsg = parse_symbolic_address (cd, strp, opindex, 966 BFD_RELOC_FRV_TLSDESC_RELAX, 967 &result_type, &value); 968 if (**strp != ')') 969 return "missing ')'"; 970 if (valuep) 971 *valuep = value; 972 ++*strp; 973 if (errmsg) 974 return errmsg; 975 } 976 } 977 978 while (**strp == ' ' || **strp == '\t') 979 ++*strp; 980 981 if (**strp != '@') 982 return "missing `@'"; 983 984 ++*strp; 985 986 return NULL; 987} 988 989static const char * 990parse_call_annotation (CGEN_CPU_DESC cd, 991 const char **strp, 992 int opindex, 993 unsigned long *valuep) 994{ 995 const char *errmsg; 996 enum cgen_parse_operand_result result_type; 997 bfd_vma value; 998 999 if (**strp == '#' || **strp == '%') 1000 { 1001 if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0) 1002 { 1003 *strp += 11; 1004 errmsg = parse_symbolic_address (cd, strp, opindex, 1005 BFD_RELOC_FRV_GETTLSOFF_RELAX, 1006 &result_type, &value); 1007 if (**strp != ')') 1008 return "missing ')'"; 1009 if (valuep) 1010 *valuep = value; 1011 ++*strp; 1012 if (errmsg) 1013 return errmsg; 1014 } 1015 } 1016 1017 while (**strp == ' ' || **strp == '\t') 1018 ++*strp; 1019 1020 if (**strp != '@') 1021 return "missing `@'"; 1022 1023 ++*strp; 1024 1025 return NULL; 1026} 1027 1028static const char * 1029parse_ld_annotation (CGEN_CPU_DESC cd, 1030 const char **strp, 1031 int opindex, 1032 unsigned long *valuep) 1033{ 1034 const char *errmsg; 1035 enum cgen_parse_operand_result result_type; 1036 bfd_vma value; 1037 1038 if (**strp == '#' || **strp == '%') 1039 { 1040 if (strncasecmp (*strp + 1, "tlsoff(", 7) == 0) 1041 { 1042 *strp += 8; 1043 errmsg = parse_symbolic_address (cd, strp, opindex, 1044 BFD_RELOC_FRV_TLSOFF_RELAX, 1045 &result_type, &value); 1046 if (**strp != ')') 1047 return "missing ')'"; 1048 if (valuep) 1049 *valuep = value; 1050 ++*strp; 1051 if (errmsg) 1052 return errmsg; 1053 } 1054 } 1055 1056 while (**strp == ' ' || **strp == '\t') 1057 ++*strp; 1058 1059 if (**strp != '@') 1060 return "missing `@'"; 1061 1062 ++*strp; 1063 1064 return NULL; 1065} 1066 1067static const char * 1068parse_ulo16 (CGEN_CPU_DESC cd, 1069 const char **strp, 1070 int opindex, 1071 unsigned long *valuep) 1072{ 1073 const char *errmsg; 1074 enum cgen_parse_operand_result result_type; 1075 bfd_vma value; 1076 1077 if (**strp == '#' || **strp == '%') 1078 { 1079 if (strncasecmp (*strp + 1, "lo(", 3) == 0) 1080 { 1081 *strp += 4; 1082 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16, 1083 & result_type, & value); 1084 if (**strp != ')') 1085 return "missing `)'"; 1086 ++*strp; 1087 if (errmsg == NULL 1088 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 1089 value &= 0xffff; 1090 *valuep = value; 1091 return errmsg; 1092 } 1093 if (strncasecmp (*strp + 1, "gprello(", 8) == 0) 1094 { 1095 *strp += 9; 1096 errmsg = parse_symbolic_address (cd, strp, opindex, 1097 BFD_RELOC_FRV_GPRELLO, 1098 & result_type, & value); 1099 if (**strp != ')') 1100 return "missing ')'"; 1101 ++*strp; 1102 *valuep = value; 1103 return errmsg; 1104 } 1105 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0) 1106 { 1107 *strp += 7; 1108 errmsg = parse_symbolic_address (cd, strp, opindex, 1109 BFD_RELOC_FRV_GOTLO, 1110 & result_type, & value); 1111 if (**strp != ')') 1112 return "missing ')'"; 1113 ++*strp; 1114 *valuep = value; 1115 return errmsg; 1116 } 1117 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0) 1118 { 1119 *strp += 15; 1120 errmsg = parse_symbolic_address (cd, strp, opindex, 1121 BFD_RELOC_FRV_FUNCDESC_GOTLO, 1122 & result_type, & value); 1123 if (**strp != ')') 1124 return "missing ')'"; 1125 ++*strp; 1126 *valuep = value; 1127 return errmsg; 1128 } 1129 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0) 1130 { 1131 *strp += 10; 1132 errmsg = parse_symbolic_address (cd, strp, opindex, 1133 BFD_RELOC_FRV_GOTOFFLO, 1134 & result_type, & value); 1135 if (**strp != ')') 1136 return "missing ')'"; 1137 ++*strp; 1138 *valuep = value; 1139 return errmsg; 1140 } 1141 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0) 1142 { 1143 *strp += 18; 1144 errmsg = parse_symbolic_address (cd, strp, opindex, 1145 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO, 1146 & result_type, & value); 1147 if (**strp != ')') 1148 return "missing ')'"; 1149 ++*strp; 1150 *valuep = value; 1151 return errmsg; 1152 } 1153 else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0) 1154 { 1155 *strp += 14; 1156 errmsg = parse_symbolic_address (cd, strp, opindex, 1157 BFD_RELOC_FRV_GOTTLSDESCLO, 1158 & result_type, & value); 1159 if (**strp != ')') 1160 return "missing ')'"; 1161 ++*strp; 1162 *valuep = value; 1163 return errmsg; 1164 } 1165 else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0) 1166 { 1167 *strp += 11; 1168 errmsg = parse_symbolic_address (cd, strp, opindex, 1169 BFD_RELOC_FRV_TLSMOFFLO, 1170 & result_type, & value); 1171 if (**strp != ')') 1172 return "missing ')'"; 1173 ++*strp; 1174 *valuep = value; 1175 return errmsg; 1176 } 1177 else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0) 1178 { 1179 *strp += 13; 1180 errmsg = parse_symbolic_address (cd, strp, opindex, 1181 BFD_RELOC_FRV_GOTTLSOFFLO, 1182 & result_type, & value); 1183 if (**strp != ')') 1184 return "missing ')'"; 1185 ++*strp; 1186 *valuep = value; 1187 return errmsg; 1188 } 1189 } 1190 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 1191} 1192 1193static const char * 1194parse_uslo16 (CGEN_CPU_DESC cd, 1195 const char **strp, 1196 int opindex, 1197 signed long *valuep) 1198{ 1199 const char *errmsg; 1200 enum cgen_parse_operand_result result_type; 1201 bfd_vma value; 1202 1203 if (**strp == '#' || **strp == '%') 1204 { 1205 if (strncasecmp (*strp + 1, "lo(", 3) == 0) 1206 { 1207 *strp += 4; 1208 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16, 1209 & result_type, & value); 1210 if (**strp != ')') 1211 return "missing `)'"; 1212 ++*strp; 1213 if (errmsg == NULL 1214 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 1215 value &= 0xffff; 1216 *valuep = value; 1217 return errmsg; 1218 } 1219 else if (strncasecmp (*strp + 1, "gprello(", 8) == 0) 1220 { 1221 *strp += 9; 1222 errmsg = parse_symbolic_address (cd, strp, opindex, 1223 BFD_RELOC_FRV_GPRELLO, 1224 & result_type, & value); 1225 if (**strp != ')') 1226 return "missing ')'"; 1227 ++*strp; 1228 *valuep = value; 1229 return errmsg; 1230 } 1231 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0) 1232 { 1233 *strp += 7; 1234 errmsg = parse_symbolic_address (cd, strp, opindex, 1235 BFD_RELOC_FRV_GOTLO, 1236 & result_type, & value); 1237 if (**strp != ')') 1238 return "missing ')'"; 1239 ++*strp; 1240 *valuep = value; 1241 return errmsg; 1242 } 1243 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0) 1244 { 1245 *strp += 15; 1246 errmsg = parse_symbolic_address (cd, strp, opindex, 1247 BFD_RELOC_FRV_FUNCDESC_GOTLO, 1248 & result_type, & value); 1249 if (**strp != ')') 1250 return "missing ')'"; 1251 ++*strp; 1252 *valuep = value; 1253 return errmsg; 1254 } 1255 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0) 1256 { 1257 *strp += 10; 1258 errmsg = parse_symbolic_address (cd, strp, opindex, 1259 BFD_RELOC_FRV_GOTOFFLO, 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, "gotofffuncdesclo(", 17) == 0) 1268 { 1269 *strp += 18; 1270 errmsg = parse_symbolic_address (cd, strp, opindex, 1271 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO, 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, "gottlsdesclo(", 13) == 0) 1280 { 1281 *strp += 14; 1282 errmsg = parse_symbolic_address (cd, strp, opindex, 1283 BFD_RELOC_FRV_GOTTLSDESCLO, 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, "tlsmofflo(", 10) == 0) 1292 { 1293 *strp += 11; 1294 errmsg = parse_symbolic_address (cd, strp, opindex, 1295 BFD_RELOC_FRV_TLSMOFFLO, 1296 & result_type, & value); 1297 if (**strp != ')') 1298 return "missing ')'"; 1299 ++*strp; 1300 *valuep = value; 1301 return errmsg; 1302 } 1303 else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0) 1304 { 1305 *strp += 13; 1306 errmsg = parse_symbolic_address (cd, strp, opindex, 1307 BFD_RELOC_FRV_GOTTLSOFFLO, 1308 & result_type, & value); 1309 if (**strp != ')') 1310 return "missing ')'"; 1311 ++*strp; 1312 *valuep = value; 1313 return errmsg; 1314 } 1315 } 1316 return cgen_parse_signed_integer (cd, strp, opindex, valuep); 1317} 1318 1319static const char * 1320parse_uhi16 (CGEN_CPU_DESC cd, 1321 const char **strp, 1322 int opindex, 1323 unsigned long *valuep) 1324{ 1325 const char *errmsg; 1326 enum cgen_parse_operand_result result_type; 1327 bfd_vma value; 1328 1329 if (**strp == '#' || **strp == '%') 1330 { 1331 if (strncasecmp (*strp + 1, "hi(", 3) == 0) 1332 { 1333 *strp += 4; 1334 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16, 1335 & result_type, & value); 1336 if (**strp != ')') 1337 return "missing `)'"; 1338 ++*strp; 1339 if (errmsg == NULL 1340 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 1341 { 1342 /* If bfd_vma is wider than 32 bits, but we have a sign- 1343 or zero-extension, truncate it. */ 1344 if (value >= - ((bfd_vma)1 << 31) 1345 || value <= ((bfd_vma)1 << 31) - (bfd_vma)1) 1346 value &= (((bfd_vma)1 << 16) << 16) - 1; 1347 value >>= 16; 1348 } 1349 *valuep = value; 1350 return errmsg; 1351 } 1352 else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0) 1353 { 1354 *strp += 9; 1355 errmsg = parse_symbolic_address (cd, strp, opindex, 1356 BFD_RELOC_FRV_GPRELHI, 1357 & result_type, & value); 1358 if (**strp != ')') 1359 return "missing ')'"; 1360 ++*strp; 1361 *valuep = value; 1362 return errmsg; 1363 } 1364 else if (strncasecmp (*strp + 1, "gothi(", 6) == 0) 1365 { 1366 *strp += 7; 1367 errmsg = parse_symbolic_address (cd, strp, opindex, 1368 BFD_RELOC_FRV_GOTHI, 1369 & result_type, & value); 1370 if (**strp != ')') 1371 return "missing ')'"; 1372 ++*strp; 1373 *valuep = value; 1374 return errmsg; 1375 } 1376 else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0) 1377 { 1378 *strp += 15; 1379 errmsg = parse_symbolic_address (cd, strp, opindex, 1380 BFD_RELOC_FRV_FUNCDESC_GOTHI, 1381 & result_type, & value); 1382 if (**strp != ')') 1383 return "missing ')'"; 1384 ++*strp; 1385 *valuep = value; 1386 return errmsg; 1387 } 1388 else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0) 1389 { 1390 *strp += 10; 1391 errmsg = parse_symbolic_address (cd, strp, opindex, 1392 BFD_RELOC_FRV_GOTOFFHI, 1393 & result_type, & value); 1394 if (**strp != ')') 1395 return "missing ')'"; 1396 ++*strp; 1397 *valuep = value; 1398 return errmsg; 1399 } 1400 else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0) 1401 { 1402 *strp += 18; 1403 errmsg = parse_symbolic_address (cd, strp, opindex, 1404 BFD_RELOC_FRV_FUNCDESC_GOTOFFHI, 1405 & result_type, & value); 1406 if (**strp != ')') 1407 return "missing ')'"; 1408 ++*strp; 1409 *valuep = value; 1410 return errmsg; 1411 } 1412 else if (strncasecmp (*strp + 1, "gottlsdeschi(", 13) == 0) 1413 { 1414 *strp += 14; 1415 errmsg = parse_symbolic_address (cd, strp, opindex, 1416 BFD_RELOC_FRV_GOTTLSDESCHI, 1417 &result_type, &value); 1418 if (**strp != ')') 1419 return "missing ')'"; 1420 ++*strp; 1421 *valuep = value; 1422 return errmsg; 1423 } 1424 else if (strncasecmp (*strp + 1, "tlsmoffhi(", 10) == 0) 1425 { 1426 *strp += 11; 1427 errmsg = parse_symbolic_address (cd, strp, opindex, 1428 BFD_RELOC_FRV_TLSMOFFHI, 1429 & result_type, & value); 1430 if (**strp != ')') 1431 return "missing ')'"; 1432 ++*strp; 1433 *valuep = value; 1434 return errmsg; 1435 } 1436 else if (strncasecmp (*strp + 1, "gottlsoffhi(", 12) == 0) 1437 { 1438 *strp += 13; 1439 errmsg = parse_symbolic_address (cd, strp, opindex, 1440 BFD_RELOC_FRV_GOTTLSOFFHI, 1441 & result_type, & value); 1442 if (**strp != ')') 1443 return "missing ')'"; 1444 ++*strp; 1445 *valuep = value; 1446 return errmsg; 1447 } 1448 } 1449 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 1450} 1451 1452static long 1453parse_register_number (const char **strp) 1454{ 1455 int regno; 1456 1457 if (**strp < '0' || **strp > '9') 1458 return -1; /* error */ 1459 1460 regno = **strp - '0'; 1461 for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp) 1462 regno = regno * 10 + (**strp - '0'); 1463 1464 return regno; 1465} 1466 1467static const char * 1468parse_spr (CGEN_CPU_DESC cd, 1469 const char **strp, 1470 CGEN_KEYWORD * table, 1471 long *valuep) 1472{ 1473 const char *save_strp; 1474 long regno; 1475 1476 /* Check for spr index notation. */ 1477 if (strncasecmp (*strp, "spr[", 4) == 0) 1478 { 1479 *strp += 4; 1480 regno = parse_register_number (strp); 1481 if (**strp != ']') 1482 return _("missing `]'"); 1483 ++*strp; 1484 if (! spr_valid (regno)) 1485 return _("Special purpose register number is out of range"); 1486 *valuep = regno; 1487 return NULL; 1488 } 1489 1490 save_strp = *strp; 1491 regno = parse_register_number (strp); 1492 if (regno != -1) 1493 { 1494 if (! spr_valid (regno)) 1495 return _("Special purpose register number is out of range"); 1496 *valuep = regno; 1497 return NULL; 1498 } 1499 1500 *strp = save_strp; 1501 return cgen_parse_keyword (cd, strp, table, valuep); 1502} 1503 1504static const char * 1505parse_d12 (CGEN_CPU_DESC cd, 1506 const char **strp, 1507 int opindex, 1508 long *valuep) 1509{ 1510 const char *errmsg; 1511 enum cgen_parse_operand_result result_type; 1512 bfd_vma value; 1513 1514 /* Check for small data reference. */ 1515 if (**strp == '#' || **strp == '%') 1516 { 1517 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0) 1518 { 1519 *strp += 9; 1520 errmsg = parse_symbolic_address (cd, strp, opindex, 1521 BFD_RELOC_FRV_GPREL12, 1522 & result_type, & value); 1523 if (**strp != ')') 1524 return "missing `)'"; 1525 ++*strp; 1526 *valuep = value; 1527 return errmsg; 1528 } 1529 else if (strncasecmp (*strp + 1, "got12(", 6) == 0) 1530 { 1531 *strp += 7; 1532 errmsg = parse_symbolic_address (cd, strp, opindex, 1533 BFD_RELOC_FRV_GOT12, 1534 & result_type, & value); 1535 if (**strp != ')') 1536 return "missing ')'"; 1537 ++*strp; 1538 *valuep = value; 1539 return errmsg; 1540 } 1541 else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0) 1542 { 1543 *strp += 15; 1544 errmsg = parse_symbolic_address (cd, strp, opindex, 1545 BFD_RELOC_FRV_FUNCDESC_GOT12, 1546 & result_type, & value); 1547 if (**strp != ')') 1548 return "missing ')'"; 1549 ++*strp; 1550 *valuep = value; 1551 return errmsg; 1552 } 1553 else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0) 1554 { 1555 *strp += 10; 1556 errmsg = parse_symbolic_address (cd, strp, opindex, 1557 BFD_RELOC_FRV_GOTOFF12, 1558 & result_type, & value); 1559 if (**strp != ')') 1560 return "missing ')'"; 1561 ++*strp; 1562 *valuep = value; 1563 return errmsg; 1564 } 1565 else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0) 1566 { 1567 *strp += 18; 1568 errmsg = parse_symbolic_address (cd, strp, opindex, 1569 BFD_RELOC_FRV_FUNCDESC_GOTOFF12, 1570 & result_type, & value); 1571 if (**strp != ')') 1572 return "missing ')'"; 1573 ++*strp; 1574 *valuep = value; 1575 return errmsg; 1576 } 1577 else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0) 1578 { 1579 *strp += 14; 1580 errmsg = parse_symbolic_address (cd, strp, opindex, 1581 BFD_RELOC_FRV_GOTTLSDESC12, 1582 & result_type, & value); 1583 if (**strp != ')') 1584 return "missing ')'"; 1585 ++*strp; 1586 *valuep = value; 1587 return errmsg; 1588 } 1589 else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0) 1590 { 1591 *strp += 11; 1592 errmsg = parse_symbolic_address (cd, strp, opindex, 1593 BFD_RELOC_FRV_TLSMOFF12, 1594 & result_type, & value); 1595 if (**strp != ')') 1596 return "missing ')'"; 1597 ++*strp; 1598 *valuep = value; 1599 return errmsg; 1600 } 1601 else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0) 1602 { 1603 *strp += 13; 1604 errmsg = parse_symbolic_address (cd, strp, opindex, 1605 BFD_RELOC_FRV_GOTTLSOFF12, 1606 & result_type, & value); 1607 if (**strp != ')') 1608 return "missing ')'"; 1609 ++*strp; 1610 *valuep = value; 1611 return errmsg; 1612 } 1613 } 1614 return cgen_parse_signed_integer (cd, strp, opindex, valuep); 1615} 1616 1617static const char * 1618parse_s12 (CGEN_CPU_DESC cd, 1619 const char **strp, 1620 int opindex, 1621 long *valuep) 1622{ 1623 const char *errmsg; 1624 enum cgen_parse_operand_result result_type; 1625 bfd_vma value; 1626 1627 /* Check for small data reference. */ 1628 if (**strp == '#' || **strp == '%') 1629 { 1630 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0) 1631 { 1632 *strp += 9; 1633 errmsg = parse_symbolic_address (cd, strp, opindex, 1634 BFD_RELOC_FRV_GPREL12, 1635 & result_type, & value); 1636 if (**strp != ')') 1637 return "missing `)'"; 1638 ++*strp; 1639 *valuep = value; 1640 return errmsg; 1641 } 1642 else if (strncasecmp (*strp + 1, "got12(", 6) == 0) 1643 { 1644 *strp += 7; 1645 errmsg = parse_symbolic_address (cd, strp, opindex, 1646 BFD_RELOC_FRV_GOT12, 1647 & result_type, & value); 1648 if (**strp != ')') 1649 return "missing ')'"; 1650 ++*strp; 1651 *valuep = value; 1652 return errmsg; 1653 } 1654 else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0) 1655 { 1656 *strp += 15; 1657 errmsg = parse_symbolic_address (cd, strp, opindex, 1658 BFD_RELOC_FRV_FUNCDESC_GOT12, 1659 & result_type, & value); 1660 if (**strp != ')') 1661 return "missing ')'"; 1662 ++*strp; 1663 *valuep = value; 1664 return errmsg; 1665 } 1666 else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0) 1667 { 1668 *strp += 10; 1669 errmsg = parse_symbolic_address (cd, strp, opindex, 1670 BFD_RELOC_FRV_GOTOFF12, 1671 & result_type, & value); 1672 if (**strp != ')') 1673 return "missing ')'"; 1674 ++*strp; 1675 *valuep = value; 1676 return errmsg; 1677 } 1678 else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0) 1679 { 1680 *strp += 18; 1681 errmsg = parse_symbolic_address (cd, strp, opindex, 1682 BFD_RELOC_FRV_FUNCDESC_GOTOFF12, 1683 & result_type, & value); 1684 if (**strp != ')') 1685 return "missing ')'"; 1686 ++*strp; 1687 *valuep = value; 1688 return errmsg; 1689 } 1690 else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0) 1691 { 1692 *strp += 14; 1693 errmsg = parse_symbolic_address (cd, strp, opindex, 1694 BFD_RELOC_FRV_GOTTLSDESC12, 1695 & result_type, & value); 1696 if (**strp != ')') 1697 return "missing ')'"; 1698 ++*strp; 1699 *valuep = value; 1700 return errmsg; 1701 } 1702 else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0) 1703 { 1704 *strp += 11; 1705 errmsg = parse_symbolic_address (cd, strp, opindex, 1706 BFD_RELOC_FRV_TLSMOFF12, 1707 & result_type, & value); 1708 if (**strp != ')') 1709 return "missing ')'"; 1710 ++*strp; 1711 *valuep = value; 1712 return errmsg; 1713 } 1714 else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0) 1715 { 1716 *strp += 13; 1717 errmsg = parse_symbolic_address (cd, strp, opindex, 1718 BFD_RELOC_FRV_GOTTLSOFF12, 1719 & result_type, & value); 1720 if (**strp != ')') 1721 return "missing ')'"; 1722 ++*strp; 1723 *valuep = value; 1724 return errmsg; 1725 } 1726 } 1727 1728 if (**strp == '#') 1729 ++*strp; 1730 return cgen_parse_signed_integer (cd, strp, opindex, valuep); 1731} 1732 1733static const char * 1734parse_u12 (CGEN_CPU_DESC cd, 1735 const char **strp, 1736 int opindex, 1737 long *valuep) 1738{ 1739 const char *errmsg; 1740 enum cgen_parse_operand_result result_type; 1741 bfd_vma value; 1742 1743 /* Check for small data reference. */ 1744 if ((**strp == '#' || **strp == '%') 1745 && strncasecmp (*strp + 1, "gprel12(", 8) == 0) 1746 { 1747 *strp += 9; 1748 errmsg = parse_symbolic_address (cd, strp, opindex, 1749 BFD_RELOC_FRV_GPRELU12, 1750 & result_type, & value); 1751 if (**strp != ')') 1752 return "missing `)'"; 1753 ++*strp; 1754 *valuep = value; 1755 return errmsg; 1756 } 1757 else 1758 { 1759 if (**strp == '#') 1760 ++*strp; 1761 return cgen_parse_signed_integer (cd, strp, opindex, valuep); 1762 } 1763} 1764 1765static const char * 1766parse_A (CGEN_CPU_DESC cd, 1767 const char **strp, 1768 int opindex, 1769 unsigned long *valuep, 1770 unsigned long A) 1771{ 1772 const char *errmsg; 1773 1774 if (**strp == '#') 1775 ++*strp; 1776 1777 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 1778 if (errmsg) 1779 return errmsg; 1780 1781 if (*valuep != A) 1782 return _("Value of A operand must be 0 or 1"); 1783 1784 return NULL; 1785} 1786 1787static const char * 1788parse_A0 (CGEN_CPU_DESC cd, 1789 const char **strp, 1790 int opindex, 1791 unsigned long *valuep) 1792{ 1793 return parse_A (cd, strp, opindex, valuep, 0); 1794} 1795 1796static const char * 1797parse_A1 (CGEN_CPU_DESC cd, 1798 const char **strp, 1799 int opindex, 1800 unsigned long *valuep) 1801{ 1802 return parse_A (cd, strp, opindex, valuep, 1); 1803} 1804 1805static const char * 1806parse_even_register (CGEN_CPU_DESC cd, 1807 const char ** strP, 1808 CGEN_KEYWORD * tableP, 1809 long * valueP) 1810{ 1811 const char * errmsg; 1812 const char * saved_star_strP = * strP; 1813 1814 errmsg = cgen_parse_keyword (cd, strP, tableP, valueP); 1815 1816 if (errmsg == NULL && ((* valueP) & 1)) 1817 { 1818 errmsg = _("register number must be even"); 1819 * strP = saved_star_strP; 1820 } 1821 1822 return errmsg; 1823} 1824 1825static const char * 1826parse_call_label (CGEN_CPU_DESC cd, 1827 const char **strp, 1828 int opindex, 1829 int opinfo, 1830 enum cgen_parse_operand_result *resultp, 1831 bfd_vma *valuep) 1832{ 1833 const char *errmsg; 1834 bfd_vma value; 1835 1836 /* Check for small data reference. */ 1837 if (opinfo == 0 && (**strp == '#' || **strp == '%')) 1838 { 1839 if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0) 1840 { 1841 *strp += 11; 1842 errmsg = parse_symbolic_address (cd, strp, opindex, 1843 BFD_RELOC_FRV_GETTLSOFF, 1844 resultp, &value); 1845 if (**strp != ')') 1846 return _("missing `)'"); 1847 ++*strp; 1848 *valuep = value; 1849 return errmsg; 1850 } 1851 } 1852 1853 return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep); 1854} 1855 1856/* -- */ 1857 1858/* -- dis.c */ 1859static void 1860print_at (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 1861 void * dis_info, 1862 long reloc_ann ATTRIBUTE_UNUSED, 1863 long value ATTRIBUTE_UNUSED, 1864 bfd_vma pc ATTRIBUTE_UNUSED, 1865 int length ATTRIBUTE_UNUSED) 1866{ 1867 disassemble_info *info = (disassemble_info *) dis_info; 1868 1869 (*info->fprintf_func) (info->stream, "@"); 1870} 1871 1872static void 1873print_spr (CGEN_CPU_DESC cd, 1874 void * dis_info, 1875 CGEN_KEYWORD *names, 1876 long regno, 1877 unsigned int attrs) 1878{ 1879 /* Use the register index format for any unnamed registers. */ 1880 if (cgen_keyword_lookup_value (names, regno) == NULL) 1881 { 1882 disassemble_info *info = (disassemble_info *) dis_info; 1883 (*info->fprintf_func) (info->stream, "spr[%ld]", regno); 1884 } 1885 else 1886 print_keyword (cd, dis_info, names, regno, attrs); 1887} 1888 1889static void 1890print_hi (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 1891 void * dis_info, 1892 long value, 1893 unsigned int attrs ATTRIBUTE_UNUSED, 1894 bfd_vma pc ATTRIBUTE_UNUSED, 1895 int length ATTRIBUTE_UNUSED) 1896{ 1897 disassemble_info *info = (disassemble_info *) dis_info; 1898 1899 (*info->fprintf_func) (info->stream, value ? "0x%lx" : "hi(0x%lx)", value); 1900} 1901 1902static void 1903print_lo (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 1904 void * dis_info, 1905 long value, 1906 unsigned int attrs ATTRIBUTE_UNUSED, 1907 bfd_vma pc ATTRIBUTE_UNUSED, 1908 int length ATTRIBUTE_UNUSED) 1909{ 1910 disassemble_info *info = (disassemble_info *) dis_info; 1911 if (value) 1912 (*info->fprintf_func) (info->stream, "0x%lx", value); 1913 else 1914 (*info->fprintf_func) (info->stream, "lo(0x%lx)", value); 1915} 1916 1917/* -- */ 1918