2 ** Math helper functions for assembler VM.
3 ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h
16 /* -- Wrapper functions --------------------------------------------------- */
18 #if LJ_TARGET_X86 && __ELF__ && __PIC__
19 /* Wrapper functions to deal with the ELF/x86 PIC disaster. */
20 LJ_FUNCA
double lj_wrap_log(double x
) { return log(x
); }
21 LJ_FUNCA
double lj_wrap_log10(double x
) { return log10(x
); }
22 LJ_FUNCA
double lj_wrap_exp(double x
) { return exp(x
); }
23 LJ_FUNCA
double lj_wrap_sin(double x
) { return sin(x
); }
24 LJ_FUNCA
double lj_wrap_cos(double x
) { return cos(x
); }
25 LJ_FUNCA
double lj_wrap_tan(double x
) { return tan(x
); }
26 LJ_FUNCA
double lj_wrap_asin(double x
) { return asin(x
); }
27 LJ_FUNCA
double lj_wrap_acos(double x
) { return acos(x
); }
28 LJ_FUNCA
double lj_wrap_atan(double x
) { return atan(x
); }
29 LJ_FUNCA
double lj_wrap_sinh(double x
) { return sinh(x
); }
30 LJ_FUNCA
double lj_wrap_cosh(double x
) { return cosh(x
); }
31 LJ_FUNCA
double lj_wrap_tanh(double x
) { return tanh(x
); }
32 LJ_FUNCA
double lj_wrap_atan2(double x
, double y
) { return atan2(x
, y
); }
33 LJ_FUNCA
double lj_wrap_pow(double x
, double y
) { return pow(x
, y
); }
34 LJ_FUNCA
double lj_wrap_fmod(double x
, double y
) { return fmod(x
, y
); }
37 /* -- Helper functions ---------------------------------------------------- */
39 /* Required to prevent the C compiler from applying FMA optimizations.
41 ** Yes, there's -ffp-contract and the FP_CONTRACT pragma ... in theory.
42 ** But the current state of C compilers is a mess in this regard.
43 ** Also, this function is not performance sensitive at all.
45 LJ_NOINLINE
static double lj_vm_floormul(double x
, double y
)
47 return lj_vm_floor(x
/ y
) * y
;
50 double lj_vm_foldarith(double x
, double y
, int op
)
53 case IR_ADD
- IR_ADD
: return x
+y
; break;
54 case IR_SUB
- IR_ADD
: return x
-y
; break;
55 case IR_MUL
- IR_ADD
: return x
*y
; break;
56 case IR_DIV
- IR_ADD
: return x
/y
; break;
57 case IR_MOD
- IR_ADD
: return x
-lj_vm_floormul(x
, y
); break;
58 case IR_POW
- IR_ADD
: return pow(x
, y
); break;
59 case IR_NEG
- IR_ADD
: return -x
; break;
60 case IR_ABS
- IR_ADD
: return fabs(x
); break;
62 case IR_LDEXP
- IR_ADD
: return ldexp(x
, (int)y
); break;
63 case IR_MIN
- IR_ADD
: return x
< y
? x
: y
; break;
64 case IR_MAX
- IR_ADD
: return x
> y
? x
: y
; break;
70 /* -- Helper functions for generated machine code ------------------------- */
72 #if (LJ_HASJIT && !(LJ_TARGET_ARM || LJ_TARGET_ARM64 || LJ_TARGET_PPC)) || LJ_TARGET_MIPS
73 int32_t LJ_FASTCALL
lj_vm_modi(int32_t a
, int32_t b
)
76 /* This must be checked before using this function. */
77 lj_assertX(b
!= 0, "modulo with zero divisor");
78 ua
= a
< 0 ? ~(uint32_t)a
+1u : (uint32_t)a
;
79 ub
= b
< 0 ? ~(uint32_t)b
+1u : (uint32_t)b
;
81 if (y
!= 0 && (a
^b
) < 0) y
= y
- ub
;
82 if (((int32_t)y
^b
) < 0) y
= ~y
+1u;
90 double lj_vm_log2(double a
)
92 return log(a
) * 1.4426950408889634074;
96 /* Computes fpm(x) for extended math functions. */
97 double lj_vm_foldfpm(double x
, int fpm
)
100 case IRFPM_FLOOR
: return lj_vm_floor(x
);
101 case IRFPM_CEIL
: return lj_vm_ceil(x
);
102 case IRFPM_TRUNC
: return lj_vm_trunc(x
);
103 case IRFPM_SQRT
: return sqrt(x
);
104 case IRFPM_LOG
: return log(x
);
105 case IRFPM_LOG2
: return lj_vm_log2(x
);
106 default: lj_assertX(0, "bad fpm %d", fpm
);
112 int lj_vm_errno(void)