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 #include <stdint.h> 20 21 int err; 22 23 #include "hex_test.h" 24 25 static uint32_t preg_alias(uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3) 26 { 27 uint32_t ret; 28 asm volatile("p0 = %1\n\t" 29 "p1 = %2\n\t" 30 "p2 = %3\n\t" 31 "p3 = %4\n\t" 32 "%0 = C4\n" 33 : "=r"(ret) 34 : "r"(v0), "r"(v1), "r"(v2), "r"(v3) 35 : "p0", "p1", "p2", "p3"); 36 return ret; 37 } 38 39 static uint32_t preg_alias_pair(uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3) 40 { 41 uint64_t c54; 42 asm volatile("p0 = %1\n\t" 43 "p1 = %2\n\t" 44 "p2 = %3\n\t" 45 "p3 = %4\n\t" 46 "%0 = C5:4\n" 47 : "=r"(c54) 48 : "r"(v0), "r"(v1), "r"(v2), "r"(v3) 49 : "p0", "p1", "p2", "p3"); 50 return (uint32_t)c54; 51 } 52 53 typedef union { 54 uint32_t creg; 55 struct { 56 uint8_t p0; 57 uint8_t p1; 58 uint8_t p2; 59 uint8_t p3; 60 } pregs; 61 } PRegs; 62 63 static inline void creg_alias(uint32_t cval, PRegs *pregs) 64 { 65 asm("c4 = %4\n\t" 66 "%0 = p0\n\t" 67 "%1 = p1\n\t" 68 "%2 = p2\n\t" 69 "%3 = p3\n\t" 70 : "=r"(pregs->pregs.p0), "=r"(pregs->pregs.p1), 71 "=r"(pregs->pregs.p2), "=r"(pregs->pregs.p3) 72 : "r"(cval) 73 : "c4", "p0", "p1", "p2", "p3"); 74 } 75 76 static inline void creg_alias_pair(uint32_t cval, PRegs *pregs) 77 { 78 uint64_t cval_pair = (0xdeadbeefULL << 32) | cval; 79 uint32_t c5; 80 81 asm ("c5:4 = %5\n\t" 82 "%0 = p0\n\t" 83 "%1 = p1\n\t" 84 "%2 = p2\n\t" 85 "%3 = p3\n\t" 86 "%4 = c5\n\t" 87 : "=r"(pregs->pregs.p0), "=r"(pregs->pregs.p1), 88 "=r"(pregs->pregs.p2), "=r"(pregs->pregs.p3), "=r"(c5) 89 : "r"(cval_pair) 90 : "c4", "c5", "p0", "p1", "p2", "p3"); 91 92 check32(c5, 0xdeadbeef); 93 } 94 95 static void test_packet(void) 96 { 97 /* 98 * Test that setting c4 inside a packet doesn't impact the predicates 99 * that are read during the packet. 100 */ 101 102 uint32_t result; 103 uint32_t old_val = 0x0000001c; 104 105 /* Test a predicated register transfer */ 106 result = old_val; 107 asm ( 108 "c4 = %1\n\t" 109 "{\n\t" 110 " c4 = %2\n\t" 111 " if (!p2) %0 = %3\n\t" 112 "}\n\t" 113 : "+r"(result) 114 : "r"(0xffffffff), "r"(0xff00ffff), "r"(0x837ed653) 115 : "c4", "p0", "p1", "p2", "p3"); 116 check32(result, old_val); 117 118 /* Test a predicated store */ 119 result = 0xffffffff; 120 asm ("c4 = %0\n\t" 121 "{\n\t" 122 " c4 = %1\n\t" 123 " if (!p2) memw(%2) = #0\n\t" 124 "}\n\t" 125 : 126 : "r"(0), "r"(0xffffffff), "r"(&result) 127 : "c4", "p0", "p1", "p2", "p3", "memory"); 128 check32(result, 0x0); 129 } 130 131 int main() 132 { 133 uint32_t c4; 134 PRegs pregs; 135 136 c4 = preg_alias(0xff, 0x00, 0xff, 0x00); 137 check32(c4, 0x00ff00ff); 138 c4 = preg_alias(0xff, 0x00, 0x00, 0x00); 139 check32(c4, 0x000000ff); 140 c4 = preg_alias(0x00, 0xff, 0x00, 0x00); 141 check32(c4, 0x0000ff00); 142 c4 = preg_alias(0x00, 0x00, 0xff, 0x00); 143 check32(c4, 0x00ff0000); 144 c4 = preg_alias(0x00, 0x00, 0x00, 0xff); 145 check32(c4, 0xff000000); 146 c4 = preg_alias(0xff, 0xff, 0xff, 0xff); 147 check32(c4, 0xffffffff); 148 149 c4 = preg_alias_pair(0xff, 0x00, 0xff, 0x00); 150 check32(c4, 0x00ff00ff); 151 c4 = preg_alias_pair(0xff, 0x00, 0x00, 0x00); 152 check32(c4, 0x000000ff); 153 c4 = preg_alias_pair(0x00, 0xff, 0x00, 0x00); 154 check32(c4, 0x0000ff00); 155 c4 = preg_alias_pair(0x00, 0x00, 0xff, 0x00); 156 check32(c4, 0x00ff0000); 157 c4 = preg_alias_pair(0x00, 0x00, 0x00, 0xff); 158 check32(c4, 0xff000000); 159 c4 = preg_alias_pair(0xff, 0xff, 0xff, 0xff); 160 check32(c4, 0xffffffff); 161 162 creg_alias(0x00ff00ff, &pregs); 163 check32(pregs.creg, 0x00ff00ff); 164 creg_alias(0x00ffff00, &pregs); 165 check32(pregs.creg, 0x00ffff00); 166 creg_alias(0x00000000, &pregs); 167 check32(pregs.creg, 0x00000000); 168 creg_alias(0xff000000, &pregs); 169 check32(pregs.creg, 0xff000000); 170 creg_alias(0x00ff0000, &pregs); 171 check32(pregs.creg, 0x00ff0000); 172 creg_alias(0x0000ff00, &pregs); 173 check32(pregs.creg, 0x0000ff00); 174 creg_alias(0x000000ff, &pregs); 175 check32(pregs.creg, 0x000000ff); 176 creg_alias(0xffffffff, &pregs); 177 check32(pregs.creg, 0xffffffff); 178 179 creg_alias_pair(0x00ff00ff, &pregs); 180 check32(pregs.creg, 0x00ff00ff); 181 creg_alias_pair(0x00ffff00, &pregs); 182 check32(pregs.creg, 0x00ffff00); 183 creg_alias_pair(0x00000000, &pregs); 184 check32(pregs.creg, 0x00000000); 185 creg_alias_pair(0xff000000, &pregs); 186 check32(pregs.creg, 0xff000000); 187 creg_alias_pair(0x00ff0000, &pregs); 188 check32(pregs.creg, 0x00ff0000); 189 creg_alias_pair(0x0000ff00, &pregs); 190 check32(pregs.creg, 0x0000ff00); 191 creg_alias_pair(0x000000ff, &pregs); 192 check32(pregs.creg, 0x000000ff); 193 creg_alias_pair(0xffffffff, &pregs); 194 check32(pregs.creg, 0xffffffff); 195 196 test_packet(); 197 198 puts(err ? "FAIL" : "PASS"); 199 return err; 200 } 201