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_instruction_fetch.h"
28
29#include "gallium/drivers/r600/r600_pipe.h"
30
31namespace r600 {
32
33/* refactor this to add status create methods for specific tasks */
34FetchInstruction::FetchInstruction(EVFetchInstr op,
35                                   EVFetchType type,
36                                   GPRVector dst,
37                                   PValue src, int offset,
38                                   int buffer_id, PValue buffer_offset,
39                                   EBufferIndexMode cp_rel,
40                                   bool use_const_field):
41   Instruction(vtx),
42   m_vc_opcode(op),
43   m_fetch_type(type),
44   m_endian_swap(vtx_es_none),
45   m_src(src),
46   m_dst(dst),
47   m_offset(offset),
48   m_is_mega_fetch(1),
49   m_mega_fetch_count(16),
50   m_buffer_id(buffer_id),
51   m_semantic_id(0),
52   m_buffer_index_mode(cp_rel),
53   m_flags(0),
54   m_uncached(false),
55   m_indexed(false),
56   m_array_base(0),
57   m_array_size(0),
58   m_elm_size(0),
59   m_buffer_offset(buffer_offset),
60   m_dest_swizzle({0,1,2,3})
61{
62   if (use_const_field) {
63      m_flags.set(vtx_use_const_field);
64      m_data_format = fmt_invalid;
65      m_num_format = vtx_nf_norm;
66   } else {
67      m_flags.set(vtx_format_comp_signed);
68      m_data_format = fmt_32_32_32_32_float;
69      m_num_format = vtx_nf_scaled;
70   }
71
72   add_remappable_src_value(&m_src);
73   add_remappable_src_value(&m_buffer_offset);
74
75   add_remappable_dst_value(&m_dst);
76}
77
78/* Resource query */
79FetchInstruction::FetchInstruction(EVFetchInstr vc_opcode,
80                                   EVFetchType fetch_type,
81                                   EVTXDataFormat data_format,
82                                   EVFetchNumFormat num_format,
83                                   EVFetchEndianSwap endian_swap,
84                                   const PValue src,
85                                   const GPRVector dst,
86                                   uint32_t offset,
87                                   bool is_mega_fetch,
88                                   uint32_t mega_fetch_count,
89                                   uint32_t buffer_id,
90                                   uint32_t semantic_id,
91
92                                   EBufferIndexMode buffer_index_mode,
93                                   bool uncached,
94                                   bool indexed,
95                                   int array_base,
96                                   int array_size,
97                                   int elm_size,
98                                   PValue buffer_offset,
99                                   const std::array<int, 4>& dest_swizzle):
100   Instruction(vtx),
101   m_vc_opcode(vc_opcode),
102   m_fetch_type(fetch_type),
103   m_data_format(data_format),
104   m_num_format(num_format),
105   m_endian_swap(endian_swap),
106   m_src(src),
107   m_dst(dst),
108   m_offset(offset),
109   m_is_mega_fetch(is_mega_fetch),
110   m_mega_fetch_count(mega_fetch_count),
111   m_buffer_id(buffer_id),
112   m_semantic_id(semantic_id),
113   m_buffer_index_mode(buffer_index_mode),
114   m_uncached(uncached),
115   m_indexed(indexed),
116   m_array_base(array_base),
117   m_array_size(array_size),
118   m_elm_size(elm_size),
119   m_buffer_offset(buffer_offset),
120   m_dest_swizzle(dest_swizzle)
121{
122   add_remappable_src_value(&m_src);
123   add_remappable_dst_value(&m_dst);
124   add_remappable_src_value(&m_buffer_offset);
125}
126
127FetchInstruction::FetchInstruction(GPRVector dst,
128                                   PValue src,
129                                   int buffer_id, PValue buffer_offset,
130                                   EVTXDataFormat format,
131                                   EVFetchNumFormat num_format):
132   Instruction(vtx),
133   m_vc_opcode(vc_fetch),
134   m_fetch_type(no_index_offset),
135   m_data_format(format),
136   m_num_format(num_format),
137   m_endian_swap(vtx_es_none),
138   m_src(src),
139   m_dst(dst),
140   m_offset(0),
141   m_is_mega_fetch(0),
142   m_mega_fetch_count(0),
143   m_buffer_id(buffer_id),
144   m_semantic_id(0),
145   m_buffer_index_mode(bim_none),
146   m_flags(0),
147   m_uncached(false),
148   m_indexed(false),
149   m_array_base(0),
150   m_array_size(0),
151   m_elm_size(1),
152   m_buffer_offset(buffer_offset),
153   m_dest_swizzle({0,1,2,3})
154{
155   m_flags.set(vtx_format_comp_signed);
156
157   add_remappable_src_value(&m_src);
158   add_remappable_dst_value(&m_dst);
159   add_remappable_src_value(&m_buffer_offset);
160}
161
162
163/* Resource query */
164FetchInstruction::FetchInstruction(GPRVector dst,
165                                   PValue src,
166                                   int buffer_id,
167                                   EBufferIndexMode cp_rel):
168   Instruction(vtx),
169   m_vc_opcode(vc_get_buf_resinfo),
170   m_fetch_type(no_index_offset),
171   m_data_format(fmt_32_32_32_32),
172   m_num_format(vtx_nf_norm),
173   m_endian_swap(vtx_es_none),
174   m_src(src),
175   m_dst(dst),
176   m_offset(0),
177   m_is_mega_fetch(0),
178   m_mega_fetch_count(16),
179   m_buffer_id(buffer_id),
180   m_semantic_id(0),
181   m_buffer_index_mode(cp_rel),
182   m_flags(0),
183   m_uncached(false),
184   m_indexed(false),
185   m_array_base(0),
186   m_array_size(0),
187   m_elm_size(0),
188   m_dest_swizzle({0,1,2,3})
189{
190   m_flags.set(vtx_format_comp_signed);
191   add_remappable_src_value(&m_src);
192   add_remappable_dst_value(&m_dst);
193   add_remappable_src_value(&m_buffer_offset);
194}
195
196FetchInstruction::FetchInstruction(GPRVector dst, PValue src, int scratch_size):
197   Instruction(vtx),
198   m_vc_opcode(vc_read_scratch),
199   m_fetch_type(vertex_data),
200   m_data_format(fmt_32_32_32_32),
201   m_num_format(vtx_nf_int),
202   m_endian_swap(vtx_es_none),
203   m_dst(dst),
204   m_offset(0),
205   m_is_mega_fetch(0),
206   m_mega_fetch_count(16),
207   m_buffer_id(0),
208   m_semantic_id(0),
209   m_buffer_index_mode(bim_none),
210   m_flags(0),
211   m_uncached(true),
212   m_array_base(0),
213   m_array_size(0),
214   m_elm_size(3),
215   m_dest_swizzle({0,1,2,3})
216{
217   if (src->type() == Value::literal) {
218      const auto& lv = static_cast<const LiteralValue&>(*src);
219      m_array_base = lv.value();
220      m_indexed = false;
221      m_src.reset(new GPRValue(0,0));
222      m_array_size = 0;
223   } else {
224      m_array_base = 0;
225      m_src = src;
226      m_indexed = true;
227      m_array_size = scratch_size - 1;
228   }
229   add_remappable_src_value(&m_src);
230   add_remappable_dst_value(&m_dst);
231   add_remappable_src_value(&m_buffer_offset);
232}
233
234void FetchInstruction::replace_values(const ValueSet& candidates, PValue new_value)
235{
236   if (!m_src)
237      return;
238   for (auto c: candidates) {
239      for (int i = 0; i < 4; ++i) {
240         if (*c == *m_dst.reg_i(i))
241            m_dst.set_reg_i(i, new_value);
242      }
243      if (*m_src == *c)
244         m_src = new_value;
245   }
246}
247
248
249bool FetchInstruction::is_equal_to(const Instruction& lhs) const
250{
251   auto& l = static_cast<const FetchInstruction&>(lhs);
252   if (m_src) {
253      if (!l.m_src)
254         return false;
255      if (*m_src != *l.m_src)
256         return false;
257   } else {
258      if (l.m_src)
259         return false;
260   }
261
262   return m_vc_opcode == l.m_vc_opcode &&
263         m_fetch_type == l.m_fetch_type &&
264         m_data_format == l.m_data_format &&
265         m_num_format == l.m_num_format &&
266         m_endian_swap == l.m_endian_swap &&
267         m_dst == l.m_dst &&
268         m_offset == l.m_offset &&
269         m_buffer_id == l.m_buffer_id &&
270         m_semantic_id == l.m_semantic_id &&
271         m_buffer_index_mode == l.m_buffer_index_mode &&
272         m_flags == l.m_flags &&
273         m_indexed == l.m_indexed &&
274         m_uncached == l.m_uncached;
275}
276
277void FetchInstruction::set_format(EVTXDataFormat fmt)
278{
279   m_data_format = fmt;
280}
281
282
283void FetchInstruction::set_dest_swizzle(const std::array<int,4>& swz)
284{
285   m_dest_swizzle = swz;
286}
287
288void FetchInstruction::prelude_append(Instruction *instr)
289{
290   assert(instr);
291   m_prelude.push_back(PInstruction(instr));
292}
293
294const std::vector<PInstruction>& FetchInstruction::prelude() const
295{
296   return m_prelude;
297}
298
299LoadFromScratch::LoadFromScratch(GPRVector dst, PValue src, int scratch_size):
300   FetchInstruction(dst, src, scratch_size)
301{
302}
303
304FetchGDSOpResult::FetchGDSOpResult(const GPRVector dst, const PValue src):
305   FetchInstruction(vc_fetch,
306                    no_index_offset,
307                    fmt_32,
308                    vtx_nf_int,
309                    vtx_es_none,
310                    src,
311                    dst,
312                    0,
313                    false,
314                    0xf,
315                    R600_IMAGE_IMMED_RESOURCE_OFFSET,
316                    0,
317                    bim_none,
318                    false,
319                    false,
320                    0,
321                    0,
322                    0,
323                    PValue(),
324                    {0,7,7,7})
325{
326   set_flag(vtx_srf_mode);
327   set_flag(vtx_vpm);
328}
329
330FetchTCSIOParam::FetchTCSIOParam(GPRVector dst, PValue src, int offset):
331   FetchInstruction(vc_fetch,
332                    no_index_offset,
333                    fmt_32_32_32_32,
334                    vtx_nf_scaled,
335                    vtx_es_none,
336                    src,
337                    dst,
338                    offset,
339                    false,
340                    16,
341                    R600_LDS_INFO_CONST_BUFFER,
342                    0,
343                    bim_none,
344                    false,
345                    false,
346                    0,
347                    0,
348                    0,
349                    PValue(),
350                    {0,1,2,3})
351{
352   set_flag(vtx_srf_mode);
353   set_flag(vtx_format_comp_signed);
354}
355
356
357static const char *fmt_descr[64] = {
358   "INVALID",
359   "8",
360   "4_4",
361   "3_3_2",
362   "RESERVED_4",
363   "16",
364   "16F",
365   "8_8",
366   "5_6_5",
367   "6_5_5",
368   "1_5_5_5",
369   "4_4_4_4",
370   "5_5_5_1",
371   "32",
372   "32F",
373   "16_16",
374   "16_16F",
375   "8_24",
376   "8_24F",
377   "24_8",
378   "24_8F",
379   "10_11_11",
380   "10_11_11F",
381   "11_11_10",
382   "11_11_10F",
383   "2_10_10_10",
384   "8_8_8_8",
385   "10_10_10_2",
386   "X24_8_32F",
387   "32_32",
388   "32_32F",
389   "16_16_16_16",
390   "16_16_16_16F",
391   "RESERVED_33",
392   "32_32_32_32",
393   "32_32_32_32F",
394   "RESERVED_36",
395   "1",
396   "1_REVERSED",
397   "GB_GR",
398   "BG_RG",
399   "32_AS_8",
400   "32_AS_8_8",
401   "5_9_9_9_SHAREDEXP",
402   "8_8_8",
403   "16_16_16",
404   "16_16_16F",
405   "32_32_32",
406   "32_32_32F",
407   "BC1",
408   "BC2",
409   "BC3",
410   "BC4",
411   "BC5",
412   "APC0",
413   "APC1",
414   "APC2",
415   "APC3",
416   "APC4",
417   "APC5",
418   "APC6",
419   "APC7",
420   "CTX1",
421   "RESERVED_63"
422};
423
424
425void FetchInstruction::do_print(std::ostream& os) const
426{
427   static const std::string num_format_char[] = {"norm", "int", "scaled"};
428   static const std::string endian_swap_code[] = {
429      "noswap", "8in16", "8in32"
430   };
431   static const char buffer_index_mode_char[] = "_01E";
432   static const char *flag_string[] = {"WQM",  "CF", "signed", "no_zero",
433                                       "nostride", "AC", "TC", "VPM"};
434   switch (m_vc_opcode) {
435   case vc_fetch:
436      os << "Fetch " << m_dst;
437      break;
438   case vc_semantic:
439      os << "Fetch Semantic ID:" << m_semantic_id;
440      break;
441   case vc_get_buf_resinfo:
442      os << "Fetch BufResinfo:" << m_dst;
443      break;
444   case vc_read_scratch:
445      os << "MEM_READ_SCRATCH:" << m_dst;
446      break;
447   default:
448      os << "Fetch ERROR";
449      return;
450   }
451
452   os << ", " << *m_src;
453
454   if (m_offset)
455      os << "+" << m_offset;
456
457   os << " BUFID:" << m_buffer_id
458      << " FMT:(" << fmt_descr[m_data_format]
459      << " " << num_format_char[m_num_format]
460      << " " << endian_swap_code[m_endian_swap]
461      << ")";
462   if (m_buffer_index_mode > 0)
463      os << " IndexMode:" << buffer_index_mode_char[m_buffer_index_mode];
464
465
466   if (m_is_mega_fetch)
467      os << " MFC:" << m_mega_fetch_count;
468   else
469      os << " mfc*:" << m_mega_fetch_count;
470
471   if (m_flags.any()) {
472      os << " Flags:";
473      for( int i = 0; i < vtx_unknown; ++i) {
474         if (m_flags.test(i))
475            os << ' ' << flag_string[i];
476      }
477   }
478}
479
480}
481