1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2017-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 #ifndef _IGA_OPERAND_HPP_
10 #define _IGA_OPERAND_HPP_
11 
12 #include "ImmVal.hpp"
13 #include "Types.hpp"
14 
15 namespace iga {
16 class Block;
17 
18 class Operand {
19 public:
20     enum class Kind {
21         INVALID,   // an invalid or uninitialized operand
22         DIRECT,    // direct register reference
23         MACRO,     // madm or math.invm or math.rsqrtm
24         INDIRECT,  // register-indriect access
25         IMMEDIATE, // immediate value
26         LABEL,     // block target (can be numeric label/m_immVal)
27     };
28 
Operand()29     Operand()
30         : m_kind(Kind::INVALID)
31         , m_lblBlock(nullptr)
32         , m_type(Type::INVALID)
33         , m_regOpSrcMod(SrcModifier::NONE) { }
34 
35     // direct destination constructor (for constants etc)
Operand(DstModifier dstMod,RegName rType,const RegRef & reg,const Region::Horz & rgnHz,Type type)36     Operand(
37         DstModifier dstMod,
38         RegName rType,
39         const RegRef &reg,
40         const Region::Horz &rgnHz,
41         Type type)
42         : m_lblBlock(nullptr)
43     {
44         setDirectDestination(dstMod, rType, reg, rgnHz, type);
45     }
46 
47     // direct source constructor (for constants etc)
Operand(SrcModifier srcMod,RegName rType,const RegRef & reg,const Region & rgn,Type type)48     Operand(
49         SrcModifier srcMod,
50         RegName rType,
51         const RegRef &reg,
52         const Region &rgn,
53         Type type)
54         : m_lblBlock(nullptr)
55     {
56         setDirectSource(srcMod, rType, reg, rgn, type);
57     }
58 
59     // generally you want a reference to an operand, not a copy
60     // this prevents:
61     //    auto o = i->getSource(...); // copies all state
62     // you usually want
63     //    const auto &o = ...
64     // but in rare cases maybe you want a copy
65     //    Operand copy(i->getSource(...));
66     explicit Operand(const Operand &) = default;
67 
68     // describes if the operand is direct (Operand::Kind::DIRECT),
69     // indirect (Operand::Kind::INDIRECT) or immediate
70     // (Operand::Kind::IMMEDIATE)
getKind() const71     Kind getKind() const {return m_kind;}
72 
73     // both labels and true immediates are considered immediates
74     // for encoding and decoding sake
isImm() const75     bool isImm() const {
76         switch (getKind()) {
77         case Operand::Kind::IMMEDIATE:
78         case Operand::Kind::LABEL:
79             return true;
80         default:
81             return false;
82         }
83     }
84 
85     ///////////////////////////////////////////////////////////////////////////
86     // derived accessors
87 
88     // returns true if a direct register reference to the null register
isNull() const89     bool isNull() const {
90         return getKind() == Kind::DIRECT &&
91             getDirRegName() == RegName::ARF_NULL;
92     }
93 
94     ///////////////////////////////////////////////////////////////////////////
95     // other accessors
getDstModifier() const96     DstModifier getDstModifier() const { return m_regOpDstMod; }
getSrcModifier() const97     SrcModifier getSrcModifier() const { return m_regOpSrcMod; }
98 
99     // Applies to Operand::Kind::DIRECT
getDirRegName() const100     RegName getDirRegName() const { return m_regOpName; }
getDirRegRef() const101     const RegRef &getDirRegRef() const { return m_regOpReg; }
102 
103     // Applies to Operand::Kind::INDIRECT only
getIndAddrReg() const104     const RegRef &getIndAddrReg() const { return m_regOpReg; }
getIndImmAddr() const105     int16_t getIndImmAddr() const { return m_regOpIndOff; }
106 
107     // Applies to Operand::Kind::DIRECT and Operand::Kind::INDIRECT
getRegion() const108     Region getRegion() const { return m_regOpRgn; }
getMathMacroExt() const109     MathMacroExt getMathMacroExt() const { return m_regMathMacro; }
110     // Defined if the value is immediate
getImmediateValue() const111     const ImmVal getImmediateValue() const { return m_immValue; }
112     // if this operand corresponds to a label, this is the target block
113     // nullptr if we are using numeric labels
getTargetBlock() const114     const Block *getTargetBlock() const { return m_lblBlock; }
115 
116     // the operand type (as in :f, :d, ...)
getType() const117     Type getType() const { return m_type; }
118 
119     // re-initializes this operand as an direct destination register operand
120     void setDirectDestination(
121         DstModifier dstMod,
122         RegName rName,
123         const RegRef &reg,
124         const Region::Horz &rgnHz,
125         Type type);
126     // re-initializes this operand as a destination register operand using
127     // a math macro register access
setMacroDestination(DstModifier dstMod,RegName rName,const RegRef & reg,MathMacroExt acc,Type type)128     void setMacroDestination(
129         DstModifier dstMod,
130         RegName rName,
131         const RegRef &reg,
132         MathMacroExt acc,
133         Type type)
134     {
135         setMacroDestination(dstMod,rName,reg,acc,Region::Horz::HZ_1,type);
136     }
137     void setMacroDestination(
138         DstModifier dstMod,
139         RegName rName,
140         const RegRef &reg,
141         MathMacroExt acc,
142         Region::Horz rgnHz,
143         Type type);
144     // re-initializes this operand as an indirect destination register operand
145     void setInidirectDestination(
146         DstModifier dstMod,
147         const RegRef &reg,
148         int16_t immediateOffset,
149         const Region::Horz &rgnHz,
150         Type type);
151 
152     // re-initializes this operand as an immeidate value with a given type
153     void setImmediateSource(const ImmVal &val, Type type);
154     // re-initializes this operand as a direct source register
155     void setDirectSource(
156         SrcModifier srcMod,
157         RegName rName,
158         const RegRef &reg,
159         const Region &rgn,
160         Type type);
161     // re-initializes this operand as a source register operand using
162     // an math macro register access
setMacroSource(SrcModifier srcMod,RegName rName,const RegRef & reg,Region,MathMacroExt mme,Type type)163     void setMacroSource(
164         SrcModifier srcMod,
165         RegName rName,
166         const RegRef &reg,
167         Region /* rgn */,
168         MathMacroExt mme,
169         Type type)
170     {
171         setMacroSource(srcMod, rName, reg, mme, Region::SRC110, type);
172     }
173     void setMacroSource(
174         SrcModifier srcMod,
175         RegName rName,
176         const RegRef &reg,
177         MathMacroExt mme,
178         Region rgn,
179         Type type);
180 
181     // re-initializes this operand as an indirect register operand
182     void setInidirectSource(
183         SrcModifier srcMod,
184         RegName regName,
185         const RegRef &reg,
186         int16_t addrImmOff,
187         const Region &rgn,
188         Type type);
189     // re-initializes this operand as an immediate branch target
190     void setLabelSource(Block *blk, Type type);
191     void setLabelSource(int32_t jipOrUip, Type type);
192     // set sthe operand region
setRegion(const Region & rgn)193     void setRegion(const Region &rgn) { m_regOpRgn = rgn; }
194     // sets the operand type
setType(Type type)195     void setType(Type type) { m_type = type; }
196     // set the operand reg RegRef directly
setRegRef(const RegRef & regRef)197     void setRegRef(const RegRef& regRef)
198     {
199         m_regOpReg.regNum = regRef.regNum;
200         m_regOpReg.subRegNum = regRef.subRegNum;
201     }
202 
203   private:
204     Operand::Kind m_kind;
205 
206     // direct/indirect register information
207     union {
208         SrcModifier m_regOpSrcMod;
209         DstModifier m_regOpDstMod;
210     };
211     RegName m_regOpName = RegName::INVALID;
212     MathMacroExt m_regMathMacro = MathMacroExt::INVALID;
213     Region  m_regOpRgn = Region::INVALID;
214 
215     // direct/indirect register
216     RegRef m_regOpReg;
217 
218     // indirect register offset
219     int16_t m_regOpIndOff = 0;
220 
221     // Imm field information
222     ImmVal m_immValue;
223     // for resolved labels
224     // the literal value (for immediate data)
225     // also set before labels are resolved (label is .s32)
226     // for numeric labels the value is normalized as bytes from
227     // the pre-increment PC of the instruction.  Hence,
228     //  * Pre-BDW branches which use units of QWORDS in the
229     //    encoding will be converted to bytes.
230     //  * JMPI uses the pos-increment PC; we normalize that here
231     //    as well to a pre-increment value.
232     Block* m_lblBlock = nullptr;
233 
234     // the operand type (e.g. :d, :f, etc...)
235     Type m_type;
236 
237   public:
238     // useful constants (reusable operands to streamline codegen)
239     static const Operand DST_REG_IP_D; // brd/brc use this
240     static const Operand SRC_REG_IP_D;
241     static const Operand DST_REG_IP_UD; // jmpi Dst and Src0
242     static const Operand SRC_REG_IP_UD;
243     static const Operand DST_REG_NULL_UD; // e.g. while.Dst
244     static const Operand SRC_REG_NULL_UD;
245     static const Operand SRC_REG_NULL_UB;
246 }; // class Operand
247 } // namespace iga
248 #endif // _IGA_OPERAND_HPP_
249