• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2010 Intel Corporation
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include <inttypes.h>
7 
8 #include "brw_reg.h"
9 #include "util/macros.h"
10 
11 bool
brw_reg_saturate_immediate(brw_reg * reg)12 brw_reg_saturate_immediate(brw_reg *reg)
13 {
14    union {
15       unsigned ud;
16       int d;
17       float f;
18       double df;
19    } imm, sat_imm = { 0 };
20 
21    const unsigned size = brw_type_size_bytes(reg->type);
22 
23    /* We want to either do a 32-bit or 64-bit data copy, the type is otherwise
24     * irrelevant, so just check the size of the type and copy from/to an
25     * appropriately sized field.
26     */
27    if (size < 8)
28       imm.ud = reg->ud;
29    else
30       imm.df = reg->df;
31 
32    switch (reg->type) {
33    case BRW_TYPE_UD:
34    case BRW_TYPE_D:
35    case BRW_TYPE_UW:
36    case BRW_TYPE_W:
37    case BRW_TYPE_UQ:
38    case BRW_TYPE_Q:
39       /* Nothing to do. */
40       return false;
41    case BRW_TYPE_F:
42       sat_imm.f = SATURATE(imm.f);
43       break;
44    case BRW_TYPE_DF:
45       sat_imm.df = SATURATE(imm.df);
46       break;
47    case BRW_TYPE_UB:
48    case BRW_TYPE_B:
49       unreachable("no UB/B immediates");
50    case BRW_TYPE_V:
51    case BRW_TYPE_UV:
52    case BRW_TYPE_VF:
53       unreachable("unimplemented: saturate vector immediate");
54    case BRW_TYPE_HF:
55       unreachable("unimplemented: saturate HF immediate");
56    default:
57       unreachable("invalid type");
58    }
59 
60    if (size < 8) {
61       if (imm.ud != sat_imm.ud) {
62          reg->ud = sat_imm.ud;
63          return true;
64       }
65    } else {
66       if (imm.df != sat_imm.df) {
67          reg->df = sat_imm.df;
68          return true;
69       }
70    }
71    return false;
72 }
73 
74 bool
brw_reg_negate_immediate(brw_reg * reg)75 brw_reg_negate_immediate(brw_reg *reg)
76 {
77    switch (reg->type) {
78    case BRW_TYPE_D:
79    case BRW_TYPE_UD:
80       reg->d = -reg->d;
81       return true;
82    case BRW_TYPE_W:
83    case BRW_TYPE_UW: {
84       uint16_t value = -(int16_t)reg->ud;
85       reg->ud = value | (uint32_t)value << 16;
86       return true;
87    }
88    case BRW_TYPE_F:
89       reg->f = -reg->f;
90       return true;
91    case BRW_TYPE_VF:
92       reg->ud ^= 0x80808080;
93       return true;
94    case BRW_TYPE_DF:
95       reg->df = -reg->df;
96       return true;
97    case BRW_TYPE_UQ:
98    case BRW_TYPE_Q:
99       reg->d64 = -reg->d64;
100       return true;
101    case BRW_TYPE_UB:
102    case BRW_TYPE_B:
103       unreachable("no UB/B immediates");
104    case BRW_TYPE_UV:
105    case BRW_TYPE_V:
106       assert(!"unimplemented: negate UV/V immediate");
107    case BRW_TYPE_HF:
108       reg->ud ^= 0x80008000;
109       return true;
110    default:
111       unreachable("invalid type");
112    }
113 
114    return false;
115 }
116 
117 bool
brw_reg_abs_immediate(brw_reg * reg)118 brw_reg_abs_immediate(brw_reg *reg)
119 {
120    switch (reg->type) {
121    case BRW_TYPE_D:
122       reg->d = abs(reg->d);
123       return true;
124    case BRW_TYPE_W: {
125       uint16_t value = abs((int16_t)reg->ud);
126       reg->ud = value | (uint32_t)value << 16;
127       return true;
128    }
129    case BRW_TYPE_F:
130       reg->f = fabsf(reg->f);
131       return true;
132    case BRW_TYPE_DF:
133       reg->df = fabs(reg->df);
134       return true;
135    case BRW_TYPE_VF:
136       reg->ud &= ~0x80808080;
137       return true;
138    case BRW_TYPE_Q:
139       reg->d64 = imaxabs(reg->d64);
140       return true;
141    case BRW_TYPE_UB:
142    case BRW_TYPE_B:
143       unreachable("no UB/B immediates");
144    case BRW_TYPE_UQ:
145    case BRW_TYPE_UD:
146    case BRW_TYPE_UW:
147    case BRW_TYPE_UV:
148       /* Presumably the absolute value modifier on an unsigned source is a
149        * nop, but it would be nice to confirm.
150        */
151       assert(!"unimplemented: abs unsigned immediate");
152    case BRW_TYPE_V:
153       assert(!"unimplemented: abs V immediate");
154    case BRW_TYPE_HF:
155       reg->ud &= ~0x80008000;
156       return true;
157    default:
158       unreachable("invalid type");
159    }
160 
161    return false;
162 }
163 
164 bool
is_zero() const165 brw_reg::is_zero() const
166 {
167    if (file != IMM)
168       return false;
169 
170    assert(brw_type_size_bytes(type) > 1);
171 
172    switch (type) {
173    case BRW_TYPE_HF:
174       assert((d & 0xffff) == ((d >> 16) & 0xffff));
175       return (d & 0xffff) == 0 || (d & 0xffff) == 0x8000;
176    case BRW_TYPE_F:
177       return f == 0;
178    case BRW_TYPE_DF:
179       return df == 0;
180    case BRW_TYPE_W:
181    case BRW_TYPE_UW:
182       assert((d & 0xffff) == ((d >> 16) & 0xffff));
183       return (d & 0xffff) == 0;
184    case BRW_TYPE_D:
185    case BRW_TYPE_UD:
186       return d == 0;
187    case BRW_TYPE_UQ:
188    case BRW_TYPE_Q:
189       return u64 == 0;
190    default:
191       return false;
192    }
193 }
194 
195 bool
is_one() const196 brw_reg::is_one() const
197 {
198    if (file != IMM)
199       return false;
200 
201    assert(brw_type_size_bytes(type) > 1);
202 
203    switch (type) {
204    case BRW_TYPE_HF:
205       assert((d & 0xffff) == ((d >> 16) & 0xffff));
206       return (d & 0xffff) == 0x3c00;
207    case BRW_TYPE_F:
208       return f == 1.0f;
209    case BRW_TYPE_DF:
210       return df == 1.0;
211    case BRW_TYPE_W:
212    case BRW_TYPE_UW:
213       assert((d & 0xffff) == ((d >> 16) & 0xffff));
214       return (d & 0xffff) == 1;
215    case BRW_TYPE_D:
216    case BRW_TYPE_UD:
217       return d == 1;
218    case BRW_TYPE_UQ:
219    case BRW_TYPE_Q:
220       return u64 == 1;
221    default:
222       return false;
223    }
224 }
225 
226 bool
is_negative_one() const227 brw_reg::is_negative_one() const
228 {
229    if (file != IMM)
230       return false;
231 
232    assert(brw_type_size_bytes(type) > 1);
233 
234    switch (type) {
235    case BRW_TYPE_HF:
236       assert((d & 0xffff) == ((d >> 16) & 0xffff));
237       return (d & 0xffff) == 0xbc00;
238    case BRW_TYPE_F:
239       return f == -1.0;
240    case BRW_TYPE_DF:
241       return df == -1.0;
242    case BRW_TYPE_W:
243       assert((d & 0xffff) == ((d >> 16) & 0xffff));
244       return (d & 0xffff) == 0xffff;
245    case BRW_TYPE_D:
246       return d == -1;
247    case BRW_TYPE_Q:
248       return d64 == -1;
249    default:
250       return false;
251    }
252 }
253 
254 bool
is_null() const255 brw_reg::is_null() const
256 {
257    return file == ARF && nr == BRW_ARF_NULL;
258 }
259 
260 bool
is_accumulator() const261 brw_reg::is_accumulator() const
262 {
263    return file == ARF && (nr & 0xF0) == BRW_ARF_ACCUMULATOR;
264 }
265 
266 bool
is_address() const267 brw_reg::is_address() const
268 {
269    return file == ADDRESS;
270 }
271 
272 unsigned
address_slot(unsigned byte_offset) const273 brw_reg::address_slot(unsigned byte_offset) const
274 {
275    assert(is_address());
276    return (reg_offset(*this) + byte_offset) / 2;
277 }
278 
279 bool
equals(const brw_reg & r) const280 brw_reg::equals(const brw_reg &r) const
281 {
282    return brw_regs_equal(this, &r);
283 }
284 
285 bool
negative_equals(const brw_reg & r) const286 brw_reg::negative_equals(const brw_reg &r) const
287 {
288    return brw_regs_negative_equal(this, &r);
289 }
290 
291 bool
is_contiguous() const292 brw_reg::is_contiguous() const
293 {
294    switch (file) {
295    case ADDRESS:
296    case ARF:
297    case FIXED_GRF:
298       return hstride == BRW_HORIZONTAL_STRIDE_1 &&
299              vstride == width + hstride;
300    case VGRF:
301    case ATTR:
302       return stride == 1;
303    case UNIFORM:
304    case IMM:
305    case BAD_FILE:
306       return true;
307    }
308 
309    unreachable("Invalid register file");
310 }
311 
312 unsigned
component_size(unsigned width) const313 brw_reg::component_size(unsigned width) const
314 {
315    if (file == ADDRESS || file == ARF || file == FIXED_GRF) {
316       const unsigned w = MIN2(width, 1u << this->width);
317       const unsigned h = width >> this->width;
318       const unsigned vs = vstride ? 1 << (vstride - 1) : 0;
319       const unsigned hs = hstride ? 1 << (hstride - 1) : 0;
320       assert(w > 0);
321       /* Note this rounds up to next horizontal stride to be consistent with
322        * the VGRF case below.
323        */
324       return ((MAX2(1, h) - 1) * vs + MAX2(w * hs, 1)) * brw_type_size_bytes(type);
325    } else {
326       return MAX2(width * stride, 1) * brw_type_size_bytes(type);
327    }
328 }
329