2016-08-17 15:53:36 +01:00
|
|
|
/* This file is part of the dynarmic project.
|
|
|
|
* Copyright (c) 2016 MerryMage
|
|
|
|
* This software may be used and distributed according to the terms of the GNU
|
|
|
|
* General Public License version 2 or any later version.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <array>
|
|
|
|
|
|
|
|
#include "common/common_types.h"
|
|
|
|
#include "common/intrusive_list.h"
|
|
|
|
#include "frontend/ir/value.h"
|
|
|
|
|
2018-01-26 13:51:48 +00:00
|
|
|
namespace Dynarmic::IR {
|
2016-08-17 15:53:36 +01:00
|
|
|
|
2018-02-11 11:46:18 +00:00
|
|
|
enum class Opcode;
|
|
|
|
enum class Type;
|
|
|
|
|
2018-08-18 21:08:34 +01:00
|
|
|
constexpr size_t max_arg_count = 4;
|
|
|
|
|
2016-08-17 15:53:36 +01:00
|
|
|
/**
|
|
|
|
* A representation of a microinstruction. A single ARM/Thumb instruction may be
|
|
|
|
* converted into zero or more microinstructions.
|
|
|
|
*/
|
|
|
|
class Inst final : public Common::IntrusiveListNode<Inst> {
|
|
|
|
public:
|
2016-08-22 15:51:17 +01:00
|
|
|
explicit Inst(Opcode op) : op(op) {}
|
2016-08-17 15:53:36 +01:00
|
|
|
|
2016-08-22 17:54:47 +01:00
|
|
|
/// Determines whether or not this instruction performs an arithmetic shift.
|
|
|
|
bool IsArithmeticShift() const;
|
|
|
|
/// Determines whether or not this instruction performs a logical shift.
|
|
|
|
bool IsLogicalShift() const;
|
|
|
|
/// Determines whether or not this instruction performs a circular shift.
|
|
|
|
bool IsCircularShift() const;
|
|
|
|
/// Determines whether or not this instruction performs any kind of shift.
|
|
|
|
bool IsShift() const;
|
|
|
|
|
2019-04-26 21:41:41 +01:00
|
|
|
/// Determines whether or not this instruction is a form of barrier.
|
|
|
|
bool IsBarrier() const;
|
|
|
|
|
2016-08-22 17:54:47 +01:00
|
|
|
/// Determines whether or not this instruction performs a shared memory read.
|
|
|
|
bool IsSharedMemoryRead() const;
|
|
|
|
/// Determines whether or not this instruction performs a shared memory write.
|
|
|
|
bool IsSharedMemoryWrite() const;
|
|
|
|
/// Determines whether or not this instruction performs a shared memory read or write.
|
|
|
|
bool IsSharedMemoryReadOrWrite() const;
|
|
|
|
/// Determines whether or not this instruction performs an atomic memory write.
|
|
|
|
bool IsExclusiveMemoryWrite() const;
|
|
|
|
|
|
|
|
/// Determines whether or not this instruction performs any kind of memory read.
|
|
|
|
bool IsMemoryRead() const;
|
|
|
|
/// Determines whether or not this instruction performs any kind of memory write.
|
|
|
|
bool IsMemoryWrite() const;
|
|
|
|
/// Determines whether or not this instruction performs any kind of memory access.
|
|
|
|
bool IsMemoryReadOrWrite() const;
|
|
|
|
|
|
|
|
/// Determines whether or not this instruction reads from the CPSR.
|
|
|
|
bool ReadsFromCPSR() const;
|
|
|
|
/// Determines whether or not this instruction writes to the CPSR.
|
|
|
|
bool WritesToCPSR() const;
|
|
|
|
|
2018-07-21 02:20:20 +01:00
|
|
|
/// Determines whether or not this instruction writes to a system register.
|
|
|
|
bool WritesToSystemRegister() const;
|
|
|
|
|
2016-08-22 17:54:47 +01:00
|
|
|
/// Determines whether or not this instruction reads from a core register.
|
|
|
|
bool ReadsFromCoreRegister() const;
|
|
|
|
/// Determines whether or not this instruction writes to a core register.
|
|
|
|
bool WritesToCoreRegister() const;
|
|
|
|
|
2018-07-24 12:10:57 +01:00
|
|
|
/// Determines whether or not this instruction reads from the FPCR.
|
|
|
|
bool ReadsFromFPCR() const;
|
|
|
|
/// Determines whether or not this instruction writes to the FPCR.
|
|
|
|
bool WritesToFPCR() const;
|
|
|
|
|
|
|
|
/// Determines whether or not this instruction reads from the FPSR.
|
|
|
|
bool ReadsFromFPSR() const;
|
|
|
|
/// Determines whether or not this instruction writes to the FPSR.
|
|
|
|
bool WritesToFPSR() const;
|
|
|
|
|
|
|
|
/// Determines whether or not this instruction reads from the FPSR cumulative exception bits.
|
|
|
|
bool ReadsFromFPSRCumulativeExceptionBits() const;
|
|
|
|
/// Determines whether or not this instruction writes to the FPSR cumulative exception bits.
|
|
|
|
bool WritesToFPSRCumulativeExceptionBits() const;
|
|
|
|
/// Determines whether or not this instruction both reads from and writes to the FPSR cumulative exception bits.
|
|
|
|
bool ReadsFromAndWritesToFPSRCumulativeExceptionBits() const;
|
|
|
|
|
|
|
|
/// Determines whether or not this instruction reads from the FPSR cumulative saturation bit.
|
|
|
|
bool ReadsFromFPSRCumulativeSaturationBit() const;
|
|
|
|
/// Determines whether or not this instruction writes to the FPSR cumulative saturation bit.
|
|
|
|
bool WritesToFPSRCumulativeSaturationBit() const;
|
2016-08-22 17:54:47 +01:00
|
|
|
|
|
|
|
/// Determines whether or not this instruction alters memory-exclusivity.
|
|
|
|
bool AltersExclusiveState() const;
|
|
|
|
|
2016-12-31 11:17:47 +00:00
|
|
|
/// Determines whether or not this instruction accesses a coprocessor.
|
|
|
|
bool IsCoprocessorInstruction() const;
|
|
|
|
|
2016-08-22 17:54:47 +01:00
|
|
|
/// Determines whether or not this instruction causes a CPU exception.
|
|
|
|
bool CausesCPUException() const;
|
|
|
|
|
2019-05-03 23:28:02 +01:00
|
|
|
/// Determines whether or not this instruction is a SetCheckBit operation.
|
|
|
|
bool IsSetCheckBitOperation() const;
|
|
|
|
|
2016-08-22 17:54:47 +01:00
|
|
|
/// Determines whether or not this instruction may have side-effects.
|
|
|
|
bool MayHaveSideEffects() const;
|
|
|
|
|
2018-01-07 11:31:20 +00:00
|
|
|
/// Determines whether or not this instruction is a pseduo-instruction.
|
|
|
|
/// Pseudo-instructions depend on their parent instructions for their semantics.
|
|
|
|
bool IsAPseudoOperation() const;
|
|
|
|
|
2019-05-24 06:37:03 +01:00
|
|
|
/// Determines whether or not this instruction supports the GetNZCVFromOp pseudo-operation.
|
2018-01-07 11:31:20 +00:00
|
|
|
bool MayGetNZCVFromOp() const;
|
|
|
|
|
2017-01-29 22:54:54 +00:00
|
|
|
/// Determines if all arguments of this instruction are immediates.
|
|
|
|
bool AreAllArgsImmediates() const;
|
|
|
|
|
2016-11-30 21:51:06 +00:00
|
|
|
size_t UseCount() const { return use_count; }
|
2016-08-17 15:53:36 +01:00
|
|
|
bool HasUses() const { return use_count > 0; }
|
2016-11-30 21:51:06 +00:00
|
|
|
|
2017-04-04 13:10:50 +01:00
|
|
|
/// Determines if there is a pseudo-operation associated with this instruction.
|
|
|
|
bool HasAssociatedPseudoOperation() const;
|
2016-08-25 21:08:47 +01:00
|
|
|
/// Gets a pseudo-operation associated with this instruction.
|
|
|
|
Inst* GetAssociatedPseudoOperation(Opcode opcode);
|
2016-08-17 15:53:36 +01:00
|
|
|
|
|
|
|
/// Get the microop this microinstruction represents.
|
|
|
|
Opcode GetOpcode() const { return op; }
|
|
|
|
/// Get the type this instruction returns.
|
2016-08-23 15:48:30 +01:00
|
|
|
Type GetType() const;
|
2016-08-17 15:53:36 +01:00
|
|
|
/// Get the number of arguments this instruction has.
|
2018-02-11 11:46:18 +00:00
|
|
|
size_t NumArgs() const;
|
2016-08-17 15:53:36 +01:00
|
|
|
|
|
|
|
Value GetArg(size_t index) const;
|
|
|
|
void SetArg(size_t index, Value value);
|
|
|
|
|
|
|
|
void Invalidate();
|
2018-01-18 13:00:07 +00:00
|
|
|
void ClearArgs();
|
2016-08-17 15:53:36 +01:00
|
|
|
|
2017-01-29 22:52:33 +00:00
|
|
|
void ReplaceUsesWith(Value replacement);
|
2016-08-17 15:53:36 +01:00
|
|
|
|
|
|
|
private:
|
2017-01-29 22:53:46 +00:00
|
|
|
void Use(const Value& value);
|
|
|
|
void UndoUse(const Value& value);
|
2016-08-17 15:53:36 +01:00
|
|
|
|
|
|
|
Opcode op;
|
2016-11-30 21:51:06 +00:00
|
|
|
size_t use_count = 0;
|
2018-08-18 21:08:34 +01:00
|
|
|
std::array<Value, max_arg_count> args;
|
2016-08-25 21:08:47 +01:00
|
|
|
|
2016-12-04 20:52:06 +00:00
|
|
|
// Pointers to related pseudooperations:
|
|
|
|
// Since not all combinations are possible, we use a union to save space
|
|
|
|
union {
|
|
|
|
Inst* carry_inst = nullptr;
|
|
|
|
Inst* ge_inst;
|
2018-09-14 20:06:11 +01:00
|
|
|
Inst* upper_inst;
|
2016-12-04 20:52:06 +00:00
|
|
|
};
|
2016-08-25 21:08:47 +01:00
|
|
|
Inst* overflow_inst = nullptr;
|
2018-09-14 20:06:11 +01:00
|
|
|
union {
|
|
|
|
Inst* nzcv_inst = nullptr;
|
|
|
|
Inst* lower_inst;
|
|
|
|
};
|
2016-08-17 15:53:36 +01:00
|
|
|
};
|
|
|
|
|
2018-01-26 13:51:48 +00:00
|
|
|
} // namespace Dynarmic::IR
|