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