Implement coprocessor-related microinstructions

* CoprocInternalOperation
* CoprocSendOneWord
* CoprocSendTwoWords
* CoprocGetOneWord
* CoprocGetTwoWords
* CoprocLoadWords
* CoprocStoreWords
This commit is contained in:
MerryMage
2016-12-31 11:17:47 +00:00
committed by Merry
parent b3ae57619d
commit 48693eb6ff
6 changed files with 312 additions and 1 deletions

View File

@@ -709,6 +709,80 @@ Value IREmitter::ExclusiveWriteMemory64(const Value& vaddr, const Value& value_l
}
}
void IREmitter::CoprocInternalOperation(size_t coproc_no, bool two, size_t opc1, Arm::CoprocReg CRd, Arm::CoprocReg CRn, Arm::CoprocReg CRm, size_t opc2) {
ASSERT(coproc_no <= 15);
std::array<u8, 8> coproc_info{static_cast<u8>(coproc_no),
static_cast<u8>(two ? 1 : 0),
static_cast<u8>(opc1),
static_cast<u8>(CRd),
static_cast<u8>(CRn),
static_cast<u8>(CRm),
static_cast<u8>(opc2)};
Inst(Opcode::CoprocInternalOperation, {Value(coproc_info)});
}
void IREmitter::CoprocSendOneWord(size_t coproc_no, bool two, size_t opc1, Arm::CoprocReg CRn, Arm::CoprocReg CRm, size_t opc2, const Value& word) {
ASSERT(coproc_no <= 15);
std::array<u8, 8> coproc_info{static_cast<u8>(coproc_no),
static_cast<u8>(two ? 1 : 0),
static_cast<u8>(opc1),
static_cast<u8>(CRn),
static_cast<u8>(CRm),
static_cast<u8>(opc2)};
Inst(Opcode::CoprocSendOneWord, {Value(coproc_info), word});
}
void IREmitter::CoprocSendTwoWords(size_t coproc_no, bool two, size_t opc, Arm::CoprocReg CRm, const Value& word1, const Value& word2) {
ASSERT(coproc_no <= 15);
std::array<u8, 8> coproc_info{static_cast<u8>(coproc_no),
static_cast<u8>(two ? 1 : 0),
static_cast<u8>(opc),
static_cast<u8>(CRm)};
Inst(Opcode::CoprocSendTwoWords, {Value(coproc_info), word1, word2});
}
Value IREmitter::CoprocGetOneWord(size_t coproc_no, bool two, size_t opc1, Arm::CoprocReg CRn, Arm::CoprocReg CRm, size_t opc2) {
ASSERT(coproc_no <= 15);
std::array<u8, 8> coproc_info{static_cast<u8>(coproc_no),
static_cast<u8>(two ? 1 : 0),
static_cast<u8>(opc1),
static_cast<u8>(CRn),
static_cast<u8>(CRm),
static_cast<u8>(opc2)};
return Inst(Opcode::CoprocGetOneWord, {Value(coproc_info)});
}
Value IREmitter::CoprocGetTwoWords(size_t coproc_no, bool two, size_t opc, Arm::CoprocReg CRm) {
ASSERT(coproc_no <= 15);
std::array<u8, 8> coproc_info{static_cast<u8>(coproc_no),
static_cast<u8>(two ? 1 : 0),
static_cast<u8>(opc),
static_cast<u8>(CRm)};
return Inst(Opcode::CoprocGetTwoWords, {Value(coproc_info)});
}
void IREmitter::CoprocLoadWords(size_t coproc_no, bool two, bool long_transfer, Arm::CoprocReg CRd, const Value& address, bool has_option, u8 option) {
ASSERT(coproc_no <= 15);
std::array<u8, 8> coproc_info{static_cast<u8>(coproc_no),
static_cast<u8>(two ? 1 : 0),
static_cast<u8>(long_transfer ? 1 : 0),
static_cast<u8>(CRd),
static_cast<u8>(has_option ? 1 : 0),
static_cast<u8>(option)};
Inst(Opcode::CoprocLoadWords, {Value(coproc_info), address});
}
void IREmitter::CoprocStoreWords(size_t coproc_no, bool two, bool long_transfer, Arm::CoprocReg CRd, const Value& address, bool has_option, u8 option) {
ASSERT(coproc_no <= 15);
std::array<u8, 8> coproc_info{static_cast<u8>(coproc_no),
static_cast<u8>(two ? 1 : 0),
static_cast<u8>(long_transfer ? 1 : 0),
static_cast<u8>(CRd),
static_cast<u8>(has_option ? 1 : 0),
static_cast<u8>(option)};
Inst(Opcode::CoprocStoreWords, {Value(coproc_info), address});
}
void IREmitter::Breakpoint() {
Inst(Opcode::Breakpoint, {});
}

