xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_netbsd.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 // Implement shared vtbl methods.
     8 #include "xptcprivate.h"
    10 // The Linux/PPC ABI (aka PPC/SYSV ABI) passes the first 8 integral
    11 // parameters and the first 8 floating point parameters in registers
    12 // (r3-r10 and f1-f8), no stack space is allocated for these by the
    13 // caller.  The rest of the parameters are passed in the callers stack
    14 // area. The stack pointer has to retain 16-byte alignment, longlongs
    15 // and doubles are aligned on 8-byte boundaries.
    17 #define PARAM_BUFFER_COUNT     16
    18 #define GPR_COUNT               8
    19 #define FPR_COUNT               8
    21 // PrepareAndDispatch() is called by SharedStub() and calls the actual method.
    22 //
    23 // - 'args[]' contains the arguments passed on stack
    24 // - 'gprData[]' contains the arguments passed in integer registers
    25 // - 'fprData[]' contains the arguments passed in floating point registers
    26 // 
    27 // The parameters are mapped into an array of type 'nsXPTCMiniVariant'
    28 // and then the method gets called.
    30 extern "C" nsresult ATTRIBUTE_USED
    31 PrepareAndDispatch(nsXPTCStubBase* self,
    32                    uint32_t methodIndex,
    33                    uint32_t* args,
    34                    uint32_t *gprData,
    35                    double *fprData)
    36 {
    37     nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
    38     nsXPTCMiniVariant* dispatchParams = nullptr;
    39     nsIInterfaceInfo* iface_info = nullptr;
    40     const nsXPTMethodInfo* info;
    41     uint32_t paramCount;
    42     uint32_t i;
    43     nsresult result = NS_ERROR_FAILURE;
    45     NS_ASSERTION(self,"no self");
    47     self->GetInterfaceInfo(&iface_info);
    48     NS_ASSERTION(iface_info,"no interface info");
    49     if (! iface_info)
    50         return NS_ERROR_UNEXPECTED;
    52     iface_info->GetMethodInfo(uint16_t(methodIndex), &info);
    53     NS_ASSERTION(info,"no method info");
    54     if (! info)
    55         return NS_ERROR_UNEXPECTED;
    57     paramCount = info->GetParamCount();
    59     // setup variant array pointer
    60     if(paramCount > PARAM_BUFFER_COUNT)
    61         dispatchParams = new nsXPTCMiniVariant[paramCount];
    62     else
    63         dispatchParams = paramBuffer;
    65     NS_ASSERTION(dispatchParams,"no place for params");
    66     if (! dispatchParams)
    67         return NS_ERROR_OUT_OF_MEMORY;
    69     uint32_t* ap = args;
    70     uint32_t gpr = 1;    // skip one GPR register
    71     uint32_t fpr = 0;
    72     uint32_t tempu32;
    73     uint64_t tempu64;
    75     for(i = 0; i < paramCount; i++) {
    76         const nsXPTParamInfo& param = info->GetParam(i);
    77         const nsXPTType& type = param.GetType();
    78         nsXPTCMiniVariant* dp = &dispatchParams[i];
    80         if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
    81             if (fpr < FPR_COUNT)
    82                 dp->val.d = fprData[fpr++];
    83             else {
    84                 if ((uint32_t) ap & 4) ap++; // doubles are 8-byte aligned on stack
    85                 dp->val.d = *(double*) ap;
    86                 ap += 2;
    87 		if (gpr < GPR_COUNT)
    88 		    gpr += 2;
    89             }
    90             continue;
    91         }
    92         else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
    93             if (fpr < FPR_COUNT)
    94                 dp->val.f = (float) fprData[fpr++]; // in registers floats are passed as doubles
    95             else {
    96                 dp->val.f = *(float*) ap;
    97 		ap += 1;
    98 		if (gpr < GPR_COUNT)
    99 		    gpr += 1;
   100             }
   101             continue;
   102         }
   103         else if (!param.IsOut() && (type == nsXPTType::T_I64
   104                                     || type == nsXPTType::T_U64)) {
   105             if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
   106             if ((gpr + 1) < GPR_COUNT) {
   107                 tempu64 = *(uint64_t*) &gprData[gpr];
   108                 gpr += 2;
   109             }
   110             else {
   111                 if ((uint32_t) ap & 4) ap++; // longlongs are 8-byte aligned on stack
   112                 tempu64 = *(uint64_t*) ap;
   113                 ap += 2;
   114             }
   115         }
   116         else {
   117             if (gpr < GPR_COUNT)
   118                 tempu32 = gprData[gpr++];
   119             else
   120                 tempu32 = *ap++;
   121         }
   123         if(param.IsOut() || !type.IsArithmetic()) {
   124             dp->val.p = (void*) tempu32;
   125             continue;
   126         }
   128         switch(type) {
   129         case nsXPTType::T_I8:      dp->val.i8  = (int8_t)   tempu32; break;
   130         case nsXPTType::T_I16:     dp->val.i16 = (int16_t)  tempu32; break;
   131         case nsXPTType::T_I32:     dp->val.i32 = (int32_t)  tempu32; break;
   132         case nsXPTType::T_I64:     dp->val.i64 = (int64_t)  tempu64; break;
   133         case nsXPTType::T_U8:      dp->val.u8  = (uint8_t)  tempu32; break;
   134         case nsXPTType::T_U16:     dp->val.u16 = (uint16_t) tempu32; break;
   135         case nsXPTType::T_U32:     dp->val.u32 = (uint32_t) tempu32; break;
   136         case nsXPTType::T_U64:     dp->val.u64 = (uint64_t) tempu64; break;
   137         case nsXPTType::T_BOOL:    dp->val.b   = (bool)   tempu32; break;
   138         case nsXPTType::T_CHAR:    dp->val.c   = (char)     tempu32; break;
   139         case nsXPTType::T_WCHAR:   dp->val.wc  = (wchar_t)  tempu32; break;
   141         default:
   142             NS_ERROR("bad type");
   143             break;
   144         }
   145     }
   147     result = self->CallMethod((uint16_t) methodIndex, info, dispatchParams);
   149     NS_RELEASE(iface_info);
   151     if (dispatchParams != paramBuffer)
   152         delete [] dispatchParams;
   154     return result;
   155 }
   157 // Load r11 with the constant 'n' and branch to SharedStub().
   158 //
   159 // XXX Yes, it's ugly that we're relying on gcc's name-mangling here;
   160 // however, it's quick, dirty, and'll break when the ABI changes on
   161 // us, which is what we want ;-).
   163 #define STUB_ENTRY(n)                                       \
   164 __asm__ (                                                   \
   165         ".section \".text\" \n\t"                           \
   166         ".align 2 \n\t"                                     \
   167 	".globl  Stub"#n"__14nsXPTCStubBase \n\t"           \
   168 	".type   Stub"#n"__14nsXPTCStubBase,@function \n\n" \
   169                                                             \
   170 "Stub"#n"__14nsXPTCStubBase: \n\t"                          \
   171 	"li     11,"#n" \n\t"                               \
   172 	"b      SharedStub@local \n"                        \
   173 );
   175 #define SENTINEL_ENTRY(n)                            \
   176 nsresult nsXPTCStubBase::Sentinel##n()               \
   177 {                                                    \
   178   NS_ERROR("nsXPTCStubBase::Sentinel called"); \
   179   return NS_ERROR_NOT_IMPLEMENTED;                   \
   180 }
   182 #include "xptcstubsdef.inc"

mercurial