mozilla-aarch64-bmo-963024.patch
changeset 715 e1c226a4de34
equal deleted inserted replaced
714:b686e856c800 715:e1c226a4de34
       
     1 
       
     2 # HG changeset patch
       
     3 # User Marcin Juszkiewicz <mjuszkiewicz@redhat.com>
       
     4 # Date 1393440196 18000
       
     5 # Node ID d56b5c1a557348d4ac14a4d1ea7a5b5d240e3647
       
     6 # Parent  6a46f53ad944b44385398822d7bcf7621a785d91
       
     7 Bug 963024 - AArch64 support for XPCOM. r=froydnj
       
     8 
       
     9 diff --git a/xpcom/reflect/xptcall/src/md/unix/moz.build b/xpcom/reflect/xptcall/src/md/unix/moz.build
       
    10 --- a/xpcom/reflect/xptcall/src/md/unix/moz.build
       
    11 +++ b/xpcom/reflect/xptcall/src/md/unix/moz.build
       
    12 @@ -144,16 +144,23 @@ if CONFIG['OS_ARCH'] == 'NetBSD':
       
    13      if CONFIG['OS_TEST'] in ('amiga', 'atari', 'hp300', 'mac68k', 'mvme68k',
       
    14                               'next68k', 'sun3', 'sun3x', 'x68k'):
       
    15          SOURCES += [
       
    16              'xptcinvoke_netbsd_m68k.cpp',
       
    17              'xptcstubs_netbsd_m68k.cpp'
       
    18          ]
       
    19  
       
    20  if CONFIG['OS_ARCH'] == 'Linux':
       
    21 +    if CONFIG['OS_TEST'] == 'aarch64':
       
    22 +        SOURCES += [
       
    23 +            'xptcinvoke_aarch64.cpp',
       
    24 +            'xptcinvoke_asm_aarch64.s',
       
    25 +            'xptcstubs_aarch64.cpp',
       
    26 +            'xptcstubs_asm_aarch64.s',
       
    27 +        ]
       
    28      if CONFIG['OS_TEST'] == 'm68k':
       
    29          SOURCES += [
       
    30              'xptcinvoke_linux_m68k.cpp',
       
    31              'xptcstubs_linux_m68k.cpp',
       
    32          ]
       
    33      if CONFIG['OS_TEST'].find('mips') != -1:
       
    34          if CONFIG['OS_TEST'].find('mips64') != -1:
       
    35              SOURCES += [
       
    36 diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_aarch64.cpp b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_aarch64.cpp
       
    37 new file mode 100644
       
    38 --- /dev/null
       
    39 +++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_aarch64.cpp
       
    40 @@ -0,0 +1,136 @@
       
    41 +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       
    42 +/* This Source Code Form is subject to the terms of the Mozilla Public
       
    43 + * License, v. 2.0. If a copy of the MPL was not distributed with this
       
    44 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       
    45 +
       
    46 +/* Platform specific code to invoke XPCOM methods on native objects */
       
    47 +
       
    48 +#include "xptcprivate.h"
       
    49 +
       
    50 +#if !defined(__aarch64__)
       
    51 +#error "This code is for Linux AArch64 only."
       
    52 +#endif
       
    53 +
       
    54 +
       
    55 +/* "Procedure Call Standard for the ARM 64-bit Architecture" document, sections
       
    56 + * "5.4 Parameter Passing" and "6.1.2 Procedure Calling" contain all the
       
    57 + * needed information.
       
    58 + *
       
    59 + * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf
       
    60 + */
       
    61 +
       
    62 +#ifndef __AARCH64EL__
       
    63 +#error "Only little endian compatibility was tested"
       
    64 +#endif
       
    65 +
       
    66 +/*
       
    67 + * Allocation of integer function arguments initially to registers r1-r7
       
    68 + * and then to stack. Handling of 'that' argument which goes to register r0
       
    69 + * is handled separately and does not belong here.
       
    70 + *
       
    71 + * 'ireg_args'  - pointer to the current position in the buffer,
       
    72 + *                corresponding to the register arguments
       
    73 + * 'stack_args' - pointer to the current position in the buffer,
       
    74 + *                corresponding to the arguments on stack
       
    75 + * 'end'        - pointer to the end of the registers argument
       
    76 + *                buffer.
       
    77 + */
       
    78 +static inline void alloc_word(uint64_t* &ireg_args,
       
    79 +                              uint64_t* &stack_args,
       
    80 +                              uint64_t* end,
       
    81 +                              uint64_t  data)
       
    82 +{
       
    83 +    if (ireg_args < end) {
       
    84 +        *ireg_args = data;
       
    85 +        ireg_args++;
       
    86 +    } else {
       
    87 +        *stack_args = data;
       
    88 +        stack_args++;
       
    89 +    }
       
    90 +}
       
    91 +
       
    92 +static inline void alloc_double(double* &freg_args,
       
    93 +                                uint64_t* &stack_args,
       
    94 +                                double* end,
       
    95 +                                double  data)
       
    96 +{
       
    97 +    if (freg_args < end) {
       
    98 +        *freg_args = data;
       
    99 +        freg_args++;
       
   100 +    } else {
       
   101 +        memcpy(stack_args, &data, sizeof(data));
       
   102 +        stack_args++;
       
   103 +    }
       
   104 +}
       
   105 +
       
   106 +static inline void alloc_float(double* &freg_args,
       
   107 +                               uint64_t* &stack_args,
       
   108 +                               double* end,
       
   109 +                               float  data)
       
   110 +{
       
   111 +    if (freg_args < end) {
       
   112 +        memcpy(freg_args, &data, sizeof(data));
       
   113 +        freg_args++;
       
   114 +    } else {
       
   115 +        memcpy(stack_args, &data, sizeof(data));
       
   116 +        stack_args++;
       
   117 +    }
       
   118 +}
       
   119 +
       
   120 +
       
   121 +extern "C" void
       
   122 +invoke_copy_to_stack(uint64_t* stk, uint64_t *end,
       
   123 +                     uint32_t paramCount, nsXPTCVariant* s)
       
   124 +{
       
   125 +    uint64_t *ireg_args = stk;
       
   126 +    uint64_t *ireg_end  = ireg_args + 8;
       
   127 +    double *freg_args = (double *)ireg_end;
       
   128 +    double *freg_end  = freg_args + 8;
       
   129 +    uint64_t *stack_args = (uint64_t *)freg_end;
       
   130 +
       
   131 +    // leave room for 'that' argument in x0
       
   132 +    ++ireg_args;
       
   133 +
       
   134 +    for (uint32_t i = 0; i < paramCount; i++, s++) {
       
   135 +        if (s->IsPtrData()) {
       
   136 +            alloc_word(ireg_args, stack_args, ireg_end, (uint64_t)s->ptr);
       
   137 +            continue;
       
   138 +        }
       
   139 +        // According to the ABI, integral types that are smaller than 8 bytes
       
   140 +        // are to be passed in 8-byte registers or 8-byte stack slots.
       
   141 +        switch (s->type) {
       
   142 +            case nsXPTType::T_FLOAT:
       
   143 +                alloc_float(freg_args, stack_args, freg_end, s->val.f);
       
   144 +                break;
       
   145 +            case nsXPTType::T_DOUBLE:
       
   146 +                alloc_double(freg_args, stack_args, freg_end, s->val.d);
       
   147 +                break;
       
   148 +            case nsXPTType::T_I8:  alloc_word(ireg_args, stk, end, s->val.i8);   break;
       
   149 +            case nsXPTType::T_I16: alloc_word(ireg_args, stk, end, s->val.i16);  break;
       
   150 +            case nsXPTType::T_I32: alloc_word(ireg_args, stk, end, s->val.i32);  break;
       
   151 +            case nsXPTType::T_I64: alloc_word(ireg_args, stk, end, s->val.i64);  break;
       
   152 +            case nsXPTType::T_U8:  alloc_word(ireg_args, stk, end, s->val.u8);   break;
       
   153 +            case nsXPTType::T_U16: alloc_word(ireg_args, stk, end, s->val.u16);  break;
       
   154 +            case nsXPTType::T_U32: alloc_word(ireg_args, stk, end, s->val.u32);  break;
       
   155 +            case nsXPTType::T_U64: alloc_word(ireg_args, stk, end, s->val.u64);  break;
       
   156 +            case nsXPTType::T_BOOL: alloc_word(ireg_args, stk, end, s->val.b);   break;
       
   157 +            case nsXPTType::T_CHAR: alloc_word(ireg_args, stk, end, s->val.c);   break;
       
   158 +            case nsXPTType::T_WCHAR: alloc_word(ireg_args, stk, end, s->val.wc); break;
       
   159 +            default:
       
   160 +                // all the others are plain pointer types
       
   161 +                alloc_word(ireg_args, stack_args, ireg_end,
       
   162 +                           reinterpret_cast<uint64_t>(s->val.p));
       
   163 +                break;
       
   164 +        }
       
   165 +    }
       
   166 +}
       
   167 +
       
   168 +extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
       
   169 +                                      uint32_t paramCount, nsXPTCVariant* params);
       
   170 +
       
   171 +EXPORT_XPCOM_API(nsresult)
       
   172 +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
       
   173 +                 uint32_t paramCount, nsXPTCVariant* params)
       
   174 +{
       
   175 +    return _NS_InvokeByIndex(that, methodIndex, paramCount, params);
       
   176 +}
       
   177 diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_aarch64.s b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_aarch64.s
       
   178 new file mode 100644
       
   179 --- /dev/null
       
   180 +++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_aarch64.s
       
   181 @@ -0,0 +1,67 @@
       
   182 +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       
   183 +/* This Source Code Form is subject to the terms of the Mozilla Public
       
   184 + * License, v. 2.0. If a copy of the MPL was not distributed with this
       
   185 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       
   186 +
       
   187 +        .section ".text"
       
   188 +            .globl _NS_InvokeByIndex
       
   189 +            .type  _NS_InvokeByIndex,@function
       
   190 +
       
   191 +/*
       
   192 + * _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
       
   193 + *                   uint32_t paramCount, nsXPTCVariant* params)
       
   194 + */
       
   195 +
       
   196 +_NS_InvokeByIndex:
       
   197 +            # set up frame
       
   198 +            stp         x29, x30, [sp,#-32]!
       
   199 +            mov         x29, sp
       
   200 +            stp         x19, x20, [sp,#16]
       
   201 +
       
   202 +            # save methodIndex across function calls
       
   203 +            mov         w20, w1
       
   204 +
       
   205 +            # end of stack area passed to invoke_copy_to_stack
       
   206 +            mov         x1, sp
       
   207 +
       
   208 +            # assume 8 bytes of stack for each argument with 16-byte alignment
       
   209 +            add         w19, w2, #1
       
   210 +            and         w19, w19, #0xfffffffe
       
   211 +            sub         sp, sp, w19, uxth #3
       
   212 +
       
   213 +            # temporary place to store args passed in r0-r7,v0-v7
       
   214 +            sub         sp, sp, #128
       
   215 +
       
   216 +            # save 'that' on stack
       
   217 +            str         x0, [sp]
       
   218 +
       
   219 +            # start of stack area passed to invoke_copy_to_stack
       
   220 +            mov         x0, sp
       
   221 +            bl          invoke_copy_to_stack
       
   222 +
       
   223 +            # load arguments passed in r0-r7
       
   224 +            ldp         x6, x7, [sp, #48]
       
   225 +            ldp         x4, x5, [sp, #32]
       
   226 +            ldp         x2, x3, [sp, #16]
       
   227 +            ldp         x0, x1, [sp],#64
       
   228 +
       
   229 +            # load arguments passed in v0-v7
       
   230 +            ldp         d6, d7, [sp, #48]
       
   231 +            ldp         d4, d5, [sp, #32]
       
   232 +            ldp         d2, d3, [sp, #16]
       
   233 +            ldp         d0, d1, [sp],#64
       
   234 +
       
   235 +            # call the method
       
   236 +            ldr         x16, [x0]
       
   237 +            add         x16, x16, w20, uxth #3
       
   238 +            ldr         x16, [x16]
       
   239 +            blr         x16
       
   240 +
       
   241 +            add         sp, sp, w19, uxth #3
       
   242 +            ldp         x19, x20, [sp,#16]
       
   243 +            ldp         x29, x30, [sp],#32
       
   244 +            ret
       
   245 +
       
   246 +            .size _NS_InvokeByIndex, . - _NS_InvokeByIndex
       
   247 +
       
   248 +
       
   249 diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcstubs_aarch64.cpp b/xpcom/reflect/xptcall/src/md/unix/xptcstubs_aarch64.cpp
       
   250 new file mode 100644
       
   251 --- /dev/null
       
   252 +++ b/xpcom/reflect/xptcall/src/md/unix/xptcstubs_aarch64.cpp
       
   253 @@ -0,0 +1,219 @@
       
   254 +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       
   255 +/* This Source Code Form is subject to the terms of the Mozilla Public
       
   256 + * License, v. 2.0. If a copy of the MPL was not distributed with this
       
   257 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       
   258 +
       
   259 +#include "xptcprivate.h"
       
   260 +#include "xptiprivate.h"
       
   261 +
       
   262 +#ifndef __AARCH64EL__
       
   263 +#error "Only little endian compatibility was tested"
       
   264 +#endif
       
   265 +
       
   266 +/*
       
   267 + * This is for AArch64 ABI
       
   268 + *
       
   269 + * When we're called, the "gp" registers are stored in gprData and
       
   270 + * the "fp" registers are stored in fprData. Each array has 8 regs
       
   271 + * but first reg in gprData is a placeholder for 'self'.
       
   272 + */
       
   273 +extern "C" nsresult
       
   274 +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args,
       
   275 +                   uint64_t *gprData, double *fprData)
       
   276 +{
       
   277 +#define PARAM_BUFFER_COUNT        16
       
   278 +#define PARAM_GPR_COUNT            8
       
   279 +#define PARAM_FPR_COUNT            8
       
   280 +
       
   281 +    nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
       
   282 +    nsXPTCMiniVariant* dispatchParams = NULL;
       
   283 +    const nsXPTMethodInfo* info;
       
   284 +    nsresult result = NS_ERROR_FAILURE;
       
   285 +
       
   286 +    NS_ASSERTION(self,"no self");
       
   287 +
       
   288 +    self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
       
   289 +    NS_ASSERTION(info,"no method info");
       
   290 +
       
   291 +    uint32_t paramCount = info->GetParamCount();
       
   292 +
       
   293 +    // setup variant array pointer
       
   294 +    if (paramCount > PARAM_BUFFER_COUNT) {
       
   295 +        dispatchParams = new nsXPTCMiniVariant[paramCount];
       
   296 +    } else {
       
   297 +        dispatchParams = paramBuffer;
       
   298 +    }
       
   299 +    NS_ASSERTION(dispatchParams,"no place for params");
       
   300 +
       
   301 +    uint64_t* ap = args;
       
   302 +    uint32_t next_gpr = 1; // skip first arg which is 'self'
       
   303 +    uint32_t next_fpr = 0;
       
   304 +    for (uint32_t i = 0; i < paramCount; i++) {
       
   305 +        const nsXPTParamInfo& param = info->GetParam(i);
       
   306 +        const nsXPTType& type = param.GetType();
       
   307 +        nsXPTCMiniVariant* dp = &dispatchParams[i];
       
   308 +
       
   309 +        if (param.IsOut() || !type.IsArithmetic()) {
       
   310 +            if (next_gpr < PARAM_GPR_COUNT) {
       
   311 +                dp->val.p = (void*)gprData[next_gpr++];
       
   312 +            } else {
       
   313 +                dp->val.p = (void*)*ap++;
       
   314 +            }
       
   315 +            continue;
       
   316 +        }
       
   317 +
       
   318 +        switch (type) {
       
   319 +            case nsXPTType::T_I8:
       
   320 +                if (next_gpr < PARAM_GPR_COUNT) {
       
   321 +                    dp->val.i8  = (int8_t)gprData[next_gpr++];
       
   322 +                } else {
       
   323 +                    dp->val.i8  = (int8_t)*ap++;
       
   324 +                }
       
   325 +                break;
       
   326 +
       
   327 +            case nsXPTType::T_I16:
       
   328 +                if (next_gpr < PARAM_GPR_COUNT) {
       
   329 +                    dp->val.i16  = (int16_t)gprData[next_gpr++];
       
   330 +                } else {
       
   331 +                    dp->val.i16  = (int16_t)*ap++;
       
   332 +                }
       
   333 +                break;
       
   334 +
       
   335 +            case nsXPTType::T_I32:
       
   336 +                if (next_gpr < PARAM_GPR_COUNT) {
       
   337 +                    dp->val.i32  = (int32_t)gprData[next_gpr++];
       
   338 +                } else {
       
   339 +                    dp->val.i32  = (int32_t)*ap++;
       
   340 +                }
       
   341 +                break;
       
   342 +
       
   343 +            case nsXPTType::T_I64:
       
   344 +                if (next_gpr < PARAM_GPR_COUNT) {
       
   345 +                    dp->val.i64  = (int64_t)gprData[next_gpr++];
       
   346 +                } else {
       
   347 +                    dp->val.i64  = (int64_t)*ap++;
       
   348 +                }
       
   349 +                break;
       
   350 +
       
   351 +            case nsXPTType::T_U8:
       
   352 +                if (next_gpr < PARAM_GPR_COUNT) {
       
   353 +                    dp->val.u8  = (uint8_t)gprData[next_gpr++];
       
   354 +                } else {
       
   355 +                    dp->val.u8  = (uint8_t)*ap++;
       
   356 +                }
       
   357 +                break;
       
   358 +
       
   359 +            case nsXPTType::T_U16:
       
   360 +                if (next_gpr < PARAM_GPR_COUNT) {
       
   361 +                    dp->val.u16  = (uint16_t)gprData[next_gpr++];
       
   362 +                } else {
       
   363 +                    dp->val.u16  = (uint16_t)*ap++;
       
   364 +                }
       
   365 +                break;
       
   366 +
       
   367 +            case nsXPTType::T_U32:
       
   368 +                if (next_gpr < PARAM_GPR_COUNT) {
       
   369 +                    dp->val.u32  = (uint32_t)gprData[next_gpr++];
       
   370 +                } else {
       
   371 +                    dp->val.u32  = (uint32_t)*ap++;
       
   372 +                }
       
   373 +                break;
       
   374 +
       
   375 +            case nsXPTType::T_U64:
       
   376 +                if (next_gpr < PARAM_GPR_COUNT) {
       
   377 +                    dp->val.u64  = (uint64_t)gprData[next_gpr++];
       
   378 +                } else {
       
   379 +                    dp->val.u64  = (uint64_t)*ap++;
       
   380 +                }
       
   381 +                break;
       
   382 +
       
   383 +            case nsXPTType::T_FLOAT:
       
   384 +                if (next_fpr < PARAM_FPR_COUNT) {
       
   385 +                    memcpy(&dp->val.f, &fprData[next_fpr++], sizeof(dp->val.f));
       
   386 +                } else {
       
   387 +                    memcpy(&dp->val.f, ap++, sizeof(dp->val.f));
       
   388 +                }
       
   389 +                break;
       
   390 +
       
   391 +            case nsXPTType::T_DOUBLE:
       
   392 +                if (next_fpr < PARAM_FPR_COUNT) {
       
   393 +                    memcpy(&dp->val.d, &fprData[next_fpr++], sizeof(dp->val.d));
       
   394 +                } else {
       
   395 +                    memcpy(&dp->val.d, ap++, sizeof(dp->val.d));
       
   396 +                }
       
   397 +                break;
       
   398 +
       
   399 +            case nsXPTType::T_BOOL:
       
   400 +                if (next_gpr < PARAM_GPR_COUNT) {
       
   401 +                    dp->val.b  = (bool)gprData[next_gpr++];
       
   402 +                } else {
       
   403 +                    dp->val.b  = (bool)*ap++;
       
   404 +                }
       
   405 +                break;
       
   406 +
       
   407 +            case nsXPTType::T_CHAR:
       
   408 +                if (next_gpr < PARAM_GPR_COUNT) {
       
   409 +                    dp->val.c  = (char)gprData[next_gpr++];
       
   410 +                } else {
       
   411 +                    dp->val.c  = (char)*ap++;
       
   412 +                }
       
   413 +                break;
       
   414 +
       
   415 +            case nsXPTType::T_WCHAR:
       
   416 +                if (next_gpr < PARAM_GPR_COUNT) {
       
   417 +                    dp->val.wc  = (wchar_t)gprData[next_gpr++];
       
   418 +                } else {
       
   419 +                    dp->val.wc  = (wchar_t)*ap++;
       
   420 +                }
       
   421 +                break;
       
   422 +
       
   423 +            default:
       
   424 +                NS_ASSERTION(0, "bad type");
       
   425 +                break;
       
   426 +        }
       
   427 +    }
       
   428 +
       
   429 +    result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
       
   430 +
       
   431 +    if (dispatchParams != paramBuffer) {
       
   432 +        delete [] dispatchParams;
       
   433 +    }
       
   434 +
       
   435 +    return result;
       
   436 +}
       
   437 +
       
   438 +// Load w17 with the constant 'n' and branch to SharedStub().
       
   439 +# define STUB_ENTRY(n)                                                  \
       
   440 +    __asm__ (                                                           \
       
   441 +            ".section \".text\" \n\t"                                   \
       
   442 +            ".align 2\n\t"                                              \
       
   443 +            ".if "#n" < 10 \n\t"                                        \
       
   444 +            ".globl  _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t"               \
       
   445 +            ".hidden _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t"               \
       
   446 +            ".type   _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n"     \
       
   447 +            "_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t"                      \
       
   448 +            ".elseif "#n" < 100 \n\t"                                   \
       
   449 +            ".globl  _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t"               \
       
   450 +            ".hidden _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t"               \
       
   451 +            ".type   _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n"     \
       
   452 +            "_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t"                      \
       
   453 +            ".elseif "#n" < 1000 \n\t"                                  \
       
   454 +            ".globl  _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t"               \
       
   455 +            ".hidden _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t"               \
       
   456 +            ".type   _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n"     \
       
   457 +            "_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t"                      \
       
   458 +            ".else  \n\t"                                               \
       
   459 +            ".err   \"stub number "#n" >= 1000 not yet supported\"\n"   \
       
   460 +            ".endif \n\t"                                               \
       
   461 +            "mov    w17,#"#n" \n\t"                                     \
       
   462 +            "b      SharedStub \n"                                      \
       
   463 +);
       
   464 +
       
   465 +#define SENTINEL_ENTRY(n)                              \
       
   466 +    nsresult nsXPTCStubBase::Sentinel##n()             \
       
   467 +{                                                      \
       
   468 +    NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
       
   469 +    return NS_ERROR_NOT_IMPLEMENTED;                   \
       
   470 +}
       
   471 +
       
   472 +#include "xptcstubsdef.inc"
       
   473 diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_aarch64.s b/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_aarch64.s
       
   474 new file mode 100644
       
   475 --- /dev/null
       
   476 +++ b/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_aarch64.s
       
   477 @@ -0,0 +1,39 @@
       
   478 +# This Source Code Form is subject to the terms of the Mozilla Public
       
   479 +# License, v. 2.0. If a copy of the MPL was not distributed with this
       
   480 +# file, You can obtain one at http://mozilla.org/MPL/2.0/.
       
   481 +
       
   482 +            .set NGPREGS,8
       
   483 +            .set NFPREGS,8
       
   484 +
       
   485 +            .section ".text"
       
   486 +            .globl SharedStub
       
   487 +            .hidden SharedStub
       
   488 +            .type  SharedStub,@function
       
   489 +SharedStub:
       
   490 +            stp         x29, x30, [sp,#-16]!
       
   491 +            mov         x29, sp
       
   492 +
       
   493 +            sub         sp, sp, #8*(NGPREGS+NFPREGS)
       
   494 +            stp         x0, x1, [sp, #64+(0*8)]
       
   495 +            stp         x2, x3, [sp, #64+(2*8)]
       
   496 +            stp         x4, x5, [sp, #64+(4*8)]
       
   497 +            stp         x6, x7, [sp, #64+(6*8)]
       
   498 +            stp         d0, d1, [sp, #(0*8)]
       
   499 +            stp         d2, d3, [sp, #(2*8)]
       
   500 +            stp         d4, d5, [sp, #(4*8)]
       
   501 +            stp         d6, d7, [sp, #(6*8)]
       
   502 +
       
   503 +            # methodIndex passed from stub
       
   504 +            mov         w1, w17
       
   505 +
       
   506 +            add         x2, sp, #16+(8*(NGPREGS+NFPREGS))
       
   507 +            add         x3, sp, #8*NFPREGS
       
   508 +            add         x4, sp, #0
       
   509 +
       
   510 +            bl          PrepareAndDispatch
       
   511 +
       
   512 +            add         sp, sp, #8*(NGPREGS+NFPREGS)
       
   513 +            ldp         x29, x30, [sp],#16
       
   514 +            ret
       
   515 +
       
   516 +            .size SharedStub, . - SharedStub
       
   517