22#ifndef ZEND_MULTIPLY_H
23#define ZEND_MULTIPLY_H
25#if defined(PHP_HAVE_BUILTIN_SMULL_OVERFLOW) && SIZEOF_LONG == SIZEOF_ZEND_LONG
27#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
29 if (((usedval) = __builtin_smull_overflow((a), (b), &__tmpvar))) { \
30 (dval) = (double) (a) * (double) (b); \
32 else (lval) = __tmpvar; \
35#elif defined(PHP_HAVE_BUILTIN_SMULLL_OVERFLOW) && SIZEOF_LONG_LONG == SIZEOF_ZEND_LONG
37#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
39 if (((usedval) = __builtin_smulll_overflow((a), (b), &__tmpvar))) { \
40 (dval) = (double) (a) * (double) (b); \
42 else (lval) = __tmpvar; \
45#elif (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__)
47#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
49 __asm__ ("imul %3,%0\n" \
51 : "=r"(__tmpvar),"=r"(usedval) \
52 : "0"(a), "r"(b), "1"(0)); \
53 if (usedval) (dval) = (double) (a) * (double) (b); \
54 else (lval) = __tmpvar; \
57#elif defined(__arm__) && defined(__GNUC__)
59#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
61 __asm__("smull %0, %1, %2, %3\n" \
62 "sub %1, %1, %0, asr #31" \
63 : "=r"(__tmpvar), "=r"(usedval) \
65 if (usedval) (dval) = (double) (a) * (double) (b); \
66 else (lval) = __tmpvar; \
69#elif defined(__aarch64__) && defined(__GNUC__)
71#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
73 __asm__("mul %0, %2, %3\n" \
74 "smulh %1, %2, %3\n" \
75 "sub %1, %1, %0, asr #63\n" \
76 : "=&r"(__tmpvar), "=&r"(usedval) \
78 if (usedval) (dval) = (double) (a) * (double) (b); \
79 else (lval) = __tmpvar; \
82#elif defined(ZEND_WIN32)
85# pragma intrinsic(_mul128)
86# define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
88 __int64 __low = _mul128((a), (b), &__high); \
89 if ((__low >> 63I64) == __high) { \
94 (dval) = (double)(a) * (double)(b); \
97# elif defined(_M_ARM64)
98# pragma intrinsic(__mulh)
99# define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
100 __int64 __high = __mulh((a), (b)); \
101 __int64 __low = (a) * (b); \
102 if ((__low >> 63I64) == __high) { \
107 (dval) = (double)(a) * (double)(b); \
111# define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
112 zend_long __lres = (a) * (b); \
113 long double __dres = (long double)(a) * (long double)(b); \
114 long double __delta = (long double) __lres - __dres; \
115 if ( ((usedval) = (( __dres + __delta ) != __dres))) { \
123#elif defined(__powerpc64__) && defined(__GNUC__)
125#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
126 long __low, __high; \
127 __asm__("mulld %0,%2,%3\n\t" \
129 : "=&r"(__low), "=&r"(__high) \
131 if ((__low >> 63) != __high) { \
132 (dval) = (double) (a) * (double) (b); \
140#elif SIZEOF_ZEND_LONG == 4
142#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
143 int64_t __result = (int64_t) (a) * (int64_t) (b); \
144 if (__result > ZEND_LONG_MAX || __result < ZEND_LONG_MIN) { \
145 (dval) = (double) __result; \
148 (lval) = (long) __result; \
155#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
156 long __lres = (a) * (b); \
157 long double __dres = (long double)(a) * (long double)(b); \
158 long double __delta = (long double) __lres - __dres; \
159 if ( ((usedval) = (( __dres + __delta ) != __dres))) { \
168#if defined(__GNUC__) && (defined(__native_client__) || defined(i386))
173 size_t m_overflow = 0;
176 __asm__ (
"mull %3\n\tadcl $0,%1"
177 :
"=&a"(
res),
"=&d" (m_overflow)
181 __asm__ (
"mull %3\n\taddl %4,%0\n\tadcl $0,%1"
182 :
"=&a"(
res),
"=&d" (m_overflow)
196#elif defined(__GNUC__) && defined(__x86_64__)
210 __asm__ (
"mul" LP_SUFF
" %3\n\t"
212 :
"=&a"(
res),
"=&d" (m_overflow)
216 __asm__ (
"mul" LP_SUFF
" %3\n\t"
219 :
"=&a"(
res),
"=&d" (m_overflow)
233#elif defined(__GNUC__) && defined(__arm__)
240 __asm__ (
"umlal %0,%1,%2,%3"
241 :
"=r"(
res),
"=r"(m_overflow)
255#elif defined(__GNUC__) && defined(__aarch64__)
262 __asm__ (
"mul %0,%2,%3\n\tumulh %1,%2,%3\n\tadds %0,%0,%4\n\tadc %1,%1,xzr"
263 :
"=&r"(
res),
"=&r"(m_overflow)
276#elif defined(__GNUC__) && defined(__powerpc64__)
281 unsigned long m_overflow;
283 __asm__ (
"mulld %0,%2,%3\n\t"
284 "mulhdu %1,%2,%3\n\t"
287 :
"=&r"(
res),
"=&r"(m_overflow)
300#elif SIZEOF_SIZE_T == 4
304 uint64_t
res = (uint64_t) nmemb * (uint64_t)
size + (uint64_t)
offset;
319 double _d = (double)nmemb * (
double)
size + (double)
offset;
320 double _delta = (double)
res - _d;
334 size_t ret = zend_safe_address(nmemb,
size,
offset, &overflow);
347 size_t ret = zend_safe_address(nmemb,
size,
offset, &overflow);
ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn(int type, const char *format,...)
#define zend_always_inline
#define ZEND_CONST_COND(_condition, _default)
#define UNEXPECTED(condition)