Back to index

lightning-sunbird  0.9+nobinonly
xptcstubs_ppc_linux.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Franz.Sirl-kernel@lauterbach.com (Franz Sirl)
00024  *   beard@netscape.com (Patrick Beard)
00025  *   waterson@netscape.com (Chris Waterson)
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either of the GNU General Public License Version 2 or later (the "GPL"),
00029  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 // Implement shared vtbl methods.
00042 
00043 #include "xptcprivate.h"
00044 
00045 // The Linux/PPC ABI (aka PPC/SYSV ABI) passes the first 8 integral
00046 // parameters and the first 8 floating point parameters in registers
00047 // (r3-r10 and f1-f8), no stack space is allocated for these by the
00048 // caller.  The rest of the parameters are passed in the callers stack
00049 // area. The stack pointer has to retain 16-byte alignment, longlongs
00050 // and doubles are aligned on 8-byte boundaries.
00051 
00052 #define PARAM_BUFFER_COUNT     16
00053 #define GPR_COUNT               8
00054 #define FPR_COUNT               8
00055 
00056 // PrepareAndDispatch() is called by SharedStub() and calls the actual method.
00057 //
00058 // - 'args[]' contains the arguments passed on stack
00059 // - 'gprData[]' contains the arguments passed in integer registers
00060 // - 'fprData[]' contains the arguments passed in floating point registers
00061 // 
00062 // The parameters are mapped into an array of type 'nsXPTCMiniVariant'
00063 // and then the method gets called.
00064 
00065 extern "C" nsresult
00066 PrepareAndDispatch(nsXPTCStubBase* self,
00067                    PRUint32 methodIndex,
00068                    PRUint32* args,
00069                    PRUint32 *gprData,
00070                    double *fprData)
00071 {
00072     nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
00073     nsXPTCMiniVariant* dispatchParams = NULL;
00074     nsIInterfaceInfo* iface_info = NULL;
00075     const nsXPTMethodInfo* info;
00076     PRUint32 paramCount;
00077     PRUint32 i;
00078     nsresult result = NS_ERROR_FAILURE;
00079 
00080     NS_ASSERTION(self,"no self");
00081 
00082     self->GetInterfaceInfo(&iface_info);
00083     NS_ASSERTION(iface_info,"no interface info");
00084     if (! iface_info)
00085         return NS_ERROR_UNEXPECTED;
00086 
00087     iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
00088     NS_ASSERTION(info,"no method info");
00089     if (! info)
00090         return NS_ERROR_UNEXPECTED;
00091 
00092     paramCount = info->GetParamCount();
00093 
00094     // setup variant array pointer
00095     if(paramCount > PARAM_BUFFER_COUNT)
00096         dispatchParams = new nsXPTCMiniVariant[paramCount];
00097     else
00098         dispatchParams = paramBuffer;
00099 
00100     NS_ASSERTION(dispatchParams,"no place for params");
00101     if (! dispatchParams)
00102         return NS_ERROR_OUT_OF_MEMORY;
00103 
00104     PRUint32* ap = args;
00105     PRUint32 gpr = 1;    // skip one GPR register
00106     PRUint32 fpr = 0;
00107     PRUint32 tempu32;
00108     PRUint64 tempu64;
00109 
00110     for(i = 0; i < paramCount; i++) {
00111         const nsXPTParamInfo& param = info->GetParam(i);
00112         const nsXPTType& type = param.GetType();
00113         nsXPTCMiniVariant* dp = &dispatchParams[i];
00114        
00115         if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
00116             if (fpr < FPR_COUNT)
00117                 dp->val.d = fprData[fpr++];
00118             else {
00119                 if ((PRUint32) ap & 4) ap++; // doubles are 8-byte aligned on stack
00120                 dp->val.d = *(double*) ap;
00121                 ap += 2;
00122             }
00123             continue;
00124         }
00125         else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
00126             if (fpr < FPR_COUNT)
00127                 dp->val.f = (float) fprData[fpr++]; // in registers floats are passed as doubles
00128             else
00129                 dp->val.f = *(float*) ap++;
00130             continue;
00131         }
00132         else if (!param.IsOut() && (type == nsXPTType::T_I64
00133                                     || type == nsXPTType::T_U64)) {
00134             if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
00135             if ((gpr + 1) < GPR_COUNT) {
00136                 tempu64 = *(PRUint64*) &gprData[gpr];
00137                 gpr += 2;
00138             }
00139             else {
00140                 if ((PRUint32) ap & 4) ap++; // longlongs are 8-byte aligned on stack
00141                 tempu64 = *(PRUint64*) ap;
00142                 ap += 2;
00143             }
00144         }
00145         else {
00146             if (gpr < GPR_COUNT)
00147                 tempu32 = gprData[gpr++];
00148             else
00149                 tempu32 = *ap++;
00150         }
00151 
00152         if(param.IsOut() || !type.IsArithmetic()) {
00153             dp->val.p = (void*) tempu32;
00154             continue;
00155         }
00156 
00157         switch(type) {
00158         case nsXPTType::T_I8:      dp->val.i8  = (PRInt8)   tempu32; break;
00159         case nsXPTType::T_I16:     dp->val.i16 = (PRInt16)  tempu32; break;
00160         case nsXPTType::T_I32:     dp->val.i32 = (PRInt32)  tempu32; break;
00161         case nsXPTType::T_I64:     dp->val.i64 = (PRInt64)  tempu64; break;
00162         case nsXPTType::T_U8:      dp->val.u8  = (PRUint8)  tempu32; break;
00163         case nsXPTType::T_U16:     dp->val.u16 = (PRUint16) tempu32; break;
00164         case nsXPTType::T_U32:     dp->val.u32 = (PRUint32) tempu32; break;
00165         case nsXPTType::T_U64:     dp->val.u64 = (PRUint64) tempu64; break;
00166         case nsXPTType::T_BOOL:    dp->val.b   = (PRBool)   tempu32; break;
00167         case nsXPTType::T_CHAR:    dp->val.c   = (char)     tempu32; break;
00168         case nsXPTType::T_WCHAR:   dp->val.wc  = (wchar_t)  tempu32; break;
00169 
00170         default:
00171             NS_ASSERTION(0, "bad type");
00172             break;
00173         }
00174     }
00175 
00176     result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams);
00177 
00178     NS_RELEASE(iface_info);
00179 
00180     if (dispatchParams != paramBuffer)
00181         delete [] dispatchParams;
00182 
00183     return result;
00184 }
00185 
00186 // Load r11 with the constant 'n' and branch to SharedStub().
00187 //
00188 // XXX Yes, it's ugly that we're relying on gcc's name-mangling here;
00189 // however, it's quick, dirty, and'll break when the ABI changes on
00190 // us, which is what we want ;-).
00191 
00192 #if __GXX_ABI_VERSION < 100
00193 // gcc-2 version
00194 # define STUB_ENTRY(n)                                       \
00195 __asm__ (                                                   \
00196         ".section \".text\" \n\t"                           \
00197         ".align 2 \n\t"                                     \
00198        ".globl  Stub"#n"__14nsXPTCStubBase \n\t"           \
00199        ".type   Stub"#n"__14nsXPTCStubBase,@function \n\n" \
00200                                                             \
00201 "Stub"#n"__14nsXPTCStubBase: \n\t"                          \
00202        "li     11,"#n" \n\t"                               \
00203        "b      SharedStub@local \n"                        \
00204 );
00205 #else
00206 // gcc-3 version
00207 //
00208 // As G++3 ABI contains the length of the functionname in the mangled
00209 // name, it is difficult to get a generic assembler mechanism like
00210 // in the G++ 2.95 case.
00211 // Create names would be like:
00212 // _ZN14nsXPTCStubBase5Stub1Ev
00213 // _ZN14nsXPTCStubBase6Stub12Ev
00214 // _ZN14nsXPTCStubBase7Stub123Ev
00215 // _ZN14nsXPTCStubBase8Stub1234Ev
00216 // etc.
00217 // Use assembler directives to get the names right...
00218 
00219 # define STUB_ENTRY(n)                                                \
00220 __asm__ (                                                      \
00221        ".align       2 \n\t"                                                 \
00222        ".if   "#n" < 10 \n\t"                                         \
00223        ".globl       _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t"                    \
00224        ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n"          \
00225 "_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t"                                \
00226                                                                \
00227        ".elseif "#n" < 100 \n\t"                               \
00228        ".globl       _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t"                    \
00229        ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n"          \
00230 "_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t"                                \
00231                                                                \
00232        ".elseif "#n" < 1000 \n\t"                              \
00233        ".globl       _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t"                    \
00234        ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n"          \
00235 "_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t"                                \
00236                                                                \
00237        ".else \n\t"                                            \
00238        ".err  \"stub number "#n" >= 1000 not yet supported\"\n"       \
00239        ".endif \n\t"                                           \
00240                                                                \
00241        "li    11,"#n" \n\t"                                    \
00242        "b     SharedStub@local \n"                             \
00243 );
00244 #endif
00245 
00246 #define SENTINEL_ENTRY(n)                            \
00247 nsresult nsXPTCStubBase::Sentinel##n()               \
00248 {                                                    \
00249   NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
00250   return NS_ERROR_NOT_IMPLEMENTED;                   \
00251 }
00252 
00253 #include "xptcstubsdef.inc"