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