diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index b33cb34a48fdfb8583a87e36694dd9b91f11c96e..c392226f8029f99240196c7cb1ff698b73564c10 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -774,6 +774,30 @@ void EncApp::xInitLibCfg()
 #if TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM || MULTI_PASS_DMVR
   m_cEncLib.setUseDMVDMode                                       ( m_DMVDMode );
 #endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  m_cEncLib.setTMToolsEnableFlag                                 ( m_tmToolsEnableFlag );
+#if TM_AMVP
+  m_cEncLib.setUseTMAmvpMode                                     ( m_tmAmvpMode );
+#endif
+#if TM_MRG
+  m_cEncLib.setUseTMMrgMode                                      ( m_tmMrgMode );
+#endif
+#if JVET_W0097_GPM_MMVD_TM && TM_MRG
+  m_cEncLib.setUseGPMTMMode                                      ( m_tmGPMMode );
+#endif
+#if JVET_Z0061_TM_OBMC && ENABLE_OBMC
+  m_cEncLib.setUseOBMCTMMode                                     ( m_tmOBMCMode );
+#endif
+#if JVET_X0141_CIIP_TIMD_TM && TM_MRG
+  m_cEncLib.setUseCIIPTMMode                                     ( m_tmCIIPMode );
+#endif
+#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+  m_cEncLib.setUseTmvpNmvpReordering                             ( m_useTmvpNmvpReorder );
+#endif
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  m_cEncLib.setUseTMMMVD                                         ( m_useTMMMVD );
+#endif
+#endif
 #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
   m_cEncLib.setUseAltGPMSplitModeCode                            ( m_altGPMSplitModeCode );
 #endif
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index dd451e192fe718649e56cc3bc197728338d9277c..33e31f1c9ffec8ef1994bb24a366974092e96811 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -1014,6 +1014,30 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
 #if TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM || MULTI_PASS_DMVR
   ("DMVD",                                            m_DMVDMode,                                        true, "DMVD mode (0:off, 1:on)  [default: on]" )
 #endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  ("EnableTMTools",                                   m_tmToolsEnableFlag,                               true, "Enable TM tools (0:off, 1:on)  [default: on]" )
+#if TM_AMVP
+  ("TMAmvp",                                          m_tmAmvpMode,                                      true, "TM-AMVP mode (0:off, 1:on)  [default: on]" )
+#endif
+#if TM_MRG
+  ("TMMrg",                                           m_tmMrgMode,                                       true, "TM-MRG mode (0:off, 1:on)  [default: on]" )
+#endif
+#if JVET_W0097_GPM_MMVD_TM && TM_MRG
+  ("GPMTM",                                           m_tmGPMMode,                                       true, "GPM-TM mode (0:off, 1:on)  [default: on]" )
+#endif
+#if JVET_Z0061_TM_OBMC && ENABLE_OBMC
+  ("OBMCTM",                                          m_tmOBMCMode,                                      true, "OBMC-TM mode (0:off, 1:on)  [default: on]")
+#endif
+#if JVET_X0141_CIIP_TIMD_TM && TM_MRG
+  ("CIIPTM",                                          m_tmCIIPMode,                                         2, "CIIP-TM mode (0:off, 1:on, 2:on conditionally for non-negative intra period)  [default: 2]")
+#endif
+#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+  ("TmvpNmvpAML",                                     m_useTmvpNmvpReorder,                              true, "Enable ARMC for TMVP and non-adjacent MVP (0:off, 1:on)  [default: on]")
+#endif
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  ("TMMMVD",                                          m_useTMMMVD,                                       true, "Enable TM-MMVD (0:off, 1:on)  [default: on]")
+#endif
+#endif
 #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
   ("AltGPMSplitModeCode",                             m_altGPMSplitModeCode,                             true, "Enable alternative GPM split mode coding (0:off, 1:on)  [default: on]" )
 #endif
@@ -3720,6 +3744,151 @@ bool EncAppCfg::xCheckParameter()
     m_DMVR = false;
   }
 #endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  if (!m_tmToolsEnableFlag)
+  {
+#if TM_AMVP
+    if (m_tmAmvpMode)
+    {
+      msg(WARNING, "TM-AMVP mode is forcefully disabled since the enable flag of TM tools is set off. \n");
+      m_tmAmvpMode = false;
+    }
+#endif
+#if TM_MRG
+    if (m_tmMrgMode)
+    {
+      msg(WARNING, "TM-MRG mode is forcefully disabled since the enable flag of TM tools is set off. \n");
+      m_tmMrgMode = false;
+    }
+#endif
+#if JVET_W0097_GPM_MMVD_TM && TM_MRG
+    if (m_tmGPMMode)
+    {
+      msg(WARNING, "GPM-TM mode is forcefully disabled since the enable flag of TM tools is set off. \n");
+      m_tmGPMMode = false;
+    }
+#endif
+#if JVET_Z0061_TM_OBMC && ENABLE_OBMC
+    if (m_tmOBMCMode)
+    {
+      msg(WARNING, "OBMC-TM mode is forcefully disabled since the enable flag of TM tools is set off. \n");
+      m_tmOBMCMode = false;
+    }
+#endif
+#if JVET_X0141_CIIP_TIMD_TM && TM_MRG
+    if (m_tmCIIPMode != 0)
+    {
+      msg(WARNING, "CIIP-TM mode is forcefully disabled since the enable flag of TM tools is set off. \n");
+      m_tmCIIPMode = 0;
+    }
+#endif
+#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+    if (m_useTmvpNmvpReorder)
+    {
+      msg(WARNING, "Reordering for TMVP and non-adjacent MVP is forcefully disabled since the enable flag of TM tools is set off. \n");
+      m_useTmvpNmvpReorder = false;
+    }
+#endif
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+    if (m_useTMMMVD)
+    {
+      msg(WARNING, "TM-MMVD mode is forcefully disabled since the enable flag of TM tools is set off. \n");
+      m_useTMMMVD = false;
+    }
+#endif
+#if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
+    if (m_altGPMSplitModeCode)
+    {
+      msg(WARNING, "GPM split mode reordering is forcefully disabled since the enable flag of TM tools is set off. \n");
+      m_altGPMSplitModeCode = false;
+    }
+#endif
+#if JVET_W0090_ARMC_TM
+    if (m_AML)
+    {
+      msg(WARNING, "ARMC is forcefully disabled since the enable flag of TM tools is set off. \n");
+      m_AML = false;
+    }
+#endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+    if (m_armcRefinedMotion)
+    {
+      msg(WARNING, "Refined motion for ARMC is forcefully disabled since the enable flag of TM tools is set off. \n");
+      m_armcRefinedMotion = false;
+    }
+#endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+    if (m_numQPOffset)
+    {
+      msg(WARNING, "Diversity criterion for ARMC is forcefully disabled since the enable flag of TM tools is set off. \n");
+      m_numQPOffset = 0;
+    }
+#endif
+#if JVET_Z0054_BLK_REF_PIC_REORDER
+    if (m_useARL)
+    {
+      msg(WARNING, "Reference picture reordering is forcefully disabled since the enable flag of TM tools is set off. \n");
+      m_useARL = false;
+    }
+#endif
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+    if (m_MVSD)
+    {
+      msg(WARNING, "MVD sign prediction is forcefully disabled since the enable flag of TM tools is set off. \n");
+      m_MVSD = false;
+    }
+#endif
+  }
+#endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_W0097_GPM_MMVD_TM && TM_MRG
+  if (!m_Geo && m_tmGPMMode)
+  {
+    msg(WARNING, "GPM-TM mode is forcefully disabled since GPM is disabled. \n");
+    m_tmGPMMode = false;
+  }
+#endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Z0061_TM_OBMC && ENABLE_OBMC
+  if (!m_OBMC && m_tmOBMCMode)
+  {
+    msg(WARNING, "OBMC-TM mode is forcefully disabled since OBMC is disabled. \n");
+    m_tmOBMCMode = false;
+  }
+#endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_X0141_CIIP_TIMD_TM && TM_MRG
+  if (!m_ciip && m_tmCIIPMode != 0)
+  {
+    msg(WARNING, "CIIP-TM mode is forcefully disabled since CIIP is disabled. \n");
+    m_tmCIIPMode = 0;
+  }
+#endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+  if (!m_AML && m_useTmvpNmvpReorder)
+  {
+    msg(WARNING, "Forcefully disable reordering for TMVP and non-adjacent MVP since ARMC is disabled. \n");
+    m_useTmvpNmvpReorder = false;
+  }
+#endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  if (!m_AML && m_armcRefinedMotion)
+  {
+    msg(WARNING, "Forcefully disable refined motion for ARMC since ARMC is disabled. \n");
+    m_armcRefinedMotion = false;
+  }
+#endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  if (!m_AML && m_numQPOffset)
+  {
+    msg(WARNING, "Forcefully disable diversity criterion for ARMC since ARMC is disabled. \n");
+    m_numQPOffset = 0;
+  }
+#endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  if (!m_MMVD && !m_AffineMmvdMode && m_useTMMMVD)
+  {
+    msg(WARNING, "Forcefully disable TM-MMVD since neither MMVD nor AffineMMVD is enabled. \n");
+    m_useTMMMVD = 0;
+  }
+#endif
 
   xConfirmPara( m_MTS < 0 || m_MTS > 3, "MTS must be greater than 0 smaller than 4" );
   xConfirmPara( m_MTSIntraMaxCand < 0 || m_MTSIntraMaxCand > 5, "m_MTSIntraMaxCand must be greater than 0 and smaller than 6" );
@@ -4902,7 +5071,7 @@ void EncAppCfg::xPrintParameter()
     msg( VERBOSE, "DualITree:%d ", m_dualTree );
     msg( VERBOSE, "IMV:%d ", m_ImvMode );
     msg( VERBOSE, "BIO:%d ", m_BIO );
-#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC && !JVET_AA0132_CONFIGURABLE_TM_TOOLS
     msg( VERBOSE, "ArmcRefinedMotion:%d ", m_armcRefinedMotion );
 #endif
     msg( VERBOSE, "LMChroma:%d ", m_LMChroma );
@@ -4935,11 +5104,13 @@ void EncAppCfg::xPrintParameter()
     msg(VERBOSE, "AffineAmvp:%d ", m_AffineAmvp);
     msg(VERBOSE, "DMVR:%d ", m_DMVR);
     msg(VERBOSE, "MmvdDisNum:%d ", m_MmvdDisNum);
+#if !JVET_AA0132_CONFIGURABLE_TM_TOOLS
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
     msg(VERBOSE, "MVSD:%d ", m_MVSD);
 #endif
 #if JVET_Z0054_BLK_REF_PIC_REORDER
     msg(VERBOSE, "ARL:%d ", m_useARL);
+#endif
 #endif
     msg(VERBOSE, "JointCbCr:%d ", m_JointCbCrMode);
   }
@@ -5062,17 +5233,55 @@ void EncAppCfg::xPrintParameter()
     msg( VERBOSE, "FastPicLevelLIC:%d ", m_fastPicLevelLIC );
   }
 #endif
+#if !JVET_AA0132_CONFIGURABLE_TM_TOOLS
 #if JVET_W0090_ARMC_TM
   msg( VERBOSE, "AML:%d ", m_AML );
 #endif
+#endif
 #if TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM || MULTI_PASS_DMVR
   msg( VERBOSE, "DMVD:%d ", m_DMVDMode );
 #endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  msg( VERBOSE, "EnableTMTools:%d ( ", m_tmToolsEnableFlag );
+#if TM_AMVP
+  msg( VERBOSE, "TMAmvp:%d ", m_tmAmvpMode );
+#endif
+#if TM_MRG
+  msg( VERBOSE, "TMMrg:%d ", m_tmMrgMode );
+#endif
+#if JVET_W0097_GPM_MMVD_TM && TM_MRG
+  msg( VERBOSE, "GPMTM:%d ", m_tmGPMMode );
+#endif
+#if JVET_Z0061_TM_OBMC && ENABLE_OBMC
+  msg( VERBOSE, "OBMCTM:%d ", m_tmOBMCMode );
+#endif
+#if JVET_X0141_CIIP_TIMD_TM && TM_MRG
+  msg( VERBOSE, "CIIPTM:%d ", m_tmCIIPMode );
+#endif
+#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+  msg( VERBOSE, "TmvpNmvpAML:%d ", m_useTmvpNmvpReorder );
+#endif
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  msg( VERBOSE, "TMMMVD:%d ", m_useTMMMVD );
+#endif
+#if JVET_W0090_ARMC_TM
+  msg( VERBOSE, "AML:%d ", m_AML );
+#endif
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  msg(VERBOSE, "ArmcRefinedMotion:%d ", m_armcRefinedMotion);
+#endif
+#if JVET_Z0054_BLK_REF_PIC_REORDER
+  msg( VERBOSE, "ARL:%d ", m_useARL );
+#endif
+#endif
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
   msg( VERBOSE, "MVSD:%d ", m_MVSD );
 #endif
 #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
-    msg(VERBOSE, "AltGPMSplitModeCode:%d ", m_altGPMSplitModeCode);
+  msg( VERBOSE, "AltGPMSplitModeCode:%d ", m_altGPMSplitModeCode );
+#endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  msg( VERBOSE, ") " );
 #endif
 
   // transform and coefficient coding
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index 06b451d8dcdc193347bee0a8eae64e3b6094bf6d..157621de4960bb70c66e08d2ce5981fd0d512356 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -394,6 +394,30 @@ protected:
 #if TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM || MULTI_PASS_DMVR
   bool      m_DMVDMode;
 #endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  bool      m_tmToolsEnableFlag;
+#if TM_AMVP
+  bool      m_tmAmvpMode;
+#endif
+#if TM_MRG
+  bool      m_tmMrgMode;
+#endif
+#if JVET_W0097_GPM_MMVD_TM && TM_MRG
+  bool      m_tmGPMMode;
+#endif
+#if JVET_Z0061_TM_OBMC && ENABLE_OBMC
+  bool      m_tmOBMCMode;
+#endif
+#if JVET_X0141_CIIP_TIMD_TM && TM_MRG
+  int       m_tmCIIPMode;
+#endif
+#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+  bool      m_useTmvpNmvpReorder;
+#endif
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  bool      m_useTMMMVD;
+#endif
+#endif
 #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
   bool      m_altGPMSplitModeCode;
 #endif
diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h
index 60c11d9cefdd51274946e827dc39bf345ada3c40..898abd3b9aceb6006dee16513cd53a3f57f71bb1 100644
--- a/source/Lib/CommonLib/CommonDef.h
+++ b/source/Lib/CommonLib/CommonDef.h
@@ -648,6 +648,13 @@ static const int MMVD_BASE_MV_NUM =                                 3; ///< max
 static const int MMVD_BASE_MV_NUM =                                 2; ///< max number of base candidate
 #endif
 static const int MMVD_ADD_NUM =                                     (MMVD_MAX_REFINE_NUM * MMVD_BASE_MV_NUM);///< total number of mmvd candidate
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+static const int VVC_MMVD_BASE_MV_NUM =                             2; ///< max number of base candidate
+static const int VVC_MMVD_REFINE_STEP =                             8; ///< max number of distance step
+static const int VVC_MMVD_MAX_DIR =                                 4;
+static const int VVC_MMVD_MAX_REFINE_NUM =                          (VVC_MMVD_REFINE_STEP * VVC_MMVD_MAX_DIR); ///< max number of candidate from a base candidate
+static const int VVC_MMVD_ADD_NUM =                                 (VVC_MMVD_MAX_REFINE_NUM * VVC_MMVD_BASE_MV_NUM);///< total number of mmvd candidate
+#endif
 #if MERGE_ENC_OPT
 static const int MMVD_MRG_MAX_RD_NUM =                              20;
 #else
@@ -778,6 +785,13 @@ static const int    AFFINE_MMVD_SIZE_SHIFT =                        1;
 #endif
 static const int    AF_MMVD_MAX_REFINE_NUM = AF_MMVD_STEP_NUM * AF_MMVD_OFFSET_DIR; ///< max number of candidate from a base candidate
 static const int    AF_MMVD_NUM = AF_MMVD_BASE_NUM * AF_MMVD_MAX_REFINE_NUM;        ///< total number of affine mmvd candidate
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+static const int    ECM3_AF_MMVD_BASE_NUM =                         1;
+static const int    ECM3_AF_MMVD_STEP_NUM =                         5; // number of distance offset used in ECM3
+static const int    ECM3_AF_MMVD_OFFSET_DIR =                       4; // 00: (+, 0); 01: (-, 0); 10: (0, +); 11 (0, -);
+static const int    ECM3_AF_MMVD_MAX_REFINE_NUM = ECM3_AF_MMVD_STEP_NUM * ECM3_AF_MMVD_OFFSET_DIR; ///< max number of candidate from a base candidate used in ECM3
+static const int    ECM3_AF_MMVD_NUM = ECM3_AF_MMVD_BASE_NUM * ECM3_AF_MMVD_MAX_REFINE_NUM;   ///< total number of affine mmvd candidate used in ECM3
+#endif
 #if !MERGE_ENC_OPT
 static const int    NUM_AF_MMVD_SATD_CAND = std::min((int)1, MRG_MAX_NUM_CANDS);
 #endif
diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp
index f7b2a4dfa2b2280b73f26bce7c8bde7ea300bb57..9494bd3a441c53281897168f1ef975c024d376a5 100644
--- a/source/Lib/CommonLib/ContextModelling.cpp
+++ b/source/Lib/CommonLib/ContextModelling.cpp
@@ -928,7 +928,7 @@ void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx)
 {
   const Slice &slice = *pu.cs->slice;
   const int mvShift = MV_FRACTIONAL_BITS_DIFF;
-#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED && !JVET_AA0132_CONFIGURABLE_TM_TOOLS
   const int refMvdCands[] = { 1 << mvShift , 2 << mvShift , 4 << mvShift , 8 << mvShift , 16 << mvShift ,  32 << mvShift };
 #else
   const int refMvdCands[8] = { 1 << mvShift , 2 << mvShift , 4 << mvShift , 8 << mvShift , 16 << mvShift , 32 << mvShift,  64 << mvShift , 128 << mvShift };
@@ -948,6 +948,10 @@ void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx)
   tempIdx = candIdxMaped;
 #else
   tempIdx = candIdx;
+#endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  if (pu.cs->sps->getUseTMMMVD())
+  {
 #endif
   fPosGroup = tempIdx / (MMVD_BASE_MV_NUM * MMVD_MAX_REFINE_NUM);
   tempIdx = tempIdx - fPosGroup * (MMVD_BASE_MV_NUM * MMVD_MAX_REFINE_NUM);
@@ -959,6 +963,18 @@ void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx)
 #else
   fPosStep = tempIdx / 4;
   fPosPosition = tempIdx - fPosStep * (4);
+#endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  }
+  else
+  {
+    fPosGroup = tempIdx / (VVC_MMVD_BASE_MV_NUM * VVC_MMVD_MAX_REFINE_NUM);
+    tempIdx = tempIdx - fPosGroup * (VVC_MMVD_BASE_MV_NUM * VVC_MMVD_MAX_REFINE_NUM);
+    fPosBaseIdx = tempIdx / VVC_MMVD_MAX_REFINE_NUM;
+    tempIdx = tempIdx - fPosBaseIdx * (VVC_MMVD_MAX_REFINE_NUM);
+    fPosStep = tempIdx / VVC_MMVD_MAX_DIR;
+    fPosPosition = tempIdx - fPosStep * VVC_MMVD_MAX_DIR;
+  }
 #endif
   int offset = refMvdCands[fPosStep];
   if ( pu.cu->slice->getPicHeader()->getDisFracMMVD() )
@@ -980,7 +996,11 @@ void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx)
 #endif
    
 #if JVET_AA0093_ENHANCED_MMVD_EXTENSION
-  if ((refList0 != -1) && (refList1 != -1))
+  if ((refList0 != -1) && (refList1 != -1)
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    && pu.cs->sps->getUseTMMMVD()
+#endif
+    )
   {
     tempMv[0] = Mv(0,0);
     tempMv[1] = Mv(0,0);
@@ -1017,7 +1037,11 @@ void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx)
     pu.mv[REF_PIC_LIST_1] = mmvdBaseMv[fPosBaseIdx][1].mv + tempMv[1];
     pu.refIdx[REF_PIC_LIST_1] = refList1;
   }
