116dce513Schristos/* Fujitsu FRV opcode support, for GNU Binutils. -*- C -*- 216dce513Schristos 316dce513Schristos Copyright 2000, 2001, 2003, 2004, 2005, 2007, 2009 416dce513Schristos Free Software Foundation, Inc. 516dce513Schristos 616dce513Schristos Contributed by Red Hat Inc; developed under contract from Fujitsu. 716dce513Schristos 816dce513Schristos This file is part of the GNU Binutils. 916dce513Schristos 1016dce513Schristos This program is free software; you can redistribute it and/or modify 1116dce513Schristos it under the terms of the GNU General Public License as published by 1216dce513Schristos the Free Software Foundation; either version 3 of the License, or 1316dce513Schristos (at your option) any later version. 1416dce513Schristos 1516dce513Schristos This program is distributed in the hope that it will be useful, 1616dce513Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 1716dce513Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1816dce513Schristos GNU General Public License for more details. 1916dce513Schristos 2016dce513Schristos You should have received a copy of the GNU General Public License 2116dce513Schristos along with this program; if not, write to the Free Software 2216dce513Schristos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 2316dce513Schristos MA 02110-1301, USA. */ 2416dce513Schristos 2516dce513Schristos 2616dce513Schristos/* This file is an addendum to frv.cpu. Heavy use of C code isn't 2716dce513Schristos appropriate in .cpu files, so it resides here. This especially applies 2816dce513Schristos to assembly/disassembly where parsing/printing can be quite involved. 2916dce513Schristos Such things aren't really part of the specification of the cpu, per se, 3016dce513Schristos so .cpu files provide the general framework and .opc files handle the 3116dce513Schristos nitty-gritty details as necessary. 3216dce513Schristos 3316dce513Schristos Each section is delimited with start and end markers. 3416dce513Schristos 3516dce513Schristos <arch>-opc.h additions use: "-- opc.h" 3616dce513Schristos <arch>-opc.c additions use: "-- opc.c" 3716dce513Schristos <arch>-asm.c additions use: "-- asm.c" 3816dce513Schristos <arch>-dis.c additions use: "-- dis.c" 3916dce513Schristos <arch>-ibd.h additions use: "-- ibd.h". */ 4016dce513Schristos 4116dce513Schristos/* -- opc.h */ 4216dce513Schristos 4316dce513Schristos#undef CGEN_DIS_HASH_SIZE 4416dce513Schristos#define CGEN_DIS_HASH_SIZE 128 4516dce513Schristos#undef CGEN_DIS_HASH 4616dce513Schristos#define CGEN_DIS_HASH(buffer, value) (((value) >> 18) & 127) 4716dce513Schristos 4816dce513Schristos/* Allows reason codes to be output when assembler errors occur. */ 4916dce513Schristos#define CGEN_VERBOSE_ASSEMBLER_ERRORS 5016dce513Schristos 5116dce513Schristos/* Vliw support. */ 5216dce513Schristos#define FRV_VLIW_SIZE 8 /* fr550 has largest vliw size of 8. */ 5316dce513Schristos#define PAD_VLIW_COMBO ,UNIT_NIL,UNIT_NIL,UNIT_NIL,UNIT_NIL 5416dce513Schristos 5516dce513Schristostypedef CGEN_ATTR_VALUE_ENUM_TYPE VLIW_COMBO[FRV_VLIW_SIZE]; 5616dce513Schristos 5716dce513Schristostypedef struct 5816dce513Schristos{ 5916dce513Schristos int next_slot; 6016dce513Schristos int constraint_violation; 6116dce513Schristos unsigned long mach; 6216dce513Schristos unsigned long elf_flags; 6316dce513Schristos CGEN_ATTR_VALUE_ENUM_TYPE * unit_mapping; 6416dce513Schristos VLIW_COMBO * current_vliw; 6516dce513Schristos CGEN_ATTR_VALUE_ENUM_TYPE major[FRV_VLIW_SIZE]; 6616dce513Schristos const CGEN_INSN * insn[FRV_VLIW_SIZE]; 6716dce513Schristos} FRV_VLIW; 6816dce513Schristos 69*e992f068Schristosbool frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long); 70*e992f068Schristosbool frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long); 71*e992f068Schristosbool frv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long); 72*e992f068Schristosbool frv_is_branch_insn (const CGEN_INSN *); 73*e992f068Schristosbool frv_is_float_insn (const CGEN_INSN *); 74*e992f068Schristosbool frv_is_media_insn (const CGEN_INSN *); 7516dce513Schristosvoid frv_vliw_reset (FRV_VLIW *, unsigned long, unsigned long); 7616dce513Schristosint frv_vliw_add_insn (FRV_VLIW *, const CGEN_INSN *); 77*e992f068Schristosbool spr_valid (long); 7816dce513Schristos/* -- */ 7916dce513Schristos 8016dce513Schristos/* -- opc.c */ 81ede78133Schristos#include "opintl.h" 8216dce513Schristos#include "elf/frv.h" 8316dce513Schristos#include <stdio.h> 8416dce513Schristos 8516dce513Schristos/* DEBUG appears below as argument of OP macro. */ 8616dce513Schristos#undef DEBUG 8716dce513Schristos 8816dce513Schristos/* Returns TRUE if {MAJOR,MACH} is a major branch of the FRV 8916dce513Schristos development tree. */ 9016dce513Schristos 91*e992f068Schristosbool 9216dce513Schristosfrv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach) 9316dce513Schristos{ 9416dce513Schristos switch (mach) 9516dce513Schristos { 9616dce513Schristos case bfd_mach_fr400: 9716dce513Schristos if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6) 98*e992f068Schristos return true; 9916dce513Schristos break; 10016dce513Schristos case bfd_mach_fr450: 10116dce513Schristos if (major >= FR450_MAJOR_B_1 && major <= FR450_MAJOR_B_6) 102*e992f068Schristos return true; 10316dce513Schristos break; 10416dce513Schristos default: 10516dce513Schristos if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6) 106*e992f068Schristos return true; 10716dce513Schristos break; 10816dce513Schristos } 10916dce513Schristos 110*e992f068Schristos return false; 11116dce513Schristos} 11216dce513Schristos 11316dce513Schristos/* Returns TRUE if {MAJOR,MACH} supports floating point insns. */ 11416dce513Schristos 115*e992f068Schristosbool 11616dce513Schristosfrv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach) 11716dce513Schristos{ 11816dce513Schristos switch (mach) 11916dce513Schristos { 12016dce513Schristos case bfd_mach_fr400: 12116dce513Schristos case bfd_mach_fr450: 122*e992f068Schristos return false; 12316dce513Schristos default: 12416dce513Schristos if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8) 125*e992f068Schristos return true; 12616dce513Schristos break; 12716dce513Schristos } 12816dce513Schristos 129*e992f068Schristos return false; 13016dce513Schristos} 13116dce513Schristos 13216dce513Schristos/* Returns TRUE if {MAJOR,MACH} supports media insns. */ 13316dce513Schristos 134*e992f068Schristosbool 13516dce513Schristosfrv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach) 13616dce513Schristos{ 13716dce513Schristos switch (mach) 13816dce513Schristos { 13916dce513Schristos case bfd_mach_fr400: 14016dce513Schristos if (major >= FR400_MAJOR_M_1 && major <= FR400_MAJOR_M_2) 141*e992f068Schristos return true; 14216dce513Schristos break; 14316dce513Schristos case bfd_mach_fr450: 14416dce513Schristos if (major >= FR450_MAJOR_M_1 && major <= FR450_MAJOR_M_6) 145*e992f068Schristos return true; 14616dce513Schristos break; 14716dce513Schristos default: 14816dce513Schristos if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8) 149*e992f068Schristos return true; 15016dce513Schristos break; 15116dce513Schristos } 15216dce513Schristos 153*e992f068Schristos return false; 15416dce513Schristos} 15516dce513Schristos 156*e992f068Schristosbool 15716dce513Schristosfrv_is_branch_insn (const CGEN_INSN *insn) 15816dce513Schristos{ 15916dce513Schristos if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR), 16016dce513Schristos bfd_mach_fr400)) 161*e992f068Schristos return true; 16216dce513Schristos if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR), 16316dce513Schristos bfd_mach_fr450)) 164*e992f068Schristos return true; 16516dce513Schristos if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR), 16616dce513Schristos bfd_mach_fr500)) 167*e992f068Schristos return true; 16816dce513Schristos 169*e992f068Schristos return false; 17016dce513Schristos} 17116dce513Schristos 172*e992f068Schristosbool 17316dce513Schristosfrv_is_float_insn (const CGEN_INSN *insn) 17416dce513Schristos{ 17516dce513Schristos if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR), 17616dce513Schristos bfd_mach_fr400)) 177*e992f068Schristos return true; 17816dce513Schristos if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR), 17916dce513Schristos bfd_mach_fr450)) 180*e992f068Schristos return true; 18116dce513Schristos if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR), 18216dce513Schristos bfd_mach_fr500)) 183*e992f068Schristos return true; 18416dce513Schristos 185*e992f068Schristos return false; 18616dce513Schristos} 18716dce513Schristos 188*e992f068Schristosbool 18916dce513Schristosfrv_is_media_insn (const CGEN_INSN *insn) 19016dce513Schristos{ 19116dce513Schristos if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR), 19216dce513Schristos bfd_mach_fr400)) 193*e992f068Schristos return true; 19416dce513Schristos if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR), 19516dce513Schristos bfd_mach_fr450)) 196*e992f068Schristos return true; 19716dce513Schristos if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR), 19816dce513Schristos bfd_mach_fr500)) 199*e992f068Schristos return true; 20016dce513Schristos 201*e992f068Schristos return false; 20216dce513Schristos} 20316dce513Schristos 20416dce513Schristos/* This table represents the allowable packing for vliw insns for the fr400. 20516dce513Schristos The fr400 has only 2 vliw slots. Represent this by not allowing any insns 20616dce513Schristos in the extra slots. 20716dce513Schristos Subsets of any given row are also allowed. */ 20816dce513Schristosstatic VLIW_COMBO fr400_allowed_vliw[] = 20916dce513Schristos{ 21016dce513Schristos /* slot0 slot1 slot2 slot3 */ 21116dce513Schristos { UNIT_I0, UNIT_I1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 21216dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 21316dce513Schristos { UNIT_I0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 21416dce513Schristos { UNIT_FM0, UNIT_FM1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 21516dce513Schristos { UNIT_FM0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 21616dce513Schristos { UNIT_B0, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 21716dce513Schristos { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 21816dce513Schristos { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO } 21916dce513Schristos}; 22016dce513Schristos 22116dce513Schristos/* This table represents the allowable packing for vliw insns for the fr500. 22216dce513Schristos The fr500 has only 4 vliw slots. Represent this by not allowing any insns 22316dce513Schristos in the extra slots. 22416dce513Schristos Subsets of any given row are also allowed. */ 22516dce513Schristosstatic VLIW_COMBO fr500_allowed_vliw[] = 22616dce513Schristos{ 22716dce513Schristos /* slot0 slot1 slot2 slot3 */ 22816dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1 PAD_VLIW_COMBO }, 22916dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0 PAD_VLIW_COMBO }, 23016dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0 PAD_VLIW_COMBO }, 23116dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO }, 23216dce513Schristos { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO }, 23316dce513Schristos { UNIT_I0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO }, 23416dce513Schristos { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO }, 23516dce513Schristos { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO }, 23616dce513Schristos { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 23716dce513Schristos { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }, 23816dce513Schristos { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO } 23916dce513Schristos}; 24016dce513Schristos 24116dce513Schristos/* This table represents the allowable packing for vliw insns for the fr550. 24216dce513Schristos Subsets of any given row are also allowed. */ 24316dce513Schristosstatic VLIW_COMBO fr550_allowed_vliw[] = 24416dce513Schristos{ 24516dce513Schristos /* slot0 slot1 slot2 slot3 slot4 slot5 slot6 slot7 */ 24616dce513Schristos { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL }, 24716dce513Schristos { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL }, 24816dce513Schristos { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 24916dce513Schristos { UNIT_I0, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 25016dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_FM3 }, 25116dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_B0 }, 25216dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_FM3, UNIT_B0 }, 25316dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_B0, UNIT_B1 }, 25416dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 }, 25516dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL }, 25616dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 }, 25716dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 }, 25816dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL }, 25916dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL }, 26016dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1, UNIT_NIL }, 26116dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL }, 26216dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 26316dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL }, 26416dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL }, 26516dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 26616dce513Schristos { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 26716dce513Schristos { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 26816dce513Schristos { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 26916dce513Schristos { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL }, 27016dce513Schristos { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 27116dce513Schristos { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 27216dce513Schristos { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }, 27316dce513Schristos { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL } 27416dce513Schristos}; 27516dce513Schristos 27616dce513Schristos/* Some insns are assigned specialized implementation units which map to 27716dce513Schristos different actual implementation units on different machines. These 27816dce513Schristos tables perform that mapping. */ 27916dce513Schristosstatic CGEN_ATTR_VALUE_ENUM_TYPE fr400_unit_mapping[] = 28016dce513Schristos{ 28116dce513Schristos/* unit in insn actual unit */ 28216dce513Schristos/* NIL */ UNIT_NIL, 28316dce513Schristos/* I0 */ UNIT_I0, 28416dce513Schristos/* I1 */ UNIT_I1, 28516dce513Schristos/* I01 */ UNIT_I01, 28616dce513Schristos/* I2 */ UNIT_NIL, /* no I2 or I3 unit */ 28716dce513Schristos/* I3 */ UNIT_NIL, 28816dce513Schristos/* IALL */ UNIT_I01, /* only I0 and I1 units */ 28916dce513Schristos/* FM0 */ UNIT_FM0, 29016dce513Schristos/* FM1 */ UNIT_FM1, 29116dce513Schristos/* FM01 */ UNIT_FM01, 29216dce513Schristos/* FM2 */ UNIT_NIL, /* no F2 or M2 units */ 29316dce513Schristos/* FM3 */ UNIT_NIL, /* no F3 or M3 units */ 29416dce513Schristos/* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */ 29516dce513Schristos/* FMLOW */ UNIT_FM0, /* Only F0,M0 units */ 29616dce513Schristos/* B0 */ UNIT_B0, /* branches only in B0 unit. */ 29716dce513Schristos/* B1 */ UNIT_B0, 29816dce513Schristos/* B01 */ UNIT_B0, 29916dce513Schristos/* C */ UNIT_C, 30016dce513Schristos/* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */ 30116dce513Schristos/* IACC */ UNIT_I01, /* iacc multiply in I0 or I1 unit. */ 30216dce513Schristos/* LOAD */ UNIT_I0, /* load only in I0 unit. */ 30316dce513Schristos/* STORE */ UNIT_I0, /* store only in I0 unit. */ 30416dce513Schristos/* SCAN */ UNIT_I0, /* scan only in I0 unit. */ 30516dce513Schristos/* DCPL */ UNIT_C, /* dcpl only in C unit. */ 30616dce513Schristos/* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */ 30716dce513Schristos/* MDCUTSSI */ UNIT_FM0, /* mdcutssi only in FM0 unit. */ 30816dce513Schristos/* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */ 30916dce513Schristos}; 31016dce513Schristos 31116dce513Schristos/* Some insns are assigned specialized implementation units which map to 31216dce513Schristos different actual implementation units on different machines. These 31316dce513Schristos tables perform that mapping. */ 31416dce513Schristosstatic CGEN_ATTR_VALUE_ENUM_TYPE fr450_unit_mapping[] = 31516dce513Schristos{ 31616dce513Schristos/* unit in insn actual unit */ 31716dce513Schristos/* NIL */ UNIT_NIL, 31816dce513Schristos/* I0 */ UNIT_I0, 31916dce513Schristos/* I1 */ UNIT_I1, 32016dce513Schristos/* I01 */ UNIT_I01, 32116dce513Schristos/* I2 */ UNIT_NIL, /* no I2 or I3 unit */ 32216dce513Schristos/* I3 */ UNIT_NIL, 32316dce513Schristos/* IALL */ UNIT_I01, /* only I0 and I1 units */ 32416dce513Schristos/* FM0 */ UNIT_FM0, 32516dce513Schristos/* FM1 */ UNIT_FM1, 32616dce513Schristos/* FM01 */ UNIT_FM01, 32716dce513Schristos/* FM2 */ UNIT_NIL, /* no F2 or M2 units */ 32816dce513Schristos/* FM3 */ UNIT_NIL, /* no F3 or M3 units */ 32916dce513Schristos/* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */ 33016dce513Schristos/* FMLOW */ UNIT_FM0, /* Only F0,M0 units */ 33116dce513Schristos/* B0 */ UNIT_B0, /* branches only in B0 unit. */ 33216dce513Schristos/* B1 */ UNIT_B0, 33316dce513Schristos/* B01 */ UNIT_B0, 33416dce513Schristos/* C */ UNIT_C, 33516dce513Schristos/* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */ 33616dce513Schristos/* IACC */ UNIT_I01, /* iacc multiply in I0 or I1 unit. */ 33716dce513Schristos/* LOAD */ UNIT_I0, /* load only in I0 unit. */ 33816dce513Schristos/* STORE */ UNIT_I0, /* store only in I0 unit. */ 33916dce513Schristos/* SCAN */ UNIT_I0, /* scan only in I0 unit. */ 34016dce513Schristos/* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */ 34116dce513Schristos/* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */ 34216dce513Schristos/* MDCUTSSI */ UNIT_FM01, /* mdcutssi in FM0 or FM1. */ 34316dce513Schristos/* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */ 34416dce513Schristos}; 34516dce513Schristos 34616dce513Schristosstatic CGEN_ATTR_VALUE_ENUM_TYPE fr500_unit_mapping[] = 34716dce513Schristos{ 34816dce513Schristos/* unit in insn actual unit */ 34916dce513Schristos/* NIL */ UNIT_NIL, 35016dce513Schristos/* I0 */ UNIT_I0, 35116dce513Schristos/* I1 */ UNIT_I1, 35216dce513Schristos/* I01 */ UNIT_I01, 35316dce513Schristos/* I2 */ UNIT_NIL, /* no I2 or I3 unit */ 35416dce513Schristos/* I3 */ UNIT_NIL, 35516dce513Schristos/* IALL */ UNIT_I01, /* only I0 and I1 units */ 35616dce513Schristos/* FM0 */ UNIT_FM0, 35716dce513Schristos/* FM1 */ UNIT_FM1, 35816dce513Schristos/* FM01 */ UNIT_FM01, 35916dce513Schristos/* FM2 */ UNIT_NIL, /* no F2 or M2 units */ 36016dce513Schristos/* FM3 */ UNIT_NIL, /* no F3 or M2 units */ 36116dce513Schristos/* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */ 36216dce513Schristos/* FMLOW */ UNIT_FM0, /* Only F0,M0 units */ 36316dce513Schristos/* B0 */ UNIT_B0, 36416dce513Schristos/* B1 */ UNIT_B1, 36516dce513Schristos/* B01 */ UNIT_B01, 36616dce513Schristos/* C */ UNIT_C, 36716dce513Schristos/* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */ 36816dce513Schristos/* IACC */ UNIT_NIL, /* iacc multiply not implemented */ 36916dce513Schristos/* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */ 37016dce513Schristos/* STORE */ UNIT_I0, /* store only in I0 unit. */ 37116dce513Schristos/* SCAN */ UNIT_I01, /* scan in I0 or I1 unit. */ 37216dce513Schristos/* DCPL */ UNIT_C, /* dcpl only in C unit. */ 37316dce513Schristos/* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */ 37416dce513Schristos/* MDCUTSSI */ UNIT_FM0, /* mdcutssi only in FM0 unit. */ 37516dce513Schristos/* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */ 37616dce513Schristos}; 37716dce513Schristos 37816dce513Schristosstatic CGEN_ATTR_VALUE_ENUM_TYPE fr550_unit_mapping[] = 37916dce513Schristos{ 38016dce513Schristos/* unit in insn actual unit */ 38116dce513Schristos/* NIL */ UNIT_NIL, 38216dce513Schristos/* I0 */ UNIT_I0, 38316dce513Schristos/* I1 */ UNIT_I1, 38416dce513Schristos/* I01 */ UNIT_I01, 38516dce513Schristos/* I2 */ UNIT_I2, 38616dce513Schristos/* I3 */ UNIT_I3, 38716dce513Schristos/* IALL */ UNIT_IALL, 38816dce513Schristos/* FM0 */ UNIT_FM0, 38916dce513Schristos/* FM1 */ UNIT_FM1, 39016dce513Schristos/* FM01 */ UNIT_FM01, 39116dce513Schristos/* FM2 */ UNIT_FM2, 39216dce513Schristos/* FM3 */ UNIT_FM3, 39316dce513Schristos/* FMALL */ UNIT_FMALL, 39416dce513Schristos/* FMLOW */ UNIT_FM01, /* Only F0,F1,M0,M1 units */ 39516dce513Schristos/* B0 */ UNIT_B0, 39616dce513Schristos/* B1 */ UNIT_B1, 39716dce513Schristos/* B01 */ UNIT_B01, 39816dce513Schristos/* C */ UNIT_C, 39916dce513Schristos/* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */ 40016dce513Schristos/* IACC */ UNIT_NIL, /* iacc multiply not implemented. */ 40116dce513Schristos/* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */ 40216dce513Schristos/* STORE */ UNIT_I01, /* store in I0 or I1 unit. */ 40316dce513Schristos/* SCAN */ UNIT_IALL, /* scan in any integer unit. */ 40416dce513Schristos/* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */ 40516dce513Schristos/* MDUALACC */ UNIT_FMALL,/* media dual acc insn in all media units */ 40616dce513Schristos/* MDCUTSSI */ UNIT_FM01, /* mdcutssi in FM0 or FM1 unit. */ 40716dce513Schristos/* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */ 40816dce513Schristos}; 40916dce513Schristos 41016dce513Schristosvoid 41116dce513Schristosfrv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags) 41216dce513Schristos{ 41316dce513Schristos vliw->next_slot = 0; 41416dce513Schristos vliw->constraint_violation = 0; 41516dce513Schristos vliw->mach = mach; 41616dce513Schristos vliw->elf_flags = elf_flags; 41716dce513Schristos 41816dce513Schristos switch (mach) 41916dce513Schristos { 42016dce513Schristos case bfd_mach_fr400: 42116dce513Schristos vliw->current_vliw = fr400_allowed_vliw; 42216dce513Schristos vliw->unit_mapping = fr400_unit_mapping; 42316dce513Schristos break; 42416dce513Schristos case bfd_mach_fr450: 42516dce513Schristos vliw->current_vliw = fr400_allowed_vliw; 42616dce513Schristos vliw->unit_mapping = fr450_unit_mapping; 42716dce513Schristos break; 42816dce513Schristos case bfd_mach_fr550: 42916dce513Schristos vliw->current_vliw = fr550_allowed_vliw; 43016dce513Schristos vliw->unit_mapping = fr550_unit_mapping; 43116dce513Schristos break; 43216dce513Schristos default: 43316dce513Schristos vliw->current_vliw = fr500_allowed_vliw; 43416dce513Schristos vliw->unit_mapping = fr500_unit_mapping; 43516dce513Schristos break; 43616dce513Schristos } 43716dce513Schristos} 43816dce513Schristos 43916dce513Schristos/* Return TRUE if unit1 is a match for unit2. 44016dce513Schristos Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the 44116dce513Schristos *_allowed_vliw tables above. */ 442*e992f068Schristosstatic bool 44316dce513Schristosmatch_unit (FRV_VLIW *vliw, 44416dce513Schristos CGEN_ATTR_VALUE_ENUM_TYPE unit1, CGEN_ATTR_VALUE_ENUM_TYPE unit2) 44516dce513Schristos{ 44616dce513Schristos /* Map any specialized implementation units to actual ones. */ 44716dce513Schristos unit1 = vliw->unit_mapping[unit1]; 44816dce513Schristos 44916dce513Schristos if (unit1 == unit2) 450*e992f068Schristos return true; 45116dce513Schristos if (unit1 < unit2) 452*e992f068Schristos return false; 45316dce513Schristos 45416dce513Schristos switch (unit1) 45516dce513Schristos { 45616dce513Schristos case UNIT_I01: 45716dce513Schristos case UNIT_FM01: 45816dce513Schristos case UNIT_B01: 45916dce513Schristos /* The 01 versions of these units are within 2 enums of the 0 or 1 46016dce513Schristos versions. */ 46116dce513Schristos if (unit1 - unit2 <= 2) 462*e992f068Schristos return true; 46316dce513Schristos break; 46416dce513Schristos case UNIT_IALL: 46516dce513Schristos case UNIT_FMALL: 46616dce513Schristos /* The ALL versions of these units are within 5 enums of the 0, 1, 2 or 3 46716dce513Schristos versions. */ 46816dce513Schristos if (unit1 - unit2 <= 5) 469*e992f068Schristos return true; 47016dce513Schristos break; 47116dce513Schristos default: 47216dce513Schristos break; 47316dce513Schristos } 47416dce513Schristos 475*e992f068Schristos return false; 47616dce513Schristos} 47716dce513Schristos 47816dce513Schristos/* Return TRUE if the vliws match, FALSE otherwise. */ 47916dce513Schristos 480*e992f068Schristosstatic bool 48116dce513Schristosmatch_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size) 48216dce513Schristos{ 48316dce513Schristos int i; 48416dce513Schristos 48516dce513Schristos for (i = 0; i < vliw_size; ++i) 48616dce513Schristos if ((*vliw1)[i] != (*vliw2)[i]) 487*e992f068Schristos return false; 48816dce513Schristos 489*e992f068Schristos return true; 49016dce513Schristos} 49116dce513Schristos 49216dce513Schristos/* Find the next vliw vliw in the table that can accomodate the new insn. 49316dce513Schristos If one is found then return it. Otherwise return NULL. */ 49416dce513Schristos 49516dce513Schristosstatic VLIW_COMBO * 49616dce513Schristosadd_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit) 49716dce513Schristos{ 49816dce513Schristos int next = vliw->next_slot; 49916dce513Schristos VLIW_COMBO *current = vliw->current_vliw; 50016dce513Schristos VLIW_COMBO *potential; 50116dce513Schristos 50216dce513Schristos if (next <= 0) 50316dce513Schristos { 504ede78133Schristos /* xgettext:c-format */ 505ede78133Schristos opcodes_error_handler (_("internal error: bad vliw->next_slot value")); 506ede78133Schristos abort (); 50716dce513Schristos } 50816dce513Schristos 50916dce513Schristos /* The table is sorted by units allowed within slots, so vliws with 51016dce513Schristos identical starting sequences are together. */ 51116dce513Schristos potential = current; 51216dce513Schristos do 51316dce513Schristos { 51416dce513Schristos if (match_unit (vliw, unit, (*potential)[next])) 51516dce513Schristos return potential; 51616dce513Schristos ++potential; 51716dce513Schristos } 51816dce513Schristos while (match_vliw (potential, current, next)); 51916dce513Schristos 52016dce513Schristos return NULL; 52116dce513Schristos} 52216dce513Schristos 52316dce513Schristos/* Look for the given major insn type in the given vliw. 52416dce513Schristos Returns TRUE if found, FALSE otherwise. */ 52516dce513Schristos 526*e992f068Schristosstatic bool 52716dce513Schristosfind_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major) 52816dce513Schristos{ 52916dce513Schristos int i; 53016dce513Schristos 53116dce513Schristos for (i = 0; i < vliw->next_slot; ++i) 53216dce513Schristos if (vliw->major[i] == major) 533*e992f068Schristos return true; 53416dce513Schristos 535*e992f068Schristos return false; 53616dce513Schristos} 53716dce513Schristos 53816dce513Schristos/* Check for constraints between the insns in the vliw due to major insn 53916dce513Schristos types. */ 54016dce513Schristos 541*e992f068Schristosstatic bool 54216dce513Schristosfr400_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major) 54316dce513Schristos{ 54416dce513Schristos /* In the cpu file, all media insns are represented as being allowed in 54516dce513Schristos both media units. This makes it easier since this is the case for fr500. 54616dce513Schristos Catch the invalid combinations here. Insns of major class FR400_MAJOR_M_2 54716dce513Schristos cannot coexist with any other media insn in a vliw. */ 54816dce513Schristos switch (major) 54916dce513Schristos { 55016dce513Schristos case FR400_MAJOR_M_2: 55116dce513Schristos return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1) 55216dce513Schristos && ! find_major_in_vliw (vliw, FR400_MAJOR_M_2); 55316dce513Schristos case FR400_MAJOR_M_1: 55416dce513Schristos return ! find_major_in_vliw (vliw, FR400_MAJOR_M_2); 55516dce513Schristos default: 55616dce513Schristos break; 55716dce513Schristos } 558*e992f068Schristos return true; 55916dce513Schristos} 56016dce513Schristos 561*e992f068Schristosstatic bool 56216dce513Schristosfr450_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major) 56316dce513Schristos{ 56416dce513Schristos CGEN_ATTR_VALUE_ENUM_TYPE other_major; 56516dce513Schristos 56616dce513Schristos /* Our caller guarantees there's at least one other instruction. */ 56716dce513Schristos other_major = CGEN_INSN_ATTR_VALUE (vliw->insn[0], CGEN_INSN_FR450_MAJOR); 56816dce513Schristos 56916dce513Schristos /* (M4, M5) and (M4, M6) are allowed. */ 57016dce513Schristos if (other_major == FR450_MAJOR_M_4) 57116dce513Schristos if (major == FR450_MAJOR_M_5 || major == FR450_MAJOR_M_6) 572*e992f068Schristos return true; 57316dce513Schristos 57416dce513Schristos /* Otherwise, instructions in even-numbered media categories cannot be 57516dce513Schristos executed in parallel with other media instructions. */ 57616dce513Schristos switch (major) 57716dce513Schristos { 57816dce513Schristos case FR450_MAJOR_M_2: 57916dce513Schristos case FR450_MAJOR_M_4: 58016dce513Schristos case FR450_MAJOR_M_6: 58116dce513Schristos return !(other_major >= FR450_MAJOR_M_1 58216dce513Schristos && other_major <= FR450_MAJOR_M_6); 58316dce513Schristos 58416dce513Schristos case FR450_MAJOR_M_1: 58516dce513Schristos case FR450_MAJOR_M_3: 58616dce513Schristos case FR450_MAJOR_M_5: 58716dce513Schristos return !(other_major == FR450_MAJOR_M_2 58816dce513Schristos || other_major == FR450_MAJOR_M_4 58916dce513Schristos || other_major == FR450_MAJOR_M_6); 59016dce513Schristos 59116dce513Schristos default: 592*e992f068Schristos return true; 59316dce513Schristos } 59416dce513Schristos} 59516dce513Schristos 596*e992f068Schristosstatic bool 59716dce513Schristosfind_unit_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit) 59816dce513Schristos{ 59916dce513Schristos int i; 60016dce513Schristos 60116dce513Schristos for (i = 0; i < vliw->next_slot; ++i) 60216dce513Schristos if (CGEN_INSN_ATTR_VALUE (vliw->insn[i], CGEN_INSN_UNIT) == unit) 603*e992f068Schristos return true; 60416dce513Schristos 605*e992f068Schristos return false; /* Not found. */ 60616dce513Schristos} 60716dce513Schristos 608*e992f068Schristosstatic bool 60916dce513Schristosfind_major_in_slot (FRV_VLIW *vliw, 61016dce513Schristos CGEN_ATTR_VALUE_ENUM_TYPE major, 61116dce513Schristos CGEN_ATTR_VALUE_ENUM_TYPE slot) 61216dce513Schristos{ 61316dce513Schristos int i; 61416dce513Schristos 61516dce513Schristos for (i = 0; i < vliw->next_slot; ++i) 61616dce513Schristos if (vliw->major[i] == major && (*vliw->current_vliw)[i] == slot) 617*e992f068Schristos return true; 61816dce513Schristos 619*e992f068Schristos return false; 62016dce513Schristos} 62116dce513Schristos 622*e992f068Schristosstatic bool 62316dce513Schristosfr550_find_media_in_vliw (FRV_VLIW *vliw) 62416dce513Schristos{ 62516dce513Schristos int i; 62616dce513Schristos 62716dce513Schristos for (i = 0; i < vliw->next_slot; ++i) 62816dce513Schristos { 62916dce513Schristos if (vliw->major[i] < FR550_MAJOR_M_1 || vliw->major[i] > FR550_MAJOR_M_5) 63016dce513Schristos continue; 63116dce513Schristos 63216dce513Schristos /* Found a media insn, however, MNOP and MCLRACC don't count. */ 63316dce513Schristos if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MNOP 63416dce513Schristos || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_0 63516dce513Schristos || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_1) 63616dce513Schristos continue; 63716dce513Schristos 638*e992f068Schristos return true; /* Found one. */ 63916dce513Schristos } 64016dce513Schristos 641*e992f068Schristos return false; 64216dce513Schristos} 64316dce513Schristos 644*e992f068Schristosstatic bool 64516dce513Schristosfr550_find_float_in_vliw (FRV_VLIW *vliw) 64616dce513Schristos{ 64716dce513Schristos int i; 64816dce513Schristos 64916dce513Schristos for (i = 0; i < vliw->next_slot; ++i) 65016dce513Schristos { 65116dce513Schristos if (vliw->major[i] < FR550_MAJOR_F_1 || vliw->major[i] > FR550_MAJOR_F_4) 65216dce513Schristos continue; 65316dce513Schristos 65416dce513Schristos /* Found a floating point insn, however, FNOP doesn't count. */ 65516dce513Schristos if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_FNOP) 65616dce513Schristos continue; 65716dce513Schristos 658*e992f068Schristos return true; /* Found one. */ 65916dce513Schristos } 66016dce513Schristos 661*e992f068Schristos return false; 66216dce513Schristos} 66316dce513Schristos 664*e992f068Schristosstatic bool 66516dce513Schristosfr550_check_insn_major_constraints (FRV_VLIW *vliw, 66616dce513Schristos CGEN_ATTR_VALUE_ENUM_TYPE major, 66716dce513Schristos const CGEN_INSN *insn) 66816dce513Schristos{ 66916dce513Schristos CGEN_ATTR_VALUE_ENUM_TYPE unit; 67016dce513Schristos CGEN_ATTR_VALUE_ENUM_TYPE slot = (*vliw->current_vliw)[vliw->next_slot]; 67116dce513Schristos switch (slot) 67216dce513Schristos { 67316dce513Schristos case UNIT_I2: 67416dce513Schristos /* If it's a store, then there must be another store in I1 */ 67516dce513Schristos unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT); 67616dce513Schristos if (unit == UNIT_STORE) 67716dce513Schristos return find_unit_in_vliw (vliw, UNIT_STORE); 67816dce513Schristos break; 67916dce513Schristos case UNIT_FM2: 68016dce513Schristos case UNIT_FM3: 68116dce513Schristos /* Floating point insns other than FNOP in slot f2 or f3 cannot coexist 68216dce513Schristos with media insns. */ 68316dce513Schristos if (major >= FR550_MAJOR_F_1 && major <= FR550_MAJOR_F_4 68416dce513Schristos && CGEN_INSN_NUM (insn) != FRV_INSN_FNOP) 68516dce513Schristos return ! fr550_find_media_in_vliw (vliw); 68616dce513Schristos /* Media insns other than MNOP in slot m2 or m3 cannot coexist with 68716dce513Schristos floating point insns. */ 68816dce513Schristos if (major >= FR550_MAJOR_M_1 && major <= FR550_MAJOR_M_5 68916dce513Schristos && CGEN_INSN_NUM (insn) != FRV_INSN_MNOP) 69016dce513Schristos return ! fr550_find_float_in_vliw (vliw); 69116dce513Schristos /* F-2 in slot f2 or f3 cannot coexist with F-2 or F-4 in slot f1 or f2 69216dce513Schristos respectively. */ 69316dce513Schristos if (major == FR550_MAJOR_F_2) 69416dce513Schristos return ! find_major_in_slot (vliw, FR550_MAJOR_F_2, 69516dce513Schristos slot - (UNIT_FM2 - UNIT_FM0)) 69616dce513Schristos && ! find_major_in_slot (vliw, FR550_MAJOR_F_4, 69716dce513Schristos slot - (UNIT_FM2 - UNIT_FM0)); 69816dce513Schristos /* M-2 or M-5 in slot m2 or m3 cannot coexist with M-2 in slot m1 or m2 69916dce513Schristos respectively. */ 70016dce513Schristos if (major == FR550_MAJOR_M_2 || major == FR550_MAJOR_M_5) 70116dce513Schristos return ! find_major_in_slot (vliw, FR550_MAJOR_M_2, 70216dce513Schristos slot - (UNIT_FM2 - UNIT_FM0)); 70316dce513Schristos /* M-4 in slot m2 or m3 cannot coexist with M-4 in slot m1 or m2 70416dce513Schristos respectively. */ 70516dce513Schristos if (major == FR550_MAJOR_M_4) 70616dce513Schristos return ! find_major_in_slot (vliw, FR550_MAJOR_M_4, 70716dce513Schristos slot - (UNIT_FM2 - UNIT_FM0)); 70816dce513Schristos break; 70916dce513Schristos default: 71016dce513Schristos break; 71116dce513Schristos } 712*e992f068Schristos return true; /* All OK. */ 71316dce513Schristos} 71416dce513Schristos 715*e992f068Schristosstatic bool 71616dce513Schristosfr500_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major) 71716dce513Schristos{ 71816dce513Schristos /* TODO: A table might be faster for some of the more complex instances 71916dce513Schristos here. */ 72016dce513Schristos switch (major) 72116dce513Schristos { 72216dce513Schristos case FR500_MAJOR_I_1: 72316dce513Schristos case FR500_MAJOR_I_4: 72416dce513Schristos case FR500_MAJOR_I_5: 72516dce513Schristos case FR500_MAJOR_I_6: 72616dce513Schristos case FR500_MAJOR_B_1: 72716dce513Schristos case FR500_MAJOR_B_2: 72816dce513Schristos case FR500_MAJOR_B_3: 72916dce513Schristos case FR500_MAJOR_B_4: 73016dce513Schristos case FR500_MAJOR_B_5: 73116dce513Schristos case FR500_MAJOR_B_6: 73216dce513Schristos case FR500_MAJOR_F_4: 73316dce513Schristos case FR500_MAJOR_F_8: 73416dce513Schristos case FR500_MAJOR_M_8: 735*e992f068Schristos return true; /* OK */ 73616dce513Schristos case FR500_MAJOR_I_2: 73716dce513Schristos /* Cannot coexist with I-3 insn. */ 73816dce513Schristos return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3); 73916dce513Schristos case FR500_MAJOR_I_3: 74016dce513Schristos /* Cannot coexist with I-2 insn. */ 74116dce513Schristos return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2); 74216dce513Schristos case FR500_MAJOR_F_1: 74316dce513Schristos case FR500_MAJOR_F_2: 74416dce513Schristos /* Cannot coexist with F-5, F-6, or M-7 insn. */ 74516dce513Schristos return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5) 74616dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6) 74716dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 74816dce513Schristos case FR500_MAJOR_F_3: 74916dce513Schristos /* Cannot coexist with F-7, or M-7 insn. */ 75016dce513Schristos return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7) 75116dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 75216dce513Schristos case FR500_MAJOR_F_5: 75316dce513Schristos /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn. */ 75416dce513Schristos return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1) 75516dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2) 75616dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6) 75716dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7) 75816dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 75916dce513Schristos case FR500_MAJOR_F_6: 76016dce513Schristos /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn. */ 76116dce513Schristos return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1) 76216dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2) 76316dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5) 76416dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6) 76516dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 76616dce513Schristos case FR500_MAJOR_F_7: 76716dce513Schristos /* Cannot coexist with F-3, F-5, F-7, or M-7 insn. */ 76816dce513Schristos return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3) 76916dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5) 77016dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7) 77116dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 77216dce513Schristos case FR500_MAJOR_M_1: 77316dce513Schristos /* Cannot coexist with M-7 insn. */ 77416dce513Schristos return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 77516dce513Schristos case FR500_MAJOR_M_2: 77616dce513Schristos case FR500_MAJOR_M_3: 77716dce513Schristos /* Cannot coexist with M-5, M-6 or M-7 insn. */ 77816dce513Schristos return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5) 77916dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6) 78016dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 78116dce513Schristos case FR500_MAJOR_M_4: 78216dce513Schristos /* Cannot coexist with M-6 insn. */ 78316dce513Schristos return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6); 78416dce513Schristos case FR500_MAJOR_M_5: 78516dce513Schristos /* Cannot coexist with M-2, M-3, M-5, M-6 or M-7 insn. */ 78616dce513Schristos return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2) 78716dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3) 78816dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5) 78916dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6) 79016dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 79116dce513Schristos case FR500_MAJOR_M_6: 79216dce513Schristos /* Cannot coexist with M-2, M-3, M-4, M-5, M-6 or M-7 insn. */ 79316dce513Schristos return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2) 79416dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3) 79516dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_4) 79616dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5) 79716dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6) 79816dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7); 79916dce513Schristos case FR500_MAJOR_M_7: 80016dce513Schristos /* Cannot coexist with M-1, M-2, M-3, M-5, M-6 or M-7 insn. */ 80116dce513Schristos return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1) 80216dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_2) 80316dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3) 80416dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5) 80516dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6) 80616dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7) 80716dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_F_1) 80816dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2) 80916dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_F_3) 81016dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5) 81116dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6) 81216dce513Schristos && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7); 81316dce513Schristos default: 814ede78133Schristos /* xgettext:c-format */ 815ede78133Schristos opcodes_error_handler (_("internal error: bad major code")); 81616dce513Schristos abort (); 81716dce513Schristos break; 81816dce513Schristos } 819*e992f068Schristos return true; 82016dce513Schristos} 82116dce513Schristos 822*e992f068Schristosstatic bool 82316dce513Schristoscheck_insn_major_constraints (FRV_VLIW *vliw, 82416dce513Schristos CGEN_ATTR_VALUE_ENUM_TYPE major, 82516dce513Schristos const CGEN_INSN *insn) 82616dce513Schristos{ 82716dce513Schristos switch (vliw->mach) 82816dce513Schristos { 82916dce513Schristos case bfd_mach_fr400: 83016dce513Schristos return fr400_check_insn_major_constraints (vliw, major); 83116dce513Schristos 83216dce513Schristos case bfd_mach_fr450: 83316dce513Schristos return fr450_check_insn_major_constraints (vliw, major); 83416dce513Schristos 83516dce513Schristos case bfd_mach_fr550: 83616dce513Schristos return fr550_check_insn_major_constraints (vliw, major, insn); 83716dce513Schristos 83816dce513Schristos default: 83916dce513Schristos return fr500_check_insn_major_constraints (vliw, major); 84016dce513Schristos } 84116dce513Schristos} 84216dce513Schristos 84316dce513Schristos/* Add in insn to the VLIW vliw if possible. 84416dce513Schristos Return 0 if successful, non-zero otherwise. */ 84516dce513Schristos 84616dce513Schristosint 84716dce513Schristosfrv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn) 84816dce513Schristos{ 84916dce513Schristos int slot_index; 85016dce513Schristos CGEN_ATTR_VALUE_ENUM_TYPE major; 85116dce513Schristos CGEN_ATTR_VALUE_ENUM_TYPE unit; 85216dce513Schristos VLIW_COMBO *new_vliw; 85316dce513Schristos 85416dce513Schristos if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn)) 85516dce513Schristos return 1; 85616dce513Schristos 85716dce513Schristos slot_index = vliw->next_slot; 85816dce513Schristos if (slot_index >= FRV_VLIW_SIZE) 85916dce513Schristos return 1; 86016dce513Schristos 86116dce513Schristos unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT); 86216dce513Schristos if (unit == UNIT_NIL) 86316dce513Schristos { 864ede78133Schristos /* xgettext:c-format */ 865ede78133Schristos opcodes_error_handler (_("internal error: bad insn unit")); 866ede78133Schristos abort (); 86716dce513Schristos } 86816dce513Schristos 86916dce513Schristos switch (vliw->mach) 87016dce513Schristos { 87116dce513Schristos case bfd_mach_fr400: 87216dce513Schristos major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR); 87316dce513Schristos break; 87416dce513Schristos case bfd_mach_fr450: 87516dce513Schristos major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR); 87616dce513Schristos break; 87716dce513Schristos case bfd_mach_fr550: 87816dce513Schristos major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR550_MAJOR); 87916dce513Schristos break; 88016dce513Schristos default: 88116dce513Schristos major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR); 88216dce513Schristos break; 88316dce513Schristos } 88416dce513Schristos 88516dce513Schristos if (slot_index <= 0) 88616dce513Schristos { 88716dce513Schristos /* Any insn can be added to slot 0. */ 88816dce513Schristos while (! match_unit (vliw, unit, (*vliw->current_vliw)[0])) 88916dce513Schristos ++vliw->current_vliw; 89016dce513Schristos vliw->major[0] = major; 89116dce513Schristos vliw->insn[0] = insn; 89216dce513Schristos vliw->next_slot = 1; 89316dce513Schristos return 0; 89416dce513Schristos } 89516dce513Schristos 89616dce513Schristos /* If there are already insns in the vliw(s) check to see that 89716dce513Schristos this one can be added. Do this by finding an allowable vliw 89816dce513Schristos combination that can accept the new insn. */ 89916dce513Schristos if (! (vliw->elf_flags & EF_FRV_NOPACK)) 90016dce513Schristos { 90116dce513Schristos new_vliw = add_next_to_vliw (vliw, unit); 90216dce513Schristos if (new_vliw && check_insn_major_constraints (vliw, major, insn)) 90316dce513Schristos { 90416dce513Schristos vliw->current_vliw = new_vliw; 90516dce513Schristos vliw->major[slot_index] = major; 90616dce513Schristos vliw->insn[slot_index] = insn; 90716dce513Schristos vliw->next_slot++; 90816dce513Schristos return 0; 90916dce513Schristos } 91016dce513Schristos 91116dce513Schristos /* The frv machine supports all packing conbinations. If we fail, 91216dce513Schristos to add the insn, then it could not be handled as if it was the fr500. 91316dce513Schristos Just return as if it was handled ok. */ 91416dce513Schristos if (vliw->mach == bfd_mach_frv) 91516dce513Schristos return 0; 91616dce513Schristos } 91716dce513Schristos 91816dce513Schristos vliw->constraint_violation = 1; 91916dce513Schristos return 1; 92016dce513Schristos} 92116dce513Schristos 922*e992f068Schristosbool 92316dce513Schristosspr_valid (long regno) 92416dce513Schristos{ 925*e992f068Schristos if (regno < 0) return false; 926*e992f068Schristos if (regno <= 4095) return true; 927*e992f068Schristos return false; 92816dce513Schristos} 92916dce513Schristos/* -- */ 93016dce513Schristos 93116dce513Schristos/* -- asm.c */ 93216dce513Schristosinline static const char * 93316dce513Schristosparse_symbolic_address (CGEN_CPU_DESC cd, 93416dce513Schristos const char **strp, 93516dce513Schristos int opindex, 93616dce513Schristos int opinfo, 93716dce513Schristos enum cgen_parse_operand_result *resultp, 93816dce513Schristos bfd_vma *valuep) 93916dce513Schristos{ 94016dce513Schristos enum cgen_parse_operand_result result_type; 94116dce513Schristos const char *errmsg = (* cd->parse_operand_fn) 94216dce513Schristos (cd, CGEN_PARSE_OPERAND_SYMBOLIC, strp, opindex, opinfo, 94316dce513Schristos &result_type, valuep); 94416dce513Schristos 94516dce513Schristos if (errmsg == NULL 94616dce513Schristos && result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED) 94716dce513Schristos return "symbolic expression required"; 94816dce513Schristos 94916dce513Schristos if (resultp) 95016dce513Schristos *resultp = result_type; 95116dce513Schristos 95216dce513Schristos return errmsg; 95316dce513Schristos} 95416dce513Schristos 95516dce513Schristosstatic const char * 95616dce513Schristosparse_ldd_annotation (CGEN_CPU_DESC cd, 95716dce513Schristos const char **strp, 95816dce513Schristos int opindex, 95916dce513Schristos unsigned long *valuep) 96016dce513Schristos{ 96116dce513Schristos const char *errmsg; 96216dce513Schristos enum cgen_parse_operand_result result_type; 96316dce513Schristos bfd_vma value; 96416dce513Schristos 96516dce513Schristos if (**strp == '#' || **strp == '%') 96616dce513Schristos { 96716dce513Schristos if (strncasecmp (*strp + 1, "tlsdesc(", 8) == 0) 96816dce513Schristos { 96916dce513Schristos *strp += 9; 97016dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 97116dce513Schristos BFD_RELOC_FRV_TLSDESC_RELAX, 97216dce513Schristos &result_type, &value); 97316dce513Schristos if (**strp != ')') 97416dce513Schristos return "missing ')'"; 97516dce513Schristos if (valuep) 97616dce513Schristos *valuep = value; 97716dce513Schristos ++*strp; 97816dce513Schristos if (errmsg) 97916dce513Schristos return errmsg; 98016dce513Schristos } 98116dce513Schristos } 98216dce513Schristos 98316dce513Schristos while (**strp == ' ' || **strp == '\t') 98416dce513Schristos ++*strp; 98516dce513Schristos 98616dce513Schristos if (**strp != '@') 98716dce513Schristos return "missing `@'"; 98816dce513Schristos 98916dce513Schristos ++*strp; 99016dce513Schristos 99116dce513Schristos return NULL; 99216dce513Schristos} 99316dce513Schristos 99416dce513Schristosstatic const char * 99516dce513Schristosparse_call_annotation (CGEN_CPU_DESC cd, 99616dce513Schristos const char **strp, 99716dce513Schristos int opindex, 99816dce513Schristos unsigned long *valuep) 99916dce513Schristos{ 100016dce513Schristos const char *errmsg; 100116dce513Schristos enum cgen_parse_operand_result result_type; 100216dce513Schristos bfd_vma value; 100316dce513Schristos 100416dce513Schristos if (**strp == '#' || **strp == '%') 100516dce513Schristos { 100616dce513Schristos if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0) 100716dce513Schristos { 100816dce513Schristos *strp += 11; 100916dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 101016dce513Schristos BFD_RELOC_FRV_GETTLSOFF_RELAX, 101116dce513Schristos &result_type, &value); 101216dce513Schristos if (**strp != ')') 101316dce513Schristos return "missing ')'"; 101416dce513Schristos if (valuep) 101516dce513Schristos *valuep = value; 101616dce513Schristos ++*strp; 101716dce513Schristos if (errmsg) 101816dce513Schristos return errmsg; 101916dce513Schristos } 102016dce513Schristos } 102116dce513Schristos 102216dce513Schristos while (**strp == ' ' || **strp == '\t') 102316dce513Schristos ++*strp; 102416dce513Schristos 102516dce513Schristos if (**strp != '@') 102616dce513Schristos return "missing `@'"; 102716dce513Schristos 102816dce513Schristos ++*strp; 102916dce513Schristos 103016dce513Schristos return NULL; 103116dce513Schristos} 103216dce513Schristos 103316dce513Schristosstatic const char * 103416dce513Schristosparse_ld_annotation (CGEN_CPU_DESC cd, 103516dce513Schristos const char **strp, 103616dce513Schristos int opindex, 103716dce513Schristos unsigned long *valuep) 103816dce513Schristos{ 103916dce513Schristos const char *errmsg; 104016dce513Schristos enum cgen_parse_operand_result result_type; 104116dce513Schristos bfd_vma value; 104216dce513Schristos 104316dce513Schristos if (**strp == '#' || **strp == '%') 104416dce513Schristos { 104516dce513Schristos if (strncasecmp (*strp + 1, "tlsoff(", 7) == 0) 104616dce513Schristos { 104716dce513Schristos *strp += 8; 104816dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 104916dce513Schristos BFD_RELOC_FRV_TLSOFF_RELAX, 105016dce513Schristos &result_type, &value); 105116dce513Schristos if (**strp != ')') 105216dce513Schristos return "missing ')'"; 105316dce513Schristos if (valuep) 105416dce513Schristos *valuep = value; 105516dce513Schristos ++*strp; 105616dce513Schristos if (errmsg) 105716dce513Schristos return errmsg; 105816dce513Schristos } 105916dce513Schristos } 106016dce513Schristos 106116dce513Schristos while (**strp == ' ' || **strp == '\t') 106216dce513Schristos ++*strp; 106316dce513Schristos 106416dce513Schristos if (**strp != '@') 106516dce513Schristos return "missing `@'"; 106616dce513Schristos 106716dce513Schristos ++*strp; 106816dce513Schristos 106916dce513Schristos return NULL; 107016dce513Schristos} 107116dce513Schristos 107216dce513Schristosstatic const char * 107316dce513Schristosparse_ulo16 (CGEN_CPU_DESC cd, 107416dce513Schristos const char **strp, 107516dce513Schristos int opindex, 107616dce513Schristos unsigned long *valuep) 107716dce513Schristos{ 107816dce513Schristos const char *errmsg; 107916dce513Schristos enum cgen_parse_operand_result result_type; 108016dce513Schristos bfd_vma value; 108116dce513Schristos 108216dce513Schristos if (**strp == '#' || **strp == '%') 108316dce513Schristos { 108416dce513Schristos if (strncasecmp (*strp + 1, "lo(", 3) == 0) 108516dce513Schristos { 108616dce513Schristos *strp += 4; 108716dce513Schristos errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16, 108816dce513Schristos & result_type, & value); 108916dce513Schristos if (**strp != ')') 109016dce513Schristos return "missing `)'"; 109116dce513Schristos ++*strp; 109216dce513Schristos if (errmsg == NULL 109316dce513Schristos && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 109416dce513Schristos value &= 0xffff; 109516dce513Schristos *valuep = value; 109616dce513Schristos return errmsg; 109716dce513Schristos } 109816dce513Schristos if (strncasecmp (*strp + 1, "gprello(", 8) == 0) 109916dce513Schristos { 110016dce513Schristos *strp += 9; 110116dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 110216dce513Schristos BFD_RELOC_FRV_GPRELLO, 110316dce513Schristos & result_type, & value); 110416dce513Schristos if (**strp != ')') 110516dce513Schristos return "missing ')'"; 110616dce513Schristos ++*strp; 110716dce513Schristos *valuep = value; 110816dce513Schristos return errmsg; 110916dce513Schristos } 111016dce513Schristos else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0) 111116dce513Schristos { 111216dce513Schristos *strp += 7; 111316dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 111416dce513Schristos BFD_RELOC_FRV_GOTLO, 111516dce513Schristos & result_type, & value); 111616dce513Schristos if (**strp != ')') 111716dce513Schristos return "missing ')'"; 111816dce513Schristos ++*strp; 111916dce513Schristos *valuep = value; 112016dce513Schristos return errmsg; 112116dce513Schristos } 112216dce513Schristos else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0) 112316dce513Schristos { 112416dce513Schristos *strp += 15; 112516dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 112616dce513Schristos BFD_RELOC_FRV_FUNCDESC_GOTLO, 112716dce513Schristos & result_type, & value); 112816dce513Schristos if (**strp != ')') 112916dce513Schristos return "missing ')'"; 113016dce513Schristos ++*strp; 113116dce513Schristos *valuep = value; 113216dce513Schristos return errmsg; 113316dce513Schristos } 113416dce513Schristos else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0) 113516dce513Schristos { 113616dce513Schristos *strp += 10; 113716dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 113816dce513Schristos BFD_RELOC_FRV_GOTOFFLO, 113916dce513Schristos & result_type, & value); 114016dce513Schristos if (**strp != ')') 114116dce513Schristos return "missing ')'"; 114216dce513Schristos ++*strp; 114316dce513Schristos *valuep = value; 114416dce513Schristos return errmsg; 114516dce513Schristos } 114616dce513Schristos else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0) 114716dce513Schristos { 114816dce513Schristos *strp += 18; 114916dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 115016dce513Schristos BFD_RELOC_FRV_FUNCDESC_GOTOFFLO, 115116dce513Schristos & result_type, & value); 115216dce513Schristos if (**strp != ')') 115316dce513Schristos return "missing ')'"; 115416dce513Schristos ++*strp; 115516dce513Schristos *valuep = value; 115616dce513Schristos return errmsg; 115716dce513Schristos } 115816dce513Schristos else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0) 115916dce513Schristos { 116016dce513Schristos *strp += 14; 116116dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 116216dce513Schristos BFD_RELOC_FRV_GOTTLSDESCLO, 116316dce513Schristos & result_type, & value); 116416dce513Schristos if (**strp != ')') 116516dce513Schristos return "missing ')'"; 116616dce513Schristos ++*strp; 116716dce513Schristos *valuep = value; 116816dce513Schristos return errmsg; 116916dce513Schristos } 117016dce513Schristos else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0) 117116dce513Schristos { 117216dce513Schristos *strp += 11; 117316dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 117416dce513Schristos BFD_RELOC_FRV_TLSMOFFLO, 117516dce513Schristos & result_type, & value); 117616dce513Schristos if (**strp != ')') 117716dce513Schristos return "missing ')'"; 117816dce513Schristos ++*strp; 117916dce513Schristos *valuep = value; 118016dce513Schristos return errmsg; 118116dce513Schristos } 118216dce513Schristos else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0) 118316dce513Schristos { 118416dce513Schristos *strp += 13; 118516dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 118616dce513Schristos BFD_RELOC_FRV_GOTTLSOFFLO, 118716dce513Schristos & result_type, & value); 118816dce513Schristos if (**strp != ')') 118916dce513Schristos return "missing ')'"; 119016dce513Schristos ++*strp; 119116dce513Schristos *valuep = value; 119216dce513Schristos return errmsg; 119316dce513Schristos } 119416dce513Schristos } 119516dce513Schristos return cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 119616dce513Schristos} 119716dce513Schristos 119816dce513Schristosstatic const char * 119916dce513Schristosparse_uslo16 (CGEN_CPU_DESC cd, 120016dce513Schristos const char **strp, 120116dce513Schristos int opindex, 120216dce513Schristos signed long *valuep) 120316dce513Schristos{ 120416dce513Schristos const char *errmsg; 120516dce513Schristos enum cgen_parse_operand_result result_type; 120616dce513Schristos bfd_vma value; 120716dce513Schristos 120816dce513Schristos if (**strp == '#' || **strp == '%') 120916dce513Schristos { 121016dce513Schristos if (strncasecmp (*strp + 1, "lo(", 3) == 0) 121116dce513Schristos { 121216dce513Schristos *strp += 4; 121316dce513Schristos errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16, 121416dce513Schristos & result_type, & value); 121516dce513Schristos if (**strp != ')') 121616dce513Schristos return "missing `)'"; 121716dce513Schristos ++*strp; 121816dce513Schristos if (errmsg == NULL 121916dce513Schristos && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 122016dce513Schristos value &= 0xffff; 122116dce513Schristos *valuep = value; 122216dce513Schristos return errmsg; 122316dce513Schristos } 122416dce513Schristos else if (strncasecmp (*strp + 1, "gprello(", 8) == 0) 122516dce513Schristos { 122616dce513Schristos *strp += 9; 122716dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 122816dce513Schristos BFD_RELOC_FRV_GPRELLO, 122916dce513Schristos & result_type, & value); 123016dce513Schristos if (**strp != ')') 123116dce513Schristos return "missing ')'"; 123216dce513Schristos ++*strp; 123316dce513Schristos *valuep = value; 123416dce513Schristos return errmsg; 123516dce513Schristos } 123616dce513Schristos else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0) 123716dce513Schristos { 123816dce513Schristos *strp += 7; 123916dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 124016dce513Schristos BFD_RELOC_FRV_GOTLO, 124116dce513Schristos & result_type, & value); 124216dce513Schristos if (**strp != ')') 124316dce513Schristos return "missing ')'"; 124416dce513Schristos ++*strp; 124516dce513Schristos *valuep = value; 124616dce513Schristos return errmsg; 124716dce513Schristos } 124816dce513Schristos else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0) 124916dce513Schristos { 125016dce513Schristos *strp += 15; 125116dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 125216dce513Schristos BFD_RELOC_FRV_FUNCDESC_GOTLO, 125316dce513Schristos & result_type, & value); 125416dce513Schristos if (**strp != ')') 125516dce513Schristos return "missing ')'"; 125616dce513Schristos ++*strp; 125716dce513Schristos *valuep = value; 125816dce513Schristos return errmsg; 125916dce513Schristos } 126016dce513Schristos else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0) 126116dce513Schristos { 126216dce513Schristos *strp += 10; 126316dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 126416dce513Schristos BFD_RELOC_FRV_GOTOFFLO, 126516dce513Schristos & result_type, & value); 126616dce513Schristos if (**strp != ')') 126716dce513Schristos return "missing ')'"; 126816dce513Schristos ++*strp; 126916dce513Schristos *valuep = value; 127016dce513Schristos return errmsg; 127116dce513Schristos } 127216dce513Schristos else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0) 127316dce513Schristos { 127416dce513Schristos *strp += 18; 127516dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 127616dce513Schristos BFD_RELOC_FRV_FUNCDESC_GOTOFFLO, 127716dce513Schristos & result_type, & value); 127816dce513Schristos if (**strp != ')') 127916dce513Schristos return "missing ')'"; 128016dce513Schristos ++*strp; 128116dce513Schristos *valuep = value; 128216dce513Schristos return errmsg; 128316dce513Schristos } 128416dce513Schristos else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0) 128516dce513Schristos { 128616dce513Schristos *strp += 14; 128716dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 128816dce513Schristos BFD_RELOC_FRV_GOTTLSDESCLO, 128916dce513Schristos & result_type, & value); 129016dce513Schristos if (**strp != ')') 129116dce513Schristos return "missing ')'"; 129216dce513Schristos ++*strp; 129316dce513Schristos *valuep = value; 129416dce513Schristos return errmsg; 129516dce513Schristos } 129616dce513Schristos else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0) 129716dce513Schristos { 129816dce513Schristos *strp += 11; 129916dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 130016dce513Schristos BFD_RELOC_FRV_TLSMOFFLO, 130116dce513Schristos & result_type, & value); 130216dce513Schristos if (**strp != ')') 130316dce513Schristos return "missing ')'"; 130416dce513Schristos ++*strp; 130516dce513Schristos *valuep = value; 130616dce513Schristos return errmsg; 130716dce513Schristos } 130816dce513Schristos else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0) 130916dce513Schristos { 131016dce513Schristos *strp += 13; 131116dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 131216dce513Schristos BFD_RELOC_FRV_GOTTLSOFFLO, 131316dce513Schristos & result_type, & value); 131416dce513Schristos if (**strp != ')') 131516dce513Schristos return "missing ')'"; 131616dce513Schristos ++*strp; 131716dce513Schristos *valuep = value; 131816dce513Schristos return errmsg; 131916dce513Schristos } 132016dce513Schristos } 132116dce513Schristos return cgen_parse_signed_integer (cd, strp, opindex, valuep); 132216dce513Schristos} 132316dce513Schristos 132416dce513Schristosstatic const char * 132516dce513Schristosparse_uhi16 (CGEN_CPU_DESC cd, 132616dce513Schristos const char **strp, 132716dce513Schristos int opindex, 132816dce513Schristos unsigned long *valuep) 132916dce513Schristos{ 133016dce513Schristos const char *errmsg; 133116dce513Schristos enum cgen_parse_operand_result result_type; 133216dce513Schristos bfd_vma value; 133316dce513Schristos 133416dce513Schristos if (**strp == '#' || **strp == '%') 133516dce513Schristos { 133616dce513Schristos if (strncasecmp (*strp + 1, "hi(", 3) == 0) 133716dce513Schristos { 133816dce513Schristos *strp += 4; 133916dce513Schristos errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16, 134016dce513Schristos & result_type, & value); 134116dce513Schristos if (**strp != ')') 134216dce513Schristos return "missing `)'"; 134316dce513Schristos ++*strp; 134416dce513Schristos if (errmsg == NULL 134516dce513Schristos && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 134616dce513Schristos { 134716dce513Schristos /* If value is wider than 32 bits then be 134816dce513Schristos careful about how we extract bits 16-31. */ 134916dce513Schristos if (sizeof (value) > 4) 135016dce513Schristos value &= (((bfd_vma)1 << 16) << 16) - 1; 135116dce513Schristos 135216dce513Schristos value >>= 16; 135316dce513Schristos } 135416dce513Schristos *valuep = value; 135516dce513Schristos return errmsg; 135616dce513Schristos } 135716dce513Schristos else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0) 135816dce513Schristos { 135916dce513Schristos *strp += 9; 136016dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 136116dce513Schristos BFD_RELOC_FRV_GPRELHI, 136216dce513Schristos & result_type, & value); 136316dce513Schristos if (**strp != ')') 136416dce513Schristos return "missing ')'"; 136516dce513Schristos ++*strp; 136616dce513Schristos *valuep = value; 136716dce513Schristos return errmsg; 136816dce513Schristos } 136916dce513Schristos else if (strncasecmp (*strp + 1, "gothi(", 6) == 0) 137016dce513Schristos { 137116dce513Schristos *strp += 7; 137216dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 137316dce513Schristos BFD_RELOC_FRV_GOTHI, 137416dce513Schristos & result_type, & value); 137516dce513Schristos if (**strp != ')') 137616dce513Schristos return "missing ')'"; 137716dce513Schristos ++*strp; 137816dce513Schristos *valuep = value; 137916dce513Schristos return errmsg; 138016dce513Schristos } 138116dce513Schristos else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0) 138216dce513Schristos { 138316dce513Schristos *strp += 15; 138416dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 138516dce513Schristos BFD_RELOC_FRV_FUNCDESC_GOTHI, 138616dce513Schristos & result_type, & value); 138716dce513Schristos if (**strp != ')') 138816dce513Schristos return "missing ')'"; 138916dce513Schristos ++*strp; 139016dce513Schristos *valuep = value; 139116dce513Schristos return errmsg; 139216dce513Schristos } 139316dce513Schristos else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0) 139416dce513Schristos { 139516dce513Schristos *strp += 10; 139616dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 139716dce513Schristos BFD_RELOC_FRV_GOTOFFHI, 139816dce513Schristos & result_type, & value); 139916dce513Schristos if (**strp != ')') 140016dce513Schristos return "missing ')'"; 140116dce513Schristos ++*strp; 140216dce513Schristos *valuep = value; 140316dce513Schristos return errmsg; 140416dce513Schristos } 140516dce513Schristos else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0) 140616dce513Schristos { 140716dce513Schristos *strp += 18; 140816dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 140916dce513Schristos BFD_RELOC_FRV_FUNCDESC_GOTOFFHI, 141016dce513Schristos & result_type, & value); 141116dce513Schristos if (**strp != ')') 141216dce513Schristos return "missing ')'"; 141316dce513Schristos ++*strp; 141416dce513Schristos *valuep = value; 141516dce513Schristos return errmsg; 141616dce513Schristos } 141716dce513Schristos else if (strncasecmp (*strp + 1, "gottlsdeschi(", 13) == 0) 141816dce513Schristos { 141916dce513Schristos *strp += 14; 142016dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 142116dce513Schristos BFD_RELOC_FRV_GOTTLSDESCHI, 142216dce513Schristos &result_type, &value); 142316dce513Schristos if (**strp != ')') 142416dce513Schristos return "missing ')'"; 142516dce513Schristos ++*strp; 142616dce513Schristos *valuep = value; 142716dce513Schristos return errmsg; 142816dce513Schristos } 142916dce513Schristos else if (strncasecmp (*strp + 1, "tlsmoffhi(", 10) == 0) 143016dce513Schristos { 143116dce513Schristos *strp += 11; 143216dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 143316dce513Schristos BFD_RELOC_FRV_TLSMOFFHI, 143416dce513Schristos & result_type, & value); 143516dce513Schristos if (**strp != ')') 143616dce513Schristos return "missing ')'"; 143716dce513Schristos ++*strp; 143816dce513Schristos *valuep = value; 143916dce513Schristos return errmsg; 144016dce513Schristos } 144116dce513Schristos else if (strncasecmp (*strp + 1, "gottlsoffhi(", 12) == 0) 144216dce513Schristos { 144316dce513Schristos *strp += 13; 144416dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 144516dce513Schristos BFD_RELOC_FRV_GOTTLSOFFHI, 144616dce513Schristos & result_type, & value); 144716dce513Schristos if (**strp != ')') 144816dce513Schristos return "missing ')'"; 144916dce513Schristos ++*strp; 145016dce513Schristos *valuep = value; 145116dce513Schristos return errmsg; 145216dce513Schristos } 145316dce513Schristos } 145416dce513Schristos return cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 145516dce513Schristos} 145616dce513Schristos 145716dce513Schristosstatic long 145816dce513Schristosparse_register_number (const char **strp) 145916dce513Schristos{ 146016dce513Schristos int regno; 146116dce513Schristos 146216dce513Schristos if (**strp < '0' || **strp > '9') 146316dce513Schristos return -1; /* error */ 146416dce513Schristos 146516dce513Schristos regno = **strp - '0'; 146616dce513Schristos for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp) 146716dce513Schristos regno = regno * 10 + (**strp - '0'); 146816dce513Schristos 146916dce513Schristos return regno; 147016dce513Schristos} 147116dce513Schristos 147216dce513Schristosstatic const char * 147316dce513Schristosparse_spr (CGEN_CPU_DESC cd, 147416dce513Schristos const char **strp, 147516dce513Schristos CGEN_KEYWORD * table, 147616dce513Schristos long *valuep) 147716dce513Schristos{ 147816dce513Schristos const char *save_strp; 147916dce513Schristos long regno; 148016dce513Schristos 148116dce513Schristos /* Check for spr index notation. */ 148216dce513Schristos if (strncasecmp (*strp, "spr[", 4) == 0) 148316dce513Schristos { 148416dce513Schristos *strp += 4; 148516dce513Schristos regno = parse_register_number (strp); 148616dce513Schristos if (**strp != ']') 148716dce513Schristos return _("missing `]'"); 148816dce513Schristos ++*strp; 148916dce513Schristos if (! spr_valid (regno)) 149016dce513Schristos return _("Special purpose register number is out of range"); 149116dce513Schristos *valuep = regno; 149216dce513Schristos return NULL; 149316dce513Schristos } 149416dce513Schristos 149516dce513Schristos save_strp = *strp; 149616dce513Schristos regno = parse_register_number (strp); 149716dce513Schristos if (regno != -1) 149816dce513Schristos { 149916dce513Schristos if (! spr_valid (regno)) 150016dce513Schristos return _("Special purpose register number is out of range"); 150116dce513Schristos *valuep = regno; 150216dce513Schristos return NULL; 150316dce513Schristos } 150416dce513Schristos 150516dce513Schristos *strp = save_strp; 150616dce513Schristos return cgen_parse_keyword (cd, strp, table, valuep); 150716dce513Schristos} 150816dce513Schristos 150916dce513Schristosstatic const char * 151016dce513Schristosparse_d12 (CGEN_CPU_DESC cd, 151116dce513Schristos const char **strp, 151216dce513Schristos int opindex, 151316dce513Schristos long *valuep) 151416dce513Schristos{ 151516dce513Schristos const char *errmsg; 151616dce513Schristos enum cgen_parse_operand_result result_type; 151716dce513Schristos bfd_vma value; 151816dce513Schristos 151916dce513Schristos /* Check for small data reference. */ 152016dce513Schristos if (**strp == '#' || **strp == '%') 152116dce513Schristos { 152216dce513Schristos if (strncasecmp (*strp + 1, "gprel12(", 8) == 0) 152316dce513Schristos { 152416dce513Schristos *strp += 9; 152516dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 152616dce513Schristos BFD_RELOC_FRV_GPREL12, 152716dce513Schristos & result_type, & value); 152816dce513Schristos if (**strp != ')') 152916dce513Schristos return "missing `)'"; 153016dce513Schristos ++*strp; 153116dce513Schristos *valuep = value; 153216dce513Schristos return errmsg; 153316dce513Schristos } 153416dce513Schristos else if (strncasecmp (*strp + 1, "got12(", 6) == 0) 153516dce513Schristos { 153616dce513Schristos *strp += 7; 153716dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 153816dce513Schristos BFD_RELOC_FRV_GOT12, 153916dce513Schristos & result_type, & value); 154016dce513Schristos if (**strp != ')') 154116dce513Schristos return "missing ')'"; 154216dce513Schristos ++*strp; 154316dce513Schristos *valuep = value; 154416dce513Schristos return errmsg; 154516dce513Schristos } 154616dce513Schristos else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0) 154716dce513Schristos { 154816dce513Schristos *strp += 15; 154916dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 155016dce513Schristos BFD_RELOC_FRV_FUNCDESC_GOT12, 155116dce513Schristos & result_type, & value); 155216dce513Schristos if (**strp != ')') 155316dce513Schristos return "missing ')'"; 155416dce513Schristos ++*strp; 155516dce513Schristos *valuep = value; 155616dce513Schristos return errmsg; 155716dce513Schristos } 155816dce513Schristos else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0) 155916dce513Schristos { 156016dce513Schristos *strp += 10; 156116dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 156216dce513Schristos BFD_RELOC_FRV_GOTOFF12, 156316dce513Schristos & result_type, & value); 156416dce513Schristos if (**strp != ')') 156516dce513Schristos return "missing ')'"; 156616dce513Schristos ++*strp; 156716dce513Schristos *valuep = value; 156816dce513Schristos return errmsg; 156916dce513Schristos } 157016dce513Schristos else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0) 157116dce513Schristos { 157216dce513Schristos *strp += 18; 157316dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 157416dce513Schristos BFD_RELOC_FRV_FUNCDESC_GOTOFF12, 157516dce513Schristos & result_type, & value); 157616dce513Schristos if (**strp != ')') 157716dce513Schristos return "missing ')'"; 157816dce513Schristos ++*strp; 157916dce513Schristos *valuep = value; 158016dce513Schristos return errmsg; 158116dce513Schristos } 158216dce513Schristos else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0) 158316dce513Schristos { 158416dce513Schristos *strp += 14; 158516dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 158616dce513Schristos BFD_RELOC_FRV_GOTTLSDESC12, 158716dce513Schristos & result_type, & value); 158816dce513Schristos if (**strp != ')') 158916dce513Schristos return "missing ')'"; 159016dce513Schristos ++*strp; 159116dce513Schristos *valuep = value; 159216dce513Schristos return errmsg; 159316dce513Schristos } 159416dce513Schristos else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0) 159516dce513Schristos { 159616dce513Schristos *strp += 11; 159716dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 159816dce513Schristos BFD_RELOC_FRV_TLSMOFF12, 159916dce513Schristos & result_type, & value); 160016dce513Schristos if (**strp != ')') 160116dce513Schristos return "missing ')'"; 160216dce513Schristos ++*strp; 160316dce513Schristos *valuep = value; 160416dce513Schristos return errmsg; 160516dce513Schristos } 160616dce513Schristos else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0) 160716dce513Schristos { 160816dce513Schristos *strp += 13; 160916dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 161016dce513Schristos BFD_RELOC_FRV_GOTTLSOFF12, 161116dce513Schristos & result_type, & value); 161216dce513Schristos if (**strp != ')') 161316dce513Schristos return "missing ')'"; 161416dce513Schristos ++*strp; 161516dce513Schristos *valuep = value; 161616dce513Schristos return errmsg; 161716dce513Schristos } 161816dce513Schristos } 161916dce513Schristos return cgen_parse_signed_integer (cd, strp, opindex, valuep); 162016dce513Schristos} 162116dce513Schristos 162216dce513Schristosstatic const char * 162316dce513Schristosparse_s12 (CGEN_CPU_DESC cd, 162416dce513Schristos const char **strp, 162516dce513Schristos int opindex, 162616dce513Schristos long *valuep) 162716dce513Schristos{ 162816dce513Schristos const char *errmsg; 162916dce513Schristos enum cgen_parse_operand_result result_type; 163016dce513Schristos bfd_vma value; 163116dce513Schristos 163216dce513Schristos /* Check for small data reference. */ 163316dce513Schristos if (**strp == '#' || **strp == '%') 163416dce513Schristos { 163516dce513Schristos if (strncasecmp (*strp + 1, "gprel12(", 8) == 0) 163616dce513Schristos { 163716dce513Schristos *strp += 9; 163816dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 163916dce513Schristos BFD_RELOC_FRV_GPREL12, 164016dce513Schristos & result_type, & value); 164116dce513Schristos if (**strp != ')') 164216dce513Schristos return "missing `)'"; 164316dce513Schristos ++*strp; 164416dce513Schristos *valuep = value; 164516dce513Schristos return errmsg; 164616dce513Schristos } 164716dce513Schristos else if (strncasecmp (*strp + 1, "got12(", 6) == 0) 164816dce513Schristos { 164916dce513Schristos *strp += 7; 165016dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 165116dce513Schristos BFD_RELOC_FRV_GOT12, 165216dce513Schristos & result_type, & value); 165316dce513Schristos if (**strp != ')') 165416dce513Schristos return "missing ')'"; 165516dce513Schristos ++*strp; 165616dce513Schristos *valuep = value; 165716dce513Schristos return errmsg; 165816dce513Schristos } 165916dce513Schristos else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0) 166016dce513Schristos { 166116dce513Schristos *strp += 15; 166216dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 166316dce513Schristos BFD_RELOC_FRV_FUNCDESC_GOT12, 166416dce513Schristos & result_type, & value); 166516dce513Schristos if (**strp != ')') 166616dce513Schristos return "missing ')'"; 166716dce513Schristos ++*strp; 166816dce513Schristos *valuep = value; 166916dce513Schristos return errmsg; 167016dce513Schristos } 167116dce513Schristos else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0) 167216dce513Schristos { 167316dce513Schristos *strp += 10; 167416dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 167516dce513Schristos BFD_RELOC_FRV_GOTOFF12, 167616dce513Schristos & result_type, & value); 167716dce513Schristos if (**strp != ')') 167816dce513Schristos return "missing ')'"; 167916dce513Schristos ++*strp; 168016dce513Schristos *valuep = value; 168116dce513Schristos return errmsg; 168216dce513Schristos } 168316dce513Schristos else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0) 168416dce513Schristos { 168516dce513Schristos *strp += 18; 168616dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 168716dce513Schristos BFD_RELOC_FRV_FUNCDESC_GOTOFF12, 168816dce513Schristos & result_type, & value); 168916dce513Schristos if (**strp != ')') 169016dce513Schristos return "missing ')'"; 169116dce513Schristos ++*strp; 169216dce513Schristos *valuep = value; 169316dce513Schristos return errmsg; 169416dce513Schristos } 169516dce513Schristos else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0) 169616dce513Schristos { 169716dce513Schristos *strp += 14; 169816dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 169916dce513Schristos BFD_RELOC_FRV_GOTTLSDESC12, 170016dce513Schristos & result_type, & value); 170116dce513Schristos if (**strp != ')') 170216dce513Schristos return "missing ')'"; 170316dce513Schristos ++*strp; 170416dce513Schristos *valuep = value; 170516dce513Schristos return errmsg; 170616dce513Schristos } 170716dce513Schristos else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0) 170816dce513Schristos { 170916dce513Schristos *strp += 11; 171016dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 171116dce513Schristos BFD_RELOC_FRV_TLSMOFF12, 171216dce513Schristos & result_type, & value); 171316dce513Schristos if (**strp != ')') 171416dce513Schristos return "missing ')'"; 171516dce513Schristos ++*strp; 171616dce513Schristos *valuep = value; 171716dce513Schristos return errmsg; 171816dce513Schristos } 171916dce513Schristos else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0) 172016dce513Schristos { 172116dce513Schristos *strp += 13; 172216dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 172316dce513Schristos BFD_RELOC_FRV_GOTTLSOFF12, 172416dce513Schristos & result_type, & value); 172516dce513Schristos if (**strp != ')') 172616dce513Schristos return "missing ')'"; 172716dce513Schristos ++*strp; 172816dce513Schristos *valuep = value; 172916dce513Schristos return errmsg; 173016dce513Schristos } 173116dce513Schristos } 173216dce513Schristos 173316dce513Schristos if (**strp == '#') 173416dce513Schristos ++*strp; 173516dce513Schristos return cgen_parse_signed_integer (cd, strp, opindex, valuep); 173616dce513Schristos} 173716dce513Schristos 173816dce513Schristosstatic const char * 173916dce513Schristosparse_u12 (CGEN_CPU_DESC cd, 174016dce513Schristos const char **strp, 174116dce513Schristos int opindex, 174216dce513Schristos long *valuep) 174316dce513Schristos{ 174416dce513Schristos const char *errmsg; 174516dce513Schristos enum cgen_parse_operand_result result_type; 174616dce513Schristos bfd_vma value; 174716dce513Schristos 174816dce513Schristos /* Check for small data reference. */ 174916dce513Schristos if ((**strp == '#' || **strp == '%') 175016dce513Schristos && strncasecmp (*strp + 1, "gprel12(", 8) == 0) 175116dce513Schristos { 175216dce513Schristos *strp += 9; 175316dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 175416dce513Schristos BFD_RELOC_FRV_GPRELU12, 175516dce513Schristos & result_type, & value); 175616dce513Schristos if (**strp != ')') 175716dce513Schristos return "missing `)'"; 175816dce513Schristos ++*strp; 175916dce513Schristos *valuep = value; 176016dce513Schristos return errmsg; 176116dce513Schristos } 176216dce513Schristos else 176316dce513Schristos { 176416dce513Schristos if (**strp == '#') 176516dce513Schristos ++*strp; 176616dce513Schristos return cgen_parse_signed_integer (cd, strp, opindex, valuep); 176716dce513Schristos } 176816dce513Schristos} 176916dce513Schristos 177016dce513Schristosstatic const char * 177116dce513Schristosparse_A (CGEN_CPU_DESC cd, 177216dce513Schristos const char **strp, 177316dce513Schristos int opindex, 177416dce513Schristos unsigned long *valuep, 177516dce513Schristos unsigned long A) 177616dce513Schristos{ 177716dce513Schristos const char *errmsg; 177816dce513Schristos 177916dce513Schristos if (**strp == '#') 178016dce513Schristos ++*strp; 178116dce513Schristos 178216dce513Schristos errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 178316dce513Schristos if (errmsg) 178416dce513Schristos return errmsg; 178516dce513Schristos 178616dce513Schristos if (*valuep != A) 178716dce513Schristos return _("Value of A operand must be 0 or 1"); 178816dce513Schristos 178916dce513Schristos return NULL; 179016dce513Schristos} 179116dce513Schristos 179216dce513Schristosstatic const char * 179316dce513Schristosparse_A0 (CGEN_CPU_DESC cd, 179416dce513Schristos const char **strp, 179516dce513Schristos int opindex, 179616dce513Schristos unsigned long *valuep) 179716dce513Schristos{ 179816dce513Schristos return parse_A (cd, strp, opindex, valuep, 0); 179916dce513Schristos} 180016dce513Schristos 180116dce513Schristosstatic const char * 180216dce513Schristosparse_A1 (CGEN_CPU_DESC cd, 180316dce513Schristos const char **strp, 180416dce513Schristos int opindex, 180516dce513Schristos unsigned long *valuep) 180616dce513Schristos{ 180716dce513Schristos return parse_A (cd, strp, opindex, valuep, 1); 180816dce513Schristos} 180916dce513Schristos 181016dce513Schristosstatic const char * 181116dce513Schristosparse_even_register (CGEN_CPU_DESC cd, 181216dce513Schristos const char ** strP, 181316dce513Schristos CGEN_KEYWORD * tableP, 181416dce513Schristos long * valueP) 181516dce513Schristos{ 181616dce513Schristos const char * errmsg; 181716dce513Schristos const char * saved_star_strP = * strP; 181816dce513Schristos 181916dce513Schristos errmsg = cgen_parse_keyword (cd, strP, tableP, valueP); 182016dce513Schristos 182116dce513Schristos if (errmsg == NULL && ((* valueP) & 1)) 182216dce513Schristos { 182316dce513Schristos errmsg = _("register number must be even"); 182416dce513Schristos * strP = saved_star_strP; 182516dce513Schristos } 182616dce513Schristos 182716dce513Schristos return errmsg; 182816dce513Schristos} 182916dce513Schristos 183016dce513Schristosstatic const char * 183116dce513Schristosparse_call_label (CGEN_CPU_DESC cd, 183216dce513Schristos const char **strp, 183316dce513Schristos int opindex, 183416dce513Schristos int opinfo, 183516dce513Schristos enum cgen_parse_operand_result *resultp, 183616dce513Schristos bfd_vma *valuep) 183716dce513Schristos{ 183816dce513Schristos const char *errmsg; 183916dce513Schristos bfd_vma value; 184016dce513Schristos 184116dce513Schristos /* Check for small data reference. */ 184216dce513Schristos if (opinfo == 0 && (**strp == '#' || **strp == '%')) 184316dce513Schristos { 184416dce513Schristos if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0) 184516dce513Schristos { 184616dce513Schristos *strp += 11; 184716dce513Schristos errmsg = parse_symbolic_address (cd, strp, opindex, 184816dce513Schristos BFD_RELOC_FRV_GETTLSOFF, 184916dce513Schristos resultp, &value); 185016dce513Schristos if (**strp != ')') 185116dce513Schristos return _("missing `)'"); 185216dce513Schristos ++*strp; 185316dce513Schristos *valuep = value; 185416dce513Schristos return errmsg; 185516dce513Schristos } 185616dce513Schristos } 185716dce513Schristos 185816dce513Schristos return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep); 185916dce513Schristos} 186016dce513Schristos 186116dce513Schristos/* -- */ 186216dce513Schristos 186316dce513Schristos/* -- dis.c */ 186416dce513Schristosstatic void 186516dce513Schristosprint_at (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 186616dce513Schristos void * dis_info, 186716dce513Schristos long reloc_ann ATTRIBUTE_UNUSED, 186816dce513Schristos long value ATTRIBUTE_UNUSED, 186916dce513Schristos bfd_vma pc ATTRIBUTE_UNUSED, 187016dce513Schristos int length ATTRIBUTE_UNUSED) 187116dce513Schristos{ 187216dce513Schristos disassemble_info *info = (disassemble_info *) dis_info; 187316dce513Schristos 187416dce513Schristos (*info->fprintf_func) (info->stream, "@"); 187516dce513Schristos} 187616dce513Schristos 187716dce513Schristosstatic void 187816dce513Schristosprint_spr (CGEN_CPU_DESC cd, 187916dce513Schristos void * dis_info, 188016dce513Schristos CGEN_KEYWORD *names, 188116dce513Schristos long regno, 188216dce513Schristos unsigned int attrs) 188316dce513Schristos{ 188416dce513Schristos /* Use the register index format for any unnamed registers. */ 188516dce513Schristos if (cgen_keyword_lookup_value (names, regno) == NULL) 188616dce513Schristos { 188716dce513Schristos disassemble_info *info = (disassemble_info *) dis_info; 188816dce513Schristos (*info->fprintf_func) (info->stream, "spr[%ld]", regno); 188916dce513Schristos } 189016dce513Schristos else 189116dce513Schristos print_keyword (cd, dis_info, names, regno, attrs); 189216dce513Schristos} 189316dce513Schristos 189416dce513Schristosstatic void 189516dce513Schristosprint_hi (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 189616dce513Schristos void * dis_info, 189716dce513Schristos long value, 189816dce513Schristos unsigned int attrs ATTRIBUTE_UNUSED, 189916dce513Schristos bfd_vma pc ATTRIBUTE_UNUSED, 190016dce513Schristos int length ATTRIBUTE_UNUSED) 190116dce513Schristos{ 190216dce513Schristos disassemble_info *info = (disassemble_info *) dis_info; 190316dce513Schristos 190416dce513Schristos (*info->fprintf_func) (info->stream, value ? "0x%lx" : "hi(0x%lx)", value); 190516dce513Schristos} 190616dce513Schristos 190716dce513Schristosstatic void 190816dce513Schristosprint_lo (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 190916dce513Schristos void * dis_info, 191016dce513Schristos long value, 191116dce513Schristos unsigned int attrs ATTRIBUTE_UNUSED, 191216dce513Schristos bfd_vma pc ATTRIBUTE_UNUSED, 191316dce513Schristos int length ATTRIBUTE_UNUSED) 191416dce513Schristos{ 191516dce513Schristos disassemble_info *info = (disassemble_info *) dis_info; 191616dce513Schristos if (value) 191716dce513Schristos (*info->fprintf_func) (info->stream, "0x%lx", value); 191816dce513Schristos else 191916dce513Schristos (*info->fprintf_func) (info->stream, "lo(0x%lx)", value); 192016dce513Schristos} 192116dce513Schristos 192216dce513Schristos/* -- */ 1923