/* 
	definitions for SPU Bubble mechanism
*/

#ifndef __SPU_BUBBLE_LAYOUT_H
#define __SPU_BUBBLE_LAYOUT_H
#pragma once

#if defined(PS3) || defined(BUBBLE_GEN)

//namespace containing data structs for binary layout
//all is stored with big endianess (except for the binary data copied from the elf itself)
namespace NBubBin
{
	inline const unsigned short EncodeBubbleSize(const uint32 cOrigVal)
	{
		return (unsigned short)(cOrigVal >> 2);
	}

	inline const uint32 DecodeBubbleSize(const unsigned short cOrigVal)
	{
		return ((uint32)cOrigVal) << 2;
	}

	/*binary layout of spu binary:
	header																  - bin header
	SJobStringHandle x num jobs						  - string and binary job offsets for each jobs
	Job String table (array of chars indexed into via SJobStringHandle's) - string table (just char array)
	Job binaries														- job binaries, must be 16 byte aligned
	Bubble directory: unsigned int x num bubbles	- offset for each bubble where to find
	SBubble x num bubbles										- bubble binary itself, each bubble must be 128 byte aligned
	*/
	//header of binary
	struct SHeader
	{
		unsigned int jobStringOff;		//offset of string table start
		unsigned int jobOff;					//offset of job binary start
		unsigned int bubbleOff;				//offset of bubble directory start
		unsigned short bubbleNum;			//number of bubbles contained
		unsigned short jobNum;				//number of jobs contained
	};

	//struct which will be used to map a job to a handle (which will be the address of the corresponding SJob entry))
	struct SJobStringHandle
	{
		unsigned int jobEntryOffset;		//offset job in binary (total offset)
		unsigned int jobStringStart;		//offset of string table in binary
		unsigned int jobStringSize;			//size of string (num chars)
	};

	//binary representation of a job
	struct SJob
	{
		unsigned short totalJobSize;		//total size of job in 4 bytes (header plus executable code) (size >> 2)
		short initialBubbles[4];				//id of first 4 bubbles, entry point points into initialBubbles[0], other might be -1
		unsigned short destBubbleOff;		//relative offset of the entry point into the first bubble (in 4 byte units)
		unsigned short branchOff;				//offset of the branch (relative to the job start (not text start))
		unsigned short bhOff;						//offset of the branch hint (relative to the job start (not text start))
		//here follows the executable text
	};

	//cross bubble entry header (all cross bubble entries belonging to the same ID)
	//required for fast indexing (during patching)
	//do not increase size, the sizeof value is used as shift in SetActiveBubbles
	struct SCrossEntry
	{
		unsigned short destBubbleId;	//ID of dest bubble id of where function can be found (global for all bubbles)
		unsigned short numEntries;		//number of cross bubble entries
		unsigned short offset;				//offset of cross bubble entries relative to bubble binary start
		unsigned short pad;
		//the SPatchEntryBase entries follow here
	};

	//header for binary representation of bubbles
	struct SBubble
	{
		unsigned int size;									//size of whole bubble
		unsigned short segOff;							//offset of segment text relative to bubble start
		unsigned short crossCallBubbleNum;	//number of different bubbles for cross bubble call destinations (number of SCrossEntry's)
	};

	//since cross calls can only exist in a multi bubble environment, unsigned short suffices for any text offset (max 32 KB)
	//16 bytes are necessary to load the entire contents at once
	//never change order, it is accessed in asm via rotations
	//keep order in sync with SReturnStackEntry in SPUBubbles.h
	struct SCrossPatch
	{
		unsigned short pad0;					//was: unsigned short textOffset;		//source offset of cross bubble branch within text section of current bubble
		unsigned short sourceBubbleID;//source bubble ID, required for fast access in miss handler
		unsigned short pad1;					//was: unsigned short bhTextOffset;	//difference to textOffset in bytes is also used for creating the branch instr.itself
		unsigned short destOffset;		//branch target offset in destination bubble (relative to its bubble start)

		unsigned short destBubbleID;	//destination bubble ID, required for fast access in miss handler
		unsigned short pad[3];

//		static const unsigned short scNoEntry = 0xFFFF;
		static const unsigned short scMaxBubbleID = 0x7FFF;
		static const unsigned short scWeak			  = 0x8000;
#if defined(__SPU__)
	} _ALIGN(16);
#else
	};
#endif

} //NBubBin

#endif //PS3
#endif //__SPU_BUBBLE_LAYOUT_H