View File

@@ -8,6 +8,8 @@
#include <initializer_list>
#include <dynarmic/coprocessor_util.h>
#include "common/common_types.h"
#include "frontend/ir/basic_block.h"
#include "frontend/ir/location_descriptor.h"
@@ -213,6 +215,14 @@ public:
Value ExclusiveWriteMemory32(const Value& vaddr, const Value& value);
Value ExclusiveWriteMemory64(const Value& vaddr, const Value& value_lo, const Value& value_hi);
void CoprocInternalOperation(size_t coproc_no, bool two, size_t opc1, Arm::CoprocReg CRd, Arm::CoprocReg CRn, Arm::CoprocReg CRm, size_t opc2);
void CoprocSendOneWord(size_t coproc_no, bool two, size_t opc1, Arm::CoprocReg CRn, Arm::CoprocReg CRm, size_t opc2, const Value& word);
void CoprocSendTwoWords(size_t coproc_no, bool two, size_t opc, Arm::CoprocReg CRm, const Value& word1, const Value& word2);
Value CoprocGetOneWord(size_t coproc_no, bool two, size_t opc1, Arm::CoprocReg CRn, Arm::CoprocReg CRm, size_t opc2);
Value CoprocGetTwoWords(size_t coproc_no, bool two, size_t opc, Arm::CoprocReg CRm);
void CoprocLoadWords(size_t coproc_no, bool two, bool long_transfer, Arm::CoprocReg CRd, const Value& address, bool has_option, u8 option);
void CoprocStoreWords(size_t coproc_no, bool two, bool long_transfer, Arm::CoprocReg CRd, const Value& address, bool has_option, u8 option);
void Breakpoint();
void SetTerm(const Terminal& terminal);

View File

@@ -213,6 +213,22 @@ bool Inst::AltersExclusiveState() const {
IsExclusiveMemoryWrite();
}
bool Inst::IsCoprocessorInstruction() const {
switch (op) {
case Opcode::CoprocInternalOperation:
case Opcode::CoprocSendOneWord:
case Opcode::CoprocSendTwoWords:
case Opcode::CoprocGetOneWord:
case Opcode::CoprocGetTwoWords:
case Opcode::CoprocLoadWords:
case Opcode::CoprocStoreWords:
return true;
default:
return false;
}
}
bool Inst::MayHaveSideEffects() const {
return op == Opcode::PushRSB ||
CausesCPUException() ||
@@ -220,7 +236,8 @@ bool Inst::MayHaveSideEffects() const {
WritesToCPSR() ||
WritesToFPSCR() ||
AltersExclusiveState() ||
IsMemoryWrite();
IsMemoryWrite() ||
IsCoprocessorInstruction();
}
void Inst::DecrementRemainingUses() {

View File

@@ -67,6 +67,9 @@ public:
/// Determines whether or not this instruction alters memory-exclusivity.
bool AltersExclusiveState() const;
/// Determines whether or not this instruction accesses a coprocessor.
bool IsCoprocessorInstruction() const;
/// Determines whether or not this instruction causes a CPU exception.
bool CausesCPUException() const;

View File

@@ -158,3 +158,12 @@ OPCODE(ExclusiveWriteMemory8, T::U32, T::U32, T::U8
OPCODE(ExclusiveWriteMemory16, T::U32, T::U32, T::U16 )
OPCODE(ExclusiveWriteMemory32, T::U32, T::U32, T::U32 )
OPCODE(ExclusiveWriteMemory64, T::U32, T::U32, T::U32, T::U32 )
// Coprocessor
OPCODE(CoprocInternalOperation, T::Void, T::CoprocInfo )
OPCODE(CoprocSendOneWord, T::Void, T::CoprocInfo, T::U32 )
OPCODE(CoprocSendTwoWords, T::Void, T::CoprocInfo, T::U32, T::U32 )
OPCODE(CoprocGetOneWord, T::U32, T::CoprocInfo )
OPCODE(CoprocGetTwoWords, T::U64, T::CoprocInfo )
OPCODE(CoprocLoadWords, T::Void, T::CoprocInfo, T::U32 )
OPCODE(CoprocStoreWords, T::Void, T::CoprocInfo, T::U32 )