mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2024-11-14 05:17:40 -07:00
are you really this much of a derp, Arisotura
This commit is contained in:
parent
22d2b612b8
commit
c60840b7b8
4546
src/teakra/src/InstrDecode.cpp
Normal file
4546
src/teakra/src/InstrDecode.cpp
Normal file
File diff suppressed because it is too large
Load Diff
4543
src/teakra/src/InstrDecode.h
Normal file
4543
src/teakra/src/InstrDecode.h
Normal file
File diff suppressed because it is too large
Load Diff
24596
src/teakra/src/InstrTable.h
Normal file
24596
src/teakra/src/InstrTable.h
Normal file
File diff suppressed because it is too large
Load Diff
700
src/teakra/src/interp_operand.h
Normal file
700
src/teakra/src/interp_operand.h
Normal file
@ -0,0 +1,700 @@
|
||||
#pragma once
|
||||
#include "common_types.h"
|
||||
|
||||
template <typename T, T... values>
|
||||
inline constexpr bool NoOverlap = (values + ...) == (values | ...);
|
||||
|
||||
template <unsigned bits>
|
||||
struct Operand {
|
||||
static_assert(bits > 0 && bits <= 16);
|
||||
static constexpr unsigned Bits = bits;
|
||||
|
||||
public:
|
||||
u16 storage{};
|
||||
|
||||
template <typename OperandT, unsigned pos>
|
||||
friend struct At;
|
||||
|
||||
template <typename OperandT, u16 value>
|
||||
friend struct Const;
|
||||
};
|
||||
|
||||
template <typename OperandT, unsigned pos>
|
||||
struct At {
|
||||
static constexpr unsigned Bits = OperandT::Bits;
|
||||
static_assert((Bits < 16 && pos < 16 && Bits + pos <= 16) || (Bits == 16 && pos == 16));
|
||||
static constexpr u16 Mask = (((1 << Bits) - 1) << pos) & 0xFFFF;
|
||||
static constexpr bool NeedExpansion = pos == 16;
|
||||
static constexpr bool PassAsParameter = true;
|
||||
using FilterResult = OperandT;
|
||||
static constexpr OperandT Extract(u16 opcode, u16 expansion) {
|
||||
OperandT operand{};
|
||||
if (NeedExpansion)
|
||||
operand.storage = expansion;
|
||||
else
|
||||
operand.storage = (u16)((opcode & Mask) >> pos);
|
||||
return operand;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename OperandT, unsigned pos>
|
||||
struct AtNamed {
|
||||
using BaseType = At<OperandT, pos>;
|
||||
static constexpr unsigned Bits = BaseType::Bits;
|
||||
static constexpr u16 Mask = BaseType::Mask;
|
||||
static constexpr bool NeedExpansion = BaseType::NeedExpansion;
|
||||
static constexpr bool PassAsParameter = BaseType::PassAsParameter;
|
||||
using FilterResult = typename BaseType::FilterResult::NameType;
|
||||
static constexpr auto Extract(u16 opcode, u16 expansion) {
|
||||
return BaseType::Extract(opcode, expansion).GetName();
|
||||
}
|
||||
};
|
||||
|
||||
template <unsigned pos>
|
||||
struct Unused {
|
||||
static_assert(pos < 16);
|
||||
static constexpr u16 Mask = 1 << pos;
|
||||
static constexpr bool NeedExpansion = false;
|
||||
static constexpr bool PassAsParameter = false;
|
||||
};
|
||||
|
||||
template <typename OperandT, u16 value>
|
||||
struct Const {
|
||||
static constexpr u16 Mask = 0;
|
||||
static constexpr bool NeedExpansion = false;
|
||||
static constexpr bool PassAsParameter = true;
|
||||
using FilterResult = OperandT;
|
||||
static constexpr OperandT Extract(u16, u16) {
|
||||
OperandT operand{};
|
||||
operand.storage = value;
|
||||
return operand;
|
||||
}
|
||||
};
|
||||
|
||||
enum class SumBase {
|
||||
Zero,
|
||||
Acc,
|
||||
Sv,
|
||||
SvRnd,
|
||||
};
|
||||
|
||||
template <typename T, T value>
|
||||
struct Cn {
|
||||
static constexpr u16 Mask = 0;
|
||||
static constexpr bool NeedExpansion = false;
|
||||
static constexpr bool PassAsParameter = true;
|
||||
using FilterResult = T;
|
||||
static constexpr T Extract(u16, u16) {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
using SX = Cn<bool, true>;
|
||||
using UX = Cn<bool, false>;
|
||||
using SY = Cn<bool, true>;
|
||||
using UY = Cn<bool, false>;
|
||||
using BZr = Cn<SumBase, SumBase::Zero>;
|
||||
using BAc = Cn<SumBase, SumBase::Acc>;
|
||||
using BSv = Cn<SumBase, SumBase::Sv>;
|
||||
using BSr = Cn<SumBase, SumBase::SvRnd>;
|
||||
using PA = Cn<bool, true>;
|
||||
using PP = Cn<bool, false>;
|
||||
using Sub = Cn<bool, true>;
|
||||
using Add = Cn<bool, false>;
|
||||
using EMod = Cn<bool, false>;
|
||||
using DMod = Cn<bool, true>;
|
||||
|
||||
template <typename OperandT, unsigned pos, u16 value>
|
||||
struct AtConst {
|
||||
using Base = At<OperandT, pos>;
|
||||
static_assert(Base::NeedExpansion == false, "");
|
||||
static constexpr u16 Mask = Base::Mask;
|
||||
static constexpr u16 Pad = value << pos;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
constexpr unsigned intlog2(unsigned n) {
|
||||
if (n % 2 != 0)
|
||||
throw "wtf";
|
||||
return (n == 2) ? 1 : 1 + intlog2(n / 2);
|
||||
}
|
||||
|
||||
template <typename EnumT, EnumT... names>
|
||||
struct EnumOperand : Operand<intlog2(sizeof...(names))> {
|
||||
using NameType = EnumT;
|
||||
static constexpr EnumT values[] = {names...};
|
||||
constexpr EnumT GetName() const {
|
||||
return values[this->storage];
|
||||
}
|
||||
};
|
||||
|
||||
template <typename EnumT>
|
||||
struct EnumAllOperand : Operand<intlog2((unsigned)EnumT::EnumEnd)> {
|
||||
using NameType = EnumT;
|
||||
constexpr EnumT GetName() const {
|
||||
return (EnumT)this->storage;
|
||||
}
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
|
||||
enum class RegName {
|
||||
a0, a0l, a0h, a0e,
|
||||
a1, a1l, a1h, a1e,
|
||||
b0, b0l, b0h, b0e,
|
||||
b1, b1l, b1h, b1e,
|
||||
|
||||
r0, r1, r2, r3, r4, r5, r6, r7,
|
||||
|
||||
y0, p,
|
||||
|
||||
pc, sp, sv, lc,
|
||||
|
||||
ar0, ar1,
|
||||
arp0, arp1, arp2, arp3,
|
||||
|
||||
ext0, ext1, ext2, ext3,
|
||||
|
||||
stt0, stt1, stt2,
|
||||
st0, st1, st2,
|
||||
cfgi, cfgj,
|
||||
mod0, mod1, mod2, mod3,
|
||||
|
||||
undefine,
|
||||
};
|
||||
|
||||
template <RegName ... reg_names>
|
||||
using RegOperand = EnumOperand <RegName, reg_names...>;
|
||||
|
||||
struct Register : RegOperand<
|
||||
RegName::r0,
|
||||
RegName::r1,
|
||||
RegName::r2,
|
||||
RegName::r3,
|
||||
RegName::r4,
|
||||
RegName::r5,
|
||||
RegName::r7,
|
||||
RegName::y0,
|
||||
RegName::st0,
|
||||
RegName::st1,
|
||||
RegName::st2,
|
||||
RegName::p, // take special care of this as src operand
|
||||
RegName::pc,
|
||||
RegName::sp,
|
||||
RegName::cfgi,
|
||||
RegName::cfgj,
|
||||
RegName::b0h,
|
||||
RegName::b1h,
|
||||
RegName::b0l,
|
||||
RegName::b1l,
|
||||
RegName::ext0,
|
||||
RegName::ext1,
|
||||
RegName::ext2,
|
||||
RegName::ext3,
|
||||
RegName::a0, // take special care of this as src operand
|
||||
RegName::a1, // take special care of this as src operand
|
||||
RegName::a0l,
|
||||
RegName::a1l,
|
||||
RegName::a0h,
|
||||
RegName::a1h,
|
||||
RegName::lc,
|
||||
RegName::sv
|
||||
> {
|
||||
// only used in mov(Register, Register)
|
||||
constexpr RegName GetNameForMovFromP() {
|
||||
return (this->storage & 1) ? RegName::a1 : RegName::a0;
|
||||
}
|
||||
};
|
||||
struct Ax : RegOperand<
|
||||
RegName::a0,
|
||||
RegName::a1
|
||||
> {};
|
||||
struct Axl : RegOperand<
|
||||
RegName::a0l,
|
||||
RegName::a1l
|
||||
> {};
|
||||
struct Axh : RegOperand<
|
||||
RegName::a0h,
|
||||
RegName::a1h
|
||||
> {};
|
||||
struct Bx : RegOperand<
|
||||
RegName::b0,
|
||||
RegName::b1
|
||||
> {};
|
||||
struct Bxl : RegOperand<
|
||||
RegName::b0l,
|
||||
RegName::b1l
|
||||
> {};
|
||||
struct Bxh : RegOperand<
|
||||
RegName::b0h,
|
||||
RegName::b1h
|
||||
> {};
|
||||
struct Px : Operand<1> {
|
||||
constexpr Px() = default;
|
||||
constexpr Px(u16 index) {
|
||||
this->storage = index;
|
||||
}
|
||||
constexpr u16 Index() const {
|
||||
return this->storage;
|
||||
}
|
||||
};
|
||||
struct Ab : RegOperand<
|
||||
RegName::b0,
|
||||
RegName::b1,
|
||||
RegName::a0,
|
||||
RegName::a1
|
||||
> {};
|
||||
struct Abl : RegOperand<
|
||||
RegName::b0l,
|
||||
RegName::b1l,
|
||||
RegName::a0l,
|
||||
RegName::a1l
|
||||
> {};
|
||||
struct Abh : RegOperand<
|
||||
RegName::b0h,
|
||||
RegName::b1h,
|
||||
RegName::a0h,
|
||||
RegName::a1h
|
||||
> {};
|
||||
struct Abe : RegOperand<
|
||||
RegName::b0e,
|
||||
RegName::b1e,
|
||||
RegName::a0e,
|
||||
RegName::a1e
|
||||
> {};
|
||||
struct Ablh : RegOperand<
|
||||
RegName::b0l,
|
||||
RegName::b0h,
|
||||
RegName::b1l,
|
||||
RegName::b1h,
|
||||
RegName::a0l,
|
||||
RegName::a0h,
|
||||
RegName::a1l,
|
||||
RegName::a1h
|
||||
> {};
|
||||
struct RnOld : RegOperand<
|
||||
RegName::r0,
|
||||
RegName::r1,
|
||||
RegName::r2,
|
||||
RegName::r3,
|
||||
RegName::r4,
|
||||
RegName::r5,
|
||||
RegName::r7,
|
||||
RegName::y0
|
||||
> {};
|
||||
struct Rn : RegOperand<
|
||||
RegName::r0,
|
||||
RegName::r1,
|
||||
RegName::r2,
|
||||
RegName::r3,
|
||||
RegName::r4,
|
||||
RegName::r5,
|
||||
RegName::r6,
|
||||
RegName::r7
|
||||
> {
|
||||
constexpr Rn() = default;
|
||||
constexpr Rn(u16 index) {
|
||||
this->storage = index;
|
||||
}
|
||||
constexpr u16 Index() const {
|
||||
return this->storage;
|
||||
}
|
||||
};
|
||||
|
||||
struct R45 : RegOperand<
|
||||
RegName::r4,
|
||||
RegName::r5
|
||||
> {
|
||||
constexpr u16 Index() const {
|
||||
return this->storage + 4;
|
||||
}
|
||||
};
|
||||
|
||||
struct R0123 : RegOperand<
|
||||
RegName::r0,
|
||||
RegName::r1,
|
||||
RegName::r2,
|
||||
RegName::r3
|
||||
> {
|
||||
constexpr u16 Index() const {
|
||||
return this->storage;
|
||||
}
|
||||
};
|
||||
|
||||
struct ArArpSttMod : RegOperand<
|
||||
RegName::ar0,
|
||||
RegName::ar1,
|
||||
RegName::arp0,
|
||||
RegName::arp1,
|
||||
RegName::arp2,
|
||||
RegName::arp3,
|
||||
RegName::undefine,
|
||||
RegName::undefine,
|
||||
RegName::stt0,
|
||||
RegName::stt1,
|
||||
RegName::stt2,
|
||||
RegName::undefine,
|
||||
RegName::mod0,
|
||||
RegName::mod1,
|
||||
RegName::mod2,
|
||||
RegName::mod3
|
||||
> {};
|
||||
struct ArArp : RegOperand<
|
||||
RegName::ar0,
|
||||
RegName::ar1,
|
||||
RegName::arp0,
|
||||
RegName::arp1,
|
||||
RegName::arp2,
|
||||
RegName::arp3,
|
||||
RegName::undefine,
|
||||
RegName::undefine
|
||||
> {};
|
||||
struct SttMod : RegOperand<
|
||||
RegName::stt0,
|
||||
RegName::stt1,
|
||||
RegName::stt2,
|
||||
RegName::undefine,
|
||||
RegName::mod0,
|
||||
RegName::mod1,
|
||||
RegName::mod2,
|
||||
RegName::mod3
|
||||
> {};
|
||||
|
||||
struct Ar : RegOperand<
|
||||
RegName::ar0,
|
||||
RegName::ar1
|
||||
> {
|
||||
constexpr u16 Index() const {
|
||||
return this->storage;
|
||||
}
|
||||
};
|
||||
|
||||
struct Arp : RegOperand<
|
||||
RegName::arp0,
|
||||
RegName::arp1,
|
||||
RegName::arp2,
|
||||
RegName::arp3
|
||||
> {
|
||||
constexpr u16 Index() const {
|
||||
return this->storage;
|
||||
}
|
||||
};
|
||||
|
||||
enum SwapTypeValue {
|
||||
a0b0,
|
||||
a0b1,
|
||||
a1b0,
|
||||
a1b1,
|
||||
a0b0a1b1,
|
||||
a0b1a1b0,
|
||||
a0b0a1,
|
||||
a0b1a1,
|
||||
a1b0a0,
|
||||
a1b1a0,
|
||||
b0a0b1,
|
||||
b0a1b1,
|
||||
b1a0b0,
|
||||
b1a1b0,
|
||||
reserved0,
|
||||
reserved1,
|
||||
|
||||
EnumEnd,
|
||||
};
|
||||
|
||||
using SwapType = EnumAllOperand<SwapTypeValue>;
|
||||
|
||||
enum class StepValue {
|
||||
Zero,
|
||||
Increase,
|
||||
Decrease,
|
||||
PlusStep,
|
||||
Increase2Mode1,
|
||||
Decrease2Mode1,
|
||||
Increase2Mode2,
|
||||
Decrease2Mode2,
|
||||
};
|
||||
|
||||
using StepZIDS = EnumOperand<StepValue,
|
||||
StepValue::Zero,
|
||||
StepValue::Increase,
|
||||
StepValue::Decrease,
|
||||
StepValue::PlusStep
|
||||
>;
|
||||
|
||||
template<unsigned bits, u16 offset = 0>
|
||||
struct ArIndex : Operand<bits>{
|
||||
constexpr u16 Index() const {
|
||||
return this->storage + offset;
|
||||
}
|
||||
};
|
||||
|
||||
struct ArRn1 : ArIndex<1> {};
|
||||
struct ArRn2 : ArIndex<2> {};
|
||||
struct ArStep1 : ArIndex<1> {};
|
||||
struct ArStep1Alt : ArIndex<1, 2> {};
|
||||
struct ArStep2 : ArIndex<2> {};
|
||||
struct ArpRn1 : ArIndex<1> {};
|
||||
struct ArpRn2 : ArIndex<2> {};
|
||||
struct ArpStep1 : ArIndex<1> {};
|
||||
struct ArpStep2 : ArIndex<2> {};
|
||||
|
||||
struct Address18_2 : Operand<2> {
|
||||
constexpr u32 Address32() const {
|
||||
return (u32)(this->storage) << 16;
|
||||
}
|
||||
};
|
||||
struct Address18_16 : Operand<16> {
|
||||
constexpr u32 Address32() const {
|
||||
return this->storage;
|
||||
}
|
||||
};
|
||||
|
||||
constexpr u32 Address32(Address18_16 low, Address18_2 high) {
|
||||
return low.Address32() | high.Address32();
|
||||
}
|
||||
|
||||
struct Address16 : Operand<16> {
|
||||
constexpr u32 Address32() {
|
||||
return this->storage;
|
||||
}
|
||||
};
|
||||
|
||||
struct RelAddr7 : Operand<7> {
|
||||
constexpr u32 Relative32() {
|
||||
return SignExtend<7, u32>(this->storage);
|
||||
}
|
||||
};
|
||||
|
||||
template <unsigned bits>
|
||||
struct Imm : Operand<bits> {
|
||||
constexpr u16 Unsigned16() const {
|
||||
return this->storage;
|
||||
}
|
||||
};
|
||||
|
||||
template <unsigned bits>
|
||||
struct Imms : Operand<bits> {
|
||||
constexpr u16 Signed16() const {
|
||||
return SignExtend<bits, u16>(this->storage);
|
||||
}
|
||||
};
|
||||
|
||||
struct Imm2 : Imm<2> {};
|
||||
struct Imm4 : Imm<4> {};
|
||||
struct Imm5 : Imm<5> {};
|
||||
struct Imm5s : Imms<5> {};
|
||||
struct Imm6s : Imms<6> {};
|
||||
struct Imm7s : Imms<7> {};
|
||||
struct Imm8 : Imm<8> {};
|
||||
struct Imm8s : Imms<8> {};
|
||||
struct Imm9 : Imm<9> {};
|
||||
struct Imm16 : Imm<16> {};
|
||||
|
||||
struct MemImm8 : Imm8 {};
|
||||
//struct MemImm16 : Imm16 {};
|
||||
struct MemR7Imm7s : Imm7s {};
|
||||
struct MemR7Imm16 : Imm16 {};
|
||||
|
||||
typedef u16 MemImm16;ttsrty
|
||||
|
||||
|
||||
enum class AlmOp {
|
||||
Or,
|
||||
And,
|
||||
Xor,
|
||||
Add,
|
||||
Tst0,
|
||||
Tst1,
|
||||
Cmp,
|
||||
Sub,
|
||||
Msu,
|
||||
Addh,
|
||||
Addl,
|
||||
Subh,
|
||||
Subl,
|
||||
Sqr,
|
||||
Sqra,
|
||||
Cmpu,
|
||||
|
||||
Reserved
|
||||
};
|
||||
|
||||
using Alm = EnumOperand<AlmOp,
|
||||
AlmOp::Or,
|
||||
AlmOp::And,
|
||||
AlmOp::Xor,
|
||||
AlmOp::Add,
|
||||
AlmOp::Tst0,
|
||||
AlmOp::Tst1,
|
||||
AlmOp::Cmp,
|
||||
AlmOp::Sub,
|
||||
AlmOp::Msu,
|
||||
AlmOp::Addh,
|
||||
AlmOp::Addl,
|
||||
AlmOp::Subh,
|
||||
AlmOp::Subl,
|
||||
AlmOp::Sqr,
|
||||
AlmOp::Sqra,
|
||||
AlmOp::Cmpu
|
||||
>;
|
||||
|
||||
using Alu = EnumOperand<AlmOp,
|
||||
AlmOp::Or,
|
||||
AlmOp::And,
|
||||
AlmOp::Xor,
|
||||
AlmOp::Add,
|
||||
AlmOp::Reserved,
|
||||
AlmOp::Reserved,
|
||||
AlmOp::Cmp,
|
||||
AlmOp::Sub
|
||||
>;
|
||||
|
||||
enum class AlbOp {
|
||||
Set,
|
||||
Rst,
|
||||
Chng,
|
||||
Addv,
|
||||
Tst0,
|
||||
Tst1,
|
||||
Cmpv,
|
||||
Subv,
|
||||
|
||||
EnumEnd
|
||||
};
|
||||
|
||||
using Alb = EnumAllOperand<AlbOp>;
|
||||
|
||||
enum class MulOp {
|
||||
Mpy,
|
||||
Mpysu,
|
||||
Mac,
|
||||
Macus,
|
||||
Maa,
|
||||
Macuu,
|
||||
Macsu,
|
||||
Maasu,
|
||||
};
|
||||
|
||||
using Mul3 = EnumOperand<MulOp,
|
||||
MulOp::Mpy,
|
||||
MulOp::Mpysu,
|
||||
MulOp::Mac,
|
||||
MulOp::Macus,
|
||||
MulOp::Maa,
|
||||
MulOp::Macuu,
|
||||
MulOp::Macsu,
|
||||
MulOp::Maasu
|
||||
>;
|
||||
|
||||
using Mul2 = EnumOperand<MulOp,
|
||||
MulOp::Mpy,
|
||||
MulOp::Mac,
|
||||
MulOp::Maa,
|
||||
MulOp::Macsu
|
||||
>;
|
||||
|
||||
enum class ModaOp {
|
||||
Shr,
|
||||
Shr4,
|
||||
Shl,
|
||||
Shl4,
|
||||
Ror,
|
||||
Rol,
|
||||
Clr,
|
||||
Reserved,
|
||||
Not,
|
||||
Neg,
|
||||
Rnd,
|
||||
Pacr,
|
||||
Clrr,
|
||||
Inc,
|
||||
Dec,
|
||||
Copy,
|
||||
|
||||
};
|
||||
|
||||
using Moda4 = EnumOperand<ModaOp,
|
||||
ModaOp::Shr,
|
||||
ModaOp::Shr4,
|
||||
ModaOp::Shl,
|
||||
ModaOp::Shl4,
|
||||
ModaOp::Ror,
|
||||
ModaOp::Rol,
|
||||
ModaOp::Clr,
|
||||
ModaOp::Reserved,
|
||||
ModaOp::Not,
|
||||
ModaOp::Neg,
|
||||
ModaOp::Rnd,
|
||||
ModaOp::Pacr,
|
||||
ModaOp::Clrr,
|
||||
ModaOp::Inc,
|
||||
ModaOp::Dec,
|
||||
ModaOp::Copy
|
||||
>;
|
||||
|
||||
using Moda3 = EnumOperand<ModaOp,
|
||||
ModaOp::Shr,
|
||||
ModaOp::Shr4,
|
||||
ModaOp::Shl,
|
||||
ModaOp::Shl4,
|
||||
ModaOp::Ror,
|
||||
ModaOp::Rol,
|
||||
ModaOp::Clr,
|
||||
ModaOp::Clrr
|
||||
>;
|
||||
|
||||
enum class CondValue {
|
||||
True,
|
||||
Eq,
|
||||
Neq,
|
||||
Gt,
|
||||
Ge,
|
||||
Lt,
|
||||
Le,
|
||||
Nn,
|
||||
C,
|
||||
V,
|
||||
E,
|
||||
L,
|
||||
Nr,
|
||||
Niu0,
|
||||
Iu0,
|
||||
Iu1,
|
||||
|
||||
EnumEnd
|
||||
};
|
||||
|
||||
using Cond = EnumAllOperand<CondValue>;
|
||||
|
||||
struct BankFlags : Operand<6>{
|
||||
constexpr bool Cfgi() const {
|
||||
return (this->storage & 1) != 0;
|
||||
}
|
||||
constexpr bool R4() const {
|
||||
return (this->storage & 2) != 0;
|
||||
}
|
||||
constexpr bool R1() const {
|
||||
return (this->storage & 4) != 0;
|
||||
}
|
||||
constexpr bool R0() const {
|
||||
return (this->storage & 8) != 0;
|
||||
}
|
||||
constexpr bool R7() const {
|
||||
return (this->storage & 16) != 0;
|
||||
}
|
||||
constexpr bool Cfgj() const {
|
||||
return (this->storage & 32) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
enum class CbsCondValue {
|
||||
Ge,
|
||||
Gt,
|
||||
|
||||
EnumEnd
|
||||
};
|
||||
|
||||
using CbsCond = EnumAllOperand<CbsCondValue>;
|
||||
|
||||
// clang-format on
|
Loading…
Reference in New Issue
Block a user