DIRECTORY Atom USING [PropList, PutPropOnList], Basics USING [LowHalf], DragOpsCross USING [Byte, ByteAddress, bytesPerPage, bytesPerWord, FieldDescriptor, ioRescheduleRequest, ioResetRequest, JDist8, PCmdFormat, ProcessorRegister, Word, ZerosByte], DragOpsCrossUtils USING [BytePCToWordAddress, CardToWord, HalfToCard, IntToWord, WordToBytes, WordToHalves], HandCoding USING [const0, const1, ConstSpec, drADDB, drADDDB, drADDQB, drALS, drDUP, drFSDB, drJSR, drLC1, drLIP, drLIQB, drLRn, drIODA, drQOR, drQRX, drRADD, drRET, drRETN, drROR, drRRX, drRSUB, drSHL, drSHR, drSIP, drSRn, Lit16, Lit8, popSrc, pushDst, RegSpec, topSrc], HandCodingPseudos USING [Label, LabelRep], HandCodingSupport USING [Area, GetCurrentArea, OutputAlphaBeta, OutputAlphaBetaGammaDelta, OutputByte, OutputWord, 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, Basics, 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; Label: TYPE = HandCodingPseudos.Label; LabelRep: TYPE = HandCodingPseudos.LabelRep; LabelUsageList: TYPE = LIST OF LabelUsage; LabelUsage: TYPE = RECORD [ area: Area, offset: INT _ 0, delta: INT _ 0, distWidth: [0..4] _ 1, fixoff: [0..4] _ 0, wordAddr: BOOL ]; 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 => { delta: Word _ DragOpsCrossUtils.IntToWord[here - use.delta]; IF use.wordAddr THEN { offset: [0..bytesPerWord) _ 0; [delta, offset] _ DragOpsCrossUtils.BytePCToWordAddress[[delta]]; IF offset # 0 THEN ERROR LabellingError["label not on word boundary"]; }; HandCodingSupport.OutputAlphaBetaGammaDelta[area, 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, 1]; 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, 1]]]; }; GenDataLabel: PUBLIC PROC [area: Area, bytes: CARD] RETURNS [label: Label _ NIL] = { zerosByte: DragOpsCross.Byte _ DragOpsCross.ZerosByte; old: CARD _ (IF area = NIL THEN area _ HandCodingSupport.GetCurrentArea[] ELSE area).currentPC; pc: CARD _ area.currentData; HandCodingSupport.SetOutputPC[pc, area]; label _ GenLabelHere[]; IF bytes # 0 THEN DO mod: CARDINAL _ Basics.LowHalf[pc] MOD bytesPerPage; rem: CARDINAL _ bytesPerPage - mod; HandCodingSupport.OutputByte[area, zerosByte]; IF bytes > rem THEN { pc _ pc + rem; bytes _ bytes - rem; HandCodingSupport.SetOutputPC[pc, area]; } ELSE { area.currentData _ pc + bytes; bytes _ 0; EXIT; }; ENDLOOP; HandCodingSupport.SetOutputPC[old, area]; }; OutputWordAddr: PUBLIC PROC [area: Area, label: Label, offset: INT _ 0] = { addr: INT _ DeltaLabels[label, offset, 4, 0, TRUE]; HandCodingSupport.OutputWord[area, DragOpsCrossUtils.IntToWord[addr], FALSE]; }; OutputByteAddr: PUBLIC PROC [area: Area, label: Label, offset: INT _ 0] = { addr: INT _ DeltaLabels[label, offset, 4, 0, FALSE]; HandCodingSupport.OutputWord[area, DragOpsCrossUtils.IntToWord[addr], FALSE]; }; PushWordAddr: PUBLIC PROC [area: Area, label: Label, offset: INT _ 0] = { addr: INT _ DeltaLabels[label, offset, 4, 1, TRUE]; drLIQB[DragOpsCrossUtils.IntToWord[addr]]; }; PushByteAddr: PUBLIC PROC [area: Area, label: Label, offset: INT _ 0] = { addr: INT _ DeltaLabels[label, offset, 4, 1, FALSE]; drLIQB[DragOpsCrossUtils.IntToWord[addr]]; }; AddWordAddr: PUBLIC PROC [area: Area, label: Label, offset: INT _ 0] = { addr: INT _ DeltaLabels[label, offset, 4, 1, TRUE]; drADDQB[DragOpsCrossUtils.IntToWord[addr]]; }; AddByteAddr: PUBLIC PROC [area: Area, label: Label, offset: INT _ 0] = { addr: INT _ DeltaLabels[label, offset, 4, 1, FALSE]; drADDQB[DragOpsCrossUtils.IntToWord[addr]]; }; DeltaLabels: PROC [label: Label, plus: INT, width: [0..4], fixoff: NAT, word: BOOL _ FALSE] RETURNS [INT] = { pc: CARD; area: Area = HandCodingSupport.GetCurrentArea[]; pc _ area.currentPC; SELECT label.area FROM area => { delta: INT _ label.offset + plus; SELECT TRUE FROM width # 4 => delta _ delta - pc; word => delta _ LOOPHOLE[delta, CARD] / CARD[bytesPerWord]; ENDCASE; RETURN [delta]; }; NIL => { uses: LabelUsageList _ NARROW[label.uses]; uses _ CONS[[area: area, offset: pc, distWidth: width, delta: plus, fixoff: fixoff, wordAddr: word], 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]], [cardinal[label.offset]]] ELSE IO.PutF[st, " -- %w: %g\n", [cardinal[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] = { SELECT TRUE FROM reg.kind = reg => drLRn[reg]; reg = topSrc => drDUP[]; ENDCASE => drQOR[pushA0, reg]; }; 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] = { SELECT const FROM const0 => drQRX[pushA0, reg]; const1 => drQRX[pushA1, reg]; ENDCASE => 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, 1]] ELSE drADDB[DeltaLabels[dest, -2, 1, 1]]; drJSR[]; }; 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] = { lit: Lit8 _ (LOOPHOLE[rets, CARDINAL]-1) MOD 256; SELECT TRUE FROM 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]]; }; CauseReschedule: PUBLIC PROC = { pCmd: DragOpsCross.PCmdFormat _ [cache[space: io, direction: write]]; drLC1[]; drLIQB[DragOpsCrossUtils.CardToWord[DragOpsCross.ioRescheduleRequest]]; drIODA[LOOPHOLE[pCmd]]; }; CauseReset: PUBLIC PROC = { pCmd: DragOpsCross.PCmdFormat _ [cache[space: io, direction: write]]; drLC1[]; drLIQB[DragOpsCrossUtils.CardToWord[DragOpsCross.ioResetRequest]]; drIODA[LOOPHOLE[pCmd]]; }; GetSPLimit: PUBLIC PROC = { LoadProcessorReg[ifuSLimit]; }; SetSPLimit: PUBLIC PROC = { StoreProcessorReg[ifuSLimit]; }; GetYoungestPC: PUBLIC PROC = { LoadProcessorReg[ifuYoungestPC]; }; GetYoungestStatus: PUBLIC PROC = { LoadProcessorReg[ifuYoungestL]; }; GetEldestPC: PUBLIC PROC = { LoadProcessorReg[ifuEldestPC]; }; GetEldestStatus: PUBLIC PROC = { LoadProcessorReg[ifuEldestL]; }; SetYoungestPC: PUBLIC PROC = { StoreProcessorReg[ifuYoungestPC]; }; SetYoungestStatus: PUBLIC PROC = { StoreProcessorReg[ifuYoungestL]; }; SetEldestPC: PUBLIC PROC = { StoreProcessorReg[ifuEldestPC]; }; SetEldestStatus: 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. °HandCodingPseudosImpl.mesa Copyright Ó 1984, 1985, 1986, 1987 by Xerox Corporation. All rights reserved. Russ Atkinson (RRA) April 24, 1987 5:02:57 pm PDT McCreight, December 31, 1985 3:14:26 pm PST Labelling 4-byte addresses are absolute, not relative Reserves a given number of data bytes and returns a label to the start of the bytes. No alignment takes place. Puts out the label as a word address into the code stream. No alignment takes place. Puts out the label as a byte address into the code stream. No alignment takes place. Pushes the label as a word address. No alignment takes place. Pushes the label as a byte address. No alignment takes place. Adds the label as a word address to [S]. No alignment takes place. Adds the label as a byte address to [S]. No alignment takes place. 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 ... 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 correct 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. ... 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. ... 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. Êv˜codešœ™KšœN™NK™1K™+K˜šÏk ˜ Kšœœ˜%Kšœœ ˜Kšœ œŸ˜±KšœœU˜lKšœ œÿ˜Kšœœ˜*Kšœœt˜‹Kšœœœ˜!Kšœœ1˜DKšœœ œ˜Kšœœ=˜I——headšœœ˜$KšœAœ˜gKšœ˜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šœ<˜<šœœ˜Kšœ˜KšœA˜AKšœ œœ.˜FK˜—Kšœ9˜9K˜—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šœ<˜BK˜K˜—š ž œœœœœœ˜TK™oKšœ6˜6Kš œœœœœ+œ˜_Kšœœ˜Kšœ(˜(K˜šœ œ˜Kšœœœ˜4Kšœœ˜#Kšœ.˜.šœ ˜šœ˜Kšœ˜Kšœ˜Kšœ(˜(K˜—šœ˜Kšœ˜Kšœ ˜ Kšœ˜K˜——Kšœ˜—Kšœ)˜)K˜K™—šžœœœ$œ ˜KK™UKšœœ$œ˜3KšœFœ˜MK˜K™—šžœœœ$œ ˜KK™UKšœœ$œ˜4KšœFœ˜MK˜K™—šž œœœ$œ ˜IK™>Kšœœ$œ˜3Kšœ*˜*K˜K™—šž œœœ$œ ˜IK™>Kšœœ$œ˜4Kšœ*˜*K˜K™—šž œœœ$œ ˜HK™CKšœœ$œ˜3Kšœ+˜+K˜K™—šž œœœ$œ ˜HK™CKšœœ$œ˜4Kšœ+˜+K˜K™—šž œœœœœœœœ˜mKšœö™öKšœœ˜ Kšœ0˜0Kšœ˜šœ ˜šœ ˜ Kšœ‚™‚Kšœœ˜!šœœ˜Kšœ ˜ Kšœœœœ˜;Kšœ˜—Kšœ ˜Kšœ˜—šœ˜K™BKšœœ ˜*Kšœœ`˜kKšœ˜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šœœF˜MKšœœI˜P—Kšœ˜—Kšœ˜K˜—K˜K™—š žœœœœœ ˜Kšœ ˜ K˜K˜—šžœœœ%˜7šœ˜Kšœ˜Kšœ˜Kšœ(˜/—K˜—K˜šž œœœœœœœ˜RKšœ0˜0Kšœœ˜šœœ˜šœ˜Kšœ%˜)Kšœ%˜)——Kšœ˜K˜K˜—š žœœœ-œœ˜YKšœ™Kšœœœœ˜1Kšœ˜Kšœ œœ˜$Kšœœœ ˜$K˜K˜—š ž œœœœœ˜JKšœ(™(Kšœ œœœ˜1šœœ˜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šœ•™•KšœE˜EK˜KšœG˜GKšœœ˜Kšœ˜K˜—šž œœœ˜Kšœ™KšœE˜EK˜KšœB˜BKšœœ˜Kšœ˜—K˜šž œœœ˜Kšœ-™-Kšœ˜Kšœ˜K˜—šž œœœ˜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˜—…—1QB