1# gr28-gr31, fr31, icc3, fcc3 are used as tmps.
2# consider them call clobbered by these macros.
3
4	.macro start
5	.data
6failmsg:
7	.ascii "fail\n"
8passmsg:
9	.ascii "pass\n"
10	.text
11	.global _start
12_start:
13	; enable data and insn caches in copy-back mode
14	; Also enable all registers
15	or_spr_immed	0xc80003c0,hsr0
16	and_spr_immed	0xfffff3ff,hsr0
17
18	; turn on psr.nem, psr.cm, psr.ef, psr.em, psr.esr,
19	; disable external interrupts
20	or_spr_immed	0x69f8,psr
21
22	; If fsr exists, enable all fp_exceptions except inexact
23	movsg		psr,gr28
24	srli		gr28,28,gr28
25	subicc 		gr28,0x2,gr0,icc3 ; is fr400?
26	beq 		icc3,0,nofsr0
27	or_spr_immed	0x3d000000,fsr0
28nofsr0:
29
30	; Set the stack pointer
31	sethi.p		0x7,sp
32	setlo		0xfffc,sp	; TODO -- what's a good value for this?
33
34	; Set the TBR address
35	sethi.p		0xf,gr28
36	setlo		0xf000,gr28
37	movgs		gr28,tbr	; TODO -- what's a good value for this?
38
39	; Go to user mode -- causes too many problems
40	;and_spr_immed	0xfffffffb,psr
41	.endm
42
43; Set GR with another GR
44	.macro set_gr_gr src targ
45	addi	\src,0,\targ
46	.endm
47
48; Set GR with immediate value
49	.macro set_gr_immed val reg
50	.if (\val >= -32768) && (\val <= 23767)
51	setlos	\val,\reg
52	.else
53	setlo.p	%lo(\val),\reg
54	sethi	%hi(\val),\reg
55	.endif
56	.endm
57
58	.macro set_gr_limmed valh vall reg
59	sethi.p	\valh,\reg
60	setlo	\vall,\reg
61	.endm
62
63; Set GR with address value
64	.macro set_gr_addr addr reg
65	sethi.p	%hi(\addr),\reg
66	setlo	%lo(\addr),\reg
67	.endm
68
69; Set GR with SPR
70	.macro set_gr_spr src targ
71	movsg	\src,\targ
72	.endm
73
74; Set GR with a value from memory
75	.macro set_gr_mem addr reg
76	set_gr_addr	\addr,gr28
77	ldi		@(gr28,0),\reg
78	.endm
79
80; Increment GR with immediate value
81	.macro inc_gr_immed val reg
82	.if (\val >= -2048) && (\val <= 2047)
83	addi \reg,\val,\reg
84	.else
85	set_gr_immed \val,gr28
86	add \reg,gr28,\reg
87	.endif
88	.endm
89
90; AND GR with immediate value
91	.macro and_gr_immed val reg
92	.if (\val >= -2048) && (\val <= 2047)
93	andi \reg,\val,\reg
94	.else
95	set_gr_immed \val,gr28
96	and \reg,gr28,\reg
97	.endif
98	.endm
99
100; OR GR with immediate value
101	.macro or_gr_immed val reg
102	.if (\val >= -2048) && (\val <= 2047)
103	ori \reg,\val,\reg
104	.else
105	set_gr_immed \val,gr28
106	or \reg,gr28,\reg
107	.endif
108	.endm
109
110; Set FR with another FR
111	.macro set_fr_fr src targ
112	fmovs	\src,\targ
113	.endm
114
115; Set FR with integer immediate value
116	.macro set_fr_iimmed valh vall reg
117	set_gr_limmed	\valh,\vall,gr28
118	movgf		gr28,\reg
119	.endm
120
121; Set FR with integer immediate value
122	.macro set_fr_immed val reg
123	set_gr_immed	\val,gr28
124	movgf		gr28,\reg
125	.endm
126
127; Set FR with a value from memory
128	.macro set_fr_mem addr reg
129	set_gr_addr	\addr,gr28
130	ldfi		@(gr28,0),\reg
131	.endm
132
133; Set double FR with another double FR
134	.macro set_dfr_dfr src targ
135	fmovd	\src,\targ
136	.endm
137
138; Set double FR with a value from memory
139	.macro set_dfr_mem addr reg
140	set_gr_addr	\addr,gr28
141	lddfi		@(gr28,0),\reg
142	.endm
143
144; Set CPR with immediate value
145	.macro set_cpr_immed val reg
146	addi		sp,-4,gr28
147	set_gr_immed	\val,gr29
148	st		gr29,@(gr28,gr0)
149	ldc		@(gr28,gr0),\reg
150	.endm
151
152	.macro set_cpr_limmed valh vall reg
153	addi		sp,-4,gr28
154	set_gr_limmed	\valh,\vall,gr29
155	st		gr29,@(gr28,gr0)
156	ldc		@(gr28,gr0),\reg
157	.endm
158
159; Set SPR with immediate value
160	.macro set_spr_immed val reg
161	set_gr_immed	\val,gr28
162	movgs		gr28,\reg
163	.endm
164
165	.macro set_spr_limmed valh vall reg
166	set_gr_limmed	\valh,\vall,gr28
167	movgs		gr28,\reg
168	.endm
169
170	.macro set_spr_addr addr reg
171	set_gr_addr	\addr,gr28
172	movgs		gr28,\reg
173	.endm
174
175; increment SPR with immediate value
176	.macro inc_spr_immed val reg
177	movsg		\reg,gr28
178	inc_gr_immed 	\val,gr28
179	movgs		gr28,\reg
180	.endm
181
182; OR spr with immediate value
183	.macro or_spr_immed val reg
184	movsg		\reg,gr28
185	set_gr_immed 	\val,gr29
186	or		gr28,gr29,gr28
187	movgs		gr28,\reg
188	.endm
189
190; AND spr with immediate value
191	.macro and_spr_immed val reg
192	movsg		\reg,gr28
193	set_gr_immed 	\val,gr29
194	and		gr28,gr29,gr28
195	movgs		gr28,\reg
196	.endm
197
198; Set accumulator with immediate value
199	.macro set_acc_immed val reg
200	set_fr_immed	\val,fr31
201	mwtacc		fr31,\reg
202	.endm
203
204; Set accumulator guard with immediate value
205	.macro set_accg_immed val reg
206	set_fr_immed	\val,fr31
207	mwtaccg		fr31,\reg
208	.endm
209
210; Set memory with immediate value
211	.macro set_mem_immed val base
212	set_gr_immed	\val,gr28
213	sti		gr28,@(\base,0)
214	.endm
215
216	.macro set_mem_limmed valh vall base
217	set_gr_limmed	\valh,\vall,gr28
218	sti		gr28,@(\base,0)
219	.endm
220
221; Set memory with GR value
222	.macro set_mem_gr reg addr
223	set_gr_addr	\addr,gr28
224	sti		\reg,@(gr28,0)
225	.endm
226
227; Test the value of a general register against another general register
228	.macro test_gr_gr reg1 reg2
229	subcc \reg1,\reg2,gr0,icc3
230	beq icc3,0,test_gr\@
231	fail
232test_gr\@:
233	.endm
234
235; Test the value of an immediate against a general register
236	.macro test_gr_immed val reg
237	.if (\val >= -512) && (\val <= 511)
238	subicc \reg,\val,gr0,icc3
239	.else
240	set_gr_immed \val,gr28
241	subcc \reg,gr28,gr0,icc3
242	.endif
243	beq icc3,0,test_gr\@
244	fail
245test_gr\@:
246	.endm
247
248	.macro test_gr_limmed valh vall reg
249	set_gr_limmed \valh,\vall,gr28
250	subcc \reg,gr28,gr0,icc3
251	beq icc3,0,test_gr\@
252	fail
253test_gr\@:
254	.endm
255
256; Test the value of an floating register against an integer immediate
257	.macro test_fr_limmed valh vall reg
258	movfg		\reg,gr29
259	set_gr_limmed	\valh,\vall,gr28
260	subcc		gr29,gr28,gr0,icc3
261	beq icc3,0,test_gr\@
262	fail
263test_gr\@:
264	.endm
265
266	.macro test_fr_iimmed val reg
267	movfg		\reg,gr29
268	set_gr_immed	\val,gr28
269	subcc		gr29,gr28,gr0,icc3
270	beq icc3,0,test_gr\@
271	fail
272test_gr\@:
273	.endm
274
275; Test the value of a floating register against another floating point register
276	.macro test_fr_fr reg1 reg2
277	fcmps	\reg1,\reg2,fcc3
278	fbeq 	fcc3,0,test_gr\@
279	fail
280test_gr\@:
281	.endm
282
283; Test the value of a double floating register against another
284; double floating point register
285	.macro test_dfr_dfr reg1 reg2
286	fcmpd	\reg1,\reg2,fcc3
287	fbeq 	fcc3,0,test_gr\@
288	fail
289test_gr\@:
290	.endm
291
292; Test the value of a special purpose register against an integer immediate
293	.macro test_spr_immed val reg
294	movsg		\reg,gr29
295	set_gr_immed	\val,gr28
296	subcc		gr29,gr28,gr0,icc3
297	beq icc3,0,test_gr\@
298	fail
299test_gr\@:
300	.endm
301
302	.macro test_spr_limmed valh vall reg
303	movsg		\reg,gr29
304	set_gr_limmed	\valh,\vall,gr28
305	subcc		gr29,gr28,gr0,icc3
306	beq icc3,0,test_gr\@
307	fail
308test_gr\@:
309	.endm
310
311	.macro test_spr_gr spr gr
312	movsg		\spr,gr28
313	test_gr_gr	\gr,gr28
314	.endm
315
316	.macro test_spr_addr addr reg
317	movsg		\reg,gr29
318	set_gr_addr	\addr,gr28
319	test_gr_gr	gr28,gr29
320	.endm
321
322; Test spr bits masked and shifted against the given value
323	.macro test_spr_bits	mask,shift,val,reg
324	movsg		\reg,gr28
325	set_gr_immed 	\mask,gr29
326	and		gr28,gr29,gr28
327	srli		gr28,\shift,gr29
328	test_gr_immed	\val,gr29
329	.endm
330
331
332; Test the value of an accumulator against an integer immediate
333	.macro test_acc_immed val reg
334	mrdacc		\reg,fr31
335	test_fr_iimmed	\val,fr31
336	.endm
337
338; Test the value of an accumulator against an integer immediate
339	.macro test_acc_limmed valh vall reg
340	mrdacc		\reg,fr31
341	test_fr_limmed	\valh,\vall,fr31
342	.endm
343
344; Test the value of an accumulator guard against an integer immediate
345	.macro test_accg_immed val reg
346	mrdaccg		\reg,fr31
347	test_fr_iimmed	\val,fr31
348	.endm
349
350; Test CPR agains an immediate value
351	.macro test_cpr_limmed valh vall reg
352	addi		sp,-4,gr31
353	stc		\reg,@(gr31,gr0)
354	test_mem_limmed	\valh,\vall,gr31
355	.endm
356
357; Test the value of an immediate against memory
358	.macro test_mem_immed val base
359	ldi		@(\base,0),gr29
360	.if (\val >= -512) && (\val <= 511)
361	subicc gr29,\val,gr0,icc3
362	.else
363	set_gr_immed \val,gr28
364	subcc gr29,gr28,gr0,icc3
365	.endif
366	beq icc3,0,test_gr\@
367	fail
368test_gr\@:
369	.endm
370
371	.macro test_mem_limmed valh vall base
372	ldi		@(\base,0),gr29
373	set_gr_limmed \valh,\vall,gr28
374	subcc gr29,gr28,gr0,icc3
375	beq icc3,0,test_gr\@
376	fail
377test_gr\@:
378	.endm
379
380; Set an integer condition code
381	.macro set_icc mask iccno
382	set_gr_immed	4,gr29
383	smuli		gr29,\iccno,gr30
384	addi		gr31,16,gr31
385	set_gr_immed	0xf,gr28
386	sll		gr28,gr31,gr28
387	not		gr28,gr28
388	movsg		ccr,gr29
389	and		gr28,gr29,gr29
390	set_gr_immed	\mask,gr28
391	sll		gr28,gr31,gr28
392	or		gr28,gr29,gr29
393	movgs		gr29,ccr
394	.endm
395; started here
396; Test the condition codes
397	.macro test_icc N Z V C iccno
398	.if (\N == 1)
399	bp   \iccno,0,fail\@
400	.else
401	bn   \iccno,0,fail\@
402	.endif
403	.if (\Z == 1)
404	bne  \iccno,0,fail\@
405	.else
406	beq   \iccno,0,fail\@
407	.endif
408	.if (\V == 1)
409	bnv \iccno,0,fail\@
410	.else
411	bv   \iccno,0,fail\@
412	.endif
413	.if (\C == 1)
414	bnc   \iccno,0,fail\@
415	.else
416	bc   \iccno,0,fail\@
417	.endif
418	bra test_cc\@
419fail\@:
420	fail
421test_cc\@:
422	.endm
423
424; Set an floating point condition code
425	.macro set_fcc mask fccno
426	set_gr_immed	4,gr29
427	smuli		gr29,\fccno,gr30
428	set_gr_immed	0xf,gr28
429	sll		gr28,gr31,gr28
430	not		gr28,gr28
431	movsg		ccr,gr29
432	and		gr28,gr29,gr29
433	set_gr_immed	\mask,gr28
434	sll		gr28,gr31,gr28
435	or		gr28,gr29,gr29
436	movgs		gr29,ccr
437	.endm
438
439; Test the condition codes
440	.macro test_fcc val fccno
441	set_gr_immed	4,gr29
442	smuli		gr29,\fccno,gr30
443	movsg		ccr,gr29
444	srl		gr29,gr31,gr29
445	andi		gr29,0xf,gr29
446	test_gr_immed	\val,gr29
447	.endm
448
449; Set PSR.ET
450	.macro set_psr_et val
451	movsg		psr,gr28
452	.if (\val == 1)
453	ori		gr28,1,gr28		; Turn on SPR.ET
454	.else
455	andi		gr28,0xfffffffe,gr28	; Turn off SPR.ET
456	.endif
457	movgs		gr28,psr
458	.endm
459
460; Floating point constants
461	.macro float_constants
462f0:		.float	0.0
463f1:		.float	1.0
464f2:		.float	2.0
465f3:		.float	3.0
466f6:		.float	6.0
467f9:		.float	9.0
468fn0:		.float	-0.0
469fn1:		.float	-1.0
470finf:		.long	0x7f800000
471fninf:		.long	0xff800000
472fmax:		.long	0x7f7fffff
473fmin:		.long	0xff7fffff
474feps:		.long	0x00400000
475fneps:		.long	0x80400000
476fnan1:		.long	0x7fc00000
477fnan2:		.long	0x7f800001
478	.endm
479
480	.macro double_constants
481d0:		.double	0.0
482d1:		.double	1.0
483d2:		.double	2.0
484d3:		.double	3.0
485d6:		.double	6.0
486d9:		.double	9.0
487dn0:		.double	-0.0
488dn1:		.double	-1.0
489dinf:		.long	0x7ff00000
490		.long	0x00000000
491dninf:		.long	0xfff00000
492		.long	0x00000000
493dmax:		.long	0x7fefffff
494		.long	0xffffffff
495dmin:		.long	0xffefffff
496		.long	0xffffffff
497deps:		.long	0x00080000
498		.long	0x00000000
499dneps:		.long	0x80080000
500		.long	0x00000000
501dnan1:		.long	0x7ff80000
502		.long	0x00000000
503dnan2:		.long	0x7ff00000
504		.long	0x00000001
505	.endm
506
507; Load floating point constants
508	.macro load_float_constants
509	set_fr_mem	fninf,fr0
510	set_fr_mem	fmin,fr4
511	set_fr_mem	fn1,fr8
512	set_fr_mem	fneps,fr12
513	set_fr_mem	fn0,fr16
514	set_fr_mem	f0,fr20
515	set_fr_mem	feps,fr24
516	set_fr_mem	f1,fr28
517	set_fr_mem	f2,fr32
518	set_fr_mem	f3,fr36
519	set_fr_mem	f6,fr40
520	set_fr_mem	f9,fr44
521	set_fr_mem	fmax,fr48
522	set_fr_mem	finf,fr52
523	set_fr_mem	fnan1,fr56
524	set_fr_mem	fnan2,fr60
525	.endm
526
527	.macro load_float_constants1
528	set_fr_mem	fninf,fr1
529	set_fr_mem	fmin,fr5
530	set_fr_mem	fn1,fr9
531	set_fr_mem	fneps,fr13
532	set_fr_mem	fn0,fr17
533	set_fr_mem	f0,fr21
534	set_fr_mem	feps,fr25
535	set_fr_mem	f1,fr29
536	set_fr_mem	f2,fr33
537	set_fr_mem	f3,fr37
538	set_fr_mem	f6,fr41
539	set_fr_mem	f9,fr45
540	set_fr_mem	fmax,fr49
541	set_fr_mem	finf,fr53
542	set_fr_mem	fnan1,fr57
543	set_fr_mem	fnan2,fr61
544	.endm
545
546	.macro load_float_constants2
547	set_fr_mem	fninf,fr2
548	set_fr_mem	fmin,fr6
549	set_fr_mem	fn1,fr10
550	set_fr_mem	fneps,fr14
551	set_fr_mem	fn0,fr18
552	set_fr_mem	f0,fr22
553	set_fr_mem	feps,fr26
554	set_fr_mem	f1,fr30
555	set_fr_mem	f2,fr34
556	set_fr_mem	f3,fr38
557	set_fr_mem	f6,fr42
558	set_fr_mem	f9,fr46
559	set_fr_mem	fmax,fr50
560	set_fr_mem	finf,fr54
561	set_fr_mem	fnan1,fr58
562	set_fr_mem	fnan2,fr62
563	.endm
564
565	.macro load_float_constants3
566	set_fr_mem	fninf,fr3
567	set_fr_mem	fmin,fr7
568	set_fr_mem	fn1,fr11
569	set_fr_mem	fneps,fr15
570	set_fr_mem	fn0,fr19
571	set_fr_mem	f0,fr23
572	set_fr_mem	feps,fr27
573	set_fr_mem	f1,fr31
574	set_fr_mem	f2,fr35
575	set_fr_mem	f3,fr39
576	set_fr_mem	f6,fr43
577	set_fr_mem	f9,fr47
578	set_fr_mem	fmax,fr51
579	set_fr_mem	finf,fr55
580	set_fr_mem	fnan1,fr59
581	set_fr_mem	fnan2,fr63
582	.endm
583
584	.macro load_double_constants
585	set_dfr_mem	dninf,fr0
586	set_dfr_mem	dmin,fr4
587	set_dfr_mem	dn1,fr8
588	set_dfr_mem	dneps,fr12
589	set_dfr_mem	dn0,fr16
590	set_dfr_mem	d0,fr20
591	set_dfr_mem	deps,fr24
592	set_dfr_mem	d1,fr28
593	set_dfr_mem	d2,fr32
594	set_dfr_mem	d3,fr36
595	set_dfr_mem	d6,fr40
596	set_dfr_mem	d9,fr44
597	set_dfr_mem	dmax,fr48
598	set_dfr_mem	dinf,fr52
599	set_dfr_mem	dnan1,fr56
600	set_dfr_mem	dnan2,fr60
601	.endm
602
603; Lock the insn cache at the given address
604	.macro lock_insn_cache address
605	icpl		\address,gr0,1
606	.endm
607
608; Lock the data cache at the given address
609	.macro lock_data_cache address
610	dcpl		\address,gr0,1
611	.endm
612
613; Invalidate the data cache at the given address
614	.macro invalidate_data_cache address
615	dci		@(\address,gr0)
616	.endm
617
618; Flush the data cache at the given address
619	.macro flush_data_cache address
620	dcf		@(\address,gr0)
621	.endm
622
623; Write a bctrlr 0,0 insn at the address contained in the given register
624	.macro set_bctrlr_0_0 address
625	set_mem_immed	0x80382000,\address	; bctrlr 0,0
626	flush_data_cache \address
627	.endm
628
629; Exit with return code
630	.macro exit rc
631	setlos		#1,gr7
632	set_gr_immed	\rc,gr8
633	tira		gr0,#0
634	.endm
635
636; Pass the test case
637	.macro pass
638pass\@:
639	setlos.p	#5,gr10
640	setlos		#1,gr8
641	setlos		#5,gr7
642	set_gr_addr  	passmsg,gr9
643	tira		gr0,#0
644	exit		#0
645	.endm
646
647; Fail the testcase
648	.macro fail
649fail\@:
650	setlos.p	#5,gr10
651	setlos		#1,gr8
652	setlos		#5,gr7
653	set_gr_addr	failmsg,gr9
654	tira		gr0,#0
655	exit		#1
656	.endm
657