xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_openbsd.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 *
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 // Platform specific code to invoke XPCOM methods on native objects
michael@0 8
michael@0 9 #include "xptcprivate.h"
michael@0 10
michael@0 11 // 6 integral parameters are passed in registers
michael@0 12 const uint32_t GPR_COUNT = 6;
michael@0 13
michael@0 14 // 8 floating point parameters are passed in SSE registers
michael@0 15 const uint32_t FPR_COUNT = 8;
michael@0 16
michael@0 17 // Remember that these 'words' are 64-bit long
michael@0 18 static inline void
michael@0 19 invoke_count_words(uint32_t paramCount, nsXPTCVariant * s,
michael@0 20 uint32_t & nr_gpr, uint32_t & nr_fpr, uint32_t & nr_stack)
michael@0 21 {
michael@0 22 nr_gpr = 1; // skip one GP register for 'that'
michael@0 23 nr_fpr = 0;
michael@0 24 nr_stack = 0;
michael@0 25
michael@0 26 /* Compute number of eightbytes of class MEMORY. */
michael@0 27 for (uint32_t i = 0; i < paramCount; i++, s++) {
michael@0 28 if (!s->IsPtrData()
michael@0 29 && (s->type == nsXPTType::T_FLOAT || s->type == nsXPTType::T_DOUBLE)) {
michael@0 30 if (nr_fpr < FPR_COUNT)
michael@0 31 nr_fpr++;
michael@0 32 else
michael@0 33 nr_stack++;
michael@0 34 }
michael@0 35 else {
michael@0 36 if (nr_gpr < GPR_COUNT)
michael@0 37 nr_gpr++;
michael@0 38 else
michael@0 39 nr_stack++;
michael@0 40 }
michael@0 41 }
michael@0 42 }
michael@0 43
michael@0 44 static void
michael@0 45 invoke_copy_to_stack(uint64_t * d, uint32_t paramCount, nsXPTCVariant * s,
michael@0 46 uint64_t * gpregs, double * fpregs)
michael@0 47 {
michael@0 48 uint32_t nr_gpr = 1; // skip one GP register for 'that'
michael@0 49 uint32_t nr_fpr = 0;
michael@0 50 uint64_t value;
michael@0 51
michael@0 52 for (uint32_t i = 0; i < paramCount; i++, s++) {
michael@0 53 if (s->IsPtrData())
michael@0 54 value = (uint64_t) s->ptr;
michael@0 55 else {
michael@0 56 switch (s->type) {
michael@0 57 case nsXPTType::T_FLOAT: break;
michael@0 58 case nsXPTType::T_DOUBLE: break;
michael@0 59 case nsXPTType::T_I8: value = s->val.i8; break;
michael@0 60 case nsXPTType::T_I16: value = s->val.i16; break;
michael@0 61 case nsXPTType::T_I32: value = s->val.i32; break;
michael@0 62 case nsXPTType::T_I64: value = s->val.i64; break;
michael@0 63 case nsXPTType::T_U8: value = s->val.u8; break;
michael@0 64 case nsXPTType::T_U16: value = s->val.u16; break;
michael@0 65 case nsXPTType::T_U32: value = s->val.u32; break;
michael@0 66 case nsXPTType::T_U64: value = s->val.u64; break;
michael@0 67 case nsXPTType::T_BOOL: value = s->val.b; break;
michael@0 68 case nsXPTType::T_CHAR: value = s->val.c; break;
michael@0 69 case nsXPTType::T_WCHAR: value = s->val.wc; break;
michael@0 70 default: value = (uint64_t) s->val.p; break;
michael@0 71 }
michael@0 72 }
michael@0 73
michael@0 74 if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
michael@0 75 if (nr_fpr < FPR_COUNT)
michael@0 76 fpregs[nr_fpr++] = s->val.d;
michael@0 77 else {
michael@0 78 *((double *)d) = s->val.d;
michael@0 79 d++;
michael@0 80 }
michael@0 81 }
michael@0 82 else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
michael@0 83 if (nr_fpr < FPR_COUNT)
michael@0 84 // The value in %xmm register is already prepared to
michael@0 85 // be retrieved as a float. Therefore, we pass the
michael@0 86 // value verbatim, as a double without conversion.
michael@0 87 fpregs[nr_fpr++] = s->val.d;
michael@0 88 else {
michael@0 89 *((float *)d) = s->val.f;
michael@0 90 d++;
michael@0 91 }
michael@0 92 }
michael@0 93 else {
michael@0 94 if (nr_gpr < GPR_COUNT)
michael@0 95 gpregs[nr_gpr++] = value;
michael@0 96 else
michael@0 97 *d++ = value;
michael@0 98 }
michael@0 99 }
michael@0 100 }
michael@0 101
michael@0 102 EXPORT_XPCOM_API(nsresult)
michael@0 103 NS_InvokeByIndex(nsISupports * that, uint32_t methodIndex,
michael@0 104 uint32_t paramCount, nsXPTCVariant * params)
michael@0 105 {
michael@0 106 uint32_t nr_gpr, nr_fpr, nr_stack;
michael@0 107 invoke_count_words(paramCount, params, nr_gpr, nr_fpr, nr_stack);
michael@0 108
michael@0 109 // Stack, if used, must be 16-bytes aligned
michael@0 110 if (nr_stack)
michael@0 111 nr_stack = (nr_stack + 1) & ~1;
michael@0 112
michael@0 113 // Load parameters to stack, if necessary
michael@0 114 uint64_t *stack = (uint64_t *) __builtin_alloca(nr_stack * 8);
michael@0 115 uint64_t gpregs[GPR_COUNT];
michael@0 116 double fpregs[FPR_COUNT];
michael@0 117 invoke_copy_to_stack(stack, paramCount, params, gpregs, fpregs);
michael@0 118
michael@0 119 // Load FPR registers from fpregs[]
michael@0 120 register double d0 asm("xmm0");
michael@0 121 register double d1 asm("xmm1");
michael@0 122 register double d2 asm("xmm2");
michael@0 123 register double d3 asm("xmm3");
michael@0 124 register double d4 asm("xmm4");
michael@0 125 register double d5 asm("xmm5");
michael@0 126 register double d6 asm("xmm6");
michael@0 127 register double d7 asm("xmm7");
michael@0 128
michael@0 129 switch (nr_fpr) {
michael@0 130 #define ARG_FPR(N) \
michael@0 131 case N+1: d##N = fpregs[N];
michael@0 132 ARG_FPR(7);
michael@0 133 ARG_FPR(6);
michael@0 134 ARG_FPR(5);
michael@0 135 ARG_FPR(4);
michael@0 136 ARG_FPR(3);
michael@0 137 ARG_FPR(2);
michael@0 138 ARG_FPR(1);
michael@0 139 ARG_FPR(0);
michael@0 140 case 0:;
michael@0 141 #undef ARG_FPR
michael@0 142 }
michael@0 143
michael@0 144 // Load GPR registers from gpregs[]
michael@0 145 register uint64_t a0 asm("rdi");
michael@0 146 register uint64_t a1 asm("rsi");
michael@0 147 register uint64_t a2 asm("rdx");
michael@0 148 register uint64_t a3 asm("rcx");
michael@0 149 register uint64_t a4 asm("r8");
michael@0 150 register uint64_t a5 asm("r9");
michael@0 151
michael@0 152 switch (nr_gpr) {
michael@0 153 #define ARG_GPR(N) \
michael@0 154 case N+1: a##N = gpregs[N];
michael@0 155 ARG_GPR(5);
michael@0 156 ARG_GPR(4);
michael@0 157 ARG_GPR(3);
michael@0 158 ARG_GPR(2);
michael@0 159 ARG_GPR(1);
michael@0 160 case 1: a0 = (uint64_t) that;
michael@0 161 case 0:;
michael@0 162 #undef ARG_GPR
michael@0 163 }
michael@0 164
michael@0 165 // Ensure that assignments to SSE registers won't be optimized away
michael@0 166 asm("" ::
michael@0 167 "x" (d0), "x" (d1), "x" (d2), "x" (d3),
michael@0 168 "x" (d4), "x" (d5), "x" (d6), "x" (d7));
michael@0 169
michael@0 170 // Get pointer to method
michael@0 171 uint64_t methodAddress = *((uint64_t *)that);
michael@0 172 methodAddress += 8 * methodIndex;
michael@0 173 methodAddress = *((uint64_t *)methodAddress);
michael@0 174
michael@0 175 typedef nsresult (*Method)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
michael@0 176 nsresult result = ((Method)methodAddress)(a0, a1, a2, a3, a4, a5);
michael@0 177 return result;
michael@0 178 }

mercurial