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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <array>
#include <cstddef>
#include <optional>
#include <string_view>
#include <vector>
#include "Common/Assembler/AssemblerShared.h"
#include "Common/Assembler/CaseInsensitiveDict.h"
#include "Common/CommonTypes.h"
namespace Common::GekkoAssembler::detail
{
///////////////////
// PARSER TABLES //
///////////////////
enum class ParseAlg
{
None,
Op1,
NoneOrOp1,
Op1Off1,
Op2,
Op1Or2,
Op3,
Op2Or3,
Op4,
Op5,
Op1Off1Op2,
};
struct ParseInfo
{
size_t mnemonic_index;
ParseAlg parse_algorithm;
};
// Mapping of SPRG names to values
extern const CaseInsensitiveDict<u32, '_'> sprg_map;
// Mapping of directive names to an enumeration
extern const CaseInsensitiveDict<GekkoDirective> directives_map;
// Mapping of normal Gekko mnemonics to their index and argument form
extern const CaseInsensitiveDict<ParseInfo, '.', '_'> mnemonic_tokens;
// Mapping of extended Gekko mnemonics to their index and argument form
extern const CaseInsensitiveDict<ParseInfo, '.', '_', '+', '-'> extended_mnemonic_tokens;
//////////////////////
// ASSEMBLER TABLES //
//////////////////////
constexpr size_t MAX_OPERANDS = 5;
struct OperandList
{
std::array<Tagged<Interval, u32>, MAX_OPERANDS> list;
u32 count;
bool overfill;
constexpr u32 operator[](size_t index) const { return ValueOf(list[index]); }
constexpr u32& operator[](size_t index) { return ValueOf(list[index]); }
void Insert(size_t before, u32 val);
template <typename It>
void Copy(It begin, It end)
{
count = 0;
for (auto& i : list)
{
if (begin == end)
{
break;
}
i = *begin;
begin++;
count++;
}
overfill = begin != end;
}
};
struct OperandDesc
{
u32 mask;
struct
{
u32 shift : 31;
bool is_signed : 1;
};
u32 MaxVal() const;
u32 MinVal() const;
u32 TruncBits() const;
bool Fits(u32 val) const;
u32 Fit(u32 val) const;
};
// MnemonicDesc holds the machine-code template for mnemonics
struct MnemonicDesc
{
// Initial value for a given mnemonic (opcode, func code, LK, AA, OE)
const u32 initial_value;
const u32 operand_count;
// Masks for operands
std::array<OperandDesc, MAX_OPERANDS> operand_masks;
};
// ExtendedMnemonicDesc holds the name of the mnemonic it transforms to as well as a
// transformer callback to translate the operands into the correct form for the base mnemonic
struct ExtendedMnemonicDesc
{
size_t mnemonic_index;
void (*transform_operands)(OperandList&);
};
static constexpr size_t NUM_MNEMONICS = static_cast<size_t>(GekkoMnemonic::LastMnemonic) + 1;
static constexpr size_t NUM_EXT_MNEMONICS =
static_cast<size_t>(ExtendedGekkoMnemonic::LastMnemonic) + 1;
static constexpr size_t VARIANT_PERMUTATIONS = 4;
// Table for mapping mnemonic+variants to their descriptors
extern const std::array<MnemonicDesc, NUM_MNEMONICS * VARIANT_PERMUTATIONS> mnemonics;
// Table for mapping extended mnemonic+variants to their descriptors
extern const std::array<ExtendedMnemonicDesc, NUM_EXT_MNEMONICS * VARIANT_PERMUTATIONS>
extended_mnemonics;
//////////////////
// LEXER TABLES //
//////////////////
// In place of the reliace on std::regex, DFAs will be defined for matching sufficiently complex
// tokens This gives an extra benefit of providing reasons for match failures
using TransitionF = bool (*)(char c);
using DfaEdge = std::pair<TransitionF, size_t>;
struct DfaNode
{
std::vector<DfaEdge> edges;
// If nullopt: this is a final node
// If string: invalid reason
std::optional<std::string_view> match_failure_reason;
};
// Floating point strings that will be accepted by std::stof/std::stod
// regex: [\+-]?(\d+(\.\d+)?|\.\d+)(e[\+-]?\d+)?
extern const std::vector<DfaNode> float_dfa;
// C-style strings
// regex: "([^\\\n]|\\([0-7]{1,3}|x[0-9a-fA-F]+|[^x0-7\n]))*"
extern const std::vector<DfaNode> string_dfa;
} // namespace Common::GekkoAssembler::detail
|