diff options
author | Mike Pall <mike> | 2016-02-10 18:49:22 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2016-02-10 18:49:22 +0100 |
commit | f547a1425e9db10eec59d586c94ba78b897497f6 (patch) | |
tree | 6d84512e0251db236868d9141af1019a3823b5d7 /src/lj_asm_mips.h | |
parent | 825dcdc4d1e09c71ffc24565aefbb05a9cb3c2f4 (diff) | |
download | luajit-f547a1425e9db10eec59d586c94ba78b897497f6.tar.gz luajit-f547a1425e9db10eec59d586c94ba78b897497f6.tar.bz2 luajit-f547a1425e9db10eec59d586c94ba78b897497f6.zip |
MIPS: Add soft-float support to JIT compiler backend.
Diffstat (limited to 'src/lj_asm_mips.h')
-rw-r--r-- | src/lj_asm_mips.h | 406 |
1 files changed, 336 insertions, 70 deletions
diff --git a/src/lj_asm_mips.h b/src/lj_asm_mips.h index adea0e32..b15fb7a6 100644 --- a/src/lj_asm_mips.h +++ b/src/lj_asm_mips.h | |||
@@ -228,27 +228,39 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | |||
228 | { | 228 | { |
229 | uint32_t n, nargs = CCI_XNARGS(ci); | 229 | uint32_t n, nargs = CCI_XNARGS(ci); |
230 | int32_t ofs = 16; | 230 | int32_t ofs = 16; |
231 | #if LJ_SOFTFP | ||
232 | Reg gpr = REGARG_FIRSTGPR; | ||
233 | #else | ||
231 | Reg gpr, fpr = REGARG_FIRSTFPR; | 234 | Reg gpr, fpr = REGARG_FIRSTFPR; |
235 | #endif | ||
232 | if ((void *)ci->func) | 236 | if ((void *)ci->func) |
233 | emit_call(as, (void *)ci->func); | 237 | emit_call(as, (void *)ci->func, 1); |
238 | #if !LJ_SOFTFP | ||
234 | for (gpr = REGARG_FIRSTGPR; gpr <= REGARG_LASTGPR; gpr++) | 239 | for (gpr = REGARG_FIRSTGPR; gpr <= REGARG_LASTGPR; gpr++) |
235 | as->cost[gpr] = REGCOST(~0u, ASMREF_L); | 240 | as->cost[gpr] = REGCOST(~0u, ASMREF_L); |
236 | gpr = REGARG_FIRSTGPR; | 241 | gpr = REGARG_FIRSTGPR; |
242 | #endif | ||
237 | for (n = 0; n < nargs; n++) { /* Setup args. */ | 243 | for (n = 0; n < nargs; n++) { /* Setup args. */ |
238 | IRRef ref = args[n]; | 244 | IRRef ref = args[n]; |
239 | if (ref) { | 245 | if (ref) { |
240 | IRIns *ir = IR(ref); | 246 | IRIns *ir = IR(ref); |
247 | #if !LJ_SOFTFP | ||
241 | if (irt_isfp(ir->t) && fpr <= REGARG_LASTFPR && | 248 | if (irt_isfp(ir->t) && fpr <= REGARG_LASTFPR && |
242 | !(ci->flags & CCI_VARARG)) { | 249 | !(ci->flags & CCI_VARARG)) { |
243 | lua_assert(rset_test(as->freeset, fpr)); /* Already evicted. */ | 250 | lua_assert(rset_test(as->freeset, fpr)); /* Already evicted. */ |
244 | ra_leftov(as, fpr, ref); | 251 | ra_leftov(as, fpr, ref); |
245 | fpr += 2; | 252 | fpr += 2; |
246 | gpr += irt_isnum(ir->t) ? 2 : 1; | 253 | gpr += irt_isnum(ir->t) ? 2 : 1; |
247 | } else { | 254 | } else |
255 | #endif | ||
256 | { | ||
257 | #if !LJ_SOFTFP | ||
248 | fpr = REGARG_LASTFPR+1; | 258 | fpr = REGARG_LASTFPR+1; |
259 | #endif | ||
249 | if (irt_isnum(ir->t)) gpr = (gpr+1) & ~1; | 260 | if (irt_isnum(ir->t)) gpr = (gpr+1) & ~1; |
250 | if (gpr <= REGARG_LASTGPR) { | 261 | if (gpr <= REGARG_LASTGPR) { |
251 | lua_assert(rset_test(as->freeset, gpr)); /* Already evicted. */ | 262 | lua_assert(rset_test(as->freeset, gpr)); /* Already evicted. */ |
263 | #if !LJ_SOFTFP | ||
252 | if (irt_isfp(ir->t)) { | 264 | if (irt_isfp(ir->t)) { |
253 | RegSet of = as->freeset; | 265 | RegSet of = as->freeset; |
254 | Reg r; | 266 | Reg r; |
@@ -265,19 +277,23 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | |||
265 | emit_tg(as, MIPSI_MFC1, gpr, r); | 277 | emit_tg(as, MIPSI_MFC1, gpr, r); |
266 | gpr++; | 278 | gpr++; |
267 | } | 279 | } |
268 | } else { | 280 | } else |
281 | #endif | ||
282 | { | ||
269 | ra_leftov(as, gpr, ref); | 283 | ra_leftov(as, gpr, ref); |
270 | gpr++; | 284 | gpr++; |
271 | } | 285 | } |
272 | } else { | 286 | } else { |
273 | Reg r = ra_alloc1z(as, ref, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); | 287 | Reg r = ra_alloc1z(as, ref, !LJ_SOFTFP && irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); |
274 | if (irt_isnum(ir->t)) ofs = (ofs + 4) & ~4; | 288 | if (irt_isnum(ir->t)) ofs = (ofs + 4) & ~4; |
275 | emit_spstore(as, ir, r, ofs); | 289 | emit_spstore(as, ir, r, ofs); |
276 | ofs += irt_isnum(ir->t) ? 8 : 4; | 290 | ofs += irt_isnum(ir->t) ? 8 : 4; |
277 | } | 291 | } |
278 | } | 292 | } |
279 | } else { | 293 | } else { |
294 | #if !LJ_SOFTFP | ||
280 | fpr = REGARG_LASTFPR+1; | 295 | fpr = REGARG_LASTFPR+1; |
296 | #endif | ||
281 | if (gpr <= REGARG_LASTGPR) | 297 | if (gpr <= REGARG_LASTGPR) |
282 | gpr++; | 298 | gpr++; |
283 | else | 299 | else |
@@ -291,9 +307,11 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | |||
291 | static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) | 307 | static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) |
292 | { | 308 | { |
293 | RegSet drop = RSET_SCRATCH; | 309 | RegSet drop = RSET_SCRATCH; |
294 | int hiop = ((ir+1)->o == IR_HIOP); | 310 | int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t)); |
311 | #if !LJ_SOFTFP | ||
295 | if ((ci->flags & CCI_NOFPRCLOBBER)) | 312 | if ((ci->flags & CCI_NOFPRCLOBBER)) |
296 | drop &= ~RSET_FPR; | 313 | drop &= ~RSET_FPR; |
314 | #endif | ||
297 | if (ra_hasreg(ir->r)) | 315 | if (ra_hasreg(ir->r)) |
298 | rset_clear(drop, ir->r); /* Dest reg handled below. */ | 316 | rset_clear(drop, ir->r); /* Dest reg handled below. */ |
299 | if (hiop && ra_hasreg((ir+1)->r)) | 317 | if (hiop && ra_hasreg((ir+1)->r)) |
@@ -301,7 +319,7 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) | |||
301 | ra_evictset(as, drop); /* Evictions must be performed first. */ | 319 | ra_evictset(as, drop); /* Evictions must be performed first. */ |
302 | if (ra_used(ir)) { | 320 | if (ra_used(ir)) { |
303 | lua_assert(!irt_ispri(ir->t)); | 321 | lua_assert(!irt_ispri(ir->t)); |
304 | if (irt_isfp(ir->t)) { | 322 | if (!LJ_SOFTFP && irt_isfp(ir->t)) { |
305 | if ((ci->flags & CCI_CASTU64)) { | 323 | if ((ci->flags & CCI_CASTU64)) { |
306 | int32_t ofs = sps_scale(ir->s); | 324 | int32_t ofs = sps_scale(ir->s); |
307 | Reg dest = ir->r; | 325 | Reg dest = ir->r; |
@@ -353,6 +371,7 @@ static void asm_callx(ASMState *as, IRIns *ir) | |||
353 | asm_gencall(as, &ci, args); | 371 | asm_gencall(as, &ci, args); |
354 | } | 372 | } |
355 | 373 | ||
374 | #if !LJ_SOFTFP | ||
356 | static void asm_callround(ASMState *as, IRIns *ir, IRCallID id) | 375 | static void asm_callround(ASMState *as, IRIns *ir, IRCallID id) |
357 | { | 376 | { |
358 | /* The modified regs must match with the *.dasc implementation. */ | 377 | /* The modified regs must match with the *.dasc implementation. */ |
@@ -361,9 +380,10 @@ static void asm_callround(ASMState *as, IRIns *ir, IRCallID id) | |||
361 | if (ra_hasreg(ir->r)) rset_clear(drop, ir->r); | 380 | if (ra_hasreg(ir->r)) rset_clear(drop, ir->r); |
362 | ra_evictset(as, drop); | 381 | ra_evictset(as, drop); |
363 | ra_destreg(as, ir, RID_FPRET); | 382 | ra_destreg(as, ir, RID_FPRET); |
364 | emit_call(as, (void *)lj_ir_callinfo[id].func); | 383 | emit_call(as, (void *)lj_ir_callinfo[id].func, 0); |
365 | ra_leftov(as, REGARG_FIRSTFPR, ir->op1); | 384 | ra_leftov(as, REGARG_FIRSTFPR, ir->op1); |
366 | } | 385 | } |
386 | #endif | ||
367 | 387 | ||
368 | /* -- Returns ------------------------------------------------------------- */ | 388 | /* -- Returns ------------------------------------------------------------- */ |
369 | 389 | ||
@@ -385,6 +405,7 @@ static void asm_retf(ASMState *as, IRIns *ir) | |||
385 | 405 | ||
386 | /* -- Type conversions ---------------------------------------------------- */ | 406 | /* -- Type conversions ---------------------------------------------------- */ |
387 | 407 | ||
408 | #if !LJ_SOFTFP | ||
388 | static void asm_tointg(ASMState *as, IRIns *ir, Reg left) | 409 | static void asm_tointg(ASMState *as, IRIns *ir, Reg left) |
389 | { | 410 | { |
390 | Reg tmp = ra_scratch(as, rset_exclude(RSET_FPR, left)); | 411 | Reg tmp = ra_scratch(as, rset_exclude(RSET_FPR, left)); |
@@ -406,15 +427,23 @@ static void asm_tobit(ASMState *as, IRIns *ir) | |||
406 | emit_tg(as, MIPSI_MFC1, dest, tmp); | 427 | emit_tg(as, MIPSI_MFC1, dest, tmp); |
407 | emit_fgh(as, MIPSI_ADD_D, tmp, left, right); | 428 | emit_fgh(as, MIPSI_ADD_D, tmp, left, right); |
408 | } | 429 | } |
430 | #endif | ||
409 | 431 | ||
410 | static void asm_conv(ASMState *as, IRIns *ir) | 432 | static void asm_conv(ASMState *as, IRIns *ir) |
411 | { | 433 | { |
412 | IRType st = (IRType)(ir->op2 & IRCONV_SRCMASK); | 434 | IRType st = (IRType)(ir->op2 & IRCONV_SRCMASK); |
435 | #if !LJ_SOFTFP | ||
413 | int stfp = (st == IRT_NUM || st == IRT_FLOAT); | 436 | int stfp = (st == IRT_NUM || st == IRT_FLOAT); |
437 | #endif | ||
414 | IRRef lref = ir->op1; | 438 | IRRef lref = ir->op1; |
415 | lua_assert(irt_type(ir->t) != st); | ||
416 | lua_assert(!(irt_isint64(ir->t) || | 439 | lua_assert(!(irt_isint64(ir->t) || |
417 | (st == IRT_I64 || st == IRT_U64))); /* Handled by SPLIT. */ | 440 | (st == IRT_I64 || st == IRT_U64))); /* Handled by SPLIT. */ |
441 | #if LJ_SOFTFP | ||
442 | /* FP conversions are handled by SPLIT. */ | ||
443 | lua_assert(!irt_isfp(ir->t) && !(st == IRT_NUM || st == IRT_FLOAT)); | ||
444 | /* Can't check for same types: SPLIT uses CONV int.int + BXOR for sfp NEG. */ | ||
445 | #else | ||
446 | lua_assert(irt_type(ir->t) != st); | ||
418 | if (irt_isfp(ir->t)) { | 447 | if (irt_isfp(ir->t)) { |
419 | Reg dest = ra_dest(as, ir, RSET_FPR); | 448 | Reg dest = ra_dest(as, ir, RSET_FPR); |
420 | if (stfp) { /* FP to FP conversion. */ | 449 | if (stfp) { /* FP to FP conversion. */ |
@@ -477,7 +506,9 @@ static void asm_conv(ASMState *as, IRIns *ir) | |||
477 | tmp, left); | 506 | tmp, left); |
478 | } | 507 | } |
479 | } | 508 | } |
480 | } else { | 509 | } else |
510 | #endif | ||
511 | { | ||
481 | Reg dest = ra_dest(as, ir, RSET_GPR); | 512 | Reg dest = ra_dest(as, ir, RSET_GPR); |
482 | if (st >= IRT_I8 && st <= IRT_U16) { /* Extend to 32 bit integer. */ | 513 | if (st >= IRT_I8 && st <= IRT_U16) { /* Extend to 32 bit integer. */ |
483 | Reg left = ra_alloc1(as, ir->op1, RSET_GPR); | 514 | Reg left = ra_alloc1(as, ir->op1, RSET_GPR); |
@@ -505,16 +536,42 @@ static void asm_strto(ASMState *as, IRIns *ir) | |||
505 | { | 536 | { |
506 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_strscan_num]; | 537 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_strscan_num]; |
507 | IRRef args[2]; | 538 | IRRef args[2]; |
539 | int32_t ofs = 0; | ||
540 | #if LJ_SOFTFP | ||
541 | ra_evictset(as, RSET_SCRATCH); | ||
542 | if (ra_used(ir)) { | ||
543 | if (ra_hasspill(ir->s) && ra_hasspill((ir+1)->s) && | ||
544 | (ir->s & 1) == LJ_BE && (ir->s ^ 1) == (ir+1)->s) { | ||
545 | int i; | ||
546 | for (i = 0; i < 2; i++) { | ||
547 | Reg r = (ir+i)->r; | ||
548 | if (ra_hasreg(r)) { | ||
549 | ra_free(as, r); | ||
550 | ra_modified(as, r); | ||
551 | emit_spload(as, ir+i, r, sps_scale((ir+i)->s)); | ||
552 | } | ||
553 | } | ||
554 | ofs = sps_scale(ir->s & ~1); | ||
555 | } else { | ||
556 | Reg rhi = ra_dest(as, ir+1, RSET_GPR); | ||
557 | Reg rlo = ra_dest(as, ir, rset_exclude(RSET_GPR, rhi)); | ||
558 | emit_tsi(as, MIPSI_LW, rhi, RID_SP, ofs+(LJ_BE?0:4)); | ||
559 | emit_tsi(as, MIPSI_LW, rlo, RID_SP, ofs+(LJ_BE?4:0)); | ||
560 | } | ||
561 | } | ||
562 | #else | ||
508 | RegSet drop = RSET_SCRATCH; | 563 | RegSet drop = RSET_SCRATCH; |
509 | if (ra_hasreg(ir->r)) rset_set(drop, ir->r); /* Spill dest reg (if any). */ | 564 | if (ra_hasreg(ir->r)) rset_set(drop, ir->r); /* Spill dest reg (if any). */ |
510 | ra_evictset(as, drop); | 565 | ra_evictset(as, drop); |
566 | ofs = sps_scale(ir->s); | ||
567 | #endif | ||
511 | asm_guard(as, MIPSI_BEQ, RID_RET, RID_ZERO); /* Test return status. */ | 568 | asm_guard(as, MIPSI_BEQ, RID_RET, RID_ZERO); /* Test return status. */ |
512 | args[0] = ir->op1; /* GCstr *str */ | 569 | args[0] = ir->op1; /* GCstr *str */ |
513 | args[1] = ASMREF_TMP1; /* TValue *n */ | 570 | args[1] = ASMREF_TMP1; /* TValue *n */ |
514 | asm_gencall(as, ci, args); | 571 | asm_gencall(as, ci, args); |
515 | /* Store the result to the spill slot or temp slots. */ | 572 | /* Store the result to the spill slot or temp slots. */ |
516 | emit_tsi(as, MIPSI_ADDIU, ra_releasetmp(as, ASMREF_TMP1), | 573 | emit_tsi(as, MIPSI_ADDIU, ra_releasetmp(as, ASMREF_TMP1), |
517 | RID_SP, sps_scale(ir->s)); | 574 | RID_SP, ofs); |
518 | } | 575 | } |
519 | 576 | ||
520 | /* -- Memory references --------------------------------------------------- */ | 577 | /* -- Memory references --------------------------------------------------- */ |
@@ -532,12 +589,15 @@ static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) | |||
532 | /* Otherwise use g->tmptv to hold the TValue. */ | 589 | /* Otherwise use g->tmptv to hold the TValue. */ |
533 | RegSet allow = rset_exclude(RSET_GPR, dest); | 590 | RegSet allow = rset_exclude(RSET_GPR, dest); |
534 | Reg type; | 591 | Reg type; |
535 | emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, offsetof(global_State, tmptv)-32768); | 592 | emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, (int32_t)(offsetof(global_State, tmptv)-32768)); |
536 | if (!irt_ispri(ir->t)) { | 593 | if (!irt_ispri(ir->t)) { |
537 | Reg src = ra_alloc1(as, ref, allow); | 594 | Reg src = ra_alloc1(as, ref, allow); |
538 | emit_setgl(as, src, tmptv.gcr); | 595 | emit_setgl(as, src, tmptv.gcr); |
539 | } | 596 | } |
540 | type = ra_allock(as, irt_toitype(ir->t), allow); | 597 | if (LJ_SOFTFP && (ir+1)->o == IR_HIOP) |
598 | type = ra_alloc1(as, ref+1, allow); | ||
599 | else | ||
600 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); | ||
541 | emit_setgl(as, type, tmptv.it); | 601 | emit_setgl(as, type, tmptv.it); |
542 | } | 602 | } |
543 | } | 603 | } |
@@ -585,15 +645,37 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) | |||
585 | MCLabel l_end, l_loop, l_next; | 645 | MCLabel l_end, l_loop, l_next; |
586 | 646 | ||
587 | rset_clear(allow, tab); | 647 | rset_clear(allow, tab); |
648 | #if LJ_SOFTFP | ||
649 | if (!irref_isk(refkey)) { | ||
650 | key = ra_alloc1(as, refkey, allow); | ||
651 | rset_clear(allow, key); | ||
652 | if (irkey[1].o == IR_HIOP) { | ||
653 | if (ra_hasreg((irkey+1)->r)) { | ||
654 | tmpnum = (irkey+1)->r; | ||
655 | type = RID_TMP; | ||
656 | tmp1 = ra_scratch(as, allow); | ||
657 | rset_clear(allow, tmp1); | ||
658 | ra_noweak(as, tmpnum); | ||
659 | } else { | ||
660 | type = tmpnum = ra_allocref(as, refkey+1, allow); | ||
661 | } | ||
662 | rset_clear(allow, tmpnum); | ||
663 | } else { | ||
664 | type = ra_allock(as, (int32_t)irt_toitype(irkey->t), allow); | ||
665 | rset_clear(allow, type); | ||
666 | } | ||
667 | } | ||
668 | #else | ||
588 | if (irt_isnum(kt)) { | 669 | if (irt_isnum(kt)) { |
589 | key = ra_alloc1(as, refkey, RSET_FPR); | 670 | key = ra_alloc1(as, refkey, RSET_FPR); |
590 | tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key)); | 671 | tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key)); |
591 | } else if (!irt_ispri(kt)) { | 672 | } else if (!irt_ispri(kt)) { |
592 | key = ra_alloc1(as, refkey, allow); | 673 | key = ra_alloc1(as, refkey, allow); |
593 | rset_clear(allow, key); | 674 | rset_clear(allow, key); |
594 | type = ra_allock(as, irt_toitype(irkey->t), allow); | 675 | type = ra_allock(as, (int32_t)irt_toitype(irkey->t), allow); |
595 | rset_clear(allow, type); | 676 | rset_clear(allow, type); |
596 | } | 677 | } |
678 | #endif | ||
597 | tmp2 = ra_scratch(as, allow); | 679 | tmp2 = ra_scratch(as, allow); |
598 | rset_clear(allow, tmp2); | 680 | rset_clear(allow, tmp2); |
599 | 681 | ||
@@ -615,7 +697,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) | |||
615 | emit_ti(as, MIPSI_LI, RID_TMP, as->snapno); | 697 | emit_ti(as, MIPSI_LI, RID_TMP, as->snapno); |
616 | l_end = asm_exitstub_addr(as); | 698 | l_end = asm_exitstub_addr(as); |
617 | } | 699 | } |
618 | if (irt_isnum(kt)) { | 700 | if (!LJ_SOFTFP && irt_isnum(kt)) { |
619 | emit_branch(as, MIPSI_BC1T, 0, 0, l_end); | 701 | emit_branch(as, MIPSI_BC1T, 0, 0, l_end); |
620 | emit_fgh(as, MIPSI_C_EQ_D, 0, tmpnum, key); | 702 | emit_fgh(as, MIPSI_C_EQ_D, 0, tmpnum, key); |
621 | *--as->mcp = MIPSI_NOP; /* Avoid NaN comparison overhead. */ | 703 | *--as->mcp = MIPSI_NOP; /* Avoid NaN comparison overhead. */ |
@@ -660,7 +742,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) | |||
660 | emit_dst(as, MIPSI_XOR, tmp1, tmp1, tmp2); | 742 | emit_dst(as, MIPSI_XOR, tmp1, tmp1, tmp2); |
661 | emit_rotr(as, tmp1, tmp1, dest, (-HASH_ROT2-HASH_ROT1)&31); | 743 | emit_rotr(as, tmp1, tmp1, dest, (-HASH_ROT2-HASH_ROT1)&31); |
662 | emit_dst(as, MIPSI_SUBU, tmp2, tmp2, dest); | 744 | emit_dst(as, MIPSI_SUBU, tmp2, tmp2, dest); |
663 | if (irt_isnum(kt)) { | 745 | if (LJ_SOFTFP ? (irkey[1].o == IR_HIOP) : irt_isnum(kt)) { |
664 | emit_dst(as, MIPSI_XOR, tmp2, tmp2, tmp1); | 746 | emit_dst(as, MIPSI_XOR, tmp2, tmp2, tmp1); |
665 | if ((as->flags & JIT_F_MIPS32R2)) { | 747 | if ((as->flags & JIT_F_MIPS32R2)) { |
666 | emit_dta(as, MIPSI_ROTR, dest, tmp1, (-HASH_ROT1)&31); | 748 | emit_dta(as, MIPSI_ROTR, dest, tmp1, (-HASH_ROT1)&31); |
@@ -670,8 +752,13 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) | |||
670 | emit_dta(as, MIPSI_SRL, dest, tmp1, (-HASH_ROT1)&31); | 752 | emit_dta(as, MIPSI_SRL, dest, tmp1, (-HASH_ROT1)&31); |
671 | } | 753 | } |
672 | emit_dst(as, MIPSI_ADDU, tmp1, tmp1, tmp1); | 754 | emit_dst(as, MIPSI_ADDU, tmp1, tmp1, tmp1); |
755 | #if LJ_SOFTFP | ||
756 | emit_ds(as, MIPSI_MOVE, tmp1, type); | ||
757 | emit_ds(as, MIPSI_MOVE, tmp2, key); | ||
758 | #else | ||
673 | emit_tg(as, MIPSI_MFC1, tmp2, key); | 759 | emit_tg(as, MIPSI_MFC1, tmp2, key); |
674 | emit_tg(as, MIPSI_MFC1, tmp1, key+1); | 760 | emit_tg(as, MIPSI_MFC1, tmp1, key+1); |
761 | #endif | ||
675 | } else { | 762 | } else { |
676 | emit_dst(as, MIPSI_XOR, tmp2, key, tmp1); | 763 | emit_dst(as, MIPSI_XOR, tmp2, key, tmp1); |
677 | emit_rotr(as, dest, tmp1, tmp2, (-HASH_ROT1)&31); | 764 | emit_rotr(as, dest, tmp1, tmp2, (-HASH_ROT1)&31); |
@@ -795,8 +882,8 @@ static MIPSIns asm_fxloadins(IRIns *ir) | |||
795 | case IRT_U8: return MIPSI_LBU; | 882 | case IRT_U8: return MIPSI_LBU; |
796 | case IRT_I16: return MIPSI_LH; | 883 | case IRT_I16: return MIPSI_LH; |
797 | case IRT_U16: return MIPSI_LHU; | 884 | case IRT_U16: return MIPSI_LHU; |
798 | case IRT_NUM: return MIPSI_LDC1; | 885 | case IRT_NUM: lua_assert(!LJ_SOFTFP); return MIPSI_LDC1; |
799 | case IRT_FLOAT: return MIPSI_LWC1; | 886 | case IRT_FLOAT: if (!LJ_SOFTFP) return MIPSI_LWC1; |
800 | default: return MIPSI_LW; | 887 | default: return MIPSI_LW; |
801 | } | 888 | } |
802 | } | 889 | } |
@@ -806,8 +893,8 @@ static MIPSIns asm_fxstoreins(IRIns *ir) | |||
806 | switch (irt_type(ir->t)) { | 893 | switch (irt_type(ir->t)) { |
807 | case IRT_I8: case IRT_U8: return MIPSI_SB; | 894 | case IRT_I8: case IRT_U8: return MIPSI_SB; |
808 | case IRT_I16: case IRT_U16: return MIPSI_SH; | 895 | case IRT_I16: case IRT_U16: return MIPSI_SH; |
809 | case IRT_NUM: return MIPSI_SDC1; | 896 | case IRT_NUM: lua_assert(!LJ_SOFTFP); return MIPSI_SDC1; |
810 | case IRT_FLOAT: return MIPSI_SWC1; | 897 | case IRT_FLOAT: if (!LJ_SOFTFP) return MIPSI_SWC1; |
811 | default: return MIPSI_SW; | 898 | default: return MIPSI_SW; |
812 | } | 899 | } |
813 | } | 900 | } |
@@ -845,7 +932,8 @@ static void asm_fstore(ASMState *as, IRIns *ir) | |||
845 | 932 | ||
846 | static void asm_xload(ASMState *as, IRIns *ir) | 933 | static void asm_xload(ASMState *as, IRIns *ir) |
847 | { | 934 | { |
848 | Reg dest = ra_dest(as, ir, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); | 935 | Reg dest = ra_dest(as, ir, |
936 | (!LJ_SOFTFP && irt_isfp(ir->t)) ? RSET_FPR : RSET_GPR); | ||
849 | lua_assert(!(ir->op2 & IRXLOAD_UNALIGNED)); | 937 | lua_assert(!(ir->op2 & IRXLOAD_UNALIGNED)); |
850 | asm_fusexref(as, asm_fxloadins(ir), dest, ir->op1, RSET_GPR, 0); | 938 | asm_fusexref(as, asm_fxloadins(ir), dest, ir->op1, RSET_GPR, 0); |
851 | } | 939 | } |
@@ -853,7 +941,8 @@ static void asm_xload(ASMState *as, IRIns *ir) | |||
853 | static void asm_xstore_(ASMState *as, IRIns *ir, int32_t ofs) | 941 | static void asm_xstore_(ASMState *as, IRIns *ir, int32_t ofs) |
854 | { | 942 | { |
855 | if (ir->r != RID_SINK) { | 943 | if (ir->r != RID_SINK) { |
856 | Reg src = ra_alloc1z(as, ir->op2, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); | 944 | Reg src = ra_alloc1z(as, ir->op2, |
945 | (!LJ_SOFTFP && irt_isfp(ir->t)) ? RSET_FPR : RSET_GPR); | ||
857 | asm_fusexref(as, asm_fxstoreins(ir), src, ir->op1, | 946 | asm_fusexref(as, asm_fxstoreins(ir), src, ir->op1, |
858 | rset_exclude(RSET_GPR, src), ofs); | 947 | rset_exclude(RSET_GPR, src), ofs); |
859 | } | 948 | } |
@@ -863,25 +952,34 @@ static void asm_xstore_(ASMState *as, IRIns *ir, int32_t ofs) | |||
863 | 952 | ||
864 | static void asm_ahuvload(ASMState *as, IRIns *ir) | 953 | static void asm_ahuvload(ASMState *as, IRIns *ir) |
865 | { | 954 | { |
866 | IRType1 t = ir->t; | 955 | int hiop = (LJ_SOFTFP && (ir+1)->o == IR_HIOP); |
956 | IRType t = hiop ? IRT_NUM : irt_type(ir->t); | ||
867 | Reg dest = RID_NONE, type = RID_TMP, idx; | 957 | Reg dest = RID_NONE, type = RID_TMP, idx; |
868 | RegSet allow = RSET_GPR; | 958 | RegSet allow = RSET_GPR; |
869 | int32_t ofs = 0; | 959 | int32_t ofs = 0; |
960 | if (hiop && ra_used(ir+1)) { | ||
961 | type = ra_dest(as, ir+1, allow); | ||
962 | rset_clear(allow, type); | ||
963 | } | ||
870 | if (ra_used(ir)) { | 964 | if (ra_used(ir)) { |
871 | lua_assert(irt_isnum(t) || irt_isint(t) || irt_isaddr(t)); | 965 | lua_assert((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) || |
872 | dest = ra_dest(as, ir, irt_isnum(t) ? RSET_FPR : RSET_GPR); | 966 | irt_isint(ir->t) || irt_isaddr(ir->t)); |
967 | dest = ra_dest(as, ir, (!LJ_SOFTFP && t == IRT_NUM) ? RSET_FPR : allow); | ||
873 | rset_clear(allow, dest); | 968 | rset_clear(allow, dest); |
874 | } | 969 | } |
875 | idx = asm_fuseahuref(as, ir->op1, &ofs, allow); | 970 | idx = asm_fuseahuref(as, ir->op1, &ofs, allow); |
876 | rset_clear(allow, idx); | 971 | rset_clear(allow, idx); |
877 | if (irt_isnum(t)) { | 972 | if (t == IRT_NUM) { |
878 | asm_guard(as, MIPSI_BEQ, type, RID_ZERO); | 973 | asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO); |
879 | emit_tsi(as, MIPSI_SLTIU, type, type, (int32_t)LJ_TISNUM); | 974 | emit_tsi(as, MIPSI_SLTIU, RID_TMP, type, (int32_t)LJ_TISNUM); |
880 | if (ra_hasreg(dest)) | ||
881 | emit_hsi(as, MIPSI_LDC1, dest, idx, ofs); | ||
882 | } else { | 975 | } else { |
883 | asm_guard(as, MIPSI_BNE, type, ra_allock(as, irt_toitype(t), allow)); | 976 | asm_guard(as, MIPSI_BNE, type, ra_allock(as, irt_toitype_(t), allow)); |
884 | if (ra_hasreg(dest)) emit_tsi(as, MIPSI_LW, dest, idx, ofs+(LJ_BE?4:0)); | 977 | } |
978 | if (ra_hasreg(dest)) { | ||
979 | if (!LJ_SOFTFP && t == IRT_NUM) | ||
980 | emit_hsi(as, MIPSI_LDC1, dest, idx, ofs); | ||
981 | else | ||
982 | emit_tsi(as, MIPSI_LW, dest, idx, ofs+(LJ_BE?4:0)); | ||
885 | } | 983 | } |
886 | emit_tsi(as, MIPSI_LW, type, idx, ofs+(LJ_BE?0:4)); | 984 | emit_tsi(as, MIPSI_LW, type, idx, ofs+(LJ_BE?0:4)); |
887 | } | 985 | } |
@@ -893,18 +991,22 @@ static void asm_ahustore(ASMState *as, IRIns *ir) | |||
893 | int32_t ofs = 0; | 991 | int32_t ofs = 0; |
894 | if (ir->r == RID_SINK) | 992 | if (ir->r == RID_SINK) |
895 | return; | 993 | return; |
896 | if (irt_isnum(ir->t)) { | 994 | if (!LJ_SOFTFP && irt_isnum(ir->t)) { |
897 | src = ra_alloc1(as, ir->op2, RSET_FPR); | 995 | src = ra_alloc1(as, ir->op2, RSET_FPR); |
898 | } else { | 996 | } else { |
997 | int hiop = (LJ_SOFTFP && (ir+1)->o == IR_HIOP); | ||
899 | if (!irt_ispri(ir->t)) { | 998 | if (!irt_ispri(ir->t)) { |
900 | src = ra_alloc1(as, ir->op2, allow); | 999 | src = ra_alloc1(as, ir->op2, allow); |
901 | rset_clear(allow, src); | 1000 | rset_clear(allow, src); |
902 | } | 1001 | } |
903 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); | 1002 | if (hiop) |
1003 | type = ra_alloc1(as, (ir+1)->op2, allow); | ||
1004 | else | ||
1005 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); | ||
904 | rset_clear(allow, type); | 1006 | rset_clear(allow, type); |
905 | } | 1007 | } |
906 | idx = asm_fuseahuref(as, ir->op1, &ofs, allow); | 1008 | idx = asm_fuseahuref(as, ir->op1, &ofs, allow); |
907 | if (irt_isnum(ir->t)) { | 1009 | if (!LJ_SOFTFP && irt_isnum(ir->t)) { |
908 | emit_hsi(as, MIPSI_SDC1, src, idx, ofs); | 1010 | emit_hsi(as, MIPSI_SDC1, src, idx, ofs); |
909 | } else { | 1011 | } else { |
910 | if (ra_hasreg(src)) | 1012 | if (ra_hasreg(src)) |
@@ -916,35 +1018,45 @@ static void asm_ahustore(ASMState *as, IRIns *ir) | |||
916 | static void asm_sload(ASMState *as, IRIns *ir) | 1018 | static void asm_sload(ASMState *as, IRIns *ir) |
917 | { | 1019 | { |
918 | int32_t ofs = 8*((int32_t)ir->op1-1) + ((ir->op2 & IRSLOAD_FRAME) ? 4 : 0); | 1020 | int32_t ofs = 8*((int32_t)ir->op1-1) + ((ir->op2 & IRSLOAD_FRAME) ? 4 : 0); |
919 | IRType1 t = ir->t; | 1021 | int hiop = (LJ_SOFTFP && (ir+1)->o == IR_HIOP); |
1022 | IRType t = hiop ? IRT_NUM : irt_type(ir->t); | ||
920 | Reg dest = RID_NONE, type = RID_NONE, base; | 1023 | Reg dest = RID_NONE, type = RID_NONE, base; |
921 | RegSet allow = RSET_GPR; | 1024 | RegSet allow = RSET_GPR; |
922 | lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */ | 1025 | lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */ |
923 | lua_assert(irt_isguard(t) || !(ir->op2 & IRSLOAD_TYPECHECK)); | 1026 | lua_assert(irt_isguard(ir->t) || !(ir->op2 & IRSLOAD_TYPECHECK)); |
924 | lua_assert(!irt_isint(t) || (ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME))); | 1027 | #if LJ_SOFTFP |
925 | if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(t) && irt_isint(t)) { | 1028 | lua_assert(!(ir->op2 & IRSLOAD_CONVERT)); /* Handled by LJ_SOFTFP SPLIT. */ |
1029 | if (hiop && ra_used(ir+1)) { | ||
1030 | type = ra_dest(as, ir+1, allow); | ||
1031 | rset_clear(allow, type); | ||
1032 | } | ||
1033 | #else | ||
1034 | if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(ir->t) && t == IRT_INT) { | ||
926 | dest = ra_scratch(as, RSET_FPR); | 1035 | dest = ra_scratch(as, RSET_FPR); |
927 | asm_tointg(as, ir, dest); | 1036 | asm_tointg(as, ir, dest); |
928 | t.irt = IRT_NUM; /* Continue with a regular number type check. */ | 1037 | t = IRT_NUM; /* Continue with a regular number type check. */ |
929 | } else if (ra_used(ir)) { | 1038 | } else |
930 | lua_assert(irt_isnum(t) || irt_isint(t) || irt_isaddr(t)); | 1039 | #endif |
931 | dest = ra_dest(as, ir, irt_isnum(t) ? RSET_FPR : RSET_GPR); | 1040 | if (ra_used(ir)) { |
1041 | lua_assert((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) || | ||
1042 | irt_isint(ir->t) || irt_isaddr(ir->t)); | ||
1043 | dest = ra_dest(as, ir, (!LJ_SOFTFP && t == IRT_NUM) ? RSET_FPR : allow); | ||
932 | rset_clear(allow, dest); | 1044 | rset_clear(allow, dest); |
933 | base = ra_alloc1(as, REF_BASE, allow); | 1045 | base = ra_alloc1(as, REF_BASE, allow); |
934 | rset_clear(allow, base); | 1046 | rset_clear(allow, base); |
935 | if ((ir->op2 & IRSLOAD_CONVERT)) { | 1047 | if (!LJ_SOFTFP && (ir->op2 & IRSLOAD_CONVERT)) { |
936 | if (irt_isint(t)) { | 1048 | if (t == IRT_INT) { |
937 | Reg tmp = ra_scratch(as, RSET_FPR); | 1049 | Reg tmp = ra_scratch(as, RSET_FPR); |
938 | emit_tg(as, MIPSI_MFC1, dest, tmp); | 1050 | emit_tg(as, MIPSI_MFC1, dest, tmp); |
939 | emit_fg(as, MIPSI_TRUNC_W_D, tmp, tmp); | 1051 | emit_fg(as, MIPSI_TRUNC_W_D, tmp, tmp); |
940 | dest = tmp; | 1052 | dest = tmp; |
941 | t.irt = IRT_NUM; /* Check for original type. */ | 1053 | t = IRT_NUM; /* Check for original type. */ |
942 | } else { | 1054 | } else { |
943 | Reg tmp = ra_scratch(as, RSET_GPR); | 1055 | Reg tmp = ra_scratch(as, RSET_GPR); |
944 | emit_fg(as, MIPSI_CVT_D_W, dest, dest); | 1056 | emit_fg(as, MIPSI_CVT_D_W, dest, dest); |
945 | emit_tg(as, MIPSI_MTC1, tmp, dest); | 1057 | emit_tg(as, MIPSI_MTC1, tmp, dest); |
946 | dest = tmp; | 1058 | dest = tmp; |
947 | t.irt = IRT_INT; /* Check for original type. */ | 1059 | t = IRT_INT; /* Check for original type. */ |
948 | } | 1060 | } |
949 | } | 1061 | } |
950 | goto dotypecheck; | 1062 | goto dotypecheck; |
@@ -952,22 +1064,32 @@ static void asm_sload(ASMState *as, IRIns *ir) | |||
952 | base = ra_alloc1(as, REF_BASE, allow); | 1064 | base = ra_alloc1(as, REF_BASE, allow); |
953 | rset_clear(allow, base); | 1065 | rset_clear(allow, base); |
954 | dotypecheck: | 1066 | dotypecheck: |
955 | if (irt_isnum(t)) { | 1067 | if ((ir->op2 & IRSLOAD_TYPECHECK)) { |
956 | if ((ir->op2 & IRSLOAD_TYPECHECK)) { | 1068 | if (ra_noreg(type)) { |
957 | asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO); | 1069 | if (ofs < 256 && ra_hasreg(dest) && (dest & 1) == 0 && |
958 | emit_tsi(as, MIPSI_SLTIU, RID_TMP, RID_TMP, (int32_t)LJ_TISNUM); | 1070 | rset_test((as->freeset & allow), dest+1)) { |
959 | type = RID_TMP; | 1071 | type = dest+1; |
1072 | ra_modified(as, type); | ||
1073 | } else { | ||
1074 | type = RID_TMP; | ||
1075 | } | ||
960 | } | 1076 | } |
961 | if (ra_hasreg(dest)) emit_hsi(as, MIPSI_LDC1, dest, base, ofs); | 1077 | if (t == IRT_NUM) { |
962 | } else { | 1078 | asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO); |
963 | if ((ir->op2 & IRSLOAD_TYPECHECK)) { | 1079 | emit_tsi(as, MIPSI_SLTIU, RID_TMP, type, (int32_t)LJ_TISNUM); |
964 | Reg ktype = ra_allock(as, irt_toitype(t), allow); | 1080 | } else { |
965 | asm_guard(as, MIPSI_BNE, RID_TMP, ktype); | 1081 | Reg ktype = ra_allock(as, irt_toitype_(t), allow); |
966 | type = RID_TMP; | 1082 | asm_guard(as, MIPSI_BNE, type, ktype); |
967 | } | 1083 | } |
968 | if (ra_hasreg(dest)) emit_tsi(as, MIPSI_LW, dest, base, ofs ^ (LJ_BE?4:0)); | ||
969 | } | 1084 | } |
970 | if (ra_hasreg(type)) emit_tsi(as, MIPSI_LW, type, base, ofs ^ (LJ_BE?0:4)); | 1085 | if (ra_hasreg(dest)) { |
1086 | if (!LJ_SOFTFP && t == IRT_NUM) | ||
1087 | emit_hsi(as, MIPSI_LDC1, dest, base, ofs); | ||
1088 | else | ||
1089 | emit_tsi(as, MIPSI_LW, dest, base, ofs ^ (LJ_BE?4:0)); | ||
1090 | } | ||
1091 | if (ra_hasreg(type)) | ||
1092 | emit_tsi(as, MIPSI_LW, type, base, ofs ^ (LJ_BE?0:4)); | ||
971 | } | 1093 | } |
972 | 1094 | ||
973 | /* -- Allocations --------------------------------------------------------- */ | 1095 | /* -- Allocations --------------------------------------------------------- */ |
@@ -1080,6 +1202,7 @@ static void asm_obar(ASMState *as, IRIns *ir) | |||
1080 | 1202 | ||
1081 | /* -- Arithmetic and logic operations ------------------------------------- */ | 1203 | /* -- Arithmetic and logic operations ------------------------------------- */ |
1082 | 1204 | ||
1205 | #if !LJ_SOFTFP | ||
1083 | static void asm_fparith(ASMState *as, IRIns *ir, MIPSIns mi) | 1206 | static void asm_fparith(ASMState *as, IRIns *ir, MIPSIns mi) |
1084 | { | 1207 | { |
1085 | Reg dest = ra_dest(as, ir, RSET_FPR); | 1208 | Reg dest = ra_dest(as, ir, RSET_FPR); |
@@ -1106,12 +1229,16 @@ static void asm_fpmath(ASMState *as, IRIns *ir) | |||
1106 | else | 1229 | else |
1107 | asm_callid(as, ir, IRCALL_lj_vm_floor + ir->op2); | 1230 | asm_callid(as, ir, IRCALL_lj_vm_floor + ir->op2); |
1108 | } | 1231 | } |
1232 | #endif | ||
1109 | 1233 | ||
1110 | static void asm_add(ASMState *as, IRIns *ir) | 1234 | static void asm_add(ASMState *as, IRIns *ir) |
1111 | { | 1235 | { |
1236 | #if !LJ_SOFTFP | ||
1112 | if (irt_isnum(ir->t)) { | 1237 | if (irt_isnum(ir->t)) { |
1113 | asm_fparith(as, ir, MIPSI_ADD_D); | 1238 | asm_fparith(as, ir, MIPSI_ADD_D); |
1114 | } else { | 1239 | } else |
1240 | #endif | ||
1241 | { | ||
1115 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1242 | Reg dest = ra_dest(as, ir, RSET_GPR); |
1116 | Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); | 1243 | Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); |
1117 | if (irref_isk(ir->op2)) { | 1244 | if (irref_isk(ir->op2)) { |
@@ -1128,9 +1255,12 @@ static void asm_add(ASMState *as, IRIns *ir) | |||
1128 | 1255 | ||
1129 | static void asm_sub(ASMState *as, IRIns *ir) | 1256 | static void asm_sub(ASMState *as, IRIns *ir) |
1130 | { | 1257 | { |
1258 | #if !LJ_SOFTFP | ||
1131 | if (irt_isnum(ir->t)) { | 1259 | if (irt_isnum(ir->t)) { |
1132 | asm_fparith(as, ir, MIPSI_SUB_D); | 1260 | asm_fparith(as, ir, MIPSI_SUB_D); |
1133 | } else { | 1261 | } else |
1262 | #endif | ||
1263 | { | ||
1134 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1264 | Reg dest = ra_dest(as, ir, RSET_GPR); |
1135 | Reg right, left = ra_alloc2(as, ir, RSET_GPR); | 1265 | Reg right, left = ra_alloc2(as, ir, RSET_GPR); |
1136 | right = (left >> 8); left &= 255; | 1266 | right = (left >> 8); left &= 255; |
@@ -1140,9 +1270,12 @@ static void asm_sub(ASMState *as, IRIns *ir) | |||
1140 | 1270 | ||
1141 | static void asm_mul(ASMState *as, IRIns *ir) | 1271 | static void asm_mul(ASMState *as, IRIns *ir) |
1142 | { | 1272 | { |
1273 | #if !LJ_SOFTFP | ||
1143 | if (irt_isnum(ir->t)) { | 1274 | if (irt_isnum(ir->t)) { |
1144 | asm_fparith(as, ir, MIPSI_MUL_D); | 1275 | asm_fparith(as, ir, MIPSI_MUL_D); |
1145 | } else { | 1276 | } else |
1277 | #endif | ||
1278 | { | ||
1146 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1279 | Reg dest = ra_dest(as, ir, RSET_GPR); |
1147 | Reg right, left = ra_alloc2(as, ir, RSET_GPR); | 1280 | Reg right, left = ra_alloc2(as, ir, RSET_GPR); |
1148 | right = (left >> 8); left &= 255; | 1281 | right = (left >> 8); left &= 255; |
@@ -1156,9 +1289,12 @@ static void asm_mul(ASMState *as, IRIns *ir) | |||
1156 | 1289 | ||
1157 | static void asm_neg(ASMState *as, IRIns *ir) | 1290 | static void asm_neg(ASMState *as, IRIns *ir) |
1158 | { | 1291 | { |
1292 | #if !LJ_SOFTFP | ||
1159 | if (irt_isnum(ir->t)) { | 1293 | if (irt_isnum(ir->t)) { |
1160 | asm_fpunary(as, ir, MIPSI_NEG_D); | 1294 | asm_fpunary(as, ir, MIPSI_NEG_D); |
1161 | } else { | 1295 | } else |
1296 | #endif | ||
1297 | { | ||
1162 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1298 | Reg dest = ra_dest(as, ir, RSET_GPR); |
1163 | Reg left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); | 1299 | Reg left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); |
1164 | emit_dst(as, MIPSI_SUBU, dest, RID_ZERO, left); | 1300 | emit_dst(as, MIPSI_SUBU, dest, RID_ZERO, left); |
@@ -1396,9 +1532,25 @@ static void asm_bror(ASMState *as, IRIns *ir) | |||
1396 | } | 1532 | } |
1397 | } | 1533 | } |
1398 | 1534 | ||
1535 | #if LJ_SOFTFP | ||
1536 | static void asm_sfpmin_max(ASMState *as, IRIns *ir) | ||
1537 | { | ||
1538 | CCallInfo ci = lj_ir_callinfo[(IROp)ir->o == IR_MIN ? IRCALL_lj_vm_sfmin : IRCALL_lj_vm_sfmax]; | ||
1539 | IRRef args[4]; | ||
1540 | args[0^LJ_BE] = ir->op1; | ||
1541 | args[1^LJ_BE] = (ir+1)->op1; | ||
1542 | args[2^LJ_BE] = ir->op2; | ||
1543 | args[3^LJ_BE] = (ir+1)->op2; | ||
1544 | asm_setupresult(as, ir, &ci); | ||
1545 | emit_call(as, (void *)ci.func, 0); | ||
1546 | ci.func = NULL; | ||
1547 | asm_gencall(as, &ci, args); | ||
1548 | } | ||
1549 | #endif | ||
1550 | |||
1399 | static void asm_min_max(ASMState *as, IRIns *ir, int ismax) | 1551 | static void asm_min_max(ASMState *as, IRIns *ir, int ismax) |
1400 | { | 1552 | { |
1401 | if (irt_isnum(ir->t)) { | 1553 | if (!LJ_SOFTFP && irt_isnum(ir->t)) { |
1402 | Reg dest = ra_dest(as, ir, RSET_FPR); | 1554 | Reg dest = ra_dest(as, ir, RSET_FPR); |
1403 | Reg right, left = ra_alloc2(as, ir, RSET_FPR); | 1555 | Reg right, left = ra_alloc2(as, ir, RSET_FPR); |
1404 | right = (left >> 8); left &= 255; | 1556 | right = (left >> 8); left &= 255; |
@@ -1429,11 +1581,72 @@ static void asm_min_max(ASMState *as, IRIns *ir, int ismax) | |||
1429 | 1581 | ||
1430 | /* -- Comparisons --------------------------------------------------------- */ | 1582 | /* -- Comparisons --------------------------------------------------------- */ |
1431 | 1583 | ||
1584 | #if LJ_SOFTFP | ||
1585 | /* SFP comparisons. */ | ||
1586 | static void asm_sfpcomp(ASMState *as, IRIns *ir) | ||
1587 | { | ||
1588 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_softfp_cmp]; | ||
1589 | RegSet drop = RSET_SCRATCH; | ||
1590 | Reg r; | ||
1591 | IRRef args[4]; | ||
1592 | args[LJ_LE ? 0 : 1] = ir->op1; args[LJ_LE ? 1 : 0] = (ir+1)->op1; | ||
1593 | args[LJ_LE ? 2 : 3] = ir->op2; args[LJ_LE ? 3 : 2] = (ir+1)->op2; | ||
1594 | |||
1595 | for (r = REGARG_FIRSTGPR; r <= REGARG_FIRSTGPR+3; r++) { | ||
1596 | if (!rset_test(as->freeset, r) && | ||
1597 | regcost_ref(as->cost[r]) == args[r-REGARG_FIRSTGPR]) | ||
1598 | rset_clear(drop, r); | ||
1599 | } | ||
1600 | ra_evictset(as, drop); | ||
1601 | |||
1602 | asm_setupresult(as, ir, ci); | ||
1603 | |||
1604 | switch ((IROp)ir->o) { | ||
1605 | case IR_LT: | ||
1606 | asm_guard(as, MIPSI_BGEZ, RID_RET, 0); | ||
1607 | break; | ||
1608 | case IR_ULT: | ||
1609 | asm_guard(as, MIPSI_BEQ, RID_RET, RID_TMP); | ||
1610 | emit_loadi(as, RID_TMP, 1); | ||
1611 | asm_guard(as, MIPSI_BEQ, RID_RET, RID_ZERO); | ||
1612 | break; | ||
1613 | case IR_GE: | ||
1614 | asm_guard(as, MIPSI_BEQ, RID_RET, RID_TMP); | ||
1615 | emit_loadi(as, RID_TMP, 2); | ||
1616 | asm_guard(as, MIPSI_BLTZ, RID_RET, 0); | ||
1617 | break; | ||
1618 | case IR_LE: | ||
1619 | asm_guard(as, MIPSI_BGTZ, RID_RET, 0); | ||
1620 | break; | ||
1621 | case IR_GT: | ||
1622 | asm_guard(as, MIPSI_BEQ, RID_RET, RID_TMP); | ||
1623 | emit_loadi(as, RID_TMP, 2); | ||
1624 | asm_guard(as, MIPSI_BLEZ, RID_RET, 0); | ||
1625 | break; | ||
1626 | case IR_UGE: | ||
1627 | asm_guard(as, MIPSI_BLTZ, RID_RET, 0); | ||
1628 | break; | ||
1629 | case IR_ULE: | ||
1630 | asm_guard(as, MIPSI_BEQ, RID_RET, RID_TMP); | ||
1631 | emit_loadi(as, RID_TMP, 1); | ||
1632 | break; | ||
1633 | case IR_UGT: case IR_ABC: | ||
1634 | asm_guard(as, MIPSI_BLEZ, RID_RET, 0); | ||
1635 | break; | ||
1636 | case IR_EQ: case IR_NE: | ||
1637 | asm_guard(as, (ir->o & 1) ? MIPSI_BEQ : MIPSI_BNE, RID_RET, RID_ZERO); | ||
1638 | default: | ||
1639 | break; | ||
1640 | } | ||
1641 | asm_gencall(as, ci, args); | ||
1642 | } | ||
1643 | #endif | ||
1644 | |||
1432 | static void asm_comp(ASMState *as, IRIns *ir) | 1645 | static void asm_comp(ASMState *as, IRIns *ir) |
1433 | { | 1646 | { |
1434 | /* ORDER IR: LT GE LE GT ULT UGE ULE UGT. */ | 1647 | /* ORDER IR: LT GE LE GT ULT UGE ULE UGT. */ |
1435 | IROp op = ir->o; | 1648 | IROp op = ir->o; |
1436 | if (irt_isnum(ir->t)) { | 1649 | if (!LJ_SOFTFP && irt_isnum(ir->t)) { |
1437 | Reg right, left = ra_alloc2(as, ir, RSET_FPR); | 1650 | Reg right, left = ra_alloc2(as, ir, RSET_FPR); |
1438 | right = (left >> 8); left &= 255; | 1651 | right = (left >> 8); left &= 255; |
1439 | asm_guard(as, (op&1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0); | 1652 | asm_guard(as, (op&1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0); |
@@ -1466,9 +1679,9 @@ static void asm_comp(ASMState *as, IRIns *ir) | |||
1466 | 1679 | ||
1467 | static void asm_equal(ASMState *as, IRIns *ir) | 1680 | static void asm_equal(ASMState *as, IRIns *ir) |
1468 | { | 1681 | { |
1469 | Reg right, left = ra_alloc2(as, ir, irt_isnum(ir->t) ? RSET_FPR : RSET_GPR); | 1682 | Reg right, left = ra_alloc2(as, ir, (!LJ_SOFTFP && irt_isnum(ir->t)) ? RSET_FPR : RSET_GPR); |
1470 | right = (left >> 8); left &= 255; | 1683 | right = (left >> 8); left &= 255; |
1471 | if (irt_isnum(ir->t)) { | 1684 | if (!LJ_SOFTFP && irt_isnum(ir->t)) { |
1472 | asm_guard(as, (ir->o & 1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0); | 1685 | asm_guard(as, (ir->o & 1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0); |
1473 | emit_fgh(as, MIPSI_C_EQ_D, 0, left, right); | 1686 | emit_fgh(as, MIPSI_C_EQ_D, 0, left, right); |
1474 | } else { | 1687 | } else { |
@@ -1518,23 +1731,48 @@ static void asm_comp64eq(ASMState *as, IRIns *ir) | |||
1518 | /* Hiword op of a split 64 bit op. Previous op must be the loword op. */ | 1731 | /* Hiword op of a split 64 bit op. Previous op must be the loword op. */ |
1519 | static void asm_hiop(ASMState *as, IRIns *ir) | 1732 | static void asm_hiop(ASMState *as, IRIns *ir) |
1520 | { | 1733 | { |
1521 | #if LJ_HASFFI | 1734 | #if LJ_HASFFI || LJ_SOFTFP |
1522 | /* HIOP is marked as a store because it needs its own DCE logic. */ | 1735 | /* HIOP is marked as a store because it needs its own DCE logic. */ |
1523 | int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */ | 1736 | int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */ |
1524 | if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1; | 1737 | if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1; |
1525 | if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */ | 1738 | if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */ |
1526 | as->curins--; /* Always skip the CONV. */ | 1739 | as->curins--; /* Always skip the CONV. */ |
1740 | #if LJ_HASFFI && !LJ_SOFTFP | ||
1527 | if (usehi || uselo) | 1741 | if (usehi || uselo) |
1528 | asm_conv64(as, ir); | 1742 | asm_conv64(as, ir); |
1529 | return; | 1743 | return; |
1744 | #endif | ||
1530 | } else if ((ir-1)->o < IR_EQ) { /* 64 bit integer comparisons. ORDER IR. */ | 1745 | } else if ((ir-1)->o < IR_EQ) { /* 64 bit integer comparisons. ORDER IR. */ |
1531 | as->curins--; /* Always skip the loword comparison. */ | 1746 | as->curins--; /* Always skip the loword comparison. */ |
1747 | #if LJ_SOFTFP | ||
1748 | if (!irt_isint(ir->t)) { | ||
1749 | asm_sfpcomp(as, ir-1); | ||
1750 | return; | ||
1751 | } | ||
1752 | #endif | ||
1753 | #if LJ_HASFFI | ||
1532 | asm_comp64(as, ir); | 1754 | asm_comp64(as, ir); |
1755 | #endif | ||
1533 | return; | 1756 | return; |
1534 | } else if ((ir-1)->o <= IR_NE) { /* 64 bit integer comparisons. ORDER IR. */ | 1757 | } else if ((ir-1)->o <= IR_NE) { /* 64 bit integer comparisons. ORDER IR. */ |
1535 | as->curins--; /* Always skip the loword comparison. */ | 1758 | as->curins--; /* Always skip the loword comparison. */ |
1759 | #if LJ_SOFTFP | ||
1760 | if (!irt_isint(ir->t)) { | ||
1761 | asm_sfpcomp(as, ir-1); | ||
1762 | return; | ||
1763 | } | ||
1764 | #endif | ||
1765 | #if LJ_HASFFI | ||
1536 | asm_comp64eq(as, ir); | 1766 | asm_comp64eq(as, ir); |
1767 | #endif | ||
1537 | return; | 1768 | return; |
1769 | #if LJ_SOFTFP | ||
1770 | } else if ((ir-1)->o == IR_MIN || (ir-1)->o == IR_MAX) { | ||
1771 | as->curins--; /* Always skip the loword min/max. */ | ||
1772 | if (uselo || usehi) | ||
1773 | asm_sfpmin_max(as, ir-1); | ||
1774 | return; | ||
1775 | #endif | ||
1538 | } else if ((ir-1)->o == IR_XSTORE) { | 1776 | } else if ((ir-1)->o == IR_XSTORE) { |
1539 | as->curins--; /* Handle both stores here. */ | 1777 | as->curins--; /* Handle both stores here. */ |
1540 | if ((ir-1)->r != RID_SINK) { | 1778 | if ((ir-1)->r != RID_SINK) { |
@@ -1545,14 +1783,27 @@ static void asm_hiop(ASMState *as, IRIns *ir) | |||
1545 | } | 1783 | } |
1546 | if (!usehi) return; /* Skip unused hiword op for all remaining ops. */ | 1784 | if (!usehi) return; /* Skip unused hiword op for all remaining ops. */ |
1547 | switch ((ir-1)->o) { | 1785 | switch ((ir-1)->o) { |
1786 | #if LJ_HASFFI | ||
1548 | case IR_ADD: as->curins--; asm_add64(as, ir); break; | 1787 | case IR_ADD: as->curins--; asm_add64(as, ir); break; |
1549 | case IR_SUB: as->curins--; asm_sub64(as, ir); break; | 1788 | case IR_SUB: as->curins--; asm_sub64(as, ir); break; |
1550 | case IR_NEG: as->curins--; asm_neg64(as, ir); break; | 1789 | case IR_NEG: as->curins--; asm_neg64(as, ir); break; |
1790 | #endif | ||
1791 | #if LJ_SOFTFP | ||
1792 | case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD: | ||
1793 | case IR_STRTO: | ||
1794 | if (!uselo) | ||
1795 | ra_allocref(as, ir->op1, RSET_GPR); /* Mark lo op as used. */ | ||
1796 | break; | ||
1797 | #endif | ||
1551 | case IR_CALLN: | 1798 | case IR_CALLN: |
1799 | case IR_CALLS: | ||
1552 | case IR_CALLXS: | 1800 | case IR_CALLXS: |
1553 | if (!uselo) | 1801 | if (!uselo) |
1554 | ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ | 1802 | ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ |
1555 | break; | 1803 | break; |
1804 | #if LJ_SOFTFP | ||
1805 | case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: | ||
1806 | #endif | ||
1556 | case IR_CNEWI: | 1807 | case IR_CNEWI: |
1557 | /* Nothing to do here. Handled by lo op itself. */ | 1808 | /* Nothing to do here. Handled by lo op itself. */ |
1558 | break; | 1809 | break; |
@@ -1619,8 +1870,19 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap) | |||
1619 | if ((sn & SNAP_NORESTORE)) | 1870 | if ((sn & SNAP_NORESTORE)) |
1620 | continue; | 1871 | continue; |
1621 | if (irt_isnum(ir->t)) { | 1872 | if (irt_isnum(ir->t)) { |
1873 | #if LJ_SOFTFP | ||
1874 | Reg tmp; | ||
1875 | RegSet allow = rset_exclude(RSET_GPR, RID_BASE); | ||
1876 | lua_assert(irref_isk(ref)); /* LJ_SOFTFP: must be a number constant. */ | ||
1877 | tmp = ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, allow); | ||
1878 | emit_tsi(as, MIPSI_SW, tmp, RID_BASE, ofs+(LJ_BE?4:0)); | ||
1879 | if (rset_test(as->freeset, tmp+1)) allow = RID2RSET(tmp+1); | ||
1880 | tmp = ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, allow); | ||
1881 | emit_tsi(as, MIPSI_SW, tmp, RID_BASE, ofs+(LJ_BE?0:4)); | ||
1882 | #else | ||
1622 | Reg src = ra_alloc1(as, ref, RSET_FPR); | 1883 | Reg src = ra_alloc1(as, ref, RSET_FPR); |
1623 | emit_hsi(as, MIPSI_SDC1, src, RID_BASE, ofs); | 1884 | emit_hsi(as, MIPSI_SDC1, src, RID_BASE, ofs); |
1885 | #endif | ||
1624 | } else { | 1886 | } else { |
1625 | Reg type; | 1887 | Reg type; |
1626 | RegSet allow = rset_exclude(RSET_GPR, RID_BASE); | 1888 | RegSet allow = rset_exclude(RSET_GPR, RID_BASE); |
@@ -1633,6 +1895,10 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap) | |||
1633 | if ((sn & (SNAP_CONT|SNAP_FRAME))) { | 1895 | if ((sn & (SNAP_CONT|SNAP_FRAME))) { |
1634 | if (s == 0) continue; /* Do not overwrite link to previous frame. */ | 1896 | if (s == 0) continue; /* Do not overwrite link to previous frame. */ |
1635 | type = ra_allock(as, (int32_t)(*flinks--), allow); | 1897 | type = ra_allock(as, (int32_t)(*flinks--), allow); |
1898 | #if LJ_SOFTFP | ||
1899 | } else if ((sn & SNAP_SOFTFPNUM)) { | ||
1900 | type = ra_alloc1(as, ref+1, rset_exclude(RSET_GPR, RID_BASE)); | ||
1901 | #endif | ||
1636 | } else { | 1902 | } else { |
1637 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); | 1903 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); |
1638 | } | 1904 | } |
@@ -1756,11 +2022,11 @@ static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci) | |||
1756 | int nslots = 4, ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR; | 2022 | int nslots = 4, ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR; |
1757 | asm_collectargs(as, ir, ci, args); | 2023 | asm_collectargs(as, ir, ci, args); |
1758 | for (i = 0; i < nargs; i++) { | 2024 | for (i = 0; i < nargs; i++) { |
1759 | if (args[i] && irt_isfp(IR(args[i])->t) && | 2025 | if (!LJ_SOFTFP && args[i] && irt_isfp(IR(args[i])->t) && |
1760 | nfpr > 0 && !(ci->flags & CCI_VARARG)) { | 2026 | nfpr > 0 && !(ci->flags & CCI_VARARG)) { |
1761 | nfpr--; | 2027 | nfpr--; |
1762 | ngpr -= irt_isnum(IR(args[i])->t) ? 2 : 1; | 2028 | ngpr -= irt_isnum(IR(args[i])->t) ? 2 : 1; |
1763 | } else if (args[i] && irt_isnum(IR(args[i])->t)) { | 2029 | } else if (!LJ_SOFTFP && args[i] && irt_isnum(IR(args[i])->t)) { |
1764 | nfpr = 0; | 2030 | nfpr = 0; |
1765 | ngpr = ngpr & ~1; | 2031 | ngpr = ngpr & ~1; |
1766 | if (ngpr > 0) ngpr -= 2; else nslots = (nslots+3) & ~1; | 2032 | if (ngpr > 0) ngpr -= 2; else nslots = (nslots+3) & ~1; |