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 .
*/
2017-01-29 22:54:54 +00:00
# include <algorithm>
2018-08-11 10:43:40 +01:00
# include <fmt/ostream.h>
2016-08-17 15:53:36 +01:00
# include "common/assert.h"
# include "frontend/ir/microinstruction.h"
2018-02-11 11:46:18 +00:00
# include "frontend/ir/opcodes.h"
# include "frontend/ir/type.h"
2016-08-17 15:53:36 +01:00
2018-01-26 13:51:48 +00:00
namespace Dynarmic : : IR {
2016-08-17 15:53:36 +01:00
2016-08-22 17:54:47 +01:00
bool Inst : : IsArithmeticShift ( ) const {
2018-01-07 00:11:57 +00:00
return op = = Opcode : : ArithmeticShiftRight32 | |
op = = Opcode : : ArithmeticShiftRight64 ;
2016-08-22 17:54:47 +01:00
}
bool Inst : : IsCircularShift ( ) const {
2018-01-07 00:11:57 +00:00
return op = = Opcode : : RotateRight32 | |
op = = Opcode : : RotateRight64 | |
2016-08-22 17:54:47 +01:00
op = = Opcode : : RotateRightExtended ;
}
bool Inst : : IsLogicalShift ( ) const {
switch ( op ) {
2018-01-07 00:11:57 +00:00
case Opcode : : LogicalShiftLeft32 :
case Opcode : : LogicalShiftLeft64 :
case Opcode : : LogicalShiftRight32 :
2016-08-22 17:54:47 +01:00
case Opcode : : LogicalShiftRight64 :
return true ;
default :
return false ;
}
}
bool Inst : : IsShift ( ) const {
return IsArithmeticShift ( ) | |
IsCircularShift ( ) | |
IsLogicalShift ( ) ;
}
2019-04-26 21:41:41 +01:00
bool Inst : : IsBarrier ( ) const {
switch ( op ) {
case Opcode : : A32DataMemoryBarrier :
case Opcode : : A32DataSynchronizationBarrier :
case Opcode : : A32InstructionSynchronizationBarrier :
case Opcode : : A64DataMemoryBarrier :
case Opcode : : A64DataSynchronizationBarrier :
case Opcode : : A64InstructionSynchronizationBarrier :
return true ;
default :
return false ;
}
}
2016-08-22 17:54:47 +01:00
bool Inst : : IsSharedMemoryRead ( ) const {
switch ( op ) {
2018-01-01 16:19:43 +00:00
case Opcode : : A32ReadMemory8 :
case Opcode : : A32ReadMemory16 :
case Opcode : : A32ReadMemory32 :
case Opcode : : A32ReadMemory64 :
2018-01-10 01:13:23 +00:00
case Opcode : : A64ReadMemory8 :
case Opcode : : A64ReadMemory16 :
case Opcode : : A64ReadMemory32 :
case Opcode : : A64ReadMemory64 :
2018-01-25 23:56:14 +00:00
case Opcode : : A64ReadMemory128 :
2016-08-22 17:54:47 +01:00
return true ;
default :
return false ;
}
}
bool Inst : : IsSharedMemoryWrite ( ) const {
switch ( op ) {
2018-01-01 16:19:43 +00:00
case Opcode : : A32WriteMemory8 :
case Opcode : : A32WriteMemory16 :
case Opcode : : A32WriteMemory32 :
case Opcode : : A32WriteMemory64 :
2018-01-10 01:13:23 +00:00
case Opcode : : A64WriteMemory8 :
case Opcode : : A64WriteMemory16 :
case Opcode : : A64WriteMemory32 :
case Opcode : : A64WriteMemory64 :
2018-01-25 23:56:14 +00:00
case Opcode : : A64WriteMemory128 :
2016-08-22 17:54:47 +01:00
return true ;
default :
return false ;
}
}
bool Inst : : IsSharedMemoryReadOrWrite ( ) const {
return IsSharedMemoryRead ( ) | | IsSharedMemoryWrite ( ) ;
}
bool Inst : : IsExclusiveMemoryWrite ( ) const {
switch ( op ) {
2018-01-01 16:19:43 +00:00
case Opcode : : A32ExclusiveWriteMemory8 :
case Opcode : : A32ExclusiveWriteMemory16 :
case Opcode : : A32ExclusiveWriteMemory32 :
case Opcode : : A32ExclusiveWriteMemory64 :
A64: Implement STXRB, STXRH, STXR, STLXRB, STLXRH, STLXR, LDXRB, LDXRH, LDXR, LDAXRB, LDAXRH, LDAXR
2018-02-13 00:19:04 +00:00
case Opcode : : A64ExclusiveWriteMemory8 :
case Opcode : : A64ExclusiveWriteMemory16 :
case Opcode : : A64ExclusiveWriteMemory32 :
case Opcode : : A64ExclusiveWriteMemory64 :
case Opcode : : A64ExclusiveWriteMemory128 :
2016-08-22 17:54:47 +01:00
return true ;
default :
return false ;
}
}
bool Inst : : IsMemoryRead ( ) const {
return IsSharedMemoryRead ( ) ;
}
bool Inst : : IsMemoryWrite ( ) const {
return IsSharedMemoryWrite ( ) | | IsExclusiveMemoryWrite ( ) ;
}
bool Inst : : IsMemoryReadOrWrite ( ) const {
return IsMemoryRead ( ) | | IsMemoryWrite ( ) ;
}
bool Inst : : ReadsFromCPSR ( ) const {
switch ( op ) {
2018-01-01 16:19:43 +00:00
case Opcode : : A32GetCpsr :
case Opcode : : A32GetNFlag :
case Opcode : : A32GetZFlag :
case Opcode : : A32GetCFlag :
case Opcode : : A32GetVFlag :
case Opcode : : A32GetGEFlags :
2018-01-26 23:37:54 +00:00
case Opcode : : A64GetCFlag :
2019-03-06 18:54:09 +00:00
case Opcode : : A64GetNZCVRaw :
2018-01-23 17:45:14 +00:00
case Opcode : : ConditionalSelect32 :
case Opcode : : ConditionalSelect64 :
2018-02-05 00:38:47 +00:00
case Opcode : : ConditionalSelectNZCV :
2016-08-22 17:54:47 +01:00
return true ;
default :
return false ;
}
}
bool Inst : : WritesToCPSR ( ) const {
switch ( op ) {
2018-01-01 16:19:43 +00:00
case Opcode : : A32SetCpsr :
case Opcode : : A32SetCpsrNZCV :
case Opcode : : A32SetCpsrNZCVQ :
case Opcode : : A32SetNFlag :
case Opcode : : A32SetZFlag :
case Opcode : : A32SetCFlag :
case Opcode : : A32SetVFlag :
case Opcode : : A32OrQFlag :
case Opcode : : A32SetGEFlags :
case Opcode : : A32SetGEFlagsCompressed :
2019-03-06 18:54:09 +00:00
case Opcode : : A64SetNZCVRaw :
2018-01-07 14:46:35 +00:00
case Opcode : : A64SetNZCV :
2016-08-22 17:54:47 +01:00
return true ;
default :
return false ;
}
}
2018-07-21 02:20:20 +01:00
bool Inst : : WritesToSystemRegister ( ) const {
switch ( op ) {
case Opcode : : A64SetTPIDR :
return true ;
default :
return false ;
}
}
2016-08-22 17:54:47 +01:00
bool Inst : : ReadsFromCoreRegister ( ) const {
switch ( op ) {
2018-01-01 16:19:43 +00:00
case Opcode : : A32GetRegister :
case Opcode : : A32GetExtendedRegister32 :
case Opcode : : A32GetExtendedRegister64 :
2018-01-07 00:11:57 +00:00
case Opcode : : A64GetW :
case Opcode : : A64GetX :
2018-01-26 18:35:19 +00:00
case Opcode : : A64GetS :
2018-01-23 17:45:14 +00:00
case Opcode : : A64GetD :
case Opcode : : A64GetQ :
2018-01-07 11:31:20 +00:00
case Opcode : : A64GetSP :
2016-08-22 17:54:47 +01:00
return true ;
default :
return false ;
}
}
bool Inst : : WritesToCoreRegister ( ) const {
switch ( op ) {
2018-01-01 16:19:43 +00:00
case Opcode : : A32SetRegister :
case Opcode : : A32SetExtendedRegister32 :
case Opcode : : A32SetExtendedRegister64 :
case Opcode : : A32BXWritePC :
2018-01-07 00:11:57 +00:00
case Opcode : : A64SetW :
case Opcode : : A64SetX :
2018-01-26 18:35:19 +00:00
case Opcode : : A64SetS :
2018-01-23 17:45:14 +00:00
case Opcode : : A64SetD :
case Opcode : : A64SetQ :
2018-01-07 11:31:20 +00:00
case Opcode : : A64SetSP :
2018-01-07 13:56:32 +00:00
case Opcode : : A64SetPC :
2016-08-22 17:54:47 +01:00
return true ;
default :
return false ;
}
}
2018-07-24 12:10:57 +01:00
bool Inst : : ReadsFromFPCR ( ) const {
2016-08-22 17:54:47 +01:00
switch ( op ) {
2018-01-01 16:19:43 +00:00
case Opcode : : A32GetFpscr :
case Opcode : : A32GetFpscrNZCV :
2018-02-20 17:38:29 +00:00
case Opcode : : A64GetFPCR :
2016-08-22 17:54:47 +01:00
return true ;
default :
return false ;
}
}
2018-07-24 12:10:57 +01:00
bool Inst : : WritesToFPCR ( ) const {
2016-08-22 17:54:47 +01:00
switch ( op ) {
2018-01-01 16:19:43 +00:00
case Opcode : : A32SetFpscr :
case Opcode : : A32SetFpscrNZCV :
2018-02-20 17:38:29 +00:00
case Opcode : : A64SetFPCR :
2018-07-24 12:10:57 +01:00
return true ;
default :
return false ;
}
}
bool Inst : : ReadsFromFPSR ( ) const {
return op = = Opcode : : A32GetFpscr | |
op = = Opcode : : A32GetFpscrNZCV | |
op = = Opcode : : A64GetFPSR | |
ReadsFromFPSRCumulativeExceptionBits ( ) | |
ReadsFromFPSRCumulativeSaturationBit ( ) ;
}
bool Inst : : WritesToFPSR ( ) const {
return op = = Opcode : : A32SetFpscr | |
op = = Opcode : : A32SetFpscrNZCV | |
op = = Opcode : : A64SetFPSR | |
WritesToFPSRCumulativeExceptionBits ( ) | |
WritesToFPSRCumulativeSaturationBit ( ) ;
}
bool Inst : : ReadsFromFPSRCumulativeExceptionBits ( ) const {
return ReadsFromAndWritesToFPSRCumulativeExceptionBits ( ) ;
}
bool Inst : : WritesToFPSRCumulativeExceptionBits ( ) const {
return ReadsFromAndWritesToFPSRCumulativeExceptionBits ( ) ;
}
bool Inst : : ReadsFromAndWritesToFPSRCumulativeExceptionBits ( ) const {
switch ( op ) {
2016-08-22 17:54:47 +01:00
case Opcode : : FPAdd32 :
case Opcode : : FPAdd64 :
2016-11-26 11:17:16 +00:00
case Opcode : : FPCompare32 :
case Opcode : : FPCompare64 :
2016-08-22 17:54:47 +01:00
case Opcode : : FPDiv32 :
case Opcode : : FPDiv64 :
2018-07-23 03:49:35 +01:00
case Opcode : : FPMax32 :
case Opcode : : FPMax64 :
case Opcode : : FPMaxNumeric32 :
case Opcode : : FPMaxNumeric64 :
case Opcode : : FPMin32 :
case Opcode : : FPMin64 :
case Opcode : : FPMinNumeric32 :
case Opcode : : FPMinNumeric64 :
2016-08-22 17:54:47 +01:00
case Opcode : : FPMul32 :
case Opcode : : FPMul64 :
2019-04-13 05:12:25 +01:00
case Opcode : : FPMulAdd16 :
2018-07-23 03:49:35 +01:00
case Opcode : : FPMulAdd32 :
case Opcode : : FPMulAdd64 :
2019-04-14 00:00:49 +01:00
case Opcode : : FPRecipEstimate16 :
2018-07-25 19:17:07 +01:00
case Opcode : : FPRecipEstimate32 :
case Opcode : : FPRecipEstimate64 :
2019-03-09 22:36:00 +00:00
case Opcode : : FPRecipExponent16 :
2019-03-04 14:43:15 +00:00
case Opcode : : FPRecipExponent32 :
case Opcode : : FPRecipExponent64 :
2019-04-13 23:52:36 +01:00
case Opcode : : FPRecipStepFused16 :
2018-07-25 19:17:07 +01:00
case Opcode : : FPRecipStepFused32 :
case Opcode : : FPRecipStepFused64 :
2019-04-13 22:40:56 +01:00
case Opcode : : FPRoundInt16 :
2018-07-23 03:49:35 +01:00
case Opcode : : FPRoundInt32 :
case Opcode : : FPRoundInt64 :
2019-04-13 23:34:35 +01:00
case Opcode : : FPRSqrtEstimate16 :
2018-07-23 03:49:35 +01:00
case Opcode : : FPRSqrtEstimate32 :
case Opcode : : FPRSqrtEstimate64 :
2019-04-15 01:55:25 +01:00
case Opcode : : FPRSqrtStepFused16 :
2018-07-24 12:10:57 +01:00
case Opcode : : FPRSqrtStepFused32 :
case Opcode : : FPRSqrtStepFused64 :
case Opcode : : FPSqrt32 :
case Opcode : : FPSqrt64 :
2016-08-22 17:54:47 +01:00
case Opcode : : FPSub32 :
case Opcode : : FPSub64 :
2019-03-23 14:02:51 +00:00
case Opcode : : FPHalfToDouble :
case Opcode : : FPHalfToSingle :
2018-07-24 12:10:57 +01:00
case Opcode : : FPSingleToDouble :
2019-03-23 14:02:51 +00:00
case Opcode : : FPSingleToHalf :
case Opcode : : FPDoubleToHalf :
2018-07-24 12:10:57 +01:00
case Opcode : : FPDoubleToSingle :
case Opcode : : FPDoubleToFixedS32 :
case Opcode : : FPDoubleToFixedS64 :
case Opcode : : FPDoubleToFixedU32 :
case Opcode : : FPDoubleToFixedU64 :
2019-04-15 05:20:37 +01:00
case Opcode : : FPHalfToFixedS32 :
case Opcode : : FPHalfToFixedS64 :
case Opcode : : FPHalfToFixedU32 :
case Opcode : : FPHalfToFixedU64 :
2018-07-24 12:10:57 +01:00
case Opcode : : FPSingleToFixedS32 :
case Opcode : : FPSingleToFixedS64 :
case Opcode : : FPSingleToFixedU32 :
case Opcode : : FPSingleToFixedU64 :
2018-09-18 20:36:37 +01:00
case Opcode : : FPFixedU32ToSingle :
case Opcode : : FPFixedS32ToSingle :
case Opcode : : FPFixedU32ToDouble :
case Opcode : : FPFixedU64ToDouble :
case Opcode : : FPFixedU64ToSingle :
case Opcode : : FPFixedS32ToDouble :
case Opcode : : FPFixedS64ToDouble :
case Opcode : : FPFixedS64ToSingle :
2018-07-24 12:10:57 +01:00
case Opcode : : FPVectorAdd32 :
case Opcode : : FPVectorAdd64 :
case Opcode : : FPVectorDiv32 :
case Opcode : : FPVectorDiv64 :
2019-05-25 00:26:40 +01:00
case Opcode : : FPVectorEqual16 :
2018-07-24 12:10:57 +01:00
case Opcode : : FPVectorEqual32 :
case Opcode : : FPVectorEqual64 :
2018-09-18 21:46:17 +01:00
case Opcode : : FPVectorFromSignedFixed32 :
case Opcode : : FPVectorFromSignedFixed64 :
case Opcode : : FPVectorFromUnsignedFixed32 :
case Opcode : : FPVectorFromUnsignedFixed64 :
2018-07-24 12:10:57 +01:00
case Opcode : : FPVectorGreater32 :
case Opcode : : FPVectorGreater64 :
case Opcode : : FPVectorGreaterEqual32 :
case Opcode : : FPVectorGreaterEqual64 :
case Opcode : : FPVectorMul32 :
case Opcode : : FPVectorMul64 :
2019-04-13 06:42:35 +01:00
case Opcode : : FPVectorMulAdd16 :
2018-07-25 19:17:07 +01:00
case Opcode : : FPVectorMulAdd32 :
case Opcode : : FPVectorMulAdd64 :
2018-07-24 12:10:57 +01:00
case Opcode : : FPVectorPairedAddLower32 :
case Opcode : : FPVectorPairedAddLower64 :
case Opcode : : FPVectorPairedAdd32 :
case Opcode : : FPVectorPairedAdd64 :
2019-04-14 00:02:26 +01:00
case Opcode : : FPVectorRecipEstimate16 :
2018-07-25 19:17:07 +01:00
case Opcode : : FPVectorRecipEstimate32 :
case Opcode : : FPVectorRecipEstimate64 :
2019-04-13 23:54:53 +01:00
case Opcode : : FPVectorRecipStepFused16 :
2018-07-25 19:17:07 +01:00
case Opcode : : FPVectorRecipStepFused32 :
case Opcode : : FPVectorRecipStepFused64 :
2019-04-13 22:51:12 +01:00
case Opcode : : FPVectorRoundInt16 :
case Opcode : : FPVectorRoundInt32 :
case Opcode : : FPVectorRoundInt64 :
2019-04-13 23:36:24 +01:00
case Opcode : : FPVectorRSqrtEstimate16 :
2018-07-24 12:10:57 +01:00
case Opcode : : FPVectorRSqrtEstimate32 :
case Opcode : : FPVectorRSqrtEstimate64 :
2019-04-15 02:01:00 +01:00
case Opcode : : FPVectorRSqrtStepFused16 :
2018-07-24 12:10:57 +01:00
case Opcode : : FPVectorRSqrtStepFused32 :
case Opcode : : FPVectorRSqrtStepFused64 :
2019-03-04 17:43:24 +00:00
case Opcode : : FPVectorSqrt32 :
case Opcode : : FPVectorSqrt64 :
2018-07-24 12:10:57 +01:00
case Opcode : : FPVectorSub32 :
case Opcode : : FPVectorSub64 :
2019-04-15 05:20:37 +01:00
case Opcode : : FPVectorToSignedFixed16 :
2019-04-15 05:53:15 +01:00
case Opcode : : FPVectorToSignedFixed32 :
case Opcode : : FPVectorToSignedFixed64 :
2019-04-15 05:20:37 +01:00
case Opcode : : FPVectorToUnsignedFixed16 :
2019-04-15 05:53:15 +01:00
case Opcode : : FPVectorToUnsignedFixed32 :
case Opcode : : FPVectorToUnsignedFixed64 :
2016-08-22 17:54:47 +01:00
return true ;
default :
return false ;
}
}
2018-07-24 12:10:57 +01:00
bool Inst : : ReadsFromFPSRCumulativeSaturationBit ( ) const {
return false ;
}
bool Inst : : WritesToFPSRCumulativeSaturationBit ( ) const {
2018-07-24 16:06:55 +01:00
switch ( op ) {
2018-07-24 19:04:40 +01:00
case Opcode : : A64OrQC :
2018-09-04 16:26:15 +01:00
case Opcode : : VectorSignedSaturatedAbs8 :
case Opcode : : VectorSignedSaturatedAbs16 :
case Opcode : : VectorSignedSaturatedAbs32 :
case Opcode : : VectorSignedSaturatedAbs64 :
2018-09-09 02:08:34 +01:00
case Opcode : : VectorSignedSaturatedAccumulateUnsigned8 :
case Opcode : : VectorSignedSaturatedAccumulateUnsigned16 :
case Opcode : : VectorSignedSaturatedAccumulateUnsigned32 :
case Opcode : : VectorSignedSaturatedAccumulateUnsigned64 :
2018-09-15 13:38:17 +01:00
case Opcode : : VectorSignedSaturatedDoublingMultiply16 :
case Opcode : : VectorSignedSaturatedDoublingMultiply32 :
case Opcode : : VectorSignedSaturatedDoublingMultiplyLong16 :
case Opcode : : VectorSignedSaturatedDoublingMultiplyLong32 :
2018-07-24 17:59:14 +01:00
case Opcode : : VectorSignedSaturatedNarrowToSigned16 :
case Opcode : : VectorSignedSaturatedNarrowToSigned32 :
case Opcode : : VectorSignedSaturatedNarrowToSigned64 :
2018-07-24 16:06:55 +01:00
case Opcode : : VectorSignedSaturatedNarrowToUnsigned16 :
case Opcode : : VectorSignedSaturatedNarrowToUnsigned32 :
case Opcode : : VectorSignedSaturatedNarrowToUnsigned64 :
2018-09-06 20:50:25 +01:00
case Opcode : : VectorSignedSaturatedNeg8 :
case Opcode : : VectorSignedSaturatedNeg16 :
case Opcode : : VectorSignedSaturatedNeg32 :
case Opcode : : VectorSignedSaturatedNeg64 :
2018-09-15 20:13:39 +01:00
case Opcode : : VectorSignedSaturatedShiftLeft8 :
case Opcode : : VectorSignedSaturatedShiftLeft16 :
case Opcode : : VectorSignedSaturatedShiftLeft32 :
case Opcode : : VectorSignedSaturatedShiftLeft64 :
2019-04-12 20:47:35 +01:00
case Opcode : : VectorSignedSaturatedShiftLeftUnsigned8 :
case Opcode : : VectorSignedSaturatedShiftLeftUnsigned16 :
case Opcode : : VectorSignedSaturatedShiftLeftUnsigned32 :
case Opcode : : VectorSignedSaturatedShiftLeftUnsigned64 :
2018-09-09 07:01:09 +01:00
case Opcode : : VectorUnsignedSaturatedAccumulateSigned8 :
case Opcode : : VectorUnsignedSaturatedAccumulateSigned16 :
case Opcode : : VectorUnsignedSaturatedAccumulateSigned32 :
case Opcode : : VectorUnsignedSaturatedAccumulateSigned64 :
2018-07-24 18:17:45 +01:00
case Opcode : : VectorUnsignedSaturatedNarrow16 :
case Opcode : : VectorUnsignedSaturatedNarrow32 :
case Opcode : : VectorUnsignedSaturatedNarrow64 :
2018-09-18 23:09:47 +01:00
case Opcode : : VectorUnsignedSaturatedShiftLeft8 :
case Opcode : : VectorUnsignedSaturatedShiftLeft16 :
case Opcode : : VectorUnsignedSaturatedShiftLeft32 :
case Opcode : : VectorUnsignedSaturatedShiftLeft64 :
2018-07-24 16:06:55 +01:00
return true ;
default :
return false ;
}
2018-07-24 12:10:57 +01:00
}
2016-08-22 17:54:47 +01:00
bool Inst : : CausesCPUException ( ) const {
2018-08-25 22:56:15 +01:00
return op = = Opcode : : Breakpoint | |
op = = Opcode : : A32CallSupervisor | |
op = = Opcode : : A32ExceptionRaised | |
op = = Opcode : : A64CallSupervisor | |
2018-01-13 17:54:29 +00:00
op = = Opcode : : A64ExceptionRaised ;
2016-08-22 17:54:47 +01:00
}
bool Inst : : AltersExclusiveState ( ) const {
2018-01-01 16:19:43 +00:00
return op = = Opcode : : A32ClearExclusive | |
op = = Opcode : : A32SetExclusive | |
A64: Implement STXRB, STXRH, STXR, STLXRB, STLXRH, STLXR, LDXRB, LDXRH, LDXR, LDAXRB, LDAXRH, LDAXR
2018-02-13 00:19:04 +00:00
op = = Opcode : : A64ClearExclusive | |
op = = Opcode : : A64SetExclusive | |
2016-08-22 17:54:47 +01:00
IsExclusiveMemoryWrite ( ) ;
}
2016-12-31 11:17:47 +00:00
bool Inst : : IsCoprocessorInstruction ( ) const {
switch ( op ) {
2018-01-01 16:19:43 +00:00
case Opcode : : A32CoprocInternalOperation :
case Opcode : : A32CoprocSendOneWord :
case Opcode : : A32CoprocSendTwoWords :
case Opcode : : A32CoprocGetOneWord :
case Opcode : : A32CoprocGetTwoWords :
case Opcode : : A32CoprocLoadWords :
case Opcode : : A32CoprocStoreWords :
2016-12-31 11:17:47 +00:00
return true ;
default :
return false ;
}
}
2019-05-03 23:28:02 +01:00
bool Inst : : IsSetCheckBitOperation ( ) const {
return op = = Opcode : : A32SetCheckBit | |
op = = Opcode : : A64SetCheckBit ;
}
2016-08-22 17:54:47 +01:00
bool Inst : : MayHaveSideEffects ( ) const {
2019-04-26 21:41:41 +01:00
return op = = Opcode : : PushRSB | |
op = = Opcode : : A64DataCacheOperationRaised | |
2019-05-03 23:28:02 +01:00
IsSetCheckBitOperation ( ) | |
2019-04-26 21:41:41 +01:00
IsBarrier ( ) | |
CausesCPUException ( ) | |
WritesToCoreRegister ( ) | |
WritesToSystemRegister ( ) | |
WritesToCPSR ( ) | |
WritesToFPCR ( ) | |
WritesToFPSR ( ) | |
AltersExclusiveState ( ) | |
IsMemoryWrite ( ) | |
2016-12-31 11:17:47 +00:00
IsCoprocessorInstruction ( ) ;
2016-11-30 21:51:06 +00:00
}
2016-08-22 17:54:47 +01:00
2018-01-07 11:31:20 +00:00
bool Inst : : IsAPseudoOperation ( ) const {
switch ( op ) {
case Opcode : : GetCarryFromOp :
case Opcode : : GetOverflowFromOp :
case Opcode : : GetGEFromOp :
case Opcode : : GetNZCVFromOp :
2018-09-14 20:06:11 +01:00
case Opcode : : GetUpperFromOp :
case Opcode : : GetLowerFromOp :
2018-01-07 11:31:20 +00:00
return true ;
default :
return false ;
}
}
bool Inst : : MayGetNZCVFromOp ( ) const {
switch ( op ) {
case Opcode : : Add32 :
case Opcode : : Add64 :
case Opcode : : Sub32 :
case Opcode : : Sub64 :
2018-01-07 12:52:12 +00:00
case Opcode : : And32 :
case Opcode : : And64 :
case Opcode : : Eor32 :
case Opcode : : Eor64 :
case Opcode : : Or32 :
case Opcode : : Or64 :
case Opcode : : Not32 :
case Opcode : : Not64 :
2018-01-07 11:31:20 +00:00
return true ;
default :
return false ;
}
}
2017-01-29 22:54:54 +00:00
bool Inst : : AreAllArgsImmediates ( ) const {
return std : : all_of ( args . begin ( ) , args . begin ( ) + NumArgs ( ) , [ ] ( const auto & value ) { return value . IsImmediate ( ) ; } ) ;
}
2017-04-04 13:10:50 +01:00
bool Inst : : HasAssociatedPseudoOperation ( ) const {
2018-09-14 20:06:11 +01:00
return carry_inst | | overflow_inst | | ge_inst | | nzcv_inst | | upper_inst | | lower_inst ;
2017-04-04 13:10:50 +01:00
}
2016-08-25 21:08:47 +01:00
Inst * Inst : : GetAssociatedPseudoOperation ( Opcode opcode ) {
// This is faster than doing a search through the block.
switch ( opcode ) {
2018-01-07 11:31:20 +00:00
case Opcode : : GetCarryFromOp :
2017-02-26 23:27:41 +00:00
ASSERT ( ! carry_inst | | carry_inst - > GetOpcode ( ) = = Opcode : : GetCarryFromOp ) ;
2016-08-25 21:08:47 +01:00
return carry_inst ;
2018-01-07 11:31:20 +00:00
case Opcode : : GetOverflowFromOp :
2017-02-26 23:27:41 +00:00
ASSERT ( ! overflow_inst | | overflow_inst - > GetOpcode ( ) = = Opcode : : GetOverflowFromOp ) ;
2016-08-25 21:08:47 +01:00
return overflow_inst ;
2018-01-07 11:31:20 +00:00
case Opcode : : GetGEFromOp :
2017-02-26 23:27:41 +00:00
ASSERT ( ! ge_inst | | ge_inst - > GetOpcode ( ) = = Opcode : : GetGEFromOp ) ;
2016-12-04 20:52:06 +00:00
return ge_inst ;
2018-01-07 11:31:20 +00:00
case Opcode : : GetNZCVFromOp :
ASSERT ( ! nzcv_inst | | nzcv_inst - > GetOpcode ( ) = = Opcode : : GetNZCVFromOp ) ;
return nzcv_inst ;
2018-09-14 20:06:11 +01:00
case Opcode : : GetUpperFromOp :
ASSERT ( ! upper_inst | | upper_inst - > GetOpcode ( ) = = Opcode : : GetUpperFromOp ) ;
return upper_inst ;
case Opcode : : GetLowerFromOp :
ASSERT ( ! lower_inst | | lower_inst - > GetOpcode ( ) = = Opcode : : GetLowerFromOp ) ;
return lower_inst ;
2016-08-25 21:08:47 +01:00
default :
break ;
}
ASSERT_MSG ( false , " Not a valid pseudo-operation " ) ;
return nullptr ;
}
2016-08-23 15:48:30 +01:00
Type Inst : : GetType ( ) const {
if ( op = = Opcode : : Identity )
return args [ 0 ] . GetType ( ) ;
return GetTypeOf ( op ) ;
}
2018-02-11 11:46:18 +00:00
size_t Inst : : NumArgs ( ) const {
return GetNumArgsOf ( op ) ;
}
2016-08-17 15:53:36 +01:00
Value Inst : : GetArg ( size_t index ) const {
2018-08-11 10:43:40 +01:00
ASSERT_MSG ( index < GetNumArgsOf ( op ) , " Inst::GetArg: index {} >= number of arguments of {} ({}) " , index , op , GetNumArgsOf ( op ) ) ;
2018-08-18 21:08:34 +01:00
ASSERT_MSG ( ! args [ index ] . IsEmpty ( ) | | GetArgTypeOf ( op , index ) = = IR : : Type : : Opaque , " Inst::GetArg: index {} is empty " , index , args [ index ] . GetType ( ) ) ;
2016-08-17 15:53:36 +01:00
return args [ index ] ;
}
void Inst : : SetArg ( size_t index , Value value ) {
2018-08-11 10:43:40 +01:00
ASSERT_MSG ( index < GetNumArgsOf ( op ) , " Inst::SetArg: index {} >= number of arguments of {} ({}) " , index , op , GetNumArgsOf ( op ) ) ;
ASSERT_MSG ( AreTypesCompatible ( value . GetType ( ) , GetArgTypeOf ( op , index ) ) , " Inst::SetArg: type {} of argument {} not compatible with operation {} ({}) " , value . GetType ( ) , index , op , GetArgTypeOf ( op , index ) ) ;
2016-08-17 15:53:36 +01:00
if ( ! args [ index ] . IsImmediate ( ) ) {
UndoUse ( args [ index ] ) ;
}
if ( ! value . IsImmediate ( ) ) {
Use ( value ) ;
}
args [ index ] = value ;
}
void Inst : : Invalidate ( ) {
2018-01-18 13:00:07 +00:00
ClearArgs ( ) ;
op = Opcode : : Void ;
}
void Inst : : ClearArgs ( ) {
2016-08-17 15:53:36 +01:00
for ( auto & value : args ) {
if ( ! value . IsImmediate ( ) ) {
UndoUse ( value ) ;
}
2017-02-18 21:29:23 +00:00
value = { } ;
2016-08-17 15:53:36 +01:00
}
}
2017-01-29 22:52:33 +00:00
void Inst : : ReplaceUsesWith ( Value replacement ) {
2016-08-17 15:53:36 +01:00
Invalidate ( ) ;
op = Opcode : : Identity ;
if ( ! replacement . IsImmediate ( ) ) {
Use ( replacement ) ;
}
args [ 0 ] = replacement ;
}
2017-01-29 22:53:46 +00:00
void Inst : : Use ( const Value & value ) {
2016-08-17 15:53:36 +01:00
value . GetInst ( ) - > use_count + + ;
switch ( op ) {
2016-08-22 23:40:30 +01:00
case Opcode : : GetCarryFromOp :
2016-08-25 21:08:47 +01:00
ASSERT_MSG ( ! value . GetInst ( ) - > carry_inst , " Only one of each type of pseudo-op allowed " ) ;
2016-08-22 23:40:30 +01:00
value . GetInst ( ) - > carry_inst = this ;
break ;
case Opcode : : GetOverflowFromOp :
2016-08-25 21:08:47 +01:00
ASSERT_MSG ( ! value . GetInst ( ) - > overflow_inst , " Only one of each type of pseudo-op allowed " ) ;
2016-08-22 23:40:30 +01:00
value . GetInst ( ) - > overflow_inst = this ;
break ;
2016-12-04 20:52:06 +00:00
case Opcode : : GetGEFromOp :
ASSERT_MSG ( ! value . GetInst ( ) - > ge_inst , " Only one of each type of pseudo-op allowed " ) ;
value . GetInst ( ) - > ge_inst = this ;
break ;
2018-01-07 11:31:20 +00:00
case Opcode : : GetNZCVFromOp :
ASSERT_MSG ( ! value . GetInst ( ) - > nzcv_inst , " Only one of each type of pseudo-op allowed " ) ;
2018-01-07 14:46:35 +00:00
ASSERT_MSG ( value . GetInst ( ) - > MayGetNZCVFromOp ( ) , " This value doesn't support the GetNZCVFromOp pseduo-op " ) ;
2018-01-07 11:31:20 +00:00
value . GetInst ( ) - > nzcv_inst = this ;
break ;
2018-09-14 20:06:11 +01:00
case Opcode : : GetUpperFromOp :
ASSERT_MSG ( ! value . GetInst ( ) - > upper_inst , " Only one of each type of pseudo-op allowed " ) ;
value . GetInst ( ) - > upper_inst = this ;
break ;
case Opcode : : GetLowerFromOp :
ASSERT_MSG ( ! value . GetInst ( ) - > lower_inst , " Only one of each type of pseudo-op allowed " ) ;
value . GetInst ( ) - > lower_inst = this ;
break ;
2016-08-22 23:40:30 +01:00
default :
break ;
2016-08-17 15:53:36 +01:00
}
}
2017-01-29 22:53:46 +00:00
void Inst : : UndoUse ( const Value & value ) {
2016-08-17 15:53:36 +01:00
value . GetInst ( ) - > use_count - - ;
switch ( op ) {
2016-08-22 23:40:30 +01:00
case Opcode : : GetCarryFromOp :
2017-02-26 23:27:41 +00:00
ASSERT ( value . GetInst ( ) - > carry_inst - > GetOpcode ( ) = = Opcode : : GetCarryFromOp ) ;
2016-08-22 23:40:30 +01:00
value . GetInst ( ) - > carry_inst = nullptr ;
break ;
case Opcode : : GetOverflowFromOp :
2017-02-26 23:27:41 +00:00
ASSERT ( value . GetInst ( ) - > overflow_inst - > GetOpcode ( ) = = Opcode : : GetOverflowFromOp ) ;
2016-08-22 23:40:30 +01:00
value . GetInst ( ) - > overflow_inst = nullptr ;
break ;
2016-12-04 20:52:06 +00:00
case Opcode : : GetGEFromOp :
2017-02-26 23:27:41 +00:00
ASSERT ( value . GetInst ( ) - > ge_inst - > GetOpcode ( ) = = Opcode : : GetGEFromOp ) ;
2016-12-04 20:52:06 +00:00
value . GetInst ( ) - > ge_inst = nullptr ;
break ;
2018-01-07 11:31:20 +00:00
case Opcode : : GetNZCVFromOp :
ASSERT ( value . GetInst ( ) - > nzcv_inst - > GetOpcode ( ) = = Opcode : : GetNZCVFromOp ) ;
value . GetInst ( ) - > nzcv_inst = nullptr ;
break ;
2018-09-14 20:06:11 +01:00
case Opcode : : GetUpperFromOp :
ASSERT ( value . GetInst ( ) - > upper_inst - > GetOpcode ( ) = = Opcode : : GetUpperFromOp ) ;
value . GetInst ( ) - > upper_inst = nullptr ;
break ;
case Opcode : : GetLowerFromOp :
ASSERT ( value . GetInst ( ) - > lower_inst - > GetOpcode ( ) = = Opcode : : GetLowerFromOp ) ;
value . GetInst ( ) - > lower_inst = nullptr ;
break ;
2016-08-22 23:40:30 +01:00
default :
break ;
2016-08-17 15:53:36 +01:00
}
}
2018-01-26 13:51:48 +00:00
} // namespace Dynarmic::IR