1 /*
2 * Copyright © 2022 Collabora Ltd.
3 * SPDX-License-Identifier: MIT
4 */
5 #ifndef MME_VALUE_H
6 #define MME_VALUE_H
7
8 #include <stdbool.h>
9 #include <stdint.h>
10
11 #include "util/bitscan.h"
12 #include "util/macros.h"
13
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17
18 enum mme_value_type {
19 /* This must be zero, making a zero-initizlied mme_value a ZERO */
20 MME_VALUE_TYPE_ZERO = 0,
21 MME_VALUE_TYPE_IMM,
22 MME_VALUE_TYPE_REG,
23 };
24
25 struct mme_value {
26 enum mme_value_type type;
27
28 union {
29 uint32_t imm;
30 uint32_t reg;
31 };
32 };
33
34 struct mme_value64 {
35 struct mme_value lo;
36 struct mme_value hi;
37 };
38
39 static inline struct mme_value
mme_zero()40 mme_zero()
41 {
42 struct mme_value val = {
43 .type = MME_VALUE_TYPE_ZERO,
44 };
45 return val;
46 }
47
48 static inline struct mme_value
mme_imm(uint32_t imm)49 mme_imm(uint32_t imm)
50 {
51 struct mme_value val = {
52 .type = MME_VALUE_TYPE_IMM,
53 .imm = imm,
54 };
55 return val;
56 }
57
58 static inline bool
mme_is_zero(struct mme_value x)59 mme_is_zero(struct mme_value x)
60 {
61 switch (x.type) {
62 case MME_VALUE_TYPE_ZERO: return true;
63 case MME_VALUE_TYPE_IMM: return x.imm == 0;
64 case MME_VALUE_TYPE_REG: return false;
65 default: unreachable("Invalid MME value type");
66 }
67 }
68
69 static inline struct mme_value64
mme_value64(struct mme_value lo,struct mme_value hi)70 mme_value64(struct mme_value lo, struct mme_value hi)
71 {
72 struct mme_value64 val = { lo, hi };
73 return val;
74 }
75
76 static inline struct mme_value64
mme_imm64(uint64_t imm)77 mme_imm64(uint64_t imm)
78 {
79 struct mme_value64 val = {
80 mme_imm((uint32_t)imm),
81 mme_imm((uint32_t)(imm >> 32)),
82 };
83 return val;
84 }
85
86 struct mme_reg_alloc {
87 uint32_t exists;
88 uint32_t alloc;
89 };
90
91 static inline void
mme_reg_alloc_init(struct mme_reg_alloc * a,uint32_t exists)92 mme_reg_alloc_init(struct mme_reg_alloc *a, uint32_t exists)
93 {
94 a->alloc = 0;
95 a->exists = exists;
96 }
97
98 static inline struct mme_value
mme_reg_alloc_alloc(struct mme_reg_alloc * a)99 mme_reg_alloc_alloc(struct mme_reg_alloc *a)
100 {
101 uint8_t reg = ffs(~a->alloc & a->exists) - 1;
102 assert(reg < 32);
103 assert(a->exists & (1u << reg));
104
105 a->alloc |= (1u << reg);
106
107 struct mme_value val = {
108 .type = MME_VALUE_TYPE_REG,
109 .reg = reg,
110 };
111
112 return val;
113 }
114
115 static inline void
mme_reg_alloc_realloc(struct mme_reg_alloc * a,struct mme_value val)116 mme_reg_alloc_realloc(struct mme_reg_alloc *a, struct mme_value val)
117 {
118 assert(val.type == MME_VALUE_TYPE_REG);
119
120 assert(val.reg < 32);
121 assert(a->exists & (1u << val.reg));
122 assert(!(a->alloc & (1u << val.reg)));
123
124 a->alloc |= (1u << val.reg);
125 }
126
127 static inline void
mme_reg_alloc_free(struct mme_reg_alloc * a,struct mme_value val)128 mme_reg_alloc_free(struct mme_reg_alloc *a, struct mme_value val)
129 {
130 assert(val.type == MME_VALUE_TYPE_REG);
131
132 assert(val.reg < 32);
133 assert(a->exists & (1u << val.reg));
134 assert(a->alloc & (1u << val.reg));
135
136 a->alloc &= ~(1u << val.reg);
137 }
138
139 #ifdef __cplusplus
140 }
141 #endif
142
143 #endif /* MME_VALUE_H */
144