DIRECTORY TamarinOps, TamarinOpsUtils, Rope USING [ROPE]; MonkeyHeart: CEDAR DEFINITIONS IMPORTS TamarinOpsUtils = BEGIN OPEN TamarinOps, TamarinOpsUtils; Processor: TYPE = REF ProcessorRep; -- eventually something else ProcessorRep: TYPE = RECORD [ logger: ChangeLogger _ NIL, ccResult: BOOL _ FALSE, resetRequested: BOOL _ TRUE, trapsEnabled: BOOL _ FALSE, version: [0..255] _ 0, stats: ProcessorStats _ [], lastCallRtn: INT _ 0, -- inst count of last call/return instBuffer: InstBuffer _ NIL, euCarry: BOOL _ FALSE, vmMap: VMMap _ NIL, regs: ARRAY ProcessorRegister OF TaggedWord _ ALL[TagZerosWord], regsGood: ARRAY ProcessorRegister OF BOOL _ ALL[FALSE], mi: MicroCode _ NIL, nextuPCa: NAT _ 0, nextuPCb: NAT _ 0, memory: Memory _ NIL, memState: {deadCycle, ifStarted, dfStarted, blockdfStarted} ]; Memory: TYPE = REF MemoryRep; MemoryRep: TYPE = RECORD [ fetch: MemFetchProc _ NIL, write: MemWriteProc _ NIL]; MemFetchProc: TYPE = PROC [processor: Processor, addr: Word, old,new: Word] RETURNS [word: Word, tx: TrapIndex, rCycles: NAT]; MemWriteProc: TYPE = PROC [data: REF, processor: Processor, addr: Word, old,new: Word] RETURNS [word: Word, tx: TrapIndex, rCycles: NAT]; microCodeWidth: NAT = 109; microCodeHeight: NAT = 512; MicroCode: TYPE = REF MicroCodeRep; MicroCodeRep: TYPE = ARRAY [0..512) OF MicroInstruction; MicroInstruction: TYPE = MACHINE DEPENDENT RECORD [ readCxt (0: 15..15): BOOL, -- 1 bit writeCxt (0: 14..14): BOOL, -- 1 bit newTopCxt (0: 13..13): BOOL, -- 1 bit newBotCxt (0: 12..12): BOOL, -- 1 bit altCxt (0: 9..11): [0..8), -- 3 bits memOp( 0: 3..8): [0..64), -- 6 bits tag (0: 0..2): [0..4), -- 2 bits euOp (1: 9..15): [0..128), -- 7 bits rd1Addr (1: 6..8): [0..8), -- 3 bits rd2Addr (1: 3..5): [0..8), -- 3 bits w2Addr (1: 0..2): [0..8), -- 3 bits dswap (2: 15..15): BOOL, -- 1 bit rAddr (2: 12..14): [0..8), -- 3 bits waddr (2: 9..11): [0..8), -- 3 bits newarg (2: 7..8): [0..4), -- 2 bits newarg2 (2: 5..6): [0..4), -- 2 bits newtos (2: 3..4): [0..4), -- 2 bits muxread (2: 0..2): [0..8), -- 3 bits muxwrite (3: 12..15): [0..16), -- 4 bits tosPrime (3: 11..11): BOOL, -- 1 bit argPrime (3: 10..10): BOOL, -- 1 bit arg2Prime (3: 9..9): BOOL, -- 1 bit k (3: 0..8): [0..512), -- 9 bits invertCCode (4: 15..15): BOOL, -- 1 bit dpCCode (4: 8..14): [0..128), -- 7 bits muxCCode (4: 1..7): [0..32), -- 5 bits only updatePC (4: 0..0): BOOL, -- 1 bit resultCCode (5: 11..15): [0..32), -- 5 bits memCCode (5: 9..10): [0..4), -- 2 bits writeOnTrue (5: 8..8): BOOL, -- 1 bit nextInstA (5: 0..7): [0..256), -- 8 bits nextInstB (6: 8..15): [0..256), -- 8 bits misc (6: 3..7): [0..32), -- 5 bits opLength (6: 0..2): [0..8) -- 3 bits ]; readCxtPos: INT = 108; readCxtLen: INT = 1; writeCxtPos: INT = 107; writeCxtLen: INT = 1; newTopCxtPos: INT = 106; newTopCxtLen: INT = 1; newBotCxtPos: INT = 105; newBotCxtLen: INT = 1; altCxtPos: INT = 102; altCxtLen: INT = 3; memOpPos: INT = 96; memOpLen: INT = 6; tagPos: INT = 94; tagLen: INT = 2; euOpPos: INT = 87; euOpLen: INT = 7; rd1AddrPos: INT = 84; rd1AddrLen: INT = 3; rd2AddrPos: INT = 81; rd2AddrLen: INT = 3; w2AddrPos: INT = 78; w2AddrLen: INT = 3; dswapPos: INT = 77; dswapLen: INT = 1; rAddrPos: INT = 74; rAddrLen: INT = 3; waddrPos: INT = 71; waddrLen: INT = 3; newargPos: INT = 69; newargLen: INT = 2; newarg2Pos: INT = 67; newarg2Len: INT = 2; newtosPos: INT = 65; newtosLen: INT = 2; muxreadPos: INT = 62; muxreadLen: INT = 3; muxwritePos: INT = 58; muxwriteLen: INT = 4; tosPrimePos: INT = 57; tosPrimeLen: INT = 1; argPrimePos: INT = 56; argPrimeLen: INT = 1; arg2PrimePos: INT = 55; arg2PrimeLen: INT = 1; kPos: INT = 49; kLen: INT = 9; invertCCodePos: INT = 45; invertCCodeLen: INT = 1; dpCCodePos: INT = 38; dpCCodeLen: INT = 7; muxCCodePos: INT = 33; muxCCodeLen: INT = 5; updatePCPos: INT = 32; updatePCLen: INT = 1; resultCCodePos: INT = 27; resultCCodeLen: INT = 5; memCCodePos: INT = 25; memCCodeLen: INT = 2; writeOnTruePos: INT = 24; writeOnTrueLen: INT = 1; nextInstAPos: INT = 16; nextInstALen: INT = 8; nextInstBPos: INT = 8; nextInstBLen: INT = 8; miscPos: INT = 3; miscLen: INT = 5; opLengthPos: INT = 0; opLengthLen: INT = 3; VMMap: TYPE = REF VMMapRep; VMMapRep: TYPE = RECORD [ entryValid: BOOL, virtualPage: Word, physPage: Word, pageFault: BOOL, pageDirty: BOOL]; CondCode: TYPE = PACKED ARRAY [0..3) OF BOOL; InstBuffer: TYPE = REF InstBufferRep; InstBufferRep: TYPE = RECORD [ basePC: Word _ ZerosWord, -- index of PC corresponding to startValid nextPC: Word _ ZerosWord, -- next PC in straightline code validWords: IBufWordIndex _ 0, -- # of valid words in buffer bytesDiscarded: INT _ 0, forcedEmpty: INT _ 0, -- # of times forced empty refillAtPriority: BOOL _ TRUE, -- flag for setting refill priority words: SEQUENCE max: NAT OF Word ]; IBufWordIndex: TYPE = [0..NumIBufWords); NumIBufWords: NAT = 4; IBufIndex: TYPE = [0..NumIBufWords*bytesPerWord); ProcessorStats: TYPE = RECORD [ instructions: INT _ 0, cycles: INT _ 0, euFetches: INT _ 0, euStores: INT _ 0, instBytes: INT _ 0, jumps: INT _ 0, calls: INT _ 0, stackOver: INT _ 0, instBufferCycles: INT _ 0, lookaheadProbes: INT _ 0, lookaheadRejects: INT _ 0 ]; ChangeLogger: TYPE = REF ChangeLoggerRep; ChangeLoggerRep: TYPE = RECORD [ data: REF _ NIL, regChange: RegChangeProc _ NIL, memChange: MemChangeProc _ NIL, ioChange: IOChangeProc _ NIL, instStart: InstStartProc _ NIL, instDone: InstDoneProc _ NIL ]; RegChangeProc: TYPE = PROC [data: REF, processor: Processor, reg: ProcessorRegister, old,new: Word]; MemChangeProc: TYPE = PROC [data: REF, processor: Processor, addr: Word, old,new: Word]; IOChangeProc: TYPE = PROC [data: REF, processor: Processor, addr: Word, old,new: Word]; InstStartProc: TYPE = PROC [data: REF, processor: Processor, thisPC: Word, inst: Inst, rest: Word]; InstDoneProc: TYPE = PROC [data: REF, processor: Processor, newPC, rtnPC: Word, control: Control, cycles: INT]; Control: TYPE = {nextOpcode, nextuInst, doCall, doReturn, doAbort}; ALUOps: TYPE = MACHINE DEPENDENT { SAdd(0), SSub(1), UAdd(2), USub(3), VAdd(4), VSub(5), LAdd(6), LSub(7), FOP(8), FOPK(9), And(10), Or(11), Xor(12), BndChk(13), Reserve14(14), Reserve15(15), Reserve16(16), Reserve17(17), Reserve18(18), Reserve19(19), Reserve20(20), Reserve21(21), Reserve22(22), Reserve23(23), Reserve24(24), Reserve25(25), Reserve26(26), Reserve27(27), Reserve28(28), Reserve29(29), Reserve30(30), Reserve31(31)}; EUPageFault: TrapIndex = EUPageFault; EUWriteFault: TrapIndex = EUWriteFault; NoFault: TrapIndex = ALUCondFalse; NoTLBmiss: TrapIndex = ALUCondFalse; NewProcessor: PROC [logger: ChangeLogger] RETURNS [Processor]; InstructionExecute: PROC [processor: Processor]; FlushInstBuffer: PROC [processor: Processor]; Signs: TYPE = MACHINE DEPENDENT { a0b0c0 (0), a0b0c1 (1), a0b1c0 (2), a0b1c1 (3), a1b0c0 (4), a1b0c1 (5), a1b1c0 (6), a1b1c1 (7)}; ALUHelper: PROC [a,b,c: BOOL] RETURNS [Signs] = INLINE { RETURN [LOOPHOLE[ 4*LOOPHOLE[a, CARDINAL] + 2*LOOPHOLE[b, CARDINAL] + LOOPHOLE[c, CARDINAL]]]; }; InstBytes: PROC [inst: Inst] RETURNS [bytes: [1..5]] = INLINE { SELECT LOOPHOLE[inst, CARDINAL] FROM < 40B => bytes _ 1; < 100B => bytes _ 5; ENDCASE => bytes _ LOOPHOLE[inst, CARDINAL] / 64; }; RegPlus: PROC [reg: ProcessorRegister, delta: INTEGER] RETURNS [ProcessorRegister] = INLINE { RETURN [LOOPHOLE[(LOOPHOLE[reg, CARDINAL] + LOOPHOLE[delta, CARDINAL]) MOD 256]]; }; StackPlus: PROC [reg: ProcessorRegister, delta: INTEGER] RETURNS [ProcessorRegister] = INLINE { RETURN [LOOPHOLE[(LOOPHOLE[reg, CARDINAL] + LOOPHOLE[delta, CARDINAL]) MOD 128]]; }; AlphaZ: PROC [rest: Word] RETURNS [CARDINAL] = INLINE { RETURN [LOOPHOLE[WordToBytes[rest][3]]]; }; AlphaBetaZ: PROC [rest: Word] RETURNS [CARDINAL] = INLINE { RETURN [LOOPHOLE[WordToHalves[rest][1]]]; }; AlphaS: PROC [rest: Word] RETURNS [INTEGER] = INLINE { i: INTEGER _ LOOPHOLE[WordToBytes[rest][3], CARDINAL]; RETURN [IF i > 127 THEN i _ i - 256 ELSE i]; }; AlphaBetaS: PROC [rest: Word] RETURNS [INTEGER] = INLINE { RETURN [LOOPHOLE[WordToHalves[rest][1]]]; }; BetaZ: PROC [rest: Word] RETURNS [CARDINAL] = INLINE { RETURN [LOOPHOLE[WordToBytes[rest][2]]]; }; BetaS: PROC [rest: Word] RETURNS [INTEGER] = INLINE { i: INTEGER _ LOOPHOLE[WordToBytes[rest][2], CARDINAL]; RETURN [IF i > 127 THEN i _ i - 256 ELSE i]; }; WordToReg: PROC [word: Word] RETURNS [ProcessorRegister] = INLINE { RETURN [LOOPHOLE[WordToBytes[word][3]]]; }; RegToWord: PROC [reg: ProcessorRegister] RETURNS [Word] = INLINE { RETURN [HalvesToWord[[LOOPHOLE[0], LOOPHOLE[reg]]]]; }; TrapPC: PUBLIC PROC [tx: TamarinOps.TrapIndex] RETURNS [Word] = INLINE { RETURN [CardToWord[TamarinOpsUtils.TrapIndexToBytePC[tx]]]; }; DoALUOp: PUBLIC PROC [processor: Processor, wordA,wordB: Word, op: ALUOps, trap: TrapIndex] RETURNS [res: Word, resCode: TrapIndex _ NoFault]; FieldUnit: PUBLIC PROC [Left,Right: Word, fd: FieldDescriptor] RETURNS [out: Word]; WillPushOverflow: PUBLIC PROC [processor: Processor] RETURNS [BOOL]; OutsideEnvelope: PUBLIC SIGNAL [explanation: Rope.ROPE]; END. `MonkeyHeart.mesa Copyright Σ 1987 by Xerox Corporation. All rights reserved. Pilfered by Ross January 28, 1987 11:57:47 am PST Originally by Russ Atkinson (RRA) September 16, 1986 6:25:55 am PDT Last Edited by: Ross February 3, 1987 3:56:39 pm PST Interface for Basic Tamarin machine. Borrowed heavily from LizardHeart.mesa (notice even the name similarities). Position and Length of all MicroCodeWords: Circular buffer used to hold instructions for decoding. Number of unconditional jump instructions Number of call instructions Stack overflows Cycles spent waiting for instructions Cache fetches due to instruction buffer lookahead Reject cycles due to instruction buffer lookahead Copied from /Indigo/Dragon/Rosemary/Dragon.mesa Used to indicate page fault from cache, even for IFU fetches. Used to indicate write protect fault from EU cache. Any unused code will do. But we need a state to indicate that everything is OK. Any unused code will do. But we need a state to indicate that everything is OK. This routine flushes the instruction buffer. This occurs on a bad jump prediction, a trap, or an xop. INLINE routines for picking apart various pieces of the input Utility Routines for manipulating data (incomplete) Turns a trap index into a byte PC. This is a full routine to keep from making the compiler unhappy with excessive INLINEs. ... returns TRUE if the next push will overflow the IFU stack. Signals OutsideEnvelope in illegal cases. The program has been caught red-handed doing something that no reasonable Tamarin program should do; something for which the hardware response needn't be defined. Κ ~˜codešœ™Kšœ<™˜M—šœžœ˜KšžœžœFžœ˜ZK˜—K˜Kšœ žœ6˜CK˜šœžœžœž œ˜"Kšœ/™/KšœHžœžœΉ˜K˜—šœ%˜%Kšœ=™=—šœ'˜'Kšœ3™3K˜—šœ"˜"KšœMžœ™P—šœ$˜$KšœMžœ™P—K˜šΟn œžœžœ ˜>K˜—Kš œžœ˜0K˜š œžœ˜-Kšœf™fK˜——šœ=™=K˜šœžœžœž œ˜!K˜0K˜0K˜—š   œžœ žœžœ žœ˜8šžœžœ˜Kš œžœžœžœžœžœžœ˜L—K˜K˜—š  œžœžœžœ˜?šžœžœžœž˜$K˜K˜Kšžœ žœžœ˜1—K˜K˜—š  œžœ!žœžœžœ˜]Kšžœžœžœžœžœžœžœ˜QK˜K˜—š  œž˜Kšœ žœžœžœ˜OKšžœžœžœžœžœžœžœ˜QK˜K˜—š  œžœžœžœžœ˜7Kšžœžœ˜(K˜K˜—š   œžœžœžœžœ˜;Kšžœžœ˜)K˜K˜—š  œžœžœžœžœ˜6Kšœžœžœžœ˜6Kšžœžœ žœ žœ˜,K˜K˜—š   œžœžœžœžœ˜:Kšžœžœ˜)K˜K˜—š  œžœžœžœžœ˜6Kšžœžœ˜(K˜K˜—š  œžœžœžœžœ˜5Kšœžœžœžœ˜6Kšžœžœ žœ žœ˜,K˜K˜—š  œžœžœžœ˜CKšžœžœ˜(Kšœ˜K˜—š  œžœžœ žœ˜BKšžœžœžœ ˜4Kšœ˜—K™Kšœ3™3K˜š œž œžœ žœ˜HKšœ{™{Kšžœ5˜;K˜—K˜š œž œGžœ+˜ŽK˜—Kš  œž œ)žœ ˜SK˜š  œžœžœžœžœ˜DKšœi™i—K˜šœžœžœžœ˜8Kšœ’™’—K˜K˜—Kšžœ˜K˜˜K˜J˜——…—#Š7h