diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp
index 9e3f188a12..07cef479e5 100644
--- a/rpcs3/Emu/Cell/SPUThread.cpp
+++ b/rpcs3/Emu/Cell/SPUThread.cpp
@@ -1837,6 +1837,11 @@ void spu_thread::cpu_task()
 		}
 	}
 
+	if (spurs_addr && group->max_run != 6)
+	{
+		group->spurs_running++;
+	}
+
 	if (jit)
 	{
 		while (true)
@@ -1884,6 +1889,14 @@ void spu_thread::cpu_task()
 
 		allow_interrupts_in_cpu_work = false;
 	}
+
+	if (spurs_addr && group->max_run != 6)
+	{
+		if (group->spurs_running.exchange(0))
+		{
+			group->spurs_running.notify_all();
+		}
+	}
 }
 
 void spu_thread::cpu_work()
@@ -5469,12 +5482,71 @@ s64 spu_thread::get_ch_value(u32 ch)
 
 	case SPU_RdEventStat:
 	{
+		const bool is_spurs_task_wait = pc == 0x11a8 && group->max_run != 6 && spurs_addr;
+
+		if (is_spurs_task_wait)
+		{
+			const u32 prev_running = group->spurs_running.fetch_op([](u32& x)
+			{
+				if (x)
+				{
+					x--;
+					return true;
+				}
+
+				return false;
+			}).first;
+
+			if (prev_running == group->max_run)
+			{
+				group->spurs_running.notify_all();
+			}
+		}
+
 		const u32 mask1 = ch_events.load().mask;
 
 		auto events = get_events(mask1, false, true);
 
+		const auto wait_spurs_task = [&]
+		{
+			if (is_spurs_task_wait)
+			{
+				// Wait for other threads to complete their tasks (temporarily)
+				if (!is_stopped())
+				{
+					const u32 prev_running = group->spurs_running.fetch_op([max = group->max_run](u32& x)
+					{
+						if (x < max)
+						{
+							x++;
+							return true;
+						}
+
+						return false;
+					}).first;
+
+					if (prev_running >= group->max_run)
+					{
+						const u64 before = get_system_time();
+						thread_ctrl::wait_on(group->spurs_running, prev_running, 10000);
+
+						// Check for missed waiting (due to thread-state notification or value change)
+						const u32 new_running = group->spurs_running;
+
+						if (!is_stopped() && new_running >= group->max_run && get_system_time() - before < 1500)
+						{
+							thread_ctrl::wait_on(group->spurs_running, new_running, 10000);
+						}
+
+						group->spurs_running++;
+					}
+				}
+			}
+		};
+
 		if (events.count)
 		{
+			wait_spurs_task();
 			return events.events & mask1;
 		}
 
@@ -5490,7 +5562,7 @@ s64 spu_thread::get_ch_value(u32 ch)
 		const u32 old_raddr = raddr;
 
 		// Does not need to safe-access reservation if LR is the only event masked
-		// Because it's either an access violation or a livelock if an invalid memory is passed
+		// Because it's either an access violation or a live-lock if an invalid memory is passed
 		if (raddr && mask1 > SPU_EVENT_LR)
 		{
 			auto area = vm::get(vm::any, raddr);
@@ -5504,7 +5576,7 @@ s64 spu_thread::get_ch_value(u32 ch)
 			}
 			else if (area)
 			{
-				// Ensure possesion over reservation memory so it won't be deallocated
+				// Ensure possession over reservation memory so it won't be de-allocated
 				auto [base_addr, shm_] = area->peek(raddr);
 
 				if (shm_)
@@ -5690,6 +5762,7 @@ s64 spu_thread::get_ch_value(u32 ch)
 			thread_ctrl::wait_on(state, old, 100);
 		}
 
+		wait_spurs_task();
 		wakeup_delay();
 
 		if (is_paused(state - cpu_flag::suspend))
diff --git a/rpcs3/Emu/Cell/lv2/sys_spu.cpp b/rpcs3/Emu/Cell/lv2/sys_spu.cpp
index 8985ba33e6..150d755536 100644
--- a/rpcs3/Emu/Cell/lv2/sys_spu.cpp
+++ b/rpcs3/Emu/Cell/lv2/sys_spu.cpp
@@ -1057,7 +1057,7 @@ error_code sys_spu_thread_group_start(ppu_thread& ppu, u32 id)
 	default: return CELL_ESTAT;
 	}
 
-	const u32 max_threads = group->max_run;
+	const u32 max_threads = group->max_num;
 
 	group->join_state = 0;
 	group->exit_status = 0;
diff --git a/rpcs3/Emu/Cell/lv2/sys_spu.h b/rpcs3/Emu/Cell/lv2/sys_spu.h
index 690a273f4c..8b0b890b39 100644
--- a/rpcs3/Emu/Cell/lv2/sys_spu.h
+++ b/rpcs3/Emu/Cell/lv2/sys_spu.h
@@ -289,6 +289,7 @@ struct lv2_spu_group
 	atomic_t<s32> exit_status; // SPU Thread Group Exit Status
 	atomic_t<u32> join_state; // flags used to detect exit cause and signal
 	atomic_t<u32> running = 0; // Number of running threads
+	atomic_t<u32> spurs_running = 0;
 	atomic_t<u32> stop_count = 0;
 	atomic_t<u32> wait_term_count = 0; 
 	u32 waiter_spu_index = -1; // Index of SPU executing a waiting syscall