diff --git a/src/lib_math.c b/src/lib_math.c index a1d8a618..e4fc4c0f 100644 --- a/src/lib_math.c +++ b/src/lib_math.c @@ -33,7 +33,6 @@ LJLIB_ASM(math_sqrt) LJLIB_REC(math_unary IRFPM_SQRT) lj_lib_checknum(L, 1); return FFH_RETRY; } -LJLIB_ASM_(math_log) LJLIB_REC(math_unary IRFPM_LOG) LJLIB_ASM_(math_log10) LJLIB_REC(math_unary IRFPM_LOG10) LJLIB_ASM_(math_exp) LJLIB_REC(math_unary IRFPM_EXP) LJLIB_ASM_(math_sin) LJLIB_REC(math_unary IRFPM_SIN) @@ -48,6 +47,22 @@ LJLIB_ASM_(math_tanh) LJLIB_REC(math_htrig IRCALL_tanh) LJLIB_ASM_(math_frexp) LJLIB_ASM_(math_modf) LJLIB_REC(.) +LJLIB_ASM(math_log) LJLIB_REC(math_log) +{ + double x = lj_lib_checknum(L, 1); + if (L->base+1 < L->top) { + double y = lj_lib_checknum(L, 2); +#ifdef LUAJIT_NO_LOG2 + x = log(x); y = 1.0 / log(y); +#else + x = lj_vm_log2(x); y = 1.0 / lj_vm_log2(y); +#endif + setnumV(L->base-1, x*y); /* Do NOT join the expression to x / y. */ + return FFH_RES(1); + } + return FFH_RETRY; +} + LJLIB_PUSH(57.29577951308232) LJLIB_ASM_(math_deg) LJLIB_REC(math_degrad) diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c index b9e0d8f9..270c10c5 100644 --- a/src/lj_ffrecord.c +++ b/src/lj_ffrecord.c @@ -447,6 +447,28 @@ static void LJ_FASTCALL recff_math_unary(jit_State *J, RecordFFData *rd) J->base[0] = emitir(IRTN(IR_FPMATH), lj_ir_tonum(J, J->base[0]), rd->data); } +/* Record math.log. */ +static void LJ_FASTCALL recff_math_log(jit_State *J, RecordFFData *rd) +{ + TRef tr = lj_ir_tonum(J, J->base[0]); + if (J->base[1]) { +#ifdef LUAJIT_NO_LOG2 + uint32_t fpm = IRFPM_LOG; +#else + uint32_t fpm = IRFPM_LOG2; +#endif + TRef trb = lj_ir_tonum(J, J->base[1]); + tr = emitir(IRTN(IR_FPMATH), tr, fpm); + trb = emitir(IRTN(IR_FPMATH), trb, fpm); + trb = emitir(IRTN(IR_DIV), lj_ir_knum_one(J), trb); + tr = emitir(IRTN(IR_MUL), tr, trb); + } else { + tr = emitir(IRTN(IR_FPMATH), tr, IRFPM_LOG); + } + J->base[0] = tr; + UNUSED(rd); +} + /* Record math.atan2. */ static void LJ_FASTCALL recff_math_atan2(jit_State *J, RecordFFData *rd) { diff --git a/src/lj_vm.h b/src/lj_vm.h index 4f9a10b8..813335e3 100644 --- a/src/lj_vm.h +++ b/src/lj_vm.h @@ -60,6 +60,11 @@ LJ_ASMF double lj_vm_floor_hf(double); LJ_ASMF double lj_vm_ceil_hf(double); #endif #endif +#if defined(LUAJIT_NO_LOG2) || LJ_TARGET_X86ORX64 +LJ_ASMF double lj_vm_log2(double); +#else +#define lj_vm_log2 log2 +#endif #if LJ_HASJIT #if LJ_TARGET_X86ORX64 @@ -80,11 +85,6 @@ LJ_ASMF double lj_vm_trunc_hf(double); #endif #endif LJ_ASMF double lj_vm_powi(double, int32_t); -#ifdef LUAJIT_NO_LOG2 -LJ_ASMF double lj_vm_log2(double); -#else -#define lj_vm_log2 log2 -#endif #ifdef LUAJIT_NO_EXP2 LJ_ASMF double lj_vm_exp2(double); #else diff --git a/src/vm_arm.dasc b/src/vm_arm.dasc index 31657b70..331a1b70 100644 --- a/src/vm_arm.dasc +++ b/src/vm_arm.dasc @@ -1468,7 +1468,28 @@ static void build_subroutines(BuildCtx *ctx) | math_extern sqrt |.endif | - | math_extern log + |.ffunc math_log + |.if HFABI + | ldr CARG2, [BASE, #4] + | cmp NARGS8:RC, #8 // Need exactly 1 argument. + | vldr d0, [BASE] + | bne ->fff_fallback + |.else + | ldrd CARG12, [BASE] + | cmp NARGS8:RC, #8 // Need exactly 1 argument. + | bne ->fff_fallback + |.endif + | checktp CARG2, LJ_TISNUM + | bhs ->fff_fallback + | .IOS mov RA, BASE + | bl extern log + | .IOS mov BASE, RA + |.if HFABI + | b ->fff_resd + |.else + | b ->fff_restv + |.endif + | | math_extern log10 | math_extern exp | math_extern sin diff --git a/src/vm_mips.dasc b/src/vm_mips.dasc index fdf07343..719d9252 100644 --- a/src/vm_mips.dasc +++ b/src/vm_mips.dasc @@ -1486,7 +1486,19 @@ static void build_subroutines(BuildCtx *ctx) | math_round floor | math_round ceil | - | math_extern log + |.ffunc math_log + | lw CARG3, HI(BASE) + | li AT, 8 + | bne NARGS8:RC, AT, ->fff_fallback // Exactly 1 argument. + |. load_got log + | sltiu AT, CARG3, LJ_TISNUM + | beqz AT, ->fff_fallback + |. nop + | call_extern + |. ldc1 FARG1, 0(BASE) + | b ->fff_resn + |. nop + | | math_extern log10 | math_extern exp | math_extern sin diff --git a/src/vm_ppc.dasc b/src/vm_ppc.dasc index 7c567aad..6dbfb90d 100644 --- a/src/vm_ppc.dasc +++ b/src/vm_ppc.dasc @@ -1804,7 +1804,16 @@ static void build_subroutines(BuildCtx *ctx) |.else | math_extern sqrt |.endif - | math_extern log + | + |.ffunc math_log + | cmplwi NARGS8:RC, 8 + | lwz CARG3, 0(BASE) + | lfd FARG1, 0(BASE) + | bne ->fff_fallback // Need exactly 1 argument. + | checknum CARG3; bge ->fff_fallback + | blex log + | b ->fff_resn + | | math_extern log10 | math_extern exp | math_extern sin diff --git a/src/vm_ppcspe.dasc b/src/vm_ppcspe.dasc index 0adbcd7e..2af06494 100644 --- a/src/vm_ppcspe.dasc +++ b/src/vm_ppcspe.dasc @@ -1426,7 +1426,18 @@ static void build_subroutines(BuildCtx *ctx) | math_round ceil | | math_extern sqrt - | math_extern log + | + |.ffunc math_log + | cmplwi NARGS8:RC, 8 + | evldd CARG2, 0(BASE) + | bne ->fff_fallback // Need exactly 1 argument. + | checknum CARG2 + | evmergehi CARG1, CARG2, CARG2 + | checkfail ->fff_fallback + | bl extern log + | evmergelo CRET1, CRET1, CRET2 + | b ->fff_restv + | | math_extern log10 | math_extern exp | math_extern sin diff --git a/src/vm_x86.dasc b/src/vm_x86.dasc index 67984c6c..75683225 100644 --- a/src/vm_x86.dasc +++ b/src/vm_x86.dasc @@ -2045,7 +2045,12 @@ static void build_subroutines(BuildCtx *ctx) |.else |.ffunc_n math_sqrt; fsqrt; jmp ->fff_resn |.endif - |.ffunc_n math_log, fldln2; fyl2x; jmp ->fff_resn + | + |.ffunc math_log + | cmp NARGS:RD, 1+1; jne ->fff_fallback // Exactly one argument. + | cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback + | fldln2; fld qword [BASE]; fyl2x; jmp ->fff_resn + | |.ffunc_n math_log10, fldlg2; fyl2x; jmp ->fff_resn |.ffunc_n math_exp; call ->vm_exp_x87; jmp ->fff_resn | @@ -3157,6 +3162,29 @@ static void build_subroutines(BuildCtx *ctx) | ret |.endif | + |// FP log2(x). Called by math.log(x, base). + |->vm_log2: + |.if X64WIN + | movsd qword [rsp+8], xmm0 // Use scratch area. + | fld1 + | fld qword [rsp+8] + | fyl2x + | fstp qword [rsp+8] + | movsd xmm0, qword [rsp+8] + |.elif X64 + | movsd qword [rsp-8], xmm0 // Use red zone. + | fld1 + | fld qword [rsp-8] + | fyl2x + | fstp qword [rsp-8] + | movsd xmm0, qword [rsp-8] + |.else + | fld1 + | fld qword [esp+4] + | fyl2x + |.endif + | ret + | |// FP exponentiation e^x and 2^x. Called by math.exp fast function and |// from JIT code. Arg/ret on x87 stack. No int/xmm regs modified. |// Caveat: needs 3 slots on x87 stack!