github.com/notti/nocgo@v0.0.0-20190619201224-fc443047424c/internal/ffi/call_amd64.s (about)

     1  #include "textflag.h"
     2  #include "go_asm.h"
     3  
     4  // runtime has #include "go_asm.h"
     5  // we need to fake the defines here:
     6  #define slice_array 0
     7  #define slice_len 8
     8  #define slice_cap 16
     9  
    10  
    11  #define LOADREG(off, target) \
    12      MOVLQSX spec_intargs+argument__size*off(R12), AX \
    13      TESTQ AX, AX \
    14      JS xmm \
    15      MOVWQZX AX, R11 \
    16      SHRL $16, AX \
    17      ADDQ R13, R11 \
    18      CMPB AX, $const_type64 \
    19      JNE 3(PC) \
    20      MOVQ 0(R11), target \ // 64bit
    21      JMP 20(PC) \
    22      CMPB AX, $const_typeS32 \
    23      JNE 3(PC) \
    24      MOVLQSX 0(R11), target \ // signed 32 bit
    25      JMP 18(PC) \
    26      CMPB AX, $const_typeU32 \
    27      JNE 3(PC) \
    28      MOVLQZX 0(R11), target \ // unsigned 32 bit
    29      JMP 14(PC) \
    30      CMPB AX, $const_typeS16 \
    31      JNE 3(PC) \
    32      MOVWQSX 0(R11), target \ // signed 16 bit
    33      JMP 10(PC) \
    34      CMPB AX, $const_typeU16 \
    35      JNE 3(PC) \
    36      MOVWQZX 0(R11), target \ // unsigned 16 bit
    37      JMP 6(PC) \
    38      CMPB AX, $const_typeS8 \
    39      JNE 3(PC) \
    40      MOVBQSX 0(R11), target \ // signed 8 bit
    41      JMP 2(PC) \
    42      MOVBQZX 0(R11), target // unsigned 8 bit
    43  
    44  #define LOADXMMREG(off, target) \
    45      MOVLQSX spec_xmmargs+argument__size*off(R12), AX \
    46      TESTQ AX, AX \
    47      JS prepared \
    48      MOVWQZX AX, R11 \
    49      SHRL $16, AX \
    50      ADDQ R13, R11 \
    51      CMPB AX, $const_typeDouble \
    52      JNE 3(PC) \
    53      MOVSD 0(R11), target \ // float 64bit
    54      JMP 2(PC) \
    55      MOVSS 0(R11), target \ // float 32bit
    56  
    57  TEXT ·cgocall(SB),NOSPLIT,$0
    58      JMP runtime·cgocall(SB)
    59  
    60  // pass struct { &args, &spec } to cgocall
    61  TEXT ·callWrapper(SB),NOSPLIT|WRAPPER,$32
    62      MOVQ DX, 24(SP)
    63      LEAQ argframe+0(FP), AX
    64      MOVQ AX, 16(SP)
    65      LEAQ 16(SP), AX
    66      MOVQ AX, 8(SP)
    67      LEAQ asmcall(SB), AX
    68      MOVQ AX, 0(SP)
    69      CALL ·cgocall(SB)
    70      RET
    71  
    72  TEXT asmcall(SB),NOSPLIT,$0
    73      MOVQ 8(DI), R12      // spec (preserved)
    74      MOVQ 0(DI), R13      // base of args (preserved)
    75      MOVQ SP, R14         // stack for restoring later on (preserved)
    76  
    77      ANDQ $~0x1F, SP // 32 byte alignment for cdecl (in case someone wants to pass __m256 on the stack)
    78      // for no __m256 16 byte would be ok
    79      // this is actually already done by cgocall - but asmcall was called from there and destroys that :(
    80  
    81      MOVQ spec_stack+slice_len(R12), AX // length of stack registers
    82      TESTQ AX, AX
    83      JZ reg
    84  
    85      // ok we have stack arguments so let's do that first
    86  
    87      // Fix alignment depending on number of arguments
    88      MOVQ AX, BX
    89      ANDQ $3, BX
    90      SHLQ $3, BX
    91      SUBQ BX, SP
    92  
    93      MOVQ spec_stack+slice_array(R12), BX
    94  
    95  next:
    96      DECQ AX
    97      MOVQ (BX)(AX*argument__size), CX
    98      //check type and push to stack
    99      MOVWQZX CX, R11
   100      SHRL $16, CX
   101      ADDQ R13, R11
   102  
   103  #define LOADSTACK(type, instr) \
   104      CMPB CX, type \
   105      JNE 7(PC) \
   106      SUBQ $8, SP \
   107      instr 0(R11), CX \
   108      instr CX, 0(SP) \
   109      TESTQ AX, AX \
   110      JZ reg \
   111      JMP next
   112  
   113      LOADSTACK($const_type64, MOVQ)
   114      LOADSTACK($const_typeU32, MOVL)
   115      LOADSTACK($const_typeU16, MOVW)
   116      LOADSTACK($const_typeU8, MOVB)
   117  
   118      INT $3
   119  
   120  reg:
   121      // load register arguments
   122      LOADREG(0, DI)
   123      LOADREG(1, SI)
   124      LOADREG(2, DX)
   125      LOADREG(3, CX)
   126      LOADREG(4, R8)
   127      LOADREG(5, R9)
   128  
   129  xmm:
   130      // load xmm arguments
   131      LOADXMMREG(0, X0)
   132      LOADXMMREG(1, X1)
   133      LOADXMMREG(2, X2)
   134      LOADXMMREG(3, X3)
   135      LOADXMMREG(4, X4)
   136      LOADXMMREG(5, X5)
   137      LOADXMMREG(6, X6)
   138      LOADXMMREG(7, X7)
   139  
   140  prepared:
   141      // load number of vector registers
   142      MOVBQSX spec_rax(R12), AX
   143  
   144      // do the actuall call
   145      CALL spec_fn(R12)
   146  
   147      MOVQ R14, SP
   148  
   149      // TODO: check R13, if it still points to the correct stack! (could happen if we have a callback into go that splits the stack)
   150  
   151      // store ret
   152      MOVLQSX spec_ret(R12), BX
   153      TESTQ BX, BX
   154      JS DONE
   155      MOVWQZX BX, R11
   156      SHRL $16, BX
   157      ADDQ R13, R11
   158  
   159      CMPB BX, $const_type64
   160      JNE 3(PC)
   161      MOVQ AX, (R11)
   162      JMP DONE
   163  
   164      CMPB BX, $const_typeU32
   165      JNE 3(PC)
   166      MOVL AX, (R11)
   167      JMP DONE
   168  
   169      CMPB BX, $const_typeU16
   170      JNE 3(PC)
   171      MOVW AX, (R11)
   172      JMP DONE
   173  
   174      CMPB BX, $const_typeU8
   175      JNE 3(PC)
   176      MOVB AX, (R11)
   177      JMP DONE
   178  
   179      CMPB BX, $const_typeDouble
   180      JNE 3(PC)
   181      MOVSD X0, (R11)
   182      JMP DONE
   183  
   184      CMPB BX, $const_typeFloat
   185      JNE 3(PC)
   186      MOVSS X0, (R11)
   187      JMP DONE
   188  
   189      INT $3
   190  
   191  DONE:
   192      RET