c67-gen.c 69 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541
  1. /*
  2. * TMS320C67xx code generator for TCC
  3. *
  4. * Copyright (c) 2001, 2002 Fabrice Bellard
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. */
  20. #ifdef TARGET_DEFS_ONLY
  21. /* #define ASSEMBLY_LISTING_C67 */
  22. /* number of available registers */
  23. #define NB_REGS 24
  24. /* a register can belong to several classes. The classes must be
  25. sorted from more general to more precise (see gv2() code which does
  26. assumptions on it). */
  27. #define RC_INT 0x0001 /* generic integer register */
  28. #define RC_FLOAT 0x0002 /* generic float register */
  29. #define RC_EAX 0x0004
  30. #define RC_ST0 0x0008
  31. #define RC_ECX 0x0010
  32. #define RC_EDX 0x0020
  33. #define RC_INT_BSIDE 0x00000040 /* generic integer register on b side */
  34. #define RC_C67_A4 0x00000100
  35. #define RC_C67_A5 0x00000200
  36. #define RC_C67_B4 0x00000400
  37. #define RC_C67_B5 0x00000800
  38. #define RC_C67_A6 0x00001000
  39. #define RC_C67_A7 0x00002000
  40. #define RC_C67_B6 0x00004000
  41. #define RC_C67_B7 0x00008000
  42. #define RC_C67_A8 0x00010000
  43. #define RC_C67_A9 0x00020000
  44. #define RC_C67_B8 0x00040000
  45. #define RC_C67_B9 0x00080000
  46. #define RC_C67_A10 0x00100000
  47. #define RC_C67_A11 0x00200000
  48. #define RC_C67_B10 0x00400000
  49. #define RC_C67_B11 0x00800000
  50. #define RC_C67_A12 0x01000000
  51. #define RC_C67_A13 0x02000000
  52. #define RC_C67_B12 0x04000000
  53. #define RC_C67_B13 0x08000000
  54. #define RC_IRET RC_C67_A4 /* function return: integer register */
  55. #define RC_LRET RC_C67_A5 /* function return: second integer register */
  56. #define RC_FRET RC_C67_A4 /* function return: float register */
  57. /* pretty names for the registers */
  58. enum {
  59. TREG_EAX = 0, // really A2
  60. TREG_ECX, // really A3
  61. TREG_EDX, // really B0
  62. TREG_ST0, // really B1
  63. TREG_C67_A4,
  64. TREG_C67_A5,
  65. TREG_C67_B4,
  66. TREG_C67_B5,
  67. TREG_C67_A6,
  68. TREG_C67_A7,
  69. TREG_C67_B6,
  70. TREG_C67_B7,
  71. TREG_C67_A8,
  72. TREG_C67_A9,
  73. TREG_C67_B8,
  74. TREG_C67_B9,
  75. TREG_C67_A10,
  76. TREG_C67_A11,
  77. TREG_C67_B10,
  78. TREG_C67_B11,
  79. TREG_C67_A12,
  80. TREG_C67_A13,
  81. TREG_C67_B12,
  82. TREG_C67_B13,
  83. };
  84. /* return registers for function */
  85. #define REG_IRET TREG_C67_A4 /* single word int return register */
  86. #define REG_LRET TREG_C67_A5 /* second word return register (for long long) */
  87. #define REG_FRET TREG_C67_A4 /* float return register */
  88. /* defined if function parameters must be evaluated in reverse order */
  89. /* #define INVERT_FUNC_PARAMS */
  90. /* defined if structures are passed as pointers. Otherwise structures
  91. are directly pushed on stack. */
  92. /* #define FUNC_STRUCT_PARAM_AS_PTR */
  93. /* pointer size, in bytes */
  94. #define PTR_SIZE 4
  95. /* long double size and alignment, in bytes */
  96. #define LDOUBLE_SIZE 12
  97. #define LDOUBLE_ALIGN 4
  98. /* maximum alignment (for aligned attribute support) */
  99. #define MAX_ALIGN 8
  100. /******************************************************/
  101. #else /* ! TARGET_DEFS_ONLY */
  102. /******************************************************/
  103. #include "tcc.h"
  104. ST_DATA const int reg_classes[NB_REGS] = {
  105. /* eax */ RC_INT | RC_FLOAT | RC_EAX,
  106. // only allow even regs for floats (allow for doubles)
  107. /* ecx */ RC_INT | RC_ECX,
  108. /* edx */ RC_INT | RC_INT_BSIDE | RC_FLOAT | RC_EDX,
  109. // only allow even regs for floats (allow for doubles)
  110. /* st0 */ RC_INT | RC_INT_BSIDE | RC_ST0,
  111. /* A4 */ RC_C67_A4,
  112. /* A5 */ RC_C67_A5,
  113. /* B4 */ RC_C67_B4,
  114. /* B5 */ RC_C67_B5,
  115. /* A6 */ RC_C67_A6,
  116. /* A7 */ RC_C67_A7,
  117. /* B6 */ RC_C67_B6,
  118. /* B7 */ RC_C67_B7,
  119. /* A8 */ RC_C67_A8,
  120. /* A9 */ RC_C67_A9,
  121. /* B8 */ RC_C67_B8,
  122. /* B9 */ RC_C67_B9,
  123. /* A10 */ RC_C67_A10,
  124. /* A11 */ RC_C67_A11,
  125. /* B10 */ RC_C67_B10,
  126. /* B11 */ RC_C67_B11,
  127. /* A12 */ RC_C67_A10,
  128. /* A13 */ RC_C67_A11,
  129. /* B12 */ RC_C67_B10,
  130. /* B13 */ RC_C67_B11
  131. };
  132. // although tcc thinks it is passing parameters on the stack,
  133. // the C67 really passes up to the first 10 params in special
  134. // regs or regs pairs (for 64 bit params). So keep track of
  135. // the stack offsets so we can translate to the appropriate
  136. // reg (pair)
  137. #define NoCallArgsPassedOnStack 10
  138. int NoOfCurFuncArgs;
  139. int TranslateStackToReg[NoCallArgsPassedOnStack];
  140. int ParamLocOnStack[NoCallArgsPassedOnStack];
  141. int TotalBytesPushedOnStack;
  142. #ifndef FALSE
  143. # define FALSE 0
  144. # define TRUE 1
  145. #endif
  146. #undef BOOL
  147. #define BOOL int
  148. #define ALWAYS_ASSERT(x) \
  149. do {\
  150. if (!(x))\
  151. tcc_error("internal compiler error file at %s:%d", __FILE__, __LINE__);\
  152. } while (0)
  153. /******************************************************/
  154. static unsigned long func_sub_sp_offset;
  155. static int func_ret_sub;
  156. static BOOL C67_invert_test;
  157. static int C67_compare_reg;
  158. #ifdef ASSEMBLY_LISTING_C67
  159. FILE *f = NULL;
  160. #endif
  161. void C67_g(int c)
  162. {
  163. int ind1;
  164. if (nocode_wanted)
  165. return;
  166. #ifdef ASSEMBLY_LISTING_C67
  167. fprintf(f, " %08X", c);
  168. #endif
  169. ind1 = ind + 4;
  170. if (ind1 > (int) cur_text_section->data_allocated)
  171. section_realloc(cur_text_section, ind1);
  172. cur_text_section->data[ind] = c & 0xff;
  173. cur_text_section->data[ind + 1] = (c >> 8) & 0xff;
  174. cur_text_section->data[ind + 2] = (c >> 16) & 0xff;
  175. cur_text_section->data[ind + 3] = (c >> 24) & 0xff;
  176. ind = ind1;
  177. }
  178. /* output a symbol and patch all calls to it */
  179. void gsym_addr(int t, int a)
  180. {
  181. int n, *ptr;
  182. while (t) {
  183. ptr = (int *) (cur_text_section->data + t);
  184. {
  185. Sym *sym;
  186. // extract 32 bit address from MVKH/MVKL
  187. n = ((*ptr >> 7) & 0xffff);
  188. n |= ((*(ptr + 1) >> 7) & 0xffff) << 16;
  189. // define a label that will be relocated
  190. sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
  191. greloc(cur_text_section, sym, t, R_C60LO16);
  192. greloc(cur_text_section, sym, t + 4, R_C60HI16);
  193. // clear out where the pointer was
  194. *ptr &= ~(0xffff << 7);
  195. *(ptr + 1) &= ~(0xffff << 7);
  196. }
  197. t = n;
  198. }
  199. }
  200. void gsym(int t)
  201. {
  202. gsym_addr(t, ind);
  203. }
  204. // these are regs that tcc doesn't really know about,
  205. // but assign them unique values so the mapping routines
  206. // can distinguish them
  207. #define C67_A0 105
  208. #define C67_SP 106
  209. #define C67_B3 107
  210. #define C67_FP 108
  211. #define C67_B2 109
  212. #define C67_CREG_ZERO -1 /* Special code for no condition reg test */
  213. int ConvertRegToRegClass(int r)
  214. {
  215. // only works for A4-B13
  216. return RC_C67_A4 << (r - TREG_C67_A4);
  217. }
  218. // map TCC reg to C67 reg number
  219. int C67_map_regn(int r)
  220. {
  221. if (r == 0) // normal tcc regs
  222. return 0x2; // A2
  223. else if (r == 1) // normal tcc regs
  224. return 3; // A3
  225. else if (r == 2) // normal tcc regs
  226. return 0; // B0
  227. else if (r == 3) // normal tcc regs
  228. return 1; // B1
  229. else if (r >= TREG_C67_A4 && r <= TREG_C67_B13) // these form a pattern of alt pairs
  230. return (((r & 0xfffffffc) >> 1) | (r & 1)) + 2;
  231. else if (r == C67_A0)
  232. return 0; // set to A0 (offset reg)
  233. else if (r == C67_B2)
  234. return 2; // set to B2 (offset reg)
  235. else if (r == C67_B3)
  236. return 3; // set to B3 (return address reg)
  237. else if (r == C67_SP)
  238. return 15; // set to SP (B15) (offset reg)
  239. else if (r == C67_FP)
  240. return 15; // set to FP (A15) (offset reg)
  241. else if (r == C67_CREG_ZERO)
  242. return 0; // Special code for no condition reg test
  243. else
  244. ALWAYS_ASSERT(FALSE);
  245. return 0;
  246. }
  247. // mapping from tcc reg number to
  248. // C67 register to condition code field
  249. //
  250. // valid condition code regs are:
  251. //
  252. // tcc reg 2 ->B0 -> 1
  253. // tcc reg 3 ->B1 -> 2
  254. // tcc reg 0 -> A2 -> 5
  255. // tcc reg 1 -> A3 -> X
  256. // tcc reg B2 -> 3
  257. int C67_map_regc(int r)
  258. {
  259. if (r == 0) // normal tcc regs
  260. return 0x5;
  261. else if (r == 2) // normal tcc regs
  262. return 0x1;
  263. else if (r == 3) // normal tcc regs
  264. return 0x2;
  265. else if (r == C67_B2) // normal tcc regs
  266. return 0x3;
  267. else if (r == C67_CREG_ZERO)
  268. return 0; // Special code for no condition reg test
  269. else
  270. ALWAYS_ASSERT(FALSE);
  271. return 0;
  272. }
  273. // map TCC reg to C67 reg side A or B
  274. int C67_map_regs(int r)
  275. {
  276. if (r == 0) // normal tcc regs
  277. return 0x0;
  278. else if (r == 1) // normal tcc regs
  279. return 0x0;
  280. else if (r == 2) // normal tcc regs
  281. return 0x1;
  282. else if (r == 3) // normal tcc regs
  283. return 0x1;
  284. else if (r >= TREG_C67_A4 && r <= TREG_C67_B13) // these form a pattern of alt pairs
  285. return (r & 2) >> 1;
  286. else if (r == C67_A0)
  287. return 0; // set to A side
  288. else if (r == C67_B2)
  289. return 1; // set to B side
  290. else if (r == C67_B3)
  291. return 1; // set to B side
  292. else if (r == C67_SP)
  293. return 0x1; // set to SP (B15) B side
  294. else if (r == C67_FP)
  295. return 0x0; // set to FP (A15) A side
  296. else
  297. ALWAYS_ASSERT(FALSE);
  298. return 0;
  299. }
  300. int C67_map_S12(char *s)
  301. {
  302. if (strstr(s, ".S1") != NULL)
  303. return 0;
  304. else if (strcmp(s, ".S2"))
  305. return 1;
  306. else
  307. ALWAYS_ASSERT(FALSE);
  308. return 0;
  309. }
  310. int C67_map_D12(char *s)
  311. {
  312. if (strstr(s, ".D1") != NULL)
  313. return 0;
  314. else if (strcmp(s, ".D2"))
  315. return 1;
  316. else
  317. ALWAYS_ASSERT(FALSE);
  318. return 0;
  319. }
  320. void C67_asm(char *s, int a, int b, int c)
  321. {
  322. BOOL xpath;
  323. #ifdef ASSEMBLY_LISTING_C67
  324. if (!f) {
  325. f = fopen("TCC67_out.txt", "wt");
  326. }
  327. fprintf(f, "%04X ", ind);
  328. #endif
  329. if (strstr(s, "MVKL") == s) {
  330. C67_g((C67_map_regn(b) << 23) |
  331. ((a & 0xffff) << 7) | (0x0a << 2) | (C67_map_regs(b) << 1));
  332. } else if (strstr(s, "MVKH") == s) {
  333. C67_g((C67_map_regn(b) << 23) |
  334. (((a >> 16) & 0xffff) << 7) |
  335. (0x1a << 2) | (C67_map_regs(b) << 1));
  336. } else if (strstr(s, "STW.D SP POST DEC") == s) {
  337. C67_g((C67_map_regn(a) << 23) | //src
  338. (15 << 18) | //SP B15
  339. (2 << 13) | //ucst5 (must keep 8 byte boundary !!)
  340. (0xa << 9) | //mode a = post dec ucst
  341. (0 << 8) | //r (LDDW bit 0)
  342. (1 << 7) | //y D1/D2 use B side
  343. (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  344. (1 << 2) | //opcode
  345. (C67_map_regs(a) << 1) | //side of src
  346. (0 << 0)); //parallel
  347. } else if (strstr(s, "STB.D *+SP[A0]") == s) {
  348. C67_g((C67_map_regn(a) << 23) | //src
  349. (15 << 18) | //base reg A15
  350. (0 << 13) | //offset reg A0
  351. (5 << 9) | //mode 5 = pos offset, base reg + off reg
  352. (0 << 8) | //r (LDDW bit 0)
  353. (0 << 7) | //y D1/D2 A side
  354. (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  355. (1 << 2) | //opcode
  356. (C67_map_regs(a) << 1) | //side of src
  357. (0 << 0)); //parallel
  358. } else if (strstr(s, "STH.D *+SP[A0]") == s) {
  359. C67_g((C67_map_regn(a) << 23) | //src
  360. (15 << 18) | //base reg A15
  361. (0 << 13) | //offset reg A0
  362. (5 << 9) | //mode 5 = pos offset, base reg + off reg
  363. (0 << 8) | //r (LDDW bit 0)
  364. (0 << 7) | //y D1/D2 A side
  365. (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  366. (1 << 2) | //opcode
  367. (C67_map_regs(a) << 1) | //side of src
  368. (0 << 0)); //parallel
  369. } else if (strstr(s, "STB.D *+SP[A0]") == s) {
  370. C67_g((C67_map_regn(a) << 23) | //src
  371. (15 << 18) | //base reg A15
  372. (0 << 13) | //offset reg A0
  373. (5 << 9) | //mode 5 = pos offset, base reg + off reg
  374. (0 << 8) | //r (LDDW bit 0)
  375. (0 << 7) | //y D1/D2 A side
  376. (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  377. (1 << 2) | //opcode
  378. (C67_map_regs(a) << 1) | //side of src
  379. (0 << 0)); //parallel
  380. } else if (strstr(s, "STH.D *+SP[A0]") == s) {
  381. C67_g((C67_map_regn(a) << 23) | //src
  382. (15 << 18) | //base reg A15
  383. (0 << 13) | //offset reg A0
  384. (5 << 9) | //mode 5 = pos offset, base reg + off reg
  385. (0 << 8) | //r (LDDW bit 0)
  386. (0 << 7) | //y D1/D2 A side
  387. (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  388. (1 << 2) | //opcode
  389. (C67_map_regs(a) << 1) | //side of src
  390. (0 << 0)); //parallel
  391. } else if (strstr(s, "STW.D *+SP[A0]") == s) {
  392. C67_g((C67_map_regn(a) << 23) | //src
  393. (15 << 18) | //base reg A15
  394. (0 << 13) | //offset reg A0
  395. (5 << 9) | //mode 5 = pos offset, base reg + off reg
  396. (0 << 8) | //r (LDDW bit 0)
  397. (0 << 7) | //y D1/D2 A side
  398. (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  399. (1 << 2) | //opcode
  400. (C67_map_regs(a) << 1) | //side of src
  401. (0 << 0)); //parallel
  402. } else if (strstr(s, "STW.D *") == s) {
  403. C67_g((C67_map_regn(a) << 23) | //src
  404. (C67_map_regn(b) << 18) | //base reg A0
  405. (0 << 13) | //cst5
  406. (1 << 9) | //mode 1 = pos cst offset
  407. (0 << 8) | //r (LDDW bit 0)
  408. (C67_map_regs(b) << 7) | //y D1/D2 base reg side
  409. (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  410. (1 << 2) | //opcode
  411. (C67_map_regs(a) << 1) | //side of src
  412. (0 << 0)); //parallel
  413. } else if (strstr(s, "STH.D *") == s) {
  414. C67_g((C67_map_regn(a) << 23) | //src
  415. (C67_map_regn(b) << 18) | //base reg A0
  416. (0 << 13) | //cst5
  417. (1 << 9) | //mode 1 = pos cst offset
  418. (0 << 8) | //r (LDDW bit 0)
  419. (C67_map_regs(b) << 7) | //y D1/D2 base reg side
  420. (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  421. (1 << 2) | //opcode
  422. (C67_map_regs(a) << 1) | //side of src
  423. (0 << 0)); //parallel
  424. } else if (strstr(s, "STB.D *") == s) {
  425. C67_g((C67_map_regn(a) << 23) | //src
  426. (C67_map_regn(b) << 18) | //base reg A0
  427. (0 << 13) | //cst5
  428. (1 << 9) | //mode 1 = pos cst offset
  429. (0 << 8) | //r (LDDW bit 0)
  430. (C67_map_regs(b) << 7) | //y D1/D2 base reg side
  431. (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  432. (1 << 2) | //opcode
  433. (C67_map_regs(a) << 1) | //side of src
  434. (0 << 0)); //parallel
  435. } else if (strstr(s, "STW.D +*") == s) {
  436. ALWAYS_ASSERT(c < 32);
  437. C67_g((C67_map_regn(a) << 23) | //src
  438. (C67_map_regn(b) << 18) | //base reg A0
  439. (c << 13) | //cst5
  440. (1 << 9) | //mode 1 = pos cst offset
  441. (0 << 8) | //r (LDDW bit 0)
  442. (C67_map_regs(b) << 7) | //y D1/D2 base reg side
  443. (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  444. (1 << 2) | //opcode
  445. (C67_map_regs(a) << 1) | //side of src
  446. (0 << 0)); //parallel
  447. } else if (strstr(s, "LDW.D SP PRE INC") == s) {
  448. C67_g((C67_map_regn(a) << 23) | //dst
  449. (15 << 18) | //base reg B15
  450. (2 << 13) | //ucst5 (must keep 8 byte boundary)
  451. (9 << 9) | //mode 9 = pre inc ucst5
  452. (0 << 8) | //r (LDDW bit 0)
  453. (1 << 7) | //y D1/D2 B side
  454. (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  455. (1 << 2) | //opcode
  456. (C67_map_regs(a) << 1) | //side of dst
  457. (0 << 0)); //parallel
  458. } else if (strstr(s, "LDDW.D SP PRE INC") == s) {
  459. C67_g((C67_map_regn(a) << 23) | //dst
  460. (15 << 18) | //base reg B15
  461. (1 << 13) | //ucst5 (must keep 8 byte boundary)
  462. (9 << 9) | //mode 9 = pre inc ucst5
  463. (1 << 8) | //r (LDDW bit 1)
  464. (1 << 7) | //y D1/D2 B side
  465. (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  466. (1 << 2) | //opcode
  467. (C67_map_regs(a) << 1) | //side of dst
  468. (0 << 0)); //parallel
  469. } else if (strstr(s, "LDW.D *+SP[A0]") == s) {
  470. C67_g((C67_map_regn(a) << 23) | //dst
  471. (15 << 18) | //base reg A15
  472. (0 << 13) | //offset reg A0
  473. (5 << 9) | //mode 5 = pos offset, base reg + off reg
  474. (0 << 8) | //r (LDDW bit 0)
  475. (0 << 7) | //y D1/D2 A side
  476. (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  477. (1 << 2) | //opcode
  478. (C67_map_regs(a) << 1) | //side of dst
  479. (0 << 0)); //parallel
  480. } else if (strstr(s, "LDDW.D *+SP[A0]") == s) {
  481. C67_g((C67_map_regn(a) << 23) | //dst
  482. (15 << 18) | //base reg A15
  483. (0 << 13) | //offset reg A0
  484. (5 << 9) | //mode 5 = pos offset, base reg + off reg
  485. (1 << 8) | //r (LDDW bit 1)
  486. (0 << 7) | //y D1/D2 A side
  487. (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  488. (1 << 2) | //opcode
  489. (C67_map_regs(a) << 1) | //side of dst
  490. (0 << 0)); //parallel
  491. } else if (strstr(s, "LDH.D *+SP[A0]") == s) {
  492. C67_g((C67_map_regn(a) << 23) | //dst
  493. (15 << 18) | //base reg A15
  494. (0 << 13) | //offset reg A0
  495. (5 << 9) | //mode 5 = pos offset, base reg + off reg
  496. (0 << 8) | //r (LDDW bit 0)
  497. (0 << 7) | //y D1/D2 A side
  498. (4 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  499. (1 << 2) | //opcode
  500. (C67_map_regs(a) << 1) | //side of dst
  501. (0 << 0)); //parallel
  502. } else if (strstr(s, "LDB.D *+SP[A0]") == s) {
  503. C67_g((C67_map_regn(a) << 23) | //dst
  504. (15 << 18) | //base reg A15
  505. (0 << 13) | //offset reg A0
  506. (5 << 9) | //mode 5 = pos offset, base reg + off reg
  507. (0 << 8) | //r (LDDW bit 0)
  508. (0 << 7) | //y D1/D2 A side
  509. (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  510. (1 << 2) | //opcode
  511. (C67_map_regs(a) << 1) | //side of dst
  512. (0 << 0)); //parallel
  513. } else if (strstr(s, "LDHU.D *+SP[A0]") == s) {
  514. C67_g((C67_map_regn(a) << 23) | //dst
  515. (15 << 18) | //base reg A15
  516. (0 << 13) | //offset reg A0
  517. (5 << 9) | //mode 5 = pos offset, base reg + off reg
  518. (0 << 8) | //r (LDDW bit 0)
  519. (0 << 7) | //y D1/D2 A side
  520. (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  521. (1 << 2) | //opcode
  522. (C67_map_regs(a) << 1) | //side of dst
  523. (0 << 0)); //parallel
  524. } else if (strstr(s, "LDBU.D *+SP[A0]") == s) {
  525. C67_g((C67_map_regn(a) << 23) | //dst
  526. (15 << 18) | //base reg A15
  527. (0 << 13) | //offset reg A0
  528. (5 << 9) | //mode 5 = pos offset, base reg + off reg
  529. (0 << 8) | //r (LDDW bit 0)
  530. (0 << 7) | //y D1/D2 A side
  531. (1 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  532. (1 << 2) | //opcode
  533. (C67_map_regs(a) << 1) | //side of dst
  534. (0 << 0)); //parallel
  535. } else if (strstr(s, "LDW.D *") == s) {
  536. C67_g((C67_map_regn(b) << 23) | //dst
  537. (C67_map_regn(a) << 18) | //base reg A15
  538. (0 << 13) | //cst5
  539. (1 << 9) | //mode 1 = pos cst offset
  540. (0 << 8) | //r (LDDW bit 0)
  541. (C67_map_regs(a) << 7) | //y D1/D2 src side
  542. (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  543. (1 << 2) | //opcode
  544. (C67_map_regs(b) << 1) | //side of dst
  545. (0 << 0)); //parallel
  546. } else if (strstr(s, "LDDW.D *") == s) {
  547. C67_g((C67_map_regn(b) << 23) | //dst
  548. (C67_map_regn(a) << 18) | //base reg A15
  549. (0 << 13) | //cst5
  550. (1 << 9) | //mode 1 = pos cst offset
  551. (1 << 8) | //r (LDDW bit 1)
  552. (C67_map_regs(a) << 7) | //y D1/D2 src side
  553. (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  554. (1 << 2) | //opcode
  555. (C67_map_regs(b) << 1) | //side of dst
  556. (0 << 0)); //parallel
  557. } else if (strstr(s, "LDH.D *") == s) {
  558. C67_g((C67_map_regn(b) << 23) | //dst
  559. (C67_map_regn(a) << 18) | //base reg A15
  560. (0 << 13) | //cst5
  561. (1 << 9) | //mode 1 = pos cst offset
  562. (0 << 8) | //r (LDDW bit 0)
  563. (C67_map_regs(a) << 7) | //y D1/D2 src side
  564. (4 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  565. (1 << 2) | //opcode
  566. (C67_map_regs(b) << 1) | //side of dst
  567. (0 << 0)); //parallel
  568. } else if (strstr(s, "LDB.D *") == s) {
  569. C67_g((C67_map_regn(b) << 23) | //dst
  570. (C67_map_regn(a) << 18) | //base reg A15
  571. (0 << 13) | //cst5
  572. (1 << 9) | //mode 1 = pos cst offset
  573. (0 << 8) | //r (LDDW bit 0)
  574. (C67_map_regs(a) << 7) | //y D1/D2 src side
  575. (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  576. (1 << 2) | //opcode
  577. (C67_map_regs(b) << 1) | //side of dst
  578. (0 << 0)); //parallel
  579. } else if (strstr(s, "LDHU.D *") == s) {
  580. C67_g((C67_map_regn(b) << 23) | //dst
  581. (C67_map_regn(a) << 18) | //base reg A15
  582. (0 << 13) | //cst5
  583. (1 << 9) | //mode 1 = pos cst offset
  584. (0 << 8) | //r (LDDW bit 0)
  585. (C67_map_regs(a) << 7) | //y D1/D2 src side
  586. (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  587. (1 << 2) | //opcode
  588. (C67_map_regs(b) << 1) | //side of dst
  589. (0 << 0)); //parallel
  590. } else if (strstr(s, "LDBU.D *") == s) {
  591. C67_g((C67_map_regn(b) << 23) | //dst
  592. (C67_map_regn(a) << 18) | //base reg A15
  593. (0 << 13) | //cst5
  594. (1 << 9) | //mode 1 = pos cst offset
  595. (0 << 8) | //r (LDDW bit 0)
  596. (C67_map_regs(a) << 7) | //y D1/D2 src side
  597. (1 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  598. (1 << 2) | //opcode
  599. (C67_map_regs(b) << 1) | //side of dst
  600. (0 << 0)); //parallel
  601. } else if (strstr(s, "LDW.D +*") == s) {
  602. C67_g((C67_map_regn(b) << 23) | //dst
  603. (C67_map_regn(a) << 18) | //base reg A15
  604. (1 << 13) | //cst5
  605. (1 << 9) | //mode 1 = pos cst offset
  606. (0 << 8) | //r (LDDW bit 0)
  607. (C67_map_regs(a) << 7) | //y D1/D2 src side
  608. (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  609. (1 << 2) | //opcode
  610. (C67_map_regs(b) << 1) | //side of dst
  611. (0 << 0)); //parallel
  612. } else if (strstr(s, "CMPLTSP") == s) {
  613. xpath = C67_map_regs(a) ^ C67_map_regs(b);
  614. ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  615. C67_g((C67_map_regn(c) << 23) | //dst
  616. (C67_map_regn(b) << 18) | //src2
  617. (C67_map_regn(a) << 13) | //src1
  618. (xpath << 12) | //x use cross path for src2
  619. (0x3a << 6) | //opcode
  620. (0x8 << 2) | //opcode fixed
  621. (C67_map_regs(c) << 1) | //side for reg c
  622. (0 << 0)); //parallel
  623. } else if (strstr(s, "CMPGTSP") == s) {
  624. xpath = C67_map_regs(a) ^ C67_map_regs(b);
  625. ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  626. C67_g((C67_map_regn(c) << 23) | //dst
  627. (C67_map_regn(b) << 18) | //src2
  628. (C67_map_regn(a) << 13) | //src1
  629. (xpath << 12) | //x use cross path for src2
  630. (0x39 << 6) | //opcode
  631. (0x8 << 2) | //opcode fixed
  632. (C67_map_regs(c) << 1) | //side for reg c
  633. (0 << 0)); //parallel
  634. } else if (strstr(s, "CMPEQSP") == s) {
  635. xpath = C67_map_regs(a) ^ C67_map_regs(b);
  636. ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  637. C67_g((C67_map_regn(c) << 23) | //dst
  638. (C67_map_regn(b) << 18) | //src2
  639. (C67_map_regn(a) << 13) | //src1
  640. (xpath << 12) | //x use cross path for src2
  641. (0x38 << 6) | //opcode
  642. (0x8 << 2) | //opcode fixed
  643. (C67_map_regs(c) << 1) | //side for reg c
  644. (0 << 0)); //parallel
  645. }
  646. else if (strstr(s, "CMPLTDP") == s) {
  647. xpath = C67_map_regs(a) ^ C67_map_regs(b);
  648. ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  649. C67_g((C67_map_regn(c) << 23) | //dst
  650. (C67_map_regn(b) << 18) | //src2
  651. (C67_map_regn(a) << 13) | //src1
  652. (xpath << 12) | //x use cross path for src2
  653. (0x2a << 6) | //opcode
  654. (0x8 << 2) | //opcode fixed
  655. (C67_map_regs(c) << 1) | //side for reg c
  656. (0 << 0)); //parallel
  657. } else if (strstr(s, "CMPGTDP") == s) {
  658. xpath = C67_map_regs(a) ^ C67_map_regs(b);
  659. ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  660. C67_g((C67_map_regn(c) << 23) | //dst
  661. (C67_map_regn(b) << 18) | //src2
  662. (C67_map_regn(a) << 13) | //src1
  663. (xpath << 12) | //x use cross path for src2
  664. (0x29 << 6) | //opcode
  665. (0x8 << 2) | //opcode fixed
  666. (C67_map_regs(c) << 1) | //side for reg c
  667. (0 << 0)); //parallel
  668. } else if (strstr(s, "CMPEQDP") == s) {
  669. xpath = C67_map_regs(a) ^ C67_map_regs(b);
  670. ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  671. C67_g((C67_map_regn(c) << 23) | //dst
  672. (C67_map_regn(b) << 18) | //src2
  673. (C67_map_regn(a) << 13) | //src1
  674. (xpath << 12) | //x use cross path for src2
  675. (0x28 << 6) | //opcode
  676. (0x8 << 2) | //opcode fixed
  677. (C67_map_regs(c) << 1) | //side for reg c
  678. (0 << 0)); //parallel
  679. } else if (strstr(s, "CMPLT") == s) {
  680. xpath = C67_map_regs(a) ^ C67_map_regs(b);
  681. ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  682. C67_g((C67_map_regn(c) << 23) | //dst
  683. (C67_map_regn(b) << 18) | //src2
  684. (C67_map_regn(a) << 13) | //src1
  685. (xpath << 12) | //x use cross path for src2
  686. (0x57 << 5) | //opcode
  687. (0x6 << 2) | //opcode fixed
  688. (C67_map_regs(c) << 1) | //side for reg c
  689. (0 << 0)); //parallel
  690. } else if (strstr(s, "CMPGT") == s) {
  691. xpath = C67_map_regs(a) ^ C67_map_regs(b);
  692. ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  693. C67_g((C67_map_regn(c) << 23) | //dst
  694. (C67_map_regn(b) << 18) | //src2
  695. (C67_map_regn(a) << 13) | //src1
  696. (xpath << 12) | //x use cross path for src2
  697. (0x47 << 5) | //opcode
  698. (0x6 << 2) | //opcode fixed
  699. (C67_map_regs(c) << 1) | //side for reg c
  700. (0 << 0)); //parallel
  701. } else if (strstr(s, "CMPEQ") == s) {
  702. xpath = C67_map_regs(a) ^ C67_map_regs(b);
  703. ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  704. C67_g((C67_map_regn(c) << 23) | //dst
  705. (C67_map_regn(b) << 18) | //src2
  706. (C67_map_regn(a) << 13) | //src1
  707. (xpath << 12) | //x use cross path for src2
  708. (0x53 << 5) | //opcode
  709. (0x6 << 2) | //opcode fixed
  710. (C67_map_regs(c) << 1) | //side for reg c
  711. (0 << 0)); //parallel
  712. } else if (strstr(s, "CMPLTU") == s) {
  713. xpath = C67_map_regs(a) ^ C67_map_regs(b);
  714. ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  715. C67_g((C67_map_regn(c) << 23) | //dst
  716. (C67_map_regn(b) << 18) | //src2
  717. (C67_map_regn(a) << 13) | //src1
  718. (xpath << 12) | //x use cross path for src2
  719. (0x5f << 5) | //opcode
  720. (0x6 << 2) | //opcode fixed
  721. (C67_map_regs(c) << 1) | //side for reg c
  722. (0 << 0)); //parallel
  723. } else if (strstr(s, "CMPGTU") == s) {
  724. xpath = C67_map_regs(a) ^ C67_map_regs(b);
  725. ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  726. C67_g((C67_map_regn(c) << 23) | //dst
  727. (C67_map_regn(b) << 18) | //src2
  728. (C67_map_regn(a) << 13) | //src1
  729. (xpath << 12) | //x use cross path for src2
  730. (0x4f << 5) | //opcode
  731. (0x6 << 2) | //opcode fixed
  732. (C67_map_regs(c) << 1) | //side for reg c
  733. (0 << 0)); //parallel
  734. } else if (strstr(s, "B DISP") == s) {
  735. C67_g((0 << 29) | //creg
  736. (0 << 28) | //z
  737. (a << 7) | //cnst
  738. (0x4 << 2) | //opcode fixed
  739. (0 << 1) | //S0/S1
  740. (0 << 0)); //parallel
  741. } else if (strstr(s, "B.") == s) {
  742. xpath = C67_map_regs(c) ^ 1;
  743. C67_g((C67_map_regc(b) << 29) | //creg
  744. (a << 28) | //inv
  745. (0 << 23) | //dst
  746. (C67_map_regn(c) << 18) | //src2
  747. (0 << 13) | //
  748. (xpath << 12) | //x cross path if !B side
  749. (0xd << 6) | //opcode
  750. (0x8 << 2) | //opcode fixed
  751. (1 << 1) | //must be S2
  752. (0 << 0)); //parallel
  753. } else if (strstr(s, "MV.L") == s) {
  754. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  755. C67_g((0 << 29) | //creg
  756. (0 << 28) | //inv
  757. (C67_map_regn(c) << 23) | //dst
  758. (C67_map_regn(b) << 18) | //src2
  759. (0 << 13) | //src1 (cst5)
  760. (xpath << 12) | //x cross path if opposite sides
  761. (0x2 << 5) | //opcode
  762. (0x6 << 2) | //opcode fixed
  763. (C67_map_regs(c) << 1) | //side of dest
  764. (0 << 0)); //parallel
  765. } else if (strstr(s, "SPTRUNC.L") == s) {
  766. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  767. C67_g((0 << 29) | //creg
  768. (0 << 28) | //inv
  769. (C67_map_regn(c) << 23) | //dst
  770. (C67_map_regn(b) << 18) | //src2
  771. (0 << 13) | //src1 NA
  772. (xpath << 12) | //x cross path if opposite sides
  773. (0xb << 5) | //opcode
  774. (0x6 << 2) | //opcode fixed
  775. (C67_map_regs(c) << 1) | //side of dest
  776. (0 << 0)); //parallel
  777. } else if (strstr(s, "DPTRUNC.L") == s) {
  778. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  779. C67_g((0 << 29) | //creg
  780. (0 << 28) | //inv
  781. (C67_map_regn(c) << 23) | //dst
  782. ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
  783. (0 << 13) | //src1 NA
  784. (xpath << 12) | //x cross path if opposite sides
  785. (0x1 << 5) | //opcode
  786. (0x6 << 2) | //opcode fixed
  787. (C67_map_regs(c) << 1) | //side of dest
  788. (0 << 0)); //parallel
  789. } else if (strstr(s, "INTSP.L") == s) {
  790. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  791. C67_g((0 << 29) | //creg
  792. (0 << 28) | //inv
  793. (C67_map_regn(c) << 23) | //dst
  794. (C67_map_regn(b) << 18) | //src2
  795. (0 << 13) | //src1 NA
  796. (xpath << 12) | //x cross path if opposite sides
  797. (0x4a << 5) | //opcode
  798. (0x6 << 2) | //opcode fixed
  799. (C67_map_regs(c) << 1) | //side of dest
  800. (0 << 0)); //parallel
  801. } else if (strstr(s, "INTSPU.L") == s) {
  802. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  803. C67_g((0 << 29) | //creg
  804. (0 << 28) | //inv
  805. (C67_map_regn(c) << 23) | //dst
  806. (C67_map_regn(b) << 18) | //src2
  807. (0 << 13) | //src1 NA
  808. (xpath << 12) | //x cross path if opposite sides
  809. (0x49 << 5) | //opcode
  810. (0x6 << 2) | //opcode fixed
  811. (C67_map_regs(c) << 1) | //side of dest
  812. (0 << 0)); //parallel
  813. } else if (strstr(s, "INTDP.L") == s) {
  814. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  815. C67_g((0 << 29) | //creg
  816. (0 << 28) | //inv
  817. (C67_map_regn(c) << 23) | //dst
  818. (C67_map_regn(b) << 18) | //src2
  819. (0 << 13) | //src1 NA
  820. (xpath << 12) | //x cross path if opposite sides
  821. (0x39 << 5) | //opcode
  822. (0x6 << 2) | //opcode fixed
  823. (C67_map_regs(c) << 1) | //side of dest
  824. (0 << 0)); //parallel
  825. } else if (strstr(s, "INTDPU.L") == s) {
  826. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  827. C67_g((0 << 29) | //creg
  828. (0 << 28) | //inv
  829. (C67_map_regn(c) << 23) | //dst
  830. ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
  831. (0 << 13) | //src1 NA
  832. (xpath << 12) | //x cross path if opposite sides
  833. (0x3b << 5) | //opcode
  834. (0x6 << 2) | //opcode fixed
  835. (C67_map_regs(c) << 1) | //side of dest
  836. (0 << 0)); //parallel
  837. } else if (strstr(s, "SPDP.L") == s) {
  838. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  839. C67_g((0 << 29) | //creg
  840. (0 << 28) | //inv
  841. (C67_map_regn(c) << 23) | //dst
  842. (C67_map_regn(b) << 18) | //src2
  843. (0 << 13) | //src1 NA
  844. (xpath << 12) | //x cross path if opposite sides
  845. (0x2 << 6) | //opcode
  846. (0x8 << 2) | //opcode fixed
  847. (C67_map_regs(c) << 1) | //side of dest
  848. (0 << 0)); //parallel
  849. } else if (strstr(s, "DPSP.L") == s) {
  850. ALWAYS_ASSERT(C67_map_regs(b) == C67_map_regs(c));
  851. C67_g((0 << 29) | //creg
  852. (0 << 28) | //inv
  853. (C67_map_regn(c) << 23) | //dst
  854. ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
  855. (0 << 13) | //src1 NA
  856. (0 << 12) | //x cross path if opposite sides
  857. (0x9 << 5) | //opcode
  858. (0x6 << 2) | //opcode fixed
  859. (C67_map_regs(c) << 1) | //side of dest
  860. (0 << 0)); //parallel
  861. } else if (strstr(s, "ADD.L") == s) {
  862. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  863. ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  864. C67_g((0 << 29) | //creg
  865. (0 << 28) | //inv
  866. (C67_map_regn(c) << 23) | //dst
  867. (C67_map_regn(b) << 18) | //src2 (possible x path)
  868. (C67_map_regn(a) << 13) | //src1
  869. (xpath << 12) | //x cross path if opposite sides
  870. (0x3 << 5) | //opcode
  871. (0x6 << 2) | //opcode fixed
  872. (C67_map_regs(c) << 1) | //side of dest
  873. (0 << 0)); //parallel
  874. } else if (strstr(s, "SUB.L") == s) {
  875. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  876. ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  877. C67_g((0 << 29) | //creg
  878. (0 << 28) | //inv
  879. (C67_map_regn(c) << 23) | //dst
  880. (C67_map_regn(b) << 18) | //src2 (possible x path)
  881. (C67_map_regn(a) << 13) | //src1
  882. (xpath << 12) | //x cross path if opposite sides
  883. (0x7 << 5) | //opcode
  884. (0x6 << 2) | //opcode fixed
  885. (C67_map_regs(c) << 1) | //side of dest
  886. (0 << 0)); //parallel
  887. } else if (strstr(s, "OR.L") == s) {
  888. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  889. ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  890. C67_g((0 << 29) | //creg
  891. (0 << 28) | //inv
  892. (C67_map_regn(c) << 23) | //dst
  893. (C67_map_regn(b) << 18) | //src2 (possible x path)
  894. (C67_map_regn(a) << 13) | //src1
  895. (xpath << 12) | //x cross path if opposite sides
  896. (0x7f << 5) | //opcode
  897. (0x6 << 2) | //opcode fixed
  898. (C67_map_regs(c) << 1) | //side of dest
  899. (0 << 0)); //parallel
  900. } else if (strstr(s, "AND.L") == s) {
  901. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  902. ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  903. C67_g((0 << 29) | //creg
  904. (0 << 28) | //inv
  905. (C67_map_regn(c) << 23) | //dst
  906. (C67_map_regn(b) << 18) | //src2 (possible x path)
  907. (C67_map_regn(a) << 13) | //src1
  908. (xpath << 12) | //x cross path if opposite sides
  909. (0x7b << 5) | //opcode
  910. (0x6 << 2) | //opcode fixed
  911. (C67_map_regs(c) << 1) | //side of dest
  912. (0 << 0)); //parallel
  913. } else if (strstr(s, "XOR.L") == s) {
  914. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  915. ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  916. C67_g((0 << 29) | //creg
  917. (0 << 28) | //inv
  918. (C67_map_regn(c) << 23) | //dst
  919. (C67_map_regn(b) << 18) | //src2 (possible x path)
  920. (C67_map_regn(a) << 13) | //src1
  921. (xpath << 12) | //x cross path if opposite sides
  922. (0x6f << 5) | //opcode
  923. (0x6 << 2) | //opcode fixed
  924. (C67_map_regs(c) << 1) | //side of dest
  925. (0 << 0)); //parallel
  926. } else if (strstr(s, "ADDSP.L") == s) {
  927. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  928. ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  929. C67_g((0 << 29) | //creg
  930. (0 << 28) | //inv
  931. (C67_map_regn(c) << 23) | //dst
  932. (C67_map_regn(b) << 18) | //src2 (possible x path)
  933. (C67_map_regn(a) << 13) | //src1
  934. (xpath << 12) | //x cross path if opposite sides
  935. (0x10 << 5) | //opcode
  936. (0x6 << 2) | //opcode fixed
  937. (C67_map_regs(c) << 1) | //side of dest
  938. (0 << 0)); //parallel
  939. } else if (strstr(s, "ADDDP.L") == s) {
  940. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  941. ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  942. C67_g((0 << 29) | //creg
  943. (0 << 28) | //inv
  944. (C67_map_regn(c) << 23) | //dst
  945. (C67_map_regn(b) << 18) | //src2 (possible x path)
  946. (C67_map_regn(a) << 13) | //src1
  947. (xpath << 12) | //x cross path if opposite sides
  948. (0x18 << 5) | //opcode
  949. (0x6 << 2) | //opcode fixed
  950. (C67_map_regs(c) << 1) | //side of dest
  951. (0 << 0)); //parallel
  952. } else if (strstr(s, "SUBSP.L") == s) {
  953. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  954. ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  955. C67_g((0 << 29) | //creg
  956. (0 << 28) | //inv
  957. (C67_map_regn(c) << 23) | //dst
  958. (C67_map_regn(b) << 18) | //src2 (possible x path)
  959. (C67_map_regn(a) << 13) | //src1
  960. (xpath << 12) | //x cross path if opposite sides
  961. (0x11 << 5) | //opcode
  962. (0x6 << 2) | //opcode fixed
  963. (C67_map_regs(c) << 1) | //side of dest
  964. (0 << 0)); //parallel
  965. } else if (strstr(s, "SUBDP.L") == s) {
  966. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  967. ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  968. C67_g((0 << 29) | //creg
  969. (0 << 28) | //inv
  970. (C67_map_regn(c) << 23) | //dst
  971. (C67_map_regn(b) << 18) | //src2 (possible x path)
  972. (C67_map_regn(a) << 13) | //src1
  973. (xpath << 12) | //x cross path if opposite sides
  974. (0x19 << 5) | //opcode
  975. (0x6 << 2) | //opcode fixed
  976. (C67_map_regs(c) << 1) | //side of dest
  977. (0 << 0)); //parallel
  978. } else if (strstr(s, "MPYSP.M") == s) {
  979. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  980. ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  981. C67_g((0 << 29) | //creg
  982. (0 << 28) | //inv
  983. (C67_map_regn(c) << 23) | //dst
  984. (C67_map_regn(b) << 18) | //src2 (possible x path)
  985. (C67_map_regn(a) << 13) | //src1
  986. (xpath << 12) | //x cross path if opposite sides
  987. (0x1c << 7) | //opcode
  988. (0x0 << 2) | //opcode fixed
  989. (C67_map_regs(c) << 1) | //side of dest
  990. (0 << 0)); //parallel
  991. } else if (strstr(s, "MPYDP.M") == s) {
  992. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  993. ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  994. C67_g((0 << 29) | //creg
  995. (0 << 28) | //inv
  996. (C67_map_regn(c) << 23) | //dst
  997. (C67_map_regn(b) << 18) | //src2 (possible x path)
  998. (C67_map_regn(a) << 13) | //src1
  999. (xpath << 12) | //x cross path if opposite sides
  1000. (0x0e << 7) | //opcode
  1001. (0x0 << 2) | //opcode fixed
  1002. (C67_map_regs(c) << 1) | //side of dest
  1003. (0 << 0)); //parallel
  1004. } else if (strstr(s, "MPYI.M") == s) {
  1005. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  1006. ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  1007. C67_g((0 << 29) | //creg
  1008. (0 << 28) | //inv
  1009. (C67_map_regn(c) << 23) | //dst
  1010. (C67_map_regn(b) << 18) | //src2
  1011. (C67_map_regn(a) << 13) | //src1 (cst5)
  1012. (xpath << 12) | //x cross path if opposite sides
  1013. (0x4 << 7) | //opcode
  1014. (0x0 << 2) | //opcode fixed
  1015. (C67_map_regs(c) << 1) | //side of dest
  1016. (0 << 0)); //parallel
  1017. } else if (strstr(s, "SHR.S") == s) {
  1018. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  1019. ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  1020. C67_g((0 << 29) | //creg
  1021. (0 << 28) | //inv
  1022. (C67_map_regn(c) << 23) | //dst
  1023. (C67_map_regn(b) << 18) | //src2
  1024. (C67_map_regn(a) << 13) | //src1
  1025. (xpath << 12) | //x cross path if opposite sides
  1026. (0x37 << 6) | //opcode
  1027. (0x8 << 2) | //opcode fixed
  1028. (C67_map_regs(c) << 1) | //side of dest
  1029. (0 << 0)); //parallel
  1030. } else if (strstr(s, "SHRU.S") == s) {
  1031. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  1032. ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  1033. C67_g((0 << 29) | //creg
  1034. (0 << 28) | //inv
  1035. (C67_map_regn(c) << 23) | //dst
  1036. (C67_map_regn(b) << 18) | //src2
  1037. (C67_map_regn(a) << 13) | //src1
  1038. (xpath << 12) | //x cross path if opposite sides
  1039. (0x27 << 6) | //opcode
  1040. (0x8 << 2) | //opcode fixed
  1041. (C67_map_regs(c) << 1) | //side of dest
  1042. (0 << 0)); //parallel
  1043. } else if (strstr(s, "SHL.S") == s) {
  1044. xpath = C67_map_regs(b) ^ C67_map_regs(c);
  1045. ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  1046. C67_g((0 << 29) | //creg
  1047. (0 << 28) | //inv
  1048. (C67_map_regn(c) << 23) | //dst
  1049. (C67_map_regn(b) << 18) | //src2
  1050. (C67_map_regn(a) << 13) | //src1
  1051. (xpath << 12) | //x cross path if opposite sides
  1052. (0x33 << 6) | //opcode
  1053. (0x8 << 2) | //opcode fixed
  1054. (C67_map_regs(c) << 1) | //side of dest
  1055. (0 << 0)); //parallel
  1056. } else if (strstr(s, "||ADDK") == s) {
  1057. xpath = 0; // no xpath required just use the side of the src/dst
  1058. C67_g((0 << 29) | //creg
  1059. (0 << 28) | //inv
  1060. (C67_map_regn(b) << 23) | //dst
  1061. (a << 07) | //scst16
  1062. (0x14 << 2) | //opcode fixed
  1063. (C67_map_regs(b) << 1) | //side of dst
  1064. (1 << 0)); //parallel
  1065. } else if (strstr(s, "ADDK") == s) {
  1066. xpath = 0; // no xpath required just use the side of the src/dst
  1067. C67_g((0 << 29) | //creg
  1068. (0 << 28) | //inv
  1069. (C67_map_regn(b) << 23) | //dst
  1070. (a << 07) | //scst16
  1071. (0x14 << 2) | //opcode fixed
  1072. (C67_map_regs(b) << 1) | //side of dst
  1073. (0 << 0)); //parallel
  1074. } else if (strstr(s, "NOP") == s) {
  1075. C67_g(((a - 1) << 13) | //no of cycles
  1076. (0 << 0)); //parallel
  1077. } else
  1078. ALWAYS_ASSERT(FALSE);
  1079. #ifdef ASSEMBLY_LISTING_C67
  1080. fprintf(f, " %s %d %d %d\n", s, a, b, c);
  1081. #endif
  1082. }
  1083. //r=reg to load, fr=from reg, symbol for relocation, constant
  1084. void C67_MVKL(int r, int fc)
  1085. {
  1086. C67_asm("MVKL.", fc, r, 0);
  1087. }
  1088. void C67_MVKH(int r, int fc)
  1089. {
  1090. C67_asm("MVKH.", fc, r, 0);
  1091. }
  1092. void C67_STB_SP_A0(int r)
  1093. {
  1094. C67_asm("STB.D *+SP[A0]", r, 0, 0); // STB r,*+SP[A0]
  1095. }
  1096. void C67_STH_SP_A0(int r)
  1097. {
  1098. C67_asm("STH.D *+SP[A0]", r, 0, 0); // STH r,*+SP[A0]
  1099. }
  1100. void C67_STW_SP_A0(int r)
  1101. {
  1102. C67_asm("STW.D *+SP[A0]", r, 0, 0); // STW r,*+SP[A0]
  1103. }
  1104. void C67_STB_PTR(int r, int r2)
  1105. {
  1106. C67_asm("STB.D *", r, r2, 0); // STB r, *r2
  1107. }
  1108. void C67_STH_PTR(int r, int r2)
  1109. {
  1110. C67_asm("STH.D *", r, r2, 0); // STH r, *r2
  1111. }
  1112. void C67_STW_PTR(int r, int r2)
  1113. {
  1114. C67_asm("STW.D *", r, r2, 0); // STW r, *r2
  1115. }
  1116. void C67_STW_PTR_PRE_INC(int r, int r2, int n)
  1117. {
  1118. C67_asm("STW.D +*", r, r2, n); // STW r, *+r2
  1119. }
  1120. void C67_PUSH(int r)
  1121. {
  1122. C67_asm("STW.D SP POST DEC", r, 0, 0); // STW r,*SP--
  1123. }
  1124. void C67_LDW_SP_A0(int r)
  1125. {
  1126. C67_asm("LDW.D *+SP[A0]", r, 0, 0); // LDW *+SP[A0],r
  1127. }
  1128. void C67_LDDW_SP_A0(int r)
  1129. {
  1130. C67_asm("LDDW.D *+SP[A0]", r, 0, 0); // LDDW *+SP[A0],r
  1131. }
  1132. void C67_LDH_SP_A0(int r)
  1133. {
  1134. C67_asm("LDH.D *+SP[A0]", r, 0, 0); // LDH *+SP[A0],r
  1135. }
  1136. void C67_LDB_SP_A0(int r)
  1137. {
  1138. C67_asm("LDB.D *+SP[A0]", r, 0, 0); // LDB *+SP[A0],r
  1139. }
  1140. void C67_LDHU_SP_A0(int r)
  1141. {
  1142. C67_asm("LDHU.D *+SP[A0]", r, 0, 0); // LDHU *+SP[A0],r
  1143. }
  1144. void C67_LDBU_SP_A0(int r)
  1145. {
  1146. C67_asm("LDBU.D *+SP[A0]", r, 0, 0); // LDBU *+SP[A0],r
  1147. }
  1148. void C67_LDW_PTR(int r, int r2)
  1149. {
  1150. C67_asm("LDW.D *", r, r2, 0); // LDW *r,r2
  1151. }
  1152. void C67_LDDW_PTR(int r, int r2)
  1153. {
  1154. C67_asm("LDDW.D *", r, r2, 0); // LDDW *r,r2
  1155. }
  1156. void C67_LDH_PTR(int r, int r2)
  1157. {
  1158. C67_asm("LDH.D *", r, r2, 0); // LDH *r,r2
  1159. }
  1160. void C67_LDB_PTR(int r, int r2)
  1161. {
  1162. C67_asm("LDB.D *", r, r2, 0); // LDB *r,r2
  1163. }
  1164. void C67_LDHU_PTR(int r, int r2)
  1165. {
  1166. C67_asm("LDHU.D *", r, r2, 0); // LDHU *r,r2
  1167. }
  1168. void C67_LDBU_PTR(int r, int r2)
  1169. {
  1170. C67_asm("LDBU.D *", r, r2, 0); // LDBU *r,r2
  1171. }
  1172. void C67_LDW_PTR_PRE_INC(int r, int r2)
  1173. {
  1174. C67_asm("LDW.D +*", r, r2, 0); // LDW *+r,r2
  1175. }
  1176. void C67_POP(int r)
  1177. {
  1178. C67_asm("LDW.D SP PRE INC", r, 0, 0); // LDW *++SP,r
  1179. }
  1180. void C67_POP_DW(int r)
  1181. {
  1182. C67_asm("LDDW.D SP PRE INC", r, 0, 0); // LDDW *++SP,r
  1183. }
  1184. void C67_CMPLT(int s1, int s2, int dst)
  1185. {
  1186. C67_asm("CMPLT.L1", s1, s2, dst);
  1187. }
  1188. void C67_CMPGT(int s1, int s2, int dst)
  1189. {
  1190. C67_asm("CMPGT.L1", s1, s2, dst);
  1191. }
  1192. void C67_CMPEQ(int s1, int s2, int dst)
  1193. {
  1194. C67_asm("CMPEQ.L1", s1, s2, dst);
  1195. }
  1196. void C67_CMPLTU(int s1, int s2, int dst)
  1197. {
  1198. C67_asm("CMPLTU.L1", s1, s2, dst);
  1199. }
  1200. void C67_CMPGTU(int s1, int s2, int dst)
  1201. {
  1202. C67_asm("CMPGTU.L1", s1, s2, dst);
  1203. }
  1204. void C67_CMPLTSP(int s1, int s2, int dst)
  1205. {
  1206. C67_asm("CMPLTSP.S1", s1, s2, dst);
  1207. }
  1208. void C67_CMPGTSP(int s1, int s2, int dst)
  1209. {
  1210. C67_asm("CMPGTSP.S1", s1, s2, dst);
  1211. }
  1212. void C67_CMPEQSP(int s1, int s2, int dst)
  1213. {
  1214. C67_asm("CMPEQSP.S1", s1, s2, dst);
  1215. }
  1216. void C67_CMPLTDP(int s1, int s2, int dst)
  1217. {
  1218. C67_asm("CMPLTDP.S1", s1, s2, dst);
  1219. }
  1220. void C67_CMPGTDP(int s1, int s2, int dst)
  1221. {
  1222. C67_asm("CMPGTDP.S1", s1, s2, dst);
  1223. }
  1224. void C67_CMPEQDP(int s1, int s2, int dst)
  1225. {
  1226. C67_asm("CMPEQDP.S1", s1, s2, dst);
  1227. }
  1228. void C67_IREG_B_REG(int inv, int r1, int r2) // [!R] B r2
  1229. {
  1230. C67_asm("B.S2", inv, r1, r2);
  1231. }
  1232. // call with how many 32 bit words to skip
  1233. // (0 would branch to the branch instruction)
  1234. void C67_B_DISP(int disp) // B +2 Branch with constant displacement
  1235. {
  1236. // Branch point is relative to the 8 word fetch packet
  1237. //
  1238. // we will assume the text section always starts on an 8 word (32 byte boundary)
  1239. //
  1240. // so add in how many words into the fetch packet the branch is
  1241. C67_asm("B DISP", disp + ((ind & 31) >> 2), 0, 0);
  1242. }
  1243. void C67_NOP(int n)
  1244. {
  1245. C67_asm("NOP", n, 0, 0);
  1246. }
  1247. void C67_ADDK(int n, int r)
  1248. {
  1249. ALWAYS_ASSERT(abs(n) < 32767);
  1250. C67_asm("ADDK", n, r, 0);
  1251. }
  1252. void C67_ADDK_PARALLEL(int n, int r)
  1253. {
  1254. ALWAYS_ASSERT(abs(n) < 32767);
  1255. C67_asm("||ADDK", n, r, 0);
  1256. }
  1257. void C67_Adjust_ADDK(int *inst, int n)
  1258. {
  1259. ALWAYS_ASSERT(abs(n) < 32767);
  1260. *inst = (*inst & (~(0xffff << 7))) | ((n & 0xffff) << 7);
  1261. }
  1262. void C67_MV(int r, int v)
  1263. {
  1264. C67_asm("MV.L", 0, r, v);
  1265. }
  1266. void C67_DPTRUNC(int r, int v)
  1267. {
  1268. C67_asm("DPTRUNC.L", 0, r, v);
  1269. }
  1270. void C67_SPTRUNC(int r, int v)
  1271. {
  1272. C67_asm("SPTRUNC.L", 0, r, v);
  1273. }
  1274. void C67_INTSP(int r, int v)
  1275. {
  1276. C67_asm("INTSP.L", 0, r, v);
  1277. }
  1278. void C67_INTDP(int r, int v)
  1279. {
  1280. C67_asm("INTDP.L", 0, r, v);
  1281. }
  1282. void C67_INTSPU(int r, int v)
  1283. {
  1284. C67_asm("INTSPU.L", 0, r, v);
  1285. }
  1286. void C67_INTDPU(int r, int v)
  1287. {
  1288. C67_asm("INTDPU.L", 0, r, v);
  1289. }
  1290. void C67_SPDP(int r, int v)
  1291. {
  1292. C67_asm("SPDP.L", 0, r, v);
  1293. }
  1294. void C67_DPSP(int r, int v) // note regs must be on the same side
  1295. {
  1296. C67_asm("DPSP.L", 0, r, v);
  1297. }
  1298. void C67_ADD(int r, int v)
  1299. {
  1300. C67_asm("ADD.L", v, r, v);
  1301. }
  1302. void C67_SUB(int r, int v)
  1303. {
  1304. C67_asm("SUB.L", v, r, v);
  1305. }
  1306. void C67_AND(int r, int v)
  1307. {
  1308. C67_asm("AND.L", v, r, v);
  1309. }
  1310. void C67_OR(int r, int v)
  1311. {
  1312. C67_asm("OR.L", v, r, v);
  1313. }
  1314. void C67_XOR(int r, int v)
  1315. {
  1316. C67_asm("XOR.L", v, r, v);
  1317. }
  1318. void C67_ADDSP(int r, int v)
  1319. {
  1320. C67_asm("ADDSP.L", v, r, v);
  1321. }
  1322. void C67_SUBSP(int r, int v)
  1323. {
  1324. C67_asm("SUBSP.L", v, r, v);
  1325. }
  1326. void C67_MPYSP(int r, int v)
  1327. {
  1328. C67_asm("MPYSP.M", v, r, v);
  1329. }
  1330. void C67_ADDDP(int r, int v)
  1331. {
  1332. C67_asm("ADDDP.L", v, r, v);
  1333. }
  1334. void C67_SUBDP(int r, int v)
  1335. {
  1336. C67_asm("SUBDP.L", v, r, v);
  1337. }
  1338. void C67_MPYDP(int r, int v)
  1339. {
  1340. C67_asm("MPYDP.M", v, r, v);
  1341. }
  1342. void C67_MPYI(int r, int v)
  1343. {
  1344. C67_asm("MPYI.M", v, r, v);
  1345. }
  1346. void C67_SHL(int r, int v)
  1347. {
  1348. C67_asm("SHL.S", r, v, v);
  1349. }
  1350. void C67_SHRU(int r, int v)
  1351. {
  1352. C67_asm("SHRU.S", r, v, v);
  1353. }
  1354. void C67_SHR(int r, int v)
  1355. {
  1356. C67_asm("SHR.S", r, v, v);
  1357. }
  1358. /* load 'r' from value 'sv' */
  1359. void load(int r, SValue * sv)
  1360. {
  1361. int v, t, ft, fc, fr, size = 0, element;
  1362. BOOL Unsigned = FALSE;
  1363. SValue v1;
  1364. fr = sv->r;
  1365. ft = sv->type.t;
  1366. fc = sv->c.i;
  1367. v = fr & VT_VALMASK;
  1368. if (fr & VT_LVAL) {
  1369. if (v == VT_LLOCAL) {
  1370. v1.type.t = VT_INT;
  1371. v1.r = VT_LOCAL | VT_LVAL;
  1372. v1.c.i = fc;
  1373. load(r, &v1);
  1374. fr = r;
  1375. } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
  1376. tcc_error("long double not supported");
  1377. } else if ((ft & VT_TYPE) == VT_BYTE) {
  1378. size = 1;
  1379. } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
  1380. size = 1;
  1381. Unsigned = TRUE;
  1382. } else if ((ft & VT_TYPE) == VT_SHORT) {
  1383. size = 2;
  1384. } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
  1385. size = 2;
  1386. Unsigned = TRUE;
  1387. } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
  1388. size = 8;
  1389. } else {
  1390. size = 4;
  1391. }
  1392. // check if fc is a positive reference on the stack,
  1393. // if it is tcc is referencing what it thinks is a parameter
  1394. // on the stack, so check if it is really in a register.
  1395. if (v == VT_LOCAL && fc > 0) {
  1396. int stack_pos = 8;
  1397. for (t = 0; t < NoCallArgsPassedOnStack; t++) {
  1398. if (fc == stack_pos)
  1399. break;
  1400. stack_pos += TranslateStackToReg[t];
  1401. }
  1402. // param has been pushed on stack, get it like a local var
  1403. fc = ParamLocOnStack[t] - 8;
  1404. }
  1405. if ((fr & VT_VALMASK) < VT_CONST) // check for pure indirect
  1406. {
  1407. if (size == 1) {
  1408. if (Unsigned)
  1409. C67_LDBU_PTR(v, r); // LDBU *v,r
  1410. else
  1411. C67_LDB_PTR(v, r); // LDB *v,r
  1412. } else if (size == 2) {
  1413. if (Unsigned)
  1414. C67_LDHU_PTR(v, r); // LDHU *v,r
  1415. else
  1416. C67_LDH_PTR(v, r); // LDH *v,r
  1417. } else if (size == 4) {
  1418. C67_LDW_PTR(v, r); // LDW *v,r
  1419. } else if (size == 8) {
  1420. C67_LDDW_PTR(v, r); // LDDW *v,r
  1421. }
  1422. C67_NOP(4); // NOP 4
  1423. return;
  1424. } else if (fr & VT_SYM) {
  1425. greloc(cur_text_section, sv->sym, ind, R_C60LO16); // rem the inst need to be patched
  1426. greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
  1427. C67_MVKL(C67_A0, fc); //r=reg to load, constant
  1428. C67_MVKH(C67_A0, fc); //r=reg to load, constant
  1429. if (size == 1) {
  1430. if (Unsigned)
  1431. C67_LDBU_PTR(C67_A0, r); // LDBU *A0,r
  1432. else
  1433. C67_LDB_PTR(C67_A0, r); // LDB *A0,r
  1434. } else if (size == 2) {
  1435. if (Unsigned)
  1436. C67_LDHU_PTR(C67_A0, r); // LDHU *A0,r
  1437. else
  1438. C67_LDH_PTR(C67_A0, r); // LDH *A0,r
  1439. } else if (size == 4) {
  1440. C67_LDW_PTR(C67_A0, r); // LDW *A0,r
  1441. } else if (size == 8) {
  1442. C67_LDDW_PTR(C67_A0, r); // LDDW *A0,r
  1443. }
  1444. C67_NOP(4); // NOP 4
  1445. return;
  1446. } else {
  1447. element = size;
  1448. // divide offset in bytes to create element index
  1449. C67_MVKL(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
  1450. C67_MVKH(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
  1451. if (size == 1) {
  1452. if (Unsigned)
  1453. C67_LDBU_SP_A0(r); // LDBU r, SP[A0]
  1454. else
  1455. C67_LDB_SP_A0(r); // LDB r, SP[A0]
  1456. } else if (size == 2) {
  1457. if (Unsigned)
  1458. C67_LDHU_SP_A0(r); // LDHU r, SP[A0]
  1459. else
  1460. C67_LDH_SP_A0(r); // LDH r, SP[A0]
  1461. } else if (size == 4) {
  1462. C67_LDW_SP_A0(r); // LDW r, SP[A0]
  1463. } else if (size == 8) {
  1464. C67_LDDW_SP_A0(r); // LDDW r, SP[A0]
  1465. }
  1466. C67_NOP(4); // NOP 4
  1467. return;
  1468. }
  1469. } else {
  1470. if (v == VT_CONST) {
  1471. if (fr & VT_SYM) {
  1472. greloc(cur_text_section, sv->sym, ind, R_C60LO16); // rem the inst need to be patched
  1473. greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
  1474. }
  1475. C67_MVKL(r, fc); //r=reg to load, constant
  1476. C67_MVKH(r, fc); //r=reg to load, constant
  1477. } else if (v == VT_LOCAL) {
  1478. C67_MVKL(r, fc + 8); //r=reg to load, constant C67 stack points to next free
  1479. C67_MVKH(r, fc + 8); //r=reg to load, constant
  1480. C67_ADD(C67_FP, r); // MV v,r v -> r
  1481. } else if (v == VT_CMP) {
  1482. C67_MV(C67_compare_reg, r); // MV v,r v -> r
  1483. } else if (v == VT_JMP || v == VT_JMPI) {
  1484. t = v & 1;
  1485. C67_B_DISP(4); // Branch with constant displacement, skip over this branch, load, nop, load
  1486. C67_MVKL(r, t); // r=reg to load, 0 or 1 (do this while branching)
  1487. C67_NOP(4); // NOP 4
  1488. gsym(fc); // modifies other branches to branch here
  1489. C67_MVKL(r, t ^ 1); // r=reg to load, 0 or 1
  1490. } else if (v != r) {
  1491. C67_MV(v, r); // MV v,r v -> r
  1492. if ((ft & VT_BTYPE) == VT_DOUBLE)
  1493. C67_MV(v + 1, r + 1); // MV v,r v -> r
  1494. }
  1495. }
  1496. }
  1497. /* store register 'r' in lvalue 'v' */
  1498. void store(int r, SValue * v)
  1499. {
  1500. int fr, bt, ft, fc, size, t, element;
  1501. ft = v->type.t;
  1502. fc = v->c.i;
  1503. fr = v->r & VT_VALMASK;
  1504. bt = ft & VT_BTYPE;
  1505. /* XXX: incorrect if float reg to reg */
  1506. if (bt == VT_LDOUBLE) {
  1507. tcc_error("long double not supported");
  1508. } else {
  1509. if (bt == VT_SHORT)
  1510. size = 2;
  1511. else if (bt == VT_BYTE)
  1512. size = 1;
  1513. else if (bt == VT_DOUBLE)
  1514. size = 8;
  1515. else
  1516. size = 4;
  1517. if ((v->r & VT_VALMASK) == VT_CONST) {
  1518. /* constant memory reference */
  1519. if (v->r & VT_SYM) {
  1520. greloc(cur_text_section, v->sym, ind, R_C60LO16); // rem the inst need to be patched
  1521. greloc(cur_text_section, v->sym, ind + 4, R_C60HI16);
  1522. }
  1523. C67_MVKL(C67_A0, fc); //r=reg to load, constant
  1524. C67_MVKH(C67_A0, fc); //r=reg to load, constant
  1525. if (size == 1)
  1526. C67_STB_PTR(r, C67_A0); // STB r, *A0
  1527. else if (size == 2)
  1528. C67_STH_PTR(r, C67_A0); // STH r, *A0
  1529. else if (size == 4 || size == 8)
  1530. C67_STW_PTR(r, C67_A0); // STW r, *A0
  1531. if (size == 8)
  1532. C67_STW_PTR_PRE_INC(r + 1, C67_A0, 1); // STW r, *+A0[1]
  1533. } else if ((v->r & VT_VALMASK) == VT_LOCAL) {
  1534. // check case of storing to passed argument that
  1535. // tcc thinks is on the stack but for C67 is
  1536. // passed as a reg. However it may have been
  1537. // saved to the stack, if that reg was required
  1538. // for a call to a child function
  1539. if (fc > 0) // argument ??
  1540. {
  1541. // walk through sizes and figure which param
  1542. int stack_pos = 8;
  1543. for (t = 0; t < NoCallArgsPassedOnStack; t++) {
  1544. if (fc == stack_pos)
  1545. break;
  1546. stack_pos += TranslateStackToReg[t];
  1547. }
  1548. // param has been pushed on stack, get it like a local var
  1549. fc = ParamLocOnStack[t] - 8;
  1550. }
  1551. if (size == 8)
  1552. element = 4;
  1553. else
  1554. element = size;
  1555. // divide offset in bytes to create word index
  1556. C67_MVKL(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
  1557. C67_MVKH(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
  1558. if (size == 1)
  1559. C67_STB_SP_A0(r); // STB r, SP[A0]
  1560. else if (size == 2)
  1561. C67_STH_SP_A0(r); // STH r, SP[A0]
  1562. else if (size == 4 || size == 8)
  1563. C67_STW_SP_A0(r); // STW r, SP[A0]
  1564. if (size == 8) {
  1565. C67_ADDK(1, C67_A0); // ADDK 1,A0
  1566. C67_STW_SP_A0(r + 1); // STW r, SP[A0]
  1567. }
  1568. } else {
  1569. if (size == 1)
  1570. C67_STB_PTR(r, fr); // STB r, *fr
  1571. else if (size == 2)
  1572. C67_STH_PTR(r, fr); // STH r, *fr
  1573. else if (size == 4 || size == 8)
  1574. C67_STW_PTR(r, fr); // STW r, *fr
  1575. if (size == 8) {
  1576. C67_STW_PTR_PRE_INC(r + 1, fr, 1); // STW r, *+fr[1]
  1577. }
  1578. }
  1579. }
  1580. }
  1581. /* 'is_jmp' is '1' if it is a jump */
  1582. static void gcall_or_jmp(int is_jmp)
  1583. {
  1584. int r;
  1585. Sym *sym;
  1586. if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
  1587. /* constant case */
  1588. if (vtop->r & VT_SYM) {
  1589. /* relocation case */
  1590. // get add into A0, then start the jump B3
  1591. greloc(cur_text_section, vtop->sym, ind, R_C60LO16); // rem the inst need to be patched
  1592. greloc(cur_text_section, vtop->sym, ind + 4, R_C60HI16);
  1593. C67_MVKL(C67_A0, 0); //r=reg to load, constant
  1594. C67_MVKH(C67_A0, 0); //r=reg to load, constant
  1595. C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0); // B.S2x A0
  1596. if (is_jmp) {
  1597. C67_NOP(5); // simple jump, just put NOP
  1598. } else {
  1599. // Call, must load return address into B3 during delay slots
  1600. sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0); // symbol for return address
  1601. greloc(cur_text_section, sym, ind, R_C60LO16); // rem the inst need to be patched
  1602. greloc(cur_text_section, sym, ind + 4, R_C60HI16);
  1603. C67_MVKL(C67_B3, 0); //r=reg to load, constant
  1604. C67_MVKH(C67_B3, 0); //r=reg to load, constant
  1605. C67_NOP(3); // put remaining NOPs
  1606. }
  1607. } else {
  1608. /* put an empty PC32 relocation */
  1609. ALWAYS_ASSERT(FALSE);
  1610. }
  1611. } else {
  1612. /* otherwise, indirect call */
  1613. r = gv(RC_INT);
  1614. C67_IREG_B_REG(0, C67_CREG_ZERO, r); // B.S2x r
  1615. if (is_jmp) {
  1616. C67_NOP(5); // simple jump, just put NOP
  1617. } else {
  1618. // Call, must load return address into B3 during delay slots
  1619. sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0); // symbol for return address
  1620. greloc(cur_text_section, sym, ind, R_C60LO16); // rem the inst need to be patched
  1621. greloc(cur_text_section, sym, ind + 4, R_C60HI16);
  1622. C67_MVKL(C67_B3, 0); //r=reg to load, constant
  1623. C67_MVKH(C67_B3, 0); //r=reg to load, constant
  1624. C67_NOP(3); // put remaining NOPs
  1625. }
  1626. }
  1627. }
  1628. /* Return the number of registers needed to return the struct, or 0 if
  1629. returning via struct pointer. */
  1630. ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) {
  1631. *ret_align = 1; // Never have to re-align return values for x86-64
  1632. return 0;
  1633. }
  1634. /* generate function call with address in (vtop->t, vtop->c) and free function
  1635. context. Stack entry is popped */
  1636. void gfunc_call(int nb_args)
  1637. {
  1638. int i, r, size = 0;
  1639. int args_sizes[NoCallArgsPassedOnStack];
  1640. if (nb_args > NoCallArgsPassedOnStack) {
  1641. tcc_error("more than 10 function params not currently supported");
  1642. // handle more than 10, put some on the stack
  1643. }
  1644. for (i = 0; i < nb_args; i++) {
  1645. if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
  1646. ALWAYS_ASSERT(FALSE);
  1647. } else {
  1648. /* simple type (currently always same size) */
  1649. /* XXX: implicit cast ? */
  1650. if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
  1651. tcc_error("long long not supported");
  1652. } else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
  1653. tcc_error("long double not supported");
  1654. } else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
  1655. size = 8;
  1656. } else {
  1657. size = 4;
  1658. }
  1659. // put the parameter into the corresponding reg (pair)
  1660. r = gv(RC_C67_A4 << (2 * i));
  1661. // must put on stack because with 1 pass compiler , no way to tell
  1662. // if an up coming nested call might overwrite these regs
  1663. C67_PUSH(r);
  1664. if (size == 8) {
  1665. C67_STW_PTR_PRE_INC(r + 1, C67_SP, 3); // STW r, *+SP[3] (go back and put the other)
  1666. }
  1667. args_sizes[i] = size;
  1668. }
  1669. vtop--;
  1670. }
  1671. // POP all the params on the stack into registers for the
  1672. // immediate call (in reverse order)
  1673. for (i = nb_args - 1; i >= 0; i--) {
  1674. if (args_sizes[i] == 8)
  1675. C67_POP_DW(TREG_C67_A4 + i * 2);
  1676. else
  1677. C67_POP(TREG_C67_A4 + i * 2);
  1678. }
  1679. gcall_or_jmp(0);
  1680. vtop--;
  1681. }
  1682. // to be compatible with Code Composer for the C67
  1683. // the first 10 parameters must be passed in registers
  1684. // (pairs for 64 bits) starting wit; A4:A5, then B4:B5 and
  1685. // ending with B12:B13.
  1686. //
  1687. // When a call is made, if the caller has its parameters
  1688. // in regs A4-B13 these must be saved before/as the call
  1689. // parameters are loaded and restored upon return (or if/when needed).
  1690. /* generate function prolog of type 't' */
  1691. void gfunc_prolog(CType * func_type)
  1692. {
  1693. int addr, align, size, func_call, i;
  1694. Sym *sym;
  1695. CType *type;
  1696. sym = func_type->ref;
  1697. func_call = sym->f.func_call;
  1698. addr = 8;
  1699. /* if the function returns a structure, then add an
  1700. implicit pointer parameter */
  1701. func_vt = sym->type;
  1702. func_var = (sym->f.func_type == FUNC_ELLIPSIS);
  1703. if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
  1704. func_vc = addr;
  1705. addr += 4;
  1706. }
  1707. NoOfCurFuncArgs = 0;
  1708. /* define parameters */
  1709. while ((sym = sym->next) != NULL) {
  1710. type = &sym->type;
  1711. sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr);
  1712. size = type_size(type, &align);
  1713. size = (size + 3) & ~3;
  1714. // keep track of size of arguments so
  1715. // we can translate where tcc thinks they
  1716. // are on the stack into the appropriate reg
  1717. TranslateStackToReg[NoOfCurFuncArgs] = size;
  1718. NoOfCurFuncArgs++;
  1719. #ifdef FUNC_STRUCT_PARAM_AS_PTR
  1720. /* structs are passed as pointer */
  1721. if ((type->t & VT_BTYPE) == VT_STRUCT) {
  1722. size = 4;
  1723. }
  1724. #endif
  1725. addr += size;
  1726. }
  1727. func_ret_sub = 0;
  1728. /* pascal type call ? */
  1729. if (func_call == FUNC_STDCALL)
  1730. func_ret_sub = addr - 8;
  1731. C67_MV(C67_FP, C67_A0); // move FP -> A0
  1732. C67_MV(C67_SP, C67_FP); // move SP -> FP
  1733. // place all the args passed in regs onto the stack
  1734. loc = 0;
  1735. for (i = 0; i < NoOfCurFuncArgs; i++) {
  1736. ParamLocOnStack[i] = loc; // remember where the param is
  1737. loc += -8;
  1738. C67_PUSH(TREG_C67_A4 + i * 2);
  1739. if (TranslateStackToReg[i] == 8) {
  1740. C67_STW_PTR_PRE_INC(TREG_C67_A4 + i * 2 + 1, C67_SP, 3); // STW r, *+SP[1] (go back and put the other)
  1741. }
  1742. }
  1743. TotalBytesPushedOnStack = -loc;
  1744. func_sub_sp_offset = ind; // remember where we put the stack instruction
  1745. C67_ADDK(0, C67_SP); // ADDK.L2 loc,SP (just put zero temporarily)
  1746. C67_PUSH(C67_A0);
  1747. C67_PUSH(C67_B3);
  1748. }
  1749. /* generate function epilog */
  1750. void gfunc_epilog(void)
  1751. {
  1752. {
  1753. int local = (-loc + 7) & -8; // stack must stay aligned to 8 bytes for LDDW instr
  1754. C67_POP(C67_B3);
  1755. C67_NOP(4); // NOP wait for load
  1756. C67_IREG_B_REG(0, C67_CREG_ZERO, C67_B3); // B.S2 B3
  1757. C67_POP(C67_FP);
  1758. C67_ADDK(local, C67_SP); // ADDK.L2 loc,SP
  1759. C67_Adjust_ADDK((int *) (cur_text_section->data +
  1760. func_sub_sp_offset),
  1761. -local + TotalBytesPushedOnStack);
  1762. C67_NOP(3); // NOP
  1763. }
  1764. }
  1765. /* generate a jump to a label */
  1766. int gjmp(int t)
  1767. {
  1768. int ind1 = ind;
  1769. if (nocode_wanted)
  1770. return t;
  1771. C67_MVKL(C67_A0, t); //r=reg to load, constant
  1772. C67_MVKH(C67_A0, t); //r=reg to load, constant
  1773. C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0); // [!R] B.S2x A0
  1774. C67_NOP(5);
  1775. return ind1;
  1776. }
  1777. /* generate a jump to a fixed address */
  1778. void gjmp_addr(int a)
  1779. {
  1780. Sym *sym;
  1781. // I guess this routine is used for relative short
  1782. // local jumps, for now just handle it as the general
  1783. // case
  1784. // define a label that will be relocated
  1785. sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
  1786. greloc(cur_text_section, sym, ind, R_C60LO16);
  1787. greloc(cur_text_section, sym, ind + 4, R_C60HI16);
  1788. gjmp(0); // place a zero there later the symbol will be added to it
  1789. }
  1790. /* generate a test. set 'inv' to invert test. Stack entry is popped */
  1791. int gtst(int inv, int t)
  1792. {
  1793. int ind1, n;
  1794. int v, *p;
  1795. v = vtop->r & VT_VALMASK;
  1796. if (nocode_wanted) {
  1797. ;
  1798. } else if (v == VT_CMP) {
  1799. /* fast case : can jump directly since flags are set */
  1800. // C67 uses B2 sort of as flags register
  1801. ind1 = ind;
  1802. C67_MVKL(C67_A0, t); //r=reg to load, constant
  1803. C67_MVKH(C67_A0, t); //r=reg to load, constant
  1804. if (C67_compare_reg != TREG_EAX && // check if not already in a conditional test reg
  1805. C67_compare_reg != TREG_EDX &&
  1806. C67_compare_reg != TREG_ST0 && C67_compare_reg != C67_B2) {
  1807. C67_MV(C67_compare_reg, C67_B2);
  1808. C67_compare_reg = C67_B2;
  1809. }
  1810. C67_IREG_B_REG(C67_invert_test ^ inv, C67_compare_reg, C67_A0); // [!R] B.S2x A0
  1811. C67_NOP(5);
  1812. t = ind1; //return where we need to patch
  1813. } else if (v == VT_JMP || v == VT_JMPI) {
  1814. /* && or || optimization */
  1815. if ((v & 1) == inv) {
  1816. /* insert vtop->c jump list in t */
  1817. // I guess the idea is to traverse to the
  1818. // null at the end of the list and store t
  1819. // there
  1820. n = vtop->c.i;
  1821. while (n != 0) {
  1822. p = (int *) (cur_text_section->data + n);
  1823. // extract 32 bit address from MVKH/MVKL
  1824. n = ((*p >> 7) & 0xffff);
  1825. n |= ((*(p + 1) >> 7) & 0xffff) << 16;
  1826. }
  1827. *p |= (t & 0xffff) << 7;
  1828. *(p + 1) |= ((t >> 16) & 0xffff) << 7;
  1829. t = vtop->c.i;
  1830. } else {
  1831. t = gjmp(t);
  1832. gsym(vtop->c.i);
  1833. }
  1834. }
  1835. vtop--;
  1836. return t;
  1837. }
  1838. /* generate an integer binary operation */
  1839. void gen_opi(int op)
  1840. {
  1841. int r, fr, opc, t;
  1842. switch (op) {
  1843. case '+':
  1844. case TOK_ADDC1: /* add with carry generation */
  1845. opc = 0;
  1846. gen_op8:
  1847. // C67 can't do const compares, must load into a reg
  1848. // so just go to gv2 directly - tktk
  1849. if (op >= TOK_ULT && op <= TOK_GT)
  1850. gv2(RC_INT_BSIDE, RC_INT); // make sure r (src1) is on the B Side of CPU
  1851. else
  1852. gv2(RC_INT, RC_INT);
  1853. r = vtop[-1].r;
  1854. fr = vtop[0].r;
  1855. C67_compare_reg = C67_B2;
  1856. if (op == TOK_LT) {
  1857. C67_CMPLT(r, fr, C67_B2);
  1858. C67_invert_test = FALSE;
  1859. } else if (op == TOK_GE) {
  1860. C67_CMPLT(r, fr, C67_B2);
  1861. C67_invert_test = TRUE;
  1862. } else if (op == TOK_GT) {
  1863. C67_CMPGT(r, fr, C67_B2);
  1864. C67_invert_test = FALSE;
  1865. } else if (op == TOK_LE) {
  1866. C67_CMPGT(r, fr, C67_B2);
  1867. C67_invert_test = TRUE;
  1868. } else if (op == TOK_EQ) {
  1869. C67_CMPEQ(r, fr, C67_B2);
  1870. C67_invert_test = FALSE;
  1871. } else if (op == TOK_NE) {
  1872. C67_CMPEQ(r, fr, C67_B2);
  1873. C67_invert_test = TRUE;
  1874. } else if (op == TOK_ULT) {
  1875. C67_CMPLTU(r, fr, C67_B2);
  1876. C67_invert_test = FALSE;
  1877. } else if (op == TOK_UGE) {
  1878. C67_CMPLTU(r, fr, C67_B2);
  1879. C67_invert_test = TRUE;
  1880. } else if (op == TOK_UGT) {
  1881. C67_CMPGTU(r, fr, C67_B2);
  1882. C67_invert_test = FALSE;
  1883. } else if (op == TOK_ULE) {
  1884. C67_CMPGTU(r, fr, C67_B2);
  1885. C67_invert_test = TRUE;
  1886. } else if (op == '+')
  1887. C67_ADD(fr, r); // ADD r,fr,r
  1888. else if (op == '-')
  1889. C67_SUB(fr, r); // SUB r,fr,r
  1890. else if (op == '&')
  1891. C67_AND(fr, r); // AND r,fr,r
  1892. else if (op == '|')
  1893. C67_OR(fr, r); // OR r,fr,r
  1894. else if (op == '^')
  1895. C67_XOR(fr, r); // XOR r,fr,r
  1896. else
  1897. ALWAYS_ASSERT(FALSE);
  1898. vtop--;
  1899. if (op >= TOK_ULT && op <= TOK_GT) {
  1900. vtop->r = VT_CMP;
  1901. vtop->c.i = op;
  1902. }
  1903. break;
  1904. case '-':
  1905. case TOK_SUBC1: /* sub with carry generation */
  1906. opc = 5;
  1907. goto gen_op8;
  1908. case TOK_ADDC2: /* add with carry use */
  1909. opc = 2;
  1910. goto gen_op8;
  1911. case TOK_SUBC2: /* sub with carry use */
  1912. opc = 3;
  1913. goto gen_op8;
  1914. case '&':
  1915. opc = 4;
  1916. goto gen_op8;
  1917. case '^':
  1918. opc = 6;
  1919. goto gen_op8;
  1920. case '|':
  1921. opc = 1;
  1922. goto gen_op8;
  1923. case '*':
  1924. case TOK_UMULL:
  1925. gv2(RC_INT, RC_INT);
  1926. r = vtop[-1].r;
  1927. fr = vtop[0].r;
  1928. vtop--;
  1929. C67_MPYI(fr, r); // 32 bit multiply fr,r,fr
  1930. C67_NOP(8); // NOP 8 for worst case
  1931. break;
  1932. case TOK_SHL:
  1933. gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
  1934. r = vtop[-1].r;
  1935. fr = vtop[0].r;
  1936. vtop--;
  1937. C67_SHL(fr, r); // arithmetic/logical shift
  1938. break;
  1939. case TOK_SHR:
  1940. gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
  1941. r = vtop[-1].r;
  1942. fr = vtop[0].r;
  1943. vtop--;
  1944. C67_SHRU(fr, r); // logical shift
  1945. break;
  1946. case TOK_SAR:
  1947. gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
  1948. r = vtop[-1].r;
  1949. fr = vtop[0].r;
  1950. vtop--;
  1951. C67_SHR(fr, r); // arithmetic shift
  1952. break;
  1953. case '/':
  1954. t = TOK__divi;
  1955. call_func:
  1956. vswap();
  1957. /* call generic idiv function */
  1958. vpush_global_sym(&func_old_type, t);
  1959. vrott(3);
  1960. gfunc_call(2);
  1961. vpushi(0);
  1962. vtop->r = REG_IRET;
  1963. vtop->r2 = VT_CONST;
  1964. break;
  1965. case TOK_UDIV:
  1966. case TOK_PDIV:
  1967. t = TOK__divu;
  1968. goto call_func;
  1969. case '%':
  1970. t = TOK__remi;
  1971. goto call_func;
  1972. case TOK_UMOD:
  1973. t = TOK__remu;
  1974. goto call_func;
  1975. default:
  1976. opc = 7;
  1977. goto gen_op8;
  1978. }
  1979. }
  1980. /* generate a floating point operation 'v = t1 op t2' instruction. The
  1981. two operands are guaranteed to have the same floating point type */
  1982. /* XXX: need to use ST1 too */
  1983. void gen_opf(int op)
  1984. {
  1985. int ft, fc, fr, r;
  1986. if (op >= TOK_ULT && op <= TOK_GT)
  1987. gv2(RC_EDX, RC_EAX); // make sure src2 is on b side
  1988. else
  1989. gv2(RC_FLOAT, RC_FLOAT); // make sure src2 is on b side
  1990. ft = vtop->type.t;
  1991. fc = vtop->c.i;
  1992. r = vtop->r;
  1993. fr = vtop[-1].r;
  1994. if ((ft & VT_BTYPE) == VT_LDOUBLE)
  1995. tcc_error("long doubles not supported");
  1996. if (op >= TOK_ULT && op <= TOK_GT) {
  1997. r = vtop[-1].r;
  1998. fr = vtop[0].r;
  1999. C67_compare_reg = C67_B2;
  2000. if (op == TOK_LT) {
  2001. if ((ft & VT_BTYPE) == VT_DOUBLE)
  2002. C67_CMPLTDP(r, fr, C67_B2);
  2003. else
  2004. C67_CMPLTSP(r, fr, C67_B2);
  2005. C67_invert_test = FALSE;
  2006. } else if (op == TOK_GE) {
  2007. if ((ft & VT_BTYPE) == VT_DOUBLE)
  2008. C67_CMPLTDP(r, fr, C67_B2);
  2009. else
  2010. C67_CMPLTSP(r, fr, C67_B2);
  2011. C67_invert_test = TRUE;
  2012. } else if (op == TOK_GT) {
  2013. if ((ft & VT_BTYPE) == VT_DOUBLE)
  2014. C67_CMPGTDP(r, fr, C67_B2);
  2015. else
  2016. C67_CMPGTSP(r, fr, C67_B2);
  2017. C67_invert_test = FALSE;
  2018. } else if (op == TOK_LE) {
  2019. if ((ft & VT_BTYPE) == VT_DOUBLE)
  2020. C67_CMPGTDP(r, fr, C67_B2);
  2021. else
  2022. C67_CMPGTSP(r, fr, C67_B2);
  2023. C67_invert_test = TRUE;
  2024. } else if (op == TOK_EQ) {
  2025. if ((ft & VT_BTYPE) == VT_DOUBLE)
  2026. C67_CMPEQDP(r, fr, C67_B2);
  2027. else
  2028. C67_CMPEQSP(r, fr, C67_B2);
  2029. C67_invert_test = FALSE;
  2030. } else if (op == TOK_NE) {
  2031. if ((ft & VT_BTYPE) == VT_DOUBLE)
  2032. C67_CMPEQDP(r, fr, C67_B2);
  2033. else
  2034. C67_CMPEQSP(r, fr, C67_B2);
  2035. C67_invert_test = TRUE;
  2036. } else {
  2037. ALWAYS_ASSERT(FALSE);
  2038. }
  2039. vtop->r = VT_CMP; // tell TCC that result is in "flags" actually B2
  2040. } else {
  2041. if (op == '+') {
  2042. if ((ft & VT_BTYPE) == VT_DOUBLE) {
  2043. C67_ADDDP(r, fr); // ADD fr,r,fr
  2044. C67_NOP(6);
  2045. } else {
  2046. C67_ADDSP(r, fr); // ADD fr,r,fr
  2047. C67_NOP(3);
  2048. }
  2049. vtop--;
  2050. } else if (op == '-') {
  2051. if ((ft & VT_BTYPE) == VT_DOUBLE) {
  2052. C67_SUBDP(r, fr); // SUB fr,r,fr
  2053. C67_NOP(6);
  2054. } else {
  2055. C67_SUBSP(r, fr); // SUB fr,r,fr
  2056. C67_NOP(3);
  2057. }
  2058. vtop--;
  2059. } else if (op == '*') {
  2060. if ((ft & VT_BTYPE) == VT_DOUBLE) {
  2061. C67_MPYDP(r, fr); // MPY fr,r,fr
  2062. C67_NOP(9);
  2063. } else {
  2064. C67_MPYSP(r, fr); // MPY fr,r,fr
  2065. C67_NOP(3);
  2066. }
  2067. vtop--;
  2068. } else if (op == '/') {
  2069. if ((ft & VT_BTYPE) == VT_DOUBLE) {
  2070. // must call intrinsic DP floating point divide
  2071. vswap();
  2072. /* call generic idiv function */
  2073. vpush_global_sym(&func_old_type, TOK__divd);
  2074. vrott(3);
  2075. gfunc_call(2);
  2076. vpushi(0);
  2077. vtop->r = REG_FRET;
  2078. vtop->r2 = REG_LRET;
  2079. } else {
  2080. // must call intrinsic SP floating point divide
  2081. vswap();
  2082. /* call generic idiv function */
  2083. vpush_global_sym(&func_old_type, TOK__divf);
  2084. vrott(3);
  2085. gfunc_call(2);
  2086. vpushi(0);
  2087. vtop->r = REG_FRET;
  2088. vtop->r2 = VT_CONST;
  2089. }
  2090. } else
  2091. ALWAYS_ASSERT(FALSE);
  2092. }
  2093. }
  2094. /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
  2095. and 'long long' cases. */
  2096. void gen_cvt_itof(int t)
  2097. {
  2098. int r;
  2099. gv(RC_INT);
  2100. r = vtop->r;
  2101. if ((t & VT_BTYPE) == VT_DOUBLE) {
  2102. if (t & VT_UNSIGNED)
  2103. C67_INTDPU(r, r);
  2104. else
  2105. C67_INTDP(r, r);
  2106. C67_NOP(4);
  2107. vtop->type.t = VT_DOUBLE;
  2108. } else {
  2109. if (t & VT_UNSIGNED)
  2110. C67_INTSPU(r, r);
  2111. else
  2112. C67_INTSP(r, r);
  2113. C67_NOP(3);
  2114. vtop->type.t = VT_FLOAT;
  2115. }
  2116. }
  2117. /* convert fp to int 't' type */
  2118. /* XXX: handle long long case */
  2119. void gen_cvt_ftoi(int t)
  2120. {
  2121. int r;
  2122. gv(RC_FLOAT);
  2123. r = vtop->r;
  2124. if (t != VT_INT)
  2125. tcc_error("long long not supported");
  2126. else {
  2127. if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
  2128. C67_DPTRUNC(r, r);
  2129. C67_NOP(3);
  2130. } else {
  2131. C67_SPTRUNC(r, r);
  2132. C67_NOP(3);
  2133. }
  2134. vtop->type.t = VT_INT;
  2135. }
  2136. }
  2137. /* convert from one floating point type to another */
  2138. void gen_cvt_ftof(int t)
  2139. {
  2140. int r, r2;
  2141. if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE &&
  2142. (t & VT_BTYPE) == VT_FLOAT) {
  2143. // convert double to float
  2144. gv(RC_FLOAT); // get it in a register pair
  2145. r = vtop->r;
  2146. C67_DPSP(r, r); // convert it to SP same register
  2147. C67_NOP(3);
  2148. vtop->type.t = VT_FLOAT;
  2149. vtop->r2 = VT_CONST; // set this as unused
  2150. } else if ((vtop->type.t & VT_BTYPE) == VT_FLOAT &&
  2151. (t & VT_BTYPE) == VT_DOUBLE) {
  2152. // convert float to double
  2153. gv(RC_FLOAT); // get it in a register
  2154. r = vtop->r;
  2155. if (r == TREG_EAX) { // make sure the paired reg is avail
  2156. r2 = get_reg(RC_ECX);
  2157. } else if (r == TREG_EDX) {
  2158. r2 = get_reg(RC_ST0);
  2159. } else {
  2160. ALWAYS_ASSERT(FALSE);
  2161. r2 = 0; /* avoid warning */
  2162. }
  2163. C67_SPDP(r, r); // convert it to DP same register
  2164. C67_NOP(1);
  2165. vtop->type.t = VT_DOUBLE;
  2166. vtop->r2 = r2; // set this as unused
  2167. } else {
  2168. ALWAYS_ASSERT(FALSE);
  2169. }
  2170. }
  2171. /* computed goto support */
  2172. void ggoto(void)
  2173. {
  2174. gcall_or_jmp(1);
  2175. vtop--;
  2176. }
  2177. /* Save the stack pointer onto the stack and return the location of its address */
  2178. ST_FUNC void gen_vla_sp_save(int addr) {
  2179. tcc_error("variable length arrays unsupported for this target");
  2180. }
  2181. /* Restore the SP from a location on the stack */
  2182. ST_FUNC void gen_vla_sp_restore(int addr) {
  2183. tcc_error("variable length arrays unsupported for this target");
  2184. }
  2185. /* Subtract from the stack pointer, and push the resulting value onto the stack */
  2186. ST_FUNC void gen_vla_alloc(CType *type, int align) {
  2187. tcc_error("variable length arrays unsupported for this target");
  2188. }
  2189. /* end of C67 code generator */
  2190. /*************************************************************/
  2191. #endif
  2192. /*************************************************************/