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 
31 namespace r600 {
32 
33 /* refactor this to add status create methods for specific tasks */
FetchInstruction(EVFetchInstr op,EVFetchType type,GPRVector dst,PValue src,int offset,int buffer_id,PValue buffer_offset,EBufferIndexMode cp_rel,bool use_const_field)34 FetchInstruction::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 */
FetchInstruction(EVFetchInstr vc_opcode,EVFetchType fetch_type,EVTXDataFormat data_format,EVFetchNumFormat num_format,EVFetchEndianSwap endian_swap,const PValue src,const GPRVector dst,uint32_t offset,bool is_mega_fetch,uint32_t mega_fetch_count,uint32_t buffer_id,uint32_t semantic_id,EBufferIndexMode buffer_index_mode,bool uncached,bool indexed,int array_base,int array_size,int elm_size,PValue buffer_offset,const std::array<int,4> & dest_swizzle)79 FetchInstruction::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 
FetchInstruction(GPRVector dst,PValue src,int buffer_id,PValue buffer_offset,EVTXDataFormat format,EVFetchNumFormat num_format)127 FetchInstruction::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 */
FetchInstruction(GPRVector dst,PValue src,int buffer_id,EBufferIndexMode cp_rel)164 FetchInstruction::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 
FetchInstruction(GPRVector dst,PValue src,int scratch_size)196 FetchInstruction::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 
replace_values(const ValueSet & candidates,PValue new_value)234 void 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 
is_equal_to(const Instruction & lhs) const249 bool 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 
set_format(EVTXDataFormat fmt)277 void FetchInstruction::set_format(EVTXDataFormat fmt)
278 {
279    m_data_format = fmt;
280 }
281 
282 
set_dest_swizzle(const std::array<int,4> & swz)283 void FetchInstruction::set_dest_swizzle(const std::array<int,4>& swz)
284 {
285    m_dest_swizzle = swz;
286 }
287 
prelude_append(Instruction * instr)288 void FetchInstruction::prelude_append(Instruction *instr)
289 {
290    assert(instr);
291    m_prelude.push_back(PInstruction(instr));
292 }
293 
prelude() const294 const std::vector<PInstruction>& FetchInstruction::prelude() const
295 {
296    return m_prelude;
297 }
298 
LoadFromScratch(GPRVector dst,PValue src,int scratch_size)299 LoadFromScratch::LoadFromScratch(GPRVector dst, PValue src, int scratch_size):
300    FetchInstruction(dst, src, scratch_size)
301 {
302 }
303 
FetchGDSOpResult(const GPRVector dst,const PValue src)304 FetchGDSOpResult::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 
FetchTCSIOParam(GPRVector dst,PValue src,int offset)330 FetchTCSIOParam::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 
357 static 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 
do_print(std::ostream & os) const425 void 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