You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

90 lines
3.0 KiB

// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
/* This file is part of the dynarmic project.
* Copyright (c) 2016 MerryMage
* SPDX-License-Identifier: 0BSD
*/
#pragma once
#include <array>
#include <mcl/container/intrusive_list.hpp>
#include "dynarmic/common/common_types.h"
#include "dynarmic/ir/value.h"
#include "dynarmic/ir/opcodes.h"
namespace Dynarmic::IR {
enum class Opcode;
enum class Type;
constexpr size_t max_arg_count = 4;
/// A representation of a microinstruction. A single ARM/Thumb instruction may be
/// converted into zero or more microinstructions.
//class Inst final {
class Inst final : public mcl::intrusive_list_node<Inst> {
public:
explicit Inst(Opcode op) : op(op) {}
/// @brief Determines if all arguments of this instruction are immediates.
bool AreAllArgsImmediates() const;
size_t UseCount() const { return use_count; }
bool HasUses() const { return use_count > 0; }
/// Determines if there is a pseudo-operation associated with this instruction.
inline bool HasAssociatedPseudoOperation() const noexcept {
return next_pseudoop && !IsAPseudoOperation(op);
}
/// Gets a pseudo-operation associated with this instruction.
Inst* GetAssociatedPseudoOperation(Opcode opcode);
/// Get the microop this microinstruction represents.
Opcode GetOpcode() const { return op; }
/// Get the type this instruction returns.
Type GetType() const;
/// Get the number of arguments this instruction has.
inline size_t NumArgs() const noexcept {
return GetNumArgsOf(op);
}
inline Value GetArg(size_t index) const noexcept {
DEBUG_ASSERT_MSG(index < GetNumArgsOf(op), "Inst::GetArg: index {} >= number of arguments of {} ({})", index, op, GetNumArgsOf(op));
DEBUG_ASSERT_MSG(!args[index].IsEmpty() || GetArgTypeOf(op, index) == IR::Type::Opaque, "Inst::GetArg: index {} is empty", index, args[index].GetType());
return args[index];
}
void SetArg(size_t index, Value value) noexcept;
inline void Invalidate() noexcept {
ClearArgs();
op = Opcode::Void;
}
void ClearArgs();
void ReplaceUsesWith(Value replacement);
// IR name (i.e. instruction number in block). This is set in the naming pass. Treat 0 as an invalid name.
// This is used for debugging and fastmem instruction identification.
void SetName(unsigned value) { name = value; }
unsigned GetName() const { return name; }
private:
void Use(const Value& value);
void UndoUse(const Value& value);
// TODO: so much padding wasted with mcl::intrusive_node
// 16 + 1, 24
Opcode op; //2 (6)
// Linked list of pseudooperations associated with this instruction.
Inst* next_pseudoop = nullptr; //8 (14)
unsigned use_count = 0; //4 (0)
unsigned name = 0; //4 (4)
alignas(64) std::array<Value, max_arg_count> args; //16 * 4 = 64 (1 cache line)
};
static_assert(sizeof(Inst) == 128);
} // namespace Dynarmic::IR