DIRECTORY MIPSArchitecture USING [MIPSInstruction, MIPSContents], BreakWorldArchitecture USING [Address], Rope USING [ROPE]; MIPSManger: CEDAR DEFINITIONS ~ { Manger: TYPE ~ MACHINE DEPENDENT RECORD [ variants: SELECT COMPUTED MangerVariant FROM normal => [ sheep1: MIPSArchitecture.MIPSInstruction, sheep2: MIPSArchitecture.MIPSInstruction, normalContinue: MIPSArchitecture.MIPSInstruction, normalNoop: MIPSArchitecture.MIPSInstruction, tag: MIPSArchitecture.MIPSInstruction, breakpointPC: MIPSArchitecture.MIPSContents], branch => [ branchB: MIPSArchitecture.MIPSInstruction, branchDelay: MIPSArchitecture.MIPSInstruction, branchContinue: MIPSArchitecture.MIPSInstruction, branchNoop: MIPSArchitecture.MIPSInstruction, tag: MIPSArchitecture.MIPSInstruction, breakpointPC: MIPSArchitecture.MIPSContents], call => [ callJ: MIPSArchitecture.MIPSInstruction, callNoop: MIPSArchitecture.MIPSInstruction, dummy1: MIPSArchitecture.MIPSInstruction, dummy2: MIPSArchitecture.MIPSInstruction, tag: MIPSArchitecture.MIPSInstruction, breakpointPC: MIPSArchitecture.MIPSContents], jump => [ jumpJ: MIPSArchitecture.MIPSInstruction, jumpNoop: MIPSArchitecture.MIPSInstruction, dummy1: MIPSArchitecture.MIPSInstruction, dummy2: MIPSArchitecture.MIPSInstruction, tag: MIPSArchitecture.MIPSInstruction, breakpointPC: MIPSArchitecture.MIPSContents] ENDCASE ]; MangerVariant: TYPE ~ { noneOfTheAbove, normal, branch, call, jump }; NormalManger: TYPE ~ Manger.normal; BranchManger: TYPE ~ Manger.branch; CallManger: TYPE ~ Manger.call; JumpManger: TYPE ~ Manger.jump; Install: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS []; Uninstall: PROCEDURE [ address: BreakWorldArchitecture.Address, manger: BreakWorldArchitecture.Address, patchCode: BreakWorldArchitecture.Address] RETURNS []; ErrorCode: TYPE ~ ATOM _ nullErrorCode; nullErrorCode: ErrorCode ~ NIL; ErrorMessage: TYPE ~ Rope.ROPE _ nullErrorMessage; nullErrorMessage: ErrorMessage ~ NIL; CantInstall: ERROR [code: ErrorCode, message: ErrorMessage]; CantUninstall: ERROR [code: ErrorCode, message: ErrorMessage]; }. MIPSManger.mesa Copyright 1992 by Xerox Corporation. All rights reserved. Katsuyuki Komatsu August 5, 1992 6:02 pm PDT Jas, October 19, 1992 5:11 pm PDT Mangers come in (for now) five flavors: normal for ordinary instructions (non-delayed control transfers), branch for simple delayed control transfers (e.g. conditional control transfers), call for jump and link & jump and link register instruction (e.g. calls), jump for jump instruction (e.g. unconditional control transfers). The tag for which kind of manger it is is kept in the ``tag'' field of the manger. The tag is used to figure out how to put the original instruction back when the breakpoint is removed. Normal instruction stream: becomes: normal manger: norm1 j patch norm1 norm2 noop norm2 continue: continue: j continue noop -- This is the normal case, we just jump to the patch to exeucte the instructions. Branch instruction stream: becomes: branch manger: bcc target j patch bcc target delaySlot noop delaySlot continue: continue: j continue noop -- With a simple delay slot, we just jump to a copy (relocated) of the instruction and its delay slot. If the branch falls through, we just transfer back to the main code stream. Call instruction stream: becomes: call manger: jal(r) target jal patch j(r) target delaySlot delaySlot noop -- The trick here is to call the patch, thus setting up the return address because the callee probably uses it (e.g. to return, or return aggregate results, etc.). We allow the instruction in the delay slot to execute (what if it messes with the return address? So be it, that's what it wanted to do.). In the manger, we jmpl to the callee without setting the return address. Jump instruction stream: becomes: jump manger: j(r) target j patch j(r) target delaySlot delaySlot noop -- This is just a computed delayed transfer. We branch to a copy of the instruction. We allow the instruction in the delay slot to execute. The breakpointPC is necessary for the MIPS breakpoints due to the their implementation of a virtual fp. A mapping from the patch code back to where the breakpoint was set. Types Manger variants are ``computed'' by examining the ``tag'' field. no delay slot has simple delay slot has delay slot, and have to get return address pointed to breakpoint address, since callee computes return point. Use a call to get to the patch. has delay slot, and is an unconditional branch. Procedures Errors NewlineDelimiter codeKKKt