]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/dev/arm/munge.c
xnu-4570.1.46.tar.gz
[apple/xnu.git] / bsd / dev / arm / munge.c
diff --git a/bsd/dev/arm/munge.c b/bsd/dev/arm/munge.c
new file mode 100644 (file)
index 0000000..d98953a
--- /dev/null
@@ -0,0 +1,767 @@
+/*
+ * Coyright (c) 2005-2015 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ * 
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+/* 
+ * For arm32 ABI where 64-bit types are aligned to even registers and
+ * 64-bits on stack, we need to unpack registers differently. So
+ * we use the mungers for that. Currently this is just ARMv7k.
+ *
+ * Since arm32 has no need for munging otherwise, we don't include
+ * any of this for other arm32 ABIs
+ */
+#if __arm__ && (__BIGGEST_ALIGNMENT__ > 4)
+
+#include <sys/munge.h>
+#include <sys/param.h>
+#include <mach/thread_status.h>
+#include <libkern/libkern.h>
+#include <stdint.h>
+
+
+/* 
+ * Userspace args are in r0-r6, then r8, then stack unless this is an
+ * indirect call in which case the syscall number is in r0 then args
+ * are in registers r1-r6, then r8, then stack. This is for mach and
+ * BSD style syscalls.
+ */
+
+
+#define SS_TO_STYLE(ss)                            ((ss->r[12] != 0) ? kDirect : kIndirect)
+#define REGS_TO_STYLE(regs)                        (SS_TO_STYLE(((const arm_saved_state_t *)regs)))
+
+typedef enum {
+       kIndirect = 0,
+       kDirect
+} style_t;
+
+#define DECLARE_AND_CAST(regs, args, ss, uu_args)  const arm_saved_state_t *ss = (const arm_saved_state_t *)regs; \
+                                                   uint32_t *uu_args = (uint32_t *)args;
+
+/* 
+ * We start 32 bytes after sp since 4 registers are pushed onto the stack
+ * in the userspace syscall handler, and the first 4 stack argumnets are moved 
+ * into registers already
+ */
+#define ARG_SP_BYTE_OFFSET                         32
+
+
+/*
+ * Marshal in arguments from userspace where no padding exists
+ */
+
+static int
+marshal_no_pad(const arm_saved_state_t *ss, uint32_t *args, const uint32_t word_count)
+{
+       int error = 0;
+       /* init assuming kDirect style */
+       uint32_t copy_count, contiguous_reg_count = 7, contiguous_reg_start = 0;
+       style_t style = SS_TO_STYLE(ss);
+
+       if (style == kIndirect) {
+               contiguous_reg_count--;
+               contiguous_reg_start++;
+       }
+
+       /* r0 through r6 */
+       copy_count = MIN(word_count, contiguous_reg_count);
+       memcpy(args, &(ss->r[contiguous_reg_start]), copy_count * sizeof(uint32_t));
+       args += copy_count;
+
+       if (word_count > copy_count) {
+               /* r8 */
+               *args = ss->r[8];
+               args++;
+               copy_count++;
+
+               /* stack */
+               if (word_count > copy_count) {
+                       error = copyin(ss->sp + ARG_SP_BYTE_OFFSET,
+                                   args, (word_count - copy_count) * sizeof(uint32_t));
+                       if (error)
+                               return error;
+               }
+       }
+       return error;
+}
+
+/*
+ * Define mungers to marshal userspace data into argument structs
+ */
+
+int
+munge_w(const void *regs, void *args)
+{
+       return marshal_no_pad(regs, args, 1);
+}
+
+int 
+munge_ww(const void *regs, void *args)
+{
+       return marshal_no_pad(regs, args, 2);
+}
+
+int 
+munge_www(const void *regs, void *args)
+{
+       return marshal_no_pad(regs, args, 3);
+}
+
+int 
+munge_wwww(const void *regs, void *args)
+{
+       return marshal_no_pad(regs, args, 4);
+}
+
+int 
+munge_wwwww(const void *regs, void *args)
+{
+       return marshal_no_pad(regs, args, 5);
+}
+
+int 
+munge_wwwwww(const void *regs, void *args)
+{
+       return marshal_no_pad(regs, args, 6);
+}
+
+int 
+munge_wwwwwww(const void *regs, void *args)
+{
+       return marshal_no_pad(regs, args, 7);
+}
+
+int 
+munge_wwwwwwww(const void *regs, void *args)
+{
+       return marshal_no_pad(regs, args, 8);
+}
+
+int 
+munge_wwl(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               return marshal_no_pad(regs, args, 3);
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               uu_args[0] = ss->r[1]; // w
+               uu_args[1] = ss->r[2]; // w
+               uu_args[2] = ss->r[4]; // l (longs are aligned to even registers for armv7k, so skip r3)
+               uu_args[3] = ss->r[5]; // 
+               return 0;
+       }
+}
+
+int 
+munge_wwlw(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               return marshal_no_pad(regs, args, 5);
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               int error = munge_wwl(regs, args); // wwl
+               uu_args[4] = ss->r[6]; // w
+               return error;
+       }
+}
+
+int
+munge_wwlww(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               // the long-long here is aligned on an even register
+               // so there shouldn't be any padding
+               return marshal_no_pad(regs, args, 6);
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               int error = munge_wwlw(regs, args); // wwlw
+               uu_args[5] = ss->r[8]; // w
+               return error;
+       }
+}
+
+int 
+munge_wwlll(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               return marshal_no_pad(regs, args, 8);
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               int error = munge_wwl(regs, args);  // wwl
+               if (error)
+                       return error;
+               uu_args[4] = ss->r[6];              // l
+               uu_args[5] = ss->r[8];              //
+               return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // l
+                          &(uu_args[6]), 2 * sizeof(uint32_t));
+       }
+}
+
+int
+munge_wwllww(const void *regs, void *args)
+{
+       return munge_wwlll(regs, args);
+}
+
+int
+munge_wl(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               memcpy(args, regs, 4 * sizeof(uint32_t));
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               uu_args[0] = ss->r[1]; // w
+               uu_args[2] = ss->r[2]; // l
+               uu_args[3] = ss->r[3]; //
+       }
+       return 0;
+}
+
+int
+munge_wlw(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               memcpy(args, regs, 5 * sizeof(uint32_t));       
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               uu_args[0] = ss->r[1]; // w
+               uu_args[2] = ss->r[2]; // l
+               uu_args[3] = ss->r[3]; //
+               uu_args[4] = ss->r[4]; // w
+       }
+       return 0;
+}
+
+int
+munge_wlww(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               memcpy(args, regs, 6 * sizeof(uint32_t));
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               uu_args[0] = ss->r[1]; // w
+               uu_args[2] = ss->r[2]; // l
+               uu_args[3] = ss->r[3]; //
+               uu_args[4] = ss->r[4]; // w
+               uu_args[5] = ss->r[5]; // w
+       }
+       return 0;
+}
+
+int
+munge_wlwwwll(const void *regs, void *args)
+{
+       DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+       if (REGS_TO_STYLE(regs) == kDirect) {
+               memcpy(args, regs, 7 * sizeof(uint32_t)); // wlwww
+               return copyin(ss->sp + ARG_SP_BYTE_OFFSET,       // ll
+                          uu_args + 8, 4 * sizeof(uint32_t));
+       }
+       else {
+               uu_args[0] = ss->r[1];                    // w
+               uu_args[2] = ss->r[2];                    // l
+               uu_args[3] = ss->r[3];                    // 
+               uu_args[4] = ss->r[4];                    // w
+               uu_args[5] = ss->r[5];                    // w
+               uu_args[6] = ss->r[6];                    // w
+               return copyin(ss->sp + ARG_SP_BYTE_OFFSET,       // ll
+                          uu_args + 8, 4 * sizeof(uint32_t));
+       }
+}
+
+int
+munge_wlwwwllw(const void *regs, void *args)
+{
+       DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+       if (REGS_TO_STYLE(regs) == kDirect) {
+               memcpy(args, regs, 7 * sizeof(uint32_t)); // wlwww
+               return copyin(ss->sp + ARG_SP_BYTE_OFFSET,
+                          uu_args + 8, 5 * sizeof(uint32_t)); // ll
+       }
+       else {
+               uu_args[0] = ss->r[1];                    // w
+               uu_args[2] = ss->r[2];                    // l
+               uu_args[3] = ss->r[3];                    // 
+               uu_args[4] = ss->r[4];                    // w
+               uu_args[5] = ss->r[5];                    // w
+               uu_args[6] = ss->r[6];                    // w
+               return copyin(ss->sp + ARG_SP_BYTE_OFFSET,       // llw
+                          uu_args + 8, 5 * sizeof(uint32_t));
+       }
+}
+
+int 
+munge_wlwwlwlw(const void *regs, void *args)
+{
+       DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+       if (REGS_TO_STYLE(regs) == kDirect)
+               uu_args[0] = ss->r[0];      // w
+       else
+               uu_args[0] = ss->r[1];      // w
+
+       uu_args[2] = ss->r[2];              // l
+       uu_args[3] = ss->r[3];              //
+       uu_args[4] = ss->r[4];              // w
+       uu_args[5] = ss->r[5];              // w
+       uu_args[6] = ss->r[6];              // l
+       uu_args[7] = ss->r[8];              //
+       return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // wlw
+                  uu_args + 8, 5 * sizeof(uint32_t));
+}
+
+int 
+munge_wll(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               memcpy(args, regs, 6 * sizeof(uint32_t));       
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               uu_args[0] = ss->r[1]; // w
+               uu_args[2] = ss->r[2]; // l
+               uu_args[3] = ss->r[3]; //
+               uu_args[4] = ss->r[4]; // l
+               uu_args[5] = ss->r[5]; //
+       }
+       return 0;
+}
+
+int 
+munge_wlll(const void *regs, void *args)
+{
+       DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+       int error = munge_wll(regs, args); // wll
+       uu_args[6] = ss->r[6]; // l
+       uu_args[7] = ss->r[8]; //
+       return error;
+}
+
+int 
+munge_wllll(const void *regs, void *args)
+{
+       DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+       munge_wlll(regs, args);             // wlll
+       return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // l
+                  uu_args + 8, 2 * sizeof(uint32_t));
+}
+
+int
+munge_wllww(const void *regs, void *args)
+{
+       return munge_wlll(regs, args);
+}
+
+int 
+munge_wllwwll(const void *regs, void *args)
+{
+       DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+       int error = munge_wlll(regs, args); // wllww
+       if (error)
+               return error;
+       return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // ll
+                  uu_args + 8, 4 * sizeof(uint32_t));
+}
+
+int 
+munge_wwwlw(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               memcpy(args, regs, 7 * sizeof(uint32_t));
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               uu_args[0] = ss->r[1]; // w
+               uu_args[1] = ss->r[2]; // w
+               uu_args[2] = ss->r[3]; // w
+               uu_args[4] = ss->r[4]; // l
+               uu_args[5] = ss->r[5]; //
+               uu_args[6] = ss->r[6]; // w
+       }
+       return 0;
+}
+
+int
+munge_wwwlww(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               return munge_wlll(regs, args);
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               uu_args[0] = ss->r[1]; // w
+               uu_args[1] = ss->r[2]; // w
+               uu_args[2] = ss->r[3]; // w
+               uu_args[4] = ss->r[4]; // l
+               uu_args[5] = ss->r[5]; //
+               uu_args[6] = ss->r[6]; // w
+               uu_args[7] = ss->r[8]; // w
+               return 0;
+       }
+}
+       
+int 
+munge_wwwl(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               return munge_wll(regs, args);
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               uu_args[0] = ss->r[1]; // w
+               uu_args[1] = ss->r[2]; // w
+               uu_args[2] = ss->r[3]; // w
+               uu_args[4] = ss->r[4]; // l
+               uu_args[5] = ss->r[5]; //
+               return 0;
+       }
+}
+
+int 
+munge_wwwwl(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               return marshal_no_pad(regs, args, 6);
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               uu_args[0] = ss->r[1]; // w
+               uu_args[1] = ss->r[2]; // w
+               uu_args[2] = ss->r[3]; // w
+               uu_args[3] = ss->r[4]; // w
+               uu_args[4] = ss->r[6]; // l
+               uu_args[5] = ss->r[8]; //
+               return 0;
+       }
+}
+
+int
+munge_wwwwlw(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               return marshal_no_pad(regs, args, 7);
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               int error = munge_wwwwl(regs, args); // wwwwl
+               if (error)
+                       return error;
+               return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // w
+                          uu_args + 6, sizeof(uint32_t));
+       }
+}
+
+int 
+munge_wwwwwl(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               return munge_wlll(regs, args);
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               uu_args[0] = ss->r[1]; // w
+               uu_args[1] = ss->r[2]; // w
+               uu_args[2] = ss->r[3]; // w
+               uu_args[3] = ss->r[4]; // w
+               uu_args[4] = ss->r[5]; // w
+               uu_args[6] = ss->r[6]; // l
+               uu_args[7] = ss->r[8]; //
+               return 0;
+       }
+}
+
+int 
+munge_wwwwwlww(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               return munge_wllll(regs, args);
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               int error = munge_wwwwwl(regs, args); // wwwwwl
+               if (error)
+                       return error;
+               return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // ww
+                          uu_args + 8, 2 * sizeof(uint32_t));
+       }
+}
+
+int
+munge_wwwwwllw(const void *regs, void *args)
+{
+       DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+       int error = munge_wwwwwl(regs, args); // wwwwwl
+       if (error)
+               return error;
+       return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // lw
+                  uu_args + 8, 3 * sizeof(uint32_t));
+}
+
+int
+munge_wwwwwlll(const void *regs, void *args)
+{
+       DECLARE_AND_CAST(regs, args, ss, uu_args);
+       int error;
+
+       if (REGS_TO_STYLE(regs) == kDirect) {
+               error = munge_wlll(regs, args);     // wlll
+               if (error)
+                       return error;
+               return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // ll
+                          uu_args + 8, 4 * sizeof(uint32_t));
+       }
+       else {
+               error = munge_wwwwwl(regs, args);   // wwwwwl
+               if (error)
+                       return error;
+               return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // ll
+                          uu_args + 8, 4 * sizeof(uint32_t));
+       }
+}
+
+int
+munge_wwwwwwl(const void *regs, void *args)
+{
+       munge_wwlll(regs, args);
+
+       if (REGS_TO_STYLE(regs) == kDirect)
+               return marshal_no_pad(regs, args, 8);
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               memcpy(args, &(ss->r[1]), 6 * sizeof(uint32_t)); // wwwwww
+               return copyin(ss->sp + ARG_SP_BYTE_OFFSET,       // l
+                          &(uu_args[6]), 2 * sizeof(uint32_t));
+       }
+}
+
+int 
+munge_wwwwwwlw(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               return marshal_no_pad(regs, args, 9);
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               memcpy(args, &(ss->r[1]), 6 * sizeof(uint32_t)); // wwwwww
+               return copyin(ss->sp + ARG_SP_BYTE_OFFSET,       // lw
+                          &(uu_args[6]), 3 * sizeof(uint32_t));
+       }
+}
+       
+int 
+munge_wwwwwwll(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               return marshal_no_pad(regs, args, 10);
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               memcpy(args, &(ss->r[1]), 6 * sizeof(uint32_t)); // wwwwww
+               return copyin(ss->sp + ARG_SP_BYTE_OFFSET,       // ll
+                          &(uu_args[6]), 4 * sizeof(uint32_t));
+       }
+}
+
+int 
+munge_wsw(const void *regs, void *args)
+{
+       return munge_wlw(regs, args);
+}
+
+int 
+munge_wws(const void *regs, void *args)
+{
+       return munge_wwl(regs, args);
+}
+
+int
+munge_wwws(const void *regs, void *args)
+{
+       return munge_wwwl(regs, args);
+}
+
+int
+munge_wwwsw(const void *regs, void *args)
+{
+       return munge_wwwlw(regs, args);
+}
+
+int 
+munge_llllll(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               return marshal_no_pad(regs, args, 12);
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               uu_args[0]  = ss->r[2];             // l
+               uu_args[1]  = ss->r[3];             //
+               uu_args[2]  = ss->r[4];             // l
+               uu_args[3]  = ss->r[5];             //
+               uu_args[4]  = ss->r[6];             // l
+               uu_args[5]  = ss->r[8];             //
+               return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // lll
+                          uu_args + 6, 6 * sizeof(uint32_t));
+       }
+}
+
+int 
+munge_ll(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               return marshal_no_pad(regs, args, 4);
+       else
+               memcpy(args, (const uint32_t*)regs + 2, 4 * sizeof(uint32_t));
+       return 0;
+}
+
+int 
+munge_l(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               return marshal_no_pad(regs, args, 2);
+       else
+               memcpy(args, (const uint32_t*)regs + 2, 2 * sizeof(uint32_t));
+       return 0;
+}
+
+int 
+munge_lw(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               return marshal_no_pad(regs, args, 3);
+       else
+               memcpy(args, (const uint32_t*)regs + 2, 3 * sizeof(uint32_t));
+       return 0;
+}
+
+int
+munge_lwww(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               return marshal_no_pad(regs, args, 5);
+       else
+               memcpy(args, (const uint32_t*)regs + 2, 5 * sizeof(uint32_t));
+       return 0;
+}
+
+int 
+munge_lwwwwwww(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               return marshal_no_pad(regs, args, 9);
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               uu_args[0]  = ss->r[2];             // l
+               uu_args[1]  = ss->r[3];             // 
+               uu_args[2]  = ss->r[4];             // w
+               uu_args[3]  = ss->r[5];             // w
+               uu_args[4]  = ss->r[6];             // w
+               uu_args[5]  = ss->r[8];             // w
+               return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // www
+                          uu_args + 6, 3 * sizeof(uint32_t));
+       }
+}
+
+int
+munge_wwlwww(const void *regs, void *args)
+{
+       if (REGS_TO_STYLE(regs) == kDirect)
+               return marshal_no_pad(regs, args, 7);
+       else {
+               DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+               uu_args[0]  = ss->r[1];             // w
+               uu_args[1]  = ss->r[2];             // w
+               uu_args[2]  = ss->r[4];             // l
+               uu_args[3]  = ss->r[5];             //
+               uu_args[4]  = ss->r[6];             // w
+               uu_args[5]  = ss->r[8];             // w
+               return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // w
+                          uu_args + 6, sizeof(uint32_t));
+       }
+               
+}
+
+int
+munge_wlwwwl(const void *regs, void *args)
+{
+       DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+       if (REGS_TO_STYLE(regs) == kDirect) {
+               memcpy(args, regs,  7 * sizeof(uint32_t)); // wlwww
+               return copyin(ss->sp + ARG_SP_BYTE_OFFSET, //  l
+                          uu_args + 8, 2 * sizeof(uint32_t));
+       } else {
+               uu_args[0]  = ss->r[1];             // w
+               uu_args[2]  = ss->r[2];             // l
+               uu_args[3]  = ss->r[3];             //
+               uu_args[4]  = ss->r[4];             // w
+               uu_args[5]  = ss->r[5];             // w
+               uu_args[6]  = ss->r[6];             // w
+               return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // l
+                          uu_args + 8, 2 * sizeof(uint32_t));
+       }
+}
+
+int
+munge_wwlwwwl(const void *regs, void *args)
+{
+        DECLARE_AND_CAST(regs, args, ss, uu_args);
+
+       if (REGS_TO_STYLE(regs) == kDirect) {
+               memcpy(args, regs,  7 * sizeof(uint32_t)); // wwlwww
+               return copyin(ss->sp + ARG_SP_BYTE_OFFSET, //  l
+                          uu_args + 8, 2 * sizeof(uint32_t));
+       } else {
+               uu_args[0]  = ss->r[1];             // w
+               uu_args[1]  = ss->r[2];             // w
+               uu_args[2]  = ss->r[4];             // l
+               uu_args[3]  = ss->r[5];             //
+               uu_args[4]  = ss->r[6];             // w
+               uu_args[5]  = ss->r[8];             // w
+               return copyin(ss->sp + ARG_SP_BYTE_OFFSET, // wl
+                          uu_args + 6, 4 * sizeof(uint32_t));
+       }
+}
+
+#endif // __arm__ && (__BIGGEST_ALIGNMENT__ > 4)