xpcom/reflect/xptcall/src/md/unix/xptcinvoke_aarch64.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /* Platform specific code to invoke XPCOM methods on native objects */
     8 #include "xptcprivate.h"
    10 #if !defined(__aarch64__)
    11 #error "This code is for Linux AArch64 only."
    12 #endif
    15 /* "Procedure Call Standard for the ARM 64-bit Architecture" document, sections
    16  * "5.4 Parameter Passing" and "6.1.2 Procedure Calling" contain all the
    17  * needed information.
    18  *
    19  * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf
    20  */
    22 #ifndef __AARCH64EL__
    23 #error "Only little endian compatibility was tested"
    24 #endif
    26 /*
    27  * Allocation of integer function arguments initially to registers r1-r7
    28  * and then to stack. Handling of 'that' argument which goes to register r0
    29  * is handled separately and does not belong here.
    30  *
    31  * 'ireg_args'  - pointer to the current position in the buffer,
    32  *                corresponding to the register arguments
    33  * 'stack_args' - pointer to the current position in the buffer,
    34  *                corresponding to the arguments on stack
    35  * 'end'        - pointer to the end of the registers argument
    36  *                buffer.
    37  */
    38 static inline void alloc_word(uint64_t* &ireg_args,
    39                               uint64_t* &stack_args,
    40                               uint64_t* end,
    41                               uint64_t  data)
    42 {
    43     if (ireg_args < end) {
    44         *ireg_args = data;
    45         ireg_args++;
    46     } else {
    47         *stack_args = data;
    48         stack_args++;
    49     }
    50 }
    52 static inline void alloc_double(double* &freg_args,
    53                                 uint64_t* &stack_args,
    54                                 double* end,
    55                                 double  data)
    56 {
    57     if (freg_args < end) {
    58         *freg_args = data;
    59         freg_args++;
    60     } else {
    61         memcpy(stack_args, &data, sizeof(data));
    62         stack_args++;
    63     }
    64 }
    66 static inline void alloc_float(double* &freg_args,
    67                                uint64_t* &stack_args,
    68                                double* end,
    69                                float  data)
    70 {
    71     if (freg_args < end) {
    72         memcpy(freg_args, &data, sizeof(data));
    73         freg_args++;
    74     } else {
    75         memcpy(stack_args, &data, sizeof(data));
    76         stack_args++;
    77     }
    78 }
    81 extern "C" void
    82 invoke_copy_to_stack(uint64_t* stk, uint64_t *end,
    83                      uint32_t paramCount, nsXPTCVariant* s)
    84 {
    85     uint64_t *ireg_args = stk;
    86     uint64_t *ireg_end  = ireg_args + 8;
    87     double *freg_args = (double *)ireg_end;
    88     double *freg_end  = freg_args + 8;
    89     uint64_t *stack_args = (uint64_t *)freg_end;
    91     // leave room for 'that' argument in x0
    92     ++ireg_args;
    94     for (uint32_t i = 0; i < paramCount; i++, s++) {
    95         if (s->IsPtrData()) {
    96             alloc_word(ireg_args, stack_args, ireg_end, (uint64_t)s->ptr);
    97             continue;
    98         }
    99         // According to the ABI, integral types that are smaller than 8 bytes
   100         // are to be passed in 8-byte registers or 8-byte stack slots.
   101         switch (s->type) {
   102             case nsXPTType::T_FLOAT:
   103                 alloc_float(freg_args, stack_args, freg_end, s->val.f);
   104                 break;
   105             case nsXPTType::T_DOUBLE:
   106                 alloc_double(freg_args, stack_args, freg_end, s->val.d);
   107                 break;
   108             case nsXPTType::T_I8:  alloc_word(ireg_args, stk, end, s->val.i8);   break;
   109             case nsXPTType::T_I16: alloc_word(ireg_args, stk, end, s->val.i16);  break;
   110             case nsXPTType::T_I32: alloc_word(ireg_args, stk, end, s->val.i32);  break;
   111             case nsXPTType::T_I64: alloc_word(ireg_args, stk, end, s->val.i64);  break;
   112             case nsXPTType::T_U8:  alloc_word(ireg_args, stk, end, s->val.u8);   break;
   113             case nsXPTType::T_U16: alloc_word(ireg_args, stk, end, s->val.u16);  break;
   114             case nsXPTType::T_U32: alloc_word(ireg_args, stk, end, s->val.u32);  break;
   115             case nsXPTType::T_U64: alloc_word(ireg_args, stk, end, s->val.u64);  break;
   116             case nsXPTType::T_BOOL: alloc_word(ireg_args, stk, end, s->val.b);   break;
   117             case nsXPTType::T_CHAR: alloc_word(ireg_args, stk, end, s->val.c);   break;
   118             case nsXPTType::T_WCHAR: alloc_word(ireg_args, stk, end, s->val.wc); break;
   119             default:
   120                 // all the others are plain pointer types
   121                 alloc_word(ireg_args, stack_args, ireg_end,
   122                            reinterpret_cast<uint64_t>(s->val.p));
   123                 break;
   124         }
   125     }
   126 }
   128 extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
   129                                       uint32_t paramCount, nsXPTCVariant* params);
   131 EXPORT_XPCOM_API(nsresult)
   132 NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
   133                  uint32_t paramCount, nsXPTCVariant* params)
   134 {
   135     return _NS_InvokeByIndex(that, methodIndex, paramCount, params);
   136 }

mercurial