1 /*
2  * Copyright (c) 2013 Rob Clark <robdclark@gmail.com>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23 
24 #ifndef REGMASK_H_
25 #define REGMASK_H_
26 
27 #include <string.h>
28 #include "util/bitset.h"
29 
30 #define MAX_REG 256
31 
32 typedef BITSET_DECLARE(regmaskstate_t, 2 * MAX_REG);
33 
34 typedef struct {
35 	bool mergedregs;
36 	regmaskstate_t mask;
37 } regmask_t;
38 
39 static inline bool
__regmask_get(regmask_t * regmask,bool half,unsigned n)40 __regmask_get(regmask_t *regmask, bool half, unsigned n)
41 {
42 	if (regmask->mergedregs) {
43 		/* a6xx+ case, with merged register file, we track things in terms
44 		 * of half-precision registers, with a full precisions register
45 		 * using two half-precision slots:
46 		 */
47 		if (half) {
48 			return BITSET_TEST(regmask->mask, n);
49 		} else {
50 			n *= 2;
51 			return BITSET_TEST(regmask->mask, n) ||
52 				BITSET_TEST(regmask->mask, n+1);
53 		}
54 	} else {
55 		/* pre a6xx case, with separate register file for half and full
56 		 * precision:
57 		 */
58 		if (half)
59 			n += MAX_REG;
60 		return BITSET_TEST(regmask->mask, n);
61 	}
62 }
63 
64 static inline void
__regmask_set(regmask_t * regmask,bool half,unsigned n)65 __regmask_set(regmask_t *regmask, bool half, unsigned n)
66 {
67 	if (regmask->mergedregs) {
68 		/* a6xx+ case, with merged register file, we track things in terms
69 		 * of half-precision registers, with a full precisions register
70 		 * using two half-precision slots:
71 		 */
72 		if (half) {
73 			BITSET_SET(regmask->mask, n);
74 		} else {
75 			n *= 2;
76 			BITSET_SET(regmask->mask, n);
77 			BITSET_SET(regmask->mask, n+1);
78 		}
79 	} else {
80 		/* pre a6xx case, with separate register file for half and full
81 		 * precision:
82 		 */
83 		if (half)
84 			n += MAX_REG;
85 		BITSET_SET(regmask->mask, n);
86 	}
87 }
88 
89 static inline void
__regmask_clear(regmask_t * regmask,bool half,unsigned n)90 __regmask_clear(regmask_t *regmask, bool half, unsigned n)
91 {
92 	if (regmask->mergedregs) {
93 		/* a6xx+ case, with merged register file, we track things in terms
94 		 * of half-precision registers, with a full precisions register
95 		 * using two half-precision slots:
96 		 */
97 		if (half) {
98 			BITSET_CLEAR(regmask->mask, n);
99 		} else {
100 			n *= 2;
101 			BITSET_CLEAR(regmask->mask, n);
102 			BITSET_CLEAR(regmask->mask, n+1);
103 		}
104 	} else {
105 		/* pre a6xx case, with separate register file for half and full
106 		 * precision:
107 		 */
108 		if (half)
109 			n += MAX_REG;
110 		BITSET_CLEAR(regmask->mask, n);
111 	}
112 }
113 
114 static inline void
regmask_init(regmask_t * regmask,bool mergedregs)115 regmask_init(regmask_t *regmask, bool mergedregs)
116 {
117 	memset(&regmask->mask, 0, sizeof(regmask->mask));
118 	regmask->mergedregs = mergedregs;
119 }
120 
121 static inline void
regmask_or(regmask_t * dst,regmask_t * a,regmask_t * b)122 regmask_or(regmask_t *dst, regmask_t *a, regmask_t *b)
123 {
124 	assert(dst->mergedregs == a->mergedregs);
125 	assert(dst->mergedregs == b->mergedregs);
126 
127 	for (unsigned i = 0; i < ARRAY_SIZE(dst->mask); i++)
128 		dst->mask[i] = a->mask[i] | b->mask[i];
129 }
130 
131 #endif /* REGMASK_H_ */
132