Home | History | Annotate | Download | only in i965
      1 /*
      2  Copyright (C) Intel Corp.  2006.  All Rights Reserved.
      3  Intel funded Tungsten Graphics to
      4  develop this 3D driver.
      5 
      6  Permission is hereby granted, free of charge, to any person obtaining
      7  a copy of this software and associated documentation files (the
      8  "Software"), to deal in the Software without restriction, including
      9  without limitation the rights to use, copy, modify, merge, publish,
     10  distribute, sublicense, and/or sell copies of the Software, and to
     11  permit persons to whom the Software is furnished to do so, subject to
     12  the following conditions:
     13 
     14  The above copyright notice and this permission notice (including the
     15  next paragraph) shall be included in all copies or substantial
     16  portions of the Software.
     17 
     18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     19  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     21  IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
     22  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     23  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     24  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25 
     26  **********************************************************************/
     27  /*
     28   * Authors:
     29   *   Keith Whitwell <keithw (at) vmware.com>
     30   */
     31 
     32 /** @file brw_reg.h
     33  *
     34  * This file defines struct brw_reg, which is our representation for EU
     35  * registers.  They're not a hardware specific format, just an abstraction
     36  * that intends to capture the full flexibility of the hardware registers.
     37  *
     38  * The brw_eu_emit.c layer's brw_set_dest/brw_set_src[01] functions encode
     39  * the abstract brw_reg type into the actual hardware instruction encoding.
     40  */
     41 
     42 #ifndef BRW_REG_H
     43 #define BRW_REG_H
     44 
     45 #include <stdbool.h>
     46 #include "main/compiler.h"
     47 #include "main/macros.h"
     48 #include "program/prog_instruction.h"
     49 #include "brw_defines.h"
     50 
     51 #ifdef __cplusplus
     52 extern "C" {
     53 #endif
     54 
     55 struct gen_device_info;
     56 
     57 /** Number of general purpose registers (VS, WM, etc) */
     58 #define BRW_MAX_GRF 128
     59 
     60 /**
     61  * First GRF used for the MRF hack.
     62  *
     63  * On gen7, MRFs are no longer used, and contiguous GRFs are used instead.  We
     64  * haven't converted our compiler to be aware of this, so it asks for MRFs and
     65  * brw_eu_emit.c quietly converts them to be accesses of the top GRFs.  The
     66  * register allocators have to be careful of this to avoid corrupting the "MRF"s
     67  * with actual GRF allocations.
     68  */
     69 #define GEN7_MRF_HACK_START 112
     70 
     71 /** Number of message register file registers */
     72 #define BRW_MAX_MRF(gen) (gen == 6 ? 24 : 16)
     73 
     74 #define BRW_SWIZZLE4(a,b,c,d) (((a)<<0) | ((b)<<2) | ((c)<<4) | ((d)<<6))
     75 #define BRW_GET_SWZ(swz, idx) (((swz) >> ((idx)*2)) & 0x3)
     76 
     77 #define BRW_SWIZZLE_NOOP      BRW_SWIZZLE4(0,1,2,3)
     78 #define BRW_SWIZZLE_XYZW      BRW_SWIZZLE4(0,1,2,3)
     79 #define BRW_SWIZZLE_XXXX      BRW_SWIZZLE4(0,0,0,0)
     80 #define BRW_SWIZZLE_YYYY      BRW_SWIZZLE4(1,1,1,1)
     81 #define BRW_SWIZZLE_ZZZZ      BRW_SWIZZLE4(2,2,2,2)
     82 #define BRW_SWIZZLE_WWWW      BRW_SWIZZLE4(3,3,3,3)
     83 #define BRW_SWIZZLE_XYXY      BRW_SWIZZLE4(0,1,0,1)
     84 #define BRW_SWIZZLE_YXYX      BRW_SWIZZLE4(1,0,1,0)
     85 #define BRW_SWIZZLE_XZXZ      BRW_SWIZZLE4(0,2,0,2)
     86 #define BRW_SWIZZLE_YZXW      BRW_SWIZZLE4(1,2,0,3)
     87 #define BRW_SWIZZLE_YWYW      BRW_SWIZZLE4(1,3,1,3)
     88 #define BRW_SWIZZLE_ZXYW      BRW_SWIZZLE4(2,0,1,3)
     89 #define BRW_SWIZZLE_ZWZW      BRW_SWIZZLE4(2,3,2,3)
     90 #define BRW_SWIZZLE_WZWZ      BRW_SWIZZLE4(3,2,3,2)
     91 #define BRW_SWIZZLE_WZYX      BRW_SWIZZLE4(3,2,1,0)
     92 #define BRW_SWIZZLE_XXZZ      BRW_SWIZZLE4(0,0,2,2)
     93 #define BRW_SWIZZLE_YYWW      BRW_SWIZZLE4(1,1,3,3)
     94 #define BRW_SWIZZLE_YXWZ      BRW_SWIZZLE4(1,0,3,2)
     95 
     96 #define BRW_SWZ_COMP_INPUT(comp) (BRW_SWIZZLE_XYZW >> ((comp)*2))
     97 #define BRW_SWZ_COMP_OUTPUT(comp) (BRW_SWIZZLE_XYZW << ((comp)*2))
     98 
     99 static inline bool
    100 brw_is_single_value_swizzle(unsigned swiz)
    101 {
    102    return (swiz == BRW_SWIZZLE_XXXX ||
    103            swiz == BRW_SWIZZLE_YYYY ||
    104            swiz == BRW_SWIZZLE_ZZZZ ||
    105            swiz == BRW_SWIZZLE_WWWW);
    106 }
    107 
    108 /**
    109  * Compute the swizzle obtained from the application of \p swz0 on the result
    110  * of \p swz1.  The argument ordering is expected to match function
    111  * composition.
    112  */
    113 static inline unsigned
    114 brw_compose_swizzle(unsigned swz0, unsigned swz1)
    115 {
    116    return BRW_SWIZZLE4(
    117       BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 0)),
    118       BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 1)),
    119       BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 2)),
    120       BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 3)));
    121 }
    122 
    123 /**
    124  * Return the result of applying swizzle \p swz to shuffle the bits of \p mask
    125  * (AKA image).
    126  */
    127 static inline unsigned
    128 brw_apply_swizzle_to_mask(unsigned swz, unsigned mask)
    129 {
    130    unsigned result = 0;
    131 
    132    for (unsigned i = 0; i < 4; i++) {
    133       if (mask & (1 << BRW_GET_SWZ(swz, i)))
    134          result |= 1 << i;
    135    }
    136 
    137    return result;
    138 }
    139 
    140 /**
    141  * Return the result of applying the inverse of swizzle \p swz to shuffle the
    142  * bits of \p mask (AKA preimage).  Useful to find out which components are
    143  * read from a swizzled source given the instruction writemask.
    144  */
    145 static inline unsigned
    146 brw_apply_inv_swizzle_to_mask(unsigned swz, unsigned mask)
    147 {
    148    unsigned result = 0;
    149 
    150    for (unsigned i = 0; i < 4; i++) {
    151       if (mask & (1 << i))
    152          result |= 1 << BRW_GET_SWZ(swz, i);
    153    }
    154 
    155    return result;
    156 }
    157 
    158 /**
    159  * Construct an identity swizzle for the set of enabled channels given by \p
    160  * mask.  The result will only reference channels enabled in the provided \p
    161  * mask, assuming that \p mask is non-zero.  The constructed swizzle will
    162  * satisfy the property that for any instruction OP and any mask:
    163  *
    164  *    brw_OP(p, brw_writemask(dst, mask),
    165  *           brw_swizzle(src, brw_swizzle_for_mask(mask)));
    166  *
    167  * will be equivalent to the same instruction without swizzle:
    168  *
    169  *    brw_OP(p, brw_writemask(dst, mask), src);
    170  */
    171 static inline unsigned
    172 brw_swizzle_for_mask(unsigned mask)
    173 {
    174    unsigned last = (mask ? ffs(mask) - 1 : 0);
    175    unsigned swz[4];
    176 
    177    for (unsigned i = 0; i < 4; i++)
    178       last = swz[i] = (mask & (1 << i) ? i : last);
    179 
    180    return BRW_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
    181 }
    182 
    183 /**
    184  * Construct an identity swizzle for the first \p n components of a vector.
    185  * When only a subset of channels of a vec4 are used we don't want to
    186  * reference the other channels, as that will tell optimization passes that
    187  * those other channels are used.
    188  */
    189 static inline unsigned
    190 brw_swizzle_for_size(unsigned n)
    191 {
    192    return brw_swizzle_for_mask((1 << n) - 1);
    193 }
    194 
    195 /**
    196  * Converse of brw_swizzle_for_mask().  Returns the mask of components
    197  * accessed by the specified swizzle \p swz.
    198  */
    199 static inline unsigned
    200 brw_mask_for_swizzle(unsigned swz)
    201 {
    202    return brw_apply_inv_swizzle_to_mask(swz, ~0);
    203 }
    204 
    205 enum PACKED brw_reg_type {
    206    BRW_REGISTER_TYPE_UD = 0,
    207    BRW_REGISTER_TYPE_D,
    208    BRW_REGISTER_TYPE_UW,
    209    BRW_REGISTER_TYPE_W,
    210    BRW_REGISTER_TYPE_F,
    211 
    212    /** Non-immediates only: @{ */
    213    BRW_REGISTER_TYPE_UB,
    214    BRW_REGISTER_TYPE_B,
    215    /** @} */
    216 
    217    /** Immediates only: @{ */
    218    BRW_REGISTER_TYPE_UV, /* Gen6+ */
    219    BRW_REGISTER_TYPE_V,
    220    BRW_REGISTER_TYPE_VF,
    221    /** @} */
    222 
    223    BRW_REGISTER_TYPE_DF, /* Gen7+ (no immediates until Gen8+) */
    224 
    225    /* Gen8+ */
    226    BRW_REGISTER_TYPE_HF,
    227    BRW_REGISTER_TYPE_UQ,
    228    BRW_REGISTER_TYPE_Q,
    229 };
    230 
    231 unsigned brw_reg_type_to_hw_type(const struct gen_device_info *devinfo,
    232                                  enum brw_reg_type type, enum brw_reg_file file);
    233 const char *brw_reg_type_letters(unsigned brw_reg_type);
    234 uint32_t brw_swizzle_immediate(enum brw_reg_type type, uint32_t x, unsigned swz);
    235 
    236 #define REG_SIZE (8*4)
    237 
    238 /* These aren't hardware structs, just something useful for us to pass around:
    239  *
    240  * Align1 operation has a lot of control over input ranges.  Used in
    241  * WM programs to implement shaders decomposed into "channel serial"
    242  * or "structure of array" form:
    243  */
    244 struct brw_reg {
    245    union {
    246       struct {
    247          enum brw_reg_type type:4;
    248          enum brw_reg_file file:3;      /* :2 hardware format */
    249          unsigned negate:1;             /* source only */
    250          unsigned abs:1;                /* source only */
    251          unsigned address_mode:1;       /* relative addressing, hopefully! */
    252          unsigned pad0:1;
    253          unsigned subnr:5;              /* :1 in align16 */
    254          unsigned nr:16;
    255       };
    256       uint32_t bits;
    257    };
    258 
    259    union {
    260       struct {
    261          unsigned swizzle:8;      /* src only, align16 only */
    262          unsigned writemask:4;    /* dest only, align16 only */
    263          int  indirect_offset:10; /* relative addressing offset */
    264          unsigned vstride:4;      /* source only */
    265          unsigned width:3;        /* src only, align1 only */
    266          unsigned hstride:2;      /* align1 only */
    267          unsigned pad1:1;
    268       };
    269 
    270       double df;
    271       uint64_t u64;
    272       float f;
    273       int   d;
    274       unsigned ud;
    275    };
    276 };
    277 
    278 static inline bool
    279 brw_regs_equal(const struct brw_reg *a, const struct brw_reg *b)
    280 {
    281    const bool df = a->type == BRW_REGISTER_TYPE_DF && a->file == IMM;
    282    return a->bits == b->bits && (df ? a->u64 == b->u64 : a->ud == b->ud);
    283 }
    284 
    285 struct brw_indirect {
    286    unsigned addr_subnr:4;
    287    int addr_offset:10;
    288    unsigned pad:18;
    289 };
    290 
    291 
    292 static inline unsigned
    293 type_sz(unsigned type)
    294 {
    295    switch(type) {
    296    case BRW_REGISTER_TYPE_UQ:
    297    case BRW_REGISTER_TYPE_Q:
    298    case BRW_REGISTER_TYPE_DF:
    299       return 8;
    300    case BRW_REGISTER_TYPE_UD:
    301    case BRW_REGISTER_TYPE_D:
    302    case BRW_REGISTER_TYPE_F:
    303    case BRW_REGISTER_TYPE_VF:
    304       return 4;
    305    case BRW_REGISTER_TYPE_UW:
    306    case BRW_REGISTER_TYPE_W:
    307    case BRW_REGISTER_TYPE_UV:
    308    case BRW_REGISTER_TYPE_V:
    309    case BRW_REGISTER_TYPE_HF:
    310       return 2;
    311    case BRW_REGISTER_TYPE_UB:
    312    case BRW_REGISTER_TYPE_B:
    313       return 1;
    314    default:
    315       unreachable("not reached");
    316    }
    317 }
    318 
    319 /**
    320  * Return an integer type of the requested size and signedness.
    321  */
    322 static inline enum brw_reg_type
    323 brw_int_type(unsigned sz, bool is_signed)
    324 {
    325    switch (sz) {
    326    case 1:
    327       return (is_signed ? BRW_REGISTER_TYPE_B : BRW_REGISTER_TYPE_UB);
    328    case 2:
    329       return (is_signed ? BRW_REGISTER_TYPE_W : BRW_REGISTER_TYPE_UW);
    330    case 4:
    331       return (is_signed ? BRW_REGISTER_TYPE_D : BRW_REGISTER_TYPE_UD);
    332    case 8:
    333       return (is_signed ? BRW_REGISTER_TYPE_Q : BRW_REGISTER_TYPE_UQ);
    334    default:
    335       unreachable("Not reached.");
    336    }
    337 }
    338 
    339 /**
    340  * Construct a brw_reg.
    341  * \param file      one of the BRW_x_REGISTER_FILE values
    342  * \param nr        register number/index
    343  * \param subnr     register sub number
    344  * \param negate    register negate modifier
    345  * \param abs       register abs modifier
    346  * \param type      one of BRW_REGISTER_TYPE_x
    347  * \param vstride   one of BRW_VERTICAL_STRIDE_x
    348  * \param width     one of BRW_WIDTH_x
    349  * \param hstride   one of BRW_HORIZONTAL_STRIDE_x
    350  * \param swizzle   one of BRW_SWIZZLE_x
    351  * \param writemask WRITEMASK_X/Y/Z/W bitfield
    352  */
    353 static inline struct brw_reg
    354 brw_reg(enum brw_reg_file file,
    355         unsigned nr,
    356         unsigned subnr,
    357         unsigned negate,
    358         unsigned abs,
    359         enum brw_reg_type type,
    360         unsigned vstride,
    361         unsigned width,
    362         unsigned hstride,
    363         unsigned swizzle,
    364         unsigned writemask)
    365 {
    366    struct brw_reg reg;
    367    if (file == BRW_GENERAL_REGISTER_FILE)
    368       assert(nr < BRW_MAX_GRF);
    369    else if (file == BRW_ARCHITECTURE_REGISTER_FILE)
    370       assert(nr <= BRW_ARF_TIMESTAMP);
    371    /* Asserting on the MRF register number requires to know the hardware gen
    372     * (gen6 has 24 MRF registers), which we don't know here, so we assert
    373     * for that in the generators and in brw_eu_emit.c
    374     */
    375 
    376    reg.type = type;
    377    reg.file = file;
    378    reg.negate = negate;
    379    reg.abs = abs;
    380    reg.address_mode = BRW_ADDRESS_DIRECT;
    381    reg.pad0 = 0;
    382    reg.subnr = subnr * type_sz(type);
    383    reg.nr = nr;
    384 
    385    /* Could do better: If the reg is r5.3<0;1,0>, we probably want to
    386     * set swizzle and writemask to W, as the lower bits of subnr will
    387     * be lost when converted to align16.  This is probably too much to
    388     * keep track of as you'd want it adjusted by suboffset(), etc.
    389     * Perhaps fix up when converting to align16?
    390     */
    391    reg.swizzle = swizzle;
    392    reg.writemask = writemask;
    393    reg.indirect_offset = 0;
    394    reg.vstride = vstride;
    395    reg.width = width;
    396    reg.hstride = hstride;
    397    reg.pad1 = 0;
    398    return reg;
    399 }
    400 
    401 /** Construct float[16] register */
    402 static inline struct brw_reg
    403 brw_vec16_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
    404 {
    405    return brw_reg(file,
    406                   nr,
    407                   subnr,
    408                   0,
    409                   0,
    410                   BRW_REGISTER_TYPE_F,
    411                   BRW_VERTICAL_STRIDE_16,
    412                   BRW_WIDTH_16,
    413                   BRW_HORIZONTAL_STRIDE_1,
    414                   BRW_SWIZZLE_XYZW,
    415                   WRITEMASK_XYZW);
    416 }
    417 
    418 /** Construct float[8] register */
    419 static inline struct brw_reg
    420 brw_vec8_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
    421 {
    422    return brw_reg(file,
    423                   nr,
    424                   subnr,
    425                   0,
    426                   0,
    427                   BRW_REGISTER_TYPE_F,
    428                   BRW_VERTICAL_STRIDE_8,
    429                   BRW_WIDTH_8,
    430                   BRW_HORIZONTAL_STRIDE_1,
    431                   BRW_SWIZZLE_XYZW,
    432                   WRITEMASK_XYZW);
    433 }
    434 
    435 /** Construct float[4] register */
    436 static inline struct brw_reg
    437 brw_vec4_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
    438 {
    439    return brw_reg(file,
    440                   nr,
    441                   subnr,
    442                   0,
    443                   0,
    444                   BRW_REGISTER_TYPE_F,
    445                   BRW_VERTICAL_STRIDE_4,
    446                   BRW_WIDTH_4,
    447                   BRW_HORIZONTAL_STRIDE_1,
    448                   BRW_SWIZZLE_XYZW,
    449                   WRITEMASK_XYZW);
    450 }
    451 
    452 /** Construct float[2] register */
    453 static inline struct brw_reg
    454 brw_vec2_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
    455 {
    456    return brw_reg(file,
    457                   nr,
    458                   subnr,
    459                   0,
    460                   0,
    461                   BRW_REGISTER_TYPE_F,
    462                   BRW_VERTICAL_STRIDE_2,
    463                   BRW_WIDTH_2,
    464                   BRW_HORIZONTAL_STRIDE_1,
    465                   BRW_SWIZZLE_XYXY,
    466                   WRITEMASK_XY);
    467 }
    468 
    469 /** Construct float[1] register */
    470 static inline struct brw_reg
    471 brw_vec1_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
    472 {
    473    return brw_reg(file,
    474                   nr,
    475                   subnr,
    476                   0,
    477                   0,
    478                   BRW_REGISTER_TYPE_F,
    479                   BRW_VERTICAL_STRIDE_0,
    480                   BRW_WIDTH_1,
    481                   BRW_HORIZONTAL_STRIDE_0,
    482                   BRW_SWIZZLE_XXXX,
    483                   WRITEMASK_X);
    484 }
    485 
    486 static inline struct brw_reg
    487 brw_vecn_reg(unsigned width, enum brw_reg_file file,
    488              unsigned nr, unsigned subnr)
    489 {
    490    switch (width) {
    491    case 1:
    492       return brw_vec1_reg(file, nr, subnr);
    493    case 2:
    494       return brw_vec2_reg(file, nr, subnr);
    495    case 4:
    496       return brw_vec4_reg(file, nr, subnr);
    497    case 8:
    498       return brw_vec8_reg(file, nr, subnr);
    499    case 16:
    500       return brw_vec16_reg(file, nr, subnr);
    501    default:
    502       unreachable("Invalid register width");
    503    }
    504 }
    505 
    506 static inline struct brw_reg
    507 retype(struct brw_reg reg, enum brw_reg_type type)
    508 {
    509    reg.type = type;
    510    return reg;
    511 }
    512 
    513 static inline struct brw_reg
    514 firsthalf(struct brw_reg reg)
    515 {
    516    return reg;
    517 }
    518 
    519 static inline struct brw_reg
    520 sechalf(struct brw_reg reg)
    521 {
    522    if (reg.vstride)
    523       reg.nr++;
    524    return reg;
    525 }
    526 
    527 static inline struct brw_reg
    528 offset(struct brw_reg reg, unsigned delta)
    529 {
    530    reg.nr += delta;
    531    return reg;
    532 }
    533 
    534 
    535 static inline struct brw_reg
    536 byte_offset(struct brw_reg reg, unsigned bytes)
    537 {
    538    unsigned newoffset = reg.nr * REG_SIZE + reg.subnr + bytes;
    539    reg.nr = newoffset / REG_SIZE;
    540    reg.subnr = newoffset % REG_SIZE;
    541    return reg;
    542 }
    543 
    544 static inline struct brw_reg
    545 suboffset(struct brw_reg reg, unsigned delta)
    546 {
    547    return byte_offset(reg, delta * type_sz(reg.type));
    548 }
    549 
    550 /** Construct unsigned word[16] register */
    551 static inline struct brw_reg
    552 brw_uw16_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
    553 {
    554    return suboffset(retype(brw_vec16_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
    555 }
    556 
    557 /** Construct unsigned word[8] register */
    558 static inline struct brw_reg
    559 brw_uw8_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
    560 {
    561    return suboffset(retype(brw_vec8_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
    562 }
    563 
    564 /** Construct unsigned word[1] register */
    565 static inline struct brw_reg
    566 brw_uw1_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
    567 {
    568    return suboffset(retype(brw_vec1_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
    569 }
    570 
    571 static inline struct brw_reg
    572 brw_ud1_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
    573 {
    574    return retype(brw_vec1_reg(file, nr, subnr), BRW_REGISTER_TYPE_UD);
    575 }
    576 
    577 static inline struct brw_reg
    578 brw_imm_reg(enum brw_reg_type type)
    579 {
    580    return brw_reg(BRW_IMMEDIATE_VALUE,
    581                   0,
    582                   0,
    583                   0,
    584                   0,
    585                   type,
    586                   BRW_VERTICAL_STRIDE_0,
    587                   BRW_WIDTH_1,
    588                   BRW_HORIZONTAL_STRIDE_0,
    589                   0,
    590                   0);
    591 }
    592 
    593 /** Construct float immediate register */
    594 static inline struct brw_reg
    595 brw_imm_df(double df)
    596 {
    597    struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_DF);
    598    imm.df = df;
    599    return imm;
    600 }
    601 
    602 static inline struct brw_reg
    603 brw_imm_f(float f)
    604 {
    605    struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_F);
    606    imm.f = f;
    607    return imm;
    608 }
    609 
    610 /** Construct integer immediate register */
    611 static inline struct brw_reg
    612 brw_imm_d(int d)
    613 {
    614    struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_D);
    615    imm.d = d;
    616    return imm;
    617 }
    618 
    619 /** Construct uint immediate register */
    620 static inline struct brw_reg
    621 brw_imm_ud(unsigned ud)
    622 {
    623    struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UD);
    624    imm.ud = ud;
    625    return imm;
    626 }
    627 
    628 /** Construct ushort immediate register */
    629 static inline struct brw_reg
    630 brw_imm_uw(uint16_t uw)
    631 {
    632    struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UW);
    633    imm.ud = uw | (uw << 16);
    634    return imm;
    635 }
    636 
    637 /** Construct short immediate register */
    638 static inline struct brw_reg
    639 brw_imm_w(int16_t w)
    640 {
    641    struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_W);
    642    imm.d = w | (w << 16);
    643    return imm;
    644 }
    645 
    646 /* brw_imm_b and brw_imm_ub aren't supported by hardware - the type
    647  * numbers alias with _V and _VF below:
    648  */
    649 
    650 /** Construct vector of eight signed half-byte values */
    651 static inline struct brw_reg
    652 brw_imm_v(unsigned v)
    653 {
    654    struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_V);
    655    imm.ud = v;
    656    return imm;
    657 }
    658 
    659 /** Construct vector of eight unsigned half-byte values */
    660 static inline struct brw_reg
    661 brw_imm_uv(unsigned uv)
    662 {
    663    struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UV);
    664    imm.ud = uv;
    665    return imm;
    666 }
    667 
    668 /** Construct vector of four 8-bit float values */
    669 static inline struct brw_reg
    670 brw_imm_vf(unsigned v)
    671 {
    672    struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF);
    673    imm.ud = v;
    674    return imm;
    675 }
    676 
    677 static inline struct brw_reg
    678 brw_imm_vf4(unsigned v0, unsigned v1, unsigned v2, unsigned v3)
    679 {
    680    struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF);
    681    imm.vstride = BRW_VERTICAL_STRIDE_0;
    682    imm.width = BRW_WIDTH_4;
    683    imm.hstride = BRW_HORIZONTAL_STRIDE_1;
    684    imm.ud = ((v0 << 0) | (v1 << 8) | (v2 << 16) | (v3 << 24));
    685    return imm;
    686 }
    687 
    688 
    689 static inline struct brw_reg
    690 brw_address(struct brw_reg reg)
    691 {
    692    return brw_imm_uw(reg.nr * REG_SIZE + reg.subnr);
    693 }
    694 
    695 /** Construct float[1] general-purpose register */
    696 static inline struct brw_reg
    697 brw_vec1_grf(unsigned nr, unsigned subnr)
    698 {
    699    return brw_vec1_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
    700 }
    701 
    702 /** Construct float[2] general-purpose register */
    703 static inline struct brw_reg
    704 brw_vec2_grf(unsigned nr, unsigned subnr)
    705 {
    706    return brw_vec2_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
    707 }
    708 
    709 /** Construct float[4] general-purpose register */
    710 static inline struct brw_reg
    711 brw_vec4_grf(unsigned nr, unsigned subnr)
    712 {
    713    return brw_vec4_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
    714 }
    715 
    716 /** Construct float[8] general-purpose register */
    717 static inline struct brw_reg
    718 brw_vec8_grf(unsigned nr, unsigned subnr)
    719 {
    720    return brw_vec8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
    721 }
    722 
    723 /** Construct float[16] general-purpose register */
    724 static inline struct brw_reg
    725 brw_vec16_grf(unsigned nr, unsigned subnr)
    726 {
    727    return brw_vec16_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
    728 }
    729 
    730 static inline struct brw_reg
    731 brw_vecn_grf(unsigned width, unsigned nr, unsigned subnr)
    732 {
    733    return brw_vecn_reg(width, BRW_GENERAL_REGISTER_FILE, nr, subnr);
    734 }
    735 
    736 
    737 static inline struct brw_reg
    738 brw_uw8_grf(unsigned nr, unsigned subnr)
    739 {
    740    return brw_uw8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
    741 }
    742 
    743 static inline struct brw_reg
    744 brw_uw16_grf(unsigned nr, unsigned subnr)
    745 {
    746    return brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
    747 }
    748 
    749 
    750 /** Construct null register (usually used for setting condition codes) */
    751 static inline struct brw_reg
    752 brw_null_reg(void)
    753 {
    754    return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_NULL, 0);
    755 }
    756 
    757 static inline struct brw_reg
    758 brw_null_vec(unsigned width)
    759 {
    760    return brw_vecn_reg(width, BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_NULL, 0);
    761 }
    762 
    763 static inline struct brw_reg
    764 brw_address_reg(unsigned subnr)
    765 {
    766    return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_ADDRESS, subnr);
    767 }
    768 
    769 /* If/else instructions break in align16 mode if writemask & swizzle
    770  * aren't xyzw.  This goes against the convention for other scalar
    771  * regs:
    772  */
    773 static inline struct brw_reg
    774 brw_ip_reg(void)
    775 {
    776    return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE,
    777                   BRW_ARF_IP,
    778                   0,
    779                   0,
    780                   0,
    781                   BRW_REGISTER_TYPE_UD,
    782                   BRW_VERTICAL_STRIDE_4, /* ? */
    783                   BRW_WIDTH_1,
    784                   BRW_HORIZONTAL_STRIDE_0,
    785                   BRW_SWIZZLE_XYZW, /* NOTE! */
    786                   WRITEMASK_XYZW); /* NOTE! */
    787 }
    788 
    789 static inline struct brw_reg
    790 brw_notification_reg(void)
    791 {
    792    return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE,
    793                   BRW_ARF_NOTIFICATION_COUNT,
    794                   0,
    795                   0,
    796                   0,
    797                   BRW_REGISTER_TYPE_UD,
    798                   BRW_VERTICAL_STRIDE_0,
    799                   BRW_WIDTH_1,
    800                   BRW_HORIZONTAL_STRIDE_0,
    801                   BRW_SWIZZLE_XXXX,
    802                   WRITEMASK_X);
    803 }
    804 
    805 static inline struct brw_reg
    806 brw_sr0_reg(unsigned subnr)
    807 {
    808    return brw_ud1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_STATE, subnr);
    809 }
    810 
    811 static inline struct brw_reg
    812 brw_acc_reg(unsigned width)
    813 {
    814    return brw_vecn_reg(width, BRW_ARCHITECTURE_REGISTER_FILE,
    815                        BRW_ARF_ACCUMULATOR, 0);
    816 }
    817 
    818 static inline struct brw_reg
    819 brw_flag_reg(int reg, int subreg)
    820 {
    821    return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE,
    822                       BRW_ARF_FLAG + reg, subreg);
    823 }
    824 
    825 /**
    826  * Return the mask register present in Gen4-5, or the related register present
    827  * in Gen7.5 and later hardware referred to as "channel enable" register in
    828  * the documentation.
    829  */
    830 static inline struct brw_reg
    831 brw_mask_reg(unsigned subnr)
    832 {
    833    return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_MASK, subnr);
    834 }
    835 
    836 static inline struct brw_reg
    837 brw_vmask_reg()
    838 {
    839    return brw_sr0_reg(3);
    840 }
    841 
    842 static inline struct brw_reg
    843 brw_dmask_reg()
    844 {
    845    return brw_sr0_reg(2);
    846 }
    847 
    848 static inline struct brw_reg
    849 brw_message_reg(unsigned nr)
    850 {
    851    return brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, nr, 0);
    852 }
    853 
    854 static inline struct brw_reg
    855 brw_uvec_mrf(unsigned width, unsigned nr, unsigned subnr)
    856 {
    857    return retype(brw_vecn_reg(width, BRW_MESSAGE_REGISTER_FILE, nr, subnr),
    858                  BRW_REGISTER_TYPE_UD);
    859 }
    860 
    861 /* This is almost always called with a numeric constant argument, so
    862  * make things easy to evaluate at compile time:
    863  */
    864 static inline unsigned cvt(unsigned val)
    865 {
    866    switch (val) {
    867    case 0: return 0;
    868    case 1: return 1;
    869    case 2: return 2;
    870    case 4: return 3;
    871    case 8: return 4;
    872    case 16: return 5;
    873    case 32: return 6;
    874    }
    875    return 0;
    876 }
    877 
    878 static inline struct brw_reg
    879 stride(struct brw_reg reg, unsigned vstride, unsigned width, unsigned hstride)
    880 {
    881    reg.vstride = cvt(vstride);
    882    reg.width = cvt(width) - 1;
    883    reg.hstride = cvt(hstride);
    884    return reg;
    885 }
    886 
    887 /**
    888  * Multiply the vertical and horizontal stride of a register by the given
    889  * factor \a s.
    890  */
    891 static inline struct brw_reg
    892 spread(struct brw_reg reg, unsigned s)
    893 {
    894    if (s) {
    895       assert(_mesa_is_pow_two(s));
    896 
    897       if (reg.hstride)
    898          reg.hstride += cvt(s) - 1;
    899 
    900       if (reg.vstride)
    901          reg.vstride += cvt(s) - 1;
    902 
    903       return reg;
    904    } else {
    905       return stride(reg, 0, 1, 0);
    906    }
    907 }
    908 
    909 static inline struct brw_reg
    910 vec16(struct brw_reg reg)
    911 {
    912    return stride(reg, 16,16,1);
    913 }
    914 
    915 static inline struct brw_reg
    916 vec8(struct brw_reg reg)
    917 {
    918    return stride(reg, 8,8,1);
    919 }
    920 
    921 static inline struct brw_reg
    922 vec4(struct brw_reg reg)
    923 {
    924    return stride(reg, 4,4,1);
    925 }
    926 
    927 static inline struct brw_reg
    928 vec2(struct brw_reg reg)
    929 {
    930    return stride(reg, 2,2,1);
    931 }
    932 
    933 static inline struct brw_reg
    934 vec1(struct brw_reg reg)
    935 {
    936    return stride(reg, 0,1,0);
    937 }
    938 
    939 
    940 static inline struct brw_reg
    941 get_element(struct brw_reg reg, unsigned elt)
    942 {
    943    return vec1(suboffset(reg, elt));
    944 }
    945 
    946 static inline struct brw_reg
    947 get_element_ud(struct brw_reg reg, unsigned elt)
    948 {
    949    return vec1(suboffset(retype(reg, BRW_REGISTER_TYPE_UD), elt));
    950 }
    951 
    952 static inline struct brw_reg
    953 get_element_d(struct brw_reg reg, unsigned elt)
    954 {
    955    return vec1(suboffset(retype(reg, BRW_REGISTER_TYPE_D), elt));
    956 }
    957 
    958 static inline struct brw_reg
    959 brw_swizzle(struct brw_reg reg, unsigned swz)
    960 {
    961    if (reg.file == BRW_IMMEDIATE_VALUE)
    962       reg.ud = brw_swizzle_immediate(reg.type, reg.ud, swz);
    963    else
    964       reg.swizzle = brw_compose_swizzle(swz, reg.swizzle);
    965 
    966    return reg;
    967 }
    968 
    969 static inline struct brw_reg
    970 brw_writemask(struct brw_reg reg, unsigned mask)
    971 {
    972    assert(reg.file != BRW_IMMEDIATE_VALUE);
    973    reg.writemask &= mask;
    974    return reg;
    975 }
    976 
    977 static inline struct brw_reg
    978 brw_set_writemask(struct brw_reg reg, unsigned mask)
    979 {
    980    assert(reg.file != BRW_IMMEDIATE_VALUE);
    981    reg.writemask = mask;
    982    return reg;
    983 }
    984 
    985 static inline unsigned
    986 brw_writemask_for_size(unsigned n)
    987 {
    988    return (1 << n) - 1;
    989 }
    990 
    991 static inline unsigned
    992 brw_writemask_for_component_packing(unsigned n, unsigned first_component)
    993 {
    994    assert(first_component + n <= 4);
    995    return (((1 << n) - 1) << first_component);
    996 }
    997 
    998 static inline struct brw_reg
    999 negate(struct brw_reg reg)
   1000 {
   1001    reg.negate ^= 1;
   1002    return reg;
   1003 }
   1004 
   1005 static inline struct brw_reg
   1006 brw_abs(struct brw_reg reg)
   1007 {
   1008    reg.abs = 1;
   1009    reg.negate = 0;
   1010    return reg;
   1011 }
   1012 
   1013 /************************************************************************/
   1014 
   1015 static inline struct brw_reg
   1016 brw_vec4_indirect(unsigned subnr, int offset)
   1017 {
   1018    struct brw_reg reg =  brw_vec4_grf(0, 0);
   1019    reg.subnr = subnr;
   1020    reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
   1021    reg.indirect_offset = offset;
   1022    return reg;
   1023 }
   1024 
   1025 static inline struct brw_reg
   1026 brw_vec1_indirect(unsigned subnr, int offset)
   1027 {
   1028    struct brw_reg reg =  brw_vec1_grf(0, 0);
   1029    reg.subnr = subnr;
   1030    reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
   1031    reg.indirect_offset = offset;
   1032    return reg;
   1033 }
   1034 
   1035 static inline struct brw_reg
   1036 brw_VxH_indirect(unsigned subnr, int offset)
   1037 {
   1038    struct brw_reg reg = brw_vec1_grf(0, 0);
   1039    reg.vstride = BRW_VERTICAL_STRIDE_ONE_DIMENSIONAL;
   1040    reg.subnr = subnr;
   1041    reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
   1042    reg.indirect_offset = offset;
   1043    return reg;
   1044 }
   1045 
   1046 static inline struct brw_reg
   1047 deref_4f(struct brw_indirect ptr, int offset)
   1048 {
   1049    return brw_vec4_indirect(ptr.addr_subnr, ptr.addr_offset + offset);
   1050 }
   1051 
   1052 static inline struct brw_reg
   1053 deref_1f(struct brw_indirect ptr, int offset)
   1054 {
   1055    return brw_vec1_indirect(ptr.addr_subnr, ptr.addr_offset + offset);
   1056 }
   1057 
   1058 static inline struct brw_reg
   1059 deref_4b(struct brw_indirect ptr, int offset)
   1060 {
   1061    return retype(deref_4f(ptr, offset), BRW_REGISTER_TYPE_B);
   1062 }
   1063 
   1064 static inline struct brw_reg
   1065 deref_1uw(struct brw_indirect ptr, int offset)
   1066 {
   1067    return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UW);
   1068 }
   1069 
   1070 static inline struct brw_reg
   1071 deref_1d(struct brw_indirect ptr, int offset)
   1072 {
   1073    return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_D);
   1074 }
   1075 
   1076 static inline struct brw_reg
   1077 deref_1ud(struct brw_indirect ptr, int offset)
   1078 {
   1079    return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UD);
   1080 }
   1081 
   1082 static inline struct brw_reg
   1083 get_addr_reg(struct brw_indirect ptr)
   1084 {
   1085    return brw_address_reg(ptr.addr_subnr);
   1086 }
   1087 
   1088 static inline struct brw_indirect
   1089 brw_indirect_offset(struct brw_indirect ptr, int offset)
   1090 {
   1091    ptr.addr_offset += offset;
   1092    return ptr;
   1093 }
   1094 
   1095 static inline struct brw_indirect
   1096 brw_indirect(unsigned addr_subnr, int offset)
   1097 {
   1098    struct brw_indirect ptr;
   1099    ptr.addr_subnr = addr_subnr;
   1100    ptr.addr_offset = offset;
   1101    ptr.pad = 0;
   1102    return ptr;
   1103 }
   1104 
   1105 static inline bool
   1106 region_matches(struct brw_reg reg, enum brw_vertical_stride v,
   1107                enum brw_width w, enum brw_horizontal_stride h)
   1108 {
   1109    return reg.vstride == v &&
   1110           reg.width == w &&
   1111           reg.hstride == h;
   1112 }
   1113 
   1114 #define has_scalar_region(reg) \
   1115    region_matches(reg, BRW_VERTICAL_STRIDE_0, BRW_WIDTH_1, \
   1116                   BRW_HORIZONTAL_STRIDE_0)
   1117 
   1118 /* brw_packed_float.c */
   1119 int brw_float_to_vf(float f);
   1120 float brw_vf_to_float(unsigned char vf);
   1121 
   1122 #ifdef __cplusplus
   1123 }
   1124 #endif
   1125 
   1126 #endif
   1127