ext: Fix undefined-behavior bug in bitshift
[gem5.git] / ext / nomali / lib / types.hh
1 /*
2 * Copyright (c) 2014-2015 ARM Limited
3 * All rights reserved
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * Authors: Andreas Sandberg
18 */
19
20 #ifndef _LIBNOMALIMODEL_TYPES_HH
21 #define _LIBNOMALIMODEL_TYPES_HH
22
23 #include <cassert>
24 #include <cstdint>
25
26 #include <utility>
27 #include <vector>
28
29 namespace NoMali{
30
31 /**
32 * @{
33 * @name Register handling utilities
34 */
35
36 /**
37 * Register address wrapper
38 *
39 * This class wraps a register address. Unlike a simple typedef, this
40 * provides safety from automatic type conversions from other integer
41 * types since the constructor must be called explicitly.
42 */
43 struct RegAddr {
44 explicit RegAddr(uint32_t v)
45 : value(v) {}
46
47 const uint32_t value;
48 };
49
50 inline bool
51 operator<(const RegAddr &lhs, const RegAddr &rhs) {
52 return lhs.value < rhs.value;
53 }
54
55 inline bool
56 operator>(const RegAddr &lhs, const RegAddr &rhs) {
57 return lhs.value > rhs.value;
58 }
59
60 inline bool
61 operator<=(const RegAddr &lhs, const RegAddr &rhs) {
62 return lhs.value <= rhs.value;
63 }
64
65 inline bool
66 operator>=(const RegAddr &lhs, const RegAddr &rhs) {
67 return lhs.value >= rhs.value;
68 }
69
70 inline bool
71 operator==(const RegAddr &lhs, const RegAddr &rhs) {
72 return lhs.value == rhs.value;
73 }
74
75 inline bool
76 operator!=(const RegAddr &lhs, const RegAddr &rhs) {
77 return lhs.value != rhs.value;
78 }
79
80 inline RegAddr
81 operator+(const RegAddr &lhs, const RegAddr &rhs) {
82 return RegAddr(lhs.value + rhs.value);
83 }
84
85 inline RegAddr
86 operator-(const RegAddr &lhs, const RegAddr &rhs) {
87 assert(lhs >= rhs);
88 return RegAddr(lhs.value - rhs.value);
89 }
90
91 /**
92 * Class for register storage
93 *
94 * This class wraps a std::vector and implements a subset of its
95 * functionality. Specifically, it is constant size and prevents
96 * indexing with anything other than RegAddr instances.
97 */
98 class RegVector
99 {
100 private:
101 typedef std::vector<uint32_t> vector_t;
102
103 public:
104 typedef vector_t::iterator iterator;
105 typedef vector_t::const_iterator const_iterator;
106 typedef vector_t::size_type size_type;
107
108 public:
109 RegVector(size_type size)
110 : vector(size, 0) {}
111
112 /** @{ */
113 /**
114 * Helper function to get a 64-bit register.
115 *
116 * @param addr Address to the low part of the register.
117 * @return 64-bit value representing the concatenation of the HI
118 * and LO parts of the register.
119 */
120 const uint32_t get64(const RegAddr &addr) const {
121 const unsigned idx_lo = index(addr);
122 const unsigned idx_hi = idx_lo + 1;
123 return (((uint64_t)vector[idx_hi]) << 32) | vector[idx_lo];
124 }
125
126 /**
127 * Helper function to set a 64-bit register.
128 *
129 * @param addr Address to the low part of the register.
130 * @param value Value to write into the 64-bit register.
131 */
132 void set64(const RegAddr &addr, uint64_t value) {
133 const unsigned idx_lo = index(addr);
134 const unsigned idx_hi = idx_lo + 1;
135 vector[idx_lo] = value & 0xFFFFFFFF;
136 vector[idx_hi] = (value >> 32) & 0xFFFFFFFF;
137 }
138
139 const uint32_t &operator[](const RegAddr &addr) const {
140 return vector[index(addr)];
141 }
142
143 uint32_t &operator[](const RegAddr &addr) {
144 return vector[index(addr)];
145 }
146
147
148 iterator begin() noexcept { return vector.begin(); }
149 const_iterator begin() const noexcept { return vector.begin(); }
150 const_iterator cbegin() const noexcept { return vector.cbegin(); }
151
152 iterator end() noexcept { return vector.end(); }
153 const_iterator end() const noexcept { return vector.end(); }
154 const_iterator cend() const noexcept { return vector.cend(); }
155
156 const size_type size() const noexcept { return vector.size(); }
157
158 private:
159 // Disable default constructor
160 RegVector();
161
162 static uint32_t index(const RegAddr &addr) {
163 assert((addr.value & 0x3) == 0);
164 return addr.value >> 2;
165 }
166
167
168 vector_t vector;
169 };
170 /** @} */
171
172 /**
173 * Class representing the status codes in the Midgard architecture.
174 */
175 struct Status {
176 /**
177 * Class representing the subsystem a status code originates from.
178 */
179 enum StatusClass {
180 CLASS_NOFAULT = 0,
181 CLASS_JOB = 1,
182 CLASS_GPU = 2,
183 CLASS_MMU = 3,
184 };
185
186 typedef uint8_t Code;
187 typedef uint8_t SubCode;
188
189 Status(StatusClass cls, Code code, SubCode subcode)
190 : value((cls << 6) | (code << 3) | subcode) {
191 assert((cls & ~0x3) == 0);
192 assert((code & ~0x7) == 0);
193 assert((subcode & ~0x7) == 0);
194 }
195
196 explicit Status(uint8_t v)
197 : value(v) {}
198
199 StatusClass statusClass() const {
200 return (StatusClass)((value >> 6) & 0x3);
201 }
202
203 Code code() const {
204 return (value >> 3) & 0x7;
205 }
206
207 SubCode subCode() const {
208 return value & 0x7;
209 }
210
211 const uint8_t value;
212 };
213
214
215 }
216
217 #endif
218