xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm_netbsd.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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 /* Platform specific code to invoke XPCOM methods on native objects */
michael@0 7
michael@0 8 #include "xptcprivate.h"
michael@0 9
michael@0 10 // Remember that these 'words' are 32bit DWORDS
michael@0 11
michael@0 12 static uint32_t
michael@0 13 invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
michael@0 14 {
michael@0 15 uint32_t result = 0;
michael@0 16 for(uint32_t i = 0; i < paramCount; i++, s++)
michael@0 17 {
michael@0 18 if(s->IsPtrData())
michael@0 19 {
michael@0 20 result++;
michael@0 21 continue;
michael@0 22 }
michael@0 23 switch(s->type)
michael@0 24 {
michael@0 25 case nsXPTType::T_I8 :
michael@0 26 case nsXPTType::T_I16 :
michael@0 27 case nsXPTType::T_I32 :
michael@0 28 result++;
michael@0 29 break;
michael@0 30 case nsXPTType::T_I64 :
michael@0 31 result+=2;
michael@0 32 break;
michael@0 33 case nsXPTType::T_U8 :
michael@0 34 case nsXPTType::T_U16 :
michael@0 35 case nsXPTType::T_U32 :
michael@0 36 result++;
michael@0 37 break;
michael@0 38 case nsXPTType::T_U64 :
michael@0 39 result+=2;
michael@0 40 break;
michael@0 41 case nsXPTType::T_FLOAT :
michael@0 42 result++;
michael@0 43 break;
michael@0 44 case nsXPTType::T_DOUBLE :
michael@0 45 result+=2;
michael@0 46 break;
michael@0 47 case nsXPTType::T_BOOL :
michael@0 48 case nsXPTType::T_CHAR :
michael@0 49 case nsXPTType::T_WCHAR :
michael@0 50 result++;
michael@0 51 break;
michael@0 52 default:
michael@0 53 // all the others are plain pointer types
michael@0 54 result++;
michael@0 55 break;
michael@0 56 }
michael@0 57 }
michael@0 58 return result;
michael@0 59 }
michael@0 60
michael@0 61 static void
michael@0 62 invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s)
michael@0 63 {
michael@0 64 for(uint32_t i = 0; i < paramCount; i++, d++, s++)
michael@0 65 {
michael@0 66 if(s->IsPtrData())
michael@0 67 {
michael@0 68 *((void**)d) = s->ptr;
michael@0 69 continue;
michael@0 70 }
michael@0 71 switch(s->type)
michael@0 72 {
michael@0 73 case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break;
michael@0 74 case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break;
michael@0 75 case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break;
michael@0 76 case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break;
michael@0 77 case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break;
michael@0 78 case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break;
michael@0 79 case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break;
michael@0 80 case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break;
michael@0 81 case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
michael@0 82 case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
michael@0 83 case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break;
michael@0 84 case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break;
michael@0 85 case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
michael@0 86 default:
michael@0 87 // all the others are plain pointer types
michael@0 88 *((void**)d) = s->val.p;
michael@0 89 break;
michael@0 90 }
michael@0 91 }
michael@0 92 }
michael@0 93
michael@0 94 extern "C"
michael@0 95 struct my_params_struct {
michael@0 96 nsISupports* that;
michael@0 97 uint32_t Index;
michael@0 98 uint32_t Count;
michael@0 99 nsXPTCVariant* params;
michael@0 100 uint32_t fn_count;
michael@0 101 uint32_t fn_copy;
michael@0 102 };
michael@0 103
michael@0 104 XPTC_PUBLIC_API(nsresult)
michael@0 105 XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
michael@0 106 uint32_t paramCount, nsXPTCVariant* params)
michael@0 107 {
michael@0 108 uint32_t result;
michael@0 109 struct my_params_struct my_params;
michael@0 110 my_params.that = that;
michael@0 111 my_params.Index = methodIndex;
michael@0 112 my_params.Count = paramCount;
michael@0 113 my_params.params = params;
michael@0 114 my_params.fn_copy = (uint32_t) &invoke_copy_to_stack;
michael@0 115 my_params.fn_count = (uint32_t) &invoke_count_words;
michael@0 116
michael@0 117 /* This is to call a given method of class that.
michael@0 118 * The parameters are in params, the number is in paramCount.
michael@0 119 * The routine will issue calls to count the number of words
michael@0 120 * required for argument passing and to copy the arguments to
michael@0 121 * the stack.
michael@0 122 * Since APCS passes the first 3 params in r1-r3, we need to
michael@0 123 * load the first three words from the stack and correct the stack
michael@0 124 * pointer (sp) in the appropriate way. This means:
michael@0 125 *
michael@0 126 * 1.) more than 3 arguments: load r1-r3, correct sp and remember No.
michael@0 127 * of bytes left on the stack in r4
michael@0 128 *
michael@0 129 * 2.) <= 2 args: load r1-r3 (we won't be causing a stack overflow I hope),
michael@0 130 * restore sp as if nothing had happened and set the marker r4 to zero.
michael@0 131 *
michael@0 132 * Afterwards sp will be restored using the value in r4 (which is not a temporary register
michael@0 133 * and will be preserved by the function/method called according to APCS [ARM Procedure
michael@0 134 * Calling Standard]).
michael@0 135 *
michael@0 136 * !!! IMPORTANT !!!
michael@0 137 * This routine makes assumptions about the vtable layout of the c++ compiler. It's implemented
michael@0 138 * for arm-linux GNU g++ >= 2.8.1 (including egcs and gcc-2.95.[1-3])!
michael@0 139 *
michael@0 140 */
michael@0 141
michael@0 142 __asm__ __volatile__(
michael@0 143 "ldr r1, [%1, #12] \n\t" /* prepare to call invoke_count_words */
michael@0 144 "ldr ip, [%1, #16] \n\t" /* r0=paramCount, r1=params */
michael@0 145 "ldr r0, [%1, #8] \n\t"
michael@0 146 "mov lr, pc \n\t" /* call it... */
michael@0 147 "mov pc, ip \n\t"
michael@0 148 "mov r4, r0, lsl #2 \n\t" /* This is the amount of bytes needed. */
michael@0 149 "sub sp, sp, r4 \n\t" /* use stack space for the args... */
michael@0 150 "mov r0, sp \n\t" /* prepare a pointer an the stack */
michael@0 151 "ldr r1, [%1, #8] \n\t" /* =paramCount */
michael@0 152 "ldr r2, [%1, #12] \n\t" /* =params */
michael@0 153 "ldr ip, [%1, #20] \n\t" /* =invoke_copy_to_stack */
michael@0 154 "mov lr, pc \n\t" /* copy args to the stack like the */
michael@0 155 "mov pc, ip \n\t" /* compiler would. */
michael@0 156 "ldr r0, [%1] \n\t" /* =that */
michael@0 157 "ldr r1, [r0, #0] \n\t" /* get that->vtable offset */
michael@0 158 "ldr r2, [%1, #4] \n\t"
michael@0 159 "add r2, r1, r2, lsl #3\n\t" /* a vtable_entry(x)=8 + (8 bytes * x) */
michael@0 160 "add r2, r2, #8 \n\t" /* with this compilers */
michael@0 161 "ldr r3, [r2] \n\t" /* get virtual offset from vtable */
michael@0 162 "mov r3, r3, lsl #16 \n\t"
michael@0 163 "add r0, r0, r3, asr #16\n\t"
michael@0 164 "ldr ip, [r2, #4] \n\t" /* get method address from vtable */
michael@0 165 "cmp r4, #12 \n\t" /* more than 3 arguments??? */
michael@0 166 "ldmgtia sp!, {r1, r2, r3}\n\t" /* yes: load arguments for r1-r3 */
michael@0 167 "subgt r4, r4, #12 \n\t" /* and correct the stack pointer */
michael@0 168 "ldmleia sp, {r1, r2, r3}\n\t" /* no: load r1-r3 from stack */
michael@0 169 "addle sp, sp, r4 \n\t" /* and restore stack pointer */
michael@0 170 "movle r4, #0 \n\t" /* a mark for restoring sp */
michael@0 171 "mov lr, pc \n\t" /* call mathod */
michael@0 172 "mov pc, ip \n\t"
michael@0 173 "add sp, sp, r4 \n\t" /* restore stack pointer */
michael@0 174 "mov %0, r0 \n\t" /* the result... */
michael@0 175 : "=r" (result)
michael@0 176 : "r" (&my_params)
michael@0 177 : "r0", "r1", "r2", "r3", "r4", "ip", "lr"
michael@0 178 );
michael@0 179
michael@0 180 return result;
michael@0 181 }

mercurial