-#else
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  else
+#endif
+#endif
+#if !JVET_AA0093_ENHANCED_MMVD_EXTENSION || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_AA0093_ENHANCED_MMVD_EXTENSION)
   if ((refList0 != -1) && (refList1 != -1))
   {
     const int poc0 = slice.getRefPOC(REF_PIC_LIST_0, refList0);
diff --git a/source/Lib/CommonLib/Contexts.cpp b/source/Lib/CommonLib/Contexts.cpp
index a5164509bd83c1c9b69125ca7863bb883d5c5820..78339e8f0548bc56d7218c4afa4a471083f3d5f9 100644
--- a/source/Lib/CommonLib/Contexts.cpp
+++ b/source/Lib/CommonLib/Contexts.cpp
@@ -942,17 +942,17 @@ const CtxSet ContextSetCfg::MmvdFlag = ContextSetCfg::addCtxSet
 const CtxSet ContextSetCfg::MmvdMergeIdx = ContextSetCfg::addCtxSet
 ({
 #if JVET_AA0093_ENHANCED_MMVD_EXTENSION
-  {  58, 58, 58, 58},
-  {  43, 43, 43, 43},
-  { CNU, CNU, CNU, CNU },
-  {   9, 9, 9, 9},
-  {  10, 10, 10, 10},
-  { DWS, DWS,DWS,DWS},
-  {  18, 18,18,18},
-  {  11, 11,11,11},
-  { DWE, DWE,DWE,DWE},
-  { 116, 116,116,116},
-  { 118, 118,118,118},
+  {  58,  58,  58,  58, },
+  {  43,  43,  43,  43, },
+  { CNU, CNU, CNU, CNU, },
+  {   9,   9,   9,   9, },
+  {  10,  10,  10,  10, },
+  { DWS, DWS, DWS, DWS, },
+  {  18,  18,  18,  18, },
+  {  11,  11,  11,  11, },
+  { DWE, DWE, DWE, DWE, },
+  { 116, 116, 116, 116, },
+  { 118, 118, 118, 118, },
 #else
   {  58, },
   {  43, },
@@ -997,6 +997,23 @@ const CtxSet ContextSetCfg::MmvdStepMvpIdx = ContextSetCfg::addCtxSet
 #endif
   });
 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+const CtxSet ContextSetCfg::MmvdStepMvpIdxECM3 = ContextSetCfg::addCtxSet
+({
+  {  59 },
+  {  60 },
+  {  35 },
+  {   0 },
+  {   0 },
+  {   0 },
+  { DWE },
+  { DWE },
+  { DWE },
+  { DWO },
+  { DWO },
+});
+#endif
+
 #if JVET_W0097_GPM_MMVD_TM
 const CtxSet ContextSetCfg::GeoMmvdFlag = ContextSetCfg::addCtxSet
 ({
@@ -1150,6 +1167,23 @@ const CtxSet ContextSetCfg::AfMmvdOffsetStep = ContextSetCfg::addCtxSet
   { 117 },
 #endif
   });
+
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+const CtxSet ContextSetCfg::AfMmvdOffsetStepECM3 = ContextSetCfg::addCtxSet
+({
+  {  21 },
+  {  13 },
+  { CNU },
+  {   5 },
+  {   5 },
+  { DWS },
+  {  18 },
+  {  18 },
+  { DWE },
+  { 126 },
+  { 117 },
+});
+#endif
 #endif
 
 #if JVET_AA0061_IBC_MBVD
@@ -3175,6 +3209,18 @@ const CtxSet ContextSetCfg::MmvdStepMvpIdx = ContextSetCfg::addCtxSet
 #endif
 });
 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+const CtxSet ContextSetCfg::MmvdStepMvpIdxECM3 = ContextSetCfg::addCtxSet
+({
+  { 59 },
+  { 60 },
+  { 35 },
+  { 0 },
+  { 0 },
+  { 0 }
+});
+#endif
+
 #if JVET_W0097_GPM_MMVD_TM
 const CtxSet ContextSetCfg::GeoMmvdFlag = ContextSetCfg::addCtxSet
 ({
@@ -3260,6 +3306,18 @@ const CtxSet ContextSetCfg::AfMmvdOffsetStep = ContextSetCfg::addCtxSet
   { 0 }
 #endif
 });
+
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+const CtxSet ContextSetCfg::AfMmvdOffsetStepECM3 = ContextSetCfg::addCtxSet
+({
+  { 51 },
+  { 60 },
+  { 35 },
+  {  0 },
+  {  0 },
+  {  0 }
+});
+#endif
 #endif
 
 #if JVET_AA0061_IBC_MBVD
@@ -4697,6 +4755,16 @@ const CtxSet ContextSetCfg::MmvdStepMvpIdx = ContextSetCfg::addCtxSet
   {   0, },
 });
 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+const CtxSet ContextSetCfg::MmvdStepMvpIdxECM3 = ContextSetCfg::addCtxSet
+({
+  {  59, },
+  {  60, },
+  { CNU, },
+  {   0, },
+});
+#endif
+
 #if JVET_W0097_GPM_MMVD_TM
 const CtxSet ContextSetCfg::GeoMmvdFlag = ContextSetCfg::addCtxSet
 ({
@@ -4747,6 +4815,15 @@ const CtxSet ContextSetCfg::AfMmvdOffsetStep = ContextSetCfg::addCtxSet
 	{ 35 },
 	{ 0 }
 });
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+const CtxSet ContextSetCfg::AfMmvdOffsetStepECM3 = ContextSetCfg::addCtxSet
+({
+  { 51 },
+  { 60 },
+  { 35 },
+  {  0 }
+  });
+#endif
 #endif
 
 #if JVET_AA0061_IBC_MBVD
diff --git a/source/Lib/CommonLib/Contexts.h b/source/Lib/CommonLib/Contexts.h
index 491ea1c3e3471f5ad9b48b98ad2339fa5dddfbfe..19352e5410fe0c69b4bccf976d185514aa859472 100644
--- a/source/Lib/CommonLib/Contexts.h
+++ b/source/Lib/CommonLib/Contexts.h
@@ -383,6 +383,9 @@ public:
   static const CtxSet   MmvdFlag;
   static const CtxSet   MmvdMergeIdx;
   static const CtxSet   MmvdStepMvpIdx;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  static const CtxSet   MmvdStepMvpIdxECM3;
+#endif
 #if JVET_W0097_GPM_MMVD_TM
   static const CtxSet   GeoMmvdFlag;
   static const CtxSet   GeoMmvdStepMvpIdx;
@@ -401,6 +404,9 @@ public:
   static const CtxSet   AfMmvdFlag;
   static const CtxSet   AfMmvdIdx;
   static const CtxSet   AfMmvdOffsetStep;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  static const CtxSet   AfMmvdOffsetStepECM3;
+#endif
 #endif
   #if JVET_AA0061_IBC_MBVD
   static const CtxSet   IbcMbvdFlag;
diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp
index e946c262c235e2c815268b748e25816dd4e6f570..b605a0d2b7a48bd91beae4bd8bcc5853b2533554 100644
--- a/source/Lib/CommonLib/InterPrediction.cpp
+++ b/source/Lib/CommonLib/InterPrediction.cpp
@@ -1982,14 +1982,23 @@ void InterPrediction::xPredInterBlk ( const ComponentID& compID, const Predictio
                                     )
 {
 #if JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING || JVET_Z0061_TM_OBMC
-#if  JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  int filterIdx = 0;
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  if (isAML)
+  {
+    bool changeIF = pu.mmvdMergeFlag;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    changeIF &= pu.cs->sps->getUseTMMMVD();
+#endif
 #if TM_MRG && JVET_AA0093_REFINED_MOTION_FOR_ARMC
-  int filterIdx = isAML && (pu.mmvdMergeFlag || (pu.tmMergeFlag && !pu.ciipFlag && !pu.cu->geoFlag)) ? 1 : 0;
-#else
-  int filterIdx = isAML && pu.mmvdMergeFlag ? 1 : 0;
+    changeIF |= (pu.tmMergeFlag && !pu.ciipFlag && !pu.cu->geoFlag
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+                 && pu.cs->sps->getUseTMMrgMode()
 #endif
-#else
-  int filterIdx = 0;
+    );
+#endif
+    filterIdx = changeIF ? 1 : filterIdx;
+  }
 #endif
   if (bilinearMC)
   {
@@ -3945,6 +3954,9 @@ void InterPrediction::xPredAffineTpl(const PredictionUnit &pu, const RefPicList
         xGetSublkAMLTemplate(*pu.cu, COMPONENT_Y, *refPic, Mv(iMvScaleTmpHor, iMvScaleTmpVer), blockWidth, blockHeight, w, h, numTemplate, refLeftTemplate, refAboveTemplate
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
                              , pu.afMmvdFlag
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+                            && pu.cs->sps->getUseTMMMVD()
+#endif
 #endif
 #if JVET_AA0146_WRAP_AROUND_FIX
                              , wrapRef
@@ -4264,6 +4276,18 @@ void InterPrediction::subBlockOBMC(PredictionUnit  &pu, PelUnitBuf* pDst)
         bool isAbove   = (iBlkBoundary == 0) ? 1 : 0;
         int  iOBMCmode = selectOBMCmode(pu, subPu, isAbove, iLength, uiMinCUW, curOffset);
 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+        if (iOBMCmode == -1)
+        {
+          xSubBlockMotionCompensation(subPu, cTmp1);
+          for (int compID = 0; compID < MAX_NUM_COMPONENT; compID++)
+          {
+            xSubblockOBMC(ComponentID(compID), subPu, cPred, cTmp1, iBlkBoundary);
+          }
+          iSub += iLength;
+        }
+        else
+#endif
         if (iOBMCmode == 1)   // 1: current;
         {
           iSub += iLength;
@@ -6211,7 +6235,11 @@ void  InterPrediction::sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx
   cDistParam.applyWeight = false;
   int nWidth = pu.lumaSize().width;
   int nHeight = pu.lumaSize().height;
-  if (!xAMLGetCurBlkTemplate(pu, nWidth, nHeight))
+  if (!xAMLGetCurBlkTemplate(pu, nWidth, nHeight)
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    || !pu.cs->sps->getUseTMMMVD()
+#endif
+    )
   {
     return;
   }
@@ -6542,7 +6570,11 @@ void  InterPrediction::sortInterMergeMMVDCandidates(PredictionUnit& pu, MergeCtx
   cDistParam.applyWeight = false;
   int nWidth = pu.lumaSize().width;
   int nHeight = pu.lumaSize().height;
-  if (!xAMLGetCurBlkTemplate(pu, nWidth, nHeight))
+  if (!xAMLGetCurBlkTemplate(pu, nWidth, nHeight)
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    || !pu.cs->sps->getUseTMMMVD()
+#endif
+    )
   {
     return;
   }
@@ -6708,7 +6740,11 @@ void  InterPrediction::sortAffineMergeCandidates(PredictionUnit pu, AffineMergeC
     candCostList[i] = MAX_UINT;
   }
 
-  if (baseCount < 1)
+  if (baseCount < 1
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    || !pu.cs->sps->getUseTMMMVD()
+#endif
+    )
   {
     return;
   }
@@ -6943,7 +6979,11 @@ void  InterPrediction::sortAffineMergeCandidates(PredictionUnit pu, AffineMergeC
     candCostList[i] = MAX_UINT;
   }
   
-  if (baseCount < 1)
+  if (baseCount < 1
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    || !pu.cs->sps->getUseTMMMVD()
+#endif
+    )
   {
     return;
   }
@@ -7287,7 +7327,11 @@ void InterPrediction::adjustMergeCandidates(PredictionUnit& pu, MergeCtx& mvpMer
     int          cnt = 0;
     int maxPairToBeAdded = std::min(mvpMergeCandCtx.numCandToTestEnc, numCandInCategory); 
 #if TM_MRG
-    if (pu.tmMergeFlag)
+    if (pu.tmMergeFlag
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+        && pu.cs->sps->getUseTMMrgMode()
+#endif
+    )
     {
       maxPairToBeAdded = std::min(mvpMergeCandCtx.numCandToTestEnc, TM_MRG_MAX_NUM_INIT_CANDS);
     }
@@ -7365,15 +7409,17 @@ void InterPrediction::adjustMergeCandidates(PredictionUnit& pu, MergeCtx& mvpMer
           pairMergeCand.LICFlags[cnt] = false;
         }
 #endif
+        uint32_t mvdSimilarityThresh = 1;
 #if TM_MRG
-        if (!pairMergeCand.xCheckSimilarMotion(cnt, pu.tmMergeFlag ? PU::getTMMvdThreshold(pu) : 1))
-        {
-          if (!mvpMergeCandCtx.xCheckSimilarMotion2Lists(cnt, &pairMergeCand, pu.tmMergeFlag ? PU::getTMMvdThreshold(pu) : 1))
-#else
-        if (!pairMergeCand.xCheckSimilarMotion(cnt, 1))
-        {
-          if (!mvpMergeCandCtx.xCheckSimilarMotion2Lists(cnt, &pairMergeCand, 1))
+        mvdSimilarityThresh =
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+                              pu.cs->sps->getUseTMMrgMode() &&
+#endif
+                              pu.tmMergeFlag ? PU::getTMMvdThreshold(pu) : mvdSimilarityThresh;
 #endif
+        if (!pairMergeCand.xCheckSimilarMotion(cnt, mvdSimilarityThresh))
+        {
+          if (!mvpMergeCandCtx.xCheckSimilarMotion2Lists(cnt, &pairMergeCand, mvdSimilarityThresh))
           {
             pairAdded = true;
             cnt++;
@@ -7442,7 +7488,11 @@ void InterPrediction::adjustMergeCandidates(PredictionUnit& pu, MergeCtx& mvpMer
     {
       min = MAX_UINT64;
 #if TM_MRG
-      if(pu.tmMergeFlag)
+      if(pu.tmMergeFlag
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+        && pu.cs->sps->getUseTMMrgMode()
+#endif
+      )
       {
         candToBeRemoved = 0;
         min = candCostList[0];
@@ -7736,7 +7786,11 @@ void InterPrediction::adjustMergeCandidatesInOneCandidateGroup(PredictionUnit &p
       }
     }
 #if TM_MRG
-    if (pu.tmMergeFlag || (mvpMergeCandCtx.numCandToTestEnc != mvpMergeCandCtx.numValidMergeCand && uiMergeCand > mvpMergeCandCtx.numCandToTestEnc ))
+    if ((
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+          pu.cs->sps->getUseTMMrgMode() &&
+#endif
+    	  pu.tmMergeFlag) || (mvpMergeCandCtx.numCandToTestEnc != mvpMergeCandCtx.numValidMergeCand && uiMergeCand > mvpMergeCandCtx.numCandToTestEnc ))
 #else
     if ((mvpMergeCandCtx.numCandToTestEnc != mvpMergeCandCtx.numValidMergeCand && uiMergeCand > mvpMergeCandCtx.numCandToTestEnc ))
 #endif
@@ -9353,6 +9407,12 @@ void InterPrediction::xOBMCWeightedAverageY(const PredictionUnit &pu, const CPel
 int InterPrediction::selectOBMCmode(PredictionUnit &pu, PredictionUnit &subblockPu, bool isAbove, int iLength,
                                     uint32_t uiMinCUW, Position off)
 {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Z0061_TM_OBMC && ENABLE_OBMC
+  if (!pu.cs->sps->getUseOBMCTMMode())
+  {
+    return -1;
+  }
+#endif
   const Position posSubBlock(pu.lumaPos().offset(off));
   Position       posNeighborMotion = Position(0, 0);
   if (isAbove)
@@ -10852,7 +10912,11 @@ Distortion InterPrediction::deriveTMMv(const PredictionUnit& pu, bool fillCurTpl
   if (otherMvf == nullptr) // uni prediction
   {
 #if TM_MRG && JVET_AA0093_REFINED_MOTION_FOR_ARMC
-    if (pu.reduceTplSize && pu.tmMergeFlag)
+    if (pu.reduceTplSize && pu.tmMergeFlag
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+        && pu.cs->sps->getUseTMMrgMode()
+#endif
+    )
     {
       tplCtrl.deriveMvUni<1>();
     }
@@ -10876,7 +10940,11 @@ Distortion InterPrediction::deriveTMMv(const PredictionUnit& pu, bool fillCurTpl
 #endif
     const Picture& otherRefPic = *cu.slice->getRefPic((RefPicList)(1-eRefList), otherMvf->refIdx)->unscaledPic;
 #if TM_MRG && JVET_AA0093_REFINED_MOTION_FOR_ARMC
-    if (pu.reduceTplSize && pu.tmMergeFlag)
+    if (pu.reduceTplSize && pu.tmMergeFlag
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+        && pu.cs->sps->getUseTMMrgMode()
+#endif
+    )
     {
       tplCtrl.removeHighFreq<1>(otherRefPic, otherMvf->mv, getBcwWeight(cu.BcwIdx, eRefList));
       tplCtrl.deriveMvUni<1>();
@@ -10992,7 +11060,11 @@ TplMatchingCtrl::TplMatchingCtrl( const PredictionUnit&     pu,
 #endif
   // Initialization
 #if TM_MRG && JVET_AA0093_REFINED_MOTION_FOR_ARMC
-  if (m_pu.reduceTplSize && pu.tmMergeFlag)
+  if (m_pu.reduceTplSize && pu.tmMergeFlag
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+     && m_pu.cs->sps->getUseTMMrgMode()
+#endif
+  )
   {
     bool tplAvalableAbove = xFillCurTemplate<1, true >((fillCurTpl ? curTplAbove : nullptr));
     bool tplAvalableLeft  = xFillCurTemplate<1, false>((fillCurTpl ? curTplLeft  : nullptr));
@@ -12016,7 +12088,11 @@ bool InterPrediction::processBDMVR(PredictionUnit& pu)
   }
 
 #if TM_MRG
-  if (pu.tmMergeFlag)
+  if (pu.tmMergeFlag
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+      && pu.cs->sps->getUseTMMrgMode()
+#endif
+  )
   {
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
     deriveTMMv(pu, tmCost);
@@ -13312,6 +13388,19 @@ void InterPrediction::amvpMergeModeMvRefinement(PredictionUnit& pu, MvField* mvF
   }
 #if TM_AMVP || TM_MRG
   else
+#if TM_AMVP && TM_MRG
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    if (pu.cu->cs->sps->getUseTMAmvpMode() || pu.cu->cs->sps->getUseTMMrgMode())
+#endif
+#elif TM_AMVP
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    if (pu.cu->cs->sps->getUseTMAmvpMode())
+#endif
+#elif TM_MRG
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    if (pu.cu->cs->sps->getUseTMMrgMode())
+#endif
+#endif
   {
     Distortion tmCost[2];
     tmCost[refListMerge] = deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), refListMerge, pu.refIdx[refListMerge], 0, pu.mv[refListMerge]);
@@ -14756,6 +14845,7 @@ void InterPrediction::deriveMVDcandAffine(const PredictionUnit& pu, RefPicList e
       cMvdDerived[n] = aMvCostVec[n].first;
     }
   }
+
   void InterPrediction::deriveMvdSignSMVD(const Mv& cMvPred, const Mv& cMvPred2, const Mv& cMvdKnownAtDecoder, PredictionUnit& pu, std::vector<Mv>& cMvdDerived)
   {
 #if JVET_Z0054_BLK_REF_PIC_REORDER
@@ -14767,6 +14857,10 @@ void InterPrediction::deriveMVDcandAffine(const PredictionUnit& pu, RefPicList e
       return;
     }
     std::vector<std::pair<Mv, Distortion>> aMvCostVec;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    if (pu.cs->sps->getUseARL())
+    {
+#endif
     PelUnitBuf pcBufPredRefTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE)));
     PelUnitBuf pcBufPredCurTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE)));
     PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight)));
@@ -14815,6 +14909,33 @@ void InterPrediction::deriveMVDcandAffine(const PredictionUnit& pu, RefPicList e
 
       aMvCostVec.push_back(std::pair<Mv, Distortion>(*it, uiCost));
     }
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    }
+    else
+    {
+      InterPredResources interRes(m_pcReshape, m_pcRdCost, m_if, m_filteredBlockTmp[0][COMPONENT_Y], m_filteredBlock[3][1][0], m_filteredBlock[3][0][0]);
+
+      // For L0
+      int refIdx = pu.cs->slice->getSymRefIdx(REF_PIC_LIST_0);
+      CHECK(refIdx < 0, "Invalid reference index for SMVD L0");
+      const Picture& refPic = *pu.cu->slice->getRefPic(REF_PIC_LIST_0, refIdx)->unscaledPic;
+
+      TplMatchingCtrl tplCtrl(pu, interRes, refPic, true, COMPONENT_Y, true, 0, m_pcCurTplAbove, m_pcCurTplLeft, m_pcRefTplAbove, m_pcRefTplLeft, Mv(0, 0), nullptr, 0);
+#if JVET_Z0067_RPR_ENABLE
+      bool  bIsRefScaled = pu.cu->slice->getRefPic(REF_PIC_LIST_0, refIdx)->isRefScaled(pu.cs->pps);
+#endif
+      for (std::vector<Mv>::iterator it = cMvdDerived.begin(); it != cMvdDerived.end(); ++it)
+      {
+        Mv cMvTest = cMvPred + *it;
+        Distortion uiCost = 
+#if JVET_Z0067_RPR_ENABLE
+                            bIsRefScaled ? std::numeric_limits<Distortion>::max() : 
+#endif
+                            tplCtrl.xGetTempMatchError<TM_TPL_SIZE>(cMvTest);
+        aMvCostVec.push_back(std::pair<Mv, Distortion>(*it, uiCost));
+      }
+    }
+#endif
     std::stable_sort(aMvCostVec.begin(), aMvCostVec.end(), [](const std::pair<Mv, Distortion> & l, const std::pair<Mv, Distortion> & r) {return l.second < r.second; });
 #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
 
diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp
index f6698ee24376111a4fa79a63e61d6a1ba626c66a..44c25f9a587c13d7a6052492451e4e91abb74159 100644
--- a/source/Lib/CommonLib/Slice.cpp
+++ b/source/Lib/CommonLib/Slice.cpp
@@ -3491,6 +3491,27 @@ SPS::SPS()
 #if TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM || MULTI_PASS_DMVR
  , m_DMVDMode                 ( false )
 #endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+, m_tmToolsEnableFlag         ( false )
+#if TM_AMVP
+ , m_tmAmvpMode               ( false )
+#endif
+#if TM_MRG
+ , m_tmMrgMode                ( false )
+#endif
+#if JVET_W0097_GPM_MMVD_TM && TM_MRG
+ , m_tmGPMMode                ( false )
+#endif
+#if JVET_Z0061_TM_OBMC && ENABLE_OBMC
+ , m_tmOBMCMode               ( false )
+#endif
+#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+ , m_useTmvpNmvpReorder       ( false )
+#endif
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+ , m_useTMMMVD                ( false )
+#endif
+#endif
 #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
 , m_altGPMSplitModeCode       ( false )
 #endif
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index 6214c6bc13a1ad8341c686526a66071712dbe7f2..4e498324b34cd1bb678335c3437e10a8efd7da58 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -1526,6 +1526,27 @@ private:
 #if TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM || MULTI_PASS_DMVR
   bool              m_DMVDMode;
 #endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  bool              m_tmToolsEnableFlag;
+#if TM_AMVP
+  bool              m_tmAmvpMode;
+#endif
+#if TM_MRG
+  bool              m_tmMrgMode;
+#endif
+#if JVET_W0097_GPM_MMVD_TM && TM_MRG
+  bool              m_tmGPMMode;
+#endif
+#if JVET_Z0061_TM_OBMC && ENABLE_OBMC
+  bool              m_tmOBMCMode;
+#endif
+#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+  bool              m_useTmvpNmvpReorder;
+#endif
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  bool              m_useTMMMVD;
+#endif
+#endif
 #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
   bool              m_altGPMSplitModeCode;
 #endif
@@ -2029,6 +2050,34 @@ void                    setCCALFEnabledFlag( bool b )
   void                    setUseDMVDMode(bool b)                                                          { m_DMVDMode = b; }
   bool                    getUseDMVDMode() const                                                          { return m_DMVDMode; }
 #endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  void                    setTMToolsEnableFlag(bool b)                                                    { m_tmToolsEnableFlag = b; }
+  bool                    getTMToolsEnableFlag() const                                                    { return m_tmToolsEnableFlag; }
+#if TM_AMVP
+  void                    setUseTMAmvpMode(bool b)                                                        { m_tmAmvpMode = b; }
+  bool                    getUseTMAmvpMode() const                                                        { return m_tmAmvpMode; }
+#endif
+#if TM_MRG
+  void                    setUseTMMrgMode(bool b)                                                         { m_tmMrgMode = b; }
+  bool                    getUseTMMrgMode() const                                                         { return m_tmMrgMode; } // Controls regular merge mode with TM, while others (e.g., GPM-TM, CIIP-TM, OBMC-TM) are controlled separately
+#endif
+#if JVET_W0097_GPM_MMVD_TM && TM_MRG
+  void                    setUseGPMTMMode(bool b)                                                         { m_tmGPMMode = b; }
+  bool                    getUseGPMTMMode() const                                                         { return m_tmGPMMode; }
+#endif
+#if JVET_Z0061_TM_OBMC && ENABLE_OBMC
+  void                    setUseOBMCTMMode(bool b)                                                        { m_tmOBMCMode = b; }
+  bool                    getUseOBMCTMMode() const                                                        { return m_tmOBMCMode; }
+#endif
+#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+  void                    setUseTmvpNmvpReordering(bool b)                                                { m_useTmvpNmvpReorder = b; }
+  bool                    getUseTmvpNmvpReordering() const                                                { return m_useTmvpNmvpReorder; }
+#endif
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  void                    setUseTMMMVD(bool b)                                                            { m_useTMMMVD = b; }
+  bool                    getUseTMMMVD() const                                                            { return m_useTMMMVD; }
+#endif
+#endif
 #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
   void                    setUseAltGPMSplitModeCode(bool b)                                               { m_altGPMSplitModeCode = b; }
   bool                    getUseAltGPMSplitModeCode() const                                               { return m_altGPMSplitModeCode; }
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index e83c5cb8641a3884884d812b3bbe9cb20d5a0514..4f88ec4c0d08d4e71cb3c943dc651c9d4443a47b 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -206,6 +206,7 @@
 #if ENABLE_OBMC
 #define JVET_Z0061_TM_OBMC                                1 // JVET-Z0061: Template matching based OBMC
 #endif
+#define JVET_AA0132_CONFIGURABLE_TM_TOOLS                 1 // JVET-AA0132: Configuration parameters and SPS flags for template matching tools
 #endif
 #define JVET_W0097_GPM_MMVD_TM                            1 // JVET-W0097: GPM-MMVD and GPM-TM, GPM-TM part is controlled by TM_MRG
 #define JVET_X0141_CIIP_TIMD_TM                           1 // JVET-X0141: CIIP with TIMD and TM merge, CIIP-TM part is controlled by TM_MRG, and CIIP-TIMD part is controlled by JVET_W0123_TIMD_FUSION
@@ -303,7 +304,6 @@
 
 
 
-
 // clang-format off
 #define JVET_V0056                                        1 // JVET-V0056: MCTF changes
 
diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp
index fd4df93b535770d1ce6258a0928d4b3303c6c825..4c3c5cdc8aaa14f4b6207323e61bd86cb52541de 100644
--- a/source/Lib/CommonLib/UnitTools.cpp
+++ b/source/Lib/CommonLib/UnitTools.cpp
@@ -2468,7 +2468,11 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const
 
   // above left
 #if JVET_Z0084_IBC_TM && JVET_Z0075_IBC_HMVP_ENLARGE && JVET_W0090_ARMC_TM
-  if ((cnt < 4 && pu.cs->sps->getUseAML() && mrgCandIdx >= 0)) //Only for AMVP case
+  if ((cnt < 4 && pu.cs->sps->getUseAML() && mrgCandIdx >= 0)
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_W0090_ARMC_TM
+	  || !pu.cs->sps->getUseAML()
+#endif
+  ) //Only for AMVP case
 #elif !JVET_Z0075_IBC_HMVP_ENLARGE
   if (cnt < 4)
 #endif
@@ -3103,6 +3107,13 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
 #endif
 )
 {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+  if (!pu.cs->sps->getUseAML() || !pu.cs->sps->getUseTmvpNmvpReordering())
+  {
+    tmvpMrgCtx  = nullptr;
+    namvpMrgCtx = nullptr;
+  }
+#endif
   const unsigned plevel = pu.cs->sps->getLog2ParallelMergeLevelMinus2() + 2;
   const CodingStructure &cs  = *pu.cs;
   const Slice &slice         = *pu.cs->slice;
@@ -3118,11 +3129,20 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
   {
     additionalMRGCand += namvpMrgCtx->numValidMergeCand;
   }
-  const uint32_t maxNumMergeCand = pu.tmMergeFlag ? std::min((int)(TM_MRG_MAX_NUM_INIT_CANDS + additionalMRGCand), ((int)NUM_MERGE_CANDS - (3)))
-                                                  : std::min((int) (pu.cs->sps->getMaxNumMergeCand() + additionalMRGCand), ((int)NUM_MERGE_CANDS - (3)));
+  const uint32_t maxNumMergeCand =
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+                                   !pu.cs->sps->getUseAML() || !pu.cs->sps->getUseTmvpNmvpReordering() ?
+                                   (pu.tmMergeFlag ? pu.cs->sps->getMaxNumTMMergeCand() : pu.cs->sps->getMaxNumMergeCand()) :
+#endif
+                                   (pu.tmMergeFlag ? std::min((int)(TM_MRG_MAX_NUM_INIT_CANDS        + additionalMRGCand), ((int)NUM_MERGE_CANDS - (3)))
+                                                   : std::min((int)(pu.cs->sps->getMaxNumMergeCand() + additionalMRGCand), ((int)NUM_MERGE_CANDS - (3))));
 #else
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
-  const uint32_t maxNumMergeCand = pu.tmMergeFlag ? (pu.cs->sps->getUseAML()) ? TM_MRG_MAX_NUM_INIT_CANDS : pu.cs->sps->getMaxNumTMMergeCand() : pu.cs->sps->getMaxNumMergeCand();
+  const uint32_t maxNumMergeCand = pu.tmMergeFlag ? ((pu.cs->sps->getUseAML()
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+                                                  && pu.cs->sps->getUseTmvpNmvpReordering()
+#endif
+                                                    ) ? TM_MRG_MAX_NUM_INIT_CANDS : pu.cs->sps->getMaxNumTMMergeCand()) : pu.cs->sps->getMaxNumMergeCand();
 #else
   const uint32_t maxNumMergeCand     = pu.tmMergeFlag ? pu.cs->sps->getMaxNumTMMergeCand() : pu.cs->sps->getMaxNumMergeCand();
 #endif
@@ -3756,7 +3776,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
     {
 #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
 #if TM_MRG
-      if (!pu.tmMergeFlag)
+      if (!pu.tmMergeFlag
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+          || !pu.cs->sps->getUseTMMrgMode()
+#endif
+      )
 #endif
       {
         for (uint32_t ui = 0; ui < tmvpMrgCtx->numValidMergeCand && cnt < maxNumMergeCand - 1; ++ui)
@@ -3897,6 +3921,12 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
   for (int iDistanceIndex = 0; iDistanceIndex < NADISTANCE_LEVEL && cnt < maxNumMergeCand - 1; iDistanceIndex++)
 #endif
   {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+    if (!pu.cs->sps->getUseAML() && cnt >= maxNumMergeCand - 1)
+    {
+      continue;
+    }
+#endif
     const int iNADistanceHor = pu.Y().width  * (iDistanceIndex + 1);
     const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1);
 
@@ -3906,6 +3936,12 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
     for (int NASPIdx = 0; NASPIdx < iNACANDIDATE_NUM[iDistanceIndex] && cnt < maxNumMergeCand - 1; NASPIdx++)
 #endif
     {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+      if (!pu.cs->sps->getUseAML() && cnt >= maxNumMergeCand - 1)
+      {
+        continue;
+      }
+#endif
       switch (idxMap[iDistanceIndex][NASPIdx])
       {
       case 0:offsetX = -iNADistanceHor - 1; offsetY = pu.Y().height + iNADistanceVer - 1; break;
@@ -4034,6 +4070,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
 
 #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
   int maxNumMergeCandMin1 = maxNumMergeCand;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  maxNumMergeCandMin1 -= !pu.cs->sps->getUseAML() ? 1 : 0;
+#endif
 #else
   int maxNumMergeCandMin1 = maxNumMergeCand - 1;
 #endif
@@ -4068,10 +4107,14 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
     }
   }
 
-#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC 
+#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC)
   // pairwise-average candidates
   {
-    if (cnt > 1 && cnt < maxNumMergeCand)
+    if (cnt > 1 && cnt < maxNumMergeCand
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+      && !pu.cs->sps->getUseAML()
+#endif
+      )
     {
       mrgCtx.mvFieldNeighbours[cnt * 2].setMvField( Mv( 0, 0 ), NOT_VALID );
       mrgCtx.mvFieldNeighbours[cnt * 2 + 1].setMvField( Mv( 0, 0 ), NOT_VALID );
@@ -5114,25 +5157,31 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx,
 #endif
 )
 {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+  if (!pu.cs->sps->getUseAML() || !pu.cs->sps->getUseTmvpNmvpReordering())
+  {
+    mvpMrgCtx1 = nullptr;
+    mvpMrgCtx2 = nullptr;
+  }
+#endif
   const unsigned plevel = pu.cs->sps->getLog2ParallelMergeLevelMinus2() + 2;
   const CodingStructure &cs = *pu.cs;
   const Slice &slice = *pu.cs->slice;
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
 #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
-  uint32_t additionalMRGCand = 0;
-  if (mvpMrgCtx1 != NULL)
-  {
-    additionalMRGCand = mvpMrgCtx1->numValidMergeCand;
-  }
-  if (mvpMrgCtx2 != NULL)
-  {
-    additionalMRGCand += mvpMrgCtx2->numValidMergeCand;
-  }
-  const uint32_t maxNumMergeCand = (pu.cs->sps->getUseAML()) ? std::min((int)(BM_MRG_MAX_NUM_INIT_CANDS + additionalMRGCand), ((int)NUM_MERGE_CANDS - (3))) 
-                                                             : pu.cs->sps->getMaxNumBMMergeCand();
+  uint32_t additionalMRGCand = (mvpMrgCtx1 != NULL ? mvpMrgCtx1->numValidMergeCand : 0)
+                             + (mvpMrgCtx2 != NULL ? mvpMrgCtx2->numValidMergeCand : 0);
+#endif
+  const uint32_t maxNumMergeCand = pu.cs->sps->getUseAML()
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+                                && pu.cs->sps->getUseTmvpNmvpReordering()
+#endif
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+                                 ? std::min((int)(BM_MRG_MAX_NUM_INIT_CANDS + additionalMRGCand), ((int)NUM_MERGE_CANDS - (3)))
 #else
-  const uint32_t maxNumMergeCand = (pu.cs->sps->getUseAML()) ? BM_MRG_MAX_NUM_INIT_CANDS : pu.cs->sps->getMaxNumBMMergeCand();
+                                 ? BM_MRG_MAX_NUM_INIT_CANDS
 #endif
+								 : pu.cs->sps->getMaxNumBMMergeCand();
 #else
   const uint32_t maxNumMergeCand = pu.cs->sps->getMaxNumBMMergeCand();
 #endif
@@ -5572,6 +5621,9 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx,
 
 #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
   int maxNumMergeCandMin1 = maxNumMergeCand;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  maxNumMergeCandMin1 -= !pu.cs->sps->getUseAML() ? 1 : 0;
+#endif
 #else
   int maxNumMergeCandMin1 = maxNumMergeCand - 1;
 #endif
@@ -5696,7 +5748,10 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx,
     }
   }
 
-#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC)
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  if (!pu.cs->sps->getUseAML())
+#endif
   {
     if (cnt > 1 && cnt < maxNumMergeCand)
     {
@@ -5799,6 +5854,14 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx,
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
 void PU::getTmvpBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx)
 {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  if (!pu.cs->sps->getUseTmvpNmvpReordering())
+  {
+    mrgCtx.numValidMergeCand = 0;
+    return;
+  }
+#endif
+
   const CodingStructure &cs = *pu.cs;
   const Slice &slice = *pu.cs->slice;
 
@@ -5987,6 +6050,13 @@ void PU::getTmvpBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx)
 #if NON_ADJACENT_MRG_CAND && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
 void PU::getNonAdjacentBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx)
 {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  if (!pu.cs->sps->getUseTmvpNmvpReordering())
+  {
+    mrgCtx.numValidMergeCand = 0;
+    return;
+  }
+#endif
   const unsigned plevel = pu.cs->sps->getLog2ParallelMergeLevelMinus2() + 2;
   const CodingStructure &cs = *pu.cs;
 
@@ -6131,6 +6201,13 @@ void PU::getNonAdjacentBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx)
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
 void PU::getTmvpMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx)
 {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  if (!pu.cs->sps->getUseTmvpNmvpReordering())
+  {
+    mrgCtx.numValidMergeCand = 0;
+    return;
+  }
+#endif
   const CodingStructure &cs = *pu.cs;
   const Slice &slice = *pu.cs->slice;
 
@@ -6138,7 +6215,11 @@ void PU::getTmvpMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx)
   const uint32_t mvdSimilarityThresh = 1;
 #endif
 #if TM_MRG && JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
-  const uint32_t maxNumMergeCand = pu.tmMergeFlag ? 1 :NUM_TMVP_CANDS;
+  const uint32_t maxNumMergeCand =
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+                                   pu.cs->sps->getUseTMMrgMode() &&
+#endif
+                                   pu.tmMergeFlag ? 1 :NUM_TMVP_CANDS;
 #else
   const uint32_t maxNumMergeCand = NUM_TMVP_CANDS;
 #endif
@@ -6403,16 +6484,32 @@ void PU::getTmvpMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx)
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM && NON_ADJACENT_MRG_CAND
 void PU::getNonAdjacentMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx)
 {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  if (!pu.cs->sps->getUseTmvpNmvpReordering())
+  {
+    mrgCtx.numValidMergeCand = 0;
+    return;
+  }
+#endif
   const unsigned plevel = pu.cs->sps->getLog2ParallelMergeLevelMinus2() + 2;
   const CodingStructure &cs = *pu.cs;
   const Slice &slice = *pu.cs->slice;
 
 #if TM_MRG
-#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC 
-  const uint32_t mvdSimilarityThresh = pu.tmMergeFlag ? PU::getTMMvdThreshold(pu) : 1;
-#else
-  const uint32_t mvdSimilarityThresh = getBDMVRMvdThreshold(pu);
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS || JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  bool useMvdThreshold = true;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  useMvdThreshold &= pu.cs->sps->getUseTMMrgMode();
+#endif
+#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+  useMvdThreshold &= pu.tmMergeFlag;
+#endif
+#endif
+  const uint32_t mvdSimilarityThresh =
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS || JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+                                       !useMvdThreshold ? 1 :
 #endif
+                                       getBDMVRMvdThreshold(pu);
 #endif
   const uint32_t maxNumMergeCand = NUM_NON_ADJ_CANDS;
 
@@ -6692,11 +6789,15 @@ bool PU::checkRprLicCondition( const PredictionUnit & pu )
 }
 #endif
 
-#if JVET_Y0128_NON_CTC
+#if JVET_Y0128_NON_CTC || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_AMVP)
 bool PU::checkTmEnableCondition(const SPS* sps, const PPS* pps, const Picture* refPic)
 {
 #if TM_AMVP || TM_MRG || MULTI_PASS_DMVR
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_AMVP
+  if (sps->getUseTMAmvpMode())
+#else
   if (sps->getUseDMVDMode())
+#endif
   {
     if (sps->getRprEnabledFlag())
     {
@@ -6804,7 +6905,15 @@ void PU::getInterMMVDMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx,
   int refIdxList0, refIdxList1;
   int k;
   int currBaseNum = 0;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  const uint16_t maxNumMergeCand = std::min<int>(mrgCtx.numValidMergeCand, (pu.cs->sps->getUseTMMMVD() ? MMVD_BASE_MV_NUM : VVC_MMVD_BASE_MV_NUM));
+#else
+  const uint16_t maxNumMergeCand = std::min<int>(mrgCtx.numValidMergeCand, MMVD_BASE_MV_NUM);
+#endif
+#else
   const uint16_t maxNumMergeCand = mrgCtx.numValidMergeCand;
+#endif
 
   for( k = 0; k < maxNumMergeCand; k++ )
   {
@@ -6829,10 +6938,12 @@ void PU::getInterMMVDMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx,
     mrgCtx.mmvdUseAltHpelIf[currBaseNum] = mrgCtx.useAltHpelIf[k];
     currBaseNum++;
 
+#if !JVET_AA0132_CONFIGURABLE_TM_TOOLS
     if( currBaseNum == MMVD_BASE_MV_NUM )
     {
       break;
     }
+#endif
   }
 }
 bool PU::getColocatedMVP(const PredictionUnit &pu, const RefPicList &eRefPicList, const Position &_pos, Mv& rcMv, const int &refIdx, bool sbFlag
@@ -7305,7 +7416,7 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in
 {
   CodingStructure &cs = *pu.cs;
 #if TM_AMVP
-#if JVET_Y0128_NON_CTC
+#if JVET_Y0128_NON_CTC || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_AMVP)
   interPred = PU::checkTmEnableCondition(pu.cs->sps, pu.cs->pps, pu.cu->slice->getRefPic(eRefPicList, refIdx)) ? interPred : nullptr;
 #else
   interPred = pu.cu->cs->sps->getUseDMVDMode() ? interPred : nullptr;
@@ -7526,7 +7637,13 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in
 #endif
 
 #if TM_AMVP
-  if (pu.cu->cs->sps->getUseDMVDMode() && interPred != nullptr && pInfo->numCand > 0)
+  if (
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    pu.cu->cs->sps->getUseTMAmvpMode()
+#else
+    pu.cu->cs->sps->getUseDMVDMode()
+#endif
+    && interPred != nullptr && pInfo->numCand > 0)
   {
     struct AMVPSort
     {
@@ -7571,18 +7688,13 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in
 #endif
     for (int candIdx = 0; candIdx < pInfo->numCand; ++candIdx)
     {
+      tmCost[candIdx] = interPred->deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), eRefPicList, refIdx
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
-      if (armcRefinedMotion)
-      {
-        tmCost[candIdx] = interPred->deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), eRefPicList, refIdx, TM_MAX_NUM_OF_ITERATIONS, pInfo->mvCand[candIdx]);
-      }
-      else
-      {
-        tmCost[candIdx] = interPred->deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), eRefPicList, refIdx, 0, pInfo->mvCand[candIdx]);
-      }
+                                            , (armcRefinedMotion ? TM_MAX_NUM_OF_ITERATIONS : 0)
 #else
-      tmCost[candIdx] = interPred->deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), eRefPicList, refIdx, 0, pInfo->mvCand[candIdx]);
+                                            , 0
 #endif
+                                            , pInfo->mvCand[candIdx]);
       temp.AMVPCand = pInfo->mvCand[candIdx];
       temp.cost = tmCost[candIdx];
       input.push_back(temp);
@@ -7618,7 +7730,13 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in
     pInfo->numCand++;
   }
 #if TM_AMVP
-  pInfo->numCand = (pu.cu->cs->sps->getUseDMVDMode() && interPred != nullptr ? 1 : pInfo->numCand);
+  pInfo->numCand = (
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+                    pu.cu->cs->sps->getUseTMAmvpMode() 
+#else
+                    pu.cu->cs->sps->getUseDMVDMode() 
+#endif
+                 && interPred != nullptr ? 1 : pInfo->numCand);
 #endif
 
   for (Mv &mv : pInfo->mvCand)
@@ -10306,7 +10424,7 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx
                                    int mrgCandIdx, bool isAfMmvd
 #endif
 #if JVET_Z0139_NA_AFF && JVET_W0090_ARMC_TM
-    , bool isZeroCandIdx
+                           ,       bool isZeroCandIdx
 #endif
 )
 {
@@ -11188,11 +11306,12 @@ void PU::getAfMmvdMvf(const PredictionUnit& pu, const AffineMergeCtx& affineMerg
   CHECK(!pu.cu->affine, "Affine flag is not on for Affine MMVD mode!");
   CHECK(affineMergeCtx.mergeType[afMmvdBase] != MRG_TYPE_DEFAULT_N, "AFF_MMVD base candidate type is not regular Affine!");
 
-#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
-  static const int32_t refMvdCands[AF_MMVD_STEP_NUM] = { 1, 2, 4, 8 };
+#if JVET_AA0093_ENHANCED_MMVD_EXTENSION && !JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  static const int32_t refMvdCands[] = { 1, 2, 4, 8 };
 #else
-  static const int32_t refMvdCands[AF_MMVD_STEP_NUM] = { 1, 2, 4, 8, 16 };
+  static const int32_t refMvdCands[] = { 1, 2, 4, 8, 16 };
 #endif
+
 #if JVET_Y0128_NON_CTC
   const int32_t iPicSize = pu.cu->slice->getPic()->lumaSize().area();
   const int32_t mvShift  = iPicSize < 921600 ? 0 : ( iPicSize < 4096000 ? 2 : MV_FRACTIONAL_BITS_INTERNAL - 1); // 921600 = 1280x720, 4096000 = 2560x1600
@@ -11250,7 +11369,11 @@ void PU::getAfMmvdMvf(const PredictionUnit& pu, const AffineMergeCtx& affineMerg
 #if JVET_AA0093_ENHANCED_MMVD_EXTENSION
     else if (interDir == 3)
     {
-      if (offsetDir >=  16)
+      if (offsetDir >= 16
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+        || !pu.cs->sps->getUseTMMMVD()
+#endif
+        )
       {
         int poc_cur = pu.cu->slice->getPOC();
         int poc_l0  = pu.cu->slice->getRefPOC(REF_PIC_LIST_0, refIdxL0);
@@ -11289,6 +11412,16 @@ void PU::getAfMmvdMvf(const PredictionUnit& pu, const AffineMergeCtx& affineMerg
 
 int32_t PU::getAfMmvdEstBits(const PredictionUnit &pu)
 {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  if (!pu.cs->sps->getUseTMMMVD())
+  {
+    int baseBits = (ECM3_AF_MMVD_BASE_NUM == 1 ? 0 : pu.afMmvdBaseIdx + (pu.afMmvdBaseIdx == ECM3_AF_MMVD_BASE_NUM - 1 ? 0: 1));
+    int stepBits = pu.afMmvdStep + (pu.afMmvdStep == ECM3_AF_MMVD_STEP_NUM - 1 ? 0 : 1);
+    int dirBits  = gp_sizeIdxInfo->idxFrom(ECM3_AF_MMVD_OFFSET_DIR);
+    return stepBits + dirBits + baseBits;
+  }
+#endif
+
   int baseBits = (AF_MMVD_BASE_NUM == 1 ? 0 : pu.afMmvdBaseIdx + (pu.afMmvdBaseIdx == AF_MMVD_BASE_NUM - 1 ? 0: 1));
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
   int stepBits = pu.afMmvdMergeIdx + (pu.afMmvdMergeIdx == AF_MMVD_MAX_REFINE_NUM - 1 ? 0 : 1);
@@ -13572,7 +13705,6 @@ Mv PU::getMultiHypMVP(PredictionUnit &pu, const MultiHypPredictionData &mhData)
 }
 #endif
 
-
 bool CU::isBcwIdxCoded( const CodingUnit &cu )
 {
   if( cu.cs->sps->getUseBcw() == false )
diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h
index f8eb6f82499345763c8b7b2c9e0418e72ee4424a..d2e010e83c75d9417452f135161dc6fad92d7411 100644
--- a/source/Lib/CommonLib/UnitTools.h
+++ b/source/Lib/CommonLib/UnitTools.h
@@ -358,7 +358,7 @@ namespace PU
                            const int mrgCandIdx = -1
 #endif
 #if JVET_Z0139_NA_AFF && JVET_W0090_ARMC_TM
-    , bool isZeroCandIdx = false 
+                         , bool isZeroCandIdx = false 
 #endif
   );
 #if AFFINE_MMVD
@@ -450,7 +450,7 @@ namespace PU
 #if INTER_LIC && RPR_ENABLE
   bool checkRprLicCondition(const PredictionUnit& pu);
 #endif
-#if JVET_Y0128_NON_CTC
+#if JVET_Y0128_NON_CTC || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_AMVP)
   bool checkTmEnableCondition(const SPS* sps, const PPS* pps, const Picture* refPic);
 #endif
 #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp
index 6ac643054e1f366e55f3ea03db268697d10ba1ff..12af76a58a6089d5bad8bc5745ac4fee29ce627d 100644
--- a/source/Lib/DecoderLib/CABACReader.cpp
+++ b/source/Lib/DecoderLib/CABACReader.cpp
@@ -1686,8 +1686,15 @@ void CABACReader::cu_pred_data( CodingUnit &cu )
 #if INTER_LIC
   cu_lic_flag( cu ); // local illumination compensation
 #endif
-#if !JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if !JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED)
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  if (!cu.cs->sps->getUseMVSD())
+  {
+#endif
   cu_bcw_flag(cu);
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  }
+#endif
 #endif
 #if ENABLE_OBMC
   obmc_flag  ( cu );
@@ -3106,7 +3113,14 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx )
     affine_flag   ( *pu.cu );
     smvd_mode( pu );
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    if(pu.cs->sps->getUseMVSD())
+    {
+#endif
     cu_bcw_flag(*pu.cu);
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    }
+#endif
 #endif
 #if JVET_Z0054_BLK_REF_PIC_REORDER
     refPairIdx(pu);
@@ -3393,11 +3407,17 @@ void CABACReader::affine_mmvd_data(PredictionUnit& pu)
   int numCandMinus1Base = AF_MMVD_BASE_NUM - 1;
 #if JVET_AA0093_ENHANCED_MMVD_EXTENSION
   unsigned ctxId = 0;
-  const CodingStructure *cs = pu.cu->cs;
-  const CodingUnit *cuLeft = cs->getCURestricted( pu.cu->lumaPos().offset( -1, 0 ), *pu.cu, CH_L );
-  ctxId = (cuLeft && cuLeft->affine) ? 1 : 0;
-  const CodingUnit *cuAbove = cs->getCURestricted( pu.cu->lumaPos().offset( 0, -1 ), *pu.cu, CH_L );
-  ctxId += (cuAbove && cuAbove->affine) ? 1 : 0;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  static_assert(ECM3_AF_MMVD_BASE_NUM == 1, "The value of ECM3_AF_MMVD_BASE_NUM must be 1");
+  if (pu.cs->sps->getUseTMMMVD())
+#endif
+  {
+    const CodingStructure *cs = pu.cu->cs;
+    const CodingUnit *cuLeft = cs->getCURestricted(pu.cu->lumaPos().offset(-1, 0), *pu.cu, CH_L);
+    ctxId = (cuLeft && cuLeft->affine) ? 1 : 0;
+    const CodingUnit *cuAbove = cs->getCURestricted(pu.cu->lumaPos().offset(0, -1), *pu.cu, CH_L);
+    ctxId += (cuAbove && cuAbove->affine) ? 1 : 0;
+  }
   numCandMinus1Base = (ctxId == 0) ? 0 : ((ctxId == 1) ? 1 : AF_MMVD_BASE_NUM-1);
 #endif
   if (numCandMinus1Base > 0)
@@ -3428,6 +3448,10 @@ void CABACReader::affine_mmvd_data(PredictionUnit& pu)
   DTRACE(g_trace_ctx, D_SYNTAX, "afMmvd_base_idx() afMmvd_base_idx=%d\n", afMmvdBaseIdx);
   
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  if (pu.cs->sps->getUseTMMMVD())
+  {
+#endif
   unsigned int ricePar = 1;
 #if JVET_AA0093_ENHANCED_MMVD_EXTENSION
   int numStepCandMinus1 =  (AF_MMVD_MAX_REFINE_NUM >> (ricePar+AFFINE_MMVD_SIZE_SHIFT)) / AFFINE_BI_DIR  - 1;
@@ -3455,14 +3479,28 @@ void CABACReader::affine_mmvd_data(PredictionUnit& pu)
   pu.afMmvdMergeIdx = uiUnaryIdx;
   pu.afMmvdStep = 0;
   pu.afMmvdDir = 0;
-#else
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    return;
+  }
+#endif
+#endif
+
+#if !JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED)
   {
     // Decode Step Value
     uint8_t stepOffset = 0;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+    int numStepCandMinus1 = ECM3_AF_MMVD_STEP_NUM - 1;
+#else
     int numStepCandMinus1 = AF_MMVD_STEP_NUM - 1;
+#endif
     if (numStepCandMinus1 > 0)
     {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+      if (m_BinDecoder.decodeBin(Ctx::AfMmvdOffsetStepECM3()))
+#else
       if (m_BinDecoder.decodeBin(Ctx::AfMmvdOffsetStep()))
+#endif
       {
         stepOffset++;
         for (; stepOffset < numStepCandMinus1; stepOffset++)
@@ -3483,6 +3521,9 @@ void CABACReader::affine_mmvd_data(PredictionUnit& pu)
     b1 = m_BinDecoder.decodeBinEP();
     uint8_t offDir = (b1 << 1) | b0;
     pu.afMmvdDir = offDir;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+    pu.afMmvdMergeIdx = (uint8_t)(pu.afMmvdBaseIdx * ECM3_AF_MMVD_MAX_REFINE_NUM + pu.afMmvdStep * ECM3_AF_MMVD_OFFSET_DIR + pu.afMmvdDir);
+#endif
     DTRACE(g_trace_ctx, D_SYNTAX, "afMmvd_offsetDir() afMmvd_offsetDir=%d\n", offDir);
   }
 #endif
@@ -3549,7 +3590,54 @@ void CABACReader::ibcMbvdData(PredictionUnit& pu)
 void CABACReader::tm_merge_flag(PredictionUnit& pu)
 {
   pu.tmMergeFlag = false;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_X0141_CIIP_TIMD_TM && TM_MRG
+  if (pu.ciipFlag)
+  {
+    if (pu.cs->slice->getSPS()->getUseCiipTmMrg())
+    {
+      pu.tmMergeFlag = m_BinDecoder.decodeBin(Ctx::CiipTMMergeFlag());
+    }
+    return;
+  }
+#endif
+
+#if (JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_MRG) || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_W0097_GPM_MMVD_TM && TM_MRG)
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_W0097_GPM_MMVD_TM && TM_MRG
+  if (pu.cu->geoFlag)
+  {
+    if (!pu.cs->slice->getSPS()->getUseGPMTMMode())
+    {
+      return;
+    }
+  }
+  else
+#endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_MRG
+  if (pu.regularMergeFlag
+#if JVET_Z0084_IBC_TM && IBC_TM_MRG
+    && !CU::isIBC(*pu.cu)
+#endif
+    )
+  {
+    if (!pu.cs->slice->getSPS()->getUseTMMrgMode())
+    {
+      return;
+    }
+  }
+  else
+#endif
+  if (!pu.cs->slice->getSPS()->getUseDMVDMode())
+  {
+#if (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_X0141_CIIP_TIMD_TM && TM_MRG) && (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_W0097_GPM_MMVD_TM && TM_MRG) && (JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_MRG)
+#if !(JVET_Z0084_IBC_TM && IBC_TM_MRG)
+    CHECK(true, "Unknown mode to read tm_merge_flag");
+#endif
+#endif
+    return;
+  }
+#else
   if (pu.cs->slice->getSPS()->getUseDMVDMode())
+#endif
   {
     RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE(STATS__CABAC_BITS__MERGE_FLAG, pu.lumaSize());
 #if JVET_Z0084_IBC_TM && IBC_TM_MRG
@@ -3678,7 +3766,11 @@ void CABACReader::merge_data( PredictionUnit& pu )
 #endif
 #if JVET_X0049_ADAPT_DMVR
 #if TM_MRG
-      if (pu.tmMergeFlag)
+      if (pu.tmMergeFlag
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+        || !pu.cs->slice->getSPS()->getUseTMMrgMode()
+#endif
+        )
 #endif
       {
         bm_merge_flag(pu);
@@ -3701,7 +3793,11 @@ void CABACReader::merge_data( PredictionUnit& pu )
       {
         RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE(STATS__CABAC_BITS__MERGE_FLAG, pu.lumaSize());
 #if JVET_AA0093_ENHANCED_MMVD_EXTENSION
-        unsigned  ctxId = pu.cu->skip ? 0 : 1;
+        unsigned  ctxId =
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+                          !pu.cs->sps->getUseTMMMVD() ||
+#endif
+                          pu.cu->skip ? 0 : 1;
         cu.firstPU->mmvdMergeFlag = m_BinDecoder.decodeBin(Ctx::MmvdFlag(ctxId));
 #else
         cu.firstPU->mmvdMergeFlag = m_BinDecoder.decodeBin(Ctx::MmvdFlag(0));
@@ -3735,12 +3831,16 @@ void CABACReader::merge_data( PredictionUnit& pu )
       {
         pu.ciipFlag = true;
 #if JVET_X0141_CIIP_TIMD_TM && TM_MRG
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+        tm_merge_flag(pu);
+#else
         if (pu.cs->slice->getSPS()->getUseCiipTmMrg())
         {
           RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE(STATS__CABAC_BITS__MERGE_FLAG, pu.lumaSize()); 
           pu.tmMergeFlag = (m_BinDecoder.decodeBin(Ctx::CiipTMMergeFlag()));
         }
 #endif
+#endif
 #if CIIP_PDPC
         RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE(STATS__CABAC_BITS__INTRA_PDPC_FLAG, pu.lumaSize()); 
         pu.ciipPDPC = ( m_BinDecoder.decodeBin( Ctx::CiipFlag( 1 ) ) );
@@ -4267,10 +4367,14 @@ void CABACReader::geoModeIdx(PredictionUnit& pu)
 }
 #endif
 
-#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
 void CABACReader::mmvd_merge_idx(PredictionUnit& pu)
 {
   RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE(STATS__CABAC_BITS__MERGE_INDEX, pu.lumaSize());
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  if (pu.cs->sps->getUseTMMMVD())
+  {
+#endif
   unsigned int uiUnaryIdx = 0;
   int var0 = 0;
 #if JVET_AA0093_ENHANCED_MMVD_EXTENSION
@@ -4318,22 +4422,35 @@ void CABACReader::mmvd_merge_idx(PredictionUnit& pu)
   uiUnaryIdx += temp;
   pu.mmvdMergeIdx = var0 * MMVD_MAX_REFINE_NUM  +uiUnaryIdx;
   DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_idx() mmvd_merge_idx=%d\n", pu.mmvdMergeIdx);
-}
-#else
-void CABACReader::mmvd_merge_idx(PredictionUnit& pu)
-{
-  RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE(STATS__CABAC_BITS__MERGE_INDEX, pu.lumaSize());
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    return;
+  }
+#endif
+#endif
 
+#if !JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED)
   int var0 = 0;
   if (pu.cs->sps->getMaxNumMergeCand() > 1)
   {
+#if !JVET_AA0093_ENHANCED_MMVD_EXTENSION
     static_assert(MMVD_BASE_MV_NUM == 2, "");
+#endif
     var0 = m_BinDecoder.decodeBin(Ctx::MmvdMergeIdx());
   }
   DTRACE(g_trace_ctx, D_SYNTAX, "base_mvp_idx() base_mvp_idx=%d\n", var0);
-  int numStepCandMinus1 = MMVD_REFINE_STEP - 1;
+  int numStepCandMinus1 = 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+                          VVC_MMVD_REFINE_STEP - 1;
+#else
+                          MMVD_REFINE_STEP - 1;
+#endif
   int var1 = 0;
+
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  if (m_BinDecoder.decodeBin(Ctx::MmvdStepMvpIdxECM3()))
+#else
   if (m_BinDecoder.decodeBin(Ctx::MmvdStepMvpIdx()))
+#endif
   {
     var1++;
     for (; var1 < numStepCandMinus1; var1++)
@@ -4363,11 +4480,15 @@ void CABACReader::mmvd_merge_idx(PredictionUnit& pu)
     }
   }
   DTRACE(g_trace_ctx, D_SYNTAX, "pos() pos=%d\n", var2);
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  int mvpIdx = (var0 * VVC_MMVD_MAX_REFINE_NUM + var1 * VVC_MMVD_MAX_DIR + var2);
+#else
   int mvpIdx = (var0 * MMVD_MAX_REFINE_NUM + var1 * 4 + var2);
+#endif
   pu.mmvdMergeIdx = mvpIdx;
   DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_idx() mmvd_merge_idx=%d\n", pu.mmvdMergeIdx);
-}
 #endif
+}
 
 void CABACReader::inter_pred_idc( PredictionUnit& pu )
 {
@@ -4605,7 +4726,7 @@ void CABACReader::mvp_flag( PredictionUnit& pu, RefPicList eRefList )
   {
     unsigned mvpIdx = 0;
 #if TM_AMVP
-#if JVET_Y0128_NON_CTC
+#if JVET_Y0128_NON_CTC || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_AMVP)
     if (PU::checkTmEnableCondition(pu.cs->sps, pu.cs->pps, pu.cu->slice->getRefPic(eRefList, pu.refIdx[eRefList])) == false)
 #else
     if(!pu.cu->cs->sps->getUseDMVDMode() || pu.cu->affine || CU::isIBC(*pu.cu))
@@ -4626,7 +4747,7 @@ void CABACReader::mvp_flag( PredictionUnit& pu, RefPicList eRefList )
   }
 #endif
 #if TM_AMVP
-#if JVET_Y0128_NON_CTC
+#if JVET_Y0128_NON_CTC || JVET_AA0132_CONFIGURABLE_TM_TOOLS
   unsigned mvpIdx = 0;
   if (pu.cu->affine || CU::isIBC(*pu.cu))
   {
@@ -4635,11 +4756,23 @@ void CABACReader::mvp_flag( PredictionUnit& pu, RefPicList eRefList )
 #if JVET_Z0054_BLK_REF_PIC_REORDER
   else if (PU::useRefCombList(pu))
   {
-    mvpIdx = pu.refIdxLC >= pu.cs->slice->getNumNonScaledRefPic() || !pu.cs->sps->getUseDMVDMode() ? m_BinDecoder.decodeBin(Ctx::MVPIdx()) : 0;
+    mvpIdx = pu.refIdxLC >= pu.cs->slice->getNumNonScaledRefPic()
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+          || !pu.cs->sps->getUseTMAmvpMode()
+#else
+          || !pu.cs->sps->getUseDMVDMode()
+#endif
+           ? m_BinDecoder.decodeBin(Ctx::MVPIdx()) : 0;
   }
   else if (PU::useRefPairList(pu))
   {
-    mvpIdx = pu.refPairIdx >= pu.cs->slice->getNumNonScaledRefPicPair() || !pu.cs->sps->getUseDMVDMode() ? m_BinDecoder.decodeBin(Ctx::MVPIdx()) : 0;
+    mvpIdx = pu.refPairIdx >= pu.cs->slice->getNumNonScaledRefPicPair()
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+          || !pu.cs->sps->getUseTMAmvpMode()
+#else
+          || !pu.cs->sps->getUseDMVDMode()
+#endif
+           ? m_BinDecoder.decodeBin(Ctx::MVPIdx()) : 0;
   }
 #endif
   else if (PU::checkTmEnableCondition(pu.cs->sps, pu.cs->pps, pu.cu->slice->getRefPic(eRefList, pu.refIdx[eRefList])) == false)
@@ -4684,10 +4817,14 @@ void CABACReader::Ciip_flag(PredictionUnit& pu)
   if( pu.ciipFlag )
   {
 #if JVET_X0141_CIIP_TIMD_TM && TM_MRG
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    tm_merge_flag(pu);
+#else
     if (pu.cs->slice->getSPS()->getUseCiipTmMrg())
     {
       pu.tmMergeFlag = (m_BinDecoder.decodeBin(Ctx::CiipTMMergeFlag()));
     }
+#endif
 #endif
     pu.ciipPDPC = (m_BinDecoder.decodeBin(Ctx::CiipFlag(1)));
   }
@@ -4695,7 +4832,11 @@ void CABACReader::Ciip_flag(PredictionUnit& pu)
 #if JVET_X0141_CIIP_TIMD_TM && TM_MRG
   if (pu.ciipFlag && pu.cs->slice->getSPS()->getUseCiipTmMrg())
   {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    tm_merge_flag(pu);
+#else
     pu.tmMergeFlag = (m_BinDecoder.decodeBin(Ctx::CiipTMMergeFlag()));
+#endif
   }
 #endif
 #endif
diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp
index bad189a68cc6b87d409563cf8a444227556fd74b..90d12ad9201fc35ed8db0f5f410aeb3dcef01a0b 100644
--- a/source/Lib/DecoderLib/DecCu.cpp
+++ b/source/Lib/DecoderLib/DecCu.cpp
@@ -1670,7 +1670,12 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
           mrgCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize);
         }
 
-        int   fPosBaseIdx = pu.mmvdMergeIdx / MMVD_MAX_REFINE_NUM;
+        int   fPosBaseIdx = 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+                            !pu.cs->sps->getUseTMMMVD() ? 
+                            pu.mmvdMergeIdx / VVC_MMVD_MAX_REFINE_NUM :
+#endif
+                            pu.mmvdMergeIdx / MMVD_MAX_REFINE_NUM;
         PU::getInterMergeCandidates(pu, mrgCtx, 1, fPosBaseIdx + 1);
         PU::getInterMMVDMergeCandidates(pu, mrgCtx,
           pu.mmvdMergeIdx
@@ -1801,36 +1806,29 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
 #if AFFINE_MMVD
 #if JVET_W0090_ARMC_TM
           int affMrgIdx = pu.cs->sps->getUseAML() && (((pu.mergeIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE < pu.cs->sps->getMaxNumAffineMergeCand()) || (pu.mergeIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE) == 0) ? pu.mergeIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE * ADAPTIVE_AFFINE_SUB_GROUP_SIZE + ADAPTIVE_AFFINE_SUB_GROUP_SIZE - 1 : pu.mergeIdx;
+		  if (pu.afMmvdFlag)
+		  {
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
-#if JVET_Z0139_NA_AFF
-          PU::getAffineMergeCand(pu, affineMergeCtx, 
-#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
-            m_pcInterPred,
+            affMrgIdx = 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_AA0093_ENHANCED_MMVD_EXTENSION
+                        !pu.cs->sps->getUseTMMMVD() ?
+                        ECM3_AF_MMVD_BASE_NUM :
 #endif
-            (pu.afMmvdFlag ? AF_MMVD_BASE_NUM : affMrgIdx), pu.afMmvdFlag, pu.mergeIdx == 0);
+			            AF_MMVD_BASE_NUM;
 #else
-          PU::getAffineMergeCand(pu, affineMergeCtx, 
+			affMrgIdx = pu.afMmvdBaseIdx;
+#endif			  
+		  }
+          PU::getAffineMergeCand(pu, affineMergeCtx
 #if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
-            m_pcInterPred,
-#endif
-            (pu.afMmvdFlag ? AF_MMVD_BASE_NUM : affMrgIdx), pu.afMmvdFlag);
+                               , m_pcInterPred
 #endif
-#else
+                               , affMrgIdx
+							   , pu.afMmvdFlag
 #if JVET_Z0139_NA_AFF
-          PU::getAffineMergeCand(pu, affineMergeCtx, 
-#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
-            m_pcInterPred,
-#endif
-            (pu.afMmvdFlag ? pu.afMmvdBaseIdx : affMrgIdx), pu.afMmvdFlag, pu.mergeIdx == 0);
-#else
-          PU::getAffineMergeCand(pu, affineMergeCtx, 
-#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION
-            m_pcInterPred,
+							   , pu.mergeIdx == 0
 #endif
-            (pu.afMmvdFlag ? pu.afMmvdBaseIdx : affMrgIdx), pu.afMmvdFlag);
-#endif
-#endif
-
+		  );
 #else
           PU::getAffineMergeCand(pu, affineMergeCtx, (pu.afMmvdFlag ? pu.afMmvdBaseIdx : pu.mergeIdx), pu.afMmvdFlag);
 #endif
@@ -1840,6 +1838,10 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
             pu.mergeIdx = PU::getMergeIdxFromAfMmvdBaseIdx(affineMergeCtx, pu.afMmvdBaseIdx);
             CHECK(pu.mergeIdx >= pu.cu->slice->getPicHeader()->getMaxNumAffineMergeCand(), "Affine MMVD mode doesn't have a valid base candidate!");
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+            if(pu.cs->sps->getUseTMMMVD())
+            {
+#endif
             uint32_t affMmvdLUT[AF_MMVD_NUM];
             uint32_t tempVal = pu.afMmvdMergeIdx;
             m_pcInterPred->sortAffineMergeCandidates(pu, affineMergeCtx, affMmvdLUT, tempVal );
@@ -1851,6 +1853,9 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
             stepIdx = stepIdx / AF_MMVD_OFFSET_DIR;
             pu.afMmvdDir      = (uint8_t)dirIdx;
             pu.afMmvdStep     = (uint8_t)stepIdx;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+            }
+#endif
 #endif
             PU::getAfMmvdMvf(pu, affineMergeCtx, affineMergeCtx.mvFieldNeighbours + (pu.mergeIdx << 1), pu.mergeIdx, pu.afMmvdStep, pu.afMmvdDir);
           }
@@ -2022,6 +2027,17 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
             {
               uint8_t mergeIdx = pu.bmDir == 2 ? pu.mergeIdx - BM_MRG_MAX_NUM_CANDS : pu.mergeIdx;
 #if JVET_W0090_ARMC_TM
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+              if (pu.cs->sps->getUseAML() && !pu.cs->sps->getUseTmvpNmvpReordering())
+              {
+                PU::getInterBMCandidates(pu, mrgCtx, pu.cs->sps->getUseAML() && (((mergeIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE < pu.cs->sps->getMaxNumBMMergeCand()) || (mergeIdx / ADAPTIVE_SUB_GROUP_SIZE) == 0) ? mergeIdx / ADAPTIVE_SUB_GROUP_SIZE * ADAPTIVE_SUB_GROUP_SIZE + ADAPTIVE_SUB_GROUP_SIZE - 1 : mergeIdx);
+                uint8_t bmDir = pu.bmDir;
+                pu.bmDir = 0;
+                m_pcInterPred->adjustInterMergeCandidates(pu, mrgCtx, mergeIdx);
+                pu.bmDir = bmDir;
+              }
+              else
+#endif
               if (pu.cs->sps->getUseAML())
               {
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING
@@ -2218,6 +2234,14 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
             else
 #endif
 #if JVET_W0090_ARMC_TM
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+            if (pu.cs->sps->getUseAML() && !pu.cs->sps->getUseTmvpNmvpReordering())
+            {
+              PU::getInterMergeCandidates(pu, mrgCtx, 0, pu.cs->sps->getUseAML() && (((pu.mergeIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE < pu.cs->sps->getMaxNumMergeCand()) || (pu.mergeIdx / ADAPTIVE_SUB_GROUP_SIZE) == 0) ? pu.mergeIdx / ADAPTIVE_SUB_GROUP_SIZE * ADAPTIVE_SUB_GROUP_SIZE + ADAPTIVE_SUB_GROUP_SIZE - 1 : pu.mergeIdx);
+              m_pcInterPred->adjustInterMergeCandidates(pu, mrgCtx, pu.mergeIdx);
+            }
+            else
+#endif
             if (pu.cs->sps->getUseAML())
             {
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING
@@ -2266,11 +2290,14 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
               if (!tplAvail)
               {
                 PU::getInterMergeCandidates(pu, mrgCtx, 0, -1);
+                mrgCtx.numValidMergeCand =
 #if TM_MRG
-                mrgCtx.numValidMergeCand = pu.tmMergeFlag ? pu.cs->sps->getMaxNumTMMergeCand() : pu.cs->sps->getMaxNumMergeCand();
-#else
-                mrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumMergeCand();
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+                                           pu.cs->sps->getUseTMMrgMode() &&
+#endif
+                                           pu.tmMergeFlag ? pu.cs->sps->getMaxNumTMMergeCand() :
 #endif
+                                           pu.cs->sps->getMaxNumMergeCand();
               }
               else
 #endif
@@ -2280,6 +2307,9 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
 #if TM_MRG && JVET_AA0093_REFINED_MOTION_FOR_ARMC
               tmMergeRefinedMotion = PU::isArmcRefinedMotionEnabled(pu, 2);
               tmMergeRefinedMotion &= tplAvail;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+              tmMergeRefinedMotion &= pu.cs->sps->getUseTMMrgMode();
+#endif
 #endif
               if (tplAvail)
               {
@@ -2381,12 +2411,15 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
               }
 #else
               PU::getInterMergeCandidates(pu, mrgCtx, 0, pu.cs->sps->getUseAML() && (((pu.mergeIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE < pu.cs->sps->getMaxNumMergeCand()) || (pu.mergeIdx / ADAPTIVE_SUB_GROUP_SIZE) == 0) ? pu.mergeIdx / ADAPTIVE_SUB_GROUP_SIZE * ADAPTIVE_SUB_GROUP_SIZE + ADAPTIVE_SUB_GROUP_SIZE - 1 : pu.mergeIdx);
-#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+#if TM_MRG && JVET_AA0093_REFINED_MOTION_FOR_ARMC
               tmMergeRefinedMotion = PU::isArmcRefinedMotionEnabled(pu, 2);
               int nWidth = pu.lumaSize().width;
               int nHeight = pu.lumaSize().height;
               bool tplAvail = m_pcInterPred->xAMLGetCurBlkTemplate(pu, nWidth, nHeight);
               tmMergeRefinedMotion &= tplAvail;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+              tmMergeRefinedMotion &= pu.cs->sps->getUseTMMrgMode();
+#endif
               if (pu.tmMergeFlag && tmMergeRefinedMotion)
               {
                 int tmpPuMrgIdx = pu.mergeIdx;
@@ -2558,7 +2591,7 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
 #if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)
           else
           {
-#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+#if TM_MRG && JVET_AA0093_REFINED_MOTION_FOR_ARMC
             if (pu.tmMergeFlag && !tmMergeRefinedMotion)
 #else
             if (pu.tmMergeFlag)
@@ -2844,7 +2877,7 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
                 if (pu.amvpMergeModeFlag[1 - eRefList] == true)
                 {
 #if TM_AMVP
-#if JVET_Y0128_NON_CTC
+#if JVET_Y0128_NON_CTC || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_AMVP)
                   amvpInfo.numCand = PU::checkTmEnableCondition(pu.cs->sps, pu.cs->pps, pu.cu->slice->getRefPic(eRefList, pu.refIdx[eRefList])) ? 1 : 2;
 #else
                   amvpInfo.numCand = 1;
diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp
index 377df7775dfee0d1899b9b8cf9a60e6db6285c33..eaa5b29243a6148f8bac1e42ee05d767b0fc8abf 100644
--- a/source/Lib/DecoderLib/VLCReader.cpp
+++ b/source/Lib/DecoderLib/VLCReader.cpp
@@ -2187,6 +2187,9 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
       copyRefPicList(pcSPS, rplListSource->getReferencePictureList(ii), rplListDest->getReferencePictureList(ii));
   }
 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  READ_FLAG( uiCode, "sps_tm_tools_enabled_flag" );                 pcSPS->setTMToolsEnableFlag( uiCode );
+#endif
 #if INTER_LIC
   READ_FLAG( uiCode, "sps_lic_enabled_flag" );                      pcSPS->setLicEnabledFlag( uiCode );
 #endif
@@ -2216,15 +2219,36 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
   READ_FLAG( uiCode,  "sps_amvr_enabled_flag" );                     pcSPS->setAMVREnabledFlag ( uiCode != 0 );
 
 #if JVET_W0090_ARMC_TM
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  pcSPS->setUseAML(false);
+  if(pcSPS->getTMToolsEnableFlag())
+  {
+#endif
   READ_FLAG( uiCode, "sps_aml_enabled_flag");                        pcSPS->setUseAML ( uiCode != 0 );
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  }
+#endif
+#endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+  pcSPS->setUseTmvpNmvpReordering(false);
+  if (pcSPS->getUseAML())
+  {
+    READ_FLAG( uiCode, "sps_aml_tmvp_nmvp_enabled_flag");            pcSPS->setUseTmvpNmvpReordering ( uiCode != 0 );
+  }
 #endif
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  pcSPS->setUseArmcRefinedMotion (false);
+#endif
   if (pcSPS->getUseAML())
   {
     READ_FLAG( uiCode, "sps_ArmcRefinedMotion_enabled_flag");        pcSPS->setUseArmcRefinedMotion ( uiCode != 0 );
   }
 #endif
 #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  pcSPS->setNumLambda(0);
+#endif
   if (pcSPS->getUseAML())
   {
     READ_UVLC(uiCode, "num_Lambda");
@@ -2261,7 +2285,15 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
   }
 #endif
 #if JVET_Z0054_BLK_REF_PIC_REORDER
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  pcSPS->setUseARL(false);
+  if (pcSPS->getTMToolsEnableFlag())
+  {
+#endif
   READ_FLAG( uiCode, "sps_arl_enabled_flag");                        pcSPS->setUseARL ( uiCode != 0 );
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  }
+#endif
 #endif
   READ_FLAG( uiCode, "sps_bdof_enabled_flag" );                      pcSPS->setBDOFEnabledFlag ( uiCode != 0 );
   if (pcSPS->getBDOFEnabledFlag())
@@ -2290,6 +2322,10 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
     pcSPS->setFpelMmvdEnabledFlag( false );
   }
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  uiCode = 0;
+  if (pcSPS->getTMToolsEnableFlag())
+#endif
   READ_FLAG(uiCode, "sps_mvsd_enabled_flag");
   pcSPS->setUseMVSD(uiCode != 0);
 #endif
@@ -2300,8 +2336,30 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
 #if TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM || MULTI_PASS_DMVR
   READ_FLAG( uiCode,    "sps_dmvd_enabled_flag" );                      pcSPS->setUseDMVDMode( uiCode != 0 );
 #endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_AMVP
+  pcSPS->setUseTMAmvpMode(false);
+  if (pcSPS->getTMToolsEnableFlag())
+  {
+    READ_FLAG( uiCode,    "sps_tm_amvp_enabled_flag" );                   pcSPS->setUseTMAmvpMode( uiCode != 0 );
+  }
+#endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_MRG
+  pcSPS->setUseTMMrgMode(false);
+  if (pcSPS->getTMToolsEnableFlag())
+  {
+    READ_FLAG( uiCode,    "sps_tm_mrg_enabled_flag" );                    pcSPS->setUseTMMrgMode( uiCode != 0 );
+  }
+#endif
 #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  pcSPS->setUseAltGPMSplitModeCode(false);
+  if (pcSPS->getTMToolsEnableFlag())
+  {
+#endif
   READ_FLAG( uiCode,    "sps_alt_gpm_code_enabled_flag" );              pcSPS->setUseAltGPMSplitModeCode( uiCode != 0 );
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  }
+#endif
 #endif
 #if JVET_X0049_ADAPT_DMVR
   READ_UVLC(uiCode, "six_minus_max_num_bm_merge_cand");
@@ -2340,11 +2398,22 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
       pcSPS->setProfControlPresentFlag( false );
     }
   }
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  pcSPS->setUseTMMMVD(false);
+  if (pcSPS->getTMToolsEnableFlag() && (pcSPS->getUseMMVD() || pcSPS->getUseAffineMmvdMode()))
+  {
+    READ_FLAG(uiCode, "sps_tm_mmvd_enabled_flag");                  pcSPS->setUseTMMMVD(uiCode != 0);
+  }
+#endif
 
   READ_FLAG( uiCode,    "sps_bcw_enabled_flag" );                   pcSPS->setUseBcw( uiCode != 0 );
   READ_FLAG( uiCode,     "sps_ciip_enabled_flag" );                           pcSPS->setUseCiip             ( uiCode != 0 );
 #if JVET_X0141_CIIP_TIMD_TM && TM_MRG
-  if (pcSPS->getUseCiip())
+  if (pcSPS->getUseCiip()
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    && pcSPS->getTMToolsEnableFlag()
+#endif
+    )
   {
     READ_FLAG(uiCode, "sps_ciip_tm_merge_enabled_flag");                           pcSPS->setUseCiipTmMrg(uiCode != 0);
   }
@@ -2370,7 +2439,20 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
       {
         pcSPS->setMaxNumGeoCand(2);
       }
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_W0097_GPM_MMVD_TM && TM_MRG
+      pcSPS->setUseGPMTMMode( false );
+      if (pcSPS->getTMToolsEnableFlag())
+      {
+        READ_FLAG( uiCode,    "sps_gpm_tm_enabled_flag" );                      pcSPS->setUseGPMTMMode( uiCode != 0 );
+      }
+#endif
+    }
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_W0097_GPM_MMVD_TM && TM_MRG
+    else
+    {
+      pcSPS->setUseGPMTMMode( false );
     }
+#endif
   }
   else
   {
@@ -2493,6 +2575,13 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
 #endif
 #if ENABLE_OBMC
   READ_FLAG(uiCode, "sps_obmc_flag");                              pcSPS->setUseOBMC(uiCode != 0);
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Z0061_TM_OBMC
+  pcSPS->setUseOBMCTMMode(false);
+  if (pcSPS->getTMToolsEnableFlag() && pcSPS->getUseOBMC())
+  {
+    READ_FLAG(uiCode, "sps_obmc_tm_flag");                         pcSPS->setUseOBMCTMMode(uiCode != 0);
+  }
+#endif
 #endif
 #if JVET_Z0135_TEMP_CABAC_WIN_WEIGHT
   READ_FLAG( uiCode, "sps_cabac_temp_init_flag" );							pcSPS->setTempCabacInitMode( uiCode != 0 );
diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp
index bfd0b401fc82d6e80f25e8f450be5cb46fb4efca..6c60377bd4b35d17bc2646650450be25ddd2e36e 100644
--- a/source/Lib/EncoderLib/CABACWriter.cpp
+++ b/source/Lib/EncoderLib/CABACWriter.cpp
@@ -1149,8 +1149,15 @@ void CABACWriter::cu_pred_data( const CodingUnit& cu )
 #if INTER_LIC
   cu_lic_flag(cu);
 #endif
-#if !JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if !JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED)
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  if (!cu.cs->sps->getUseMVSD())
+  {
+#endif
   cu_bcw_flag(cu);
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  }
+#endif
 #endif
 #if ENABLE_OBMC 
   obmc_flag( cu );
@@ -2724,7 +2731,14 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu )
     affine_flag   ( *pu.cu );
     smvd_mode( pu );
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    if(pu.cs->sps->getUseMVSD())
+    {
+#endif
     cu_bcw_flag(*pu.cu);
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    }
+#endif
 #endif
 #if JVET_Z0054_BLK_REF_PIC_REORDER
     refPairIdx(pu);
@@ -2989,11 +3003,17 @@ void CABACWriter::affine_mmvd_data(const PredictionUnit& pu)
   int numCandMinus1Base = AF_MMVD_BASE_NUM - 1;
 #if JVET_AA0093_ENHANCED_MMVD_EXTENSION
   unsigned ctxId = 0;
-  const CodingStructure *cs = pu.cu->cs;
-  const CodingUnit *cuLeft = cs->getCURestricted( pu.cu->lumaPos().offset( -1, 0 ), *pu.cu, CH_L );
-  ctxId = (cuLeft && cuLeft->affine) ? 1 : 0;
-  const CodingUnit *cuAbove = cs->getCURestricted( pu.cu->lumaPos().offset( 0, -1 ), *pu.cu, CH_L );
-  ctxId += (cuAbove && cuAbove->affine) ? 1 : 0;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  static_assert(ECM3_AF_MMVD_BASE_NUM == 1, "The value of ECM3_AF_MMVD_BASE_NUM must be 1");
+  if (pu.cs->sps->getUseTMMMVD())
+#endif
+  {
+    const CodingStructure *cs = pu.cu->cs;
+    const CodingUnit *cuLeft = cs->getCURestricted(pu.cu->lumaPos().offset(-1, 0), *pu.cu, CH_L);
+    ctxId = (cuLeft && cuLeft->affine) ? 1 : 0;
+    const CodingUnit *cuAbove = cs->getCURestricted(pu.cu->lumaPos().offset(0, -1), *pu.cu, CH_L);
+    ctxId += (cuAbove && cuAbove->affine) ? 1 : 0;
+  }
   numCandMinus1Base = (ctxId == 0) ? 0 : ((ctxId == 1) ? 1 : AF_MMVD_BASE_NUM-1);
 #endif
   if (numCandMinus1Base > 0)
@@ -3025,6 +3045,10 @@ void CABACWriter::affine_mmvd_data(const PredictionUnit& pu)
   DTRACE(g_trace_ctx, D_SYNTAX, "afMmvd_base_idx() afMmvd_base_idx=%d\n", afMmvdBaseIdx);
 
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  if(pu.cs->sps->getUseTMMMVD())
+  {
+#endif
 #if JVET_AA0093_ENHANCED_MMVD_EXTENSION
   uint16_t sym = pu.afMmvdMergeIdx;
 #else
@@ -3057,14 +3081,28 @@ void CABACWriter::affine_mmvd_data(const PredictionUnit& pu)
       break;
     }
   }
-#else
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    return;
+  }
+#endif
+#endif
+
+#if !JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED)
   {
     // Code Step Value
     uint8_t step = pu.afMmvdStep;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+    int numCandMinus1Base = ECM3_AF_MMVD_STEP_NUM - 1;
+#else
     int numCandMinus1Base = AF_MMVD_STEP_NUM - 1;
+#endif
     if (numCandMinus1Base > 0)
     {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+      m_BinEncoder.encodeBin((step == 0 ? 0 : 1), Ctx::AfMmvdOffsetStepECM3());
+#else
       m_BinEncoder.encodeBin((step == 0 ? 0 : 1), Ctx::AfMmvdOffsetStep());
+#endif
 
       if (step > 0)
       {
@@ -3159,8 +3197,48 @@ void CABACWriter::ibcMbvdData(const PredictionUnit& pu)
 #if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)
 void CABACWriter::tm_merge_flag(const PredictionUnit& pu)
 {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_X0141_CIIP_TIMD_TM && TM_MRG
+  if (pu.ciipFlag)
+  {
+    if (pu.cs->slice->getSPS()->getUseCiipTmMrg())
+    {
+      m_BinEncoder.encodeBin(pu.tmMergeFlag, Ctx::CiipTMMergeFlag());
+    }
+    return;
+  }
+#endif
+
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_W0097_GPM_MMVD_TM && TM_MRG
+  if (pu.cu->geoFlag)
+  {
+    if (!pu.cs->slice->getSPS()->getUseGPMTMMode())
+    {
+      return;
+    }
+  }
+  else
+#endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_MRG
+  if (pu.regularMergeFlag
+#if JVET_Z0084_IBC_TM && IBC_TM_MRG
+    && !CU::isIBC(*pu.cu)
+#endif
+    )
+  {
+    if (!pu.cs->slice->getSPS()->getUseTMMrgMode())
+    {
+      return;
+    }
+  }
+  else
+#endif
   if (!pu.cs->slice->getSPS()->getUseDMVDMode())
   {
+#if (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_X0141_CIIP_TIMD_TM && TM_MRG) && (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_W0097_GPM_MMVD_TM && TM_MRG) && (JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_MRG)
+#if !(JVET_Z0084_IBC_TM && IBC_TM_MRG)
+    CHECK(true, "Unknown mode to code tm_merge_flag");
+#endif
+#endif
     return;
   }
 
@@ -3277,7 +3355,11 @@ void CABACWriter::merge_data(const PredictionUnit& pu)
 #endif
 #if JVET_X0049_ADAPT_DMVR 
 #if TM_MRG
-    if ((pu.tmMergeFlag || pu.bmMergeFlag))
+    if ((pu.tmMergeFlag || pu.bmMergeFlag)
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+      || !pu.cs->slice->getSPS()->getUseTMMrgMode()
+#endif
+      )
 #endif
     {
        bm_merge_flag(pu);
@@ -3293,7 +3375,11 @@ void CABACWriter::merge_data(const PredictionUnit& pu)
       )
     {
 #if JVET_AA0093_ENHANCED_MMVD_EXTENSION
-      unsigned  ctxId = pu.cu->skip ? 0 : 1;
+      unsigned  ctxId = 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+                        !pu.cs->sps->getUseTMMMVD() ||
+#endif
+                        pu.cu->skip ? 0 : 1;
       m_BinEncoder.encodeBin(pu.mmvdMergeFlag, Ctx::MmvdFlag(ctxId));
 #else
       m_BinEncoder.encodeBin(pu.mmvdMergeFlag, Ctx::MmvdFlag(0));
@@ -3320,10 +3406,14 @@ void CABACWriter::merge_data(const PredictionUnit& pu)
     if (pu.ciipFlag && !geoAvailable && ciipAvailable)
     {
 #if JVET_X0141_CIIP_TIMD_TM && TM_MRG
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+      tm_merge_flag(pu);
+#else
       if (pu.cs->slice->getSPS()->getUseCiipTmMrg())
       {
           m_BinEncoder.encodeBin(pu.tmMergeFlag, Ctx::CiipTMMergeFlag());
       }
+#endif
 #endif
       m_BinEncoder.encodeBin(pu.ciipPDPC, Ctx::CiipFlag(1));
     }
@@ -3331,7 +3421,11 @@ void CABACWriter::merge_data(const PredictionUnit& pu)
 #if JVET_X0141_CIIP_TIMD_TM && TM_MRG
     if (pu.ciipFlag && !geoAvailable && ciipAvailable && pu.cs->slice->getSPS()->getUseCiipTmMrg())
     {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+      tm_merge_flag(pu);
+#else
       m_BinEncoder.encodeBin(pu.tmMergeFlag, Ctx::CiipTMMergeFlag());
+#endif
     }
 #endif
 #endif
@@ -3718,9 +3812,13 @@ void CABACWriter::merge_idx( const PredictionUnit& pu )
   }
 }
 
-#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
 void CABACWriter::mmvd_merge_idx(const PredictionUnit& pu)
 {
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  if(pu.cs->sps->getUseTMMMVD())
+  {
+#endif
   int mvpIdx = pu.mmvdMergeIdx;
   int var0;
   var0 = mvpIdx / MMVD_MAX_REFINE_NUM;
@@ -3760,7 +3858,7 @@ void CABACWriter::mmvd_merge_idx(const PredictionUnit& pu)
 #endif
   if(ricePar > 0)
   {
-    m_BinEncoder.encodeBinsEP( mvpIdx % (1 << ricePar), ricePar);
+    m_BinEncoder.encodeBinsEP(mvpIdx % (1 << ricePar), ricePar);
   }
   mvpIdx >>= ricePar;
   for (unsigned int uiUnaryIdx = 0; uiUnaryIdx < numStepCandMinus1; ++uiUnaryIdx)
@@ -3772,35 +3870,59 @@ void CABACWriter::mmvd_merge_idx(const PredictionUnit& pu)
       break;
     }
   }
-  
+
   DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_idx() mmvd_merge_idx=%d\n", pu.mmvdMergeIdx);
-}
-#else
-void CABACWriter::mmvd_merge_idx(const PredictionUnit& pu)
-{
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    return;
+  }
+#endif
+#endif
+
+#if !JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED)
   int var0, var1, var2;
   int mvpIdx = pu.mmvdMergeIdx;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  var0 = mvpIdx / VVC_MMVD_MAX_REFINE_NUM;
+  var1 = (mvpIdx - (var0 * VVC_MMVD_MAX_REFINE_NUM)) / 4;
+  var2 = mvpIdx - (var0 * VVC_MMVD_MAX_REFINE_NUM) - var1 * 4;
+#else
   var0 = mvpIdx / MMVD_MAX_REFINE_NUM;
   var1 = (mvpIdx - (var0 * MMVD_MAX_REFINE_NUM)) / 4;
   var2 = mvpIdx - (var0 * MMVD_MAX_REFINE_NUM) - var1 * 4;
+#endif
   if (pu.cs->sps->getMaxNumMergeCand() > 1)
   {
+#if !JVET_AA0093_ENHANCED_MMVD_EXTENSION
     static_assert(MMVD_BASE_MV_NUM == 2, "");
+#endif
     assert(var0 < 2);
     m_BinEncoder.encodeBin(var0, Ctx::MmvdMergeIdx());
   }
   DTRACE(g_trace_ctx, D_SYNTAX, "base_mvp_idx() base_mvp_idx=%d\n", var0);
 
-  int numStepCandMinus1 = MMVD_REFINE_STEP - 1;
+  int numStepCandMinus1 = 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+                          VVC_MMVD_REFINE_STEP - 1;
+#else
+                          MMVD_REFINE_STEP - 1;
+#endif
   if (numStepCandMinus1 > 0)
   {
     if (var1 == 0)
     {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+      m_BinEncoder.encodeBin(0, Ctx::MmvdStepMvpIdxECM3());
+#else
       m_BinEncoder.encodeBin(0, Ctx::MmvdStepMvpIdx());
+#endif
     }
     else
     {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+      m_BinEncoder.encodeBin(1, Ctx::MmvdStepMvpIdxECM3());
+#else
       m_BinEncoder.encodeBin(1, Ctx::MmvdStepMvpIdx());
+#endif
       for (unsigned idx = 1; idx < numStepCandMinus1; idx++)
       {
         m_BinEncoder.encodeBinEP(var1 == idx ? 0 : 1);
@@ -3817,8 +3939,8 @@ void CABACWriter::mmvd_merge_idx(const PredictionUnit& pu)
 
   DTRACE(g_trace_ctx, D_SYNTAX, "pos() pos=%d\n", var2);
   DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_idx() mmvd_merge_idx=%d\n", pu.mmvdMergeIdx);
-}
 #endif
+}
 
 #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
 void CABACWriter::geoModeIdx(const uint8_t geoMode, const uint8_t altCodeIdx)
@@ -4528,7 +4650,7 @@ void CABACWriter::mvp_flag( const PredictionUnit& pu, RefPicList eRefList )
     if (pu.mvpIdx[eRefList] < 2)
     {
 #if TM_AMVP
-#if JVET_Y0128_NON_CTC
+#if JVET_Y0128_NON_CTC || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_AMVP)
       if (PU::checkTmEnableCondition(pu.cs->sps, pu.cs->pps, pu.cu->slice->getRefPic(eRefList, pu.refIdx[eRefList])) == false)
 #else
       if(!pu.cu->cs->sps->getUseDMVDMode() || pu.cu->affine || CU::isIBC(*pu.cu))
@@ -4547,7 +4669,7 @@ void CABACWriter::mvp_flag( const PredictionUnit& pu, RefPicList eRefList )
   }
 #endif
 #if TM_AMVP
-#if JVET_Y0128_NON_CTC
+#if JVET_Y0128_NON_CTC || JVET_AA0132_CONFIGURABLE_TM_TOOLS
   bool needToCodeMvpIdx = false;
   if (pu.cu->affine || CU::isIBC(*pu.cu))
   {
@@ -4556,11 +4678,23 @@ void CABACWriter::mvp_flag( const PredictionUnit& pu, RefPicList eRefList )
 #if JVET_Z0054_BLK_REF_PIC_REORDER
   else if (PU::useRefCombList(pu))
   {
-    needToCodeMvpIdx = pu.refIdxLC >= pu.cs->slice->getNumNonScaledRefPic() || !pu.cs->sps->getUseDMVDMode();
+    needToCodeMvpIdx = pu.refIdxLC >= pu.cs->slice->getNumNonScaledRefPic()
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+                    || !pu.cs->sps->getUseTMAmvpMode()
+#else
+                    || !pu.cs->sps->getUseDMVDMode()
+#endif
+      ;
   }
   else if (PU::useRefPairList(pu))
   {
-    needToCodeMvpIdx = pu.refPairIdx >= pu.cs->slice->getNumNonScaledRefPicPair() || !pu.cs->sps->getUseDMVDMode();
+    needToCodeMvpIdx = pu.refPairIdx >= pu.cs->slice->getNumNonScaledRefPicPair()
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+                    || !pu.cs->sps->getUseTMAmvpMode()
+#else
+                    || !pu.cs->sps->getUseDMVDMode()
+#endif
+      ;
   }
 #endif
   else if (PU::checkTmEnableCondition(pu.cs->sps, pu.cs->pps, pu.cu->slice->getRefPic(eRefList, pu.refIdx[eRefList])) == false)
@@ -4595,10 +4729,14 @@ void CABACWriter::Ciip_flag(const PredictionUnit& pu)
   if( pu.ciipFlag )
   {
 #if JVET_X0141_CIIP_TIMD_TM && TM_MRG
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    tm_merge_flag(pu);
+#else
     if (pu.cs->slice->getSPS()->getUseCiipTmMrg())
     {
         m_BinEncoder.encodeBin(pu.tmMergeFlag, Ctx::CiipTMMergeFlag());
     }
+#endif
 #endif
     m_BinEncoder.encodeBin(pu.ciipPDPC, Ctx::CiipFlag(1));
   }
@@ -4606,7 +4744,11 @@ void CABACWriter::Ciip_flag(const PredictionUnit& pu)
 #if JVET_X0141_CIIP_TIMD_TM && TM_MRG
   if (pu.ciipFlag && pu.cs->slice->getSPS()->getUseCiipTmMrg())
   {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    tm_merge_flag(pu);
+#else
     m_BinEncoder.encodeBin(pu.tmMergeFlag, Ctx::CiipTMMergeFlag());
+#endif
   }
 #endif
 #endif
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index fd74572ac1f8c6dc35a31803937c487336be57e4..c5503db4efa1f016fa33e3711425e2d83c480d52 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -409,6 +409,30 @@ protected:
 #if TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM || MULTI_PASS_DMVR
   bool      m_DMVDMode;
 #endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  bool      m_tmToolsEnableFlag;
+#if TM_AMVP
+  bool      m_tmAmvpMode;
+#endif
+#if TM_MRG
+  bool      m_tmMrgMode;
+#endif
+#if JVET_W0097_GPM_MMVD_TM && TM_MRG
+  bool      m_tmGPMMode;
+#endif
+#if JVET_Z0061_TM_OBMC && ENABLE_OBMC
+  bool      m_tmOBMCMode;
+#endif
+#if JVET_X0141_CIIP_TIMD_TM && TM_MRG
+  int       m_tmCIIPMode;
+#endif
+#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+  bool      m_useTmvpNmvpReorder;
+#endif
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  bool      m_useTMMMVD;
+#endif
+#endif
 #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
   bool      m_altGPMSplitModeCode;
 #endif
@@ -1339,6 +1363,38 @@ public:
   void      setUseDMVDMode                  (bool b)         { m_DMVDMode = b; }
   bool      getUseDMVDMode                  ()         const { return m_DMVDMode; }
 #endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  void      setTMToolsEnableFlag            (bool b)         { m_tmToolsEnableFlag = b; }
+  bool      getTMToolsEnableFlag            ()         const { return m_tmToolsEnableFlag; }
+#if TM_AMVP
+  void      setUseTMAmvpMode                (bool b)         { m_tmAmvpMode = b; }
+  bool      getUseTMAmvpMode                ()         const { return m_tmAmvpMode; }
+#endif
+#if TM_MRG
+  void      setUseTMMrgMode                 (bool b)         { m_tmMrgMode = b; }
+  bool      getUseTMMrgMode                 ()         const { return m_tmMrgMode; }
+#endif
+#if JVET_W0097_GPM_MMVD_TM && TM_MRG
+  void      setUseGPMTMMode                  (bool b)         { m_tmGPMMode = b; }
+  bool      getUseGPMTMMode                  ()         const { return m_tmGPMMode; }
+#endif
+#if JVET_Z0061_TM_OBMC && ENABLE_OBMC
+  void      setUseOBMCTMMode                (bool b)         { m_tmOBMCMode = b; }
+  bool      getUseOBMCTMMode                ()         const { return m_tmOBMCMode; }
+#endif
+#if JVET_X0141_CIIP_TIMD_TM && TM_MRG
+  void      setUseCIIPTMMode                (int i)          { m_tmCIIPMode = i; }
+  int       getUseCIIPTMMode                ()         const { return m_tmCIIPMode; }
+#endif
+#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+  void      setUseTmvpNmvpReordering        (bool b)         { m_useTmvpNmvpReorder = b; }
+  bool      getUseTmvpNmvpReordering        ()         const { return m_useTmvpNmvpReorder; }
+#endif
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  void      setUseTMMMVD                    (bool b)         { m_useTMMMVD = b; }
+  bool      getUseTMMMVD                    ()         const { return m_useTMMMVD; }
+#endif
+#endif
 #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
   void      setUseAltGPMSplitModeCode       (bool b)         { m_altGPMSplitModeCode = b; }
   bool      getUseAltGPMSplitModeCode       ()         const { return m_altGPMSplitModeCode; }
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index b7137e5ca898431d12c7193fc373e2eaa4d1503c..2135c14d8d1d76fe0606ea924e7b10f69f37c2a0 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -248,6 +248,12 @@ void EncCu::create( EncCfg* encCfg )
 #else
   m_fastGpmMmvdRelatedCU = ((encCfg->getIntraPeriod() < 0) && ((sourceWidth * sourceHeight) >= (1280 * 720))) && !encCfg->getIBCMode();
 #endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_MRG
+  if (!encCfg->getUseTMMrgMode())
+  {
+    m_fastGpmMmvdRelatedCU = ((encCfg->getIntraPeriod() < 0) && ((sourceWidth * sourceHeight) >= (1280 * 720))) && !encCfg->getIBCMode();
+  }
+#endif
 
   m_includeMoreMMVDCandFirstPass = ((encCfg->getIntraPeriod() > 0) || ((encCfg->getIntraPeriod() < 0) && m_fastGpmMmvdSearch));
   m_maxNumGPMDirFirstPass = ((encCfg->getIntraPeriod() < 0) ? 50 : (m_fastGpmMmvdSearch ? 36 : 64));
@@ -3168,6 +3174,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #if JVET_AA0093_ENHANCED_MMVD_EXTENSION
   uint8_t numBaseAffine = AF_MMVD_BASE_NUM;
   unsigned ctxId = 0;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  if (tempCS->sps->getUseTMMMVD())
+#endif
   {
     CodingUnit cu( tempCS->area );
     cu.cs       = tempCS;
@@ -3337,6 +3346,13 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
     if (sps.getUseAML())
     {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+      if (!sps.getUseTmvpNmvpReordering())
+      {
+        m_pcInterSearch->adjustInterMergeCandidates(pu, mergeCtx);
+      }
+      else
+#endif
       if (tplAvail)
       {
 #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND 
@@ -3459,7 +3475,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
     pu.mmvdMergeFlag = flag;
 #endif
 #if TM_MRG && MERGE_ENC_OPT
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    if (cu.cs->sps->getUseTMMrgMode())
+#else
     if (cu.cs->sps->getUseDMVDMode())
+#endif
     {
       cu.firstPU = &pu;
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
@@ -3531,6 +3551,13 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       if (sps.getUseAML())
       {
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+        if (!sps.getUseTmvpNmvpReordering())
+        {
+          m_pcInterSearch->adjustInterMergeCandidates(pu, tmMrgCtx);
+        }
+        else
+#endif
         if (tplAvail)
         {
 #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND 
@@ -3824,6 +3851,13 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         {
           pu.bmDir = 0;
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+          if (!sps.getUseTmvpNmvpReordering())
+          {
+            m_pcInterSearch->adjustInterMergeCandidates(pu, bmMrgCtx);
+          }
+          else
+#endif
           if (tplAvail)
           {
 #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND 
@@ -3867,11 +3901,22 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
   }
 #if AFFINE_MMVD && MERGE_ENC_OPT
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
-  int  afMmvdBaseIdxToMergeIdxOffset = (int)PU::getMergeIdxFromAfMmvdBaseIdx(affineMergeCtxTmp, 0);
+  int  afMmvdBaseIdxToMergeIdxOffset = 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+                                       !tempCS->sps->getUseTMMMVD() ?
+                                       (int)PU::getMergeIdxFromAfMmvdBaseIdx(affineMergeCtx,    0) :
+#endif
+                                       (int)PU::getMergeIdxFromAfMmvdBaseIdx(affineMergeCtxTmp, 0);
 #else
   int  afMmvdBaseIdxToMergeIdxOffset = (int)PU::getMergeIdxFromAfMmvdBaseIdx(affineMergeCtx, 0);
 #endif
   int  afMmvdBaseCount = std::min<int>((int)AF_MMVD_BASE_NUM, affineMergeCtx.numValidMergeCand - afMmvdBaseIdxToMergeIdxOffset);
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  if (!tempCS->sps->getUseTMMMVD())
+  {
+    afMmvdBaseCount = std::min<int>((int)ECM3_AF_MMVD_BASE_NUM, affineMergeCtx.numValidMergeCand - afMmvdBaseIdxToMergeIdxOffset);
+  }
+#endif
   bool affineMmvdAvail = affineMrgAvail && afMmvdBaseCount >= 1 && sps.getUseAffineMmvdMode();
 #endif
   bool candHasNoResidual[MRG_MAX_NUM_CANDS + MMVD_ADD_NUM] = { false };
@@ -3890,7 +3935,12 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #if !MERGE_ENC_OPT
   int                                         insertPos;
 #endif
-  unsigned                                    uiNumMrgSATDCand = mergeCtx.numValidMergeCand + MMVD_ADD_NUM;
+  unsigned                                    uiNumMrgSATDCand = 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+                                                                 !tempCS->sps->getUseTMMMVD() ?
+                                                                 mergeCtx.numValidMergeCand + VVC_MMVD_ADD_NUM :
+#endif
+                                                                 mergeCtx.numValidMergeCand + MMVD_ADD_NUM;
 
 #if !MERGE_ENC_OPT
   struct ModeInfo
@@ -3913,7 +3963,12 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 #endif
   static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM>  rdModeList;
   bool                                        mrgTempBufSet = false;
-  const int candNum = mergeCtx.numValidMergeCand + (tempCS->sps->getUseMMVD() ? std::min<int>(MMVD_BASE_MV_NUM, mergeCtx.numValidMergeCand) * MMVD_MAX_REFINE_NUM : 0);
+  const int candNum = 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+                      !tempCS->sps->getUseTMMMVD() ?
+                      mergeCtx.numValidMergeCand + (tempCS->sps->getUseMMVD() ? std::min<int>(VVC_MMVD_BASE_MV_NUM, mergeCtx.numValidMergeCand) * VVC_MMVD_MAX_REFINE_NUM : 0) :
+#endif
+                      mergeCtx.numValidMergeCand + (tempCS->sps->getUseMMVD() ? std::min<int>(MMVD_BASE_MV_NUM, mergeCtx.numValidMergeCand) * MMVD_MAX_REFINE_NUM : 0);
 
   for (int i = 0; i < candNum; i++)
   {
@@ -4041,7 +4096,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
     }
 
 #if TM_MRG
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    if (tempCS->sps->getUseTMMrgMode())
+#else
     if (tempCS->sps->getUseDMVDMode())
+#endif
     {
       bestIsSkip = false;
       uiNumMrgSATDCand += TM_MAX_NUM_SATD_CAND;
@@ -4451,7 +4510,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       }
 #if MERGE_ENC_OPT
 #if TM_MRG
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+      if (sps.getUseTMMrgMode())
+#else
       if (sps.getUseDMVDMode())
+#endif
       {
         xCheckSATDCostTMMerge(tempCS, cu, pu, tmMrgCtx, acMergeTempBuffer, singleMergeTempBuffer, uiNumMrgSATDCand, rdModeList, candCostList, distParam, ctxStart
 #if MULTI_PASS_DMVR
@@ -4571,6 +4634,12 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         uiNumMrgSATDCand = mergeCtx.numValidMergeCand + std::min<int>(MMVD_BASE_MV_NUM, mergeCtx.numValidMergeCand) * MMVD_MAX_REFINE_NUM;
 #else
         uiNumMrgSATDCand = mergeCtx.numValidMergeCand + ((mergeCtx.numValidMergeCand > 1) ? MMVD_ADD_NUM : MMVD_ADD_NUM >> 1);
+#endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+        if(!tempCS->sps->getUseTMMMVD())
+        {
+          uiNumMrgSATDCand = mergeCtx.numValidMergeCand + ((mergeCtx.numValidMergeCand > 1) ? VVC_MMVD_ADD_NUM : VVC_MMVD_ADD_NUM >> 1);
+        }
 #endif
       }
       else
@@ -4597,6 +4666,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
         }
       }
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+     if(tempCS->sps->getUseTMMMVD())
+#endif
      if (rdModeList[uiMrgHADIdx].isMMVD && (uiMergeCand - (uiMergeCand / MMVD_MAX_REFINE_NUM)* MMVD_MAX_REFINE_NUM >= (MMVD_MAX_REFINE_NUM >> MMVD_SIZE_SHIFT)))
      {
 	     continue;
@@ -4705,14 +4777,34 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       {
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
         int uiMergeCandTemp = affMmvdLUT[uiMergeCand];
-        int baseIdx = (int)uiMergeCandTemp / AF_MMVD_MAX_REFINE_NUM;
-        int stepIdx = (int)uiMergeCandTemp - baseIdx * AF_MMVD_MAX_REFINE_NUM;
+        int baseIdx = 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+                      !pu.cs->sps->getUseTMMMVD() ?
+                      (int)uiMergeCandTemp / ECM3_AF_MMVD_MAX_REFINE_NUM :
+#endif
+                      (int)uiMergeCandTemp / AF_MMVD_MAX_REFINE_NUM;
+        int stepIdx = 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+                      !pu.cs->sps->getUseTMMMVD() ?
+                      (int)uiMergeCandTemp - baseIdx * ECM3_AF_MMVD_MAX_REFINE_NUM :
+#endif
+                      (int)uiMergeCandTemp - baseIdx * AF_MMVD_MAX_REFINE_NUM;
 #else
         int baseIdx = (int)uiMergeCand / AF_MMVD_MAX_REFINE_NUM;
         int stepIdx = (int)uiMergeCand - baseIdx * AF_MMVD_MAX_REFINE_NUM;
 #endif
-        int dirIdx  = stepIdx % AF_MMVD_OFFSET_DIR;
-            stepIdx = stepIdx / AF_MMVD_OFFSET_DIR;
+        int dirIdx  = 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+                      !pu.cs->sps->getUseTMMMVD() ?
+                      stepIdx % ECM3_AF_MMVD_OFFSET_DIR :
+#endif
+                      stepIdx % AF_MMVD_OFFSET_DIR;
+            stepIdx = 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+                      !pu.cs->sps->getUseTMMMVD() ?
+                      stepIdx / ECM3_AF_MMVD_OFFSET_DIR :
+#endif
+                      stepIdx / AF_MMVD_OFFSET_DIR;
 
         cu.affine           = true;
         cu.imv              = IMV_OFF;
@@ -5294,7 +5386,11 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct
     geoMMVDIdxCost[idx] = (double)fractBits * sqrtLambdaFracBits;
   }
 #if TM_MRG
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  for (int idx = 0; idx < 2 && sps.getUseGPMTMMode(); idx++)
+#else
   for (int idx = 0; idx < 2 && sps.getUseDMVDMode(); idx++)
+#endif
   {
     uint64_t fracBits = m_CABACEstimator->geo_tmFlag_est(ctxStart, idx);
     geoTMFlagCost[idx] = (double)fracBits * sqrtLambdaFracBits;
@@ -5749,10 +5845,18 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct
                    geoModeCost[splitDir];
 #endif
 #if TM_MRG
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+        if (sps.getUseGPMTMMode() 
+#if JVET_Y0065_GPM_INTRA
+          && mergeCand0 < GEO_MAX_NUM_UNI_CANDS && mergeCand1 < GEO_MAX_NUM_UNI_CANDS
+#endif
+          )
+#else
 #if JVET_Y0065_GPM_INTRA
         if (sps.getUseDMVDMode() && mergeCand0 < GEO_MAX_NUM_UNI_CANDS && mergeCand1 < GEO_MAX_NUM_UNI_CANDS)
 #else
         if (sps.getUseDMVDMode())
+#endif
 #endif
         {
           tempCost += geoTMFlagCost[0];
@@ -5879,10 +5983,18 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct
                         + geoMergeIdxCost[mergeCand0] + (m_fastGpmMmvdSearch ? geoMergeIdxCost[mergeCand1 > mergeCand0 ? (mergeCand1 - 1) : mergeCand1] : geoMergeIdxCost[mergeCand1]) + geoMMVDFlagCost[mmvdFlag0] + geoMMVDFlagCost[mmvdFlag1];
 #endif
 #if TM_MRG
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+      if (sps.getUseGPMTMMode()
+#if JVET_Y0065_GPM_INTRA
+        && !isIntra0 && !isIntra1
+#endif
+        )
+#else
 #if JVET_Y0065_GPM_INTRA
       if (sps.getUseDMVDMode() && !isIntra0 && !isIntra1)
 #else
       if (sps.getUseDMVDMode())
+#endif
 #endif
       {
         updateCost += geoTMFlagCost[0];
@@ -5983,10 +6095,18 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct
                       + geoMergeIdxCost[mergeCand0] + (m_fastGpmMmvdSearch ? geoMergeIdxCost[mergeCand1 > mergeCand0 ? (mergeCand1 - 1) : mergeCand1] : geoMergeIdxCost[mergeCand1]) + geoMMVDFlagCost[mmvdFlag0] + geoMMVDFlagCost[mmvdFlag1];
 #endif
 #if TM_MRG
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    if (sps.getUseGPMTMMode()
+#if JVET_Y0065_GPM_INTRA
+      && !isIntra0 && !isIntra1
+#endif
+      )
+#else
 #if JVET_Y0065_GPM_INTRA
     if (sps.getUseDMVDMode() && !isIntra0 && !isIntra1)
 #else
     if (sps.getUseDMVDMode())
+#endif
 #endif
     {
       updateCost += geoTMFlagCost[0];
@@ -6648,10 +6768,18 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct
                    + geoModeCost[splitDir];
 #endif
 #if TM_MRG
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+          if (sps.getUseGPMTMMode() 
+#if JVET_Y0065_GPM_INTRA
+            && mergeCand0 < GEO_MAX_NUM_UNI_CANDS && mergeCand1 < GEO_MAX_NUM_UNI_CANDS
+#endif
+            )
+#else
 #if JVET_Y0065_GPM_INTRA
           if (sps.getUseDMVDMode() && mergeCand0 < GEO_MAX_NUM_UNI_CANDS && mergeCand1 < GEO_MAX_NUM_UNI_CANDS)
 #else
           if (sps.getUseDMVDMode())
+#endif
 #endif
           {
             tempCost += geoTMFlagCost[0];
@@ -6667,10 +6795,18 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct
     uint8_t maxNumTmMrgCand = maxNumMergeCandidates;
     PelUnitBuf geoTmBuffer[GEO_TM_MAX_NUM_CANDS];
     PelUnitBuf geoTmTempBuf[GEO_TM_MAX_NUM_CANDS];
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    if (sps.getUseGPMTMMode()
+#if JVET_Y0065_GPM_INTRA
+      && !bUseOnlyOneVector
+#endif
+      )
+#else
 #if JVET_Y0065_GPM_INTRA
     if (sps.getUseDMVDMode() && !bUseOnlyOneVector)
 #else
     if (sps.getUseDMVDMode())
+#endif
 #endif
     {
       for (int i = GEO_TM_SHAPE_AL; i < GEO_NUM_TM_MV_CAND; i++)
@@ -7047,7 +7183,11 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct
         }
 #endif
 #if TM_MRG
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+        if (sps.getUseGPMTMMode())
+#else
         if (sps.getUseDMVDMode())
+#endif
         {
 #if JVET_Y0065_GPM_INTRA
           if (!mmvdFlag0 && !mmvdFlag1 && !isIntra0 && !isIntra1)
@@ -7212,7 +7352,11 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct
       }
 #endif
 #if TM_MRG
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+      if (sps.getUseGPMTMMode())
+#else
       if (sps.getUseDMVDMode())
+#endif
       {
 #if JVET_Y0065_GPM_INTRA
         if (!mmvdFlag0 && !mmvdFlag1 && !isIntra0 && !isIntra1)
@@ -8660,14 +8804,22 @@ void EncCu::xCheckSATDCostMmvdMerge(CodingStructure *&tempCS, CodingUnit &cu, Pr
       && std::min(tempCS->area.lwidth(), tempCS->area.lheight()) >= MULTI_HYP_PRED_RESTRICT_MIN_WH);
 #endif
 
+  const int tempNum =
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+                      !pu.cs->sps->getUseTMMMVD() ?
+                      ((mergeCtx.numValidMergeCand > 1) ? VVC_MMVD_ADD_NUM : (VVC_MMVD_ADD_NUM >> 1)) :
+#endif
 #if JVET_AA0093_ENHANCED_MMVD_EXTENSION
-  const int tempNum =  (std::min<int>(MMVD_BASE_MV_NUM, mergeCtx.numValidMergeCand) * MMVD_MAX_REFINE_NUM);
+                      (std::min<int>(MMVD_BASE_MV_NUM, mergeCtx.numValidMergeCand) * MMVD_MAX_REFINE_NUM);
 #else
-  const int tempNum = (mergeCtx.numValidMergeCand > 1) ? MMVD_ADD_NUM : MMVD_ADD_NUM >> 1;
+                      (mergeCtx.numValidMergeCand > 1) ? MMVD_ADD_NUM : MMVD_ADD_NUM >> 1;
 #endif
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
   for (int mmvdMergeCandtemp = 0; mmvdMergeCandtemp < tempNum; mmvdMergeCandtemp++)
   {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+    if(pu.cs->sps->getUseTMMMVD())
+#endif
 #if JVET_AA0093_ENHANCED_MMVD_EXTENSION
     if(mmvdMergeCandtemp - (mmvdMergeCandtemp/MMVD_MAX_REFINE_NUM )* MMVD_MAX_REFINE_NUM  >= ((MMVD_MAX_REFINE_NUM >> MMVD_SIZE_SHIFT )/MMVD_BI_DIR))
 #else
@@ -8681,14 +8833,28 @@ void EncCu::xCheckSATDCostMmvdMerge(CodingStructure *&tempCS, CodingUnit &cu, Pr
   for (int mmvdMergeCand = 0; mmvdMergeCand < tempNum; mmvdMergeCand++)
   {
 #endif
-    int baseIdx = mmvdMergeCand / MMVD_MAX_REFINE_NUM;
+    int baseIdx = 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+                 !pu.cs->sps->getUseTMMMVD() ?
+                 mmvdMergeCand / VVC_MMVD_MAX_REFINE_NUM :
+#endif
+                  mmvdMergeCand / MMVD_MAX_REFINE_NUM;
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
-    int refineStep = (mmvdMergeCand - (baseIdx * MMVD_MAX_REFINE_NUM )) / MMVD_MAX_DIR ;
+    int refineStep = 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+                     !pu.cs->sps->getUseTMMMVD() ?
+                     (mmvdMergeCand - (baseIdx * VVC_MMVD_MAX_REFINE_NUM )) / VVC_MMVD_MAX_DIR :
+#endif
+                     (mmvdMergeCand - (baseIdx * MMVD_MAX_REFINE_NUM )) / MMVD_MAX_DIR ;
 #else
     int refineStep = (mmvdMergeCand - (baseIdx * MMVD_MAX_REFINE_NUM)) / 4;
 #endif
-#if  !JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
-    if( refineStep >= m_pcEncCfg->getMmvdDisNum() )
+#if  !JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED)
+    if( refineStep >= m_pcEncCfg->getMmvdDisNum() 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+     && !pu.cs->sps->getUseTMMMVD()
+#endif
+      )
     {
       continue;
     }
@@ -8702,7 +8868,11 @@ void EncCu::xCheckSATDCostMmvdMerge(CodingStructure *&tempCS, CodingUnit &cu, Pr
     pu.mvRefine = true;
     distParam.cur = singleMergeTempBuffer->Y();
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
-    pu.mmvdEncOptMode = (refineStep > 1 ? 2 : 1);
+    pu.mmvdEncOptMode = (refineStep > 1
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+                                    + (pu.cs->sps->getUseTMMMVD() ? 0 : 1)
+#endif
+                                    ? 2 : 1);
 #else
     pu.mmvdEncOptMode = (refineStep > 2 ? 2 : 1);
 #endif
@@ -8979,10 +9149,21 @@ void EncCu::xCheckSATDCostAffineMmvdMerge(       CodingStructure*& tempCS,
 
   int baseIdxToMergeIdxOffset = (int)PU::getMergeIdxFromAfMmvdBaseIdx(affineMergeCtx, 0);
   int baseCount               = std::min<int>((int)AF_MMVD_BASE_NUM, affineMergeCtx.numValidMergeCand - baseIdxToMergeIdxOffset);
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_AA0093_ENHANCED_MMVD_EXTENSION
+  if (!tempCS->sps->getUseTMMMVD())
+  {
+    baseCount = std::min<int>((int)ECM3_AF_MMVD_BASE_NUM, affineMergeCtx.numValidMergeCand - baseIdxToMergeIdxOffset);
+  }
+#endif
 #if JVET_AA0093_ENHANCED_MMVD_EXTENSION
   baseCount = std::min<int>(baseCount, numBaseAffine);
 #endif
-  int afMmvdCandCount         = baseCount * AF_MMVD_MAX_REFINE_NUM;
+  int afMmvdCandCount         = 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+                                !pu.cs->sps->getUseTMMMVD() ?
+                                baseCount * ECM3_AF_MMVD_MAX_REFINE_NUM :
+#endif
+                                baseCount * AF_MMVD_MAX_REFINE_NUM;
   if (baseCount < 1)
   {
     return;
@@ -8999,6 +9180,9 @@ void EncCu::xCheckSATDCostAffineMmvdMerge(       CodingStructure*& tempCS,
   for (uint32_t uiMergeCandTemp = 0; uiMergeCandTemp < afMmvdCandCount; uiMergeCandTemp++)
   {
     uint32_t uiMergeCand = affMmvdLUT[uiMergeCandTemp];
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    if(pu.cs->sps->getUseTMMMVD())
+#endif
 #if JVET_AA0093_ENHANCED_MMVD_EXTENSION
     if(uiMergeCandTemp - (uiMergeCandTemp/AF_MMVD_MAX_REFINE_NUM )* AF_MMVD_MAX_REFINE_NUM  >= ((AF_MMVD_MAX_REFINE_NUM >> AFFINE_MMVD_SIZE_SHIFT ) / AFFINE_BI_DIR))
 #else
@@ -9011,10 +9195,30 @@ void EncCu::xCheckSATDCostAffineMmvdMerge(       CodingStructure*& tempCS,
   for (uint32_t uiMergeCand = 0; uiMergeCand < afMmvdCandCount; uiMergeCand++)
   {
 #endif
-    int baseIdx = (int)uiMergeCand / AF_MMVD_MAX_REFINE_NUM;
-    int stepIdx = (int)uiMergeCand - baseIdx * AF_MMVD_MAX_REFINE_NUM;
-    int dirIdx  = stepIdx % AF_MMVD_OFFSET_DIR;
-        stepIdx = stepIdx / AF_MMVD_OFFSET_DIR;
+    int baseIdx = 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+                  !pu.cs->sps->getUseTMMMVD() ?
+                  (int)uiMergeCand / ECM3_AF_MMVD_MAX_REFINE_NUM :
+#endif
+                  (int)uiMergeCand / AF_MMVD_MAX_REFINE_NUM;
+    int stepIdx = 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+                  !pu.cs->sps->getUseTMMMVD() ?
+                  (int)uiMergeCand - baseIdx * ECM3_AF_MMVD_MAX_REFINE_NUM :
+#endif
+                  (int)uiMergeCand - baseIdx * AF_MMVD_MAX_REFINE_NUM;
+    int dirIdx  = 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+                  !pu.cs->sps->getUseTMMMVD() ?
+                  stepIdx % ECM3_AF_MMVD_OFFSET_DIR :
+#endif
+                  stepIdx % AF_MMVD_OFFSET_DIR;
+        stepIdx = 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+                  !pu.cs->sps->getUseTMMMVD() ?
+                  stepIdx / ECM3_AF_MMVD_OFFSET_DIR :
+#endif
+                  stepIdx / AF_MMVD_OFFSET_DIR;
 
     // Pass Affine MMVD parameters from candidate to PU
     {
@@ -9037,7 +9241,11 @@ void EncCu::xCheckSATDCostAffineMmvdMerge(       CodingStructure*& tempCS,
       pu.cu->LICFlag    = affineMergeCtx.LICFlags          [pu.mergeIdx];
 #endif
       pu.cu->BcwIdx     = affineMergeCtx.BcwIdx            [pu.mergeIdx];
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+      CHECK(pu.afMmvdDir >= (pu.cs->sps->getUseTMMMVD() ? AF_MMVD_OFFSET_DIR : ECM3_AF_MMVD_OFFSET_DIR) || pu.afMmvdStep >= (pu.cs->sps->getUseTMMMVD() ? AF_MMVD_STEP_NUM : ECM3_AF_MMVD_STEP_NUM), "Affine MMVD dir or Affine MMVD step is out of range ");
+#else
       CHECK(pu.afMmvdDir >= AF_MMVD_OFFSET_DIR || pu.afMmvdStep >= AF_MMVD_STEP_NUM, "Affine MMVD dir or Affine MMVD step is out of range ");
+#endif
       CHECK(pu.mergeType != MRG_TYPE_DEFAULT_N, "Affine MMVD must have non-SbTMVP base!");
     }
 
@@ -10387,25 +10595,25 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
 #if JVET_Z0084_IBC_TM && IBC_TM_MRG
     if (pu.cs->sps->getUseDMVDMode() == true)
     {
-    pu.tmMergeFlag = true;
+      pu.tmMergeFlag = true;
 #if JVET_AA0070_RRIBC
-    pu.mergeFlag = true;
-    PU::getIBCMergeCandidates(pu, mergeCtxTm);
-    pu.mergeFlag = false;
+      pu.mergeFlag = true;
+      PU::getIBCMergeCandidates(pu, mergeCtxTm);
+      pu.mergeFlag = false;
 #else
-    PU::getIBCMergeCandidates(pu, mergeCtxTm);
+      PU::getIBCMergeCandidates(pu, mergeCtxTm);
 #endif
 #if JVET_Y0058_IBC_LIST_MODIFY && JVET_W0090_ARMC_TM
-    if (pu.cs->sps->getUseAML())
-    {
+      if (pu.cs->sps->getUseAML())
+      {
 #if JVET_Z0075_IBC_HMVP_ENLARGE
-      m_pcInterSearch->adjustIBCMergeCandidates(pu, mergeCtxTm, 0, IBC_MRG_MAX_NUM_CANDS_MEM);
+        m_pcInterSearch->adjustIBCMergeCandidates(pu, mergeCtxTm, 0, IBC_MRG_MAX_NUM_CANDS_MEM);
 #else
-      m_pcInterSearch->adjustIBCMergeCandidates(pu, mergeCtxTm);
+        m_pcInterSearch->adjustIBCMergeCandidates(pu, mergeCtxTm);
 #endif
-    }
+      }
 #endif
-    pu.tmMergeFlag = false;
+      pu.tmMergeFlag = false;
     }
     else
     {
@@ -13039,6 +13247,7 @@ void EncCu::xCheckSATDCostBMMerge(CodingStructure*& tempCS,
 
   const double sqrtLambdaForFirstPassIntra = m_pcRdCost->getMotionLambda() * FRAC_BITS_SCALE;
   int insertPos = -1;
+/* // remove below commented code since it has been refactored" and remove it when the SW is going to be merged
 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
   uint32_t maxNumCand = armcRefinedMotion ? mrgCtx.numValidMergeCand : ((pu.cs->sps->getUseAML()) ? min(mrgCtx.numValidMergeCand, mrgCtx.numCandToTestEnc) : mrgCtx.numCandToTestEnc);
@@ -13052,6 +13261,22 @@ void EncCu::xCheckSATDCostBMMerge(CodingStructure*& tempCS,
   const uint32_t maxNumCand = mrgCtx.numCandToTestEnc;
 #endif
 #endif
+*/
+  uint32_t maxNumCand = mrgCtx.numCandToTestEnc;
+#if (JVET_Y0134_TMVP_NAMVP_CAND_REORDERING || JVET_AA0093_REFINED_MOTION_FOR_ARMC) && JVET_W0090_ARMC_TM
+  if (pu.cs->sps->getUseAML()
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING
+    && pu.cs->sps->getUseTmvpNmvpReordering()
+#endif
+    )
+  {
+    maxNumCand = min(mrgCtx.numValidMergeCand, mrgCtx.numCandToTestEnc);
+  }
+#if JVET_AA0093_REFINED_MOTION_FOR_ARMC
+  maxNumCand = armcRefinedMotion ? mrgCtx.numValidMergeCand : maxNumCand;
+#endif
+#endif
+
   bool subPuRefine[2] = { false, false };
   Mv   finalMvDir[2];
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index cf39a5696ddf259adae2c4da6e8e17736d751031..55cfebe1c5d87f6108b61af80eaa5ac25c2b52e4 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -1582,6 +1582,27 @@ void EncLib::xInitSPS( SPS& sps )
 #if TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM || MULTI_PASS_DMVR
   sps.setUseDMVDMode           ( m_DMVDMode );
 #endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  sps.setTMToolsEnableFlag     ( m_tmToolsEnableFlag );
+#if TM_AMVP
+  sps.setUseTMAmvpMode         ( m_tmAmvpMode );
+#endif
+#if TM_MRG
+  sps.setUseTMMrgMode          ( m_tmMrgMode );
+#endif
+#if JVET_W0097_GPM_MMVD_TM && TM_MRG
+  sps.setUseGPMTMMode          ( m_tmGPMMode );
+#endif
+#if JVET_Z0061_TM_OBMC && ENABLE_OBMC
+  sps.setUseOBMCTMMode         ( m_tmOBMCMode );
+#endif
+#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+  sps.setUseTmvpNmvpReordering ( m_useTmvpNmvpReorder );
+#endif
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  sps.setUseTMMMVD             ( m_useTMMMVD );
+#endif
+#endif
 #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
   sps.setUseAltGPMSplitModeCode( m_altGPMSplitModeCode );
 #endif
@@ -1627,6 +1648,10 @@ void EncLib::xInitSPS( SPS& sps )
 #if JVET_X0141_CIIP_TIMD_TM && TM_MRG
   if(sps.getUseCiip())
   {
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+   if(m_tmCIIPMode == 2)
+   {
+#endif
    if(getIntraPeriod() < 0)
    {
       sps.setUseCiipTmMrg (false);
@@ -1635,6 +1660,13 @@ void EncLib::xInitSPS( SPS& sps )
    {
       sps.setUseCiipTmMrg (true);
    }
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+   }
+   else
+   {
+      sps.setUseCiipTmMrg  (m_tmCIIPMode == 1);
+   }
+#endif
   }
 #endif
   sps.setUseGeo                ( m_Geo );
diff --git a/source/Lib/EncoderLib/EncModeCtrl.cpp b/source/Lib/EncoderLib/EncModeCtrl.cpp
index 462e57b11fb4670fa64c838285e2d79554a60dc8..1f688924db4370b684cb94bcd3c211c61fa99298 100644
--- a/source/Lib/EncoderLib/EncModeCtrl.cpp
+++ b/source/Lib/EncoderLib/EncModeCtrl.cpp
@@ -1557,7 +1557,11 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru
           m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_GEO, ETO_STANDARD, qp } );
         }
 #if TM_MRG && !MERGE_ENC_OPT
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+        if (cs.sps->getUseTMMrgMode())
+#else
         if (cs.sps->getUseDMVDMode())
+#endif
         {
           m_ComprCUCtxList.back().testModes.push_back({ ETM_MERGE_TM,     ETO_STANDARD, qp });
         }
@@ -1589,7 +1593,11 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru
           m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_GEO, ETO_STANDARD, qp } );
         }
 #if TM_MRG && !MERGE_ENC_OPT
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+        if (cs.sps->getUseTMMrgMode())
+#else
         if (cs.sps->getUseDMVDMode())
+#endif
         {
           m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_TM,     ETO_STANDARD, qp } );
         }
diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp
index f30b307361332137be8e94962346c41b101758df..9a542c4d6674c719a409d7a4438cbd675b3c6f57 100644
--- a/source/Lib/EncoderLib/InterSearch.cpp
+++ b/source/Lib/EncoderLib/InterSearch.cpp
@@ -3202,7 +3202,7 @@ bool InterSearch::predInterHashSearch(CodingUnit& cu, Partitioner& partitioner,
     pu.mvpIdx[bestRefPicList] = bestMVPIndex;
 
 #if TM_AMVP
-#if JVET_Y0128_NON_CTC
+#if JVET_Y0128_NON_CTC || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_AMVP)
     pu.mvpNum[bestRefPicList] = PU::checkTmEnableCondition(pu.cs->sps, pu.cs->pps, pu.cu->slice->getRefPic(bestRefPicList, bestRefIndex)) ? 1 : 2;
 #else
     pu.mvpNum[bestRefPicList] = 1;
@@ -3965,7 +3965,11 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
 #if TM_AMVP
           unsigned amvpNumCandCur = aacAMVPInfo[curRefList][refIdxCur].numCand;
           unsigned amvpNumCandTar = aacAMVPInfo[tarRefList][refIdxTar].numCand;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+          if (!pu.cs->sps->getUseTMAmvpMode())
+#else
           if (!pu.cs->sps->getUseDMVDMode())
+#endif
           {
             amvpNumCandCur = AMVP_MAX_NUM_CANDS;
             amvpNumCandTar = AMVP_MAX_NUM_CANDS;
@@ -4510,6 +4514,10 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
     {
 #if !TM_AMVP
       m_storeBeforeLIC = true;
+#else
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_AMVP
+      m_storeBeforeLIC = pu.cs->sps->getUseTMAmvpMode() ? false : true;
+#endif
 #endif
       m_predictionBeforeLIC = m_tmpStorageLCU.getBuf(UnitAreaRelative(*pu.cu, pu));
     }
@@ -4521,15 +4529,19 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
       PU::spanMotionInfo( *cu.firstPU, MergeCtx(), mvBufEncAmBDMVR_L0, mvBufEncAmBDMVR_L1, getBdofSubPuMvOffset() );
     }
 #endif
-#if INTER_LIC && !TM_AMVP
+#if INTER_LIC && (!TM_AMVP || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_AMVP))
     m_storeBeforeLIC = false;
 #endif
     puIdx++;
   }
 
 #if INTER_LIC
-#if !TM_AMVP // This LIC optimization must be off; otherwise, enc/dec mismatching will result. Because the cost metrics (MRSAD or SAD) of TM mode is adaptive to LIC flag, refined MVs would change when LIC flag is 1 or 0.
-  if (cu.LICFlag && pu.interDir != 10) // xCheckRDCostInterIMV initializes pu.interDir by using 10. When checkAffine and checkNonAffine are both false, pu.interDir remains 10 which should be avoided
+#if !TM_AMVP || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_AMVP) // This LIC optimization must be off; otherwise, enc/dec mismatching will result. Because the cost metrics (MRSAD or SAD) of TM mode is adaptive to LIC flag, refined MVs would change when LIC flag is 1 or 0.
+  if (cu.LICFlag && pu.interDir != 10
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_AMVP
+    && !pu.cs->sps->getUseTMAmvpMode()
+#endif
+    ) // xCheckRDCostInterIMV initializes pu.interDir by using 10. When checkAffine and checkNonAffine are both false, pu.interDir remains 10 which should be avoided
   {
     CHECK(pu.interDir != 1 && pu.interDir != 2, "Invalid InterDir for LIC");
 
@@ -5540,13 +5552,20 @@ void InterSearch::xEstimateMvPredAMVP( PredictionUnit& pu, PelUnitBuf& origBuf,
 #endif
       pcAMVPInfo->mvCand[0] = mvFieldAmListCommon[mvFieldAmvpIdx0].mv;
       pcAMVPInfo->numCand = 1;
-#if !TM_AMVP || JVET_Y0128_NON_CTC || JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE
+#if !TM_AMVP || JVET_Y0128_NON_CTC || JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE || JVET_AA0132_CONFIGURABLE_TM_TOOLS
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && (TM_AMVP && !JVET_Y0128_NON_CTC && !JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE)
+      if(!pu.cu->cs->sps->getUseTMAmvpMode())
+      {
+#endif
       const int mvFieldAmvpIdx1 = mvFieldAmvpIdx0 + 1;
       if (mvFieldAmListCommon[mvFieldAmvpIdx1].refIdx >= 0)
       {
         pcAMVPInfo->mvCand[1] = mvFieldAmListCommon[mvFieldAmvpIdx1].mv;
         pcAMVPInfo->numCand = 2;
       }
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && (TM_AMVP && !JVET_Y0128_NON_CTC && !JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE)
+      }
+#endif
 #endif
 #if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE
       const int mvFieldAmvpIdx2 = mvFieldAmvpIdx0 + 2;
@@ -11437,7 +11456,11 @@ void InterSearch::symmvdCheckBestMvp(
 #if TM_AMVP
   unsigned amvpNumCandCur = amvpCur.numCand;
   unsigned amvpNumCandTar = amvpTar.numCand;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  if (!pu.cs->sps->getUseTMAmvpMode())
+#else
   if (!pu.cs->sps->getUseDMVDMode())
+#endif
   {
     amvpNumCandCur = AMVP_MAX_NUM_CANDS;
     amvpNumCandTar = AMVP_MAX_NUM_CANDS;
diff --git a/source/Lib/EncoderLib/InterSearch.h b/source/Lib/EncoderLib/InterSearch.h
index 6340850c4b848acaf70331d70443ec58dca71abe..59e5d4f7cbb32300f5ddbdfe2ea6fd3cf28b53ce 100644
--- a/source/Lib/EncoderLib/InterSearch.h
+++ b/source/Lib/EncoderLib/InterSearch.h
@@ -205,6 +205,9 @@ struct ModeInfo
 #if AFFINE_MMVD
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
     mergeCand = pu.afMmvdFlag ?  pu.afMmvdMergeIdx : pu.mergeIdx;
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    mergeCand = !pu.cs->sps->getUseTMMMVD() && pu.afMmvdFlag ? pu.afMmvdBaseIdx * ECM3_AF_MMVD_MAX_REFINE_NUM + pu.afMmvdStep * ECM3_AF_MMVD_OFFSET_DIR + pu.afMmvdDir : mergeCand;
+#endif
 #else
     mergeCand = pu.afMmvdFlag ? pu.afMmvdBaseIdx * AF_MMVD_MAX_REFINE_NUM + pu.afMmvdStep * AF_MMVD_OFFSET_DIR + pu.afMmvdDir : pu.mergeIdx;
 #endif
diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp
index 9da96f496113ef5f5d948d83f6d52226b6867947..6f5d798b93e83925eff1a4dea3f2b6752b564d91 100644
--- a/source/Lib/EncoderLib/VLCWriter.cpp
+++ b/source/Lib/EncoderLib/VLCWriter.cpp
@@ -1340,6 +1340,9 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
     }
   }
 
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  WRITE_FLAG(pcSPS->getTMToolsEnableFlag() ? 1 : 0, "sps_tm_tools_enabled_flag");
+#endif
 #if INTER_LIC
   WRITE_FLAG(pcSPS->getLicEnabledFlag() ? 1 : 0, "sps_lic_enabled_flag");
 #endif
@@ -1356,8 +1359,21 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
   WRITE_FLAG( pcSPS->getAMVREnabledFlag() ? 1 : 0,                                   "sps_amvr_enabled_flag" );
 
 #if JVET_W0090_ARMC_TM
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  if(pcSPS->getTMToolsEnableFlag())
+#endif
   WRITE_FLAG( pcSPS->getUseAML() ? 1 : 0,                                             "sps_aml_enabled_flag" );
 #endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM
+  if (pcSPS->getUseAML())
+  {
+    WRITE_FLAG( pcSPS->getUseTmvpNmvpReordering() ? 1 : 0,                            "sps_aml_tmvp_nmvp_enabled_flag" );
+  }
+  else
+  {
+    CHECK(pcSPS->getUseTmvpNmvpReordering(), "Reordering for TMVP and non-adjacent MVP cannot be used when ARMC is disabled");
+  }
+#endif
 #if JVET_AA0093_REFINED_MOTION_FOR_ARMC
   if (pcSPS->getUseAML())
   {
@@ -1390,10 +1406,13 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
         }
       }
       WRITE_CODE(pcSPS->getLambdaVal(i), pcSPS->getMaxbitsLambdaVal(), "Lambda");
-      }
     }
+  }
 #endif
 #if JVET_Z0054_BLK_REF_PIC_REORDER
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  if (pcSPS->getTMToolsEnableFlag())
+#endif
   WRITE_FLAG( pcSPS->getUseARL() ? 1 : 0,                                             "sps_arl_enabled_flag" );
 #endif
   WRITE_FLAG( pcSPS->getBDOFEnabledFlag() ? 1 : 0,                                   "sps_bdof_enabled_flag" );
@@ -1413,6 +1432,9 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
     WRITE_FLAG(pcSPS->getFpelMmvdEnabledFlag() ? 1 : 0,                               "sps_mmvd_fullpel_only_flag");
   }
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  if (pcSPS->getTMToolsEnableFlag())
+#endif
   WRITE_FLAG(pcSPS->getUseMVSD() ? 1 : 0,                                                      "sps_mvsd_enabled_flag");
 #endif
   WRITE_UVLC(MRG_MAX_NUM_CANDS - pcSPS->getMaxNumMergeCand(), "six_minus_max_num_merge_cand");
@@ -1420,9 +1442,22 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
 #if TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM || MULTI_PASS_DMVR
   WRITE_FLAG( pcSPS->getUseDMVDMode() ? 1 : 0,                                                 "sps_dmvd_enabled_flag" );
 #endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  if (pcSPS->getTMToolsEnableFlag())
+  {
+#endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_AMVP
+  WRITE_FLAG( pcSPS->getUseTMAmvpMode() ? 1 : 0,                                               "sps_tm_amvp_enabled_flag" );
+#endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_MRG
+  WRITE_FLAG(pcSPS->getUseTMMrgMode() ? 1 : 0,                                                 "sps_tm_mrg_enabled_flag");
+#endif
 #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
   WRITE_FLAG( pcSPS->getUseAltGPMSplitModeCode() ? 1 : 0,                                      "sps_alt_gpm_code_enabled_flag" );
 #endif
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+  }
+#endif
 #if JVET_X0049_ADAPT_DMVR
   WRITE_UVLC(BM_MRG_MAX_NUM_CANDS - pcSPS->getMaxNumBMMergeCand(), "six_minus_max_num_bm_merge_cand");
 #endif
@@ -1444,16 +1479,33 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
       WRITE_FLAG(pcSPS->getProfControlPresentFlag() ? 1 : 0,                                   "sps_prof_pic_present_flag" );
     }
   }
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  if (pcSPS->getUseMMVD() || pcSPS->getUseAffineMmvdMode())
+  {
+    if (pcSPS->getTMToolsEnableFlag())
+    {
+      WRITE_FLAG(pcSPS->getUseTMMMVD() ? 1 : 0, "sps_tm_mmvd_enabled_flag");
+    }
+  }
+  else
+  {
+    CHECK(pcSPS->getUseTMMMVD(), "TM-MMVD cannot be used when neither MMVD not AffineMMVD is enabled");
+  }
+#endif
 
   WRITE_FLAG(pcSPS->getUseBcw() ? 1 : 0, "sps_bcw_enabled_flag");
 
   WRITE_FLAG( pcSPS->getUseCiip() ? 1 : 0,                                                  "sps_ciip_enabled_flag" );
-  #if JVET_X0141_CIIP_TIMD_TM && TM_MRG
-  if (pcSPS->getUseCiip())
+#if JVET_X0141_CIIP_TIMD_TM && TM_MRG
+  if (pcSPS->getUseCiip()
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
+    && pcSPS->getTMToolsEnableFlag()
+#endif
+    )
   {
     WRITE_FLAG(pcSPS->getUseCiipTmMrg() ? 1 : 0, "sps_ciip_tm_merge_enabled_flag");
   }
-  #endif
+#endif
   if (pcSPS->getMaxNumMergeCand() >= 2)
   {
     WRITE_FLAG(pcSPS->getUseGeo() ? 1 : 0, "sps_gpm_enabled_flag");
@@ -1468,7 +1520,19 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
         WRITE_UVLC(pcSPS->getMaxNumMergeCand() - pcSPS->getMaxNumGeoCand(),
                    "max_num_merge_cand_minus_max_num_gpm_cand");
       }
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_W0097_GPM_MMVD_TM && TM_MRG
+      if (pcSPS->getTMToolsEnableFlag())
+      {
+        WRITE_FLAG(pcSPS->getUseGPMTMMode() ? 1 : 0, "sps_gpm_tm_enabled_flag");
+      }
+#endif
+    }
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_W0097_GPM_MMVD_TM && TM_MRG
+    else
+    {
+      CHECK(pcSPS->getUseGPMTMMode(), "GPM-TM mode cannot be used when GPM is disabled");
     }
+#endif
   }
 #if MULTI_HYP_PRED
   WRITE_FLAG(pcSPS->getUseInterMultiHyp() ? 1 : 0, "inter_multi_hyp_enable_flag");
@@ -1568,6 +1632,19 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
 #endif
 #if ENABLE_OBMC
   WRITE_FLAG(pcSPS->getUseOBMC() ? 1 : 0, "sps_obmc_flag");
+#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Z0061_TM_OBMC
+  if (pcSPS->getUseOBMC())
+  {
+    if (pcSPS->getTMToolsEnableFlag())
+    {
+      WRITE_FLAG(pcSPS->getUseOBMCTMMode() ? 1 : 0, "sps_obmc_tm_flag");
+    }
+  }
+  else
+  {
+    CHECK(pcSPS->getUseOBMCTMMode(), "OBMC-TM mode cannot be used when OBMC is disabled");
+  }
+#endif
 #endif
 #if JVET_Z0135_TEMP_CABAC_WIN_WEIGHT
   WRITE_FLAG( pcSPS->getTempCabacInitMode() ? 1 : 0, "sps_cabac_temp_init_flag" );