summaryrefslogtreecommitdiffstats
path: root/src/shader_recompiler/frontend/maxwell/translate/translate.cpp
blob: dcc3f6c0ede489d286455bc17bbf3212989d2f0b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

#include "shader_recompiler/environment.h"
#include "shader_recompiler/frontend/ir/basic_block.h"
#include "shader_recompiler/frontend/maxwell/decode.h"
#include "shader_recompiler/frontend/maxwell/location.h"
#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
#include "shader_recompiler/frontend/maxwell/translate/translate.h"

namespace Shader::Maxwell {

template <auto visitor_method>
static void Invoke(TranslatorVisitor& visitor, Location pc, u64 insn) {
    using MethodType = decltype(visitor_method);
    if constexpr (std::is_invocable_r_v<void, MethodType, TranslatorVisitor&, Location, u64>) {
        (visitor.*visitor_method)(pc, insn);
    } else if constexpr (std::is_invocable_r_v<void, MethodType, TranslatorVisitor&, u64>) {
        (visitor.*visitor_method)(insn);
    } else {
        (visitor.*visitor_method)();
    }
}

IR::Block Translate(ObjectPool<IR::Inst>& inst_pool, Environment& env,
                    const Flow::Block& flow_block) {
    IR::Block block{inst_pool, flow_block.begin.Offset(), flow_block.end.Offset()};
    TranslatorVisitor visitor{env, block};

    const Location pc_end{flow_block.end};
    Location pc{flow_block.begin};
    while (pc != pc_end) {
        const u64 insn{env.ReadInstruction(pc.Offset())};
        const Opcode opcode{Decode(insn)};
        switch (opcode) {
#define INST(name, cute, mask)                                                                     \
    case Opcode::name:                                                                             \
        Invoke<&TranslatorVisitor::name>(visitor, pc, insn);                                       \
        break;
#include "shader_recompiler/frontend/maxwell/maxwell.inc"
#undef OPCODE
        default:
            throw LogicError("Invalid opcode {}", opcode);
        }
        ++pc;
    }
    return block;
}

} // namespace Shader::Maxwell