xref: /qemu/tests/tcg/hexagon/multi_result.c (revision 0a65d286)
1d934c16dSTaylor Simpson /*
2d934c16dSTaylor Simpson  *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
3d934c16dSTaylor Simpson  *
4d934c16dSTaylor Simpson  *  This program is free software; you can redistribute it and/or modify
5d934c16dSTaylor Simpson  *  it under the terms of the GNU General Public License as published by
6d934c16dSTaylor Simpson  *  the Free Software Foundation; either version 2 of the License, or
7d934c16dSTaylor Simpson  *  (at your option) any later version.
8d934c16dSTaylor Simpson  *
9d934c16dSTaylor Simpson  *  This program is distributed in the hope that it will be useful,
10d934c16dSTaylor Simpson  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11d934c16dSTaylor Simpson  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12d934c16dSTaylor Simpson  *  GNU General Public License for more details.
13d934c16dSTaylor Simpson  *
14d934c16dSTaylor Simpson  *  You should have received a copy of the GNU General Public License
15d934c16dSTaylor Simpson  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
16d934c16dSTaylor Simpson  */
17d934c16dSTaylor Simpson 
18d934c16dSTaylor Simpson #include <stdio.h>
19d934c16dSTaylor Simpson 
20d934c16dSTaylor Simpson static int sfrecipa(int Rs, int Rt, int *pred_result)
21d934c16dSTaylor Simpson {
22d934c16dSTaylor Simpson   int result;
23d934c16dSTaylor Simpson   int predval;
24d934c16dSTaylor Simpson 
25d934c16dSTaylor Simpson   asm volatile("%0,p0 = sfrecipa(%2, %3)\n\t"
26d934c16dSTaylor Simpson                "%1 = p0\n\t"
27d934c16dSTaylor Simpson                : "+r"(result), "=r"(predval)
28d934c16dSTaylor Simpson                : "r"(Rs), "r"(Rt)
29d934c16dSTaylor Simpson                : "p0");
30d934c16dSTaylor Simpson   *pred_result = predval;
31d934c16dSTaylor Simpson   return result;
32d934c16dSTaylor Simpson }
33d934c16dSTaylor Simpson 
34dd8705bdSTaylor Simpson static int sfinvsqrta(int Rs, int *pred_result)
35dd8705bdSTaylor Simpson {
36dd8705bdSTaylor Simpson   int result;
37dd8705bdSTaylor Simpson   int predval;
38dd8705bdSTaylor Simpson 
39dd8705bdSTaylor Simpson   asm volatile("%0,p0 = sfinvsqrta(%2)\n\t"
40dd8705bdSTaylor Simpson                "%1 = p0\n\t"
41dd8705bdSTaylor Simpson                : "+r"(result), "=r"(predval)
42dd8705bdSTaylor Simpson                : "r"(Rs)
43dd8705bdSTaylor Simpson                : "p0");
44dd8705bdSTaylor Simpson   *pred_result = predval;
45dd8705bdSTaylor Simpson   return result;
46dd8705bdSTaylor Simpson }
47dd8705bdSTaylor Simpson 
48da74cd2dSTaylor Simpson static long long vacsh(long long Rxx, long long Rss, long long Rtt,
49da74cd2dSTaylor Simpson                        int *pred_result, int *ovf_result)
50da74cd2dSTaylor Simpson {
51da74cd2dSTaylor Simpson   long long result = Rxx;
52da74cd2dSTaylor Simpson   int predval;
53da74cd2dSTaylor Simpson   int usr;
54da74cd2dSTaylor Simpson 
55da74cd2dSTaylor Simpson   /*
56da74cd2dSTaylor Simpson    * This instruction can set bit 0 (OVF/overflow) in usr
57da74cd2dSTaylor Simpson    * Clear the bit first, then return that bit to the caller
58da74cd2dSTaylor Simpson    */
59da74cd2dSTaylor Simpson   asm volatile("r2 = usr\n\t"
60da74cd2dSTaylor Simpson                "r2 = clrbit(r2, #0)\n\t"        /* clear overflow bit */
61da74cd2dSTaylor Simpson                "usr = r2\n\t"
62da74cd2dSTaylor Simpson                "%0,p0 = vacsh(%3, %4)\n\t"
63da74cd2dSTaylor Simpson                "%1 = p0\n\t"
64da74cd2dSTaylor Simpson                "%2 = usr\n\t"
65da74cd2dSTaylor Simpson                : "+r"(result), "=r"(predval), "=r"(usr)
66da74cd2dSTaylor Simpson                : "r"(Rss), "r"(Rtt)
67da74cd2dSTaylor Simpson                : "r2", "p0", "usr");
68da74cd2dSTaylor Simpson   *pred_result = predval;
69da74cd2dSTaylor Simpson   *ovf_result = (usr & 1);
70da74cd2dSTaylor Simpson   return result;
71da74cd2dSTaylor Simpson }
72da74cd2dSTaylor Simpson 
73*0a65d286STaylor Simpson static long long vminub(long long Rtt, long long Rss,
74*0a65d286STaylor Simpson                         int *pred_result)
75*0a65d286STaylor Simpson {
76*0a65d286STaylor Simpson   long long result;
77*0a65d286STaylor Simpson   int predval;
78*0a65d286STaylor Simpson 
79*0a65d286STaylor Simpson   asm volatile("%0,p0 = vminub(%2, %3)\n\t"
80*0a65d286STaylor Simpson                "%1 = p0\n\t"
81*0a65d286STaylor Simpson                : "=r"(result), "=r"(predval)
82*0a65d286STaylor Simpson                : "r"(Rtt), "r"(Rss)
83*0a65d286STaylor Simpson                : "p0");
84*0a65d286STaylor Simpson   *pred_result = predval;
85*0a65d286STaylor Simpson   return result;
86*0a65d286STaylor Simpson }
87*0a65d286STaylor Simpson 
88d934c16dSTaylor Simpson int err;
89d934c16dSTaylor Simpson 
90da74cd2dSTaylor Simpson static void check_ll(long long val, long long expect)
91da74cd2dSTaylor Simpson {
92da74cd2dSTaylor Simpson     if (val != expect) {
93da74cd2dSTaylor Simpson         printf("ERROR: 0x%016llx != 0x%016llx\n", val, expect);
94da74cd2dSTaylor Simpson         err++;
95da74cd2dSTaylor Simpson     }
96da74cd2dSTaylor Simpson }
97da74cd2dSTaylor Simpson 
98d934c16dSTaylor Simpson static void check(int val, int expect)
99d934c16dSTaylor Simpson {
100d934c16dSTaylor Simpson     if (val != expect) {
101d934c16dSTaylor Simpson         printf("ERROR: 0x%08x != 0x%08x\n", val, expect);
102d934c16dSTaylor Simpson         err++;
103d934c16dSTaylor Simpson     }
104d934c16dSTaylor Simpson }
105d934c16dSTaylor Simpson 
106d934c16dSTaylor Simpson static void check_p(int val, int expect)
107d934c16dSTaylor Simpson {
108d934c16dSTaylor Simpson     if (val != expect) {
109d934c16dSTaylor Simpson         printf("ERROR: 0x%02x != 0x%02x\n", val, expect);
110d934c16dSTaylor Simpson         err++;
111d934c16dSTaylor Simpson     }
112d934c16dSTaylor Simpson }
113d934c16dSTaylor Simpson 
114d934c16dSTaylor Simpson static void test_sfrecipa()
115d934c16dSTaylor Simpson {
116d934c16dSTaylor Simpson     int res;
117d934c16dSTaylor Simpson     int pred_result;
118d934c16dSTaylor Simpson 
119d934c16dSTaylor Simpson     res = sfrecipa(0x04030201, 0x05060708, &pred_result);
120d934c16dSTaylor Simpson     check(res, 0x59f38001);
121d934c16dSTaylor Simpson     check_p(pred_result, 0x00);
122d934c16dSTaylor Simpson }
123d934c16dSTaylor Simpson 
124dd8705bdSTaylor Simpson static void test_sfinvsqrta()
125dd8705bdSTaylor Simpson {
126dd8705bdSTaylor Simpson     int res;
127dd8705bdSTaylor Simpson     int pred_result;
128dd8705bdSTaylor Simpson 
129dd8705bdSTaylor Simpson     res = sfinvsqrta(0x04030201, &pred_result);
130dd8705bdSTaylor Simpson     check(res, 0x4d330000);
131dd8705bdSTaylor Simpson     check_p(pred_result, 0xe0);
132dd8705bdSTaylor Simpson 
133dd8705bdSTaylor Simpson     res = sfinvsqrta(0x0, &pred_result);
134dd8705bdSTaylor Simpson     check(res, 0x3f800000);
135dd8705bdSTaylor Simpson     check_p(pred_result, 0x0);
136dd8705bdSTaylor Simpson }
137dd8705bdSTaylor Simpson 
138da74cd2dSTaylor Simpson static void test_vacsh()
139da74cd2dSTaylor Simpson {
140da74cd2dSTaylor Simpson     long long res64;
141da74cd2dSTaylor Simpson     int pred_result;
142da74cd2dSTaylor Simpson     int ovf_result;
143da74cd2dSTaylor Simpson 
144da74cd2dSTaylor Simpson     res64 = vacsh(0x0004000300020001LL,
145da74cd2dSTaylor Simpson                   0x0001000200030004LL,
146da74cd2dSTaylor Simpson                   0x0000000000000000LL, &pred_result, &ovf_result);
147da74cd2dSTaylor Simpson     check_ll(res64, 0x0004000300030004LL);
148da74cd2dSTaylor Simpson     check_p(pred_result, 0xf0);
149da74cd2dSTaylor Simpson     check(ovf_result, 0);
150da74cd2dSTaylor Simpson 
151da74cd2dSTaylor Simpson     res64 = vacsh(0x0004000300020001LL,
152da74cd2dSTaylor Simpson                   0x0001000200030004LL,
153da74cd2dSTaylor Simpson                   0x000affff000d0000LL, &pred_result, &ovf_result);
154da74cd2dSTaylor Simpson     check_ll(res64, 0x000e0003000f0004LL);
155da74cd2dSTaylor Simpson     check_p(pred_result, 0xcc);
156da74cd2dSTaylor Simpson     check(ovf_result, 0);
157da74cd2dSTaylor Simpson 
158da74cd2dSTaylor Simpson     res64 = vacsh(0x00047fff00020001LL,
159da74cd2dSTaylor Simpson                   0x00017fff00030004LL,
160da74cd2dSTaylor Simpson                   0x000a0fff000d0000LL, &pred_result, &ovf_result);
161da74cd2dSTaylor Simpson     check_ll(res64, 0x000e7fff000f0004LL);
162da74cd2dSTaylor Simpson     check_p(pred_result, 0xfc);
163da74cd2dSTaylor Simpson     check(ovf_result, 1);
164da74cd2dSTaylor Simpson 
165da74cd2dSTaylor Simpson     res64 = vacsh(0x0004000300020001LL,
166da74cd2dSTaylor Simpson                   0x0001000200030009LL,
167da74cd2dSTaylor Simpson                   0x000affff000d0001LL, &pred_result, &ovf_result);
168da74cd2dSTaylor Simpson     check_ll(res64, 0x000e0003000f0008LL);
169da74cd2dSTaylor Simpson     check_p(pred_result, 0xcc);
170da74cd2dSTaylor Simpson     check(ovf_result, 0);
171da74cd2dSTaylor Simpson }
172da74cd2dSTaylor Simpson 
173*0a65d286STaylor Simpson static void test_vminub()
174*0a65d286STaylor Simpson {
175*0a65d286STaylor Simpson     long long res64;
176*0a65d286STaylor Simpson     int pred_result;
177*0a65d286STaylor Simpson 
178*0a65d286STaylor Simpson     res64 = vminub(0x0807060504030201LL,
179*0a65d286STaylor Simpson                    0x0102030405060708LL,
180*0a65d286STaylor Simpson                    &pred_result);
181*0a65d286STaylor Simpson     check_ll(res64, 0x0102030404030201LL);
182*0a65d286STaylor Simpson     check_p(pred_result, 0xf0);
183*0a65d286STaylor Simpson 
184*0a65d286STaylor Simpson     res64 = vminub(0x0802060405030701LL,
185*0a65d286STaylor Simpson                    0x0107030504060208LL,
186*0a65d286STaylor Simpson                    &pred_result);
187*0a65d286STaylor Simpson     check_ll(res64, 0x0102030404030201LL);
188*0a65d286STaylor Simpson     check_p(pred_result, 0xaa);
189*0a65d286STaylor Simpson }
190*0a65d286STaylor Simpson 
191d934c16dSTaylor Simpson int main()
192d934c16dSTaylor Simpson {
193d934c16dSTaylor Simpson     test_sfrecipa();
194dd8705bdSTaylor Simpson     test_sfinvsqrta();
195da74cd2dSTaylor Simpson     test_vacsh();
196*0a65d286STaylor Simpson     test_vminub();
197d934c16dSTaylor Simpson 
198d934c16dSTaylor Simpson     puts(err ? "FAIL" : "PASS");
199d934c16dSTaylor Simpson     return err;
200d934c16dSTaylor Simpson }
201