frv.opc 55 KB

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