xref: /openbmc/qemu/tests/tcg/hexagon/preg_alias.c (revision e8d1e0cd)
1 /*
2  *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <stdio.h>
19 
20 static inline int preg_alias(int v0, int v1, int v2, int v3)
21 {
22   int ret;
23   asm volatile("p0 = %1\n\t"
24                "p1 = %2\n\t"
25                "p2 = %3\n\t"
26                "p3 = %4\n\t"
27                "%0 = C4\n"
28                : "=r"(ret)
29                : "r"(v0), "r"(v1), "r"(v2), "r"(v3)
30                : "p0", "p1", "p2", "p3");
31   return ret;
32 }
33 
34 static inline int preg_alias_pair(int v0, int v1, int v2, int v3)
35 {
36   long long c54;
37   asm volatile("p0 = %1\n\t"
38                "p1 = %2\n\t"
39                "p2 = %3\n\t"
40                "p3 = %4\n\t"
41                "%0 = C5:4\n"
42                : "=r"(c54)
43                : "r"(v0), "r"(v1), "r"(v2), "r"(v3)
44                : "p0", "p1", "p2", "p3");
45   return (int)c54;
46 }
47 
48 typedef union {
49     int creg;
50     struct {
51       unsigned char p0;
52       unsigned char p1;
53       unsigned char p2;
54       unsigned char p3;
55     } pregs;
56 } PRegs;
57 
58 static inline void creg_alias(int cval, PRegs *pregs)
59 {
60   asm("c4 = %4\n\t"
61       "%0 = p0\n\t"
62       "%1 = p1\n\t"
63       "%2 = p2\n\t"
64       "%3 = p3\n\t"
65       : "=r"(pregs->pregs.p0), "=r"(pregs->pregs.p1),
66         "=r"(pregs->pregs.p2), "=r"(pregs->pregs.p3)
67       : "r"(cval)
68       : "c4", "p0", "p1", "p2", "p3");
69 }
70 
71 int err;
72 
73 static void check(int val, int expect)
74 {
75     if (val != expect) {
76         printf("ERROR: 0x%08x != 0x%08x\n", val, expect);
77         err++;
78     }
79 }
80 
81 static inline void creg_alias_pair(unsigned int cval, PRegs *pregs)
82 {
83   unsigned long long cval_pair = (0xdeadbeefULL << 32) | cval;
84   int c5;
85 
86   asm ("c5:4 = %5\n\t"
87        "%0 = p0\n\t"
88        "%1 = p1\n\t"
89        "%2 = p2\n\t"
90        "%3 = p3\n\t"
91        "%4 = c5\n\t"
92        : "=r"(pregs->pregs.p0), "=r"(pregs->pregs.p1),
93          "=r"(pregs->pregs.p2), "=r"(pregs->pregs.p3), "=r"(c5)
94        : "r"(cval_pair)
95        : "c4", "c5", "p0", "p1", "p2", "p3");
96 
97   check(c5, 0xdeadbeef);
98 }
99 
100 static void test_packet(void)
101 {
102     /*
103      * Test that setting c4 inside a packet doesn't impact the predicates
104      * that are read during the packet.
105      */
106 
107     int result;
108     int old_val = 0x0000001c;
109 
110     /* Test a predicated register transfer */
111     result = old_val;
112     asm (
113          "c4 = %1\n\t"
114          "{\n\t"
115          "    c4 = %2\n\t"
116          "    if (!p2) %0 = %3\n\t"
117          "}\n\t"
118          : "+r"(result)
119          : "r"(0xffffffff), "r"(0xff00ffff), "r"(0x837ed653)
120          : "c4", "p0", "p1", "p2", "p3");
121     check(result, old_val);
122 
123     /* Test a predicated store */
124     result = 0xffffffff;
125     asm ("c4 = %0\n\t"
126          "{\n\t"
127          "    c4 = %1\n\t"
128          "    if (!p2) memw(%2) = #0\n\t"
129          "}\n\t"
130          :
131          : "r"(0), "r"(0xffffffff), "r"(&result)
132          : "c4", "p0", "p1", "p2", "p3", "memory");
133     check(result, 0x0);
134 }
135 
136 int main()
137 {
138     int c4;
139     PRegs pregs;
140 
141     c4 = preg_alias(0xff, 0x00, 0xff, 0x00);
142     check(c4, 0x00ff00ff);
143     c4 = preg_alias(0xff, 0x00, 0x00, 0x00);
144     check(c4, 0x000000ff);
145     c4 = preg_alias(0x00, 0xff, 0x00, 0x00);
146     check(c4, 0x0000ff00);
147     c4 = preg_alias(0x00, 0x00, 0xff, 0x00);
148     check(c4, 0x00ff0000);
149     c4 = preg_alias(0x00, 0x00, 0x00, 0xff);
150     check(c4, 0xff000000);
151     c4 = preg_alias(0xff, 0xff, 0xff, 0xff);
152     check(c4, 0xffffffff);
153 
154     c4 = preg_alias_pair(0xff, 0x00, 0xff, 0x00);
155     check(c4, 0x00ff00ff);
156       c4 = preg_alias_pair(0xff, 0x00, 0x00, 0x00);
157     check(c4, 0x000000ff);
158     c4 = preg_alias_pair(0x00, 0xff, 0x00, 0x00);
159     check(c4, 0x0000ff00);
160     c4 = preg_alias_pair(0x00, 0x00, 0xff, 0x00);
161     check(c4, 0x00ff0000);
162     c4 = preg_alias_pair(0x00, 0x00, 0x00, 0xff);
163     check(c4, 0xff000000);
164     c4 = preg_alias_pair(0xff, 0xff, 0xff, 0xff);
165     check(c4, 0xffffffff);
166 
167     creg_alias(0x00ff00ff, &pregs);
168     check(pregs.creg, 0x00ff00ff);
169     creg_alias(0x00ffff00, &pregs);
170     check(pregs.creg, 0x00ffff00);
171     creg_alias(0x00000000, &pregs);
172     check(pregs.creg, 0x00000000);
173     creg_alias(0xff000000, &pregs);
174     check(pregs.creg, 0xff000000);
175     creg_alias(0x00ff0000, &pregs);
176     check(pregs.creg, 0x00ff0000);
177     creg_alias(0x0000ff00, &pregs);
178     check(pregs.creg, 0x0000ff00);
179     creg_alias(0x000000ff, &pregs);
180     check(pregs.creg, 0x000000ff);
181     creg_alias(0xffffffff, &pregs);
182     check(pregs.creg, 0xffffffff);
183 
184     creg_alias_pair(0x00ff00ff, &pregs);
185     check(pregs.creg, 0x00ff00ff);
186     creg_alias_pair(0x00ffff00, &pregs);
187     check(pregs.creg, 0x00ffff00);
188     creg_alias_pair(0x00000000, &pregs);
189     check(pregs.creg, 0x00000000);
190     creg_alias_pair(0xff000000, &pregs);
191     check(pregs.creg, 0xff000000);
192     creg_alias_pair(0x00ff0000, &pregs);
193     check(pregs.creg, 0x00ff0000);
194     creg_alias_pair(0x0000ff00, &pregs);
195     check(pregs.creg, 0x0000ff00);
196     creg_alias_pair(0x000000ff, &pregs);
197     check(pregs.creg, 0x000000ff);
198     creg_alias_pair(0xffffffff, &pregs);
199     check(pregs.creg, 0xffffffff);
200 
201     test_packet();
202 
203     puts(err ? "FAIL" : "PASS");
204     return err;
205 }
206