DIRECTORY Atom USING [PropList, PutPropOnList], DragOpsCross USING [FieldDescriptor, IFUStatusRec, ioRescheduleRequest, ioResetRequest, JDist8, ProcessorRegister, Word], DragOpsCrossUtils USING [CardToWord, HalfToCard, IntToWord, IOOperandToCard, WordToBytes, WordToHalves], HandCoding USING [const0, ConstSpec, drADDB, drADDDB, drALS, drFSDB, drJS, drJ1, drLC1, drLFC, drLIP, drLIQB, drLRn, drIOS, drRADD, drRET, drRETN, drRETK, drROR, drRRX, drRSUB, drSHL, drSHR, drSIP, drSRn, Lit16, Lit8, popSrc, pushDst, RegSpec, topSrc], HandCodingPseudos USING [Label, LabelRep], HandCodingSupport USING [Area, GetCurrentArea, OIcommon, OutputAlphaBeta, OutputAlphaBetaGammaDelta, OutputByte, SetOutputPC, WordAlign], IO USING [PutF, PutRope, STREAM], PriorityQueue USING [Empty, Insert, Predict, Ref, Remove, SortPred], Rope USING [Compare, ROPE], SymTab USING [Create, EachPairAction, Fetch, GetSize, Pairs, Ref, Store]; HandCodingPseudosImpl: CEDAR PROGRAM IMPORTS Atom, DragOpsCrossUtils, HandCoding, HandCodingSupport, IO, PriorityQueue, Rope, SymTab EXPORTS HandCodingPseudos = BEGIN OPEN DragOpsCross, HandCoding; ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; Area: TYPE = HandCodingSupport.Area; CARD: TYPE = LONG CARDINAL; Label: TYPE = HandCodingPseudos.Label; LabelRep: TYPE = HandCodingPseudos.LabelRep; LabelUsageList: TYPE = LIST OF LabelUsage; LabelUsage: TYPE = RECORD [ area: Area, offset: INT _ 0, delta: INTEGER _ 0, distWidth: [0..4] _ 1, fixoff: [0..4] _ 0 ]; LabellingError: PUBLIC ERROR [why: ROPE] = CODE; SetLabel: PUBLIC PROC [label: Label] = { area: Area = HandCodingSupport.GetCurrentArea[]; here: CARD _ area.currentPC; IF label.area # NIL THEN ERROR LabellingError["duplicate definition"]; label.offset _ here; label.area _ area; FOR each: LabelUsageList _ NARROW[label.uses], each.rest UNTIL each = NIL DO use: LabelUsage = each.first; where: INT = use.offset; delta: INT = here - where - use.delta; word: Word = DragOpsCrossUtils.IntToWord[delta]; IF use.area # area THEN ERROR LabellingError["wrong area"]; HandCodingSupport.SetOutputPC[where+use.fixoff, area]; SELECT use.distWidth FROM 1 => { IF delta < -128 OR delta > 127 THEN ERROR LabellingError["delta not in a byte"]; HandCodingSupport.OutputByte[area, DragOpsCrossUtils.WordToBytes[word][3]]; }; 2 => { IF delta < FIRST[INTEGER] OR delta > LAST[INTEGER] THEN ERROR LabellingError["delta not in two bytes"]; HandCodingSupport.OutputAlphaBeta[ area, DragOpsCrossUtils.HalfToCard[DragOpsCrossUtils.WordToHalves[word][1]]]; }; 4 => { HandCodingSupport.OutputAlphaBetaGammaDelta[ area, DragOpsCrossUtils.IntToWord[here - use.delta]]; }; ENDCASE; HandCodingSupport.SetOutputPC[here, area]; ENDLOOP; }; GenLabel: PUBLIC PROC RETURNS [label: Label] = { RETURN [NEW[LabelRep _ [area: NIL, name: NIL, offset: -1, uses: NIL]]]; }; GenLabelHere: PUBLIC PROC RETURNS [label: Label] = { label _ GenLabel[]; SetLabel[label]; }; UseLabel8A: PUBLIC PROC [label: Label] RETURNS [JDist8] = { offset: INT = DeltaLabels[label, 0, 1, 1]; IF offset < -128 OR offset > 127 THEN ERROR LabellingError["delta not in a byte"]; RETURN [IF offset < 0 THEN 256+offset ELSE offset]; }; UseLabel8B: PUBLIC PROC [label: Label] RETURNS [JDist8] = { offset: INT = DeltaLabels[label, 0, 1, 2]; IF offset < -128 OR offset > 127 THEN ERROR LabellingError["delta not in a byte"]; RETURN [IF offset < 0 THEN 256+offset ELSE offset]; }; UseLabel16: PUBLIC PROC [label: Label] RETURNS [Lit16] = { offset: INT = DeltaLabels[label, 0, 2]; IF offset < FIRST[INTEGER] OR offset > LAST[INTEGER] THEN ERROR LabellingError["delta not in two bytes"]; RETURN [IF offset < 0 THEN (offset + LAST[CARDINAL]) + 1 ELSE offset]; }; UseLabel32: PUBLIC PROC [label: Label] RETURNS [Word] = { RETURN [DragOpsCrossUtils.IntToWord[DeltaLabels[label, 0, 4]]]; }; DeltaLabels: PROC [label: Label, plus: INTEGER _ 0, width: [0..4] _ 1, fixoff: NAT _ 1] RETURNS [INT] = { pc: CARD; area: Area = HandCodingSupport.GetCurrentArea[]; pc _ area.currentPC; SELECT label.area FROM area => { IF width = 4 THEN RETURN [label.offset-plus] ELSE RETURN [label.offset - pc - plus]; }; NIL => { uses: LabelUsageList _ NARROW[label.uses]; uses _ CONS[[area: area, offset: pc, distWidth: width, delta: plus, fixoff: fixoff], uses]; label.uses _ uses; RETURN [0]; }; ENDCASE => ERROR LabellingError["wrong area"]; }; SymHolder: TYPE = RECORD[tab: SymTab.Ref]; MakeLabelGlobal: PUBLIC PROC [name: ROPE, label: Label] = { area: Area = HandCodingSupport.GetCurrentArea[]; tab: SymTab.Ref _ GetGlobalLabelTable[area]; IF tab = NIL THEN { tab _ SymTab.Create[29, FALSE]; area.props _ Atom.PutPropOnList[area.props, $GlobalLabels, NEW[SymHolder _ [tab]]]; }; [] _ SymTab.Store[tab, name, label]; label.name _ name; }; LabelNameSort: PriorityQueue.SortPred = { xx: HandCodingPseudos.Label = NARROW[x]; yy: HandCodingPseudos.Label = NARROW[y]; RETURN [Rope.Compare[xx.name, yy.name, FALSE] = less]; }; LabelAddrSort: PriorityQueue.SortPred = { xx: HandCodingPseudos.Label = NARROW[x]; yy: HandCodingPseudos.Label = NARROW[y]; RETURN [xx.offset < yy.offset]; }; ShowGlobalLabelTable: PUBLIC PROC [st: IO.STREAM, sortNames: BOOL _ TRUE, area: HandCodingSupport.Area _ NIL] = { tab: SymTab.Ref = GetGlobalLabelTable[area]; IF tab # NIL THEN { action: SymTab.EachPairAction = { label: HandCodingPseudos.Label = NARROW[val]; PriorityQueue.Insert[pq, label]; quit _ FALSE; }; pq: PriorityQueue.Ref = PriorityQueue.Predict[ SymTab.GetSize[tab], IF sortNames THEN LabelNameSort ELSE LabelAddrSort, NIL]; [] _ SymTab.Pairs[tab, action]; WHILE NOT PriorityQueue.Empty[pq] DO label: HandCodingPseudos.Label = NARROW[PriorityQueue.Remove[pq]]; IF sortNames THEN IO.PutF[st, " %g = %w\n", [rope[label.name]], [integer[label.offset]]] ELSE IO.PutF[st, " -- %w: %g\n", [integer[label.offset]], [rope[label.name]]]; ENDLOOP; IO.PutRope[st, "\n"]; }; }; GetGlobalLabel: PUBLIC PROC [name: ROPE] RETURNS [Label] = { tab: SymTab.Ref _ GetGlobalLabelTable[NIL]; IF tab = NIL THEN RETURN [NIL]; RETURN [NARROW[SymTab.Fetch[tab, name].val]]; }; GetGlobalLabelTable: PUBLIC PROC [area: Area] RETURNS [tab: SymTab.Ref _ NIL] = { IF area = NIL THEN area _ HandCodingSupport.GetCurrentArea[]; FOR each: Atom.PropList _ area.props, each.rest WHILE each # NIL DO IF each.first.key = $GlobalLabels THEN { symHold: REF SymHolder _ NARROW[each.first.val]; tab _ symHold.tab; EXIT; }; ENDLOOP; }; LReg: PUBLIC PROC [reg: RegSpec] = { IF reg.kind = reg THEN drLRn[reg] ELSE drROR[c: pushDst, a: reg, b: const0]; }; PReg: PUBLIC PROC [reg: RegSpec] = { drROR[c: reg, a: topSrc, b: const0]; }; SReg: PUBLIC PROC [reg: RegSpec] = { IF reg.kind = reg THEN drSRn[reg] ELSE drROR[c: reg, a: popSrc, b: const0]; }; AddReg: PUBLIC PROC [reg: RegSpec, const: ConstSpec] = { drRADD[c: reg, a: reg, b: const]; }; SubReg: PUBLIC PROC [reg: RegSpec, const: ConstSpec] = { drRSUB[c: reg, a: reg, b: const]; }; SetRegConst: PUBLIC PROC [reg: RegSpec, const: ConstSpec] = { drROR[c: reg, a: const, b: const0]; }; MoveReg: PUBLIC PROC [dst,src: RegSpec] = { SELECT TRUE FROM dst.kind = aux AND src.kind = reg => { drLRn[reg: src]; drROR[c: dst, a: popSrc, b: const0]; }; dst.kind = reg AND src.kind = aux => { drROR[c: pushDst, a: src, b: const0]; drSRn[reg: dst]; }; ENDCASE => drROR[c: dst, a: src, b: const0]; }; MoveRegI: PUBLIC PROC [dst,src: RegSpec, const: ConstSpec] = { drRRX[c: dst, a: src, b: const]; }; LRegI: PUBLIC PROC [reg: RegSpec, const: ConstSpec] = { drRRX[c: pushDst, a: reg, b: const]; }; IndexedJump: PUBLIC PROC [dest: Label, long: BOOL _ FALSE, back: BOOL _ FALSE] = { area: Area = HandCodingSupport.GetCurrentArea[]; thisPC: CARD _ area.currentPC; IF dest # NIL THEN IF long THEN drADDDB[DeltaLabels[dest, 3, 2]] ELSE drADDB[DeltaLabels[dest, 2, 1]]; drJS[]; }; ProcedureEntry: PUBLIC PROC [label: Label, args: [0..15], dontChangeRL: BOOL _ FALSE] = { lit: Lit8 _ (1-LOOPHOLE[args, CARDINAL]) MOD 256; HandCodingSupport.WordAlign[]; IF label # NIL THEN SetLabel[label]; IF NOT dontChangeRL THEN drALS[lit]; }; ProcedureExit: PUBLIC PROC [rets: [0..15], dontChangeSP: BOOL _ FALSE, enableTraps: BOOL _ FALSE] = { lit: Lit8 _ (LOOPHOLE[rets, CARDINAL]-1) MOD 256; SELECT TRUE FROM enableTraps => drRETK[lit]; dontChangeSP => drRETN[]; ENDCASE => drRET[lit]; }; SetupField: PUBLIC PROC [fd: FieldDescriptor] = { drFSDB[LOOPHOLE[fd, Lit16]]; }; ExtractField: PUBLIC PROC [first: [0..31], bits: [0..31]] = { fd: FieldDescriptor = [ reserved: 0, insert: FALSE, mask: bits, shift: first + bits ]; drSHR[LOOPHOLE[fd, Lit16]]; }; ShiftLeft: PUBLIC PROC [bits: [0..31]] = { fd: FieldDescriptor = [ reserved: 0, insert: FALSE, mask: 0, shift: bits ]; drSHL[LOOPHOLE[fd, Lit16]]; }; LoadProcessorReg: PUBLIC PROC [which: DragOpsCross.ProcessorRegister] = { drLIP[LOOPHOLE[which]]; }; StoreProcessorReg: PUBLIC PROC [which: DragOpsCross.ProcessorRegister] = { drSIP[LOOPHOLE[which]]; }; EnableTraps: PUBLIC PROC = { status: DragOpsCross.IFUStatusRec _ [ ]; status.userModeKeep _ TRUE; status.rescheduleKeep _ TRUE; status.trapsEnabledKeep _ FALSE; status.trapsEnabled _ TRUE; drLIQB[LOOPHOLE[status]]; StoreProcessorReg[ifuStatus]; }; DisableTraps: PUBLIC PROC = { status: DragOpsCross.IFUStatusRec _ [ ]; status.userModeKeep _ TRUE; status.rescheduleKeep _ TRUE; status.trapsEnabledKeep _ FALSE; status.trapsEnabled _ FALSE; drLIQB[LOOPHOLE[status]]; StoreProcessorReg[ifuStatus]; }; CauseReschedule: PUBLIC PROC = { drLC1[]; drLIQB[DragOpsCrossUtils.CardToWord[DragOpsCross.ioRescheduleRequest]]; drIOS[DragOpsCrossUtils.IOOperandToCard[ [pCmd: [register: first, mode: kernelOnly, direction: write]]]]; }; CauseReset: PUBLIC PROC = { drLC1[]; drLIQB[DragOpsCrossUtils.CardToWord[DragOpsCross.ioResetRequest]]; drIOS[DragOpsCrossUtils.IOOperandToCard[ [pCmd: [register: first, mode: kernelOnly, direction: write]]]]; }; GetSPLimit: PUBLIC PROC = { LoadProcessorReg[ifuSLimit]; }; SetSPLimit: PUBLIC PROC = { StoreProcessorReg[ifuSLimit]; }; GetL: PUBLIC PROC = { drLFC[5]; -- stupid call to put L on the IFU stack HandCodingSupport.OIcommon[dJ5]; -- jump around the dumb little routine drJ1[]; LoadProcessorReg[ifuYoungestL]; drRETN[]; }; SetL: PUBLIC PROC = { drLFC[5]; -- stupid call to put L on the IFU stack HandCodingSupport.OIcommon[dJ5]; -- jump around the dumb little routine drJ1[]; StoreProcessorReg[ifuYoungestL]; drRETN[]; }; GetYoungestPC: PUBLIC PROC = { LoadProcessorReg[ifuYoungestPC]; }; GetYoungestL: PUBLIC PROC = { LoadProcessorReg[ifuYoungestL]; }; GetEldestPC: PUBLIC PROC = { LoadProcessorReg[ifuEldestPC]; }; GetEldestL: PUBLIC PROC = { LoadProcessorReg[ifuEldestL]; }; SetYoungestPC: PUBLIC PROC = { StoreProcessorReg[ifuYoungestPC]; }; SetYoungestL: PUBLIC PROC = { StoreProcessorReg[ifuYoungestL]; }; SetEldestPC: PUBLIC PROC = { StoreProcessorReg[ifuEldestPC]; }; SetEldestL: PUBLIC PROC = { StoreProcessorReg[ifuEldestL]; }; Pause: PUBLIC PROC = { HandCodingSupport.OutputByte[HandCodingSupport.GetCurrentArea[], LOOPHOLE[0]]; }; Halt: PUBLIC PROC [code: CARDINAL] = { area: Area = HandCodingSupport.GetCurrentArea[]; HandCodingSupport.OutputByte[area, LOOPHOLE[377B]]; HandCodingSupport.OutputAlphaBeta[area, code]; }; END. zHandCodingPseudosImpl.mesa Copyright c 1984, 1985 by Xerox Corporation. All rights reserved. Russ Atkinson (RRA) October 7, 1985 6:33:49 pm PDT McCreight, December 31, 1985 3:14:26 pm PST Labelling 4-byte addresses are absolute, not relative Return the number of bytes between the current PC and the label. The current PC is remembered as the place to do fixups. The plus argument is used to pretend that the current PC is that many bytes forward (reduces delta) from where it is for the purpose of determining delta, but not for the purpose of determining the PC for fixup. The width of the label is necessary for fixups and sign extension. The fixoff is necessary to determine how many bytes lie between the pc and the start of the label. This label is known and in the same area, so generating the offset is easy. Notice that 32-bit labels are absolute, not relative. the label is not yet defined, so save the given location for fixup the label is not in the same area, so complain about it shows the global label table for the given area to the given stream. If sortNames, then the labels come out sorted by name, otherwise sorted by address. Now, if there are any, output any global symbols that have accumulated. We go to a little extra trouble to ensure that the symbols are sorted by name. [key: Key, val: Val] RETURNS [quit: BOOL] Macros We go through extra stuff here to legally mix aux and reg kinds. Further checking is performed by the opcode routines themselves. Notes procedure entry. generates the procedure exit instruction, if enableTraps then RETK else RET. RETK expects new Status on the stack. ... generates the appropriate instruction to extract the specified bits from [S], which is performed by left shifting the pair ([S], [S]) until the field is in the corretc position, then masking out the correct # of bits. ... generates the appropriate instruction to extract the specified bits from [S], which is performed by left shifting the pair ([S], [S]) until the field is in the corretc position, then masking out the correct # of bits. generates the appropriate instruction to shift [S] left by bits IFU primitives Loads the specified IFU or EU register onto the stack. Pops the stack into the specified IFU register. ... enables reschedule interrupts and stack overflow. ... disables reschedule interrupts and stack overflow. ... causes a reschedule interrupt when interrupts are next enabled (possibly immediately). We do this by writing anything to a peculiar IO location. ... causes a reset trap. ... enables/disables stack overflow trapping. ... enables/disables stack overflow trapping. ... returns the current value of L. ... sets the current value of L. ... gets the youngest PC entry in the IFU stack (into [S]). S_S+1. ... gets the youngest L entry in the IFU stack (into [S]). S_S+1. ... flushes the eldest entry in the IFU stack and puts the PC into [S+1]. S_S+1. The results are undefined if there was no PC to get. ... pushes the RL part of the eldest IFU stack entry. ... sets the youngest PC entry in the IFU stack (from [S]). S_S-1. ... sets the youngest L entry in the IFU stack (from [S]). S_S-1. ... causes a new eldest IFU stack entry to be created and sets the PC part of that entry (from [S]). S_S-1. ... sets the RL part of the eldest IFU stack entry (from [S]). Interaction with the interpreter ... Instructs the interpreter to pause. ... Instructs the interpreter to pause. Κ˜codešœ™Kšœ Οmœ7™BK™2K™+K˜—šΟk ˜ Kšœžœ˜%Kšœ žœg˜yKšœžœQ˜hKšœ žœμ˜όKšœžœ˜*Kšœžœr˜‰Kšžœžœžœ˜!Kšœžœ1˜DKšœžœ žœ˜Kšœžœ=˜I—headšœžœž˜$Kšžœ9žœ˜_Kšžœ˜Kšœžœžœ˜&K˜Kšžœžœžœ˜Kšžœžœžœžœ˜—™ K˜Kšœžœ˜$Kšžœžœžœžœ˜Kšœžœ˜&Kšœ žœ˜,Kšœžœžœžœ ˜*šœ žœžœ˜Kšœ ˜ Kšœžœ˜Kšœžœ˜Kšœ˜Kšœ˜Kšœ˜—K˜Kš œžœžœžœžœ˜0K˜šΟnœžœžœ˜(Kšœ0˜0Kšœžœ˜Kšžœžœžœžœ(˜FKšœ˜Kšœ˜š žœžœžœžœž˜LKšœ˜Kšœžœ˜Kšœžœ˜&Kšœ0˜0Kšžœžœžœ˜;Kšœ6˜6šžœž˜˜šžœžœ ž˜#Kšžœ'˜,—KšœK˜KKšœ˜—˜š žœ žœžœžœ žœžœž˜7Kšžœ*˜/—šœ"˜"Kšœ˜KšœG˜G—K˜—˜Kšœ+™+šœ,˜,Kšœ5˜5—K˜—Kšžœ˜—Kšœ*˜*Kšžœ˜—K˜K˜—šŸœžœžœžœ˜0Kš žœžœžœžœžœ˜GK˜K˜—šŸ œžœžœžœ˜4Kšœ˜Kšœ˜K˜K˜—šŸ œžœžœžœ ˜;Kšœžœ˜*šžœžœž˜%Kšžœ'˜,—Kšžœžœ žœ žœ ˜3K˜K˜—šŸ œžœžœžœ ˜;Kšœžœ˜*šžœžœž˜%Kšžœ'˜,—Kšžœžœ žœ žœ ˜3K˜K˜—šŸ œžœžœžœ ˜:Kšœžœ˜'š žœ žœžœžœ žœžœž˜9Kšžœ*˜/—Kš žœžœ žœ žœžœžœ ˜FK˜K˜—šŸ œžœžœžœ ˜9Kšžœ9˜?K˜K˜—š Ÿ œžœžœ!žœžœžœ˜iKšœφ™φKšœžœ˜ Kšœ0˜0Kšœ˜šžœ ž˜šœ ˜ Kšœ‚™‚šžœ ˜ Kšžœžœ˜Kšžœžœ˜'—Kšœ˜—šžœ˜K™BKšœžœ ˜*KšœžœP˜[Kšœ˜Kšžœ˜ Kšœ˜—šžœ˜ Kšœ7™7Kšžœ˜#——K˜K˜—šœ žœžœ˜*K˜—šŸœžœžœžœ˜;K˜0Kšœ,˜,šžœžœžœ˜Kšœžœ˜Kšœ;žœ˜SK˜—Kšœ$˜$K˜K˜K˜—šœ)˜)Kšœžœ˜(Kšœžœ˜(Kšžœ!žœ ˜6K˜K˜—šœ)˜)Kšœžœ˜(Kšœžœ˜(Kšžœ˜K˜K˜—šŸœž œžœžœ žœžœ!žœ˜qKšœ™™™Kšœ,˜,Kšœ—™—šžœžœžœ˜šœ!˜!Kšœžœžœ™)Kšœ!žœ˜-Kšœ ˜ Kšœžœ˜ K˜—šœ.˜.Kš œžœ žœžœžœ˜N—Kšœ˜šžœžœž˜$Kšœ!žœ˜Bšžœ ˜ KšžœžœE˜LKšžœžœH˜O—Kšžœ˜—Kšžœ˜K˜—K˜K™—š Ÿœžœžœžœžœ ˜Kšœ ˜ K˜K˜—šŸœžœžœ%˜7Kšœ$˜$K˜—K˜šŸ œžœžœžœžœžœžœ˜RKšœ0˜0Kšœžœ˜šžœžœž˜šžœ˜Kšžœ!˜%Kšžœ!˜%——K˜K˜K˜—š Ÿœžœžœ-žœžœ˜YKšœ™Kšœžœžœžœ˜1Kšœ˜Kšžœ žœžœ˜$Kšžœžœžœ ˜$K˜K˜—šŸ œžœžœžœžœžœžœ˜eKšœM™MKšΟb&™&Kšœ žœžœžœ˜1šžœžœž˜Kšœ˜Kšœ˜Kšžœ˜—Kšœ˜K˜—šŸ œžœžœ˜1K™έKšœžœ ˜Kšœ˜K˜—šŸ œžœžœ$˜=K™έšœ˜Kšœ ˜ Kšœžœ˜Kšœ ˜ Kšœ˜K˜—Kšœžœ ˜Kšœ˜K˜—šŸ œžœžœ˜*K™?šœ˜Kšœ ˜ Kšœžœ˜Kšœ˜Kšœ ˜ K˜—Kšœžœ ˜Kšœ˜——šœ™K˜šŸœžœžœ,˜IKšœ6™6Kšœžœž˜Kšœ˜K˜—šŸœžœžœ,˜JKšœ/™/Kšœžœ ˜Kšœ˜K˜—šŸ œžœžœ˜Kšœ5™5Kšœ(˜(Kšœžœ˜Kšœžœ˜Kšœžœ˜ Kšœžœ˜Kšœžœ ˜Kšœ˜Kšœ˜—K˜šŸ œžœžœ˜Kšœ6™6Kšœ(˜(Kšœžœ˜Kšœžœ˜Kšœžœ˜ Kšœžœ˜Kšœžœ ˜Kšœ˜Kšœ˜—K˜šŸœžœžœ˜ Kšœ•™•K˜KšœG˜GKšœi˜iKšœ˜K˜—šŸ œžœžœ˜Kšœ™K˜KšœB˜BKšœi˜iKšœ˜—K˜šŸ œžœžœ˜Kšœ-™-Kšœ˜Kšœ˜K˜—šŸ œžœžœ˜Kšœ-™-Kšœ˜Kšœ˜K˜—šŸœžœžœ˜Kšœ#™#Kšœ Οc(˜3šœ!‘&˜GK˜Kšœ˜K˜ —Kšœ˜K˜—šŸœžœžœ˜Kšœ ™ Kšœ ‘(˜3šœ!‘&˜GK˜Kšœ ˜ K˜ —K˜—K˜šŸ œž œ˜KšœC™CKšœ ˜ K˜K˜—šŸ œž œ˜KšœB™BKšœ˜K˜K˜—šŸ œž œ˜Kšœ‡™‡Kšœ˜K˜K˜—šŸ œž œ˜Kšœ7™7Kšœ˜Kšœ˜K˜—šŸ œž œ˜KšœC™CKšœ!˜!Kšœ˜K˜—šŸ œž œ˜KšœB™BKšœ ˜ Kšœ˜K˜—šŸ œž œ˜Kšœl™lKšœ˜Kšœ˜K˜—šŸ œž œ˜Kšœ>™>Kšœ˜Kšœ˜——™ K˜šŸœžœžœ˜Kšœ'™'KšœAžœ˜NK˜K˜—šŸœžœžœžœ˜&Kšœ'™'Kšœ0˜0Kšœ#žœ˜3Kšœ.˜.K˜—K˜—Kšžœ˜K˜—…—+¨I2