--- old/usr/src/common/saveargs/saveargs.c	2013-02-22 23:58:01.533527862 -0500
+++ new/usr/src/common/saveargs/saveargs.c	2013-02-22 23:58:01.569238882 -0500
@@ -93,10 +93,7 @@
  *     function prolog already reserves.
  *
  * We loop through the first SAVEARGS_INSN_SEQ_LEN bytes of the function
- * looking for each argument saving instruction we would expect to see.  We
- * loop byte-by-byte, rather than doing anything smart about insn lengths,
- * only deviating from this when we know we have our insn, and can skip the
- * rest of it.
+ * looking for each argument saving instruction we would expect to see.
  *
  * If there are odd number of arguments to a function, additional space is
  * reserved on the stack to maintain 16-byte alignment.  For example,
@@ -108,6 +105,9 @@
 
 #include <sys/sysmacros.h>
 #include <sys/types.h>
+#include <libdisasm.h>
+#include <string.h>
+
 #include <saveargs.h>
 
 /*
@@ -162,8 +162,8 @@
 };
 
 static const uint8_t save_fp_pushes[] = {
-    0x55,	/* pushq %rbp */
-    0xcc	/* int $0x3 */
+	0x55,	/* pushq %rbp */
+	0xcc	/* int $0x3 */
 };
 #define	NUM_FP_PUSHES (sizeof (save_fp_pushes) / sizeof (save_fp_pushes[0]))
 
@@ -173,30 +173,80 @@
 };
 #define	NUM_FP_MOVS (sizeof (save_fp_movs) / sizeof (save_fp_movs[0]))
 
+typedef struct {
+	uint8_t *data;
+	size_t size;
+} text_t;
+
+static int
+do_read(void *data, uint64_t addr, void *buf, size_t len)
+{
+	text_t	*t = data;
+
+	if (addr > t->size)
+		return (-1);
+
+	len = MIN(len, t->size - addr);
+	
+	(void) memcpy(buf, (char *)t->data + addr, len);
+	
+	return (len);
+}
+
+/* ARGSUSED */
+int
+do_lookup(void *data, uint64_t addr, char *buf, size_t buflen, uint64_t *start,
+    size_t *symlen)
+{
+	/* We don't actually need lookup info */
+	return (-1);
+}
+
 static int
