s32 sys_spu_thread_group_start(u32 id) { sys_spu.warning("sys_spu_thread_group_start(id=0x%x)", id); LV2_LOCK; const auto group = idm::get<lv2_spu_group_t>(id); if (!group) { return CELL_ESRCH; } if (group->state != SPU_THREAD_GROUP_STATUS_INITIALIZED) { return CELL_ESTAT; } // SPU_THREAD_GROUP_STATUS_READY state is not used group->state = SPU_THREAD_GROUP_STATUS_RUNNING; group->join_state = 0; for (auto& t : group->threads) { if (t) { if (t->index >= group->threads.size()) { throw EXCEPTION("Unexpected SPU thread index (%d)", t->index); } auto& args = group->args[t->index]; auto& image = group->images[t->index]; // Copy SPU image: // TODO: use segment info std::memcpy(vm::base(t->offset), image->segs.get_ptr(), 256 * 1024); t->pc = image->entry_point; t->cpu_init(); t->gpr[3] = v128::from64(0, args.arg1); t->gpr[4] = v128::from64(0, args.arg2); t->gpr[5] = v128::from64(0, args.arg3); t->gpr[6] = v128::from64(0, args.arg4); t->status.exchange(SPU_STATUS_RUNNING); } } // because SPU_THREAD_GROUP_STATUS_READY is not possible, run event is delivered immediately group->send_run_event(lv2_lock, id, 0, 0); // TODO: check data2 and data3 for (auto& thread : group->threads) { if (thread) { thread->state -= cpu_state::stop; (*thread)->lock_notify(); } } return CELL_OK; }
s32 sys_spu_thread_group_start(u32 id) { sys_spu.Warning("sys_spu_thread_group_start(id=0x%x)", id); LV2_LOCK; const auto group = Emu.GetIdManager().get<spu_group_t>(id); if (!group) { return CELL_ESRCH; } if (group->state != SPU_THREAD_GROUP_STATUS_INITIALIZED) { return CELL_ESTAT; } // SPU_THREAD_GROUP_STATUS_READY state is not used group->state = SPU_THREAD_GROUP_STATUS_RUNNING; group->join_state = 0; for (auto& t : group->threads) { if (t) { if (t->index >= group->threads.size()) { throw EXCEPTION("Unexpected SPU thread index (%d)", t->index); } auto& args = group->args[t->index]; auto& image = group->images[t->index]; // Copy SPU image: // TODO: use segment info std::memcpy(vm::get_ptr<void>(t->offset), vm::get_ptr<void>(image->addr), 256 * 1024); t->PC = image->entry_point; t->Run(); t->GPR[3] = u128::from64(0, args.arg1); t->GPR[4] = u128::from64(0, args.arg2); t->GPR[5] = u128::from64(0, args.arg3); t->GPR[6] = u128::from64(0, args.arg4); t->status.exchange(SPU_STATUS_RUNNING); } } // because SPU_THREAD_GROUP_STATUS_READY is not possible, run event is delivered immediately group->send_run_event(lv2_lock, id, 0, 0); // TODO: check data2 and data3 for (auto& t : group->threads) { if (t) t->Exec(); } return CELL_OK; }