{FakeKernel.mc  Last edited by Sturgis:           2-Sep-83 16:39:43}



{Init the TPC's for all the tasks (except 6, and 7) to point to Idle.  Idle must be at[0F,10] to cancel possible pending condition bits.}

	SetTask[0]; StartAddress[Idle];
	SetTask[1]; StartAddress[Idle];
	SetTask[2]; StartAddress[Idle];
	SetTask[3]; StartAddress[Idle];
	SetTask[4]; StartAddress[Idle];
	SetTask[5]; StartAddress[Idle];
	
{the code for this module will lie in low mem, in the so called cp image?  The new IOP assembly code will assure that the cp image remains unchanged as each bank is loaded, thus the Idle loop will appear in each bank at the same address}

Reserve[0]; Reserve[80,0FFF];

Idle:	CANCELBR[Idle, 0F],	c*, at[0F];


{following register definitions use registers specified in Dandelion.df as belonging to Emulator, IOP/Kernel or IOP}

RegDef[T,	R,	1];
RegDef[rK,	R,	0F];
RegDef[rKrh,	RH,	0F];
RegDef[uKSaveR,	U,	0F4];
RegDef[uIOPCtlSave, U,	0FA];



SetTask[7]; StartAddress[KStart];


KStart:
	rK ← 41, CANCELBR[$, 0F],	c1;
	DCtl ← rK LRot0, GOTO[KEntry],	c2; {not sure if Dctl needed}
	
	
	
	

{following code borrowed from bootkernel.mc of apilot100}



Set[IOPInMode, 1];	{IOP port input mode}
Set[IOPAWMode, 3];	{IOP port alwaysWU mode}


KEntry:	uKSaveR ← rK,			c*;
	rK ← RShift1 ~IOPStatus,	c*;
	uIOPCtlSave ← rK,		c*;
	IOPCtl ← IOPInMode,		c*;  {enable IOP port}





KRefresh:	Refresh,	c*;
	Refresh,	c*;
	Refresh,	c*;

KLoop:	Xbus← IOPStatus, XLDisp,	c*; {IOPReq?, x.8 guaranteed 0}
	rK← rK+1, NibCarryBr, BRANCH[$, KCommand],	c*;
	BRANCH[KLoop, KRefresh],	c*;

{here for kernel command from IOP}
{this loop seems to get the cycles into phase}
{I always thought a task woke up at c1, hence there should be no issue, however, the code I am copying has these loops}
KCommand:	Xbus← 0, XC2npcDisp, CANCELBR[$, 1],	c*;
KCommand1:	BRANCH[$, KDisp, 1],	c*;
	Xbus← 0, XC2npcDisp, GOTO[KCommand1],	c*;

KDisp:	Noop,	c1;
	Xbus← IOPIData, XDisp,	c2;
	DISP2[KTable],	c3;



{****************************************************************************************}
{command = 0, exit Kernel}
{****************************************************************************************}

KTable:	ExitKernel,				c1, at[0C, 10, KTable];
	rK ← uKSaveR,				c2;
	IOPCtl ← uIOPCtlSave, GOTO[KEntry],	c3;
		
	
	
	
{****************************************************************************************}
{command = 1, refresh}
{****************************************************************************************}

KRefCmd:
	Refresh, GOTO[KRefresh], {sneak in an extra refresh}	c1, at[0D, 10, KTable];
	
	
{****************************************************************************************}
{command = 2, step bank register  [this is the new command]}
{****************************************************************************************}

KCmd2:	rK ← uKSaveR,		c1, at[0E, 10, KTable];
	rK ← rK + 1,		c2;
	uKSaveR ← rK,		c3;
	
	Bank ← {Ybus ← rK} 1,		c1; {force it to 1 for the moment}
	IOPOData ← rK LRot0,		c2; {let IOP know what the new bank is}
	{noop} GOTO[KRefresh],	c3;

{****************************************************************************************}
{command = 3}
{my boot multi bank patch will use the command to see if my kernel is listening}

{****************************************************************************************}

KCmd3:	IOPOData ← 7,		c1, at[0F, 10, KTable];
	{noop}			c2;
	{noop} GOTO[KRefresh],	c3;

{Remarks:
 1-Sep-83  9:06:24:
	Original version used a task 0 which did an EnterKernel to capture Kernel task, with a dance involving a register to determine that subsequent task 0 execution should go to idle.  Now I just use two explict task starts, I am pretty sure that the boot code in IOP will load the low cp before setting the task registers, so that kernel will simply suddenly start executing in my new code.  Also had to add protect statements to CedarOpsA and CedarOpsB to keep the ordinary code out of the Low cp area, thus preventing ordinary code from clobbering my special low cp code.
 1-Sep-83 10:31:32: remove the DCtl ← 0 I had placed in the Idle loop
 1-Sep-83 11:06:46: add cmd 3 to provide a test that this kernel is running, also start reserve at 80 rather than 100, since cpimage in IOP is only 80 long.
  1-Sep-83 13:03:38: add a response byte to SetBank command, so IOP will know what the new bank is for debugging
   1-Sep-83 13:09:47: added a LRot0 to the cmmand loading bank register, since assembler insisted on some such for IOPOData
    1-Sep-83 15:41:13: must save IOPCtl to restore when leaving Kernel mode, as kernel can be called when IOP task is sending data to IOP, as well as when IOP task is waiting for a request from IOP.  For the moment, I am setting bank absolutely to 1.  will fix this later.
 1-Sep-83 15:57:39: ExitKernel must go to KEntry upon re-entry to kernel, so that it can save IOPCtl
  1-Sep-83 16:39:38: added DCtl ← 41 to KStart, not sure if needed.
   2-Sep-83 16:43:17: UGH: KENtry must not only save IOPCtl, but also must save rK, as this is used by the IOP read memory loop, which is active!  failure to do so causes loss of 2nd byte of first work of the three work group making up one control store word.
}