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