123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- #ifndef SECTORLISP_H_
- #define SECTORLISP_H_
- #include <unistd.h>
- #include <termios.h>
- #include <sys/ioctl.h>
- /*───────────────────────────────────────────────────────────────────────────│─╗
- │ The LISP Challenge § Richard Stallman Math 55 Systems Integration Code ─╬─│┼
- ╚────────────────────────────────────────────────────────────────────────────│*/
- #define CompilerBarrier() asm volatile("" ::: "memory")
- #define ISATOM(x) /* a.k.a. !(x&1) */ \
- ({ \
- _Bool IsAtom; \
- asm("test%z1\t$1,%1" : "=@ccnz"(IsAtom) : "Qm"((char)x)); \
- IsAtom; \
- })
- #define OBJECT(t, v) /* a.k.a. v<<1|t */ \
- ({ \
- __typeof(v) Val = (v); \
- asm("shl\t%0" : "+r"(Val)); \
- Val | (t); \
- })
- #define SUB(x, y) /* a.k.a. x-y */ \
- ({ \
- __typeof(x) Reg = (x); \
- asm("sub\t%1,%0" : "+rm"(Reg) : "g"(y)); \
- Reg; \
- })
- #define STOS(di, c) asm("stos%z1" : "+D"(di), "=m"(*(di)) : "a"(c))
- #define LODS(si) \
- ({ \
- typeof(*(si)) c; \
- asm("lods%z2" : "+S"(si), "=a"(c) : "m"(*(si))); \
- c; \
- })
- static inline void *SetMemory(void *di, int al, unsigned long cx) {
- asm("rep stosb"
- : "=D"(di), "=c"(cx), "=m"(*(char(*)[cx])di)
- : "0"(di), "1"(cx), "a"(al));
- return di;
- }
- static inline void *CopyMemory(void *di, const void *si, unsigned long cx) {
- asm("rep movsb"
- : "=D"(di), "=S"(si), "=c"(cx), "=m"(*(char(*)[cx])di)
- : "0"(di), "1"(si), "2"(cx));
- return di;
- }
- static void RawMode(void) {
- #ifndef __REAL_MODE__
- struct termios t;
- if (ioctl(1, TCGETS, &t) != -1) {
- t.c_cc[VMIN] = 1;
- t.c_cc[VTIME] = 1;
- t.c_iflag &= ~(INPCK | ISTRIP | PARMRK | INLCR | IGNCR | ICRNL | IXON);
- t.c_lflag &= ~(IEXTEN | ICANON | ECHO | ECHONL);
- t.c_cflag &= ~(CSIZE | PARENB);
- t.c_oflag &= ~OPOST;
- t.c_cflag |= CS8;
- t.c_iflag |= IUTF8;
- ioctl(1, TCSETS, &t);
- }
- #endif
- }
- __attribute__((__noinline__)) static void PrintChar(long c) {
- #ifdef __REAL_MODE__
- asm volatile("mov\t$0x0E,%%ah\n\t"
- "int\t$0x10"
- : /* no outputs */
- : "a"(c), "b"(7)
- : "memory");
- #else
- static short buf;
- int rc;
- buf = c;
- write(1, &buf, 1);
- #endif
- }
- static int ReadChar(void) {
- int c;
- #ifdef __REAL_MODE__
- asm volatile("int\t$0x16" : "=a"(c) : "0"(0) : "memory");
- c &= 0xff;
- #else
- static int buf;
- read(0, &buf, 1);
- c = buf;
- #endif
- return c;
- }
- #define PEEK_(REG, BASE, INDEX, DISP) \
- ({ \
- __typeof(*(BASE)) Reg; \
- if (__builtin_constant_p(INDEX) && !(INDEX)) { \
- asm("mov\t%c2(%1),%0" \
- : REG(Reg) \
- : "bDS"(BASE), "i"((DISP) * sizeof(*(BASE))), \
- "m"(BASE[(INDEX) + (DISP)])); \
- } else { \
- asm("mov\t%c3(%1,%2),%0" \
- : REG(Reg) \
- : "b"(BASE), "DS"((long)(INDEX) * sizeof(*(BASE))), \
- "i"((DISP) * sizeof(*(BASE))), "m"(BASE[(INDEX) + (DISP)])); \
- } \
- Reg; \
- })
- #define PEEK(BASE, INDEX, DISP) /* a.k.a. b[i] */ \
- (sizeof(*(BASE)) == 1 ? PEEK_("=Q", BASE, INDEX, DISP) \
- : PEEK_("=r", BASE, INDEX, DISP))
- #define PEEK_ARRAY_(REG, OBJECT, MEMBER, INDEX, DISP) \
- ({ \
- __typeof(*(OBJECT->MEMBER)) Reg; \
- if (!(OBJECT)) { \
- asm("mov\t%c2(%1),%0" \
- : REG(Reg) \
- : "bDS"((long)(INDEX) * sizeof(*(OBJECT->MEMBER))), \
- "i"(__builtin_offsetof(__typeof(*(OBJECT)), MEMBER) + \
- sizeof(*(OBJECT->MEMBER)) * (DISP)), \
- "m"(OBJECT->MEMBER)); \
- } else { \
- asm("mov\t%c3(%1,%2),%0" \
- : REG(Reg) \
- : "b"(OBJECT), "DS"((long)(INDEX) * sizeof(*(OBJECT->MEMBER))), \
- "i"(__builtin_offsetof(__typeof(*(OBJECT)), MEMBER) + \
- sizeof(*(OBJECT->MEMBER)) * (DISP)), \
- "m"(OBJECT->MEMBER)); \
- } \
- Reg; \
- })
- #define PEEK_ARRAY(OBJECT, MEMBER, INDEX, DISP) /* o->m[i] */ \
- (sizeof(*(OBJECT->MEMBER)) == 1 \
- ? PEEK_ARRAY_("=Q", OBJECT, MEMBER, INDEX, DISP) \
- : PEEK_ARRAY_("=r", OBJECT, MEMBER, INDEX, DISP))
- #define POKE_ARRAY_(REG, OBJECT, MEMBER, INDEX, DISP, VALUE) \
- do { \
- if (!(OBJECT)) { \
- asm("mov\t%1,%c3(%2)" \
- : "=m"(OBJECT->MEMBER) \
- : REG((__typeof(*(OBJECT->MEMBER)))(VALUE)), \
- "bDS"((long)(INDEX) * sizeof(*(OBJECT->MEMBER))), \
- "i"(__builtin_offsetof(__typeof(*(OBJECT)), MEMBER) + \
- sizeof(*(OBJECT->MEMBER)) * (DISP))); \
- } else { \
- asm("mov\t%1,%c4(%2,%3)" \
- : "=m"(OBJECT->MEMBER) \
- : REG((__typeof(*(OBJECT->MEMBER)))(VALUE)), "b"(OBJECT), \
- "DS"((long)(INDEX) * sizeof(*(OBJECT->MEMBER))), \
- "i"(__builtin_offsetof(__typeof(*(OBJECT)), MEMBER) + \
- sizeof(*(OBJECT->MEMBER)) * (DISP))); \
- } \
- } while (0)
- #define POKE_ARRAY(OBJECT, MEMBER, INDEX, DISP, VALUE) /* o->m[i]=v */ \
- do { \
- __typeof(*(OBJECT->MEMBER)) Reg; \
- switch (sizeof(*(OBJECT->MEMBER))) { \
- case 1: \
- POKE_ARRAY_("Q", OBJECT, MEMBER, INDEX, DISP, VALUE); \
- break; \
- default: \
- POKE_ARRAY_("r", OBJECT, MEMBER, INDEX, DISP, VALUE); \
- break; \
- } \
- } while (0)
- #endif /* SECTORLISP_H_ */
|