/* $Id$ */
+#include "zend_portability.h"
+
#ifndef ZEND_MULTIPLY_H
#define ZEND_MULTIPLY_H
-#if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__)
+#if __has_builtin(__builtin_smull_overflow) && SIZEOF_LONG == SIZEOF_ZEND_LONG
+
+#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
+ long __tmpvar; \
+ if (((usedval) = __builtin_smull_overflow((a), (b), &__tmpvar))) { \
+ (dval) = (double) (a) * (double) (b); \
+ } \
+ else (lval) = __tmpvar; \
+} while (0)
+
+#elif __has_builtin(__builtin_smulll_overflow) && SIZEOF_LONG_LONG == SIZEOF_ZEND_LONG
+
+#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
+ long long __tmpvar; \
+ if (((usedval) = __builtin_smulll_overflow((a), (b), &__tmpvar))) { \
+ (dval) = (double) (a) * (double) (b); \
+ } \
+ else (lval) = __tmpvar; \
+} while (0)
+
+#elif (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__)
#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
zend_long __tmpvar; \
#include <ieeefp.h>
#endif
+#include "zend_portability.h"
#include "zend_strtod.h"
#include "zend_multiply.h"
static zend_always_inline void fast_long_add_function(zval *result, zval *op1, zval *op2)
{
-#if defined(__GNUC__) && defined(__i386__) && !(4 == __GNUC__ && 8 == __GNUC_MINOR__)
+#if __has_builtin(__builtin_saddl_overflow) && SIZEOF_LONG == SIZEOF_ZEND_LONG
+ long lresult;
+ if (UNEXPECTED(__builtin_saddl_overflow(Z_LVAL_P(op1), Z_LVAL_P(op2), &lresult))) {
+ ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2));
+ } else {
+ ZVAL_LONG(result, lresult);
+ }
+#elif __has_builtin(__builtin_saddll_overflow) && SIZEOF_LONG_LONG == SIZEOF_ZEND_LONG
+ long long llresult;
+ if (UNEXPECTED(__builtin_saddl_overflow(Z_LVAL_P(op1), Z_LVAL_P(op2), &llresult))) {
+ ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2));
+ } else {
+ ZVAL_LONG(result, llresult);
+ }
+#elif defined(__GNUC__) && defined(__i386__) && !(4 == __GNUC__ && 8 == __GNUC_MINOR__)
__asm__(
"movl (%1), %%eax\n\t"
"addl (%2), %%eax\n\t"
static zend_always_inline void fast_long_sub_function(zval *result, zval *op1, zval *op2)
{
-#if defined(__GNUC__) && defined(__i386__) && !(4 == __GNUC__ && 8 == __GNUC_MINOR__)
+#if __has_builtin(__builtin_ssubl_overflow) && SIZEOF_LONG == SIZEOF_ZEND_LONG
+ long lresult;
+ if (UNEXPECTED(__builtin_ssubl_overflow(Z_LVAL_P(op1), Z_LVAL_P(op2), &lresult))) {
+ ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2));
+ } else {
+ ZVAL_LONG(result, lresult);
+ }
+#elif __has_builtin(__builtin_ssubll_overflow) && SIZEOF_LONG_LONG == SIZEOF_ZEND_LONG
+ long long llresult;
+ if (UNEXPECTED(__builtin_ssubl_overflow(Z_LVAL_P(op1), Z_LVAL_P(op2), &llresult))) {
+ ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2));
+ } else {
+ ZVAL_LONG(result, llresult);
+ }
+#elif defined(__GNUC__) && defined(__i386__) && !(4 == __GNUC__ && 8 == __GNUC_MINOR__)
__asm__(
"movl (%1), %%eax\n\t"
"subl (%2), %%eax\n\t"