1/* -*- mesa-c++  -*-
2 *
3 * Copyright (c) 2018 Collabora LTD
4 *
5 * Author: Gert Wollny <gert.wollny@collabora.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * on the rights to use, copy, modify, merge, publish, distribute, sub
11 * license, and/or sell copies of the Software, and to permit persons to whom
12 * the Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27#include "sfn_value.h"
28#include "util/macros.h"
29
30#include <iostream>
31#include <iomanip>
32#include <cassert>
33
34namespace r600 {
35
36using std::unique_ptr;
37using std::make_shared;
38
39const char *Value::component_names = "xyzw01?_!";
40
41Value::Value():
42   m_type(gpr),
43   m_chan(0)
44{
45}
46
47Value::Value(Type type, uint32_t chan):
48   m_type(type),
49   m_chan(chan)
50{
51
52}
53
54
55
56Value::Value(Type type):
57   Value(type, 0)
58{
59}
60
61Value::Type Value::type() const
62{
63   return m_type;
64}
65
66void Value::set_chan(uint32_t chan)
67{
68   m_chan = chan;
69}
70
71void Value::print(std::ostream& os) const
72{
73   do_print(os);
74}
75
76void Value::print(std::ostream& os, const PrintFlags& flags) const
77{
78   if (flags.flags & PrintFlags::has_neg) os << '-';
79   if (flags.flags & PrintFlags::has_abs) os << '|';
80   do_print(os, flags);
81   if (flags.flags & PrintFlags::has_abs) os << '|';
82}
83
84void Value::do_print(std::ostream& os, const PrintFlags& flags) const
85{
86   (void)flags;
87   do_print(os);
88}
89
90bool Value::operator < (const Value& lhs) const
91{
92   return sel() < lhs.sel() ||
93         (sel() == lhs.sel() && chan() < lhs.chan());
94}
95
96
97LiteralValue::LiteralValue(float value, uint32_t chan):
98   Value(Value::literal, chan)
99{
100   m_value.f=value;
101}
102
103
104LiteralValue::LiteralValue(uint32_t value, uint32_t chan):
105   Value(Value::literal, chan)
106{
107   m_value.u=value;
108}
109
110LiteralValue::LiteralValue(int value, uint32_t chan):
111   Value(Value::literal, chan)
112{
113   m_value.u=value;
114}
115
116uint32_t LiteralValue::sel() const
117{
118   return ALU_SRC_LITERAL;
119}
120
121uint32_t LiteralValue::value() const
122{
123   return m_value.u;
124}
125
126float LiteralValue::value_float() const
127{
128   return m_value.f;
129}
130
131void LiteralValue::do_print(std::ostream& os) const
132{
133   os << "[0x" << std::setbase(16) << m_value.u << " " << std::setbase(10)
134      << m_value.f << "].";
135   os << component_names[chan()];
136}
137
138void LiteralValue::do_print(std::ostream& os, UNUSED const PrintFlags& flags) const
139{
140   os << "[0x" << std::setbase(16) << m_value.u << " "
141      << std::setbase(10);
142
143   os << m_value.f << "f";
144
145   os<< "]";
146}
147
148bool LiteralValue::is_equal_to(const Value& other) const
149{
150   assert(other.type() == Value::Type::literal);
151   const auto& rhs = static_cast<const LiteralValue&>(other);
152   return (sel() == rhs.sel() &&
153           value() == rhs.value());
154}
155
156InlineConstValue::InlineConstValue(int value, int chan):
157   Value(Value::cinline,  chan),
158   m_value(static_cast<AluInlineConstants>(value))
159{
160}
161
162uint32_t InlineConstValue::sel() const
163{
164   return m_value;
165}
166
167void InlineConstValue::do_print(std::ostream& os) const
168{
169   auto sv_info = alu_src_const.find(m_value);
170   if (sv_info != alu_src_const.end()) {
171      os << sv_info->second.descr;
172      if (sv_info->second.use_chan)
173         os << '.' << component_names[chan()];
174      else if (chan() > 0)
175         os << "." << component_names[chan()]
176            << " (W: Channel ignored)";
177   } else {
178      if (m_value >= ALU_SRC_PARAM_BASE && m_value < ALU_SRC_PARAM_BASE + 32)
179         os << " Param" << m_value - ALU_SRC_PARAM_BASE;
180      else
181         os << " E: unknown inline constant " << m_value;
182   }
183}
184
185bool InlineConstValue::is_equal_to(const Value& other) const
186{
187   assert(other.type() == Value::Type::cinline);
188   const auto& rhs = static_cast<const InlineConstValue&>(other);
189   return sel() == rhs.sel();
190}
191
192PValue Value::zero(new InlineConstValue(ALU_SRC_0, 0));
193PValue Value::one_f(new InlineConstValue(ALU_SRC_1, 0));
194PValue Value::one_i(new InlineConstValue(ALU_SRC_1_INT, 0));
195PValue Value::zero_dot_5(new InlineConstValue(ALU_SRC_0_5, 0));
196
197UniformValue::UniformValue(uint32_t sel, uint32_t chan, uint32_t kcache_bank):
198   Value(Value::kconst, chan)
199{
200   m_index = sel;
201   m_kcache_bank = kcache_bank;
202}
203
204UniformValue::UniformValue(uint32_t sel, uint32_t chan, PValue addr):
205   Value(Value::kconst, chan),
206   m_index(sel),
207   m_kcache_bank(1),
208   m_addr(addr)
209{
210
211}
212
213uint32_t UniformValue::sel() const
214{
215   const int bank_base[4] = {128, 160, 256, 288};
216   return m_index < 512 ? m_index + bank_base[m_kcache_bank] : m_index;
217}
218
219uint32_t UniformValue::kcache_bank() const
220{
221   return m_kcache_bank;
222}
223
224bool UniformValue::is_equal_to(const Value& other) const
225{
226   const UniformValue& o = static_cast<const UniformValue&>(other);
227   return sel()  == o.sel() &&
228         m_kcache_bank == o.kcache_bank();
229}
230
231void UniformValue::do_print(std::ostream& os) const
232{
233   if (m_index < 512)
234      os << "KC" << m_kcache_bank << "[" << m_index;
235   else if (m_addr)
236      os << "KC[" << *m_addr << "][" << m_index;
237   else
238      os << "KCx[" << m_index;
239   os << "]." << component_names[chan()];
240}
241
242}
243