xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc64_linux.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

michael@0 1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 // Implement shared vtbl methods.
michael@0 7
michael@0 8 #include "xptcprivate.h"
michael@0 9 #include "xptiprivate.h"
michael@0 10
michael@0 11 // The Linux/PPC64 ABI passes the first 8 integral
michael@0 12 // parameters and the first 13 floating point parameters in registers
michael@0 13 // (r3-r10 and f1-f13), no stack space is allocated for these by the
michael@0 14 // caller. The rest of the parameters are passed in the caller's stack
michael@0 15 // area. The stack pointer has to retain 16-byte alignment.
michael@0 16
michael@0 17 // The PowerPC64 platform ABI can be found here:
michael@0 18 // http://www.freestandards.org/spec/ELF/ppc64/
michael@0 19 // and in particular:
michael@0 20 // http://www.freestandards.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#FUNC-CALL
michael@0 21
michael@0 22 #define PARAM_BUFFER_COUNT 16
michael@0 23 #define GPR_COUNT 7
michael@0 24 #define FPR_COUNT 13
michael@0 25
michael@0 26 // PrepareAndDispatch() is called by SharedStub() and calls the actual method.
michael@0 27 //
michael@0 28 // - 'args[]' contains the arguments passed on stack
michael@0 29 // - 'gprData[]' contains the arguments passed in integer registers
michael@0 30 // - 'fprData[]' contains the arguments passed in floating point registers
michael@0 31 //
michael@0 32 // The parameters are mapped into an array of type 'nsXPTCMiniVariant'
michael@0 33 // and then the method gets called.
michael@0 34 #include <stdio.h>
michael@0 35 extern "C" nsresult ATTRIBUTE_USED
michael@0 36 PrepareAndDispatch(nsXPTCStubBase* self,
michael@0 37 uint64_t methodIndex,
michael@0 38 uint64_t* args,
michael@0 39 uint64_t *gprData,
michael@0 40 double *fprData)
michael@0 41 {
michael@0 42 nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
michael@0 43 nsXPTCMiniVariant* dispatchParams = nullptr;
michael@0 44 const nsXPTMethodInfo* info;
michael@0 45 uint32_t paramCount;
michael@0 46 uint32_t i;
michael@0 47 nsresult result = NS_ERROR_FAILURE;
michael@0 48
michael@0 49 NS_ASSERTION(self,"no self");
michael@0 50
michael@0 51 self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
michael@0 52 NS_ASSERTION(info,"no method info");
michael@0 53 if (! info)
michael@0 54 return NS_ERROR_UNEXPECTED;
michael@0 55
michael@0 56 paramCount = info->GetParamCount();
michael@0 57
michael@0 58 // setup variant array pointer
michael@0 59 if(paramCount > PARAM_BUFFER_COUNT)
michael@0 60 dispatchParams = new nsXPTCMiniVariant[paramCount];
michael@0 61 else
michael@0 62 dispatchParams = paramBuffer;
michael@0 63
michael@0 64 NS_ASSERTION(dispatchParams,"no place for params");
michael@0 65 if (! dispatchParams)
michael@0 66 return NS_ERROR_OUT_OF_MEMORY;
michael@0 67
michael@0 68 uint64_t* ap = args;
michael@0 69 uint64_t tempu64;
michael@0 70
michael@0 71 for(i = 0; i < paramCount; i++) {
michael@0 72 const nsXPTParamInfo& param = info->GetParam(i);
michael@0 73 const nsXPTType& type = param.GetType();
michael@0 74 nsXPTCMiniVariant* dp = &dispatchParams[i];
michael@0 75
michael@0 76 if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
michael@0 77 if (i < FPR_COUNT)
michael@0 78 dp->val.d = fprData[i];
michael@0 79 else
michael@0 80 dp->val.d = *(double*) ap;
michael@0 81 } else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
michael@0 82 if (i < FPR_COUNT)
michael@0 83 dp->val.f = (float) fprData[i]; // in registers floats are passed as doubles
michael@0 84 else {
michael@0 85 float *p = (float *)ap;
michael@0 86 #ifndef __LITTLE_ENDIAN__
michael@0 87 p++;
michael@0 88 #endif
michael@0 89 dp->val.f = *p;
michael@0 90 }
michael@0 91 } else { /* integer type or pointer */
michael@0 92 if (i < GPR_COUNT)
michael@0 93 tempu64 = gprData[i];
michael@0 94 else
michael@0 95 tempu64 = *ap;
michael@0 96
michael@0 97 if (param.IsOut() || !type.IsArithmetic())
michael@0 98 dp->val.p = (void*) tempu64;
michael@0 99 else if (type == nsXPTType::T_I8)
michael@0 100 dp->val.i8 = (int8_t) tempu64;
michael@0 101 else if (type == nsXPTType::T_I16)
michael@0 102 dp->val.i16 = (int16_t) tempu64;
michael@0 103 else if (type == nsXPTType::T_I32)
michael@0 104 dp->val.i32 = (int32_t) tempu64;
michael@0 105 else if (type == nsXPTType::T_I64)
michael@0 106 dp->val.i64 = (int64_t) tempu64;
michael@0 107 else if (type == nsXPTType::T_U8)
michael@0 108 dp->val.u8 = (uint8_t) tempu64;
michael@0 109 else if (type == nsXPTType::T_U16)
michael@0 110 dp->val.u16 = (uint16_t) tempu64;
michael@0 111 else if (type == nsXPTType::T_U32)
michael@0 112 dp->val.u32 = (uint32_t) tempu64;
michael@0 113 else if (type == nsXPTType::T_U64)
michael@0 114 dp->val.u64 = (uint64_t) tempu64;
michael@0 115 else if (type == nsXPTType::T_BOOL)
michael@0 116 dp->val.b = (bool) tempu64;
michael@0 117 else if (type == nsXPTType::T_CHAR)
michael@0 118 dp->val.c = (char) tempu64;
michael@0 119 else if (type == nsXPTType::T_WCHAR)
michael@0 120 dp->val.wc = (wchar_t) tempu64;
michael@0 121 else
michael@0 122 NS_ERROR("bad type");
michael@0 123 }
michael@0 124
michael@0 125 if (i >= 7)
michael@0 126 ap++;
michael@0 127 }
michael@0 128
michael@0 129 result = self->mOuter->CallMethod((uint16_t) methodIndex, info,
michael@0 130 dispatchParams);
michael@0 131
michael@0 132 if (dispatchParams != paramBuffer)
michael@0 133 delete [] dispatchParams;
michael@0 134
michael@0 135 return result;
michael@0 136 }
michael@0 137
michael@0 138 // Load r11 with the constant 'n' and branch to SharedStub().
michael@0 139 //
michael@0 140 // XXX Yes, it's ugly that we're relying on gcc's name-mangling here;
michael@0 141 // however, it's quick, dirty, and'll break when the ABI changes on
michael@0 142 // us, which is what we want ;-).
michael@0 143
michael@0 144
michael@0 145 // gcc-3 version
michael@0 146 //
michael@0 147 // As G++3 ABI contains the length of the functionname in the mangled
michael@0 148 // name, it is difficult to get a generic assembler mechanism like
michael@0 149 // in the G++ 2.95 case.
michael@0 150 // Create names would be like:
michael@0 151 // _ZN14nsXPTCStubBase5Stub1Ev
michael@0 152 // _ZN14nsXPTCStubBase6Stub12Ev
michael@0 153 // _ZN14nsXPTCStubBase7Stub123Ev
michael@0 154 // _ZN14nsXPTCStubBase8Stub1234Ev
michael@0 155 // etc.
michael@0 156 // Use assembler directives to get the names right...
michael@0 157
michael@0 158 #if _CALL_ELF == 2
michael@0 159 # define STUB_ENTRY(n) \
michael@0 160 __asm__ ( \
michael@0 161 ".section \".text\" \n\t" \
michael@0 162 ".align 2 \n\t" \
michael@0 163 ".if "#n" < 10 \n\t" \
michael@0 164 ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \
michael@0 165 ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \
michael@0 166 "_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \
michael@0 167 "0: addis 2,12,.TOC.-0b@ha \n\t" \
michael@0 168 "addi 2,2,.TOC.-0b@l \n\t" \
michael@0 169 ".localentry _ZN14nsXPTCStubBase5Stub"#n"Ev,.-_ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \
michael@0 170 \
michael@0 171 ".elseif "#n" < 100 \n\t" \
michael@0 172 ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \
michael@0 173 ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \
michael@0 174 "_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \
michael@0 175 "0: addis 2,12,.TOC.-0b@ha \n\t" \
michael@0 176 "addi 2,2,.TOC.-0b@l \n\t" \
michael@0 177 ".localentry _ZN14nsXPTCStubBase6Stub"#n"Ev,.-_ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \
michael@0 178 \
michael@0 179 ".elseif "#n" < 1000 \n\t" \
michael@0 180 ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \
michael@0 181 ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \
michael@0 182 "_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \
michael@0 183 "0: addis 2,12,.TOC.-0b@ha \n\t" \
michael@0 184 "addi 2,2,.TOC.-0b@l \n\t" \
michael@0 185 ".localentry _ZN14nsXPTCStubBase7Stub"#n"Ev,.-_ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \
michael@0 186 \
michael@0 187 ".else \n\t" \
michael@0 188 ".err \"stub number "#n" >= 1000 not yet supported\"\n" \
michael@0 189 ".endif \n\t" \
michael@0 190 \
michael@0 191 "li 11,"#n" \n\t" \
michael@0 192 "b SharedStub \n" \
michael@0 193 );
michael@0 194 #else
michael@0 195 # define STUB_ENTRY(n) \
michael@0 196 __asm__ ( \
michael@0 197 ".section \".toc\",\"aw\" \n\t" \
michael@0 198 ".section \".text\" \n\t" \
michael@0 199 ".align 2 \n\t" \
michael@0 200 ".if "#n" < 10 \n\t" \
michael@0 201 ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \
michael@0 202 ".section \".opd\",\"aw\" \n\t" \
michael@0 203 ".align 3 \n\t" \
michael@0 204 "_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \
michael@0 205 ".quad ._ZN14nsXPTCStubBase5Stub"#n"Ev,.TOC.@tocbase \n\t" \
michael@0 206 ".previous \n\t" \
michael@0 207 ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \
michael@0 208 "._ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \
michael@0 209 \
michael@0 210 ".elseif "#n" < 100 \n\t" \
michael@0 211 ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \
michael@0 212 ".section \".opd\",\"aw\" \n\t" \
michael@0 213 ".align 3 \n\t" \
michael@0 214 "_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \
michael@0 215 ".quad ._ZN14nsXPTCStubBase6Stub"#n"Ev,.TOC.@tocbase \n\t" \
michael@0 216 ".previous \n\t" \
michael@0 217 ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \
michael@0 218 "._ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \
michael@0 219 \
michael@0 220 ".elseif "#n" < 1000 \n\t" \
michael@0 221 ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \
michael@0 222 ".section \".opd\",\"aw\" \n\t" \
michael@0 223 ".align 3 \n\t" \
michael@0 224 "_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \
michael@0 225 ".quad ._ZN14nsXPTCStubBase7Stub"#n"Ev,.TOC.@tocbase \n\t" \
michael@0 226 ".previous \n\t" \
michael@0 227 ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \
michael@0 228 "._ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \
michael@0 229 \
michael@0 230 ".else \n\t" \
michael@0 231 ".err \"stub number "#n" >= 1000 not yet supported\"\n" \
michael@0 232 ".endif \n\t" \
michael@0 233 \
michael@0 234 "li 11,"#n" \n\t" \
michael@0 235 "b SharedStub \n" \
michael@0 236 );
michael@0 237 #endif
michael@0 238
michael@0 239 #define SENTINEL_ENTRY(n) \
michael@0 240 nsresult nsXPTCStubBase::Sentinel##n() \
michael@0 241 { \
michael@0 242 NS_ERROR("nsXPTCStubBase::Sentinel called"); \
michael@0 243 return NS_ERROR_NOT_IMPLEMENTED; \
michael@0 244 }
michael@0 245
michael@0 246 #include "xptcstubsdef.inc"

mercurial