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 | |
parent | 825dcdc4d1e09c71ffc24565aefbb05a9cb3c2f4 (diff) | |
download | luajit-f547a1425e9db10eec59d586c94ba78b897497f6.tar.gz luajit-f547a1425e9db10eec59d586c94ba78b897497f6.tar.bz2 luajit-f547a1425e9db10eec59d586c94ba78b897497f6.zip |
MIPS: Add soft-float support to JIT compiler backend.
-rw-r--r-- | src/lj_arch.h | 3 | ||||
-rw-r--r-- | src/lj_asm_mips.h | 406 | ||||
-rw-r--r-- | src/lj_emit_mips.h | 10 | ||||
-rw-r--r-- | src/lj_ircall.h | 12 | ||||
-rw-r--r-- | src/lj_opt_split.c | 10 | ||||
-rw-r--r-- | src/lj_target_mips.h | 30 | ||||
-rw-r--r-- | src/vm_mips.dasc | 30 |
7 files changed, 418 insertions, 83 deletions
diff --git a/src/lj_arch.h b/src/lj_arch.h index 7096ad5e..3d27e4e3 100644 --- a/src/lj_arch.h +++ b/src/lj_arch.h | |||
@@ -305,9 +305,6 @@ | |||
305 | #endif | 305 | #endif |
306 | 306 | ||
307 | /* Temporarily disable features until the code has been merged. */ | 307 | /* Temporarily disable features until the code has been merged. */ |
308 | #if !LJ_ARCH_HASFPU | ||
309 | #define LJ_ARCH_NOJIT 1 | ||
310 | #endif | ||
311 | #if !defined(LUAJIT_NO_UNWIND) && __GNU_COMPACT_EH__ | 308 | #if !defined(LUAJIT_NO_UNWIND) && __GNU_COMPACT_EH__ |
312 | #define LUAJIT_NO_UNWIND 1 | 309 | #define LUAJIT_NO_UNWIND 1 |
313 | #endif | 310 | #endif |
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; |
diff --git a/src/lj_emit_mips.h b/src/lj_emit_mips.h index 8e7ee66f..f3db918f 100644 --- a/src/lj_emit_mips.h +++ b/src/lj_emit_mips.h | |||
@@ -152,16 +152,18 @@ static void emit_jmp(ASMState *as, MCode *target) | |||
152 | emit_branch(as, MIPSI_B, RID_ZERO, RID_ZERO, (target)); | 152 | emit_branch(as, MIPSI_B, RID_ZERO, RID_ZERO, (target)); |
153 | } | 153 | } |
154 | 154 | ||
155 | static void emit_call(ASMState *as, void *target) | 155 | static void emit_call(ASMState *as, void *target, int needcfa) |
156 | { | 156 | { |
157 | MCode *p = as->mcp; | 157 | MCode *p = as->mcp; |
158 | *--p = MIPSI_NOP; | 158 | *--p = MIPSI_NOP; |
159 | if ((((uintptr_t)target ^ (uintptr_t)p) >> 28) == 0) | 159 | if ((((uintptr_t)target ^ (uintptr_t)p) >> 28) == 0) { |
160 | *--p = MIPSI_JAL | (((uintptr_t)target >>2) & 0x03ffffffu); | 160 | *--p = MIPSI_JAL | (((uintptr_t)target >>2) & 0x03ffffffu); |
161 | else /* Target out of range: need indirect call. */ | 161 | } else { /* Target out of range: need indirect call. */ |
162 | *--p = MIPSI_JALR | MIPSF_S(RID_CFUNCADDR); | 162 | *--p = MIPSI_JALR | MIPSF_S(RID_CFUNCADDR); |
163 | needcfa = 1; | ||
164 | } | ||
163 | as->mcp = p; | 165 | as->mcp = p; |
164 | ra_allockreg(as, i32ptr(target), RID_CFUNCADDR); | 166 | if (needcfa) ra_allockreg(as, i32ptr(target), RID_CFUNCADDR); |
165 | } | 167 | } |
166 | 168 | ||
167 | /* -- Emit generic operations --------------------------------------------- */ | 169 | /* -- Emit generic operations --------------------------------------------- */ |
diff --git a/src/lj_ircall.h b/src/lj_ircall.h index 1f44b03d..53f38eeb 100644 --- a/src/lj_ircall.h +++ b/src/lj_ircall.h | |||
@@ -78,6 +78,12 @@ typedef struct CCallInfo { | |||
78 | #define IRCALLCOND_SOFTFP_FFI(x) NULL | 78 | #define IRCALLCOND_SOFTFP_FFI(x) NULL |
79 | #endif | 79 | #endif |
80 | 80 | ||
81 | #if LJ_SOFTFP && LJ_TARGET_MIPS | ||
82 | #define IRCALLCOND_SOFTFP_MIPS(x) x | ||
83 | #else | ||
84 | #define IRCALLCOND_SOFTFP_MIPS(x) NULL | ||
85 | #endif | ||
86 | |||
81 | #define LJ_NEED_FP64 (LJ_TARGET_ARM || LJ_TARGET_PPC || LJ_TARGET_MIPS) | 87 | #define LJ_NEED_FP64 (LJ_TARGET_ARM || LJ_TARGET_PPC || LJ_TARGET_MIPS) |
82 | 88 | ||
83 | #if LJ_HASFFI && (LJ_SOFTFP || LJ_NEED_FP64) | 89 | #if LJ_HASFFI && (LJ_SOFTFP || LJ_NEED_FP64) |
@@ -189,6 +195,8 @@ typedef struct CCallInfo { | |||
189 | _(SOFTFP, softfp_cmp, 4, N, NIL, 0) \ | 195 | _(SOFTFP, softfp_cmp, 4, N, NIL, 0) \ |
190 | _(SOFTFP, softfp_i2d, 1, N, NUM, 0) \ | 196 | _(SOFTFP, softfp_i2d, 1, N, NUM, 0) \ |
191 | _(SOFTFP, softfp_d2i, 2, N, INT, 0) \ | 197 | _(SOFTFP, softfp_d2i, 2, N, INT, 0) \ |
198 | _(SOFTFP_MIPS, lj_vm_sfmin, 4, N, NUM, 0) \ | ||
199 | _(SOFTFP_MIPS, lj_vm_sfmax, 4, N, NUM, 0) \ | ||
192 | _(SOFTFP_FFI, softfp_ui2d, 1, N, NUM, 0) \ | 200 | _(SOFTFP_FFI, softfp_ui2d, 1, N, NUM, 0) \ |
193 | _(SOFTFP_FFI, softfp_f2d, 1, N, NUM, 0) \ | 201 | _(SOFTFP_FFI, softfp_f2d, 1, N, NUM, 0) \ |
194 | _(SOFTFP_FFI, softfp_d2ui, 2, N, INT, 0) \ | 202 | _(SOFTFP_FFI, softfp_d2ui, 2, N, INT, 0) \ |
@@ -306,6 +314,10 @@ extern float softfp_ui2f(uint32_t a); | |||
306 | extern int32_t softfp_f2i(float a); | 314 | extern int32_t softfp_f2i(float a); |
307 | extern uint32_t softfp_f2ui(float a); | 315 | extern uint32_t softfp_f2ui(float a); |
308 | #endif | 316 | #endif |
317 | #if LJ_TARGET_MIPS | ||
318 | extern double lj_vm_sfmin(double a, double b); | ||
319 | extern double lj_vm_sfmax(double a, double b); | ||
320 | #endif | ||
309 | #endif | 321 | #endif |
310 | 322 | ||
311 | #if LJ_HASFFI && LJ_NEED_FP64 && !(LJ_TARGET_ARM && LJ_SOFTFP) | 323 | #if LJ_HASFFI && LJ_NEED_FP64 && !(LJ_TARGET_ARM && LJ_SOFTFP) |
diff --git a/src/lj_opt_split.c b/src/lj_opt_split.c index 4652c737..d12c7dfd 100644 --- a/src/lj_opt_split.c +++ b/src/lj_opt_split.c | |||
@@ -192,7 +192,7 @@ static IRRef split_ptr(jit_State *J, IRIns *oir, IRRef ref) | |||
192 | nref = ir->op1; | 192 | nref = ir->op1; |
193 | if (ofs == 0) return nref; | 193 | if (ofs == 0) return nref; |
194 | } | 194 | } |
195 | return split_emit(J, IRTI(IR_ADD), nref, lj_ir_kint(J, ofs)); | 195 | return split_emit(J, IRT(IR_ADD, IRT_PTR), nref, lj_ir_kint(J, ofs)); |
196 | } | 196 | } |
197 | 197 | ||
198 | #if LJ_HASFFI | 198 | #if LJ_HASFFI |
@@ -452,11 +452,15 @@ static void split_ir(jit_State *J) | |||
452 | IRIns inslo = *nir; /* Save/undo the emit of the lo XLOAD. */ | 452 | IRIns inslo = *nir; /* Save/undo the emit of the lo XLOAD. */ |
453 | J->cur.nins--; | 453 | J->cur.nins--; |
454 | hi = split_ptr(J, oir, ir->op1); /* Insert the hiref ADD. */ | 454 | hi = split_ptr(J, oir, ir->op1); /* Insert the hiref ADD. */ |
455 | #if LJ_BE | ||
456 | hi = split_emit(J, IRT(IR_XLOAD, IRT_INT), hi, ir->op2); | ||
457 | inslo.t.irt = IRT_SOFTFP | (inslo.t.irt & IRT_GUARD); | ||
458 | #endif | ||
455 | nref = lj_ir_nextins(J); | 459 | nref = lj_ir_nextins(J); |
456 | nir = IR(nref); | 460 | nir = IR(nref); |
457 | *nir = inslo; /* Re-emit lo XLOAD immediately before hi XLOAD. */ | 461 | *nir = inslo; /* Re-emit lo XLOAD. */ |
458 | hi = split_emit(J, IRT(IR_XLOAD, IRT_SOFTFP), hi, ir->op2); | ||
459 | #if LJ_LE | 462 | #if LJ_LE |
463 | hi = split_emit(J, IRT(IR_XLOAD, IRT_SOFTFP), hi, ir->op2); | ||
460 | ir->prev = nref; | 464 | ir->prev = nref; |
461 | #else | 465 | #else |
462 | ir->prev = hi; hi = nref; | 466 | ir->prev = hi; hi = nref; |
diff --git a/src/lj_target_mips.h b/src/lj_target_mips.h index 76645bca..f75bdaab 100644 --- a/src/lj_target_mips.h +++ b/src/lj_target_mips.h | |||
@@ -13,11 +13,15 @@ | |||
13 | _(R8) _(R9) _(R10) _(R11) _(R12) _(R13) _(R14) _(R15) \ | 13 | _(R8) _(R9) _(R10) _(R11) _(R12) _(R13) _(R14) _(R15) \ |
14 | _(R16) _(R17) _(R18) _(R19) _(R20) _(R21) _(R22) _(R23) \ | 14 | _(R16) _(R17) _(R18) _(R19) _(R20) _(R21) _(R22) _(R23) \ |
15 | _(R24) _(R25) _(SYS1) _(SYS2) _(R28) _(SP) _(R30) _(RA) | 15 | _(R24) _(R25) _(SYS1) _(SYS2) _(R28) _(SP) _(R30) _(RA) |
16 | #if LJ_SOFTFP | ||
17 | #define FPRDEF(_) | ||
18 | #else | ||
16 | #define FPRDEF(_) \ | 19 | #define FPRDEF(_) \ |
17 | _(F0) _(F1) _(F2) _(F3) _(F4) _(F5) _(F6) _(F7) \ | 20 | _(F0) _(F1) _(F2) _(F3) _(F4) _(F5) _(F6) _(F7) \ |
18 | _(F8) _(F9) _(F10) _(F11) _(F12) _(F13) _(F14) _(F15) \ | 21 | _(F8) _(F9) _(F10) _(F11) _(F12) _(F13) _(F14) _(F15) \ |
19 | _(F16) _(F17) _(F18) _(F19) _(F20) _(F21) _(F22) _(F23) \ | 22 | _(F16) _(F17) _(F18) _(F19) _(F20) _(F21) _(F22) _(F23) \ |
20 | _(F24) _(F25) _(F26) _(F27) _(F28) _(F29) _(F30) _(F31) | 23 | _(F24) _(F25) _(F26) _(F27) _(F28) _(F29) _(F30) _(F31) |
24 | #endif | ||
21 | #define VRIDDEF(_) | 25 | #define VRIDDEF(_) |
22 | 26 | ||
23 | #define RIDENUM(name) RID_##name, | 27 | #define RIDENUM(name) RID_##name, |
@@ -38,7 +42,11 @@ enum { | |||
38 | RID_RETHI = RID_R2, | 42 | RID_RETHI = RID_R2, |
39 | RID_RETLO = RID_R3, | 43 | RID_RETLO = RID_R3, |
40 | #endif | 44 | #endif |
45 | #if LJ_SOFTFP | ||
46 | RID_FPRET = RID_R2, | ||
47 | #else | ||
41 | RID_FPRET = RID_F0, | 48 | RID_FPRET = RID_F0, |
49 | #endif | ||
42 | RID_CFUNCADDR = RID_R25, | 50 | RID_CFUNCADDR = RID_R25, |
43 | 51 | ||
44 | /* These definitions must match with the *.dasc file(s): */ | 52 | /* These definitions must match with the *.dasc file(s): */ |
@@ -51,8 +59,12 @@ enum { | |||
51 | /* Register ranges [min, max) and number of registers. */ | 59 | /* Register ranges [min, max) and number of registers. */ |
52 | RID_MIN_GPR = RID_R0, | 60 | RID_MIN_GPR = RID_R0, |
53 | RID_MAX_GPR = RID_RA+1, | 61 | RID_MAX_GPR = RID_RA+1, |
54 | RID_MIN_FPR = RID_F0, | 62 | RID_MIN_FPR = RID_MAX_GPR, |
63 | #if LJ_SOFTFP | ||
64 | RID_MAX_FPR = RID_MIN_FPR, | ||
65 | #else | ||
55 | RID_MAX_FPR = RID_F31+1, | 66 | RID_MAX_FPR = RID_F31+1, |
67 | #endif | ||
56 | RID_NUM_GPR = RID_MAX_GPR - RID_MIN_GPR, | 68 | RID_NUM_GPR = RID_MAX_GPR - RID_MIN_GPR, |
57 | RID_NUM_FPR = RID_MAX_FPR - RID_MIN_FPR /* Only even regs are used. */ | 69 | RID_NUM_FPR = RID_MAX_FPR - RID_MIN_FPR /* Only even regs are used. */ |
58 | }; | 70 | }; |
@@ -67,28 +79,42 @@ enum { | |||
67 | (RID2RSET(RID_ZERO)|RID2RSET(RID_TMP)|RID2RSET(RID_SP)|\ | 79 | (RID2RSET(RID_ZERO)|RID2RSET(RID_TMP)|RID2RSET(RID_SP)|\ |
68 | RID2RSET(RID_SYS1)|RID2RSET(RID_SYS2)|RID2RSET(RID_JGL)) | 80 | RID2RSET(RID_SYS1)|RID2RSET(RID_SYS2)|RID2RSET(RID_JGL)) |
69 | #define RSET_GPR (RSET_RANGE(RID_MIN_GPR, RID_MAX_GPR) - RSET_FIXED) | 81 | #define RSET_GPR (RSET_RANGE(RID_MIN_GPR, RID_MAX_GPR) - RSET_FIXED) |
82 | #if LJ_SOFTFP | ||
83 | #define RSET_FPR 0 | ||
84 | #else | ||
70 | #define RSET_FPR \ | 85 | #define RSET_FPR \ |
71 | (RID2RSET(RID_F0)|RID2RSET(RID_F2)|RID2RSET(RID_F4)|RID2RSET(RID_F6)|\ | 86 | (RID2RSET(RID_F0)|RID2RSET(RID_F2)|RID2RSET(RID_F4)|RID2RSET(RID_F6)|\ |
72 | RID2RSET(RID_F8)|RID2RSET(RID_F10)|RID2RSET(RID_F12)|RID2RSET(RID_F14)|\ | 87 | RID2RSET(RID_F8)|RID2RSET(RID_F10)|RID2RSET(RID_F12)|RID2RSET(RID_F14)|\ |
73 | RID2RSET(RID_F16)|RID2RSET(RID_F18)|RID2RSET(RID_F20)|RID2RSET(RID_F22)|\ | 88 | RID2RSET(RID_F16)|RID2RSET(RID_F18)|RID2RSET(RID_F20)|RID2RSET(RID_F22)|\ |
74 | RID2RSET(RID_F24)|RID2RSET(RID_F26)|RID2RSET(RID_F28)|RID2RSET(RID_F30)) | 89 | RID2RSET(RID_F24)|RID2RSET(RID_F26)|RID2RSET(RID_F28)|RID2RSET(RID_F30)) |
90 | #endif | ||
75 | #define RSET_ALL (RSET_GPR|RSET_FPR) | 91 | #define RSET_ALL (RSET_GPR|RSET_FPR) |
76 | #define RSET_INIT RSET_ALL | 92 | #define RSET_INIT RSET_ALL |
77 | 93 | ||
78 | #define RSET_SCRATCH_GPR \ | 94 | #define RSET_SCRATCH_GPR \ |
79 | (RSET_RANGE(RID_R1, RID_R15+1)|\ | 95 | (RSET_RANGE(RID_R1, RID_R15+1)|\ |
80 | RID2RSET(RID_R24)|RID2RSET(RID_R25)|RID2RSET(RID_R28)) | 96 | RID2RSET(RID_R24)|RID2RSET(RID_R25)|RID2RSET(RID_R28)) |
97 | #if LJ_SOFTFP | ||
98 | #define RSET_SCRATCH_FPR 0 | ||
99 | #else | ||
81 | #define RSET_SCRATCH_FPR \ | 100 | #define RSET_SCRATCH_FPR \ |
82 | (RID2RSET(RID_F0)|RID2RSET(RID_F2)|RID2RSET(RID_F4)|RID2RSET(RID_F6)|\ | 101 | (RID2RSET(RID_F0)|RID2RSET(RID_F2)|RID2RSET(RID_F4)|RID2RSET(RID_F6)|\ |
83 | RID2RSET(RID_F8)|RID2RSET(RID_F10)|RID2RSET(RID_F12)|RID2RSET(RID_F14)|\ | 102 | RID2RSET(RID_F8)|RID2RSET(RID_F10)|RID2RSET(RID_F12)|RID2RSET(RID_F14)|\ |
84 | RID2RSET(RID_F16)|RID2RSET(RID_F18)) | 103 | RID2RSET(RID_F16)|RID2RSET(RID_F18)) |
104 | #endif | ||
85 | #define RSET_SCRATCH (RSET_SCRATCH_GPR|RSET_SCRATCH_FPR) | 105 | #define RSET_SCRATCH (RSET_SCRATCH_GPR|RSET_SCRATCH_FPR) |
86 | #define REGARG_FIRSTGPR RID_R4 | 106 | #define REGARG_FIRSTGPR RID_R4 |
87 | #define REGARG_LASTGPR RID_R7 | 107 | #define REGARG_LASTGPR RID_R7 |
88 | #define REGARG_NUMGPR 4 | 108 | #define REGARG_NUMGPR 4 |
109 | #if LJ_ABI_SOFTFP | ||
110 | #define REGARG_FIRSTFPR 0 | ||
111 | #define REGARG_LASTFPR 0 | ||
112 | #define REGARG_NUMFPR 0 | ||
113 | #else | ||
89 | #define REGARG_FIRSTFPR RID_F12 | 114 | #define REGARG_FIRSTFPR RID_F12 |
90 | #define REGARG_LASTFPR RID_F14 | 115 | #define REGARG_LASTFPR RID_F14 |
91 | #define REGARG_NUMFPR 2 | 116 | #define REGARG_NUMFPR 2 |
117 | #endif | ||
92 | 118 | ||
93 | /* -- Spill slots --------------------------------------------------------- */ | 119 | /* -- Spill slots --------------------------------------------------------- */ |
94 | 120 | ||
@@ -111,7 +137,9 @@ enum { | |||
111 | 137 | ||
112 | /* This definition must match with the *.dasc file(s). */ | 138 | /* This definition must match with the *.dasc file(s). */ |
113 | typedef struct { | 139 | typedef struct { |
140 | #if !LJ_SOFTFP | ||
114 | lua_Number fpr[RID_NUM_FPR]; /* Floating-point registers. */ | 141 | lua_Number fpr[RID_NUM_FPR]; /* Floating-point registers. */ |
142 | #endif | ||
115 | int32_t gpr[RID_NUM_GPR]; /* General-purpose registers. */ | 143 | int32_t gpr[RID_NUM_GPR]; /* General-purpose registers. */ |
116 | int32_t spill[256]; /* Spill slots. */ | 144 | int32_t spill[256]; /* Spill slots. */ |
117 | } ExitState; | 145 | } ExitState; |
diff --git a/src/vm_mips.dasc b/src/vm_mips.dasc index 8c307d8d..71ae39a3 100644 --- a/src/vm_mips.dasc +++ b/src/vm_mips.dasc | |||
@@ -2731,6 +2731,25 @@ static void build_subroutines(BuildCtx *ctx) | |||
2731 | |. li CRET1, 0 | 2731 | |. li CRET1, 0 |
2732 | |.endif | 2732 | |.endif |
2733 | | | 2733 | | |
2734 | |.macro sfmin_max, name, intins | ||
2735 | |->vm_sf .. name: | ||
2736 | |.if JIT and not FPU | ||
2737 | | move TMP2, ra | ||
2738 | | bal ->vm_sfcmpolt | ||
2739 | |. nop | ||
2740 | | move TMP0, CRET1 | ||
2741 | | move SFRETHI, SFARG1HI | ||
2742 | | move SFRETLO, SFARG1LO | ||
2743 | | move ra, TMP2 | ||
2744 | | intins SFRETHI, SFARG2HI, TMP0 | ||
2745 | | jr ra | ||
2746 | |. intins SFRETLO, SFARG2LO, TMP0 | ||
2747 | |.endif | ||
2748 | |.endmacro | ||
2749 | | | ||
2750 | | sfmin_max min, movz | ||
2751 | | sfmin_max max, movn | ||
2752 | | | ||
2734 | |//----------------------------------------------------------------------- | 2753 | |//----------------------------------------------------------------------- |
2735 | |//-- Miscellaneous functions -------------------------------------------- | 2754 | |//-- Miscellaneous functions -------------------------------------------- |
2736 | |//----------------------------------------------------------------------- | 2755 | |//----------------------------------------------------------------------- |
@@ -4882,8 +4901,15 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
4882 | | move SFARG1LO, SFRETLO | 4901 | | move SFARG1LO, SFRETLO |
4883 | | bal ->vm_sfcmpolex | 4902 | | bal ->vm_sfcmpolex |
4884 | |. lw TMP3, FORL_STEP*8+HI(RA) | 4903 | |. lw TMP3, FORL_STEP*8+HI(RA) |
4885 | | b <1 | 4904 | if ( op == BC_JFORL ) { |
4886 | |. lw TMP2, ARG5 | 4905 | | lhu RD, -4+OFS_RD(PC) |
4906 | | lw TMP2, ARG5 | ||
4907 | | b <1 | ||
4908 | |. decode_RD8b RD | ||
4909 | } else { | ||
4910 | | b <1 | ||
4911 | |. lw TMP2, ARG5 | ||
4912 | } | ||
4887 | } | 4913 | } |
4888 | |.endif | 4914 | |.endif |
4889 | break; | 4915 | break; |