From 7457ee869aa182fbecec6c7f567d93fd85382b57 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Wed, 1 Sep 2010 20:27:39 +0200 Subject: [PATCH] PPC: Add comparison instructions. --- src/buildvm_ppc.dasc | 133 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 128 insertions(+), 5 deletions(-) diff --git a/src/buildvm_ppc.dasc b/src/buildvm_ppc.dasc index 6ac1b036..abd688e9 100644 --- a/src/buildvm_ppc.dasc +++ b/src/buildvm_ppc.dasc @@ -922,23 +922,146 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) /* Remember: all ops branch for a true comparison, fall through otherwise. */ case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: - | NYI + | // RA = src1*8, RD = src2*8, JMP with RD = target + | evlddx TMP0, BASE, RA + | addi PC, PC, 4 + | evlddx TMP1, BASE, RD + | addis TMP3, PC, -(BCBIAS_J*4 >> 16) + | lwz INS, -4(PC) + | evmergehi RB, TMP0, TMP1 + | decode_RD4 TMP2, INS + | checknum RB + | add TMP2, TMP2, TMP3 + | checkanyfail ->vmeta_comp + if (op == BC_ISLT || op == BC_ISGE) { + | efdcmplt TMP0, TMP1 + } else { + | efdcmpgt TMP0, TMP1 + } + if (op == BC_ISLT || op == BC_ISGT) { + | iselgt PC, TMP2, PC + } else { + | iselgt PC, PC, TMP2 + } + | ins_next break; case BC_ISEQV: case BC_ISNEV: - | NYI + vk = op == BC_ISEQV; + | // RA = src1*8, RD = src2*8, JMP with RD = target + | evlddx TMP0, BASE, RA + | addi PC, PC, 4 + | evlddx TMP1, BASE, RD + | addis TMP3, PC, -(BCBIAS_J*4 >> 16) + | lwz INS, -4(PC) + | evmergehi RB, TMP0, TMP1 + | decode_RD4 TMP2, INS + | checknum RB + | add TMP2, TMP2, TMP3 + | checkanyfail >5 + | efdcmpeq TMP0, TMP1 + if (vk) { + | iselgt PC, TMP2, PC + } else { + | iselgt PC, PC, TMP2 + } + |1: + | ins_next + | + |5: // Either or both types are not numbers. + | evcmpeq TMP0, TMP1 + | not TMP3, RB + | cmplwi cr1, TMP3, ~LJ_TISPRI // Primitive? + | crorc 4*cr7+lt, 4*cr0+so, 4*cr0+lt // 1: Same tv or different type. + | cmplwi cr6, TMP3, ~LJ_TISTABUD // Table or userdata? + | crandc 4*cr7+gt, 4*cr0+lt, 4*cr1+gt // 2: Same type and primitive. + | mr SAVE0, PC + if (vk) { + | isel PC, TMP2, PC, 4*cr7+gt + } else { + | isel TMP2, PC, TMP2, 4*cr7+gt + } + | cror 4*cr7+lt, 4*cr7+lt, 4*cr7+gt // 1 or 2. + if (vk) { + | isel PC, TMP2, PC, 4*cr0+so + } else { + | isel PC, PC, TMP2, 4*cr0+so + } + | blt cr7, <1 // Done if 1 or 2. + | blt cr6, <1 // Done if not tab/ud. + | + | // Different tables or userdatas. Need to check __eq metamethod. + | // Field metatable must be at same offset for GCtab and GCudata! + | lwz TAB:TMP3, TAB:TMP1->metatable + | li RB, 1-vk // ne = 0 or 1. + | cmplwi TAB:TMP3, 0 + | beq <1 // No metatable? + | lbz TMP0, TAB:TMP3->nomm + | andi. TMP0, TMP0, 1<vmeta_equal // Handle __eq metamethod. break; case BC_ISEQS: case BC_ISNES: - | NYI + vk = op == BC_ISEQS; + | // RA = src*8, RD = str_const*8 (~), JMP with RD = target + | evlddx TMP0, BASE, RA + | srwi RD, RD, 1 + | lwz INS, 0(PC) + | subfic RD, RD, -4 + | addi PC, PC, 4 + | lwzx STR:TMP1, KBASE, RD // KBASE-4-str_const*4 + | addis TMP3, PC, -(BCBIAS_J*4 >> 16) + | decode_RD4 TMP2, INS + | evmergelo STR:TMP1, TISSTR, STR:TMP1 + | add TMP2, TMP2, TMP3 + | evcmpeq TMP0, STR:TMP1 + if (vk) { + | isel PC, TMP2, PC, 4*cr0+so + } else { + | isel PC, PC, TMP2, 4*cr0+so + } + | ins_next break; case BC_ISEQN: case BC_ISNEN: - | NYI + vk = op == BC_ISEQN; + | // RA = src*8, RD = num_const*8, JMP with RD = target + | evlddx TMP0, BASE, RA + | addi PC, PC, 4 + | evlddx TMP1, KBASE, RD + | addis TMP3, PC, -(BCBIAS_J*4 >> 16) + | lwz INS, -4(PC) + | efdcmpeq TMP0, TMP1 // NYI: avoid comparison with NaN. + | decode_RD4 TMP2, INS + | add TMP2, TMP2, TMP3 + if (vk) { + | iselgt PC, TMP2, PC + } else { + | iselgt PC, PC, TMP2 + } + | ins_next break; case BC_ISEQP: case BC_ISNEP: - | NYI + vk = op == BC_ISEQP; + | // RA = src*8, RD = primitive_type*8 (~), JMP with RD = target + | lwzx TMP0, BASE, RA + | srwi TMP1, RD, 3 + | lwz INS, 0(PC) + | addi PC, PC, 4 + | not TMP1, TMP1 + | addis TMP3, PC, -(BCBIAS_J*4 >> 16) + | cmplw TMP0, TMP1 + | decode_RD4 TMP2, INS + | add TMP2, TMP2, TMP3 + if (vk) { + | iseleq PC, TMP2, PC + } else { + | iseleq PC, PC, TMP2 + } + | ins_next break; /* -- Unary test and copy ops ------------------------------------------- */