diff options
Diffstat (limited to 'src/lj_asm_mips.h')
-rw-r--r-- | src/lj_asm_mips.h | 1590 |
1 files changed, 1178 insertions, 412 deletions
diff --git a/src/lj_asm_mips.h b/src/lj_asm_mips.h index 190a55eb..9309b781 100644 --- a/src/lj_asm_mips.h +++ b/src/lj_asm_mips.h | |||
@@ -23,7 +23,7 @@ static Reg ra_alloc1z(ASMState *as, IRRef ref, RegSet allow) | |||
23 | { | 23 | { |
24 | Reg r = IR(ref)->r; | 24 | Reg r = IR(ref)->r; |
25 | if (ra_noreg(r)) { | 25 | if (ra_noreg(r)) { |
26 | if (!(allow & RSET_FPR) && irref_isk(ref) && IR(ref)->i == 0) | 26 | if (!(allow & RSET_FPR) && irref_isk(ref) && get_kval(IR(ref)) == 0) |
27 | return RID_ZERO; | 27 | return RID_ZERO; |
28 | r = ra_allocref(as, ref, allow); | 28 | r = ra_allocref(as, ref, allow); |
29 | } else { | 29 | } else { |
@@ -101,7 +101,12 @@ static void asm_guard(ASMState *as, MIPSIns mi, Reg rs, Reg rt) | |||
101 | as->invmcp = NULL; | 101 | as->invmcp = NULL; |
102 | as->loopinv = 1; | 102 | as->loopinv = 1; |
103 | as->mcp = p+1; | 103 | as->mcp = p+1; |
104 | #if !LJ_TARGET_MIPSR6 | ||
104 | mi = mi ^ ((mi>>28) == 1 ? 0x04000000u : 0x00010000u); /* Invert cond. */ | 105 | mi = mi ^ ((mi>>28) == 1 ? 0x04000000u : 0x00010000u); /* Invert cond. */ |
106 | #else | ||
107 | mi = mi ^ ((mi>>28) == 1 ? 0x04000000u : | ||
108 | (mi>>28) == 4 ? 0x00800000u : 0x00010000u); /* Invert cond. */ | ||
109 | #endif | ||
105 | target = p; /* Patch target later in asm_loop_fixup. */ | 110 | target = p; /* Patch target later in asm_loop_fixup. */ |
106 | } | 111 | } |
107 | emit_ti(as, MIPSI_LI, RID_TMP, as->snapno); | 112 | emit_ti(as, MIPSI_LI, RID_TMP, as->snapno); |
@@ -165,9 +170,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow) | |||
165 | } else if (ir->o == IR_UREFC) { | 170 | } else if (ir->o == IR_UREFC) { |
166 | if (irref_isk(ir->op1)) { | 171 | if (irref_isk(ir->op1)) { |
167 | GCfunc *fn = ir_kfunc(IR(ir->op1)); | 172 | GCfunc *fn = ir_kfunc(IR(ir->op1)); |
168 | int32_t ofs = i32ptr(&gcref(fn->l.uvptr[(ir->op2 >> 8)])->uv.tv); | 173 | intptr_t ofs = (intptr_t)&gcref(fn->l.uvptr[(ir->op2 >> 8)])->uv.tv; |
169 | int32_t jgl = (intptr_t)J2G(as->J); | 174 | intptr_t jgl = (intptr_t)J2G(as->J); |
170 | if ((uint32_t)(ofs-jgl) < 65536) { | 175 | if ((uintptr_t)(ofs-jgl) < 65536) { |
171 | *ofsp = ofs-jgl-32768; | 176 | *ofsp = ofs-jgl-32768; |
172 | return RID_JGL; | 177 | return RID_JGL; |
173 | } else { | 178 | } else { |
@@ -189,20 +194,21 @@ static void asm_fusexref(ASMState *as, MIPSIns mi, Reg rt, IRRef ref, | |||
189 | Reg base; | 194 | Reg base; |
190 | if (ra_noreg(ir->r) && canfuse(as, ir)) { | 195 | if (ra_noreg(ir->r) && canfuse(as, ir)) { |
191 | if (ir->o == IR_ADD) { | 196 | if (ir->o == IR_ADD) { |
192 | int32_t ofs2; | 197 | intptr_t ofs2; |
193 | if (irref_isk(ir->op2) && (ofs2 = ofs + IR(ir->op2)->i, checki16(ofs2))) { | 198 | if (irref_isk(ir->op2) && (ofs2 = ofs + get_kval(IR(ir->op2)), |
199 | checki16(ofs2))) { | ||
194 | ref = ir->op1; | 200 | ref = ir->op1; |
195 | ofs = ofs2; | 201 | ofs = (int32_t)ofs2; |
196 | } | 202 | } |
197 | } else if (ir->o == IR_STRREF) { | 203 | } else if (ir->o == IR_STRREF) { |
198 | int32_t ofs2 = 65536; | 204 | intptr_t ofs2 = 65536; |
199 | lua_assert(ofs == 0); | 205 | lua_assert(ofs == 0); |
200 | ofs = (int32_t)sizeof(GCstr); | 206 | ofs = (int32_t)sizeof(GCstr); |
201 | if (irref_isk(ir->op2)) { | 207 | if (irref_isk(ir->op2)) { |
202 | ofs2 = ofs + IR(ir->op2)->i; | 208 | ofs2 = ofs + get_kval(IR(ir->op2)); |
203 | ref = ir->op1; | 209 | ref = ir->op1; |
204 | } else if (irref_isk(ir->op1)) { | 210 | } else if (irref_isk(ir->op1)) { |
205 | ofs2 = ofs + IR(ir->op1)->i; | 211 | ofs2 = ofs + get_kval(IR(ir->op1)); |
206 | ref = ir->op2; | 212 | ref = ir->op2; |
207 | } | 213 | } |
208 | if (!checki16(ofs2)) { | 214 | if (!checki16(ofs2)) { |
@@ -210,7 +216,7 @@ static void asm_fusexref(ASMState *as, MIPSIns mi, Reg rt, IRRef ref, | |||
210 | Reg right, left = ra_alloc2(as, ir, allow); | 216 | Reg right, left = ra_alloc2(as, ir, allow); |
211 | right = (left >> 8); left &= 255; | 217 | right = (left >> 8); left &= 255; |
212 | emit_hsi(as, mi, rt, RID_TMP, ofs); | 218 | emit_hsi(as, mi, rt, RID_TMP, ofs); |
213 | emit_dst(as, MIPSI_ADDU, RID_TMP, left, right); | 219 | emit_dst(as, MIPSI_AADDU, RID_TMP, left, right); |
214 | return; | 220 | return; |
215 | } | 221 | } |
216 | ofs = ofs2; | 222 | ofs = ofs2; |
@@ -225,29 +231,41 @@ static void asm_fusexref(ASMState *as, MIPSIns mi, Reg rt, IRRef ref, | |||
225 | /* Generate a call to a C function. */ | 231 | /* Generate a call to a C function. */ |
226 | static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | 232 | static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) |
227 | { | 233 | { |
228 | uint32_t n, nargs = CCI_NARGS(ci); | 234 | uint32_t n, nargs = CCI_XNARGS(ci); |
229 | int32_t ofs = 16; | 235 | int32_t ofs = LJ_32 ? 16 : 0; |
236 | #if LJ_SOFTFP | ||
237 | Reg gpr = REGARG_FIRSTGPR; | ||
238 | #else | ||
230 | Reg gpr, fpr = REGARG_FIRSTFPR; | 239 | Reg gpr, fpr = REGARG_FIRSTFPR; |
240 | #endif | ||
231 | if ((void *)ci->func) | 241 | if ((void *)ci->func) |
232 | emit_call(as, (void *)ci->func); | 242 | emit_call(as, (void *)ci->func, 1); |
243 | #if !LJ_SOFTFP | ||
233 | for (gpr = REGARG_FIRSTGPR; gpr <= REGARG_LASTGPR; gpr++) | 244 | for (gpr = REGARG_FIRSTGPR; gpr <= REGARG_LASTGPR; gpr++) |
234 | as->cost[gpr] = REGCOST(~0u, ASMREF_L); | 245 | as->cost[gpr] = REGCOST(~0u, ASMREF_L); |
235 | gpr = REGARG_FIRSTGPR; | 246 | gpr = REGARG_FIRSTGPR; |
247 | #endif | ||
236 | for (n = 0; n < nargs; n++) { /* Setup args. */ | 248 | for (n = 0; n < nargs; n++) { /* Setup args. */ |
237 | IRRef ref = args[n]; | 249 | IRRef ref = args[n]; |
238 | if (ref) { | 250 | if (ref) { |
239 | IRIns *ir = IR(ref); | 251 | IRIns *ir = IR(ref); |
252 | #if !LJ_SOFTFP | ||
240 | if (irt_isfp(ir->t) && fpr <= REGARG_LASTFPR && | 253 | if (irt_isfp(ir->t) && fpr <= REGARG_LASTFPR && |
241 | !(ci->flags & CCI_VARARG)) { | 254 | !(ci->flags & CCI_VARARG)) { |
242 | lua_assert(rset_test(as->freeset, fpr)); /* Already evicted. */ | 255 | lua_assert(rset_test(as->freeset, fpr)); /* Already evicted. */ |
243 | ra_leftov(as, fpr, ref); | 256 | ra_leftov(as, fpr, ref); |
244 | fpr += 2; | 257 | fpr += LJ_32 ? 2 : 1; |
245 | gpr += irt_isnum(ir->t) ? 2 : 1; | 258 | gpr += (LJ_32 && irt_isnum(ir->t)) ? 2 : 1; |
246 | } else { | 259 | } else |
260 | #endif | ||
261 | { | ||
262 | #if LJ_32 && !LJ_SOFTFP | ||
247 | fpr = REGARG_LASTFPR+1; | 263 | fpr = REGARG_LASTFPR+1; |
248 | if (irt_isnum(ir->t)) gpr = (gpr+1) & ~1; | 264 | #endif |
265 | if (LJ_32 && irt_isnum(ir->t)) gpr = (gpr+1) & ~1; | ||
249 | if (gpr <= REGARG_LASTGPR) { | 266 | if (gpr <= REGARG_LASTGPR) { |
250 | lua_assert(rset_test(as->freeset, gpr)); /* Already evicted. */ | 267 | lua_assert(rset_test(as->freeset, gpr)); /* Already evicted. */ |
268 | #if !LJ_SOFTFP | ||
251 | if (irt_isfp(ir->t)) { | 269 | if (irt_isfp(ir->t)) { |
252 | RegSet of = as->freeset; | 270 | RegSet of = as->freeset; |
253 | Reg r; | 271 | Reg r; |
@@ -256,31 +274,55 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | |||
256 | r = ra_alloc1(as, ref, RSET_FPR); | 274 | r = ra_alloc1(as, ref, RSET_FPR); |
257 | as->freeset |= (of & RSET_RANGE(REGARG_FIRSTGPR, REGARG_LASTGPR+1)); | 275 | as->freeset |= (of & RSET_RANGE(REGARG_FIRSTGPR, REGARG_LASTGPR+1)); |
258 | if (irt_isnum(ir->t)) { | 276 | if (irt_isnum(ir->t)) { |
277 | #if LJ_32 | ||
259 | emit_tg(as, MIPSI_MFC1, gpr+(LJ_BE?0:1), r+1); | 278 | emit_tg(as, MIPSI_MFC1, gpr+(LJ_BE?0:1), r+1); |
260 | emit_tg(as, MIPSI_MFC1, gpr+(LJ_BE?1:0), r); | 279 | emit_tg(as, MIPSI_MFC1, gpr+(LJ_BE?1:0), r); |
261 | lua_assert(rset_test(as->freeset, gpr+1)); /* Already evicted. */ | 280 | lua_assert(rset_test(as->freeset, gpr+1)); /* Already evicted. */ |
262 | gpr += 2; | 281 | gpr += 2; |
282 | #else | ||
283 | emit_tg(as, MIPSI_DMFC1, gpr, r); | ||
284 | gpr++; fpr++; | ||
285 | #endif | ||
263 | } else if (irt_isfloat(ir->t)) { | 286 | } else if (irt_isfloat(ir->t)) { |
264 | emit_tg(as, MIPSI_MFC1, gpr, r); | 287 | emit_tg(as, MIPSI_MFC1, gpr, r); |
265 | gpr++; | 288 | gpr++; |
289 | #if LJ_64 | ||
290 | fpr++; | ||
291 | #endif | ||
266 | } | 292 | } |
267 | } else { | 293 | } else |
294 | #endif | ||
295 | { | ||
268 | ra_leftov(as, gpr, ref); | 296 | ra_leftov(as, gpr, ref); |
269 | gpr++; | 297 | gpr++; |
298 | #if LJ_64 && !LJ_SOFTFP | ||
299 | fpr++; | ||
300 | #endif | ||
270 | } | 301 | } |
271 | } else { | 302 | } else { |
272 | Reg r = ra_alloc1z(as, ref, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); | 303 | Reg r = ra_alloc1z(as, ref, !LJ_SOFTFP && irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); |
304 | #if LJ_32 | ||
273 | if (irt_isnum(ir->t)) ofs = (ofs + 4) & ~4; | 305 | if (irt_isnum(ir->t)) ofs = (ofs + 4) & ~4; |
274 | emit_spstore(as, ir, r, ofs); | 306 | emit_spstore(as, ir, r, ofs); |
275 | ofs += irt_isnum(ir->t) ? 8 : 4; | 307 | ofs += irt_isnum(ir->t) ? 8 : 4; |
308 | #else | ||
309 | emit_spstore(as, ir, r, ofs + ((LJ_BE && !irt_isfp(ir->t) && !irt_is64(ir->t)) ? 4 : 0)); | ||
310 | ofs += 8; | ||
311 | #endif | ||
276 | } | 312 | } |
277 | } | 313 | } |
278 | } else { | 314 | } else { |
315 | #if !LJ_SOFTFP | ||
279 | fpr = REGARG_LASTFPR+1; | 316 | fpr = REGARG_LASTFPR+1; |
280 | if (gpr <= REGARG_LASTGPR) | 317 | #endif |
318 | if (gpr <= REGARG_LASTGPR) { | ||
281 | gpr++; | 319 | gpr++; |
282 | else | 320 | #if LJ_64 && !LJ_SOFTFP |
283 | ofs += 4; | 321 | fpr++; |
322 | #endif | ||
323 | } else { | ||
324 | ofs += LJ_32 ? 4 : 8; | ||
325 | } | ||
284 | } | 326 | } |
285 | checkmclim(as); | 327 | checkmclim(as); |
286 | } | 328 | } |
@@ -290,50 +332,57 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | |||
290 | static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) | 332 | static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) |
291 | { | 333 | { |
292 | RegSet drop = RSET_SCRATCH; | 334 | RegSet drop = RSET_SCRATCH; |
335 | #if LJ_32 | ||
293 | int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t)); | 336 | int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t)); |
337 | #endif | ||
338 | #if !LJ_SOFTFP | ||
294 | if ((ci->flags & CCI_NOFPRCLOBBER)) | 339 | if ((ci->flags & CCI_NOFPRCLOBBER)) |
295 | drop &= ~RSET_FPR; | 340 | drop &= ~RSET_FPR; |
341 | #endif | ||
296 | if (ra_hasreg(ir->r)) | 342 | if (ra_hasreg(ir->r)) |
297 | rset_clear(drop, ir->r); /* Dest reg handled below. */ | 343 | rset_clear(drop, ir->r); /* Dest reg handled below. */ |
344 | #if LJ_32 | ||
298 | if (hiop && ra_hasreg((ir+1)->r)) | 345 | if (hiop && ra_hasreg((ir+1)->r)) |
299 | rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */ | 346 | rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */ |
347 | #endif | ||
300 | ra_evictset(as, drop); /* Evictions must be performed first. */ | 348 | ra_evictset(as, drop); /* Evictions must be performed first. */ |
301 | if (ra_used(ir)) { | 349 | if (ra_used(ir)) { |
302 | lua_assert(!irt_ispri(ir->t)); | 350 | lua_assert(!irt_ispri(ir->t)); |
303 | if (irt_isfp(ir->t)) { | 351 | if (!LJ_SOFTFP && irt_isfp(ir->t)) { |
304 | if ((ci->flags & CCI_CASTU64)) { | 352 | if ((ci->flags & CCI_CASTU64)) { |
305 | int32_t ofs = sps_scale(ir->s); | 353 | int32_t ofs = sps_scale(ir->s); |
306 | Reg dest = ir->r; | 354 | Reg dest = ir->r; |
307 | if (ra_hasreg(dest)) { | 355 | if (ra_hasreg(dest)) { |
308 | ra_free(as, dest); | 356 | ra_free(as, dest); |
309 | ra_modified(as, dest); | 357 | ra_modified(as, dest); |
358 | #if LJ_32 | ||
310 | emit_tg(as, MIPSI_MTC1, RID_RETHI, dest+1); | 359 | emit_tg(as, MIPSI_MTC1, RID_RETHI, dest+1); |
311 | emit_tg(as, MIPSI_MTC1, RID_RETLO, dest); | 360 | emit_tg(as, MIPSI_MTC1, RID_RETLO, dest); |
361 | #else | ||
362 | emit_tg(as, MIPSI_DMTC1, RID_RET, dest); | ||
363 | #endif | ||
312 | } | 364 | } |
313 | if (ofs) { | 365 | if (ofs) { |
366 | #if LJ_32 | ||
314 | emit_tsi(as, MIPSI_SW, RID_RETLO, RID_SP, ofs+(LJ_BE?4:0)); | 367 | emit_tsi(as, MIPSI_SW, RID_RETLO, RID_SP, ofs+(LJ_BE?4:0)); |
315 | emit_tsi(as, MIPSI_SW, RID_RETHI, RID_SP, ofs+(LJ_BE?0:4)); | 368 | emit_tsi(as, MIPSI_SW, RID_RETHI, RID_SP, ofs+(LJ_BE?0:4)); |
369 | #else | ||
370 | emit_tsi(as, MIPSI_SD, RID_RET, RID_SP, ofs); | ||
371 | #endif | ||
316 | } | 372 | } |
317 | } else { | 373 | } else { |
318 | ra_destreg(as, ir, RID_FPRET); | 374 | ra_destreg(as, ir, RID_FPRET); |
319 | } | 375 | } |
376 | #if LJ_32 | ||
320 | } else if (hiop) { | 377 | } else if (hiop) { |
321 | ra_destpair(as, ir); | 378 | ra_destpair(as, ir); |
379 | #endif | ||
322 | } else { | 380 | } else { |
323 | ra_destreg(as, ir, RID_RET); | 381 | ra_destreg(as, ir, RID_RET); |
324 | } | 382 | } |
325 | } | 383 | } |
326 | } | 384 | } |
327 | 385 | ||
328 | static void asm_call(ASMState *as, IRIns *ir) | ||
329 | { | ||
330 | IRRef args[CCI_NARGS_MAX]; | ||
331 | const CCallInfo *ci = &lj_ir_callinfo[ir->op2]; | ||
332 | asm_collectargs(as, ir, ci, args); | ||
333 | asm_setupresult(as, ir, ci); | ||
334 | asm_gencall(as, ci, args); | ||
335 | } | ||
336 | |||
337 | static void asm_callx(ASMState *as, IRIns *ir) | 386 | static void asm_callx(ASMState *as, IRIns *ir) |
338 | { | 387 | { |
339 | IRRef args[CCI_NARGS_MAX*2]; | 388 | IRRef args[CCI_NARGS_MAX*2]; |
@@ -346,7 +395,7 @@ static void asm_callx(ASMState *as, IRIns *ir) | |||
346 | func = ir->op2; irf = IR(func); | 395 | func = ir->op2; irf = IR(func); |
347 | if (irf->o == IR_CARG) { func = irf->op1; irf = IR(func); } | 396 | if (irf->o == IR_CARG) { func = irf->op1; irf = IR(func); } |
348 | if (irref_isk(func)) { /* Call to constant address. */ | 397 | if (irref_isk(func)) { /* Call to constant address. */ |
349 | ci.func = (ASMFunction)(void *)(irf->i); | 398 | ci.func = (ASMFunction)(void *)get_kval(irf); |
350 | } else { /* Need specific register for indirect calls. */ | 399 | } else { /* Need specific register for indirect calls. */ |
351 | Reg r = ra_alloc1(as, func, RID2RSET(RID_CFUNCADDR)); | 400 | Reg r = ra_alloc1(as, func, RID2RSET(RID_CFUNCADDR)); |
352 | MCode *p = as->mcp; | 401 | MCode *p = as->mcp; |
@@ -361,27 +410,23 @@ static void asm_callx(ASMState *as, IRIns *ir) | |||
361 | asm_gencall(as, &ci, args); | 410 | asm_gencall(as, &ci, args); |
362 | } | 411 | } |
363 | 412 | ||
364 | static void asm_callid(ASMState *as, IRIns *ir, IRCallID id) | 413 | #if !LJ_SOFTFP |
365 | { | ||
366 | const CCallInfo *ci = &lj_ir_callinfo[id]; | ||
367 | IRRef args[2]; | ||
368 | args[0] = ir->op1; | ||
369 | args[1] = ir->op2; | ||
370 | asm_setupresult(as, ir, ci); | ||
371 | asm_gencall(as, ci, args); | ||
372 | } | ||
373 | |||
374 | static void asm_callround(ASMState *as, IRIns *ir, IRCallID id) | 414 | static void asm_callround(ASMState *as, IRIns *ir, IRCallID id) |
375 | { | 415 | { |
376 | /* The modified regs must match with the *.dasc implementation. */ | 416 | /* The modified regs must match with the *.dasc implementation. */ |
377 | RegSet drop = RID2RSET(RID_R1)|RID2RSET(RID_R12)|RID2RSET(RID_FPRET)| | 417 | RegSet drop = RID2RSET(RID_R1)|RID2RSET(RID_R12)|RID2RSET(RID_FPRET)| |
378 | RID2RSET(RID_F2)|RID2RSET(RID_F4)|RID2RSET(REGARG_FIRSTFPR); | 418 | RID2RSET(RID_F2)|RID2RSET(RID_F4)|RID2RSET(REGARG_FIRSTFPR) |
419 | #if LJ_TARGET_MIPSR6 | ||
420 | |RID2RSET(RID_F21) | ||
421 | #endif | ||
422 | ; | ||
379 | if (ra_hasreg(ir->r)) rset_clear(drop, ir->r); | 423 | if (ra_hasreg(ir->r)) rset_clear(drop, ir->r); |
380 | ra_evictset(as, drop); | 424 | ra_evictset(as, drop); |
381 | ra_destreg(as, ir, RID_FPRET); | 425 | ra_destreg(as, ir, RID_FPRET); |
382 | emit_call(as, (void *)lj_ir_callinfo[id].func); | 426 | emit_call(as, (void *)lj_ir_callinfo[id].func, 0); |
383 | ra_leftov(as, REGARG_FIRSTFPR, ir->op1); | 427 | ra_leftov(as, REGARG_FIRSTFPR, ir->op1); |
384 | } | 428 | } |
429 | #endif | ||
385 | 430 | ||
386 | /* -- Returns ------------------------------------------------------------- */ | 431 | /* -- Returns ------------------------------------------------------------- */ |
387 | 432 | ||
@@ -390,25 +435,31 @@ static void asm_retf(ASMState *as, IRIns *ir) | |||
390 | { | 435 | { |
391 | Reg base = ra_alloc1(as, REF_BASE, RSET_GPR); | 436 | Reg base = ra_alloc1(as, REF_BASE, RSET_GPR); |
392 | void *pc = ir_kptr(IR(ir->op2)); | 437 | void *pc = ir_kptr(IR(ir->op2)); |
393 | int32_t delta = 1+bc_a(*((const BCIns *)pc - 1)); | 438 | int32_t delta = 1+LJ_FR2+bc_a(*((const BCIns *)pc - 1)); |
394 | as->topslot -= (BCReg)delta; | 439 | as->topslot -= (BCReg)delta; |
395 | if ((int32_t)as->topslot < 0) as->topslot = 0; | 440 | if ((int32_t)as->topslot < 0) as->topslot = 0; |
396 | irt_setmark(IR(REF_BASE)->t); /* Children must not coalesce with BASE reg. */ | 441 | irt_setmark(IR(REF_BASE)->t); /* Children must not coalesce with BASE reg. */ |
397 | emit_setgl(as, base, jit_base); | 442 | emit_setgl(as, base, jit_base); |
398 | emit_addptr(as, base, -8*delta); | 443 | emit_addptr(as, base, -8*delta); |
399 | asm_guard(as, MIPSI_BNE, RID_TMP, | 444 | asm_guard(as, MIPSI_BNE, RID_TMP, |
400 | ra_allock(as, i32ptr(pc), rset_exclude(RSET_GPR, base))); | 445 | ra_allock(as, igcptr(pc), rset_exclude(RSET_GPR, base))); |
401 | emit_tsi(as, MIPSI_LW, RID_TMP, base, -8); | 446 | emit_tsi(as, MIPSI_AL, RID_TMP, base, -8); |
402 | } | 447 | } |
403 | 448 | ||
404 | /* -- Type conversions ---------------------------------------------------- */ | 449 | /* -- Type conversions ---------------------------------------------------- */ |
405 | 450 | ||
451 | #if !LJ_SOFTFP | ||
406 | static void asm_tointg(ASMState *as, IRIns *ir, Reg left) | 452 | static void asm_tointg(ASMState *as, IRIns *ir, Reg left) |
407 | { | 453 | { |
408 | Reg tmp = ra_scratch(as, rset_exclude(RSET_FPR, left)); | 454 | Reg tmp = ra_scratch(as, rset_exclude(RSET_FPR, left)); |
409 | Reg dest = ra_dest(as, ir, RSET_GPR); | 455 | Reg dest = ra_dest(as, ir, RSET_GPR); |
456 | #if !LJ_TARGET_MIPSR6 | ||
410 | asm_guard(as, MIPSI_BC1F, 0, 0); | 457 | asm_guard(as, MIPSI_BC1F, 0, 0); |
411 | emit_fgh(as, MIPSI_C_EQ_D, 0, tmp, left); | 458 | emit_fgh(as, MIPSI_C_EQ_D, 0, tmp, left); |
459 | #else | ||
460 | asm_guard(as, MIPSI_BC1EQZ, 0, (tmp&31)); | ||
461 | emit_fgh(as, MIPSI_CMP_EQ_D, tmp, tmp, left); | ||
462 | #endif | ||
412 | emit_fg(as, MIPSI_CVT_D_W, tmp, tmp); | 463 | emit_fg(as, MIPSI_CVT_D_W, tmp, tmp); |
413 | emit_tg(as, MIPSI_MFC1, dest, tmp); | 464 | emit_tg(as, MIPSI_MFC1, dest, tmp); |
414 | emit_fg(as, MIPSI_CVT_W_D, tmp, left); | 465 | emit_fg(as, MIPSI_CVT_W_D, tmp, left); |
@@ -424,15 +475,53 @@ static void asm_tobit(ASMState *as, IRIns *ir) | |||
424 | emit_tg(as, MIPSI_MFC1, dest, tmp); | 475 | emit_tg(as, MIPSI_MFC1, dest, tmp); |
425 | emit_fgh(as, MIPSI_ADD_D, tmp, left, right); | 476 | emit_fgh(as, MIPSI_ADD_D, tmp, left, right); |
426 | } | 477 | } |
478 | #elif LJ_64 /* && LJ_SOFTFP */ | ||
479 | static void asm_tointg(ASMState *as, IRIns *ir, Reg r) | ||
480 | { | ||
481 | /* The modified regs must match with the *.dasc implementation. */ | ||
482 | RegSet drop = RID2RSET(REGARG_FIRSTGPR)|RID2RSET(RID_RET)|RID2RSET(RID_RET+1)| | ||
483 | RID2RSET(RID_R1)|RID2RSET(RID_R12); | ||
484 | if (ra_hasreg(ir->r)) rset_clear(drop, ir->r); | ||
485 | ra_evictset(as, drop); | ||
486 | /* Return values are in RID_RET (converted value) and RID_RET+1 (status). */ | ||
487 | ra_destreg(as, ir, RID_RET); | ||
488 | asm_guard(as, MIPSI_BNE, RID_RET+1, RID_ZERO); | ||
489 | emit_call(as, (void *)lj_ir_callinfo[IRCALL_lj_vm_tointg].func, 0); | ||
490 | if (r == RID_NONE) | ||
491 | ra_leftov(as, REGARG_FIRSTGPR, ir->op1); | ||
492 | else if (r != REGARG_FIRSTGPR) | ||
493 | emit_move(as, REGARG_FIRSTGPR, r); | ||
494 | } | ||
495 | |||
496 | static void asm_tobit(ASMState *as, IRIns *ir) | ||
497 | { | ||
498 | Reg dest = ra_dest(as, ir, RSET_GPR); | ||
499 | emit_dta(as, MIPSI_SLL, dest, dest, 0); | ||
500 | asm_callid(as, ir, IRCALL_lj_vm_tobit); | ||
501 | } | ||
502 | #endif | ||
427 | 503 | ||
428 | static void asm_conv(ASMState *as, IRIns *ir) | 504 | static void asm_conv(ASMState *as, IRIns *ir) |
429 | { | 505 | { |
430 | IRType st = (IRType)(ir->op2 & IRCONV_SRCMASK); | 506 | IRType st = (IRType)(ir->op2 & IRCONV_SRCMASK); |
507 | #if !LJ_SOFTFP32 | ||
431 | int stfp = (st == IRT_NUM || st == IRT_FLOAT); | 508 | int stfp = (st == IRT_NUM || st == IRT_FLOAT); |
509 | #endif | ||
510 | #if LJ_64 | ||
511 | int st64 = (st == IRT_I64 || st == IRT_U64 || st == IRT_P64); | ||
512 | #endif | ||
432 | IRRef lref = ir->op1; | 513 | IRRef lref = ir->op1; |
433 | lua_assert(irt_type(ir->t) != st); | 514 | #if LJ_32 |
434 | lua_assert(!(irt_isint64(ir->t) || | 515 | lua_assert(!(irt_isint64(ir->t) || |
435 | (st == IRT_I64 || st == IRT_U64))); /* Handled by SPLIT. */ | 516 | (st == IRT_I64 || st == IRT_U64))); /* Handled by SPLIT. */ |
517 | #endif | ||
518 | #if LJ_SOFTFP32 | ||
519 | /* FP conversions are handled by SPLIT. */ | ||
520 | lua_assert(!irt_isfp(ir->t) && !(st == IRT_NUM || st == IRT_FLOAT)); | ||
521 | /* Can't check for same types: SPLIT uses CONV int.int + BXOR for sfp NEG. */ | ||
522 | #else | ||
523 | lua_assert(irt_type(ir->t) != st); | ||
524 | #if !LJ_SOFTFP | ||
436 | if (irt_isfp(ir->t)) { | 525 | if (irt_isfp(ir->t)) { |
437 | Reg dest = ra_dest(as, ir, RSET_FPR); | 526 | Reg dest = ra_dest(as, ir, RSET_FPR); |
438 | if (stfp) { /* FP to FP conversion. */ | 527 | if (stfp) { /* FP to FP conversion. */ |
@@ -448,16 +537,44 @@ static void asm_conv(ASMState *as, IRIns *ir) | |||
448 | emit_fgh(as, MIPSI_ADD_D, dest, dest, tmp); | 537 | emit_fgh(as, MIPSI_ADD_D, dest, dest, tmp); |
449 | emit_fg(as, MIPSI_CVT_D_W, dest, dest); | 538 | emit_fg(as, MIPSI_CVT_D_W, dest, dest); |
450 | emit_lsptr(as, MIPSI_LDC1, (tmp & 31), | 539 | emit_lsptr(as, MIPSI_LDC1, (tmp & 31), |
451 | (void *)lj_ir_k64_find(as->J, U64x(41e00000,00000000)), | 540 | (void *)&as->J->k64[LJ_K64_2P31], RSET_GPR); |
452 | RSET_GPR); | ||
453 | emit_tg(as, MIPSI_MTC1, RID_TMP, dest); | 541 | emit_tg(as, MIPSI_MTC1, RID_TMP, dest); |
454 | emit_dst(as, MIPSI_XOR, RID_TMP, RID_TMP, left); | 542 | emit_dst(as, MIPSI_XOR, RID_TMP, RID_TMP, left); |
455 | emit_ti(as, MIPSI_LUI, RID_TMP, 0x8000); | 543 | emit_ti(as, MIPSI_LUI, RID_TMP, 0x8000); |
544 | #if LJ_64 | ||
545 | } else if(st == IRT_U64) { /* U64 to FP conversion. */ | ||
546 | /* if (x >= 1u<<63) y = (double)(int64_t)(x&(1u<<63)-1) + pow(2.0, 63) */ | ||
547 | Reg left = ra_alloc1(as, lref, RSET_GPR); | ||
548 | Reg tmp = ra_scratch(as, rset_exclude(RSET_FPR, dest)); | ||
549 | MCLabel l_end = emit_label(as); | ||
550 | if (irt_isfloat(ir->t)) { | ||
551 | emit_fgh(as, MIPSI_ADD_S, dest, dest, tmp); | ||
552 | emit_lsptr(as, MIPSI_LWC1, (tmp & 31), (void *)&as->J->k32[LJ_K32_2P63], | ||
553 | rset_exclude(RSET_GPR, left)); | ||
554 | emit_fg(as, MIPSI_CVT_S_L, dest, dest); | ||
555 | } else { | ||
556 | emit_fgh(as, MIPSI_ADD_D, dest, dest, tmp); | ||
557 | emit_lsptr(as, MIPSI_LDC1, (tmp & 31), (void *)&as->J->k64[LJ_K64_2P63], | ||
558 | rset_exclude(RSET_GPR, left)); | ||
559 | emit_fg(as, MIPSI_CVT_D_L, dest, dest); | ||
560 | } | ||
561 | emit_branch(as, MIPSI_BGEZ, left, RID_ZERO, l_end); | ||
562 | emit_tg(as, MIPSI_DMTC1, RID_TMP, dest); | ||
563 | emit_tsml(as, MIPSI_DEXTM, RID_TMP, left, 30, 0); | ||
564 | #endif | ||
456 | } else { /* Integer to FP conversion. */ | 565 | } else { /* Integer to FP conversion. */ |
457 | Reg left = ra_alloc1(as, lref, RSET_GPR); | 566 | Reg left = ra_alloc1(as, lref, RSET_GPR); |
567 | #if LJ_32 | ||
458 | emit_fg(as, irt_isfloat(ir->t) ? MIPSI_CVT_S_W : MIPSI_CVT_D_W, | 568 | emit_fg(as, irt_isfloat(ir->t) ? MIPSI_CVT_S_W : MIPSI_CVT_D_W, |
459 | dest, dest); | 569 | dest, dest); |
460 | emit_tg(as, MIPSI_MTC1, left, dest); | 570 | emit_tg(as, MIPSI_MTC1, left, dest); |
571 | #else | ||
572 | MIPSIns mi = irt_isfloat(ir->t) ? | ||
573 | (st64 ? MIPSI_CVT_S_L : MIPSI_CVT_S_W) : | ||
574 | (st64 ? MIPSI_CVT_D_L : MIPSI_CVT_D_W); | ||
575 | emit_fg(as, mi, dest, dest); | ||
576 | emit_tg(as, st64 ? MIPSI_DMTC1 : MIPSI_MTC1, left, dest); | ||
577 | #endif | ||
461 | } | 578 | } |
462 | } else if (stfp) { /* FP to integer conversion. */ | 579 | } else if (stfp) { /* FP to integer conversion. */ |
463 | if (irt_isguard(ir->t)) { | 580 | if (irt_isguard(ir->t)) { |
@@ -468,7 +585,7 @@ static void asm_conv(ASMState *as, IRIns *ir) | |||
468 | Reg dest = ra_dest(as, ir, RSET_GPR); | 585 | Reg dest = ra_dest(as, ir, RSET_GPR); |
469 | Reg left = ra_alloc1(as, lref, RSET_FPR); | 586 | Reg left = ra_alloc1(as, lref, RSET_FPR); |
470 | Reg tmp = ra_scratch(as, rset_exclude(RSET_FPR, left)); | 587 | Reg tmp = ra_scratch(as, rset_exclude(RSET_FPR, left)); |
471 | if (irt_isu32(ir->t)) { | 588 | if (irt_isu32(ir->t)) { /* FP to U32 conversion. */ |
472 | /* y = (int)floor(x - 2147483648.0) ^ 0x80000000 */ | 589 | /* y = (int)floor(x - 2147483648.0) ^ 0x80000000 */ |
473 | emit_dst(as, MIPSI_XOR, dest, dest, RID_TMP); | 590 | emit_dst(as, MIPSI_XOR, dest, dest, RID_TMP); |
474 | emit_ti(as, MIPSI_LUI, RID_TMP, 0x8000); | 591 | emit_ti(as, MIPSI_LUI, RID_TMP, 0x8000); |
@@ -479,25 +596,111 @@ static void asm_conv(ASMState *as, IRIns *ir) | |||
479 | tmp, left, tmp); | 596 | tmp, left, tmp); |
480 | if (st == IRT_FLOAT) | 597 | if (st == IRT_FLOAT) |
481 | emit_lsptr(as, MIPSI_LWC1, (tmp & 31), | 598 | emit_lsptr(as, MIPSI_LWC1, (tmp & 31), |
482 | (void *)lj_ir_k64_find(as->J, U64x(4f000000,4f000000)), | 599 | (void *)&as->J->k32[LJ_K32_2P31], RSET_GPR); |
483 | RSET_GPR); | ||
484 | else | 600 | else |
485 | emit_lsptr(as, MIPSI_LDC1, (tmp & 31), | 601 | emit_lsptr(as, MIPSI_LDC1, (tmp & 31), |
486 | (void *)lj_ir_k64_find(as->J, U64x(41e00000,00000000)), | 602 | (void *)&as->J->k64[LJ_K64_2P31], RSET_GPR); |
487 | RSET_GPR); | 603 | #if LJ_64 |
604 | } else if (irt_isu64(ir->t)) { /* FP to U64 conversion. */ | ||
605 | MCLabel l_end; | ||
606 | emit_tg(as, MIPSI_DMFC1, dest, tmp); | ||
607 | l_end = emit_label(as); | ||
608 | /* For inputs >= 2^63 add -2^64 and convert again. */ | ||
609 | if (st == IRT_NUM) { | ||
610 | emit_fg(as, MIPSI_TRUNC_L_D, tmp, tmp); | ||
611 | emit_fgh(as, MIPSI_ADD_D, tmp, left, tmp); | ||
612 | emit_lsptr(as, MIPSI_LDC1, (tmp & 31), | ||
613 | (void *)&as->J->k64[LJ_K64_M2P64], | ||
614 | rset_exclude(RSET_GPR, dest)); | ||
615 | emit_fg(as, MIPSI_TRUNC_L_D, tmp, left); /* Delay slot. */ | ||
616 | #if !LJ_TARGET_MIPSR6 | ||
617 | emit_branch(as, MIPSI_BC1T, 0, 0, l_end); | ||
618 | emit_fgh(as, MIPSI_C_OLT_D, 0, left, tmp); | ||
619 | #else | ||
620 | emit_branch(as, MIPSI_BC1NEZ, 0, (left&31), l_end); | ||
621 | emit_fgh(as, MIPSI_CMP_LT_D, left, left, tmp); | ||
622 | #endif | ||
623 | emit_lsptr(as, MIPSI_LDC1, (tmp & 31), | ||
624 | (void *)&as->J->k64[LJ_K64_2P63], | ||
625 | rset_exclude(RSET_GPR, dest)); | ||
626 | } else { | ||
627 | emit_fg(as, MIPSI_TRUNC_L_S, tmp, tmp); | ||
628 | emit_fgh(as, MIPSI_ADD_S, tmp, left, tmp); | ||
629 | emit_lsptr(as, MIPSI_LWC1, (tmp & 31), | ||
630 | (void *)&as->J->k32[LJ_K32_M2P64], | ||
631 | rset_exclude(RSET_GPR, dest)); | ||
632 | emit_fg(as, MIPSI_TRUNC_L_S, tmp, left); /* Delay slot. */ | ||
633 | #if !LJ_TARGET_MIPSR6 | ||
634 | emit_branch(as, MIPSI_BC1T, 0, 0, l_end); | ||
635 | emit_fgh(as, MIPSI_C_OLT_S, 0, left, tmp); | ||
636 | #else | ||
637 | emit_branch(as, MIPSI_BC1NEZ, 0, (left&31), l_end); | ||
638 | emit_fgh(as, MIPSI_CMP_LT_S, left, left, tmp); | ||
639 | #endif | ||
640 | emit_lsptr(as, MIPSI_LWC1, (tmp & 31), | ||
641 | (void *)&as->J->k32[LJ_K32_2P63], | ||
642 | rset_exclude(RSET_GPR, dest)); | ||
643 | } | ||
644 | #endif | ||
488 | } else { | 645 | } else { |
646 | #if LJ_32 | ||
489 | emit_tg(as, MIPSI_MFC1, dest, tmp); | 647 | emit_tg(as, MIPSI_MFC1, dest, tmp); |
490 | emit_fg(as, st == IRT_FLOAT ? MIPSI_TRUNC_W_S : MIPSI_TRUNC_W_D, | 648 | emit_fg(as, st == IRT_FLOAT ? MIPSI_TRUNC_W_S : MIPSI_TRUNC_W_D, |
491 | tmp, left); | 649 | tmp, left); |
650 | #else | ||
651 | MIPSIns mi = irt_is64(ir->t) ? | ||
652 | (st == IRT_NUM ? MIPSI_TRUNC_L_D : MIPSI_TRUNC_L_S) : | ||
653 | (st == IRT_NUM ? MIPSI_TRUNC_W_D : MIPSI_TRUNC_W_S); | ||
654 | emit_tg(as, irt_is64(ir->t) ? MIPSI_DMFC1 : MIPSI_MFC1, dest, left); | ||
655 | emit_fg(as, mi, left, left); | ||
656 | #endif | ||
492 | } | 657 | } |
493 | } | 658 | } |
494 | } else { | 659 | } else |
660 | #else | ||
661 | if (irt_isfp(ir->t)) { | ||
662 | #if LJ_64 && LJ_HASFFI | ||
663 | if (stfp) { /* FP to FP conversion. */ | ||
664 | asm_callid(as, ir, irt_isnum(ir->t) ? IRCALL_softfp_f2d : | ||
665 | IRCALL_softfp_d2f); | ||
666 | } else { /* Integer to FP conversion. */ | ||
667 | IRCallID cid = ((IRT_IS64 >> st) & 1) ? | ||
668 | (irt_isnum(ir->t) ? | ||
669 | (st == IRT_I64 ? IRCALL_fp64_l2d : IRCALL_fp64_ul2d) : | ||
670 | (st == IRT_I64 ? IRCALL_fp64_l2f : IRCALL_fp64_ul2f)) : | ||
671 | (irt_isnum(ir->t) ? | ||
672 | (st == IRT_INT ? IRCALL_softfp_i2d : IRCALL_softfp_ui2d) : | ||
673 | (st == IRT_INT ? IRCALL_softfp_i2f : IRCALL_softfp_ui2f)); | ||
674 | asm_callid(as, ir, cid); | ||
675 | } | ||
676 | #else | ||
677 | asm_callid(as, ir, IRCALL_softfp_i2d); | ||
678 | #endif | ||
679 | } else if (stfp) { /* FP to integer conversion. */ | ||
680 | if (irt_isguard(ir->t)) { | ||
681 | /* Checked conversions are only supported from number to int. */ | ||
682 | lua_assert(irt_isint(ir->t) && st == IRT_NUM); | ||
683 | asm_tointg(as, ir, RID_NONE); | ||
684 | } else { | ||
685 | IRCallID cid = irt_is64(ir->t) ? | ||
686 | ((st == IRT_NUM) ? | ||
687 | (irt_isi64(ir->t) ? IRCALL_fp64_d2l : IRCALL_fp64_d2ul) : | ||
688 | (irt_isi64(ir->t) ? IRCALL_fp64_f2l : IRCALL_fp64_f2ul)) : | ||
689 | ((st == IRT_NUM) ? | ||
690 | (irt_isint(ir->t) ? IRCALL_softfp_d2i : IRCALL_softfp_d2ui) : | ||
691 | (irt_isint(ir->t) ? IRCALL_softfp_f2i : IRCALL_softfp_f2ui)); | ||
692 | asm_callid(as, ir, cid); | ||
693 | } | ||
694 | } else | ||
695 | #endif | ||
696 | #endif | ||
697 | { | ||
495 | Reg dest = ra_dest(as, ir, RSET_GPR); | 698 | Reg dest = ra_dest(as, ir, RSET_GPR); |
496 | if (st >= IRT_I8 && st <= IRT_U16) { /* Extend to 32 bit integer. */ | 699 | if (st >= IRT_I8 && st <= IRT_U16) { /* Extend to 32 bit integer. */ |
497 | Reg left = ra_alloc1(as, ir->op1, RSET_GPR); | 700 | Reg left = ra_alloc1(as, ir->op1, RSET_GPR); |
498 | lua_assert(irt_isint(ir->t) || irt_isu32(ir->t)); | 701 | lua_assert(irt_isint(ir->t) || irt_isu32(ir->t)); |
499 | if ((ir->op2 & IRCONV_SEXT)) { | 702 | if ((ir->op2 & IRCONV_SEXT)) { |
500 | if ((as->flags & JIT_F_MIPS32R2)) { | 703 | if (LJ_64 || (as->flags & JIT_F_MIPSXXR2)) { |
501 | emit_dst(as, st == IRT_I8 ? MIPSI_SEB : MIPSI_SEH, dest, 0, left); | 704 | emit_dst(as, st == IRT_I8 ? MIPSI_SEB : MIPSI_SEH, dest, 0, left); |
502 | } else { | 705 | } else { |
503 | uint32_t shift = st == IRT_I8 ? 24 : 16; | 706 | uint32_t shift = st == IRT_I8 ? 24 : 16; |
@@ -509,49 +712,108 @@ static void asm_conv(ASMState *as, IRIns *ir) | |||
509 | (int32_t)(st == IRT_U8 ? 0xff : 0xffff)); | 712 | (int32_t)(st == IRT_U8 ? 0xff : 0xffff)); |
510 | } | 713 | } |
511 | } else { /* 32/64 bit integer conversions. */ | 714 | } else { /* 32/64 bit integer conversions. */ |
715 | #if LJ_32 | ||
512 | /* Only need to handle 32/32 bit no-op (cast) on 32 bit archs. */ | 716 | /* Only need to handle 32/32 bit no-op (cast) on 32 bit archs. */ |
513 | ra_leftov(as, dest, lref); /* Do nothing, but may need to move regs. */ | 717 | ra_leftov(as, dest, lref); /* Do nothing, but may need to move regs. */ |
718 | #else | ||
719 | if (irt_is64(ir->t)) { | ||
720 | if (st64) { | ||
721 | /* 64/64 bit no-op (cast)*/ | ||
722 | ra_leftov(as, dest, lref); | ||
723 | } else { | ||
724 | Reg left = ra_alloc1(as, lref, RSET_GPR); | ||
725 | if ((ir->op2 & IRCONV_SEXT)) { /* 32 to 64 bit sign extension. */ | ||
726 | emit_dta(as, MIPSI_SLL, dest, left, 0); | ||
727 | } else { /* 32 to 64 bit zero extension. */ | ||
728 | emit_tsml(as, MIPSI_DEXT, dest, left, 31, 0); | ||
729 | } | ||
730 | } | ||
731 | } else { | ||
732 | if (st64) { | ||
733 | /* This is either a 32 bit reg/reg mov which zeroes the hiword | ||
734 | ** or a load of the loword from a 64 bit address. | ||
735 | */ | ||
736 | Reg left = ra_alloc1(as, lref, RSET_GPR); | ||
737 | emit_tsml(as, MIPSI_DEXT, dest, left, 31, 0); | ||
738 | } else { /* 32/32 bit no-op (cast). */ | ||
739 | /* Do nothing, but may need to move regs. */ | ||
740 | ra_leftov(as, dest, lref); | ||
741 | } | ||
742 | } | ||
743 | #endif | ||
514 | } | 744 | } |
515 | } | 745 | } |
516 | } | 746 | } |
517 | 747 | ||
518 | #if LJ_HASFFI | ||
519 | static void asm_conv64(ASMState *as, IRIns *ir) | ||
520 | { | ||
521 | IRType st = (IRType)((ir-1)->op2 & IRCONV_SRCMASK); | ||
522 | IRType dt = (((ir-1)->op2 & IRCONV_DSTMASK) >> IRCONV_DSH); | ||
523 | IRCallID id; | ||
524 | const CCallInfo *ci; | ||
525 | IRRef args[2]; | ||
526 | args[LJ_BE?0:1] = ir->op1; | ||
527 | args[LJ_BE?1:0] = (ir-1)->op1; | ||
528 | if (st == IRT_NUM || st == IRT_FLOAT) { | ||
529 | id = IRCALL_fp64_d2l + ((st == IRT_FLOAT) ? 2 : 0) + (dt - IRT_I64); | ||
530 | ir--; | ||
531 | } else { | ||
532 | id = IRCALL_fp64_l2d + ((dt == IRT_FLOAT) ? 2 : 0) + (st - IRT_I64); | ||
533 | } | ||
534 | ci = &lj_ir_callinfo[id]; | ||
535 | asm_setupresult(as, ir, ci); | ||
536 | asm_gencall(as, ci, args); | ||
537 | } | ||
538 | #endif | ||
539 | |||
540 | static void asm_strto(ASMState *as, IRIns *ir) | 748 | static void asm_strto(ASMState *as, IRIns *ir) |
541 | { | 749 | { |
542 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_strscan_num]; | 750 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_strscan_num]; |
543 | IRRef args[2]; | 751 | IRRef args[2]; |
752 | int32_t ofs = 0; | ||
753 | #if LJ_SOFTFP32 | ||
754 | ra_evictset(as, RSET_SCRATCH); | ||
755 | if (ra_used(ir)) { | ||
756 | if (ra_hasspill(ir->s) && ra_hasspill((ir+1)->s) && | ||
757 | (ir->s & 1) == LJ_BE && (ir->s ^ 1) == (ir+1)->s) { | ||
758 | int i; | ||
759 | for (i = 0; i < 2; i++) { | ||
760 | Reg r = (ir+i)->r; | ||
761 | if (ra_hasreg(r)) { | ||
762 | ra_free(as, r); | ||
763 | ra_modified(as, r); | ||
764 | emit_spload(as, ir+i, r, sps_scale((ir+i)->s)); | ||
765 | } | ||
766 | } | ||
767 | ofs = sps_scale(ir->s & ~1); | ||
768 | } else { | ||
769 | Reg rhi = ra_dest(as, ir+1, RSET_GPR); | ||
770 | Reg rlo = ra_dest(as, ir, rset_exclude(RSET_GPR, rhi)); | ||
771 | emit_tsi(as, MIPSI_LW, rhi, RID_SP, ofs+(LJ_BE?0:4)); | ||
772 | emit_tsi(as, MIPSI_LW, rlo, RID_SP, ofs+(LJ_BE?4:0)); | ||
773 | } | ||
774 | } | ||
775 | #else | ||
544 | RegSet drop = RSET_SCRATCH; | 776 | RegSet drop = RSET_SCRATCH; |
545 | if (ra_hasreg(ir->r)) rset_set(drop, ir->r); /* Spill dest reg (if any). */ | 777 | if (ra_hasreg(ir->r)) rset_set(drop, ir->r); /* Spill dest reg (if any). */ |
546 | ra_evictset(as, drop); | 778 | ra_evictset(as, drop); |
779 | ofs = sps_scale(ir->s); | ||
780 | #endif | ||
547 | asm_guard(as, MIPSI_BEQ, RID_RET, RID_ZERO); /* Test return status. */ | 781 | asm_guard(as, MIPSI_BEQ, RID_RET, RID_ZERO); /* Test return status. */ |
548 | args[0] = ir->op1; /* GCstr *str */ | 782 | args[0] = ir->op1; /* GCstr *str */ |
549 | args[1] = ASMREF_TMP1; /* TValue *n */ | 783 | args[1] = ASMREF_TMP1; /* TValue *n */ |
550 | asm_gencall(as, ci, args); | 784 | asm_gencall(as, ci, args); |
551 | /* Store the result to the spill slot or temp slots. */ | 785 | /* Store the result to the spill slot or temp slots. */ |
552 | emit_tsi(as, MIPSI_ADDIU, ra_releasetmp(as, ASMREF_TMP1), | 786 | emit_tsi(as, MIPSI_AADDIU, ra_releasetmp(as, ASMREF_TMP1), |
553 | RID_SP, sps_scale(ir->s)); | 787 | RID_SP, ofs); |
788 | } | ||
789 | |||
790 | /* -- Memory references --------------------------------------------------- */ | ||
791 | |||
792 | #if LJ_64 | ||
793 | /* Store tagged value for ref at base+ofs. */ | ||
794 | static void asm_tvstore64(ASMState *as, Reg base, int32_t ofs, IRRef ref) | ||
795 | { | ||
796 | RegSet allow = rset_exclude(RSET_GPR, base); | ||
797 | IRIns *ir = IR(ref); | ||
798 | lua_assert(irt_ispri(ir->t) || irt_isaddr(ir->t) || irt_isinteger(ir->t)); | ||
799 | if (irref_isk(ref)) { | ||
800 | TValue k; | ||
801 | lj_ir_kvalue(as->J->L, &k, ir); | ||
802 | emit_tsi(as, MIPSI_SD, ra_allock(as, (int64_t)k.u64, allow), base, ofs); | ||
803 | } else { | ||
804 | Reg src = ra_alloc1(as, ref, allow); | ||
805 | Reg type = ra_allock(as, (int64_t)irt_toitype(ir->t) << 47, | ||
806 | rset_exclude(allow, src)); | ||
807 | emit_tsi(as, MIPSI_SD, RID_TMP, base, ofs); | ||
808 | if (irt_isinteger(ir->t)) { | ||
809 | emit_dst(as, MIPSI_DADDU, RID_TMP, RID_TMP, type); | ||
810 | emit_tsml(as, MIPSI_DEXT, RID_TMP, src, 31, 0); | ||
811 | } else { | ||
812 | emit_dst(as, MIPSI_DADDU, RID_TMP, src, type); | ||
813 | } | ||
814 | } | ||
554 | } | 815 | } |
816 | #endif | ||
555 | 817 | ||
556 | /* Get pointer to TValue. */ | 818 | /* Get pointer to TValue. */ |
557 | static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) | 819 | static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) |
@@ -559,44 +821,32 @@ static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) | |||
559 | IRIns *ir = IR(ref); | 821 | IRIns *ir = IR(ref); |
560 | if (irt_isnum(ir->t)) { | 822 | if (irt_isnum(ir->t)) { |
561 | if (irref_isk(ref)) /* Use the number constant itself as a TValue. */ | 823 | if (irref_isk(ref)) /* Use the number constant itself as a TValue. */ |
562 | ra_allockreg(as, i32ptr(ir_knum(ir)), dest); | 824 | ra_allockreg(as, igcptr(ir_knum(ir)), dest); |
563 | else /* Otherwise force a spill and use the spill slot. */ | 825 | else /* Otherwise force a spill and use the spill slot. */ |
564 | emit_tsi(as, MIPSI_ADDIU, dest, RID_SP, ra_spill(as, ir)); | 826 | emit_tsi(as, MIPSI_AADDIU, dest, RID_SP, ra_spill(as, ir)); |
565 | } else { | 827 | } else { |
566 | /* Otherwise use g->tmptv to hold the TValue. */ | 828 | /* Otherwise use g->tmptv to hold the TValue. */ |
829 | #if LJ_32 | ||
567 | RegSet allow = rset_exclude(RSET_GPR, dest); | 830 | RegSet allow = rset_exclude(RSET_GPR, dest); |
568 | Reg type; | 831 | Reg type; |
569 | emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, offsetof(global_State, tmptv)-32768); | 832 | emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, (int32_t)(offsetof(global_State, tmptv)-32768)); |
570 | if (!irt_ispri(ir->t)) { | 833 | if (!irt_ispri(ir->t)) { |
571 | Reg src = ra_alloc1(as, ref, allow); | 834 | Reg src = ra_alloc1(as, ref, allow); |
572 | emit_setgl(as, src, tmptv.gcr); | 835 | emit_setgl(as, src, tmptv.gcr); |
573 | } | 836 | } |
574 | type = ra_allock(as, irt_toitype(ir->t), allow); | 837 | if (LJ_SOFTFP && (ir+1)->o == IR_HIOP) |
838 | type = ra_alloc1(as, ref+1, allow); | ||
839 | else | ||
840 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); | ||
575 | emit_setgl(as, type, tmptv.it); | 841 | emit_setgl(as, type, tmptv.it); |
842 | #else | ||
843 | asm_tvstore64(as, dest, 0, ref); | ||
844 | emit_tsi(as, MIPSI_DADDIU, dest, RID_JGL, | ||
845 | (int32_t)(offsetof(global_State, tmptv)-32768)); | ||
846 | #endif | ||
576 | } | 847 | } |
577 | } | 848 | } |
578 | 849 | ||
579 | static void asm_tostr(ASMState *as, IRIns *ir) | ||
580 | { | ||
581 | IRRef args[2]; | ||
582 | args[0] = ASMREF_L; | ||
583 | as->gcsteps++; | ||
584 | if (irt_isnum(IR(ir->op1)->t) || (ir+1)->o == IR_HIOP) { | ||
585 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_fromnum]; | ||
586 | args[1] = ASMREF_TMP1; /* const lua_Number * */ | ||
587 | asm_setupresult(as, ir, ci); /* GCstr * */ | ||
588 | asm_gencall(as, ci, args); | ||
589 | asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op1); | ||
590 | } else { | ||
591 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_fromint]; | ||
592 | args[1] = ir->op1; /* int32_t k */ | ||
593 | asm_setupresult(as, ir, ci); /* GCstr * */ | ||
594 | asm_gencall(as, ci, args); | ||
595 | } | ||
596 | } | ||
597 | |||
598 | /* -- Memory references --------------------------------------------------- */ | ||
599 | |||
600 | static void asm_aref(ASMState *as, IRIns *ir) | 850 | static void asm_aref(ASMState *as, IRIns *ir) |
601 | { | 851 | { |
602 | Reg dest = ra_dest(as, ir, RSET_GPR); | 852 | Reg dest = ra_dest(as, ir, RSET_GPR); |
@@ -608,14 +858,18 @@ static void asm_aref(ASMState *as, IRIns *ir) | |||
608 | ofs += 8*IR(ir->op2)->i; | 858 | ofs += 8*IR(ir->op2)->i; |
609 | if (checki16(ofs)) { | 859 | if (checki16(ofs)) { |
610 | base = ra_alloc1(as, refa, RSET_GPR); | 860 | base = ra_alloc1(as, refa, RSET_GPR); |
611 | emit_tsi(as, MIPSI_ADDIU, dest, base, ofs); | 861 | emit_tsi(as, MIPSI_AADDIU, dest, base, ofs); |
612 | return; | 862 | return; |
613 | } | 863 | } |
614 | } | 864 | } |
615 | base = ra_alloc1(as, ir->op1, RSET_GPR); | 865 | base = ra_alloc1(as, ir->op1, RSET_GPR); |
616 | idx = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, base)); | 866 | idx = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, base)); |
617 | emit_dst(as, MIPSI_ADDU, dest, RID_TMP, base); | 867 | #if !LJ_TARGET_MIPSR6 |
868 | emit_dst(as, MIPSI_AADDU, dest, RID_TMP, base); | ||
618 | emit_dta(as, MIPSI_SLL, RID_TMP, idx, 3); | 869 | emit_dta(as, MIPSI_SLL, RID_TMP, idx, 3); |
870 | #else | ||
871 | emit_dst(as, MIPSI_ALSA | MIPSF_A(3-1), dest, idx, base); | ||
872 | #endif | ||
619 | } | 873 | } |
620 | 874 | ||
621 | /* Inlined hash lookup. Specialized for key type and for const keys. | 875 | /* Inlined hash lookup. Specialized for key type and for const keys. |
@@ -626,51 +880,109 @@ static void asm_aref(ASMState *as, IRIns *ir) | |||
626 | ** } while ((n = nextnode(n))); | 880 | ** } while ((n = nextnode(n))); |
627 | ** return niltv(L); | 881 | ** return niltv(L); |
628 | */ | 882 | */ |
629 | static void asm_href(ASMState *as, IRIns *ir) | 883 | static void asm_href(ASMState *as, IRIns *ir, IROp merge) |
630 | { | 884 | { |
631 | RegSet allow = RSET_GPR; | 885 | RegSet allow = RSET_GPR; |
632 | int destused = ra_used(ir); | 886 | int destused = ra_used(ir); |
633 | Reg dest = ra_dest(as, ir, allow); | 887 | Reg dest = ra_dest(as, ir, allow); |
634 | Reg tab = ra_alloc1(as, ir->op1, rset_clear(allow, dest)); | 888 | Reg tab = ra_alloc1(as, ir->op1, rset_clear(allow, dest)); |
635 | Reg key = RID_NONE, type = RID_NONE, tmpnum = RID_NONE, tmp1 = RID_TMP, tmp2; | 889 | Reg key = RID_NONE, type = RID_NONE, tmpnum = RID_NONE, tmp1 = RID_TMP, tmp2; |
890 | #if LJ_64 | ||
891 | Reg cmp64 = RID_NONE; | ||
892 | #endif | ||
636 | IRRef refkey = ir->op2; | 893 | IRRef refkey = ir->op2; |
637 | IRIns *irkey = IR(refkey); | 894 | IRIns *irkey = IR(refkey); |
895 | int isk = irref_isk(refkey); | ||
638 | IRType1 kt = irkey->t; | 896 | IRType1 kt = irkey->t; |
639 | uint32_t khash; | 897 | uint32_t khash; |
640 | MCLabel l_end, l_loop, l_next; | 898 | MCLabel l_end, l_loop, l_next; |
641 | 899 | ||
642 | rset_clear(allow, tab); | 900 | rset_clear(allow, tab); |
643 | if (irt_isnum(kt)) { | 901 | #if LJ_SOFTFP32 |
902 | if (!isk) { | ||
903 | key = ra_alloc1(as, refkey, allow); | ||
904 | rset_clear(allow, key); | ||
905 | if (irkey[1].o == IR_HIOP) { | ||
906 | if (ra_hasreg((irkey+1)->r)) { | ||
907 | type = tmpnum = (irkey+1)->r; | ||
908 | tmp1 = ra_scratch(as, allow); | ||
909 | rset_clear(allow, tmp1); | ||
910 | ra_noweak(as, tmpnum); | ||
911 | } else { | ||
912 | type = tmpnum = ra_allocref(as, refkey+1, allow); | ||
913 | } | ||
914 | rset_clear(allow, tmpnum); | ||
915 | } else { | ||
916 | type = ra_allock(as, (int32_t)irt_toitype(irkey->t), allow); | ||
917 | rset_clear(allow, type); | ||
918 | } | ||
919 | } | ||
920 | #else | ||
921 | if (!LJ_SOFTFP && irt_isnum(kt)) { | ||
644 | key = ra_alloc1(as, refkey, RSET_FPR); | 922 | key = ra_alloc1(as, refkey, RSET_FPR); |
645 | tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key)); | 923 | tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key)); |
646 | } else if (!irt_ispri(kt)) { | 924 | } else if (!irt_ispri(kt)) { |
647 | key = ra_alloc1(as, refkey, allow); | 925 | key = ra_alloc1(as, refkey, allow); |
648 | rset_clear(allow, key); | 926 | rset_clear(allow, key); |
649 | type = ra_allock(as, irt_toitype(irkey->t), allow); | 927 | #if LJ_32 |
928 | type = ra_allock(as, (int32_t)irt_toitype(irkey->t), allow); | ||
650 | rset_clear(allow, type); | 929 | rset_clear(allow, type); |
930 | #endif | ||
651 | } | 931 | } |
932 | #endif | ||
652 | tmp2 = ra_scratch(as, allow); | 933 | tmp2 = ra_scratch(as, allow); |
653 | rset_clear(allow, tmp2); | 934 | rset_clear(allow, tmp2); |
935 | #if LJ_64 | ||
936 | if (LJ_SOFTFP || !irt_isnum(kt)) { | ||
937 | /* Allocate cmp64 register used for 64-bit comparisons */ | ||
938 | if (LJ_SOFTFP && irt_isnum(kt)) { | ||
939 | cmp64 = key; | ||
940 | } else if (!isk && irt_isaddr(kt)) { | ||
941 | cmp64 = tmp2; | ||
942 | } else { | ||
943 | int64_t k; | ||
944 | if (isk && irt_isaddr(kt)) { | ||
945 | k = ((int64_t)irt_toitype(irkey->t) << 47) | irkey[1].tv.u64; | ||
946 | } else { | ||
947 | lua_assert(irt_ispri(kt) && !irt_isnil(kt)); | ||
948 | k = ~((int64_t)~irt_toitype(ir->t) << 47); | ||
949 | } | ||
950 | cmp64 = ra_allock(as, k, allow); | ||
951 | rset_clear(allow, cmp64); | ||
952 | } | ||
953 | } | ||
954 | #endif | ||
654 | 955 | ||
655 | /* Key not found in chain: load niltv. */ | 956 | /* Key not found in chain: jump to exit (if merged) or load niltv. */ |
656 | l_end = emit_label(as); | 957 | l_end = emit_label(as); |
657 | if (destused) | 958 | as->invmcp = NULL; |
959 | if (merge == IR_NE) | ||
960 | asm_guard(as, MIPSI_B, RID_ZERO, RID_ZERO); | ||
961 | else if (destused) | ||
658 | emit_loada(as, dest, niltvg(J2G(as->J))); | 962 | emit_loada(as, dest, niltvg(J2G(as->J))); |
659 | else | ||
660 | *--as->mcp = MIPSI_NOP; | ||
661 | /* Follow hash chain until the end. */ | 963 | /* Follow hash chain until the end. */ |
662 | emit_move(as, dest, tmp1); | 964 | emit_move(as, dest, tmp1); |
663 | l_loop = --as->mcp; | 965 | l_loop = --as->mcp; |
664 | emit_tsi(as, MIPSI_LW, tmp1, dest, (int32_t)offsetof(Node, next)); | 966 | emit_tsi(as, MIPSI_AL, tmp1, dest, (int32_t)offsetof(Node, next)); |
665 | l_next = emit_label(as); | 967 | l_next = emit_label(as); |
666 | 968 | ||
667 | /* Type and value comparison. */ | 969 | /* Type and value comparison. */ |
668 | if (irt_isnum(kt)) { | 970 | if (merge == IR_EQ) { /* Must match asm_guard(). */ |
971 | emit_ti(as, MIPSI_LI, RID_TMP, as->snapno); | ||
972 | l_end = asm_exitstub_addr(as); | ||
973 | } | ||
974 | if (!LJ_SOFTFP && irt_isnum(kt)) { | ||
975 | #if !LJ_TARGET_MIPSR6 | ||
669 | emit_branch(as, MIPSI_BC1T, 0, 0, l_end); | 976 | emit_branch(as, MIPSI_BC1T, 0, 0, l_end); |
670 | emit_fgh(as, MIPSI_C_EQ_D, 0, tmpnum, key); | 977 | emit_fgh(as, MIPSI_C_EQ_D, 0, tmpnum, key); |
671 | emit_tg(as, MIPSI_MFC1, tmp1, key+1); | 978 | #else |
979 | emit_branch(as, MIPSI_BC1NEZ, 0, (tmpnum&31), l_end); | ||
980 | emit_fgh(as, MIPSI_CMP_EQ_D, tmpnum, tmpnum, key); | ||
981 | #endif | ||
982 | *--as->mcp = MIPSI_NOP; /* Avoid NaN comparison overhead. */ | ||
672 | emit_branch(as, MIPSI_BEQ, tmp1, RID_ZERO, l_next); | 983 | emit_branch(as, MIPSI_BEQ, tmp1, RID_ZERO, l_next); |
673 | emit_tsi(as, MIPSI_SLTIU, tmp1, tmp1, (int32_t)LJ_TISNUM); | 984 | emit_tsi(as, MIPSI_SLTIU, tmp1, tmp1, (int32_t)LJ_TISNUM); |
985 | #if LJ_32 | ||
674 | emit_hsi(as, MIPSI_LDC1, tmpnum, dest, (int32_t)offsetof(Node, key.n)); | 986 | emit_hsi(as, MIPSI_LDC1, tmpnum, dest, (int32_t)offsetof(Node, key.n)); |
675 | } else { | 987 | } else { |
676 | if (irt_ispri(kt)) { | 988 | if (irt_ispri(kt)) { |
@@ -683,24 +995,39 @@ static void asm_href(ASMState *as, IRIns *ir) | |||
683 | } | 995 | } |
684 | emit_tsi(as, MIPSI_LW, tmp1, dest, (int32_t)offsetof(Node, key.it)); | 996 | emit_tsi(as, MIPSI_LW, tmp1, dest, (int32_t)offsetof(Node, key.it)); |
685 | *l_loop = MIPSI_BNE | MIPSF_S(tmp1) | ((as->mcp-l_loop-1) & 0xffffu); | 997 | *l_loop = MIPSI_BNE | MIPSF_S(tmp1) | ((as->mcp-l_loop-1) & 0xffffu); |
998 | #else | ||
999 | emit_dta(as, MIPSI_DSRA32, tmp1, tmp1, 15); | ||
1000 | emit_tg(as, MIPSI_DMTC1, tmp1, tmpnum); | ||
1001 | emit_tsi(as, MIPSI_LD, tmp1, dest, (int32_t)offsetof(Node, key.u64)); | ||
1002 | } else { | ||
1003 | emit_branch(as, MIPSI_BEQ, tmp1, cmp64, l_end); | ||
1004 | emit_tsi(as, MIPSI_LD, tmp1, dest, (int32_t)offsetof(Node, key.u64)); | ||
1005 | } | ||
1006 | *l_loop = MIPSI_BNE | MIPSF_S(tmp1) | ((as->mcp-l_loop-1) & 0xffffu); | ||
1007 | if (!isk && irt_isaddr(kt)) { | ||
1008 | type = ra_allock(as, (int64_t)irt_toitype(kt) << 47, allow); | ||
1009 | emit_dst(as, MIPSI_DADDU, tmp2, key, type); | ||
1010 | rset_clear(allow, type); | ||
1011 | } | ||
1012 | #endif | ||
686 | 1013 | ||
687 | /* Load main position relative to tab->node into dest. */ | 1014 | /* Load main position relative to tab->node into dest. */ |
688 | khash = irref_isk(refkey) ? ir_khash(irkey) : 1; | 1015 | khash = isk ? ir_khash(irkey) : 1; |
689 | if (khash == 0) { | 1016 | if (khash == 0) { |
690 | emit_tsi(as, MIPSI_LW, dest, tab, (int32_t)offsetof(GCtab, node)); | 1017 | emit_tsi(as, MIPSI_AL, dest, tab, (int32_t)offsetof(GCtab, node)); |
691 | } else { | 1018 | } else { |
692 | Reg tmphash = tmp1; | 1019 | Reg tmphash = tmp1; |
693 | if (irref_isk(refkey)) | 1020 | if (isk) |
694 | tmphash = ra_allock(as, khash, allow); | 1021 | tmphash = ra_allock(as, khash, allow); |
695 | emit_dst(as, MIPSI_ADDU, dest, dest, tmp1); | 1022 | emit_dst(as, MIPSI_AADDU, dest, dest, tmp1); |
696 | lua_assert(sizeof(Node) == 24); | 1023 | lua_assert(sizeof(Node) == 24); |
697 | emit_dst(as, MIPSI_SUBU, tmp1, tmp2, tmp1); | 1024 | emit_dst(as, MIPSI_SUBU, tmp1, tmp2, tmp1); |
698 | emit_dta(as, MIPSI_SLL, tmp1, tmp1, 3); | 1025 | emit_dta(as, MIPSI_SLL, tmp1, tmp1, 3); |
699 | emit_dta(as, MIPSI_SLL, tmp2, tmp1, 5); | 1026 | emit_dta(as, MIPSI_SLL, tmp2, tmp1, 5); |
700 | emit_dst(as, MIPSI_AND, tmp1, tmp2, tmphash); | 1027 | emit_dst(as, MIPSI_AND, tmp1, tmp2, tmphash); |
701 | emit_tsi(as, MIPSI_LW, dest, tab, (int32_t)offsetof(GCtab, node)); | 1028 | emit_tsi(as, MIPSI_AL, dest, tab, (int32_t)offsetof(GCtab, node)); |
702 | emit_tsi(as, MIPSI_LW, tmp2, tab, (int32_t)offsetof(GCtab, hmask)); | 1029 | emit_tsi(as, MIPSI_LW, tmp2, tab, (int32_t)offsetof(GCtab, hmask)); |
703 | if (irref_isk(refkey)) { | 1030 | if (isk) { |
704 | /* Nothing to do. */ | 1031 | /* Nothing to do. */ |
705 | } else if (irt_isstr(kt)) { | 1032 | } else if (irt_isstr(kt)) { |
706 | emit_tsi(as, MIPSI_LW, tmp1, key, (int32_t)offsetof(GCstr, hash)); | 1033 | emit_tsi(as, MIPSI_LW, tmp1, key, (int32_t)offsetof(GCstr, hash)); |
@@ -710,9 +1037,10 @@ static void asm_href(ASMState *as, IRIns *ir) | |||
710 | emit_dst(as, MIPSI_XOR, tmp1, tmp1, tmp2); | 1037 | emit_dst(as, MIPSI_XOR, tmp1, tmp1, tmp2); |
711 | emit_rotr(as, tmp1, tmp1, dest, (-HASH_ROT2-HASH_ROT1)&31); | 1038 | emit_rotr(as, tmp1, tmp1, dest, (-HASH_ROT2-HASH_ROT1)&31); |
712 | emit_dst(as, MIPSI_SUBU, tmp2, tmp2, dest); | 1039 | emit_dst(as, MIPSI_SUBU, tmp2, tmp2, dest); |
713 | if (irt_isnum(kt)) { | 1040 | #if LJ_32 |
1041 | if (LJ_SOFTFP ? (irkey[1].o == IR_HIOP) : irt_isnum(kt)) { | ||
714 | emit_dst(as, MIPSI_XOR, tmp2, tmp2, tmp1); | 1042 | emit_dst(as, MIPSI_XOR, tmp2, tmp2, tmp1); |
715 | if ((as->flags & JIT_F_MIPS32R2)) { | 1043 | if ((as->flags & JIT_F_MIPSXXR2)) { |
716 | emit_dta(as, MIPSI_ROTR, dest, tmp1, (-HASH_ROT1)&31); | 1044 | emit_dta(as, MIPSI_ROTR, dest, tmp1, (-HASH_ROT1)&31); |
717 | } else { | 1045 | } else { |
718 | emit_dst(as, MIPSI_OR, dest, dest, tmp1); | 1046 | emit_dst(as, MIPSI_OR, dest, dest, tmp1); |
@@ -720,13 +1048,35 @@ static void asm_href(ASMState *as, IRIns *ir) | |||
720 | emit_dta(as, MIPSI_SRL, dest, tmp1, (-HASH_ROT1)&31); | 1048 | emit_dta(as, MIPSI_SRL, dest, tmp1, (-HASH_ROT1)&31); |
721 | } | 1049 | } |
722 | emit_dst(as, MIPSI_ADDU, tmp1, tmp1, tmp1); | 1050 | emit_dst(as, MIPSI_ADDU, tmp1, tmp1, tmp1); |
1051 | #if LJ_SOFTFP | ||
1052 | emit_ds(as, MIPSI_MOVE, tmp1, type); | ||
1053 | emit_ds(as, MIPSI_MOVE, tmp2, key); | ||
1054 | #else | ||
723 | emit_tg(as, MIPSI_MFC1, tmp2, key); | 1055 | emit_tg(as, MIPSI_MFC1, tmp2, key); |
724 | emit_tg(as, MIPSI_MFC1, tmp1, key+1); | 1056 | emit_tg(as, MIPSI_MFC1, tmp1, key+1); |
1057 | #endif | ||
725 | } else { | 1058 | } else { |
726 | emit_dst(as, MIPSI_XOR, tmp2, key, tmp1); | 1059 | emit_dst(as, MIPSI_XOR, tmp2, key, tmp1); |
727 | emit_rotr(as, dest, tmp1, tmp2, (-HASH_ROT1)&31); | 1060 | emit_rotr(as, dest, tmp1, tmp2, (-HASH_ROT1)&31); |
728 | emit_dst(as, MIPSI_ADDU, tmp1, key, ra_allock(as, HASH_BIAS, allow)); | 1061 | emit_dst(as, MIPSI_ADDU, tmp1, key, ra_allock(as, HASH_BIAS, allow)); |
729 | } | 1062 | } |
1063 | #else | ||
1064 | emit_dst(as, MIPSI_XOR, tmp2, tmp2, tmp1); | ||
1065 | emit_dta(as, MIPSI_ROTR, dest, tmp1, (-HASH_ROT1)&31); | ||
1066 | if (irt_isnum(kt)) { | ||
1067 | emit_dst(as, MIPSI_ADDU, tmp1, tmp1, tmp1); | ||
1068 | emit_dta(as, MIPSI_DSRA32, tmp1, LJ_SOFTFP ? key : tmp1, 0); | ||
1069 | emit_dta(as, MIPSI_SLL, tmp2, LJ_SOFTFP ? key : tmp1, 0); | ||
1070 | #if !LJ_SOFTFP | ||
1071 | emit_tg(as, MIPSI_DMFC1, tmp1, key); | ||
1072 | #endif | ||
1073 | } else { | ||
1074 | checkmclim(as); | ||
1075 | emit_dta(as, MIPSI_DSRA32, tmp1, tmp1, 0); | ||
1076 | emit_dta(as, MIPSI_SLL, tmp2, key, 0); | ||
1077 | emit_dst(as, MIPSI_DADDU, tmp1, key, type); | ||
1078 | } | ||
1079 | #endif | ||
730 | } | 1080 | } |
731 | } | 1081 | } |
732 | } | 1082 | } |
@@ -739,17 +1089,24 @@ static void asm_hrefk(ASMState *as, IRIns *ir) | |||
739 | int32_t kofs = ofs + (int32_t)offsetof(Node, key); | 1089 | int32_t kofs = ofs + (int32_t)offsetof(Node, key); |
740 | Reg dest = (ra_used(ir)||ofs > 32736) ? ra_dest(as, ir, RSET_GPR) : RID_NONE; | 1090 | Reg dest = (ra_used(ir)||ofs > 32736) ? ra_dest(as, ir, RSET_GPR) : RID_NONE; |
741 | Reg node = ra_alloc1(as, ir->op1, RSET_GPR); | 1091 | Reg node = ra_alloc1(as, ir->op1, RSET_GPR); |
742 | Reg key = RID_NONE, type = RID_TMP, idx = node; | ||
743 | RegSet allow = rset_exclude(RSET_GPR, node); | 1092 | RegSet allow = rset_exclude(RSET_GPR, node); |
1093 | Reg idx = node; | ||
1094 | #if LJ_32 | ||
1095 | Reg key = RID_NONE, type = RID_TMP; | ||
744 | int32_t lo, hi; | 1096 | int32_t lo, hi; |
1097 | #else | ||
1098 | Reg key = ra_scratch(as, allow); | ||
1099 | int64_t k; | ||
1100 | #endif | ||
745 | lua_assert(ofs % sizeof(Node) == 0); | 1101 | lua_assert(ofs % sizeof(Node) == 0); |
746 | if (ofs > 32736) { | 1102 | if (ofs > 32736) { |
747 | idx = dest; | 1103 | idx = dest; |
748 | rset_clear(allow, dest); | 1104 | rset_clear(allow, dest); |
749 | kofs = (int32_t)offsetof(Node, key); | 1105 | kofs = (int32_t)offsetof(Node, key); |
750 | } else if (ra_hasreg(dest)) { | 1106 | } else if (ra_hasreg(dest)) { |
751 | emit_tsi(as, MIPSI_ADDIU, dest, node, ofs); | 1107 | emit_tsi(as, MIPSI_AADDIU, dest, node, ofs); |
752 | } | 1108 | } |
1109 | #if LJ_32 | ||
753 | if (!irt_ispri(irkey->t)) { | 1110 | if (!irt_ispri(irkey->t)) { |
754 | key = ra_scratch(as, allow); | 1111 | key = ra_scratch(as, allow); |
755 | rset_clear(allow, key); | 1112 | rset_clear(allow, key); |
@@ -768,22 +1125,20 @@ nolo: | |||
768 | asm_guard(as, MIPSI_BNE, type, hi ? ra_allock(as, hi, allow) : RID_ZERO); | 1125 | asm_guard(as, MIPSI_BNE, type, hi ? ra_allock(as, hi, allow) : RID_ZERO); |
769 | if (ra_hasreg(key)) emit_tsi(as, MIPSI_LW, key, idx, kofs+(LJ_BE?4:0)); | 1126 | if (ra_hasreg(key)) emit_tsi(as, MIPSI_LW, key, idx, kofs+(LJ_BE?4:0)); |
770 | emit_tsi(as, MIPSI_LW, type, idx, kofs+(LJ_BE?0:4)); | 1127 | emit_tsi(as, MIPSI_LW, type, idx, kofs+(LJ_BE?0:4)); |
771 | if (ofs > 32736) | 1128 | #else |
772 | emit_tsi(as, MIPSI_ADDU, dest, node, ra_allock(as, ofs, allow)); | 1129 | if (irt_ispri(irkey->t)) { |
773 | } | 1130 | lua_assert(!irt_isnil(irkey->t)); |
774 | 1131 | k = ~((int64_t)~irt_toitype(irkey->t) << 47); | |
775 | static void asm_newref(ASMState *as, IRIns *ir) | 1132 | } else if (irt_isnum(irkey->t)) { |
776 | { | 1133 | k = (int64_t)ir_knum(irkey)->u64; |
777 | if (ir->r != RID_SINK) { | 1134 | } else { |
778 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_tab_newkey]; | 1135 | k = ((int64_t)irt_toitype(irkey->t) << 47) | (int64_t)ir_kgc(irkey); |
779 | IRRef args[3]; | ||
780 | args[0] = ASMREF_L; /* lua_State *L */ | ||
781 | args[1] = ir->op1; /* GCtab *t */ | ||
782 | args[2] = ASMREF_TMP1; /* cTValue *key */ | ||
783 | asm_setupresult(as, ir, ci); /* TValue * */ | ||
784 | asm_gencall(as, ci, args); | ||
785 | asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op2); | ||
786 | } | 1136 | } |
1137 | asm_guard(as, MIPSI_BNE, key, ra_allock(as, k, allow)); | ||
1138 | emit_tsi(as, MIPSI_LD, key, idx, kofs); | ||
1139 | #endif | ||
1140 | if (ofs > 32736) | ||
1141 | emit_tsi(as, MIPSI_AADDU, dest, node, ra_allock(as, ofs, allow)); | ||
787 | } | 1142 | } |
788 | 1143 | ||
789 | static void asm_uref(ASMState *as, IRIns *ir) | 1144 | static void asm_uref(ASMState *as, IRIns *ir) |
@@ -792,19 +1147,19 @@ static void asm_uref(ASMState *as, IRIns *ir) | |||
792 | if (irref_isk(ir->op1)) { | 1147 | if (irref_isk(ir->op1)) { |
793 | GCfunc *fn = ir_kfunc(IR(ir->op1)); | 1148 | GCfunc *fn = ir_kfunc(IR(ir->op1)); |
794 | MRef *v = &gcref(fn->l.uvptr[(ir->op2 >> 8)])->uv.v; | 1149 | MRef *v = &gcref(fn->l.uvptr[(ir->op2 >> 8)])->uv.v; |
795 | emit_lsptr(as, MIPSI_LW, dest, v, RSET_GPR); | 1150 | emit_lsptr(as, MIPSI_AL, dest, v, RSET_GPR); |
796 | } else { | 1151 | } else { |
797 | Reg uv = ra_scratch(as, RSET_GPR); | 1152 | Reg uv = ra_scratch(as, RSET_GPR); |
798 | Reg func = ra_alloc1(as, ir->op1, RSET_GPR); | 1153 | Reg func = ra_alloc1(as, ir->op1, RSET_GPR); |
799 | if (ir->o == IR_UREFC) { | 1154 | if (ir->o == IR_UREFC) { |
800 | asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO); | 1155 | asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO); |
801 | emit_tsi(as, MIPSI_ADDIU, dest, uv, (int32_t)offsetof(GCupval, tv)); | 1156 | emit_tsi(as, MIPSI_AADDIU, dest, uv, (int32_t)offsetof(GCupval, tv)); |
802 | emit_tsi(as, MIPSI_LBU, RID_TMP, uv, (int32_t)offsetof(GCupval, closed)); | 1157 | emit_tsi(as, MIPSI_LBU, RID_TMP, uv, (int32_t)offsetof(GCupval, closed)); |
803 | } else { | 1158 | } else { |
804 | emit_tsi(as, MIPSI_LW, dest, uv, (int32_t)offsetof(GCupval, v)); | 1159 | emit_tsi(as, MIPSI_AL, dest, uv, (int32_t)offsetof(GCupval, v)); |
805 | } | 1160 | } |
806 | emit_tsi(as, MIPSI_LW, uv, func, | 1161 | emit_tsi(as, MIPSI_AL, uv, func, (int32_t)offsetof(GCfuncL, uvptr) + |
807 | (int32_t)offsetof(GCfuncL, uvptr) + 4*(int32_t)(ir->op2 >> 8)); | 1162 | (int32_t)sizeof(MRef) * (int32_t)(ir->op2 >> 8)); |
808 | } | 1163 | } |
809 | } | 1164 | } |
810 | 1165 | ||
@@ -816,6 +1171,7 @@ static void asm_fref(ASMState *as, IRIns *ir) | |||
816 | 1171 | ||
817 | static void asm_strref(ASMState *as, IRIns *ir) | 1172 | static void asm_strref(ASMState *as, IRIns *ir) |
818 | { | 1173 | { |
1174 | #if LJ_32 | ||
819 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1175 | Reg dest = ra_dest(as, ir, RSET_GPR); |
820 | IRRef ref = ir->op2, refk = ir->op1; | 1176 | IRRef ref = ir->op2, refk = ir->op1; |
821 | int32_t ofs = (int32_t)sizeof(GCstr); | 1177 | int32_t ofs = (int32_t)sizeof(GCstr); |
@@ -847,6 +1203,20 @@ static void asm_strref(ASMState *as, IRIns *ir) | |||
847 | else | 1203 | else |
848 | emit_dst(as, MIPSI_ADDU, dest, r, | 1204 | emit_dst(as, MIPSI_ADDU, dest, r, |
849 | ra_allock(as, ofs, rset_exclude(RSET_GPR, r))); | 1205 | ra_allock(as, ofs, rset_exclude(RSET_GPR, r))); |
1206 | #else | ||
1207 | RegSet allow = RSET_GPR; | ||
1208 | Reg dest = ra_dest(as, ir, allow); | ||
1209 | Reg base = ra_alloc1(as, ir->op1, allow); | ||
1210 | IRIns *irr = IR(ir->op2); | ||
1211 | int32_t ofs = sizeof(GCstr); | ||
1212 | rset_clear(allow, base); | ||
1213 | if (irref_isk(ir->op2) && checki16(ofs + irr->i)) { | ||
1214 | emit_tsi(as, MIPSI_DADDIU, dest, base, ofs + irr->i); | ||
1215 | } else { | ||
1216 | emit_tsi(as, MIPSI_DADDIU, dest, dest, ofs); | ||
1217 | emit_dst(as, MIPSI_DADDU, dest, base, ra_alloc1(as, ir->op2, allow)); | ||
1218 | } | ||
1219 | #endif | ||
850 | } | 1220 | } |
851 | 1221 | ||
852 | /* -- Loads and stores ---------------------------------------------------- */ | 1222 | /* -- Loads and stores ---------------------------------------------------- */ |
@@ -858,9 +1228,11 @@ static MIPSIns asm_fxloadins(IRIns *ir) | |||
858 | case IRT_U8: return MIPSI_LBU; | 1228 | case IRT_U8: return MIPSI_LBU; |
859 | case IRT_I16: return MIPSI_LH; | 1229 | case IRT_I16: return MIPSI_LH; |
860 | case IRT_U16: return MIPSI_LHU; | 1230 | case IRT_U16: return MIPSI_LHU; |
861 | case IRT_NUM: return MIPSI_LDC1; | 1231 | case IRT_NUM: lua_assert(!LJ_SOFTFP32); if (!LJ_SOFTFP) return MIPSI_LDC1; |
862 | case IRT_FLOAT: return MIPSI_LWC1; | 1232 | /* fallthrough */ |
863 | default: return MIPSI_LW; | 1233 | case IRT_FLOAT: if (!LJ_SOFTFP) return MIPSI_LWC1; |
1234 | /* fallthrough */ | ||
1235 | default: return (LJ_64 && irt_is64(ir->t)) ? MIPSI_LD : MIPSI_LW; | ||
864 | } | 1236 | } |
865 | } | 1237 | } |
866 | 1238 | ||
@@ -869,26 +1241,34 @@ static MIPSIns asm_fxstoreins(IRIns *ir) | |||
869 | switch (irt_type(ir->t)) { | 1241 | switch (irt_type(ir->t)) { |
870 | case IRT_I8: case IRT_U8: return MIPSI_SB; | 1242 | case IRT_I8: case IRT_U8: return MIPSI_SB; |
871 | case IRT_I16: case IRT_U16: return MIPSI_SH; | 1243 | case IRT_I16: case IRT_U16: return MIPSI_SH; |
872 | case IRT_NUM: return MIPSI_SDC1; | 1244 | case IRT_NUM: lua_assert(!LJ_SOFTFP32); if (!LJ_SOFTFP) return MIPSI_SDC1; |
873 | case IRT_FLOAT: return MIPSI_SWC1; | 1245 | /* fallthrough */ |
874 | default: return MIPSI_SW; | 1246 | case IRT_FLOAT: if (!LJ_SOFTFP) return MIPSI_SWC1; |
1247 | /* fallthrough */ | ||
1248 | default: return (LJ_64 && irt_is64(ir->t)) ? MIPSI_SD : MIPSI_SW; | ||
875 | } | 1249 | } |
876 | } | 1250 | } |
877 | 1251 | ||
878 | static void asm_fload(ASMState *as, IRIns *ir) | 1252 | static void asm_fload(ASMState *as, IRIns *ir) |
879 | { | 1253 | { |
880 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1254 | Reg dest = ra_dest(as, ir, RSET_GPR); |
881 | Reg idx = ra_alloc1(as, ir->op1, RSET_GPR); | ||
882 | MIPSIns mi = asm_fxloadins(ir); | 1255 | MIPSIns mi = asm_fxloadins(ir); |
1256 | Reg idx; | ||
883 | int32_t ofs; | 1257 | int32_t ofs; |
884 | if (ir->op2 == IRFL_TAB_ARRAY) { | 1258 | if (ir->op1 == REF_NIL) { |
885 | ofs = asm_fuseabase(as, ir->op1); | 1259 | idx = RID_JGL; |
886 | if (ofs) { /* Turn the t->array load into an add for colocated arrays. */ | 1260 | ofs = (ir->op2 << 2) - 32768 - GG_OFS(g); |
887 | emit_tsi(as, MIPSI_ADDIU, dest, idx, ofs); | 1261 | } else { |
888 | return; | 1262 | idx = ra_alloc1(as, ir->op1, RSET_GPR); |
1263 | if (ir->op2 == IRFL_TAB_ARRAY) { | ||
1264 | ofs = asm_fuseabase(as, ir->op1); | ||
1265 | if (ofs) { /* Turn the t->array load into an add for colocated arrays. */ | ||
1266 | emit_tsi(as, MIPSI_AADDIU, dest, idx, ofs); | ||
1267 | return; | ||
1268 | } | ||
889 | } | 1269 | } |
1270 | ofs = field_ofs[ir->op2]; | ||
890 | } | 1271 | } |
891 | ofs = field_ofs[ir->op2]; | ||
892 | lua_assert(!irt_isfp(ir->t)); | 1272 | lua_assert(!irt_isfp(ir->t)); |
893 | emit_tsi(as, mi, dest, idx, ofs); | 1273 | emit_tsi(as, mi, dest, idx, ofs); |
894 | } | 1274 | } |
@@ -908,43 +1288,79 @@ static void asm_fstore(ASMState *as, IRIns *ir) | |||
908 | 1288 | ||
909 | static void asm_xload(ASMState *as, IRIns *ir) | 1289 | static void asm_xload(ASMState *as, IRIns *ir) |
910 | { | 1290 | { |
911 | Reg dest = ra_dest(as, ir, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); | 1291 | Reg dest = ra_dest(as, ir, |
912 | lua_assert(!(ir->op2 & IRXLOAD_UNALIGNED)); | 1292 | (!LJ_SOFTFP && irt_isfp(ir->t)) ? RSET_FPR : RSET_GPR); |
1293 | lua_assert(LJ_TARGET_UNALIGNED || !(ir->op2 & IRXLOAD_UNALIGNED)); | ||
913 | asm_fusexref(as, asm_fxloadins(ir), dest, ir->op1, RSET_GPR, 0); | 1294 | asm_fusexref(as, asm_fxloadins(ir), dest, ir->op1, RSET_GPR, 0); |
914 | } | 1295 | } |
915 | 1296 | ||
916 | static void asm_xstore(ASMState *as, IRIns *ir, int32_t ofs) | 1297 | static void asm_xstore_(ASMState *as, IRIns *ir, int32_t ofs) |
917 | { | 1298 | { |
918 | if (ir->r != RID_SINK) { | 1299 | if (ir->r != RID_SINK) { |
919 | Reg src = ra_alloc1z(as, ir->op2, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); | 1300 | Reg src = ra_alloc1z(as, ir->op2, |
1301 | (!LJ_SOFTFP && irt_isfp(ir->t)) ? RSET_FPR : RSET_GPR); | ||
920 | asm_fusexref(as, asm_fxstoreins(ir), src, ir->op1, | 1302 | asm_fusexref(as, asm_fxstoreins(ir), src, ir->op1, |
921 | rset_exclude(RSET_GPR, src), ofs); | 1303 | rset_exclude(RSET_GPR, src), ofs); |
922 | } | 1304 | } |
923 | } | 1305 | } |
924 | 1306 | ||
1307 | #define asm_xstore(as, ir) asm_xstore_(as, ir, 0) | ||
1308 | |||
925 | static void asm_ahuvload(ASMState *as, IRIns *ir) | 1309 | static void asm_ahuvload(ASMState *as, IRIns *ir) |
926 | { | 1310 | { |
927 | IRType1 t = ir->t; | 1311 | int hiop = (LJ_SOFTFP32 && (ir+1)->o == IR_HIOP); |
928 | Reg dest = RID_NONE, type = RID_TMP, idx; | 1312 | Reg dest = RID_NONE, type = RID_TMP, idx; |
929 | RegSet allow = RSET_GPR; | 1313 | RegSet allow = RSET_GPR; |
930 | int32_t ofs = 0; | 1314 | int32_t ofs = 0; |
1315 | IRType1 t = ir->t; | ||
1316 | if (hiop) { | ||
1317 | t.irt = IRT_NUM; | ||
1318 | if (ra_used(ir+1)) { | ||
1319 | type = ra_dest(as, ir+1, allow); | ||
1320 | rset_clear(allow, type); | ||
1321 | } | ||
1322 | } | ||
931 | if (ra_used(ir)) { | 1323 | if (ra_used(ir)) { |
932 | lua_assert(irt_isnum(t) || irt_isint(t) || irt_isaddr(t)); | 1324 | lua_assert((LJ_SOFTFP32 ? 0 : irt_isnum(ir->t)) || |
933 | dest = ra_dest(as, ir, irt_isnum(t) ? RSET_FPR : RSET_GPR); | 1325 | irt_isint(ir->t) || irt_isaddr(ir->t)); |
1326 | dest = ra_dest(as, ir, (!LJ_SOFTFP && irt_isnum(t)) ? RSET_FPR : allow); | ||
934 | rset_clear(allow, dest); | 1327 | rset_clear(allow, dest); |
1328 | #if LJ_64 | ||
1329 | if (irt_isaddr(t)) | ||
1330 | emit_tsml(as, MIPSI_DEXTM, dest, dest, 14, 0); | ||
1331 | else if (irt_isint(t)) | ||
1332 | emit_dta(as, MIPSI_SLL, dest, dest, 0); | ||
1333 | #endif | ||
935 | } | 1334 | } |
936 | idx = asm_fuseahuref(as, ir->op1, &ofs, allow); | 1335 | idx = asm_fuseahuref(as, ir->op1, &ofs, allow); |
937 | rset_clear(allow, idx); | 1336 | rset_clear(allow, idx); |
938 | if (irt_isnum(t)) { | 1337 | if (irt_isnum(t)) { |
939 | asm_guard(as, MIPSI_BEQ, type, RID_ZERO); | 1338 | asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO); |
940 | emit_tsi(as, MIPSI_SLTIU, type, type, (int32_t)LJ_TISNUM); | 1339 | emit_tsi(as, MIPSI_SLTIU, RID_TMP, type, (int32_t)LJ_TISNUM); |
941 | if (ra_hasreg(dest)) | ||
942 | emit_hsi(as, MIPSI_LDC1, dest, idx, ofs); | ||
943 | } else { | 1340 | } else { |
944 | asm_guard(as, MIPSI_BNE, type, ra_allock(as, irt_toitype(t), allow)); | 1341 | asm_guard(as, MIPSI_BNE, type, |
945 | if (ra_hasreg(dest)) emit_tsi(as, MIPSI_LW, dest, idx, ofs+(LJ_BE?4:0)); | 1342 | ra_allock(as, (int32_t)irt_toitype(t), allow)); |
1343 | } | ||
1344 | #if LJ_32 | ||
1345 | if (ra_hasreg(dest)) { | ||
1346 | if (!LJ_SOFTFP && irt_isnum(t)) | ||
1347 | emit_hsi(as, MIPSI_LDC1, dest, idx, ofs); | ||
1348 | else | ||
1349 | emit_tsi(as, MIPSI_LW, dest, idx, ofs+(LJ_BE?4:0)); | ||
946 | } | 1350 | } |
947 | emit_tsi(as, MIPSI_LW, type, idx, ofs+(LJ_BE?0:4)); | 1351 | emit_tsi(as, MIPSI_LW, type, idx, ofs+(LJ_BE?0:4)); |
1352 | #else | ||
1353 | if (ra_hasreg(dest)) { | ||
1354 | if (!LJ_SOFTFP && irt_isnum(t)) { | ||
1355 | emit_hsi(as, MIPSI_LDC1, dest, idx, ofs); | ||
1356 | dest = type; | ||
1357 | } | ||
1358 | } else { | ||
1359 | dest = type; | ||
1360 | } | ||
1361 | emit_dta(as, MIPSI_DSRA32, type, dest, 15); | ||
1362 | emit_tsi(as, MIPSI_LD, dest, idx, ofs); | ||
1363 | #endif | ||
948 | } | 1364 | } |
949 | 1365 | ||
950 | static void asm_ahustore(ASMState *as, IRIns *ir) | 1366 | static void asm_ahustore(ASMState *as, IRIns *ir) |
@@ -954,81 +1370,176 @@ static void asm_ahustore(ASMState *as, IRIns *ir) | |||
954 | int32_t ofs = 0; | 1370 | int32_t ofs = 0; |
955 | if (ir->r == RID_SINK) | 1371 | if (ir->r == RID_SINK) |
956 | return; | 1372 | return; |
957 | if (irt_isnum(ir->t)) { | 1373 | if (!LJ_SOFTFP32 && irt_isnum(ir->t)) { |
958 | src = ra_alloc1(as, ir->op2, RSET_FPR); | 1374 | src = ra_alloc1(as, ir->op2, LJ_SOFTFP ? RSET_GPR : RSET_FPR); |
1375 | idx = asm_fuseahuref(as, ir->op1, &ofs, allow); | ||
1376 | emit_hsi(as, LJ_SOFTFP ? MIPSI_SD : MIPSI_SDC1, src, idx, ofs); | ||
959 | } else { | 1377 | } else { |
1378 | #if LJ_32 | ||
960 | if (!irt_ispri(ir->t)) { | 1379 | if (!irt_ispri(ir->t)) { |
961 | src = ra_alloc1(as, ir->op2, allow); | 1380 | src = ra_alloc1(as, ir->op2, allow); |
962 | rset_clear(allow, src); | 1381 | rset_clear(allow, src); |
963 | } | 1382 | } |
964 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); | 1383 | if (LJ_SOFTFP && (ir+1)->o == IR_HIOP) |
1384 | type = ra_alloc1(as, (ir+1)->op2, allow); | ||
1385 | else | ||
1386 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); | ||
965 | rset_clear(allow, type); | 1387 | rset_clear(allow, type); |
966 | } | 1388 | idx = asm_fuseahuref(as, ir->op1, &ofs, allow); |
967 | idx = asm_fuseahuref(as, ir->op1, &ofs, allow); | ||
968 | if (irt_isnum(ir->t)) { | ||
969 | emit_hsi(as, MIPSI_SDC1, src, idx, ofs); | ||
970 | } else { | ||
971 | if (ra_hasreg(src)) | 1389 | if (ra_hasreg(src)) |
972 | emit_tsi(as, MIPSI_SW, src, idx, ofs+(LJ_BE?4:0)); | 1390 | emit_tsi(as, MIPSI_SW, src, idx, ofs+(LJ_BE?4:0)); |
973 | emit_tsi(as, MIPSI_SW, type, idx, ofs+(LJ_BE?0:4)); | 1391 | emit_tsi(as, MIPSI_SW, type, idx, ofs+(LJ_BE?0:4)); |
1392 | #else | ||
1393 | Reg tmp = RID_TMP; | ||
1394 | if (irt_ispri(ir->t)) { | ||
1395 | tmp = ra_allock(as, ~((int64_t)~irt_toitype(ir->t) << 47), allow); | ||
1396 | rset_clear(allow, tmp); | ||
1397 | } else { | ||
1398 | src = ra_alloc1(as, ir->op2, allow); | ||
1399 | rset_clear(allow, src); | ||
1400 | type = ra_allock(as, (int64_t)irt_toitype(ir->t) << 47, allow); | ||
1401 | rset_clear(allow, type); | ||
1402 | } | ||
1403 | idx = asm_fuseahuref(as, ir->op1, &ofs, allow); | ||
1404 | emit_tsi(as, MIPSI_SD, tmp, idx, ofs); | ||
1405 | if (ra_hasreg(src)) { | ||
1406 | if (irt_isinteger(ir->t)) { | ||
1407 | emit_dst(as, MIPSI_DADDU, tmp, tmp, type); | ||
1408 | emit_tsml(as, MIPSI_DEXT, tmp, src, 31, 0); | ||
1409 | } else { | ||
1410 | emit_dst(as, MIPSI_DADDU, tmp, src, type); | ||
1411 | } | ||
1412 | } | ||
1413 | #endif | ||
974 | } | 1414 | } |
975 | } | 1415 | } |
976 | 1416 | ||
977 | static void asm_sload(ASMState *as, IRIns *ir) | 1417 | static void asm_sload(ASMState *as, IRIns *ir) |
978 | { | 1418 | { |
979 | int32_t ofs = 8*((int32_t)ir->op1-1) + ((ir->op2 & IRSLOAD_FRAME) ? 4 : 0); | ||
980 | IRType1 t = ir->t; | ||
981 | Reg dest = RID_NONE, type = RID_NONE, base; | 1419 | Reg dest = RID_NONE, type = RID_NONE, base; |
982 | RegSet allow = RSET_GPR; | 1420 | RegSet allow = RSET_GPR; |
1421 | IRType1 t = ir->t; | ||
1422 | #if LJ_32 | ||
1423 | int32_t ofs = 8*((int32_t)ir->op1-1) + ((ir->op2 & IRSLOAD_FRAME) ? 4 : 0); | ||
1424 | int hiop = (LJ_SOFTFP32 && (ir+1)->o == IR_HIOP); | ||
1425 | if (hiop) | ||
1426 | t.irt = IRT_NUM; | ||
1427 | #else | ||
1428 | int32_t ofs = 8*((int32_t)ir->op1-2); | ||
1429 | #endif | ||
983 | lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */ | 1430 | lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */ |
984 | lua_assert(irt_isguard(t) || !(ir->op2 & IRSLOAD_TYPECHECK)); | 1431 | lua_assert(irt_isguard(ir->t) || !(ir->op2 & IRSLOAD_TYPECHECK)); |
985 | lua_assert(!irt_isint(t) || (ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME))); | 1432 | #if LJ_SOFTFP32 |
1433 | lua_assert(!(ir->op2 & IRSLOAD_CONVERT)); /* Handled by LJ_SOFTFP SPLIT. */ | ||
1434 | if (hiop && ra_used(ir+1)) { | ||
1435 | type = ra_dest(as, ir+1, allow); | ||
1436 | rset_clear(allow, type); | ||
1437 | } | ||
1438 | #else | ||
986 | if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(t) && irt_isint(t)) { | 1439 | if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(t) && irt_isint(t)) { |
987 | dest = ra_scratch(as, RSET_FPR); | 1440 | dest = ra_scratch(as, LJ_SOFTFP ? allow : RSET_FPR); |
988 | asm_tointg(as, ir, dest); | 1441 | asm_tointg(as, ir, dest); |
989 | t.irt = IRT_NUM; /* Continue with a regular number type check. */ | 1442 | t.irt = IRT_NUM; /* Continue with a regular number type check. */ |
990 | } else if (ra_used(ir)) { | 1443 | } else |
991 | lua_assert(irt_isnum(t) || irt_isint(t) || irt_isaddr(t)); | 1444 | #endif |
992 | dest = ra_dest(as, ir, irt_isnum(t) ? RSET_FPR : RSET_GPR); | 1445 | if (ra_used(ir)) { |
1446 | lua_assert((LJ_SOFTFP32 ? 0 : irt_isnum(ir->t)) || | ||
1447 | irt_isint(ir->t) || irt_isaddr(ir->t)); | ||
1448 | dest = ra_dest(as, ir, (!LJ_SOFTFP && irt_isnum(t)) ? RSET_FPR : allow); | ||
993 | rset_clear(allow, dest); | 1449 | rset_clear(allow, dest); |
994 | base = ra_alloc1(as, REF_BASE, allow); | 1450 | base = ra_alloc1(as, REF_BASE, allow); |
995 | rset_clear(allow, base); | 1451 | rset_clear(allow, base); |
996 | if ((ir->op2 & IRSLOAD_CONVERT)) { | 1452 | if (!LJ_SOFTFP32 && (ir->op2 & IRSLOAD_CONVERT)) { |
997 | if (irt_isint(t)) { | 1453 | if (irt_isint(t)) { |
998 | Reg tmp = ra_scratch(as, RSET_FPR); | 1454 | Reg tmp = ra_scratch(as, LJ_SOFTFP ? RSET_GPR : RSET_FPR); |
1455 | #if LJ_SOFTFP | ||
1456 | ra_evictset(as, rset_exclude(RSET_SCRATCH, dest)); | ||
1457 | ra_destreg(as, ir, RID_RET); | ||
1458 | emit_call(as, (void *)lj_ir_callinfo[IRCALL_softfp_d2i].func, 0); | ||
1459 | if (tmp != REGARG_FIRSTGPR) | ||
1460 | emit_move(as, REGARG_FIRSTGPR, tmp); | ||
1461 | #else | ||
999 | emit_tg(as, MIPSI_MFC1, dest, tmp); | 1462 | emit_tg(as, MIPSI_MFC1, dest, tmp); |
1000 | emit_fg(as, MIPSI_CVT_W_D, tmp, tmp); | 1463 | emit_fg(as, MIPSI_TRUNC_W_D, tmp, tmp); |
1464 | #endif | ||
1001 | dest = tmp; | 1465 | dest = tmp; |
1002 | t.irt = IRT_NUM; /* Check for original type. */ | 1466 | t.irt = IRT_NUM; /* Check for original type. */ |
1003 | } else { | 1467 | } else { |
1004 | Reg tmp = ra_scratch(as, RSET_GPR); | 1468 | Reg tmp = ra_scratch(as, RSET_GPR); |
1469 | #if LJ_SOFTFP | ||
1470 | ra_evictset(as, rset_exclude(RSET_SCRATCH, dest)); | ||
1471 | ra_destreg(as, ir, RID_RET); | ||
1472 | emit_call(as, (void *)lj_ir_callinfo[IRCALL_softfp_i2d].func, 0); | ||
1473 | emit_dta(as, MIPSI_SLL, REGARG_FIRSTGPR, tmp, 0); | ||
1474 | #else | ||
1005 | emit_fg(as, MIPSI_CVT_D_W, dest, dest); | 1475 | emit_fg(as, MIPSI_CVT_D_W, dest, dest); |
1006 | emit_tg(as, MIPSI_MTC1, tmp, dest); | 1476 | emit_tg(as, MIPSI_MTC1, tmp, dest); |
1477 | #endif | ||
1007 | dest = tmp; | 1478 | dest = tmp; |
1008 | t.irt = IRT_INT; /* Check for original type. */ | 1479 | t.irt = IRT_INT; /* Check for original type. */ |
1009 | } | 1480 | } |
1010 | } | 1481 | } |
1482 | #if LJ_64 | ||
1483 | else if (irt_isaddr(t)) { | ||
1484 | /* Clear type from pointers. */ | ||
1485 | emit_tsml(as, MIPSI_DEXTM, dest, dest, 14, 0); | ||
1486 | } else if (irt_isint(t) && (ir->op2 & IRSLOAD_TYPECHECK)) { | ||
1487 | /* Sign-extend integers. */ | ||
1488 | emit_dta(as, MIPSI_SLL, dest, dest, 0); | ||
1489 | } | ||
1490 | #endif | ||
1011 | goto dotypecheck; | 1491 | goto dotypecheck; |
1012 | } | 1492 | } |
1013 | base = ra_alloc1(as, REF_BASE, allow); | 1493 | base = ra_alloc1(as, REF_BASE, allow); |
1014 | rset_clear(allow, base); | 1494 | rset_clear(allow, base); |
1015 | dotypecheck: | 1495 | dotypecheck: |
1016 | if (irt_isnum(t)) { | 1496 | #if LJ_32 |
1017 | if ((ir->op2 & IRSLOAD_TYPECHECK)) { | 1497 | if ((ir->op2 & IRSLOAD_TYPECHECK)) { |
1018 | asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO); | 1498 | if (ra_noreg(type)) |
1019 | emit_tsi(as, MIPSI_SLTIU, RID_TMP, RID_TMP, (int32_t)LJ_TISNUM); | ||
1020 | type = RID_TMP; | 1499 | type = RID_TMP; |
1021 | } | 1500 | if (irt_isnum(t)) { |
1022 | if (ra_hasreg(dest)) emit_hsi(as, MIPSI_LDC1, dest, base, ofs); | 1501 | asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO); |
1023 | } else { | 1502 | emit_tsi(as, MIPSI_SLTIU, RID_TMP, type, (int32_t)LJ_TISNUM); |
1024 | if ((ir->op2 & IRSLOAD_TYPECHECK)) { | 1503 | } else { |
1025 | Reg ktype = ra_allock(as, irt_toitype(t), allow); | 1504 | Reg ktype = ra_allock(as, irt_toitype(t), allow); |
1026 | asm_guard(as, MIPSI_BNE, RID_TMP, ktype); | 1505 | asm_guard(as, MIPSI_BNE, type, ktype); |
1027 | type = RID_TMP; | 1506 | } |
1507 | } | ||
1508 | if (ra_hasreg(dest)) { | ||
1509 | if (!LJ_SOFTFP && irt_isnum(t)) | ||
1510 | emit_hsi(as, MIPSI_LDC1, dest, base, ofs); | ||
1511 | else | ||
1512 | emit_tsi(as, MIPSI_LW, dest, base, ofs ^ (LJ_BE?4:0)); | ||
1513 | } | ||
1514 | if (ra_hasreg(type)) | ||
1515 | emit_tsi(as, MIPSI_LW, type, base, ofs ^ (LJ_BE?0:4)); | ||
1516 | #else | ||
1517 | if ((ir->op2 & IRSLOAD_TYPECHECK)) { | ||
1518 | type = dest < RID_MAX_GPR ? dest : RID_TMP; | ||
1519 | if (irt_ispri(t)) { | ||
1520 | asm_guard(as, MIPSI_BNE, type, | ||
1521 | ra_allock(as, ~((int64_t)~irt_toitype(t) << 47) , allow)); | ||
1522 | } else { | ||
1523 | if (irt_isnum(t)) { | ||
1524 | asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO); | ||
1525 | emit_tsi(as, MIPSI_SLTIU, RID_TMP, RID_TMP, (int32_t)LJ_TISNUM); | ||
1526 | if (!LJ_SOFTFP && ra_hasreg(dest)) | ||
1527 | emit_hsi(as, MIPSI_LDC1, dest, base, ofs); | ||
1528 | } else { | ||
1529 | asm_guard(as, MIPSI_BNE, RID_TMP, | ||
1530 | ra_allock(as, (int32_t)irt_toitype(t), allow)); | ||
1531 | } | ||
1532 | emit_dta(as, MIPSI_DSRA32, RID_TMP, type, 15); | ||
1028 | } | 1533 | } |
1029 | if (ra_hasreg(dest)) emit_tsi(as, MIPSI_LW, dest, base, ofs ^ (LJ_BE?4:0)); | 1534 | emit_tsi(as, MIPSI_LD, type, base, ofs); |
1535 | } else if (ra_hasreg(dest)) { | ||
1536 | if (!LJ_SOFTFP && irt_isnum(t)) | ||
1537 | emit_hsi(as, MIPSI_LDC1, dest, base, ofs); | ||
1538 | else | ||
1539 | emit_tsi(as, irt_isint(t) ? MIPSI_LW : MIPSI_LD, dest, base, | ||
1540 | ofs ^ ((LJ_BE && irt_isint(t)) ? 4 : 0)); | ||
1030 | } | 1541 | } |
1031 | if (ra_hasreg(type)) emit_tsi(as, MIPSI_LW, type, base, ofs ^ (LJ_BE?0:4)); | 1542 | #endif |
1032 | } | 1543 | } |
1033 | 1544 | ||
1034 | /* -- Allocations --------------------------------------------------------- */ | 1545 | /* -- Allocations --------------------------------------------------------- */ |
@@ -1037,19 +1548,15 @@ dotypecheck: | |||
1037 | static void asm_cnew(ASMState *as, IRIns *ir) | 1548 | static void asm_cnew(ASMState *as, IRIns *ir) |
1038 | { | 1549 | { |
1039 | CTState *cts = ctype_ctsG(J2G(as->J)); | 1550 | CTState *cts = ctype_ctsG(J2G(as->J)); |
1040 | CTypeID ctypeid = (CTypeID)IR(ir->op1)->i; | 1551 | CTypeID id = (CTypeID)IR(ir->op1)->i; |
1041 | CTSize sz = (ir->o == IR_CNEWI || ir->op2 == REF_NIL) ? | 1552 | CTSize sz; |
1042 | lj_ctype_size(cts, ctypeid) : (CTSize)IR(ir->op2)->i; | 1553 | CTInfo info = lj_ctype_info(cts, id, &sz); |
1043 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco]; | 1554 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco]; |
1044 | IRRef args[2]; | 1555 | IRRef args[4]; |
1045 | RegSet allow = (RSET_GPR & ~RSET_SCRATCH); | ||
1046 | RegSet drop = RSET_SCRATCH; | 1556 | RegSet drop = RSET_SCRATCH; |
1047 | lua_assert(sz != CTSIZE_INVALID); | 1557 | lua_assert(sz != CTSIZE_INVALID || (ir->o == IR_CNEW && ir->op2 != REF_NIL)); |
1048 | 1558 | ||
1049 | args[0] = ASMREF_L; /* lua_State *L */ | ||
1050 | args[1] = ASMREF_TMP1; /* MSize size */ | ||
1051 | as->gcsteps++; | 1559 | as->gcsteps++; |
1052 | |||
1053 | if (ra_hasreg(ir->r)) | 1560 | if (ra_hasreg(ir->r)) |
1054 | rset_clear(drop, ir->r); /* Dest reg handled below. */ | 1561 | rset_clear(drop, ir->r); /* Dest reg handled below. */ |
1055 | ra_evictset(as, drop); | 1562 | ra_evictset(as, drop); |
@@ -1058,8 +1565,9 @@ static void asm_cnew(ASMState *as, IRIns *ir) | |||
1058 | 1565 | ||
1059 | /* Initialize immutable cdata object. */ | 1566 | /* Initialize immutable cdata object. */ |
1060 | if (ir->o == IR_CNEWI) { | 1567 | if (ir->o == IR_CNEWI) { |
1568 | RegSet allow = (RSET_GPR & ~RSET_SCRATCH); | ||
1569 | #if LJ_32 | ||
1061 | int32_t ofs = sizeof(GCcdata); | 1570 | int32_t ofs = sizeof(GCcdata); |
1062 | lua_assert(sz == 4 || sz == 8); | ||
1063 | if (sz == 8) { | 1571 | if (sz == 8) { |
1064 | ofs += 4; | 1572 | ofs += 4; |
1065 | lua_assert((ir+1)->o == IR_HIOP); | 1573 | lua_assert((ir+1)->o == IR_HIOP); |
@@ -1072,12 +1580,29 @@ static void asm_cnew(ASMState *as, IRIns *ir) | |||
1072 | if (ofs == sizeof(GCcdata)) break; | 1580 | if (ofs == sizeof(GCcdata)) break; |
1073 | ofs -= 4; if (LJ_BE) ir++; else ir--; | 1581 | ofs -= 4; if (LJ_BE) ir++; else ir--; |
1074 | } | 1582 | } |
1583 | #else | ||
1584 | emit_tsi(as, sz == 8 ? MIPSI_SD : MIPSI_SW, ra_alloc1(as, ir->op2, allow), | ||
1585 | RID_RET, sizeof(GCcdata)); | ||
1586 | #endif | ||
1587 | lua_assert(sz == 4 || sz == 8); | ||
1588 | } else if (ir->op2 != REF_NIL) { /* Create VLA/VLS/aligned cdata. */ | ||
1589 | ci = &lj_ir_callinfo[IRCALL_lj_cdata_newv]; | ||
1590 | args[0] = ASMREF_L; /* lua_State *L */ | ||
1591 | args[1] = ir->op1; /* CTypeID id */ | ||
1592 | args[2] = ir->op2; /* CTSize sz */ | ||
1593 | args[3] = ASMREF_TMP1; /* CTSize align */ | ||
1594 | asm_gencall(as, ci, args); | ||
1595 | emit_loadi(as, ra_releasetmp(as, ASMREF_TMP1), (int32_t)ctype_align(info)); | ||
1596 | return; | ||
1075 | } | 1597 | } |
1598 | |||
1076 | /* Initialize gct and ctypeid. lj_mem_newgco() already sets marked. */ | 1599 | /* Initialize gct and ctypeid. lj_mem_newgco() already sets marked. */ |
1077 | emit_tsi(as, MIPSI_SB, RID_RET+1, RID_RET, offsetof(GCcdata, gct)); | 1600 | emit_tsi(as, MIPSI_SB, RID_RET+1, RID_RET, offsetof(GCcdata, gct)); |
1078 | emit_tsi(as, MIPSI_SH, RID_TMP, RID_RET, offsetof(GCcdata, ctypeid)); | 1601 | emit_tsi(as, MIPSI_SH, RID_TMP, RID_RET, offsetof(GCcdata, ctypeid)); |
1079 | emit_ti(as, MIPSI_LI, RID_RET+1, ~LJ_TCDATA); | 1602 | emit_ti(as, MIPSI_LI, RID_RET+1, ~LJ_TCDATA); |
1080 | emit_ti(as, MIPSI_LI, RID_TMP, ctypeid); /* Lower 16 bit used. Sign-ext ok. */ | 1603 | emit_ti(as, MIPSI_LI, RID_TMP, id); /* Lower 16 bit used. Sign-ext ok. */ |
1604 | args[0] = ASMREF_L; /* lua_State *L */ | ||
1605 | args[1] = ASMREF_TMP1; /* MSize size */ | ||
1081 | asm_gencall(as, ci, args); | 1606 | asm_gencall(as, ci, args); |
1082 | ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)), | 1607 | ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)), |
1083 | ra_releasetmp(as, ASMREF_TMP1)); | 1608 | ra_releasetmp(as, ASMREF_TMP1)); |
@@ -1094,7 +1619,7 @@ static void asm_tbar(ASMState *as, IRIns *ir) | |||
1094 | Reg mark = ra_scratch(as, rset_exclude(RSET_GPR, tab)); | 1619 | Reg mark = ra_scratch(as, rset_exclude(RSET_GPR, tab)); |
1095 | Reg link = RID_TMP; | 1620 | Reg link = RID_TMP; |
1096 | MCLabel l_end = emit_label(as); | 1621 | MCLabel l_end = emit_label(as); |
1097 | emit_tsi(as, MIPSI_SW, link, tab, (int32_t)offsetof(GCtab, gclist)); | 1622 | emit_tsi(as, MIPSI_AS, link, tab, (int32_t)offsetof(GCtab, gclist)); |
1098 | emit_tsi(as, MIPSI_SB, mark, tab, (int32_t)offsetof(GCtab, marked)); | 1623 | emit_tsi(as, MIPSI_SB, mark, tab, (int32_t)offsetof(GCtab, marked)); |
1099 | emit_setgl(as, tab, gc.grayagain); | 1624 | emit_setgl(as, tab, gc.grayagain); |
1100 | emit_getgl(as, link, gc.grayagain); | 1625 | emit_getgl(as, link, gc.grayagain); |
@@ -1117,7 +1642,7 @@ static void asm_obar(ASMState *as, IRIns *ir) | |||
1117 | args[0] = ASMREF_TMP1; /* global_State *g */ | 1642 | args[0] = ASMREF_TMP1; /* global_State *g */ |
1118 | args[1] = ir->op1; /* TValue *tv */ | 1643 | args[1] = ir->op1; /* TValue *tv */ |
1119 | asm_gencall(as, ci, args); | 1644 | asm_gencall(as, ci, args); |
1120 | emit_tsi(as, MIPSI_ADDIU, ra_releasetmp(as, ASMREF_TMP1), RID_JGL, -32768); | 1645 | emit_tsi(as, MIPSI_AADDIU, ra_releasetmp(as, ASMREF_TMP1), RID_JGL, -32768); |
1121 | obj = IR(ir->op1)->r; | 1646 | obj = IR(ir->op1)->r; |
1122 | tmp = ra_scratch(as, rset_exclude(RSET_GPR, obj)); | 1647 | tmp = ra_scratch(as, rset_exclude(RSET_GPR, obj)); |
1123 | emit_branch(as, MIPSI_BEQ, RID_TMP, RID_ZERO, l_end); | 1648 | emit_branch(as, MIPSI_BEQ, RID_TMP, RID_ZERO, l_end); |
@@ -1132,6 +1657,7 @@ static void asm_obar(ASMState *as, IRIns *ir) | |||
1132 | 1657 | ||
1133 | /* -- Arithmetic and logic operations ------------------------------------- */ | 1658 | /* -- Arithmetic and logic operations ------------------------------------- */ |
1134 | 1659 | ||
1660 | #if !LJ_SOFTFP | ||
1135 | static void asm_fparith(ASMState *as, IRIns *ir, MIPSIns mi) | 1661 | static void asm_fparith(ASMState *as, IRIns *ir, MIPSIns mi) |
1136 | { | 1662 | { |
1137 | Reg dest = ra_dest(as, ir, RSET_FPR); | 1663 | Reg dest = ra_dest(as, ir, RSET_FPR); |
@@ -1146,83 +1672,180 @@ static void asm_fpunary(ASMState *as, IRIns *ir, MIPSIns mi) | |||
1146 | Reg left = ra_hintalloc(as, ir->op1, dest, RSET_FPR); | 1672 | Reg left = ra_hintalloc(as, ir->op1, dest, RSET_FPR); |
1147 | emit_fg(as, mi, dest, left); | 1673 | emit_fg(as, mi, dest, left); |
1148 | } | 1674 | } |
1675 | #endif | ||
1149 | 1676 | ||
1150 | static int asm_fpjoin_pow(ASMState *as, IRIns *ir) | 1677 | #if !LJ_SOFTFP32 |
1151 | { | 1678 | static void asm_fpmath(ASMState *as, IRIns *ir) |
1152 | IRIns *irp = IR(ir->op1); | 1679 | { |
1153 | if (irp == ir-1 && irp->o == IR_MUL && !ra_used(irp)) { | 1680 | if (ir->op2 == IRFPM_EXP2 && asm_fpjoin_pow(as, ir)) |
1154 | IRIns *irpp = IR(irp->op1); | 1681 | return; |
1155 | if (irpp == ir-2 && irpp->o == IR_FPMATH && | 1682 | #if !LJ_SOFTFP |
1156 | irpp->op2 == IRFPM_LOG2 && !ra_used(irpp)) { | 1683 | if (ir->op2 <= IRFPM_TRUNC) |
1157 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_pow]; | 1684 | asm_callround(as, ir, IRCALL_lj_vm_floor + ir->op2); |
1158 | IRRef args[2]; | 1685 | else if (ir->op2 == IRFPM_SQRT) |
1159 | args[0] = irpp->op1; | 1686 | asm_fpunary(as, ir, MIPSI_SQRT_D); |
1160 | args[1] = irp->op2; | 1687 | else |
1161 | asm_setupresult(as, ir, ci); | 1688 | #endif |
1162 | asm_gencall(as, ci, args); | 1689 | asm_callid(as, ir, IRCALL_lj_vm_floor + ir->op2); |
1163 | return 1; | ||
1164 | } | ||
1165 | } | ||
1166 | return 0; | ||
1167 | } | 1690 | } |
1691 | #endif | ||
1692 | |||
1693 | #if !LJ_SOFTFP | ||
1694 | #define asm_fpadd(as, ir) asm_fparith(as, ir, MIPSI_ADD_D) | ||
1695 | #define asm_fpsub(as, ir) asm_fparith(as, ir, MIPSI_SUB_D) | ||
1696 | #define asm_fpmul(as, ir) asm_fparith(as, ir, MIPSI_MUL_D) | ||
1697 | #elif LJ_64 /* && LJ_SOFTFP */ | ||
1698 | #define asm_fpadd(as, ir) asm_callid(as, ir, IRCALL_softfp_add) | ||
1699 | #define asm_fpsub(as, ir) asm_callid(as, ir, IRCALL_softfp_sub) | ||
1700 | #define asm_fpmul(as, ir) asm_callid(as, ir, IRCALL_softfp_mul) | ||
1701 | #endif | ||
1168 | 1702 | ||
1169 | static void asm_add(ASMState *as, IRIns *ir) | 1703 | static void asm_add(ASMState *as, IRIns *ir) |
1170 | { | 1704 | { |
1171 | if (irt_isnum(ir->t)) { | 1705 | IRType1 t = ir->t; |
1172 | asm_fparith(as, ir, MIPSI_ADD_D); | 1706 | #if !LJ_SOFTFP32 |
1173 | } else { | 1707 | if (irt_isnum(t)) { |
1708 | asm_fpadd(as, ir); | ||
1709 | } else | ||
1710 | #endif | ||
1711 | { | ||
1712 | /* TODO MIPSR6: Fuse ADD(BSHL(a,1-4),b) or ADD(ADD(a,a),b) to MIPSI_ALSA. */ | ||
1174 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1713 | Reg dest = ra_dest(as, ir, RSET_GPR); |
1175 | Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); | 1714 | Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); |
1176 | if (irref_isk(ir->op2)) { | 1715 | if (irref_isk(ir->op2)) { |
1177 | int32_t k = IR(ir->op2)->i; | 1716 | intptr_t k = get_kval(IR(ir->op2)); |
1178 | if (checki16(k)) { | 1717 | if (checki16(k)) { |
1179 | emit_tsi(as, MIPSI_ADDIU, dest, left, k); | 1718 | emit_tsi(as, (LJ_64 && irt_is64(t)) ? MIPSI_DADDIU : MIPSI_ADDIU, dest, |
1719 | left, k); | ||
1180 | return; | 1720 | return; |
1181 | } | 1721 | } |
1182 | } | 1722 | } |
1183 | right = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, left)); | 1723 | right = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, left)); |
1184 | emit_dst(as, MIPSI_ADDU, dest, left, right); | 1724 | emit_dst(as, (LJ_64 && irt_is64(t)) ? MIPSI_DADDU : MIPSI_ADDU, dest, |
1725 | left, right); | ||
1185 | } | 1726 | } |
1186 | } | 1727 | } |
1187 | 1728 | ||
1188 | static void asm_sub(ASMState *as, IRIns *ir) | 1729 | static void asm_sub(ASMState *as, IRIns *ir) |
1189 | { | 1730 | { |
1731 | #if !LJ_SOFTFP32 | ||
1190 | if (irt_isnum(ir->t)) { | 1732 | if (irt_isnum(ir->t)) { |
1191 | asm_fparith(as, ir, MIPSI_SUB_D); | 1733 | asm_fpsub(as, ir); |
1192 | } else { | 1734 | } else |
1735 | #endif | ||
1736 | { | ||
1193 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1737 | Reg dest = ra_dest(as, ir, RSET_GPR); |
1194 | Reg right, left = ra_alloc2(as, ir, RSET_GPR); | 1738 | Reg right, left = ra_alloc2(as, ir, RSET_GPR); |
1195 | right = (left >> 8); left &= 255; | 1739 | right = (left >> 8); left &= 255; |
1196 | emit_dst(as, MIPSI_SUBU, dest, left, right); | 1740 | emit_dst(as, (LJ_64 && irt_is64(ir->t)) ? MIPSI_DSUBU : MIPSI_SUBU, dest, |
1741 | left, right); | ||
1197 | } | 1742 | } |
1198 | } | 1743 | } |
1199 | 1744 | ||
1200 | static void asm_mul(ASMState *as, IRIns *ir) | 1745 | static void asm_mul(ASMState *as, IRIns *ir) |
1201 | { | 1746 | { |
1747 | #if !LJ_SOFTFP32 | ||
1202 | if (irt_isnum(ir->t)) { | 1748 | if (irt_isnum(ir->t)) { |
1203 | asm_fparith(as, ir, MIPSI_MUL_D); | 1749 | asm_fpmul(as, ir); |
1204 | } else { | 1750 | } else |
1751 | #endif | ||
1752 | { | ||
1205 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1753 | Reg dest = ra_dest(as, ir, RSET_GPR); |
1206 | Reg right, left = ra_alloc2(as, ir, RSET_GPR); | 1754 | Reg right, left = ra_alloc2(as, ir, RSET_GPR); |
1207 | right = (left >> 8); left &= 255; | 1755 | right = (left >> 8); left &= 255; |
1208 | emit_dst(as, MIPSI_MUL, dest, left, right); | 1756 | if (LJ_64 && irt_is64(ir->t)) { |
1757 | #if !LJ_TARGET_MIPSR6 | ||
1758 | emit_dst(as, MIPSI_MFLO, dest, 0, 0); | ||
1759 | emit_dst(as, MIPSI_DMULT, 0, left, right); | ||
1760 | #else | ||
1761 | emit_dst(as, MIPSI_DMUL, dest, left, right); | ||
1762 | #endif | ||
1763 | } else { | ||
1764 | emit_dst(as, MIPSI_MUL, dest, left, right); | ||
1765 | } | ||
1209 | } | 1766 | } |
1210 | } | 1767 | } |
1211 | 1768 | ||
1769 | static void asm_mod(ASMState *as, IRIns *ir) | ||
1770 | { | ||
1771 | #if LJ_64 && LJ_HASFFI | ||
1772 | if (!irt_isint(ir->t)) | ||
1773 | asm_callid(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_modi64 : | ||
1774 | IRCALL_lj_carith_modu64); | ||
1775 | else | ||
1776 | #endif | ||
1777 | asm_callid(as, ir, IRCALL_lj_vm_modi); | ||
1778 | } | ||
1779 | |||
1780 | #if !LJ_SOFTFP32 | ||
1781 | static void asm_pow(ASMState *as, IRIns *ir) | ||
1782 | { | ||
1783 | #if LJ_64 && LJ_HASFFI | ||
1784 | if (!irt_isnum(ir->t)) | ||
1785 | asm_callid(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_powi64 : | ||
1786 | IRCALL_lj_carith_powu64); | ||
1787 | else | ||
1788 | #endif | ||
1789 | asm_callid(as, ir, IRCALL_lj_vm_powi); | ||
1790 | } | ||
1791 | |||
1792 | static void asm_div(ASMState *as, IRIns *ir) | ||
1793 | { | ||
1794 | #if LJ_64 && LJ_HASFFI | ||
1795 | if (!irt_isnum(ir->t)) | ||
1796 | asm_callid(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_divi64 : | ||
1797 | IRCALL_lj_carith_divu64); | ||
1798 | else | ||
1799 | #endif | ||
1800 | #if !LJ_SOFTFP | ||
1801 | asm_fparith(as, ir, MIPSI_DIV_D); | ||
1802 | #else | ||
1803 | asm_callid(as, ir, IRCALL_softfp_div); | ||
1804 | #endif | ||
1805 | } | ||
1806 | #endif | ||
1807 | |||
1212 | static void asm_neg(ASMState *as, IRIns *ir) | 1808 | static void asm_neg(ASMState *as, IRIns *ir) |
1213 | { | 1809 | { |
1810 | #if !LJ_SOFTFP | ||
1214 | if (irt_isnum(ir->t)) { | 1811 | if (irt_isnum(ir->t)) { |
1215 | asm_fpunary(as, ir, MIPSI_NEG_D); | 1812 | asm_fpunary(as, ir, MIPSI_NEG_D); |
1216 | } else { | 1813 | } else |
1814 | #elif LJ_64 /* && LJ_SOFTFP */ | ||
1815 | if (irt_isnum(ir->t)) { | ||
1816 | Reg dest = ra_dest(as, ir, RSET_GPR); | ||
1817 | Reg left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); | ||
1818 | emit_dst(as, MIPSI_XOR, dest, left, | ||
1819 | ra_allock(as, 0x8000000000000000ll, rset_exclude(RSET_GPR, dest))); | ||
1820 | } else | ||
1821 | #endif | ||
1822 | { | ||
1217 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1823 | Reg dest = ra_dest(as, ir, RSET_GPR); |
1218 | Reg left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); | 1824 | Reg left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); |
1219 | emit_dst(as, MIPSI_SUBU, dest, RID_ZERO, left); | 1825 | emit_dst(as, (LJ_64 && irt_is64(ir->t)) ? MIPSI_DSUBU : MIPSI_SUBU, dest, |
1826 | RID_ZERO, left); | ||
1220 | } | 1827 | } |
1221 | } | 1828 | } |
1222 | 1829 | ||
1830 | #if !LJ_SOFTFP | ||
1831 | #define asm_abs(as, ir) asm_fpunary(as, ir, MIPSI_ABS_D) | ||
1832 | #elif LJ_64 /* && LJ_SOFTFP */ | ||
1833 | static void asm_abs(ASMState *as, IRIns *ir) | ||
1834 | { | ||
1835 | Reg dest = ra_dest(as, ir, RSET_GPR); | ||
1836 | Reg left = ra_alloc1(as, ir->op1, RSET_GPR); | ||
1837 | emit_tsml(as, MIPSI_DEXTM, dest, left, 30, 0); | ||
1838 | } | ||
1839 | #endif | ||
1840 | |||
1841 | #define asm_atan2(as, ir) asm_callid(as, ir, IRCALL_atan2) | ||
1842 | #define asm_ldexp(as, ir) asm_callid(as, ir, IRCALL_ldexp) | ||
1843 | |||
1223 | static void asm_arithov(ASMState *as, IRIns *ir) | 1844 | static void asm_arithov(ASMState *as, IRIns *ir) |
1224 | { | 1845 | { |
1846 | /* TODO MIPSR6: bovc/bnvc. Caveat: no delay slot to load RID_TMP. */ | ||
1225 | Reg right, left, tmp, dest = ra_dest(as, ir, RSET_GPR); | 1847 | Reg right, left, tmp, dest = ra_dest(as, ir, RSET_GPR); |
1848 | lua_assert(!irt_is64(ir->t)); | ||
1226 | if (irref_isk(ir->op2)) { | 1849 | if (irref_isk(ir->op2)) { |
1227 | int k = IR(ir->op2)->i; | 1850 | int k = IR(ir->op2)->i; |
1228 | if (ir->o == IR_SUBOV) k = -k; | 1851 | if (ir->o == IR_SUBOV) k = -k; |
@@ -1253,16 +1876,29 @@ static void asm_arithov(ASMState *as, IRIns *ir) | |||
1253 | emit_move(as, RID_TMP, dest == left ? left : right); | 1876 | emit_move(as, RID_TMP, dest == left ? left : right); |
1254 | } | 1877 | } |
1255 | 1878 | ||
1879 | #define asm_addov(as, ir) asm_arithov(as, ir) | ||
1880 | #define asm_subov(as, ir) asm_arithov(as, ir) | ||
1881 | |||
1256 | static void asm_mulov(ASMState *as, IRIns *ir) | 1882 | static void asm_mulov(ASMState *as, IRIns *ir) |
1257 | { | 1883 | { |
1258 | #if LJ_DUALNUM | 1884 | Reg dest = ra_dest(as, ir, RSET_GPR); |
1259 | #error "NYI: MULOV" | 1885 | Reg tmp, right, left = ra_alloc2(as, ir, RSET_GPR); |
1886 | right = (left >> 8); left &= 255; | ||
1887 | tmp = ra_scratch(as, rset_exclude(rset_exclude(rset_exclude(RSET_GPR, left), | ||
1888 | right), dest)); | ||
1889 | asm_guard(as, MIPSI_BNE, RID_TMP, tmp); | ||
1890 | emit_dta(as, MIPSI_SRA, RID_TMP, dest, 31); | ||
1891 | #if !LJ_TARGET_MIPSR6 | ||
1892 | emit_dst(as, MIPSI_MFHI, tmp, 0, 0); | ||
1893 | emit_dst(as, MIPSI_MFLO, dest, 0, 0); | ||
1894 | emit_dst(as, MIPSI_MULT, 0, left, right); | ||
1260 | #else | 1895 | #else |
1261 | UNUSED(as); UNUSED(ir); lua_assert(0); /* Unused in single-number mode. */ | 1896 | emit_dst(as, MIPSI_MUL, dest, left, right); |
1897 | emit_dst(as, MIPSI_MUH, tmp, left, right); | ||
1262 | #endif | 1898 | #endif |
1263 | } | 1899 | } |
1264 | 1900 | ||
1265 | #if LJ_HASFFI | 1901 | #if LJ_32 && LJ_HASFFI |
1266 | static void asm_add64(ASMState *as, IRIns *ir) | 1902 | static void asm_add64(ASMState *as, IRIns *ir) |
1267 | { | 1903 | { |
1268 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1904 | Reg dest = ra_dest(as, ir, RSET_GPR); |
@@ -1346,7 +1982,7 @@ static void asm_neg64(ASMState *as, IRIns *ir) | |||
1346 | } | 1982 | } |
1347 | #endif | 1983 | #endif |
1348 | 1984 | ||
1349 | static void asm_bitnot(ASMState *as, IRIns *ir) | 1985 | static void asm_bnot(ASMState *as, IRIns *ir) |
1350 | { | 1986 | { |
1351 | Reg left, right, dest = ra_dest(as, ir, RSET_GPR); | 1987 | Reg left, right, dest = ra_dest(as, ir, RSET_GPR); |
1352 | IRIns *irl = IR(ir->op1); | 1988 | IRIns *irl = IR(ir->op1); |
@@ -1360,11 +1996,12 @@ static void asm_bitnot(ASMState *as, IRIns *ir) | |||
1360 | emit_dst(as, MIPSI_NOR, dest, left, right); | 1996 | emit_dst(as, MIPSI_NOR, dest, left, right); |
1361 | } | 1997 | } |
1362 | 1998 | ||
1363 | static void asm_bitswap(ASMState *as, IRIns *ir) | 1999 | static void asm_bswap(ASMState *as, IRIns *ir) |
1364 | { | 2000 | { |
1365 | Reg dest = ra_dest(as, ir, RSET_GPR); | 2001 | Reg dest = ra_dest(as, ir, RSET_GPR); |
1366 | Reg left = ra_alloc1(as, ir->op1, RSET_GPR); | 2002 | Reg left = ra_alloc1(as, ir->op1, RSET_GPR); |
1367 | if ((as->flags & JIT_F_MIPS32R2)) { | 2003 | #if LJ_32 |
2004 | if ((as->flags & JIT_F_MIPSXXR2)) { | ||
1368 | emit_dta(as, MIPSI_ROTR, dest, RID_TMP, 16); | 2005 | emit_dta(as, MIPSI_ROTR, dest, RID_TMP, 16); |
1369 | emit_dst(as, MIPSI_WSBH, RID_TMP, 0, left); | 2006 | emit_dst(as, MIPSI_WSBH, RID_TMP, 0, left); |
1370 | } else { | 2007 | } else { |
@@ -1379,6 +2016,15 @@ static void asm_bitswap(ASMState *as, IRIns *ir) | |||
1379 | emit_dta(as, MIPSI_SRL, tmp, left, 24); | 2016 | emit_dta(as, MIPSI_SRL, tmp, left, 24); |
1380 | emit_dta(as, MIPSI_SLL, RID_TMP, left, 24); | 2017 | emit_dta(as, MIPSI_SLL, RID_TMP, left, 24); |
1381 | } | 2018 | } |
2019 | #else | ||
2020 | if (irt_is64(ir->t)) { | ||
2021 | emit_dst(as, MIPSI_DSHD, dest, 0, RID_TMP); | ||
2022 | emit_dst(as, MIPSI_DSBH, RID_TMP, 0, left); | ||
2023 | } else { | ||
2024 | emit_dta(as, MIPSI_ROTR, dest, RID_TMP, 16); | ||
2025 | emit_dst(as, MIPSI_WSBH, RID_TMP, 0, left); | ||
2026 | } | ||
2027 | #endif | ||
1382 | } | 2028 | } |
1383 | 2029 | ||
1384 | static void asm_bitop(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik) | 2030 | static void asm_bitop(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik) |
@@ -1386,7 +2032,7 @@ static void asm_bitop(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik) | |||
1386 | Reg dest = ra_dest(as, ir, RSET_GPR); | 2032 | Reg dest = ra_dest(as, ir, RSET_GPR); |
1387 | Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); | 2033 | Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); |
1388 | if (irref_isk(ir->op2)) { | 2034 | if (irref_isk(ir->op2)) { |
1389 | int32_t k = IR(ir->op2)->i; | 2035 | intptr_t k = get_kval(IR(ir->op2)); |
1390 | if (checku16(k)) { | 2036 | if (checku16(k)) { |
1391 | emit_tsi(as, mik, dest, left, k); | 2037 | emit_tsi(as, mik, dest, left, k); |
1392 | return; | 2038 | return; |
@@ -1396,22 +2042,34 @@ static void asm_bitop(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik) | |||
1396 | emit_dst(as, mi, dest, left, right); | 2042 | emit_dst(as, mi, dest, left, right); |
1397 | } | 2043 | } |
1398 | 2044 | ||
2045 | #define asm_band(as, ir) asm_bitop(as, ir, MIPSI_AND, MIPSI_ANDI) | ||
2046 | #define asm_bor(as, ir) asm_bitop(as, ir, MIPSI_OR, MIPSI_ORI) | ||
2047 | #define asm_bxor(as, ir) asm_bitop(as, ir, MIPSI_XOR, MIPSI_XORI) | ||
2048 | |||
1399 | static void asm_bitshift(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik) | 2049 | static void asm_bitshift(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik) |
1400 | { | 2050 | { |
1401 | Reg dest = ra_dest(as, ir, RSET_GPR); | 2051 | Reg dest = ra_dest(as, ir, RSET_GPR); |
1402 | if (irref_isk(ir->op2)) { /* Constant shifts. */ | 2052 | if (irref_isk(ir->op2)) { /* Constant shifts. */ |
1403 | uint32_t shift = (uint32_t)(IR(ir->op2)->i & 31); | 2053 | uint32_t shift = (uint32_t)IR(ir->op2)->i; |
1404 | emit_dta(as, mik, dest, ra_hintalloc(as, ir->op1, dest, RSET_GPR), shift); | 2054 | if (LJ_64 && irt_is64(ir->t)) mik |= (shift & 32) ? MIPSI_D32 : MIPSI_D; |
2055 | emit_dta(as, mik, dest, ra_hintalloc(as, ir->op1, dest, RSET_GPR), | ||
2056 | (shift & 31)); | ||
1405 | } else { | 2057 | } else { |
1406 | Reg right, left = ra_alloc2(as, ir, RSET_GPR); | 2058 | Reg right, left = ra_alloc2(as, ir, RSET_GPR); |
1407 | right = (left >> 8); left &= 255; | 2059 | right = (left >> 8); left &= 255; |
2060 | if (LJ_64 && irt_is64(ir->t)) mi |= MIPSI_DV; | ||
1408 | emit_dst(as, mi, dest, right, left); /* Shift amount is in rs. */ | 2061 | emit_dst(as, mi, dest, right, left); /* Shift amount is in rs. */ |
1409 | } | 2062 | } |
1410 | } | 2063 | } |
1411 | 2064 | ||
1412 | static void asm_bitror(ASMState *as, IRIns *ir) | 2065 | #define asm_bshl(as, ir) asm_bitshift(as, ir, MIPSI_SLLV, MIPSI_SLL) |
2066 | #define asm_bshr(as, ir) asm_bitshift(as, ir, MIPSI_SRLV, MIPSI_SRL) | ||
2067 | #define asm_bsar(as, ir) asm_bitshift(as, ir, MIPSI_SRAV, MIPSI_SRA) | ||
2068 | #define asm_brol(as, ir) lua_assert(0) | ||
2069 | |||
2070 | static void asm_bror(ASMState *as, IRIns *ir) | ||
1413 | { | 2071 | { |
1414 | if ((as->flags & JIT_F_MIPS32R2)) { | 2072 | if (LJ_64 || (as->flags & JIT_F_MIPSXXR2)) { |
1415 | asm_bitshift(as, ir, MIPSI_ROTRV, MIPSI_ROTR); | 2073 | asm_bitshift(as, ir, MIPSI_ROTRV, MIPSI_ROTR); |
1416 | } else { | 2074 | } else { |
1417 | Reg dest = ra_dest(as, ir, RSET_GPR); | 2075 | Reg dest = ra_dest(as, ir, RSET_GPR); |
@@ -1430,12 +2088,38 @@ static void asm_bitror(ASMState *as, IRIns *ir) | |||
1430 | } | 2088 | } |
1431 | } | 2089 | } |
1432 | 2090 | ||
2091 | #if LJ_SOFTFP | ||
2092 | static void asm_sfpmin_max(ASMState *as, IRIns *ir) | ||
2093 | { | ||
2094 | CCallInfo ci = lj_ir_callinfo[(IROp)ir->o == IR_MIN ? IRCALL_lj_vm_sfmin : IRCALL_lj_vm_sfmax]; | ||
2095 | #if LJ_64 | ||
2096 | IRRef args[2]; | ||
2097 | args[0] = ir->op1; | ||
2098 | args[1] = ir->op2; | ||
2099 | #else | ||
2100 | IRRef args[4]; | ||
2101 | args[0^LJ_BE] = ir->op1; | ||
2102 | args[1^LJ_BE] = (ir+1)->op1; | ||
2103 | args[2^LJ_BE] = ir->op2; | ||
2104 | args[3^LJ_BE] = (ir+1)->op2; | ||
2105 | #endif | ||
2106 | asm_setupresult(as, ir, &ci); | ||
2107 | emit_call(as, (void *)ci.func, 0); | ||
2108 | ci.func = NULL; | ||
2109 | asm_gencall(as, &ci, args); | ||
2110 | } | ||
2111 | #endif | ||
2112 | |||
1433 | static void asm_min_max(ASMState *as, IRIns *ir, int ismax) | 2113 | static void asm_min_max(ASMState *as, IRIns *ir, int ismax) |
1434 | { | 2114 | { |
1435 | if (irt_isnum(ir->t)) { | 2115 | if (!LJ_SOFTFP32 && irt_isnum(ir->t)) { |
2116 | #if LJ_SOFTFP | ||
2117 | asm_sfpmin_max(as, ir); | ||
2118 | #else | ||
1436 | Reg dest = ra_dest(as, ir, RSET_FPR); | 2119 | Reg dest = ra_dest(as, ir, RSET_FPR); |
1437 | Reg right, left = ra_alloc2(as, ir, RSET_FPR); | 2120 | Reg right, left = ra_alloc2(as, ir, RSET_FPR); |
1438 | right = (left >> 8); left &= 255; | 2121 | right = (left >> 8); left &= 255; |
2122 | #if !LJ_TARGET_MIPSR6 | ||
1439 | if (dest == left) { | 2123 | if (dest == left) { |
1440 | emit_fg(as, MIPSI_MOVT_D, dest, right); | 2124 | emit_fg(as, MIPSI_MOVT_D, dest, right); |
1441 | } else { | 2125 | } else { |
@@ -1443,42 +2127,143 @@ static void asm_min_max(ASMState *as, IRIns *ir, int ismax) | |||
1443 | if (dest != right) emit_fg(as, MIPSI_MOV_D, dest, right); | 2127 | if (dest != right) emit_fg(as, MIPSI_MOV_D, dest, right); |
1444 | } | 2128 | } |
1445 | emit_fgh(as, MIPSI_C_OLT_D, 0, ismax ? left : right, ismax ? right : left); | 2129 | emit_fgh(as, MIPSI_C_OLT_D, 0, ismax ? left : right, ismax ? right : left); |
2130 | #else | ||
2131 | emit_fgh(as, ismax ? MIPSI_MAX_D : MIPSI_MIN_D, dest, left, right); | ||
2132 | #endif | ||
2133 | #endif | ||
1446 | } else { | 2134 | } else { |
1447 | Reg dest = ra_dest(as, ir, RSET_GPR); | 2135 | Reg dest = ra_dest(as, ir, RSET_GPR); |
1448 | Reg right, left = ra_alloc2(as, ir, RSET_GPR); | 2136 | Reg right, left = ra_alloc2(as, ir, RSET_GPR); |
1449 | right = (left >> 8); left &= 255; | 2137 | right = (left >> 8); left &= 255; |
1450 | if (dest == left) { | 2138 | if (left == right) { |
1451 | emit_dst(as, MIPSI_MOVN, dest, right, RID_TMP); | 2139 | if (dest != left) emit_move(as, dest, left); |
1452 | } else { | 2140 | } else { |
1453 | emit_dst(as, MIPSI_MOVZ, dest, left, RID_TMP); | 2141 | #if !LJ_TARGET_MIPSR6 |
1454 | if (dest != right) emit_move(as, dest, right); | 2142 | if (dest == left) { |
2143 | emit_dst(as, MIPSI_MOVN, dest, right, RID_TMP); | ||
2144 | } else { | ||
2145 | emit_dst(as, MIPSI_MOVZ, dest, left, RID_TMP); | ||
2146 | if (dest != right) emit_move(as, dest, right); | ||
2147 | } | ||
2148 | #else | ||
2149 | emit_dst(as, MIPSI_OR, dest, dest, RID_TMP); | ||
2150 | if (dest != right) { | ||
2151 | emit_dst(as, MIPSI_SELNEZ, RID_TMP, right, RID_TMP); | ||
2152 | emit_dst(as, MIPSI_SELEQZ, dest, left, RID_TMP); | ||
2153 | } else { | ||
2154 | emit_dst(as, MIPSI_SELEQZ, RID_TMP, left, RID_TMP); | ||
2155 | emit_dst(as, MIPSI_SELNEZ, dest, right, RID_TMP); | ||
2156 | } | ||
2157 | #endif | ||
2158 | emit_dst(as, MIPSI_SLT, RID_TMP, | ||
2159 | ismax ? left : right, ismax ? right : left); | ||
1455 | } | 2160 | } |
1456 | emit_dst(as, MIPSI_SLT, RID_TMP, | ||
1457 | ismax ? left : right, ismax ? right : left); | ||
1458 | } | 2161 | } |
1459 | } | 2162 | } |
1460 | 2163 | ||
2164 | #define asm_min(as, ir) asm_min_max(as, ir, 0) | ||
2165 | #define asm_max(as, ir) asm_min_max(as, ir, 1) | ||
2166 | |||
1461 | /* -- Comparisons --------------------------------------------------------- */ | 2167 | /* -- Comparisons --------------------------------------------------------- */ |
1462 | 2168 | ||
2169 | #if LJ_SOFTFP | ||
2170 | /* SFP comparisons. */ | ||
2171 | static void asm_sfpcomp(ASMState *as, IRIns *ir) | ||
2172 | { | ||
2173 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_softfp_cmp]; | ||
2174 | RegSet drop = RSET_SCRATCH; | ||
2175 | Reg r; | ||
2176 | #if LJ_64 | ||
2177 | IRRef args[2]; | ||
2178 | args[0] = ir->op1; | ||
2179 | args[1] = ir->op2; | ||
2180 | #else | ||
2181 | IRRef args[4]; | ||
2182 | args[LJ_LE ? 0 : 1] = ir->op1; args[LJ_LE ? 1 : 0] = (ir+1)->op1; | ||
2183 | args[LJ_LE ? 2 : 3] = ir->op2; args[LJ_LE ? 3 : 2] = (ir+1)->op2; | ||
2184 | #endif | ||
2185 | |||
2186 | for (r = REGARG_FIRSTGPR; r <= REGARG_FIRSTGPR+(LJ_64?1:3); r++) { | ||
2187 | if (!rset_test(as->freeset, r) && | ||
2188 | regcost_ref(as->cost[r]) == args[r-REGARG_FIRSTGPR]) | ||
2189 | rset_clear(drop, r); | ||
2190 | } | ||
2191 | ra_evictset(as, drop); | ||
2192 | |||
2193 | asm_setupresult(as, ir, ci); | ||
2194 | |||
2195 | switch ((IROp)ir->o) { | ||
2196 | case IR_LT: | ||
2197 | asm_guard(as, MIPSI_BGEZ, RID_RET, 0); | ||
2198 | break; | ||
2199 | case IR_ULT: | ||
2200 | asm_guard(as, MIPSI_BEQ, RID_RET, RID_TMP); | ||
2201 | emit_loadi(as, RID_TMP, 1); | ||
2202 | asm_guard(as, MIPSI_BEQ, RID_RET, RID_ZERO); | ||
2203 | break; | ||
2204 | case IR_GE: | ||
2205 | asm_guard(as, MIPSI_BEQ, RID_RET, RID_TMP); | ||
2206 | emit_loadi(as, RID_TMP, 2); | ||
2207 | asm_guard(as, MIPSI_BLTZ, RID_RET, 0); | ||
2208 | break; | ||
2209 | case IR_LE: | ||
2210 | asm_guard(as, MIPSI_BGTZ, RID_RET, 0); | ||
2211 | break; | ||
2212 | case IR_GT: | ||
2213 | asm_guard(as, MIPSI_BEQ, RID_RET, RID_TMP); | ||
2214 | emit_loadi(as, RID_TMP, 2); | ||
2215 | asm_guard(as, MIPSI_BLEZ, RID_RET, 0); | ||
2216 | break; | ||
2217 | case IR_UGE: | ||
2218 | asm_guard(as, MIPSI_BLTZ, RID_RET, 0); | ||
2219 | break; | ||
2220 | case IR_ULE: | ||
2221 | asm_guard(as, MIPSI_BEQ, RID_RET, RID_TMP); | ||
2222 | emit_loadi(as, RID_TMP, 1); | ||
2223 | break; | ||
2224 | case IR_UGT: case IR_ABC: | ||
2225 | asm_guard(as, MIPSI_BLEZ, RID_RET, 0); | ||
2226 | break; | ||
2227 | case IR_EQ: case IR_NE: | ||
2228 | asm_guard(as, (ir->o & 1) ? MIPSI_BEQ : MIPSI_BNE, RID_RET, RID_ZERO); | ||
2229 | default: | ||
2230 | break; | ||
2231 | } | ||
2232 | asm_gencall(as, ci, args); | ||
2233 | } | ||
2234 | #endif | ||
2235 | |||
1463 | static void asm_comp(ASMState *as, IRIns *ir) | 2236 | static void asm_comp(ASMState *as, IRIns *ir) |
1464 | { | 2237 | { |
1465 | /* ORDER IR: LT GE LE GT ULT UGE ULE UGT. */ | 2238 | /* ORDER IR: LT GE LE GT ULT UGE ULE UGT. */ |
1466 | IROp op = ir->o; | 2239 | IROp op = ir->o; |
1467 | if (irt_isnum(ir->t)) { | 2240 | if (!LJ_SOFTFP32 && irt_isnum(ir->t)) { |
2241 | #if LJ_SOFTFP | ||
2242 | asm_sfpcomp(as, ir); | ||
2243 | #else | ||
2244 | #if !LJ_TARGET_MIPSR6 | ||
1468 | Reg right, left = ra_alloc2(as, ir, RSET_FPR); | 2245 | Reg right, left = ra_alloc2(as, ir, RSET_FPR); |
1469 | right = (left >> 8); left &= 255; | 2246 | right = (left >> 8); left &= 255; |
1470 | asm_guard(as, (op&1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0); | 2247 | asm_guard(as, (op&1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0); |
1471 | emit_fgh(as, MIPSI_C_OLT_D + ((op&3) ^ ((op>>2)&1)), 0, left, right); | 2248 | emit_fgh(as, MIPSI_C_OLT_D + ((op&3) ^ ((op>>2)&1)), 0, left, right); |
2249 | #else | ||
2250 | Reg tmp, right, left = ra_alloc2(as, ir, RSET_FPR); | ||
2251 | right = (left >> 8); left &= 255; | ||
2252 | tmp = ra_scratch(as, rset_exclude(rset_exclude(RSET_FPR, left), right)); | ||
2253 | asm_guard(as, (op&1) ? MIPSI_BC1NEZ : MIPSI_BC1EQZ, 0, (tmp&31)); | ||
2254 | emit_fgh(as, MIPSI_CMP_LT_D + ((op&3) ^ ((op>>2)&1)), tmp, left, right); | ||
2255 | #endif | ||
2256 | #endif | ||
1472 | } else { | 2257 | } else { |
1473 | Reg right, left = ra_alloc1(as, ir->op1, RSET_GPR); | 2258 | Reg right, left = ra_alloc1(as, ir->op1, RSET_GPR); |
1474 | if (op == IR_ABC) op = IR_UGT; | 2259 | if (op == IR_ABC) op = IR_UGT; |
1475 | if ((op&4) == 0 && irref_isk(ir->op2) && IR(ir->op2)->i == 0) { | 2260 | if ((op&4) == 0 && irref_isk(ir->op2) && get_kval(IR(ir->op2)) == 0) { |
1476 | MIPSIns mi = (op&2) ? ((op&1) ? MIPSI_BLEZ : MIPSI_BGTZ) : | 2261 | MIPSIns mi = (op&2) ? ((op&1) ? MIPSI_BLEZ : MIPSI_BGTZ) : |
1477 | ((op&1) ? MIPSI_BLTZ : MIPSI_BGEZ); | 2262 | ((op&1) ? MIPSI_BLTZ : MIPSI_BGEZ); |
1478 | asm_guard(as, mi, left, 0); | 2263 | asm_guard(as, mi, left, 0); |
1479 | } else { | 2264 | } else { |
1480 | if (irref_isk(ir->op2)) { | 2265 | if (irref_isk(ir->op2)) { |
1481 | int32_t k = IR(ir->op2)->i; | 2266 | intptr_t k = get_kval(IR(ir->op2)); |
1482 | if ((op&2)) k++; | 2267 | if ((op&2)) k++; |
1483 | if (checki16(k)) { | 2268 | if (checki16(k)) { |
1484 | asm_guard(as, (op&1) ? MIPSI_BNE : MIPSI_BEQ, RID_TMP, RID_ZERO); | 2269 | asm_guard(as, (op&1) ? MIPSI_BNE : MIPSI_BEQ, RID_TMP, RID_ZERO); |
@@ -1495,19 +2280,28 @@ static void asm_comp(ASMState *as, IRIns *ir) | |||
1495 | } | 2280 | } |
1496 | } | 2281 | } |
1497 | 2282 | ||
1498 | static void asm_compeq(ASMState *as, IRIns *ir) | 2283 | static void asm_equal(ASMState *as, IRIns *ir) |
1499 | { | 2284 | { |
1500 | Reg right, left = ra_alloc2(as, ir, irt_isnum(ir->t) ? RSET_FPR : RSET_GPR); | 2285 | Reg right, left = ra_alloc2(as, ir, (!LJ_SOFTFP && irt_isnum(ir->t)) ? |
2286 | RSET_FPR : RSET_GPR); | ||
1501 | right = (left >> 8); left &= 255; | 2287 | right = (left >> 8); left &= 255; |
1502 | if (irt_isnum(ir->t)) { | 2288 | if (!LJ_SOFTFP32 && irt_isnum(ir->t)) { |
2289 | #if LJ_SOFTFP | ||
2290 | asm_sfpcomp(as, ir); | ||
2291 | #elif !LJ_TARGET_MIPSR6 | ||
1503 | asm_guard(as, (ir->o & 1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0); | 2292 | asm_guard(as, (ir->o & 1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0); |
1504 | emit_fgh(as, MIPSI_C_EQ_D, 0, left, right); | 2293 | emit_fgh(as, MIPSI_C_EQ_D, 0, left, right); |
2294 | #else | ||
2295 | Reg tmp = ra_scratch(as, rset_exclude(rset_exclude(RSET_FPR, left), right)); | ||
2296 | asm_guard(as, (ir->o & 1) ? MIPSI_BC1NEZ : MIPSI_BC1EQZ, 0, (tmp&31)); | ||
2297 | emit_fgh(as, MIPSI_CMP_EQ_D, tmp, left, right); | ||
2298 | #endif | ||
1505 | } else { | 2299 | } else { |
1506 | asm_guard(as, (ir->o & 1) ? MIPSI_BEQ : MIPSI_BNE, left, right); | 2300 | asm_guard(as, (ir->o & 1) ? MIPSI_BEQ : MIPSI_BNE, left, right); |
1507 | } | 2301 | } |
1508 | } | 2302 | } |
1509 | 2303 | ||
1510 | #if LJ_HASFFI | 2304 | #if LJ_32 && LJ_HASFFI |
1511 | /* 64 bit integer comparisons. */ | 2305 | /* 64 bit integer comparisons. */ |
1512 | static void asm_comp64(ASMState *as, IRIns *ir) | 2306 | static void asm_comp64(ASMState *as, IRIns *ir) |
1513 | { | 2307 | { |
@@ -1549,41 +2343,79 @@ static void asm_comp64eq(ASMState *as, IRIns *ir) | |||
1549 | /* Hiword op of a split 64 bit op. Previous op must be the loword op. */ | 2343 | /* Hiword op of a split 64 bit op. Previous op must be the loword op. */ |
1550 | static void asm_hiop(ASMState *as, IRIns *ir) | 2344 | static void asm_hiop(ASMState *as, IRIns *ir) |
1551 | { | 2345 | { |
1552 | #if LJ_HASFFI | 2346 | #if LJ_32 && (LJ_HASFFI || LJ_SOFTFP) |
1553 | /* HIOP is marked as a store because it needs its own DCE logic. */ | 2347 | /* HIOP is marked as a store because it needs its own DCE logic. */ |
1554 | int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */ | 2348 | int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */ |
1555 | if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1; | 2349 | if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1; |
1556 | if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */ | 2350 | if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */ |
1557 | as->curins--; /* Always skip the CONV. */ | 2351 | as->curins--; /* Always skip the CONV. */ |
2352 | #if LJ_HASFFI && !LJ_SOFTFP | ||
1558 | if (usehi || uselo) | 2353 | if (usehi || uselo) |
1559 | asm_conv64(as, ir); | 2354 | asm_conv64(as, ir); |
1560 | return; | 2355 | return; |
2356 | #endif | ||
1561 | } else if ((ir-1)->o < IR_EQ) { /* 64 bit integer comparisons. ORDER IR. */ | 2357 | } else if ((ir-1)->o < IR_EQ) { /* 64 bit integer comparisons. ORDER IR. */ |
1562 | as->curins--; /* Always skip the loword comparison. */ | 2358 | as->curins--; /* Always skip the loword comparison. */ |
2359 | #if LJ_SOFTFP | ||
2360 | if (!irt_isint(ir->t)) { | ||
2361 | asm_sfpcomp(as, ir-1); | ||
2362 | return; | ||
2363 | } | ||
2364 | #endif | ||
2365 | #if LJ_HASFFI | ||
1563 | asm_comp64(as, ir); | 2366 | asm_comp64(as, ir); |
2367 | #endif | ||
1564 | return; | 2368 | return; |
1565 | } else if ((ir-1)->o <= IR_NE) { /* 64 bit integer comparisons. ORDER IR. */ | 2369 | } else if ((ir-1)->o <= IR_NE) { /* 64 bit integer comparisons. ORDER IR. */ |
1566 | as->curins--; /* Always skip the loword comparison. */ | 2370 | as->curins--; /* Always skip the loword comparison. */ |
2371 | #if LJ_SOFTFP | ||
2372 | if (!irt_isint(ir->t)) { | ||
2373 | asm_sfpcomp(as, ir-1); | ||
2374 | return; | ||
2375 | } | ||
2376 | #endif | ||
2377 | #if LJ_HASFFI | ||
1567 | asm_comp64eq(as, ir); | 2378 | asm_comp64eq(as, ir); |
2379 | #endif | ||
1568 | return; | 2380 | return; |
2381 | #if LJ_SOFTFP | ||
2382 | } else if ((ir-1)->o == IR_MIN || (ir-1)->o == IR_MAX) { | ||
2383 | as->curins--; /* Always skip the loword min/max. */ | ||
2384 | if (uselo || usehi) | ||
2385 | asm_sfpmin_max(as, ir-1); | ||
2386 | return; | ||
2387 | #endif | ||
1569 | } else if ((ir-1)->o == IR_XSTORE) { | 2388 | } else if ((ir-1)->o == IR_XSTORE) { |
1570 | as->curins--; /* Handle both stores here. */ | 2389 | as->curins--; /* Handle both stores here. */ |
1571 | if ((ir-1)->r != RID_SINK) { | 2390 | if ((ir-1)->r != RID_SINK) { |
1572 | asm_xstore(as, ir, LJ_LE ? 4 : 0); | 2391 | asm_xstore_(as, ir, LJ_LE ? 4 : 0); |
1573 | asm_xstore(as, ir-1, LJ_LE ? 0 : 4); | 2392 | asm_xstore_(as, ir-1, LJ_LE ? 0 : 4); |
1574 | } | 2393 | } |
1575 | return; | 2394 | return; |
1576 | } | 2395 | } |
1577 | if (!usehi) return; /* Skip unused hiword op for all remaining ops. */ | 2396 | if (!usehi) return; /* Skip unused hiword op for all remaining ops. */ |
1578 | switch ((ir-1)->o) { | 2397 | switch ((ir-1)->o) { |
2398 | #if LJ_HASFFI | ||
1579 | case IR_ADD: as->curins--; asm_add64(as, ir); break; | 2399 | case IR_ADD: as->curins--; asm_add64(as, ir); break; |
1580 | case IR_SUB: as->curins--; asm_sub64(as, ir); break; | 2400 | case IR_SUB: as->curins--; asm_sub64(as, ir); break; |
1581 | case IR_NEG: as->curins--; asm_neg64(as, ir); break; | 2401 | case IR_NEG: as->curins--; asm_neg64(as, ir); break; |
2402 | #endif | ||
2403 | #if LJ_SOFTFP | ||
2404 | case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD: | ||
2405 | case IR_STRTO: | ||
2406 | if (!uselo) | ||
2407 | ra_allocref(as, ir->op1, RSET_GPR); /* Mark lo op as used. */ | ||
2408 | break; | ||
2409 | #endif | ||
1582 | case IR_CALLN: | 2410 | case IR_CALLN: |
2411 | case IR_CALLS: | ||
1583 | case IR_CALLXS: | 2412 | case IR_CALLXS: |
1584 | if (!uselo) | 2413 | if (!uselo) |
1585 | ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ | 2414 | ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ |
1586 | break; | 2415 | break; |
2416 | #if LJ_SOFTFP | ||
2417 | case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: | ||
2418 | #endif | ||
1587 | case IR_CNEWI: | 2419 | case IR_CNEWI: |
1588 | /* Nothing to do here. Handled by lo op itself. */ | 2420 | /* Nothing to do here. Handled by lo op itself. */ |
1589 | break; | 2421 | break; |
@@ -1594,6 +2426,17 @@ static void asm_hiop(ASMState *as, IRIns *ir) | |||
1594 | #endif | 2426 | #endif |
1595 | } | 2427 | } |
1596 | 2428 | ||
2429 | /* -- Profiling ----------------------------------------------------------- */ | ||
2430 | |||
2431 | static void asm_prof(ASMState *as, IRIns *ir) | ||
2432 | { | ||
2433 | UNUSED(ir); | ||
2434 | asm_guard(as, MIPSI_BNE, RID_TMP, RID_ZERO); | ||
2435 | emit_tsi(as, MIPSI_ANDI, RID_TMP, RID_TMP, HOOK_PROFILE); | ||
2436 | emit_lsglptr(as, MIPSI_LBU, RID_TMP, | ||
2437 | (int32_t)offsetof(global_State, hookmask)); | ||
2438 | } | ||
2439 | |||
1597 | /* -- Stack handling ------------------------------------------------------ */ | 2440 | /* -- Stack handling ------------------------------------------------------ */ |
1598 | 2441 | ||
1599 | /* Check Lua stack size for overflow. Use exit handler as fallback. */ | 2442 | /* Check Lua stack size for overflow. Use exit handler as fallback. */ |
@@ -1604,46 +2447,67 @@ static void asm_stack_check(ASMState *as, BCReg topslot, | |||
1604 | Reg tmp, pbase = irp ? (ra_hasreg(irp->r) ? irp->r : RID_TMP) : RID_BASE; | 2447 | Reg tmp, pbase = irp ? (ra_hasreg(irp->r) ? irp->r : RID_TMP) : RID_BASE; |
1605 | ExitNo oldsnap = as->snapno; | 2448 | ExitNo oldsnap = as->snapno; |
1606 | rset_clear(allow, pbase); | 2449 | rset_clear(allow, pbase); |
2450 | #if LJ_32 | ||
1607 | tmp = allow ? rset_pickbot(allow) : | 2451 | tmp = allow ? rset_pickbot(allow) : |
1608 | (pbase == RID_RETHI ? RID_RETLO : RID_RETHI); | 2452 | (pbase == RID_RETHI ? RID_RETLO : RID_RETHI); |
2453 | #else | ||
2454 | tmp = allow ? rset_pickbot(allow) : RID_RET; | ||
2455 | #endif | ||
1609 | as->snapno = exitno; | 2456 | as->snapno = exitno; |
1610 | asm_guard(as, MIPSI_BNE, RID_TMP, RID_ZERO); | 2457 | asm_guard(as, MIPSI_BNE, RID_TMP, RID_ZERO); |
1611 | as->snapno = oldsnap; | 2458 | as->snapno = oldsnap; |
1612 | if (allow == RSET_EMPTY) /* Restore temp. register. */ | 2459 | if (allow == RSET_EMPTY) /* Restore temp. register. */ |
1613 | emit_tsi(as, MIPSI_LW, tmp, RID_SP, 0); | 2460 | emit_tsi(as, MIPSI_AL, tmp, RID_SP, 0); |
1614 | else | 2461 | else |
1615 | ra_modified(as, tmp); | 2462 | ra_modified(as, tmp); |
1616 | emit_tsi(as, MIPSI_SLTIU, RID_TMP, RID_TMP, (int32_t)(8*topslot)); | 2463 | emit_tsi(as, MIPSI_SLTIU, RID_TMP, RID_TMP, (int32_t)(8*topslot)); |
1617 | emit_dst(as, MIPSI_SUBU, RID_TMP, tmp, pbase); | 2464 | emit_dst(as, MIPSI_ASUBU, RID_TMP, tmp, pbase); |
1618 | emit_tsi(as, MIPSI_LW, tmp, tmp, offsetof(lua_State, maxstack)); | 2465 | emit_tsi(as, MIPSI_AL, tmp, tmp, offsetof(lua_State, maxstack)); |
1619 | if (pbase == RID_TMP) | 2466 | if (pbase == RID_TMP) |
1620 | emit_getgl(as, RID_TMP, jit_base); | 2467 | emit_getgl(as, RID_TMP, jit_base); |
1621 | emit_getgl(as, tmp, jit_L); | 2468 | emit_getgl(as, tmp, cur_L); |
1622 | if (allow == RSET_EMPTY) /* Spill temp. register. */ | 2469 | if (allow == RSET_EMPTY) /* Spill temp. register. */ |
1623 | emit_tsi(as, MIPSI_SW, tmp, RID_SP, 0); | 2470 | emit_tsi(as, MIPSI_AS, tmp, RID_SP, 0); |
1624 | } | 2471 | } |
1625 | 2472 | ||
1626 | /* Restore Lua stack from on-trace state. */ | 2473 | /* Restore Lua stack from on-trace state. */ |
1627 | static void asm_stack_restore(ASMState *as, SnapShot *snap) | 2474 | static void asm_stack_restore(ASMState *as, SnapShot *snap) |
1628 | { | 2475 | { |
1629 | SnapEntry *map = &as->T->snapmap[snap->mapofs]; | 2476 | SnapEntry *map = &as->T->snapmap[snap->mapofs]; |
1630 | SnapEntry *flinks = &as->T->snapmap[snap_nextofs(as->T, snap)-1]; | 2477 | #if LJ_32 || defined(LUA_USE_ASSERT) |
2478 | SnapEntry *flinks = &as->T->snapmap[snap_nextofs(as->T, snap)-1-LJ_FR2]; | ||
2479 | #endif | ||
1631 | MSize n, nent = snap->nent; | 2480 | MSize n, nent = snap->nent; |
1632 | /* Store the value of all modified slots to the Lua stack. */ | 2481 | /* Store the value of all modified slots to the Lua stack. */ |
1633 | for (n = 0; n < nent; n++) { | 2482 | for (n = 0; n < nent; n++) { |
1634 | SnapEntry sn = map[n]; | 2483 | SnapEntry sn = map[n]; |
1635 | BCReg s = snap_slot(sn); | 2484 | BCReg s = snap_slot(sn); |
1636 | int32_t ofs = 8*((int32_t)s-1); | 2485 | int32_t ofs = 8*((int32_t)s-1-LJ_FR2); |
1637 | IRRef ref = snap_ref(sn); | 2486 | IRRef ref = snap_ref(sn); |
1638 | IRIns *ir = IR(ref); | 2487 | IRIns *ir = IR(ref); |
1639 | if ((sn & SNAP_NORESTORE)) | 2488 | if ((sn & SNAP_NORESTORE)) |
1640 | continue; | 2489 | continue; |
1641 | if (irt_isnum(ir->t)) { | 2490 | if (irt_isnum(ir->t)) { |
2491 | #if LJ_SOFTFP32 | ||
2492 | Reg tmp; | ||
2493 | RegSet allow = rset_exclude(RSET_GPR, RID_BASE); | ||
2494 | lua_assert(irref_isk(ref)); /* LJ_SOFTFP: must be a number constant. */ | ||
2495 | tmp = ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, allow); | ||
2496 | emit_tsi(as, MIPSI_SW, tmp, RID_BASE, ofs+(LJ_BE?4:0)); | ||
2497 | if (rset_test(as->freeset, tmp+1)) allow = RID2RSET(tmp+1); | ||
2498 | tmp = ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, allow); | ||
2499 | emit_tsi(as, MIPSI_SW, tmp, RID_BASE, ofs+(LJ_BE?0:4)); | ||
2500 | #elif LJ_SOFTFP /* && LJ_64 */ | ||
2501 | Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, RID_BASE)); | ||
2502 | emit_tsi(as, MIPSI_SD, src, RID_BASE, ofs); | ||
2503 | #else | ||
1642 | Reg src = ra_alloc1(as, ref, RSET_FPR); | 2504 | Reg src = ra_alloc1(as, ref, RSET_FPR); |
1643 | emit_hsi(as, MIPSI_SDC1, src, RID_BASE, ofs); | 2505 | emit_hsi(as, MIPSI_SDC1, src, RID_BASE, ofs); |
2506 | #endif | ||
1644 | } else { | 2507 | } else { |
1645 | Reg type; | 2508 | #if LJ_32 |
1646 | RegSet allow = rset_exclude(RSET_GPR, RID_BASE); | 2509 | RegSet allow = rset_exclude(RSET_GPR, RID_BASE); |
2510 | Reg type; | ||
1647 | lua_assert(irt_ispri(ir->t) || irt_isaddr(ir->t) || irt_isinteger(ir->t)); | 2511 | lua_assert(irt_ispri(ir->t) || irt_isaddr(ir->t) || irt_isinteger(ir->t)); |
1648 | if (!irt_ispri(ir->t)) { | 2512 | if (!irt_ispri(ir->t)) { |
1649 | Reg src = ra_alloc1(as, ref, allow); | 2513 | Reg src = ra_alloc1(as, ref, allow); |
@@ -1653,10 +2517,17 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap) | |||
1653 | if ((sn & (SNAP_CONT|SNAP_FRAME))) { | 2517 | if ((sn & (SNAP_CONT|SNAP_FRAME))) { |
1654 | if (s == 0) continue; /* Do not overwrite link to previous frame. */ | 2518 | if (s == 0) continue; /* Do not overwrite link to previous frame. */ |
1655 | type = ra_allock(as, (int32_t)(*flinks--), allow); | 2519 | type = ra_allock(as, (int32_t)(*flinks--), allow); |
2520 | #if LJ_SOFTFP | ||
2521 | } else if ((sn & SNAP_SOFTFPNUM)) { | ||
2522 | type = ra_alloc1(as, ref+1, rset_exclude(RSET_GPR, RID_BASE)); | ||
2523 | #endif | ||
1656 | } else { | 2524 | } else { |
1657 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); | 2525 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); |
1658 | } | 2526 | } |
1659 | emit_tsi(as, MIPSI_SW, type, RID_BASE, ofs+(LJ_BE?0:4)); | 2527 | emit_tsi(as, MIPSI_SW, type, RID_BASE, ofs+(LJ_BE?0:4)); |
2528 | #else | ||
2529 | asm_tvstore64(as, RID_BASE, ofs, ref); | ||
2530 | #endif | ||
1660 | } | 2531 | } |
1661 | checkmclim(as); | 2532 | checkmclim(as); |
1662 | } | 2533 | } |
@@ -1680,7 +2551,7 @@ static void asm_gc_check(ASMState *as) | |||
1680 | args[0] = ASMREF_TMP1; /* global_State *g */ | 2551 | args[0] = ASMREF_TMP1; /* global_State *g */ |
1681 | args[1] = ASMREF_TMP2; /* MSize steps */ | 2552 | args[1] = ASMREF_TMP2; /* MSize steps */ |
1682 | asm_gencall(as, ci, args); | 2553 | asm_gencall(as, ci, args); |
1683 | emit_tsi(as, MIPSI_ADDIU, ra_releasetmp(as, ASMREF_TMP1), RID_JGL, -32768); | 2554 | emit_tsi(as, MIPSI_AADDIU, ra_releasetmp(as, ASMREF_TMP1), RID_JGL, -32768); |
1684 | tmp = ra_releasetmp(as, ASMREF_TMP2); | 2555 | tmp = ra_releasetmp(as, ASMREF_TMP2); |
1685 | emit_loadi(as, tmp, as->gcsteps); | 2556 | emit_loadi(as, tmp, as->gcsteps); |
1686 | /* Jump around GC step if GC total < GC threshold. */ | 2557 | /* Jump around GC step if GC total < GC threshold. */ |
@@ -1755,7 +2626,7 @@ static void asm_tail_fixup(ASMState *as, TraceNo lnk) | |||
1755 | MCode *target = lnk ? traceref(as->J,lnk)->mcode : (MCode *)lj_vm_exit_interp; | 2626 | MCode *target = lnk ? traceref(as->J,lnk)->mcode : (MCode *)lj_vm_exit_interp; |
1756 | int32_t spadj = as->T->spadjust; | 2627 | int32_t spadj = as->T->spadjust; |
1757 | MCode *p = as->mctop-1; | 2628 | MCode *p = as->mctop-1; |
1758 | *p = spadj ? (MIPSI_ADDIU|MIPSF_T(RID_SP)|MIPSF_S(RID_SP)|spadj) : MIPSI_NOP; | 2629 | *p = spadj ? (MIPSI_AADDIU|MIPSF_T(RID_SP)|MIPSF_S(RID_SP)|spadj) : MIPSI_NOP; |
1759 | p[-1] = MIPSI_J|(((uintptr_t)target>>2)&0x03ffffffu); | 2630 | p[-1] = MIPSI_J|(((uintptr_t)target>>2)&0x03ffffffu); |
1760 | } | 2631 | } |
1761 | 2632 | ||
@@ -1766,139 +2637,26 @@ static void asm_tail_prep(ASMState *as) | |||
1766 | as->invmcp = as->loopref ? as->mcp : NULL; | 2637 | as->invmcp = as->loopref ? as->mcp : NULL; |
1767 | } | 2638 | } |
1768 | 2639 | ||
1769 | /* -- Instruction dispatch ------------------------------------------------ */ | ||
1770 | |||
1771 | /* Assemble a single instruction. */ | ||
1772 | static void asm_ir(ASMState *as, IRIns *ir) | ||
1773 | { | ||
1774 | switch ((IROp)ir->o) { | ||
1775 | /* Miscellaneous ops. */ | ||
1776 | case IR_LOOP: asm_loop(as); break; | ||
1777 | case IR_NOP: case IR_XBAR: lua_assert(!ra_used(ir)); break; | ||
1778 | case IR_USE: | ||
1779 | ra_alloc1(as, ir->op1, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); break; | ||
1780 | case IR_PHI: asm_phi(as, ir); break; | ||
1781 | case IR_HIOP: asm_hiop(as, ir); break; | ||
1782 | case IR_GCSTEP: asm_gcstep(as, ir); break; | ||
1783 | |||
1784 | /* Guarded assertions. */ | ||
1785 | case IR_EQ: case IR_NE: asm_compeq(as, ir); break; | ||
1786 | case IR_LT: case IR_GE: case IR_LE: case IR_GT: | ||
1787 | case IR_ULT: case IR_UGE: case IR_ULE: case IR_UGT: | ||
1788 | case IR_ABC: | ||
1789 | asm_comp(as, ir); | ||
1790 | break; | ||
1791 | |||
1792 | case IR_RETF: asm_retf(as, ir); break; | ||
1793 | |||
1794 | /* Bit ops. */ | ||
1795 | case IR_BNOT: asm_bitnot(as, ir); break; | ||
1796 | case IR_BSWAP: asm_bitswap(as, ir); break; | ||
1797 | |||
1798 | case IR_BAND: asm_bitop(as, ir, MIPSI_AND, MIPSI_ANDI); break; | ||
1799 | case IR_BOR: asm_bitop(as, ir, MIPSI_OR, MIPSI_ORI); break; | ||
1800 | case IR_BXOR: asm_bitop(as, ir, MIPSI_XOR, MIPSI_XORI); break; | ||
1801 | |||
1802 | case IR_BSHL: asm_bitshift(as, ir, MIPSI_SLLV, MIPSI_SLL); break; | ||
1803 | case IR_BSHR: asm_bitshift(as, ir, MIPSI_SRLV, MIPSI_SRL); break; | ||
1804 | case IR_BSAR: asm_bitshift(as, ir, MIPSI_SRAV, MIPSI_SRA); break; | ||
1805 | case IR_BROL: lua_assert(0); break; | ||
1806 | case IR_BROR: asm_bitror(as, ir); break; | ||
1807 | |||
1808 | /* Arithmetic ops. */ | ||
1809 | case IR_ADD: asm_add(as, ir); break; | ||
1810 | case IR_SUB: asm_sub(as, ir); break; | ||
1811 | case IR_MUL: asm_mul(as, ir); break; | ||
1812 | case IR_DIV: asm_fparith(as, ir, MIPSI_DIV_D); break; | ||
1813 | case IR_MOD: asm_callid(as, ir, IRCALL_lj_vm_modi); break; | ||
1814 | case IR_POW: asm_callid(as, ir, IRCALL_lj_vm_powi); break; | ||
1815 | case IR_NEG: asm_neg(as, ir); break; | ||
1816 | |||
1817 | case IR_ABS: asm_fpunary(as, ir, MIPSI_ABS_D); break; | ||
1818 | case IR_ATAN2: asm_callid(as, ir, IRCALL_atan2); break; | ||
1819 | case IR_LDEXP: asm_callid(as, ir, IRCALL_ldexp); break; | ||
1820 | case IR_MIN: asm_min_max(as, ir, 0); break; | ||
1821 | case IR_MAX: asm_min_max(as, ir, 1); break; | ||
1822 | case IR_FPMATH: | ||
1823 | if (ir->op2 == IRFPM_EXP2 && asm_fpjoin_pow(as, ir)) | ||
1824 | break; | ||
1825 | if (ir->op2 <= IRFPM_TRUNC) | ||
1826 | asm_callround(as, ir, IRCALL_lj_vm_floor + ir->op2); | ||
1827 | else if (ir->op2 == IRFPM_SQRT) | ||
1828 | asm_fpunary(as, ir, MIPSI_SQRT_D); | ||
1829 | else | ||
1830 | asm_callid(as, ir, IRCALL_lj_vm_floor + ir->op2); | ||
1831 | break; | ||
1832 | |||
1833 | /* Overflow-checking arithmetic ops. */ | ||
1834 | case IR_ADDOV: asm_arithov(as, ir); break; | ||
1835 | case IR_SUBOV: asm_arithov(as, ir); break; | ||
1836 | case IR_MULOV: asm_mulov(as, ir); break; | ||
1837 | |||
1838 | /* Memory references. */ | ||
1839 | case IR_AREF: asm_aref(as, ir); break; | ||
1840 | case IR_HREF: asm_href(as, ir); break; | ||
1841 | case IR_HREFK: asm_hrefk(as, ir); break; | ||
1842 | case IR_NEWREF: asm_newref(as, ir); break; | ||
1843 | case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break; | ||
1844 | case IR_FREF: asm_fref(as, ir); break; | ||
1845 | case IR_STRREF: asm_strref(as, ir); break; | ||
1846 | |||
1847 | /* Loads and stores. */ | ||
1848 | case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD: | ||
1849 | asm_ahuvload(as, ir); | ||
1850 | break; | ||
1851 | case IR_FLOAD: asm_fload(as, ir); break; | ||
1852 | case IR_XLOAD: asm_xload(as, ir); break; | ||
1853 | case IR_SLOAD: asm_sload(as, ir); break; | ||
1854 | |||
1855 | case IR_ASTORE: case IR_HSTORE: case IR_USTORE: asm_ahustore(as, ir); break; | ||
1856 | case IR_FSTORE: asm_fstore(as, ir); break; | ||
1857 | case IR_XSTORE: asm_xstore(as, ir, 0); break; | ||
1858 | |||
1859 | /* Allocations. */ | ||
1860 | case IR_SNEW: case IR_XSNEW: asm_snew(as, ir); break; | ||
1861 | case IR_TNEW: asm_tnew(as, ir); break; | ||
1862 | case IR_TDUP: asm_tdup(as, ir); break; | ||
1863 | case IR_CNEW: case IR_CNEWI: asm_cnew(as, ir); break; | ||
1864 | |||
1865 | /* Write barriers. */ | ||
1866 | case IR_TBAR: asm_tbar(as, ir); break; | ||
1867 | case IR_OBAR: asm_obar(as, ir); break; | ||
1868 | |||
1869 | /* Type conversions. */ | ||
1870 | case IR_CONV: asm_conv(as, ir); break; | ||
1871 | case IR_TOBIT: asm_tobit(as, ir); break; | ||
1872 | case IR_TOSTR: asm_tostr(as, ir); break; | ||
1873 | case IR_STRTO: asm_strto(as, ir); break; | ||
1874 | |||
1875 | /* Calls. */ | ||
1876 | case IR_CALLN: case IR_CALLL: case IR_CALLS: asm_call(as, ir); break; | ||
1877 | case IR_CALLXS: asm_callx(as, ir); break; | ||
1878 | case IR_CARG: break; | ||
1879 | |||
1880 | default: | ||
1881 | setintV(&as->J->errinfo, ir->o); | ||
1882 | lj_trace_err_info(as->J, LJ_TRERR_NYIIR); | ||
1883 | break; | ||
1884 | } | ||
1885 | } | ||
1886 | |||
1887 | /* -- Trace setup --------------------------------------------------------- */ | 2640 | /* -- Trace setup --------------------------------------------------------- */ |
1888 | 2641 | ||
1889 | /* Ensure there are enough stack slots for call arguments. */ | 2642 | /* Ensure there are enough stack slots for call arguments. */ |
1890 | static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci) | 2643 | static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci) |
1891 | { | 2644 | { |
1892 | IRRef args[CCI_NARGS_MAX*2]; | 2645 | IRRef args[CCI_NARGS_MAX*2]; |
1893 | uint32_t i, nargs = (int)CCI_NARGS(ci); | 2646 | uint32_t i, nargs = CCI_XNARGS(ci); |
2647 | #if LJ_32 | ||
1894 | int nslots = 4, ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR; | 2648 | int nslots = 4, ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR; |
2649 | #else | ||
2650 | int nslots = 0, ngpr = REGARG_NUMGPR; | ||
2651 | #endif | ||
1895 | asm_collectargs(as, ir, ci, args); | 2652 | asm_collectargs(as, ir, ci, args); |
1896 | for (i = 0; i < nargs; i++) { | 2653 | for (i = 0; i < nargs; i++) { |
1897 | if (args[i] && irt_isfp(IR(args[i])->t) && | 2654 | #if LJ_32 |
2655 | if (!LJ_SOFTFP && args[i] && irt_isfp(IR(args[i])->t) && | ||
1898 | nfpr > 0 && !(ci->flags & CCI_VARARG)) { | 2656 | nfpr > 0 && !(ci->flags & CCI_VARARG)) { |
1899 | nfpr--; | 2657 | nfpr--; |
1900 | ngpr -= irt_isnum(IR(args[i])->t) ? 2 : 1; | 2658 | ngpr -= irt_isnum(IR(args[i])->t) ? 2 : 1; |
1901 | } else if (args[i] && irt_isnum(IR(args[i])->t)) { | 2659 | } else if (!LJ_SOFTFP && args[i] && irt_isnum(IR(args[i])->t)) { |
1902 | nfpr = 0; | 2660 | nfpr = 0; |
1903 | ngpr = ngpr & ~1; | 2661 | ngpr = ngpr & ~1; |
1904 | if (ngpr > 0) ngpr -= 2; else nslots = (nslots+3) & ~1; | 2662 | if (ngpr > 0) ngpr -= 2; else nslots = (nslots+3) & ~1; |
@@ -1906,6 +2664,9 @@ static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci) | |||
1906 | nfpr = 0; | 2664 | nfpr = 0; |
1907 | if (ngpr > 0) ngpr--; else nslots++; | 2665 | if (ngpr > 0) ngpr--; else nslots++; |
1908 | } | 2666 | } |
2667 | #else | ||
2668 | if (ngpr > 0) ngpr--; else nslots += 2; | ||
2669 | #endif | ||
1909 | } | 2670 | } |
1910 | if (nslots > as->evenspill) /* Leave room for args in stack slots. */ | 2671 | if (nslots > as->evenspill) /* Leave room for args in stack slots. */ |
1911 | as->evenspill = nslots; | 2672 | as->evenspill = nslots; |
@@ -1936,7 +2697,12 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target) | |||
1936 | if (((p[-1] ^ (px-p)) & 0xffffu) == 0 && | 2697 | if (((p[-1] ^ (px-p)) & 0xffffu) == 0 && |
1937 | ((p[-1] & 0xf0000000u) == MIPSI_BEQ || | 2698 | ((p[-1] & 0xf0000000u) == MIPSI_BEQ || |
1938 | (p[-1] & 0xfc1e0000u) == MIPSI_BLTZ || | 2699 | (p[-1] & 0xfc1e0000u) == MIPSI_BLTZ || |
1939 | (p[-1] & 0xffe00000u) == MIPSI_BC1F)) { | 2700 | #if !LJ_TARGET_MIPSR6 |
2701 | (p[-1] & 0xffe00000u) == MIPSI_BC1F | ||
2702 | #else | ||
2703 | (p[-1] & 0xff600000u) == MIPSI_BC1EQZ | ||
2704 | #endif | ||
2705 | )) { | ||
1940 | ptrdiff_t delta = target - p; | 2706 | ptrdiff_t delta = target - p; |
1941 | if (((delta + 0x8000) >> 16) == 0) { /* Patch in-range branch. */ | 2707 | if (((delta + 0x8000) >> 16) == 0) { /* Patch in-range branch. */ |
1942 | patchbranch: | 2708 | patchbranch: |