1 /* 2 * Copyright(c) 2019-2022 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 : "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 : "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 : "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 : "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