Advertisement
Guest User

Untitled

a guest
Aug 1st, 2019
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.41 KB | None | 0 0
  1. #include <stdio.h>
  2.  
  3. #include "as_config.h"
  4.  
  5. #ifndef AS_MAX_PORTABILITY
  6. #ifdef AS_X64_MSVC
  7.  
  8. #include "as_callfunc.h"
  9. #include "as_scriptengine.h"
  10. #include "as_texts.h"
  11. #include "as_context.h"
  12.  
  13. BEGIN_AS_NAMESPACE
  14.  
  15. #if defined(__clang__)
  16. static asQWORD __attribute__((noinline)) CallX64(const asQWORD* args, const asQWORD* floatArgs, const int paramSize, asQWORD func)
  17. {
  18.     volatile asQWORD ret = 0;
  19.  
  20.     __asm__ __volatile__(
  21.         "# Move the parameters into registers before the rsp is modified\n"
  22.         "mov %1, %%r10\n" // r10 = args
  23.         "mov %2, %%r11\n" // r11 = floatArgs
  24.         "xor %%r12, %%r12\n"
  25.         "mov %3, %%r12d\n"
  26.         "mov %4, %%r14\n" // r14 = func
  27.  
  28.         "# Store the stack pointer in r15 since it is guaranteed not to change over a function call\n"
  29.         "mov %%rsp, %%r15\n"
  30.  
  31.         "# Allocate space on the stack for the arguments\n"
  32.         "# Make room for at least 4 arguments even if there are less. When\n"
  33.         "# the compiler does optimizations for speed it may use these for \n"
  34.         "# temporary storage.\n"
  35.         "mov %%r12, %%rdi\n"
  36.         "add $32,%%edi\n"
  37.  
  38.         "# Make sure the stack pointer is 16byte aligned so the\n"
  39.         "# whole program optimizations will work properly\n"
  40.         "# TODO: runtime optimize: Can this be optimized with fewer instructions?\n"
  41.         "mov %%rsp,%%rsi\n"
  42.         "sub %%rdi,%%rsi\n"
  43.         "and $0x8,%%rsi\n"
  44.         "add %%rsi,%%rdi\n"
  45.         "sub %%rdi,%%rsp\n"
  46.  
  47.         "# Jump straight to calling the function if no parameters\n"
  48.         "cmp $0,%%r12 # Compare paramSize with 0\n"
  49.         "je callfunc # Jump to call funtion if (paramSize == 0)\n"
  50.  
  51.         "# Copy arguments from script stack to application stack\n"
  52.         "# Order is (first to last):\n"
  53.         "# rcx, rdx, r8, r9 & everything else goes on stack\n"
  54.         "movq   (%%r10),%%rcx\n"
  55.         "movq  8(%%r10),%%rdx\n"
  56.         "movq 16(%%r10),%%r8\n"
  57.         "movq 24(%%r10),%%r9\n"
  58.  
  59.         "# Negate the 4 params from the size to be copied\n"
  60.         "sub $32,%%r12d\n"
  61.         "js copyfloat # Jump if negative result\n"
  62.         "jz copyfloat # Jump if zero result\n"
  63.  
  64.         "# Now copy all remaining params onto stack allowing space for first four\n"
  65.         "# params to be flushed back to the stack if required by the callee.\n"
  66.         "add $32,%%r10 # Position input pointer 4 args ahead\n"
  67.         "mov %%rsp,%%r13 # Put the stack pointer into r13\n"
  68.         "add $32,%%r13 # Leave space for first 4 args on stack\n"
  69.  
  70.         "copyoverflow:\n"
  71.         "movq (%%r10),%%rdi # Read param from source stack into rdi\n"
  72.         "movq %%rdi,(%%r13) # Copy param to real stack\n"
  73.         "add $8,%%r13 # Move virtual stack pointer\n"
  74.         "add $8,%%r10 # Move source stack pointer\n"
  75.         "sub $8,%%r12d # Decrement remaining count\n"
  76.         "jnz copyoverflow # Continue if more params\n"
  77.  
  78.         "copyfloat:\n"
  79.         "# Any floating point params?\n"
  80.         "cmp $0,%%r11\n"
  81.         "je callfunc\n"
  82.  
  83.         "movlpd   (%%r11),%%xmm0\n"
  84.         "movlpd  8(%%r11),%%xmm1\n"
  85.         "movlpd 16(%%r11),%%xmm2\n"
  86.         "movlpd 24(%%r11),%%xmm3\n"
  87.  
  88.         "callfunc:\n"
  89.         "call *%%r14\n"
  90.  
  91.         "# restore stack pointer\n"
  92.         "mov %%r15, %%rsp\n"
  93.  
  94.         "lea  %0, %%rbx\n"     // Load the address of the ret variable into rbx
  95.         "movq %%rax,(%%rbx)\n" // Copy the returned value into the ret variable
  96.  
  97.         : // no output
  98.     : "m" (ret), "r" (args), "r" (floatArgs), "r" (paramSize), "r" (func)
  99.         : "rdi", "rsi", "rsp", "rbx", "r10", "r11", "%r12", "r13", "r14", "r15"
  100.         );
  101.  
  102.     return ret;
  103. }
  104.  
  105. static asDWORD GetReturnedFloat()
  106. {
  107.     volatile asDWORD ret = 0;
  108.  
  109.     __asm__ __volatile__(
  110.         "lea      %0, %%rax\n"
  111.         "movss    %%xmm0, (%%rax)"
  112.         : /* no output */
  113.     : "m" (ret)
  114.         : "%rax"
  115.         );
  116.  
  117.     return ret;
  118. }
  119.  
  120. static asQWORD GetReturnedDouble()
  121. {
  122.     volatile asQWORD ret = 0;
  123.  
  124.     __asm__ __volatile__(
  125.         "lea     %0, %%rax\n"
  126.         "movlpd  %%xmm0, (%%rax)"
  127.         : /* no optput */
  128.     : "m" (ret)
  129.         : "%rax"
  130.         );
  131.  
  132.     return ret;
  133. }
  134. #else
  135. // These functions are implemented in as_callfunc_x64_msvc.asm
  136. extern "C" asQWORD CallX64(const asQWORD *args, const asQWORD *floatArgs, int paramSize, asQWORD func);
  137. extern "C" asDWORD GetReturnedFloat();
  138. extern "C" asQWORD GetReturnedDouble();
  139. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement