diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lj_arch.h | 1 | ||||
-rw-r--r-- | src/lj_asm_ppc.h | 321 |
2 files changed, 278 insertions, 44 deletions
diff --git a/src/lj_arch.h b/src/lj_arch.h index 0145a7c0..5962f3af 100644 --- a/src/lj_arch.h +++ b/src/lj_arch.h | |||
@@ -273,7 +273,6 @@ | |||
273 | #endif | 273 | #endif |
274 | 274 | ||
275 | #if LJ_ABI_SOFTFP | 275 | #if LJ_ABI_SOFTFP |
276 | #define LJ_ARCH_NOJIT 1 /* NYI */ | ||
277 | #define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL | 276 | #define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL |
278 | #else | 277 | #else |
279 | #define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL_SINGLE | 278 | #define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL_SINGLE |
diff --git a/src/lj_asm_ppc.h b/src/lj_asm_ppc.h index 6daa861b..1955429f 100644 --- a/src/lj_asm_ppc.h +++ b/src/lj_asm_ppc.h | |||
@@ -226,6 +226,7 @@ static void asm_fusexrefx(ASMState *as, PPCIns pi, Reg rt, IRRef ref, | |||
226 | emit_tab(as, pi, rt, left, right); | 226 | emit_tab(as, pi, rt, left, right); |
227 | } | 227 | } |
228 | 228 | ||
229 | #if !LJ_SOFTFP | ||
229 | /* Fuse to multiply-add/sub instruction. */ | 230 | /* Fuse to multiply-add/sub instruction. */ |
230 | static int asm_fusemadd(ASMState *as, IRIns *ir, PPCIns pi, PPCIns pir) | 231 | static int asm_fusemadd(ASMState *as, IRIns *ir, PPCIns pi, PPCIns pir) |
231 | { | 232 | { |
@@ -245,6 +246,7 @@ static int asm_fusemadd(ASMState *as, IRIns *ir, PPCIns pi, PPCIns pir) | |||
245 | } | 246 | } |
246 | return 0; | 247 | return 0; |
247 | } | 248 | } |
249 | #endif | ||
248 | 250 | ||
249 | /* -- Calls --------------------------------------------------------------- */ | 251 | /* -- Calls --------------------------------------------------------------- */ |
250 | 252 | ||
@@ -253,13 +255,17 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | |||
253 | { | 255 | { |
254 | uint32_t n, nargs = CCI_XNARGS(ci); | 256 | uint32_t n, nargs = CCI_XNARGS(ci); |
255 | int32_t ofs = 8; | 257 | int32_t ofs = 8; |
256 | Reg gpr = REGARG_FIRSTGPR, fpr = REGARG_FIRSTFPR; | 258 | Reg gpr = REGARG_FIRSTGPR; |
259 | #if !LJ_SOFTFP | ||
260 | Reg fpr = REGARG_FIRSTFPR; | ||
261 | #endif | ||
257 | if ((void *)ci->func) | 262 | if ((void *)ci->func) |
258 | emit_call(as, (void *)ci->func); | 263 | emit_call(as, (void *)ci->func); |
259 | for (n = 0; n < nargs; n++) { /* Setup args. */ | 264 | for (n = 0; n < nargs; n++) { /* Setup args. */ |
260 | IRRef ref = args[n]; | 265 | IRRef ref = args[n]; |
261 | if (ref) { | 266 | if (ref) { |
262 | IRIns *ir = IR(ref); | 267 | IRIns *ir = IR(ref); |
268 | #if !LJ_SOFTFP | ||
263 | if (irt_isfp(ir->t)) { | 269 | if (irt_isfp(ir->t)) { |
264 | if (fpr <= REGARG_LASTFPR) { | 270 | if (fpr <= REGARG_LASTFPR) { |
265 | lua_assert(rset_test(as->freeset, fpr)); /* Already evicted. */ | 271 | lua_assert(rset_test(as->freeset, fpr)); /* Already evicted. */ |
@@ -271,7 +277,9 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | |||
271 | emit_spstore(as, ir, r, ofs); | 277 | emit_spstore(as, ir, r, ofs); |
272 | ofs += irt_isnum(ir->t) ? 8 : 4; | 278 | ofs += irt_isnum(ir->t) ? 8 : 4; |
273 | } | 279 | } |
274 | } else { | 280 | } else |
281 | #endif | ||
282 | { | ||
275 | if (gpr <= REGARG_LASTGPR) { | 283 | if (gpr <= REGARG_LASTGPR) { |
276 | lua_assert(rset_test(as->freeset, gpr)); /* Already evicted. */ | 284 | lua_assert(rset_test(as->freeset, gpr)); /* Already evicted. */ |
277 | ra_leftov(as, gpr, ref); | 285 | ra_leftov(as, gpr, ref); |
@@ -290,8 +298,10 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | |||
290 | } | 298 | } |
291 | checkmclim(as); | 299 | checkmclim(as); |
292 | } | 300 | } |
301 | #if !LJ_SOFTFP | ||
293 | if ((ci->flags & CCI_VARARG)) /* Vararg calls need to know about FPR use. */ | 302 | if ((ci->flags & CCI_VARARG)) /* Vararg calls need to know about FPR use. */ |
294 | emit_tab(as, fpr == REGARG_FIRSTFPR ? PPCI_CRXOR : PPCI_CREQV, 6, 6, 6); | 303 | emit_tab(as, fpr == REGARG_FIRSTFPR ? PPCI_CRXOR : PPCI_CREQV, 6, 6, 6); |
304 | #endif | ||
295 | } | 305 | } |
296 | 306 | ||
297 | /* Setup result reg/sp for call. Evict scratch regs. */ | 307 | /* Setup result reg/sp for call. Evict scratch regs. */ |
@@ -299,8 +309,10 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) | |||
299 | { | 309 | { |
300 | RegSet drop = RSET_SCRATCH; | 310 | RegSet drop = RSET_SCRATCH; |
301 | int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t)); | 311 | int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t)); |
312 | #if !LJ_SOFTFP | ||
302 | if ((ci->flags & CCI_NOFPRCLOBBER)) | 313 | if ((ci->flags & CCI_NOFPRCLOBBER)) |
303 | drop &= ~RSET_FPR; | 314 | drop &= ~RSET_FPR; |
315 | #endif | ||
304 | if (ra_hasreg(ir->r)) | 316 | if (ra_hasreg(ir->r)) |
305 | rset_clear(drop, ir->r); /* Dest reg handled below. */ | 317 | rset_clear(drop, ir->r); /* Dest reg handled below. */ |
306 | if (hiop && ra_hasreg((ir+1)->r)) | 318 | if (hiop && ra_hasreg((ir+1)->r)) |
@@ -308,7 +320,7 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) | |||
308 | ra_evictset(as, drop); /* Evictions must be performed first. */ | 320 | ra_evictset(as, drop); /* Evictions must be performed first. */ |
309 | if (ra_used(ir)) { | 321 | if (ra_used(ir)) { |
310 | lua_assert(!irt_ispri(ir->t)); | 322 | lua_assert(!irt_ispri(ir->t)); |
311 | if (irt_isfp(ir->t)) { | 323 | if (!LJ_SOFTFP && irt_isfp(ir->t)) { |
312 | if ((ci->flags & CCI_CASTU64)) { | 324 | if ((ci->flags & CCI_CASTU64)) { |
313 | /* Use spill slot or temp slots. */ | 325 | /* Use spill slot or temp slots. */ |
314 | int32_t ofs = ir->s ? sps_scale(ir->s) : SPOFS_TMP; | 326 | int32_t ofs = ir->s ? sps_scale(ir->s) : SPOFS_TMP; |
@@ -377,6 +389,7 @@ static void asm_retf(ASMState *as, IRIns *ir) | |||
377 | 389 | ||
378 | /* -- Type conversions ---------------------------------------------------- */ | 390 | /* -- Type conversions ---------------------------------------------------- */ |
379 | 391 | ||
392 | #if !LJ_SOFTFP | ||
380 | static void asm_tointg(ASMState *as, IRIns *ir, Reg left) | 393 | static void asm_tointg(ASMState *as, IRIns *ir, Reg left) |
381 | { | 394 | { |
382 | RegSet allow = RSET_FPR; | 395 | RegSet allow = RSET_FPR; |
@@ -409,15 +422,23 @@ static void asm_tobit(ASMState *as, IRIns *ir) | |||
409 | emit_fai(as, PPCI_STFD, tmp, RID_SP, SPOFS_TMP); | 422 | emit_fai(as, PPCI_STFD, tmp, RID_SP, SPOFS_TMP); |
410 | emit_fab(as, PPCI_FADD, tmp, left, right); | 423 | emit_fab(as, PPCI_FADD, tmp, left, right); |
411 | } | 424 | } |
425 | #endif | ||
412 | 426 | ||
413 | static void asm_conv(ASMState *as, IRIns *ir) | 427 | static void asm_conv(ASMState *as, IRIns *ir) |
414 | { | 428 | { |
415 | IRType st = (IRType)(ir->op2 & IRCONV_SRCMASK); | 429 | IRType st = (IRType)(ir->op2 & IRCONV_SRCMASK); |
430 | #if !LJ_SOFTFP | ||
416 | int stfp = (st == IRT_NUM || st == IRT_FLOAT); | 431 | int stfp = (st == IRT_NUM || st == IRT_FLOAT); |
432 | #endif | ||
417 | IRRef lref = ir->op1; | 433 | IRRef lref = ir->op1; |
418 | lua_assert(irt_type(ir->t) != st); | ||
419 | lua_assert(!(irt_isint64(ir->t) || | 434 | lua_assert(!(irt_isint64(ir->t) || |
420 | (st == IRT_I64 || st == IRT_U64))); /* Handled by SPLIT. */ | 435 | (st == IRT_I64 || st == IRT_U64))); /* Handled by SPLIT. */ |
436 | #if LJ_SOFTFP | ||
437 | /* FP conversions are handled by SPLIT. */ | ||
438 | lua_assert(!irt_isfp(ir->t) && !(st == IRT_NUM || st == IRT_FLOAT)); | ||
439 | /* Can't check for same types: SPLIT uses CONV int.int + BXOR for sfp NEG. */ | ||
440 | #else | ||
441 | lua_assert(irt_type(ir->t) != st); | ||
421 | if (irt_isfp(ir->t)) { | 442 | if (irt_isfp(ir->t)) { |
422 | Reg dest = ra_dest(as, ir, RSET_FPR); | 443 | Reg dest = ra_dest(as, ir, RSET_FPR); |
423 | if (stfp) { /* FP to FP conversion. */ | 444 | if (stfp) { /* FP to FP conversion. */ |
@@ -476,7 +497,9 @@ static void asm_conv(ASMState *as, IRIns *ir) | |||
476 | emit_fb(as, PPCI_FCTIWZ, tmp, left); | 497 | emit_fb(as, PPCI_FCTIWZ, tmp, left); |
477 | } | 498 | } |
478 | } | 499 | } |
479 | } else { | 500 | } else |
501 | #endif | ||
502 | { | ||
480 | Reg dest = ra_dest(as, ir, RSET_GPR); | 503 | Reg dest = ra_dest(as, ir, RSET_GPR); |
481 | if (st >= IRT_I8 && st <= IRT_U16) { /* Extend to 32 bit integer. */ | 504 | if (st >= IRT_I8 && st <= IRT_U16) { /* Extend to 32 bit integer. */ |
482 | Reg left = ra_alloc1(as, ir->op1, RSET_GPR); | 505 | Reg left = ra_alloc1(as, ir->op1, RSET_GPR); |
@@ -496,17 +519,41 @@ static void asm_strto(ASMState *as, IRIns *ir) | |||
496 | { | 519 | { |
497 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_strscan_num]; | 520 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_strscan_num]; |
498 | IRRef args[2]; | 521 | IRRef args[2]; |
499 | int32_t ofs; | 522 | int32_t ofs = SPOFS_TMP; |
523 | #if LJ_SOFTFP | ||
524 | ra_evictset(as, RSET_SCRATCH); | ||
525 | if (ra_used(ir)) { | ||
526 | if (ra_hasspill(ir->s) && ra_hasspill((ir+1)->s) && | ||
527 | (ir->s & 1) == LJ_BE && (ir->s ^ 1) == (ir+1)->s) { | ||
528 | int i; | ||
529 | for (i = 0; i < 2; i++) { | ||
530 | Reg r = (ir+i)->r; | ||
531 | if (ra_hasreg(r)) { | ||
532 | ra_free(as, r); | ||
533 | ra_modified(as, r); | ||
534 | emit_spload(as, ir+i, r, sps_scale((ir+i)->s)); | ||
535 | } | ||
536 | } | ||
537 | ofs = sps_scale(ir->s & ~1); | ||
538 | } else { | ||
539 | Reg rhi = ra_dest(as, ir+1, RSET_GPR); | ||
540 | Reg rlo = ra_dest(as, ir, rset_exclude(RSET_GPR, rhi)); | ||
541 | emit_tai(as, PPCI_LWZ, rhi, RID_SP, ofs); | ||
542 | emit_tai(as, PPCI_LWZ, rlo, RID_SP, ofs+4); | ||
543 | } | ||
544 | } | ||
545 | #else | ||
500 | RegSet drop = RSET_SCRATCH; | 546 | RegSet drop = RSET_SCRATCH; |
501 | if (ra_hasreg(ir->r)) rset_set(drop, ir->r); /* Spill dest reg (if any). */ | 547 | if (ra_hasreg(ir->r)) rset_set(drop, ir->r); /* Spill dest reg (if any). */ |
502 | ra_evictset(as, drop); | 548 | ra_evictset(as, drop); |
549 | if (ir->s) ofs = sps_scale(ir->s); | ||
550 | #endif | ||
503 | asm_guardcc(as, CC_EQ); | 551 | asm_guardcc(as, CC_EQ); |
504 | emit_ai(as, PPCI_CMPWI, RID_RET, 0); /* Test return status. */ | 552 | emit_ai(as, PPCI_CMPWI, RID_RET, 0); /* Test return status. */ |
505 | args[0] = ir->op1; /* GCstr *str */ | 553 | args[0] = ir->op1; /* GCstr *str */ |
506 | args[1] = ASMREF_TMP1; /* TValue *n */ | 554 | args[1] = ASMREF_TMP1; /* TValue *n */ |
507 | asm_gencall(as, ci, args); | 555 | asm_gencall(as, ci, args); |
508 | /* Store the result to the spill slot or temp slots. */ | 556 | /* Store the result to the spill slot or temp slots. */ |
509 | ofs = ir->s ? sps_scale(ir->s) : SPOFS_TMP; | ||
510 | emit_tai(as, PPCI_ADDI, ra_releasetmp(as, ASMREF_TMP1), RID_SP, ofs); | 557 | emit_tai(as, PPCI_ADDI, ra_releasetmp(as, ASMREF_TMP1), RID_SP, ofs); |
511 | } | 558 | } |
512 | 559 | ||
@@ -530,7 +577,10 @@ static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) | |||
530 | Reg src = ra_alloc1(as, ref, allow); | 577 | Reg src = ra_alloc1(as, ref, allow); |
531 | emit_setgl(as, src, tmptv.gcr); | 578 | emit_setgl(as, src, tmptv.gcr); |
532 | } | 579 | } |
533 | type = ra_allock(as, irt_toitype(ir->t), allow); | 580 | if (LJ_SOFTFP && (ir+1)->o == IR_HIOP) |
581 | type = ra_alloc1(as, ref+1, allow); | ||
582 | else | ||
583 | type = ra_allock(as, irt_toitype(ir->t), allow); | ||
534 | emit_setgl(as, type, tmptv.it); | 584 | emit_setgl(as, type, tmptv.it); |
535 | } | 585 | } |
536 | } | 586 | } |
@@ -574,11 +624,27 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) | |||
574 | Reg tisnum = RID_NONE, tmpnum = RID_NONE; | 624 | Reg tisnum = RID_NONE, tmpnum = RID_NONE; |
575 | IRRef refkey = ir->op2; | 625 | IRRef refkey = ir->op2; |
576 | IRIns *irkey = IR(refkey); | 626 | IRIns *irkey = IR(refkey); |
627 | int isk = irref_isk(refkey); | ||
577 | IRType1 kt = irkey->t; | 628 | IRType1 kt = irkey->t; |
578 | uint32_t khash; | 629 | uint32_t khash; |
579 | MCLabel l_end, l_loop, l_next; | 630 | MCLabel l_end, l_loop, l_next; |
580 | 631 | ||
581 | rset_clear(allow, tab); | 632 | rset_clear(allow, tab); |
633 | #if LJ_SOFTFP | ||
634 | if (!isk) { | ||
635 | key = ra_alloc1(as, refkey, allow); | ||
636 | rset_clear(allow, key); | ||
637 | if (irkey[1].o == IR_HIOP) { | ||
638 | if (ra_hasreg((irkey+1)->r)) { | ||
639 | tmpnum = (irkey+1)->r; | ||
640 | ra_noweak(as, tmpnum); | ||
641 | } else { | ||
642 | tmpnum = ra_allocref(as, refkey+1, allow); | ||
643 | } | ||
644 | rset_clear(allow, tmpnum); | ||
645 | } | ||
646 | } | ||
647 | #else | ||
582 | if (irt_isnum(kt)) { | 648 | if (irt_isnum(kt)) { |
583 | key = ra_alloc1(as, refkey, RSET_FPR); | 649 | key = ra_alloc1(as, refkey, RSET_FPR); |
584 | tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key)); | 650 | tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key)); |
@@ -588,6 +654,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) | |||
588 | key = ra_alloc1(as, refkey, allow); | 654 | key = ra_alloc1(as, refkey, allow); |
589 | rset_clear(allow, key); | 655 | rset_clear(allow, key); |
590 | } | 656 | } |
657 | #endif | ||
591 | tmp2 = ra_scratch(as, allow); | 658 | tmp2 = ra_scratch(as, allow); |
592 | rset_clear(allow, tmp2); | 659 | rset_clear(allow, tmp2); |
593 | 660 | ||
@@ -610,7 +677,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) | |||
610 | asm_guardcc(as, CC_EQ); | 677 | asm_guardcc(as, CC_EQ); |
611 | else | 678 | else |
612 | emit_condbranch(as, PPCI_BC|PPCF_Y, CC_EQ, l_end); | 679 | emit_condbranch(as, PPCI_BC|PPCF_Y, CC_EQ, l_end); |
613 | if (irt_isnum(kt)) { | 680 | if (!LJ_SOFTFP && irt_isnum(kt)) { |
614 | emit_fab(as, PPCI_FCMPU, 0, tmpnum, key); | 681 | emit_fab(as, PPCI_FCMPU, 0, tmpnum, key); |
615 | emit_condbranch(as, PPCI_BC, CC_GE, l_next); | 682 | emit_condbranch(as, PPCI_BC, CC_GE, l_next); |
616 | emit_ab(as, PPCI_CMPLW, tmp1, tisnum); | 683 | emit_ab(as, PPCI_CMPLW, tmp1, tisnum); |
@@ -620,7 +687,10 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) | |||
620 | emit_ab(as, PPCI_CMPW, tmp2, key); | 687 | emit_ab(as, PPCI_CMPW, tmp2, key); |
621 | emit_condbranch(as, PPCI_BC, CC_NE, l_next); | 688 | emit_condbranch(as, PPCI_BC, CC_NE, l_next); |
622 | } | 689 | } |
623 | emit_ai(as, PPCI_CMPWI, tmp1, irt_toitype(irkey->t)); | 690 | if (LJ_SOFTFP && ra_hasreg(tmpnum)) |
691 | emit_ab(as, PPCI_CMPW, tmp1, tmpnum); | ||
692 | else | ||
693 | emit_ai(as, PPCI_CMPWI, tmp1, irt_toitype(irkey->t)); | ||
624 | if (!irt_ispri(kt)) | 694 | if (!irt_ispri(kt)) |
625 | emit_tai(as, PPCI_LWZ, tmp2, dest, (int32_t)offsetof(Node, key.gcr)); | 695 | emit_tai(as, PPCI_LWZ, tmp2, dest, (int32_t)offsetof(Node, key.gcr)); |
626 | } | 696 | } |
@@ -629,19 +699,19 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) | |||
629 | (((char *)as->mcp-(char *)l_loop) & 0xffffu); | 699 | (((char *)as->mcp-(char *)l_loop) & 0xffffu); |
630 | 700 | ||
631 | /* Load main position relative to tab->node into dest. */ | 701 | /* Load main position relative to tab->node into dest. */ |
632 | khash = irref_isk(refkey) ? ir_khash(irkey) : 1; | 702 | khash = isk ? ir_khash(irkey) : 1; |
633 | if (khash == 0) { | 703 | if (khash == 0) { |
634 | emit_tai(as, PPCI_LWZ, dest, tab, (int32_t)offsetof(GCtab, node)); | 704 | emit_tai(as, PPCI_LWZ, dest, tab, (int32_t)offsetof(GCtab, node)); |
635 | } else { | 705 | } else { |
636 | Reg tmphash = tmp1; | 706 | Reg tmphash = tmp1; |
637 | if (irref_isk(refkey)) | 707 | if (isk) |
638 | tmphash = ra_allock(as, khash, allow); | 708 | tmphash = ra_allock(as, khash, allow); |
639 | emit_tab(as, PPCI_ADD, dest, dest, tmp1); | 709 | emit_tab(as, PPCI_ADD, dest, dest, tmp1); |
640 | emit_tai(as, PPCI_MULLI, tmp1, tmp1, sizeof(Node)); | 710 | emit_tai(as, PPCI_MULLI, tmp1, tmp1, sizeof(Node)); |
641 | emit_asb(as, PPCI_AND, tmp1, tmp2, tmphash); | 711 | emit_asb(as, PPCI_AND, tmp1, tmp2, tmphash); |
642 | emit_tai(as, PPCI_LWZ, dest, tab, (int32_t)offsetof(GCtab, node)); | 712 | emit_tai(as, PPCI_LWZ, dest, tab, (int32_t)offsetof(GCtab, node)); |
643 | emit_tai(as, PPCI_LWZ, tmp2, tab, (int32_t)offsetof(GCtab, hmask)); | 713 | emit_tai(as, PPCI_LWZ, tmp2, tab, (int32_t)offsetof(GCtab, hmask)); |
644 | if (irref_isk(refkey)) { | 714 | if (isk) { |
645 | /* Nothing to do. */ | 715 | /* Nothing to do. */ |
646 | } else if (irt_isstr(kt)) { | 716 | } else if (irt_isstr(kt)) { |
647 | emit_tai(as, PPCI_LWZ, tmp1, key, (int32_t)offsetof(GCstr, hash)); | 717 | emit_tai(as, PPCI_LWZ, tmp1, key, (int32_t)offsetof(GCstr, hash)); |
@@ -651,13 +721,19 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) | |||
651 | emit_asb(as, PPCI_XOR, tmp1, tmp1, tmp2); | 721 | emit_asb(as, PPCI_XOR, tmp1, tmp1, tmp2); |
652 | emit_rotlwi(as, tmp1, tmp1, (HASH_ROT2+HASH_ROT1)&31); | 722 | emit_rotlwi(as, tmp1, tmp1, (HASH_ROT2+HASH_ROT1)&31); |
653 | emit_tab(as, PPCI_SUBF, tmp2, dest, tmp2); | 723 | emit_tab(as, PPCI_SUBF, tmp2, dest, tmp2); |
654 | if (irt_isnum(kt)) { | 724 | if (LJ_SOFTFP ? (irkey[1].o == IR_HIOP) : irt_isnum(kt)) { |
725 | #if LJ_SOFTFP | ||
726 | emit_asb(as, PPCI_XOR, tmp2, key, tmp1); | ||
727 | emit_rotlwi(as, dest, tmp1, HASH_ROT1); | ||
728 | emit_tab(as, PPCI_ADD, tmp1, tmpnum, tmpnum); | ||
729 | #else | ||
655 | int32_t ofs = ra_spill(as, irkey); | 730 | int32_t ofs = ra_spill(as, irkey); |
656 | emit_asb(as, PPCI_XOR, tmp2, tmp2, tmp1); | 731 | emit_asb(as, PPCI_XOR, tmp2, tmp2, tmp1); |
657 | emit_rotlwi(as, dest, tmp1, HASH_ROT1); | 732 | emit_rotlwi(as, dest, tmp1, HASH_ROT1); |
658 | emit_tab(as, PPCI_ADD, tmp1, tmp1, tmp1); | 733 | emit_tab(as, PPCI_ADD, tmp1, tmp1, tmp1); |
659 | emit_tai(as, PPCI_LWZ, tmp2, RID_SP, ofs+4); | 734 | emit_tai(as, PPCI_LWZ, tmp2, RID_SP, ofs+4); |
660 | emit_tai(as, PPCI_LWZ, tmp1, RID_SP, ofs); | 735 | emit_tai(as, PPCI_LWZ, tmp1, RID_SP, ofs); |
736 | #endif | ||
661 | } else { | 737 | } else { |
662 | emit_asb(as, PPCI_XOR, tmp2, key, tmp1); | 738 | emit_asb(as, PPCI_XOR, tmp2, key, tmp1); |
663 | emit_rotlwi(as, dest, tmp1, HASH_ROT1); | 739 | emit_rotlwi(as, dest, tmp1, HASH_ROT1); |
@@ -784,8 +860,8 @@ static PPCIns asm_fxloadins(IRIns *ir) | |||
784 | case IRT_U8: return PPCI_LBZ; | 860 | case IRT_U8: return PPCI_LBZ; |
785 | case IRT_I16: return PPCI_LHA; | 861 | case IRT_I16: return PPCI_LHA; |
786 | case IRT_U16: return PPCI_LHZ; | 862 | case IRT_U16: return PPCI_LHZ; |
787 | case IRT_NUM: return PPCI_LFD; | 863 | case IRT_NUM: lua_assert(!LJ_SOFTFP); return PPCI_LFD; |
788 | case IRT_FLOAT: return PPCI_LFS; | 864 | case IRT_FLOAT: if (!LJ_SOFTFP) return PPCI_LFS; |
789 | default: return PPCI_LWZ; | 865 | default: return PPCI_LWZ; |
790 | } | 866 | } |
791 | } | 867 | } |
@@ -795,8 +871,8 @@ static PPCIns asm_fxstoreins(IRIns *ir) | |||
795 | switch (irt_type(ir->t)) { | 871 | switch (irt_type(ir->t)) { |
796 | case IRT_I8: case IRT_U8: return PPCI_STB; | 872 | case IRT_I8: case IRT_U8: return PPCI_STB; |
797 | case IRT_I16: case IRT_U16: return PPCI_STH; | 873 | case IRT_I16: case IRT_U16: return PPCI_STH; |
798 | case IRT_NUM: return PPCI_STFD; | 874 | case IRT_NUM: lua_assert(!LJ_SOFTFP); return PPCI_STFD; |
799 | case IRT_FLOAT: return PPCI_STFS; | 875 | case IRT_FLOAT: if (!LJ_SOFTFP) return PPCI_STFS; |
800 | default: return PPCI_STW; | 876 | default: return PPCI_STW; |
801 | } | 877 | } |
802 | } | 878 | } |
@@ -839,7 +915,8 @@ static void asm_fstore(ASMState *as, IRIns *ir) | |||
839 | 915 | ||
840 | static void asm_xload(ASMState *as, IRIns *ir) | 916 | static void asm_xload(ASMState *as, IRIns *ir) |
841 | { | 917 | { |
842 | Reg dest = ra_dest(as, ir, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); | 918 | Reg dest = ra_dest(as, ir, |
919 | (!LJ_SOFTFP && irt_isfp(ir->t)) ? RSET_FPR : RSET_GPR); | ||
843 | lua_assert(!(ir->op2 & IRXLOAD_UNALIGNED)); | 920 | lua_assert(!(ir->op2 & IRXLOAD_UNALIGNED)); |
844 | if (irt_isi8(ir->t)) | 921 | if (irt_isi8(ir->t)) |
845 | emit_as(as, PPCI_EXTSB, dest, dest); | 922 | emit_as(as, PPCI_EXTSB, dest, dest); |
@@ -857,7 +934,8 @@ static void asm_xstore_(ASMState *as, IRIns *ir, int32_t ofs) | |||
857 | Reg src = ra_alloc1(as, irb->op1, RSET_GPR); | 934 | Reg src = ra_alloc1(as, irb->op1, RSET_GPR); |
858 | asm_fusexrefx(as, PPCI_STWBRX, src, ir->op1, rset_exclude(RSET_GPR, src)); | 935 | asm_fusexrefx(as, PPCI_STWBRX, src, ir->op1, rset_exclude(RSET_GPR, src)); |
859 | } else { | 936 | } else { |
860 | Reg src = ra_alloc1(as, ir->op2, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); | 937 | Reg src = ra_alloc1(as, ir->op2, |
938 | (!LJ_SOFTFP && irt_isfp(ir->t)) ? RSET_FPR : RSET_GPR); | ||
861 | asm_fusexref(as, asm_fxstoreins(ir), src, ir->op1, | 939 | asm_fusexref(as, asm_fxstoreins(ir), src, ir->op1, |
862 | rset_exclude(RSET_GPR, src), ofs); | 940 | rset_exclude(RSET_GPR, src), ofs); |
863 | } | 941 | } |
@@ -871,10 +949,19 @@ static void asm_ahuvload(ASMState *as, IRIns *ir) | |||
871 | Reg dest = RID_NONE, type = RID_TMP, tmp = RID_TMP, idx; | 949 | Reg dest = RID_NONE, type = RID_TMP, tmp = RID_TMP, idx; |
872 | RegSet allow = RSET_GPR; | 950 | RegSet allow = RSET_GPR; |
873 | int32_t ofs = AHUREF_LSX; | 951 | int32_t ofs = AHUREF_LSX; |
952 | if (LJ_SOFTFP && (ir+1)->o == IR_HIOP) { | ||
953 | t.irt = IRT_NUM; | ||
954 | if (ra_used(ir+1)) { | ||
955 | type = ra_dest(as, ir+1, allow); | ||
956 | rset_clear(allow, type); | ||
957 | } | ||
958 | ofs = 0; | ||
959 | } | ||
874 | if (ra_used(ir)) { | 960 | if (ra_used(ir)) { |
875 | lua_assert(irt_isnum(t) || irt_isint(t) || irt_isaddr(t)); | 961 | lua_assert((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) || |
876 | if (!irt_isnum(t)) ofs = 0; | 962 | irt_isint(ir->t) || irt_isaddr(ir->t)); |
877 | dest = ra_dest(as, ir, irt_isnum(t) ? RSET_FPR : RSET_GPR); | 963 | if (LJ_SOFTFP || !irt_isnum(t)) ofs = 0; |
964 | dest = ra_dest(as, ir, (!LJ_SOFTFP && irt_isnum(t)) ? RSET_FPR : allow); | ||
878 | rset_clear(allow, dest); | 965 | rset_clear(allow, dest); |
879 | } | 966 | } |
880 | idx = asm_fuseahuref(as, ir->op1, &ofs, allow); | 967 | idx = asm_fuseahuref(as, ir->op1, &ofs, allow); |
@@ -883,12 +970,13 @@ static void asm_ahuvload(ASMState *as, IRIns *ir) | |||
883 | asm_guardcc(as, CC_GE); | 970 | asm_guardcc(as, CC_GE); |
884 | emit_ab(as, PPCI_CMPLW, type, tisnum); | 971 | emit_ab(as, PPCI_CMPLW, type, tisnum); |
885 | if (ra_hasreg(dest)) { | 972 | if (ra_hasreg(dest)) { |
886 | if (ofs == AHUREF_LSX) { | 973 | if (!LJ_SOFTFP && ofs == AHUREF_LSX) { |
887 | tmp = ra_scratch(as, rset_exclude(rset_exclude(RSET_GPR, | 974 | tmp = ra_scratch(as, rset_exclude(rset_exclude(RSET_GPR, |
888 | (idx&255)), (idx>>8))); | 975 | (idx&255)), (idx>>8))); |
889 | emit_fab(as, PPCI_LFDX, dest, (idx&255), tmp); | 976 | emit_fab(as, PPCI_LFDX, dest, (idx&255), tmp); |
890 | } else { | 977 | } else { |
891 | emit_fai(as, PPCI_LFD, dest, idx, ofs); | 978 | emit_fai(as, LJ_SOFTFP ? PPCI_LWZ : PPCI_LFD, dest, idx, |
979 | ofs+4*LJ_SOFTFP); | ||
892 | } | 980 | } |
893 | } | 981 | } |
894 | } else { | 982 | } else { |
@@ -911,7 +999,7 @@ static void asm_ahustore(ASMState *as, IRIns *ir) | |||
911 | int32_t ofs = AHUREF_LSX; | 999 | int32_t ofs = AHUREF_LSX; |
912 | if (ir->r == RID_SINK) | 1000 | if (ir->r == RID_SINK) |
913 | return; | 1001 | return; |
914 | if (irt_isnum(ir->t)) { | 1002 | if (!LJ_SOFTFP && irt_isnum(ir->t)) { |
915 | src = ra_alloc1(as, ir->op2, RSET_FPR); | 1003 | src = ra_alloc1(as, ir->op2, RSET_FPR); |
916 | } else { | 1004 | } else { |
917 | if (!irt_ispri(ir->t)) { | 1005 | if (!irt_ispri(ir->t)) { |
@@ -919,11 +1007,14 @@ static void asm_ahustore(ASMState *as, IRIns *ir) | |||
919 | rset_clear(allow, src); | 1007 | rset_clear(allow, src); |
920 | ofs = 0; | 1008 | ofs = 0; |
921 | } | 1009 | } |
922 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); | 1010 | if (LJ_SOFTFP && (ir+1)->o == IR_HIOP) |
1011 | type = ra_alloc1(as, (ir+1)->op2, allow); | ||
1012 | else | ||
1013 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); | ||
923 | rset_clear(allow, type); | 1014 | rset_clear(allow, type); |
924 | } | 1015 | } |
925 | idx = asm_fuseahuref(as, ir->op1, &ofs, allow); | 1016 | idx = asm_fuseahuref(as, ir->op1, &ofs, allow); |
926 | if (irt_isnum(ir->t)) { | 1017 | if (!LJ_SOFTFP && irt_isnum(ir->t)) { |
927 | if (ofs == AHUREF_LSX) { | 1018 | if (ofs == AHUREF_LSX) { |
928 | emit_fab(as, PPCI_STFDX, src, (idx&255), RID_TMP); | 1019 | emit_fab(as, PPCI_STFDX, src, (idx&255), RID_TMP); |
929 | emit_slwi(as, RID_TMP, (idx>>8), 3); | 1020 | emit_slwi(as, RID_TMP, (idx>>8), 3); |
@@ -948,21 +1039,33 @@ static void asm_sload(ASMState *as, IRIns *ir) | |||
948 | IRType1 t = ir->t; | 1039 | IRType1 t = ir->t; |
949 | Reg dest = RID_NONE, type = RID_NONE, base; | 1040 | Reg dest = RID_NONE, type = RID_NONE, base; |
950 | RegSet allow = RSET_GPR; | 1041 | RegSet allow = RSET_GPR; |
1042 | int hiop = (LJ_SOFTFP && (ir+1)->o == IR_HIOP); | ||
1043 | if (hiop) | ||
1044 | t.irt = IRT_NUM; | ||
951 | lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */ | 1045 | lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */ |
952 | lua_assert(irt_isguard(t) || !(ir->op2 & IRSLOAD_TYPECHECK)); | 1046 | lua_assert(irt_isguard(ir->t) || !(ir->op2 & IRSLOAD_TYPECHECK)); |
953 | lua_assert(LJ_DUALNUM || | 1047 | lua_assert(LJ_DUALNUM || |
954 | !irt_isint(t) || (ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME))); | 1048 | !irt_isint(t) || (ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME))); |
1049 | #if LJ_SOFTFP | ||
1050 | lua_assert(!(ir->op2 & IRSLOAD_CONVERT)); /* Handled by LJ_SOFTFP SPLIT. */ | ||
1051 | if (hiop && ra_used(ir+1)) { | ||
1052 | type = ra_dest(as, ir+1, allow); | ||
1053 | rset_clear(allow, type); | ||
1054 | } | ||
1055 | #else | ||
955 | if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(t) && irt_isint(t)) { | 1056 | if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(t) && irt_isint(t)) { |
956 | dest = ra_scratch(as, RSET_FPR); | 1057 | dest = ra_scratch(as, RSET_FPR); |
957 | asm_tointg(as, ir, dest); | 1058 | asm_tointg(as, ir, dest); |
958 | t.irt = IRT_NUM; /* Continue with a regular number type check. */ | 1059 | t.irt = IRT_NUM; /* Continue with a regular number type check. */ |
959 | } else if (ra_used(ir)) { | 1060 | } else |
1061 | #endif | ||
1062 | if (ra_used(ir)) { | ||
960 | lua_assert(irt_isnum(t) || irt_isint(t) || irt_isaddr(t)); | 1063 | lua_assert(irt_isnum(t) || irt_isint(t) || irt_isaddr(t)); |
961 | dest = ra_dest(as, ir, irt_isnum(t) ? RSET_FPR : RSET_GPR); | 1064 | dest = ra_dest(as, ir, (!LJ_SOFTFP && irt_isnum(t)) ? RSET_FPR : allow); |
962 | rset_clear(allow, dest); | 1065 | rset_clear(allow, dest); |
963 | base = ra_alloc1(as, REF_BASE, allow); | 1066 | base = ra_alloc1(as, REF_BASE, allow); |
964 | rset_clear(allow, base); | 1067 | rset_clear(allow, base); |
965 | if ((ir->op2 & IRSLOAD_CONVERT)) { | 1068 | if (!LJ_SOFTFP && (ir->op2 & IRSLOAD_CONVERT)) { |
966 | if (irt_isint(t)) { | 1069 | if (irt_isint(t)) { |
967 | emit_tai(as, PPCI_LWZ, dest, RID_SP, SPOFS_TMPLO); | 1070 | emit_tai(as, PPCI_LWZ, dest, RID_SP, SPOFS_TMPLO); |
968 | dest = ra_scratch(as, RSET_FPR); | 1071 | dest = ra_scratch(as, RSET_FPR); |
@@ -994,10 +1097,13 @@ dotypecheck: | |||
994 | if ((ir->op2 & IRSLOAD_TYPECHECK)) { | 1097 | if ((ir->op2 & IRSLOAD_TYPECHECK)) { |
995 | Reg tisnum = ra_allock(as, (int32_t)LJ_TISNUM, allow); | 1098 | Reg tisnum = ra_allock(as, (int32_t)LJ_TISNUM, allow); |
996 | asm_guardcc(as, CC_GE); | 1099 | asm_guardcc(as, CC_GE); |
997 | emit_ab(as, PPCI_CMPLW, RID_TMP, tisnum); | 1100 | #if !LJ_SOFTFP |
998 | type = RID_TMP; | 1101 | type = RID_TMP; |
1102 | #endif | ||
1103 | emit_ab(as, PPCI_CMPLW, type, tisnum); | ||
999 | } | 1104 | } |
1000 | if (ra_hasreg(dest)) emit_fai(as, PPCI_LFD, dest, base, ofs-4); | 1105 | if (ra_hasreg(dest)) emit_fai(as, LJ_SOFTFP ? PPCI_LWZ : PPCI_LFD, dest, |
1106 | base, ofs-(LJ_SOFTFP?0:4)); | ||
1001 | } else { | 1107 | } else { |
1002 | if ((ir->op2 & IRSLOAD_TYPECHECK)) { | 1108 | if ((ir->op2 & IRSLOAD_TYPECHECK)) { |
1003 | asm_guardcc(as, CC_NE); | 1109 | asm_guardcc(as, CC_NE); |
@@ -1119,6 +1225,7 @@ static void asm_obar(ASMState *as, IRIns *ir) | |||
1119 | 1225 | ||
1120 | /* -- Arithmetic and logic operations ------------------------------------- */ | 1226 | /* -- Arithmetic and logic operations ------------------------------------- */ |
1121 | 1227 | ||
1228 | #if !LJ_SOFTFP | ||
1122 | static void asm_fparith(ASMState *as, IRIns *ir, PPCIns pi) | 1229 | static void asm_fparith(ASMState *as, IRIns *ir, PPCIns pi) |
1123 | { | 1230 | { |
1124 | Reg dest = ra_dest(as, ir, RSET_FPR); | 1231 | Reg dest = ra_dest(as, ir, RSET_FPR); |
@@ -1146,13 +1253,17 @@ static void asm_fpmath(ASMState *as, IRIns *ir) | |||
1146 | else | 1253 | else |
1147 | asm_callid(as, ir, IRCALL_lj_vm_floor + ir->op2); | 1254 | asm_callid(as, ir, IRCALL_lj_vm_floor + ir->op2); |
1148 | } | 1255 | } |
1256 | #endif | ||
1149 | 1257 | ||
1150 | static void asm_add(ASMState *as, IRIns *ir) | 1258 | static void asm_add(ASMState *as, IRIns *ir) |
1151 | { | 1259 | { |
1260 | #if !LJ_SOFTFP | ||
1152 | if (irt_isnum(ir->t)) { | 1261 | if (irt_isnum(ir->t)) { |
1153 | if (!asm_fusemadd(as, ir, PPCI_FMADD, PPCI_FMADD)) | 1262 | if (!asm_fusemadd(as, ir, PPCI_FMADD, PPCI_FMADD)) |
1154 | asm_fparith(as, ir, PPCI_FADD); | 1263 | asm_fparith(as, ir, PPCI_FADD); |
1155 | } else { | 1264 | } else |
1265 | #endif | ||
1266 | { | ||
1156 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1267 | Reg dest = ra_dest(as, ir, RSET_GPR); |
1157 | Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); | 1268 | Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); |
1158 | PPCIns pi; | 1269 | PPCIns pi; |
@@ -1191,10 +1302,13 @@ static void asm_add(ASMState *as, IRIns *ir) | |||
1191 | 1302 | ||
1192 | static void asm_sub(ASMState *as, IRIns *ir) | 1303 | static void asm_sub(ASMState *as, IRIns *ir) |
1193 | { | 1304 | { |
1305 | #if !LJ_SOFTFP | ||
1194 | if (irt_isnum(ir->t)) { | 1306 | if (irt_isnum(ir->t)) { |
1195 | if (!asm_fusemadd(as, ir, PPCI_FMSUB, PPCI_FNMSUB)) | 1307 | if (!asm_fusemadd(as, ir, PPCI_FMSUB, PPCI_FNMSUB)) |
1196 | asm_fparith(as, ir, PPCI_FSUB); | 1308 | asm_fparith(as, ir, PPCI_FSUB); |
1197 | } else { | 1309 | } else |
1310 | #endif | ||
1311 | { | ||
1198 | PPCIns pi = PPCI_SUBF; | 1312 | PPCIns pi = PPCI_SUBF; |
1199 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1313 | Reg dest = ra_dest(as, ir, RSET_GPR); |
1200 | Reg left, right; | 1314 | Reg left, right; |
@@ -1220,9 +1334,12 @@ static void asm_sub(ASMState *as, IRIns *ir) | |||
1220 | 1334 | ||
1221 | static void asm_mul(ASMState *as, IRIns *ir) | 1335 | static void asm_mul(ASMState *as, IRIns *ir) |
1222 | { | 1336 | { |
1337 | #if !LJ_SOFTFP | ||
1223 | if (irt_isnum(ir->t)) { | 1338 | if (irt_isnum(ir->t)) { |
1224 | asm_fparith(as, ir, PPCI_FMUL); | 1339 | asm_fparith(as, ir, PPCI_FMUL); |
1225 | } else { | 1340 | } else |
1341 | #endif | ||
1342 | { | ||
1226 | PPCIns pi = PPCI_MULLW; | 1343 | PPCIns pi = PPCI_MULLW; |
1227 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1344 | Reg dest = ra_dest(as, ir, RSET_GPR); |
1228 | Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); | 1345 | Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); |
@@ -1250,9 +1367,12 @@ static void asm_mul(ASMState *as, IRIns *ir) | |||
1250 | 1367 | ||
1251 | static void asm_neg(ASMState *as, IRIns *ir) | 1368 | static void asm_neg(ASMState *as, IRIns *ir) |
1252 | { | 1369 | { |
1370 | #if !LJ_SOFTFP | ||
1253 | if (irt_isnum(ir->t)) { | 1371 | if (irt_isnum(ir->t)) { |
1254 | asm_fpunary(as, ir, PPCI_FNEG); | 1372 | asm_fpunary(as, ir, PPCI_FNEG); |
1255 | } else { | 1373 | } else |
1374 | #endif | ||
1375 | { | ||
1256 | Reg dest, left; | 1376 | Reg dest, left; |
1257 | PPCIns pi = PPCI_NEG; | 1377 | PPCIns pi = PPCI_NEG; |
1258 | if (as->flagmcp == as->mcp) { | 1378 | if (as->flagmcp == as->mcp) { |
@@ -1563,9 +1683,40 @@ static void asm_bitshift(ASMState *as, IRIns *ir, PPCIns pi, PPCIns pik) | |||
1563 | PPCI_RLWINM|PPCF_MB(0)|PPCF_ME(31)) | 1683 | PPCI_RLWINM|PPCF_MB(0)|PPCF_ME(31)) |
1564 | #define asm_bror(as, ir) lua_assert(0) | 1684 | #define asm_bror(as, ir) lua_assert(0) |
1565 | 1685 | ||
1686 | #if LJ_SOFTFP | ||
1687 | static void asm_sfpmin_max(ASMState *as, IRIns *ir) | ||
1688 | { | ||
1689 | CCallInfo ci = lj_ir_callinfo[IRCALL_softfp_cmp]; | ||
1690 | IRRef args[4]; | ||
1691 | MCLabel l_right, l_end; | ||
1692 | Reg desthi = ra_dest(as, ir, RSET_GPR), destlo = ra_dest(as, ir+1, RSET_GPR); | ||
1693 | Reg righthi, lefthi = ra_alloc2(as, ir, RSET_GPR); | ||
1694 | Reg rightlo, leftlo = ra_alloc2(as, ir+1, RSET_GPR); | ||
1695 | PPCCC cond = (IROp)ir->o == IR_MIN ? CC_EQ : CC_NE; | ||
1696 | righthi = (lefthi >> 8); lefthi &= 255; | ||
1697 | rightlo = (leftlo >> 8); leftlo &= 255; | ||
1698 | args[0^LJ_BE] = ir->op1; args[1^LJ_BE] = (ir+1)->op1; | ||
1699 | args[2^LJ_BE] = ir->op2; args[3^LJ_BE] = (ir+1)->op2; | ||
1700 | l_end = emit_label(as); | ||
1701 | if (desthi != righthi) emit_mr(as, desthi, righthi); | ||
1702 | if (destlo != rightlo) emit_mr(as, destlo, rightlo); | ||
1703 | l_right = emit_label(as); | ||
1704 | if (l_end != l_right) emit_jmp(as, l_end); | ||
1705 | if (desthi != lefthi) emit_mr(as, desthi, lefthi); | ||
1706 | if (destlo != leftlo) emit_mr(as, destlo, leftlo); | ||
1707 | if (l_right == as->mcp+1) { | ||
1708 | cond ^= 4; l_right = l_end; ++as->mcp; | ||
1709 | } | ||
1710 | emit_condbranch(as, PPCI_BC, cond, l_right); | ||
1711 | ra_evictset(as, RSET_SCRATCH); | ||
1712 | emit_cmpi(as, RID_RET, 1); | ||
1713 | asm_gencall(as, &ci, args); | ||
1714 | } | ||
1715 | #endif | ||
1716 | |||
1566 | static void asm_min_max(ASMState *as, IRIns *ir, int ismax) | 1717 | static void asm_min_max(ASMState *as, IRIns *ir, int ismax) |
1567 | { | 1718 | { |
1568 | if (irt_isnum(ir->t)) { | 1719 | if (!LJ_SOFTFP && irt_isnum(ir->t)) { |
1569 | Reg dest = ra_dest(as, ir, RSET_FPR); | 1720 | Reg dest = ra_dest(as, ir, RSET_FPR); |
1570 | Reg tmp = dest; | 1721 | Reg tmp = dest; |
1571 | Reg right, left = ra_alloc2(as, ir, RSET_FPR); | 1722 | Reg right, left = ra_alloc2(as, ir, RSET_FPR); |
@@ -1653,7 +1804,7 @@ static void asm_intcomp_(ASMState *as, IRRef lref, IRRef rref, Reg cr, PPCCC cc) | |||
1653 | static void asm_comp(ASMState *as, IRIns *ir) | 1804 | static void asm_comp(ASMState *as, IRIns *ir) |
1654 | { | 1805 | { |
1655 | PPCCC cc = asm_compmap[ir->o]; | 1806 | PPCCC cc = asm_compmap[ir->o]; |
1656 | if (irt_isnum(ir->t)) { | 1807 | if (!LJ_SOFTFP && irt_isnum(ir->t)) { |
1657 | Reg right, left = ra_alloc2(as, ir, RSET_FPR); | 1808 | Reg right, left = ra_alloc2(as, ir, RSET_FPR); |
1658 | right = (left >> 8); left &= 255; | 1809 | right = (left >> 8); left &= 255; |
1659 | asm_guardcc(as, (cc >> 4)); | 1810 | asm_guardcc(as, (cc >> 4)); |
@@ -1674,6 +1825,44 @@ static void asm_comp(ASMState *as, IRIns *ir) | |||
1674 | 1825 | ||
1675 | #define asm_equal(as, ir) asm_comp(as, ir) | 1826 | #define asm_equal(as, ir) asm_comp(as, ir) |
1676 | 1827 | ||
1828 | #if LJ_SOFTFP | ||
1829 | /* SFP comparisons. */ | ||
1830 | static void asm_sfpcomp(ASMState *as, IRIns *ir) | ||
1831 | { | ||
1832 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_softfp_cmp]; | ||
1833 | RegSet drop = RSET_SCRATCH; | ||
1834 | Reg r; | ||
1835 | IRRef args[4]; | ||
1836 | args[0^LJ_BE] = ir->op1; args[1^LJ_BE] = (ir+1)->op1; | ||
1837 | args[2^LJ_BE] = ir->op2; args[3^LJ_BE] = (ir+1)->op2; | ||
1838 | |||
1839 | for (r = REGARG_FIRSTGPR; r <= REGARG_FIRSTGPR+3; r++) { | ||
1840 | if (!rset_test(as->freeset, r) && | ||
1841 | regcost_ref(as->cost[r]) == args[r-REGARG_FIRSTGPR]) | ||
1842 | rset_clear(drop, r); | ||
1843 | } | ||
1844 | ra_evictset(as, drop); | ||
1845 | asm_setupresult(as, ir, ci); | ||
1846 | switch ((IROp)ir->o) { | ||
1847 | case IR_ULT: | ||
1848 | asm_guardcc(as, CC_EQ); | ||
1849 | emit_ai(as, PPCI_CMPWI, RID_RET, 0); | ||
1850 | case IR_ULE: | ||
1851 | asm_guardcc(as, CC_EQ); | ||
1852 | emit_ai(as, PPCI_CMPWI, RID_RET, 1); | ||
1853 | break; | ||
1854 | case IR_GE: case IR_GT: | ||
1855 | asm_guardcc(as, CC_EQ); | ||
1856 | emit_ai(as, PPCI_CMPWI, RID_RET, 2); | ||
1857 | default: | ||
1858 | asm_guardcc(as, (asm_compmap[ir->o] & 0xf)); | ||
1859 | emit_ai(as, PPCI_CMPWI, RID_RET, 0); | ||
1860 | break; | ||
1861 | } | ||
1862 | asm_gencall(as, ci, args); | ||
1863 | } | ||
1864 | #endif | ||
1865 | |||
1677 | #if LJ_HASFFI | 1866 | #if LJ_HASFFI |
1678 | /* 64 bit integer comparisons. */ | 1867 | /* 64 bit integer comparisons. */ |
1679 | static void asm_comp64(ASMState *as, IRIns *ir) | 1868 | static void asm_comp64(ASMState *as, IRIns *ir) |
@@ -1703,19 +1892,36 @@ static void asm_comp64(ASMState *as, IRIns *ir) | |||
1703 | /* Hiword op of a split 64 bit op. Previous op must be the loword op. */ | 1892 | /* Hiword op of a split 64 bit op. Previous op must be the loword op. */ |
1704 | static void asm_hiop(ASMState *as, IRIns *ir) | 1893 | static void asm_hiop(ASMState *as, IRIns *ir) |
1705 | { | 1894 | { |
1706 | #if LJ_HASFFI | 1895 | #if LJ_HASFFI || LJ_SOFTFP |
1707 | /* HIOP is marked as a store because it needs its own DCE logic. */ | 1896 | /* HIOP is marked as a store because it needs its own DCE logic. */ |
1708 | int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */ | 1897 | int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */ |
1709 | if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1; | 1898 | if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1; |
1710 | if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */ | 1899 | if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */ |
1711 | as->curins--; /* Always skip the CONV. */ | 1900 | as->curins--; /* Always skip the CONV. */ |
1901 | #if LJ_HASFFI && !LJ_SOFTFP | ||
1712 | if (usehi || uselo) | 1902 | if (usehi || uselo) |
1713 | asm_conv64(as, ir); | 1903 | asm_conv64(as, ir); |
1714 | return; | 1904 | return; |
1905 | #endif | ||
1715 | } else if ((ir-1)->o <= IR_NE) { /* 64 bit integer comparisons. ORDER IR. */ | 1906 | } else if ((ir-1)->o <= IR_NE) { /* 64 bit integer comparisons. ORDER IR. */ |
1716 | as->curins--; /* Always skip the loword comparison. */ | 1907 | as->curins--; /* Always skip the loword comparison. */ |
1908 | #if LJ_SOFTFP | ||
1909 | if (!irt_isint(ir->t)) { | ||
1910 | asm_sfpcomp(as, ir-1); | ||
1911 | return; | ||
1912 | } | ||
1913 | #endif | ||
1914 | #if LJ_HASFFI | ||
1717 | asm_comp64(as, ir); | 1915 | asm_comp64(as, ir); |
1916 | #endif | ||
1917 | return; | ||
1918 | #if LJ_SOFTFP | ||
1919 | } else if ((ir-1)->o == IR_MIN || (ir-1)->o == IR_MAX) { | ||
1920 | as->curins--; /* Always skip the loword min/max. */ | ||
1921 | if (uselo || usehi) | ||
1922 | asm_sfpmin_max(as, ir-1); | ||
1718 | return; | 1923 | return; |
1924 | #endif | ||
1719 | } else if ((ir-1)->o == IR_XSTORE) { | 1925 | } else if ((ir-1)->o == IR_XSTORE) { |
1720 | as->curins--; /* Handle both stores here. */ | 1926 | as->curins--; /* Handle both stores here. */ |
1721 | if ((ir-1)->r != RID_SINK) { | 1927 | if ((ir-1)->r != RID_SINK) { |
@@ -1726,14 +1932,27 @@ static void asm_hiop(ASMState *as, IRIns *ir) | |||
1726 | } | 1932 | } |
1727 | if (!usehi) return; /* Skip unused hiword op for all remaining ops. */ | 1933 | if (!usehi) return; /* Skip unused hiword op for all remaining ops. */ |
1728 | switch ((ir-1)->o) { | 1934 | switch ((ir-1)->o) { |
1935 | #if LJ_HASFFI | ||
1729 | case IR_ADD: as->curins--; asm_add64(as, ir); break; | 1936 | case IR_ADD: as->curins--; asm_add64(as, ir); break; |
1730 | case IR_SUB: as->curins--; asm_sub64(as, ir); break; | 1937 | case IR_SUB: as->curins--; asm_sub64(as, ir); break; |
1731 | case IR_NEG: as->curins--; asm_neg64(as, ir); break; | 1938 | case IR_NEG: as->curins--; asm_neg64(as, ir); break; |
1939 | #endif | ||
1940 | #if LJ_SOFTFP | ||
1941 | case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD: | ||
1942 | case IR_STRTO: | ||
1943 | if (!uselo) | ||
1944 | ra_allocref(as, ir->op1, RSET_GPR); /* Mark lo op as used. */ | ||
1945 | break; | ||
1946 | #endif | ||
1732 | case IR_CALLN: | 1947 | case IR_CALLN: |
1948 | case IR_CALLS: | ||
1733 | case IR_CALLXS: | 1949 | case IR_CALLXS: |
1734 | if (!uselo) | 1950 | if (!uselo) |
1735 | ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ | 1951 | ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ |
1736 | break; | 1952 | break; |
1953 | #if LJ_SOFTFP | ||
1954 | case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: | ||
1955 | #endif | ||
1737 | case IR_CNEWI: | 1956 | case IR_CNEWI: |
1738 | /* Nothing to do here. Handled by lo op itself. */ | 1957 | /* Nothing to do here. Handled by lo op itself. */ |
1739 | break; | 1958 | break; |
@@ -1797,8 +2016,19 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap) | |||
1797 | if ((sn & SNAP_NORESTORE)) | 2016 | if ((sn & SNAP_NORESTORE)) |
1798 | continue; | 2017 | continue; |
1799 | if (irt_isnum(ir->t)) { | 2018 | if (irt_isnum(ir->t)) { |
2019 | #if LJ_SOFTFP | ||
2020 | Reg tmp; | ||
2021 | RegSet allow = rset_exclude(RSET_GPR, RID_BASE); | ||
2022 | lua_assert(irref_isk(ref)); /* LJ_SOFTFP: must be a number constant. */ | ||
2023 | tmp = ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, allow); | ||
2024 | emit_tai(as, PPCI_STW, tmp, RID_BASE, ofs+(LJ_BE?4:0)); | ||
2025 | if (rset_test(as->freeset, tmp+1)) allow = RID2RSET(tmp+1); | ||
2026 | tmp = ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, allow); | ||
2027 | emit_tai(as, PPCI_STW, tmp, RID_BASE, ofs+(LJ_BE?0:4)); | ||
2028 | #else | ||
1800 | Reg src = ra_alloc1(as, ref, RSET_FPR); | 2029 | Reg src = ra_alloc1(as, ref, RSET_FPR); |
1801 | emit_fai(as, PPCI_STFD, src, RID_BASE, ofs); | 2030 | emit_fai(as, PPCI_STFD, src, RID_BASE, ofs); |
2031 | #endif | ||
1802 | } else { | 2032 | } else { |
1803 | Reg type; | 2033 | Reg type; |
1804 | RegSet allow = rset_exclude(RSET_GPR, RID_BASE); | 2034 | RegSet allow = rset_exclude(RSET_GPR, RID_BASE); |
@@ -1811,6 +2041,10 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap) | |||
1811 | if ((sn & (SNAP_CONT|SNAP_FRAME))) { | 2041 | if ((sn & (SNAP_CONT|SNAP_FRAME))) { |
1812 | if (s == 0) continue; /* Do not overwrite link to previous frame. */ | 2042 | if (s == 0) continue; /* Do not overwrite link to previous frame. */ |
1813 | type = ra_allock(as, (int32_t)(*flinks--), allow); | 2043 | type = ra_allock(as, (int32_t)(*flinks--), allow); |
2044 | #if LJ_SOFTFP | ||
2045 | } else if ((sn & SNAP_SOFTFPNUM)) { | ||
2046 | type = ra_alloc1(as, ref+1, rset_exclude(RSET_GPR, RID_BASE)); | ||
2047 | #endif | ||
1814 | } else { | 2048 | } else { |
1815 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); | 2049 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); |
1816 | } | 2050 | } |
@@ -1947,14 +2181,15 @@ static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci) | |||
1947 | int nslots = 2, ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR; | 2181 | int nslots = 2, ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR; |
1948 | asm_collectargs(as, ir, ci, args); | 2182 | asm_collectargs(as, ir, ci, args); |
1949 | for (i = 0; i < nargs; i++) | 2183 | for (i = 0; i < nargs; i++) |
1950 | if (args[i] && irt_isfp(IR(args[i])->t)) { | 2184 | if (!LJ_SOFTFP && args[i] && irt_isfp(IR(args[i])->t)) { |
1951 | if (nfpr > 0) nfpr--; else nslots = (nslots+3) & ~1; | 2185 | if (nfpr > 0) nfpr--; else nslots = (nslots+3) & ~1; |
1952 | } else { | 2186 | } else { |
1953 | if (ngpr > 0) ngpr--; else nslots++; | 2187 | if (ngpr > 0) ngpr--; else nslots++; |
1954 | } | 2188 | } |
1955 | if (nslots > as->evenspill) /* Leave room for args in stack slots. */ | 2189 | if (nslots > as->evenspill) /* Leave room for args in stack slots. */ |
1956 | as->evenspill = nslots; | 2190 | as->evenspill = nslots; |
1957 | return irt_isfp(ir->t) ? REGSP_HINT(RID_FPRET) : REGSP_HINT(RID_RET); | 2191 | return (!LJ_SOFTFP && irt_isfp(ir->t)) ? REGSP_HINT(RID_FPRET) : |
2192 | REGSP_HINT(RID_RET); | ||
1958 | } | 2193 | } |
1959 | 2194 | ||
1960 | static void asm_setup_target(ASMState *as) | 2195 | static void asm_setup_target(ASMState *as) |