Advertisement
Guest User

rpn-jit.c

a guest
Mar 20th, 2015
356
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.62 KB | None | 0 0
  1. /* http://redd.it/2zna5q */
  2. #define _BSD_SOURCE  // MAP_ANONYMOUS
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <stdint.h>
  6. #include <string.h>
  7. #include <unistd.h>
  8.  
  9. struct asmbuf {
  10.     size_t nconstants;
  11.     double constants[32];
  12.     size_t size, fill;
  13.     uint8_t code[];
  14. };
  15.  
  16. #ifdef __WIN32__
  17. #include <windows.h>
  18.  
  19. struct asmbuf *
  20. asmbuf_create(void)
  21. {
  22.     SYSTEM_INFO system_info;
  23.     GetSystemInfo(&system_info);
  24.     long page_size = system_info.dwPageSize;
  25.     struct asmbuf *buf =
  26.         VirtualAlloc(NULL, page_size, MEM_COMMIT, PAGE_READWRITE);
  27.     buf->size = page_size;
  28.     return buf;
  29. }
  30.  
  31. void
  32. asmbuf_free(struct asmbuf *buf)
  33. {
  34.     VirtualFree(buf, buf->size, MEM_RELEASE);
  35. }
  36.  
  37. void
  38. asmbuf_finalize(struct asmbuf *buf)
  39. {
  40.     DWORD old_protect;
  41.     VirtualProtect(buf, buf->size, PAGE_EXECUTE_READ, &old_protect);
  42. }
  43. #else /* POSIX */
  44. #include <sys/mman.h>
  45.  
  46. struct asmbuf *
  47. asmbuf_create(void)
  48. {
  49.     long page_size = sysconf(_SC_PAGESIZE);
  50.     int prot = PROT_READ | PROT_WRITE;
  51.     int flags = MAP_ANONYMOUS | MAP_PRIVATE;
  52.     struct asmbuf *buf = mmap(NULL, page_size, prot, flags, -1, 0);
  53.     buf->size = page_size;
  54.     return buf;
  55. }
  56.  
  57. void
  58. asmbuf_free(struct asmbuf *buf)
  59. {
  60.     munmap(buf, buf->size);
  61. }
  62.  
  63. void
  64. asmbuf_finalize(struct asmbuf *buf)
  65. {
  66.     mprotect(buf, buf->size, PROT_READ | PROT_EXEC);
  67. }
  68. #endif
  69.  
  70. void
  71. asmbuf_ins(struct asmbuf *buf, int size, uint64_t ins)
  72. {
  73.     for (int i = size - 1; i >= 0; i--)
  74.         buf->code[buf->fill++] = (ins >> (i * 8)) & 0xff;
  75. }
  76.  
  77. void
  78. asmbuf_immediate(struct asmbuf *buf, int size, const void *value)
  79. {
  80.     memcpy(buf->code + buf->fill, value, size);
  81.     buf->fill += size;
  82. }
  83.  
  84. static void
  85. load2(struct asmbuf *buf)
  86. {
  87.     asmbuf_ins(buf, 6, 0x660f1244cff0); // movlpd  -16(%rdi, %rcx, 8), %xmm0
  88.     asmbuf_ins(buf, 6, 0x660f124ccff8); // movlpd  -8(%rdi, %rcx, 8), %xmm1
  89. }
  90.  
  91. static void
  92. store1(struct asmbuf *buf)
  93. {
  94.     asmbuf_ins(buf, 3, 0x48ffc9);       // dec     %rcx
  95.     asmbuf_ins(buf, 6, 0x660f1344cff8); // movlpd  %xmm0, -8(%rdi, %rcx, 8)
  96. }
  97.  
  98. int
  99. main(void)
  100. {
  101.     /* %rdi  : pointer to the base of the stack
  102.      * %rsi  : index of the top of the stack when called
  103.      * %rcx  : index of the current top of the stack
  104.      * %xmm* : intermediate results
  105.      */
  106.     struct asmbuf *buf = asmbuf_create();
  107.     asmbuf_ins(buf, 3, 0x4889f1);  // mov   %rsi, %rcx
  108.     int c;
  109.     while ((c = fgetc(stdin)) != '\n' && c != EOF) {
  110.         if (c == ' ')
  111.             continue;
  112.         switch (c) {
  113.         case '0':
  114.         case '1':
  115.         case '2':
  116.         case '3':
  117.         case '4':
  118.         case '5':
  119.         case '6':
  120.         case '7':
  121.         case '8':
  122.         case '9': {
  123.             ungetc(c, stdin);
  124.             double *data = &buf->constants[buf->nconstants++];
  125.             scanf("%lf", data);
  126.             asmbuf_ins(buf, 2, 0x48a1);     // mov   (data), %rax
  127.             asmbuf_immediate(buf, 8, &data);
  128.             asmbuf_ins(buf, 4, 0x488904cf); // mov   %rax, (%rdi, %rcx, 8)
  129.             asmbuf_ins(buf, 3, 0x48ffc1);   // inc   %rcx
  130.         } break;
  131.         case '(': {
  132.             int n;
  133.             scanf("%d)", &n);
  134.             int8_t offset = -8 * n;
  135.             asmbuf_ins(buf, 4, 0x488b44f7); // mov   -offset(%rdi,%rsi,8),%rax
  136.             asmbuf_immediate(buf, 1, &offset);
  137.             asmbuf_ins(buf, 4, 0x488904cf); // mov   %rax, (%rdi, %rcx, 8)
  138.             asmbuf_ins(buf, 3, 0x48ffc1);   // inc   %rcx
  139.         } break;
  140.         case '+':
  141.             load2(buf);
  142.             asmbuf_ins(buf, 4, 0xf20f58c1);     // addsd  %xmm1,%xmm0
  143.             store1(buf);
  144.             break;
  145.         case '-':
  146.             load2(buf);
  147.             asmbuf_ins(buf, 4, 0xf20f5cc1);     // subsd  %xmm1,%xmm0
  148.             store1(buf);
  149.             break;
  150.         case '*':
  151.             load2(buf);
  152.             asmbuf_ins(buf, 4, 0xf20f59c1);     // mulsd  %xmm1,%xmm0
  153.             store1(buf);
  154.             break;
  155.         case '/':
  156.             load2(buf);
  157.             asmbuf_ins(buf, 4, 0xf20f5ec1);     // divsd  %xmm1,%xmm0
  158.             store1(buf);
  159.             break;
  160.         case 'Q':
  161.             asmbuf_ins(buf, 6, 0x660f124ccff8); // movlpd -8(%rdi,%rcx,8),%xmm1
  162.             asmbuf_ins(buf, 4, 0xf20f51c9);     // sqrtsd %xmm1,%xmm1
  163.             asmbuf_ins(buf, 6, 0x660f134ccff8); // movlpd %xmm1,-8(%rdi,%rcx,8)
  164.             break;
  165.         case '@':
  166.             asmbuf_ins(buf, 6, 0x660f124ccff8); // movlpd -8(%rdi,%rcx,8),%xmm1
  167.             asmbuf_ins(buf, 6, 0x660f134ccff8); // movlpd %xmm1,-8(%rdi,%rcx,8)
  168.             break;
  169.         }
  170.     }
  171.     asmbuf_ins(buf, 3, 0x4889c8); // mov   %rcx, %rax
  172.     asmbuf_ins(buf, 1, 0xc3);     // retq
  173.     asmbuf_finalize(buf);
  174.     __attribute__ ((sysv_abi))
  175.         long (*recurrence)(double *, long) = (void *)buf->code;
  176.  
  177.     /* Accept up to 64 initial values. */
  178.     double init[64] = {0};
  179.     long nelements = 0;
  180.     long max;
  181.     for (;;) {
  182.         char line[256];
  183.         fgets(line, sizeof(line), stdin);
  184.         long n;
  185.         double value;
  186.         if (sscanf(line, "%ld:%lf", &n, &value) != 2) {
  187.             max = strtol(line, NULL, 10);
  188.             break;
  189.         } else {
  190.             init[n] = value;
  191.             if (n + 1 > nelements)
  192.                 nelements = n + 1;
  193.         }
  194.     }
  195.  
  196.     /* Fill out the stack. */
  197.     double stack[max + 64];
  198.     memcpy(stack, init, sizeof(init));
  199.     for (int n = 0; n < nelements; n++)
  200.         printf("%d: %f\n", n, stack[n]);
  201.     for (int n = nelements; n <= max; n++) {
  202.         nelements = recurrence(stack, nelements);
  203.         printf("%d: %f\n", n, stack[nelements - 1]);
  204.     }
  205.  
  206.     return 0;
  207. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement