skyline/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell/macro_interpreter.h
PixelyIon cbe9bc5f25 Move Guest GPU into SoC Directory
We decided to restructure Skyline to draw a layer of separation between guest and host GPU. We're reserving the `gpu` namespace and directory for purely host GPU and creating a new `soc` directory and namespace for emulation of parts of the X1 SoC which is currently limited to guest GPU but will be expanded to contain components like the audio DSP down the line.
2021-03-25 01:39:21 +05:30

149 lines
4.6 KiB
C++

// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#pragma once
#include <common.h>
namespace skyline::soc::gm20b::engine::maxwell3d {
class Maxwell3D; // A forward declaration of Maxwell3D as we don't want to import it here
/**
* @brief The MacroInterpreter class handles interpreting macros. Macros are small programs that run on the GPU and are used for things like instanced rendering.
*/
class MacroInterpreter {
private:
#pragma pack(push, 1)
union Opcode {
u32 raw;
enum class Operation : u8 {
AluRegister = 0,
AddImmediate = 1,
BitfieldReplace = 2,
BitfieldExtractShiftLeftImmediate = 3,
BitfieldExtractShiftLeftRegister = 4,
ReadImmediate = 5,
Branch = 7,
};
enum class AssignmentOperation : u8 {
IgnoreAndFetch = 0,
Move = 1,
MoveAndSetMethod = 2,
FetchAndSend = 3,
MoveAndSend = 4,
FetchAndSetMethod = 5,
MoveAndSetMethodThenFetchAndSend = 6,
MoveAndSetMethodThenSendHigh = 7,
};
enum class AluOperation : u8 {
Add = 0,
AddWithCarry = 1,
Subtract = 2,
SubtractWithBorrow = 3,
BitwiseXor = 8,
BitwiseOr = 9,
BitwiseAnd = 10,
BitwiseAndNot = 11,
BitwiseNand = 12,
};
enum class BranchCondition : u8 {
Zero = 0,
NonZero = 1,
};
struct {
Operation operation : 3;
u8 _pad0_ : 1;
AssignmentOperation assignmentOperation : 3;
};
struct {
u8 _pad1_ : 4;
BranchCondition branchCondition : 1;
bool noDelay : 1;
u8 _pad2_ : 1;
u8 exit : 1;
u8 dest : 3;
u8 srcA : 3;
u8 srcB : 3;
AluOperation aluOperation : 5;
};
struct {
u16 _pad3_ : 14;
i32 immediate : 18;
};
struct {
u32 _pad_ : 17;
u8 srcBit : 5;
u8 size : 5;
u8 destBit : 5;
u32 GetMask() {
return (1 << size) - 1;
}
} bitfield;
};
#pragma pack(pop)
static_assert(sizeof(Opcode) == sizeof(u32));
/**
* @brief Metadata about the Maxwell 3D method to be called in 'Send'
*/
union MethodAddress {
u32 raw;
struct {
u16 address : 12;
u8 increment : 6;
};
};
Maxwell3D &maxwell3D; //!< A reference to the parent engine object
Opcode *opcode{}; //!< A pointer to the instruction that is currently being executed
std::array<u32, 8> registers{}; //!< The state of all the general-purpose registers in the macro interpreter
const u32 *argument{}; //!< A pointer to the argument buffer for the program, it is read from sequentially
MethodAddress methodAddress{};
bool carryFlag{}; //!< A flag representing if an arithmetic operation has set the most significant bit
/**
* @brief Steps forward one macro instruction, including delay slots
* @param delayedOpcode The target opcode to be jumped to after executing the instruction
*/
bool Step(Opcode *delayedOpcode = nullptr);
/**
* @brief Performs an ALU operation on the given source values and returns the result as a u32
*/
u32 HandleAlu(Opcode::AluOperation operation, u32 srcA, u32 srcB);
/**
* @brief Handles an opcode's assignment operation
*/
void HandleAssignment(Opcode::AssignmentOperation operation, u8 reg, u32 result);
/**
* @brief Sends a method call to the Maxwell 3D
*/
void Send(u32 argument);
/**
* @brief Writes to the specified register with sanity checking
*/
void WriteRegister(u8 reg, u32 value);
public:
MacroInterpreter(Maxwell3D &maxwell3D) : maxwell3D(maxwell3D) {}
/**
* @brief Executes a GPU macro from macro memory with the given arguments
*/
void Execute(size_t offset, const std::vector<u32> &args);
};
}