diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index a710c4bc53a1694f418a6527f8a3af9357790ffe..4defb578633c365f904130874f63616bed3b4d90 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -9,6 +9,7 @@ add_library(video_core STATIC
     engines/maxwell_3d.h
     engines/maxwell_compute.cpp
     engines/maxwell_compute.h
+    engines/shader_bytecode.h
     gpu.cpp
     gpu.h
     macro_interpreter.cpp
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
new file mode 100644
index 0000000000000000000000000000000000000000..6660742ccfb44b7dda5230bedeec2c5154a7a2ce
--- /dev/null
+++ b/src/video_core/engines/shader_bytecode.h
@@ -0,0 +1,297 @@
+// Copyright 2018 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <map>
+#include <string>
+#include "common/bit_field.h"
+
+namespace Tegra {
+namespace Shader {
+
+struct Register {
+    constexpr Register() = default;
+
+    constexpr Register(u64 value) : value(value) {}
+
+    constexpr u64 GetIndex() const {
+        return value;
+    }
+
+    constexpr operator u64() const {
+        return value;
+    }
+
+    template <typename T>
+    constexpr u64 operator-(const T& oth) const {
+        return value - oth;
+    }
+
+    template <typename T>
+    constexpr u64 operator&(const T& oth) const {
+        return value & oth;
+    }
+
+    constexpr u64 operator&(const Register& oth) const {
+        return value & oth.value;
+    }
+
+    constexpr u64 operator~() const {
+        return ~value;
+    }
+
+private:
+    u64 value;
+};
+
+union Attribute {
+    constexpr Attribute() = default;
+
+    constexpr Attribute(u64 value) : value(value) {}
+
+    enum class Index : u64 {
+        Position = 7,
+        Attribute_0 = 8,
+    };
+
+    constexpr Index GetIndex() const {
+        return index;
+    }
+
+public:
+    BitField<24, 6, Index> index;
+    BitField<22, 2, u64> element;
+    BitField<39, 8, u64> reg;
+    BitField<47, 3, u64> size;
+    u64 value;
+};
+
+union Uniform {
+    BitField<20, 14, u64> offset;
+    BitField<34, 5, u64> index;
+};
+
+union OpCode {
+    enum class Id : u64 {
+        TEXS = 0x6C,
+        IPA = 0xE0,
+        FFMA_IMM = 0x65,
+        FFMA_CR = 0x93,
+        FFMA_RC = 0xA3,
+        FFMA_RR = 0xB3,
+
+        FADD_C = 0x98B,
+        FMUL_C = 0x98D,
+        MUFU = 0xA10,
+        FADD_R = 0xB8B,
+        FMUL_R = 0xB8D,
+        LD_A = 0x1DFB,
+        ST_A = 0x1DFE,
+
+        FSETP_R = 0x5BB,
+        FSETP_C = 0x4BB,
+        EXIT = 0xE30,
+        KIL = 0xE33,
+
+        FMUL_IMM = 0x70D,
+        FMUL_IMM_x = 0x72D,
+        FADD_IMM = 0x70B,
+        FADD_IMM_x = 0x72B,
+    };
+
+    enum class Type {
+        Trivial,
+        Arithmetic,
+        Flow,
+        Memory,
+        Unknown,
+    };
+
+    struct Info {
+        Type type;
+        std::string name;
+    };
+
+    constexpr OpCode() = default;
+
+    constexpr OpCode(Id value) : value(static_cast<u64>(value)) {}
+
+    constexpr OpCode(u64 value) : value{value} {}
+
+    constexpr Id EffectiveOpCode() const {
+        switch (op1) {
+        case Id::TEXS:
+            return op1;
+        }
+
+        switch (op2) {
+        case Id::IPA:
+            return op2;
+        }
+
+        switch (op3) {
+        case Id::FFMA_IMM:
+        case Id::FFMA_CR:
+        case Id::FFMA_RC:
+        case Id::FFMA_RR:
+            return op3;
+        }
+
+        switch (op4) {
+        case Id::EXIT:
+        case Id::FSETP_R:
+        case Id::FSETP_C:
+        case Id::KIL:
+            return op4;
+        }
+
+        switch (op5) {
+        case Id::MUFU:
+        case Id::LD_A:
+        case Id::ST_A:
+        case Id::FADD_R:
+        case Id::FADD_C:
+        case Id::FMUL_R:
+        case Id::FMUL_C:
+            return op5;
+
+        case Id::FMUL_IMM:
+        case Id::FMUL_IMM_x:
+            return Id::FMUL_IMM;
+
+        case Id::FADD_IMM:
+        case Id::FADD_IMM_x:
+            return Id::FADD_IMM;
+        }
+
+        return static_cast<Id>(value);
+    }
+
+    static const Info& GetInfo(const OpCode& opcode) {
+        static const std::map<Id, Info> info_table{BuildInfoTable()};
+        const auto& search{info_table.find(opcode.EffectiveOpCode())};
+        if (search != info_table.end()) {
+            return search->second;
+        }
+
+        static const Info unknown{Type::Unknown, "UNK"};
+        return unknown;
+    }
+
+    constexpr operator Id() const {
+        return static_cast<Id>(value);
+    }
+
+    constexpr OpCode operator<<(size_t bits) const {
+        return value << bits;
+    }
+
+    constexpr OpCode operator>>(size_t bits) const {
+        return value >> bits;
+    }
+
+    template <typename T>
+    constexpr u64 operator-(const T& oth) const {
+        return value - oth;
+    }
+
+    constexpr u64 operator&(const OpCode& oth) const {
+        return value & oth.value;
+    }
+
+    constexpr u64 operator~() const {
+        return ~value;
+    }
+
+    static std::map<Id, Info> BuildInfoTable() {
+        std::map<Id, Info> info_table;
+        info_table[Id::TEXS] = {Type::Memory, "texs"};
+        info_table[Id::LD_A] = {Type::Memory, "ld_a"};
+        info_table[Id::ST_A] = {Type::Memory, "st_a"};
+        info_table[Id::IPA] = {Type::Arithmetic, "ipa"};
+        info_table[Id::MUFU] = {Type::Arithmetic, "mufu"};
+        info_table[Id::FFMA_IMM] = {Type::Arithmetic, "ffma_imm"};
+        info_table[Id::FFMA_CR] = {Type::Arithmetic, "ffma_cr"};
+        info_table[Id::FFMA_RC] = {Type::Arithmetic, "ffma_rc"};
+        info_table[Id::FFMA_RR] = {Type::Arithmetic, "ffma_rr"};
+        info_table[Id::FADD_R] = {Type::Arithmetic, "fadd_r"};
+        info_table[Id::FADD_C] = {Type::Arithmetic, "fadd_c"};
+        info_table[Id::FADD_IMM] = {Type::Arithmetic, "fadd_imm"};
+        info_table[Id::FMUL_R] = {Type::Arithmetic, "fmul_r"};
+        info_table[Id::FMUL_C] = {Type::Arithmetic, "fmul_c"};
+        info_table[Id::FMUL_IMM] = {Type::Arithmetic, "fmul_imm"};
+        info_table[Id::EXIT] = {Type::Trivial, "exit"};
+        return info_table;
+    }
+
+    BitField<57, 7, Id> op1;
+    BitField<56, 8, Id> op2;
+    BitField<55, 9, Id> op3;
+    BitField<52, 12, Id> op4;
+    BitField<51, 13, Id> op5;
+    u64 value;
+};
+static_assert(sizeof(OpCode) == 0x8, "Incorrect structure size");
+
+} // namespace Shader
+} // namespace Tegra
+
+namespace std {
+
+template <>
+struct make_unsigned<Tegra::Shader::Attribute> {
+    using type = Tegra::Shader::Attribute;
+};
+
+template <>
+struct make_unsigned<Tegra::Shader::Register> {
+    using type = Tegra::Shader::Register;
+};
+
+template <>
+struct make_unsigned<Tegra::Shader::OpCode> {
+    using type = Tegra::Shader::OpCode;
+};
+
+} // namespace std
+
+namespace Tegra {
+namespace Shader {
+
+enum class Pred : u64 {
+    UnusedIndex = 0x7,
+    NeverExecute = 0xf,
+};
+
+#pragma pack(1)
+union Instruction {
+    Instruction& operator=(const Instruction& instr) {
+        hex = instr.hex;
+        return *this;
+    }
+
+    OpCode opcode;
+    BitField<0, 8, Register> gpr1;
+    BitField<8, 8, Register> gpr2;
+    BitField<16, 4, Pred> pred;
+    BitField<39, 8, Register> gpr3;
+    BitField<45, 1, u64> nb;
+    BitField<46, 1, u64> aa;
+    BitField<48, 1, u64> na;
+    BitField<49, 1, u64> ab;
+    BitField<50, 1, u64> ad;
+    Attribute attribute;
+    Uniform uniform;
+
+    u64 hex;
+};
+static_assert(sizeof(Instruction) == 0x8, "Incorrect structure size");
+static_assert(std::is_standard_layout<Instruction>::value,
+              "Structure does not have standard layout");
+
+#pragma pack()
+
+} // namespace Shader
+} // namespace Tegra