DIRECTORY DragOpsCross, DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport; GenRichards: CEDAR PROGRAM IMPORTS DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport = BEGIN OPEN DragOpsCross, DragOpsCrossUtils, HandCoding, HandCodingPseudos; Area: TYPE = HandCodingSupport.Area; gZ: NAT = 0; gQueuePacketCount: NAT = 1; gHoldCount: NAT = 2; gTaskTable: NAT = 3; gTaskTableSize: NAT = 7; gTaskList: NAT = 10; gCurrentTask: NAT = 11; gCurrentTaskIdentity: NAT = 12; gAllocObjects: NAT = 13; gAllocWords: NAT = 14; gAllocBase: NAT = 15; gAllocPtr: NAT = 16; gAllocPtrPtr: NAT = 17; gIdleFunction: NAT = 18; gDeviceFunction: NAT = 19; gHandlerFunction: NAT = 20; gWorkFunction: NAT = 21; gSIZE: NAT = 22; globalFrameCard: LONG CARDINAL; -- global frame base globalFrame: Word; -- global frame base as word externalAlloc: Label _ NIL; externalMove: Label _ NIL; enterInit: Label _ NIL; enterAlloc: Label _ NIL; enterInitScheduler: Label _ NIL; enterCreateTask: Label _ NIL; enterCreatePacket: Label _ NIL; enterQueuePacket: Label _ NIL; enterAppend: Label _ NIL; enterSchedule: Label _ NIL; enterWait: Label _ NIL; enterHoldSelf: Label _ NIL; enterRelease: Label _ NIL; enterFindTask: Label _ NIL; enterCreateIdler: Label _ NIL; enterIdleFunction: Label _ NIL; enterCreateDevice: Label _ NIL; enterDeviceFunction: Label _ NIL; enterCreateHandler: Label _ NIL; enterHandlerFunction: Label _ NIL; enterCreateWorker: Label _ NIL; enterWorkFunction: Label _ NIL; enterMain: Label _ NIL; tcbLink: NAT = 0; tcbIdentity: NAT = 1; tcbPriority: NAT = 2; tcbInput: NAT = 3; tcbState: NAT = 4; tcbFunction: NAT = 5; tcbHandle: NAT = 6; tcbSIZE: NAT = 7; pktLink: NAT = 0; pktIdentity: NAT = 1; pktKind: NAT = 2; pktDatum: NAT = 3; pktData: NAT = 4; pktBufferSize: NAT = 3; pktSIZE: NAT = pktData+pktBufferSize+1; pktKdevicePacketKind: NAT = 0; pktKworkPacketKind: NAT = 1; waiting: Word = CardToWord[10000000000B]; waitingWithPacket: Word = CardToWord[30000000000B]; packetPending: NAT = 31; taskWaiting: NAT = 30; taskHolding: NAT = 29; All: PROC = { area: Area = HandCodingSupport.GetCurrentArea[]; externalAlloc _ HandCodingPseudos.GetGlobalLabel["Basics.AllocVector"]; externalMove _ HandCodingPseudos.GetGlobalLabel["Basics.MoveVector"]; enterInit _ GenLabel[]; enterInitScheduler _ GenLabel[]; enterCreateTask _ GenLabel[]; enterCreatePacket _ GenLabel[]; enterQueuePacket _ GenLabel[]; enterAppend _ GenLabel[]; enterSchedule _ GenLabel[]; enterWait _ GenLabel[]; enterHoldSelf _ GenLabel[]; enterRelease _ GenLabel[]; enterFindTask _ GenLabel[]; enterCreateIdler _ GenLabel[]; enterIdleFunction _ GenLabel[]; enterCreateDevice _ GenLabel[]; enterDeviceFunction _ GenLabel[]; enterCreateHandler _ GenLabel[]; enterHandlerFunction _ GenLabel[]; enterCreateWorker _ GenLabel[]; enterWorkFunction _ GenLabel[]; enterMain _ GenLabel[]; enterAlloc _ GenLabel[]; GenInit[]; -- global frame initialization comes first GenAlloc[]; -- our pet simple allocator GenInitScheduler[]; GenCreateTask[]; GenCreatePacket[]; GenQueuePacket[]; GenAppend[]; GenSchedule[]; GenWait[]; GenHoldSelf[]; GenRelease[]; GenFindTask[]; GenCreateIdler[]; GenIdleFunction[]; GenCreateDevice[]; GenDeviceFunction[]; GenCreateHandler[]; GenHandlerFunction[]; GenCreateWorker[]; GenWorkFunction[]; GenMain[]; HandCodingSupport.SetOutputPC[globalFrameCard * bytesPerWord]; HandCodingSupport.OutputWord[area, ZerosWord]; }; GenInit: PROC = { area: Area = HandCodingSupport.GetCurrentArea[]; startLabel: Label = GenLabelHere[]; HandCodingPseudos.MakeLabelGlobal["Richards.Init", startLabel]; globalFrameCard _ HandCodingSupport.ReserveData[1*wordsPerPage] / bytesPerWord; globalFrame _ CardToWord[globalFrameCard]; { G: RegSpec = reg0; top: RegSpec = reg1; EnableTraps[]; -- to detect stack overflow drASL[255]; -- ensure that stack is empty, regardless of where it was drLIQB[globalFrame]; drLC0[]; drLIQB[UseLabel32[enterIdleFunction]]; drSRIn[G, gIdleFunction]; drLIQB[UseLabel32[enterDeviceFunction]]; drSRIn[G, gDeviceFunction]; drLIQB[UseLabel32[enterHandlerFunction]]; drSRIn[G, gHandlerFunction]; drLIQB[UseLabel32[enterWorkFunction]]; drSRIn[G, gWorkFunction]; drLIDB[256+1]; drLFC[UseLabel16[externalAlloc]]; drSRIn[G, gAllocBase]; drLRIn[G, gAllocBase]; drLIDB[256]; drWSB[0]; drLIQB[UseLabel32[enterAlloc]]; drSRIn[G, gAllocPtr]; drLRn[G]; drADDB[gAllocPtr]; drSRIn[G, gAllocPtrPtr]; drLRn[G]; drADDB[gAllocPtrPtr]; drSRIn[G, gZ]; drLFC[UseLabel16[enterMain]]; }; }; GenAlloc: PROC = { returnLabel: Label = GenLabel[]; rZ: RegSpec = reg0; rWords: RegSpec = reg1; G: RegSpec = reg2; rIndex: RegSpec = reg3; ProcedureEntry[enterAlloc, 2]; HandCodingPseudos.MakeLabelGlobal["Richards.Alloc", enterAlloc]; drLIQB[globalFrame]; drLRIn[G, gAllocWords]; drLRIn[G, gAllocObjects]; drADDB[1]; drSRIn[G, gAllocObjects]; drLRIn[G, gAllocWords]; drQADD[topAtop, rWords]; drSRIn[G, gAllocWords]; drLRn[rIndex]; drLRIn[G, gAllocBase]; drRB[0]; drBC[]; drLRIn[G, gAllocBase]; drADDB[1]; drADD[]; drSRn[rZ]; ProcedureExit[1]; }; GenInitScheduler: PROC = { G: RegSpec = reg0; rZero: RegSpec = reg1; ProcedureEntry[enterInitScheduler, 0]; HandCodingPseudos.MakeLabelGlobal["Richards.InitScheduler", enterInitScheduler]; drLIQB[globalFrame]; drLC0[]; drWRI[rZero, G, gQueuePacketCount]; drWRI[rZero, G, gHoldCount]; drWRI[rZero, G, gAllocWords]; drWRI[rZero, G, gAllocObjects]; drWRI[rZero, G, gTaskTable]; drWRI[rZero, G, gTaskTable+1]; drWRI[rZero, G, gTaskTable+2]; drWRI[rZero, G, gTaskTable+3]; drWRI[rZero, G, gTaskTable+4]; drWRI[rZero, G, gTaskTable+5]; drWRI[rZero, G, gTaskTable+6]; drWRI[rZero, G, gTaskList]; ProcedureExit[0]; }; GenCreateTask: PROC = { rIdentity: RegSpec = reg0; rPriority: RegSpec = reg1; rInitialWorkQueue: RegSpec = reg2; rInitialState: RegSpec = reg3; rFunction: RegSpec = reg4; rPrivateData: RegSpec = reg5; G: RegSpec = reg6; rT: RegSpec = reg7; ProcedureEntry[enterCreateTask, 6]; HandCodingPseudos.MakeLabelGlobal["Richards.CreateTask", enterCreateTask]; drLIQB[globalFrame]; drLC0[]; { drLRIn[G, gZ]; drLIB[tcbSIZE]; drLRIn[G, gZ]; drRB[0]; drRB[0]; drSFC[]; drSRn[rT]; drLRIn[G, gTaskList]; drSRIn[rT, tcbLink]; drWRI[rIdentity, rT, tcbIdentity]; drWRI[rPriority, rT, tcbPriority]; drWRI[rInitialWorkQueue, rT, tcbInput]; drWRI[rInitialState, rT, tcbState]; drWRI[rFunction, rT, tcbFunction]; drWRI[rPrivateData, rT, tcbHandle]; }; drLRn[rT]; drSRIn[G, gTaskList]; drLRn[rT]; drRADD[pushDst, G, rIdentity]; drWB[gTaskTable]; ProcedureExit[0]; }; GenCreatePacket: PROC = { rLink: RegSpec = reg0; rIdentity: RegSpec = reg1; rKind: RegSpec = reg2; rWorkQueue: RegSpec = reg3; G: RegSpec = reg4; rZero: RegSpec = reg5; ProcedureEntry[enterCreatePacket, 3]; HandCodingPseudos.MakeLabelGlobal["Richards.CreatePacket", enterCreatePacket]; drLC0[]; drLIQB[globalFrame]; drLC0[]; { drLRIn[G, gZ]; drLIB[pktSIZE]; drLRIn[G, gZ]; drRB[0]; drRB[0]; drSFC[]; drSRn[rWorkQueue]; drWRI[rLink, rWorkQueue, pktLink]; drWRI[rIdentity, rWorkQueue, pktIdentity]; drWRI[rKind, rWorkQueue, pktKind]; drWRI[rZero, rWorkQueue, pktDatum]; drWRI[rZero, rWorkQueue, pktData]; drWRI[rZero, rWorkQueue, pktData+1]; drWRI[rZero, rWorkQueue, pktData+2]; drWRI[rZero, rWorkQueue, pktData+3]; }; drROR[reg0, const0, rWorkQueue]; ProcedureExit[1]; }; GenQueuePacket: PROC = { rPacket: RegSpec = reg0; rTask: RegSpec = reg1; G: RegSpec = reg2; rT: RegSpec = reg3; returnLabel: Label = GenLabel[]; ProcedureEntry[enterQueuePacket, 1]; HandCodingPseudos.MakeLabelGlobal["Richards.QueuePacket", enterQueuePacket]; drLC0[]; drLIQB[globalFrame]; drLRIn[rPacket, pktIdentity]; drLFC[UseLabel16[enterFindTask]]; {fiLabel: Label = GenLabel[]; drLRn[rT]; drJNEBBJ[0, UseLabel8B[fiLabel]]; drLC0[]; drJB[UseLabel8A[returnLabel]]; SetLabel[fiLabel]; }; drLRIn[G, gQueuePacketCount]; drLIDB[23246]; drRJGEBJ[left: popSrc, right: belowSrcPop, dist: 6]; Halt[201B]; -- bomb out here if the queuePacketCount gets too large drLRIn[G, gQueuePacketCount]; drADDB[1]; drSRIn[G, gQueuePacketCount]; drLC0[]; drSRIn[rPacket, pktLink]; drLRIn[G, gCurrentTaskIdentity]; drSRIn[rPacket, pktIdentity]; { elseLabel: Label = GenLabel[]; fiLabel: Label = GenLabel[]; drLRIn[rT, tcbInput]; drJNEBB[0, UseLabel8B[elseLabel]]; drWRI[rPacket, rT, tcbInput]; drLC1[]; drLRIn[rT, tcbState]; drSHD[FieldDescriptorToCard[[insert: TRUE, mask: packetPending+1, shift: packetPending]]]; drSRIn[rT, tcbState]; drLRIn[rT, tcbPriority]; drLRIn[G, gCurrentTask]; drRB[tcbPriority]; drRJGEBJ[left: popSrc, right: belowSrcPop, dist: UseLabel8B[fiLabel]]; drLRn[rT]; drJB[UseLabel8A[returnLabel]]; SetLabel[elseLabel]; drLRn[rPacket]; drRADD[pushDst, rT, const3]; drLFC[UseLabel16[enterAppend]]; SetLabel[fiLabel]; }; drLRIn[G, gCurrentTask]; SetLabel[returnLabel]; drSRn[reg0]; ProcedureExit[1]; }; GenAppend: PROC = { rPacket: RegSpec = reg0; rHead: RegSpec = reg1; G: RegSpec = reg2; rZero: RegSpec = reg3; returnLabel: Label = GenLabel[]; ProcedureEntry[enterAppend, 2]; HandCodingPseudos.MakeLabelGlobal["Richards.Append", enterAppend]; drLIQB[globalFrame]; drLC0[]; drWRI[rZero, rPacket, pktLink]; {fiLabel: Label = GenLabel[]; drLRIn[rHead, 0]; drJNEBBJ[0, UseLabel8B[fiLabel]]; drWRI[rPacket, rHead, 0]; ProcedureExit[0]; SetLabel[fiLabel]; }; { rMouse: RegSpec = reg4; loopLabel: Label = GenLabel[]; testLabel: Label = GenLabel[]; drLRIn[rHead, 0]; drJB[UseLabel8A[testLabel]]; HandCodingSupport.WordAlign[]; SetLabel[loopLabel]; drLRIn[rMouse, 0]; drSRn[rMouse]; SetLabel[testLabel]; drLRIn[rMouse, 0]; drJNEBBJ[0, UseLabel8B[loopLabel]]; drWRI[rPacket, rMouse, pktLink]; drDIS[]; }; SetLabel[returnLabel]; ProcedureExit[0]; }; GenSchedule: PROC = { G: RegSpec = reg0; rZero: RegSpec = reg1; rMessage: RegSpec = reg2; returnLabel: Label = GenLabel[]; ProcedureEntry[enterSchedule, 0]; HandCodingPseudos.MakeLabelGlobal["Richards.Schedule", enterSchedule]; drLIQB[globalFrame]; drLC0[]; drLC0[]; drLRIn[G, gTaskList]; drSRIn[G, gCurrentTask]; { testLabel: Label = GenLabel[]; loopLabel: Label = GenLabel[]; drJB[UseLabel8A[testLabel]]; HandCodingSupport.WordAlign[]; SetLabel[loopLabel]; drROR[rMessage, const0, const0]; { thenLabel: Label = GenLabel[]; elseLabel: Label = GenLabel[]; fiLabel: Label = GenLabel[]; drLRIn[G, gCurrentTask]; drRB[tcbState]; ExtractField[2, 1]; drJEBB[1, UseLabel8B[thenLabel]]; drLRIn[G, gCurrentTask]; drRB[tcbState]; drLIQB[waiting]; drRJNEB[left: popSrc, right: belowSrcPop, dist: UseLabel8B[elseLabel]]; SetLabel[thenLabel]; drLRIn[G, gCurrentTask]; drRB[tcbLink]; drSRIn[G, gCurrentTask]; drJB[UseLabel8A[fiLabel]]; SetLabel[elseLabel]; { innerElseLabel: Label = GenLabel[]; drLRIn[G, gCurrentTask]; drRB[tcbState]; drLIQB[waitingWithPacket]; drRJNEB[left: popSrc, right: belowSrcPop, dist: UseLabel8B[innerElseLabel]]; drLRIn[G, gCurrentTask]; drRB[tcbInput]; drSRn[rMessage]; drLRIn[rMessage, tcbLink]; drLRIn[G, gCurrentTask]; drWB[tcbInput]; { innerInnerElseLabel: Label = GenLabel[]; innerInnerFiLabel: Label = GenLabel[]; drLRIn[G, gCurrentTask]; drRB[tcbInput]; drJNEBB[0, UseLabel8B[innerInnerElseLabel]]; drLC0[]; drLRIn[G, gCurrentTask]; drWB[tcbState]; drJB[UseLabel8A[innerInnerFiLabel]]; SetLabel[innerInnerElseLabel]; LReg[constNI]; drLRIn[G, gCurrentTask]; drWB[tcbState]; SetLabel[innerInnerFiLabel]; }; SetLabel[innerElseLabel]; drLRIn[G, gCurrentTask]; drRB[tcbIdentity]; drSRIn[G, gCurrentTaskIdentity]; drLRn[rMessage]; drLRIn[G, gCurrentTask]; drRB[tcbHandle]; drLRIn[G, gCurrentTask]; drRB[tcbFunction]; drSFCI[]; drSRIn[G, gCurrentTask]; }; SetLabel[fiLabel]; }; SetLabel[testLabel]; drLRIn[G, gCurrentTask]; drJNEBBJ[0, UseLabel8B[loopLabel]]; }; SetLabel[returnLabel]; ProcedureExit[0]; }; GenWait: PROC = { rTask: RegSpec = reg0; G: RegSpec = reg1; ProcedureEntry[enterWait, 0]; HandCodingPseudos.MakeLabelGlobal["Richards.Wait", enterWait]; drLC0[]; drLIQB[globalFrame]; drLC1[]; drLRIn[G, gCurrentTask]; drRB[tcbState]; drSHD[FieldDescriptorToCard[[insert: TRUE, mask: taskWaiting+1, shift: taskWaiting]]]; drLRIn[G, gCurrentTask]; drWB[tcbState]; drLRIn[G, gCurrentTask]; drSRn[rTask]; ProcedureExit[1]; }; GenHoldSelf: PROC = { rTask: RegSpec = reg0; G: RegSpec = reg1; ProcedureEntry[enterHoldSelf, 0]; HandCodingPseudos.MakeLabelGlobal["Richards.HoldSelf", enterHoldSelf]; drLC0[]; drLIQB[globalFrame]; drLRIn[G, gHoldCount]; drADDB[1]; drSRIn[G, gHoldCount]; drLC1[]; drLRIn[G, gCurrentTask]; drRB[tcbState]; drSHD[FieldDescriptorToCard[[insert: TRUE, mask: taskHolding+1, shift: taskHolding]]]; drLRIn[G, gCurrentTask]; drWB[tcbState]; drLRIn[G, gCurrentTask]; drRB[tcbLink]; drSRn[rTask]; ProcedureExit[1]; }; GenRelease: PROC = { rIdentity: RegSpec = reg0; rTask: RegSpec = reg1; G: RegSpec = reg2; rT: RegSpec = reg3; ProcedureEntry[enterRelease, 1]; HandCodingPseudos.MakeLabelGlobal["Richards.Release", enterRelease]; drLC0[]; drLIQB[globalFrame]; drLRn[rIdentity]; drLFC[UseLabel16[enterFindTask]]; {elseLabel: Label = GenLabel[]; drLRn[rT]; drJNEBBJ[0, UseLabel8B[elseLabel]]; drROR[reg0, const0, const0]; ProcedureExit[1]; SetLabel[elseLabel]; }; drLC0[]; drLRIn[rT, tcbState]; drSHD[FieldDescriptorToCard[[insert: TRUE, mask: taskHolding+1, shift: taskHolding]]]; drSRIn[rT, tcbState]; { elseLabel: Label = GenLabel[]; drLRIn[rT, tcbPriority]; drLRIn[G, gCurrentTask]; drRB[tcbPriority]; drRJGEB[left: popSrc, right: belowSrcPop, dist: UseLabel8B[elseLabel]]; drROR[reg0, const0, rT]; ProcedureExit[1]; SetLabel[elseLabel]; drRRI[reg0, G, gCurrentTask]; ProcedureExit[1]; }; }; GenFindTask: PROC = { rIdentity: RegSpec = reg0; rTask: RegSpec = reg1; G: RegSpec = reg2; rT: RegSpec = reg3; returnLabel: Label = GenLabel[]; ProcedureEntry[enterFindTask, 1]; HandCodingPseudos.MakeLabelGlobal["Richards.FindTask", enterFindTask]; drLC0[]; drLIQB[globalFrame]; drRVADD[pushDst, G, rIdentity]; drRB[gTaskTable]; { drLRn[rT]; drJNEBBJ[0, UseLabel8B[returnLabel]]; Halt[377B]; }; SetLabel[returnLabel]; drROR[reg0, const0, rT]; ProcedureExit[1]; }; GenCreateIdler: PROC = { rIdentity: RegSpec = reg0; rPriority: RegSpec = reg1; rWork: RegSpec = reg2; rState: RegSpec = reg3; G: RegSpec = reg4; rData: RegSpec = reg5; ProcedureEntry[enterCreateIdler, 4]; HandCodingPseudos.MakeLabelGlobal["Richards.CreateIdler", enterCreateIdler]; drLIQB[globalFrame]; drLC0[]; { drLRIn[G, gZ]; drLIB[2]; drLRIn[G, gZ]; drRB[0]; drRB[0]; drSFC[]; drSRn[rData]; drLIB[1]; drSRIn[rData, 0]; drLIDB[10000]; drSRIn[rData, 1]; }; { drLRn[rIdentity]; drLRn[rPriority]; drLRn[rWork]; drLRn[rState]; drLRn[G]; drADDB[gIdleFunction]; drLRn[rData]; drLFC[UseLabel16[enterCreateTask]]; }; ProcedureExit[0]; }; GenIdleFunction: PROC = { rWork: RegSpec = reg0; rWord: RegSpec = reg1; G: RegSpec = reg2; rT: RegSpec = reg3; rData: RegSpec = reg4; returnLabel: Label = GenLabel[]; ProcedureEntry[enterIdleFunction, 2+1]; HandCodingPseudos.MakeLabelGlobal["Richards.IdleFunction", enterIdleFunction]; drSUBB[gIdleFunction]; -- a pointer into the global frame is an implcit argument drLC0[]; { elseLabel: Label = GenLabel[]; drLRn[rWord]; drLRIn[rData, 1]; drRVSUB[topDst, topSrc, const1]; drSRIn[rData, 1]; drLRIn[rData, 1]; drJNEBBJ[0, UseLabel8B[elseLabel]]; drLFC[UseLabel16[enterHoldSelf]]; drJB[UseLabel8A[returnLabel]]; SetLabel[elseLabel]; }; { elseLabel: Label = GenLabel[]; drLRIn[rData, 0]; drQAND[topAtop, const1]; drJNEBB[0, UseLabel8B[elseLabel]]; drLRIn[rData, 0]; ExtractField[0, 31]; drSRIn[rData, 0]; drLIB[5]; drLFC[UseLabel16[enterRelease]]; drJB[UseLabel8A[returnLabel]]; SetLabel[elseLabel]; drLRIn[rData, 0]; ExtractField[0, 31]; drLIDB[0D008H]; drRXOR[belowDst, belowSrc, popSrc]; drSRIn[rData, 0]; drLIB[6]; drLFC[UseLabel16[enterRelease]]; }; SetLabel[returnLabel]; drSRn[reg0]; ProcedureExit[1]; }; GenCreateDevice: PROC = { rIdentity: RegSpec = reg0; rPriority: RegSpec = reg1; rWork: RegSpec = reg2; rState: RegSpec = reg3; G: RegSpec = reg4; rData: RegSpec = reg5; ProcedureEntry[enterCreateDevice, 4]; HandCodingPseudos.MakeLabelGlobal["Richards.CreateDevice", enterCreateDevice]; drLIQB[globalFrame]; drLC0[]; { drLRIn[G, gZ]; drLIB[2]; drLRIn[G, gZ]; drRB[0]; drRB[0]; drSFC[]; drSRn[rData]; drLC0[]; drSRIn[rData, 0]; }; { drLRn[rIdentity]; drLRn[rPriority]; drLRn[rWork]; drLRn[rState]; drLRn[G]; drADDB[gDeviceFunction]; drLRn[rData]; drLFC[UseLabel16[enterCreateTask]]; }; ProcedureExit[0]; }; GenDeviceFunction: PROC = { rWork: RegSpec = reg0; rWord: RegSpec = reg1; G: RegSpec = reg2; rT: RegSpec = reg3; rData: RegSpec = reg4; returnLabel: Label = GenLabel[]; ProcedureEntry[enterDeviceFunction, 2+1]; HandCodingPseudos.MakeLabelGlobal["Richards.DeviceFunction", enterDeviceFunction]; drSUBB[gDeviceFunction]; -- a pointer into the global frame is an implcit argument drLC0[]; { elseLabel: Label = GenLabel[]; drLRn[rWord]; drLRn[rWork]; drJNEBB[0, UseLabel8B[elseLabel]]; { innerElseLabel: Label = GenLabel[]; drLRIn[rData, 0]; drJNEBB[0, UseLabel8B[innerElseLabel]]; drLFC[UseLabel16[enterWait]]; drJB[UseLabel8A[returnLabel]]; SetLabel[innerElseLabel]; }; drRRI[rWork, rData, 0]; drLC0[]; drSRIn[rData, 0]; drLRn[rWork]; drLFC[UseLabel16[enterQueuePacket]]; drJB[UseLabel8A[returnLabel]]; SetLabel[elseLabel]; drWRI[rWork, rData, 0]; drLFC[UseLabel16[enterHoldSelf]]; }; SetLabel[returnLabel]; drSRn[reg0]; ProcedureExit[1]; }; GenCreateHandler: PROC = { rIdentity: RegSpec = reg0; rPriority: RegSpec = reg1; rWork: RegSpec = reg2; rState: RegSpec = reg3; G: RegSpec = reg4; rData: RegSpec = reg5; ProcedureEntry[enterCreateHandler, 4]; HandCodingPseudos.MakeLabelGlobal["Richards.CreateHandler", enterCreateHandler]; drLIQB[globalFrame]; drLC0[]; { drLRIn[G, gZ]; drLIB[2]; drLRIn[G, gZ]; drRB[0]; drRB[0]; drSFC[]; drSRn[rData]; drLC0[]; drSRIn[rData, 0]; drLC0[]; drSRIn[rData, 1]; }; { drLRn[rIdentity]; drLRn[rPriority]; drLRn[rWork]; drLRn[rState]; drLRn[G]; drADDB[gHandlerFunction]; drLRn[rData]; drLFC[UseLabel16[enterCreateTask]]; }; ProcedureExit[0]; }; GenHandlerFunction: PROC = { rWork: RegSpec = reg0; rWord: RegSpec = reg1; G: RegSpec = reg2; rT: RegSpec = reg3; rData: RegSpec = reg4; rWorkPacket: RegSpec = reg5; rDevicePacket: RegSpec = reg6; rCount: RegSpec = reg7; returnLabel: Label = GenLabel[]; ProcedureEntry[enterHandlerFunction, 2+1]; HandCodingPseudos.MakeLabelGlobal["Richards.HandlerFunction", enterHandlerFunction]; drSUBB[gHandlerFunction]; -- a pointer into the global frame is an implcit argument drLC0[]; drLRn[rWord]; drLC0[]; drLC0[]; drLC0[]; {elseLabel: Label = GenLabel[]; drLRn[rWork]; drJEBB[0, UseLabel8B[elseLabel]]; { innerElseLabel: Label = GenLabel[]; innerFiLabel: Label = GenLabel[]; drLRIn[rWork, pktKind]; drJNEBB[1, UseLabel8B[innerElseLabel]]; drLRn[rWork]; drLRn[rData]; drLFC[UseLabel16[enterAppend]]; drJB[UseLabel8A[innerFiLabel]]; SetLabel[innerElseLabel]; drLRn[rWork]; drQADD[pushA1, rData]; drLFC[UseLabel16[enterAppend]]; SetLabel[innerFiLabel]; }; SetLabel[elseLabel]; }; {elseLabel: Label = GenLabel[]; drLRIn[rData, 0]; drJEBB[0, UseLabel8B[elseLabel]]; drRRI[rWorkPacket, rData, 0]; drLRIn[rWorkPacket, pktDatum]; drRBC[rCount, topSrc, constNI]; -- (check for negative while assigning) { innerElseLabel: Label = GenLabel[]; drLRn[rCount]; drRJLEBJ[left: popSrc, right: const3, dist: UseLabel8B[innerElseLabel]]; drLRIn[rData, 0]; drRB[pktLink]; drSRIn[rData, 0]; drLRn[rWorkPacket]; drLFC[UseLabel16[enterQueuePacket]]; drJB[UseLabel8A[returnLabel]]; SetLabel[innerElseLabel]; }; { drLRIn[rData, 1]; drJEBB[0, UseLabel8B[elseLabel]]; drRRI[rDevicePacket, rData, 1]; drLRIn[rData, 1]; drRB[pktLink]; drSRIn[rData, 1]; drRBC[pushDst, rCount, const4]; drQADD[topAtop, rWorkPacket]; drRB[pktData]; drSRIn[rDevicePacket, pktDatum]; drQADD[pushA1, rCount]; drQBC[topAtop, constNI]; -- INT => CARDINAL coercion drSRIn[rWorkPacket, pktDatum]; drLRn[rDevicePacket]; drLFC[UseLabel16[enterQueuePacket]]; drJB[UseLabel8A[returnLabel]]; }; SetLabel[elseLabel]; }; drLFC[UseLabel16[enterWait]]; SetLabel[returnLabel]; drSRn[reg0]; ProcedureExit[1]; }; GenCreateWorker: PROC = { rIdentity: RegSpec = reg0; rPriority: RegSpec = reg1; rWork: RegSpec = reg2; rState: RegSpec = reg3; G: RegSpec = reg4; rData: RegSpec = reg5; ProcedureEntry[enterCreateWorker, 4]; HandCodingPseudos.MakeLabelGlobal["Richards.CreateWorker", enterCreateWorker]; drLIQB[globalFrame]; drLC0[]; { drLRIn[G, gZ]; drLIB[2]; drLRIn[G, gZ]; drRB[0]; drRB[0]; drSFC[]; drSRn[rData]; drLC3[]; drSRIn[rData, 0]; drLC0[]; drSRIn[rData, 1]; }; { drLRn[rIdentity]; drLRn[rPriority]; drLRn[rWork]; drLRn[rState]; drLRn[G]; drADDB[gWorkFunction]; drLRn[rData]; drLFC[UseLabel16[enterCreateTask]]; }; ProcedureExit[0]; }; GenWorkFunction: PROC = { rWork: RegSpec = reg0; rWord: RegSpec = reg1; G: RegSpec = reg2; rT: RegSpec = reg3; rData: RegSpec = reg4; returnLabel: Label = GenLabel[]; ProcedureEntry[enterWorkFunction, 2+1]; HandCodingPseudos.MakeLabelGlobal["Richards.WorkFunction", enterWorkFunction]; drSUBB[gWorkFunction]; -- a pointer into the global frame is an implcit argument drLC0[]; drLRn[rWord]; {elseLabel: Label = GenLabel[]; drLRn[rWork]; drJNEBB[0, UseLabel8B[elseLabel]]; drLFC[UseLabel16[enterWait]]; drJB[UseLabel8A[returnLabel]]; SetLabel[elseLabel]; { drLC3[]; drLRIn[rData, 0]; drJNEBB[3, 6]; drROR[topDst, const0, const4]; drSRIn[rData, 0]; }; drLRIn[rData, 0]; drSRIn[rWork, pktIdentity]; drLC0[]; drSRIn[rWork, pktDatum]; { rI: RegSpec = reg5; rLimit: RegSpec = reg6; testLabel: Label = GenLabel[]; loopLabel: Label = GenLabel[]; drLC0[]; drLC3[]; drJB[UseLabel8A[testLabel]]; HandCodingSupport.WordAlign[]; SetLabel[loopLabel]; drLRIn[rData, 1]; drRVADD[topDst, topSrc, const1]; drSRIn[rData, 1]; {elseLabel: Label = GenLabel[]; drLRIn[rData, 1]; drRXOR[topDst, topSrc, constNI]; drLIB[26]; drRXOR[topDst, topSrc, constNI]; drRJGEBJ[left: popSrc, right: belowSrcPop, dist: UseLabel8B[elseLabel]]; drLC1[]; drSRIn[rData, 1]; SetLabel[elseLabel]; }; drLRIn[rData, 1]; drADDB[100B]; drRBC[pushDst, rI, const4]; drQADD[topAtop, rWork]; drWB[pktData]; drRADD[rI, rI, const1]; SetLabel[testLabel]; drRJGEBJ[left: topSrc, right: rI, dist: UseLabel8B[loopLabel]]; drAS[256-2]; }; drLRn[rWork]; drLFC[UseLabel16[enterQueuePacket]]; }; SetLabel[returnLabel]; drSRn[reg0]; ProcedureExit[1]; }; GenMain: PROC = { rTime: RegSpec = reg0; G: RegSpec = reg1; rWorkQ: RegSpec = reg2; rPulses: RegSpec = reg3; ProcedureEntry[enterMain, 0]; HandCodingPseudos.MakeLabelGlobal["Richards.Main", enterMain]; drLC0[]; drLIQB[globalFrame]; drLC0[]; drLC0[]; drLFC[UseLabel16[enterInitScheduler]]; drLC1[]; drLC0[]; drLC0[]; drLC0[]; drLFC[UseLabel16[enterCreateIdler]]; drLC0[]; drLC2[]; drLC1[]; drLFC[UseLabel16[enterCreatePacket]]; drSRn[rWorkQ]; drLRn[rWorkQ]; drLC2[]; drLC1[]; drLFC[UseLabel16[enterCreatePacket]]; drSRn[rWorkQ]; drLC2[]; drLIDB[1000]; drLRn[rWorkQ]; drLIQB[waitingWithPacket]; drLFC[UseLabel16[enterCreateWorker]]; drLC0[]; drLIB[5]; drLC0[]; drLFC[UseLabel16[enterCreatePacket]]; drSRn[rWorkQ]; drLRn[rWorkQ]; drLIB[5]; drLC0[]; drLFC[UseLabel16[enterCreatePacket]]; drSRn[rWorkQ]; drLRn[rWorkQ]; drLIB[5]; drLC0[]; drLFC[UseLabel16[enterCreatePacket]]; drSRn[rWorkQ]; drLC3[]; drLIDB[2000]; drLRn[rWorkQ]; drLIQB[waitingWithPacket]; drLFC[UseLabel16[enterCreateHandler]]; drLC0[]; drLIB[6]; drLC0[]; drLFC[UseLabel16[enterCreatePacket]]; drSRn[rWorkQ]; drLRn[rWorkQ]; drLIB[6]; drLC0[]; drLFC[UseLabel16[enterCreatePacket]]; drSRn[rWorkQ]; drLRn[rWorkQ]; drLIB[6]; drLC0[]; drLFC[UseLabel16[enterCreatePacket]]; drSRn[rWorkQ]; drLC4[]; drLIDB[2000]; drLRn[rWorkQ]; drLIQB[waitingWithPacket]; drLFC[UseLabel16[enterCreateHandler]]; drLIB[5]; drLIDB[4000]; drLC0[]; drLIQB[waiting]; drLFC[UseLabel16[enterCreateDevice]]; drLIB[6]; drLIDB[5000]; drLC0[]; drLIQB[waiting]; drLFC[UseLabel16[enterCreateDevice]]; drLFC[UseLabel16[enterSchedule]]; drLRIn[G, gQueuePacketCount]; drLIDB[23246]; drRJEBJ[left: popSrc, right: belowSrcPop, dist: 6]; Halt[100B]; drLRIn[G, gHoldCount]; drLIDB[9297]; drRJEBJ[left: popSrc, right: belowSrcPop, dist: 6]; Halt[101B]; drLRIn[G, gAllocObjects]; drLIDB[20]; drRJEBJ[left: popSrc, right: belowSrcPop, dist: 6]; Halt[102B]; Halt[0]; ProcedureExit[1]; }; END. "jGenRichards.mesa Copyright c 1984, 1985 by Xerox Corporation. All rights reserved. Russ Atkinson (RRA) January 23, 1986 12:54:03 pm PST This program was hand-converted from Richards.mesa, which started out life as Martin Richards' simple operating system benchmark program (written in BCPL). This program takes 2.56 seconds on a Dorado Total instructions: 693, Bytes: 1094 Offsets in the global frame Reserve space in the global frame for procedure variables Global Labels and stuff TaskControlBlock: TYPE = RECORD [ link: Task, identity: TaskIdentity, priority: TaskPriority, input: WorkQueue, state: TaskState, function: TaskOperation, handle: LONG POINTER]; WorkQueue: TYPE = LONG POINTER TO Packet; Packet: TYPE = RECORD [ link: WorkQueue, identity: TaskIdentity, kind: PacketKind, datum: CARDINAL, data: ARRAY [0..packetBufferSize] OF CARDINAL]; TaskState: TYPE = RECORD [packetPending, taskWaiting, taskHolding: BOOL _ FALSE]; This procedure generates all of the code for the bench mark. It basically handles housekeeping pertinent to the code generation, but not to the code execution. Reserve the static storage (last to avoid overwriting code) Reserve the global frame (a page is quite sufficient) This procedure generates the initialzation code for Puzzle. reserve data statically Initialialize the global variables. Initialize the procedure variables (we need one level of indirection for SFCI) Allocate enough memory to hold the objects we will allocate init the words field of the sequence allocPtr: PROC ANY RETURNS ANY _ Alloc allocPtrPtr: LONG POINTER _ LOOPHOLE[LONG[@allocPtr]] z _ LOOPHOLE[LONG[@allocPtrPtr]] Enter the main program Alloc: PROC [z: UNCOUNTED ZONE, words: CARDINAL] RETURNS [LONG POINTER] index: CARDINAL _ allocWords allocObjects _ allocObjects + 1 allocWords _ allocWords + words RETURN [@allocBase[index]] InitScheduler: PROC [] queuePacketCount _ holdCount _ 0 allocWords _ allocObjects _ 0 taskTable _ ALL[noTask] taskList _ noTask CreateTask: PROC [identity: TaskIdentity, priority: TaskPriority, initialWorkQueue: WorkQueue, initialState: TaskState, function: TaskOperation, privateData: LONG POINTER] t: Task _ z.NEW[TaskControlBlock _ [ link: taskList, identity: identity, priority: priority, input: initialWorkQueue, state: initialState, function: function, handle: privateData]]; t: Task _ z.NEW[TaskControlBlock ... link: taskList, identity: identity, priority: priority, input: initialWorkQueue, state: initialState, function: function, handle: privateData, taskList _ t taskTable[identity] _ t CreatePacket: PROC [link: WorkQueue, identity: TaskIdentity, kind: PacketKind] RETURNS [workQueue: WorkQueue] workQueue _ z.NEW[Packet _ [ link: link, identity: identity, kind: kind, datum: 0, data: ALL[0]]]; workQueue _ z.NEW[Packet ... link: link, identity: identity, kind: kind, datum: 0, data: ALL[0]]] RETURN [workQueue] QueuePacket: PROC [packet: WorkQueue] RETURNS [task: Task] t: Task _ FindTask[packet.identity] IF t = noTask THEN RETURN [noTask]; queuePacketCount _ queuePacketCount+1; packet.link _ noWork; packet.identity _ currentTaskIdentity; IF t.input = noWork ... t.input _ packet t.state.packetPending _ TRUE IF t.priority > currentTask.priority THEN ... ... RETURN [t] ELSE Append[packet, @t.input]; RETURN [currentTask] Append: PROC [packet: WorkQueue, head: LONG POINTER TO WorkQueue] packet.link _ noWork IF head^ = noWork THEN {head^ _ packet; RETURN}; FOR mouse: WorkQueue _ head^, mouse.link UNTIL mouse.link = noWork DO REPEAT FINISHED => mouse.link _ packet ENDLOOP; mouse: WorkQueue _ head^ , mouse.link UNTIL mouse.link = noWork DO REPEAT FINISHED => mouse.link _ packet ENDLOOP Schedule: PROC [] currentTask _ taskList WHILE currentTask # noTask DO message _ noWork IF currentTask.state.taskHolding OR currentTask.state = waiting THEN currentTask _ currentTask.link ELSE IF currentTask.state = waitingWithPacket THEN { message _ currentTask.input; currentTask.input _ message.link; ... }; IF currentTask.state = waitingWithPacket THEN { message _ currentTask.input currentTask.input _ message.link IF currentTask.input = noWork THEN currentTask.state _ running ELSE currentTask.state _ [packetPending: TRUE] currentTaskIdentity _ currentTask.identity; currentTask _ currentTask.function[message, currentTask.handle]; Wait: PROC [] RETURNS [task: Task] currentTask.state.taskWaiting _ TRUE RETURN [currentTask] HoldSelf: PROC [] RETURNS [task: Task] holdCount _ holdCount+1 currentTask.state.taskHolding _ TRUE RETURN [currentTask.link] Release: PROC [identity: TaskIdentity] RETURNS [task: Task] t: Task _ FindTask[identity] IF t = noTask THEN RETURN [noTask]; t.state.taskHolding _ FALSE IF t.priority > currentTask.priority THEN RETURN [t] ELSE RETURN [currentTask] FindTask: PROC [identity: TaskIdentity] RETURNS [task: Task] t: Task _ taskTable[identity] IF t = noTask THEN ERROR CreateIdler: PROC [identity: TaskIdentity, priority: TaskPriority, work: WorkQueue, state: TaskState] data: IdleTaskData _ z.NEW[IdleTaskDataRecord _ [initialControl, 10000]]; CreateTask[identity, priority, work, state, IdleFunction, data]; IdleFunction: TaskOperation == [work: WorkQueue, word: LONG POINTER] RETURNS [t: Task] data: IdleTaskData _ word data.count _ data.count-1 IF data.count = 0 THEN RETURN [HoldSelf[]]; data.control _ data.control/2; RETURN [Release[deviceA]]; data.control _ PrincOpsUtils.BITXOR[data.control/2, hashValue] RETURN [Release[deviceB]]; CreateDevice: PROC [identity: TaskIdentity, priority: TaskPriority, work: WorkQueue, state: TaskState] data: DeviceTaskData _ z.NEW[DeviceTaskDataRecord _ [noWork]]; CreateTask[identity, priority, work, state, DeviceFunction, data]; DeviceFunction: TaskOperation == [work: WorkQueue, word: LONG POINTER] RETURNS [t: Task] data: IdleTaskData _ word IF work = noWork THEN IF data.pending = noWork THEN RETURN [Wait[]] work _ data.pending data.pending _ noWork RETURN [QueuePacket[work]] ELSE data.pending _ work RETURN [HoldSelf[]] CreateHandler: PROC [identity: TaskIdentity, priority: TaskPriority, work: WorkQueue, state: TaskState] data: HandlerTaskData _ z.NEW[HandlerTaskDataRecord _ [noWork, noWork]]; CreateTask[identity, priority, work, state, HandlerFunction, data]; HandlerFunction: TaskOperation == [work: WorkQueue, word: LONG POINTER] RETURNS [t: Task] data: IdleTaskData _ word workPacket, devicePacket: WorkQueue count: INTEGER IF work # noWork THEN IF work.kind = workPacketKind THEN Append[work, @data.workIn] ELSE Append[work, @data.deviceIn] IF data.workIn # noWork THEN workPacket _ data.workIn count _ workPacket.datum IF count > packetBufferSize THEN data.workIn _ data.workIn.link RETURN [QueuePacket[workPacket]] IF data.deviceIn # noWork THEN devicePacket _ data.deviceIn data.deviceIn _ data.deviceIn.link devicePacket.datum _ workPacket.data[count] workPacket.datum _ count+1 RETURN [QueuePacket[devicePacket]] RETURN [Wait[]] CreateWorker: PROC [identity: TaskIdentity, priority: TaskPriority, work: WorkQueue, state: TaskState] data: WorkerTaskData _ z.NEW[WorkerTaskDataRecord _ [handlerA, 0]]; CreateTask[identity, priority, work, state, WorkFunction, data]; WorkFunction: TaskOperation == [work: WorkQueue, word: LONG POINTER] RETURNS [t: Task] data: IdleTaskData _ word IF work = noWork THEN RETURN [Wait[]] data.destination _ (IF data.destination = handlerA THEN handlerB ELSE handlerA); work.identity _ data.destination work.datum _ 0 data.count _ data.count+1; IF data.count > 26 THEN data.count _ 1; work.data[i] _ ('A-0C)+data.count-1; ENDLOOP RETURN [QueuePacket[work]] Main: PROC RETURNS [time: REAL] workQ: WorkQueue; pulses: BasicTime.Pulses = BasicTime.GetClockPulses[]; init rTime, G, rWorkQ, rPulses InitScheduler[] CreateIdler[idler, 0, noWork, running] workQ _ CreatePacket[noWork, worker, workPacketKind]; workQ _ CreatePacket[workQ, worker, workPacketKind]; CreateWorker[worker, 1000, workQ, waitingWithPacket]; workQ _ CreatePacket[noWork, deviceA, devicePacketKind]; workQ _ CreatePacket[workQ, deviceA, devicePacketKind]; workQ _ CreatePacket[workQ, deviceA, devicePacketKind]; CreateHandler[handlerA, 2000, workQ, waitingWithPacket]; workQ _ CreatePacket[noWork, deviceB, devicePacketKind]; workQ _ CreatePacket[workQ, deviceB, devicePacketKind] workQ _ CreatePacket[workQ, deviceB, devicePacketKind] CreateHandler[handlerB, 2000, workQ, waitingWithPacket] CreateDevice[deviceA, 4000, noWork, waiting] CreateDevice[deviceB, 5000, noWork, waiting]; Schedule[] IF queuePacketCount # 23246 THEN ERROR Bogus IF holdCount # 9297 THEN ERROR Bogus IF allocObjects # 20 THEN ERROR Bogus The following were not generated, since they are not really applicable in Dragon IF allocWords # 140 THEN ERROR Bogus; time _ BasicTime.PulsesToSeconds[BasicTime.GetClockPulses[] - pulses]; Κ N˜codešœ™Kšœ Οmœ7™BK™4K™Kšœ›™›K˜—šΟk ˜ K˜ K˜K˜ K˜K˜K˜—šœ žœž˜KšžœD˜KKšœžœžœ@˜LK˜Kšœžœ˜$K˜—™K™K™$K™—šœ™Kšœžœ˜ Kšœžœ˜Kšœ žœ˜šœ žœ˜Kšœžœ˜—Kšœ žœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜Kšœžœ˜K˜Kšœ9™9Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜K˜Kšœžœ˜K˜—šœ™K–32 sp tabStopsšœžœžœΟc˜5K–32 sp tabStopsšœŸ˜0Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜ Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜!Kšœžœ˜ Kšœžœ˜"Kšœžœ˜Kšœžœ˜Kšœžœ˜K˜—šœžœžœ™!Kšœ ™ K™K™K™K™K™šœž œ™K™—Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜K˜—Kš œ žœžœžœžœ™)šœžœžœ™K™K™K™Kšœž œ™šœžœžœžœ™/K™—Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜šœ žœ˜Kšœžœ˜—šœ žœ˜'Kšœžœ˜Kšœžœ˜K˜—K˜)Kšœ3˜3K˜—š œ žœžœ+žœžœ™QKšœžœ˜Kšœ žœ˜Kšœ žœ˜K˜—šΟnœžœ˜ Kšœ ™ K˜Kšœ0˜0K˜KšœG˜GKšœE˜EK˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ!˜!Kšœ ˜ Kšœ"˜"Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜Kšœ Ÿ*˜6Kšœ Ÿ˜(Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ K˜šœ;™;K˜Kšœ5™5Kšœ>˜>Kšœ.˜.K˜—K˜K˜—š œžœ˜Kšœ;™;Kšœ0˜0K˜#K˜Kšœ?˜?K˜Kšœ™KšœO˜OKšœ*˜*šœ˜Kšœ#™#K™Kšžœ˜K˜K™KšœŸ˜+šœ Ÿ9˜FK˜—Kšœ˜K˜K˜šœN™NKšœ/žœ˜AKšœ1žœ˜EKšœ2žœ˜GKšœ/žœ˜A—K˜šœ:žœ˜IKšœ<™<—K˜šœžœ'˜/K™$—K˜šœ(žœ ˜6Kš œ žœžœžœžœ™&K™—šœžœžœ˜7Kš œ žœžœžœžœ ™5—K˜šœžœ"žœ˜0Kšœžœžœ™ —K˜˜Kšœ™—K˜—K˜K˜—š œžœ˜Kš œžœž œžœ žœžœžœžœ™GK˜K˜ K˜K˜K˜Kšžœ˜Kšœ˜K˜K˜Kšœ@˜@K˜Kšœ˜K˜šœžœ˜Kšœžœ ™K˜—šœžœ&žœ˜@Kšœ™—šœžœ2žœ˜JKšœ™—K˜Kšœ˜Kšœžœ!˜)šœžœ$˜,Kšœ™—K˜K˜ K˜K˜K˜K˜—š œžœ˜Kš  œžœ™K˜Kšžœ˜Kšœ˜K˜Kšœ&˜&KšœP˜PK˜Kšœ˜K˜K˜šœ žœ$žœ˜AK™ —šœ žœžœ˜=Kšœ™—Kšœ žœžœ˜;Kšœ žœžœ˜=Kšœ žœžœ˜=šœ žœ˜Kšœ žœ™—šœ žœ ˜K™—K˜K˜K˜K˜—š  œžœ˜Kš  œžœŽžœžœ™«K˜Kšœ˜Kšœ˜Kšœ"˜"Kšœ˜Kšœ˜Kšœ˜Kšžœ˜Kšœ˜K˜Kšœ#˜#KšœJ˜JK˜Kšœ˜K˜K˜˜šœ žœ™$K™K™K™K™K™K™K™—Kšœžœ˜šœžœ0˜8Kšœ$™$—šœ+˜+K™—šœ"˜"K™—šœ"˜"K™—šœ'˜'K™—šœ#˜#K™—šœ"˜"K™—šœ#˜#K™—K˜K˜—šœžœ ˜!K™ K™—šœžœ ˜=K™—K˜K˜K˜K˜—š œžœ˜š  œžœ<™NKšžœ™—K˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšžœ˜Kšœ˜K˜Kšœ%˜%KšœN˜NK˜K˜Kšœ˜K˜K˜˜šœžœ ™Kšœ ™ K™K™ K™ Kšœžœ™—Kšœžœ˜šœžœ8˜@Kšœžœ ™—šœ"˜"Kšœ ™ —šœ*˜*K™—šœ"˜"K™ —šœ#˜#K™ —KšœH˜HšœJ˜JKšœžœ™—K˜K˜—˜ Kšžœ ™—K˜K˜K˜—š œžœ˜Kš  œžœžœ ™:K˜Kšœ˜Kšœ˜Kšžœ˜Kšœ˜K˜K˜ K˜K˜$KšœL˜LK˜K˜Kšœ˜K˜šœ@˜@K™#K™—šœ˜Kšœ-˜-˜(Kšžœ žœžœ ™#—Kšœ˜K˜—K™Kšœžœ$˜,Kšœ4˜4Kšœ Ÿ7˜DK˜šœžœ*žœ˜HK™&—K˜šœ#˜#K™—K˜šœžœ7˜?K™&—K™˜K˜K˜K˜˜9Kšžœ™—K™˜K™—K˜Kšœ˜Kšœ˜Kšœ%žœ1˜Zšœ˜Kšœž™—K˜Kšœ!žœ$˜FšœF˜FKšžœ#žœ™-—K˜˜*Kšžœžœ™—K˜K˜˜Nšž™K™——K˜K˜K˜—K˜Kšœžœ˜K˜K˜šœ ˜ Kšžœ™—K˜K˜K˜—š  œžœ˜Kš  œžœžœžœžœ ™AK˜Kšœ˜Kšœ˜Kšžœ˜K˜K˜K˜ K˜Kšœ˜KšœB˜BK˜Kšœ˜K˜K˜šœ˜K™K™—šœ˜Kšœ4˜4˜,Kšžœžœžœ™0—Kšœ˜K˜—K™˜šžœ&žœž™EKšž™Kšžœ™Kšžœ™—K˜K˜K˜K˜šœ˜Kšœ™—K˜K˜K˜K˜K˜K˜K˜˜Kšœ ™ —K˜K˜K˜˜#Kšžœ™#—K˜˜ Kšžœ™—˜Kšž™—K˜—K˜K˜K˜K˜—š  œžœ˜Kš œžœ™K˜Kšžœ˜Kšœ˜Kšœ˜K˜K˜ K˜Kšœ!˜!KšœF˜FK˜Kšœ˜K˜K˜K˜šœžœžœ˜/K™—K˜˜K˜K˜K˜˜Kšžœž™—K˜K˜K˜K˜˜ K™—K˜˜K˜K˜K˜K˜Kšœžœ6˜>K˜!Kšœžœ3˜;šœG˜GKšžœžœ™?—K˜Kšœ˜Kšœžœ)žœ˜B˜Kšžœ™#—K˜šœ˜Kšž™—˜K˜#šžœ&žœ™/K™K™!K™Kšœ™—K˜Kšœžœ=˜EšœL˜LKšžœ&žœ™/—K˜šœžœ3˜;K™—K˜šœ#žœ!˜EK™ K™—šœ˜K˜(K˜&Kšœžœ!˜)˜,Kšžœ™K˜—Kšœžœ!˜3˜$Kšžœ™ K™—K˜šœžœ!˜9Kšžœ%žœ™.K™—K˜Kšœ˜—K˜K˜šœžœ,žœ˜MK™+—K˜Kšœžœ"˜˜>K˜K˜Kšœ˜K˜Kšœ˜Kšœžœ!˜)Kšœ%žœ-˜Všœžœ!˜)Kšœ ž™$—K˜šœžœ˜'Kšžœ™K˜—K˜K˜K˜—š  œžœ˜Kš œžœžœ ™&K˜Kšœ˜Kšžœ˜K˜Kšœ!˜!KšœF˜FK˜K˜Kšœ˜K˜šœžœ#žœ˜:K™—K˜Kšœ˜Kšœžœ!˜)Kšœ%žœ-˜Všœžœ!˜)Kšœ ž™$—K˜šœžœ/˜7Kšžœ™K˜—K˜K˜K˜—š  œžœ˜Kš œžœžœ ™;K˜Kšœ˜Kšœ˜Kšžœ˜Kšœ˜K˜Kšœ ˜ KšœD˜DK˜K˜Kšœ˜K˜šœ4˜4K™K™—šœ˜Kšœ/˜/˜/Kšžœ žœžœ ™#K˜—Kšœ˜K˜K˜—Kšœ˜Kšœ˜Kšœ%žœ-˜Všœ˜Kšœž™—K˜˜K˜K˜Kšœ!žœ$˜FšœG˜GKšžœ"™$—K˜˜+Kšžœžœ™K˜—K˜šœ0˜0Kšžœžœ™K˜—K˜K˜—K˜K˜—š  œžœ˜Kš œžœžœ ™—šœ+˜+Kšžœ™—K˜—K˜K˜K˜ K˜K˜K˜—š œžœ˜š  œž™KšœS™S—K˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšžœ˜Kšœ˜K˜Kšœ%˜%KšœN˜NK˜Kšœ˜K˜K˜˜Kšœžœ"™>Kšœžœ˜Kšœžœ3˜;Kšœ˜K˜K˜—˜K™BK˜KšœC˜CKšœžœ+˜2K˜#K˜—K˜K˜K˜K˜—š œžœ˜šœ™Kšœž œžœ ™:—K˜Kšœ˜Kšœ˜Kšžœ˜Kšœ˜Kšœ˜K˜ K˜Kšœ)˜)KšœR˜RK˜KšœŸ9˜SK˜K˜˜Kšœ˜K˜šœ ˜ Kšœ™—K˜šœ1˜1Kšžœž™—˜Kšœ#˜#K˜Kšœ:˜:K˜˜Kšžœžœžœ ™-K˜—Kšœ˜K˜—˜K™K™—˜K™—K˜Kšœ3˜3˜Kšžœ™—K˜šœ˜Kšž™—K˜˜K™K™—šœ!˜!Kšžœ ™—K˜K˜—K˜K˜ K˜K˜K˜—š œžœ˜š  œž™KšœS™S—K˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšžœ˜Kšœ˜K˜Kšœ&˜&KšœP˜PK˜Kšœ˜K˜K˜˜Kšœžœ+™HKšœžœ˜Kšœžœ3˜;Kšœ˜Kšœ˜K˜K˜—˜K™CK˜KšœC˜CKšœžœ,˜3K˜#K˜—K˜K˜K˜K˜—š œžœ˜šœ™Kšœž œžœ ™:—K˜Kšœ˜Kšœ˜Kšžœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜ K˜Kšœ*˜*KšœT˜TK˜KšœŸ9˜TK˜šœ ˜ Kšœ™—šœ˜Kšœ#™#—šœ˜Kšœž™—K˜˜˜0Kšžœž™—K˜˜K˜#K˜!K˜˜@Kšžœ™—K˜˜=Kšžœ™—K˜K˜K˜K˜˜FKšžœ™!—K˜K˜K˜—K˜K˜K˜—˜˜4Kšžœž™—K˜˜K™—K˜K˜šœ!Ÿ'˜HK™K™—˜K˜#K˜K˜šœH˜HKšžœž™ —K˜˜4Kšœ™K™—K˜9˜Kšžœ™ K™—K˜K˜K˜K˜—˜˜4Kšžœž™K˜—šœ˜Kšœ™K˜—˜4Kšœ"™"K™—Kšœ˜Kšœ-˜-šœ ˜ Kšœ+™+K™—Kšœ˜KšœŸ˜5šœ˜K™—K˜Kšœ;˜;˜Kšžœ™"K™—K˜—K˜K˜K˜—˜Kšžœ ™—K˜K˜K˜ K˜K˜K˜—š œžœ˜š  œž™KšœS™S—K˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšžœ˜Kšœ˜K˜Kšœ%˜%KšœN˜NK˜Kšœ˜K˜K˜˜Kšœžœ'™CKšœžœ˜Kšœžœ3˜;Kšœ˜Kšœ˜K˜K˜—˜K™@K˜KšœC˜CKšœžœ)˜0K˜#K˜—K˜K˜K˜K˜—š œžœ˜šœ™Kšœž œžœ ™:—K˜Kšœ˜Kšœ˜Kšžœ˜Kšœ˜Kšœ˜K˜ K˜Kšœ'˜'KšœN˜NK˜KšœŸ9˜QK˜šœ ˜ Kšœ™—K˜˜˜1Kšžœž™—K˜˜=Kšžœ ™—K˜K˜K˜˜™Kšœžœžœ žœ ™=—K˜K˜!K˜K˜K˜K˜—˜.K™ K™—˜"K™K™—˜Kšœ˜K˜K˜K˜K˜K˜K˜K˜K˜K˜˜FK™—K˜šœ˜Kšžœžœ™'Kšœ3˜3Kšœ,˜,KšœH˜HK˜Kšœ˜K˜K˜—K˜ K˜šœ'˜'K™$—K˜Kšœ˜K˜Kšœ?˜?˜ Kšž™—K˜—K˜šœ3˜3Kšžœ™—K˜K˜—K˜K˜ K˜K˜K˜—š œžœ˜Kš œžœžœžœ™K˜K˜K˜K˜K˜K˜K˜Kšœ>˜>˜K™K™K™6—K˜Kšœ˜˜Kšœ™—K˜˜&K™K˜—K˜&˜$K™&K˜—˜SK™5—˜YK™4—KšœC˜C˜%K™5—K˜˜TK™8—˜ZK™7—˜ZK™7—KšœC˜C˜&K™8—K˜˜TK™8—˜ZK™6—˜ZK™6—KšœC˜C˜&K™7—K˜K˜4˜%K™,K™—K˜4˜%K™-—K˜˜!K™ K™—Kšœžœ%˜-Kšœ3˜3˜ Kšžœžœžœ™,K™—Kšœžœ˜%Kšœ3˜3˜ Kšžœžœžœ™$K™—Kšœžœ˜&Kšœ3˜3˜ Kšžœžœžœ™%K™K™—K˜K˜K˜K™šŸP™PK™Kšžœžœžœ™%K™KšœF™FK˜—K˜K˜—Kšžœ˜K˜K˜—…—_œ’T