DIRECTORY Atom USING [PropList, PutPropOnList], DragOpsCross USING [FieldDescriptor, ioRescheduleRequest, ioResetRequest, JDist8, PCmdFormat, ProcessorRegister, Word], DragOpsCrossUtils USING [CardToWord, HalfToCard, IntToWord, WordToBytes, WordToHalves], HandCoding USING [const0, const1, ConstSpec, drADDB, drADDDB, 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, 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; 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]], [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]] ELSE drADDB[DeltaLabels[dest, 2, 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) March 19, 1987 10:51:56 am PST 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 ... 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. ΚΠ˜codešœ™KšœN™NK™2K™+K˜šΟk ˜ Kšœœ˜%Kšœ œe˜wKšœœ@˜WKšœ œφ˜†Kšœœ˜*Kšœœh˜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š œœœœœ˜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šœœ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˜—…—(.C†