1 // Copyright 2014 Tony Wasserka
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 //     * Redistributions of source code must retain the above copyright
8 //       notice, this list of conditions and the following disclaimer.
9 //     * Redistributions in binary form must reproduce the above copyright
10 //       notice, this list of conditions and the following disclaimer in the
11 //       documentation and/or other materials provided with the distribution.
12 //     * Neither the name of the owner nor the names of its contributors may
13 //       be used to endorse or promote products derived from this software
14 //       without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #pragma once
29 
30 #include <cstdint>
31 #include <map>
32 #include <stdexcept>
33 #include <string>
34 #include <sstream>
35 
36 #include "bit_field.h"
37 
38 namespace nihstro {
39 
40 enum class RegisterType {
41     Input,
42     Output,
43     Temporary,
44     FloatUniform,
45     IntUniform,
46     BoolUniform,
47     Address,
48     ConditionalCode,
49     Unknown
50 };
51 
GetRegisterName(RegisterType type)52 static std::string GetRegisterName(RegisterType type) {
53     switch (type) {
54     case RegisterType::Input:           return "v";
55     case RegisterType::Output:          return "o";
56     case RegisterType::Temporary:       return "r";
57     case RegisterType::FloatUniform:    return "c";
58     case RegisterType::IntUniform:      return "i";
59     case RegisterType::BoolUniform:     return "b";
60     case RegisterType::ConditionalCode: return "cc";
61     case RegisterType::Unknown:         return "u";
62     default:                            return "";
63     }
64 }
65 
66 struct SourceRegister {
67     SourceRegister() = default;
68 
SourceRegisterSourceRegister69     SourceRegister(uint32_t value) {
70         this->value = value;
71     }
72 
GetRegisterTypeSourceRegister73     RegisterType GetRegisterType() const {
74         if (value < 0x10)
75             return RegisterType::Input;
76         else if (value < 0x20)
77             return RegisterType::Temporary;
78         else
79             return RegisterType::FloatUniform;
80     }
81 
GetIndexSourceRegister82     int GetIndex() const {
83         if (GetRegisterType() == RegisterType::Input)
84             return value;
85         else if (GetRegisterType() == RegisterType::Temporary)
86             return value - 0x10;
87         else if (GetRegisterType() == RegisterType::FloatUniform)
88             return value - 0x20;
89     }
90 
FromTypeAndIndexSourceRegister91     static const SourceRegister FromTypeAndIndex(RegisterType type, int index) {
92         SourceRegister reg;
93         if (type == RegisterType::Input)
94             reg.value = index;
95         else if (type == RegisterType::Temporary)
96             reg.value = index + 0x10;
97         else if (type == RegisterType::FloatUniform)
98             reg.value = index + 0x20;
99         else {
100             // TODO: Should throw an exception or something.
101         }
102         return reg;
103     }
104 
MakeInputSourceRegister105     static const SourceRegister MakeInput(int index) {
106         return FromTypeAndIndex(RegisterType::Input, index);
107     }
108 
MakeTemporarySourceRegister109     static const SourceRegister MakeTemporary(int index) {
110         return FromTypeAndIndex(RegisterType::Temporary, index);
111     }
112 
MakeFloatSourceRegister113     static const SourceRegister MakeFloat(int index) {
114         return FromTypeAndIndex(RegisterType::FloatUniform, index);
115     }
116 
GetNameSourceRegister117     std::string GetName() const {
118         std::stringstream ss;
119         ss << GetRegisterName(GetRegisterType()) << GetIndex();
120         return ss.str();
121     }
122 
uint32_tSourceRegister123     operator uint32_t() const {
124         return value;
125     }
126 
127     template<typename T>
128     decltype(uint32_t{} - T{}) operator -(const T& oth) const {
129         return value - oth;
130     }
131 
132     template<typename T>
decltypeSourceRegister133     decltype(uint32_t{} & T{}) operator &(const T& oth) const {
134         return value & oth;
135     }
136 
137     uint32_t operator &(const SourceRegister& oth) const {
138         return value & oth.value;
139     }
140 
141     uint32_t operator ~() const {
142         return ~value;
143     }
144 
145 private:
146     uint32_t value;
147 };
148 
149 struct DestRegister {
150     DestRegister() = default;
151 
DestRegisterDestRegister152     DestRegister(uint32_t value) {
153         this->value = value;
154     }
155 
GetRegisterTypeDestRegister156     RegisterType GetRegisterType() const {
157         if (value < 0x10)
158             return RegisterType::Output;
159         else
160             return RegisterType::Temporary;
161     }
162 
GetIndexDestRegister163     int GetIndex() const {
164         if (GetRegisterType() == RegisterType::Output)
165             return value;
166         else if (GetRegisterType() == RegisterType::Temporary)
167             return value - 0x10;
168         else // if (GetRegisterType() == RegisterType::FloatUniform)
169             // TODO: This will lead to negative returned values...
170             return value - 0x20;
171     }
172 
FromTypeAndIndexDestRegister173     static const DestRegister FromTypeAndIndex(RegisterType type, int index) {
174         DestRegister reg;
175         if (type == RegisterType::Output)
176             reg.value = index;
177         else if (type == RegisterType::Temporary)
178             reg.value = index + 0x10;
179         else if (type == RegisterType::FloatUniform) // TODO: Wait what? These shouldn't be writable..
180             reg.value = index + 0x20;
181         else {
182             // TODO: Should throw an exception or something.
183         }
184         return reg;
185     }
186 
MakeOutputDestRegister187     static const DestRegister MakeOutput(int index) {
188         return FromTypeAndIndex(RegisterType::Output, index);
189     }
190 
MakeTemporaryDestRegister191     static const DestRegister MakeTemporary(int index) {
192         return FromTypeAndIndex(RegisterType::Temporary, index);
193     }
194 
GetNameDestRegister195     std::string GetName() const {
196         std::stringstream ss;
197         ss << GetRegisterName(GetRegisterType()) << GetIndex();
198         return ss.str();
199     }
200 
uint32_tDestRegister201     operator uint32_t() const {
202         return value;
203     }
204 
205     template<typename T>
206     decltype(uint32_t{} - T{}) operator -(const T& oth) const {
207         return value - oth;
208     }
209 
210     template<typename T>
decltypeDestRegister211     decltype(uint32_t{} & T{}) operator &(const T& oth) const {
212         return value & oth;
213     }
214 
215     uint32_t operator &(const DestRegister& oth) const {
216         return value & oth.value;
217     }
218 
219     uint32_t operator ~() const {
220         return ~value;
221     }
222 
223 private:
224     uint32_t value;
225 };
226 
227 struct OpCode {
228     enum class Id : uint32_t {
229         ADD     = 0x00,
230         DP3     = 0x01,
231         DP4     = 0x02,
232         DPH     = 0x03,   // Dot product of Vec4 and Vec3; the Vec3 is made into
233                           // a Vec4 by appending 1.0 as the fourth component
234         DST     = 0x04,   // Distance, same as in vs_3_0
235         EX2     = 0x05,   // Base-2 exponential
236         LG2     = 0x06,   // Base-2 logarithm
237         LIT     = 0x07,   // Clamp for lighting
238         MUL     = 0x08,
239         SGE     = 0x09,   // Set to 1.0 if SRC1 is greater or equal to SRC2
240         SLT     = 0x0A,   // Set to 1.0 if SRC1 is less than SRC2
241         FLR     = 0x0B,
242         MAX     = 0x0C,
243         MIN     = 0x0D,
244         RCP     = 0x0E,   // Reciprocal
245         RSQ     = 0x0F,   // Reciprocal of square root
246 
247         MOVA    = 0x12,   // Move to Address Register
248         MOV     = 0x13,
249 
250         DPHI    = 0x18,
251         DSTI    = 0x19,
252         SGEI    = 0x1A,
253         SLTI    = 0x1B,
254 
255         BREAK   = 0x20,
256         NOP     = 0x21,
257         END     = 0x22,
258         BREAKC  = 0x23,
259         CALL    = 0x24,
260         CALLC   = 0x25,
261         CALLU   = 0x26,
262         IFU     = 0x27,
263         IFC     = 0x28,
264         LOOP    = 0x29,
265         EMIT    = 0x2A,
266         SETEMIT = 0x2B,
267         JMPC    = 0x2C,
268         JMPU    = 0x2D,
269         CMP     = 0x2E, // LSB opcode bit ignored
270 
271         // lower 3 opcode bits ignored for these
272         MADI    = 0x30,
273         MAD     = 0x38, // lower 3 opcode bits ignored
274 
275         // Pseudo-instructions, used internally by the assembler
276         PSEUDO_INSTRUCTION_START = 0x40,
277 
278         GEN_IF = PSEUDO_INSTRUCTION_START, // Generic IF (IFC or IFU)
279         ELSE,
280         ENDIF,
281         GEN_CALL,       // Generic CALL (CALL, CALC, or CALLU)
282         GEN_JMP,        // Generic JMP (JMPC or JMPU)
283         //RET,          // Return from function (not supported yet)
284         ENDLOOP,
285     };
286 
287     enum class Type {
288         Trivial,            // 3dbrew format 0
289         Arithmetic,         // 3dbrew format 1
290         Conditional,        // 3dbrew format 2
291         UniformFlowControl, // 3dbrew format 3
292         SetEmit,            // 3dbrew format 4
293         MultiplyAdd,        // 3dbrew format 5
294         Unknown
295     };
296 
297     struct Info {
298         Type type;
299 
300         // Arithmetic
301         enum : uint32_t {
302             OpDesc      = 1,
303             Src1        = 2,
304             Src2        = 4,
305             Idx         = 8,
306             Dest        = 16,
307             SrcInversed = 32,
308             CompareOps  = 64,
309             MOVA        = 128 | OpDesc | Src1 | Idx,
310             OneArgument = OpDesc | Src1 | Idx | Dest,
311             TwoArguments = OneArgument | Src2,
312             Compare = OpDesc | Idx | Src1 | Src2 | CompareOps,
313         };
314 
315         // Flow Control
316         enum : uint32_t {
317             HasUniformIndex = 1,
318             HasCondition    = 2,
319             HasExplicitDest = 4,   // target code given explicitly and context-independently (contrary to e.g. BREAKC)
320             HasFinishPoint  = 8,   // last instruction until returning to caller
321             HasAlternative  = 16,  // has an "else" branch
322             LOOP            = 32,
323 
324             BREAKC          = HasCondition,
325 
326             JMP             = HasExplicitDest,
327             JMPC            = JMP | HasCondition,
328             JMPU            = JMP | HasUniformIndex,
329 
330             CALL            = JMP | HasFinishPoint,
331             CALLC           = CALL | HasCondition,
332             CALLU           = CALL | HasUniformIndex,
333             IFU             = CALLU | HasAlternative,
334             IFC             = CALLC | HasAlternative,
335         };
336 
337         enum : uint32_t {
338             FullAndBool,
339             SimpleAndInt,
340         };
341 
342         uint32_t subtype;
343 
344         const char* name;
345 
346         // TODO: Deprecate.
NumArgumentsOpCode::Info347         size_t NumArguments() const {
348             if (type == Type::Arithmetic) {
349                 if (subtype & Src2)
350                     return 3;
351                 else if (subtype & Src1)
352                     return 2;
353             }
354 
355             return 0;
356         }
357     };
358 
359     OpCode() = default;
360 
OpCodeOpCode361     OpCode(Id value) {
362         this->value = static_cast<uint32_t>(value);
363     }
364 
OpCodeOpCode365     OpCode(uint32_t value) {
366         this->value = value;
367     }
368 
EffectiveOpCodeOpCode369     Id EffectiveOpCode() const {
370         uint32_t op = static_cast<uint32_t>(value);
371         if (static_cast<Id>(op & ~0x7) == Id::MAD)
372             return Id::MAD;
373         else if (static_cast<Id>(op & ~0x7) == Id::MADI)
374             return Id::MADI;
375         else if (static_cast<Id>(op & ~0x1) == Id::CMP)
376             return Id::CMP;
377         else
378             return static_cast<Id>(value);
379     }
380 
GetInfoOpCode381     const Info& GetInfo() const {
382         #define unknown_instruction { OpCode::Type::Unknown, 0, "UNK" }
383         static const OpCode::Info info_table[] =  {
384             { OpCode::Type::Arithmetic, OpCode::Info::TwoArguments, "add" },
385             { OpCode::Type::Arithmetic, OpCode::Info::TwoArguments, "dp3" },
386             { OpCode::Type::Arithmetic, OpCode::Info::TwoArguments, "dp4" },
387             { OpCode::Type::Arithmetic, OpCode::Info::TwoArguments, "dph" },
388             { OpCode::Type::Arithmetic, OpCode::Info::TwoArguments, "dst" },
389             { OpCode::Type::Arithmetic, OpCode::Info::OneArgument, "exp" },
390             { OpCode::Type::Arithmetic, OpCode::Info::OneArgument, "log" },
391             { OpCode::Type::Arithmetic, OpCode::Info::OneArgument, "lit" },
392             { OpCode::Type::Arithmetic, OpCode::Info::TwoArguments, "mul" },
393             { OpCode::Type::Arithmetic, OpCode::Info::TwoArguments, "sge" },
394             { OpCode::Type::Arithmetic, OpCode::Info::TwoArguments, "slt" },
395             { OpCode::Type::Arithmetic, OpCode::Info::OneArgument, "flr" },
396             { OpCode::Type::Arithmetic, OpCode::Info::TwoArguments, "max" },
397             { OpCode::Type::Arithmetic, OpCode::Info::TwoArguments, "min" },
398             { OpCode::Type::Arithmetic, OpCode::Info::OneArgument, "rcp" },
399             { OpCode::Type::Arithmetic, OpCode::Info::OneArgument, "rsq" },
400             unknown_instruction,
401             unknown_instruction,
402             { OpCode::Type::Arithmetic, OpCode::Info::MOVA, "mova" },
403             { OpCode::Type::Arithmetic, OpCode::Info::OneArgument, "mov" },
404             unknown_instruction,
405             unknown_instruction,
406             unknown_instruction,
407             unknown_instruction,
408             { OpCode::Type::Arithmetic, OpCode::Info::TwoArguments | OpCode::Info::SrcInversed, "dphi" },
409             { OpCode::Type::Arithmetic, OpCode::Info::TwoArguments | OpCode::Info::SrcInversed, "dsti" },
410             { OpCode::Type::Arithmetic, OpCode::Info::TwoArguments | OpCode::Info::SrcInversed, "sgei" },
411             { OpCode::Type::Arithmetic, OpCode::Info::TwoArguments | OpCode::Info::SrcInversed, "slti" },
412             unknown_instruction,
413             unknown_instruction,
414             unknown_instruction,
415             unknown_instruction,
416             { OpCode::Type::Trivial, 0, "break" },
417             { OpCode::Type::Trivial, 0, "nop" },
418             { OpCode::Type::Trivial, 0, "end" },
419             { OpCode::Type::Conditional, OpCode::Info::BREAKC, "breakc" },
420             { OpCode::Type::Conditional, OpCode::Info::CALL, "call" },
421             { OpCode::Type::Conditional, OpCode::Info::CALLC, "callc" },
422             { OpCode::Type::UniformFlowControl, OpCode::Info::CALLU, "callu" },
423             { OpCode::Type::UniformFlowControl, OpCode::Info::IFU, "ifu" },
424             { OpCode::Type::Conditional, OpCode::Info::IFC, "ifc" },
425             { OpCode::Type::UniformFlowControl, OpCode::Info::LOOP, "loop" },
426             { OpCode::Type::Trivial, 0, "emit" },
427             { OpCode::Type::SetEmit, 0, "setemit" },
428             { OpCode::Type::Conditional, OpCode::Info::JMPC, "jmpc" },
429             { OpCode::Type::Conditional, OpCode::Info::JMPU, "jmpu" },
430             { OpCode::Type::Arithmetic, OpCode::Info::Compare, "cmp" },
431             { OpCode::Type::Arithmetic, OpCode::Info::Compare, "cmp" },
432             { OpCode::Type::MultiplyAdd, OpCode::Info::SrcInversed, "madi" },
433             { OpCode::Type::MultiplyAdd, OpCode::Info::SrcInversed, "madi" },
434             { OpCode::Type::MultiplyAdd, OpCode::Info::SrcInversed, "madi" },
435             { OpCode::Type::MultiplyAdd, OpCode::Info::SrcInversed, "madi" },
436             { OpCode::Type::MultiplyAdd, OpCode::Info::SrcInversed, "madi" },
437             { OpCode::Type::MultiplyAdd, OpCode::Info::SrcInversed, "madi" },
438             { OpCode::Type::MultiplyAdd, OpCode::Info::SrcInversed, "madi" },
439             { OpCode::Type::MultiplyAdd, OpCode::Info::SrcInversed, "madi" },
440             { OpCode::Type::MultiplyAdd, 0, "mad" },
441             { OpCode::Type::MultiplyAdd, 0, "mad" },
442             { OpCode::Type::MultiplyAdd, 0, "mad" },
443             { OpCode::Type::MultiplyAdd, 0, "mad" },
444             { OpCode::Type::MultiplyAdd, 0, "mad" },
445             { OpCode::Type::MultiplyAdd, 0, "mad" },
446             { OpCode::Type::MultiplyAdd, 0, "mad" },
447             { OpCode::Type::MultiplyAdd, 0, "mad" }
448         };
449         #undef unknown_instruction
450         return info_table[value];
451     }
452 
IdOpCode453     operator Id() const {
454         return static_cast<Id>(value);
455     }
456 
457     OpCode operator << (size_t bits) const {
458         return value << bits;
459     }
460 
461     template<typename T>
462     decltype(uint32_t{} - T{}) operator -(const T& oth) const {
463         return value - oth;
464     }
465 
466     uint32_t operator &(const OpCode& oth) const {
467         return value & oth.value;
468     }
469 
470     uint32_t operator ~() const {
471         return ~value;
472     }
473 
474 private:
475     uint32_t value;
476 };
477 
478 } // namespace nihstro
479 
480 namespace std {
481     template<>
482     struct make_unsigned<nihstro::SourceRegister> {
483         using type = nihstro::SourceRegister;
484     };
485 
486     template<>
487     struct make_unsigned<nihstro::DestRegister> {
488         using type = nihstro::DestRegister;
489     };
490 
491     template<>
492     struct make_unsigned<nihstro::OpCode> {
493         using type = nihstro::OpCode;
494     };
495 }
496 
497 namespace nihstro {
498 
499 #pragma pack(1)
500 union Instruction {
501     Instruction& operator =(const Instruction& instr) {
502         hex = instr.hex;
503         return *this;
504     }
505 
506     uint32_t hex;
507 
508     BitField<0x1a, 0x6, OpCode> opcode;
509 
510 
511     // General notes:
512     //
513     // When two input registers are used, one of them uses a 5-bit index while the other
514     // one uses a 7-bit index. This is because at most one floating point uniform may be used
515     // as an input.
516 
517 
518     // Format used e.g. by arithmetic instructions and comparisons
519     union Common { // TODO: Remove name
520         BitField<0x00, 0x7, uint32_t> operand_desc_id;
521 
522         const SourceRegister GetSrc1(bool is_inverted) const {
523             if (!is_inverted) {
524                 return src1;
525             } else {
526                 return src1i;
527             }
528         }
529 
530         const SourceRegister GetSrc2(bool is_inverted) const {
531             if (!is_inverted) {
532                 return src2;
533             } else {
534                 return src2i;
535             }
536         }
537 
538         /**
539          * Source inputs may be reordered for certain instructions.
540          * Use GetSrc1 and GetSrc2 instead to access the input register indices hence.
541          */
542         BitField<0x07, 0x5, SourceRegister> src2;
543         BitField<0x0c, 0x7, SourceRegister> src1;
544         BitField<0x07, 0x7, SourceRegister> src2i;
545         BitField<0x0e, 0x5, SourceRegister> src1i;
546 
547         // Address register value is used for relative addressing of src1 / src2 (inverted)
548         BitField<0x13, 0x2, uint32_t> address_register_index;
549 
550         union CompareOpType {  // TODO: Make nameless once MSVC supports it
551             enum Op : uint32_t {
552                 Equal        = 0,
553                 NotEqual     = 1,
554                 LessThan     = 2,
555                 LessEqual    = 3,
556                 GreaterThan  = 4,
557                 GreaterEqual = 5,
558                 Unk6         = 6,
559                 Unk7         = 7
560             };
561 
562             BitField<0x15, 0x3, Op> y;
563             BitField<0x18, 0x3, Op> x;
564 
565             const std::string ToString(Op op) const {
566                 switch (op) {
567                 case Equal:        return "==";
568                 case NotEqual:     return "!=";
569                 case LessThan:     return "<";
570                 case LessEqual:    return "<=";
571                 case GreaterThan:  return ">";
572                 case GreaterEqual: return ">=";
573                 case Unk6:         return "UNK6";
574                 case Unk7:         return "UNK7";
575                 default:           return "";
576                 };
577             }
578         } compare_op;
579 
580         std::string AddressRegisterName() const {
581             if (address_register_index == 0) return "";
582             else if (address_register_index == 1) return "a0.x";
583             else if (address_register_index == 2) return "a0.y";
584             else /*if (address_register_index == 3)*/ return "aL";
585         }
586 
587         BitField<0x15, 0x5, DestRegister> dest;
588     } common;
589 
590     union FlowControlType {  // TODO: Make nameless once MSVC supports it
591         enum Op : uint32_t {
592             Or    = 0,
593             And   = 1,
594             JustX = 2,
595             JustY = 3
596         };
597 
598         BitField<0x00, 0x8, uint32_t> num_instructions;
599         BitField<0x0a, 0xc, uint32_t> dest_offset;
600 
601         BitField<0x16, 0x2, Op> op;
602         BitField<0x16, 0x4, uint32_t> bool_uniform_id;
603         BitField<0x16, 0x2, uint32_t> int_uniform_id; // TODO: Verify that only this many bits are used...
604 
605         BitFlag<0x18, uint32_t> refy;
606         BitFlag<0x19, uint32_t> refx;
607     } flow_control;
608 
609     union {
610         const SourceRegister GetSrc1(bool is_inverted) const {
611             // The inverted form for src1 is the same, this function is just here for consistency
612             return src1;
613         }
614 
615         const SourceRegister GetSrc2(bool is_inverted) const {
616             if (!is_inverted) {
617                 return src2;
618             } else {
619                 return src2i;
620             }
621         }
622 
623         const SourceRegister GetSrc3(bool is_inverted) const {
624             if (!is_inverted) {
625                 return src3;
626             } else {
627                 return src3i;
628             }
629         }
630 
631         BitField<0x00, 0x5, uint32_t> operand_desc_id;
632 
633         BitField<0x05, 0x5, SourceRegister> src3;
634         BitField<0x0a, 0x7, SourceRegister> src2;
635         BitField<0x11, 0x5, SourceRegister> src1;
636 
637         BitField<0x05, 0x7, SourceRegister> src3i;
638         BitField<0x0c, 0x5, SourceRegister> src2i;
639 
640         // Address register value is used for relative addressing of src2 / src3 (inverted)
641         BitField<0x16, 0x2, uint32_t> address_register_index;
642 
643         std::string AddressRegisterName() const {
644             if (address_register_index == 0) return "";
645             else if (address_register_index == 1) return "a0.x";
646             else if (address_register_index == 2) return "a0.y";
647             else /*if (address_register_index == 3)*/ return "aL";
648         }
649 
650         BitField<0x18, 0x5, DestRegister> dest;
651     } mad;
652 
653     union {
654         BitField<0x16, 1, uint32_t> winding;
655         BitField<0x17, 1, uint32_t> prim_emit;
656         BitField<0x18, 2, uint32_t> vertex_id;
657     } setemit;
658 };
659 static_assert(sizeof(Instruction) == 0x4, "Incorrect structure size");
660 static_assert(std::is_standard_layout<Instruction>::value, "Structure does not have standard layout");
661 
662 union SwizzlePattern {
663     SwizzlePattern& operator =(const SwizzlePattern& instr) {
664         hex = instr.hex;
665         return *this;
666     }
667 
668     uint32_t hex;
669 
670     enum class Selector : uint32_t {
671         x = 0,
672         y = 1,
673         z = 2,
674         w = 3
675     };
676 
677     /**
678      * Gets the raw 8-bit selector for the specified (1-indexed) source register.
679      */
680     unsigned GetRawSelector(unsigned src) const {
681         if (src == 0 || src > 3)
682             throw std::out_of_range("src needs to be between 1 and 3");
683 
684         unsigned selectors[] = {
685             src1_selector, src2_selector, src3_selector
686         };
687         return selectors[src - 1];
688     }
689 
690     Selector GetSelectorSrc1(int comp) const {
691         Selector selectors[] = {
692             src1_selector_0, src1_selector_1, src1_selector_2, src1_selector_3
693         };
694         return selectors[comp];
695     }
696 
697     Selector GetSelectorSrc2(int comp) const {
698         Selector selectors[] = {
699             src2_selector_0, src2_selector_1, src2_selector_2, src2_selector_3
700         };
701         return selectors[comp];
702     }
703 
704     Selector GetSelectorSrc3(int comp) const {
705         Selector selectors[] = {
706             src3_selector_0, src3_selector_1, src3_selector_2, src3_selector_3
707         };
708         return selectors[comp];
709     }
710 
711     void SetSelectorSrc1(int comp, Selector value) {
712         if (comp == 0)
713             src1_selector_0 = value;
714         else if (comp == 1)
715             src1_selector_1 = value;
716         else if (comp == 2)
717             src1_selector_2 = value;
718         else if (comp == 3)
719             src1_selector_3 = value;
720         else
721             throw std::out_of_range("comp needs to be smaller than 4");
722     }
723 
724     void SetSelectorSrc2(int comp, Selector value) {
725         if (comp == 0)
726             src2_selector_0 = value;
727         else if (comp == 1)
728             src2_selector_1 = value;
729         else if (comp == 2)
730             src2_selector_2 = value;
731         else if (comp == 3)
732             src2_selector_3 = value;
733         else
734             throw std::out_of_range("comp needs to be smaller than 4");
735     }
736 
737     void SetSelectorSrc3(int comp, Selector value) {
738         if (comp == 0)
739             src3_selector_0 = value;
740         else if (comp == 1)
741             src3_selector_1 = value;
742         else if (comp == 2)
743             src3_selector_2 = value;
744         else if (comp == 3)
745             src3_selector_3 = value;
746         else
747             throw std::out_of_range("comp needs to be smaller than 4");
748     }
749 
750     std::string SelectorToString(bool src2) const {
751         std::map<Selector, std::string> map = {
752             { Selector::x, "x" },
753             { Selector::y, "y" },
754             { Selector::z, "z" },
755             { Selector::w, "w" }
756         };
757         std::string ret;
758         for (int i = 0; i < 4; ++i) {
759             ret += map.at(src2 ? GetSelectorSrc2(i) : GetSelectorSrc1(i));
760         }
761         return ret;
762     }
763 
764     bool DestComponentEnabled(unsigned int i) const {
765         return (dest_mask & (0x8 >> i)) != 0;
766     }
767 
768     void SetDestComponentEnabled(unsigned int i, bool enabled) {
769         int mask = 0xffff & (0x8 >> i);
770         dest_mask = (dest_mask & ~mask) | (enabled * mask);
771     }
772 
773     std::string DestMaskToString() const {
774         std::string ret;
775         for (int i = 0; i < 4; ++i) {
776             if (!DestComponentEnabled(i))
777                 ret += "_";
778             else
779                 ret += "xyzw"[i];
780         }
781         return ret;
782     }
783 
784     // Components of "dest" that should be written to: LSB=dest.w, MSB=dest.x
785     BitField< 0, 4, uint32_t> dest_mask;
786 
787     BitFlag < 4,    uint32_t> negate_src1;
788     BitField< 5, 8, uint32_t> src1_selector;
789     BitField< 5, 2, Selector> src1_selector_3;
790     BitField< 7, 2, Selector> src1_selector_2;
791     BitField< 9, 2, Selector> src1_selector_1;
792     BitField<11, 2, Selector> src1_selector_0;
793 
794     BitFlag <13,    uint32_t> negate_src2;
795     BitField<14, 8, uint32_t> src2_selector;
796     BitField<14, 2, Selector> src2_selector_3;
797     BitField<16, 2, Selector> src2_selector_2;
798     BitField<18, 2, Selector> src2_selector_1;
799     BitField<20, 2, Selector> src2_selector_0;
800 
801     BitFlag <22,    uint32_t> negate_src3;
802     BitField<23, 8, uint32_t> src3_selector;
803     BitField<23, 2, Selector> src3_selector_3;
804     BitField<25, 2, Selector> src3_selector_2;
805     BitField<27, 2, Selector> src3_selector_1;
806     BitField<29, 2, Selector> src3_selector_0;
807 };
808 static_assert(sizeof(SwizzlePattern) == 0x4, "Incorrect structure size");
809 
810 
811 #pragma pack()
812 
813 } // namespace
814