#ifndef SECTORLISP_H_ #define SECTORLISP_H_ #include #include #include /*───────────────────────────────────────────────────────────────────────────│─╗ │ 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" : "=@ccz"(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_ */