//----------------------------------------------------------------------
// Copyright (C) 2008 Electronic Arts    
//----------------------------------------------------------------------

#include "EABase/eabase.h"

#if ! defined EA_PLATFORM_PS3_SPU

#include "EAAssert/eaassert.h"
#include "job_util/memcpy.h"
#include <stdio.h>

namespace EA { namespace Jobs {

namespace JobUtilDetail {

#if defined EA_PLATFORM_PS3
    static const unsigned char gMemCpyJob[] __attribute__((aligned(128))) __attribute__((section(".spu_image"))) = 
    {
      #include "job_util_job_memcpy.job.h"
    };

    static EntryPoint gMemCpyEp(JOB_ENVIRONMENT_SPU_THREADS, &gMemCpyJob, sizeof(gMemCpyJob));

#else
    void MemCpyJob(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
    static EntryPoint gMemCpyEp(MemCpyJob);
#endif

}

    EA::Jobs::JobInstanceHandle AsyncMemCpy(EA::Jobs::JobScheduler & js,
        void * dst,
        void const * src,
        size_t size,
        bool allowSleepOn,
        JobAffinity affinity,
        JobPriority priority)
    {
        EA::Jobs::JobInstanceHandle JIH = AsyncMemCpyNotReady(js, dst, src, size, allowSleepOn, affinity, priority);
        JIH.Enable();
        return JIH;
    }

    EA::Jobs::JobInstanceHandle AsyncMemCpyNotReady(EA::Jobs::JobScheduler &js,
        void * dst,
        void const * src,
        size_t size,
        bool allowSleepOn,
        JobAffinity affinity,
        JobPriority priority)
    {
        #ifdef EA_ASSERT_ENABLED
            EA_ASSERT(dst);
            EA_ASSERT(src);
            EA_ASSERT(size);

            // check for overlapping regions
            uintptr_t const dstStart = reinterpret_cast<uintptr_t>(dst);
            uintptr_t const dstEnd = dstStart + size;
            uintptr_t const srcStart = reinterpret_cast<uintptr_t>(src);
            uintptr_t const srcEnd = srcStart + size;

            EA_ASSERT((srcStart >= dstEnd) || (srcStart < dstStart));
            EA_ASSERT((srcEnd > dstEnd) || (srcEnd <= dstStart));
            EA_ASSERT((dstStart >= srcEnd) || (dstStart < srcStart));
            EA_ASSERT((dstEnd > srcEnd) || (dstEnd <= srcStart));
        #endif
        EntryPoint EP(JobUtilDetail::gMemCpyEp);
        EP.SetAllowSleepOn(allowSleepOn);
        EP.SetAffinity(affinity);
        EP.SetPriority(priority);

        return js.AddNotReady(EP, 
                reinterpret_cast<uintptr_t>(dst), 
                reinterpret_cast<uintptr_t>(src), 
                static_cast<uintptr_t>(size));
    }

}}

#endif
