54 lines
2.8 KiB
C
54 lines
2.8 KiB
C
#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_ */
|