|
1 |
|
2 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
3 * |
|
4 * This Source Code Form is subject to the terms of the Mozilla Public |
|
5 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
7 |
|
8 #include "xptcprivate.h" |
|
9 |
|
10 #if _HPUX |
|
11 #error "This code is for HP-PA RISC 32 bit mode only" |
|
12 #endif |
|
13 |
|
14 #include <alloca.h> |
|
15 |
|
16 typedef unsigned nsXPCVariant; |
|
17 |
|
18 extern "C" int32_t |
|
19 invoke_count_bytes(nsISupports* that, const uint32_t methodIndex, |
|
20 const uint32_t paramCount, const nsXPTCVariant* s) |
|
21 { |
|
22 int32_t result = 4; /* variant records do not include self pointer */ |
|
23 |
|
24 /* counts the number of bytes required by the argument stack, |
|
25 64 bit integer, and double requires 8 bytes. All else requires |
|
26 4 bytes. |
|
27 */ |
|
28 |
|
29 { |
|
30 uint32_t indx; |
|
31 for (indx = paramCount; indx > 0; --indx, ++s) |
|
32 { |
|
33 if (! s->IsPtrData()) |
|
34 { |
|
35 if (s->type == nsXPTType::T_I64 || s->type == nsXPTType::T_U64 || |
|
36 s->type == nsXPTType::T_DOUBLE) |
|
37 { |
|
38 /* 64 bit integer and double aligned on 8 byte boundaries */ |
|
39 result += (result & 4) + 8; |
|
40 continue; |
|
41 } |
|
42 } |
|
43 result += 4; /* all other cases use 4 bytes */ |
|
44 } |
|
45 } |
|
46 result -= 72; /* existing stack buffer is 72 bytes */ |
|
47 if (result < 0) |
|
48 return 0; |
|
49 { |
|
50 /* round up to 64 bytes boundary */ |
|
51 int32_t remainder = result & 63; |
|
52 return (remainder == 0) ? result : (result + 64 - remainder); |
|
53 } |
|
54 } |
|
55 |
|
56 extern "C" uint32_t |
|
57 invoke_copy_to_stack(uint32_t* d, |
|
58 const uint32_t paramCount, nsXPTCVariant* s) |
|
59 { |
|
60 |
|
61 typedef struct |
|
62 { |
|
63 uint32_t hi; |
|
64 uint32_t lo; |
|
65 } DU; |
|
66 |
|
67 uint32_t* dest = d; |
|
68 nsXPTCVariant* source = s; |
|
69 /* we clobber param vars by copying stuff on stack, have to use local var */ |
|
70 |
|
71 uint32_t floatflags = 0; |
|
72 /* flag indicating which floating point registers to load */ |
|
73 |
|
74 uint32_t regwords = 1; /* register 26 is reserved for ptr to 'that' */ |
|
75 uint32_t indx; |
|
76 |
|
77 for (indx = paramCount; indx > 0; --indx, --dest, ++source) |
|
78 { |
|
79 if (source->IsPtrData()) |
|
80 { |
|
81 *((void**) dest) = source->ptr; |
|
82 ++regwords; |
|
83 continue; |
|
84 } |
|
85 switch (source->type) |
|
86 { |
|
87 case nsXPTType::T_I8 : *((int32_t*) dest) = source->val.i8; break; |
|
88 case nsXPTType::T_I16 : *((int32_t*) dest) = source->val.i16; break; |
|
89 case nsXPTType::T_I32 : *((int32_t*) dest) = source->val.i32; break; |
|
90 case nsXPTType::T_I64 : |
|
91 case nsXPTType::T_U64 : |
|
92 if (regwords & 1) |
|
93 { |
|
94 /* align on double word boundary */ |
|
95 --dest; |
|
96 ++regwords; |
|
97 } |
|
98 *((uint32_t*) dest) = ((DU *) source)->lo; |
|
99 *((uint32_t*) --dest) = ((DU *) source)->hi; |
|
100 /* big endian - hi word in low addr */ |
|
101 regwords += 2; |
|
102 continue; |
|
103 case nsXPTType::T_DOUBLE : |
|
104 if (regwords & 1) |
|
105 { |
|
106 /* align on double word boundary */ |
|
107 --dest; |
|
108 ++regwords; |
|
109 } |
|
110 switch (regwords) /* load double precision float register */ |
|
111 { |
|
112 case 2: |
|
113 floatflags |= 1; |
|
114 } |
|
115 *((uint32_t*) dest) = ((DU *) source)->lo; |
|
116 *((uint32_t*) --dest) = ((DU *) source)->hi; |
|
117 /* big endian - hi word in low addr */ |
|
118 regwords += 2; |
|
119 continue; |
|
120 case nsXPTType::T_FLOAT : |
|
121 switch (regwords) /* load single precision float register */ |
|
122 { |
|
123 case 1: |
|
124 floatflags |= 2; |
|
125 break; |
|
126 case 2: |
|
127 floatflags |= 4; |
|
128 break; |
|
129 case 3: |
|
130 floatflags |= 8; |
|
131 } |
|
132 *((float*) dest) = source->val.f; |
|
133 break; |
|
134 case nsXPTType::T_U8 : *((uint32_t*) (dest)) = source->val.u8; break; |
|
135 case nsXPTType::T_U16 : *((uint32_t*) (dest)) = source->val.u16; break; |
|
136 case nsXPTType::T_U32 : *((uint32_t*) (dest)) = source->val.u32; break; |
|
137 case nsXPTType::T_BOOL : *((uint32_t*) (dest)) = source->val.b; break; |
|
138 case nsXPTType::T_CHAR : *((uint32_t*) (dest)) = source->val.c; break; |
|
139 case nsXPTType::T_WCHAR : *((int32_t*) (dest)) = source->val.wc; break; |
|
140 |
|
141 default: |
|
142 // all the others are plain pointer types |
|
143 *((void**) dest) = source->val.p; |
|
144 } |
|
145 ++regwords; |
|
146 } |
|
147 return floatflags; |
|
148 } |
|
149 |