lisp.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #ifndef SECTORLISP_H_
  2. #define SECTORLISP_H_
  3. #include <unistd.h>
  4. #include <termios.h>
  5. #include <sys/ioctl.h>
  6. /*───────────────────────────────────────────────────────────────────────────│─╗
  7. │ The LISP Challenge § Richard Stallman Math 55 Systems Integration Code ─╬─│┼
  8. ╚────────────────────────────────────────────────────────────────────────────│*/
  9. #define CompilerBarrier() asm volatile("" ::: "memory")
  10. #define ISATOM(x) /* a.k.a. !(x&1) */ \
  11. ({ \
  12. _Bool IsAtom; \
  13. asm("test%z1\t$1,%1" : "=@ccnz"(IsAtom) : "Qm"((char)x)); \
  14. IsAtom; \
  15. })
  16. #define OBJECT(t, v) /* a.k.a. v<<1|t */ \
  17. ({ \
  18. __typeof(v) Val = (v); \
  19. asm("shl\t%0" : "+r"(Val)); \
  20. Val | (t); \
  21. })
  22. #define SUB(x, y) /* a.k.a. x-y */ \
  23. ({ \
  24. __typeof(x) Reg = (x); \
  25. asm("sub\t%1,%0" : "+rm"(Reg) : "g"(y)); \
  26. Reg; \
  27. })
  28. #define STOS(di, c) asm("stos%z1" : "+D"(di), "=m"(*(di)) : "a"(c))
  29. #define LODS(si) \
  30. ({ \
  31. typeof(*(si)) c; \
  32. asm("lods%z2" : "+S"(si), "=a"(c) : "m"(*(si))); \
  33. c; \
  34. })
  35. static inline void *SetMemory(void *di, int al, unsigned long cx) {
  36. asm("rep stosb"
  37. : "=D"(di), "=c"(cx), "=m"(*(char(*)[cx])di)
  38. : "0"(di), "1"(cx), "a"(al));
  39. return di;
  40. }
  41. static inline void *CopyMemory(void *di, const void *si, unsigned long cx) {
  42. asm("rep movsb"
  43. : "=D"(di), "=S"(si), "=c"(cx), "=m"(*(char(*)[cx])di)
  44. : "0"(di), "1"(si), "2"(cx));
  45. return di;
  46. }
  47. static void RawMode(void) {
  48. #ifndef __REAL_MODE__
  49. struct termios t;
  50. if (ioctl(1, TCGETS, &t) != -1) {
  51. t.c_cc[VMIN] = 1;
  52. t.c_cc[VTIME] = 1;
  53. t.c_iflag &= ~(INPCK | ISTRIP | PARMRK | INLCR | IGNCR | ICRNL | IXON);
  54. t.c_lflag &= ~(IEXTEN | ICANON | ECHO | ECHONL);
  55. t.c_cflag &= ~(CSIZE | PARENB);
  56. t.c_oflag &= ~OPOST;
  57. t.c_cflag |= CS8;
  58. t.c_iflag |= IUTF8;
  59. ioctl(1, TCSETS, &t);
  60. }
  61. #endif
  62. }
  63. __attribute__((__noinline__)) static void PrintChar(long c) {
  64. #ifdef __REAL_MODE__
  65. asm volatile("mov\t$0x0E,%%ah\n\t"
  66. "int\t$0x10"
  67. : /* no outputs */
  68. : "a"(c), "b"(7)
  69. : "memory");
  70. #else
  71. static short buf;
  72. int rc;
  73. buf = c;
  74. write(1, &buf, 1);
  75. #endif
  76. }
  77. static int ReadChar(void) {
  78. int c;
  79. #ifdef __REAL_MODE__
  80. asm volatile("int\t$0x16" : "=a"(c) : "0"(0) : "memory");
  81. c &= 0xff;
  82. #else
  83. static int buf;
  84. read(0, &buf, 1);
  85. c = buf;
  86. #endif
  87. return c;
  88. }
  89. #define PEEK_(REG, BASE, INDEX, DISP) \
  90. ({ \
  91. __typeof(*(BASE)) Reg; \
  92. if (__builtin_constant_p(INDEX) && !(INDEX)) { \
  93. asm("mov\t%c2(%1),%0" \
  94. : REG(Reg) \
  95. : "bDS"(BASE), "i"((DISP) * sizeof(*(BASE))), \
  96. "m"(BASE[(INDEX) + (DISP)])); \
  97. } else { \
  98. asm("mov\t%c3(%1,%2),%0" \
  99. : REG(Reg) \
  100. : "b"(BASE), "DS"((long)(INDEX) * sizeof(*(BASE))), \
  101. "i"((DISP) * sizeof(*(BASE))), "m"(BASE[(INDEX) + (DISP)])); \
  102. } \
  103. Reg; \
  104. })
  105. #define PEEK(BASE, INDEX, DISP) /* a.k.a. b[i] */ \
  106. (sizeof(*(BASE)) == 1 ? PEEK_("=Q", BASE, INDEX, DISP) \
  107. : PEEK_("=r", BASE, INDEX, DISP))
  108. #define PEEK_ARRAY_(REG, OBJECT, MEMBER, INDEX, DISP) \
  109. ({ \
  110. __typeof(*(OBJECT->MEMBER)) Reg; \
  111. if (!(OBJECT)) { \
  112. asm("mov\t%c2(%1),%0" \
  113. : REG(Reg) \
  114. : "bDS"((long)(INDEX) * sizeof(*(OBJECT->MEMBER))), \
  115. "i"(__builtin_offsetof(__typeof(*(OBJECT)), MEMBER) + \
  116. sizeof(*(OBJECT->MEMBER)) * (DISP)), \
  117. "m"(OBJECT->MEMBER)); \
  118. } else { \
  119. asm("mov\t%c3(%1,%2),%0" \
  120. : REG(Reg) \
  121. : "b"(OBJECT), "DS"((long)(INDEX) * sizeof(*(OBJECT->MEMBER))), \
  122. "i"(__builtin_offsetof(__typeof(*(OBJECT)), MEMBER) + \
  123. sizeof(*(OBJECT->MEMBER)) * (DISP)), \
  124. "m"(OBJECT->MEMBER)); \
  125. } \
  126. Reg; \
  127. })
  128. #define PEEK_ARRAY(OBJECT, MEMBER, INDEX, DISP) /* o->m[i] */ \
  129. (sizeof(*(OBJECT->MEMBER)) == 1 \
  130. ? PEEK_ARRAY_("=Q", OBJECT, MEMBER, INDEX, DISP) \
  131. : PEEK_ARRAY_("=r", OBJECT, MEMBER, INDEX, DISP))
  132. #define POKE_ARRAY_(REG, OBJECT, MEMBER, INDEX, DISP, VALUE) \
  133. do { \
  134. if (!(OBJECT)) { \
  135. asm("mov\t%1,%c3(%2)" \
  136. : "=m"(OBJECT->MEMBER) \
  137. : REG((__typeof(*(OBJECT->MEMBER)))(VALUE)), \
  138. "bDS"((long)(INDEX) * sizeof(*(OBJECT->MEMBER))), \
  139. "i"(__builtin_offsetof(__typeof(*(OBJECT)), MEMBER) + \
  140. sizeof(*(OBJECT->MEMBER)) * (DISP))); \
  141. } else { \
  142. asm("mov\t%1,%c4(%2,%3)" \
  143. : "=m"(OBJECT->MEMBER) \
  144. : REG((__typeof(*(OBJECT->MEMBER)))(VALUE)), "b"(OBJECT), \
  145. "DS"((long)(INDEX) * sizeof(*(OBJECT->MEMBER))), \
  146. "i"(__builtin_offsetof(__typeof(*(OBJECT)), MEMBER) + \
  147. sizeof(*(OBJECT->MEMBER)) * (DISP))); \
  148. } \
  149. } while (0)
  150. #define POKE_ARRAY(OBJECT, MEMBER, INDEX, DISP, VALUE) /* o->m[i]=v */ \
  151. do { \
  152. __typeof(*(OBJECT->MEMBER)) Reg; \
  153. switch (sizeof(*(OBJECT->MEMBER))) { \
  154. case 1: \
  155. POKE_ARRAY_("Q", OBJECT, MEMBER, INDEX, DISP, VALUE); \
  156. break; \
  157. default: \
  158. POKE_ARRAY_("r", OBJECT, MEMBER, INDEX, DISP, VALUE); \
  159. break; \
  160. } \
  161. } while (0)
  162. #endif /* SECTORLISP_H_ */