xref: /openbmc/qemu/tests/tcg/hexagon/preg_alias.c (revision b91a0fa7)
1 /*
2  *  Copyright(c) 2019-2021 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   unsigned char val;
61   asm volatile("c4 = %0" : : "r"(cval));
62 
63   asm volatile("%0 = p0" : "=r"(val));
64   pregs->pregs.p0 = val;
65   asm volatile("%0 = p1" : "=r"(val));
66   pregs->pregs.p1 = val;
67   asm volatile("%0 = p2" : "=r"(val));
68   pregs->pregs.p2 = val;
69   asm volatile("%0 = p3" : "=r"(val));
70   pregs->pregs.p3 = val;
71 }
72 
73 int err;
74 
75 static void check(int val, int expect)
76 {
77     if (val != expect) {
78         printf("ERROR: 0x%08x != 0x%08x\n", val, expect);
79         err++;
80     }
81 }
82 
83 static inline void creg_alias_pair(unsigned int cval, PRegs *pregs)
84 {
85   unsigned long long cval_pair = (0xdeadbeefULL << 32) | cval;
86   unsigned char val;
87   int c5;
88   asm volatile("c5:4 = %0" : : "r"(cval_pair));
89 
90   asm volatile("%0 = p0" : "=r"(val));
91   pregs->pregs.p0 = val;
92   asm volatile("%0 = p1" : "=r"(val));
93   pregs->pregs.p1 = val;
94   asm volatile("%0 = p2" : "=r"(val));
95   pregs->pregs.p2 = val;
96   asm volatile("%0 = p3" : "=r"(val));
97   pregs->pregs.p3 = val;
98   asm volatile("%0 = c5" : "=r"(c5));
99   check(c5, 0xdeadbeef);
100 }
101 
102 int main()
103 {
104     int c4;
105     PRegs pregs;
106 
107     c4 = preg_alias(0xff, 0x00, 0xff, 0x00);
108     check(c4, 0x00ff00ff);
109     c4 = preg_alias(0xff, 0x00, 0x00, 0x00);
110     check(c4, 0x000000ff);
111     c4 = preg_alias(0x00, 0xff, 0x00, 0x00);
112     check(c4, 0x0000ff00);
113     c4 = preg_alias(0x00, 0x00, 0xff, 0x00);
114     check(c4, 0x00ff0000);
115     c4 = preg_alias(0x00, 0x00, 0x00, 0xff);
116     check(c4, 0xff000000);
117     c4 = preg_alias(0xff, 0xff, 0xff, 0xff);
118     check(c4, 0xffffffff);
119 
120     c4 = preg_alias_pair(0xff, 0x00, 0xff, 0x00);
121     check(c4, 0x00ff00ff);
122       c4 = preg_alias_pair(0xff, 0x00, 0x00, 0x00);
123     check(c4, 0x000000ff);
124     c4 = preg_alias_pair(0x00, 0xff, 0x00, 0x00);
125     check(c4, 0x0000ff00);
126     c4 = preg_alias_pair(0x00, 0x00, 0xff, 0x00);
127     check(c4, 0x00ff0000);
128     c4 = preg_alias_pair(0x00, 0x00, 0x00, 0xff);
129     check(c4, 0xff000000);
130     c4 = preg_alias_pair(0xff, 0xff, 0xff, 0xff);
131     check(c4, 0xffffffff);
132 
133     creg_alias(0x00ff00ff, &pregs);
134     check(pregs.creg, 0x00ff00ff);
135     creg_alias(0x00ffff00, &pregs);
136     check(pregs.creg, 0x00ffff00);
137     creg_alias(0x00000000, &pregs);
138     check(pregs.creg, 0x00000000);
139     creg_alias(0xff000000, &pregs);
140     check(pregs.creg, 0xff000000);
141     creg_alias(0x00ff0000, &pregs);
142     check(pregs.creg, 0x00ff0000);
143     creg_alias(0x0000ff00, &pregs);
144     check(pregs.creg, 0x0000ff00);
145     creg_alias(0x000000ff, &pregs);
146     check(pregs.creg, 0x000000ff);
147     creg_alias(0xffffffff, &pregs);
148     check(pregs.creg, 0xffffffff);
149 
150     creg_alias_pair(0x00ff00ff, &pregs);
151     check(pregs.creg, 0x00ff00ff);
152     creg_alias_pair(0x00ffff00, &pregs);
153     check(pregs.creg, 0x00ffff00);
154     creg_alias_pair(0x00000000, &pregs);
155     check(pregs.creg, 0x00000000);
156     creg_alias_pair(0xff000000, &pregs);
157     check(pregs.creg, 0xff000000);
158     creg_alias_pair(0x00ff0000, &pregs);
159     check(pregs.creg, 0x00ff0000);
160     creg_alias_pair(0x0000ff00, &pregs);
161     check(pregs.creg, 0x0000ff00);
162     creg_alias_pair(0x000000ff, &pregs);
163     check(pregs.creg, 0x000000ff);
164     creg_alias_pair(0xffffffff, &pregs);
165     check(pregs.creg, 0xffffffff);
166 
167     puts(err ? "FAIL" : "PASS");
168     return err;
169 }
170