Back to index

lightning-sunbird  0.9+nobinonly
xptcstubs_ppc_netbsd.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               if (gpr < GPR_COUNT)
00123                   gpr += 2;
00124             }
00125             continue;
00126         }
00127         else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
00128             if (fpr < FPR_COUNT)
00129                 dp->val.f = (float) fprData[fpr++]; // in registers floats are passed as doubles
00130             else {
00131                 dp->val.f = *(float*) ap;
00132               ap += 1;
00133               if (gpr < GPR_COUNT)
00134                   gpr += 1;
00135             }
00136             continue;
00137         }
00138         else if (!param.IsOut() && (type == nsXPTType::T_I64
00139                                     || type == nsXPTType::T_U64)) {
00140             if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
00141             if ((gpr + 1) < GPR_COUNT) {
00142                 tempu64 = *(PRUint64*) &gprData[gpr];
00143                 gpr += 2;
00144             }
00145             else {
00146                 if ((PRUint32) ap & 4) ap++; // longlongs are 8-byte aligned on stack
00147                 tempu64 = *(PRUint64*) ap;
00148                 ap += 2;
00149             }
00150         }
00151         else {
00152             if (gpr < GPR_COUNT)
00153                 tempu32 = gprData[gpr++];
00154             else
00155                 tempu32 = *ap++;
00156         }
00157 
00158         if(param.IsOut() || !type.IsArithmetic()) {
00159             dp->val.p = (void*) tempu32;
00160             continue;
00161         }
00162 
00163         switch(type) {
00164         case nsXPTType::T_I8:      dp->val.i8  = (PRInt8)   tempu32; break;
00165         case nsXPTType::T_I16:     dp->val.i16 = (PRInt16)  tempu32; break;
00166         case nsXPTType::T_I32:     dp->val.i32 = (PRInt32)  tempu32; break;
00167         case nsXPTType::T_I64:     dp->val.i64 = (PRInt64)  tempu64; break;
00168         case nsXPTType::T_U8:      dp->val.u8  = (PRUint8)  tempu32; break;
00169         case nsXPTType::T_U16:     dp->val.u16 = (PRUint16) tempu32; break;
00170         case nsXPTType::T_U32:     dp->val.u32 = (PRUint32) tempu32; break;
00171         case nsXPTType::T_U64:     dp->val.u64 = (PRUint64) tempu64; break;
00172         case nsXPTType::T_BOOL:    dp->val.b   = (PRBool)   tempu32; break;
00173         case nsXPTType::T_CHAR:    dp->val.c   = (char)     tempu32; break;
00174         case nsXPTType::T_WCHAR:   dp->val.wc  = (wchar_t)  tempu32; break;
00175 
00176         default:
00177             NS_ASSERTION(0, "bad type");
00178             break;
00179         }
00180     }
00181 
00182     result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams);
00183 
00184     NS_RELEASE(iface_info);
00185 
00186     if (dispatchParams != paramBuffer)
00187         delete [] dispatchParams;
00188 
00189     return result;
00190 }
00191 
00192 // Load r11 with the constant 'n' and branch to SharedStub().
00193 //
00194 // XXX Yes, it's ugly that we're relying on gcc's name-mangling here;
00195 // however, it's quick, dirty, and'll break when the ABI changes on
00196 // us, which is what we want ;-).
00197 
00198 #define STUB_ENTRY(n)                                       \
00199 __asm__ (                                                   \
00200         ".section \".text\" \n\t"                           \
00201         ".align 2 \n\t"                                     \
00202        ".globl  Stub"#n"__14nsXPTCStubBase \n\t"           \
00203        ".type   Stub"#n"__14nsXPTCStubBase,@function \n\n" \
00204                                                             \
00205 "Stub"#n"__14nsXPTCStubBase: \n\t"                          \
00206        "li     11,"#n" \n\t"                               \
00207        "b      SharedStub@local \n"                        \
00208 );
00209 
00210 #define SENTINEL_ENTRY(n)                            \
00211 nsresult nsXPTCStubBase::Sentinel##n()               \
00212 {                                                    \
00213   NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
00214   return NS_ERROR_NOT_IMPLEMENTED;                   \
00215 }
00216 
00217 #include "xptcstubsdef.inc"