From 16f9a5b0b0211ba77ba5c2967cd41fbc42a4749f Mon Sep 17 00:00:00 2001 From: qiaopengcheng Date: Thu, 16 Jul 2020 17:57:40 +0800 Subject: [PATCH 01/13] 13557: [MIPS64] PartD - Fixed the unaligned memory accessing within the pedecode and initial frame. Implements unaligned read within Indir. Change-Id: I7d66d113effec159548f568f7d9413a7d855feec --- src/jit/codegencommon.cpp | 20 ++++++++++---- src/jit/codegenmips64.cpp | 54 +++++++++++++++++++++++++++++++------- src/utilcode/pedecoder.cpp | 6 +++++ 3 files changed, 66 insertions(+), 14 deletions(-) diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp index 1501bdc35bc5..7e157595e225 100644 --- a/src/jit/codegencommon.cpp +++ b/src/jit/codegencommon.cpp @@ -7043,6 +7043,7 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, unsigned uCntBytes = untrLclHi - untrLclLo; assert((uCntBytes % sizeof(int)) == 0); // The smallest stack slot is always 4 bytes. unsigned uCntSlots = uCntBytes / REGSIZE_BYTES; // How many register sized stack slots we're going to use. + unsigned int padding = untrLclLo & 0x7; // When uCntSlots is 9 or less, we will emit a sequence of sd instructions inline. // When it is 10 or greater, we will emit a loop containing a sd instruction. @@ -7062,6 +7063,7 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, // rAddr is not a live incoming argument reg assert((genRegMask(rAddr) & intRegState.rsCalleeRegArgMaskLiveIn) == 0); + assert(untrLclLo%4 == 0); if (emitter::emitIns_valid_imm_for_add(untrLclLo, EA_PTRSIZE)) { @@ -7075,6 +7077,13 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, *pInitRegZeroed = false; } + if (padding) + { + assert(padding == 4); + getEmitter()->emitIns_R_R_I(INS_sw, EA_4BYTE, REG_R0, rAddr, 0); + uCntBytes -= 4; + } + if (useLoop) { noway_assert(uCntSlots >= 2); @@ -7088,17 +7097,18 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, while (uCntBytes >= REGSIZE_BYTES * 2) { /* FIXME for MIPS: can be optimize further */ - getEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_R0, rAddr, 8); - getEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_R0, rAddr, 0); - getEmitter()->emitIns_R_R_I(INS_daddiu, EA_PTRSIZE, rAddr, rAddr, 2 * REGSIZE_BYTES); + getEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_R0, rAddr, 8 + padding); + getEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_R0, rAddr, 0 + padding); + getEmitter()->emitIns_R_R_I(INS_daddiu, EA_PTRSIZE, rAddr, rAddr, 2 * REGSIZE_BYTES + padding); uCntBytes -= REGSIZE_BYTES * 2; + padding = 0; } } else // useLoop is true { /* FIXME for MIPS: maybe optimize further */ - getEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_R0, rAddr, 8); - getEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_R0, rAddr, 0); + getEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_R0, rAddr, 8 + padding); + getEmitter()->emitIns_R_R_I(INS_sd, EA_PTRSIZE, REG_R0, rAddr, 0 + padding); getEmitter()->emitIns_R_R_I(INS_daddiu, EA_PTRSIZE, rCnt, rCnt, -1); { // bne rCnt, zero, -4 * 4 diff --git a/src/jit/codegenmips64.cpp b/src/jit/codegenmips64.cpp index b7b051ffe74a..34bf5876e525 100644 --- a/src/jit/codegenmips64.cpp +++ b/src/jit/codegenmips64.cpp @@ -8251,41 +8251,77 @@ void CodeGen::genCodeForIndir(GenTreeIndir* tree) var_types type = tree->TypeGet(); instruction ins = ins_Load(type); + instruction ins2 = INS_none; regNumber targetReg = tree->gtRegNum; + regNumber tmpReg = targetReg; + emitAttr attr = emitActualTypeSize(type); + int offset = 0; genConsumeAddress(tree->Addr()); bool emitBarrier = false; - if ((tree->gtFlags & GTF_IND_VOLATILE) != 0) { bool addrIsInReg = tree->Addr()->isUsedFromReg(); - bool addrIsAligned = ((tree->gtFlags & GTF_IND_UNALIGNED) == 0); + bool addrIsUnaligned = ((tree->gtFlags & GTF_IND_UNALIGNED) != 0); - if ((ins == INS_lb) && addrIsInReg) + if ((ins == INS_lb) && addrIsInReg && addrIsUnaligned) + { + //assert(!"-------Confirm for MIPS64--lb-----\n");//ins = INS_lb; + } + else if ((ins == INS_lh) && addrIsInReg && addrIsUnaligned) { ins = INS_lb; + ins2 = INS_lb; + attr = EA_1BYTE; + assert(REG_AT != targetReg); + + getEmitter()->emitIns_R_R_I(ins2, attr, REG_AT, tree->Addr()->gtRegNum, 1); + getEmitter()->emitIns_R_R_I(INS_dsll, EA_8BYTE, REG_AT, REG_AT, 8); + assert(!tree->Addr()->isContained()); } - else if ((ins == INS_lh) && addrIsInReg && addrIsAligned) + else if ((ins == INS_lw) && addrIsInReg && addrIsUnaligned) { - ins = INS_lh; + ins = INS_lwr; + ins2 = INS_lwl; + tmpReg = (tmpReg == tree->Addr()->gtRegNum) ? REG_AT : tmpReg; + offset = 3; + assert(REG_AT != targetReg); + assert(!tree->Addr()->isContained()); } - else if ((ins == INS_ld) && addrIsInReg && addrIsAligned && genIsValidIntReg(targetReg)) + else if ((ins == INS_ld) && addrIsInReg && addrIsUnaligned && genIsValidIntReg(targetReg)) { - ins = INS_ld; + ins = INS_ldr; + ins2 = INS_ldl; + tmpReg = (tmpReg == tree->Addr()->gtRegNum) ? REG_AT : tmpReg; + offset = 7; + assert(REG_AT != targetReg); + assert(!tree->Addr()->isContained()); } else { - emitBarrier = true; + if ((tree->gtFlags & GTF_IND_VOLATILE) != 0) + emitBarrier = true; } } - getEmitter()->emitInsLoadStoreOp(ins, emitActualTypeSize(type), targetReg, tree); + getEmitter()->emitInsLoadStoreOp(ins, attr, tmpReg, tree); if (emitBarrier) { instGen_MemoryBarrier(INS_BARRIER_OSHLD); } + else if (ins2 == INS_lb) + { + getEmitter()->emitIns_R_R_I_I(INS_dins, EA_8BYTE, REG_AT, targetReg, 0, 8); + getEmitter()->emitIns_R_R_I(INS_ori, EA_8BYTE, targetReg, REG_AT, 0); + } + else if (ins2 != INS_none) + { + getEmitter()->emitIns_R_R_I(ins2, attr, tmpReg, tree->Addr()->gtRegNum, offset); + if (tmpReg != targetReg) + getEmitter()->emitIns_R_R_I(INS_ori, EA_8BYTE, targetReg, tmpReg, 0); + } genProduceReg(tree); } diff --git a/src/utilcode/pedecoder.cpp b/src/utilcode/pedecoder.cpp index 73f27ca8fdca..4179dfc2ae91 100644 --- a/src/utilcode/pedecoder.cpp +++ b/src/utilcode/pedecoder.cpp @@ -1533,6 +1533,12 @@ CHECK PEDecoder::CheckILOnlyImportDlls() const PIMAGE_IMPORT_DESCRIPTOR pID = (PIMAGE_IMPORT_DESCRIPTOR) GetDirectoryData(pDirEntryImport); CHECK(pID != NULL); PREFIX_ASSUME(pID != NULL); +#ifdef _TARGET_MIPS64_ + IMAGE_IMPORT_DESCRIPTOR tmpID[2]; + //IMAGE_IMPORT_DESCRIPTOR tmpID1; + memcpy(tmpID, pID, 2*sizeof(IMAGE_IMPORT_DESCRIPTOR)); + pID = tmpID; +#endif // Entry 0: ILT, Name, IAT must be be non-null. Forwarder, DateTime should be NULL. CHECK( IMAGE_IMPORT_DESC_FIELD(pID[0], Characteristics) != 0 From afe57e9d75893110e9c8772e87a5d7bc6624c219 Mon Sep 17 00:00:00 2001 From: wanghaomin Date: Wed, 22 Jul 2020 17:53:20 +0800 Subject: [PATCH 02/13] 13833: Implement Nullable::UnBoxIntoArgNoGC when deal with Nullable Change-Id: I7fe6b5a89b4f777c5df1be44849e5aaf8a55f3ed --- src/vm/argdestination.h | 114 ++++++++++++++++++++++++++++------------ src/vm/object.cpp | 6 +-- 2 files changed, 84 insertions(+), 36 deletions(-) diff --git a/src/vm/argdestination.h b/src/vm/argdestination.h index dc03f3d8d6dd..f2db7516351b 100644 --- a/src/vm/argdestination.h +++ b/src/vm/argdestination.h @@ -296,7 +296,6 @@ class ArgDestination #ifndef DACCESS_COMPILE -/* // Zero struct argument stored in registers described by the current ArgDestination. // Arguments: // fieldBytes - size of the structure @@ -312,12 +311,43 @@ class ArgDestination // of dealing with the eightbyte classification in single function. // This function is used rarely and so the overhead of reading the zeros from // the stack is negligible. - long long zeros[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS] = {}; - _ASSERTE(sizeof(zeros) >= (size_t)fieldBytes); + _ASSERTE(IsStructPassedInRegs()); - CopyStructToRegisters(zeros, fieldBytes, 0); + BYTE* genRegDest = (BYTE*)GetStructGenRegDestinationAddress(); + BYTE* floatRegDest = (BYTE*)GetStructFloatRegDestinationAddress(); + BYTE* stackDest = (BYTE*)GetStructStackDestinationAddress(); + + EEClass* eeClass = m_argLocDescForStructInRegs->m_eeClass; + _ASSERTE(eeClass != NULL); + + int stackSlot = 0; + for (int i = 0; i < eeClass->GetNumberEightBytes(); i++) + { + if (m_argLocDescForStructInRegs->m_idxGenReg + i < 8) + { + MIPS64ClassificationType eightByteClassification = eeClass->GetEightByteClassification(i); + + if (eightByteClassification == MIPS64ClassificationTypeDouble) + { + *(UINT64*)floatRegDest = (UINT64)0; + floatRegDest += 8; + } + else + { + _ASSERTE(IS_ALIGNED((SIZE_T)genRegDest, 8)); + *(UINT64*)genRegDest = (UINT64)0; + genRegDest += 8; + } + } + else + { + _ASSERTE(stackSlot < m_argLocDescForStructInRegs->m_cStack); + *(UINT64*)stackDest = (UINT64)0; + stackDest += 8; + stackSlot++; + } + } } -*/ // Copy struct argument into registers described by the current ArgDestination. // Arguments: @@ -333,54 +363,69 @@ class ArgDestination STATIC_CONTRACT_MODE_COOPERATIVE; _ASSERTE(IsStructPassedInRegs()); - // Is it useful for MIPS? It must be zero temporarily. - _ASSERTE(destOffset == 0); - BYTE* genRegDest = (BYTE*)GetStructGenRegDestinationAddress(); - BYTE* floatRegDest = (BYTE*)GetStructFloatRegDestinationAddress(); + BYTE* genRegDest = (BYTE*)GetStructGenRegDestinationAddress() + destOffset; + BYTE* floatRegDest = (BYTE*)GetStructFloatRegDestinationAddress() + destOffset; BYTE* stackDest = (BYTE*)GetStructStackDestinationAddress(); INDEBUG(int remainingBytes = fieldBytes;) EEClass* eeClass = m_argLocDescForStructInRegs->m_eeClass; _ASSERTE(eeClass != NULL); - int stackSlot = 0; - // We start at the first eightByte that the destOffset didn't skip completely. - for (int i = destOffset / 8; i < eeClass->GetNumberEightBytes(); i++) + if (destOffset != 0) { - if (m_argLocDescForStructInRegs->m_idxGenReg + i < 8) + _ASSERTE(destOffset <= 8); // Nullable, if size of T is more than 8, need deal with it. + if (m_argLocDescForStructInRegs->m_idxGenReg + (destOffset/8) < 8) { - //int eightByteSize = eeClass->GetEightByteSize(i); - MIPS64ClassificationType eightByteClassification = eeClass->GetEightByteClassification(i); - - // Adjust the size of the first eightByte by the destOffset - //eightByteSize -= (destOffset & 7); - //destOffset = 0; - - //_ASSERTE(remainingBytes >= eightByteSize); - + MIPS64ClassificationType eightByteClassification = eeClass->GetEightByteClassification(destOffset/8); if (eightByteClassification == MIPS64ClassificationTypeDouble) { - *(UINT64*)floatRegDest = *(UINT64*)src; - floatRegDest += 8; + memcpyNoGCRefs(floatRegDest, src, fieldBytes); } else { - _ASSERTE(IS_ALIGNED((SIZE_T)genRegDest, 8)); - *(UINT64*)genRegDest = *(UINT64*)src; - genRegDest += 8; + memcpyNoGCRefs(genRegDest, src, fieldBytes); } } else { - _ASSERTE(stackSlot < m_argLocDescForStructInRegs->m_cStack); - *(UINT64*)stackDest = *(UINT64*)src; - stackDest += 8; - stackSlot++; + memcpyNoGCRefs(stackDest, src, fieldBytes); } - src = (BYTE*)src + 8; - INDEBUG(remainingBytes -= 8;) + INDEBUG(remainingBytes -= fieldBytes;) + } + else + { + int stackSlot = 0; + for (int i = 0; i < eeClass->GetNumberEightBytes(); i++) + { + if (m_argLocDescForStructInRegs->m_idxGenReg + i < 8) + { + MIPS64ClassificationType eightByteClassification = eeClass->GetEightByteClassification(i); + + if (eightByteClassification == MIPS64ClassificationTypeDouble) + { + *(UINT64*)floatRegDest = *(UINT64*)src; + floatRegDest += 8; + } + else + { + _ASSERTE(IS_ALIGNED((SIZE_T)genRegDest, 8)); + *(UINT64*)genRegDest = *(UINT64*)src; + genRegDest += 8; + } + } + else + { + _ASSERTE(stackSlot < m_argLocDescForStructInRegs->m_cStack); + *(UINT64*)stackDest = *(UINT64*)src; + stackDest += 8; + stackSlot++; + } + + src = (BYTE*)src + 8; + INDEBUG(remainingBytes -= 8;) + } } _ASSERTE(remainingBytes <= 0); @@ -388,6 +433,8 @@ class ArgDestination #endif //DACCESS_COMPILE + // FIXME for MIPS: It may be not useful. +/* // Report managed object pointers in the struct in registers // Arguments: // fn - promotion function to apply to each managed object pointer @@ -447,6 +494,7 @@ class ArgDestination //_ASSERTE(remainingBytes <= 0); } +*/ #endif // _TARGET_MIPS64_ diff --git a/src/vm/object.cpp b/src/vm/object.cpp index 671dc44fbacd..5094b9da6edd 100644 --- a/src/vm/object.cpp +++ b/src/vm/object.cpp @@ -493,7 +493,7 @@ void InitValueClassArg(ArgDestination *argDest, MethodTable *pMT) STATIC_CONTRACT_FORBID_FAULT; STATIC_CONTRACT_MODE_COOPERATIVE; -#if defined(UNIX_AMD64_ABI) +#if defined(UNIX_AMD64_ABI) || defined(_TARGET_MIPS64_) if (argDest->IsStructPassedInRegs()) { @@ -1914,7 +1914,7 @@ BOOL Nullable::UnBoxIntoArgNoGC(ArgDestination *argDest, OBJECTREF boxedVal, Met } CONTRACTL_END; -#if defined(UNIX_AMD64_ABI) +#if defined(UNIX_AMD64_ABI) || defined(_TARGET_MIPS64_) if (argDest->IsStructPassedInRegs()) { // We should only get here if we are unboxing a T as a Nullable @@ -1952,7 +1952,7 @@ BOOL Nullable::UnBoxIntoArgNoGC(ArgDestination *argDest, OBJECTREF boxedVal, Met return TRUE; } -#endif // UNIX_AMD64_ABI +#endif // UNIX_AMD64_ABI || _TARGET_MIPS64_ return UnBoxNoGC(argDest->GetDestinationAddress(), boxedVal, destMT); } From f77c8849a05a794ab607510ea9c9efa1b4c6ba76 Mon Sep 17 00:00:00 2001 From: aoqi Date: Wed, 22 Jul 2020 15:28:58 +0800 Subject: [PATCH 03/13] 11772: added unstable tests into problem_list.txt Change-Id: I6f36b023ecf3ef4d11fa0287e118ba4c5ab6f99f --- tests/mips64/problem_list_sh.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/mips64/problem_list_sh.txt b/tests/mips64/problem_list_sh.txt index c275fd8835ce..9c269077b5ca 100644 --- a/tests/mips64/problem_list_sh.txt +++ b/tests/mips64/problem_list_sh.txt @@ -1,6 +1,7 @@ # # Copyright (c) Loongson Technology. All rights reserved. # +baseservices/threading/interlocked/add/InterlockedAddLongWithSubtract/InterlockedAddLongWithSubtract.sh mips64 # unstable on mips baseservices/threading/interlocked/compareexchange/CompareExchangeTClass_1/CompareExchangeTClass_1.sh mips64 #12739 failed on mips64 baseservices/threading/interlocked/compareexchange/CompareExchangeTString/CompareExchangeTString.sh mips64 #12739 failed on mips64 GC/Coverage/271010/271010.sh x64 mips64 #12863 failed item on x64 and mips64 @@ -32,6 +33,7 @@ JIT/Regression/CLR-x86-JIT/V1-M11-Beta1/b41391/b41391/b41391.sh x64 mips64 #1286 JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b31746/b31746/b31746.sh x64 mips64 #12863 failed item on x64 and mips64 JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b37646/b37646/b37646.sh x64 mips64 #12863 failed item on x64 and mips64 JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b41852/b41852/b41852.sh x64 mips64 #12863 failed item on x64 and mips64 +JIT/Regression/CLR-x86-JIT/V2.0-Beta2/b425314/b425314/b425314.sh mips64 # unstable on mips JIT/Regression/CLR-x86-JIT/v2.1/DDB/b175679/b175679/b175679.sh mips64 #12739 failed on mips64 JIT/Regression/JitBlue/GitHub_11408/GitHub_11408/GitHub_11408.sh x64 mips64 #12863 failed item on x64 and mips64 JIT/Regression/VS-ia64-JIT/V1.2-M01/b10827/b10827/b10827.sh mips64 #12739 failed on mips64 From 45d05009456a560399dfb2e318695c0e477843dd Mon Sep 17 00:00:00 2001 From: aoqi Date: Wed, 22 Jul 2020 19:31:34 +0800 Subject: [PATCH 04/13] 13902: updated problem_list_sh.txt when crossgen or skipcrossgen match Change-Id: Id381b9822e6d9639908c6670ae1efb957d5a69a4 --- tests/mips64/problem_list_sh.txt | 137 +++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/tests/mips64/problem_list_sh.txt b/tests/mips64/problem_list_sh.txt index 9c269077b5ca..e937c9d29b61 100644 --- a/tests/mips64/problem_list_sh.txt +++ b/tests/mips64/problem_list_sh.txt @@ -2,8 +2,16 @@ # Copyright (c) Loongson Technology. All rights reserved. # baseservices/threading/interlocked/add/InterlockedAddLongWithSubtract/InterlockedAddLongWithSubtract.sh mips64 # unstable on mips +baseservices/threading/interlocked/compareexchange/compareexchange2/compareexchange2.sh mips64 # failed when checked crossgen +baseservices/threading/interlocked/compareexchange/compareexchange3/compareexchange3.sh mips64 # failed when checked crossgen baseservices/threading/interlocked/compareexchange/CompareExchangeTClass_1/CompareExchangeTClass_1.sh mips64 #12739 failed on mips64 baseservices/threading/interlocked/compareexchange/CompareExchangeTString/CompareExchangeTString.sh mips64 #12739 failed on mips64 +baseservices/threading/interlocked/exchange/exchange2/exchange2.sh mips64 # failed when checked crossgen +baseservices/threading/interlocked/exchange/exchange3/exchange3.sh mips64 # failed when checked crossgen +baseservices/threading/interlocked/read/readthreads/readthreads.sh mips64 # failed when debug crossgen +CoreMangLib/system/runtime/interopservices/marshal/MarshalSizeOf1_PSC/MarshalSizeOf1_PSC.sh mips64 # failed when checked crossgen +CoreMangLib/system/threading/interlocked/InterlockedCompareExchange7/InterlockedCompareExchange7.sh mips64 # failed when checked crossgen +CoreMangLib/system/threading/interlocked/InterlockedExchange7/InterlockedExchange7.sh mips64 # failed when checked crossgen GC/Coverage/271010/271010.sh x64 mips64 #12863 failed item on x64 and mips64 GC/Features/LOHFragmentation/lohfragmentation/lohfragmentation.sh x64 mips64 #12863 failed item on x64 and mips64 GC/LargeMemory/Allocation/finalizertest/finalizertest.sh x64 mips64 #12863 failed item on x64 and mips64 @@ -13,31 +21,160 @@ GC/Regressions/dev10bugs/536168/536168/536168.sh x64 mips64 #12863 failed item o Interop/ExecInDefAppDom/ExecInDefAppDom/ExecInDefAppDom.sh x64 mips64 #12863 failed item on x64 and mips64 Interop/NativeCallable/NativeCallableTest/NativeCallableTest.sh mips64 #12725 blocked on mips64 JIT/Directed/arglist/vararg/vararg.sh x64 mips64 #12863 failed item on x64 and mips64 +JIT/Directed/coverage/oldtests/cse2_cs_d/cse2_cs_d.sh mips64 # failed when checked crossgen +JIT/Directed/coverage/oldtests/cse2_cs_do/cse2_cs_do.sh mips64 # failed when checked crossgen +JIT/Directed/coverage/oldtests/cse2_cs_r/cse2_cs_r.sh mips64 # failed when checked crossgen +JIT/Directed/coverage/oldtests/cse2_cs_ro/cse2_cs_ro.sh mips64 # failed when checked crossgen JIT/Directed/Misc/function_pointer/MutualThdRecur-fptr/MutualThdRecur-fptr.sh mips64 #12725 blocked on mips64 +JIT/Directed/nullabletypes/boxunboxinterface_d/boxunboxinterface_d.sh mips64 # failed when crossgen +JIT/Directed/nullabletypes/boxunboxinterface_do/boxunboxinterface_do.sh mips64 # failed when crossgen +JIT/Directed/nullabletypes/boxunboxinterface_r/boxunboxinterface_r.sh mips64 # failed when crossgen +JIT/Directed/nullabletypes/boxunboxinterface_ro/boxunboxinterface_ro.sh mips64 # failed when crossgen +JIT/Directed/nullabletypes/castclassinterface_d/castclassinterface_d.sh mips64 # failed when crossgen +JIT/Directed/nullabletypes/castclassinterface_do/castclassinterface_do.sh mips64 # failed when crossgen +JIT/Directed/nullabletypes/castclassinterface_r/castclassinterface_r.sh mips64 # failed when crossgen +JIT/Directed/nullabletypes/castclassinterface_ro/castclassinterface_ro.sh mips64 # failed when crossgen +JIT/Directed/nullabletypes/castclassvaluetype_d/castclassvaluetype_d.sh mips64 # failed when crossgen +JIT/Directed/nullabletypes/castclassvaluetype_do/castclassvaluetype_do.sh mips64 # failed when crossgen +JIT/Directed/nullabletypes/castclassvaluetype_r/castclassvaluetype_r.sh mips64 # failed when crossgen +JIT/Directed/nullabletypes/castclassvaluetype_ro/castclassvaluetype_ro.sh mips64 # failed when crossgen +JIT/Directed/nullabletypes/Desktop/boxunboxvaluetype_do/boxunboxvaluetype_do.sh mips64 # failed when crossgen +JIT/Directed/nullabletypes/Desktop/boxunboxvaluetype_r/boxunboxvaluetype_r.sh mips64 # failed when crossgen +JIT/Directed/nullabletypes/Desktop/boxunboxvaluetype_ro/boxunboxvaluetype_ro.sh mips64 # failed when crossgen JIT/Directed/PREFIX/unaligned/1/arglist/arglist.sh x64 mips64 #12863 failed item on x64 and mips64 JIT/Directed/PREFIX/unaligned/2/arglist/arglist.sh x64 mips64 #12863 failed item on x64 and mips64 JIT/Directed/PREFIX/unaligned/4/arglist/arglist.sh x64 mips64 #12863 failed item on x64 and mips64 JIT/Directed/PREFIX/volatile/1/arglist/arglist.sh x64 mips64 #12863 failed item on x64 and mips64 +JIT/HardwareIntrinsics/General/Vector128_1/Vector128_1_ro/Vector128_1_ro.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/General/Vector128_1/Vector128_1_r/Vector128_1_r.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/General/Vector128/Vector128_ro/Vector128_ro.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/General/Vector128/Vector128_r/Vector128_r.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/General/Vector256_1/Vector256_1_ro/Vector256_1_ro.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/General/Vector256_1/Vector256_1_r/Vector256_1_r.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/General/Vector256/Vector256_ro/Vector256_ro.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/General/Vector256/Vector256_r/Vector256_r.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/General/Vector64_1/Vector64_1_ro/Vector64_1_ro.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/General/Vector64_1/Vector64_1_r/Vector64_1_r.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/General/Vector64/Vector64_ro/Vector64_ro.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/General/Vector64/Vector64_r/Vector64_r.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/X86/Avx2/Avx2_r/Avx2_r.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/X86/Avx2/Avx2_ro/Avx2_ro.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/X86/Avx/Avx_r/Avx_r.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/X86/Avx/Avx_ro/Avx_ro.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/X86/Avx_Vector128/Avx_r/Avx_r.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/X86/Avx_Vector128/Avx_ro/Avx_ro.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/X86/Fma_Vector128/Fma_r/Fma_r.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/X86/Fma_Vector128/Fma_ro/Fma_ro.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/X86/Fma_Vector256/Fma_r/Fma_r.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/X86/Fma_Vector256/Fma_ro/Fma_ro.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro/Sse2_ro.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/X86/Sse2/Sse2_r/Sse2_r.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/X86/Sse2.X64/Sse2.X64_ro/Sse2.X64_ro.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/X86/Sse2.X64/Sse2.X64_r/Sse2.X64_r.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/X86/Sse3/Sse3_ro/Sse3_ro.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/X86/Sse3/Sse3_r/Sse3_r.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/X86/Sse41/Sse41_ro/Sse41_ro.sh mips64 # failed when checked crossgen +JIT/HardwareIntrinsics/X86/Sse41/Sse41_r/Sse41_r.sh mips64 # failed when checked crossgen JIT/IL_Conformance/Old/Conformance_Base/conv_ovf_i8_i/conv_ovf_i8_i.sh mips64 #12739 failed on mips64 JIT/jit64/mcc/interop/mcc_i00/mcc_i00.sh x64 mips64 #12863 failed item on x64 and mips64 JIT/jit64/opt/rngchk/ArrayWithThread_o/ArrayWithThread_o.sh mips64 #12739 failed on mips64 +JIT/jit64/valuetypes/nullable/box-unbox/box-unbox/box-unbox013/box-unbox013.sh mips64 # failed when crossgen +JIT/jit64/valuetypes/nullable/box-unbox/generics/box-unbox-generics013/box-unbox-generics013.sh mips64 # failed when crossgen +JIT/jit64/valuetypes/nullable/box-unbox/interface/box-unbox-interface018/box-unbox-interface018.sh mips64 # failed when crossgen +JIT/jit64/valuetypes/nullable/box-unbox/value/box-unbox-value013/box-unbox-value013.sh mips64 # failed when crossgen +JIT/jit64/valuetypes/nullable/castclass/castclass/castclass013/castclass013.sh mips64 # failed when crossgen +JIT/jit64/valuetypes/nullable/castclass/generics/castclass-generics013/castclass-generics013.sh mips64 # failed when crossgen +JIT/jit64/valuetypes/nullable/castclass/interface/castclass-interface018/castclass-interface018.sh mips64 # failed when crossgen +JIT/Methodical/Boxing/functional/_dbgsin_cs/_dbgsin_cs.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/functional/_dbgsin_il/_dbgsin_il.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/functional/_odbgsin_cs/_odbgsin_cs.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/functional/_orelsin_cs/_orelsin_cs.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/functional/_relsin_cs/_relsin_cs.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/functional/_relsin_il/_relsin_il.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/morph/_dbgsin_cs/_dbgsin_cs.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/morph/_odbgsin_cs/_odbgsin_cs.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/morph/_orelsin_cs/_orelsin_cs.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/morph/_relsin_cs/_relsin_cs.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/morph/sin3double/sin3double.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/seh/_dbgfault/_dbgfault.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/seh/_dbgfilter/_dbgfilter.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/seh/_dbgtry_cs/_dbgtry_cs.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/seh/_dbgtry_il/_dbgtry_il.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/seh/_odbgtry_cs/_odbgtry_cs.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/seh/_oreltry_cs/_oreltry_cs.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/seh/_relfault/_relfault.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/seh/_relfilter/_relfilter.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/seh/_reltry_cs/_reltry_cs.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/seh/_reltry_il/_reltry_il.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/xlang/_dbgsin_cs_cs/_dbgsin_cs_cs.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/xlang/_dbgsin_cs_il/_dbgsin_cs_il.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/xlang/_dbgsin_il_cs/_dbgsin_il_cs.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/xlang/_dbgsin_il_il/_dbgsin_il_il.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/xlang/_odbgsin_cs_cs/_odbgsin_cs_cs.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/xlang/_odbgsin_cs_il/_odbgsin_cs_il.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/xlang/_odbgsin_il_cs/_odbgsin_il_cs.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/xlang/_odbgsin_il_il/_odbgsin_il_il.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/xlang/_orelsin_cs_cs/_orelsin_cs_cs.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/xlang/_orelsin_cs_il/_orelsin_cs_il.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/xlang/_orelsin_il_cs/_orelsin_il_cs.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/xlang/_orelsin_il_il/_orelsin_il_il.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/xlang/_relsin_cs_cs/_relsin_cs_cs.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/xlang/_relsin_cs_il/_relsin_cs_il.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/xlang/_relsin_il_cs/_relsin_il_cs.sh mips64 # failed when checked crossgen +JIT/Methodical/Boxing/xlang/_relsin_il_il/_relsin_il_il.sh mips64 # failed when checked crossgen JIT/Methodical/Coverage/arglist_pos/arglist_pos.sh x64 mips64 #12863 failed item on x64 and mips64 JIT/Methodical/flowgraph/dev10_bug679955/volatileLocal1/volatileLocal1.sh mips64 #12739 failed on mips64 +JIT/Methodical/fp/apps/bouncingball_cs_d/bouncingball_cs_d.sh mips64 # failed when checked crossgen +JIT/Methodical/fp/apps/bouncingball_cs_do/bouncingball_cs_do.sh mips64 # failed when checked crossgen +JIT/Methodical/fp/apps/bouncingball_cs_r/bouncingball_cs_r.sh mips64 # failed when checked crossgen +JIT/Methodical/fp/apps/bouncingball_cs_ro/bouncingball_cs_ro.sh mips64 # failed when checked crossgen +JIT/Methodical/fp/exgen/1000w1d_cs_do/1000w1d_cs_do.sh mips64 # failed when crossgen +JIT/Methodical/fp/exgen/1000w1d_cs_ro/1000w1d_cs_ro.sh mips64 # failed when crossgen +JIT/Methodical/fp/exgen/10w5d_cs_d/10w5d_cs_d.sh mips64 # failed when crossgen and skipcrossgen +JIT/Methodical/fp/exgen/10w5d_cs_do/10w5d_cs_do.sh mips64 # failed when crossgen and skipcrossgen +JIT/Methodical/fp/exgen/10w5d_cs_r/10w5d_cs_r.sh mips64 # failed when crossgen and skipcrossgen +JIT/Methodical/fp/exgen/10w5d_cs_ro/10w5d_cs_ro.sh mips64 # failed when crossgen and skipcrossgen +JIT/Methodical/fp/exgen/200w1d-02_cs_do/200w1d-02_cs_do.sh mips64 # failed when crossgen +JIT/Methodical/fp/exgen/200w1d-02_cs_ro/200w1d-02_cs_ro.sh mips64 # failed when crossgen +JIT/Methodical/MDArray/basics/stringarr_cs_do/stringarr_cs_do.sh mips64 # failed when checked crossgen +JIT/Methodical/MDArray/basics/stringarr_cs_d/stringarr_cs_d.sh mips64 # failed when checked crossgen +JIT/Methodical/MDArray/basics/stringarr_cs_ro/stringarr_cs_ro.sh mips64 # failed when checked crossgen +JIT/Methodical/MDArray/basics/stringarr_cs_r/stringarr_cs_r.sh mips64 # failed when checked crossgen +JIT/Methodical/NaN/intrinsic_cs_d/intrinsic_cs_d.sh mips64 # failed when checked crossgen +JIT/Methodical/NaN/intrinsic_cs_do/intrinsic_cs_do.sh mips64 # failed when checked crossgen +JIT/Methodical/NaN/intrinsic_cs_r/intrinsic_cs_r.sh mips64 # failed when checked crossgen +JIT/Methodical/NaN/intrinsic_cs_ro/intrinsic_cs_ro.sh mips64 # failed when checked crossgen +JIT/Methodical/NaN/intrinsic_nonf_il_d/intrinsic_nonf_il_d.sh mips64 # failed when checked crossgen +JIT/Methodical/NaN/intrinsic_nonf_il_r/intrinsic_nonf_il_r.sh mips64 # failed when checked crossgen JIT/Methodical/refany/_il_dbgseq/_il_dbgseq.sh x64 mips64 #12863 failed item on x64 and mips64 JIT/Methodical/refany/_il_relseq/_il_relseq.sh x64 mips64 #12863 failed item on x64 and mips64 +JIT/opt/Inline/tests/mathfunc/mathfunc.sh mips64 # failed when checked crossgen +JIT/opt/ObjectStackAllocation/ObjectStackAllocationTests/ObjectStackAllocationTests.sh mips64 # blocked on mips when crossgen JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-5/regex-redux-5.sh mips64 #12739 failed on mips64 +JIT/Performance/CodeQuality/Benchstones/BenchF/Adams/Adams/Adams.sh mips64 # failed when checked crossgen JIT/Performance/CodeQuality/Roslyn/CscBench/CscBench.sh mips64 #12739 failed on mips64 +JIT/Performance/CodeQuality/Span/SpanBench/SpanBench.sh mips64 # failed when checked crossgen JIT/Regression/CLR-x86-EJIT/V1-M12-Beta2/b26323/b26323/b26323.sh x64 mips64 #12863 failed item on x64 and mips64 +JIT/Regression/CLR-x86-JIT/V1.1-M1-Beta1/b140711/b140711/b140711.sh mips64 # failed when checked crossgen JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b16423/b16423/b16423.sh x64 mips64 #12863 failed item on x64 and mips64 +JIT/Regression/CLR-x86-JIT/V1-M09.5-PDC/b29456/b29456/b29456.sh mips64 # failed when checked crossgen JIT/Regression/CLR-x86-JIT/V1-M11-Beta1/b41391/b41391/b41391.sh x64 mips64 #12863 failed item on x64 and mips64 JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b31746/b31746/b31746.sh x64 mips64 #12863 failed item on x64 and mips64 JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b37646/b37646/b37646.sh x64 mips64 #12863 failed item on x64 and mips64 JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b41852/b41852/b41852.sh x64 mips64 #12863 failed item on x64 and mips64 +JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b78694/b78694/b78694.sh mips64 # failed when checked crossgen JIT/Regression/CLR-x86-JIT/V2.0-Beta2/b425314/b425314/b425314.sh mips64 # unstable on mips +JIT/Regression/CLR-x86-JIT/V2.0-Beta2/b426654/b426654/b426654.sh mips64 # blocked on mips when skipcrossgen +JIT/Regression/CLR-x86-JIT/v2.1/b610750/b610750_32vs64/b610750_32vs64.sh mips64 # failed when checked crossgen JIT/Regression/CLR-x86-JIT/v2.1/DDB/b175679/b175679/b175679.sh mips64 #12739 failed on mips64 +JIT/Regression/JitBlue/DevDiv_362706/DevDiv_362706/DevDiv_362706.sh mips64 # failed when checked skipcrossgen +JIT/Regression/JitBlue/DevDiv_370233/DevDiv_370233/DevDiv_370233.sh mips64 # failed when checked skipcrossgen JIT/Regression/JitBlue/GitHub_11408/GitHub_11408/GitHub_11408.sh x64 mips64 #12863 failed item on x64 and mips64 JIT/Regression/VS-ia64-JIT/V1.2-M01/b10827/b10827/b10827.sh mips64 #12739 failed on mips64 +JIT/superpmi/superpmicollect/10w5d_cs_do.sh mips64 # failed when crossgen and skipcrossgen JIT/superpmi/superpmicollect/superpmicollect.sh x64 mips64 #12863 failed item on x64 and mips64 +Loader/AssemblyDependencyResolver/AssemblyDependencyResolverTests/AssemblyDependencyResolverTests/AssemblyDependencyResolverTests.sh mips64 # failed when checked crossgen Loader/AssemblyDependencyResolver/MissingHostPolicyTests/MissingHostPolicyTests/MissingHostPolicyTests.sh x64 mips64 #12863 failed item on x64 and mips64 +readytorun/DynamicMethodGCStress/DynamicMethodGCStress/DynamicMethodGCStress.sh mips64 # failed when crossgen tracing/eventcounter/pollingcounter/pollingcounter.sh mips64 #12739 failed on mips64 tracing/tracecontrol/tracecontrol/tracecontrol.sh x64 mips64 #12863 failed item on x64 and mips64 From 366d58ab7e4f04e53152759530495db10411bc65 Mon Sep 17 00:00:00 2001 From: "qiaopengcheng, Leslie Zhai" Date: Tue, 21 Jul 2020 14:07:22 +0800 Subject: [PATCH 05/13] 13740: [MIPS64] Fixed assert error "!CREATE_CHECK_STRING(pMT && pMT->Validate())" when testing with COMPlus_HeapVerify=1 and export COMPlus_GCStress=3. Change-Id: I9331da77d23a8ab01e07e6cb495c2accb7ecf08f --- src/inc/regdisp.h | 1 + src/vm/gcinfodecoder.cpp | 7 ++----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/inc/regdisp.h b/src/inc/regdisp.h index cdb51c0c4717..687f38eaa126 100644 --- a/src/inc/regdisp.h +++ b/src/inc/regdisp.h @@ -183,6 +183,7 @@ typedef struct _Arm64VolatileContextPointer #if defined(_TARGET_MIPS64_) typedef struct _Mips64VolatileContextPointer { + PDWORD64 R0; PDWORD64 At; PDWORD64 V0; PDWORD64 V1; diff --git a/src/vm/gcinfodecoder.cpp b/src/vm/gcinfodecoder.cpp index d932869fef77..5bccfec6ef94 100644 --- a/src/vm/gcinfodecoder.cpp +++ b/src/vm/gcinfodecoder.cpp @@ -1707,8 +1707,6 @@ OBJECTREF* GcInfoDecoder::GetCapturedRegister( #elif defined(_TARGET_MIPS64_) -#pragma message("unimplemented on MIPS yet") - #ifdef FEATURE_PAL OBJECTREF* GcInfoDecoder::GetCapturedRegister( int regNum, @@ -1731,15 +1729,14 @@ OBJECTREF* GcInfoDecoder::GetRegisterSlot( PREGDISPLAY pRD ) { - ////PORTABILITY_ASSERT("GcInfoDecoder::GetRegisterSlot, MIPS."); _ASSERTE(regNum >= 1 && regNum <= 31); DWORD64 **ppReg; if (regNum < 16) //t3 { - ppReg = &pRD->volatileCurrContextPointers.At; - return (OBJECTREF*)*(ppReg + (regNum-1)); + ppReg = &pRD->volatileCurrContextPointers.R0; + return (OBJECTREF*)*(ppReg + regNum); } else if (regNum == 24) //t8 { From 1f110bfc229cbe0ba49c5ebde61c79e7926a3f6e Mon Sep 17 00:00:00 2001 From: Leslie Zhai Date: Mon, 20 Jul 2020 12:39:08 +0800 Subject: [PATCH 06/13] 13790: PartA - Fix GCStress=0x4 infinite loop related issue. Change-Id: I465afbc64511feff2323274efa0cd2393b94c6d3 --- src/vm/gccover.cpp | 70 +++++++++++++++++++++++++++++++++++++---- src/vm/gccover.h | 6 ++-- src/vm/mips64/stubs.cpp | 2 +- 3 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/vm/gccover.cpp b/src/vm/gccover.cpp index 18bed33cfbf6..09a6c0260fd6 100644 --- a/src/vm/gccover.cpp +++ b/src/vm/gccover.cpp @@ -905,12 +905,12 @@ void replaceSafePointInstructionWithGcStressInstr(UINT32 safePointOffset, LPVOID // Is the call through a register or an immediate offset // bal - if ((instr & 0x0000) == 0x04110000) + if (((instr >> 26) & 0x3F) == 0x1 && ((instr >> 16) & 0x1F) == 0x11) { instructionIsACallThroughImmediate = TRUE; } // jalr - else if ((instr & 0x0000000F) == 0x00000009) + else if (((instr >> 26) & 0x3F) == 0x0 && (instr & 0x3F) == 0x9) { instructionIsACallThroughRegister = TRUE; } @@ -1051,7 +1051,7 @@ bool replaceInterruptibleRangesWithGcStressInstr (UINT32 startOffset, UINT32 sto } instrPtr += instrLen; -#elif defined(_TARGET_ARM64_) +#elif defined(_TARGET_ARM64_) || defined(_TARGET_MIPS64_) // Do not replace with gcstress interrupt instruction at call to JIT_RareDisableHelper if(!isCallToStopForGCJitHelper(instrPtr)) *((DWORD*)instrPtr) = INTERRUPT_INSTR; @@ -1121,7 +1121,50 @@ bool isCallToStopForGCJitHelper(PBYTE instrPtr) } } #elif defined(_TARGET_MIPS64_) - _ASSERTE(!"not implemented for MIPS64 platform"); + if ((*reinterpret_cast(instrPtr)) == 0x00000000) // Do we have a nop instruction? + { + return true; + } + + if ((((*reinterpret_cast(instrPtr)) >> 26) & 0x3F) == 0x0 && ((*reinterpret_cast(instrPtr)) & 0x3F) == 0x9) // Do we have a jalr instruction? + { + DWORD target = 0x0; + unsigned int imm1 = 0x0, imm2 = 0x0; + // jalr t9 + unsigned int regnum = ((*reinterpret_cast(instrPtr)) >> 21) & 0x1F; + instrPtr -= 4; + // ori t9,at,0x3318 + if ((((*reinterpret_cast(instrPtr)) >> 26) & 0x3f) == 0xD) // Do we have a ori instruction? + target += (*reinterpret_cast(instrPtr)) & 0xFFFF; + else + return false; + instrPtr -= 4; + // dsll at,at,0x10 + if ((((*reinterpret_cast(instrPtr)) >> 26) & 0x3F) == 0x0 && ((*reinterpret_cast(instrPtr)) & 0x3F) == 0x38) // Do we have a dsll instruction? + imm1 = ((*reinterpret_cast(instrPtr)) >> 6) & 0x1F; + else + return false; + instrPtr -= 4; + // ori at,at,0xf6a0 + if ((((*reinterpret_cast(instrPtr)) >> 26) & 0x3f) == 0xD) // Do we have a ori instruction? + target += ((*reinterpret_cast(instrPtr)) & 0xFFFF) << imm1; + else + return false; + instrPtr -= 4; + // dsll at,at,0x10 + if ((((*reinterpret_cast(instrPtr)) >> 26) & 0x3F) == 0x0 && ((*reinterpret_cast(instrPtr)) & 0x3F) == 0x38) // Do we have a dsll instruction? + imm2 = ((*reinterpret_cast(instrPtr)) >> 6) & 0x1F; + else + return false; + instrPtr -= 4; + // ori at,at,0xff + if ((((*reinterpret_cast(instrPtr)) >> 26) & 0x3f) == 0xD) // Do we have a ori instruction? + target += ((*reinterpret_cast(instrPtr)) & 0xFFFF) << (imm2 + imm1); + else + return false; + if ((TADDR)target == GetEEFuncEntryPoint(JIT_RareDisableHelper)) + return true; + } #endif return false; } @@ -1189,7 +1232,23 @@ static PBYTE getTargetOfCall(PBYTE instrPtr, PCONTEXT regs, PBYTE* nextInstr) { return 0; // Fail } #elif defined(_TARGET_MIPS64_) - _ASSERTE(!"not implemented for MIPS64 platform"); + if ((((*reinterpret_cast(instrPtr)) >> 26) & 0x3F) == 0x1 && (((*reinterpret_cast(instrPtr)) >> 16) & 0x1F) == 0x11) + { + int imm16 = (*reinterpret_cast(instrPtr)) & 0xffff; + *nextInstr = instrPtr + 4; + return PC + imm16; + } + else if ((((*reinterpret_cast(instrPtr)) >> 26) & 0x3F) == 0x0 && ((*reinterpret_cast(instrPtr)) & 0x3F) == 0x9) + { + // call through register + *nextInstr = instrPtr + 4; + unsigned int regnum = ((*reinterpret_cast(instrPtr)) >> 21) & 0x1F; + return (BYTE *)getRegVal(regnum, regs); + } + else + { + return 0; // Fail + } #endif #ifdef _TARGET_AMD64_ @@ -1592,7 +1651,6 @@ void DoGcStress (PCONTEXT regs, MethodDesc *pMD) afterCallProtect[0] = (instrVal == INTERRUPT_INSTR_PROTECT_RET); #elif defined(_TARGET_MIPS64_) - _ASSERTE(!"not implemented for MIPS64 platform"); DWORD instrVal = *(DWORD *)instrPtr; forceStack[6] = &instrVal; // This is so I can see it fastchecked diff --git a/src/vm/gccover.h b/src/vm/gccover.h index d907678f8bab..ba1a06a0b248 100644 --- a/src/vm/gccover.h +++ b/src/vm/gccover.h @@ -109,9 +109,9 @@ class GCCoverageInfo { #elif defined(_TARGET_MIPS64_) // The following encodings are undefined. -#define INTERRUPT_INSTR 0xffffffff -#define INTERRUPT_INSTR_CALL 0xfffffffe -#define INTERRUPT_INSTR_PROTECT_RET 0xfffffffd +#define INTERRUPT_INSTR 0x42000029 +#define INTERRUPT_INSTR_CALL 0x4200002A +#define INTERRUPT_INSTR_PROTECT_RET 0x4200002B #endif // _TARGET_* diff --git a/src/vm/mips64/stubs.cpp b/src/vm/mips64/stubs.cpp index 1d1f01a4b23d..a0b412a8053b 100644 --- a/src/vm/mips64/stubs.cpp +++ b/src/vm/mips64/stubs.cpp @@ -1617,7 +1617,7 @@ void StubLinkerCPU::EmitUnboxMethodStub(MethodDesc *pMD) #define END_DYNAMIC_HELPER_EMIT() \ _ASSERTE(pStart + cb == p); \ - while (p < pStart + cbAligned) { *(DWORD*)p = 0xBADC0DF0; p += 4; }\ + while (p < pStart + cbAligned) { *(DWORD*)p = 0x42000029; p += 4; }\ ClrFlushInstructionCache(pStart, cbAligned); \ return (PCODE)pStart From a2ff7061b8a5feed486bd2200548e265c0fe415d Mon Sep 17 00:00:00 2001 From: qiaopengcheng Date: Tue, 21 Jul 2020 20:05:25 +0800 Subject: [PATCH 07/13] 13790:[MIPS64] PartB - Fix update instructions error when GCStress=0x4. Change-Id: I0daee3018ae4db10abafc979b147eeedc73b31ef --- src/vm/threadsuspend.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/vm/threadsuspend.cpp b/src/vm/threadsuspend.cpp index 5c5e30daea82..f9c51537949c 100644 --- a/src/vm/threadsuspend.cpp +++ b/src/vm/threadsuspend.cpp @@ -4430,6 +4430,29 @@ void Thread::CommitGCStressInstructionUpdate() *(DWORD*)pbDestCode = *(DWORD*)pbSrcCode; +#elif defined(_TARGET_MIPS64_) + + *(DWORD*)pbDestCode = *(DWORD*)pbSrcCode; + //NOTE: not include likely and j and jal !!! + // + //b,beq; bal; bne; + if (((*(DWORD*)pbSrcCode >>26) == 4) || ((*(DWORD*)pbSrcCode >>16) == 0x411) || ((*(DWORD*)pbSrcCode >>26) == 0x14) + //bc1f; bc1t; bgez + || ((*(DWORD*)pbSrcCode & 0xffe30000) == 0x45000000) || ((*(DWORD*)pbSrcCode & 0xffe30000) == 0x45010000) || ((*(DWORD*)pbSrcCode & 0xfc1f0000) == 0x04010000) + //bgezal;bgtz;blez; + || ((*(DWORD*)pbSrcCode & 0xfc1f0000) == 0x04110000) || ((*(DWORD*)pbSrcCode & 0xfc1f0000) == 0x1c000000) || ((*(DWORD*)pbSrcCode & 0xfc1f0000) == 0x18000000) + //bltz;bltzal + || ((*(DWORD*)pbSrcCode & 0xfc1f0000) == 0x04000000) || ((*(DWORD*)pbSrcCode & 0xfc1f0000) == 0x04100000) + //jr, jr.hb; + || ((*(DWORD*)pbSrcCode & 0xfc1fffff) == 0x00000008) || ((*(DWORD*)pbSrcCode & 0xfc1fffff) == 0x00000408) + //jalr,jalr.hb + || ((*(DWORD*)pbSrcCode & 0xfc1f07ff) == 0x00000009) || ((*(DWORD*)pbSrcCode & 0xfc1f07ff) == 0x00000409)) + { + FlushInstructionCache(GetCurrentProcess(), (LPCVOID)pbDestCode, 4); + pbSrcCode += 4; + pbDestCode += 4; + *(DWORD*)pbDestCode = *(DWORD*)pbSrcCode; + } #else *pbDestCode = *pbSrcCode; From 1a80619ca11bb95df64cc8c2992f2e9f67565fa0 Mon Sep 17 00:00:00 2001 From: qiaopengcheng Date: Thu, 23 Jul 2020 21:50:57 +0800 Subject: [PATCH 08/13] 13740:[MIPS64] PartB - Fixed the assert error within "MethodTable::Validate" when GCstress=3/4. Change-Id: I90c0b8a5a5c01ea3cef88a076e273010a30e73c2 --- src/gcinfo/gcinfodumper.cpp | 2 +- src/inc/regdisp.h | 1 + src/jit/emitmips64.cpp | 49 ++++++++++++++++++++++--------------- src/vm/mips64/stubs.cpp | 2 ++ 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/gcinfo/gcinfodumper.cpp b/src/gcinfo/gcinfodumper.cpp index b6d689606e30..b81e29313136 100644 --- a/src/gcinfo/gcinfodumper.cpp +++ b/src/gcinfo/gcinfodumper.cpp @@ -190,7 +190,7 @@ BOOL GcInfoDumper::ReportPointerRecord ( #elif defined(_TARGET_MIPS64_) #undef REG #define REG(reg, field) { FIELD_OFFSET(Mips64VolatileContextPointer, field) } - //REG(zero, R0), + REG(zero, R0), REG(at, At), REG(v0, V0), REG(v1, V1), diff --git a/src/inc/regdisp.h b/src/inc/regdisp.h index 687f38eaa126..f23d8a830830 100644 --- a/src/inc/regdisp.h +++ b/src/inc/regdisp.h @@ -469,6 +469,7 @@ inline void FillRegDisplay(const PREGDISPLAY pRD, PT_CONTEXT pctx, PT_CONTEXT pC pRD->volatileCurrContextPointers.X[i] = &pctx->X[i]; #elif defined(_TARGET_MIPS64_) // _TARGET_ARM64_ /* FIXME for MIPS */ + pRD->volatileCurrContextPointers.R0 = &pctx->R0; pRD->volatileCurrContextPointers.At = &pctx->At; pRD->volatileCurrContextPointers.V0 = &pctx->V0; pRD->volatileCurrContextPointers.V1 = &pctx->V1; diff --git a/src/jit/emitmips64.cpp b/src/jit/emitmips64.cpp index 0f72f98d5015..80d0452deca8 100644 --- a/src/jit/emitmips64.cpp +++ b/src/jit/emitmips64.cpp @@ -466,6 +466,17 @@ bool emitter::emitInsMayWriteToGCReg(instrDesc* id) } return false; + //alu + case MIPS_OP_SLTI: + case MIPS_OP_SLTIU: + case MIPS_OP_ANDI: + case MIPS_OP_ORI: + case MIPS_OP_XORI: + case MIPS_OP_LUI: + case MIPS_OP_ADDI: + case MIPS_OP_ADDIU: + case MIPS_OP_DADDI: + case MIPS_OP_DADDIU: //load case 0x20://INS_lb: case 0x24://INS_lbu: @@ -3970,7 +3981,6 @@ unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp)); } - /* We update the GC info before the call as the variables cannot be used by the call. Killing variables before the call helps with boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029. @@ -4035,24 +4045,21 @@ unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t unsigned outputInstrSize = emitOutput_Instr(dst, code); dst += outputInstrSize; - - // All call instructions are 4-byte in size on MIPS64 - // - assert(outputInstrSize == callInstrSize); - - // If the GC register set has changed, report the new set. + // update volatile regs within emitThisGCrefRegs and emitThisByrefRegs. if (gcrefRegs != emitThisGCrefRegs) { emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst); } - // If the Byref register set has changed, report the new set. if (byrefRegs != emitThisByrefRegs) { emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst); } + // All call instructions are 4-byte in size on MIPS64 + // not including delay-slot which processed later. + assert(outputInstrSize == callInstrSize); - // If the method returns a GC ref, mark INTRET (R0) appropriately. + // If the method returns a GC ref, mark INTRET (V0) appropriately. if (id->idGCref() == GCT_GCREF) { gcrefRegs = emitThisGCrefRegs | RBM_INTRET; @@ -4062,7 +4069,7 @@ unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t byrefRegs = emitThisByrefRegs | RBM_INTRET; } - // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately + // If is a multi-register return method is called, mark INTRET_1 (V1) appropriately if (id->idIsLargeCall()) { instrDescCGCA* idCall = (instrDescCGCA*)id; @@ -4079,12 +4086,12 @@ unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t // If the GC register set has changed, report the new set. if (gcrefRegs != emitThisGCrefRegs) { - emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst+4); + emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst + 4); } // If the Byref register set has changed, report the new set. if (byrefRegs != emitThisByrefRegs) { - emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst+4); + emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst + 4); } // Some helper calls may be marked as not requiring GC info to be recorded. @@ -4941,14 +4948,15 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) // for stores, but we ignore those cases here.) if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref. { + BYTE* dst2 = *dp + 4; // We assume that "idReg1" is the primary destination register for all instructions if (id->idGCref() != GCT_NONE) { - emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst); + emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst2); } else { - emitGCregDeadUpd(id->idReg1(), dst); + emitGCregDeadUpd(id->idReg1(), dst2); } //if (emitInsMayWriteMultipleRegs(id)) @@ -4957,11 +4965,11 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) // // "idReg2" is the secondary destination register // if (id->idGCrefReg2() != GCT_NONE) // { - // emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst); + // emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), *dp); // } // else // { - // emitGCregDeadUpd(id->idReg2(), dst); + // emitGCregDeadUpd(id->idReg2(), *dp); // } //} } @@ -4974,9 +4982,10 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE); bool FPbased; int adr = emitComp->lvaFrameAddress(varNum, &FPbased); + BYTE* dst2 = *dp + 4; if (id->idGCref() != GCT_NONE) { - emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst); + emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst2); } else { @@ -4993,14 +5002,14 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) vt = tmpDsc->tdTempType(); } if (vt == TYP_REF || vt == TYP_BYREF) - emitGCvarDeadUpd(adr + ofs, dst); + emitGCvarDeadUpd(adr + ofs, dst2); } //if (emitInsWritesToLclVarStackLocPair(id)) //{ // unsigned ofs2 = ofs + TARGET_POINTER_SIZE; // if (id->idGCrefReg2() != GCT_NONE) // { - // emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst); + // emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), *dp); // } // else // { @@ -5017,7 +5026,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) // vt = tmpDsc->tdTempType(); // } // if (vt == TYP_REF || vt == TYP_BYREF) - // emitGCvarDeadUpd(adr + ofs2, dst); + // emitGCvarDeadUpd(adr + ofs2, *dp); // } //} } diff --git a/src/vm/mips64/stubs.cpp b/src/vm/mips64/stubs.cpp index a0b412a8053b..2a2767afbb52 100644 --- a/src/vm/mips64/stubs.cpp +++ b/src/vm/mips64/stubs.cpp @@ -281,6 +281,7 @@ static BranchInstructionFormat gBranchIF; void ClearRegDisplayArgumentAndScratchRegisters(REGDISPLAY * pRD) { + pRD->volatileCurrContextPointers.R0 = NULL; pRD->volatileCurrContextPointers.At = NULL; pRD->volatileCurrContextPointers.V0 = NULL; pRD->volatileCurrContextPointers.V1 = NULL; @@ -985,6 +986,7 @@ void ResumableFrame::UpdateRegDisplay(const PREGDISPLAY pRD) pRD->pCurrentContextPointers->Fp = &m_Regs->Fp; pRD->pCurrentContextPointers->Ra = &m_Regs->Ra; + pRD->volatileCurrContextPointers.R0 = &m_Regs->R0; pRD->volatileCurrContextPointers.At = &m_Regs->At; pRD->volatileCurrContextPointers.V0 = &m_Regs->V0; pRD->volatileCurrContextPointers.V1 = &m_Regs->V1; From 6160cccda4cc8f7fa8400d843e94ec810a19970a Mon Sep 17 00:00:00 2001 From: wangrui Date: Sat, 25 Jul 2020 15:35:30 +0800 Subject: [PATCH 09/13] 13849: Fix memory barriers. Change-Id: I324af76239d7bca75a8b1bdcedfb0fc2437355fe --- src/jit/codegen.h | 3 +-- src/jit/codegenmips64.cpp | 18 +++++++++++------- src/jit/emitmips64.cpp | 2 +- src/jit/instr.cpp | 2 +- src/jit/instr.h | 21 ++++++--------------- src/vm/mips64/asmhelpers.S | 1 + 6 files changed, 21 insertions(+), 26 deletions(-) diff --git a/src/jit/codegen.h b/src/jit/codegen.h index 6d89fae2abc8..fbde9e70c98b 100644 --- a/src/jit/codegen.h +++ b/src/jit/codegen.h @@ -1490,8 +1490,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #ifdef _TARGET_ARM64_ void instGen_MemoryBarrier(insBarrier barrierType = INS_BARRIER_ISH); #elif defined(_TARGET_MIPS64_) -////FIXME for MIPS. - void instGen_MemoryBarrier(insBarrier barrierType = INS_BARRIER_ISH); + void instGen_MemoryBarrier(insBarrier barrierType = INS_BARRIER_MB); #else void instGen_MemoryBarrier(); #endif diff --git a/src/jit/codegenmips64.cpp b/src/jit/codegenmips64.cpp index 34bf5876e525..92c6ed7c77f3 100644 --- a/src/jit/codegenmips64.cpp +++ b/src/jit/codegenmips64.cpp @@ -2752,8 +2752,8 @@ void CodeGen::genCodeForCpObj(GenTreeObj* cpObjNode) if (cpObjNode->gtFlags & GTF_BLK_VOLATILE) { - // issue a INS_BARRIER_ISHLD after a volatile CpObj operation - instGen_MemoryBarrier(INS_BARRIER_ISHLD); + // issue a INS_BARRIER_RMB after a volatile CpObj operation + instGen_MemoryBarrier(INS_BARRIER_RMB); } // Clear the gcInfo for REG_WRITE_BARRIER_SRC_BYREF and REG_WRITE_BARRIER_DST_BYREF. @@ -3490,18 +3490,22 @@ void CodeGen::genCodeForStoreInd(GenTreeStoreInd* tree) if ((ins == INS_sb) && addrIsInReg) { + instGen_MemoryBarrier(INS_BARRIER_REL); ins = INS_sb; } else if ((ins == INS_sh) && addrIsInReg && addrIsAligned) { + instGen_MemoryBarrier(INS_BARRIER_REL); ins = INS_sh; } else if ((ins == INS_sw) && genIsValidIntReg(dataReg) && addrIsInReg && addrIsAligned) { + instGen_MemoryBarrier(INS_BARRIER_REL); ins = INS_sw; } else if ((ins == INS_sd) && genIsValidIntReg(dataReg) && addrIsInReg && addrIsAligned) { + instGen_MemoryBarrier(INS_BARRIER_REL); ins = INS_sd; } else @@ -8309,7 +8313,7 @@ void CodeGen::genCodeForIndir(GenTreeIndir* tree) if (emitBarrier) { - instGen_MemoryBarrier(INS_BARRIER_OSHLD); + instGen_MemoryBarrier(INS_BARRIER_RMB); } else if (ins2 == INS_lb) { @@ -8352,8 +8356,8 @@ void CodeGen::genCodeForCpBlkHelper(GenTreeBlk* cpBlkNode) if (cpBlkNode->gtFlags & GTF_BLK_VOLATILE) { - // issue a INS_BARRIER_ISHLD after a volatile CpBlk operation - instGen_MemoryBarrier(INS_BARRIER_ISHLD); + // issue a INS_BARRIER_RMB after a volatile CpBlk operation + instGen_MemoryBarrier(INS_BARRIER_RMB); } } @@ -8498,8 +8502,8 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* cpBlkNode) if (cpBlkNode->gtFlags & GTF_BLK_VOLATILE) { - // issue a INS_BARRIER_ISHLD after a volatile CpBlkUnroll operation - instGen_MemoryBarrier(INS_BARRIER_ISHLD); + // issue a INS_BARRIER_RMB after a volatile CpBlkUnroll operation + instGen_MemoryBarrier(INS_BARRIER_RMB); } } diff --git a/src/jit/emitmips64.cpp b/src/jit/emitmips64.cpp index 80d0452deca8..8fe5e87a225e 100644 --- a/src/jit/emitmips64.cpp +++ b/src/jit/emitmips64.cpp @@ -4318,7 +4318,7 @@ LABEL_INS(bc1t) LABEL_INS_END(bc1f) LABEL_INS(sync) - code |= (reg[0] & 0x1f)<<6;//stype + code |= (imm[0] & 0x1f)<<6;//stype LABEL_INS_END(sync) LABEL_INS(ldxc1) diff --git a/src/jit/instr.cpp b/src/jit/instr.cpp index 931d28f75530..5794bcb04cef 100644 --- a/src/jit/instr.cpp +++ b/src/jit/instr.cpp @@ -2344,7 +2344,7 @@ void CodeGen::instGen_MemoryBarrier() #elif defined(_TARGET_ARM64_) getEmitter()->emitIns_BARR(INS_dmb, barrierType); #elif defined(_TARGET_MIPS64_) - instGen(INS_sync); + getEmitter()->emitIns_I(INS_sync, EA_4BYTE, barrierType); #else #error "Unknown _TARGET_" #endif diff --git a/src/jit/instr.h b/src/jit/instr.h index 3d854f884091..d9ffb2593d9a 100644 --- a/src/jit/instr.h +++ b/src/jit/instr.h @@ -284,21 +284,12 @@ enum insOpts : unsigned enum insBarrier : unsigned { - INS_BARRIER_OSHLD = 1, - INS_BARRIER_OSHST = 2, - INS_BARRIER_OSH = 3, - - INS_BARRIER_NSHLD = 5, - INS_BARRIER_NSHST = 6, - INS_BARRIER_NSH = 7, - - INS_BARRIER_ISHLD = 9, - INS_BARRIER_ISHST = 10, - INS_BARRIER_ISH = 11, - - INS_BARRIER_LD = 13, - INS_BARRIER_ST = 14, - INS_BARRIER_SY = 15, + INS_BARRIER_FULL = 0, + INS_BARRIER_WMB = 4, + INS_BARRIER_MB = 16, + INS_BARRIER_ACQ = 17, + INS_BARRIER_REL = 18, + INS_BARRIER_RMB = 19, }; #endif diff --git a/src/vm/mips64/asmhelpers.S b/src/vm/mips64/asmhelpers.S index 877fb673a855..76d106751ef7 100644 --- a/src/vm/mips64/asmhelpers.S +++ b/src/vm/mips64/asmhelpers.S @@ -201,6 +201,7 @@ LEAF_END JIT_PatchedCodeLast, _TEXT WRITE_BARRIER_ENTRY JIT_WriteBarrier .set noreorder + sync 18 sd v1, 0(v0) lui gp, %hi(%neg(%gp_rel(JIT_WriteBarrier))) From 75ccbd401c3fa5dc76abc9f9055c14a93babb31f Mon Sep 17 00:00:00 2001 From: qiaopengcheng Date: Tue, 28 Jul 2020 12:13:25 +0800 Subject: [PATCH 10/13] 13790:[MIPS64] PartC - Fixed assert error "TypeFromToken(at) == mdtCustomAttribute" when GC=4. Change-Id: I15802b796c01e7aec7182f747ef69d850d58ee6c --- src/jit/codegencommon.cpp | 7 +++++ src/jit/codegenmips64.cpp | 15 ++++----- src/jit/emitmips64.cpp | 64 ++++++++++++++++++++++++++++++++------- src/vm/gccover.cpp | 2 +- src/vm/threadsuspend.cpp | 2 +- 5 files changed, 70 insertions(+), 20 deletions(-) diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp index 7e157595e225..6233942c04dc 100644 --- a/src/jit/codegencommon.cpp +++ b/src/jit/codegencommon.cpp @@ -1872,18 +1872,25 @@ void CodeGen::genJumpToThrowHlpBlk(emitJumpKind jumpKind, SpecialCodeKind codeKi BasicBlock* tgtBlk = nullptr; emitJumpKind reverseJumpKind = emitter::emitReverseJumpKind(jumpKind); +#if defined(_TARGET_MIPS64_) + assert(reverseJumpKind == jumpKind); + tgtBlk = genCreateTempLabel(); +#else if (reverseJumpKind != jumpKind) { tgtBlk = genCreateTempLabel(); inst_JMP(reverseJumpKind, tgtBlk); } +#endif genEmitHelperCall(compiler->acdHelper(codeKind), 0, EA_UNKNOWN);//no branch-delay! // Define the spot for the normal non-exception case to jump to. if (tgtBlk != nullptr) { +#ifndef _TARGET_MIPS64_ assert(reverseJumpKind != jumpKind); +#endif genDefineTempLabel(tgtBlk); } } diff --git a/src/jit/codegenmips64.cpp b/src/jit/codegenmips64.cpp index 92c6ed7c77f3..fc362c9d1da3 100644 --- a/src/jit/codegenmips64.cpp +++ b/src/jit/codegenmips64.cpp @@ -8196,6 +8196,7 @@ void CodeGen::genCodeForIndexAddr(GenTreeIndexAddr* node) //getEmitter()->emitIns(INS_nop); } + emitAttr attr = emitActualTypeSize(node); // Can we use a ScaledAdd instruction? // if (isPow2(node->gtElemSize) && (node->gtElemSize <= 32768)) @@ -8212,22 +8213,22 @@ void CodeGen::genCodeForIndexAddr(GenTreeIndexAddr* node) CodeGen::genSetRegToIcon(tmpReg, (ssize_t)node->gtElemSize, TYP_INT); // dest = index * tmpReg + base - if (emitActualTypeSize(node) == EA_4BYTE) + if (attr == EA_4BYTE) { getEmitter()->emitIns_R_R(INS_multu, EA_4BYTE, index->gtRegNum, tmpReg); - getEmitter()->emitIns_R(INS_mflo, EA_4BYTE, REG_AT); - getEmitter()->emitIns_R_R_R(INS_addu, EA_4BYTE, node->gtRegNum, REG_AT, base->gtRegNum); + getEmitter()->emitIns_R(INS_mflo, attr, tmpReg); + getEmitter()->emitIns_R_R_R(INS_addu, attr, node->gtRegNum, tmpReg, base->gtRegNum); } else { - getEmitter()->emitIns_R_R(INS_dmultu, EA_8BYTE, index->gtRegNum, tmpReg); - getEmitter()->emitIns_R(INS_mflo, EA_8BYTE, REG_AT); - getEmitter()->emitIns_R_R_R(INS_daddu, EA_8BYTE, node->gtRegNum, REG_AT, base->gtRegNum); + getEmitter()->emitIns_R_R(INS_dmultu, EA_PTRSIZE, index->gtRegNum, tmpReg); + getEmitter()->emitIns_R(INS_mflo, attr, tmpReg); + getEmitter()->emitIns_R_R_R(INS_daddu, attr, node->gtRegNum, tmpReg, base->gtRegNum); } } // dest = dest + elemOffs - getEmitter()->emitIns_R_R_I(INS_daddiu, emitActualTypeSize(node), node->gtRegNum, node->gtRegNum, node->gtElemOffset); + getEmitter()->emitIns_R_R_I(INS_daddiu, attr, node->gtRegNum, node->gtRegNum, node->gtElemOffset); gcInfo.gcMarkRegSetNpt(base->gtGetRegMask()); diff --git a/src/jit/emitmips64.cpp b/src/jit/emitmips64.cpp index 8fe5e87a225e..a6b600fe32a7 100644 --- a/src/jit/emitmips64.cpp +++ b/src/jit/emitmips64.cpp @@ -391,9 +391,9 @@ bool emitter::emitInsMayWriteToGCReg(instrDesc* id) case MIPS_SPEC_SRAV: //case MIPS_SPEC_MOVZ: //case MIPS_SPEC_MOVN: - //case MIPS_SPEC_MFHI: + case MIPS_SPEC_MFHI: //case MIPS_SPEC_MTHI: - //case MIPS_SPEC_MFLO: + case MIPS_SPEC_MFLO: //case MIPS_SPEC_MTLO: case MIPS_SPEC_DSLLV: case MIPS_SPEC_DSRLV: @@ -3269,8 +3269,6 @@ void emitter::emitIns_R_C( assert(ins == INS_bal);//for special. assert(isGeneralRegister(reg)); - emitAttr size = EA_SIZE(attr); - // INS_OPTS_RC: placeholders. 4-ins: // bal 4 // lui at, off-hi-16bits @@ -3286,7 +3284,19 @@ void emitter::emitIns_R_C( id->idSmallCns(offs); //usually is 0. id->idInsOpt(INS_OPTS_RC); - id->idOpSize(size); + if (EA_IS_GCREF(attr)) + { + /* A special value indicates a GCref pointer value */ + id->idGCref(GCT_GCREF); + id->idOpSize(EA_PTRSIZE); + } + else if (EA_IS_BYREF(attr)) + { + /* A special value indicates a Byref pointer value */ + id->idGCref(GCT_BYREF); + id->idOpSize(EA_PTRSIZE); + } + id->idSetIsBound(); // We won't patch address since we will know the exact distance // once JIT code and data are allocated together. @@ -3360,8 +3370,6 @@ void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber reg, ssize_ assert(ins == INS_bal);//for special. assert(isGeneralRegister(reg)); - emitAttr size = EA_SIZE(attr); - // INS_OPTS_RELOC: placeholders. 4-ins: // bal 4 // lui at, off-hi-16bits @@ -3376,7 +3384,19 @@ void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber reg, ssize_ id->idInsOpt(INS_OPTS_RELOC); - id->idOpSize(size); + if (EA_IS_GCREF(attr)) + { + /* A special value indicates a GCref pointer value */ + id->idGCref(GCT_GCREF); + id->idOpSize(EA_PTRSIZE); + } + else if (EA_IS_BYREF(attr)) + { + /* A special value indicates a Byref pointer value */ + id->idGCref(GCT_BYREF); + id->idOpSize(EA_PTRSIZE); + } + id->idSetIsBound(); // We won't patch address since we will know the exact distance // once JIT code and data are allocated together. @@ -3504,7 +3524,19 @@ void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNu id->idAddr()->iiaBBlabel = dst; id->idReg1(reg); - id->idOpSize(EA_PTRSIZE); + + if (EA_IS_GCREF(attr)) + { + /* A special value indicates a GCref pointer value */ + id->idGCref(GCT_GCREF); + id->idOpSize(EA_PTRSIZE); + } + else if (EA_IS_BYREF(attr)) + { + /* A special value indicates a Byref pointer value */ + id->idGCref(GCT_BYREF); + id->idOpSize(EA_PTRSIZE); + } #ifdef DEBUG // Mark the catch return @@ -4656,6 +4688,7 @@ LABEL_INS_END(DONE) size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) { BYTE* dst = *dp; + BYTE* dst2 = dst + 4;//addr for updating gc info if needed. code_t code = 0; size_t sz;// = emitSizeOfInsDsc(id); @@ -4708,7 +4741,11 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) //regs[1] = REG_AT; regs[2] = REG_RA; *(code_t *)dst = emitInsOps(INS_daddu, regs, nullptr); + + id->idAddr()->iiaSetInstrEncode(*(code_t *)dst);//used for emitInsMayWriteToGCReg(). + dst += 4; + dst2 = dst; sz = sizeof(instrDescJmp); } @@ -4756,8 +4793,12 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) regs[1] = REG_AT; regs[2] = REG_RA; *(code_t *)dst = emitInsOps(INS_daddu, regs, nullptr); + + id->idAddr()->iiaSetInstrEncode(*(code_t *)dst);//used for emitInsMayWriteToGCReg(). dst += 4; + dst2 = dst; + sz = sizeof(instrDescJmp); } break; @@ -4812,7 +4853,10 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) *(code_t *)dst = emitInsOps(INS_daddu, regs, nullptr); } + id->idAddr()->iiaSetInstrEncode(*(code_t *)dst);//used for emitInsMayWriteToGCReg(). + dst += 4; + dst2 = dst; sz = sizeof(instrDescJmp); } break; @@ -4948,7 +4992,6 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) // for stores, but we ignore those cases here.) if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref. { - BYTE* dst2 = *dp + 4; // We assume that "idReg1" is the primary destination register for all instructions if (id->idGCref() != GCT_NONE) { @@ -4982,7 +5025,6 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE); bool FPbased; int adr = emitComp->lvaFrameAddress(varNum, &FPbased); - BYTE* dst2 = *dp + 4; if (id->idGCref() != GCT_NONE) { emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst2); diff --git a/src/vm/gccover.cpp b/src/vm/gccover.cpp index 09a6c0260fd6..102ff07f84de 100644 --- a/src/vm/gccover.cpp +++ b/src/vm/gccover.cpp @@ -1486,7 +1486,7 @@ void RemoveGcCoverageInterrupt(TADDR instrPtr, BYTE * savedInstrPtr) #elif defined(_TARGET_ARM64_) *(DWORD *)instrPtr = *(DWORD *)savedInstrPtr; #elif defined(_TARGET_MIPS64_) - _ASSERTE(!"not implemented for MIPS64 platform"); + //_ASSERTE(!"not implemented for MIPS64 platform"); *(DWORD *)instrPtr = *(DWORD *)savedInstrPtr; #else *(BYTE *)instrPtr = *savedInstrPtr; diff --git a/src/vm/threadsuspend.cpp b/src/vm/threadsuspend.cpp index f9c51537949c..80571e64b97d 100644 --- a/src/vm/threadsuspend.cpp +++ b/src/vm/threadsuspend.cpp @@ -4436,7 +4436,7 @@ void Thread::CommitGCStressInstructionUpdate() //NOTE: not include likely and j and jal !!! // //b,beq; bal; bne; - if (((*(DWORD*)pbSrcCode >>26) == 4) || ((*(DWORD*)pbSrcCode >>16) == 0x411) || ((*(DWORD*)pbSrcCode >>26) == 0x14) + if (((*(DWORD*)pbSrcCode >>26) == 4) || ((*(DWORD*)pbSrcCode >>16) == 0x411) || ((*(DWORD*)pbSrcCode >>26) == 0x5) //bc1f; bc1t; bgez || ((*(DWORD*)pbSrcCode & 0xffe30000) == 0x45000000) || ((*(DWORD*)pbSrcCode & 0xffe30000) == 0x45010000) || ((*(DWORD*)pbSrcCode & 0xfc1f0000) == 0x04010000) //bgezal;bgtz;blez; From 9274c7afa1d8bcd5b2fa1f5a4b1e7ba33524171e Mon Sep 17 00:00:00 2001 From: Leslie Zhai Date: Wed, 29 Jul 2020 15:51:29 +0800 Subject: [PATCH 11/13] 13936: Fix assert failure: !"Pointer updated without using write barrier" Change-Id: I5269d917ab11517f6592dfbc9e63d8497d9404f5 --- src/vm/mips64/asmhelpers.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/mips64/asmhelpers.S b/src/vm/mips64/asmhelpers.S index 76d106751ef7..70adb18948e1 100644 --- a/src/vm/mips64/asmhelpers.S +++ b/src/vm/mips64/asmhelpers.S @@ -230,7 +230,7 @@ WRITE_BARRIER_ENTRY JIT_WriteBarrier ld t3, 0(t3) slt AT, t0, t3 - bne AT, zero, 22f //LOCAL_LABEL(ShadowUpdateEnd) + beq AT, zero, 22f //LOCAL_LABEL(ShadowUpdateEnd) nop // *pShadow = v1 From 4b89bc956344170def9070827e0a615127903bd7 Mon Sep 17 00:00:00 2001 From: Guoyun Sun Date: Sat, 25 Jul 2020 16:06:06 +0800 Subject: [PATCH 12/13] 13951: Add a test case for uint type data comparison shift01.cs is for task #13159 Change-Id: I6a392147b8f5a4fe2a9f99cef8dbf46f23e45ef8 --- tests/src/JIT/MIPS64/shift01.cs | 51 +++++++++++++++++++++++++++++ tests/src/JIT/MIPS64/shift01.csproj | 36 ++++++++++++++++++++ tests/src/JIT/MIPS64/uint01.cs | 30 +++++++++++++++++ tests/src/JIT/MIPS64/uint01.csproj | 36 ++++++++++++++++++++ 4 files changed, 153 insertions(+) create mode 100644 tests/src/JIT/MIPS64/shift01.cs create mode 100644 tests/src/JIT/MIPS64/shift01.csproj create mode 100644 tests/src/JIT/MIPS64/uint01.cs create mode 100644 tests/src/JIT/MIPS64/uint01.csproj diff --git a/tests/src/JIT/MIPS64/shift01.cs b/tests/src/JIT/MIPS64/shift01.cs new file mode 100644 index 000000000000..ce987816df06 --- /dev/null +++ b/tests/src/JIT/MIPS64/shift01.cs @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// Copyright (c) Loongson Technology. All rights reserved. +// + +using System; + +public class Test +{ + public static int Main() + { + int result = 0; + result += Test.AddKeyword("Session", (long)0x1 << 7); + result += Test.AddKeyword("Session", (long)0x1 << 8); + result += Test.AddKeyword("Session", (long)0x1 << 15); + result += Test.AddKeyword("Session", (long)0x1 << 16); + result += Test.AddKeyword("Session", (long)0x1 << 31); + result += Test.AddKeyword("Session", (long)0x1 << 32); + result += Test.AddKeyword("Session", (long)0x1 << 47); + result += Test.AddKeyword("Session", (long)0x1 << 48); + + if (result == 8) + { + Console.WriteLine("Test Passed"); + return 100; + } + else + { + Console.WriteLine("Test Failed"); + return 1; + } + } + + public static int AddKeyword(string name, ulong value) + { + + if ((value & (value - 1)) != 0) + { + return 0; + } + else + { + return 1; + } + } + +} + diff --git a/tests/src/JIT/MIPS64/shift01.csproj b/tests/src/JIT/MIPS64/shift01.csproj new file mode 100644 index 000000000000..aede747262bd --- /dev/null +++ b/tests/src/JIT/MIPS64/shift01.csproj @@ -0,0 +1,36 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {B9C2A1E8-B95E-4765-B27D-F127A8E9D6C6} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + + + + + + + + + False + + + + PdbOnly + + + + + + + + + + + diff --git a/tests/src/JIT/MIPS64/uint01.cs b/tests/src/JIT/MIPS64/uint01.cs new file mode 100644 index 000000000000..d2b973960efe --- /dev/null +++ b/tests/src/JIT/MIPS64/uint01.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// Copyright (c) Loongson Technology. All rights reserved. +// + +using System; + +public class Test +{ + public static int Main() + { + uint value = 0xF0000000; + + if (value < 0xFFFFFFFF) + { + Console.WriteLine("Test Passed"); + return 100; + } + else + { + Console.WriteLine("Test Failed"); + return 1; + } + } + +} + diff --git a/tests/src/JIT/MIPS64/uint01.csproj b/tests/src/JIT/MIPS64/uint01.csproj new file mode 100644 index 000000000000..af5b6ae4cd4c --- /dev/null +++ b/tests/src/JIT/MIPS64/uint01.csproj @@ -0,0 +1,36 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {B9C2A1E8-B95E-4765-B27D-F127A8E9D6C6} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + + + + + + + + + False + + + + PdbOnly + + + + + + + + + + + From b2ffa7712b689206d38b4ac263d419e847e4f690 Mon Sep 17 00:00:00 2001 From: wanghaomin Date: Wed, 29 Jul 2020 15:20:06 +0800 Subject: [PATCH 13/13] 13867: Implement 32-bit compare Change-Id: I5fdbed1377e036df88fcd0f36349b4b459a58563 --- src/jit/codegenmips64.cpp | 108 ++++++++++++++++++++++++++++---------- src/jit/lsramips64.cpp | 7 +++ 2 files changed, 86 insertions(+), 29 deletions(-) diff --git a/src/jit/codegenmips64.cpp b/src/jit/codegenmips64.cpp index fc362c9d1da3..72ad03394b27 100644 --- a/src/jit/codegenmips64.cpp +++ b/src/jit/codegenmips64.cpp @@ -3802,8 +3802,18 @@ void CodeGen::genFloatToIntCast(GenTree* treeNode) } } - //FIXME: How about the case: op1->gtRegNum < 0 ? - //getEmitter()->emitIns_R_R(INS_abs_d, srcSize, op1->gtRegNum, op1->gtRegNum); + /* FIXME for MIPS: How about the case: op1->gtRegNum < 0 ? */ + //{ + // getEmitter()->emitIns_R_R(INS_dmtc1, EA_8BYTE, REG_R0, tmpReg); + + // getEmitter()->emitIns_R_R_I(srcType == TYP_DOUBLE ? INS_c_olt_d : INS_c_olt_s, EA_8BYTE, op1->gtRegNum, tmpReg, 2); + // getEmitter()->emitIns_I_I(INS_bc1f, EA_PTRSIZE, 2, 4 << 2); + // getEmitter()->emitIns(INS_nop); + + // getEmitter()->emitIns_R_R_I(INS_ori, EA_PTRSIZE, treeNode->gtRegNum, REG_R0, 0); + // getEmitter()->emitIns_I(INS_b, EA_PTRSIZE, srcType == TYP_DOUBLE ? 14 << 2 : 13 << 2); + // getEmitter()->emitIns(INS_nop); + //} getEmitter()->emitIns_R_I(INS_lui, EA_PTRSIZE, REG_AT, imm); if (srcType == TYP_DOUBLE) @@ -3819,7 +3829,7 @@ void CodeGen::genFloatToIntCast(GenTree* treeNode) getEmitter()->emitIns_R_R_R(srcType == TYP_DOUBLE ? INS_sub_d : INS_sub_s, EA_8BYTE, tmpReg, op1->gtRegNum, tmpReg); getEmitter()->emitIns_R_R_I(INS_ori, EA_PTRSIZE, REG_AT, REG_R0, 1); - getEmitter()->emitIns_R_R_I(dstSize == EA_8BYTE ? INS_dsll32 : INS_sll, EA_PTRSIZE, REG_AT, REG_AT, 31); + getEmitter()->emitIns_R_R_I(dstSize == EA_8BYTE ? INS_dsll32 : INS_dsll, EA_PTRSIZE, REG_AT, REG_AT, 31); getEmitter()->emitIns_R_R_I(srcType == TYP_DOUBLE ? INS_movt_d : INS_movt_s, EA_PTRSIZE, tmpReg, op1->gtRegNum, 2); @@ -3996,6 +4006,10 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) assert(tree->OperIs(GT_CMP, GT_LT, GT_LE, GT_EQ, GT_NE, GT_GT, GT_GE)); bool IsUnsigned = condition.IsUnsigned(); + regNumber tmpRegOp1 = tree->ExtractTempReg(); + regNumber tmpRegOp2 = tree->ExtractTempReg(); + regNumber regOp1 = op1->gtRegNum; + regNumber regOp2 = op2->gtRegNum; if (op2->isContainedIntOrIImmed()) { @@ -4021,28 +4035,37 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) } } + if (cmpSize == EA_4BYTE) + { + regOp1 = tmpRegOp1; + if (IsUnsigned) + emit->emitIns_R_R_I_I(INS_dext, EA_PTRSIZE, tmpRegOp1, op1->gtRegNum, 0, 32); + else + emit->emitIns_R_R_R(INS_addu, EA_PTRSIZE, tmpRegOp1, op1->gtRegNum, REG_R0); + } + if (tree->OperIs(GT_CMP)) { assert(!"------------should comfirm."); - //emit->emitIns_R_R_I(IsUnsigned ? INS_sltiu : INS_slti, EA_PTRSIZE, SaveCcResultReg, op1->gtRegNum, imm); + //emit->emitIns_R_R_I(IsUnsigned ? INS_sltiu : INS_slti, EA_PTRSIZE, SaveCcResultReg, regOp1, imm); } else if (tree->OperIs(GT_LT)) { if (isValidSimm16(imm)) { - emit->emitIns_R_R_I(IsUnsigned ? INS_sltiu : INS_slti, EA_PTRSIZE, SaveCcResultReg, op1->gtRegNum, imm); + emit->emitIns_R_R_I(IsUnsigned ? INS_sltiu : INS_slti, EA_PTRSIZE, SaveCcResultReg, regOp1, imm); } else { set_Reg_To_Imm(emit, EA_PTRSIZE, REG_AT, imm); - emit->emitIns_R_R_R(IsUnsigned ? INS_sltu : INS_slt, EA_PTRSIZE, SaveCcResultReg, op1->gtRegNum, REG_AT); + emit->emitIns_R_R_R(IsUnsigned ? INS_sltu : INS_slt, EA_PTRSIZE, SaveCcResultReg, regOp1, REG_AT); } } else if (tree->OperIs(GT_LE)) { set_Reg_To_Imm(emit, EA_PTRSIZE, REG_AT, imm); - emit->emitIns_R_R_R(IsUnsigned ? INS_sltu : INS_slt, EA_PTRSIZE, SaveCcResultReg, REG_AT, op1->gtRegNum); + emit->emitIns_R_R_R(IsUnsigned ? INS_sltu : INS_slt, EA_PTRSIZE, SaveCcResultReg, REG_AT, regOp1); emit->emitIns_R_R_I(INS_xori, EA_PTRSIZE, SaveCcResultReg, SaveCcResultReg, 1); } @@ -4050,19 +4073,19 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) { set_Reg_To_Imm(emit, EA_PTRSIZE, REG_AT, imm); - emit->emitIns_R_R_R(IsUnsigned ? INS_sltu : INS_slt, EA_PTRSIZE, SaveCcResultReg, REG_AT, op1->gtRegNum); + emit->emitIns_R_R_R(IsUnsigned ? INS_sltu : INS_slt, EA_PTRSIZE, SaveCcResultReg, REG_AT, regOp1); } else if (tree->OperIs(GT_GE)) { if (isValidSimm16(imm)) { - emit->emitIns_R_R_I(IsUnsigned ? INS_sltiu : INS_slti, EA_PTRSIZE, SaveCcResultReg, op1->gtRegNum, imm); + emit->emitIns_R_R_I(IsUnsigned ? INS_sltiu : INS_slti, EA_PTRSIZE, SaveCcResultReg, regOp1, imm); } else { set_Reg_To_Imm(emit, EA_PTRSIZE, REG_AT, imm); - emit->emitIns_R_R_R(IsUnsigned ? INS_sltu : INS_slt, EA_PTRSIZE, SaveCcResultReg, op1->gtRegNum, REG_AT); + emit->emitIns_R_R_R(IsUnsigned ? INS_sltu : INS_slt, EA_PTRSIZE, SaveCcResultReg, regOp1, REG_AT); } emit->emitIns_R_R_I(INS_xori, EA_PTRSIZE, SaveCcResultReg, SaveCcResultReg, 1); @@ -4073,13 +4096,13 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) { set_Reg_To_Imm(emit, EA_PTRSIZE, REG_AT, imm); - emit->emitIns_R_R_R(INS_xor, EA_PTRSIZE, SaveCcResultReg, op1->gtRegNum, REG_AT); + emit->emitIns_R_R_R(INS_xor, EA_PTRSIZE, SaveCcResultReg, regOp1, REG_AT); emit->emitIns_R_R_R(INS_sltu, EA_PTRSIZE, SaveCcResultReg, REG_R0, SaveCcResultReg); } else { - emit->emitIns_R_R_R(INS_sltu, EA_PTRSIZE, SaveCcResultReg, REG_R0, op1->gtRegNum); + emit->emitIns_R_R_R(INS_sltu, EA_PTRSIZE, SaveCcResultReg, REG_R0, regOp1); } } else if (tree->OperIs(GT_EQ)) @@ -4088,13 +4111,13 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) { set_Reg_To_Imm(emit, EA_PTRSIZE, REG_AT, imm); - emit->emitIns_R_R_R(INS_xor, EA_PTRSIZE, SaveCcResultReg, op1->gtRegNum, REG_AT); + emit->emitIns_R_R_R(INS_xor, EA_PTRSIZE, SaveCcResultReg, regOp1, REG_AT); emit->emitIns_R_R_I(INS_sltiu, EA_PTRSIZE, SaveCcResultReg, SaveCcResultReg, 1); } else { - emit->emitIns_R_R_I(INS_sltiu, EA_PTRSIZE, SaveCcResultReg, op1->gtRegNum, 1); + emit->emitIns_R_R_I(INS_sltiu, EA_PTRSIZE, SaveCcResultReg, regOp1, 1); } } else @@ -4104,38 +4127,54 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) } else { + if (cmpSize == EA_4BYTE) + { + regOp1 = tmpRegOp1; + regOp2 = tmpRegOp2; + if (IsUnsigned) + { + emit->emitIns_R_R_I_I(INS_dext, EA_PTRSIZE, tmpRegOp1, op1->gtRegNum, 0, 32); + emit->emitIns_R_R_I_I(INS_dext, EA_PTRSIZE, tmpRegOp2, op2->gtRegNum, 0, 32); + } + else + { + emit->emitIns_R_R_R(INS_addu, EA_PTRSIZE, tmpRegOp1, op1->gtRegNum, REG_R0); + emit->emitIns_R_R_R(INS_addu, EA_PTRSIZE, tmpRegOp2, op2->gtRegNum, REG_R0); + } + } + if (tree->OperIs(GT_CMP)) { assert(!"------------should comfirm-3."); } else if (/*tree->OperIs(GT_CMP) ||*/ tree->OperIs(GT_LT)) { - emit->emitIns_R_R_R(IsUnsigned ? INS_sltu : INS_slt, EA_8BYTE, SaveCcResultReg, op1->gtRegNum, op2->gtRegNum); + emit->emitIns_R_R_R(IsUnsigned ? INS_sltu : INS_slt, EA_8BYTE, SaveCcResultReg, regOp1, regOp2); } else if (tree->OperIs(GT_LE)) { - emit->emitIns_R_R_R(IsUnsigned ? INS_sltu : INS_slt, EA_8BYTE, SaveCcResultReg, op2->gtRegNum, op1->gtRegNum); + emit->emitIns_R_R_R(IsUnsigned ? INS_sltu : INS_slt, EA_8BYTE, SaveCcResultReg, regOp2, regOp1); emit->emitIns_R_R_I(INS_xori, EA_PTRSIZE, SaveCcResultReg, SaveCcResultReg, 1); } else if (tree->OperIs(GT_GT)) { - emit->emitIns_R_R_R(IsUnsigned ? INS_sltu : INS_slt, EA_8BYTE, SaveCcResultReg, op2->gtRegNum, op1->gtRegNum); + emit->emitIns_R_R_R(IsUnsigned ? INS_sltu : INS_slt, EA_8BYTE, SaveCcResultReg, regOp2, regOp1); } else if (tree->OperIs(GT_GE)) { - emit->emitIns_R_R_R(IsUnsigned ? INS_sltu : INS_slt, EA_8BYTE, SaveCcResultReg, op1->gtRegNum, op2->gtRegNum); + emit->emitIns_R_R_R(IsUnsigned ? INS_sltu : INS_slt, EA_8BYTE, SaveCcResultReg, regOp1, regOp2); emit->emitIns_R_R_I(INS_xori, EA_PTRSIZE, SaveCcResultReg, SaveCcResultReg, 1); } else if (tree->OperIs(GT_NE)) { - emit->emitIns_R_R_R(INS_xor, EA_PTRSIZE, SaveCcResultReg, op1->gtRegNum, op2->gtRegNum); + emit->emitIns_R_R_R(INS_xor, EA_PTRSIZE, SaveCcResultReg, regOp1, regOp2); emit->emitIns_R_R_R(INS_sltu, EA_PTRSIZE, SaveCcResultReg, REG_R0, SaveCcResultReg); } else if (tree->OperIs(GT_EQ)) { - emit->emitIns_R_R_R(INS_xor, EA_PTRSIZE, SaveCcResultReg, op1->gtRegNum, op2->gtRegNum); + emit->emitIns_R_R_R(INS_xor, EA_PTRSIZE, SaveCcResultReg, regOp1, regOp2); emit->emitIns_R_R_I(INS_sltiu, EA_PTRSIZE, SaveCcResultReg, SaveCcResultReg, 1); } @@ -4144,6 +4183,8 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) assert(!"unimplemented on MIPS yet"); } } + + genProduceReg(tree); } } @@ -9385,7 +9426,7 @@ void CodeGen::genIntToIntCast(GenTreeCast* cast) genConsumeRegs(cast->gtGetOp1()); emitter* emit = getEmitter(); - var_types dstType = cast->CastToType(); + var_types dstType = cast->CastToType(); var_types srcType = genActualType(cast->gtGetOp1()->TypeGet()); const regNumber srcReg = cast->gtGetOp1()->gtRegNum; const regNumber dstReg = cast->gtRegNum; @@ -9402,12 +9443,22 @@ void CodeGen::genIntToIntCast(GenTreeCast* cast) genIntCastOverflowCheck(cast, desc, srcReg); } - if ((EA_ATTR(genTypeSize(srcType)) == EA_8BYTE) && (EA_ATTR(genTypeSize(dstType)) == EA_4BYTE)) - { - // MIPS64 need to convert int64 t0 int32 - emit->emitIns_R_R_R(INS_addu, emitActualTypeSize(dstType), dstReg, srcReg, REG_R0); - } - else if ((desc.ExtendKind() != GenIntCastDesc::COPY) || (srcReg != dstReg)) + /* FIXME for MIPS: It is not needed for the time being. */ + //if ((EA_ATTR(genTypeSize(srcType)) == EA_8BYTE) && (EA_ATTR(genTypeSize(dstType)) == EA_4BYTE)) + //{ + // if (dstType == TYP_INT) + // { + // // convert t0 int32 + // emit->emitIns_R_R_I(INS_addiu, EA_4BYTE, dstReg, srcReg, 0); + // } + // else + // { + // // convert t0 uint32 + // emit->emitIns_R_R_I_I(INS_dext, EA_PTRSIZE, dstReg, srcReg, pos, 32); + // } + //} + //else if ((desc.ExtendKind() != GenIntCastDesc::COPY) || (srcReg != dstReg)) + if ((desc.ExtendKind() != GenIntCastDesc::COPY) || (srcReg != dstReg)) { instruction ins; @@ -9433,8 +9484,7 @@ void CodeGen::genIntToIntCast(GenTreeCast* cast) emit->emitIns_R_R_I_I(INS_dext, EA_PTRSIZE, dstReg, srcReg, pos, 32); break; case GenIntCastDesc::SIGN_EXTEND_INT: - emit->emitIns_R_R_I(INS_dsll32, EA_8BYTE, dstReg, srcReg, 0); - emit->emitIns_R_R_I(INS_dsra32, EA_8BYTE, dstReg, dstReg, 0); + emit->emitIns_R_R_I(INS_addiu, EA_4BYTE, dstReg, srcReg, 0); break; #endif default: diff --git a/src/jit/lsramips64.cpp b/src/jit/lsramips64.cpp index d38fb41f6785..4fcce8619479 100644 --- a/src/jit/lsramips64.cpp +++ b/src/jit/lsramips64.cpp @@ -369,6 +369,13 @@ int LinearScan::BuildNode(GenTree* tree) case GT_GE: case GT_GT: case GT_JCMP: + if (!varTypeIsFloating(tree->gtGetOp1())) + { + // We need two registers: tmpRegOp1 and tmpRegOp2 + buildInternalIntRegisterDefForNode(tree); + buildInternalIntRegisterDefForNode(tree); + buildInternalRegisterUses(); + } srcCount = BuildCmp(tree); break;