-has_saved_fp(uint8_t *ins, int size)
+instr_size(dis_handle_t *dhp, uint8_t *ins, unsigned int i, size_t size)
+{
+	text_t	t;
+
+	t.data = ins;
+	t.size = size;
+
+	dis_set_data(dhp, &t);
+	return (dis_instrlen(dhp, i));
+}
+
+static boolean_t
+has_saved_fp(dis_handle_t *dhp, uint8_t *ins, int size)
 {
-	int i, j;
-	uint32_t n;
-	int found_push = 0;
+	int 		i, j;
+	uint32_t	n;
+	boolean_t	found_push = B_FALSE;
+	int 		sz = 0;
+
+	for (i = 0; i < size; i += sz) {
+		if ((sz = instr_size(dhp, ins, i, size)) == -1)
+			return (B_FALSE);
+
+		if (found_push == B_FALSE) {
+			if (sz != 1)
+				continue;
 
-	for (i = 0; i < size; i++) {
-		if (found_push == 0) {
 			n = INSTR1(ins, i);
 			for (j = 0; j <= NUM_FP_PUSHES; j++)
 				if (save_fp_pushes[j] == n) {
-					found_push = 1;
+					found_push = B_TRUE;
 					break;
 				}
 		} else {
+			if (sz != 3)
+				continue;
 			n = INSTR3(ins, i);
 			for (j = 0; j <= NUM_FP_MOVS; j++)
 				if (save_fp_movs[j] == n)
-					return (1);
+					return (B_TRUE);
 		}
 	}
 
-	return (0);
+	return (B_FALSE);
 }
 
 int
@@ -204,65 +254,120 @@
 {
 	int		i, j;
 	uint32_t	n;
+	uint8_t		found = 0;
+	size_t		sz = 0;
+	dis_handle_t	*dhp = NULL;
+	int		ret = SAVEARGS_NO_ARGS;
 
 	argc = MIN((start_index + argc), INSTR_ARRAY_SIZE);
 
-	if (!has_saved_fp(ins, size))
+	if ((dhp = dis_handle_create(DIS_X86_SIZE64, NULL, do_lookup,
+	    do_read)) == NULL)
 		return (SAVEARGS_NO_ARGS);
 
+	if (!has_saved_fp(dhp, ins, size)) {
+		dis_handle_destroy(dhp);
+		return (SAVEARGS_NO_ARGS);
+	}
+
 	/*
-	 * Compare against Sun Studio implementation
+	 * For each possible style of argument saving, walk the insn stream as
+	 * we've been given it, and set bit N in 'found' if we find the
+	 * instruction saving the Nth argument.
 	 */
-	for (i = 4, j = 0; i <= size - 4; i++) {
-		n = INSTR4(ins, i);
-
-		if (n == save_instr[j]) {
-			i += 3;
-			if (++j >= argc)
-				return (start_index ? SAVEARGS_STRUCT_ARGS :
-				    SAVEARGS_TRAD_ARGS);
-		}
-	}
 
 	/*
-	 * Compare against GCC implementation
+	 * Compare against regular implementation
 	 */
-	for (i = 4, j = argc - 1; i <= size - 4; i++) {
+	found = 0;
+	for (i = 0; i < size; i += sz) {
+		sz = instr_size(dhp, ins, i, size);
+
+		if (sz == -1)
+			break;
+		else if (sz != 4)
+			continue;
+
 		n = INSTR4(ins, i);
 
-		if (n == save_instr[j]) {
-			i += 3;
-			if (--j < start_index)
-				return (SAVEARGS_TRAD_ARGS);
+		for (j = 0; j < argc; j++) {
+			if (n == save_instr[j]) {
+				found |= (1 << j);
+
+				if (found == ((1 << argc) - 1)) {
+					ret = start_index ?
+					    SAVEARGS_STRUCT_ARGS :
+					    SAVEARGS_TRAD_ARGS;
+					goto done;
+				}
+
+				break;
+			}
 		}
 	}
 
 	/*
 	 * Compare against GCC push-based implementation
 	 */
-	for (i = 4, j = start_index; i <= size - 2; i += 1) {
-		n = (i >= (8 - start_index)) ? INSTR2(ins, i) : INSTR1(ins, i);
+	found = 0;
+	for (i = 0; i < size; i += sz) {
+		if ((sz = instr_size(dhp, ins, i, size)) == -1)
+			break;
+
+		for (j = start_index; j < argc; j++) {
+			if (sz == 2) /* Two byte */
+				n = INSTR2(ins, i);
+			else if (sz == 1)
+				n = INSTR1(ins, i);
+			else
+				continue;
+
+			if (n == save_instr_push[j]) {
+				found |= (1 << (j - start_index));
+
+				if (found == ((1 << (argc - start_index)) - 1)) {
+					ret = SAVEARGS_TRAD_ARGS;
+					goto done;
+				}
 
-		if (n == save_instr_push[j]) {
-			if (i >= (8 - start_index))
-				i += 1;
-			if (++j >= argc)
-				return (SAVEARGS_TRAD_ARGS);
+				break;
+			}
 		}
 	}
 
-	/* Look for a GCC-style returned structure */
+	/*
+	 * Look for a GCC-style returned structure.
+	 */
+	found = 0;
 	if (start_index != 0) {
-		for (i = 4, j = argc - 2; i <= size - 4; i++) {
+		for (i = 0; i < size; i += sz) {
+			sz = instr_size(dhp, ins, i, size);
+
+			if (sz == -1)
+				break;
+			else if (sz != 4)
+				continue;
+
 			n = INSTR4(ins, i);
 
-			if (n == save_instr_sr[j]) {
-				i += 3;
-				if (--j >= (argc - 1))
-					return (SAVEARGS_TRAD_ARGS);
+			/* argc is inclusive of start_index, allow for that */
+			for (j = 0; j < (argc - start_index); j++) {
+				if (n == save_instr_sr[j]) {
+					found |= (1 << j);
+
+					if (found ==
+					    ((1 << (argc - start_index)) - 1)) {
+						ret = SAVEARGS_TRAD_ARGS;
+						goto done;
+					}
+
+					break;
+				}
 			}
 		}
 	}
 
-	return (SAVEARGS_NO_ARGS);
+done:
+	dis_handle_destroy(dhp);
+	return (ret);
 }
--- old/usr/src/common/saveargs/tests/README	2013-02-22 23:58:02.955275284 -0500
+++ new/usr/src/common/saveargs/tests/README	2013-02-22 23:58:03.007664367 -0500
@@ -7,3 +7,8 @@
 
    Actually test the full chunk of the (libproc) side of the code, running
    pstack on the range of test apps.
+
+dump:
+
+    Display each function in a given object we believe to have saved
+    arguments.
--- /dev/null	2013-02-22 23:58:05.000000000 -0500
+++ new/usr/src/common/saveargs/tests/dump/Makefile	2013-02-22 23:58:05.205623155 -0500
@@ -0,0 +1,47 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2012, Richard Lowe.
+#
+
+include $(SRC)/Makefile.master
+include $(SRC)/Makefile.master.64
+
+.KEEP_STATE:
+
+OBJECTS = dump.o saveargs.o dis_tables.o
+PROG = dump
+
+CFLAGS += -m64
+CPPFLAGS += -I$(SRC)/common/saveargs
+CERRWARN += -_gcc=-Wno-parentheses
+CERRWARN += -_gcc=-Wno-uninitialized
+
+LDFLAGS += -lctf -lelf
+LDLIBS64 += -ldisasm
+
+C99MODE = $(C99_ENABLE)
+
+%.o: $(SRC)/common/saveargs/%.c
+	$(COMPILE.c) -o $@ $<
+
+$(PROG): $(OBJECTS)
+	$(LINK.c) -o $@ $(OBJECTS) $(LDLIBS64)
+
+clean: 
+	$(RM) $(OBJECTS) $(PROG)
+
+clobber: clean
+
+all: $(PROG)
+
+install: all
--- /dev/null	2013-02-22 23:58:06.000000000 -0500
+++ new/usr/src/common/saveargs/tests/dump/dump.c	2013-02-22 23:58:06.111453622 -0500
@@ -0,0 +1,152 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+#include <err.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <libctf.h>
+#include <saveargs.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+
+extern const char *__progname;
+
+typedef struct symtab_sym {
+	GElf_Sym ss_sym;
+	char *ss_name;
+	ctf_funcinfo_t ss_finfo;
+	uint8_t *ss_data;
+	size_t ss_size;
+} symtab_sym_t;
+
+static void
+walk_symtab(Elf *elf, char *fname, ctf_file_t *fp,
+    void (*callback)(ctf_file_t *, symtab_sym_t *))
+{
+	Elf_Scn *stab = NULL;
+	Elf_Scn *text = NULL;
+	Elf_Data *stabdata = NULL;
+	Elf_Data *textdata = NULL;
+	GElf_Ehdr ehdr;
+	GElf_Shdr stabshdr;
+	GElf_Shdr textshdr;
+	int fd, foundtext = 0, foundstab = 0;
+	symtab_sym_t ss;
+
+	if ((gelf_getehdr(elf, &ehdr)) == NULL)
+		errx(1, "could not read ELF header from %s\n",
+		    fname);
+
+	while ((stab = elf_nextscn(elf, stab)) != NULL) {
+		(void) gelf_getshdr(stab, &stabshdr);
+
+		if (stabshdr.sh_type == SHT_SYMTAB) {
+			foundstab = 1;
+			break;
+		}
+	}
+
+	while ((text = elf_nextscn(elf, text)) != NULL) {
+		(void) gelf_getshdr(text, &textshdr);
+
+		if (strcmp(".text", elf_strptr(elf,
+		    ehdr.e_shstrndx, (size_t)textshdr.sh_name)) == 0) {
+			foundtext = 1;
+			break;
+		}
+	}
+
+	if (!foundstab || !foundtext)
+		goto out;
+
+	stabdata = elf_getdata(stab, NULL);
+	textdata = elf_rawdata(text,  NULL);
+	for (unsigned symdx = 0;
+	    symdx < (stabshdr.sh_size / stabshdr.sh_entsize);
+	    symdx++) {
+		(void) gelf_getsym(stabdata, symdx, &ss.ss_sym);
+
+		if ((GELF_ST_TYPE(ss.ss_sym.st_info) != STT_FUNC) ||
+		    (ss.ss_sym.st_shndx == SHN_UNDEF))
+			continue;
+
+		ss.ss_name = elf_strptr(elf, stabshdr.sh_link,
+		    ss.ss_sym.st_name);
+		ss.ss_data = ((uint8_t *)(textdata->d_buf)) +
+		    (ss.ss_sym.st_value - textshdr.sh_addr);
+
+		if (ctf_func_info(fp, symdx, &ss.ss_finfo) == CTF_ERR) {
+			fprintf(stderr, "failed to get funcinfo for: %s\n",
+			    ss.ss_name);
+			continue;
+		}
+
+		(void) callback(fp, &ss);
+	}
+
+out:
+	(void) elf_end(elf);
+	(void) close(fd);
+}
+
+void
+check_sym(ctf_file_t *ctfp, symtab_sym_t *ss)
+{
+	int rettype = ctf_type_kind(ctfp, ss->ss_finfo.ctc_return);
+	int start_index = 0;
+
+	if (ss->ss_finfo.ctc_argc == 0) /* No arguments, no point */
+		return;
+
+	if (((rettype == CTF_K_STRUCT) || (rettype == CTF_K_UNION)) &&
+	    ctf_type_size(ctfp, ss->ss_finfo.ctc_return) > 16)
+		start_index = 1;
+
+	if (saveargs_has_args(ss->ss_data, ss->ss_sym.st_size,
+	    ss->ss_finfo.ctc_argc, start_index) != SAVEARGS_NO_ARGS)
+		printf("%s has %d saved args\n", ss->ss_name,
+		    ss->ss_finfo.ctc_argc);
+}
+
+int
+main(int argc, char **argv)
+{
+	Elf		*elf;
+	ctf_file_t	*ctfp;
+	int errp, fd;
+
+	if (ctf_version(CTF_VERSION) == -1)
+		errx(1, "mismatched libctf versions\n");
+
+	if (elf_version(EV_CURRENT) == EV_NONE)
+		errx(1, "mismatched libelf versions\n");
+
+	if (argc != 2)
+		errx(2, "usage: %s <file>\n", __progname);
+
+	if ((ctfp = ctf_open(argv[1], &errp)) == NULL)
+		errx(1, "failed to ctf_open file: %s: %s\n", argv[1],
+		    ctf_errmsg(errp));
+
+	if ((fd = open(argv[1], O_RDONLY)) == -1)
+		errx(1, "could not open %s\n", argv[1]);
+
+	if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
+		errx(1, "could not interpret ELF from %s\n",
+		    argv[1]);
+
+	walk_symtab(elf, argv[1], ctfp, check_sym);
+
+	return (0);
+}
--- old/usr/src/common/saveargs/tests/testmatch/Makefile	2013-02-22 23:58:06.279277959 -0500
+++ new/usr/src/common/saveargs/tests/testmatch/Makefile	2013-02-22 23:58:06.577077352 -0500
@@ -1,3 +1,4 @@
+
 #
 # This file and its contents are supplied under the terms of the
 # Common Development and Distribution License ("CDDL"), version 1.0.
@@ -21,15 +22,19 @@
 OBJECTS = testmatch.o saveargs.o data.o
 PROG = testmatch
 
+LDLIBS64 += -ldisasm
+
 CPPFLAGS += -I$(SRC)/common/saveargs
 ASFLAGS += -P
 AS_CPPFLAGS += -D_ASM
+CERRWARN += -_gcc=-Wno-parentheses
+CERRWARN += -_gcc=-Wno-uninitialized
 
 %.o: $(SRC)/common/saveargs/%.c
 	$(COMPILE.c) -o $@ $<
 
 $(PROG): $(OBJECTS)
-	$(LINK.c) -o $@ $(OBJECTS) -lc
+	$(LINK.c) -o $@ $(OBJECTS) $(LDLIBS64)
 
 clean:
 	$(RM) $(OBJECTS) $(PROG)
--- old/usr/src/common/saveargs/tests/testmatch/data.s	2013-02-22 23:58:07.033953029 -0500
+++ new/usr/src/common/saveargs/tests/testmatch/data.s	2013-02-22 23:58:07.068750782 -0500
@@ -64,6 +64,17 @@
 subq    $0x50,%rsp
 SET_SIZE(gcc_mov_basic, gcc_mov_basic_end)
 
+FUNC(gcc_mov_noorder)
+pushq	%rbp
+movq	%rsp, %rbp
+movq    %rcx,-0x20(%rbp)
+movq	%rbx,-0x28(%rbp)
+movq    %rdi,-0x8(%rbp)
+movq    %rdx,-0x18(%rbp)
+movq    %rsi,-0x10(%rbp)
+subq    $0x50,%rsp
+SET_SIZE(gcc_mov_noorder, gcc_mov_noorder_end)
+        
 FUNC(gcc_mov_big_struct_ret)
 pushq   %rbp
 movq    %rsp,%rbp
@@ -75,6 +86,17 @@
 subq    $0x50,%rsp
 SET_SIZE(gcc_mov_big_struct_ret, gcc_mov_big_struct_ret_end)
 
+FUNC(gcc_mov_struct_noorder)
+pushq   %rbp
+movq    %rsp,%rbp
+movq    %rcx,-0x18(%rbp)
+movq    %r8,-0x20(%rbp)
+movq    %rsi,-0x8(%rbp)
+movq    %rdx,-0x10(%rbp)
+movq    %rbx,-0x28(%rbp)
+subq    $0x50,%rsp
+SET_SIZE(gcc_mov_struct_noorder, gcc_mov_struct_noorder_end)
+
 FUNC(gcc_mov_big_struct_ret_and_spill)
 pushq   %rbp
 movq    %rsp,%rbp
@@ -146,6 +168,16 @@
 subq    $0x20,%rsp
 SET_SIZE(gcc_push_basic, gcc_push_basic_end)
 
+FUNC(gcc_push_noorder)
+pushq   %rbp
+movq    %rsp,%rbp
+pushq   %rsi
+pushq   %rdi
+pushq   %rcx
+pushq   %rdx
+subq    $0x20,%rsp
+SET_SIZE(gcc_push_noorder, gcc_push_noorder_end)
+
 FUNC(gcc_push_big_struct_ret)
 pushq   %rbp
 movq    %rsp,%rbp
@@ -156,6 +188,16 @@
 subq    $0x30,%rsp
 SET_SIZE(gcc_push_big_struct_ret, gcc_push_big_struct_ret_end)
 
+FUNC(gcc_push_struct_noorder)
+pushq   %rbp
+movq    %rsp,%rbp
+pushq   %rdx
+pushq   %rsi
+pushq   %r8
+pushq   %rcx
+subq    $0x30,%rsp
+SET_SIZE(gcc_push_struct_noorder, gcc_push_struct_noorder_end)
+        
 FUNC(gcc_push_big_struct_ret_and_spill)
 pushq   %rbp
 movq    %rsp,%rbp
@@ -394,3 +436,19 @@
 movq    %rdi,-0x8(%rbp)
 subq    $0x50,%rsp
 SET_SIZE(small_struct_arg_by_value, small_struct_arg_by_value_end)
+
+FUNC(interleaved_argument_saves)
+pushq	%rbp
+movq	%rdi,%rax
+shlq	$0x21,%rax
+movq	%rsp,%rbp
+shrq	$0x29,%rax
+subq	$0x30,%rsp
+movq	%rdi,-0x8(%rbp)
+movq	%rbx,-0x28(%rbp)
+movzbl	%dil,%edi
+movq	%rcx,-0x20(%rbp)
+movq	%rdx,-0x18(%rbp)
+movq	%rsi,-0x10(%rbp)
+movq	0x0(,%rax,8),%rax
+SET_SIZE(interleaved_argument_saves, interleaved_argument_saves_end)
--- old/usr/src/common/saveargs/tests/testmatch/testmatch.c	2013-02-22 23:58:09.120524898 -0500
+++ new/usr/src/common/saveargs/tests/testmatch/testmatch.c	2013-02-22 23:58:09.224111948 -0500
@@ -24,31 +24,55 @@
 #define	SIZE_OF(name) ((caddr_t)&name##_end - (caddr_t)&name)
 
 #define	TEST_GOOD(name, argc)					\
-    if (saveargs_has_args(name, SIZE_OF(name), argc, 0) != 0)	\
-	printf("Pass: %s\n", #name);				\
-    else							\
-	printf("FAIL: %s\n", #name);
+	if (saveargs_has_args(name, SIZE_OF(name), argc, 0) ==	\
+	    SAVEARGS_TRAD_ARGS)					\
+		printf("Pass: %s\n", #name);			\
+	else							\
+		printf("FAIL: %s\n", #name);
 
 #define	TEST_GOOD_STRUCT(name, argc)				\
-    if (saveargs_has_args(name, SIZE_OF(name), argc, 1) != 0)	\
-	printf("Pass: %s\n", #name);				\
-    else							\
-	printf("FAIL: %s\n", #name);
+	if (saveargs_has_args(name, SIZE_OF(name), argc, 1) ==	\
+	    SAVEARGS_STRUCT_ARGS)				\
+		printf("Pass: %s\n", #name);			\
+	else							\
+		printf("FAIL: %s\n", #name);
+
+/*
+ * GCC deals with structures differently, so TRAD args is actually correct for
+ * this
+ */
+#define	TEST_GOOD_GSTRUCT(name, argc)				\
+	if (saveargs_has_args(name, SIZE_OF(name), argc, 1) ==	\
+	    SAVEARGS_TRAD_ARGS)					\
+		printf("Pass: %s\n", #name);			\
+	else							\
+		printf("FAIL: %s\n", #name);
 
 #define	TEST_BAD(name, argc)					\
-    if (saveargs_has_args(name, SIZE_OF(name), argc, 0) == 0)	\
-	printf("Pass: %s\n", #name);				\
-    else							\
-	printf("FAIL: %s\n", #name);
+	if (saveargs_has_args(name, SIZE_OF(name), argc, 0) == 	\
+		SAVEARGS_NO_ARGS)				\
+		printf("Pass: %s\n", #name);			\
+	else							\
+		printf("FAIL: %s\n", #name);
 
 #define	TEST_BAD_STRUCT(name, argc)				\
-    if (saveargs_has_args(name, SIZE_OF(name), argc, 1) == 0)	\
-	printf("Pass: %s\n", #name);				\
-    else							\
-	printf("FAIL: %s\n", #name);
+	if (saveargs_has_args(name, SIZE_OF(name), argc, 1) == 	\
+		SAVEARGS_NO_ARGS)				\
+		printf("Pass: %s\n", #name);			\
+	else							\
+		printf("FAIL: %s\n", #name);
+
+#define	TEST_BAD_GSTRUCT(name, argc)				\
+	if (saveargs_has_args(name, SIZE_OF(name), argc, 1) == 	\
+		SAVEARGS_NO_ARGS)				\
+		printf("Pass: %s\n", #name);			\
+	else							\
+		printf("FAIL: %s\n", #name);
 
 DEF_TEST(gcc_mov_align);
 DEF_TEST(gcc_mov_basic);
+DEF_TEST(gcc_mov_noorder);
+DEF_TEST(gcc_mov_struct_noorder);
 DEF_TEST(gcc_mov_big_struct_ret);
 DEF_TEST(gcc_mov_big_struct_ret_and_spill);
 DEF_TEST(gcc_mov_small_struct_ret);
@@ -57,6 +81,8 @@
 
 DEF_TEST(gcc_push_align);
 DEF_TEST(gcc_push_basic);
+DEF_TEST(gcc_push_noorder);
+DEF_TEST(gcc_push_struct_noorder);
 DEF_TEST(gcc_push_big_struct_ret);
 DEF_TEST(gcc_push_big_struct_ret_and_spill);
 DEF_TEST(gcc_push_small_struct_ret);
@@ -79,6 +105,8 @@
 DEF_TEST(small_struct_ret_w_float);
 DEF_TEST(big_struct_ret_w_float);
 
+DEF_TEST(interleaved_argument_saves);
+
 /*
  * Functions which should not match
  *
@@ -97,7 +125,7 @@
 	TEST_GOOD(uts_kill, 2);
 	TEST_GOOD(av1394_ic_bitreverse, 1);
 	TEST_GOOD(dtrace_instrumented, 4);
-	TEST_GOOD_STRUCT(big_struct_ret_w_float, 1);
+	TEST_GOOD_GSTRUCT(big_struct_ret_w_float, 1);
 	TEST_BAD(no_fp, 5);
 
 	TEST_GOOD(gcc_mov_align, 5);
@@ -108,12 +136,18 @@
 	TEST_GOOD(gcc_push_basic, 4);
 	TEST_GOOD(ss_mov_basic, 4);
 
-	TEST_GOOD_STRUCT(gcc_mov_big_struct_ret, 4);
-	TEST_GOOD_STRUCT(gcc_push_big_struct_ret, 4);
+	TEST_GOOD(gcc_mov_noorder, 4);
+	TEST_GOOD(gcc_push_noorder, 4);
+
+	TEST_GOOD_GSTRUCT(gcc_mov_big_struct_ret, 4);
+	TEST_GOOD_GSTRUCT(gcc_push_big_struct_ret, 4);
 	TEST_GOOD_STRUCT(ss_mov_big_struct_ret, 4);
 
-	TEST_GOOD_STRUCT(gcc_mov_big_struct_ret_and_spill, 8);
-	TEST_GOOD_STRUCT(gcc_push_big_struct_ret_and_spill, 8);
+	TEST_GOOD_GSTRUCT(gcc_mov_struct_noorder, 4);
+	TEST_GOOD_GSTRUCT(gcc_push_struct_noorder, 4);
+
+	TEST_GOOD_GSTRUCT(gcc_mov_big_struct_ret_and_spill, 8);
+	TEST_GOOD_GSTRUCT(gcc_push_big_struct_ret_and_spill, 8);
 	TEST_GOOD_STRUCT(ss_mov_big_struct_ret_and_spill, 8);
 
 	TEST_GOOD(gcc_mov_small_struct_ret, 4);
@@ -133,5 +167,7 @@
 
 	TEST_BAD(small_struct_ret_w_float, 1);
 
+	TEST_GOOD(interleaved_argument_saves, 4);
+
 	return (0);
 }
--- old/usr/src/lib/libdisasm/common/libdisasm.h	2013-02-22 23:58:10.304253586 -0500
+++ new/usr/src/lib/libdisasm/common/libdisasm.h	2013-02-22 23:58:10.338497730 -0500
@@ -27,8 +27,6 @@
 #ifndef	_LIBDISASM_H
 #define	_LIBDISASM_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/types.h>
 
 #ifdef	__cplusplus
@@ -67,6 +65,7 @@
 extern void dis_flags_set(dis_handle_t *, int f);
 extern void dis_flags_clear(dis_handle_t *, int f);
 extern int dis_max_instrlen(dis_handle_t *);
+extern int dis_instrlen(dis_handle_t *, uint64_t);
 
 /* libdisasm errors */
 #define	E_DIS_NOMEM		1	/* Out of memory */
--- old/usr/src/lib/libdisasm/common/mapfile-vers	2013-02-22 23:58:10.773175183 -0500
+++ new/usr/src/lib/libdisasm/common/mapfile-vers	2013-02-22 23:58:10.783977936 -0500
@@ -44,6 +44,7 @@
 	dis_errno;
 	dis_handle_create;
 	dis_handle_destroy;
+        dis_instrlen;
 	dis_max_instrlen;
 	dis_previnstr;
 	dis_set_data;
--- old/usr/src/lib/libdisasm/i386/dis_i386.c	2013-02-22 23:58:11.136657121 -0500
+++ new/usr/src/lib/libdisasm/i386/dis_i386.c	2013-02-22 23:58:11.156674536 -0500
@@ -24,8 +24,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <libdisasm.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -245,3 +243,12 @@
 	dis_free(hist, sizeof (uint64_t) * n);
 	return (res);
 }
+
+int
+dis_instrlen(dis_handle_t *dhp, uint64_t pc)
+{
+	if (dis_disassemble(dhp, pc, NULL, 0) != 0)
+		return (-1);
+
+	return (dhp->dh_addr - pc);
+}
--- old/usr/src/lib/libdisasm/sparc/dis_sparc.c	2013-02-22 23:58:11.614708717 -0500
+++ new/usr/src/lib/libdisasm/sparc/dis_sparc.c	2013-02-22 23:58:11.629451536 -0500
@@ -29,9 +29,6 @@
  * Use is subject to license terms.
  */
 
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * The sparc disassembler is mostly straightforward, each instruction is
  * represented by an inst_t structure.  The inst_t definitions are organized
@@ -230,6 +227,12 @@
 }
 
 int
+dis_instrlen(dis_handle_t *dhp, uint64_t pc)
+{
+	return (4);
+}
+
+int
 dis_disassemble(dis_handle_t *dhp, uint64_t addr, char *buf, size_t buflen)
 {
 	const table_t *tp = &initial_table;
--- old/usr/src/lib/libproc/Makefile.com	2013-02-22 23:58:12.009419600 -0500
+++ new/usr/src/lib/libproc/Makefile.com	2013-02-22 23:58:12.021982477 -0500
@@ -74,13 +74,6 @@
 ISAOBJS =	\
 	Pisadep.o
 
-amd64_SAVEOBJS = \
-	saveargs.o
-
-amd64_CPPFLAGS = -I$(SRC)/common/saveargs
-
-SAVEOBJS = $($(MACH64)_SAVEOBJS)
-
 OBJECTS = $(CMNOBJS) $(ISAOBJS) $(SAVEOBJS)
 
 # include library definitions
--- old/usr/src/lib/libproc/amd64/Makefile	2013-02-22 23:58:12.429228396 -0500
+++ new/usr/src/lib/libproc/amd64/Makefile	2013-02-22 23:58:12.441718739 -0500
@@ -22,15 +22,19 @@
 # Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 
 # This is a 64-bit build, and as such needs 64-bit ELF support
 CMNOBJS64 =	Psymtab_machelf64.o
+SAVEOBJS =	saveargs.o
 
 include ../Makefile.com
 include ../../Makefile.lib.64
 
-CPPFLAGS += -D_SYSCALL32
+CPPFLAGS += -D_SYSCALL32 -I$(SRC)/common/saveargs
+LDLIBS += -ldisasm
 
 install: all $(ROOTLIBS64) $(ROOTLINKS64)
+
+objs/%.o pics/%.o: $(SRC)/common/saveargs/%.c
+	$(COMPILE.c) -o $@ $<
+	$(POST_PROCESS_O)
