lj_asm_mips.h 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977
  1. /*
  2. ** MIPS IR assembler (SSA IR -> machine code).
  3. ** Copyright (C) 2005-2014 Mike Pall. See Copyright Notice in luajit.h
  4. */
  5. /* -- Register allocator extensions --------------------------------------- */
  6. /* Allocate a register with a hint. */
  7. static Reg ra_hintalloc(ASMState *as, IRRef ref, Reg hint, RegSet allow)
  8. {
  9. Reg r = IR(ref)->r;
  10. if (ra_noreg(r)) {
  11. if (!ra_hashint(r) && !iscrossref(as, ref))
  12. ra_sethint(IR(ref)->r, hint); /* Propagate register hint. */
  13. r = ra_allocref(as, ref, allow);
  14. }
  15. ra_noweak(as, r);
  16. return r;
  17. }
  18. /* Allocate a register or RID_ZERO. */
  19. static Reg ra_alloc1z(ASMState *as, IRRef ref, RegSet allow)
  20. {
  21. Reg r = IR(ref)->r;
  22. if (ra_noreg(r)) {
  23. if (!(allow & RSET_FPR) && irref_isk(ref) && IR(ref)->i == 0)
  24. return RID_ZERO;
  25. r = ra_allocref(as, ref, allow);
  26. } else {
  27. ra_noweak(as, r);
  28. }
  29. return r;
  30. }
  31. /* Allocate two source registers for three-operand instructions. */
  32. static Reg ra_alloc2(ASMState *as, IRIns *ir, RegSet allow)
  33. {
  34. IRIns *irl = IR(ir->op1), *irr = IR(ir->op2);
  35. Reg left = irl->r, right = irr->r;
  36. if (ra_hasreg(left)) {
  37. ra_noweak(as, left);
  38. if (ra_noreg(right))
  39. right = ra_alloc1z(as, ir->op2, rset_exclude(allow, left));
  40. else
  41. ra_noweak(as, right);
  42. } else if (ra_hasreg(right)) {
  43. ra_noweak(as, right);
  44. left = ra_alloc1z(as, ir->op1, rset_exclude(allow, right));
  45. } else if (ra_hashint(right)) {
  46. right = ra_alloc1z(as, ir->op2, allow);
  47. left = ra_alloc1z(as, ir->op1, rset_exclude(allow, right));
  48. } else {
  49. left = ra_alloc1z(as, ir->op1, allow);
  50. right = ra_alloc1z(as, ir->op2, rset_exclude(allow, left));
  51. }
  52. return left | (right << 8);
  53. }
  54. /* -- Guard handling ------------------------------------------------------ */
  55. /* Need some spare long-range jump slots, for out-of-range branches. */
  56. #define MIPS_SPAREJUMP 4
  57. /* Setup spare long-range jump slots per mcarea. */
  58. static void asm_sparejump_setup(ASMState *as)
  59. {
  60. MCode *mxp = as->mcbot;
  61. /* Assumes sizeof(MCLink) == 8. */
  62. if (((uintptr_t)mxp & (LJ_PAGESIZE-1)) == 8) {
  63. lua_assert(MIPSI_NOP == 0);
  64. memset(mxp+2, 0, MIPS_SPAREJUMP*8);
  65. mxp += MIPS_SPAREJUMP*2;
  66. lua_assert(mxp < as->mctop);
  67. lj_mcode_sync(as->mcbot, mxp);
  68. lj_mcode_commitbot(as->J, mxp);
  69. as->mcbot = mxp;
  70. as->mclim = as->mcbot + MCLIM_REDZONE;
  71. }
  72. }
  73. /* Setup exit stub after the end of each trace. */
  74. static void asm_exitstub_setup(ASMState *as)
  75. {
  76. MCode *mxp = as->mctop;
  77. /* sw TMP, 0(sp); j ->vm_exit_handler; li TMP, traceno */
  78. *--mxp = MIPSI_LI|MIPSF_T(RID_TMP)|as->T->traceno;
  79. *--mxp = MIPSI_J|((((uintptr_t)(void *)lj_vm_exit_handler)>>2)&0x03ffffffu);
  80. lua_assert(((uintptr_t)mxp ^ (uintptr_t)(void *)lj_vm_exit_handler)>>28 == 0);
  81. *--mxp = MIPSI_SW|MIPSF_T(RID_TMP)|MIPSF_S(RID_SP)|0;
  82. as->mctop = mxp;
  83. }
  84. /* Keep this in-sync with exitstub_trace_addr(). */
  85. #define asm_exitstub_addr(as) ((as)->mctop)
  86. /* Emit conditional branch to exit for guard. */
  87. static void asm_guard(ASMState *as, MIPSIns mi, Reg rs, Reg rt)
  88. {
  89. MCode *target = asm_exitstub_addr(as);
  90. MCode *p = as->mcp;
  91. if (LJ_UNLIKELY(p == as->invmcp)) {
  92. as->invmcp = NULL;
  93. as->loopinv = 1;
  94. as->mcp = p+1;
  95. mi = mi ^ ((mi>>28) == 1 ? 0x04000000u : 0x00010000u); /* Invert cond. */
  96. target = p; /* Patch target later in asm_loop_fixup. */
  97. }
  98. emit_ti(as, MIPSI_LI, RID_TMP, as->snapno);
  99. emit_branch(as, mi, rs, rt, target);
  100. }
  101. /* -- Operand fusion ------------------------------------------------------ */
  102. /* Limit linear search to this distance. Avoids O(n^2) behavior. */
  103. #define CONFLICT_SEARCH_LIM 31
  104. /* Check if there's no conflicting instruction between curins and ref. */
  105. static int noconflict(ASMState *as, IRRef ref, IROp conflict)
  106. {
  107. IRIns *ir = as->ir;
  108. IRRef i = as->curins;
  109. if (i > ref + CONFLICT_SEARCH_LIM)
  110. return 0; /* Give up, ref is too far away. */
  111. while (--i > ref)
  112. if (ir[i].o == conflict)
  113. return 0; /* Conflict found. */
  114. return 1; /* Ok, no conflict. */
  115. }
  116. /* Fuse the array base of colocated arrays. */
  117. static int32_t asm_fuseabase(ASMState *as, IRRef ref)
  118. {
  119. IRIns *ir = IR(ref);
  120. if (ir->o == IR_TNEW && ir->op1 <= LJ_MAX_COLOSIZE &&
  121. !neverfuse(as) && noconflict(as, ref, IR_NEWREF))
  122. return (int32_t)sizeof(GCtab);
  123. return 0;
  124. }
  125. /* Fuse array/hash/upvalue reference into register+offset operand. */
  126. static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow)
  127. {
  128. IRIns *ir = IR(ref);
  129. if (ra_noreg(ir->r)) {
  130. if (ir->o == IR_AREF) {
  131. if (mayfuse(as, ref)) {
  132. if (irref_isk(ir->op2)) {
  133. IRRef tab = IR(ir->op1)->op1;
  134. int32_t ofs = asm_fuseabase(as, tab);
  135. IRRef refa = ofs ? tab : ir->op1;
  136. ofs += 8*IR(ir->op2)->i;
  137. if (checki16(ofs)) {
  138. *ofsp = ofs;
  139. return ra_alloc1(as, refa, allow);
  140. }
  141. }
  142. }
  143. } else if (ir->o == IR_HREFK) {
  144. if (mayfuse(as, ref)) {
  145. int32_t ofs = (int32_t)(IR(ir->op2)->op2 * sizeof(Node));
  146. if (checki16(ofs)) {
  147. *ofsp = ofs;
  148. return ra_alloc1(as, ir->op1, allow);
  149. }
  150. }
  151. } else if (ir->o == IR_UREFC) {
  152. if (irref_isk(ir->op1)) {
  153. GCfunc *fn = ir_kfunc(IR(ir->op1));
  154. int32_t ofs = i32ptr(&gcref(fn->l.uvptr[(ir->op2 >> 8)])->uv.tv);
  155. int32_t jgl = (intptr_t)J2G(as->J);
  156. if ((uint32_t)(ofs-jgl) < 65536) {
  157. *ofsp = ofs-jgl-32768;
  158. return RID_JGL;
  159. } else {
  160. *ofsp = (int16_t)ofs;
  161. return ra_allock(as, ofs-(int16_t)ofs, allow);
  162. }
  163. }
  164. }
  165. }
  166. *ofsp = 0;
  167. return ra_alloc1(as, ref, allow);
  168. }
  169. /* Fuse XLOAD/XSTORE reference into load/store operand. */
  170. static void asm_fusexref(ASMState *as, MIPSIns mi, Reg rt, IRRef ref,
  171. RegSet allow, int32_t ofs)
  172. {
  173. IRIns *ir = IR(ref);
  174. Reg base;
  175. if (ra_noreg(ir->r) && canfuse(as, ir)) {
  176. if (ir->o == IR_ADD) {
  177. int32_t ofs2;
  178. if (irref_isk(ir->op2) && (ofs2 = ofs + IR(ir->op2)->i, checki16(ofs2))) {
  179. ref = ir->op1;
  180. ofs = ofs2;
  181. }
  182. } else if (ir->o == IR_STRREF) {
  183. int32_t ofs2 = 65536;
  184. lua_assert(ofs == 0);
  185. ofs = (int32_t)sizeof(GCstr);
  186. if (irref_isk(ir->op2)) {
  187. ofs2 = ofs + IR(ir->op2)->i;
  188. ref = ir->op1;
  189. } else if (irref_isk(ir->op1)) {
  190. ofs2 = ofs + IR(ir->op1)->i;
  191. ref = ir->op2;
  192. }
  193. if (!checki16(ofs2)) {
  194. /* NYI: Fuse ADD with constant. */
  195. Reg right, left = ra_alloc2(as, ir, allow);
  196. right = (left >> 8); left &= 255;
  197. emit_hsi(as, mi, rt, RID_TMP, ofs);
  198. emit_dst(as, MIPSI_ADDU, RID_TMP, left, right);
  199. return;
  200. }
  201. ofs = ofs2;
  202. }
  203. }
  204. base = ra_alloc1(as, ref, allow);
  205. emit_hsi(as, mi, rt, base, ofs);
  206. }
  207. /* -- Calls --------------------------------------------------------------- */
  208. /* Generate a call to a C function. */
  209. static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
  210. {
  211. uint32_t n, nargs = CCI_NARGS(ci);
  212. int32_t ofs = 16;
  213. Reg gpr, fpr = REGARG_FIRSTFPR;
  214. if ((void *)ci->func)
  215. emit_call(as, (void *)ci->func);
  216. for (gpr = REGARG_FIRSTGPR; gpr <= REGARG_LASTGPR; gpr++)
  217. as->cost[gpr] = REGCOST(~0u, ASMREF_L);
  218. gpr = REGARG_FIRSTGPR;
  219. for (n = 0; n < nargs; n++) { /* Setup args. */
  220. IRRef ref = args[n];
  221. if (ref) {
  222. IRIns *ir = IR(ref);
  223. if (irt_isfp(ir->t) && fpr <= REGARG_LASTFPR &&
  224. !(ci->flags & CCI_VARARG)) {
  225. lua_assert(rset_test(as->freeset, fpr)); /* Already evicted. */
  226. ra_leftov(as, fpr, ref);
  227. fpr += 2;
  228. gpr += irt_isnum(ir->t) ? 2 : 1;
  229. } else {
  230. fpr = REGARG_LASTFPR+1;
  231. if (irt_isnum(ir->t)) gpr = (gpr+1) & ~1;
  232. if (gpr <= REGARG_LASTGPR) {
  233. lua_assert(rset_test(as->freeset, gpr)); /* Already evicted. */
  234. if (irt_isfp(ir->t)) {
  235. RegSet of = as->freeset;
  236. Reg r;
  237. /* Workaround to protect argument GPRs from being used for remat. */
  238. as->freeset &= ~RSET_RANGE(REGARG_FIRSTGPR, REGARG_LASTGPR+1);
  239. r = ra_alloc1(as, ref, RSET_FPR);
  240. as->freeset |= (of & RSET_RANGE(REGARG_FIRSTGPR, REGARG_LASTGPR+1));
  241. if (irt_isnum(ir->t)) {
  242. emit_tg(as, MIPSI_MFC1, gpr+(LJ_BE?0:1), r+1);
  243. emit_tg(as, MIPSI_MFC1, gpr+(LJ_BE?1:0), r);
  244. lua_assert(rset_test(as->freeset, gpr+1)); /* Already evicted. */
  245. gpr += 2;
  246. } else if (irt_isfloat(ir->t)) {
  247. emit_tg(as, MIPSI_MFC1, gpr, r);
  248. gpr++;
  249. }
  250. } else {
  251. ra_leftov(as, gpr, ref);
  252. gpr++;
  253. }
  254. } else {
  255. Reg r = ra_alloc1z(as, ref, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR);
  256. if (irt_isnum(ir->t)) ofs = (ofs + 4) & ~4;
  257. emit_spstore(as, ir, r, ofs);
  258. ofs += irt_isnum(ir->t) ? 8 : 4;
  259. }
  260. }
  261. } else {
  262. fpr = REGARG_LASTFPR+1;
  263. if (gpr <= REGARG_LASTGPR)
  264. gpr++;
  265. else
  266. ofs += 4;
  267. }
  268. checkmclim(as);
  269. }
  270. }
  271. /* Setup result reg/sp for call. Evict scratch regs. */
  272. static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
  273. {
  274. RegSet drop = RSET_SCRATCH;
  275. int hiop = ((ir+1)->o == IR_HIOP);
  276. if ((ci->flags & CCI_NOFPRCLOBBER))
  277. drop &= ~RSET_FPR;
  278. if (ra_hasreg(ir->r))
  279. rset_clear(drop, ir->r); /* Dest reg handled below. */
  280. if (hiop && ra_hasreg((ir+1)->r))
  281. rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */
  282. ra_evictset(as, drop); /* Evictions must be performed first. */
  283. if (ra_used(ir)) {
  284. lua_assert(!irt_ispri(ir->t));
  285. if (irt_isfp(ir->t)) {
  286. if ((ci->flags & CCI_CASTU64)) {
  287. int32_t ofs = sps_scale(ir->s);
  288. Reg dest = ir->r;
  289. if (ra_hasreg(dest)) {
  290. ra_free(as, dest);
  291. ra_modified(as, dest);
  292. emit_tg(as, MIPSI_MTC1, RID_RETHI, dest+1);
  293. emit_tg(as, MIPSI_MTC1, RID_RETLO, dest);
  294. }
  295. if (ofs) {
  296. emit_tsi(as, MIPSI_SW, RID_RETLO, RID_SP, ofs+(LJ_BE?4:0));
  297. emit_tsi(as, MIPSI_SW, RID_RETHI, RID_SP, ofs+(LJ_BE?0:4));
  298. }
  299. } else {
  300. ra_destreg(as, ir, RID_FPRET);
  301. }
  302. } else if (hiop) {
  303. ra_destpair(as, ir);
  304. } else {
  305. ra_destreg(as, ir, RID_RET);
  306. }
  307. }
  308. }
  309. static void asm_call(ASMState *as, IRIns *ir)
  310. {
  311. IRRef args[CCI_NARGS_MAX];
  312. const CCallInfo *ci = &lj_ir_callinfo[ir->op2];
  313. asm_collectargs(as, ir, ci, args);
  314. asm_setupresult(as, ir, ci);
  315. asm_gencall(as, ci, args);
  316. }
  317. static void asm_callx(ASMState *as, IRIns *ir)
  318. {
  319. IRRef args[CCI_NARGS_MAX*2];
  320. CCallInfo ci;
  321. IRRef func;
  322. IRIns *irf;
  323. ci.flags = asm_callx_flags(as, ir);
  324. asm_collectargs(as, ir, &ci, args);
  325. asm_setupresult(as, ir, &ci);
  326. func = ir->op2; irf = IR(func);
  327. if (irf->o == IR_CARG) { func = irf->op1; irf = IR(func); }
  328. if (irref_isk(func)) { /* Call to constant address. */
  329. ci.func = (ASMFunction)(void *)(irf->i);
  330. } else { /* Need specific register for indirect calls. */
  331. Reg r = ra_alloc1(as, func, RID2RSET(RID_CFUNCADDR));
  332. MCode *p = as->mcp;
  333. if (r == RID_CFUNCADDR)
  334. *--p = MIPSI_NOP;
  335. else
  336. *--p = MIPSI_MOVE | MIPSF_D(RID_CFUNCADDR) | MIPSF_S(r);
  337. *--p = MIPSI_JALR | MIPSF_S(r);
  338. as->mcp = p;
  339. ci.func = (ASMFunction)(void *)0;
  340. }
  341. asm_gencall(as, &ci, args);
  342. }
  343. static void asm_callid(ASMState *as, IRIns *ir, IRCallID id)
  344. {
  345. const CCallInfo *ci = &lj_ir_callinfo[id];
  346. IRRef args[2];
  347. args[0] = ir->op1;
  348. args[1] = ir->op2;
  349. asm_setupresult(as, ir, ci);
  350. asm_gencall(as, ci, args);
  351. }
  352. static void asm_callround(ASMState *as, IRIns *ir, IRCallID id)
  353. {
  354. /* The modified regs must match with the *.dasc implementation. */
  355. RegSet drop = RID2RSET(RID_R1)|RID2RSET(RID_R12)|RID2RSET(RID_FPRET)|
  356. RID2RSET(RID_F2)|RID2RSET(RID_F4)|RID2RSET(REGARG_FIRSTFPR);
  357. if (ra_hasreg(ir->r)) rset_clear(drop, ir->r);
  358. ra_evictset(as, drop);
  359. ra_destreg(as, ir, RID_FPRET);
  360. emit_call(as, (void *)lj_ir_callinfo[id].func);
  361. ra_leftov(as, REGARG_FIRSTFPR, ir->op1);
  362. }
  363. /* -- Returns ------------------------------------------------------------- */
  364. /* Return to lower frame. Guard that it goes to the right spot. */
  365. static void asm_retf(ASMState *as, IRIns *ir)
  366. {
  367. Reg base = ra_alloc1(as, REF_BASE, RSET_GPR);
  368. void *pc = ir_kptr(IR(ir->op2));
  369. int32_t delta = 1+bc_a(*((const BCIns *)pc - 1));
  370. as->topslot -= (BCReg)delta;
  371. if ((int32_t)as->topslot < 0) as->topslot = 0;
  372. irt_setmark(IR(REF_BASE)->t); /* Children must not coalesce with BASE reg. */
  373. emit_setgl(as, base, jit_base);
  374. emit_addptr(as, base, -8*delta);
  375. asm_guard(as, MIPSI_BNE, RID_TMP,
  376. ra_allock(as, i32ptr(pc), rset_exclude(RSET_GPR, base)));
  377. emit_tsi(as, MIPSI_LW, RID_TMP, base, -8);
  378. }
  379. /* -- Type conversions ---------------------------------------------------- */
  380. static void asm_tointg(ASMState *as, IRIns *ir, Reg left)
  381. {
  382. Reg tmp = ra_scratch(as, rset_exclude(RSET_FPR, left));
  383. Reg dest = ra_dest(as, ir, RSET_GPR);
  384. asm_guard(as, MIPSI_BC1F, 0, 0);
  385. emit_fgh(as, MIPSI_C_EQ_D, 0, tmp, left);
  386. emit_fg(as, MIPSI_CVT_D_W, tmp, tmp);
  387. emit_tg(as, MIPSI_MFC1, dest, tmp);
  388. emit_fg(as, MIPSI_CVT_W_D, tmp, left);
  389. }
  390. static void asm_tobit(ASMState *as, IRIns *ir)
  391. {
  392. RegSet allow = RSET_FPR;
  393. Reg dest = ra_dest(as, ir, RSET_GPR);
  394. Reg left = ra_alloc1(as, ir->op1, allow);
  395. Reg right = ra_alloc1(as, ir->op2, rset_clear(allow, left));
  396. Reg tmp = ra_scratch(as, rset_clear(allow, right));
  397. emit_tg(as, MIPSI_MFC1, dest, tmp);
  398. emit_fgh(as, MIPSI_ADD_D, tmp, left, right);
  399. }
  400. static void asm_conv(ASMState *as, IRIns *ir)
  401. {
  402. IRType st = (IRType)(ir->op2 & IRCONV_SRCMASK);
  403. int stfp = (st == IRT_NUM || st == IRT_FLOAT);
  404. IRRef lref = ir->op1;
  405. lua_assert(irt_type(ir->t) != st);
  406. lua_assert(!(irt_isint64(ir->t) ||
  407. (st == IRT_I64 || st == IRT_U64))); /* Handled by SPLIT. */
  408. if (irt_isfp(ir->t)) {
  409. Reg dest = ra_dest(as, ir, RSET_FPR);
  410. if (stfp) { /* FP to FP conversion. */
  411. emit_fg(as, st == IRT_NUM ? MIPSI_CVT_S_D : MIPSI_CVT_D_S,
  412. dest, ra_alloc1(as, lref, RSET_FPR));
  413. } else if (st == IRT_U32) { /* U32 to FP conversion. */
  414. /* y = (x ^ 0x8000000) + 2147483648.0 */
  415. Reg left = ra_alloc1(as, lref, RSET_GPR);
  416. Reg tmp = ra_scratch(as, rset_exclude(RSET_FPR, dest));
  417. emit_fgh(as, irt_isfloat(ir->t) ? MIPSI_ADD_S : MIPSI_ADD_D,
  418. dest, dest, tmp);
  419. emit_fg(as, irt_isfloat(ir->t) ? MIPSI_CVT_S_W : MIPSI_CVT_D_W,
  420. dest, dest);
  421. if (irt_isfloat(ir->t))
  422. emit_lsptr(as, MIPSI_LWC1, (tmp & 31),
  423. (void *)lj_ir_k64_find(as->J, U64x(4f000000,4f000000)),
  424. RSET_GPR);
  425. else
  426. emit_lsptr(as, MIPSI_LDC1, (tmp & 31),
  427. (void *)lj_ir_k64_find(as->J, U64x(41e00000,00000000)),
  428. RSET_GPR);
  429. emit_tg(as, MIPSI_MTC1, RID_TMP, dest);
  430. emit_dst(as, MIPSI_XOR, RID_TMP, RID_TMP, left);
  431. emit_ti(as, MIPSI_LUI, RID_TMP, 0x8000);
  432. } else { /* Integer to FP conversion. */
  433. Reg left = ra_alloc1(as, lref, RSET_GPR);
  434. emit_fg(as, irt_isfloat(ir->t) ? MIPSI_CVT_S_W : MIPSI_CVT_D_W,
  435. dest, dest);
  436. emit_tg(as, MIPSI_MTC1, left, dest);
  437. }
  438. } else if (stfp) { /* FP to integer conversion. */
  439. if (irt_isguard(ir->t)) {
  440. /* Checked conversions are only supported from number to int. */
  441. lua_assert(irt_isint(ir->t) && st == IRT_NUM);
  442. asm_tointg(as, ir, ra_alloc1(as, lref, RSET_FPR));
  443. } else {
  444. Reg dest = ra_dest(as, ir, RSET_GPR);
  445. Reg left = ra_alloc1(as, lref, RSET_FPR);
  446. Reg tmp = ra_scratch(as, rset_exclude(RSET_FPR, left));
  447. if (irt_isu32(ir->t)) {
  448. /* y = (int)floor(x - 2147483648.0) ^ 0x80000000 */
  449. emit_dst(as, MIPSI_XOR, dest, dest, RID_TMP);
  450. emit_ti(as, MIPSI_LUI, RID_TMP, 0x8000);
  451. emit_tg(as, MIPSI_MFC1, dest, tmp);
  452. emit_fg(as, st == IRT_FLOAT ? MIPSI_FLOOR_W_S : MIPSI_FLOOR_W_D,
  453. tmp, tmp);
  454. emit_fgh(as, st == IRT_FLOAT ? MIPSI_SUB_S : MIPSI_SUB_D,
  455. tmp, left, tmp);
  456. if (st == IRT_FLOAT)
  457. emit_lsptr(as, MIPSI_LWC1, (tmp & 31),
  458. (void *)lj_ir_k64_find(as->J, U64x(4f000000,4f000000)),
  459. RSET_GPR);
  460. else
  461. emit_lsptr(as, MIPSI_LDC1, (tmp & 31),
  462. (void *)lj_ir_k64_find(as->J, U64x(41e00000,00000000)),
  463. RSET_GPR);
  464. } else {
  465. emit_tg(as, MIPSI_MFC1, dest, tmp);
  466. emit_fg(as, st == IRT_FLOAT ? MIPSI_TRUNC_W_S : MIPSI_TRUNC_W_D,
  467. tmp, left);
  468. }
  469. }
  470. } else {
  471. Reg dest = ra_dest(as, ir, RSET_GPR);
  472. if (st >= IRT_I8 && st <= IRT_U16) { /* Extend to 32 bit integer. */
  473. Reg left = ra_alloc1(as, ir->op1, RSET_GPR);
  474. lua_assert(irt_isint(ir->t) || irt_isu32(ir->t));
  475. if ((ir->op2 & IRCONV_SEXT)) {
  476. if ((as->flags & JIT_F_MIPS32R2)) {
  477. emit_dst(as, st == IRT_I8 ? MIPSI_SEB : MIPSI_SEH, dest, 0, left);
  478. } else {
  479. uint32_t shift = st == IRT_I8 ? 24 : 16;
  480. emit_dta(as, MIPSI_SRA, dest, dest, shift);
  481. emit_dta(as, MIPSI_SLL, dest, left, shift);
  482. }
  483. } else {
  484. emit_tsi(as, MIPSI_ANDI, dest, left,
  485. (int32_t)(st == IRT_U8 ? 0xff : 0xffff));
  486. }
  487. } else { /* 32/64 bit integer conversions. */
  488. /* Only need to handle 32/32 bit no-op (cast) on 32 bit archs. */
  489. ra_leftov(as, dest, lref); /* Do nothing, but may need to move regs. */
  490. }
  491. }
  492. }
  493. #if LJ_HASFFI
  494. static void asm_conv64(ASMState *as, IRIns *ir)
  495. {
  496. IRType st = (IRType)((ir-1)->op2 & IRCONV_SRCMASK);
  497. IRType dt = (((ir-1)->op2 & IRCONV_DSTMASK) >> IRCONV_DSH);
  498. IRCallID id;
  499. const CCallInfo *ci;
  500. IRRef args[2];
  501. args[LJ_BE?0:1] = ir->op1;
  502. args[LJ_BE?1:0] = (ir-1)->op1;
  503. if (st == IRT_NUM || st == IRT_FLOAT) {
  504. id = IRCALL_fp64_d2l + ((st == IRT_FLOAT) ? 2 : 0) + (dt - IRT_I64);
  505. ir--;
  506. } else {
  507. id = IRCALL_fp64_l2d + ((dt == IRT_FLOAT) ? 2 : 0) + (st - IRT_I64);
  508. }
  509. ci = &lj_ir_callinfo[id];
  510. asm_setupresult(as, ir, ci);
  511. asm_gencall(as, ci, args);
  512. }
  513. #endif
  514. static void asm_strto(ASMState *as, IRIns *ir)
  515. {
  516. const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_strscan_num];
  517. IRRef args[2];
  518. RegSet drop = RSET_SCRATCH;
  519. if (ra_hasreg(ir->r)) rset_set(drop, ir->r); /* Spill dest reg (if any). */
  520. ra_evictset(as, drop);
  521. asm_guard(as, MIPSI_BEQ, RID_RET, RID_ZERO); /* Test return status. */
  522. args[0] = ir->op1; /* GCstr *str */
  523. args[1] = ASMREF_TMP1; /* TValue *n */
  524. asm_gencall(as, ci, args);
  525. /* Store the result to the spill slot or temp slots. */
  526. emit_tsi(as, MIPSI_ADDIU, ra_releasetmp(as, ASMREF_TMP1),
  527. RID_SP, sps_scale(ir->s));
  528. }
  529. /* Get pointer to TValue. */
  530. static void asm_tvptr(ASMState *as, Reg dest, IRRef ref)
  531. {
  532. IRIns *ir = IR(ref);
  533. if (irt_isnum(ir->t)) {
  534. if (irref_isk(ref)) /* Use the number constant itself as a TValue. */
  535. ra_allockreg(as, i32ptr(ir_knum(ir)), dest);
  536. else /* Otherwise force a spill and use the spill slot. */
  537. emit_tsi(as, MIPSI_ADDIU, dest, RID_SP, ra_spill(as, ir));
  538. } else {
  539. /* Otherwise use g->tmptv to hold the TValue. */
  540. RegSet allow = rset_exclude(RSET_GPR, dest);
  541. Reg type;
  542. emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, offsetof(global_State, tmptv)-32768);
  543. if (!irt_ispri(ir->t)) {
  544. Reg src = ra_alloc1(as, ref, allow);
  545. emit_setgl(as, src, tmptv.gcr);
  546. }
  547. type = ra_allock(as, irt_toitype(ir->t), allow);
  548. emit_setgl(as, type, tmptv.it);
  549. }
  550. }
  551. static void asm_tostr(ASMState *as, IRIns *ir)
  552. {
  553. IRRef args[2];
  554. args[0] = ASMREF_L;
  555. as->gcsteps++;
  556. if (irt_isnum(IR(ir->op1)->t) || (ir+1)->o == IR_HIOP) {
  557. const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_fromnum];
  558. args[1] = ASMREF_TMP1; /* const lua_Number * */
  559. asm_setupresult(as, ir, ci); /* GCstr * */
  560. asm_gencall(as, ci, args);
  561. asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op1);
  562. } else {
  563. const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_fromint];
  564. args[1] = ir->op1; /* int32_t k */
  565. asm_setupresult(as, ir, ci); /* GCstr * */
  566. asm_gencall(as, ci, args);
  567. }
  568. }
  569. /* -- Memory references --------------------------------------------------- */
  570. static void asm_aref(ASMState *as, IRIns *ir)
  571. {
  572. Reg dest = ra_dest(as, ir, RSET_GPR);
  573. Reg idx, base;
  574. if (irref_isk(ir->op2)) {
  575. IRRef tab = IR(ir->op1)->op1;
  576. int32_t ofs = asm_fuseabase(as, tab);
  577. IRRef refa = ofs ? tab : ir->op1;
  578. ofs += 8*IR(ir->op2)->i;
  579. if (checki16(ofs)) {
  580. base = ra_alloc1(as, refa, RSET_GPR);
  581. emit_tsi(as, MIPSI_ADDIU, dest, base, ofs);
  582. return;
  583. }
  584. }
  585. base = ra_alloc1(as, ir->op1, RSET_GPR);
  586. idx = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, base));
  587. emit_dst(as, MIPSI_ADDU, dest, RID_TMP, base);
  588. emit_dta(as, MIPSI_SLL, RID_TMP, idx, 3);
  589. }
  590. /* Inlined hash lookup. Specialized for key type and for const keys.
  591. ** The equivalent C code is:
  592. ** Node *n = hashkey(t, key);
  593. ** do {
  594. ** if (lj_obj_equal(&n->key, key)) return &n->val;
  595. ** } while ((n = nextnode(n)));
  596. ** return niltv(L);
  597. */
  598. static void asm_href(ASMState *as, IRIns *ir)
  599. {
  600. RegSet allow = RSET_GPR;
  601. int destused = ra_used(ir);
  602. Reg dest = ra_dest(as, ir, allow);
  603. Reg tab = ra_alloc1(as, ir->op1, rset_clear(allow, dest));
  604. Reg key = RID_NONE, type = RID_NONE, tmpnum = RID_NONE, tmp1 = RID_TMP, tmp2;
  605. IRRef refkey = ir->op2;
  606. IRIns *irkey = IR(refkey);
  607. IRType1 kt = irkey->t;
  608. uint32_t khash;
  609. MCLabel l_end, l_loop, l_next;
  610. rset_clear(allow, tab);
  611. if (irt_isnum(kt)) {
  612. key = ra_alloc1(as, refkey, RSET_FPR);
  613. tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key));
  614. } else if (!irt_ispri(kt)) {
  615. key = ra_alloc1(as, refkey, allow);
  616. rset_clear(allow, key);
  617. type = ra_allock(as, irt_toitype(irkey->t), allow);
  618. rset_clear(allow, type);
  619. }
  620. tmp2 = ra_scratch(as, allow);
  621. rset_clear(allow, tmp2);
  622. /* Key not found in chain: load niltv. */
  623. l_end = emit_label(as);
  624. if (destused)
  625. emit_loada(as, dest, niltvg(J2G(as->J)));
  626. else
  627. *--as->mcp = MIPSI_NOP;
  628. /* Follow hash chain until the end. */
  629. emit_move(as, dest, tmp1);
  630. l_loop = --as->mcp;
  631. emit_tsi(as, MIPSI_LW, tmp1, dest, (int32_t)offsetof(Node, next));
  632. l_next = emit_label(as);
  633. /* Type and value comparison. */
  634. if (irt_isnum(kt)) {
  635. emit_branch(as, MIPSI_BC1T, 0, 0, l_end);
  636. emit_fgh(as, MIPSI_C_EQ_D, 0, tmpnum, key);
  637. emit_tg(as, MIPSI_MFC1, tmp1, key+1);
  638. emit_branch(as, MIPSI_BEQ, tmp1, RID_ZERO, l_next);
  639. emit_tsi(as, MIPSI_SLTIU, tmp1, tmp1, (int32_t)LJ_TISNUM);
  640. emit_hsi(as, MIPSI_LDC1, tmpnum, dest, (int32_t)offsetof(Node, key.n));
  641. } else {
  642. if (irt_ispri(kt)) {
  643. emit_branch(as, MIPSI_BEQ, tmp1, type, l_end);
  644. } else {
  645. emit_branch(as, MIPSI_BEQ, tmp2, key, l_end);
  646. emit_tsi(as, MIPSI_LW, tmp2, dest, (int32_t)offsetof(Node, key.gcr));
  647. emit_branch(as, MIPSI_BNE, tmp1, type, l_next);
  648. }
  649. }
  650. emit_tsi(as, MIPSI_LW, tmp1, dest, (int32_t)offsetof(Node, key.it));
  651. *l_loop = MIPSI_BNE | MIPSF_S(tmp1) | ((as->mcp-l_loop-1) & 0xffffu);
  652. /* Load main position relative to tab->node into dest. */
  653. khash = irref_isk(refkey) ? ir_khash(irkey) : 1;
  654. if (khash == 0) {
  655. emit_tsi(as, MIPSI_LW, dest, tab, (int32_t)offsetof(GCtab, node));
  656. } else {
  657. Reg tmphash = tmp1;
  658. if (irref_isk(refkey))
  659. tmphash = ra_allock(as, khash, allow);
  660. emit_dst(as, MIPSI_ADDU, dest, dest, tmp1);
  661. lua_assert(sizeof(Node) == 24);
  662. emit_dst(as, MIPSI_SUBU, tmp1, tmp2, tmp1);
  663. emit_dta(as, MIPSI_SLL, tmp1, tmp1, 3);
  664. emit_dta(as, MIPSI_SLL, tmp2, tmp1, 5);
  665. emit_dst(as, MIPSI_AND, tmp1, tmp2, tmphash);
  666. emit_tsi(as, MIPSI_LW, dest, tab, (int32_t)offsetof(GCtab, node));
  667. emit_tsi(as, MIPSI_LW, tmp2, tab, (int32_t)offsetof(GCtab, hmask));
  668. if (irref_isk(refkey)) {
  669. /* Nothing to do. */
  670. } else if (irt_isstr(kt)) {
  671. emit_tsi(as, MIPSI_LW, tmp1, key, (int32_t)offsetof(GCstr, hash));
  672. } else { /* Must match with hash*() in lj_tab.c. */
  673. emit_dst(as, MIPSI_SUBU, tmp1, tmp1, tmp2);
  674. emit_rotr(as, tmp2, tmp2, dest, (-HASH_ROT3)&31);
  675. emit_dst(as, MIPSI_XOR, tmp1, tmp1, tmp2);
  676. emit_rotr(as, tmp1, tmp1, dest, (-HASH_ROT2-HASH_ROT1)&31);
  677. emit_dst(as, MIPSI_SUBU, tmp2, tmp2, dest);
  678. if (irt_isnum(kt)) {
  679. emit_dst(as, MIPSI_XOR, tmp2, tmp2, tmp1);
  680. if ((as->flags & JIT_F_MIPS32R2)) {
  681. emit_dta(as, MIPSI_ROTR, dest, tmp1, (-HASH_ROT1)&31);
  682. } else {
  683. emit_dst(as, MIPSI_OR, dest, dest, tmp1);
  684. emit_dta(as, MIPSI_SLL, tmp1, tmp1, HASH_ROT1);
  685. emit_dta(as, MIPSI_SRL, dest, tmp1, (-HASH_ROT1)&31);
  686. }
  687. emit_dst(as, MIPSI_ADDU, tmp1, tmp1, tmp1);
  688. emit_tg(as, MIPSI_MFC1, tmp2, key);
  689. emit_tg(as, MIPSI_MFC1, tmp1, key+1);
  690. } else {
  691. emit_dst(as, MIPSI_XOR, tmp2, key, tmp1);
  692. emit_rotr(as, dest, tmp1, tmp2, (-HASH_ROT1)&31);
  693. emit_dst(as, MIPSI_ADDU, tmp1, key, ra_allock(as, HASH_BIAS, allow));
  694. }
  695. }
  696. }
  697. }
  698. static void asm_hrefk(ASMState *as, IRIns *ir)
  699. {
  700. IRIns *kslot = IR(ir->op2);
  701. IRIns *irkey = IR(kslot->op1);
  702. int32_t ofs = (int32_t)(kslot->op2 * sizeof(Node));
  703. int32_t kofs = ofs + (int32_t)offsetof(Node, key);
  704. Reg dest = (ra_used(ir)||ofs > 32736) ? ra_dest(as, ir, RSET_GPR) : RID_NONE;
  705. Reg node = ra_alloc1(as, ir->op1, RSET_GPR);
  706. Reg key = RID_NONE, type = RID_TMP, idx = node;
  707. RegSet allow = rset_exclude(RSET_GPR, node);
  708. int32_t lo, hi;
  709. lua_assert(ofs % sizeof(Node) == 0);
  710. if (ofs > 32736) {
  711. idx = dest;
  712. rset_clear(allow, dest);
  713. kofs = (int32_t)offsetof(Node, key);
  714. } else if (ra_hasreg(dest)) {
  715. emit_tsi(as, MIPSI_ADDIU, dest, node, ofs);
  716. }
  717. if (!irt_ispri(irkey->t)) {
  718. key = ra_scratch(as, allow);
  719. rset_clear(allow, key);
  720. }
  721. if (irt_isnum(irkey->t)) {
  722. lo = (int32_t)ir_knum(irkey)->u32.lo;
  723. hi = (int32_t)ir_knum(irkey)->u32.hi;
  724. } else {
  725. lo = irkey->i;
  726. hi = irt_toitype(irkey->t);
  727. if (!ra_hasreg(key))
  728. goto nolo;
  729. }
  730. asm_guard(as, MIPSI_BNE, key, lo ? ra_allock(as, lo, allow) : RID_ZERO);
  731. nolo:
  732. asm_guard(as, MIPSI_BNE, type, hi ? ra_allock(as, hi, allow) : RID_ZERO);
  733. if (ra_hasreg(key)) emit_tsi(as, MIPSI_LW, key, idx, kofs+(LJ_BE?4:0));
  734. emit_tsi(as, MIPSI_LW, type, idx, kofs+(LJ_BE?0:4));
  735. if (ofs > 32736)
  736. emit_tsi(as, MIPSI_ADDU, dest, node, ra_allock(as, ofs, allow));
  737. }
  738. static void asm_newref(ASMState *as, IRIns *ir)
  739. {
  740. if (ir->r != RID_SINK) {
  741. const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_tab_newkey];
  742. IRRef args[3];
  743. args[0] = ASMREF_L; /* lua_State *L */
  744. args[1] = ir->op1; /* GCtab *t */
  745. args[2] = ASMREF_TMP1; /* cTValue *key */
  746. asm_setupresult(as, ir, ci); /* TValue * */
  747. asm_gencall(as, ci, args);
  748. asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op2);
  749. }
  750. }
  751. static void asm_uref(ASMState *as, IRIns *ir)
  752. {
  753. /* NYI: Check that UREFO is still open and not aliasing a slot. */
  754. Reg dest = ra_dest(as, ir, RSET_GPR);
  755. if (irref_isk(ir->op1)) {
  756. GCfunc *fn = ir_kfunc(IR(ir->op1));
  757. MRef *v = &gcref(fn->l.uvptr[(ir->op2 >> 8)])->uv.v;
  758. emit_lsptr(as, MIPSI_LW, dest, v, RSET_GPR);
  759. } else {
  760. Reg uv = ra_scratch(as, RSET_GPR);
  761. Reg func = ra_alloc1(as, ir->op1, RSET_GPR);
  762. if (ir->o == IR_UREFC) {
  763. asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO);
  764. emit_tsi(as, MIPSI_ADDIU, dest, uv, (int32_t)offsetof(GCupval, tv));
  765. emit_tsi(as, MIPSI_LBU, RID_TMP, uv, (int32_t)offsetof(GCupval, closed));
  766. } else {
  767. emit_tsi(as, MIPSI_LW, dest, uv, (int32_t)offsetof(GCupval, v));
  768. }
  769. emit_tsi(as, MIPSI_LW, uv, func,
  770. (int32_t)offsetof(GCfuncL, uvptr) + 4*(int32_t)(ir->op2 >> 8));
  771. }
  772. }
  773. static void asm_fref(ASMState *as, IRIns *ir)
  774. {
  775. UNUSED(as); UNUSED(ir);
  776. lua_assert(!ra_used(ir));
  777. }
  778. static void asm_strref(ASMState *as, IRIns *ir)
  779. {
  780. Reg dest = ra_dest(as, ir, RSET_GPR);
  781. IRRef ref = ir->op2, refk = ir->op1;
  782. int32_t ofs = (int32_t)sizeof(GCstr);
  783. Reg r;
  784. if (irref_isk(ref)) {
  785. IRRef tmp = refk; refk = ref; ref = tmp;
  786. } else if (!irref_isk(refk)) {
  787. Reg right, left = ra_alloc1(as, ir->op1, RSET_GPR);
  788. IRIns *irr = IR(ir->op2);
  789. if (ra_hasreg(irr->r)) {
  790. ra_noweak(as, irr->r);
  791. right = irr->r;
  792. } else if (mayfuse(as, irr->op2) &&
  793. irr->o == IR_ADD && irref_isk(irr->op2) &&
  794. checki16(ofs + IR(irr->op2)->i)) {
  795. ofs += IR(irr->op2)->i;
  796. right = ra_alloc1(as, irr->op1, rset_exclude(RSET_GPR, left));
  797. } else {
  798. right = ra_allocref(as, ir->op2, rset_exclude(RSET_GPR, left));
  799. }
  800. emit_tsi(as, MIPSI_ADDIU, dest, dest, ofs);
  801. emit_dst(as, MIPSI_ADDU, dest, left, right);
  802. return;
  803. }
  804. r = ra_alloc1(as, ref, RSET_GPR);
  805. ofs += IR(refk)->i;
  806. if (checki16(ofs))
  807. emit_tsi(as, MIPSI_ADDIU, dest, r, ofs);
  808. else
  809. emit_dst(as, MIPSI_ADDU, dest, r,
  810. ra_allock(as, ofs, rset_exclude(RSET_GPR, r)));
  811. }
  812. /* -- Loads and stores ---------------------------------------------------- */
  813. static MIPSIns asm_fxloadins(IRIns *ir)
  814. {
  815. switch (irt_type(ir->t)) {
  816. case IRT_I8: return MIPSI_LB;
  817. case IRT_U8: return MIPSI_LBU;
  818. case IRT_I16: return MIPSI_LH;
  819. case IRT_U16: return MIPSI_LHU;
  820. case IRT_NUM: return MIPSI_LDC1;
  821. case IRT_FLOAT: return MIPSI_LWC1;
  822. default: return MIPSI_LW;
  823. }
  824. }
  825. static MIPSIns asm_fxstoreins(IRIns *ir)
  826. {
  827. switch (irt_type(ir->t)) {
  828. case IRT_I8: case IRT_U8: return MIPSI_SB;
  829. case IRT_I16: case IRT_U16: return MIPSI_SH;
  830. case IRT_NUM: return MIPSI_SDC1;
  831. case IRT_FLOAT: return MIPSI_SWC1;
  832. default: return MIPSI_SW;
  833. }
  834. }
  835. static void asm_fload(ASMState *as, IRIns *ir)
  836. {
  837. Reg dest = ra_dest(as, ir, RSET_GPR);
  838. Reg idx = ra_alloc1(as, ir->op1, RSET_GPR);
  839. MIPSIns mi = asm_fxloadins(ir);
  840. int32_t ofs;
  841. if (ir->op2 == IRFL_TAB_ARRAY) {
  842. ofs = asm_fuseabase(as, ir->op1);
  843. if (ofs) { /* Turn the t->array load into an add for colocated arrays. */
  844. emit_tsi(as, MIPSI_ADDIU, dest, idx, ofs);
  845. return;
  846. }
  847. }
  848. ofs = field_ofs[ir->op2];
  849. lua_assert(!irt_isfp(ir->t));
  850. emit_tsi(as, mi, dest, idx, ofs);
  851. }
  852. static void asm_fstore(ASMState *as, IRIns *ir)
  853. {
  854. if (ir->r != RID_SINK) {
  855. Reg src = ra_alloc1z(as, ir->op2, RSET_GPR);
  856. IRIns *irf = IR(ir->op1);
  857. Reg idx = ra_alloc1(as, irf->op1, rset_exclude(RSET_GPR, src));
  858. int32_t ofs = field_ofs[irf->op2];
  859. MIPSIns mi = asm_fxstoreins(ir);
  860. lua_assert(!irt_isfp(ir->t));
  861. emit_tsi(as, mi, src, idx, ofs);
  862. }
  863. }
  864. static void asm_xload(ASMState *as, IRIns *ir)
  865. {
  866. Reg dest = ra_dest(as, ir, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR);
  867. lua_assert(!(ir->op2 & IRXLOAD_UNALIGNED));
  868. asm_fusexref(as, asm_fxloadins(ir), dest, ir->op1, RSET_GPR, 0);
  869. }
  870. static void asm_xstore(ASMState *as, IRIns *ir, int32_t ofs)
  871. {
  872. if (ir->r != RID_SINK) {
  873. Reg src = ra_alloc1z(as, ir->op2, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR);
  874. asm_fusexref(as, asm_fxstoreins(ir), src, ir->op1,
  875. rset_exclude(RSET_GPR, src), ofs);
  876. }
  877. }
  878. static void asm_ahuvload(ASMState *as, IRIns *ir)
  879. {
  880. IRType1 t = ir->t;
  881. Reg dest = RID_NONE, type = RID_TMP, idx;
  882. RegSet allow = RSET_GPR;
  883. int32_t ofs = 0;
  884. if (ra_used(ir)) {
  885. lua_assert(irt_isnum(t) || irt_isint(t) || irt_isaddr(t));
  886. dest = ra_dest(as, ir, irt_isnum(t) ? RSET_FPR : RSET_GPR);
  887. rset_clear(allow, dest);
  888. }
  889. idx = asm_fuseahuref(as, ir->op1, &ofs, allow);
  890. rset_clear(allow, idx);
  891. if (irt_isnum(t)) {
  892. asm_guard(as, MIPSI_BEQ, type, RID_ZERO);
  893. emit_tsi(as, MIPSI_SLTIU, type, type, (int32_t)LJ_TISNUM);
  894. if (ra_hasreg(dest))
  895. emit_hsi(as, MIPSI_LDC1, dest, idx, ofs);
  896. } else {
  897. asm_guard(as, MIPSI_BNE, type, ra_allock(as, irt_toitype(t), allow));
  898. if (ra_hasreg(dest)) emit_tsi(as, MIPSI_LW, dest, idx, ofs+(LJ_BE?4:0));
  899. }
  900. emit_tsi(as, MIPSI_LW, type, idx, ofs+(LJ_BE?0:4));
  901. }
  902. static void asm_ahustore(ASMState *as, IRIns *ir)
  903. {
  904. RegSet allow = RSET_GPR;
  905. Reg idx, src = RID_NONE, type = RID_NONE;
  906. int32_t ofs = 0;
  907. if (ir->r == RID_SINK)
  908. return;
  909. if (irt_isnum(ir->t)) {
  910. src = ra_alloc1(as, ir->op2, RSET_FPR);
  911. } else {
  912. if (!irt_ispri(ir->t)) {
  913. src = ra_alloc1(as, ir->op2, allow);
  914. rset_clear(allow, src);
  915. }
  916. type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow);
  917. rset_clear(allow, type);
  918. }
  919. idx = asm_fuseahuref(as, ir->op1, &ofs, allow);
  920. if (irt_isnum(ir->t)) {
  921. emit_hsi(as, MIPSI_SDC1, src, idx, ofs);
  922. } else {
  923. if (ra_hasreg(src))
  924. emit_tsi(as, MIPSI_SW, src, idx, ofs+(LJ_BE?4:0));
  925. emit_tsi(as, MIPSI_SW, type, idx, ofs+(LJ_BE?0:4));
  926. }
  927. }
  928. static void asm_sload(ASMState *as, IRIns *ir)
  929. {
  930. int32_t ofs = 8*((int32_t)ir->op1-1) + ((ir->op2 & IRSLOAD_FRAME) ? 4 : 0);
  931. IRType1 t = ir->t;
  932. Reg dest = RID_NONE, type = RID_NONE, base;
  933. RegSet allow = RSET_GPR;
  934. lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */
  935. lua_assert(irt_isguard(t) || !(ir->op2 & IRSLOAD_TYPECHECK));
  936. lua_assert(!irt_isint(t) || (ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME)));
  937. if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(t) && irt_isint(t)) {
  938. dest = ra_scratch(as, RSET_FPR);
  939. asm_tointg(as, ir, dest);
  940. t.irt = IRT_NUM; /* Continue with a regular number type check. */
  941. } else if (ra_used(ir)) {
  942. lua_assert(irt_isnum(t) || irt_isint(t) || irt_isaddr(t));
  943. dest = ra_dest(as, ir, irt_isnum(t) ? RSET_FPR : RSET_GPR);
  944. rset_clear(allow, dest);
  945. base = ra_alloc1(as, REF_BASE, allow);
  946. rset_clear(allow, base);
  947. if ((ir->op2 & IRSLOAD_CONVERT)) {
  948. if (irt_isint(t)) {
  949. Reg tmp = ra_scratch(as, RSET_FPR);
  950. emit_tg(as, MIPSI_MFC1, dest, tmp);
  951. emit_fg(as, MIPSI_CVT_W_D, tmp, tmp);
  952. dest = tmp;
  953. t.irt = IRT_NUM; /* Check for original type. */
  954. } else {
  955. Reg tmp = ra_scratch(as, RSET_GPR);
  956. emit_fg(as, MIPSI_CVT_D_W, dest, dest);
  957. emit_tg(as, MIPSI_MTC1, tmp, dest);
  958. dest = tmp;
  959. t.irt = IRT_INT; /* Check for original type. */
  960. }
  961. }
  962. goto dotypecheck;
  963. }
  964. base = ra_alloc1(as, REF_BASE, allow);
  965. rset_clear(allow, base);
  966. dotypecheck:
  967. if (irt_isnum(t)) {
  968. if ((ir->op2 & IRSLOAD_TYPECHECK)) {
  969. asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO);
  970. emit_tsi(as, MIPSI_SLTIU, RID_TMP, RID_TMP, (int32_t)LJ_TISNUM);
  971. type = RID_TMP;
  972. }
  973. if (ra_hasreg(dest)) emit_hsi(as, MIPSI_LDC1, dest, base, ofs);
  974. } else {
  975. if ((ir->op2 & IRSLOAD_TYPECHECK)) {
  976. Reg ktype = ra_allock(as, irt_toitype(t), allow);
  977. asm_guard(as, MIPSI_BNE, RID_TMP, ktype);
  978. type = RID_TMP;
  979. }
  980. if (ra_hasreg(dest)) emit_tsi(as, MIPSI_LW, dest, base, ofs ^ (LJ_BE?4:0));
  981. }
  982. if (ra_hasreg(type)) emit_tsi(as, MIPSI_LW, type, base, ofs ^ (LJ_BE?0:4));
  983. }
  984. /* -- Allocations --------------------------------------------------------- */
  985. #if LJ_HASFFI
  986. static void asm_cnew(ASMState *as, IRIns *ir)
  987. {
  988. CTState *cts = ctype_ctsG(J2G(as->J));
  989. CTypeID ctypeid = (CTypeID)IR(ir->op1)->i;
  990. CTSize sz = (ir->o == IR_CNEWI || ir->op2 == REF_NIL) ?
  991. lj_ctype_size(cts, ctypeid) : (CTSize)IR(ir->op2)->i;
  992. const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco];
  993. IRRef args[2];
  994. RegSet allow = (RSET_GPR & ~RSET_SCRATCH);
  995. RegSet drop = RSET_SCRATCH;
  996. lua_assert(sz != CTSIZE_INVALID);
  997. args[0] = ASMREF_L; /* lua_State *L */
  998. args[1] = ASMREF_TMP1; /* MSize size */
  999. as->gcsteps++;
  1000. if (ra_hasreg(ir->r))
  1001. rset_clear(drop, ir->r); /* Dest reg handled below. */
  1002. ra_evictset(as, drop);
  1003. if (ra_used(ir))
  1004. ra_destreg(as, ir, RID_RET); /* GCcdata * */
  1005. /* Initialize immutable cdata object. */
  1006. if (ir->o == IR_CNEWI) {
  1007. int32_t ofs = sizeof(GCcdata);
  1008. lua_assert(sz == 4 || sz == 8);
  1009. if (sz == 8) {
  1010. ofs += 4;
  1011. lua_assert((ir+1)->o == IR_HIOP);
  1012. if (LJ_LE) ir++;
  1013. }
  1014. for (;;) {
  1015. Reg r = ra_alloc1z(as, ir->op2, allow);
  1016. emit_tsi(as, MIPSI_SW, r, RID_RET, ofs);
  1017. rset_clear(allow, r);
  1018. if (ofs == sizeof(GCcdata)) break;
  1019. ofs -= 4; if (LJ_BE) ir++; else ir--;
  1020. }
  1021. }
  1022. /* Initialize gct and ctypeid. lj_mem_newgco() already sets marked. */
  1023. emit_tsi(as, MIPSI_SB, RID_RET+1, RID_RET, offsetof(GCcdata, gct));
  1024. emit_tsi(as, MIPSI_SH, RID_TMP, RID_RET, offsetof(GCcdata, ctypeid));
  1025. emit_ti(as, MIPSI_LI, RID_RET+1, ~LJ_TCDATA);
  1026. emit_ti(as, MIPSI_LI, RID_TMP, ctypeid); /* Lower 16 bit used. Sign-ext ok. */
  1027. asm_gencall(as, ci, args);
  1028. ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)),
  1029. ra_releasetmp(as, ASMREF_TMP1));
  1030. }
  1031. #else
  1032. #define asm_cnew(as, ir) ((void)0)
  1033. #endif
  1034. /* -- Write barriers ------------------------------------------------------ */
  1035. static void asm_tbar(ASMState *as, IRIns *ir)
  1036. {
  1037. Reg tab = ra_alloc1(as, ir->op1, RSET_GPR);
  1038. Reg mark = ra_scratch(as, rset_exclude(RSET_GPR, tab));
  1039. Reg link = RID_TMP;
  1040. MCLabel l_end = emit_label(as);
  1041. emit_tsi(as, MIPSI_SW, link, tab, (int32_t)offsetof(GCtab, gclist));
  1042. emit_tsi(as, MIPSI_SB, mark, tab, (int32_t)offsetof(GCtab, marked));
  1043. emit_setgl(as, tab, gc.grayagain);
  1044. emit_getgl(as, link, gc.grayagain);
  1045. emit_dst(as, MIPSI_XOR, mark, mark, RID_TMP); /* Clear black bit. */
  1046. emit_branch(as, MIPSI_BEQ, RID_TMP, RID_ZERO, l_end);
  1047. emit_tsi(as, MIPSI_ANDI, RID_TMP, mark, LJ_GC_BLACK);
  1048. emit_tsi(as, MIPSI_LBU, mark, tab, (int32_t)offsetof(GCtab, marked));
  1049. }
  1050. static void asm_obar(ASMState *as, IRIns *ir)
  1051. {
  1052. const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_gc_barrieruv];
  1053. IRRef args[2];
  1054. MCLabel l_end;
  1055. Reg obj, val, tmp;
  1056. /* No need for other object barriers (yet). */
  1057. lua_assert(IR(ir->op1)->o == IR_UREFC);
  1058. ra_evictset(as, RSET_SCRATCH);
  1059. l_end = emit_label(as);
  1060. args[0] = ASMREF_TMP1; /* global_State *g */
  1061. args[1] = ir->op1; /* TValue *tv */
  1062. asm_gencall(as, ci, args);
  1063. emit_tsi(as, MIPSI_ADDIU, ra_releasetmp(as, ASMREF_TMP1), RID_JGL, -32768);
  1064. obj = IR(ir->op1)->r;
  1065. tmp = ra_scratch(as, rset_exclude(RSET_GPR, obj));
  1066. emit_branch(as, MIPSI_BEQ, RID_TMP, RID_ZERO, l_end);
  1067. emit_tsi(as, MIPSI_ANDI, tmp, tmp, LJ_GC_BLACK);
  1068. emit_branch(as, MIPSI_BEQ, RID_TMP, RID_ZERO, l_end);
  1069. emit_tsi(as, MIPSI_ANDI, RID_TMP, RID_TMP, LJ_GC_WHITES);
  1070. val = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, obj));
  1071. emit_tsi(as, MIPSI_LBU, tmp, obj,
  1072. (int32_t)offsetof(GCupval, marked)-(int32_t)offsetof(GCupval, tv));
  1073. emit_tsi(as, MIPSI_LBU, RID_TMP, val, (int32_t)offsetof(GChead, marked));
  1074. }
  1075. /* -- Arithmetic and logic operations ------------------------------------- */
  1076. static void asm_fparith(ASMState *as, IRIns *ir, MIPSIns mi)
  1077. {
  1078. Reg dest = ra_dest(as, ir, RSET_FPR);
  1079. Reg right, left = ra_alloc2(as, ir, RSET_FPR);
  1080. right = (left >> 8); left &= 255;
  1081. emit_fgh(as, mi, dest, left, right);
  1082. }
  1083. static void asm_fpunary(ASMState *as, IRIns *ir, MIPSIns mi)
  1084. {
  1085. Reg dest = ra_dest(as, ir, RSET_FPR);
  1086. Reg left = ra_hintalloc(as, ir->op1, dest, RSET_FPR);
  1087. emit_fg(as, mi, dest, left);
  1088. }
  1089. static int asm_fpjoin_pow(ASMState *as, IRIns *ir)
  1090. {
  1091. IRIns *irp = IR(ir->op1);
  1092. if (irp == ir-1 && irp->o == IR_MUL && !ra_used(irp)) {
  1093. IRIns *irpp = IR(irp->op1);
  1094. if (irpp == ir-2 && irpp->o == IR_FPMATH &&
  1095. irpp->op2 == IRFPM_LOG2 && !ra_used(irpp)) {
  1096. const CCallInfo *ci = &lj_ir_callinfo[IRCALL_pow];
  1097. IRRef args[2];
  1098. args[0] = irpp->op1;
  1099. args[1] = irp->op2;
  1100. asm_setupresult(as, ir, ci);
  1101. asm_gencall(as, ci, args);
  1102. return 1;
  1103. }
  1104. }
  1105. return 0;
  1106. }
  1107. static void asm_add(ASMState *as, IRIns *ir)
  1108. {
  1109. if (irt_isnum(ir->t)) {
  1110. asm_fparith(as, ir, MIPSI_ADD_D);
  1111. } else {
  1112. Reg dest = ra_dest(as, ir, RSET_GPR);
  1113. Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR);
  1114. if (irref_isk(ir->op2)) {
  1115. int32_t k = IR(ir->op2)->i;
  1116. if (checki16(k)) {
  1117. emit_tsi(as, MIPSI_ADDIU, dest, left, k);
  1118. return;
  1119. }
  1120. }
  1121. right = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, left));
  1122. emit_dst(as, MIPSI_ADDU, dest, left, right);
  1123. }
  1124. }
  1125. static void asm_sub(ASMState *as, IRIns *ir)
  1126. {
  1127. if (irt_isnum(ir->t)) {
  1128. asm_fparith(as, ir, MIPSI_SUB_D);
  1129. } else {
  1130. Reg dest = ra_dest(as, ir, RSET_GPR);
  1131. Reg right, left = ra_alloc2(as, ir, RSET_GPR);
  1132. right = (left >> 8); left &= 255;
  1133. emit_dst(as, MIPSI_SUBU, dest, left, right);
  1134. }
  1135. }
  1136. static void asm_mul(ASMState *as, IRIns *ir)
  1137. {
  1138. if (irt_isnum(ir->t)) {
  1139. asm_fparith(as, ir, MIPSI_MUL_D);
  1140. } else {
  1141. Reg dest = ra_dest(as, ir, RSET_GPR);
  1142. Reg right, left = ra_alloc2(as, ir, RSET_GPR);
  1143. right = (left >> 8); left &= 255;
  1144. emit_dst(as, MIPSI_MUL, dest, left, right);
  1145. }
  1146. }
  1147. static void asm_neg(ASMState *as, IRIns *ir)
  1148. {
  1149. if (irt_isnum(ir->t)) {
  1150. asm_fpunary(as, ir, MIPSI_NEG_D);
  1151. } else {
  1152. Reg dest = ra_dest(as, ir, RSET_GPR);
  1153. Reg left = ra_hintalloc(as, ir->op1, dest, RSET_GPR);
  1154. emit_dst(as, MIPSI_SUBU, dest, RID_ZERO, left);
  1155. }
  1156. }
  1157. static void asm_arithov(ASMState *as, IRIns *ir)
  1158. {
  1159. Reg right, left, tmp, dest = ra_dest(as, ir, RSET_GPR);
  1160. if (irref_isk(ir->op2)) {
  1161. int k = IR(ir->op2)->i;
  1162. if (ir->o == IR_SUBOV) k = -k;
  1163. if (checki16(k)) { /* (dest < left) == (k >= 0 ? 1 : 0) */
  1164. left = ra_alloc1(as, ir->op1, RSET_GPR);
  1165. asm_guard(as, k >= 0 ? MIPSI_BNE : MIPSI_BEQ, RID_TMP, RID_ZERO);
  1166. emit_dst(as, MIPSI_SLT, RID_TMP, dest, dest == left ? RID_TMP : left);
  1167. emit_tsi(as, MIPSI_ADDIU, dest, left, k);
  1168. if (dest == left) emit_move(as, RID_TMP, left);
  1169. return;
  1170. }
  1171. }
  1172. left = ra_alloc2(as, ir, RSET_GPR);
  1173. right = (left >> 8); left &= 255;
  1174. tmp = ra_scratch(as, rset_exclude(rset_exclude(rset_exclude(RSET_GPR, left),
  1175. right), dest));
  1176. asm_guard(as, MIPSI_BLTZ, RID_TMP, 0);
  1177. emit_dst(as, MIPSI_AND, RID_TMP, RID_TMP, tmp);
  1178. if (ir->o == IR_ADDOV) { /* ((dest^left) & (dest^right)) < 0 */
  1179. emit_dst(as, MIPSI_XOR, RID_TMP, dest, dest == right ? RID_TMP : right);
  1180. } else { /* ((dest^left) & (dest^~right)) < 0 */
  1181. emit_dst(as, MIPSI_XOR, RID_TMP, RID_TMP, dest);
  1182. emit_dst(as, MIPSI_NOR, RID_TMP, dest == right ? RID_TMP : right, RID_ZERO);
  1183. }
  1184. emit_dst(as, MIPSI_XOR, tmp, dest, dest == left ? RID_TMP : left);
  1185. emit_dst(as, ir->o == IR_ADDOV ? MIPSI_ADDU : MIPSI_SUBU, dest, left, right);
  1186. if (dest == left || dest == right)
  1187. emit_move(as, RID_TMP, dest == left ? left : right);
  1188. }
  1189. static void asm_mulov(ASMState *as, IRIns *ir)
  1190. {
  1191. #if LJ_DUALNUM
  1192. #error "NYI: MULOV"
  1193. #else
  1194. UNUSED(as); UNUSED(ir); lua_assert(0); /* Unused in single-number mode. */
  1195. #endif
  1196. }
  1197. #if LJ_HASFFI
  1198. static void asm_add64(ASMState *as, IRIns *ir)
  1199. {
  1200. Reg dest = ra_dest(as, ir, RSET_GPR);
  1201. Reg right, left = ra_alloc1(as, ir->op1, RSET_GPR);
  1202. if (irref_isk(ir->op2)) {
  1203. int32_t k = IR(ir->op2)->i;
  1204. if (k == 0) {
  1205. emit_dst(as, MIPSI_ADDU, dest, left, RID_TMP);
  1206. goto loarith;
  1207. } else if (checki16(k)) {
  1208. emit_dst(as, MIPSI_ADDU, dest, dest, RID_TMP);
  1209. emit_tsi(as, MIPSI_ADDIU, dest, left, k);
  1210. goto loarith;
  1211. }
  1212. }
  1213. emit_dst(as, MIPSI_ADDU, dest, dest, RID_TMP);
  1214. right = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, left));
  1215. emit_dst(as, MIPSI_ADDU, dest, left, right);
  1216. loarith:
  1217. ir--;
  1218. dest = ra_dest(as, ir, RSET_GPR);
  1219. left = ra_alloc1(as, ir->op1, RSET_GPR);
  1220. if (irref_isk(ir->op2)) {
  1221. int32_t k = IR(ir->op2)->i;
  1222. if (k == 0) {
  1223. if (dest != left)
  1224. emit_move(as, dest, left);
  1225. return;
  1226. } else if (checki16(k)) {
  1227. if (dest == left) {
  1228. Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, left));
  1229. emit_move(as, dest, tmp);
  1230. dest = tmp;
  1231. }
  1232. emit_dst(as, MIPSI_SLTU, RID_TMP, dest, left);
  1233. emit_tsi(as, MIPSI_ADDIU, dest, left, k);
  1234. return;
  1235. }
  1236. }
  1237. right = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, left));
  1238. if (dest == left && dest == right) {
  1239. Reg tmp = ra_scratch(as, rset_exclude(rset_exclude(RSET_GPR, left), right));
  1240. emit_move(as, dest, tmp);
  1241. dest = tmp;
  1242. }
  1243. emit_dst(as, MIPSI_SLTU, RID_TMP, dest, dest == left ? right : left);
  1244. emit_dst(as, MIPSI_ADDU, dest, left, right);
  1245. }
  1246. static void asm_sub64(ASMState *as, IRIns *ir)
  1247. {
  1248. Reg dest = ra_dest(as, ir, RSET_GPR);
  1249. Reg right, left = ra_alloc2(as, ir, RSET_GPR);
  1250. right = (left >> 8); left &= 255;
  1251. emit_dst(as, MIPSI_SUBU, dest, dest, RID_TMP);
  1252. emit_dst(as, MIPSI_SUBU, dest, left, right);
  1253. ir--;
  1254. dest = ra_dest(as, ir, RSET_GPR);
  1255. left = ra_alloc2(as, ir, RSET_GPR);
  1256. right = (left >> 8); left &= 255;
  1257. if (dest == left) {
  1258. Reg tmp = ra_scratch(as, rset_exclude(rset_exclude(RSET_GPR, left), right));
  1259. emit_move(as, dest, tmp);
  1260. dest = tmp;
  1261. }
  1262. emit_dst(as, MIPSI_SLTU, RID_TMP, left, dest);
  1263. emit_dst(as, MIPSI_SUBU, dest, left, right);
  1264. }
  1265. static void asm_neg64(ASMState *as, IRIns *ir)
  1266. {
  1267. Reg dest = ra_dest(as, ir, RSET_GPR);
  1268. Reg left = ra_alloc1(as, ir->op1, RSET_GPR);
  1269. emit_dst(as, MIPSI_SUBU, dest, dest, RID_TMP);
  1270. emit_dst(as, MIPSI_SUBU, dest, RID_ZERO, left);
  1271. ir--;
  1272. dest = ra_dest(as, ir, RSET_GPR);
  1273. left = ra_alloc1(as, ir->op1, RSET_GPR);
  1274. emit_dst(as, MIPSI_SLTU, RID_TMP, RID_ZERO, dest);
  1275. emit_dst(as, MIPSI_SUBU, dest, RID_ZERO, left);
  1276. }
  1277. #endif
  1278. static void asm_bitnot(ASMState *as, IRIns *ir)
  1279. {
  1280. Reg left, right, dest = ra_dest(as, ir, RSET_GPR);
  1281. IRIns *irl = IR(ir->op1);
  1282. if (mayfuse(as, ir->op1) && irl->o == IR_BOR) {
  1283. left = ra_alloc2(as, irl, RSET_GPR);
  1284. right = (left >> 8); left &= 255;
  1285. } else {
  1286. left = ra_hintalloc(as, ir->op1, dest, RSET_GPR);
  1287. right = RID_ZERO;
  1288. }
  1289. emit_dst(as, MIPSI_NOR, dest, left, right);
  1290. }
  1291. static void asm_bitswap(ASMState *as, IRIns *ir)
  1292. {
  1293. Reg dest = ra_dest(as, ir, RSET_GPR);
  1294. Reg left = ra_alloc1(as, ir->op1, RSET_GPR);
  1295. if ((as->flags & JIT_F_MIPS32R2)) {
  1296. emit_dta(as, MIPSI_ROTR, dest, RID_TMP, 16);
  1297. emit_dst(as, MIPSI_WSBH, RID_TMP, 0, left);
  1298. } else {
  1299. Reg tmp = ra_scratch(as, rset_exclude(rset_exclude(RSET_GPR, left), dest));
  1300. emit_dst(as, MIPSI_OR, dest, dest, tmp);
  1301. emit_dst(as, MIPSI_OR, dest, dest, RID_TMP);
  1302. emit_tsi(as, MIPSI_ANDI, dest, dest, 0xff00);
  1303. emit_dta(as, MIPSI_SLL, RID_TMP, RID_TMP, 8);
  1304. emit_dta(as, MIPSI_SRL, dest, left, 8);
  1305. emit_tsi(as, MIPSI_ANDI, RID_TMP, left, 0xff00);
  1306. emit_dst(as, MIPSI_OR, tmp, tmp, RID_TMP);
  1307. emit_dta(as, MIPSI_SRL, tmp, left, 24);
  1308. emit_dta(as, MIPSI_SLL, RID_TMP, left, 24);
  1309. }
  1310. }
  1311. static void asm_bitop(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik)
  1312. {
  1313. Reg dest = ra_dest(as, ir, RSET_GPR);
  1314. Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR);
  1315. if (irref_isk(ir->op2)) {
  1316. int32_t k = IR(ir->op2)->i;
  1317. if (checku16(k)) {
  1318. emit_tsi(as, mik, dest, left, k);
  1319. return;
  1320. }
  1321. }
  1322. right = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, left));
  1323. emit_dst(as, mi, dest, left, right);
  1324. }
  1325. static void asm_bitshift(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik)
  1326. {
  1327. Reg dest = ra_dest(as, ir, RSET_GPR);
  1328. if (irref_isk(ir->op2)) { /* Constant shifts. */
  1329. uint32_t shift = (uint32_t)(IR(ir->op2)->i & 31);
  1330. emit_dta(as, mik, dest, ra_hintalloc(as, ir->op1, dest, RSET_GPR), shift);
  1331. } else {
  1332. Reg right, left = ra_alloc2(as, ir, RSET_GPR);
  1333. right = (left >> 8); left &= 255;
  1334. emit_dst(as, mi, dest, right, left); /* Shift amount is in rs. */
  1335. }
  1336. }
  1337. static void asm_bitror(ASMState *as, IRIns *ir)
  1338. {
  1339. if ((as->flags & JIT_F_MIPS32R2)) {
  1340. asm_bitshift(as, ir, MIPSI_ROTRV, MIPSI_ROTR);
  1341. } else {
  1342. Reg dest = ra_dest(as, ir, RSET_GPR);
  1343. if (irref_isk(ir->op2)) { /* Constant shifts. */
  1344. uint32_t shift = (uint32_t)(IR(ir->op2)->i & 31);
  1345. Reg left = ra_hintalloc(as, ir->op1, dest, RSET_GPR);
  1346. emit_rotr(as, dest, left, RID_TMP, shift);
  1347. } else {
  1348. Reg right, left = ra_alloc2(as, ir, RSET_GPR);
  1349. right = (left >> 8); left &= 255;
  1350. emit_dst(as, MIPSI_OR, dest, dest, RID_TMP);
  1351. emit_dst(as, MIPSI_SRLV, dest, right, left);
  1352. emit_dst(as, MIPSI_SLLV, RID_TMP, RID_TMP, left);
  1353. emit_dst(as, MIPSI_SUBU, RID_TMP, ra_allock(as, 32, RSET_GPR), right);
  1354. }
  1355. }
  1356. }
  1357. static void asm_min_max(ASMState *as, IRIns *ir, int ismax)
  1358. {
  1359. if (irt_isnum(ir->t)) {
  1360. Reg dest = ra_dest(as, ir, RSET_FPR);
  1361. Reg right, left = ra_alloc2(as, ir, RSET_FPR);
  1362. right = (left >> 8); left &= 255;
  1363. if (dest == left) {
  1364. emit_fg(as, MIPSI_MOVT_D, dest, right);
  1365. } else {
  1366. emit_fg(as, MIPSI_MOVF_D, dest, left);
  1367. if (dest != right) emit_fg(as, MIPSI_MOV_D, dest, right);
  1368. }
  1369. emit_fgh(as, MIPSI_C_OLT_D, 0, ismax ? left : right, ismax ? right : left);
  1370. } else {
  1371. Reg dest = ra_dest(as, ir, RSET_GPR);
  1372. Reg right, left = ra_alloc2(as, ir, RSET_GPR);
  1373. right = (left >> 8); left &= 255;
  1374. if (dest == left) {
  1375. emit_dst(as, MIPSI_MOVN, dest, right, RID_TMP);
  1376. } else {
  1377. emit_dst(as, MIPSI_MOVZ, dest, left, RID_TMP);
  1378. if (dest != right) emit_move(as, dest, right);
  1379. }
  1380. emit_dst(as, MIPSI_SLT, RID_TMP,
  1381. ismax ? left : right, ismax ? right : left);
  1382. }
  1383. }
  1384. /* -- Comparisons --------------------------------------------------------- */
  1385. static void asm_comp(ASMState *as, IRIns *ir)
  1386. {
  1387. /* ORDER IR: LT GE LE GT ULT UGE ULE UGT. */
  1388. IROp op = ir->o;
  1389. if (irt_isnum(ir->t)) {
  1390. Reg right, left = ra_alloc2(as, ir, RSET_FPR);
  1391. right = (left >> 8); left &= 255;
  1392. asm_guard(as, (op&1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0);
  1393. emit_fgh(as, MIPSI_C_OLT_D + ((op&3) ^ ((op>>2)&1)), 0, left, right);
  1394. } else {
  1395. Reg right, left = ra_alloc1(as, ir->op1, RSET_GPR);
  1396. if (op == IR_ABC) op = IR_UGT;
  1397. if ((op&4) == 0 && irref_isk(ir->op2) && IR(ir->op2)->i == 0) {
  1398. MIPSIns mi = (op&2) ? ((op&1) ? MIPSI_BLEZ : MIPSI_BGTZ) :
  1399. ((op&1) ? MIPSI_BLTZ : MIPSI_BGEZ);
  1400. asm_guard(as, mi, left, 0);
  1401. } else {
  1402. if (irref_isk(ir->op2)) {
  1403. int32_t k = IR(ir->op2)->i;
  1404. if ((op&2)) k++;
  1405. if (checki16(k)) {
  1406. asm_guard(as, (op&1) ? MIPSI_BNE : MIPSI_BEQ, RID_TMP, RID_ZERO);
  1407. emit_tsi(as, (op&4) ? MIPSI_SLTIU : MIPSI_SLTI,
  1408. RID_TMP, left, k);
  1409. return;
  1410. }
  1411. }
  1412. right = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, left));
  1413. asm_guard(as, ((op^(op>>1))&1) ? MIPSI_BNE : MIPSI_BEQ, RID_TMP, RID_ZERO);
  1414. emit_dst(as, (op&4) ? MIPSI_SLTU : MIPSI_SLT,
  1415. RID_TMP, (op&2) ? right : left, (op&2) ? left : right);
  1416. }
  1417. }
  1418. }
  1419. static void asm_compeq(ASMState *as, IRIns *ir)
  1420. {
  1421. Reg right, left = ra_alloc2(as, ir, irt_isnum(ir->t) ? RSET_FPR : RSET_GPR);
  1422. right = (left >> 8); left &= 255;
  1423. if (irt_isnum(ir->t)) {
  1424. asm_guard(as, (ir->o & 1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0);
  1425. emit_fgh(as, MIPSI_C_EQ_D, 0, left, right);
  1426. } else {
  1427. asm_guard(as, (ir->o & 1) ? MIPSI_BEQ : MIPSI_BNE, left, right);
  1428. }
  1429. }
  1430. #if LJ_HASFFI
  1431. /* 64 bit integer comparisons. */
  1432. static void asm_comp64(ASMState *as, IRIns *ir)
  1433. {
  1434. /* ORDER IR: LT GE LE GT ULT UGE ULE UGT. */
  1435. IROp op = (ir-1)->o;
  1436. MCLabel l_end;
  1437. Reg rightlo, leftlo, righthi, lefthi = ra_alloc2(as, ir, RSET_GPR);
  1438. righthi = (lefthi >> 8); lefthi &= 255;
  1439. leftlo = ra_alloc2(as, ir-1,
  1440. rset_exclude(rset_exclude(RSET_GPR, lefthi), righthi));
  1441. rightlo = (leftlo >> 8); leftlo &= 255;
  1442. asm_guard(as, ((op^(op>>1))&1) ? MIPSI_BNE : MIPSI_BEQ, RID_TMP, RID_ZERO);
  1443. l_end = emit_label(as);
  1444. if (lefthi != righthi)
  1445. emit_dst(as, (op&4) ? MIPSI_SLTU : MIPSI_SLT, RID_TMP,
  1446. (op&2) ? righthi : lefthi, (op&2) ? lefthi : righthi);
  1447. emit_dst(as, MIPSI_SLTU, RID_TMP,
  1448. (op&2) ? rightlo : leftlo, (op&2) ? leftlo : rightlo);
  1449. if (lefthi != righthi)
  1450. emit_branch(as, MIPSI_BEQ, lefthi, righthi, l_end);
  1451. }
  1452. static void asm_comp64eq(ASMState *as, IRIns *ir)
  1453. {
  1454. Reg tmp, right, left = ra_alloc2(as, ir, RSET_GPR);
  1455. right = (left >> 8); left &= 255;
  1456. asm_guard(as, ((ir-1)->o & 1) ? MIPSI_BEQ : MIPSI_BNE, RID_TMP, RID_ZERO);
  1457. tmp = ra_scratch(as, rset_exclude(rset_exclude(RSET_GPR, left), right));
  1458. emit_dst(as, MIPSI_OR, RID_TMP, RID_TMP, tmp);
  1459. emit_dst(as, MIPSI_XOR, tmp, left, right);
  1460. left = ra_alloc2(as, ir-1, RSET_GPR);
  1461. right = (left >> 8); left &= 255;
  1462. emit_dst(as, MIPSI_XOR, RID_TMP, left, right);
  1463. }
  1464. #endif
  1465. /* -- Support for 64 bit ops in 32 bit mode ------------------------------- */
  1466. /* Hiword op of a split 64 bit op. Previous op must be the loword op. */
  1467. static void asm_hiop(ASMState *as, IRIns *ir)
  1468. {
  1469. #if LJ_HASFFI
  1470. /* HIOP is marked as a store because it needs its own DCE logic. */
  1471. int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */
  1472. if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1;
  1473. if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */
  1474. as->curins--; /* Always skip the CONV. */
  1475. if (usehi || uselo)
  1476. asm_conv64(as, ir);
  1477. return;
  1478. } else if ((ir-1)->o < IR_EQ) { /* 64 bit integer comparisons. ORDER IR. */
  1479. as->curins--; /* Always skip the loword comparison. */
  1480. asm_comp64(as, ir);
  1481. return;
  1482. } else if ((ir-1)->o <= IR_NE) { /* 64 bit integer comparisons. ORDER IR. */
  1483. as->curins--; /* Always skip the loword comparison. */
  1484. asm_comp64eq(as, ir);
  1485. return;
  1486. } else if ((ir-1)->o == IR_XSTORE) {
  1487. as->curins--; /* Handle both stores here. */
  1488. if ((ir-1)->r != RID_SINK) {
  1489. asm_xstore(as, ir, LJ_LE ? 4 : 0);
  1490. asm_xstore(as, ir-1, LJ_LE ? 0 : 4);
  1491. }
  1492. return;
  1493. }
  1494. if (!usehi) return; /* Skip unused hiword op for all remaining ops. */
  1495. switch ((ir-1)->o) {
  1496. case IR_ADD: as->curins--; asm_add64(as, ir); break;
  1497. case IR_SUB: as->curins--; asm_sub64(as, ir); break;
  1498. case IR_NEG: as->curins--; asm_neg64(as, ir); break;
  1499. case IR_CALLN:
  1500. case IR_CALLXS:
  1501. if (!uselo)
  1502. ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
  1503. break;
  1504. case IR_CNEWI:
  1505. /* Nothing to do here. Handled by lo op itself. */
  1506. break;
  1507. default: lua_assert(0); break;
  1508. }
  1509. #else
  1510. UNUSED(as); UNUSED(ir); lua_assert(0); /* Unused without FFI. */
  1511. #endif
  1512. }
  1513. /* -- Stack handling ------------------------------------------------------ */
  1514. /* Check Lua stack size for overflow. Use exit handler as fallback. */
  1515. static void asm_stack_check(ASMState *as, BCReg topslot,
  1516. IRIns *irp, RegSet allow, ExitNo exitno)
  1517. {
  1518. /* Try to get an unused temp. register, otherwise spill/restore RID_RET*. */
  1519. Reg tmp, pbase = irp ? (ra_hasreg(irp->r) ? irp->r : RID_TMP) : RID_BASE;
  1520. ExitNo oldsnap = as->snapno;
  1521. rset_clear(allow, pbase);
  1522. tmp = allow ? rset_pickbot(allow) :
  1523. (pbase == RID_RETHI ? RID_RETLO : RID_RETHI);
  1524. as->snapno = exitno;
  1525. asm_guard(as, MIPSI_BNE, RID_TMP, RID_ZERO);
  1526. as->snapno = oldsnap;
  1527. if (allow == RSET_EMPTY) /* Restore temp. register. */
  1528. emit_tsi(as, MIPSI_LW, tmp, RID_SP, 0);
  1529. else
  1530. ra_modified(as, tmp);
  1531. emit_tsi(as, MIPSI_SLTIU, RID_TMP, RID_TMP, (int32_t)(8*topslot));
  1532. emit_dst(as, MIPSI_SUBU, RID_TMP, tmp, pbase);
  1533. emit_tsi(as, MIPSI_LW, tmp, tmp, offsetof(lua_State, maxstack));
  1534. if (pbase == RID_TMP)
  1535. emit_getgl(as, RID_TMP, jit_base);
  1536. emit_getgl(as, tmp, jit_L);
  1537. if (allow == RSET_EMPTY) /* Spill temp. register. */
  1538. emit_tsi(as, MIPSI_SW, tmp, RID_SP, 0);
  1539. }
  1540. /* Restore Lua stack from on-trace state. */
  1541. static void asm_stack_restore(ASMState *as, SnapShot *snap)
  1542. {
  1543. SnapEntry *map = &as->T->snapmap[snap->mapofs];
  1544. SnapEntry *flinks = &as->T->snapmap[snap_nextofs(as->T, snap)-1];
  1545. MSize n, nent = snap->nent;
  1546. /* Store the value of all modified slots to the Lua stack. */
  1547. for (n = 0; n < nent; n++) {
  1548. SnapEntry sn = map[n];
  1549. BCReg s = snap_slot(sn);
  1550. int32_t ofs = 8*((int32_t)s-1);
  1551. IRRef ref = snap_ref(sn);
  1552. IRIns *ir = IR(ref);
  1553. if ((sn & SNAP_NORESTORE))
  1554. continue;
  1555. if (irt_isnum(ir->t)) {
  1556. Reg src = ra_alloc1(as, ref, RSET_FPR);
  1557. emit_hsi(as, MIPSI_SDC1, src, RID_BASE, ofs);
  1558. } else {
  1559. Reg type;
  1560. RegSet allow = rset_exclude(RSET_GPR, RID_BASE);
  1561. lua_assert(irt_ispri(ir->t) || irt_isaddr(ir->t) || irt_isinteger(ir->t));
  1562. if (!irt_ispri(ir->t)) {
  1563. Reg src = ra_alloc1(as, ref, allow);
  1564. rset_clear(allow, src);
  1565. emit_tsi(as, MIPSI_SW, src, RID_BASE, ofs+(LJ_BE?4:0));
  1566. }
  1567. if ((sn & (SNAP_CONT|SNAP_FRAME))) {
  1568. if (s == 0) continue; /* Do not overwrite link to previous frame. */
  1569. type = ra_allock(as, (int32_t)(*flinks--), allow);
  1570. } else {
  1571. type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow);
  1572. }
  1573. emit_tsi(as, MIPSI_SW, type, RID_BASE, ofs+(LJ_BE?0:4));
  1574. }
  1575. checkmclim(as);
  1576. }
  1577. lua_assert(map + nent == flinks);
  1578. }
  1579. /* -- GC handling --------------------------------------------------------- */
  1580. /* Check GC threshold and do one or more GC steps. */
  1581. static void asm_gc_check(ASMState *as)
  1582. {
  1583. const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_gc_step_jit];
  1584. IRRef args[2];
  1585. MCLabel l_end;
  1586. Reg tmp;
  1587. ra_evictset(as, RSET_SCRATCH);
  1588. l_end = emit_label(as);
  1589. /* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */
  1590. /* Assumes asm_snap_prep() already done. */
  1591. asm_guard(as, MIPSI_BNE, RID_RET, RID_ZERO);
  1592. args[0] = ASMREF_TMP1; /* global_State *g */
  1593. args[1] = ASMREF_TMP2; /* MSize steps */
  1594. asm_gencall(as, ci, args);
  1595. emit_tsi(as, MIPSI_ADDIU, ra_releasetmp(as, ASMREF_TMP1), RID_JGL, -32768);
  1596. tmp = ra_releasetmp(as, ASMREF_TMP2);
  1597. emit_loadi(as, tmp, as->gcsteps);
  1598. /* Jump around GC step if GC total < GC threshold. */
  1599. emit_branch(as, MIPSI_BNE, RID_TMP, RID_ZERO, l_end);
  1600. emit_dst(as, MIPSI_SLTU, RID_TMP, RID_TMP, tmp);
  1601. emit_getgl(as, tmp, gc.threshold);
  1602. emit_getgl(as, RID_TMP, gc.total);
  1603. as->gcsteps = 0;
  1604. checkmclim(as);
  1605. }
  1606. /* -- Loop handling ------------------------------------------------------- */
  1607. /* Fixup the loop branch. */
  1608. static void asm_loop_fixup(ASMState *as)
  1609. {
  1610. MCode *p = as->mctop;
  1611. MCode *target = as->mcp;
  1612. p[-1] = MIPSI_NOP;
  1613. if (as->loopinv) { /* Inverted loop branch? */
  1614. /* asm_guard already inverted the cond branch. Only patch the target. */
  1615. p[-3] |= ((target-p+2) & 0x0000ffffu);
  1616. } else {
  1617. p[-2] = MIPSI_J|(((uintptr_t)target>>2)&0x03ffffffu);
  1618. }
  1619. }
  1620. /* -- Head of trace ------------------------------------------------------- */
  1621. /* Coalesce BASE register for a root trace. */
  1622. static void asm_head_root_base(ASMState *as)
  1623. {
  1624. IRIns *ir = IR(REF_BASE);
  1625. Reg r = ir->r;
  1626. if (as->loopinv) as->mctop--;
  1627. if (ra_hasreg(r)) {
  1628. ra_free(as, r);
  1629. if (rset_test(as->modset, r) || irt_ismarked(ir->t))
  1630. ir->r = RID_INIT; /* No inheritance for modified BASE register. */
  1631. if (r != RID_BASE)
  1632. emit_move(as, r, RID_BASE);
  1633. }
  1634. }
  1635. /* Coalesce BASE register for a side trace. */
  1636. static RegSet asm_head_side_base(ASMState *as, IRIns *irp, RegSet allow)
  1637. {
  1638. IRIns *ir = IR(REF_BASE);
  1639. Reg r = ir->r;
  1640. if (as->loopinv) as->mctop--;
  1641. if (ra_hasreg(r)) {
  1642. ra_free(as, r);
  1643. if (rset_test(as->modset, r) || irt_ismarked(ir->t))
  1644. ir->r = RID_INIT; /* No inheritance for modified BASE register. */
  1645. if (irp->r == r) {
  1646. rset_clear(allow, r); /* Mark same BASE register as coalesced. */
  1647. } else if (ra_hasreg(irp->r) && rset_test(as->freeset, irp->r)) {
  1648. rset_clear(allow, irp->r);
  1649. emit_move(as, r, irp->r); /* Move from coalesced parent reg. */
  1650. } else {
  1651. emit_getgl(as, r, jit_base); /* Otherwise reload BASE. */
  1652. }
  1653. }
  1654. return allow;
  1655. }
  1656. /* -- Tail of trace ------------------------------------------------------- */
  1657. /* Fixup the tail code. */
  1658. static void asm_tail_fixup(ASMState *as, TraceNo lnk)
  1659. {
  1660. MCode *target = lnk ? traceref(as->J,lnk)->mcode : (MCode *)lj_vm_exit_interp;
  1661. int32_t spadj = as->T->spadjust;
  1662. MCode *p = as->mctop-1;
  1663. *p = spadj ? (MIPSI_ADDIU|MIPSF_T(RID_SP)|MIPSF_S(RID_SP)|spadj) : MIPSI_NOP;
  1664. p[-1] = MIPSI_J|(((uintptr_t)target>>2)&0x03ffffffu);
  1665. }
  1666. /* Prepare tail of code. */
  1667. static void asm_tail_prep(ASMState *as)
  1668. {
  1669. as->mcp = as->mctop-2; /* Leave room for branch plus nop or stack adj. */
  1670. as->invmcp = as->loopref ? as->mcp : NULL;
  1671. }
  1672. /* -- Instruction dispatch ------------------------------------------------ */
  1673. /* Assemble a single instruction. */
  1674. static void asm_ir(ASMState *as, IRIns *ir)
  1675. {
  1676. switch ((IROp)ir->o) {
  1677. /* Miscellaneous ops. */
  1678. case IR_LOOP: asm_loop(as); break;
  1679. case IR_NOP: case IR_XBAR: lua_assert(!ra_used(ir)); break;
  1680. case IR_USE:
  1681. ra_alloc1(as, ir->op1, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); break;
  1682. case IR_PHI: asm_phi(as, ir); break;
  1683. case IR_HIOP: asm_hiop(as, ir); break;
  1684. case IR_GCSTEP: asm_gcstep(as, ir); break;
  1685. /* Guarded assertions. */
  1686. case IR_EQ: case IR_NE: asm_compeq(as, ir); break;
  1687. case IR_LT: case IR_GE: case IR_LE: case IR_GT:
  1688. case IR_ULT: case IR_UGE: case IR_ULE: case IR_UGT:
  1689. case IR_ABC:
  1690. asm_comp(as, ir);
  1691. break;
  1692. case IR_RETF: asm_retf(as, ir); break;
  1693. /* Bit ops. */
  1694. case IR_BNOT: asm_bitnot(as, ir); break;
  1695. case IR_BSWAP: asm_bitswap(as, ir); break;
  1696. case IR_BAND: asm_bitop(as, ir, MIPSI_AND, MIPSI_ANDI); break;
  1697. case IR_BOR: asm_bitop(as, ir, MIPSI_OR, MIPSI_ORI); break;
  1698. case IR_BXOR: asm_bitop(as, ir, MIPSI_XOR, MIPSI_XORI); break;
  1699. case IR_BSHL: asm_bitshift(as, ir, MIPSI_SLLV, MIPSI_SLL); break;
  1700. case IR_BSHR: asm_bitshift(as, ir, MIPSI_SRLV, MIPSI_SRL); break;
  1701. case IR_BSAR: asm_bitshift(as, ir, MIPSI_SRAV, MIPSI_SRA); break;
  1702. case IR_BROL: lua_assert(0); break;
  1703. case IR_BROR: asm_bitror(as, ir); break;
  1704. /* Arithmetic ops. */
  1705. case IR_ADD: asm_add(as, ir); break;
  1706. case IR_SUB: asm_sub(as, ir); break;
  1707. case IR_MUL: asm_mul(as, ir); break;
  1708. case IR_DIV: asm_fparith(as, ir, MIPSI_DIV_D); break;
  1709. case IR_MOD: asm_callid(as, ir, IRCALL_lj_vm_modi); break;
  1710. case IR_POW: asm_callid(as, ir, IRCALL_lj_vm_powi); break;
  1711. case IR_NEG: asm_neg(as, ir); break;
  1712. case IR_ABS: asm_fpunary(as, ir, MIPSI_ABS_D); break;
  1713. case IR_ATAN2: asm_callid(as, ir, IRCALL_atan2); break;
  1714. case IR_LDEXP: asm_callid(as, ir, IRCALL_ldexp); break;
  1715. case IR_MIN: asm_min_max(as, ir, 0); break;
  1716. case IR_MAX: asm_min_max(as, ir, 1); break;
  1717. case IR_FPMATH:
  1718. if (ir->op2 == IRFPM_EXP2 && asm_fpjoin_pow(as, ir))
  1719. break;
  1720. if (ir->op2 <= IRFPM_TRUNC)
  1721. asm_callround(as, ir, IRCALL_lj_vm_floor + ir->op2);
  1722. else if (ir->op2 == IRFPM_SQRT)
  1723. asm_fpunary(as, ir, MIPSI_SQRT_D);
  1724. else
  1725. asm_callid(as, ir, IRCALL_lj_vm_floor + ir->op2);
  1726. break;
  1727. /* Overflow-checking arithmetic ops. */
  1728. case IR_ADDOV: asm_arithov(as, ir); break;
  1729. case IR_SUBOV: asm_arithov(as, ir); break;
  1730. case IR_MULOV: asm_mulov(as, ir); break;
  1731. /* Memory references. */
  1732. case IR_AREF: asm_aref(as, ir); break;
  1733. case IR_HREF: asm_href(as, ir); break;
  1734. case IR_HREFK: asm_hrefk(as, ir); break;
  1735. case IR_NEWREF: asm_newref(as, ir); break;
  1736. case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break;
  1737. case IR_FREF: asm_fref(as, ir); break;
  1738. case IR_STRREF: asm_strref(as, ir); break;
  1739. /* Loads and stores. */
  1740. case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD:
  1741. asm_ahuvload(as, ir);
  1742. break;
  1743. case IR_FLOAD: asm_fload(as, ir); break;
  1744. case IR_XLOAD: asm_xload(as, ir); break;
  1745. case IR_SLOAD: asm_sload(as, ir); break;
  1746. case IR_ASTORE: case IR_HSTORE: case IR_USTORE: asm_ahustore(as, ir); break;
  1747. case IR_FSTORE: asm_fstore(as, ir); break;
  1748. case IR_XSTORE: asm_xstore(as, ir, 0); break;
  1749. /* Allocations. */
  1750. case IR_SNEW: case IR_XSNEW: asm_snew(as, ir); break;
  1751. case IR_TNEW: asm_tnew(as, ir); break;
  1752. case IR_TDUP: asm_tdup(as, ir); break;
  1753. case IR_CNEW: case IR_CNEWI: asm_cnew(as, ir); break;
  1754. /* Write barriers. */
  1755. case IR_TBAR: asm_tbar(as, ir); break;
  1756. case IR_OBAR: asm_obar(as, ir); break;
  1757. /* Type conversions. */
  1758. case IR_CONV: asm_conv(as, ir); break;
  1759. case IR_TOBIT: asm_tobit(as, ir); break;
  1760. case IR_TOSTR: asm_tostr(as, ir); break;
  1761. case IR_STRTO: asm_strto(as, ir); break;
  1762. /* Calls. */
  1763. case IR_CALLN: case IR_CALLL: case IR_CALLS: asm_call(as, ir); break;
  1764. case IR_CALLXS: asm_callx(as, ir); break;
  1765. case IR_CARG: break;
  1766. default:
  1767. setintV(&as->J->errinfo, ir->o);
  1768. lj_trace_err_info(as->J, LJ_TRERR_NYIIR);
  1769. break;
  1770. }
  1771. }
  1772. /* -- Trace setup --------------------------------------------------------- */
  1773. /* Ensure there are enough stack slots for call arguments. */
  1774. static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci)
  1775. {
  1776. IRRef args[CCI_NARGS_MAX*2];
  1777. uint32_t i, nargs = (int)CCI_NARGS(ci);
  1778. int nslots = 4, ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR;
  1779. asm_collectargs(as, ir, ci, args);
  1780. for (i = 0; i < nargs; i++) {
  1781. if (args[i] && irt_isfp(IR(args[i])->t) &&
  1782. nfpr > 0 && !(ci->flags & CCI_VARARG)) {
  1783. nfpr--;
  1784. ngpr -= irt_isnum(IR(args[i])->t) ? 2 : 1;
  1785. } else if (args[i] && irt_isnum(IR(args[i])->t)) {
  1786. nfpr = 0;
  1787. ngpr = ngpr & ~1;
  1788. if (ngpr > 0) ngpr -= 2; else nslots = (nslots+3) & ~1;
  1789. } else {
  1790. nfpr = 0;
  1791. if (ngpr > 0) ngpr--; else nslots++;
  1792. }
  1793. }
  1794. if (nslots > as->evenspill) /* Leave room for args in stack slots. */
  1795. as->evenspill = nslots;
  1796. return irt_isfp(ir->t) ? REGSP_HINT(RID_FPRET) : REGSP_HINT(RID_RET);
  1797. }
  1798. static void asm_setup_target(ASMState *as)
  1799. {
  1800. asm_sparejump_setup(as);
  1801. asm_exitstub_setup(as);
  1802. }
  1803. /* -- Trace patching ------------------------------------------------------ */
  1804. /* Patch exit jumps of existing machine code to a new target. */
  1805. void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
  1806. {
  1807. MCode *p = T->mcode;
  1808. MCode *pe = (MCode *)((char *)p + T->szmcode);
  1809. MCode *px = exitstub_trace_addr(T, exitno);
  1810. MCode *cstart = NULL, *cstop = NULL;
  1811. MCode *mcarea = lj_mcode_patch(J, p, 0);
  1812. MCode exitload = MIPSI_LI | MIPSF_T(RID_TMP) | exitno;
  1813. MCode tjump = MIPSI_J|(((uintptr_t)target>>2)&0x03ffffffu);
  1814. for (p++; p < pe; p++) {
  1815. if (*p == exitload) { /* Look for load of exit number. */
  1816. if (((p[-1] ^ (px-p)) & 0xffffu) == 0) { /* Look for exitstub branch. */
  1817. ptrdiff_t delta = target - p;
  1818. if (((delta + 0x8000) >> 16) == 0) { /* Patch in-range branch. */
  1819. patchbranch:
  1820. p[-1] = (p[-1] & 0xffff0000u) | (delta & 0xffffu);
  1821. *p = MIPSI_NOP; /* Replace the load of the exit number. */
  1822. cstop = p;
  1823. if (!cstart) cstart = p-1;
  1824. } else { /* Branch out of range. Use spare jump slot in mcarea. */
  1825. int i;
  1826. for (i = 2; i < 2+MIPS_SPAREJUMP*2; i += 2) {
  1827. if (mcarea[i] == tjump) {
  1828. delta = mcarea+i - p;
  1829. goto patchbranch;
  1830. } else if (mcarea[i] == MIPSI_NOP) {
  1831. mcarea[i] = tjump;
  1832. cstart = mcarea+i;
  1833. delta = mcarea+i - p;
  1834. goto patchbranch;
  1835. }
  1836. }
  1837. /* Ignore jump slot overflow. Child trace is simply not attached. */
  1838. }
  1839. } else if (p+1 == pe) {
  1840. /* Patch NOP after code for inverted loop branch. Use of J is ok. */
  1841. lua_assert(p[1] == MIPSI_NOP);
  1842. p[1] = tjump;
  1843. *p = MIPSI_NOP; /* Replace the load of the exit number. */
  1844. cstop = p+2;
  1845. if (!cstart) cstart = p+1;
  1846. }
  1847. }
  1848. }
  1849. if (cstart) lj_mcode_sync(cstart, cstop);
  1850. lj_mcode_patch(J, mcarea, 1);
  1851. }