diff --git a/src/coreclr/clrfeatures.cmake b/src/coreclr/clrfeatures.cmake
index 9eb037300cd4f1..3b4fb203ee2c51 100644
--- a/src/coreclr/clrfeatures.cmake
+++ b/src/coreclr/clrfeatures.cmake
@@ -1,8 +1,8 @@
-if (NOT CLR_CMAKE_TARGET_ARCH_WASM)
+if (NOT CLR_CMAKE_TARGET_ARCH_WASM AND NOT CLR_CMAKE_TARGET_IOS AND NOT CLR_CMAKE_TARGET_TVOS AND NOT CLR_CMAKE_TARGET_MACCATALYST)
   set(FEATURE_JIT 1)
 endif()
 
-if (CLR_CMAKE_TARGET_ARCH_WASM OR CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS)
+if (CLR_CMAKE_TARGET_ARCH_WASM OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS OR CLR_CMAKE_TARGET_MACCATALYST)
   set(FEATURE_STATICALLY_LINKED 1)
 endif()
 
diff --git a/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt b/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt
index 6c2e0a48b74af8..14058e40a68c8f 100644
--- a/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt
+++ b/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt
@@ -205,6 +205,9 @@ target_compile_definitions(coreclr_static PUBLIC CORECLR_EMBEDDED)
 
 if (CLR_CMAKE_HOST_ANDROID)
     target_link_libraries(coreclr PUBLIC log)
