From ae38a6913ea0d2e43bf04e94423d6f03ad995f8b Mon Sep 17 00:00:00 2001 From: Michael Munday Date: Wed, 21 Dec 2016 11:02:53 -0500 Subject: [PATCH] Add support for numeric equality checks. --- src/vm_s390x.dasc | 114 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 2 deletions(-) diff --git a/src/vm_s390x.dasc b/src/vm_s390x.dasc index 0f538d08..d1db7b97 100644 --- a/src/vm_s390x.dasc +++ b/src/vm_s390x.dasc @@ -1255,8 +1255,118 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) break; case BC_ISEQV: case BC_ISNEV: - | stg r0, 0(r0) - | stg r0, 0(r0) + vk = op == BC_ISEQV; + | ins_AD // RA = src1, RD = src2, JMP with RD = target + | sllg RD, RD, 3(r0) + | ld f1, 0(RD, BASE) + | lg RD, 0(RD, BASE) + | sllg RA, RA, 3(r0) + | ld f0, 0(RA, BASE) + | lg RA, 0(RA, BASE) + | la PC, 4(PC) + | srag RB, RD, 47(r0) + | srag ITYPE, RA, 47(r0) + | clfi RB, LJ_TISNUM; jne >7 + | clfi ITYPE, LJ_TISNUM; jne >8 + | cr RD, RA + if (vk) { + | jne >9 + } else { + | je >9 + } + | llgh RD, PC_RD + | branchPC RD + |9: + | ins_next + | + |7: // RD is not an integer. + | jh >5 + | // RD is a number. + | clfi ITYPE, LJ_TISNUM; jl >1; jne >5 + | // RD is a number, RA is an integer. + | cdfbr f0, RA + | j >1 + | + |8: // RD is an integer, RA is not an integer. + | jh >5 + | // RD is an integer, RA is a number. + | cdfbr f1, RD + | j >1 + | + |1: + | cdbr f0, f1 + |4: + iseqne_fp: + if (vk) { + | jne >2 // Unordered means not equal. + } else { + | je >1 // Unordered means not equal. + } + iseqne_end: + if (vk) { + |1: // EQ: Branch to the target. + | llgh RD, PC_RD + | branchPC RD + |2: // NE: Fallthrough to next instruction. + |.if not FFI + |3: + |.endif + } else { + |.if not FFI + |3: + |.endif + |2: // NE: Branch to the target. + | llgh RD, PC_RD + | branchPC RD + |1: // EQ: Fallthrough to next instruction. + } + if (LJ_DUALNUM && (op == BC_ISEQV || op == BC_ISNEV || + op == BC_ISEQN || op == BC_ISNEN)) { + | j <9 + } else { + | ins_next + } + | + if (op == BC_ISEQV || op == BC_ISNEV) { + |5: // Either or both types are not numbers. + |.if FFI + | clfi RB, LJ_TCDATA; je ->vmeta_equal_cd + | clfi ITYPE, LJ_TCDATA; je ->vmeta_equal_cd + |.endif + | cgr RA, RD + | je <1 // Same GCobjs or pvalues? + | cr RB, ITYPE + | jne <2 // Not the same type? + | clfi RB, LJ_TISTABUD + | jh <2 // Different objects and not table/ud? + | + | // Different tables or userdatas. Need to check __eq metamethod. + | // Field metatable must be at same offset for GCtab and GCudata! + | cleartp TAB:RA + | lg TAB:RB, TAB:RA->metatable + | cghi TAB:RB, 0 + | je <2 // No metatable? + | llgc TMPR2, TAB:RB->nomm + | tmll TMPR2, 1<vmeta_equal // Handle __eq metamethod. + } else { + |.if FFI + |3: + | clfi ITYPE, LJ_TCDATA + if (LJ_DUALNUM && vk) { + | jne <9 + } else { + | jne <2 + } + | j ->vmeta_equal_cd + |.endif + } break; case BC_ISEQS: case BC_ISNES: | stg r0, 0(r0)