2 * Copyright (c) 2013 Rob Clark <robdclark@gmail.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 #define PACKED __attribute__((__packed__))
48 /* no opc.. all category 1 are variants of mov */
107 OPC_MADSH_M16
= 3, /* should this be .s16? */
162 OPC_LDG
= 0, /* load-global */
165 OPC_STG
= 3, /* store-global */
178 OPC_ATOMIC_XCHG
= 18,
181 OPC_ATOMIC_CMPXCHG
= 21,
187 OPC_LDGB_TYPED_4D
= 27,
193 /* meta instructions (category -1): */
194 /* placeholder instr to mark shader inputs: */
197 /* The "fan-in" and "fan-out" instructions are used for keeping
198 * track of instructions that write to multiple dst registers
199 * (fan-out) like texture sample instructions, or read multiple
200 * consecutive scalar registers (fan-in) (bary.f, texture samp)
215 TYPE_S8
= 7, // XXX I assume?
218 static inline uint32_t type_size(type_t type
)
233 assert(0); /* invalid type */
238 static inline int type_float(type_t type
)
240 return (type
== TYPE_F32
) || (type
== TYPE_F16
);
243 static inline int type_uint(type_t type
)
245 return (type
== TYPE_U32
) || (type
== TYPE_U16
) || (type
== TYPE_U8
);
248 static inline int type_sint(type_t type
)
250 return (type
== TYPE_S32
) || (type
== TYPE_S16
) || (type
== TYPE_S8
);
253 typedef union PACKED
{
254 /* normal gpr or const src register: */
259 /* for immediate val: */
260 int32_t iim_val
: 11;
261 /* to make compiler happy: */
263 uint32_t dummy10
: 10;
264 uint32_t dummy11
: 11;
265 uint32_t dummy12
: 12;
266 uint32_t dummy13
: 13;
270 /* special registers: */
271 #define REG_A0 61 /* address register */
272 #define REG_P0 62 /* predicate register */
274 static inline int reg_special(reg_t reg
)
276 return (reg
.num
== REG_A0
) || (reg
.num
== REG_P0
);
279 typedef struct PACKED
{
284 uint32_t dummy1
: 16;
288 uint32_t dummy1
: 12;
301 uint32_t jmp_tgt
: 1;
303 uint32_t opc_cat
: 3;
306 typedef struct PACKED
{
309 /* for normal src register: */
312 /* at least low bit of pad must be zero or it will
313 * look like a address relative src
317 /* for address relative: */
320 uint32_t src_rel_c
: 1;
321 uint32_t src_rel
: 1;
322 uint32_t unknown
: 20;
336 uint32_t dst_type
: 3;
337 uint32_t dst_rel
: 1;
338 uint32_t src_type
: 3;
342 uint32_t pos_inf
: 1;
343 uint32_t must_be_0
: 2;
344 uint32_t jmp_tgt
: 1;
346 uint32_t opc_cat
: 3;
349 typedef struct PACKED
{
354 uint32_t must_be_zero1
: 2;
355 uint32_t src1_im
: 1; /* immediate */
356 uint32_t src1_neg
: 1; /* negate */
357 uint32_t src1_abs
: 1; /* absolute value */
361 uint32_t src1_c
: 1; /* relative-const */
362 uint32_t src1_rel
: 1; /* relative address */
363 uint32_t must_be_zero
: 1;
368 uint32_t src1_c
: 1; /* const */
376 uint32_t must_be_zero2
: 2;
377 uint32_t src2_im
: 1; /* immediate */
378 uint32_t src2_neg
: 1; /* negate */
379 uint32_t src2_abs
: 1; /* absolute value */
383 uint32_t src2_c
: 1; /* relative-const */
384 uint32_t src2_rel
: 1; /* relative address */
385 uint32_t must_be_zero
: 1;
390 uint32_t src2_c
: 1; /* const */
400 uint32_t ul
: 1; /* dunno */
401 uint32_t dst_half
: 1; /* or widen/narrow.. ie. dst hrN <-> rN */
405 uint32_t full
: 1; /* not half */
407 uint32_t jmp_tgt
: 1;
409 uint32_t opc_cat
: 3;
412 typedef struct PACKED
{
417 uint32_t must_be_zero1
: 2;
419 uint32_t src1_neg
: 1;
425 uint32_t src1_rel
: 1;
426 uint32_t must_be_zero
: 1;
439 uint32_t must_be_zero2
: 2;
441 uint32_t src2_neg
: 1;
442 uint32_t src3_neg
: 1;
447 uint32_t src3_rel
: 1;
448 uint32_t must_be_zero
: 1;
464 uint32_t dst_half
: 1; /* or widen/narrow.. ie. dst hrN <-> rN */
467 uint32_t jmp_tgt
: 1;
469 uint32_t opc_cat
: 3;
472 static inline bool instr_cat3_full(instr_cat3_t
*cat3
)
482 case OPC_SAD_S32
: // really??
489 typedef struct PACKED
{
494 uint32_t must_be_zero1
: 2;
495 uint32_t src_im
: 1; /* immediate */
496 uint32_t src_neg
: 1; /* negate */
497 uint32_t src_abs
: 1; /* absolute value */
501 uint32_t src_c
: 1; /* relative-const */
502 uint32_t src_rel
: 1; /* relative address */
503 uint32_t must_be_zero
: 1;
508 uint32_t src_c
: 1; /* const */
512 uint32_t dummy1
: 16; /* seem to be ignored */
520 uint32_t dst_half
: 1; /* or widen/narrow.. ie. dst hrN <-> rN */
521 uint32_t dummy2
: 5; /* seem to be ignored */
522 uint32_t full
: 1; /* not half */
524 uint32_t jmp_tgt
: 1;
526 uint32_t opc_cat
: 3;
529 typedef struct PACKED
{
534 uint32_t full
: 1; /* not half */
537 uint32_t dummy1
: 4; /* seem to be ignored */
543 uint32_t full
: 1; /* not half */
550 /* same in either case: */
551 // XXX I think, confirm this
553 uint32_t full
: 1; /* not half */
561 uint32_t wrmask
: 4; /* write-mask */
563 uint32_t dummy2
: 1; /* seems to be ignored */
568 uint32_t is_s2en
: 1;
573 uint32_t jmp_tgt
: 1;
575 uint32_t opc_cat
: 3;
578 /* dword0 encoding for src_off: [src1 + off], src2: */
579 typedef struct PACKED
{
581 uint32_t mustbe1
: 1;
584 uint32_t src1_im
: 1;
585 uint32_t src2_im
: 1;
592 /* dword0 encoding for !src_off: [src1], src2 */
593 typedef struct PACKED
{
595 uint32_t mustbe0
: 1;
597 uint32_t ignore0
: 8;
598 uint32_t src1_im
: 1;
599 uint32_t src2_im
: 1;
606 /* dword1 encoding for dst_off: */
607 typedef struct PACKED
{
611 /* note: there is some weird stuff going on where sometimes
612 * cat6->a.off is involved.. but that seems like a bug in
613 * the blob, since it is used even if !cat6->src_off
614 * It would make sense for there to be some more bits to
615 * bring us to 11 bits worth of offset, but not sure..
618 uint32_t mustbe1
: 1;
623 /* dword1 encoding for !dst_off: */
624 typedef struct PACKED
{
629 uint32_t mustbe0
: 1;
633 /* I think some of the other cat6 instructions use additional
637 typedef union PACKED
{
644 uint32_t src_off
: 1;
649 uint32_t dst_off
: 1;
652 uint32_t g
: 1; /* or in some cases it means dst immed */
655 uint32_t jmp_tgt
: 1;
657 uint32_t opc_cat
: 3;
661 typedef union PACKED
{
672 uint32_t repeat
: 3; /* cat0-cat4 */
674 uint32_t ss
: 1; /* cat1-cat4 (cat0??) */
675 uint32_t ul
: 1; /* cat2-cat4 (and cat1 in blob.. which may be bug??) */
677 uint32_t jmp_tgt
: 1;
679 uint32_t opc_cat
: 3;
684 static inline uint32_t instr_opc(instr_t
*instr
)
686 switch (instr
->opc_cat
) {
687 case 0: return instr
->cat0
.opc
;
689 case 2: return instr
->cat2
.opc
;
690 case 3: return instr
->cat3
.opc
;
691 case 4: return instr
->cat4
.opc
;
692 case 5: return instr
->cat5
.opc
;
693 case 6: return instr
->cat6
.opc
;
698 static inline bool is_mad(opc_t opc
)
713 static inline bool is_madsh(opc_t opc
)
724 #endif /* INSTR_A3XX_H_ */