Back to index

lightning-sunbird  0.9+nobinonly
xptcstubs_linux_alpha.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  *   Glen Nakamura <glen@imodulo.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 /* Implement shared vtbl methods. */
00040 
00041 #include "xptcprivate.h"
00042 
00043 /* Prototype specifies unmangled function name and disables unused warning */
00044 static nsresult
00045 PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint64* args)
00046 __asm__("PrepareAndDispatch") __attribute__((used));
00047 
00048 static nsresult
00049 PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint64* args)
00050 {
00051     const PRUint8 PARAM_BUFFER_COUNT = 16;
00052     const PRUint8 NUM_ARG_REGS = 6-1;        // -1 for "this" pointer
00053 
00054     nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
00055     nsXPTCMiniVariant* dispatchParams = NULL;
00056     nsIInterfaceInfo* iface_info = NULL;
00057     const nsXPTMethodInfo* info;
00058     PRUint8 paramCount;
00059     PRUint8 i;
00060     nsresult result = NS_ERROR_FAILURE;
00061 
00062     NS_ASSERTION(self,"no self");
00063 
00064     self->GetInterfaceInfo(&iface_info);
00065     NS_ASSERTION(iface_info,"no interface info");
00066 
00067     iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
00068     NS_ASSERTION(info,"no interface info");
00069 
00070     paramCount = info->GetParamCount();
00071 
00072     // setup variant array pointer
00073     if(paramCount > PARAM_BUFFER_COUNT)
00074         dispatchParams = new nsXPTCMiniVariant[paramCount];
00075     else
00076         dispatchParams = paramBuffer;
00077     NS_ASSERTION(dispatchParams,"no place for params");
00078 
00079     // args[0] to args[NUM_ARG_REGS] hold floating point register values
00080     PRUint64* ap = args + NUM_ARG_REGS;
00081     for(i = 0; i < paramCount; i++, ap++)
00082     {
00083         const nsXPTParamInfo& param = info->GetParam(i);
00084         const nsXPTType& type = param.GetType();
00085         nsXPTCMiniVariant* dp = &dispatchParams[i];
00086 
00087         if(param.IsOut() || !type.IsArithmetic())
00088         {
00089             dp->val.p = (void*) *ap;
00090             continue;
00091         }
00092         // else
00093         switch(type)
00094         {
00095         case nsXPTType::T_I8     : dp->val.i8  = (PRInt8)    *ap;    break;
00096         case nsXPTType::T_I16    : dp->val.i16 = (PRInt16)   *ap;    break;
00097         case nsXPTType::T_I32    : dp->val.i32 = (PRInt32)   *ap;    break;
00098         case nsXPTType::T_I64    : dp->val.i64 = (PRInt64)   *ap;    break;
00099         case nsXPTType::T_U8     : dp->val.u8  = (PRUint8)   *ap;    break;
00100         case nsXPTType::T_U16    : dp->val.u16 = (PRUint16)  *ap;    break;
00101         case nsXPTType::T_U32    : dp->val.u32 = (PRUint32)  *ap;    break;
00102         case nsXPTType::T_U64    : dp->val.u64 = (PRUint64)  *ap;    break;
00103         case nsXPTType::T_FLOAT  :
00104             if(i < NUM_ARG_REGS)
00105             {
00106                 // floats passed via registers are stored as doubles
00107                 // in the first NUM_ARG_REGS entries in args
00108                 dp->val.u64 = (PRUint64) args[i];
00109                 dp->val.f = (float) dp->val.d;    // convert double to float
00110             }
00111             else
00112                 dp->val.u32 = (PRUint32) *ap;
00113             break;
00114         case nsXPTType::T_DOUBLE :
00115             // doubles passed via registers are also stored
00116             // in the first NUM_ARG_REGS entries in args
00117             dp->val.u64 = (i < NUM_ARG_REGS) ? args[i] : *ap;
00118             break;
00119         case nsXPTType::T_BOOL   : dp->val.b   = (PRBool)    *ap;    break;
00120         case nsXPTType::T_CHAR   : dp->val.c   = (char)      *ap;    break;
00121         case nsXPTType::T_WCHAR  : dp->val.wc  = (PRUnichar) *ap;    break;
00122         default:
00123             NS_ASSERTION(0, "bad type");
00124             break;
00125         }
00126     }
00127 
00128     result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
00129 
00130     NS_RELEASE(iface_info);
00131 
00132     if(dispatchParams != paramBuffer)
00133         delete [] dispatchParams;
00134 
00135     return result;
00136 }
00137 
00138 /*
00139  * SharedStub()
00140  *  Collects arguments and calls PrepareAndDispatch.  The "methodIndex" is
00141  *  passed to this function via $1 to preserve the argument registers.
00142  */
00143 __asm__(
00144     "#### SharedStub ####\n"
00145 ".text\n\t"
00146     ".align 5\n\t"
00147     ".ent SharedStub\n"
00148 "SharedStub:\n\t"
00149     ".frame $30,96,$26,0\n\t"
00150     ".mask 0x4000000,-96\n\t"
00151     "ldgp $29,0($27)\n"
00152 "$SharedStub..ng:\n\t"
00153     "subq $30,96,$30\n\t"
00154     "stq $26,0($30)\n\t"
00155     ".prologue 1\n\t"
00156 
00157     /*
00158      * Store arguments passed via registers to the stack.
00159      * Floating point registers are stored as doubles and converted
00160      * to floats in PrepareAndDispatch if necessary.
00161      */
00162     "stt $f17,16($30)\n\t"   /* floating point registers */
00163     "stt $f18,24($30)\n\t"
00164     "stt $f19,32($30)\n\t"
00165     "stt $f20,40($30)\n\t"
00166     "stt $f21,48($30)\n\t"
00167     "stq $17,56($30)\n\t"    /* integer registers */
00168     "stq $18,64($30)\n\t"
00169     "stq $19,72($30)\n\t"
00170     "stq $20,80($30)\n\t"
00171     "stq $21,88($30)\n\t"
00172 
00173     /*
00174      * Call PrepareAndDispatch function.
00175      */
00176     "bis $1,$1,$17\n\t"      /* pass "methodIndex" */
00177     "addq $30,16,$18\n\t"    /* pass "args" */
00178     "bsr $26,$PrepareAndDispatch..ng\n\t"
00179 
00180     "ldq $26,0($30)\n\t"
00181     "addq $30,96,$30\n\t"
00182     "ret $31,($26),1\n\t"
00183     ".end SharedStub"
00184     );
00185 
00186 /*
00187  * nsresult nsXPTCStubBase::Stub##n()
00188  *  Sets register $1 to "methodIndex" and jumps to SharedStub.
00189  */
00190 #define STUB_MANGLED_ENTRY(n, symbol) \
00191     "#### Stub"#n" ####"      "\n\t" \
00192     ".text"                   "\n\t" \
00193     ".align 5"                "\n\t" \
00194     ".globl " symbol          "\n\t" \
00195     ".ent " symbol            "\n"   \
00196 symbol ":"                    "\n\t" \
00197     ".frame $30,0,$26,0"      "\n\t" \
00198     "ldgp $29,0($27)"         "\n"   \
00199 "$" symbol "..ng:"            "\n\t" \
00200     ".prologue 1"             "\n\t" \
00201     "lda $1,"#n               "\n\t" \
00202     "br $31,$SharedStub..ng"  "\n\t" \
00203     ".end " symbol
00204 
00205 #if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
00206 
00207 #define STUB_ENTRY(n) \
00208 __asm__( \
00209     ".if "#n" < 10"                                              "\n\t" \
00210         STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase5Stub"#n"Ev")  "\n\t" \
00211     ".elseif "#n" < 100"                                         "\n\t" \
00212         STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase6Stub"#n"Ev")  "\n\t" \
00213     ".elseif "#n" < 1000"                                        "\n\t" \
00214         STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase7Stub"#n"Ev")  "\n\t" \
00215     ".else"                                                      "\n\t" \
00216     ".err \"Stub"#n" >= 1000 not yet supported.\""               "\n\t" \
00217     ".endif" \
00218     );
00219 
00220 #else /* not G++ V3 ABI */
00221 
00222 #define STUB_ENTRY(n) \
00223 __asm__( \
00224     STUB_MANGLED_ENTRY(n, "Stub"#n"__14nsXPTCStubBase") \
00225     );
00226 
00227 #endif /* G++ V3 ABI */
00228 
00229 #define SENTINEL_ENTRY(n) \
00230 nsresult nsXPTCStubBase::Sentinel##n() \
00231 { \
00232     NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
00233     return NS_ERROR_NOT_IMPLEMENTED; \
00234 }
00235 
00236 #include "xptcstubsdef.inc"