1#define szof_c			1
2#define szof_uc			szof_c
3#define szof_s			2
4#define szof_us			szof_s
5#define szof_i			4
6#if __WORDSIZE == 64
7#  define szof_ui		szof_i
8#  define szof_l		8
9#endif
10#define szof_f			4
11#define szof_d			8
12
13#define FILL(T)							\
14	name fill##T						\
15fill##T:							\
16	prolog							\
17	arg $argp						\
18	getarg %v0 $argp					\
19	arg $argi						\
20	getarg %r0 $argi					\
21	muli %r0 %r0 szof##T					\
22	addr %v1 %v0 %r0					\
23	movi %r0 0						\
24fill##T##loop:							\
25	bger fill##T##done %v0 %v1				\
26	str##T %v0 %r0						\
27	addi %r0 %r0 1						\
28	addi %v0 %v0 szof##T					\
29	jmpi fill##T##loop					\
30fill##T##done:							\
31	ret							\
32	epilog
33#define FILLF(T)						\
34	name fill##T						\
35fill##T:							\
36	prolog							\
37	arg $argp						\
38	getarg %v0 $argp					\
39	arg $argi						\
40	getarg %r0 $argi					\
41	muli %r0 %r0 szof##T					\
42	addr %v1 %v0 %r0					\
43	movi##T %f0 0.0						\
44fill##T##loop:							\
45	bger fill##T##done %v0 %v1				\
46	str##T %v0 %f0						\
47	addi##T %f0 %f0 1.0					\
48	addi %v0 %v0 szof##T					\
49	jmpi fill##T##loop					\
50fill##T##done:							\
51	ret							\
52	epilog
53
54#define fill_uc		fill_c
55#define fill_us		fill_s
56#define fill_ui		fill_i
57
58#define ARG(  T, N)			arg    $arg##T##N
59#define ARGF( T, N)			arg##T $arg##T##N
60#define ARG1( K, T)			ARG##K(T, 0)
61#define ARG2( K, T)	ARG1( K, T)	ARG##K(T, 1)
62#define ARG3( K, T)	ARG2( K, T)	ARG##K(T, 2)
63#define ARG4( K, T)	ARG3( K, T)	ARG##K(T, 3)
64#define ARG5( K, T)	ARG4( K, T)	ARG##K(T, 4)
65#define ARG6( K, T)	ARG5( K, T)	ARG##K(T, 5)
66#define ARG7( K, T)	ARG6( K, T)	ARG##K(T, 6)
67#define ARG8( K, T)	ARG7( K, T)	ARG##K(T, 7)
68#define ARG9( K, T)	ARG8( K, T)	ARG##K(T, 8)
69#define ARG10(K, T)	ARG9( K, T)	ARG##K(T, 9)
70#define ARG11(K, T)	ARG10(K, T)	ARG##K(T, 10)
71#define ARG12(K, T)	ARG11(K, T)	ARG##K(T, 11)
72#define ARG13(K, T)	ARG12(K, T)	ARG##K(T, 12)
73#define ARG14(K, T)	ARG13(K, T)	ARG##K(T, 13)
74#define ARG15(K, T)	ARG14(K, T)	ARG##K(T, 14)
75#define ARG16(K, T)	ARG15(K, T)	ARG##K(T, 15)
76#define ARG_c(N)			ARG##N( , _c)
77#define ARG_uc(N)			ARG##N( , _uc)
78#define ARG_s(N)			ARG##N( , _s)
79#define ARG_us(N)			ARG##N( , _us)
80#define ARG_i(N)			ARG##N( , _i)
81#define ARG_ui(N)			ARG##N( , _ui)
82#define ARG_l(N)			ARG##N( , _l)
83#define ARG_f(N)			ARG##N(F, _f)
84#define ARG_d(N)			ARG##N(F, _d)
85
86#define CHK(N, T, V)						\
87	getarg %r0 $arg##T##V					\
88	ldxi##T %r1 %v0 $(V * szof##T)				\
89	beqr N##T##V %r0 %r1					\
90	calli @abort						\
91N##T##V:
92#define CHKF(N, T, V)						\
93	getarg##T %f0 $arg##T##V				\
94	ldxi##T %f1 %v0 $(V * szof##T)				\
95	beqr##T N##T##V %f0 %f1					\
96	calli @abort						\
97N##T##V:
98
99#define GET1( K, N, T, V)				CHK##K(N, T, 0)
100#define GET2( K, N, T, V)	GET1( K, N, T, V)	CHK##K(N, T, 1)
101#define GET3( K, N, T, V)	GET2( K, N, T, V)	CHK##K(N, T, 2)
102#define GET4( K, N, T, V)	GET3( K, N, T, V)	CHK##K(N, T, 3)
103#define GET5( K, N, T, V)	GET4( K, N, T, V)	CHK##K(N, T, 4)
104#define GET6( K, N, T, V)	GET5( K, N, T, V)	CHK##K(N, T, 5)
105#define GET7( K, N, T, V)	GET6( K, N, T, V)	CHK##K(N, T, 6)
106#define GET8( K, N, T, V)	GET7( K, N, T, V)	CHK##K(N, T, 7)
107#define GET9( K, N, T, V)	GET8( K, N, T, V)	CHK##K(N, T, 8)
108#define GET10(K, N, T, V)	GET9( K, N, T, V)	CHK##K(N, T, 9)
109#define GET11(K, N, T, V)	GET10(K, N, T, V)	CHK##K(N, T, 10)
110#define GET12(K, N, T, V)	GET11(K, N, T, V)	CHK##K(N, T, 11)
111#define GET13(K, N, T, V)	GET12(K, N, T, V)	CHK##K(N, T, 12)
112#define GET14(K, N, T, V)	GET13(K, N, T, V)	CHK##K(N, T, 13)
113#define GET15(K, N, T, V)	GET14(K, N, T, V)	CHK##K(N, T, 14)
114#define GET16(K, N, T, V)	GET15(K, N, T, V)	CHK##K(N, T, 15)
115
116#define GET_c(N, M)		GET##N( , c##N,  _c,  M)
117#define GET_uc(N, M)		GET##N( , uc##N, _uc, M)
118#define GET_s(N, M)		GET##N( , s##N,  _s,  M)
119#define GET_us(N, M)		GET##N( , us##N, _us, M)
120#define GET_i(N, M)		GET##N( , i##N,  _i,  M)
121#define GET_ui(N, M)		GET##N( , ui##N, _ui, M)
122#define GET_l(N, M)		GET##N( , l##N,  _l,  M)
123#define GET_f(N, M)		GET##N(F, f##N,  _f,  M)
124#define GET_d(N, M)		GET##N(F, d##N,  _d,  M)
125
126#define PUSH(  T, V)		pushargi    V
127#define PUSHF( T, V)		pushargi##T V
128#define PUSH0( K, T)		/**/
129#define PUSH1( K, T)					PUSH##K(T, 0)
130#define PUSH2( K, T)		PUSH1( K, T)		PUSH##K(T, 1)
131#define PUSH3( K, T)		PUSH2( K, T)		PUSH##K(T, 2)
132#define PUSH4( K, T)		PUSH3( K, T)		PUSH##K(T, 3)
133#define PUSH5( K, T)		PUSH4( K, T)		PUSH##K(T, 4)
134#define PUSH6( K, T)		PUSH5( K, T)		PUSH##K(T, 5)
135#define PUSH7( K, T)		PUSH6( K, T)		PUSH##K(T, 6)
136#define PUSH8( K, T)		PUSH7( K, T)		PUSH##K(T, 7)
137#define PUSH9( K, T)		PUSH8( K, T)		PUSH##K(T, 8)
138#define PUSH10(K, T)		PUSH9( K, T)		PUSH##K(T, 9)
139#define PUSH11(K, T)		PUSH10(K, T)		PUSH##K(T, 10)
140#define PUSH12(K, T)		PUSH11(K, T)		PUSH##K(T, 11)
141#define PUSH13(K, T)		PUSH12(K, T)		PUSH##K(T, 12)
142#define PUSH14(K, T)		PUSH13(K, T)		PUSH##K(T, 13)
143#define PUSH15(K, T)		PUSH14(K, T)		PUSH##K(T, 14)
144#define PUSH16(K, T)		PUSH15(K, T)		PUSH##K(T, 15)
145
146#define PUSH_c( N)		PUSH##N( , _c)
147#define PUSH_uc(N)		PUSH##N( , _uc)
148#define PUSH_s( N)		PUSH##N( , _s)
149#define PUSH_us(N)		PUSH##N( , _us)
150#define PUSH_i( N)		PUSH##N( , _i)
151#define PUSH_ui(N)		PUSH##N( , _ui)
152#define PUSH_l( N)		PUSH##N( , _l)
153#define PUSH_f( N)		PUSH##N(F, _f)
154#define PUSH_d( N)		PUSH##N(F, _d)
155
156/* bottom function */
157#define DEF0(T)							\
158	name test##T##_0					\
159test##T##_0:							\
160	prolog							\
161	ret							\
162	epilog
163
164#define DEFN(N, M, T)						\
165	name test##T##_##N					\
166test##T##_##N:							\
167	prolog							\
168	arg $argp						\
169	/* stack buffer in %v0 */				\
170	getarg %v0 $argp					\
171	ARG##T(N)						\
172	/* validate arguments */				\
173	GET##T(N, M)						\
174	/* heap buffer in %v1 */				\
175	prepare							\
176		pushargi $(N * szof##T)				\
177	finishi @malloc						\
178	retval %v1						\
179	/* copy stack bufer to heap buffer */			\
180	prepare							\
181		pushargr %v1					\
182		pushargr %v0					\
183		pushargi $(N * szof##T)				\
184	finishi MEMCPY						\
185	/* stack buffer for next function in %v2 */		\
186	movi %r0 $(M * szof##T)					\
187	allocar %v2 %r0						\
188	addr %v2 %v2 %fp					\
189	/* fill stack buffer for next function */		\
190	prepare							\
191		pushargr %v2					\
192		pushargi M					\
193	finishi fill##T						\
194	/* call next function */				\
195	prepare							\
196		pushargr %v2					\
197		PUSH##T(M)					\
198	finishi test##T##_##M					\
199	/* validate stack buffer */				\
200	prepare							\
201		pushargr %v1					\
202		pushargr %v0					\
203		pushargi $(N * szof##T)				\
204	finishi @memcmp						\
205	retval %r0						\
206	beqi test##T##_##N##_done %r0 0				\
207	calli @abort						\
208test##T##_##N##_done:						\
209	/* release heap bufer */				\
210	prepare							\
211		pushargr %v1					\
212	finishi @free						\
213	ret							\
214	epilog
215
216/* top function */
217#define DEFX(T)							\
218	name test##T##_17					\
219test##T##_17:							\
220	prolog							\
221	/* heap buffer in %v1 */				\
222	prepare							\
223		pushargi $(16 * szof##T)			\
224	finishi @malloc						\
225	retval %v1						\
226	/* stack buffer for next function in %v2 */		\
227	movi %r0 $(16 * szof##T)				\
228	allocar %v2 %r0						\
229	addr %v2 %v2 %fp					\
230	/* fill stack buffer for next function */		\
231	prepare							\
232		pushargr %v2					\
233		pushargi 16					\
234	finishi fill##T						\
235	/* copy stack buffer to heap buffer */			\
236	prepare							\
237		pushargr %v1					\
238		pushargr %v2					\
239		pushargi $(16 * szof##T)			\
240	finishi MEMCPY						\
241	/* call next function */				\
242	prepare							\
243		pushargr %v2					\
244		PUSH##T(16)					\
245	finishi test##T##_16					\
246	/* validate stack buffer */				\
247	prepare							\
248		pushargr %v1					\
249		pushargr %v2					\
250		pushargi $(16 * szof##T)			\
251	finishi @memcmp						\
252	retval %r0						\
253	beqi test##T##_17_done %r0 0				\
254	calli @abort						\
255test##T##_17_done:						\
256	/* release heap bufer */				\
257	prepare							\
258		pushargr %v1					\
259	finishi @free						\
260	ret							\
261	epilog
262
263#define DEF(  T)						\
264	DEF0( T)						\
265	DEFN( 1,  0, T)						\
266	DEFN( 2,  1, T)						\
267	DEFN( 3,  2, T)						\
268	DEFN( 4,  3, T)						\
269	DEFN( 5,  4, T)						\
270	DEFN( 6,  5, T)						\
271	DEFN( 7,  6, T)						\
272	DEFN( 8,  7, T)						\
273	DEFN( 9,  8, T)						\
274	DEFN(10,  9, T)						\
275	DEFN(11, 10, T)						\
276	DEFN(12, 11, T)						\
277	DEFN(13, 12, T)						\
278	DEFN(14, 13, T)						\
279	DEFN(15, 14, T)						\
280	DEFN(16, 15, T)						\
281	DEFX(T)
282
283#define CALL(T)			calli test##T##_17
284
285.data	16
286fmt:
287.c	"%d %d %d\n"
288.code
289	jmpi main
290
291#if _AIX
292#  define MEMCPY		memcpy
293/* error: Function not implemented (memcpy) */
294	name memcpy
295memcpy:
296	prolog
297	arg $dst
298	arg $src
299	arg $len
300	getarg %r0 $dst
301	getarg %r1 $src
302	getarg %r2 $len
303	movr %v1 %r0
304	blti memcpy_done %r2 1
305memcpy_loop:
306	subi %r2 %r2 1
307	ldxr_c %v0 %r1 %r2
308	stxr_c %r2 %r0 %v0
309	bgti memcpy_loop %r2 0
310memcpy_done:
311	retr %v1
312	epilog
313#else
314#  define MEMCPY		@memcpy
315#endif
316
317	FILL(_c)
318	FILL(_s)
319	FILL(_i)
320#if __WORDSIZE == 64
321	FILL(_l)
322#endif
323	FILLF(_f)
324	FILLF(_d)
325
326	DEF(_c)
327	DEF(_uc)
328	DEF(_s)
329	DEF(_us)
330	DEF(_i)
331#if __WORDSIZE == 64
332	DEF(_ui)
333	DEF(_l)
334#endif
335	DEF(_f)
336	DEF(_d)
337
338	name main
339main:
340	prolog
341
342	CALL(_c)
343	CALL(_uc)
344	CALL(_s)
345	CALL(_us)
346	CALL(_i)
347#if __WORDSIZE == 64
348	CALL(_ui)
349	CALL(_l)
350#endif
351	CALL(_f)
352	CALL(_d)
353
354	// loop control
355	movi %v2 1
356
357	// loop a few times calling allocar
358loop:
359	// allocate 12 bytes
360	movi %r0 12
361	allocar %v0 %r0
362
363	// offset
364	movr %v1 %v0
365
366	// 1
367	stxr_i %v1 %fp %v2
368
369	// 2
370	addi %v2 %v2 1
371	addi %v1 %v1 4
372	stxr_i %v1 %fp %v2
373
374	// 3
375	addi %v2 %v2 1
376	addi %v1 %v1 4
377	stxr_i %v1 %fp %v2
378
379	// reload
380	movr %v1 %v0
381
382	// 1
383	ldxr_i %r0 %fp %v1
384
385	// 2
386	addi %v1 %v1 4
387	ldxr_i %r1 %fp %v1
388
389	// 3
390	addi %v1 %v1 4
391	ldxr_i %r2 %fp %v1
392
393	prepare
394		pushargi fmt
395		ellipsis
396		pushargr %r0
397		pushargr %r1
398		pushargr %r2
399	finishi @printf
400	blti loop %v2 9
401
402	ret
403	epilog
404