#ifndef COSMOPOLITAN_LIBC_BITS_PUSHPOP_H_
#define COSMOPOLITAN_LIBC_BITS_PUSHPOP_H_
#include "libc/macros.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)

/**
 * PushPop
 * An elegant weapon for a more civilized age.
 */
#if !defined(__GNUC__) || defined(__STRICT_ANSI__)
#define pushpop(x) (x)
#else
#define pushpop(x)                                                           \
  ({                                                                         \
    typeof(x) Popped;                                                        \
    if (isconstant(x) && (TYPE_SIGNED(typeof(x)) ? (intptr_t)(x) + 128 < 256 \
                                                 : (intptr_t)(x) < 128)) {   \
      if (x) {                                                               \
        asm("push\t%1\n\t"                                                   \
            "pop\t%q0"                                                       \
            : "=r"(Popped)                                                   \
            : "ir"(x));                                                      \
      } else {                                                               \
        asm("xor\t%k0,%k0" : "=r"(Popped));                                  \
      }                                                                      \
    } else {                                                                 \
      asm("" : "=r"(Popped) : "0"(x));                                       \
    }                                                                        \
    Popped;                                                                  \
  })
#endif

#if !defined(__GNUC__) || defined(__STRICT_ANSI__)
#define pushmov(d, x) (*(d) = (x))
#else
#define pushmov(d, x)                                                        \
  ({                                                                         \
    typeof(*(d)) Popped = (x);                                               \
    if (isconstant(x) && (TYPE_SIGNED(typeof(x)) ? (intptr_t)(x) + 128 < 256 \
                                                 : (intptr_t)(x) < 128)) {   \
      asm("pushq\t%1\n\t"                                                    \
          "popq\t%0"                                                         \
          : "=m"(*(d))                                                       \
          : "ir"(Popped));                                                   \
    } else {                                                                 \
      *(d) = Popped;                                                         \
    }                                                                        \
    Popped;                                                                  \
  })
#endif

#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_BITS_PUSHPOP_H_ */
