metag-dis.c 86 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391
  1. /* Disassemble Imagination Technologies Meta instructions.
  2. Copyright (C) 2013-2022 Free Software Foundation, Inc.
  3. Contributed by Imagination Technologies Ltd.
  4. This library is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. It is distributed in the hope that it will be useful, but WITHOUT
  9. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  11. License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  15. MA 02110-1301, USA. */
  16. #include "sysdep.h"
  17. #include "disassemble.h"
  18. #include "opintl.h"
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include "opcode/metag.h"
  23. /* Column widths for printing. */
  24. #define PREFIX_WIDTH "10"
  25. #define INSN_NAME_WIDTH "10"
  26. #define OPERAND_WIDTH 92
  27. #define ADDR_WIDTH 20
  28. #define REG_WIDTH 64
  29. #define DSP_PREFIX_WIDTH 17
  30. /* Value to print if we fail to parse a register name. */
  31. const char unknown_reg[] = "?";
  32. /* Return the size of a GET or SET instruction. */
  33. unsigned int
  34. metag_get_set_size_bytes (unsigned int opcode)
  35. {
  36. switch (((opcode) >> 24) & 0x5)
  37. {
  38. case 0x5:
  39. return 8;
  40. case 0x4:
  41. return 4;
  42. case 0x1:
  43. return 2;
  44. case 0x0:
  45. return 1;
  46. }
  47. return 1;
  48. }
  49. /* Return the size of an extended GET or SET instruction. */
  50. unsigned int
  51. metag_get_set_ext_size_bytes (unsigned int opcode)
  52. {
  53. switch (((opcode) >> 1) & 0x3)
  54. {
  55. case 0x3:
  56. return 8;
  57. case 0x2:
  58. return 4;
  59. case 0x1:
  60. return 2;
  61. case 0x0:
  62. return 1;
  63. }
  64. return 1;
  65. }
  66. /* Return the size of a conditional SET instruction. */
  67. unsigned int
  68. metag_cond_set_size_bytes (unsigned int opcode)
  69. {
  70. switch (opcode & 0x201)
  71. {
  72. case 0x201:
  73. return 8;
  74. case 0x200:
  75. return 4;
  76. case 0x001:
  77. return 2;
  78. case 0x000:
  79. return 1;
  80. }
  81. return 1;
  82. }
  83. /* Return a value sign-extended. */
  84. static int
  85. sign_extend (int n, unsigned int bits)
  86. {
  87. int mask = 1 << (bits - 1);
  88. return -(n & mask) | n;
  89. }
  90. /* Return the short interpretation of UNIT. */
  91. static unsigned int
  92. short_unit (unsigned int unit)
  93. {
  94. if (unit == UNIT_CT)
  95. return UNIT_A1;
  96. else
  97. return unit;
  98. }
  99. /* Return the register corresponding to UNIT and NUMBER or NULL. */
  100. static const metag_reg *
  101. lookup_reg (unsigned int unit, unsigned int number)
  102. {
  103. size_t i;
  104. for (i = 0; i < sizeof(metag_regtab)/sizeof(metag_regtab[0]); i++)
  105. {
  106. const metag_reg *reg = &metag_regtab[i];
  107. if (reg->unit == unit && reg->no == number)
  108. return reg;
  109. }
  110. return NULL;
  111. }
  112. /* Return the register name corresponding to UNIT and NUMBER or NULL. */
  113. static const char *
  114. lookup_reg_name (unsigned int unit, unsigned int number)
  115. {
  116. const metag_reg *reg;
  117. reg = lookup_reg (unit, number);
  118. if (reg)
  119. return reg->name;
  120. else
  121. return unknown_reg;
  122. }
  123. /* Return the unit that is the pair of UNIT. */
  124. static unsigned int
  125. get_pair_unit (unsigned int unit)
  126. {
  127. switch (unit)
  128. {
  129. case UNIT_D0:
  130. return UNIT_D1;
  131. case UNIT_D1:
  132. return UNIT_D0;
  133. case UNIT_A0:
  134. return UNIT_A1;
  135. case UNIT_A1:
  136. return UNIT_A0;
  137. default:
  138. return unit;
  139. }
  140. }
  141. /* Return the name of the pair register for UNIT and NUMBER or NULL. */
  142. static const char *
  143. lookup_pair_reg_name (unsigned int unit, unsigned int number)
  144. {
  145. if (unit == UNIT_FX)
  146. return lookup_reg_name (unit, number + 1);
  147. else
  148. return lookup_reg_name (get_pair_unit (unit), number);
  149. }
  150. /* Return the name of the accumulator register for PART. */
  151. static const char *
  152. lookup_acf_name (unsigned int part)
  153. {
  154. size_t i;
  155. for (i = 0; i < sizeof(metag_acftab)/sizeof(metag_acftab[0]); i++)
  156. {
  157. const metag_acf *acf = &metag_acftab[i];
  158. if (acf->part == part)
  159. return acf->name;
  160. }
  161. return "ACF.?";
  162. }
  163. /* Return the register name for the O2R register for UNIT and NUMBER. */
  164. static const char *
  165. lookup_o2r (enum metag_unit unit, unsigned int number)
  166. {
  167. unsigned int o2r_unit;
  168. enum metag_unit actual_unit = UNIT_A0;
  169. const metag_reg *reg;
  170. o2r_unit = (number & ~O2R_REG_MASK) >> 3;
  171. number = number & O2R_REG_MASK;
  172. if (unit == UNIT_A0)
  173. {
  174. switch (o2r_unit)
  175. {
  176. case 0:
  177. actual_unit = UNIT_A1;
  178. break;
  179. case 1:
  180. actual_unit = UNIT_D0;
  181. break;
  182. case 2:
  183. actual_unit = UNIT_RD;
  184. break;
  185. case 3:
  186. actual_unit = UNIT_D1;
  187. break;
  188. }
  189. }
  190. else if (unit == UNIT_A1)
  191. {
  192. switch (o2r_unit)
  193. {
  194. case 0:
  195. actual_unit = UNIT_D1;
  196. break;
  197. case 1:
  198. actual_unit = UNIT_D0;
  199. break;
  200. case 2:
  201. actual_unit = UNIT_RD;
  202. break;
  203. case 3:
  204. actual_unit = UNIT_A0;
  205. break;
  206. }
  207. }
  208. else if (unit == UNIT_D0)
  209. {
  210. switch (o2r_unit)
  211. {
  212. case 0:
  213. actual_unit = UNIT_A1;
  214. break;
  215. case 1:
  216. actual_unit = UNIT_D1;
  217. break;
  218. case 2:
  219. actual_unit = UNIT_RD;
  220. break;
  221. case 3:
  222. actual_unit = UNIT_A0;
  223. break;
  224. }
  225. }
  226. else if (unit == UNIT_D1)
  227. {
  228. switch (o2r_unit)
  229. {
  230. case 0:
  231. actual_unit = UNIT_A1;
  232. break;
  233. case 1:
  234. actual_unit = UNIT_D0;
  235. break;
  236. case 2:
  237. actual_unit = UNIT_RD;
  238. break;
  239. case 3:
  240. actual_unit = UNIT_A0;
  241. break;
  242. }
  243. }
  244. reg = lookup_reg (actual_unit, number);
  245. if (reg)
  246. return reg->name;
  247. else
  248. return unknown_reg;
  249. }
  250. /* Return the string for split condition code CODE. */
  251. static const char *
  252. lookup_scc_flags (unsigned int code)
  253. {
  254. size_t i;
  255. for (i = 0; i < sizeof (metag_dsp_scondtab) / sizeof (metag_dsp_scondtab[0]); i++)
  256. {
  257. if (metag_dsp_scondtab[i].code == code)
  258. {
  259. return metag_dsp_scondtab[i].name;
  260. }
  261. }
  262. return NULL;
  263. }
  264. /* Return the string for FPU split condition code CODE. */
  265. static const char *
  266. lookup_fpu_scc_flags (unsigned int code)
  267. {
  268. size_t i;
  269. for (i = 0; i < sizeof (metag_fpu_scondtab) / sizeof (metag_fpu_scondtab[0]); i++)
  270. {
  271. if (metag_fpu_scondtab[i].code == code)
  272. {
  273. return metag_fpu_scondtab[i].name;
  274. }
  275. }
  276. return NULL;
  277. }
  278. /* Print an instruction with PREFIX, NAME and OPERANDS. */
  279. static void
  280. print_insn (disassemble_info *outf, const char *prefix, const char *name,
  281. const char *operands)
  282. {
  283. outf->fprintf_func (outf->stream, "%-" PREFIX_WIDTH "s%-" INSN_NAME_WIDTH "s%s", prefix, name, operands);
  284. }
  285. /* Print an instruction with no operands. */
  286. static void
  287. print_none (unsigned int insn_word ATTRIBUTE_UNUSED,
  288. bfd_vma pc ATTRIBUTE_UNUSED,
  289. const insn_template *template,
  290. disassemble_info *outf)
  291. {
  292. outf->fprintf_func (outf->stream, "%-" PREFIX_WIDTH "s%s", "",
  293. template->name);
  294. }
  295. /* Print a unit to unit MOV instruction. */
  296. static void
  297. print_mov_u2u (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  298. const insn_template *template,
  299. disassemble_info *outf)
  300. {
  301. unsigned int dest_unit, dest_no, src_unit, src_no;
  302. unsigned int is_kick = (insn_word & 0x1) && !((insn_word >> 9) & 0x1);
  303. unsigned int major = MAJOR_OPCODE (insn_word);
  304. unsigned int minor = MINOR_OPCODE (insn_word);
  305. char buf[OPERAND_WIDTH];
  306. const char *dest_reg;
  307. const char *src_reg;
  308. dest_unit = (insn_word >> 5) & UNIT_MASK;
  309. dest_no = (insn_word >> 14) & REG_MASK;
  310. dest_reg = lookup_reg_name (dest_unit, dest_no);
  311. if (is_kick)
  312. src_unit = UNIT_TR;
  313. else
  314. src_unit = (insn_word >> 10) & UNIT_MASK;
  315. /* This is really an RTI/RTH. No, really. */
  316. if (major == OPC_MISC &&
  317. minor == 0x3 &&
  318. src_unit == 0xf)
  319. {
  320. if (insn_word & 0x800000)
  321. outf->fprintf_func (outf->stream, "%-" PREFIX_WIDTH "s%s", "",
  322. "RTI");
  323. else
  324. outf->fprintf_func (outf->stream, "%-" PREFIX_WIDTH "s%s", "",
  325. "RTH");
  326. return;
  327. }
  328. src_no = (insn_word >> 19) & REG_MASK;
  329. src_reg = lookup_reg_name (src_unit, src_no);
  330. snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
  331. if (dest_unit == UNIT_FX || src_unit == UNIT_FX)
  332. print_insn (outf, "F", template->name, buf);
  333. else
  334. print_insn (outf, "", template->name, buf);
  335. }
  336. /* Print a MOV to port instruction. */
  337. static void
  338. print_mov_port (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  339. const insn_template *template,
  340. disassemble_info *outf)
  341. {
  342. unsigned int dest_unit, dest1_no, dest2_no, src_unit, src_no;
  343. unsigned int is_movl = MINOR_OPCODE (insn_word) == MOVL_MINOR;
  344. char buf[OPERAND_WIDTH];
  345. const char *dest_reg;
  346. const char *pair_reg;
  347. const char *src_reg;
  348. if (is_movl)
  349. dest_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK);
  350. else
  351. dest_unit = (insn_word >> 5) & UNIT_MASK;
  352. dest1_no = (insn_word >> 14) & REG_MASK;
  353. dest2_no = (insn_word >> 9) & REG_MASK;
  354. dest_reg = lookup_reg_name (dest_unit, dest1_no);
  355. pair_reg = lookup_pair_reg_name (dest_unit, dest2_no);
  356. src_unit = UNIT_RD;
  357. src_no = 0;
  358. src_reg = lookup_reg_name (src_unit, src_no);
  359. if (is_movl)
  360. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, pair_reg, src_reg);
  361. else
  362. snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
  363. if (dest_unit == UNIT_FX)
  364. print_insn (outf, "F", template->name, buf);
  365. else
  366. print_insn (outf, "", template->name, buf);
  367. }
  368. /* Return the number of bits set in rmask. */
  369. static unsigned int hweight (unsigned int rmask)
  370. {
  371. unsigned int count;
  372. for (count = 0; rmask; count++)
  373. {
  374. rmask &= rmask - 1;
  375. }
  376. return count;
  377. }
  378. /* Print a MOVL to TTREC instruction. */
  379. static void
  380. print_movl_ttrec (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  381. const insn_template *template,
  382. disassemble_info *outf)
  383. {
  384. unsigned int dest_unit, dest_no, src1_no, src2_no, src_unit;
  385. char buf[OPERAND_WIDTH];
  386. const char *dest_reg;
  387. const char *src_reg;
  388. const char *pair_reg;
  389. dest_unit = UNIT_TT;
  390. dest_no = 3;
  391. dest_reg = lookup_reg_name (dest_unit, dest_no);
  392. src1_no = (insn_word >> 19) & REG_MASK;
  393. src2_no = (insn_word >> 14) & REG_MASK;
  394. src_unit = short_unit ((insn_word >> 7) & SHORT_UNIT_MASK);
  395. src_reg = lookup_reg_name (src_unit, src1_no);
  396. pair_reg = lookup_pair_reg_name (src_unit, src2_no);
  397. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src_reg, pair_reg);
  398. print_insn (outf, "", template->name, buf);
  399. }
  400. /* Format a GET or SET address mode string from INSN_WORD into BUF. */
  401. static void
  402. get_set_addr_str (char *buf, unsigned int buf_size, unsigned int size,
  403. unsigned int insn_word)
  404. {
  405. const char *base_reg;
  406. unsigned int base_unit, base_no;
  407. unsigned int imm = (insn_word >> 25) & 1;
  408. unsigned int ua = (insn_word >> 7) & 1;
  409. unsigned int pp = insn_word & 1;
  410. base_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK);
  411. base_no = (insn_word >> 14) & REG_MASK;
  412. base_reg = lookup_reg_name (base_unit, base_no);
  413. if (imm)
  414. {
  415. int offset = (insn_word >> 8) & GET_SET_IMM_MASK;
  416. offset = sign_extend (offset, GET_SET_IMM_BITS);
  417. if (offset == 0)
  418. {
  419. snprintf (buf, buf_size, "[%s]", base_reg);
  420. return;
  421. }
  422. if (offset == 1 && ua)
  423. {
  424. if (pp)
  425. snprintf (buf, buf_size, "[%s++]", base_reg);
  426. else
  427. snprintf (buf, buf_size, "[++%s]", base_reg);
  428. return;
  429. }
  430. else if (offset == -1 && ua)
  431. {
  432. if (pp)
  433. snprintf (buf, buf_size, "[%s--]", base_reg);
  434. else
  435. snprintf (buf, buf_size, "[--%s]", base_reg);
  436. return;
  437. }
  438. offset = offset * size;
  439. if (ua)
  440. {
  441. if (pp)
  442. snprintf (buf, buf_size, "[%s+#%d++]", base_reg, offset);
  443. else
  444. snprintf (buf, buf_size, "[%s++#%d]", base_reg, offset);
  445. }
  446. else
  447. snprintf (buf, buf_size, "[%s+#%d]", base_reg, offset);
  448. }
  449. else
  450. {
  451. const char *offset_reg;
  452. unsigned int offset_no;
  453. offset_no = (insn_word >> 9) & REG_MASK;
  454. offset_reg = lookup_reg_name (base_unit, offset_no);
  455. if (ua)
  456. {
  457. if (pp)
  458. snprintf (buf, buf_size, "[%s+%s++]", base_reg, offset_reg);
  459. else
  460. snprintf (buf, buf_size, "[%s++%s]", base_reg, offset_reg);
  461. }
  462. else
  463. snprintf (buf, buf_size, "[%s+%s]", base_reg, offset_reg);
  464. }
  465. }
  466. /* Format an extended GET or SET address mode string from INSN_WORD into BUF. */
  467. static void
  468. get_set_ext_addr_str (char *buf, unsigned int buf_size, unsigned int size,
  469. unsigned int insn_word)
  470. {
  471. const char *base_reg;
  472. unsigned int base_unit, base_no;
  473. int offset;
  474. base_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK);
  475. base_no = insn_word & EXT_BASE_REG_MASK;
  476. base_reg = lookup_reg_name (base_unit, base_no);
  477. offset = (insn_word >> 7) & GET_SET_EXT_IMM_MASK;
  478. offset = sign_extend (offset, GET_SET_EXT_IMM_BITS);
  479. offset = offset * size;
  480. if (offset == 0)
  481. {
  482. snprintf (buf, buf_size, "[%s]", base_reg);
  483. }
  484. else
  485. {
  486. snprintf (buf, buf_size, "[%s+#%d]", base_reg, offset);
  487. }
  488. }
  489. /* Format an MGET or MSET address mode string from INSN_WORD into BUF. */
  490. static void
  491. mget_mset_addr_str (char *buf, unsigned int buf_size,
  492. unsigned int insn_word)
  493. {
  494. const char *base_reg;
  495. unsigned int base_unit, base_no;
  496. base_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK);
  497. base_no = (insn_word >> 14) & REG_MASK;
  498. base_reg = lookup_reg_name (base_unit, base_no);
  499. snprintf (buf, buf_size, "[%s++]", base_reg);
  500. }
  501. /* Format a conditional SET address mode string from INSN_WORD into BUF. */
  502. static void
  503. cond_set_addr_str (char *buf, unsigned int buf_size,
  504. unsigned int insn_word)
  505. {
  506. const char *base_reg;
  507. unsigned int base_unit, base_no;
  508. base_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK);
  509. base_no = (insn_word >> 14) & REG_MASK;
  510. base_reg = lookup_reg_name (base_unit, base_no);
  511. snprintf (buf, buf_size, "[%s]", base_reg);
  512. }
  513. /* Format a cache instruction address mode string from INSN_WORD into BUF. */
  514. static void
  515. cache_addr_str (char *buf, unsigned int buf_size, unsigned int insn_word,
  516. int width)
  517. {
  518. const char *base_reg;
  519. unsigned int base_unit, base_no;
  520. int offset;
  521. base_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK);
  522. base_no = (insn_word >> 14) & REG_MASK;
  523. base_reg = lookup_reg_name (base_unit, base_no);
  524. offset = (insn_word >> 8) & GET_SET_IMM_MASK;
  525. offset = sign_extend (offset, GET_SET_IMM_BITS);
  526. offset = offset * width;
  527. if (offset == 0)
  528. {
  529. snprintf (buf, buf_size, "[%s]", base_reg);
  530. }
  531. else
  532. {
  533. snprintf (buf, buf_size, "[%s+#%d]", base_reg, offset);
  534. }
  535. }
  536. /* Format a list of registers starting at REG_UNIT and REG_NO and conforming
  537. to RMASK into BUF. */
  538. static void
  539. lookup_reg_list (char *reg_buf, size_t buf_len, unsigned int reg_unit,
  540. unsigned int reg_no, unsigned int rmask,
  541. bool is_fpu_64bit)
  542. {
  543. const char *regs[MGET_MSET_MAX_REGS];
  544. size_t used_regs = 1, i, remaining;
  545. regs[0] = lookup_reg_name (reg_unit, reg_no);
  546. for (i = 1; i < MGET_MSET_MAX_REGS; i++)
  547. {
  548. if (rmask & 1)
  549. {
  550. if (is_fpu_64bit)
  551. regs[used_regs] = lookup_reg_name (reg_unit, reg_no + (i * 2));
  552. else
  553. regs[used_regs] = lookup_reg_name (reg_unit, reg_no + i);
  554. used_regs++;
  555. }
  556. rmask = rmask >> 1;
  557. }
  558. remaining = buf_len;
  559. for (i = 0; i < used_regs; i++)
  560. {
  561. size_t len;
  562. if (i == 0)
  563. len = snprintf(reg_buf, remaining, "%s", regs[i]);
  564. else
  565. len = snprintf(reg_buf, remaining, ",%s", regs[i]);
  566. reg_buf += len;
  567. remaining -= len;
  568. }
  569. }
  570. /* Print a GET instruction. */
  571. static void
  572. print_get (char *buf, char *addr_buf, unsigned int size,
  573. const char *dest_reg, const char *pair_reg, unsigned int reg_unit,
  574. const insn_template *template,
  575. disassemble_info *outf)
  576. {
  577. if (size == 8)
  578. {
  579. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, pair_reg,
  580. addr_buf);
  581. }
  582. else
  583. {
  584. snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, addr_buf);
  585. }
  586. if (reg_unit == UNIT_FX)
  587. print_insn (outf, "F", template->name, buf);
  588. else
  589. print_insn (outf, "", template->name, buf);
  590. }
  591. /* Print a SET instruction. */
  592. static void
  593. print_set (char *buf, char *addr_buf, unsigned int size,
  594. const char *src_reg, const char *pair_reg, unsigned int reg_unit,
  595. const insn_template *template,
  596. disassemble_info *outf)
  597. {
  598. if (size == 8)
  599. {
  600. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", addr_buf, src_reg, pair_reg);
  601. }
  602. else
  603. {
  604. snprintf (buf, OPERAND_WIDTH, "%s,%s", addr_buf, src_reg);
  605. }
  606. if (reg_unit == UNIT_FX)
  607. print_insn (outf, "F", template->name, buf);
  608. else
  609. print_insn (outf, "", template->name, buf);
  610. }
  611. /* Print a GET or SET instruction. */
  612. static void
  613. print_get_set (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  614. const insn_template *template,
  615. disassemble_info *outf)
  616. {
  617. bool is_get = MAJOR_OPCODE (template->meta_opcode) == OPC_GET;
  618. char buf[OPERAND_WIDTH];
  619. char addr_buf[ADDR_WIDTH];
  620. unsigned int reg_unit, reg_no;
  621. unsigned int size = metag_get_set_size_bytes (insn_word);
  622. const char *reg_name;
  623. const char *pair_reg;
  624. reg_unit = (insn_word >> 1) & UNIT_MASK;
  625. reg_no = (insn_word >> 19) & REG_MASK;
  626. /* SETs should always print RD. */
  627. if (!is_get && reg_unit == UNIT_RD)
  628. reg_no = 0;
  629. reg_name = lookup_reg_name (reg_unit, reg_no);
  630. pair_reg = lookup_pair_reg_name (reg_unit, reg_no);
  631. get_set_addr_str (addr_buf, ADDR_WIDTH, size, insn_word);
  632. if (is_get)
  633. {
  634. /* RD regs are 64 bits wide so don't use the pair syntax. */
  635. if (reg_unit == UNIT_RD)
  636. print_get (buf, addr_buf, 4, reg_name, pair_reg, reg_unit,
  637. template, outf);
  638. else
  639. print_get (buf, addr_buf, size, reg_name, pair_reg, reg_unit,
  640. template, outf);
  641. }
  642. else
  643. {
  644. /* RD regs are 64 bits wide so don't use the pair syntax. */
  645. if (reg_unit == UNIT_RD)
  646. print_set (buf, addr_buf, 4, reg_name, pair_reg, reg_unit,
  647. template, outf);
  648. else
  649. print_set (buf, addr_buf, size, reg_name, pair_reg, reg_unit,
  650. template, outf);
  651. }
  652. }
  653. /* Print an extended GET or SET instruction. */
  654. static void
  655. print_get_set_ext (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  656. const insn_template *template,
  657. disassemble_info *outf)
  658. {
  659. bool is_get = MINOR_OPCODE (template->meta_opcode) == GET_EXT_MINOR;
  660. bool is_mov = MINOR_OPCODE (template->meta_opcode) == MOV_EXT_MINOR;
  661. char buf[OPERAND_WIDTH];
  662. char addr_buf[ADDR_WIDTH];
  663. unsigned int reg_unit, reg_no;
  664. unsigned int size = metag_get_set_ext_size_bytes (insn_word);
  665. const char *reg_name;
  666. const char *pair_reg;
  667. if (is_mov)
  668. reg_unit = UNIT_RD;
  669. else
  670. reg_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK);
  671. reg_no = (insn_word >> 19) & REG_MASK;
  672. reg_name = lookup_reg_name (reg_unit, reg_no);
  673. pair_reg = lookup_pair_reg_name (reg_unit, reg_no);
  674. get_set_ext_addr_str (addr_buf, ADDR_WIDTH, size, insn_word);
  675. if (is_get)
  676. print_get (buf, addr_buf, size, reg_name, pair_reg, reg_unit,
  677. template, outf);
  678. else if (is_mov)
  679. print_get (buf, addr_buf, 4, reg_name, pair_reg, reg_unit,
  680. template, outf);
  681. else
  682. print_set (buf, addr_buf, size, reg_name, pair_reg, reg_unit,
  683. template, outf);
  684. }
  685. /* Print an MGET or MSET instruction. */
  686. static void
  687. print_mget_mset (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  688. const insn_template *template,
  689. disassemble_info *outf)
  690. {
  691. bool is_get = MAJOR_OPCODE (template->meta_opcode) == OPC_GET;
  692. bool is_fpu = (MINOR_OPCODE (template->meta_opcode) & 0x6) == 0x6;
  693. bool is_64bit = (MINOR_OPCODE (template->meta_opcode) & 0x1) == 0x1;
  694. char buf[OPERAND_WIDTH];
  695. char addr_buf[ADDR_WIDTH];
  696. char reg_buf[REG_WIDTH];
  697. unsigned int reg_unit, reg_no, rmask;
  698. if (is_fpu)
  699. reg_unit = UNIT_FX;
  700. else
  701. reg_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK);
  702. reg_no = (insn_word >> 19) & REG_MASK;
  703. rmask = (insn_word >> 7) & RMASK_MASK;
  704. lookup_reg_list (reg_buf, REG_WIDTH, reg_unit, reg_no, rmask,
  705. is_fpu && is_64bit);
  706. mget_mset_addr_str (addr_buf, ADDR_WIDTH, insn_word);
  707. if (is_get)
  708. snprintf (buf, OPERAND_WIDTH, "%s,%s", reg_buf, addr_buf);
  709. else
  710. snprintf (buf, OPERAND_WIDTH, "%s,%s", addr_buf, reg_buf);
  711. if (is_fpu)
  712. print_insn (outf, "F", template->name, buf);
  713. else
  714. print_insn (outf, "", template->name, buf);
  715. }
  716. /* Print a conditional SET instruction. */
  717. static void
  718. print_cond_set (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  719. const insn_template *template,
  720. disassemble_info *outf)
  721. {
  722. char buf[OPERAND_WIDTH];
  723. char addr_buf[ADDR_WIDTH];
  724. unsigned int src_unit, src_no;
  725. unsigned int size = metag_cond_set_size_bytes (insn_word);
  726. const char *src_reg;
  727. const char *pair_reg;
  728. src_unit = (insn_word >> 10) & UNIT_MASK;
  729. src_no = (insn_word >> 19) & REG_MASK;
  730. if (src_unit == UNIT_RD)
  731. src_no = 0;
  732. src_reg = lookup_reg_name (src_unit, src_no);
  733. pair_reg = lookup_pair_reg_name (src_unit, src_no);
  734. cond_set_addr_str (addr_buf, ADDR_WIDTH, insn_word);
  735. if (src_unit == UNIT_RD)
  736. print_set (buf, addr_buf, 4, src_reg, pair_reg, src_unit,
  737. template, outf);
  738. else
  739. print_set (buf, addr_buf, size, src_reg, pair_reg, src_unit,
  740. template, outf);
  741. }
  742. /* Print a MMOV instruction. */
  743. static void
  744. print_mmov (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  745. const insn_template *template,
  746. disassemble_info *outf)
  747. {
  748. unsigned int is_fpu = template->insn_type == INSN_FPU;
  749. unsigned int is_prime = ((MINOR_OPCODE (template->meta_opcode) & 0x2) &&
  750. !is_fpu);
  751. unsigned int is_64bit = MINOR_OPCODE (template->meta_opcode) & 0x1;
  752. unsigned int is_dsp = template->meta_opcode & 0x1;
  753. unsigned int dest_unit, dest_no, rmask;
  754. char buf[OPERAND_WIDTH];
  755. char reg_buf[REG_WIDTH];
  756. char addr_buf[ADDR_WIDTH];
  757. if (is_fpu)
  758. dest_no = (insn_word >> 14) & REG_MASK;
  759. else
  760. dest_no = (insn_word >> 19) & REG_MASK;
  761. rmask = (insn_word >> 7) & RMASK_MASK;
  762. if (is_prime)
  763. {
  764. const char *dest_reg;
  765. const char *base_reg;
  766. unsigned int base_unit, base_no;
  767. int i, count = hweight (rmask);
  768. dest_reg = lookup_reg_name (UNIT_RD, dest_no);
  769. strcpy (reg_buf, dest_reg);
  770. for (i = 0; i < count; i++)
  771. {
  772. strcat (reg_buf, ",");
  773. strcat (reg_buf, dest_reg);
  774. }
  775. base_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK);
  776. base_no = (insn_word >> 14) & REG_MASK;
  777. base_reg = lookup_reg_name (base_unit, base_no);
  778. snprintf (addr_buf, ADDR_WIDTH, "[%s++]", base_reg);
  779. snprintf (buf, OPERAND_WIDTH, "%s,%s", reg_buf, addr_buf);
  780. }
  781. else
  782. {
  783. if (is_fpu)
  784. dest_unit = UNIT_FX;
  785. else
  786. dest_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK);
  787. lookup_reg_list (reg_buf, REG_WIDTH, dest_unit, dest_no, rmask,
  788. is_fpu && is_64bit);
  789. snprintf (buf, OPERAND_WIDTH, "%s,RD", reg_buf);
  790. }
  791. if (is_dsp)
  792. {
  793. char prefix_buf[10] = {0};
  794. if (is_prime)
  795. {
  796. if (dest_no == 22 || dest_no == 23)
  797. strcpy (prefix_buf, "DB");
  798. else if (dest_no == 24)
  799. strcpy (prefix_buf, "DBH");
  800. else if (dest_no == 25)
  801. strcpy (prefix_buf, "DWH");
  802. else if (dest_no == 31)
  803. strcpy (prefix_buf, "DW");
  804. }
  805. else
  806. strcpy (prefix_buf, "DW");
  807. print_insn (outf, prefix_buf, template->name, buf);
  808. }
  809. else if (is_fpu)
  810. print_insn (outf, "F", template->name, buf);
  811. else
  812. print_insn (outf, "", template->name, buf);
  813. }
  814. /* Print an MDRD instruction. */
  815. static void
  816. print_mdrd (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  817. const insn_template *template,
  818. disassemble_info *outf)
  819. {
  820. unsigned int rmask, count;
  821. char buf[OPERAND_WIDTH];
  822. rmask = (insn_word >> 7) & RMASK_MASK;
  823. count = hweight (rmask);
  824. snprintf (buf, OPERAND_WIDTH, "#%#x", count + 1);
  825. print_insn (outf, "", template->name, buf);
  826. }
  827. /* Print an XFR instruction. */
  828. static void
  829. print_xfr (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  830. const insn_template *template,
  831. disassemble_info *outf)
  832. {
  833. char buf[OPERAND_WIDTH];
  834. char dest_buf[ADDR_WIDTH];
  835. char src_buf[ADDR_WIDTH];
  836. unsigned int dest_unit, src_unit;
  837. unsigned int dest_no, src_no;
  838. unsigned int us, ud, pp;
  839. const char *dest_base_reg;
  840. const char *dest_offset_reg;
  841. const char *src_base_reg;
  842. const char *src_offset_reg;
  843. src_unit = short_unit ((insn_word >> 2) & SHORT_UNIT_MASK);
  844. src_no = (insn_word >> 19) & REG_MASK;
  845. src_base_reg = lookup_reg_name (src_unit, src_no);
  846. src_no = (insn_word >> 14) & REG_MASK;
  847. src_offset_reg = lookup_reg_name (src_unit, src_no);
  848. dest_unit = short_unit (insn_word & SHORT_UNIT_MASK);
  849. dest_no = (insn_word >> 9) & REG_MASK;
  850. dest_base_reg = lookup_reg_name (dest_unit, dest_no);
  851. dest_no = (insn_word >> 4) & REG_MASK;
  852. dest_offset_reg = lookup_reg_name (dest_unit, dest_no);
  853. us = (insn_word >> 27) & 0x1;
  854. ud = (insn_word >> 26) & 0x1;
  855. pp = (insn_word >> 24) & 0x1;
  856. if (us)
  857. if (pp)
  858. snprintf (src_buf, ADDR_WIDTH, "[%s+%s++]", src_base_reg,
  859. src_offset_reg);
  860. else
  861. snprintf (src_buf, ADDR_WIDTH, "[%s++%s]", src_base_reg,
  862. src_offset_reg);
  863. else
  864. snprintf (src_buf, ADDR_WIDTH, "[%s+%s]", src_base_reg,
  865. src_offset_reg);
  866. if (ud)
  867. if (pp)
  868. snprintf (dest_buf, ADDR_WIDTH, "[%s+%s++]", dest_base_reg,
  869. dest_offset_reg);
  870. else
  871. snprintf (dest_buf, ADDR_WIDTH, "[%s++%s]", dest_base_reg,
  872. dest_offset_reg);
  873. else
  874. snprintf (dest_buf, ADDR_WIDTH, "[%s+%s]", dest_base_reg,
  875. dest_offset_reg);
  876. snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_buf, src_buf);
  877. print_insn (outf, "", template->name, buf);
  878. }
  879. /* Print a MOV to control unit instruction. */
  880. static void
  881. print_mov_ct (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  882. const insn_template *template,
  883. disassemble_info *outf)
  884. {
  885. char buf[OPERAND_WIDTH];
  886. unsigned int reg_no;
  887. unsigned int se = (insn_word >> 1) & 0x1;
  888. unsigned int is_trace = (insn_word >> 2) & 0x1;
  889. int value;
  890. const char *dest_reg;
  891. reg_no = (insn_word >> 19) & REG_MASK;
  892. if (is_trace)
  893. dest_reg = lookup_reg_name (UNIT_TT, reg_no);
  894. else
  895. dest_reg = lookup_reg_name (UNIT_CT, reg_no);
  896. value = (insn_word >> 3) & IMM16_MASK;
  897. if (se)
  898. {
  899. value = sign_extend (value, IMM16_BITS);
  900. snprintf (buf, OPERAND_WIDTH, "%s,#%d", dest_reg, value);
  901. }
  902. else
  903. {
  904. snprintf (buf, OPERAND_WIDTH, "%s,#%#x", dest_reg, value);
  905. }
  906. print_insn (outf, "", template->name, buf);
  907. }
  908. /* Print a SWAP instruction. */
  909. static void
  910. print_swap (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  911. const insn_template *template,
  912. disassemble_info *outf)
  913. {
  914. char buf[OPERAND_WIDTH];
  915. unsigned int dest_no, src_no;
  916. unsigned int dest_unit, src_unit;
  917. const char *dest_reg;
  918. const char *src_reg;
  919. src_unit = (insn_word >> 10) & UNIT_MASK;
  920. src_no = (insn_word >> 19) & REG_MASK;
  921. src_reg = lookup_reg_name (src_unit, src_no);
  922. dest_unit = (insn_word >> 5) & UNIT_MASK;
  923. dest_no = (insn_word >> 14) & REG_MASK;
  924. dest_reg = lookup_reg_name (dest_unit, dest_no);
  925. snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
  926. if (dest_unit == UNIT_FX || src_unit == UNIT_FX)
  927. print_insn (outf, "F", template->name, buf);
  928. else
  929. print_insn (outf, "", template->name, buf);
  930. }
  931. /* Print a SWAP instruction. */
  932. static void
  933. print_jump (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  934. const insn_template *template,
  935. disassemble_info *outf)
  936. {
  937. char buf[OPERAND_WIDTH];
  938. unsigned int reg_no, reg_unit;
  939. const char *reg_name;
  940. int value;
  941. reg_unit = short_unit (insn_word & SHORT_UNIT_MASK);
  942. reg_no = (insn_word >> 19) & REG_MASK;
  943. reg_name = lookup_reg_name (reg_unit, reg_no);
  944. value = (insn_word >> 3) & IMM16_MASK;
  945. snprintf (buf, OPERAND_WIDTH, "%s,#%#x", reg_name, value);
  946. print_insn (outf, "", template->name, buf);
  947. }
  948. /* Print a CALLR instruction. */
  949. static void
  950. print_callr (unsigned int insn_word, bfd_vma pc, const insn_template *template,
  951. disassemble_info *outf)
  952. {
  953. char buf[OPERAND_WIDTH];
  954. unsigned int reg_no, reg_unit;
  955. const char *reg_name;
  956. int value;
  957. reg_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK);
  958. reg_no = insn_word & CALLR_REG_MASK;
  959. reg_name = lookup_reg_name (reg_unit, reg_no);
  960. value = (insn_word >> 5) & IMM19_MASK;
  961. value = sign_extend (value, IMM19_BITS);
  962. value = value * 4;
  963. value += pc;
  964. snprintf (buf, OPERAND_WIDTH, "%s,", reg_name);
  965. print_insn (outf, "", template->name, buf);
  966. outf->print_address_func (value, outf);
  967. }
  968. /* Print a GP ALU instruction. */
  969. static void
  970. print_alu (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  971. const insn_template *template,
  972. disassemble_info *outf)
  973. {
  974. char buf[OPERAND_WIDTH];
  975. unsigned int is_addr_op = MAJOR_OPCODE (template->meta_opcode) == OPC_ADDR;
  976. unsigned int is_mul = MAJOR_OPCODE (template->meta_opcode) == OPC_MUL;
  977. unsigned int dest_no, src1_no, src2_no;
  978. unsigned int imm = (insn_word >> 25) & 0x1;
  979. unsigned int cond = (insn_word >> 26) & 0x1;
  980. unsigned int o1z = 0;
  981. unsigned int o2r = insn_word & 0x1;
  982. unsigned int unit_bit = (insn_word >> 24) & 0x1;
  983. unsigned int ca = (insn_word >> 5) & 0x1;
  984. unsigned int se = (insn_word >> 1) & 0x1;
  985. bool is_quickrot = template->arg_type & GP_ARGS_QR;
  986. enum metag_unit base_unit;
  987. enum metag_unit dest_unit;
  988. const char *dest_reg;
  989. const char *src1_reg;
  990. const char *src2_reg;
  991. int value;
  992. if ((MAJOR_OPCODE (template->meta_opcode) == OPC_ADDR ||
  993. MAJOR_OPCODE (template->meta_opcode) == OPC_ADD ||
  994. MAJOR_OPCODE (template->meta_opcode) == OPC_SUB) &&
  995. ((insn_word >> 2) & 0x1))
  996. o1z = 1;
  997. if (is_addr_op)
  998. {
  999. if (unit_bit)
  1000. base_unit = UNIT_A1;
  1001. else
  1002. base_unit = UNIT_A0;
  1003. }
  1004. else
  1005. {
  1006. if (unit_bit)
  1007. base_unit = UNIT_D1;
  1008. else
  1009. base_unit = UNIT_D0;
  1010. }
  1011. dest_no = (insn_word >> 19) & REG_MASK;
  1012. src1_no = (insn_word >> 14) & REG_MASK;
  1013. src2_no = (insn_word >> 9) & REG_MASK;
  1014. dest_unit = base_unit;
  1015. if (imm)
  1016. {
  1017. if (cond)
  1018. {
  1019. if (ca)
  1020. {
  1021. dest_unit = (insn_word >> 1) & UNIT_MASK;
  1022. dest_reg = lookup_reg_name (dest_unit, dest_no);
  1023. }
  1024. else
  1025. dest_reg = lookup_reg_name (dest_unit, dest_no);
  1026. src1_reg = lookup_reg_name (base_unit, src1_no);
  1027. value = (insn_word >> 6) & IMM8_MASK;
  1028. if (is_quickrot)
  1029. {
  1030. unsigned int qr_unit = unit_bit ? UNIT_A1 : UNIT_A0;
  1031. unsigned int qr_no = 2;
  1032. const char *qr_reg = lookup_reg_name (qr_unit, qr_no);
  1033. snprintf (buf, OPERAND_WIDTH, "%s,%s,#%#x,%s", dest_reg,
  1034. src1_reg, value, qr_reg);
  1035. }
  1036. else
  1037. snprintf (buf, OPERAND_WIDTH, "%s,%s,#%#x", dest_reg,
  1038. src1_reg, value);
  1039. }
  1040. else
  1041. {
  1042. if (is_addr_op && (dest_no & ~CPC_REG_MASK))
  1043. {
  1044. dest_reg = lookup_reg_name (dest_unit, dest_no & CPC_REG_MASK);
  1045. src1_reg = lookup_reg_name (base_unit, 0x10);
  1046. }
  1047. else
  1048. {
  1049. dest_reg = lookup_reg_name (dest_unit, dest_no);
  1050. src1_reg = lookup_reg_name (base_unit, dest_no);
  1051. }
  1052. value = (insn_word >> 3) & IMM16_MASK;
  1053. if (se)
  1054. {
  1055. value = sign_extend (value, IMM16_BITS);
  1056. if (o1z)
  1057. {
  1058. snprintf (buf, OPERAND_WIDTH, "%s,#%d", dest_reg, value);
  1059. }
  1060. else
  1061. {
  1062. snprintf (buf, OPERAND_WIDTH, "%s,%s,#%d", dest_reg,
  1063. src1_reg, value);
  1064. }
  1065. }
  1066. else
  1067. {
  1068. if (o1z)
  1069. {
  1070. snprintf (buf, OPERAND_WIDTH, "%s,#%#x", dest_reg, value);
  1071. }
  1072. else
  1073. {
  1074. snprintf (buf, OPERAND_WIDTH, "%s,%s,#%#x", dest_reg,
  1075. src1_reg, value);
  1076. }
  1077. }
  1078. }
  1079. }
  1080. else
  1081. {
  1082. src1_reg = lookup_reg_name (base_unit, src1_no);
  1083. if (o2r)
  1084. src2_reg = lookup_o2r (base_unit, src2_no);
  1085. else
  1086. src2_reg = lookup_reg_name (base_unit, src2_no);
  1087. if (cond)
  1088. {
  1089. dest_unit = (insn_word >> 5) & UNIT_MASK;
  1090. if (is_mul)
  1091. {
  1092. if (ca)
  1093. dest_unit = (insn_word >> 1) & UNIT_MASK;
  1094. else
  1095. dest_unit = base_unit;
  1096. }
  1097. dest_reg = lookup_reg_name (dest_unit, dest_no);
  1098. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg,
  1099. src1_reg, src2_reg);
  1100. }
  1101. else
  1102. {
  1103. dest_reg = lookup_reg_name (dest_unit, dest_no);
  1104. if (is_quickrot)
  1105. {
  1106. unsigned int qr_unit = unit_bit ? UNIT_A1 : UNIT_A0;
  1107. unsigned int qr_no = 2 + ((insn_word >> 7) & 0x1);
  1108. const char *qr_reg = lookup_reg_name (qr_unit, qr_no);
  1109. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s,%s", dest_reg,
  1110. src1_reg, src2_reg, qr_reg);
  1111. }
  1112. else if (o1z)
  1113. {
  1114. snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src2_reg);
  1115. }
  1116. else
  1117. {
  1118. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg,
  1119. src1_reg, src2_reg);
  1120. }
  1121. }
  1122. }
  1123. if (dest_unit == UNIT_FX)
  1124. print_insn (outf, "F", template->name, buf);
  1125. else
  1126. print_insn (outf, "", template->name, buf);
  1127. }
  1128. /* Print a B instruction. */
  1129. static void
  1130. print_branch (unsigned int insn_word, bfd_vma pc,
  1131. const insn_template *template,
  1132. disassemble_info *outf)
  1133. {
  1134. int value;
  1135. value = (insn_word >> 5) & IMM19_MASK;
  1136. value = sign_extend (value, IMM19_BITS);
  1137. value = value * 4;
  1138. value += pc;
  1139. print_insn (outf, "", template->name, "");
  1140. outf->print_address_func (value, outf);
  1141. }
  1142. /* Print a SWITCH instruction. */
  1143. static void
  1144. print_switch (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1145. const insn_template *template,
  1146. disassemble_info *outf)
  1147. {
  1148. char buf[OPERAND_WIDTH];
  1149. unsigned int value;
  1150. value = insn_word & IMM24_MASK;
  1151. snprintf (buf, OPERAND_WIDTH, "#%#x", value);
  1152. print_insn (outf, "", template->name, buf);
  1153. }
  1154. /* Print a shift instruction. */
  1155. static void
  1156. print_shift (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1157. const insn_template *template,
  1158. disassemble_info *outf)
  1159. {
  1160. char buf[OPERAND_WIDTH];
  1161. unsigned int dest_no, src1_no, src2_no;
  1162. unsigned int imm = (insn_word >> 25) & 0x1;
  1163. unsigned int cond = (insn_word >> 26) & 0x1;
  1164. unsigned int unit_bit = (insn_word >> 24) & 0x1;
  1165. unsigned int ca = (insn_word >> 5) & 0x1;
  1166. enum metag_unit base_unit;
  1167. unsigned int dest_unit;
  1168. const char *dest_reg;
  1169. const char *src1_reg;
  1170. const char *src2_reg;
  1171. int value;
  1172. if (unit_bit)
  1173. base_unit = UNIT_D1;
  1174. else
  1175. base_unit = UNIT_D0;
  1176. dest_no = (insn_word >> 19) & REG_MASK;
  1177. src1_no = (insn_word >> 14) & REG_MASK;
  1178. src2_no = (insn_word >> 9) & REG_MASK;
  1179. dest_unit = base_unit;
  1180. if (imm)
  1181. {
  1182. if (cond && ca)
  1183. dest_unit = (insn_word >> 1) & UNIT_MASK;
  1184. dest_reg = lookup_reg_name (dest_unit, dest_no);
  1185. src1_reg = lookup_reg_name (base_unit, src1_no);
  1186. value = (insn_word >> 9) & IMM5_MASK;
  1187. snprintf (buf, OPERAND_WIDTH, "%s,%s,#%#x", dest_reg,
  1188. src1_reg, value);
  1189. }
  1190. else
  1191. {
  1192. if (cond && ca)
  1193. dest_unit = (insn_word >> 1) & UNIT_MASK;
  1194. dest_reg = lookup_reg_name (dest_unit, dest_no);
  1195. src1_reg = lookup_reg_name (base_unit, src1_no);
  1196. src2_reg = lookup_reg_name (base_unit, src2_no);
  1197. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg,
  1198. src1_reg, src2_reg);
  1199. }
  1200. if (dest_unit == UNIT_FX)
  1201. print_insn (outf, "F", template->name, buf);
  1202. else
  1203. print_insn (outf, "", template->name, buf);
  1204. }
  1205. /* Print a MIN or MAX instruction. */
  1206. static void
  1207. print_min_max (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1208. const insn_template *template,
  1209. disassemble_info *outf)
  1210. {
  1211. unsigned int base_unit, dest_no, src1_no, src2_no;
  1212. char buf[OPERAND_WIDTH];
  1213. const char *dest_reg;
  1214. const char *src1_reg;
  1215. const char *src2_reg;
  1216. if ((insn_word >> 24) & UNIT_MASK)
  1217. base_unit = UNIT_D1;
  1218. else
  1219. base_unit = UNIT_D0;
  1220. dest_no = (insn_word >> 19) & REG_MASK;
  1221. src1_no = (insn_word >> 14) & REG_MASK;
  1222. src2_no = (insn_word >> 9) & REG_MASK;
  1223. dest_reg = lookup_reg_name (base_unit, dest_no);
  1224. src1_reg = lookup_reg_name (base_unit, src1_no);
  1225. src2_reg = lookup_reg_name (base_unit, src2_no);
  1226. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg);
  1227. print_insn (outf, "", template->name, buf);
  1228. }
  1229. /* Print a bit operation instruction. */
  1230. static void
  1231. print_bitop (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1232. const insn_template *template,
  1233. disassemble_info *outf)
  1234. {
  1235. unsigned int swap_inst = MAJOR_OPCODE (template->meta_opcode) == OPC_MISC;
  1236. unsigned int base_unit, src_unit, dest_no, src_no;
  1237. unsigned int is_bexl = 0;
  1238. char buf[OPERAND_WIDTH];
  1239. const char *dest_reg;
  1240. const char *src_reg;
  1241. if (swap_inst &&
  1242. ((insn_word >> 1) & 0xb) == 0xa)
  1243. is_bexl = 1;
  1244. if (swap_inst)
  1245. {
  1246. if (insn_word & 0x1)
  1247. base_unit = UNIT_D1;
  1248. else
  1249. base_unit = UNIT_D0;
  1250. }
  1251. else
  1252. {
  1253. if ((insn_word >> 24) & 0x1)
  1254. base_unit = UNIT_D1;
  1255. else
  1256. base_unit = UNIT_D0;
  1257. }
  1258. src_unit = base_unit;
  1259. if (is_bexl)
  1260. base_unit = get_pair_unit (base_unit);
  1261. dest_no = (insn_word >> 19) & REG_MASK;
  1262. dest_reg = lookup_reg_name (base_unit, dest_no);
  1263. src_no = (insn_word >> 14) & REG_MASK;
  1264. src_reg = lookup_reg_name (src_unit, src_no);
  1265. snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
  1266. print_insn (outf, "", template->name, buf);
  1267. }
  1268. /* Print a CMP or TST instruction. */
  1269. static void
  1270. print_cmp (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1271. const insn_template *template,
  1272. disassemble_info *outf)
  1273. {
  1274. char buf[OPERAND_WIDTH];
  1275. unsigned int dest_no, src_no;
  1276. unsigned int imm = (insn_word >> 25) & 0x1;
  1277. unsigned int cond = (insn_word >> 26) & 0x1;
  1278. unsigned int o2r = insn_word & 0x1;
  1279. unsigned int unit_bit = (insn_word >> 24) & 0x1;
  1280. unsigned int se = (insn_word >> 1) & 0x1;
  1281. enum metag_unit base_unit;
  1282. const char *dest_reg;
  1283. const char *src_reg;
  1284. int value;
  1285. if (unit_bit)
  1286. base_unit = UNIT_D1;
  1287. else
  1288. base_unit = UNIT_D0;
  1289. dest_no = (insn_word >> 14) & REG_MASK;
  1290. src_no = (insn_word >> 9) & REG_MASK;
  1291. dest_reg = lookup_reg_name (base_unit, dest_no);
  1292. if (imm)
  1293. {
  1294. if (cond)
  1295. {
  1296. value = (insn_word >> 6) & IMM8_MASK;
  1297. snprintf (buf, OPERAND_WIDTH, "%s,#%#x", dest_reg, value);
  1298. }
  1299. else
  1300. {
  1301. dest_no = (insn_word >> 19) & REG_MASK;
  1302. dest_reg = lookup_reg_name (base_unit, dest_no);
  1303. value = (insn_word >> 3) & IMM16_MASK;
  1304. if (se)
  1305. {
  1306. value = sign_extend (value, IMM16_BITS);
  1307. snprintf (buf, OPERAND_WIDTH, "%s,#%d", dest_reg, value);
  1308. }
  1309. else
  1310. {
  1311. snprintf (buf, OPERAND_WIDTH, "%s,#%#x", dest_reg, value);
  1312. }
  1313. }
  1314. }
  1315. else
  1316. {
  1317. if (o2r)
  1318. src_reg = lookup_o2r (base_unit, src_no);
  1319. else
  1320. src_reg = lookup_reg_name (base_unit, src_no);
  1321. snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
  1322. }
  1323. print_insn (outf, "", template->name, buf);
  1324. }
  1325. /* Print a CACHER instruction. */
  1326. static void
  1327. print_cacher (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1328. const insn_template *template,
  1329. disassemble_info *outf)
  1330. {
  1331. char buf[OPERAND_WIDTH];
  1332. char addr_buf[ADDR_WIDTH];
  1333. unsigned int reg_unit, reg_no;
  1334. unsigned int size = ((insn_word >> 1) & 0x1) ? 8 : 4;
  1335. const char *reg_name;
  1336. const char *pair_name;
  1337. reg_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK);
  1338. reg_no = (insn_word >> 19) & REG_MASK;
  1339. reg_name = lookup_reg_name (reg_unit, reg_no);
  1340. pair_name = lookup_pair_reg_name (reg_unit, reg_no);
  1341. cache_addr_str (addr_buf, ADDR_WIDTH, insn_word, size);
  1342. if (size == 8)
  1343. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", reg_name, pair_name, addr_buf);
  1344. else
  1345. snprintf (buf, OPERAND_WIDTH, "%s,%s", reg_name, addr_buf);
  1346. print_insn (outf, "", template->name, buf);
  1347. }
  1348. /* Print a CACHEW instruction. */
  1349. static void
  1350. print_cachew (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1351. const insn_template *template,
  1352. disassemble_info *outf)
  1353. {
  1354. char buf[OPERAND_WIDTH];
  1355. char addr_buf[ADDR_WIDTH];
  1356. unsigned int reg_unit, reg_no;
  1357. unsigned int size = ((insn_word >> 1) & 0x1) ? 8 : 4;
  1358. const char *reg_name;
  1359. const char *pair_name;
  1360. reg_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK);
  1361. reg_no = (insn_word >> 19) & REG_MASK;
  1362. reg_name = lookup_reg_name (reg_unit, reg_no);
  1363. pair_name = lookup_pair_reg_name (reg_unit, reg_no);
  1364. cache_addr_str (addr_buf, ADDR_WIDTH, insn_word, 64);
  1365. if (size == 8)
  1366. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", addr_buf, reg_name, pair_name);
  1367. else
  1368. snprintf (buf, OPERAND_WIDTH, "%s,%s", addr_buf, reg_name);
  1369. print_insn (outf, "", template->name, buf);
  1370. }
  1371. /* Print an ICACHE instruction. */
  1372. static void
  1373. print_icache (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1374. const insn_template *template,
  1375. disassemble_info *outf)
  1376. {
  1377. char buf[OPERAND_WIDTH];
  1378. int offset;
  1379. int pfcount;
  1380. offset = ((insn_word >> 9) & IMM15_MASK);
  1381. pfcount = ((insn_word >> 1) & IMM4_MASK);
  1382. offset = sign_extend (offset, IMM15_BITS);
  1383. if (pfcount)
  1384. snprintf (buf, OPERAND_WIDTH, "#%d,#0x%x", offset, pfcount);
  1385. else
  1386. snprintf (buf, OPERAND_WIDTH, "#%d,#0", offset);
  1387. print_insn (outf, "", template->name, buf);
  1388. }
  1389. /* Print a LNKGET instruction. */
  1390. static void
  1391. print_lnkget (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1392. const insn_template *template,
  1393. disassemble_info *outf)
  1394. {
  1395. char buf[OPERAND_WIDTH];
  1396. char addr_buf[ADDR_WIDTH];
  1397. unsigned int reg_unit, reg_no;
  1398. unsigned int size = metag_get_set_ext_size_bytes (insn_word);
  1399. const char *reg_name;
  1400. const char *pair_name;
  1401. reg_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK);
  1402. reg_no = (insn_word >> 19) & REG_MASK;
  1403. reg_name = lookup_reg_name (reg_unit, reg_no);
  1404. pair_name = lookup_pair_reg_name (reg_unit, reg_no);
  1405. cache_addr_str (addr_buf, ADDR_WIDTH, insn_word, size);
  1406. if (size == 8)
  1407. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", reg_name, pair_name, addr_buf);
  1408. else
  1409. snprintf (buf, OPERAND_WIDTH, "%s,%s", reg_name, addr_buf);
  1410. print_insn (outf, "", template->name, buf);
  1411. }
  1412. /* Print an FPU MOV instruction. */
  1413. static void
  1414. print_fmov (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1415. const insn_template *template,
  1416. disassemble_info *outf)
  1417. {
  1418. char buf[OPERAND_WIDTH];
  1419. char prefix_buf[10];
  1420. unsigned int src_no, dest_no;
  1421. unsigned int p = (insn_word >> 6) & 0x1;
  1422. unsigned int d = (insn_word >> 5) & 0x1;
  1423. unsigned int cc = (insn_word >> 1) & CC_MASK;
  1424. bool show_cond = cc != COND_A && cc != COND_NV;
  1425. const char *dest_reg;
  1426. const char *src_reg;
  1427. const char *cc_flags;
  1428. dest_no = (insn_word >> 19) & REG_MASK;
  1429. src_no = (insn_word >> 14) & REG_MASK;
  1430. dest_reg = lookup_reg_name (UNIT_FX, dest_no);
  1431. src_reg = lookup_reg_name (UNIT_FX, src_no);
  1432. cc_flags = lookup_fpu_scc_flags (cc);
  1433. snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
  1434. snprintf (prefix_buf, 10, "F%s%s%s", p ? "L" : "",
  1435. d ? "D" : "", show_cond ? cc_flags : "");
  1436. print_insn (outf, prefix_buf, template->name, buf);
  1437. }
  1438. /* Convert an FPU rmask into a compatible form. */
  1439. static unsigned int
  1440. convert_fx_rmask (unsigned int rmask)
  1441. {
  1442. int num_bits = hweight (rmask), i;
  1443. unsigned int ret = 0;
  1444. for (i = 0; i < num_bits; i++)
  1445. {
  1446. ret <<= 1;
  1447. ret |= 0x1;
  1448. }
  1449. return ret;
  1450. }
  1451. /* Print an FPU MMOV instruction. */
  1452. static void
  1453. print_fmmov (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1454. const insn_template *template,
  1455. disassemble_info *outf)
  1456. {
  1457. /* We used to have buf[OPERAND_WIDTH] here, but gcc v8 complains
  1458. about the snprintf()s below possibly truncating the output.
  1459. (There is no way to tell gcc that this truncation is intentional).
  1460. So now we use an extra wide buffer. */
  1461. char buf[OPERAND_WIDTH * 2];
  1462. char data_buf[REG_WIDTH];
  1463. char fpu_buf[REG_WIDTH];
  1464. bool to_fpu = MAJOR_OPCODE (insn_word) == OPC_GET;
  1465. bool is_mmovl = MINOR_OPCODE (insn_word) & 0x1;
  1466. unsigned int rmask = (insn_word >> 7) & RMASK_MASK;
  1467. unsigned int fpu_no, data_no, data_unit;
  1468. data_no = (insn_word >> 19) & REG_MASK;
  1469. fpu_no = (insn_word >> 14) & REG_MASK;
  1470. if (insn_word & 0x1)
  1471. data_unit = UNIT_D1;
  1472. else
  1473. data_unit = UNIT_D0;
  1474. lookup_reg_list (data_buf, REG_WIDTH, data_unit, data_no, rmask, false);
  1475. lookup_reg_list (fpu_buf, REG_WIDTH, UNIT_FX, fpu_no,
  1476. convert_fx_rmask (rmask), is_mmovl);
  1477. if (to_fpu)
  1478. snprintf (buf, sizeof buf, "%s,%s", fpu_buf, data_buf);
  1479. else
  1480. snprintf (buf, sizeof buf, "%s,%s", data_buf, fpu_buf);
  1481. print_insn (outf, "F", template->name, buf);
  1482. }
  1483. /* Print an FPU data unit MOV instruction. */
  1484. static void
  1485. print_fmov_data (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1486. const insn_template *template,
  1487. disassemble_info *outf)
  1488. {
  1489. char buf[OPERAND_WIDTH];
  1490. unsigned int src_no, dest_no;
  1491. unsigned int to_fpu = ((insn_word >> 7) & 0x1);
  1492. unsigned int unit_bit = (insn_word >> 24) & 0x1;
  1493. enum metag_unit base_unit;
  1494. const char *dest_reg;
  1495. const char *src_reg;
  1496. dest_no = (insn_word >> 19) & REG_MASK;
  1497. src_no = (insn_word >> 9) & REG_MASK;
  1498. if (unit_bit)
  1499. base_unit = UNIT_D1;
  1500. else
  1501. base_unit = UNIT_D0;
  1502. if (to_fpu)
  1503. {
  1504. dest_reg = lookup_reg_name (UNIT_FX, dest_no);
  1505. src_reg = lookup_reg_name (base_unit, src_no);
  1506. }
  1507. else
  1508. {
  1509. dest_reg = lookup_reg_name (base_unit, dest_no);
  1510. src_reg = lookup_reg_name (UNIT_FX, src_no);
  1511. }
  1512. snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
  1513. print_insn (outf, "F", template->name, buf);
  1514. }
  1515. /* Print an FPU MOV immediate instruction. */
  1516. static void
  1517. print_fmov_i (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1518. const insn_template *template,
  1519. disassemble_info *outf)
  1520. {
  1521. char buf[OPERAND_WIDTH];
  1522. unsigned int dest_no;
  1523. unsigned int p = (insn_word >> 2) & 0x1;
  1524. unsigned int d = (insn_word >> 1) & 0x1;
  1525. const char *dest_reg;
  1526. unsigned int value = (insn_word >> 3) & IMM16_MASK;
  1527. dest_no = (insn_word >> 19) & REG_MASK;
  1528. dest_reg = lookup_reg_name (UNIT_FX, dest_no);
  1529. snprintf (buf, OPERAND_WIDTH, "%s,#%#x", dest_reg, value);
  1530. if (p)
  1531. print_insn (outf, "FL", template->name, buf);
  1532. else if (d)
  1533. print_insn (outf, "FD", template->name, buf);
  1534. else
  1535. print_insn (outf, "F", template->name, buf);
  1536. }
  1537. /* Print an FPU PACK instruction. */
  1538. static void
  1539. print_fpack (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1540. const insn_template *template,
  1541. disassemble_info *outf)
  1542. {
  1543. char buf[OPERAND_WIDTH];
  1544. unsigned int src1_no, src2_no, dest_no;
  1545. const char *dest_reg;
  1546. const char *src1_reg;
  1547. const char *src2_reg;
  1548. dest_no = (insn_word >> 19) & REG_MASK;
  1549. src1_no = (insn_word >> 14) & REG_MASK;
  1550. src2_no = (insn_word >> 9) & REG_MASK;
  1551. dest_reg = lookup_reg_name (UNIT_FX, dest_no);
  1552. src1_reg = lookup_reg_name (UNIT_FX, src1_no);
  1553. src2_reg = lookup_reg_name (UNIT_FX, src2_no);
  1554. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg);
  1555. print_insn (outf, "F", template->name, buf);
  1556. }
  1557. /* Print an FPU SWAP instruction. */
  1558. static void
  1559. print_fswap (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1560. const insn_template *template,
  1561. disassemble_info *outf)
  1562. {
  1563. char buf[OPERAND_WIDTH];
  1564. unsigned int src_no, dest_no;
  1565. const char *dest_reg;
  1566. const char *src_reg;
  1567. dest_no = (insn_word >> 19) & REG_MASK;
  1568. src_no = (insn_word >> 14) & REG_MASK;
  1569. dest_reg = lookup_reg_name (UNIT_FX, dest_no);
  1570. src_reg = lookup_reg_name (UNIT_FX, src_no);
  1571. snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
  1572. print_insn (outf, "FL", template->name, buf);
  1573. }
  1574. /* Print an FPU CMP instruction. */
  1575. static void
  1576. print_fcmp (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1577. const insn_template *template,
  1578. disassemble_info *outf)
  1579. {
  1580. char buf[OPERAND_WIDTH];
  1581. char prefix_buf[10];
  1582. unsigned int src_no, dest_no;
  1583. unsigned int a = (insn_word >> 19) & 0x1;
  1584. unsigned int z = (insn_word >> 8) & 0x1;
  1585. unsigned int p = (insn_word >> 6) & 0x1;
  1586. unsigned int d = (insn_word >> 5) & 0x1;
  1587. unsigned int q = (insn_word >> 7) & 0x1;
  1588. unsigned int cc = (insn_word >> 1) & CC_MASK;
  1589. bool show_cond = cc != COND_A && cc != COND_NV;
  1590. const char *dest_reg;
  1591. const char *src_reg;
  1592. const char *cc_flags;
  1593. dest_no = (insn_word >> 14) & REG_MASK;
  1594. src_no = (insn_word >> 9) & REG_MASK;
  1595. dest_reg = lookup_reg_name (UNIT_FX, dest_no);
  1596. src_reg = lookup_reg_name (UNIT_FX, src_no);
  1597. cc_flags = lookup_fpu_scc_flags (cc);
  1598. if (z)
  1599. snprintf (buf, OPERAND_WIDTH, "%s,#0", dest_reg);
  1600. else
  1601. snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
  1602. snprintf (prefix_buf, 10, "F%s%s%s%s%s", p ? "L" : "",
  1603. d ? "D" : "", a ? "A" : "", q ? "Q" : "",
  1604. show_cond ? cc_flags : "");
  1605. print_insn (outf, prefix_buf, template->name, buf);
  1606. }
  1607. /* Print an FPU MIN or MAX instruction. */
  1608. static void
  1609. print_fminmax (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1610. const insn_template *template,
  1611. disassemble_info *outf)
  1612. {
  1613. char buf[OPERAND_WIDTH];
  1614. char prefix_buf[10];
  1615. unsigned int p = (insn_word >> 6) & 0x1;
  1616. unsigned int d = (insn_word >> 5) & 0x1;
  1617. unsigned int src1_no, src2_no, dest_no;
  1618. unsigned int cc = (insn_word >> 1) & CC_MASK;
  1619. bool show_cond = cc != COND_A && cc != COND_NV;
  1620. const char *dest_reg;
  1621. const char *src1_reg;
  1622. const char *src2_reg;
  1623. const char *cc_flags;
  1624. dest_no = (insn_word >> 19) & REG_MASK;
  1625. src1_no = (insn_word >> 14) & REG_MASK;
  1626. src2_no = (insn_word >> 9) & REG_MASK;
  1627. dest_reg = lookup_reg_name (UNIT_FX, dest_no);
  1628. src1_reg = lookup_reg_name (UNIT_FX, src1_no);
  1629. src2_reg = lookup_reg_name (UNIT_FX, src2_no);
  1630. cc_flags = lookup_fpu_scc_flags (cc);
  1631. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg);
  1632. snprintf (prefix_buf, 10, "F%s%s%s", p ? "L" : "",
  1633. d ? "D" : "", show_cond ? cc_flags : "");
  1634. print_insn (outf, prefix_buf, template->name, buf);
  1635. }
  1636. /* Print an FPU data conversion instruction. */
  1637. static void
  1638. print_fconv (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1639. const insn_template *template,
  1640. disassemble_info *outf)
  1641. {
  1642. char buf[OPERAND_WIDTH];
  1643. char prefix_buf[10];
  1644. unsigned int p = (insn_word >> 6) & 0x1;
  1645. unsigned int z = (insn_word >> 12) & 0x1;
  1646. unsigned int src_no, dest_no;
  1647. unsigned int cc = (insn_word >> 1) & CC_MASK;
  1648. bool show_cond = cc != COND_A && cc != COND_NV;
  1649. const char *dest_reg;
  1650. const char *src_reg;
  1651. const char *cc_flags;
  1652. dest_no = (insn_word >> 19) & REG_MASK;
  1653. src_no = (insn_word >> 14) & REG_MASK;
  1654. dest_reg = lookup_reg_name (UNIT_FX, dest_no);
  1655. src_reg = lookup_reg_name (UNIT_FX, src_no);
  1656. cc_flags = lookup_fpu_scc_flags (cc);
  1657. snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
  1658. snprintf (prefix_buf, 10, "F%s%s%s", p ? "L" : "",
  1659. z ? "Z" : "", show_cond ? cc_flags : "");
  1660. print_insn (outf, prefix_buf, template->name, buf);
  1661. }
  1662. /* Print an FPU extended data conversion instruction. */
  1663. static void
  1664. print_fconvx (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1665. const insn_template *template,
  1666. disassemble_info *outf)
  1667. {
  1668. char buf[OPERAND_WIDTH];
  1669. char prefix_buf[10];
  1670. unsigned int p = (insn_word >> 6) & 0x1;
  1671. unsigned int xl = (insn_word >> 7) & 0x1;
  1672. unsigned int src_no, dest_no, fraction_bits;
  1673. unsigned int cc = (insn_word >> 1) & CC_MASK;
  1674. bool show_cond = cc != COND_A && cc != COND_NV;
  1675. const char *dest_reg;
  1676. const char *src_reg;
  1677. const char *cc_flags;
  1678. dest_no = (insn_word >> 19) & REG_MASK;
  1679. src_no = (insn_word >> 14) & REG_MASK;
  1680. dest_reg = lookup_reg_name (UNIT_FX, dest_no);
  1681. src_reg = lookup_reg_name (UNIT_FX, src_no);
  1682. cc_flags = lookup_fpu_scc_flags (cc);
  1683. if (xl)
  1684. fraction_bits = (insn_word >> 8) & IMM6_MASK;
  1685. else
  1686. fraction_bits = (insn_word >> 9) & IMM5_MASK;
  1687. snprintf (buf, OPERAND_WIDTH, "%s,%s,#%#x", dest_reg, src_reg,
  1688. fraction_bits);
  1689. snprintf (prefix_buf, 10, "F%s%s", p ? "L" : "",
  1690. show_cond ? cc_flags : "");
  1691. print_insn (outf, prefix_buf, template->name, buf);
  1692. }
  1693. /* Print an FPU basic arithmetic instruction. */
  1694. static void
  1695. print_fbarith (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1696. const insn_template *template,
  1697. disassemble_info *outf)
  1698. {
  1699. char buf[OPERAND_WIDTH];
  1700. char prefix_buf[10];
  1701. unsigned int n = (insn_word >> 7) & 0x1;
  1702. unsigned int p = (insn_word >> 6) & 0x1;
  1703. unsigned int d = (insn_word >> 5) & 0x1;
  1704. unsigned int src1_no, src2_no, dest_no;
  1705. unsigned int cc = (insn_word >> 1) & CC_MASK;
  1706. bool show_cond = cc != COND_A && cc != COND_NV;
  1707. const char *dest_reg;
  1708. const char *src1_reg;
  1709. const char *src2_reg;
  1710. const char *cc_flags;
  1711. dest_no = (insn_word >> 19) & REG_MASK;
  1712. src1_no = (insn_word >> 14) & REG_MASK;
  1713. src2_no = (insn_word >> 9) & REG_MASK;
  1714. dest_reg = lookup_reg_name (UNIT_FX, dest_no);
  1715. src1_reg = lookup_reg_name (UNIT_FX, src1_no);
  1716. src2_reg = lookup_reg_name (UNIT_FX, src2_no);
  1717. cc_flags = lookup_fpu_scc_flags (cc);
  1718. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg);
  1719. snprintf (prefix_buf, 10, "F%s%s%s%s", p ? "L" : "",
  1720. d ? "D" : "", n ? "I" : "", show_cond ? cc_flags : "");
  1721. print_insn (outf, prefix_buf, template->name, buf);
  1722. }
  1723. /* Print an FPU extended arithmetic instruction. */
  1724. static void
  1725. print_fearith (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1726. const insn_template *template,
  1727. disassemble_info *outf)
  1728. {
  1729. char buf[OPERAND_WIDTH];
  1730. char prefix_buf[10];
  1731. bool is_muz = MINOR_OPCODE (insn_word) == 0x6 && ((insn_word >> 4) & 0x1);
  1732. bool is_mac = MINOR_OPCODE (insn_word) == 0x6 && (insn_word & 0x1f) == 0;
  1733. bool is_maw = MINOR_OPCODE (insn_word) == 0x6 && ((insn_word >> 3) & 0x1);
  1734. unsigned int o3o = insn_word & 0x1;
  1735. unsigned int q = is_muz && ((insn_word >> 1) & 0x1);
  1736. unsigned int n = (insn_word >> 7) & 0x1;
  1737. unsigned int p = (insn_word >> 6) & 0x1;
  1738. unsigned int d = (insn_word >> 5) & 0x1;
  1739. unsigned int cc = (insn_word >> 1) & CC_MASK;
  1740. bool show_cond = (MINOR_OPCODE (insn_word) == 0x5 && cc != COND_A
  1741. && cc != COND_NV);
  1742. unsigned int src1_no, src2_no, dest_no;
  1743. const char *dest_reg;
  1744. const char *src1_reg;
  1745. const char *src2_reg;
  1746. const char *cc_flags;
  1747. dest_no = (insn_word >> 19) & REG_MASK;
  1748. src1_no = (insn_word >> 14) & REG_MASK;
  1749. src2_no = (insn_word >> 9) & REG_MASK;
  1750. dest_reg = lookup_reg_name (UNIT_FX, dest_no);
  1751. src1_reg = lookup_reg_name (UNIT_FX, src1_no);
  1752. src2_reg = lookup_reg_name (UNIT_FX, src2_no);
  1753. cc_flags = lookup_fpu_scc_flags (cc);
  1754. if (is_mac)
  1755. snprintf (buf, OPERAND_WIDTH, "ACF.0,%s,%s", src1_reg, src2_reg);
  1756. else if (o3o && is_maw)
  1757. snprintf (buf, OPERAND_WIDTH, "%s,%s", src1_reg, src2_reg);
  1758. else
  1759. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg);
  1760. snprintf (prefix_buf, 10, "F%s%s%s%s%s", p ? "L" : "",
  1761. d ? "D" : "", n ? "I" : "", q ? "Q" : "",
  1762. show_cond ? cc_flags : "");
  1763. print_insn (outf, prefix_buf, template->name, buf);
  1764. }
  1765. /* Print an FPU RCP or RSQ instruction. */
  1766. static void
  1767. print_frec (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1768. const insn_template *template,
  1769. disassemble_info *outf)
  1770. {
  1771. char buf[OPERAND_WIDTH];
  1772. char prefix_buf[10];
  1773. unsigned int z = (insn_word >> 10) & 0x1;
  1774. unsigned int q = (insn_word >> 9) & 0x1;
  1775. unsigned int n = (insn_word >> 7) & 0x1;
  1776. unsigned int p = (insn_word >> 6) & 0x1;
  1777. unsigned int d = (insn_word >> 5) & 0x1;
  1778. unsigned int src_no, dest_no;
  1779. const char *dest_reg;
  1780. const char *src_reg;
  1781. dest_no = (insn_word >> 19) & REG_MASK;
  1782. src_no = (insn_word >> 14) & REG_MASK;
  1783. dest_reg = lookup_reg_name (UNIT_FX, dest_no);
  1784. src_reg = lookup_reg_name (UNIT_FX, src_no);
  1785. snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
  1786. snprintf (prefix_buf, 10, "F%s%s%s%s%s", p ? "L" : "",
  1787. d ? "D" : "", n ? "I" : "", q ? "Q" : "", z ? "Z" : "");
  1788. print_insn (outf, prefix_buf, template->name, buf);
  1789. }
  1790. static void
  1791. print_fsimd (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1792. const insn_template *template,
  1793. disassemble_info *outf)
  1794. {
  1795. char buf[OPERAND_WIDTH];
  1796. unsigned int n = (insn_word >> 7) & 0x1;
  1797. unsigned int src1_no, src2_no, dest_no;
  1798. const char *dest_reg;
  1799. const char *src1_reg;
  1800. const char *src2_reg;
  1801. dest_no = (insn_word >> 19) & REG_MASK;
  1802. src1_no = (insn_word >> 14) & REG_MASK;
  1803. src2_no = (insn_word >> 9) & REG_MASK;
  1804. dest_reg = lookup_reg_name (UNIT_FX, dest_no);
  1805. src1_reg = lookup_reg_name (UNIT_FX, src1_no);
  1806. src2_reg = lookup_reg_name (UNIT_FX, src2_no);
  1807. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg);
  1808. if (n)
  1809. print_insn (outf, "FLI", template->name, buf);
  1810. else
  1811. print_insn (outf, "FL", template->name, buf);
  1812. }
  1813. /* Print an FPU accumulator GET or SET instruction. */
  1814. static void
  1815. print_fget_set_acf (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1816. const insn_template *template,
  1817. disassemble_info *outf)
  1818. {
  1819. bool is_get = MAJOR_OPCODE (template->meta_opcode) == OPC_GET;
  1820. char buf[OPERAND_WIDTH];
  1821. char addr_buf[ADDR_WIDTH];
  1822. unsigned int part;
  1823. const char *reg_name;
  1824. part = (insn_word >> 19) & ACF_PART_MASK;
  1825. reg_name = lookup_acf_name (part);
  1826. mget_mset_addr_str (addr_buf, ADDR_WIDTH, insn_word);
  1827. if (is_get)
  1828. {
  1829. snprintf (buf, OPERAND_WIDTH, "%s,%s", reg_name, addr_buf);
  1830. }
  1831. else
  1832. {
  1833. snprintf (buf, OPERAND_WIDTH, "%s,%s", addr_buf, reg_name);
  1834. }
  1835. print_insn (outf, "F", template->name, buf);
  1836. }
  1837. /* Return the name of the DSP register or accumulator for NUM and UNIT. */
  1838. static const char *
  1839. __lookup_dsp_name (unsigned int num, unsigned int unit)
  1840. {
  1841. size_t i;
  1842. for (i = 0; i < sizeof(metag_dsp_regtab)/sizeof(metag_dsp_regtab[0]); i++)
  1843. {
  1844. const metag_reg *reg = &metag_dsp_regtab[i];
  1845. if (reg->no == num)
  1846. {
  1847. if ((reg->unit == UNIT_RAM_D0 || reg->unit == UNIT_ACC_D0) &&
  1848. unit == UNIT_D0)
  1849. return reg->name;
  1850. if ((reg->unit == UNIT_RAM_D1 || reg->unit == UNIT_ACC_D1) &&
  1851. unit == UNIT_D1)
  1852. return reg->name;
  1853. }
  1854. }
  1855. return "?.?";
  1856. }
  1857. /* Return the name of the DSP register for NUM and UNIT. */
  1858. static const char *
  1859. lookup_dsp_name (unsigned int num, unsigned int unit)
  1860. {
  1861. size_t i;
  1862. for (i = 0; i < sizeof(metag_dsp_regtab)/sizeof(metag_dsp_regtab[0]); i++)
  1863. {
  1864. const metag_reg *reg = &metag_dsp_regtab[i];
  1865. if (reg->no == num && reg->unit == unit)
  1866. return reg->name;
  1867. }
  1868. return "?.?";
  1869. }
  1870. /* Return the name of the DSP RAM register for NUM and UNIT. */
  1871. static const char *
  1872. lookup_dspram_name (unsigned int num, unsigned int unit, bool load)
  1873. {
  1874. size_t i, nentries;
  1875. nentries = sizeof(metag_dsp_tmpl_regtab[load])/sizeof(metag_dsp_tmpl_regtab[load][0]);
  1876. for (i = 0; i < nentries; i++)
  1877. {
  1878. const metag_reg *reg = &metag_dsp_tmpl_regtab[load][i];
  1879. if (reg->no == num && reg->unit == unit)
  1880. return reg->name;
  1881. }
  1882. return "?.?";
  1883. }
  1884. /* This lookup function looks up the corresponding name for a register
  1885. number in a DSP instruction. SOURCE indicates whether this
  1886. register is a source or destination operand. */
  1887. static const char *
  1888. lookup_any_reg_name (unsigned int unit, unsigned int num, bool source)
  1889. {
  1890. /* A register with the top bit set (5th bit) indicates a DSPRAM
  1891. register. */
  1892. if (num > 15)
  1893. {
  1894. unsigned int dunit = (unit == UNIT_D0) ? UNIT_RAM_D0 : UNIT_RAM_D1;
  1895. return lookup_dspram_name (num, dunit, source);
  1896. }
  1897. else
  1898. return lookup_reg_name (unit, num);
  1899. }
  1900. /* Return the DSP data unit for UNIT. */
  1901. static inline enum metag_unit
  1902. dsp_data_unit_to_sym (unsigned int unit)
  1903. {
  1904. if (unit == 0)
  1905. return UNIT_D0;
  1906. else
  1907. return UNIT_D1;
  1908. }
  1909. /* Print a DSP GET or SET instruction. */
  1910. static void
  1911. print_dget_set (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  1912. const insn_template *template,
  1913. disassemble_info *outf)
  1914. {
  1915. bool is_get = (template->meta_opcode & 0x100);
  1916. char buf[OPERAND_WIDTH];
  1917. char addr_buf[ADDR_WIDTH];
  1918. char prefix[DSP_PREFIX_WIDTH];
  1919. unsigned int part;
  1920. const char *reg_name[2];
  1921. bool is_high = false;
  1922. bool is_dual = (insn_word & 0x4);
  1923. bool is_template = (insn_word & 0x2);
  1924. const char *base_reg = "?";
  1925. unsigned int addr_unit, base_no, unit;
  1926. unit = dsp_data_unit_to_sym (insn_word & 0x1);
  1927. /* Is this a load/store to a template table? */
  1928. if (is_template)
  1929. {
  1930. part = (insn_word >> 19) & 0x1f;
  1931. reg_name[0] = lookup_dsp_name (part, UNIT_DT);
  1932. }
  1933. else
  1934. {
  1935. part = (insn_word >> 19) & REG_MASK;
  1936. is_high = ((part & 0x18) == 0x18);
  1937. /* Strip bit high indicator. */
  1938. if (is_high)
  1939. part &= 0x17;
  1940. reg_name[0] = __lookup_dsp_name (part, unit);
  1941. }
  1942. /* Is this a dual unit DSP operation? The modulo operator below
  1943. makes sure that we print the Rd register in the correct order,
  1944. e.g. because there's only one bit in the instruction for the Data
  1945. Unit we have to work out what the other data unit number is.
  1946. (there's only 2). */
  1947. if (is_dual)
  1948. {
  1949. unsigned int _unit = insn_word & 0x1;
  1950. _unit = ((_unit + 1) % 2);
  1951. reg_name[1] = __lookup_dsp_name(part, dsp_data_unit_to_sym (_unit));
  1952. }
  1953. else
  1954. reg_name[1] = NULL;
  1955. addr_unit = ((insn_word >> 18) & 0x1);
  1956. if (addr_unit == 0)
  1957. addr_unit = UNIT_A0;
  1958. else
  1959. addr_unit = UNIT_A1;
  1960. base_no = (insn_word >> 14) & DSP_REG_MASK;
  1961. base_reg = lookup_reg_name (addr_unit, base_no);
  1962. /* Check if it's a post-increment/post-decrement. */
  1963. if (insn_word & 0x2000)
  1964. {
  1965. unsigned int imm = (insn_word >> 9) & DGET_SET_IMM_MASK;
  1966. const char *post_op;
  1967. switch (imm)
  1968. {
  1969. case 0x1:
  1970. post_op = "++";
  1971. break;
  1972. case 0x3:
  1973. post_op = "--";
  1974. break;
  1975. default:
  1976. post_op = "";
  1977. }
  1978. snprintf (addr_buf, ADDR_WIDTH, "[%s%s]", base_reg, post_op);
  1979. }
  1980. else
  1981. {
  1982. unsigned int offset_part = (insn_word >> 9) & DSP_REG_MASK;
  1983. const char *offset_reg = lookup_reg_name (addr_unit, offset_part);
  1984. snprintf (addr_buf, ADDR_WIDTH, "[%s+%s++]", base_reg, offset_reg);
  1985. }
  1986. if (is_get)
  1987. {
  1988. if (is_dual && !is_template)
  1989. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", reg_name[0],
  1990. reg_name[1], addr_buf);
  1991. else
  1992. snprintf (buf, OPERAND_WIDTH, "%s,%s", reg_name[0], addr_buf);
  1993. }
  1994. else
  1995. {
  1996. if (is_dual && !is_template)
  1997. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", addr_buf,
  1998. reg_name[0], reg_name[1]);
  1999. else
  2000. snprintf (buf, OPERAND_WIDTH, "%s,%s", addr_buf, reg_name[0]);
  2001. }
  2002. snprintf (prefix, DSP_PREFIX_WIDTH, "D%s", is_high ? "H" : "");
  2003. print_insn (outf, prefix, template->name, buf);
  2004. }
  2005. /* Print a DSP template instruction. */
  2006. static void
  2007. print_dtemplate (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  2008. const insn_template *template,
  2009. disassemble_info *outf)
  2010. {
  2011. char buf[OPERAND_WIDTH];
  2012. char prefix[DSP_PREFIX_WIDTH];
  2013. unsigned int offset[4];
  2014. bool is_half = (MINOR_OPCODE (insn_word) == 0x5);
  2015. bool daop_only = (MINOR_OPCODE (insn_word) == 0x3);
  2016. offset[0] = ((insn_word >> 19) & REG_MASK);
  2017. offset[1] = ((insn_word >> 14) & REG_MASK);
  2018. offset[2] = ((insn_word >> 9) & REG_MASK);
  2019. offset[3] = ((insn_word >> 4) & REG_MASK);
  2020. if (daop_only)
  2021. snprintf (buf, OPERAND_WIDTH, "#0x%x,#0x%x,#0x%x", offset[0],
  2022. offset[1], offset[2]);
  2023. else
  2024. {
  2025. snprintf (buf, OPERAND_WIDTH, "#0x%x,#0x%x,#0x%x,#0x%x", offset[0],
  2026. offset[1], offset[2], offset[3]);
  2027. }
  2028. snprintf (prefix, DSP_PREFIX_WIDTH, "D%s", is_half ? "H" : "");
  2029. print_insn (outf, prefix, template->name, buf);
  2030. }
  2031. /* Format template definition from INSN_WORD into BUF. */
  2032. static void
  2033. decode_template_definition(unsigned int insn_word, char *buf, size_t len)
  2034. {
  2035. bool load = ((insn_word >> 13) & 0x1);
  2036. bool dspram = (((insn_word >> 17) & 0x3) == 0x3);
  2037. const char *template[1];
  2038. unsigned int tidx = ((insn_word >> 9) & TEMPLATE_REGS_MASK);
  2039. enum metag_unit au, ram_unit;
  2040. unsigned int addr_reg_nums[2];
  2041. const char *addr_reg_names[2];
  2042. const char *post_op = "";
  2043. const char *join_op = "";
  2044. enum metag_unit data_unit = ((insn_word >> 24) & 0x1) ? UNIT_D1 : UNIT_D0;
  2045. template[0] = lookup_dsp_name (tidx, UNIT_DT);
  2046. addr_reg_names[1] = "";
  2047. if (dspram)
  2048. {
  2049. ram_unit = (data_unit == UNIT_D0) ? UNIT_RAM_D0 : UNIT_RAM_D1;
  2050. addr_reg_nums[0] = ((insn_word >> 19) & REG_MASK);
  2051. addr_reg_names[0] = lookup_dspram_name (addr_reg_nums[0],
  2052. ram_unit, load);
  2053. }
  2054. else
  2055. {
  2056. bool im = (((insn_word >> 18) & 0x1) != 0);
  2057. au = (((insn_word >> 23) & 0x1) == 0) ? UNIT_A0 : UNIT_A1;
  2058. addr_reg_nums[0] = ((insn_word >> 19) & DSP_REG_MASK);
  2059. addr_reg_names[0] = lookup_reg_name (au, addr_reg_nums[0]);
  2060. if (im)
  2061. {
  2062. unsigned int im_value = ((insn_word >> 14) & 0x3);
  2063. switch (im_value)
  2064. {
  2065. case 0x1:
  2066. post_op = "++";
  2067. break;
  2068. case 0x3:
  2069. post_op = "--";
  2070. break;
  2071. }
  2072. }
  2073. else
  2074. {
  2075. addr_reg_nums[1] = ((insn_word >> 14) & DSP_REG_MASK);
  2076. addr_reg_names[1] = lookup_reg_name (au, addr_reg_nums[1]);
  2077. join_op = "+";
  2078. post_op = "++";
  2079. }
  2080. }
  2081. if (load)
  2082. {
  2083. len = snprintf (buf, len, " %s,[%s%s%s%s]", template[0], addr_reg_names[0],
  2084. join_op, addr_reg_names[1], post_op);
  2085. }
  2086. else
  2087. {
  2088. len = snprintf (buf, len, " [%s%s%s%s],%s", addr_reg_names[0], join_op,
  2089. addr_reg_names[1], post_op, template[0]);
  2090. }
  2091. }
  2092. /* Print a DSP ALU instruction. */
  2093. static void
  2094. print_dalu (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
  2095. const insn_template *template,
  2096. disassemble_info *outf)
  2097. {
  2098. bool is_dual = false;
  2099. unsigned int data_unit = (((insn_word >> 24) & 0x1) ? UNIT_D1 : UNIT_D0);
  2100. const char *reg_names[3];
  2101. unsigned int reg_nums[3];
  2102. bool ac = ((insn_word >> 7) & 0x1);
  2103. char buf[OPERAND_WIDTH];
  2104. char prefix[DSP_PREFIX_WIDTH];
  2105. size_t len;
  2106. bool is_mod = false;
  2107. bool is_overflow = false;
  2108. unsigned int reg_brackets[3];
  2109. bool is_w_mx = false;
  2110. bool is_b_mx = false;
  2111. bool imm = false;
  2112. bool is_quickrot64 = false;
  2113. bool conditional = false;
  2114. const char *cc_flags = NULL;
  2115. bool is_unsigned = false;
  2116. memset (reg_brackets, 0, sizeof (reg_brackets));
  2117. if (template->arg_type & DSP_ARGS_1)
  2118. {
  2119. bool is_template = false;
  2120. const char *addr_reg = NULL;
  2121. bool qr = false;
  2122. bool is_acc_add = false;
  2123. bool is_acc_sub = false;
  2124. bool is_acc_zero = false;
  2125. bool is_split8 = (template->arg_type & DSP_ARGS_SPLIT8);
  2126. /* Read DU bit. */
  2127. data_unit = ((insn_word >> 24) & 0x1) ? UNIT_D1 : UNIT_D0;
  2128. conditional = ((insn_word >> 24) & 0x4);
  2129. /* Templates can't be conditional. */
  2130. is_template = (((insn_word & 0x02000002) == 0x2) && !conditional);
  2131. if (is_split8)
  2132. is_mod = (insn_word & 0x80);
  2133. if (template->arg_type & DSP_ARGS_QR)
  2134. {
  2135. if (!conditional)
  2136. is_quickrot64 = ((insn_word >> 5) & 0x1);
  2137. }
  2138. if (template->arg_type & DSP_ARGS_DACC)
  2139. {
  2140. is_mod = (insn_word & 0x8);
  2141. is_unsigned = (insn_word & 0x40);
  2142. }
  2143. if (is_template)
  2144. {
  2145. is_w_mx = (insn_word & 0x1);
  2146. is_dual = ((insn_word >> 0x4) & 0x1);
  2147. /* De.r,Dx.r,De.r|ACe.r */
  2148. if (template->arg_type & DSP_ARGS_ACC2)
  2149. {
  2150. is_mod = (insn_word & 0x8);
  2151. is_overflow = (insn_word & 0x20);
  2152. }
  2153. /* ACe.e,ACx.r,ACo.e? */
  2154. if ((template->arg_type & DSP_ARGS_XACC) &&
  2155. (((insn_word >> 6) & 0x5) == 0x5))
  2156. {
  2157. enum metag_unit ac_unit, ao_unit;
  2158. ac_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1;
  2159. if (ac_unit == UNIT_ACC_D0)
  2160. ao_unit = UNIT_ACC_D1;
  2161. else
  2162. ao_unit = UNIT_ACC_D0;
  2163. reg_nums[1] = ((insn_word >> 19) & REG_MASK);
  2164. /* These are dummy arguments anyway so the register
  2165. number does not matter. */
  2166. reg_names[0] = lookup_dsp_name (16, ac_unit); /* ACe.0 */
  2167. reg_names[1] = lookup_dsp_name (16, ac_unit); /* ACx.0 */
  2168. reg_names[2] = lookup_dsp_name (16, ao_unit); /* ACo.0 */
  2169. }
  2170. else
  2171. {
  2172. /* De.r|ACe.r,Dx.r,De.r */
  2173. if (template->arg_type & DSP_ARGS_DACC &&
  2174. ((insn_word & 0x84) != 0))
  2175. {
  2176. enum metag_unit ac_unit;
  2177. ac_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1;
  2178. reg_names[0] = lookup_dsp_name (16, ac_unit);
  2179. is_acc_zero = ((insn_word & 0x84) == 0x04);
  2180. is_acc_add = ((insn_word & 0x84) == 0x80);
  2181. is_acc_sub = ((insn_word & 0x84) == 0x84);
  2182. }
  2183. else
  2184. reg_names[0] = lookup_any_reg_name (data_unit, 0, false);
  2185. /* These are dummy arguments anyway so the register
  2186. number does not matter. */
  2187. reg_names[1] = lookup_any_reg_name (data_unit, 0, true);
  2188. /* De.r,Dx.r,De.r|ACe.r */
  2189. if ((template->arg_type & DSP_ARGS_ACC2) &&
  2190. ((insn_word & 0x80) == 0x80))
  2191. {
  2192. enum metag_unit ac_unit;
  2193. ac_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1;
  2194. reg_names[2] = lookup_dsp_name (16, ac_unit);
  2195. }
  2196. /* Detection of QUICKRoT and accumulator usage uses the
  2197. same bits. They are mutually exclusive. */
  2198. else if (ac && (template->arg_type & DSP_ARGS_ACC2))
  2199. {
  2200. reg_nums[2] = ((insn_word >> 9) & REG_MASK);
  2201. if (data_unit == UNIT_D0)
  2202. reg_names[2] = lookup_dsp_name (reg_nums[2], UNIT_ACC_D0);
  2203. else
  2204. reg_names[2] = lookup_dsp_name (reg_nums[2], UNIT_ACC_D1);
  2205. }
  2206. else
  2207. {
  2208. if ((template->arg_type & DSP_ARGS_QR) &&
  2209. ((insn_word & 0x40) == 0x40))
  2210. {
  2211. enum metag_unit aunit;
  2212. int reg_no;
  2213. if (conditional)
  2214. reg_no = ((insn_word >> 5) & 0x1);
  2215. else
  2216. reg_no = ((insn_word >> 7) & 0x1);
  2217. aunit = (data_unit == UNIT_D0) ? UNIT_A0 : UNIT_A1;
  2218. addr_reg = lookup_reg_name (aunit, reg_no + 2);
  2219. qr = true;
  2220. }
  2221. reg_names[2] = lookup_any_reg_name (data_unit, 0, true);
  2222. }
  2223. }
  2224. if (qr)
  2225. {
  2226. len = snprintf (buf, OPERAND_WIDTH, "%s,%s,%s,%s",
  2227. reg_names[0], reg_names[1], reg_names[2],
  2228. addr_reg);
  2229. }
  2230. else
  2231. {
  2232. len = snprintf (buf, OPERAND_WIDTH, "%s,%s,%s%s%s",
  2233. reg_names[0], reg_names[1],
  2234. reg_brackets[2] ? "[" : "",
  2235. reg_names[2], reg_brackets[2] ? "]" : "");
  2236. }
  2237. decode_template_definition (insn_word, buf + len,
  2238. OPERAND_WIDTH - len);
  2239. }
  2240. else /* Not a template definiton. */
  2241. {
  2242. reg_nums[0] = ((insn_word >> 19) & REG_MASK);
  2243. reg_nums[1] = ((insn_word >> 14) & REG_MASK);
  2244. reg_nums[2] = ((insn_word >> 9) & REG_MASK);
  2245. imm = (((insn_word >> 24) & 0x2) && (template->arg_type & DSP_ARGS_IMM));
  2246. if (imm)
  2247. is_dual = (insn_word & 0x4);
  2248. else if (!conditional)
  2249. is_dual = (insn_word & 0x10);
  2250. else
  2251. cc_flags = lookup_scc_flags ((insn_word >> 1) & CC_MASK);
  2252. /* De.r,Dx.r,De.r|ACe.r */
  2253. if (template->arg_type & DSP_ARGS_ACC2)
  2254. {
  2255. is_mod = (insn_word & 0x8);
  2256. is_overflow = (insn_word & 0x20);
  2257. }
  2258. if (template->arg_type & DSP_ARGS_SPLIT8)
  2259. {
  2260. is_overflow = (insn_word & 0x20);
  2261. }
  2262. /* ACe.e,ACx.r,ACo.e? */
  2263. if ((template->arg_type & DSP_ARGS_XACC) &&
  2264. (((insn_word >> 6) & 0x5) == 0x5))
  2265. {
  2266. enum metag_unit ac_unit, ao_unit;
  2267. ac_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1;
  2268. if (ac_unit == UNIT_ACC_D0)
  2269. ao_unit = UNIT_ACC_D1;
  2270. else
  2271. ao_unit = UNIT_ACC_D0;
  2272. reg_nums[1] = ((insn_word >> 19) & REG_MASK);
  2273. reg_names[0] = lookup_dsp_name (reg_nums[1], ac_unit);
  2274. reg_names[1] = lookup_dsp_name (reg_nums[1], ac_unit);
  2275. reg_names[2] = lookup_dsp_name (reg_nums[1], ao_unit);
  2276. }
  2277. else
  2278. {
  2279. bool o2r = (insn_word & 0x1);
  2280. /* De.r|ACe.r,Dx.r,De.r */
  2281. if ((template->arg_type & DSP_ARGS_DACC) &&
  2282. ((insn_word & 0x84) != 0))
  2283. {
  2284. enum metag_unit ac_unit;
  2285. ac_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1;
  2286. reg_names[0] = lookup_dsp_name (reg_nums[0], ac_unit);
  2287. is_acc_zero = ((insn_word & 0x84) == 0x04);
  2288. is_acc_add = ((insn_word & 0x84) == 0x80);
  2289. is_acc_sub = ((insn_word & 0x84) == 0x84);
  2290. }
  2291. else if (conditional)
  2292. {
  2293. reg_names[0] = lookup_reg_name (data_unit, reg_nums[0]);
  2294. }
  2295. else
  2296. {
  2297. reg_names[0] = lookup_any_reg_name (data_unit,
  2298. reg_nums[0], false);
  2299. if (reg_nums[0] > 15)
  2300. reg_brackets[0] = 1;
  2301. }
  2302. if (imm)
  2303. {
  2304. reg_names[1] = lookup_any_reg_name (data_unit, reg_nums[0], true);
  2305. if (reg_brackets[0])
  2306. reg_brackets[1] = 1;
  2307. }
  2308. else
  2309. {
  2310. if (is_split8 && is_mod)
  2311. {
  2312. reg_names[1] = lookup_reg_name (data_unit, reg_nums[1]);
  2313. }
  2314. else
  2315. {
  2316. reg_names[1] = lookup_any_reg_name (data_unit, reg_nums[1], true);
  2317. if (reg_nums[1] > 15)
  2318. reg_brackets[1] = 1;
  2319. }
  2320. }
  2321. /* Detection of QUICKRoT and accumulator usage uses the
  2322. same bits. They are mutually exclusive. */
  2323. if (ac && (template->arg_type & DSP_ARGS_ACC2))
  2324. {
  2325. if (data_unit == UNIT_D0)
  2326. reg_names[2] = lookup_dsp_name (reg_nums[2], UNIT_ACC_D0);
  2327. else
  2328. reg_names[2] = lookup_dsp_name (reg_nums[2], UNIT_ACC_D1);
  2329. }
  2330. else
  2331. {
  2332. if ((template->arg_type & DSP_ARGS_QR) &&
  2333. ((insn_word & 0x40) == 0x40))
  2334. {
  2335. enum metag_unit aunit;
  2336. int reg_no;
  2337. if (conditional)
  2338. reg_no = ((insn_word >> 5) & 0x1);
  2339. else
  2340. reg_no = ((insn_word >> 7) & 0x1);
  2341. aunit = (data_unit == UNIT_D0) ? UNIT_A0 : UNIT_A1;
  2342. addr_reg = lookup_reg_name (aunit, reg_no + 2);
  2343. qr = true;
  2344. }
  2345. if (o2r)
  2346. reg_names[2] = lookup_o2r (data_unit, reg_nums[2]);
  2347. else
  2348. {
  2349. /* Can't use a DSPRAM reg if both QD and L1 are
  2350. set on a QUICKRoT instruction or if we're a
  2351. split 8. */
  2352. if (((template->arg_type & DSP_ARGS_QR)
  2353. && ((insn_word & 0x30) == 0x30 && !conditional)) ||
  2354. (is_split8 && is_mod))
  2355. reg_names[2] = lookup_reg_name (data_unit, reg_nums[2]);
  2356. else
  2357. {
  2358. reg_names[2] = lookup_any_reg_name (data_unit,
  2359. reg_nums[2], true);
  2360. if (reg_nums[2] > 15)
  2361. reg_brackets[2] = 1;
  2362. }
  2363. }
  2364. }
  2365. }
  2366. if (qr)
  2367. {
  2368. len = snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,%s%s%s,%s",
  2369. reg_brackets[0] ? "[" : "",
  2370. reg_names[0], reg_brackets[0] ? "]" : "",
  2371. reg_brackets[1] ? "[" : "",
  2372. reg_names[1], reg_brackets[1] ? "]" : "",
  2373. reg_brackets[2] ? "[" : "",
  2374. reg_names[2], reg_brackets[2] ? "]" : "",
  2375. addr_reg);
  2376. }
  2377. else
  2378. {
  2379. if (imm)
  2380. {
  2381. /* Conform to the embedded assembler's policy of
  2382. printing negative numbers as decimal and positive
  2383. as hex. */
  2384. int value = ((insn_word >> 3) & IMM16_MASK);
  2385. if ((value & 0x8000) || value == 0)
  2386. {
  2387. value = sign_extend (value, IMM16_BITS);
  2388. len = snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,#%d",
  2389. reg_brackets[0] ? "[" : "",
  2390. reg_names[0], reg_brackets[0] ? "]" : "",
  2391. reg_brackets[1] ? "[" : "",
  2392. reg_names[1], reg_brackets[1] ? "]" : "",
  2393. value);
  2394. }
  2395. else
  2396. {
  2397. len = snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,#%#x",
  2398. reg_brackets[0] ? "[" : "",
  2399. reg_names[0], reg_brackets[0] ? "]" : "",
  2400. reg_brackets[1] ? "[" : "",
  2401. reg_names[1], reg_brackets[1] ? "]" : "",
  2402. value);
  2403. }
  2404. }
  2405. else
  2406. {
  2407. len = snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,%s%s%s",
  2408. reg_brackets[0] ? "[" : "",
  2409. reg_names[0], reg_brackets[0] ? "]" : "",
  2410. reg_brackets[1] ? "[" : "", reg_names[1],
  2411. reg_brackets[1] ? "]" : "",
  2412. reg_brackets[2] ? "[" : "",
  2413. reg_names[2], reg_brackets[2] ? "]" : "");
  2414. }
  2415. }
  2416. }
  2417. snprintf (prefix, DSP_PREFIX_WIDTH, "D%s%s%s%s%s%s%s%s%s%s%s%s",
  2418. cc_flags ? cc_flags : "",
  2419. is_dual ? "L" : "",
  2420. is_quickrot64 ? "Q" : "",
  2421. is_unsigned ? "U" : "",
  2422. is_mod ? "M" : "",
  2423. is_acc_zero ? "Z" : "",
  2424. is_acc_add ? "P" : "", is_acc_sub ? "N" : "",
  2425. is_overflow ? "O" : "",
  2426. is_w_mx ? "W" : "",
  2427. is_b_mx ? "B" : "",
  2428. is_template ? "T" : "");
  2429. }
  2430. else if (template->arg_type & DSP_ARGS_2) /* Group 2. */
  2431. {
  2432. bool is_template;
  2433. bool o2r = false;
  2434. int major = MAJOR_OPCODE (template->meta_opcode);
  2435. bool is_neg_or_mov = (major == OPC_ADD || major == OPC_SUB);
  2436. bool is_cmp_tst = major == OPC_CMP && (insn_word & 0x0000002c) == 0;
  2437. bool is_fpu_mov = template->insn_type == INSN_DSP_FPU;
  2438. bool to_fpu = (template->meta_opcode >> 7) & 0x1;
  2439. if (major == OPC_9)
  2440. imm = (insn_word & 0x2);
  2441. else if (template->arg_type & DSP_ARGS_IMM)
  2442. imm = ((insn_word >> 25) & 0x1);
  2443. is_template = (((insn_word & 0x02000002) == 0x2) &&
  2444. major != OPC_9);
  2445. if (imm)
  2446. is_dual = ((insn_word >> 0x2) & 0x1);
  2447. else
  2448. is_dual = ((insn_word >> 0x4) & 0x1);
  2449. /* MOV and XSD[BW] do not have o2r. */
  2450. if (major != OPC_9 && major != OPC_MISC)
  2451. o2r = (insn_word & 0x1);
  2452. if (is_neg_or_mov)
  2453. {
  2454. is_mod = (insn_word & 0x8);
  2455. is_overflow = (insn_word & 0x20);
  2456. }
  2457. /* XSD */
  2458. if (major == OPC_MISC)
  2459. data_unit = (insn_word & 0x1) ? UNIT_D1 : UNIT_D0;
  2460. else
  2461. data_unit = ((insn_word >> 24) & 0x1) ? UNIT_D1 : UNIT_D0;
  2462. /* Check for NEG,MOV,ABS,FFB, etc. */
  2463. if (is_neg_or_mov || !is_cmp_tst || imm ||
  2464. MAJOR_OPCODE (insn_word) == OPC_9 ||
  2465. MAJOR_OPCODE (insn_word) == OPC_MISC)
  2466. reg_nums[0] = ((insn_word >> 19) & REG_MASK);
  2467. else
  2468. reg_nums[0] = ((insn_word >> 14) & REG_MASK);
  2469. if (is_template)
  2470. {
  2471. is_w_mx = (insn_word & 0x1);
  2472. /* These are dummy arguments anyway so the register number
  2473. does not matter. */
  2474. if (is_fpu_mov)
  2475. {
  2476. if (to_fpu)
  2477. {
  2478. reg_names[0] = lookup_reg_name (UNIT_FX, 0);
  2479. reg_names[1] = lookup_reg_name (data_unit, 0);
  2480. }
  2481. else
  2482. {
  2483. reg_names[0] = lookup_reg_name (data_unit, 0);
  2484. reg_names[1] = lookup_reg_name (UNIT_FX, 0);
  2485. }
  2486. }
  2487. else
  2488. {
  2489. reg_names[0] = lookup_reg_name (data_unit, 0);
  2490. reg_names[1] = lookup_reg_name (data_unit, 0);
  2491. }
  2492. len = snprintf (buf, OPERAND_WIDTH, "%s,%s",
  2493. reg_names[0], reg_names[1]);
  2494. decode_template_definition (insn_word, buf + len,
  2495. OPERAND_WIDTH - len);
  2496. }
  2497. else
  2498. {
  2499. if (imm)
  2500. {
  2501. /* Conform to the embedded assembler's policy of
  2502. printing negative numbers as decimal and positive as
  2503. hex. */
  2504. unsigned int value = ((insn_word >> 3) & IMM16_MASK);
  2505. if (major == OPC_9)
  2506. {
  2507. data_unit = (insn_word & 0x1) ? UNIT_D1 : UNIT_D0;
  2508. is_dual = (insn_word & 0x4);
  2509. reg_names[0] = __lookup_dsp_name (reg_nums[0], data_unit);
  2510. }
  2511. else
  2512. {
  2513. reg_names[0] = lookup_any_reg_name (data_unit, reg_nums[0], true);
  2514. if (reg_nums[0] > 15)
  2515. reg_brackets[0] = 1;
  2516. }
  2517. if ((value & 0x8000) || value == 0)
  2518. {
  2519. value = sign_extend (value, IMM16_BITS);
  2520. snprintf (buf, OPERAND_WIDTH, "%s%s%s,#%d",
  2521. reg_brackets[0] ? "[" : "",
  2522. reg_names[0], reg_brackets[0] ? "]" : "",
  2523. value);
  2524. }
  2525. else
  2526. {
  2527. snprintf (buf, OPERAND_WIDTH, "%s%s%s,#0x%x",
  2528. reg_brackets[0] ? "[" : "",
  2529. reg_names[0], reg_brackets[0] ? "]" : "",
  2530. value);
  2531. }
  2532. }
  2533. else
  2534. {
  2535. if (is_neg_or_mov || is_cmp_tst)
  2536. reg_nums[1] = ((insn_word >> 9) & REG_MASK);
  2537. else
  2538. reg_nums[1] = ((insn_word >> 14) & REG_MASK);
  2539. if (major == OPC_9)
  2540. {
  2541. is_dual = (insn_word & 0x4);
  2542. data_unit = (insn_word & 0x1) ? UNIT_D1 : UNIT_D0;
  2543. if (MINOR_OPCODE (template->meta_opcode) == 0x1)
  2544. reg_names[0] = __lookup_dsp_name (reg_nums[0], data_unit);
  2545. else
  2546. reg_names[0] = lookup_reg_name (data_unit, reg_nums[0]);
  2547. }
  2548. else
  2549. {
  2550. unsigned int reg0_unit = data_unit;
  2551. if (is_fpu_mov && to_fpu)
  2552. reg0_unit = UNIT_FX;
  2553. reg_names[0] = lookup_any_reg_name (reg0_unit, reg_nums[0],
  2554. (!is_neg_or_mov && is_cmp_tst));
  2555. if (reg_nums[0] > 15)
  2556. reg_brackets[0] = 1;
  2557. }
  2558. if (o2r)
  2559. reg_names[1] = lookup_o2r (data_unit, reg_nums[1]);
  2560. else
  2561. {
  2562. /* Check for accumulator argument. */
  2563. if (is_neg_or_mov && ((insn_word & 0x80) == 0x80))
  2564. {
  2565. if (data_unit == UNIT_D0)
  2566. reg_names[1] = lookup_dsp_name (reg_nums[1], UNIT_ACC_D0);
  2567. else
  2568. reg_names[1] = lookup_dsp_name (reg_nums[1], UNIT_ACC_D1);
  2569. }
  2570. else
  2571. {
  2572. if (major == OPC_9)
  2573. {
  2574. if (MINOR_OPCODE (template->meta_opcode) == 0x1)
  2575. {
  2576. reg_names[1] = lookup_reg_name (data_unit, reg_nums[1]);
  2577. }
  2578. else
  2579. {
  2580. enum metag_unit u;
  2581. u = (insn_word & 0x1) ? UNIT_RAM_D1 : UNIT_RAM_D0;
  2582. reg_names[1] = lookup_dsp_name (reg_nums[1], u);
  2583. }
  2584. }
  2585. else
  2586. {
  2587. reg_names[1] = lookup_any_reg_name (data_unit,
  2588. reg_nums[1], true);
  2589. if (reg_nums[1] > 15)
  2590. reg_brackets[1] = 1;
  2591. }
  2592. }
  2593. }
  2594. snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s",
  2595. reg_brackets[0] ? "[" : "", reg_names[0],
  2596. reg_brackets[0] ? "]" : "",
  2597. reg_brackets[1] ? "[" : "", reg_names[1],
  2598. reg_brackets[1] ? "]" : "");
  2599. }
  2600. }
  2601. snprintf (prefix, DSP_PREFIX_WIDTH, "D%s%s%s%s%s%s",
  2602. is_fpu_mov ? "F" : "",
  2603. is_dual ? "L" : "",
  2604. is_mod ? "M" : "", is_overflow ? "O" : "",
  2605. is_w_mx ? "W" : "",
  2606. is_template ? "T" : "");
  2607. }
  2608. else /* Group 3. */
  2609. {
  2610. /* If both the C and CA bits are set, then the Rd register can
  2611. be in any unit. Figure out which unit from the Ud field. */
  2612. bool all_units = (((insn_word) & 0x04000020) == 0x04000020);
  2613. enum metag_unit ud_unit = ((insn_word >> 1) & UNIT_MASK);
  2614. enum metag_unit ram_unit, acc_unit;
  2615. bool round = false;
  2616. bool clamp9 = false;
  2617. bool clamp8 = false;
  2618. bool is_template = ((insn_word & 0x04000002) == 0x2);
  2619. imm = ((insn_word >> 25) & 0x1);
  2620. ac = (insn_word & 0x1);
  2621. conditional = (MINOR_OPCODE (insn_word) & 0x4);
  2622. /* Check for conditional and not Condition Always. */
  2623. if (conditional && !(insn_word & 0x20))
  2624. cc_flags = lookup_scc_flags ((insn_word >> 1) & CC_MASK);
  2625. else if (!(conditional && (insn_word & 0x20)))
  2626. is_dual = ((insn_word >> 0x4) & 0x1);
  2627. /* Conditional instructions don't have the L1 or RSPP fields. */
  2628. if ((insn_word & 0x04000000) == 0)
  2629. {
  2630. round = (((insn_word >> 2) & 0x3) == 0x1);
  2631. clamp9 = (((insn_word >> 2) & 0x3) == 0x2);
  2632. clamp8 = (((insn_word >> 2) & 0x3) == 0x3);
  2633. }
  2634. /* Read DU bit. */
  2635. data_unit = ((insn_word >> 24) & 0x1) ? UNIT_D1 : UNIT_D0;
  2636. reg_nums[0] = ((insn_word >> 19) & REG_MASK);
  2637. reg_nums[1] = ((insn_word >> 14) & REG_MASK);
  2638. ram_unit = (data_unit == UNIT_D0) ? UNIT_RAM_D0 : UNIT_RAM_D1;
  2639. acc_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1;
  2640. if (all_units)
  2641. reg_names[0] = lookup_reg_name (ud_unit, reg_nums[0]);
  2642. else
  2643. {
  2644. if (conditional)
  2645. reg_names[0] = lookup_reg_name (data_unit, reg_nums[0]);
  2646. else
  2647. {
  2648. reg_names[0] = lookup_any_reg_name (data_unit, reg_nums[0], false);
  2649. if (reg_nums[0] > 15)
  2650. reg_brackets[0] = 1;
  2651. }
  2652. }
  2653. if (ac)
  2654. {
  2655. reg_names[1] = lookup_dsp_name (reg_nums[1], acc_unit);
  2656. }
  2657. else
  2658. {
  2659. reg_names[1] = lookup_any_reg_name (data_unit, reg_nums[1], true);
  2660. if (reg_nums[1] > 15)
  2661. reg_brackets[1] = 1;
  2662. }
  2663. if (imm)
  2664. {
  2665. snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,#%#x",
  2666. reg_brackets[0] ? "[" : "",
  2667. reg_names[0], reg_brackets[0] ? "]" : "",
  2668. reg_brackets[1] ? "[" : "",
  2669. reg_names[1], reg_brackets[1] ? "]" : "",
  2670. ((insn_word >> 9) & IMM5_MASK));
  2671. }
  2672. else
  2673. {
  2674. reg_nums[2] = ((insn_word >> 9) & REG_MASK);
  2675. reg_names[2] = lookup_any_reg_name (data_unit, reg_nums[2], true);
  2676. if (reg_nums[2] > 15)
  2677. reg_brackets[2] = 1;
  2678. if (is_template)
  2679. {
  2680. bool load = ((insn_word >> 13) & 0x1);
  2681. bool dspram = (((insn_word >> 17) & 0x3) == 0x3);
  2682. const char *tname[1];
  2683. unsigned int tidx = ((insn_word >> 9) & TEMPLATE_REGS_MASK);
  2684. enum metag_unit au;
  2685. unsigned int addr_reg_nums[2];
  2686. const char *addr_reg_names[2];
  2687. const char *post_op = "";
  2688. const char *join_op = "";
  2689. is_w_mx = ((insn_word >> 5) & 0x1);
  2690. tname[0] = lookup_dsp_name (tidx, UNIT_DT);
  2691. /* These are dummy arguments anyway */
  2692. reg_names[0] = lookup_reg_name (data_unit, 0);
  2693. if (ac)
  2694. reg_names[1] = lookup_dsp_name (16, acc_unit);
  2695. else
  2696. reg_names[1] = lookup_reg_name (data_unit, 0);
  2697. reg_names[2] = lookup_reg_name (data_unit, 0);
  2698. addr_reg_names[1] = "";
  2699. if (dspram)
  2700. {
  2701. ram_unit = (data_unit == UNIT_D0) ? UNIT_RAM_D0 : UNIT_RAM_D1;
  2702. addr_reg_nums[0] = ((insn_word >> 19) & REG_MASK);
  2703. addr_reg_names[0] = lookup_dspram_name (addr_reg_nums[0],
  2704. ram_unit, load);
  2705. }
  2706. else
  2707. {
  2708. bool im = (((insn_word >> 18) & 0x1) != 0);
  2709. au = (((insn_word >> 23) & 0x1) == 0) ? UNIT_A0 : UNIT_A1;
  2710. addr_reg_nums[0] = ((insn_word >> 19) & DSP_REG_MASK);
  2711. addr_reg_names[0] = lookup_reg_name (au, addr_reg_nums[0]);
  2712. if (im)
  2713. {
  2714. unsigned int im_value = ((insn_word >> 14) & 0x3);
  2715. switch (im_value)
  2716. {
  2717. case 0x1:
  2718. post_op = "++";
  2719. break;
  2720. case 0x3:
  2721. post_op = "--";
  2722. break;
  2723. }
  2724. }
  2725. else
  2726. {
  2727. addr_reg_nums[1] = ((insn_word >> 14) & DSP_REG_MASK);
  2728. addr_reg_names[1] = lookup_reg_name (au, addr_reg_nums[1]);
  2729. join_op = "+";
  2730. post_op = "++";
  2731. }
  2732. }
  2733. if (load)
  2734. {
  2735. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s %s,[%s%s%s%s]",
  2736. reg_names[0], reg_names[1], reg_names[2],
  2737. tname[0], addr_reg_names[0], join_op,
  2738. addr_reg_names[1], post_op);
  2739. }
  2740. else
  2741. {
  2742. snprintf (buf, OPERAND_WIDTH, "%s,%s,%s [%s%s%s%s],%s",
  2743. reg_names[0], reg_names[1], reg_names[2],
  2744. addr_reg_names[0], join_op, addr_reg_names[1],
  2745. post_op, tname[0]);
  2746. }
  2747. }
  2748. else
  2749. {
  2750. snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,%s%s%s",
  2751. reg_brackets[0] ? "[" : "",
  2752. reg_names[0], reg_brackets[0] ? "]" : "",
  2753. reg_brackets[1] ? "[" : "",
  2754. reg_names[1], reg_brackets[1] ? "]" : "",
  2755. reg_brackets[2] ? "[" : "",
  2756. reg_names[2], reg_brackets[2] ? "]" : "");
  2757. }
  2758. }
  2759. snprintf (prefix, DSP_PREFIX_WIDTH, "D%s%s%s%s%s%s%s",
  2760. cc_flags ? cc_flags : "",
  2761. is_dual ? "L" : "", clamp9 ? "G" : "",
  2762. clamp8 ? "B" : "", round ? "R" : "",
  2763. is_w_mx ? "W" : "",
  2764. is_template ? "T" : "");
  2765. }
  2766. print_insn (outf, prefix, template->name, buf);
  2767. }
  2768. typedef void (*insn_printer)(unsigned int, bfd_vma, const insn_template *,
  2769. disassemble_info *);
  2770. /* Printer table. */
  2771. static const insn_printer insn_printers[ENC_MAX] =
  2772. {
  2773. [ENC_NONE] = print_none,
  2774. [ENC_MOV_U2U] = print_mov_u2u,
  2775. [ENC_MOV_PORT] = print_mov_port,
  2776. [ENC_MMOV] = print_mmov,
  2777. [ENC_MDRD] = print_mdrd,
  2778. [ENC_MOVL_TTREC] = print_movl_ttrec,
  2779. [ENC_GET_SET] = print_get_set,
  2780. [ENC_GET_SET_EXT] = print_get_set_ext,
  2781. [ENC_MGET_MSET] = print_mget_mset,
  2782. [ENC_COND_SET] = print_cond_set,
  2783. [ENC_XFR] = print_xfr,
  2784. [ENC_MOV_CT] = print_mov_ct,
  2785. [ENC_SWAP] = print_swap,
  2786. [ENC_JUMP] = print_jump,
  2787. [ENC_CALLR] = print_callr,
  2788. [ENC_ALU] = print_alu,
  2789. [ENC_SHIFT] = print_shift,
  2790. [ENC_MIN_MAX] = print_min_max,
  2791. [ENC_BITOP] = print_bitop,
  2792. [ENC_CMP] = print_cmp,
  2793. [ENC_BRANCH] = print_branch,
  2794. [ENC_KICK] = print_mov_u2u,
  2795. [ENC_SWITCH] = print_switch,
  2796. [ENC_CACHER] = print_cacher,
  2797. [ENC_CACHEW] = print_cachew,
  2798. [ENC_ICACHE] = print_icache,
  2799. [ENC_LNKGET] = print_lnkget,
  2800. [ENC_FMOV] = print_fmov,
  2801. [ENC_FMMOV] = print_fmmov,
  2802. [ENC_FMOV_DATA] = print_fmov_data,
  2803. [ENC_FMOV_I] = print_fmov_i,
  2804. [ENC_FPACK] = print_fpack,
  2805. [ENC_FSWAP] = print_fswap,
  2806. [ENC_FCMP] = print_fcmp,
  2807. [ENC_FMINMAX] = print_fminmax,
  2808. [ENC_FCONV] = print_fconv,
  2809. [ENC_FCONVX] = print_fconvx,
  2810. [ENC_FBARITH] = print_fbarith,
  2811. [ENC_FEARITH] = print_fearith,
  2812. [ENC_FREC] = print_frec,
  2813. [ENC_FSIMD] = print_fsimd,
  2814. [ENC_FGET_SET_ACF] = print_fget_set_acf,
  2815. [ENC_DGET_SET] = print_dget_set,
  2816. [ENC_DTEMPLATE] = print_dtemplate,
  2817. [ENC_DALU] = print_dalu,
  2818. };
  2819. /* Entry point for instruction printing. */
  2820. int
  2821. print_insn_metag (bfd_vma pc, disassemble_info *outf)
  2822. {
  2823. bfd_byte buf[4];
  2824. unsigned int insn_word;
  2825. size_t i;
  2826. int status;
  2827. outf->bytes_per_chunk = 4;
  2828. status = (*outf->read_memory_func) (pc & ~0x03, buf, 4, outf);
  2829. if (status)
  2830. {
  2831. (*outf->memory_error_func) (status, pc, outf);
  2832. return -1;
  2833. }
  2834. insn_word = bfd_getl32 (buf);
  2835. for (i = 0; i < sizeof(metag_optab)/sizeof(metag_optab[0]); i++)
  2836. {
  2837. const insn_template *template = &metag_optab[i];
  2838. if ((insn_word & template->meta_mask) == template->meta_opcode)
  2839. {
  2840. enum insn_encoding encoding = template->encoding;
  2841. insn_printer printer = insn_printers[encoding];
  2842. if (printer)
  2843. printer (insn_word, pc, template, outf);
  2844. return 4;
  2845. }
  2846. }
  2847. return 4;
  2848. }