]>
Commit | Line | Data |
---|---|---|
5ba3f43e A |
1 | /* |
2 | * Coyright (c) 2005-2015 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
14 | * | |
15 | * Please obtain a copy of the License at | |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
25 | * | |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ | |
27 | */ | |
28 | ||
29 | /* | |
30 | * For arm32 ABI where 64-bit types are aligned to even registers and | |
31 | * 64-bits on stack, we need to unpack registers differently. So | |
32 | * we use the mungers for that. Currently this is just ARMv7k. | |
33 | * | |
34 | * Since arm32 has no need for munging otherwise, we don't include | |
35 | * any of this for other arm32 ABIs | |
36 | */ | |
37 | #if __arm__ && (__BIGGEST_ALIGNMENT__ > 4) | |
38 | ||
39 | #include <sys/munge.h> | |
40 | #include <sys/param.h> | |
41 | #include <mach/thread_status.h> | |
42 | #include <libkern/libkern.h> | |
43 | #include <stdint.h> | |
44 | ||
45 | ||
46 | /* | |
47 | * Userspace args are in r0-r6, then r8, then stack unless this is an | |
48 | * indirect call in which case the syscall number is in r0 then args | |
49 | * are in registers r1-r6, then r8, then stack. This is for mach and | |
50 | * BSD style syscalls. | |
51 | */ | |
52 | ||
53 | ||
54 | #define SS_TO_STYLE(ss) ((ss->r[12] != 0) ? kDirect : kIndirect) | |
55 | #define REGS_TO_STYLE(regs) (SS_TO_STYLE(((const arm_saved_state_t *)regs))) | |
56 | ||
57 | typedef enum { | |
58 | kIndirect = 0, | |
59 | kDirect | |
60 | } style_t; | |
61 | ||
62 | #define DECLARE_AND_CAST(regs, args, ss, uu_args) const arm_saved_state_t *ss = (const arm_saved_state_t *)regs; \ | |
63 | uint32_t *uu_args = (uint32_t *)args; | |
64 | ||
65 | /* | |
66 | * We start 32 bytes after sp since 4 registers are pushed onto the stack | |
67 | * in the userspace syscall handler, and the first 4 stack argumnets are moved | |
68 | * into registers already | |
69 | */ | |
70 | #define ARG_SP_BYTE_OFFSET 32 | |
71 | ||
72 | ||
73 | /* | |
74 | * Marshal in arguments from userspace where no padding exists | |
75 | */ | |
76 | ||
77 | static int | |
78 | marshal_no_pad(const arm_saved_state_t *ss, uint32_t *args, const uint32_t word_count) | |
79 | { | |
80 | int error = 0; | |
81 | /* init assuming kDirect style */ | |
82 | uint32_t copy_count, contiguous_reg_count = 7, contiguous_reg_start = 0; | |
83 | style_t style = SS_TO_STYLE(ss); | |
84 | ||
85 | if (style == kIndirect) { | |
86 | contiguous_reg_count--; | |
87 | contiguous_reg_start++; | |
88 | } | |
89 | ||
90 | /* r0 through r6 */ | |
91 | copy_count = MIN(word_count, contiguous_reg_count); | |
92 | memcpy(args, &(ss->r[contiguous_reg_start]), copy_count * sizeof(uint32_t)); | |
93 | args += copy_count; | |
94 | ||
95 | if (word_count > copy_count) { | |
96 | /* r8 */ | |
97 | *args = ss->r[8]; | |
98 | args++; | |
99 | copy_count++; | |
100 | ||
101 | /* stack */ | |
102 | if (word_count > copy_count) { | |
103 | error = copyin(ss->sp + ARG_SP_BYTE_OFFSET, | |
104 | args, (word_count - copy_count) * sizeof(uint32_t)); | |
105 | if (error) | |
106 | return error; | |
107 | } | |
108 | } | |
109 | return error; | |
110 | } | |
111 | ||
112 | /* | |
113 | * Define mungers to marshal userspace data into argument structs | |
114 | */ | |
115 | ||
116 | int | |
117 | munge_w(const void *regs, void *args) | |
118 | { | |
119 | return marshal_no_pad(regs, args, 1); | |
120 | } | |
121 | ||
122 | int | |
123 | munge_ww(const void *regs, void *args) | |
124 | { | |
125 | return marshal_no_pad(regs, args, 2); | |
126 | } | |
127 | ||
128 | int | |
129 | munge_www(const void *regs, void *args) | |
130 | { | |
131 | return marshal_no_pad(regs, args, 3); | |
132 | } | |
133 | ||
134 | int | |
135 | munge_wwww(const void *regs, void *args) | |
136 | { | |
137 | return marshal_no_pad(regs, args, 4); | |
138 | } | |
139 | ||
140 | int | |
141 | munge_wwwww(const void *regs, void *args) | |
142 | { | |
143 | return marshal_no_pad(regs, args, 5); | |
144 | } | |
145 | ||
146 | int | |
147 | munge_wwwwww(const void *regs, void *args) | |
148 | { | |
149 | return marshal_no_pad(regs, args, 6); | |
150 | } | |
151 | ||
152 | int | |
153 | munge_wwwwwww(const void *regs, void *args) | |
154 | { | |
155 | return marshal_no_pad(regs, args, 7); | |
156 | } | |
157 | ||
158 | int | |
159 | munge_wwwwwwww(const void *regs, void *args) | |
160 | { | |
161 | return marshal_no_pad(regs, args, 8); | |
162 | } | |
163 | ||
164 | int | |
165 | munge_wwl(const void *regs, void *args) | |
166 | { | |
167 | if (REGS_TO_STYLE(regs) == kDirect) | |
168 | return marshal_no_pad(regs, args, 3); | |
169 | else { | |
170 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
171 | ||
172 | uu_args[0] = ss->r[1]; // w | |
173 | uu_args[1] = ss->r[2]; // w | |
174 | uu_args[2] = ss->r[4]; // l (longs are aligned to even registers for armv7k, so skip r3) | |
175 | uu_args[3] = ss->r[5]; // | |
176 | return 0; | |
177 | } | |
178 | } | |
179 | ||
180 | int | |
181 | munge_wwlw(const void *regs, void *args) | |
182 | { | |
183 | if (REGS_TO_STYLE(regs) == kDirect) | |
184 | return marshal_no_pad(regs, args, 5); | |
185 | else { | |
186 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
187 | ||
188 | int error = munge_wwl(regs, args); // wwl | |
189 | uu_args[4] = ss->r[6]; // w | |
190 | return error; | |
191 | } | |
192 | } | |
193 | ||
194 | int | |
195 | munge_wwlww(const void *regs, void *args) | |
196 | { | |
197 | if (REGS_TO_STYLE(regs) == kDirect) | |
198 | // the long-long here is aligned on an even register | |
199 | // so there shouldn't be any padding | |
200 | return marshal_no_pad(regs, args, 6); | |
201 | else { | |
202 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
203 | ||
204 | int error = munge_wwlw(regs, args); // wwlw | |
205 | uu_args[5] = ss->r[8]; // w | |
206 | return error; | |
207 | } | |
208 | } | |
209 | ||
210 | int | |
211 | munge_wwlll(const void *regs, void *args) | |
212 | { | |
213 | if (REGS_TO_STYLE(regs) == kDirect) | |
214 | return marshal_no_pad(regs, args, 8); | |
215 | else { | |
216 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
217 | ||
218 | int error = munge_wwl(regs, args); // wwl | |
219 | if (error) | |
220 | return error; | |
221 | uu_args[4] = ss->r[6]; // l | |
222 | uu_args[5] = ss->r[8]; // | |
223 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // l | |
224 | &(uu_args[6]), 2 * sizeof(uint32_t)); | |
225 | } | |
226 | } | |
227 | ||
228 | int | |
229 | munge_wwllww(const void *regs, void *args) | |
230 | { | |
231 | return munge_wwlll(regs, args); | |
232 | } | |
233 | ||
234 | int | |
235 | munge_wl(const void *regs, void *args) | |
236 | { | |
237 | if (REGS_TO_STYLE(regs) == kDirect) | |
238 | memcpy(args, regs, 4 * sizeof(uint32_t)); | |
239 | else { | |
240 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
241 | ||
242 | uu_args[0] = ss->r[1]; // w | |
243 | uu_args[2] = ss->r[2]; // l | |
244 | uu_args[3] = ss->r[3]; // | |
245 | } | |
246 | return 0; | |
247 | } | |
248 | ||
249 | int | |
250 | munge_wlw(const void *regs, void *args) | |
251 | { | |
252 | if (REGS_TO_STYLE(regs) == kDirect) | |
253 | memcpy(args, regs, 5 * sizeof(uint32_t)); | |
254 | else { | |
255 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
256 | ||
257 | uu_args[0] = ss->r[1]; // w | |
258 | uu_args[2] = ss->r[2]; // l | |
259 | uu_args[3] = ss->r[3]; // | |
260 | uu_args[4] = ss->r[4]; // w | |
261 | } | |
262 | return 0; | |
263 | } | |
264 | ||
265 | int | |
266 | munge_wlww(const void *regs, void *args) | |
267 | { | |
268 | if (REGS_TO_STYLE(regs) == kDirect) | |
269 | memcpy(args, regs, 6 * sizeof(uint32_t)); | |
270 | else { | |
271 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
272 | ||
273 | uu_args[0] = ss->r[1]; // w | |
274 | uu_args[2] = ss->r[2]; // l | |
275 | uu_args[3] = ss->r[3]; // | |
276 | uu_args[4] = ss->r[4]; // w | |
277 | uu_args[5] = ss->r[5]; // w | |
278 | } | |
279 | return 0; | |
280 | } | |
281 | ||
282 | int | |
283 | munge_wlwwwll(const void *regs, void *args) | |
284 | { | |
285 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
286 | ||
287 | if (REGS_TO_STYLE(regs) == kDirect) { | |
288 | memcpy(args, regs, 7 * sizeof(uint32_t)); // wlwww | |
289 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // ll | |
290 | uu_args + 8, 4 * sizeof(uint32_t)); | |
291 | } | |
292 | else { | |
293 | uu_args[0] = ss->r[1]; // w | |
294 | uu_args[2] = ss->r[2]; // l | |
295 | uu_args[3] = ss->r[3]; // | |
296 | uu_args[4] = ss->r[4]; // w | |
297 | uu_args[5] = ss->r[5]; // w | |
298 | uu_args[6] = ss->r[6]; // w | |
299 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // ll | |
300 | uu_args + 8, 4 * sizeof(uint32_t)); | |
301 | } | |
302 | } | |
303 | ||
304 | int | |
305 | munge_wlwwwllw(const void *regs, void *args) | |
306 | { | |
307 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
308 | ||
309 | if (REGS_TO_STYLE(regs) == kDirect) { | |
310 | memcpy(args, regs, 7 * sizeof(uint32_t)); // wlwww | |
311 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, | |
312 | uu_args + 8, 5 * sizeof(uint32_t)); // ll | |
313 | } | |
314 | else { | |
315 | uu_args[0] = ss->r[1]; // w | |
316 | uu_args[2] = ss->r[2]; // l | |
317 | uu_args[3] = ss->r[3]; // | |
318 | uu_args[4] = ss->r[4]; // w | |
319 | uu_args[5] = ss->r[5]; // w | |
320 | uu_args[6] = ss->r[6]; // w | |
321 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // llw | |
322 | uu_args + 8, 5 * sizeof(uint32_t)); | |
323 | } | |
324 | } | |
325 | ||
326 | int | |
327 | munge_wlwwlwlw(const void *regs, void *args) | |
328 | { | |
329 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
330 | ||
331 | if (REGS_TO_STYLE(regs) == kDirect) | |
332 | uu_args[0] = ss->r[0]; // w | |
333 | else | |
334 | uu_args[0] = ss->r[1]; // w | |
335 | ||
336 | uu_args[2] = ss->r[2]; // l | |
337 | uu_args[3] = ss->r[3]; // | |
338 | uu_args[4] = ss->r[4]; // w | |
339 | uu_args[5] = ss->r[5]; // w | |
340 | uu_args[6] = ss->r[6]; // l | |
341 | uu_args[7] = ss->r[8]; // | |
342 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // wlw | |
343 | uu_args + 8, 5 * sizeof(uint32_t)); | |
344 | } | |
345 | ||
346 | int | |
347 | munge_wll(const void *regs, void *args) | |
348 | { | |
349 | if (REGS_TO_STYLE(regs) == kDirect) | |
350 | memcpy(args, regs, 6 * sizeof(uint32_t)); | |
351 | else { | |
352 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
353 | ||
354 | uu_args[0] = ss->r[1]; // w | |
355 | uu_args[2] = ss->r[2]; // l | |
356 | uu_args[3] = ss->r[3]; // | |
357 | uu_args[4] = ss->r[4]; // l | |
358 | uu_args[5] = ss->r[5]; // | |
359 | } | |
360 | return 0; | |
361 | } | |
362 | ||
363 | int | |
364 | munge_wlll(const void *regs, void *args) | |
365 | { | |
366 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
367 | ||
368 | int error = munge_wll(regs, args); // wll | |
369 | uu_args[6] = ss->r[6]; // l | |
370 | uu_args[7] = ss->r[8]; // | |
371 | return error; | |
372 | } | |
373 | ||
374 | int | |
375 | munge_wllll(const void *regs, void *args) | |
376 | { | |
377 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
378 | ||
379 | munge_wlll(regs, args); // wlll | |
380 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // l | |
381 | uu_args + 8, 2 * sizeof(uint32_t)); | |
382 | } | |
383 | ||
384 | int | |
385 | munge_wllww(const void *regs, void *args) | |
386 | { | |
387 | return munge_wlll(regs, args); | |
388 | } | |
389 | ||
390 | int | |
391 | munge_wllwwll(const void *regs, void *args) | |
392 | { | |
393 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
394 | ||
395 | int error = munge_wlll(regs, args); // wllww | |
396 | if (error) | |
397 | return error; | |
398 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // ll | |
399 | uu_args + 8, 4 * sizeof(uint32_t)); | |
400 | } | |
401 | ||
402 | int | |
403 | munge_wwwlw(const void *regs, void *args) | |
404 | { | |
405 | if (REGS_TO_STYLE(regs) == kDirect) | |
406 | memcpy(args, regs, 7 * sizeof(uint32_t)); | |
407 | else { | |
408 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
409 | ||
410 | uu_args[0] = ss->r[1]; // w | |
411 | uu_args[1] = ss->r[2]; // w | |
412 | uu_args[2] = ss->r[3]; // w | |
413 | uu_args[4] = ss->r[4]; // l | |
414 | uu_args[5] = ss->r[5]; // | |
415 | uu_args[6] = ss->r[6]; // w | |
416 | } | |
417 | return 0; | |
418 | } | |
419 | ||
420 | int | |
421 | munge_wwwlww(const void *regs, void *args) | |
422 | { | |
423 | if (REGS_TO_STYLE(regs) == kDirect) | |
424 | return munge_wlll(regs, args); | |
425 | else { | |
426 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
427 | ||
428 | uu_args[0] = ss->r[1]; // w | |
429 | uu_args[1] = ss->r[2]; // w | |
430 | uu_args[2] = ss->r[3]; // w | |
431 | uu_args[4] = ss->r[4]; // l | |
432 | uu_args[5] = ss->r[5]; // | |
433 | uu_args[6] = ss->r[6]; // w | |
434 | uu_args[7] = ss->r[8]; // w | |
435 | return 0; | |
436 | } | |
437 | } | |
438 | ||
439 | int | |
440 | munge_wwwl(const void *regs, void *args) | |
441 | { | |
442 | if (REGS_TO_STYLE(regs) == kDirect) | |
443 | return munge_wll(regs, args); | |
444 | else { | |
445 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
446 | ||
447 | uu_args[0] = ss->r[1]; // w | |
448 | uu_args[1] = ss->r[2]; // w | |
449 | uu_args[2] = ss->r[3]; // w | |
450 | uu_args[4] = ss->r[4]; // l | |
451 | uu_args[5] = ss->r[5]; // | |
452 | return 0; | |
453 | } | |
454 | } | |
455 | ||
456 | int | |
457 | munge_wwwwl(const void *regs, void *args) | |
458 | { | |
459 | if (REGS_TO_STYLE(regs) == kDirect) | |
460 | return marshal_no_pad(regs, args, 6); | |
461 | else { | |
462 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
463 | ||
464 | uu_args[0] = ss->r[1]; // w | |
465 | uu_args[1] = ss->r[2]; // w | |
466 | uu_args[2] = ss->r[3]; // w | |
467 | uu_args[3] = ss->r[4]; // w | |
468 | uu_args[4] = ss->r[6]; // l | |
469 | uu_args[5] = ss->r[8]; // | |
470 | return 0; | |
471 | } | |
472 | } | |
473 | ||
474 | int | |
475 | munge_wwwwlw(const void *regs, void *args) | |
476 | { | |
477 | if (REGS_TO_STYLE(regs) == kDirect) | |
478 | return marshal_no_pad(regs, args, 7); | |
479 | else { | |
480 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
481 | ||
482 | int error = munge_wwwwl(regs, args); // wwwwl | |
483 | if (error) | |
484 | return error; | |
485 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // w | |
486 | uu_args + 6, sizeof(uint32_t)); | |
487 | } | |
488 | } | |
489 | ||
490 | int | |
491 | munge_wwwwwl(const void *regs, void *args) | |
492 | { | |
493 | if (REGS_TO_STYLE(regs) == kDirect) | |
494 | return munge_wlll(regs, args); | |
495 | else { | |
496 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
497 | ||
498 | uu_args[0] = ss->r[1]; // w | |
499 | uu_args[1] = ss->r[2]; // w | |
500 | uu_args[2] = ss->r[3]; // w | |
501 | uu_args[3] = ss->r[4]; // w | |
502 | uu_args[4] = ss->r[5]; // w | |
503 | uu_args[6] = ss->r[6]; // l | |
504 | uu_args[7] = ss->r[8]; // | |
505 | return 0; | |
506 | } | |
507 | } | |
508 | ||
509 | int | |
510 | munge_wwwwwlww(const void *regs, void *args) | |
511 | { | |
512 | if (REGS_TO_STYLE(regs) == kDirect) | |
513 | return munge_wllll(regs, args); | |
514 | else { | |
515 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
516 | ||
517 | int error = munge_wwwwwl(regs, args); // wwwwwl | |
518 | if (error) | |
519 | return error; | |
520 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // ww | |
521 | uu_args + 8, 2 * sizeof(uint32_t)); | |
522 | } | |
523 | } | |
524 | ||
525 | int | |
526 | munge_wwwwwllw(const void *regs, void *args) | |
527 | { | |
528 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
529 | ||
530 | int error = munge_wwwwwl(regs, args); // wwwwwl | |
531 | if (error) | |
532 | return error; | |
533 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // lw | |
534 | uu_args + 8, 3 * sizeof(uint32_t)); | |
535 | } | |
536 | ||
537 | int | |
538 | munge_wwwwwlll(const void *regs, void *args) | |
539 | { | |
540 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
541 | int error; | |
542 | ||
543 | if (REGS_TO_STYLE(regs) == kDirect) { | |
544 | error = munge_wlll(regs, args); // wlll | |
545 | if (error) | |
546 | return error; | |
547 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // ll | |
548 | uu_args + 8, 4 * sizeof(uint32_t)); | |
549 | } | |
550 | else { | |
551 | error = munge_wwwwwl(regs, args); // wwwwwl | |
552 | if (error) | |
553 | return error; | |
554 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // ll | |
555 | uu_args + 8, 4 * sizeof(uint32_t)); | |
556 | } | |
557 | } | |
558 | ||
559 | int | |
560 | munge_wwwwwwl(const void *regs, void *args) | |
561 | { | |
562 | munge_wwlll(regs, args); | |
563 | ||
564 | if (REGS_TO_STYLE(regs) == kDirect) | |
565 | return marshal_no_pad(regs, args, 8); | |
566 | else { | |
567 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
568 | ||
569 | memcpy(args, &(ss->r[1]), 6 * sizeof(uint32_t)); // wwwwww | |
570 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // l | |
571 | &(uu_args[6]), 2 * sizeof(uint32_t)); | |
572 | } | |
573 | } | |
574 | ||
575 | int | |
576 | munge_wwwwwwlw(const void *regs, void *args) | |
577 | { | |
578 | if (REGS_TO_STYLE(regs) == kDirect) | |
579 | return marshal_no_pad(regs, args, 9); | |
580 | else { | |
581 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
582 | ||
583 | memcpy(args, &(ss->r[1]), 6 * sizeof(uint32_t)); // wwwwww | |
584 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // lw | |
585 | &(uu_args[6]), 3 * sizeof(uint32_t)); | |
586 | } | |
587 | } | |
588 | ||
589 | int | |
590 | munge_wwwwwwll(const void *regs, void *args) | |
591 | { | |
592 | if (REGS_TO_STYLE(regs) == kDirect) | |
593 | return marshal_no_pad(regs, args, 10); | |
594 | else { | |
595 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
596 | ||
597 | memcpy(args, &(ss->r[1]), 6 * sizeof(uint32_t)); // wwwwww | |
598 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // ll | |
599 | &(uu_args[6]), 4 * sizeof(uint32_t)); | |
600 | } | |
601 | } | |
602 | ||
603 | int | |
604 | munge_wsw(const void *regs, void *args) | |
605 | { | |
606 | return munge_wlw(regs, args); | |
607 | } | |
608 | ||
609 | int | |
610 | munge_wws(const void *regs, void *args) | |
611 | { | |
612 | return munge_wwl(regs, args); | |
613 | } | |
614 | ||
615 | int | |
616 | munge_wwws(const void *regs, void *args) | |
617 | { | |
618 | return munge_wwwl(regs, args); | |
619 | } | |
620 | ||
621 | int | |
622 | munge_wwwsw(const void *regs, void *args) | |
623 | { | |
624 | return munge_wwwlw(regs, args); | |
625 | } | |
626 | ||
627 | int | |
628 | munge_llllll(const void *regs, void *args) | |
629 | { | |
630 | if (REGS_TO_STYLE(regs) == kDirect) | |
631 | return marshal_no_pad(regs, args, 12); | |
632 | else { | |
633 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
634 | ||
635 | uu_args[0] = ss->r[2]; // l | |
636 | uu_args[1] = ss->r[3]; // | |
637 | uu_args[2] = ss->r[4]; // l | |
638 | uu_args[3] = ss->r[5]; // | |
639 | uu_args[4] = ss->r[6]; // l | |
640 | uu_args[5] = ss->r[8]; // | |
641 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // lll | |
642 | uu_args + 6, 6 * sizeof(uint32_t)); | |
643 | } | |
644 | } | |
645 | ||
646 | int | |
647 | munge_ll(const void *regs, void *args) | |
648 | { | |
649 | if (REGS_TO_STYLE(regs) == kDirect) | |
650 | return marshal_no_pad(regs, args, 4); | |
651 | else | |
652 | memcpy(args, (const uint32_t*)regs + 2, 4 * sizeof(uint32_t)); | |
653 | return 0; | |
654 | } | |
655 | ||
656 | int | |
657 | munge_l(const void *regs, void *args) | |
658 | { | |
659 | if (REGS_TO_STYLE(regs) == kDirect) | |
660 | return marshal_no_pad(regs, args, 2); | |
661 | else | |
662 | memcpy(args, (const uint32_t*)regs + 2, 2 * sizeof(uint32_t)); | |
663 | return 0; | |
664 | } | |
665 | ||
666 | int | |
667 | munge_lw(const void *regs, void *args) | |
668 | { | |
669 | if (REGS_TO_STYLE(regs) == kDirect) | |
670 | return marshal_no_pad(regs, args, 3); | |
671 | else | |
672 | memcpy(args, (const uint32_t*)regs + 2, 3 * sizeof(uint32_t)); | |
673 | return 0; | |
674 | } | |
675 | ||
676 | int | |
677 | munge_lwww(const void *regs, void *args) | |
678 | { | |
679 | if (REGS_TO_STYLE(regs) == kDirect) | |
680 | return marshal_no_pad(regs, args, 5); | |
681 | else | |
682 | memcpy(args, (const uint32_t*)regs + 2, 5 * sizeof(uint32_t)); | |
683 | return 0; | |
684 | } | |
685 | ||
686 | int | |
687 | munge_lwwwwwww(const void *regs, void *args) | |
688 | { | |
689 | if (REGS_TO_STYLE(regs) == kDirect) | |
690 | return marshal_no_pad(regs, args, 9); | |
691 | else { | |
692 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
693 | ||
694 | uu_args[0] = ss->r[2]; // l | |
695 | uu_args[1] = ss->r[3]; // | |
696 | uu_args[2] = ss->r[4]; // w | |
697 | uu_args[3] = ss->r[5]; // w | |
698 | uu_args[4] = ss->r[6]; // w | |
699 | uu_args[5] = ss->r[8]; // w | |
700 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // www | |
701 | uu_args + 6, 3 * sizeof(uint32_t)); | |
702 | } | |
703 | } | |
704 | ||
705 | int | |
706 | munge_wwlwww(const void *regs, void *args) | |
707 | { | |
708 | if (REGS_TO_STYLE(regs) == kDirect) | |
709 | return marshal_no_pad(regs, args, 7); | |
710 | else { | |
711 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
712 | ||
713 | uu_args[0] = ss->r[1]; // w | |
714 | uu_args[1] = ss->r[2]; // w | |
715 | uu_args[2] = ss->r[4]; // l | |
716 | uu_args[3] = ss->r[5]; // | |
717 | uu_args[4] = ss->r[6]; // w | |
718 | uu_args[5] = ss->r[8]; // w | |
719 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // w | |
720 | uu_args + 6, sizeof(uint32_t)); | |
721 | } | |
722 | ||
723 | } | |
724 | ||
725 | int | |
726 | munge_wlwwwl(const void *regs, void *args) | |
727 | { | |
728 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
729 | ||
730 | if (REGS_TO_STYLE(regs) == kDirect) { | |
731 | memcpy(args, regs, 7 * sizeof(uint32_t)); // wlwww | |
732 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // l | |
733 | uu_args + 8, 2 * sizeof(uint32_t)); | |
734 | } else { | |
735 | uu_args[0] = ss->r[1]; // w | |
736 | uu_args[2] = ss->r[2]; // l | |
737 | uu_args[3] = ss->r[3]; // | |
738 | uu_args[4] = ss->r[4]; // w | |
739 | uu_args[5] = ss->r[5]; // w | |
740 | uu_args[6] = ss->r[6]; // w | |
741 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // l | |
742 | uu_args + 8, 2 * sizeof(uint32_t)); | |
743 | } | |
744 | } | |
745 | ||
746 | int | |
747 | munge_wwlwwwl(const void *regs, void *args) | |
748 | { | |
749 | DECLARE_AND_CAST(regs, args, ss, uu_args); | |
750 | ||
751 | if (REGS_TO_STYLE(regs) == kDirect) { | |
752 | memcpy(args, regs, 7 * sizeof(uint32_t)); // wwlwww | |
753 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // l | |
754 | uu_args + 8, 2 * sizeof(uint32_t)); | |
755 | } else { | |
756 | uu_args[0] = ss->r[1]; // w | |
757 | uu_args[1] = ss->r[2]; // w | |
758 | uu_args[2] = ss->r[4]; // l | |
759 | uu_args[3] = ss->r[5]; // | |
760 | uu_args[4] = ss->r[6]; // w | |
761 | uu_args[5] = ss->r[8]; // w | |
762 | return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // wl | |
763 | uu_args + 6, 4 * sizeof(uint32_t)); | |
764 | } | |
765 | } | |
766 | ||
767 | #endif // __arm__ && (__BIGGEST_ALIGNMENT__ > 4) |