1/*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source.  A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12/*
13 * Copyright 2012, Richard Lowe.
14 */
15
16#include <stdio.h>
17#include <sys/types.h>
18#include <saveargs.h>
19
20#define	DEF_TEST(name)		\
21    extern uint8_t name[];	\
22    extern int name##_end
23
24#define	SIZE_OF(name) ((caddr_t)&name##_end - (caddr_t)&name)
25
26#define	TEST_GOOD(name, argc)					\
27	if (saveargs_has_args(name, SIZE_OF(name), argc, 0) ==	\
28	    SAVEARGS_TRAD_ARGS)					\
29		printf("Pass: %s\n", #name);			\
30	else							\
31		printf("FAIL: %s\n", #name);
32
33#define	TEST_GOOD_STRUCT(name, argc)				\
34	if (saveargs_has_args(name, SIZE_OF(name), argc, 1) ==	\
35	    SAVEARGS_STRUCT_ARGS)				\
36		printf("Pass: %s\n", #name);			\
37	else							\
38		printf("FAIL: %s\n", #name);
39
40/*
41 * GCC deals with structures differently, so TRAD args is actually correct for
42 * this
43 */
44#define	TEST_GOOD_GSTRUCT(name, argc)				\
45	if (saveargs_has_args(name, SIZE_OF(name), argc, 1) ==	\
46	    SAVEARGS_TRAD_ARGS)					\
47		printf("Pass: %s\n", #name);			\
48	else							\
49		printf("FAIL: %s\n", #name);
50
51#define	TEST_BAD(name, argc)					\
52	if (saveargs_has_args(name, SIZE_OF(name), argc, 0) == 	\
53		SAVEARGS_NO_ARGS)				\
54		printf("Pass: %s\n", #name);			\
55	else							\
56		printf("FAIL: %s\n", #name);
57
58#define	TEST_BAD_STRUCT(name, argc)				\
59	if (saveargs_has_args(name, SIZE_OF(name), argc, 1) == 	\
60		SAVEARGS_NO_ARGS)				\
61		printf("Pass: %s\n", #name);			\
62	else							\
63		printf("FAIL: %s\n", #name);
64
65#define	TEST_BAD_GSTRUCT(name, argc)				\
66	if (saveargs_has_args(name, SIZE_OF(name), argc, 1) == 	\
67		SAVEARGS_NO_ARGS)				\
68		printf("Pass: %s\n", #name);			\
69	else							\
70		printf("FAIL: %s\n", #name);
71
72DEF_TEST(gcc_mov_align);
73DEF_TEST(gcc_mov_basic);
74DEF_TEST(gcc_mov_noorder);
75DEF_TEST(gcc_mov_struct_noorder);
76DEF_TEST(gcc_mov_big_struct_ret);
77DEF_TEST(gcc_mov_big_struct_ret_and_spill);
78DEF_TEST(gcc_mov_small_struct_ret);
79DEF_TEST(gcc_mov_small_struct_ret_and_spill);
80DEF_TEST(gcc_mov_stack_spill);
81
82DEF_TEST(gcc_push_align);
83DEF_TEST(gcc_push_basic);
84DEF_TEST(gcc_push_noorder);
85DEF_TEST(gcc_push_struct_noorder);
86DEF_TEST(gcc_push_big_struct_ret);
87DEF_TEST(gcc_push_big_struct_ret_and_spill);
88DEF_TEST(gcc_push_small_struct_ret);
89DEF_TEST(gcc_push_small_struct_ret_and_spill);
90DEF_TEST(gcc_push_stack_spill);
91
92DEF_TEST(ss_mov_align);
93DEF_TEST(ss_mov_basic);
94DEF_TEST(ss_mov_big_struct_ret);
95DEF_TEST(ss_mov_big_struct_ret_and_spill);
96DEF_TEST(ss_mov_small_struct_ret);
97DEF_TEST(ss_mov_small_struct_ret_and_spill);
98DEF_TEST(ss_mov_stack_spill);
99
100DEF_TEST(dtrace_instrumented);
101DEF_TEST(kmem_alloc);
102DEF_TEST(uts_kill);
103DEF_TEST(av1394_ic_bitreverse);
104
105DEF_TEST(small_struct_ret_w_float);
106DEF_TEST(big_struct_ret_w_float);
107
108DEF_TEST(interleaved_argument_saves);
109DEF_TEST(jmp_table);
110
111/*
112 * Functions which should not match
113 *
114 * no_fp			-- valid save-args sequence with no saved FP
115 * big_struct_arg_by_value	-- function with big struct passed by value
116 * small_struct_arg_by_value	-- function with small struct passed by value
117 */
118DEF_TEST(no_fp);
119DEF_TEST(big_struct_arg_by_value);
120DEF_TEST(small_struct_arg_by_value);
121
122int
123main(int argc, char **argv)
124{
125	TEST_GOOD(kmem_alloc, 2);
126	TEST_GOOD(uts_kill, 2);
127	TEST_GOOD(av1394_ic_bitreverse, 1);
128	TEST_GOOD(dtrace_instrumented, 4);
129	TEST_GOOD_GSTRUCT(big_struct_ret_w_float, 1);
130	TEST_BAD(no_fp, 5);
131
132	TEST_GOOD(gcc_mov_align, 5);
133	TEST_GOOD(gcc_push_align, 5);
134	TEST_GOOD(ss_mov_align, 5);
135
136	TEST_GOOD(gcc_mov_basic, 4);
137	TEST_GOOD(gcc_push_basic, 4);
138	TEST_GOOD(ss_mov_basic, 4);
139
140	TEST_GOOD(gcc_mov_noorder, 4);
141	TEST_GOOD(gcc_push_noorder, 4);
142
143	TEST_GOOD_GSTRUCT(gcc_mov_big_struct_ret, 4);
144	TEST_GOOD_GSTRUCT(gcc_push_big_struct_ret, 4);
145	TEST_GOOD_STRUCT(ss_mov_big_struct_ret, 4);
146
147	TEST_GOOD_GSTRUCT(gcc_mov_struct_noorder, 4);
148	TEST_GOOD_GSTRUCT(gcc_push_struct_noorder, 4);
149
150	TEST_GOOD_GSTRUCT(gcc_mov_big_struct_ret_and_spill, 8);
151	TEST_GOOD_GSTRUCT(gcc_push_big_struct_ret_and_spill, 8);
152	TEST_GOOD_STRUCT(ss_mov_big_struct_ret_and_spill, 8);
153
154	TEST_GOOD(gcc_mov_small_struct_ret, 4);
155	TEST_GOOD(gcc_push_small_struct_ret, 4);
156	TEST_GOOD(ss_mov_small_struct_ret, 4);
157
158	TEST_GOOD(gcc_mov_small_struct_ret_and_spill, 8);
159	TEST_GOOD(gcc_push_small_struct_ret_and_spill, 8);
160	TEST_GOOD(ss_mov_small_struct_ret_and_spill, 8);
161
162	TEST_GOOD(gcc_mov_stack_spill, 8);
163	TEST_GOOD(gcc_push_stack_spill, 8);
164	TEST_GOOD(ss_mov_stack_spill, 8);
165
166	TEST_BAD(big_struct_arg_by_value, 2);
167	TEST_BAD(small_struct_arg_by_value, 2);
168
169	TEST_BAD(small_struct_ret_w_float, 1);
170
171	TEST_GOOD(interleaved_argument_saves, 4);
172	TEST_BAD(jmp_table, 1);
173
174	return (0);
175}
176