Home | History | Annotate | Download | only in codegen
      1 /*
      2  * Copyright 2011 Christoph Bumiller
      3  *
      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:
     10  *
     11  * The above copyright notice and this permission notice shall be included in
     12  * all copies or substantial portions of the Software.
     13  *
     14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20  * OTHER DEALINGS IN THE SOFTWARE.
     21  */
     22 
     23 #ifndef __NV50_IR_TARGET_H__
     24 #define __NV50_IR_TARGET_H__
     25 
     26 #include "codegen/nv50_ir.h"
     27 
     28 namespace nv50_ir {
     29 
     30 struct RelocInfo;
     31 
     32 struct RelocEntry
     33 {
     34    enum Type
     35    {
     36       TYPE_CODE,
     37       TYPE_BUILTIN,
     38       TYPE_DATA
     39    };
     40 
     41    uint32_t data;
     42    uint32_t mask;
     43    uint32_t offset;
     44    int8_t bitPos;
     45    Type type;
     46 
     47    inline void apply(uint32_t *binary, const RelocInfo *info) const;
     48 };
     49 
     50 struct RelocInfo
     51 {
     52    uint32_t codePos;
     53    uint32_t libPos;
     54    uint32_t dataPos;
     55 
     56    uint32_t count;
     57 
     58    RelocEntry entry[0];
     59 };
     60 
     61 struct FixupData {
     62    FixupData(bool force, bool flat, uint8_t alphatest) :
     63       force_persample_interp(force), flatshade(flat), alphatest(alphatest) {}
     64    bool force_persample_interp;
     65    bool flatshade;
     66    uint8_t alphatest;
     67 };
     68 
     69 struct FixupEntry;
     70 typedef void (*FixupApply)(const FixupEntry*, uint32_t*, const FixupData&);
     71 
     72 struct FixupEntry
     73 {
     74    FixupEntry(FixupApply apply, int ipa, int reg, int loc) :
     75       apply(apply), ipa(ipa), reg(reg), loc(loc) {}
     76 
     77    FixupApply apply;
     78    union {
     79       struct {
     80          uint32_t ipa:4; // SC mode used to identify colors
     81          uint32_t reg:8; // The reg used for perspective division
     82          uint32_t loc:20; // Let's hope we don't have more than 1M-sized shaders
     83       };
     84       uint32_t val;
     85    };
     86 };
     87 
     88 struct FixupInfo
     89 {
     90    uint32_t count;
     91    FixupEntry entry[0];
     92 };
     93 
     94 class CodeEmitter
     95 {
     96 public:
     97    CodeEmitter(const Target *);
     98    virtual ~CodeEmitter() { }
     99 
    100    // returns whether the instruction was encodable and written
    101    virtual bool emitInstruction(Instruction *) = 0;
    102 
    103    virtual uint32_t getMinEncodingSize(const Instruction *) const = 0;
    104 
    105    void setCodeLocation(void *, uint32_t size);
    106    inline void *getCodeLocation() const { return code; }
    107    inline uint32_t getCodeSize() const { return codeSize; }
    108 
    109    bool addReloc(RelocEntry::Type, int w, uint32_t data, uint32_t m,
    110                  int s);
    111 
    112    inline void *getRelocInfo() const { return relocInfo; }
    113 
    114    bool addInterp(int ipa, int reg, FixupApply apply);
    115    inline void *getFixupInfo() const { return fixupInfo; }
    116 
    117    virtual void prepareEmission(Program *);
    118    virtual void prepareEmission(Function *);
    119    virtual void prepareEmission(BasicBlock *);
    120 
    121    void printBinary() const;
    122 
    123 protected:
    124    const Target *targ;
    125 
    126    uint32_t *code;
    127    uint32_t codeSize;
    128    uint32_t codeSizeLimit;
    129 
    130    RelocInfo *relocInfo;
    131    FixupInfo *fixupInfo;
    132 };
    133 
    134 
    135 enum OpClass
    136 {
    137    OPCLASS_MOVE          = 0,
    138    OPCLASS_LOAD          = 1,
    139    OPCLASS_STORE         = 2,
    140    OPCLASS_ARITH         = 3,
    141    OPCLASS_SHIFT         = 4,
    142    OPCLASS_SFU           = 5,
    143    OPCLASS_LOGIC         = 6,
    144    OPCLASS_COMPARE       = 7,
    145    OPCLASS_CONVERT       = 8,
    146    OPCLASS_ATOMIC        = 9,
    147    OPCLASS_TEXTURE       = 10,
    148    OPCLASS_SURFACE       = 11,
    149    OPCLASS_FLOW          = 12,
    150    OPCLASS_PSEUDO        = 14,
    151    OPCLASS_VECTOR        = 15,
    152    OPCLASS_BITFIELD      = 16,
    153    OPCLASS_CONTROL       = 17,
    154    OPCLASS_OTHER         = 18
    155 };
    156 
    157 class Target
    158 {
    159 public:
    160    Target(bool m, bool j, bool s) : hasJoin(m), joinAnterior(j), hasSWSched(s) { }
    161    virtual ~Target() { }
    162 
    163    static Target *create(uint32_t chipset);
    164    static void destroy(Target *);
    165 
    166    // 0x50 and 0x84 to 0xaf for nv50
    167    // 0xc0 to 0xdf for nvc0
    168    inline uint32_t getChipset() const { return chipset; }
    169 
    170    virtual CodeEmitter *getCodeEmitter(Program::Type) = 0;
    171 
    172    // Drivers should upload this so we can use it from all programs.
    173    // The address chosen is supplied to the relocation routine.
    174    virtual void getBuiltinCode(const uint32_t **code, uint32_t *size) const = 0;
    175 
    176    virtual void parseDriverInfo(const struct nv50_ir_prog_info *info) {
    177       threads = info->prop.cp.numThreads;
    178       if (threads == 0)
    179          threads = info->target >= NVISA_GK104_CHIPSET ? 1024 : 512;
    180    }
    181 
    182    virtual bool runLegalizePass(Program *, CGStage stage) const = 0;
    183 
    184 public:
    185    struct OpInfo
    186    {
    187       OpInfo *variants;
    188       operation op;
    189       uint16_t srcTypes;
    190       uint16_t dstTypes;
    191       uint32_t immdBits;
    192       uint8_t srcNr;
    193       uint8_t srcMods[3];
    194       uint8_t dstMods;
    195       uint16_t srcFiles[3];
    196       uint16_t dstFiles;
    197       unsigned int minEncSize  : 4;
    198       unsigned int vector      : 1;
    199       unsigned int predicate   : 1;
    200       unsigned int commutative : 1;
    201       unsigned int pseudo      : 1;
    202       unsigned int flow        : 1;
    203       unsigned int hasDest     : 1;
    204       unsigned int terminator  : 1;
    205    };
    206 
    207    inline const OpInfo& getOpInfo(const Instruction *) const;
    208    inline const OpInfo& getOpInfo(const operation) const;
    209 
    210    inline DataFile nativeFile(DataFile f) const;
    211 
    212    virtual bool insnCanLoad(const Instruction *insn, int s,
    213                             const Instruction *ld) const = 0;
    214    virtual bool insnCanLoadOffset(const Instruction *insn, int s,
    215                                   int offset) const = 0;
    216    virtual bool isOpSupported(operation, DataType) const = 0;
    217    virtual bool isAccessSupported(DataFile, DataType) const = 0;
    218    virtual bool isModSupported(const Instruction *,
    219                                int s, Modifier) const = 0;
    220    virtual bool isSatSupported(const Instruction *) const = 0;
    221    virtual bool isPostMultiplySupported(operation op, float f,
    222                                         int& e) const { return false; }
    223    virtual bool mayPredicate(const Instruction *,
    224                              const Value *) const = 0;
    225 
    226    // whether @insn can be issued together with @next (order matters)
    227    virtual bool canDualIssue(const Instruction *insn,
    228                              const Instruction *next) const { return false; }
    229    virtual int getLatency(const Instruction *) const { return 1; }
    230    virtual int getThroughput(const Instruction *) const { return 1; }
    231 
    232    virtual unsigned int getFileSize(DataFile) const = 0;
    233    virtual unsigned int getFileUnit(DataFile) const = 0;
    234 
    235    virtual uint32_t getSVAddress(DataFile, const Symbol *) const = 0;
    236 
    237 public:
    238    const bool hasJoin;      // true if instructions have a join modifier
    239    const bool joinAnterior; // true if join is executed before the op
    240    const bool hasSWSched;   // true if code should provide scheduling data
    241 
    242    static const uint8_t operationSrcNr[];
    243    static const OpClass operationClass[];
    244 
    245    static inline uint8_t getOpSrcNr(operation op)
    246    {
    247       return operationSrcNr[op];
    248    }
    249    static inline OpClass getOpClass(operation op)
    250    {
    251       return operationClass[op];
    252    }
    253 
    254 protected:
    255    uint32_t chipset;
    256    uint32_t threads;
    257 
    258    DataFile nativeFileMap[DATA_FILE_COUNT];
    259 
    260    OpInfo opInfo[OP_LAST + 1];
    261 };
    262 
    263 const Target::OpInfo& Target::getOpInfo(const Instruction *insn) const
    264 {
    265    return opInfo[MIN2(insn->op, OP_LAST)];
    266 }
    267 
    268 const Target::OpInfo& Target::getOpInfo(const operation op) const
    269 {
    270    return opInfo[op];
    271 }
    272 
    273 inline DataFile Target::nativeFile(DataFile f) const
    274 {
    275    return nativeFileMap[f];
    276 }
    277 
    278 } // namespace nv50_ir
    279 
    280 #endif // __NV50_IR_TARGET_H__
    281