<> <> <> <> DIRECTORY Atom USING [PropList, PutPropOnList], Convert USING [CardFromDecimalLiteral, CardFromHexLiteral, CardFromOctalLiteral, RealFromLiteral], DragOpsCross USING [Byte, bytesPerWord, FourBytes, Inst, JBBformat, JDist8, LRRBformat, QRformat, RJBformat, RRformat, ShortRegQR, TrapBase, TrapWidthBytes, Word, wordsPerPage, XopBase, ZerosWord], DragOpsCrossUtils USING [BytePCToWordAddress, CardToByte, CardToHalf, CardToWord, IntToWord, WordAddressToBytePC, WordToBytes, WordToCard], HandCoding USING [drJ1, drJ2, drJ3, IllegalDst, IllegalMix, IllegalSrc, Lit16, Lit8, RegSpec, ShortRegSpec], HandCodingPseudos USING [GenLabelHere, GetGlobalLabel, Label, MakeLabelGlobal], HandCodingSupport USING [Area, AreaRep, GetProc, ProcList, PutProc], IO USING [GetCedarToken, GetIndex, PutF, STREAM, TokenKind], ProcessProps USING [AddPropList, GetPropList], RefText USING [TrustTextAsRope], Rope USING [Cat, FromRefText, ROPE]; HandCodingSupportImpl: CEDAR PROGRAM IMPORTS Atom, Convert, DragOpsCrossUtils, HandCoding, HandCodingPseudos, IO, ProcessProps, RefText, Rope EXPORTS HandCodingSupport = BEGIN OPEN DragOpsCross, DragOpsCrossUtils, HandCoding, HandCodingSupport; CARD: TYPE = LONG CARDINAL; ROPE: TYPE = Rope.ROPE; initInst: CARD = TrapBase*bytesPerWord+64*TrapWidthBytes; <> initData: CARD = XopBase*bytesPerWord*2; <> <> DummyGet: GetProc = {RETURN [ZerosWord]}; DummyPut: PutProc = {}; <> NewArea: PUBLIC PROC [name: ATOM, getWord: GetProc, putWord: PutProc, data: REF _ NIL] RETURNS [Area] = { <> RETURN [NEW[AreaRep _ [ name: name, props: NIL, currentPC: initInst, currentData: initData, currentWord: ZerosWord, currentDirty: FALSE, getWord: getWord, putWord: putWord, data: data]]]; }; GenWithArea: PUBLIC PROC [area: Area, list: ProcList] = { <> inner: PROC = { FOR each: ProcList _ list, each.rest WHILE each # NIL DO each.first[]; ENDLOOP }; Gen1WithArea[area, inner]; }; <<>> Gen1WithArea: PUBLIC PROC [area: Area, proc: PROC] = { <> inner: PROC = { proc[]; ForceOut[area]; }; IF area = NIL THEN area _ GetCurrentArea[]; ProcessProps.AddPropList[ Atom.PutPropOnList[NIL, $CurrentArea, area], inner]; }; <<>> ForceOut: PUBLIC PROC [area: Area] = { <> addr: INT; index: [0..bytesPerWord); IF area = NIL THEN area _ GetCurrentArea[]; [addr, index] _ ConvertCurrentPC[area]; IF area.currentDirty THEN { area.putWord[area.data, addr, area.currentWord]; area.currentDirty _ FALSE; }; }; <<>> EmptyArea: PUBLIC ERROR = CODE; GetCurrentArea: PUBLIC PROC [nilOK: BOOL _ FALSE] RETURNS [area: Area _ NIL] = { <> FOR each: Atom.PropList _ ProcessProps.GetPropList[], each.rest WHILE each # NIL DO IF each.first.key = $CurrentArea THEN {area _ NARROW[each.first.val]; EXIT}; ENDLOOP; IF NOT nilOK AND area = NIL THEN ERROR EmptyArea; }; LoadArea: PUBLIC PROC [st, errs: IO.STREAM, area: Area _ NIL] = { buffer: REF TEXT _ NEW[TEXT[64]]; kind: IO.TokenKind _ tokenEOF; pBuffer: REF TEXT _ NEW[TEXT[64]]; pKind: IO.TokenKind _ tokenEOF; Next: PROC = { IF pKind = tokenEOF THEN { buffer.length _ 0; [tokenKind: kind, token: buffer] _ IO.GetCedarToken[st, buffer]} ELSE { temp: REF TEXT _ buffer; buffer _ pBuffer; pBuffer _ temp; kind _ pKind; pKind _ tokenEOF}; }; Peek: PROC RETURNS [c: CHAR _ 0C]= { IF pKind = tokenEOF THEN { pBuffer.length _ 0; [tokenKind: pKind, token: pBuffer] _ IO.GetCedarToken[st, pBuffer]; }; IF pBuffer.length = 1 THEN c _ pBuffer[0]; }; inner: PROC = { DO name: ROPE _ NIL; word: Word _ DragOpsCross.ZerosWord; undefined: BOOL _ FALSE; Next[]; SELECT kind FROM tokenID => { label: HandCodingPseudos.Label _ NIL; name _ Rope.FromRefText[buffer]; WHILE Peek[] = '. DO <> Next[]; Next[]; IF kind # tokenID THEN GO TO syntaxError; name _ Rope.Cat[name, ".", Rope.FromRefText[buffer]]; ENDLOOP; label _ HandCodingPseudos.GetGlobalLabel[name]; IF label = NIL THEN { undefined _ TRUE; } ELSE { word _ DragOpsCrossUtils.IntToWord[label.offset]; }; }; tokenDECIMAL => { word _ DragOpsCrossUtils.CardToWord[ Convert.CardFromDecimalLiteral[RefText.TrustTextAsRope[buffer]]]; }; tokenOCTAL => { word _ DragOpsCrossUtils.CardToWord[ Convert.CardFromOctalLiteral[RefText.TrustTextAsRope[buffer]]]; }; tokenHEX => { word _ DragOpsCrossUtils.CardToWord[ Convert.CardFromHexLiteral[RefText.TrustTextAsRope[buffer]]]; }; tokenREAL => { <> word _ DragOpsCrossUtils.CardToWord[ LOOPHOLE[Convert.RealFromLiteral[RefText.TrustTextAsRope[buffer]]]]; }; tokenEOF => EXIT; ENDCASE => GO TO syntaxError; IF Peek[] = '= THEN { <> Next[]; definition _ name; LOOP; }; IF definition # NIL THEN { <> card: CARD = GetOutputPC[area]; IF undefined THEN { <> IO.PutF[errs, "Warning: '%g' is undefined.\n", [rope[name]]]; LOOP; }; SetOutputPC[DragOpsCrossUtils.WordToCard[word], area]; HandCodingPseudos.MakeLabelGlobal[definition, HandCodingPseudos.GenLabelHere[]]; SetOutputPC[card, area]; definition _ NIL; LOOP; }; SELECT Peek[] FROM ': => { <> word _ DragOpsCrossUtils.WordAddressToBytePC[word]; SetOutputPC[DragOpsCrossUtils.WordToCard[word], area]; Next[]; wordMode _ TRUE; }; '/ => { <> SetOutputPC[DragOpsCrossUtils.WordToCard[word], area]; Next[]; wordMode _ FALSE; }; ENDCASE => { <> IF wordMode OR DragOpsCrossUtils.WordToCard[word] > 255 THEN OutputWord[area, word] ELSE OutputByte[area, DragOpsCrossUtils.WordToBytes[word][3]] }; IF undefined THEN { <> IO.PutF[errs, "Warning: '%g' is undefined.\n", [rope[name]]]; }; ENDLOOP; EXITS syntaxError => { IO.PutF[errs, "Error: bad syntax near %g, aborting the read.\n", [integer[IO.GetIndex[st]]]]; }; }; definition: ROPE _ NIL; wordMode: BOOL _ TRUE; IF area = NIL THEN area _ GetCurrentArea[]; ProcessProps.AddPropList[ Atom.PutPropOnList[NIL, $CurrentArea, area], inner]; }; <> InstToByte: PROC [inst: Inst] RETURNS [Byte] = INLINE {RETURN [LOOPHOLE[inst]]}; OQBcommon: PUBLIC PROC [op: Inst, rest: Word] = { area: Area = GetCurrentArea[]; OutputByte[area, InstToByte[op]]; OutputAlphaBetaGammaDelta[area, rest]; }; OIcommon: PUBLIC PROC [op: Inst] = { OutputByte[GetCurrentArea[], InstToByte[op]]; }; LRcommon: PUBLIC PROC [op: Inst, reg: RegSpec] = { WITH r: reg SELECT FROM reg => {op _ LOOPHOLE[LOOPHOLE[op, CARDINAL] + r.reg]}; ENDCASE => ERROR IllegalSrc; OutputByte[GetCurrentArea[], InstToByte[op]]; }; QRcommon: PUBLIC PROC [op: Inst, left: DragOpsCross.ShortRegQR, right: RegSpec] = { form: QRformat _ LOOPHOLE[0]; form.aOp _ VAL[ORD[left]]; WITH r: right SELECT FROM dstStack => ERROR IllegalSrc; reg => {form.reg _ r.reg}; aux => {form.reg _ r.aux; form.aux _ TRUE}; const => {form.reg _ r.const; form.opt _ TRUE}; srcStack => {form.reg _ r.stack; form.opt _ TRUE}; ENDCASE => ERROR IllegalSrc; form.op _ op; OutputAlphaBeta[GetCurrentArea[], LOOPHOLE[form, CARDINAL]]; }; OBcommon: PUBLIC PROC [op: Inst, lit: Lit8] = { area: Area = GetCurrentArea[]; OutputByte[area, InstToByte[op]]; OutputByte[area, CardToByte[lit]]; }; LRBcommon: PUBLIC PROC [op: Inst, reg: RegSpec, lit: Lit8] = { area: Area = GetCurrentArea[]; WITH r: reg SELECT FROM reg => {op _ LOOPHOLE[LOOPHOLE[op, CARDINAL] + r.reg]}; ENDCASE => ERROR IllegalSrc; OutputByte[area, InstToByte[op]]; OutputByte[area, CardToByte[lit]]; }; RRcommon: PUBLIC PROC [op: Inst, c: RegSpec, a,b: RegSpec] = { <> useAux: BOOL _ FALSE; useReg: BOOL _ FALSE; form: RRformat _ LOOPHOLE[ZerosWord]; WITH c: c SELECT FROM reg => {useReg _ TRUE; form.c _ c.reg}; aux => {useAux _ TRUE; form.c _ c.aux}; dstStack => {form.c _ c.stack; form.cOpt _ TRUE}; const => {form.c _ c.const; form.cOpt _ TRUE}; srcStack => ERROR IllegalDst; ENDCASE; WITH a: a SELECT FROM reg => {useReg _ TRUE; form.a _ a.reg}; aux => {useAux _ TRUE; form.a _ a.aux}; dstStack => ERROR IllegalSrc; const => {form.a _ a.const; form.aOpt _ TRUE}; srcStack => {form.a _ a.stack; form.aOpt _ TRUE}; ENDCASE; WITH b: b SELECT FROM reg => {useReg _ TRUE; form.b _ b.reg}; aux => {useAux _ TRUE; form.b _ b.aux}; dstStack => ERROR IllegalSrc; const => {form.b _ b.const; form.bOpt _ TRUE}; srcStack => {form.b _ b.stack; form.bOpt _ TRUE}; ENDCASE; IF useAux THEN { IF useReg THEN ERROR IllegalMix; form.aux _ TRUE; }; form.op _ op; OutputBytes[GetCurrentArea[], LOOPHOLE[form], 0, 3]; }; RJBcommon: PUBLIC PROC [op: Inst, left: ShortRegSpec, right: RegSpec, dist: JDist8] = { form: RJBformat _ LOOPHOLE[ZerosWord]; form.aOp _ VAL[ORD[left]]; WITH r: right SELECT FROM reg => {form.reg _ r.reg}; aux => {form.aux _ TRUE; form.reg _ r.aux}; dstStack => ERROR IllegalSrc; const => {form.reg _ r.const; form.opt _ TRUE}; srcStack => {form.reg _ r.stack; form.opt _ TRUE}; ENDCASE; form.op _ op; form.dist _ dist; OutputBytes[GetCurrentArea[], LOOPHOLE[form], 0, 3]; }; ODBcommon: PUBLIC PROC [op: Inst, lit: Lit16] = { area: Area = GetCurrentArea[]; OutputByte[area, InstToByte[op]]; OutputAlphaBeta[area, lit]; }; LRRBcommon: PUBLIC PROC [op: Inst, reg1,reg2: RegSpec, disp: Lit8] = { area: Area = GetCurrentArea[]; form: LRRBformat _ LOOPHOLE[ZerosWord]; form.op _ op; form.disp _ disp; WITH r: reg1 SELECT FROM reg => {form.reg1 _ r.reg}; aux => {form.reg1 _ r.aux}; ENDCASE => ERROR IllegalSrc; WITH r: reg2 SELECT FROM reg => {form.reg2 _ r.reg}; aux => {form.reg2 _ r.aux}; ENDCASE => ERROR IllegalSrc; OutputBytes[GetCurrentArea[], LOOPHOLE[form], 0, 3]; }; JBBcommon: PUBLIC PROC [op: Inst, dist: JDist8, lit: Lit8] = { form: JBBformat _ LOOPHOLE[ZerosWord]; form.op _ op; form.dist _ dist; form.lit _ lit; OutputBytes[GetCurrentArea[], LOOPHOLE[form], 0, 3]; }; <> GetOutputPC: PUBLIC PROC [area: Area _ NIL] RETURNS [CARD] = { <> IF area = NIL THEN area _ GetCurrentArea[]; RETURN [area.currentPC]; }; SetOutputPC: PUBLIC PROC [pc: CARD, area: Area _ NIL] = { <> addr: CARD; index: [0..bytesPerWord); IF area = NIL THEN area _ GetCurrentArea[]; [addr, index] _ ConvertCurrentPC[area]; IF area.currentDirty THEN { <> area.putWord[area.data, addr, area.currentWord]; area.currentDirty _ FALSE; }; area.currentPC _ pc; [addr, index] _ ConvertCurrentPC[area]; }; WordAlign: PUBLIC PROC [area: Area _ NIL] = { <> addr: CARD; index: [0..bytesPerWord); IF area = NIL THEN area _ GetCurrentArea[]; [addr, index] _ ConvertCurrentPC[area]; SELECT index FROM 1 => {HandCoding.drJ3[]; HandCoding.drJ1[]; HandCoding.drJ1[]}; 2 => {HandCoding.drJ2[]; HandCoding.drJ1[]}; 3 => HandCoding.drJ1[]; ENDCASE => {}; }; ReserveData: PUBLIC PROC [words: CARD, area: Area _ NIL] RETURNS [pc: CARD] = { <> old: CARD; IF area = NIL THEN area _ GetCurrentArea[]; old _ area.currentPC; SetOutputPC[area.currentData, area]; WordAlign[area]; pc _ area.currentPC; area.currentData _ area.currentData + words*bytesPerWord; OutputWord[area, ZerosWord, FALSE]; WHILE words > wordsPerPage DO SetOutputPC[pc+(words-1)*bytesPerWord, area]; OutputWord[area, ZerosWord, FALSE]; words _ words - wordsPerPage; ENDLOOP; SetOutputPC[old, area]; }; OutputByte: PUBLIC PROC [area: Area, byte: Byte] = { <> addr: CARD; index: [0..bytesPerWord); IF area = NIL THEN area _ GetCurrentArea[]; [addr, index] _ ConvertCurrentPC[area]; IF NOT area.currentDirty THEN { area.currentWord _ area.getWord[area.data, addr]; area.currentDirty _ TRUE; }; LOOPHOLE[area.currentWord, FourBytes][index] _ byte; area.currentPC _ area.currentPC + 1; IF index = bytesPerWord-1 THEN { area.putWord[area.data, addr, area.currentWord]; area.currentDirty _ FALSE; }; }; <<>> OutputOneByte: PUBLIC PROC [area: Area, word: Word] = { <> OutputByte[area, WordToBytes[word][3]]; }; <<>> OutputAlphaBeta: PUBLIC PROC [area: Area, lit: Lit16] = { <> IF area = NIL THEN area _ GetCurrentArea[]; OutputByte[area, LOOPHOLE[lit / 256]]; OutputByte[area, LOOPHOLE[lit MOD 256]]; }; <<>> OutputAlphaBetaGammaDelta: PUBLIC PROC [area: Area, word: Word] = { <> IF area = NIL THEN area _ GetCurrentArea[]; OutputByte[area, WordToBytes[word][0]]; OutputByte[area, WordToBytes[word][1]]; OutputByte[area, WordToBytes[word][2]]; OutputByte[area, WordToBytes[word][3]]; }; <<>> OutputWord: PUBLIC PROC [area: Area, word: Word, align: BOOL _ FALSE] = { <> addr: CARD; index: [0..bytesPerWord); IF area = NIL THEN area _ GetCurrentArea[]; [addr, index] _ ConvertCurrentPC[area]; IF area.currentDirty THEN { area.putWord[area.data, addr, area.currentWord]; area.currentDirty _ FALSE; }; SELECT TRUE FROM index = 0 => { area.putWord[area.data, addr, word]; area.currentPC _ area.currentPC + 4; }; align => { area.putWord[area.data, addr+1, word]; area.currentPC _ area.currentPC + (bytesPerWord - index) + 4 }; ENDCASE => OutputBytes[area, WordToBytes[word], 0, 4]; }; <> OutputBytes: PROC [area: Area, bytes: FourBytes, start: NAT, len: NAT] = { <> addr: CARD; index: NAT; [addr, index] _ ConvertCurrentPC[area]; THROUGH [0..len) DO IF NOT area.currentDirty THEN { area.currentWord _ area.getWord[area.data, addr]; area.currentDirty _ TRUE; }; LOOPHOLE[area.currentWord, FourBytes][index] _ bytes[start]; start _ start + 1; index _ index + 1; IF index = bytesPerWord THEN { area.putWord[area.data, addr, area.currentWord]; area.currentDirty _ FALSE; addr _ addr + 1; index _ 0; }; ENDLOOP; area.currentPC _ area.currentPC + len; }; ConvertCurrentPC: PROC [area: Area] RETURNS [addr: CARD, index: NAT] = INLINE { <> word: Word _ DragOpsCrossUtils.CardToWord[area.currentPC]; [word, index] _ DragOpsCrossUtils.BytePCToWordAddress[[word]]; addr _ DragOpsCrossUtils.WordToCard[word]; }; END.