+endif()
+
+if (CLR_CMAKE_HOST_ANDROID OR CLR_CMAKE_HOST_IOS OR CLR_CMAKE_HOST_TVOS OR CLR_CMAKE_HOST_MACCATALYST)
     target_link_libraries(coreclr_static
         PUBLIC
         coreclrminipal_objects
diff --git a/src/coreclr/interpreter/compiler.cpp b/src/coreclr/interpreter/compiler.cpp
index 924953f8419da6..68212d7b5db008 100644
--- a/src/coreclr/interpreter/compiler.cpp
+++ b/src/coreclr/interpreter/compiler.cpp
@@ -2378,6 +2378,36 @@ bool InterpCompiler::EmitNamedIntrinsicCall(NamedIntrinsic ni, CORINFO_CLASS_HAN
             return true;
         }
 
+        case NI_System_Threading_Interlocked_Exchange:
+        {
+            CHECK_STACK(2);
+            InterpType retType = GetInterpType(sig.retType);
+
+            int32_t opcode;
+            switch (retType)
+            {
+                case InterpTypeI4:
+                    opcode = INTOP_EXCHANGE_I4;
+                    break;
+                case InterpTypeI8:
+                    opcode = INTOP_EXCHANGE_I8;
+                    break;
+                default:
+                    return false;
+            }
+
+            AddIns(opcode);
+            m_pStackPointer -= 2;
+
+            int32_t addrVar = m_pStackPointer[0].var;
+            int32_t valueVar = m_pStackPointer[1].var;
+
+            PushInterpType(retType, nullptr);
+            m_pLastNewIns->SetSVars2(addrVar, valueVar);
+            m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
+            return true;
+        }
+
         case NI_System_Runtime_CompilerServices_RuntimeHelpers_IsReferenceOrContainsReferences:
         {
             CORINFO_CLASS_HANDLE clsHnd = sig.sigInst.methInst[0];
diff --git a/src/coreclr/interpreter/intops.def b/src/coreclr/interpreter/intops.def
index 5850997ec29cc9..0f01ac456e00e4 100644
--- a/src/coreclr/interpreter/intops.def
+++ b/src/coreclr/interpreter/intops.def
@@ -414,6 +414,8 @@ OPDEF(INTOP_LOAD_FRAMEVAR, "load.framevar", 2, 1, 0, InterpOpNoArgs)
 // Intrinsics
 OPDEF(INTOP_COMPARE_EXCHANGE_I4, "compare.exchange.i4", 5, 1, 3, InterpOpNoArgs)
 OPDEF(INTOP_COMPARE_EXCHANGE_I8, "compare.exchange.i8", 5, 1, 3, InterpOpNoArgs)
+OPDEF(INTOP_EXCHANGE_I4, "exchange.i4", 4, 1, 2, InterpOpNoArgs)
+OPDEF(INTOP_EXCHANGE_I8, "exchange.i8", 4, 1, 2, InterpOpNoArgs)
 
 // All instructions after this point are IROPS, instructions that are not emitted/executed
 OPDEF(INTOP_NOP, "nop", 1, 0, 0, InterpOpNoArgs)
diff --git a/src/coreclr/interpreter/intrinsics.cpp b/src/coreclr/interpreter/intrinsics.cpp
index af57f45c414d4a..2d2ba35cccb772 100644
--- a/src/coreclr/interpreter/intrinsics.cpp
+++ b/src/coreclr/interpreter/intrinsics.cpp
@@ -104,6 +104,8 @@ NamedIntrinsic GetNamedIntrinsic(COMP_HANDLE compHnd, CORINFO_METHOD_HANDLE comp
         {
             if (!strcmp(methodName, "CompareExchange"))
                 return NI_System_Threading_Interlocked_CompareExchange;
+            else if (!strcmp(methodName, "Exchange"))
+                return NI_System_Threading_Interlocked_Exchange;
             else if (!strcmp(methodName, "MemoryBarrier"))
                 return NI_System_Threading_Interlocked_MemoryBarrier;
         }
diff --git a/src/coreclr/vm/eeconfig.cpp b/src/coreclr/vm/eeconfig.cpp
index 2b7c2c3bd71bfa..3747a07d3295f9 100644
--- a/src/coreclr/vm/eeconfig.cpp
+++ b/src/coreclr/vm/eeconfig.cpp
@@ -639,7 +639,7 @@ HRESULT EEConfig::sync()
 #if defined(FEATURE_INTERPRETER)
     if (fTieredCompilation)
     {
-        // Disable tiered compilation for interpreter testing. Tiered compilation and interpreter 
+        // Disable tiered compilation for interpreter testing. Tiered compilation and interpreter
         // do not work well together currently.
         LPWSTR pwzInterpreterMaybe;
         IfFailThrow(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_Interpreter, &pwzInterpreterMaybe));
diff --git a/src/coreclr/vm/interpexec.cpp b/src/coreclr/vm/interpexec.cpp
index 5c82f07e4ec820..68a805f05a12a8 100644
--- a/src/coreclr/vm/interpexec.cpp
+++ b/src/coreclr/vm/interpexec.cpp
@@ -646,6 +646,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
                 // Normal moves between vars
                 case INTOP_MOV_4: MOV(int32_t, int32_t); break;
                 case INTOP_MOV_8: MOV(int64_t, int64_t); break;
+#undef MOV
 
                 case INTOP_MOV_VT:
                     memmove(stack + ip[1], stack + ip[2], ip[3]);
@@ -1016,6 +1017,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
                 case INTOP_BRTRUE_I8:
                     BR_UNOP(int64_t, != 0);
                     break;
+#undef BR_UNOP
 
 #define BR_BINOP_COND(cond) \
     if (cond)               \
@@ -1226,6 +1228,8 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
                     BR_BINOP_COND(isunordered(d1, d2) || d1 < d2);
                     break;
                 }
+#undef BR_BINOP_COND
+#undef BR_BINOP
 
                 case INTOP_ADD_I4:
                     LOCAL_VAR(ip[1], int32_t) = LOCAL_VAR(ip[2], int32_t) + LOCAL_VAR(ip[3], int32_t);
@@ -1682,6 +1686,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
                 case INTOP_CLT_UN_R8:
                     CMP_BINOP_FP(double, <, 1);
                     break;
+#undef CMP_BINOP_FP
 
 #define LDIND(dtype, ftype)                                 \
     do {                                                    \
@@ -1715,6 +1720,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
                 case INTOP_LDIND_R8:
                     LDIND(double, double);
                     break;
+#undef LDIND
                 case INTOP_LDIND_VT:
                 {
                     char *src = LOCAL_VAR(ip[2], char*);
@@ -1757,6 +1763,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
                 case INTOP_STIND_R8:
                     STIND(double, double);
                     break;
+#undef STIND
                 case INTOP_STIND_O:
                 {
                     char *dst = LOCAL_VAR(ip[1], char*);
@@ -2349,6 +2356,7 @@ do {                                                                           \
                     LDELEM(double, double);
                     break;
                 }
+#undef LDELEM
                 case INTOP_LDELEM_REF:
                 {
                     BASEARRAYREF arrayRef = LOCAL_VAR(ip[2], BASEARRAYREF);
@@ -2435,6 +2443,7 @@ do {                                                                           \
                     STELEM(double, double);
                     break;
                 }
+#undef STELEM
                 case INTOP_STELEM_REF:
                 {
                     BASEARRAYREF arrayRef = LOCAL_VAR(ip[1], BASEARRAYREF);
@@ -2613,6 +2622,31 @@ do                                                                      \
                     COMPARE_EXCHANGE(int64_t);
                     break;
                 }
+#undef COMPARE_EXCHANGE
+
+#define EXCHANGE(type)                                                  \
+do                                                                      \
+{                                                                       \
+    type* dst = LOCAL_VAR(ip[2], type*);                                \
+    NULL_CHECK(dst);                                                    \
+    type newValue = LOCAL_VAR(ip[3], type);                             \
+    type old = InterlockedExchangeT(dst, newValue);                     \
+    LOCAL_VAR(ip[1], type) = old;                                       \
+    ip += 4;                                                            \
+} while (0)
+
+                case INTOP_EXCHANGE_I4:
+                {
+                    EXCHANGE(int32_t);
+                    break;
+                }
+
+                case INTOP_EXCHANGE_I8:
+                {
+                    EXCHANGE(int64_t);
+                    break;
+                }
+#undef EXCHANGE
 
                 case INTOP_CALL_FINALLY:
                 {
diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp
index ed52223644defc..8ce695d3d50410 100644
--- a/src/coreclr/vm/prestub.cpp
+++ b/src/coreclr/vm/prestub.cpp
@@ -2371,13 +2371,14 @@ PCODE MethodDesc::DoPrestub(MethodTable *pDispatchingMT, CallerGCMode callerGCMo
     pCode = DoBackpatch(pMT, pDispatchingMT, FALSE);
 
 Return:
-#if defined(FEATURE_INTERPRETER) && defined(FEATURE_JIT)
+// Interpreter-FIXME: Call stubs are not yet supported on WASM
+#if defined(FEATURE_INTERPRETER) && !defined(TARGET_WASM)
     InterpByteCodeStart *pInterpreterCode = GetInterpreterCode();
     if (pInterpreterCode != NULL)
     {
         CreateNativeToInterpreterCallStub(pInterpreterCode->Method);
     }
-#endif // FEATURE_INTERPRETER && FEATURE_JIT
+#endif // FEATURE_INTERPRETER && !TARGET_WASM
 
     RETURN pCode;
 }
diff --git a/src/mono/msbuild/apple/build/AppleBuild.targets b/src/mono/msbuild/apple/build/AppleBuild.targets
index 17dd0f47455fb9..08f925649eb13f 100644
--- a/src/mono/msbuild/apple/build/AppleBuild.targets
+++ b/src/mono/msbuild/apple/build/AppleBuild.targets
@@ -99,6 +99,11 @@
     
 
     
+
+    
+    
   
 
   
diff --git a/src/native/libs/System.Globalization.Native/CMakeLists.txt b/src/native/libs/System.Globalization.Native/CMakeLists.txt
index e3fa46ac9bc3ec..08c1fe46484e23 100644
--- a/src/native/libs/System.Globalization.Native/CMakeLists.txt
+++ b/src/native/libs/System.Globalization.Native/CMakeLists.txt
@@ -192,7 +192,7 @@ if(CLR_CMAKE_TARGET_UNIX OR CLR_CMAKE_TARGET_WASI)
 endif()
 
 install (TARGETS System.Globalization.Native-Static DESTINATION ${STATIC_LIB_DESTINATION} COMPONENT libs)
-if(CLR_CMAKE_HOST_ANDROID)
+if(CLR_CMAKE_HOST_ANDROID OR CLR_CMAKE_HOST_IOS OR CLR_CMAKE_HOST_TVOS OR CLR_CMAKE_HOST_MACCATALYST)
     install (TARGETS System.Globalization.Native-Static DESTINATION sharedFramework COMPONENT runtime)
 endif()
 
diff --git a/src/native/libs/System.IO.Compression.Native/CMakeLists.txt b/src/native/libs/System.IO.Compression.Native/CMakeLists.txt
index 0adecdad88b0ac..6d6345f51d2a8a 100644
--- a/src/native/libs/System.IO.Compression.Native/CMakeLists.txt
+++ b/src/native/libs/System.IO.Compression.Native/CMakeLists.txt
@@ -215,7 +215,7 @@ endif ()
 
 install (TARGETS System.IO.Compression.Native-Static DESTINATION ${STATIC_LIB_DESTINATION} COMPONENT libs)
 
-if(CLR_CMAKE_HOST_ANDROID)
+if(CLR_CMAKE_HOST_ANDROID OR CLR_CMAKE_HOST_IOS OR CLR_CMAKE_HOST_TVOS OR CLR_CMAKE_HOST_MACCATALYST)
     install (TARGETS System.IO.Compression.Native-Static DESTINATION sharedFramework COMPONENT runtime)
 
     foreach(BROTLI_LIB ${BROTLI_LIBRARIES})
diff --git a/src/native/libs/System.Native/CMakeLists.txt b/src/native/libs/System.Native/CMakeLists.txt
index 0819d01f59bdd2..78a0533148d4ca 100644
--- a/src/native/libs/System.Native/CMakeLists.txt
+++ b/src/native/libs/System.Native/CMakeLists.txt
@@ -148,6 +148,6 @@ set_target_properties(System.Native-Static PROPERTIES OUTPUT_NAME System.Native
 
 install (TARGETS System.Native-Static DESTINATION ${STATIC_LIB_DESTINATION} COMPONENT libs)
 
-if(CLR_CMAKE_HOST_ANDROID)
+if(CLR_CMAKE_HOST_ANDROID OR CLR_CMAKE_HOST_IOS OR CLR_CMAKE_HOST_TVOS OR CLR_CMAKE_HOST_MACCATALYST)
     install (TARGETS System.Native-Static DESTINATION sharedFramework COMPONENT runtime)
 endif()
diff --git a/src/tasks/AppleAppBuilder/Xcode.cs b/src/tasks/AppleAppBuilder/Xcode.cs
index 9e0f2e6b32602c..afe16fceb5fc53 100644
--- a/src/tasks/AppleAppBuilder/Xcode.cs
+++ b/src/tasks/AppleAppBuilder/Xcode.cs
@@ -414,16 +414,20 @@ public string GenerateCMake(
                 toLink += $"    \"-force_load {componentLibToLink}\"{Environment.NewLine}";
             }
 
-            string[] dylibs = Directory.GetFiles(workspace, "*.dylib");
             if (targetRuntime == TargetRuntime.CoreCLR)
             {
-                foreach (string lib in dylibs)
+                // Interpreter-FIXME: CoreCLR on iOS currently supports only static linking.
+                // The build system needs to be updated to conditionally initialize the compiler at runtime based on an environment variable.
+                // Tracking issue: https://github.com/dotnet/runtime/issues/119006
+                string[] staticLibs = Directory.GetFiles(workspace, "*.a");
+                foreach (string lib in staticLibs)
                 {
-                    toLink += $"    \"-force_load {lib}\"{Environment.NewLine}";
+                    toLink += $"    \"{lib}\"{Environment.NewLine}";
                 }
             }
             else
             {
+                string[] dylibs = Directory.GetFiles(workspace, "*.dylib");
                 // Sort the static libraries to link so the brotli libs are added to the list last (after the compression native libs)
                 List staticLibsToLink = Directory.GetFiles(workspace, "*.a").OrderBy(libName => libName.Contains("brotli") ? 1 : 0).ToList();
                 foreach (string lib in staticLibsToLink)
diff --git a/src/tests/FunctionalTests/iOS/Simulator/CoreCLR.Interpreter/Program.cs b/src/tests/FunctionalTests/iOS/Simulator/CoreCLR.Interpreter/Program.cs
index 7441f31337175b..00bd0387b6458a 100644
--- a/src/tests/FunctionalTests/iOS/Simulator/CoreCLR.Interpreter/Program.cs
+++ b/src/tests/FunctionalTests/iOS/Simulator/CoreCLR.Interpreter/Program.cs
@@ -9,22 +9,9 @@
 
 public static class Program
 {
-    [DllImport("__Internal")]
-    public static extern void mono_ios_set_summary(string value);
-
-    public static async Task Main(string[] args)
+    public static int Main(string[] args)
     {
-        mono_ios_set_summary($"Starting functional test");
-        int result = RunInterpreter();
         Console.WriteLine("Done!");
-        await Task.Delay(5000);
-
-        return result;
-    }
-
-    [MethodImpl(MethodImplOptions.NoInlining)]
-    public unsafe static int RunInterpreter()
-    {
         return 42;
     }
 }
diff --git a/src/tests/FunctionalTests/iOS/Simulator/CoreCLR.Interpreter/iOS.Simulator.CoreCLR.Interpreter.Test.csproj b/src/tests/FunctionalTests/iOS/Simulator/CoreCLR.Interpreter/iOS.Simulator.CoreCLR.Interpreter.Test.csproj
index fbf7c10bfd0f22..23315975066cd6 100644
--- a/src/tests/FunctionalTests/iOS/Simulator/CoreCLR.Interpreter/iOS.Simulator.CoreCLR.Interpreter.Test.csproj
+++ b/src/tests/FunctionalTests/iOS/Simulator/CoreCLR.Interpreter/iOS.Simulator.CoreCLR.Interpreter.Test.csproj
@@ -13,9 +13,7 @@
   
 
   
-    
-    
-    
+