1/* Tests some basic fpu instructions.
2
3   Copyright (C) 2019-2023 Free Software Foundation, Inc.
4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 3 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18# mach: or1k
19# output: report(0x400921f9);\n
20# output: report(0xf01b866e);\n
21# output: report(0x4005bf09);\n
22# output: report(0x95aaf790);\n
23# output: report(0x00000000);\n
24# output: report(0x00001234);\n
25# output: \n
26# output: report(0x40b23400);\n
27# output: report(0x00000000);\n
28# output: report(0x40b23400);\n
29# output: report(0x00000000);\n
30# output: \n
31# output: report(0x40177081);\n
32# output: report(0xc2e33eff);\n
33# output: report(0x400921f9);\n
34# output: report(0xf01b866e);\n
35# output: \n
36# output: report(0x40211456);\n
37# output: report(0x587dfabf);\n
38# output: report(0x400921f9);\n
39# output: report(0xf01b866d);\n
40# output: \n
41# output: report(0x00000001);\n
42# output: \n
43# output: WARNING: ignoring fpu error caught in fast mode.\n
44# output: report(0x00000000);\n
45# output: \n
46# output: exit(0)\n
47
48#include "or1k-asm-test-helpers.h"
49
50	STANDARD_TEST_ENVIRONMENT
51
52	.section .exception_vectors
53
54	/* Floating point exception.  */
55	.org	0xd00
56
57	/* The handling is a bit dubious at present.  We just patch the
58	   instruction with l.nop and restart.  This will go wrong in branch
59	   delay slots.  But we don't have those in this test.  */
60	l.addi r1, r1, -EXCEPTION_STACK_SKIP_SIZE
61	PUSH r2
62	PUSH r3
63	/* Save the address of the instruction that caused the problem.  */
64	MOVE_FROM_SPR r2, SPR_EPCR_BASE
65	LOAD_IMMEDIATE r3, 0x15000000 /* Opcode for l.nop  */
66	l.sw	-4(r2), r3
67	POP r3
68	POP r2
69	l.addi r1, r1, EXCEPTION_STACK_SKIP_SIZE
70	l.rfe
71
72	.section .data
73	.align 4
74	.type   pi, @object
75	.size   pi, 8
76anchor:
77pi:
78	.double  3.14159
79
80	.type   e, @object
81	.size   e, 8
82e:
83	.double  2.71828
84
85	.type   large, @object
86	.size   large, 8
87large:
88	.long  0
89	.long  0x1234
90
91	.section .text
92start_tests:
93	PUSH LINK_REGISTER_R9
94
95	/* Test lf.itof.d int to double conversion.  Setting up:
96	 *  r11      pointer to data
97	 *  r12,r13  pi as double
98	 *  r14,r15  e  as double
99	 *  r16,r17  a long long
100	 */
101	l.ori	r11, r0, ha(anchor)
102	l.addi	r11, r11, lo(anchor)
103	l.lwz	r12, 0(r11)
104	l.lwz	r13, 4(r11)
105
106	l.lwz	r14, 8(r11)
107	l.lwz	r15, 12(r11)
108
109	l.lwz	r16, 16(r11)
110	l.lwz	r18, 20(r11)
111
112	/* Output to ensure we loaded it correctly.  */
113	REPORT_REG_TO_CONSOLE r12
114	REPORT_REG_TO_CONSOLE r13
115
116	REPORT_REG_TO_CONSOLE r14
117	REPORT_REG_TO_CONSOLE r15
118
119	REPORT_REG_TO_CONSOLE r16
120	REPORT_REG_TO_CONSOLE r18
121	PRINT_NEWLINE_TO_CONSOLE
122
123	/* Convert the big long to a double. */
124	lf.itof.d r16,r18, r16,r18
125	REPORT_REG_TO_CONSOLE r16
126	REPORT_REG_TO_CONSOLE r18
127
128	/* Convert the double back to a long, it should match before. */
129	lf.ftoi.d r16,r18, r16,r18
130	lf.itof.d r16,r18, r16,r18
131
132	REPORT_REG_TO_CONSOLE r16
133	REPORT_REG_TO_CONSOLE r18
134
135	PRINT_NEWLINE_TO_CONSOLE
136
137	/* Add and subtract some double values.  */
138	lf.add.d r12,r13, r12,r13, r14,r15
139	REPORT_REG_TO_CONSOLE r12
140	REPORT_REG_TO_CONSOLE r13
141
142	lf.sub.d r12,r13, r12,r13, r14,r15
143	REPORT_REG_TO_CONSOLE r12
144	REPORT_REG_TO_CONSOLE r13
145	PRINT_NEWLINE_TO_CONSOLE
146
147	/* Multiply and divide double values.  */
148	lf.mul.d r12,r13, r12,r13, r14,r15
149	REPORT_REG_TO_CONSOLE r12
150	REPORT_REG_TO_CONSOLE r13
151
152	lf.div.d r12,r13, r12,r13, r14,r15
153	REPORT_REG_TO_CONSOLE r12
154	REPORT_REG_TO_CONSOLE r13
155	PRINT_NEWLINE_TO_CONSOLE
156
157	/* Test lf.sfge.s set flag if r6 >= r10.  */
158	lf.sfge.d r12,r13, r14,r15
159	MOVE_FROM_SPR r2, SPR_SR
160	REPORT_BIT_TO_CONSOLE r2, SPR_SR_F
161	PRINT_NEWLINE_TO_CONSOLE
162
163	/* Test raising an exception by dividing by 0.  */
164	MOVE_FROM_SPR r2, SPR_FPCSR
165	l.ori	r2, r2, 0x1
166	MOVE_TO_SPR SPR_FPCSR, r2
167div0:	lf.div.d r2,r3, r12,r13, r0,r1
168	REPORT_EXCEPTION div0
169	PRINT_NEWLINE_TO_CONSOLE
170
171	POP LINK_REGISTER_R9
172	RETURN_TO_LINK_REGISTER_R9
173