DIRECTORY Breakpoint, BreakpointPrivate, BreakWorldArchitecture, Rope USING [ROPE], Shepherd, MIPSArchitecture, MIPSBreakpoint, MIPSBreakWorldUtilities, MIPSManger, TargetArchitecture; MIPSBreakpointImpl: CEDAR PROGRAM IMPORTS Breakpoint, BreakpointPrivate, BreakWorldArchitecture, Shepherd, MIPSArchitecture, MIPSBreakWorldUtilities, MIPSManger, TargetArchitecture ~ { SetBreakpoint: BreakpointPrivate.SetBreakProcType ~ { break: Breakpoint.Break _ Breakpoint.nullBreak; patch: Shepherd.Patch _ Shepherd.nullPatch; errorCode: Breakpoint.ErrorCode _ Breakpoint.nullErrorCode; errorMessage: Breakpoint.ErrorMessage _ Breakpoint.nullErrorMessage; CheckForDelaySlot: PROCEDURE [address: BreakWorldArchitecture.Address] RETURNS [] ~{ instruction: MIPSArchitecture.MIPSInstruction ~ MIPSBreakWorldUtilities.MIPSInstructionFromBreakWorldAddress[address: address]; prevInstruction: MIPSArchitecture.MIPSInstruction ~ MIPSBreakWorldUtilities.MIPSInstructionFromBreakWorldAddress[ address: address, displacement: -BYTES[MIPSArchitecture.MIPSInstruction]]; nextInstruction: MIPSArchitecture.MIPSInstruction ~ MIPSBreakWorldUtilities.MIPSInstructionFromBreakWorldAddress[ address: address, displacement: +BYTES[MIPSArchitecture.MIPSInstruction]]; IF MIPSArchitecture.IsDelayedControlTransfer[instruction: prevInstruction] THEN { ERROR Breakpoint.CantSet[ code: $NotInDelaySlot, message: "Cannot set breakpoint in delay slot"]; }; RETURN; }; IF address.IsNullAddress[] THEN { ERROR Breakpoint.CantSet[ code: $NotAtNullAddress, message: "Cannot set breakpoint at null address"]; }; IF breakProc.IsNullAddress[] THEN { ERROR Breakpoint.CantSet[ code: $NotWithNullAddress, message: "Cannot set breakpoint with null break procedure world address"]; }; { breakProcTargetAddress: TargetArchitecture.Address ~ breakProc.TargetAddressFromBreakWorldAddress[]; IF breakProcTargetAddress.IsNullAddress[] THEN { ERROR Breakpoint.CantSet[ code: $NotWithNullAddress, message: "Cannot set breakpoint with null break procedure target address"]; }; }; CheckForDelaySlot[address: address]; { -- extra scope to contain EXITS patch _ Shepherd.ReservePatch[ pc: address, codeSize: BYTES[MIPSBreakpoint.PatchStruct] ! Shepherd.NoMeadow => { errorCode _ $NoMeadow; errorMessage _ message; GO TO Cannot; }; Shepherd.BusyMeadow => { errorCode _ $BusyMeadow; errorMessage _ message; GO TO Cannot; }; Shepherd.BusyPC => { errorCode _ $BusyPC; errorMessage _ message; GO TO Cannot; }; Shepherd.NoRoom => { errorCode _ $NoRoom; errorMessage _ message; GO TO Cannot; }; Shepherd.CantReach => { errorCode _ $CantReach; errorMessage _ message; GO TO Cannot; }; ]; Install[ address: address, patch: patch, breakProc: breakProc, breakData: breakData, damages: damages]; break _ Breakpoint.NewBreak[address: address, patch: patch, clientData: clientData]; Breakpoint.RememberBreak[break ! Breakpoint.Cant => { errorCode _ $CantRemember; errorMessage _ message; GO TO Cannot; };]; EXITS Cannot => { ERROR Breakpoint.CantSet[code: errorCode, message: errorMessage]; }; }; RETURN [break]; }; Install: PROCEDURE [ address: BreakWorldArchitecture.Address, patch: Shepherd.Patch, breakProc: Breakpoint.BreakProc, breakData: Breakpoint.BreakData, damages: TargetArchitecture.RegisterClass] RETURNS [] ~ { IF address.IsNullAddress[] THEN { ERROR Breakpoint.CantSet[code: $NullAddress, message: "Install[nullAddress]"]; }; IF patch.IsNullPatch[] THEN { ERROR Breakpoint.CantSet[code: $NullPatch, message: "Install[nullPatch]"]; }; IF breakProc.IsNullAddress[] THEN { ERROR Breakpoint.CantSet[code: $NullAddress, message: "Install[nullBreakProc]"]; }; InstallClosureCaller[ address: address, patch: patch, breakProc: breakProc, breakData: breakData, damages: damages]; InstallManger[address: address, patch: patch]; }; InstallClosureCaller: PROCEDURE [ address: BreakWorldArchitecture.Address, patch: Shepherd.Patch, breakProc: Breakpoint.BreakProc, breakData: Breakpoint.BreakData, damages: TargetArchitecture.RegisterClass] RETURNS [] ~ { IF address.IsNullAddress[] THEN { ERROR Breakpoint.CantSet[ code: $NullAddress, message: "InstallClosureCaller[nullAddress]"]; }; IF breakProc.IsNullAddress[] THEN { ERROR Breakpoint.CantSet[ code: $NullAddress, message: "InstallClosureCaller[nullBreakProc]"]; }; IF patch.IsNullPatch[] THEN { ERROR Breakpoint.CantSet[ code: $NullPatch, message: "InstallClosureCaller[nullPatch]"]; }; { instructionAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: address]; patchAddress: BreakWorldArchitecture.Address ~ Shepherd.CodeAddressFromPatch[patch: patch]; patchMIPSAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[address: patchAddress]; frameSize: INT ~ MIPSArchitecture.stackPointerOffset + MIPSArchitecture.stackAllocationForCallee + MIPSBreakpoint.registerSaveArea; savedRegsStackOffset: INT ~ MIPSArchitecture.stackPointerOffset + MIPSArchitecture.stackAllocationForCallee; damagesRegisters: MIPSArchitecture.RegisterClass ~ MIPSArchitecture.MIPSRegisterClassFromTargetRegisterClass[registerClass: damages]; registerSaveName: Rope.ROPE ~ SELECT damagesRegisters FROM none => "_save_regs_none", globals => "_save_regs_globals", globalsAndIns => "_save_regs_mini", ENDCASE => "_save_regs"; registerRestoreName: Rope.ROPE ~ SELECT damagesRegisters FROM none => "_restore_regs_none", globals => "_restore_regs_globals", globalsAndIns => "_restore_regs_mini", ENDCASE => "_restore_regs"; closureCaller: MIPSBreakpoint.ClosureCaller; errorCode: Breakpoint.ErrorCode _ Breakpoint.nullErrorCode; errorMessage: Breakpoint.ErrorMessage _ Breakpoint.nullErrorMessage; { {ENABLE { MIPSArchitecture.CantRelocate => { errorCode _ $CantSet; errorMessage _ "Cannot relocate instruction (MIPSBreakpointImpl)."; GO TO Cannot; }; MIPSArchitecture.CantReach => { errorCode _ $CantSet; errorMessage _ "pc-relative branch is out of range (MIPSBreakpointImpl)."; GO TO Cannot; }; MIPSArchitecture.NullMIPSAddress => { errorCode _ $CantSet; errorMessage _ "A null address was supplied to breakpoint code generation (MIPSBreakpointImpl)."; GO TO Cannot; }; MIPSArchitecture.NullMIPSInstruction => { errorCode _ $CantSet; errorMessage _ "A null instruction was encountered in breakpoint code generation (MIPSBreakpointImpl)."; GO TO Cannot; }; }; { closureCaller.subiu _ MIPSArchitecture.ADDIU[ source: MIPSArchitecture.stackPointer, constant: -frameSize, dest: MIPSArchitecture.stackPointer]; BreakWorldArchitecture.PokeInstruction[ pc: patchAddress, displacement: SubIUOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: closureCaller.subiu]]; }; { closureCaller.sw _ MIPSArchitecture.SW[ source: MIPSArchitecture.ra, base: MIPSArchitecture.stackPointer, offset: savedRegsStackOffset-4]; BreakWorldArchitecture.PokeInstruction[ pc: patchAddress, displacement: SWOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: closureCaller.sw]]; }; { callSaveRegsAddress: MIPSArchitecture.MIPSAddress ~ MIPSArchitecture.MIPSAddressFromDisplacement[ address: patchMIPSAddress, displacement: CallSaveRegsOffset[]]; saveRegsAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[ address: BreakWorldArchitecture.GetProcAddress[ breakWorld: BreakWorldArchitecture.BreakWorldFromBreakWorldAddress[ address: address], procName: registerSaveName]]; IF saveRegsAddress.IsNullMIPSAddress[] THEN { ERROR Breakpoint.CantSet[ code: $CantFindRegisterSaveProcedure, message: "Can't find the register save procedure"]; }; closureCaller.callSaveRegs _ MIPSArchitecture.JAL[ pc: callSaveRegsAddress, to: saveRegsAddress]; BreakWorldArchitecture.PokeInstruction[ pc: patchAddress, displacement: CallSaveRegsOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: closureCaller.callSaveRegs]]; }; { closureCaller.noop1 _ MIPSArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: patchAddress, displacement: Noop1Offset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: closureCaller.noop1]]; }; { closureCaller.argHiClientData _ MIPSArchitecture.LUI[ hi: MIPSArchitecture.Hi[value: breakData], dest: MIPSArchitecture.Register.r4]; BreakWorldArchitecture.PokeInstruction[ pc: patchAddress, displacement: ArgHiClientDataOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: closureCaller.argHiClientData]]; }; { callClientProcAddress: MIPSArchitecture.MIPSAddress ~ MIPSArchitecture.MIPSAddressFromDisplacement[ address: patchMIPSAddress, displacement: CallClientProcOffset[]]; clientProcAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[ address: breakProc]; closureCaller.callClientProc _ MIPSArchitecture.JAL[ pc: callClientProcAddress, to: clientProcAddress]; BreakWorldArchitecture.PokeInstruction[ pc: patchAddress, displacement: CallClientProcOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: closureCaller.callClientProc]]; }; { closureCaller.argLoClientData _ MIPSArchitecture.ORI[ source: MIPSArchitecture.Register.r4, constant: MIPSArchitecture.Lo[value: breakData], dest: MIPSArchitecture.Register.r4]; BreakWorldArchitecture.PokeInstruction[ pc: patchAddress, displacement: ArgLoClientDataOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: closureCaller.argLoClientData]]; }; { callRestoreRegsAddress: MIPSArchitecture.MIPSAddress ~ MIPSArchitecture.MIPSAddressFromDisplacement[ address: patchMIPSAddress, displacement: CallRestoreRegsOffset[]]; restoreRegsAddress: MIPSArchitecture.MIPSAddress ~ MIPSBreakWorldUtilities.MIPSAddressFromBreakWorldAddress[ address: BreakWorldArchitecture.GetProcAddress[ breakWorld: BreakWorldArchitecture.BreakWorldFromBreakWorldAddress[ address: address], procName: registerRestoreName]]; IF restoreRegsAddress.IsNullMIPSAddress[] THEN { ERROR Breakpoint.CantSet[ code: $CantFindRegisterRestoreProcedure, message: "Can't find the register restore procedure"]; }; closureCaller.callRestoreRegs _ MIPSArchitecture.JAL[ pc: callRestoreRegsAddress, to: restoreRegsAddress]; BreakWorldArchitecture.PokeInstruction[ pc: patchAddress, displacement: CallRestoreRegsOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: closureCaller.callRestoreRegs]]; }; { closureCaller.noop2 _ MIPSArchitecture.Noop[]; BreakWorldArchitecture.PokeInstruction[ pc: patchAddress, displacement: Noop2Offset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: closureCaller.noop2]]; }; { closureCaller.lw _ MIPSArchitecture.LW[ base: MIPSArchitecture.stackPointer, offset: savedRegsStackOffset-4, dest: MIPSArchitecture.ra]; BreakWorldArchitecture.PokeInstruction[ pc: patchAddress, displacement: LWOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: closureCaller.lw]]; }; { closureCaller.addiu _ MIPSArchitecture.ADDIU[ source: MIPSArchitecture.stackPointer, constant: +frameSize, dest: MIPSArchitecture.stackPointer]; BreakWorldArchitecture.PokeInstruction[ pc: patchAddress, displacement: AddIUOffset[], instruction: MIPSArchitecture.TargetInstructionFromMIPSInstruction[ instruction: closureCaller.addiu]]; }; }; EXITS Cannot => { ERROR Breakpoint.CantSet[code: errorCode, message: errorMessage]; }; }; }; }; InstallManger: PROCEDURE [ address: BreakWorldArchitecture.Address, patch: Shepherd.Patch] RETURNS [] ~ { IF address.IsNullAddress[] THEN { ERROR Breakpoint.CantSet[code: $NullAddress, message: "InstallManger[nullAddress]"]; }; IF patch.IsNullPatch[] THEN { ERROR Breakpoint.CantSet[code: $NullPatch, message: "InstallManger[nullPatch]"]; }; { patchCodeAddress: BreakWorldArchitecture.Address ~ Shepherd.CodeAddressFromPatch[ patch: patch]; mangerAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.AddressFromDisplacement[ address: patchCodeAddress, displacement: MangerOffset[]]; errorCode: MIPSManger.ErrorCode _ MIPSManger.nullErrorCode; errorMessage: MIPSManger.ErrorMessage _ MIPSManger.nullErrorMessage; { --Extra scope to contain EXITS. MIPSManger.Install[ address: address, manger: mangerAddress, patchCode: patchCodeAddress ! MIPSManger.CantInstall => { errorCode _ code; errorMessage _ message; GO TO Cannot; }]; EXITS Cannot => { ERROR Breakpoint.CantSet[code: errorCode, message: errorMessage]; }; }; }; }; ClearBreakpoint: BreakpointPrivate.ClearBreakProcType ~ { errorCode: Breakpoint.ErrorCode _ Breakpoint.nullErrorCode; errorMessage: Breakpoint.ErrorMessage _ Breakpoint.nullErrorMessage; IF Breakpoint.IsNullBreak[break: break] THEN { ERROR Breakpoint.CantClear[code: $NullBreak, message: "Cannot clear null break"]; }; { -- extra scope for EXITS address: BreakWorldArchitecture.Address ~ Breakpoint.AddressFromBreak[break: break]; patch: Shepherd.Patch _ Breakpoint.PatchFromBreak[break: break]; Uninstall[patch: patch, address: address]; Shepherd.ReleasePatch[patch: patch ! Shepherd.NoMeadow => { errorCode _ $NoMeadow; errorMessage _ message; GO TO Cannot; }; Shepherd.BusyMeadow => { errorCode _ $BusyMeadow; errorMessage _ message; GO TO Cannot; };]; Breakpoint.ForgetBreak[break: break ! Breakpoint.Cant => { errorCode _ $CantForget; errorMessage _ message; GO TO Cannot; }]; EXITS Cannot => { ERROR Breakpoint.CantClear[code: errorCode, message: errorMessage]; }; }; }; Uninstall: PROCEDURE [patch: Shepherd.Patch, address: BreakWorldArchitecture.Address] ~ { IF patch.IsNullPatch[] THEN { ERROR Breakpoint.CantSet[code: $NullPatch, message: "Uninstall[nullPatch]"]; }; IF address.IsNullAddress[] THEN { ERROR Breakpoint.CantSet[code: $NullAddress, message: "Uninstall[nullAddress]"]; }; { patchCodeAddress: BreakWorldArchitecture.Address ~ Shepherd.CodeAddressFromPatch[ patch: patch]; mangerAddress: BreakWorldArchitecture.Address ~ BreakWorldArchitecture.AddressFromDisplacement[ address: patchCodeAddress, displacement: MangerOffset[]]; errorCode: MIPSManger.ErrorCode _ MIPSManger.nullErrorCode; errorMessage: MIPSManger.ErrorMessage _ MIPSManger.nullErrorMessage; { -- Extra scope for EXITS MIPSManger.Uninstall[ address: address, manger: mangerAddress, patchCode: patchCodeAddress ! MIPSManger.CantUninstall => { errorCode _ code; errorMessage _ message; GO TO Cannot; }]; EXITS Cannot => { ERROR Breakpoint.CantClear[code: errorCode, message: errorMessage]; }; }; }; }; SubIUOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { patchStruct: MIPSBreakpoint.PatchStruct; patchStructAddress: LONG POINTER TO MIPSBreakpoint.PatchStruct ~ @patchStruct; patchStructCard: CARD32 ~ LOOPHOLE[patchStructAddress]; subiuAddress: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @patchStruct.closureCaller.subiu; subiuCard: CARD32 ~ LOOPHOLE[subiuAddress]; offset: TargetArchitecture.Displacement ~ (subiuCard - patchStructCard) * BYTES[UNIT]; RETURN [offset]; }; SWOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { patchStruct: MIPSBreakpoint.PatchStruct; patchStructAddress: LONG POINTER TO MIPSBreakpoint.PatchStruct ~ @patchStruct; patchStructCard: CARD32 ~ LOOPHOLE[patchStructAddress]; swAddress: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @patchStruct.closureCaller.sw; swCard: CARD32 ~ LOOPHOLE[swAddress]; offset: TargetArchitecture.Displacement ~ (swCard - patchStructCard) * BYTES[UNIT]; RETURN [offset]; }; CallSaveRegsOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { patchStruct: MIPSBreakpoint.PatchStruct; patchStructAddress: LONG POINTER TO MIPSBreakpoint.PatchStruct ~ @patchStruct; patchStructCard: CARD32 ~ LOOPHOLE[patchStructAddress]; callSaveRegsAddress: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @patchStruct.closureCaller.callSaveRegs; callSaveRegsCard: CARD32 ~ LOOPHOLE[callSaveRegsAddress]; offset: TargetArchitecture.Displacement ~ (callSaveRegsCard - patchStructCard) * BYTES[UNIT]; RETURN [offset]; }; Noop1Offset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { patchStruct: MIPSBreakpoint.PatchStruct; patchStructAddress: LONG POINTER TO MIPSBreakpoint.PatchStruct ~ @patchStruct; patchStructCard: CARD32 ~ LOOPHOLE[patchStructAddress]; noop1Address: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @patchStruct.closureCaller.noop1; noop1Card: CARD32 ~ LOOPHOLE[noop1Address]; offset: TargetArchitecture.Displacement ~ (noop1Card - patchStructCard) * BYTES[UNIT]; RETURN [offset]; }; ArgHiClientDataOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { patchStruct: MIPSBreakpoint.PatchStruct; patchStructAddress: LONG POINTER TO MIPSBreakpoint.PatchStruct ~ @patchStruct; patchStructCard: CARD32 ~ LOOPHOLE[patchStructAddress]; argHiClientDataAddress: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @patchStruct.closureCaller.argHiClientData; argHiClientDataCard: CARD32 ~ LOOPHOLE[argHiClientDataAddress]; offset: TargetArchitecture.Displacement ~ (argHiClientDataCard - patchStructCard) * BYTES[UNIT]; RETURN [offset]; }; CallClientProcOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { patchStruct: MIPSBreakpoint.PatchStruct; patchStructAddress: LONG POINTER TO MIPSBreakpoint.PatchStruct ~ @patchStruct; patchStructCard: CARD32 ~ LOOPHOLE[patchStructAddress]; callClientProcAddress: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @patchStruct.closureCaller.callClientProc; callClientProcCard: CARD32 ~ LOOPHOLE[callClientProcAddress]; offset: TargetArchitecture.Displacement ~ (callClientProcCard - patchStructCard) * BYTES[UNIT]; RETURN [offset]; }; ArgLoClientDataOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { patchStruct: MIPSBreakpoint.PatchStruct; patchStructAddress: LONG POINTER TO MIPSBreakpoint.PatchStruct ~ @patchStruct; patchStructCard: CARD32 ~ LOOPHOLE[patchStructAddress]; argLoClientDataAddress: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @patchStruct.closureCaller.argLoClientData; argLoClientDataCard: CARD32 ~ LOOPHOLE[argLoClientDataAddress]; offset: TargetArchitecture.Displacement ~ (argLoClientDataCard - patchStructCard) * BYTES[UNIT]; RETURN [offset]; }; CallRestoreRegsOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { patchStruct: MIPSBreakpoint.PatchStruct; patchStructAddress: LONG POINTER TO MIPSBreakpoint.PatchStruct ~ @patchStruct; patchStructCard: CARD32 ~ LOOPHOLE[patchStructAddress]; callRestoreRegsAddress: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @patchStruct.closureCaller.callRestoreRegs; callRestoreRegsCard: CARD32 ~ LOOPHOLE[callRestoreRegsAddress]; offset: TargetArchitecture.Displacement ~ (callRestoreRegsCard - patchStructCard) * BYTES[UNIT]; RETURN [offset]; }; Noop2Offset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { patchStruct: MIPSBreakpoint.PatchStruct; patchStructAddress: LONG POINTER TO MIPSBreakpoint.PatchStruct ~ @patchStruct; patchStructCard: CARD32 ~ LOOPHOLE[patchStructAddress]; noop2Address: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @patchStruct.closureCaller.noop2; noop2Card: CARD32 ~ LOOPHOLE[noop2Address]; offset: TargetArchitecture.Displacement ~ (noop2Card - patchStructCard) * BYTES[UNIT]; RETURN [offset]; }; LWOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { patchStruct: MIPSBreakpoint.PatchStruct; patchStructAddress: LONG POINTER TO MIPSBreakpoint.PatchStruct ~ @patchStruct; patchStructCard: CARD32 ~ LOOPHOLE[patchStructAddress]; lwAddress: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @patchStruct.closureCaller.lw; lwCard: CARD32 ~ LOOPHOLE[lwAddress]; offset: TargetArchitecture.Displacement ~ (lwCard - patchStructCard) * BYTES[UNIT]; RETURN [offset]; }; AddIUOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { patchStruct: MIPSBreakpoint.PatchStruct; patchStructAddress: LONG POINTER TO MIPSBreakpoint.PatchStruct ~ @patchStruct; patchStructCard: CARD32 ~ LOOPHOLE[patchStructAddress]; addiuAddress: LONG POINTER TO MIPSArchitecture.MIPSInstruction ~ @patchStruct.closureCaller.addiu; addiuCard: CARD32 ~ LOOPHOLE[addiuAddress]; offset: TargetArchitecture.Displacement ~ (addiuCard - patchStructCard) * BYTES[UNIT]; RETURN [offset]; }; MangerOffset: PROCEDURE [] RETURNS [TargetArchitecture.Displacement] ~ TRUSTED { patchStruct: MIPSBreakpoint.PatchStruct; patchStructAddress: LONG POINTER TO MIPSBreakpoint.PatchStruct ~ @patchStruct; patchStructCard: CARD32 ~ LOOPHOLE[patchStructAddress]; mangerAddress: LONG POINTER TO MIPSManger.Manger ~ @patchStruct.manger; mangerCard: CARD32 ~ LOOPHOLE[mangerAddress]; offset: TargetArchitecture.Displacement ~ (mangerCard - patchStructCard) * BYTES[UNIT]; RETURN [offset]; }; BreakpointPrivate.RegisterTargetBreaks[NEW[BreakpointPrivate.TargetBreaksBody _ [ "MIPSEL", SetBreakpoint, ClearBreakpoint]]]; BreakpointPrivate.RegisterTargetBreaks[NEW[BreakpointPrivate.TargetBreaksBody _ [ "MIPSEB", SetBreakpoint, ClearBreakpoint]]]; }.   MIPSBreakpointImpl.mesa Copyright Σ 1992 by Xerox Corporation. All rights reserved. Katsuyuki Komatsu August 5, 1992 6:02 pm PDT Jas, September 1, 1992 1:59 pm PDT Laurie Horton, February 26, 1993 12:15 pm PST MIPS target-dependent implementation of the functions from Breakpoint. "Public" Procedures registered with Breakpoint. PROCEDURE [ address: BreakWorldArchitecture.Address, dataSegment: BreakWorldArchitecture.Address, clientData: Breakpoint.ClientData, breakProc: Breakpoint.BreakProc, breakData: Breakpoint.BreakData, damages: TargetArchitecture.RegisterClass _ TargetArchitecture.RegisterClass.all] RETURNS [Breakpoint.Break] -- Can't deallocate patches. Well, I could just clear the size and address, but is that safe? IF NOT patch.IsNullPatch[] THEN { Shepherd.ReleasePatch[patch: patch]; }; Generate the code in the patch. PROCEDURE [break: Break] RETURNS []; PatchStruct offset procedures. Main code Κ •NewlineDelimiter – "cedar" style™unit™Icodešœ Οrœ1™˜>—L˜—˜˜2JšœK˜K—Lšœ[˜[˜1JšœP˜P—šœ žœ˜Lšœ$˜$Lšœ,˜,Lšœ"˜"—šœžœ˜Lšœ$˜$Lšœ,˜,—šœ3˜3LšœR˜R—šœžœžœž˜:L• CharPropsS PostfixXeroxCharCodesPostfixXeroxCharCodesPostfixXeroxCharCodesšœ˜L–S PostfixXeroxCharCodesPostfixXeroxCharCodesPostfixXeroxCharCodes šœ ˜ L–SPostfixXeroxCharCodesPostfixXeroxCharCodesPostfixXeroxCharCodesšœ#˜#L–8 PostfixXeroxCharCodesPostfixXeroxCharCodesšžœ˜—šœžœžœž˜=L–S PostfixXeroxCharCodesPostfixXeroxCharCodesPostfixXeroxCharCodesšœ˜L–S PostfixXeroxCharCodesPostfixXeroxCharCodesPostfixXeroxCharCodes šœ#˜#L–SPostfixXeroxCharCodesPostfixXeroxCharCodesPostfixXeroxCharCodesšœ&˜&L–8 PostfixXeroxCharCodesPostfixXeroxCharCodesšžœ˜—L˜L™Lšœ,˜,L˜L˜;L˜D˜šœž˜ ˜"L˜L˜CLšžœžœ˜ L˜—˜L˜L˜JLšžœžœ˜ L˜—˜%L˜L˜aLšžœžœ˜ L˜—˜)L˜L˜hLšžœžœ˜ L˜—L˜——˜šœ'žœ˜-Lšœ&˜&Lšœ˜Lšœ%˜%—šœ'˜'Lšœ˜Lšœ˜šœC˜CLšœ#˜#——L˜—˜šœ$žœ˜'Lšœ˜Lšœ$˜$Lšœ ˜ —šœ'˜'Lšœ˜Lšœ˜šœC˜CLšœ ˜ ——L˜—˜šœ4˜4šœ-˜-Lšœ?˜?——šœ0˜0šœ9˜9šœ/˜/šœC˜CLšœ˜—Lšœ˜———L˜šžœ%žœ˜-šžœ˜Lšœ&˜&Lšœ3˜3—L˜—šœ.žœ˜2Lšœ.˜.—šœ'˜'Lšœ˜Lšœ$˜$šœC˜CLšœ*˜*——L˜—˜Lšœ.˜.šœ'˜'Lšœ˜Lšœ˜šœC˜CLšœ#˜#——Lšœ˜—˜šœ1žœ˜5Lšœ*˜*Lšœ$˜$—šœ'˜'Lšœ˜Lšœ'˜'šœC˜CLšœ-˜-——Lšœ˜—˜šœ6˜6šœ-˜-LšœA˜A——šœ2˜2šœ9˜9Jšœ˜——L˜šœ0žœ˜4Lšœ2˜2—šœ'˜'Lšœ˜Lšœ&˜&šœC˜CLšœ,˜,——L˜—˜šœ1žœ˜5Lšœ%˜%Lšœ0˜0Lšœ$˜$—šœ'˜'Lšœ˜Lšœ'˜'šœC˜CLšœ-˜-——L˜—˜šœ7˜7šœ-˜-LšœB˜B——šœ3˜3šœ9˜9šœ/˜/šœC˜CLšœ˜—Lšœ ˜ ———L˜šžœ(žœ˜0šžœ˜Lšœ)˜)Lšœ6˜6—L˜—šœ1žœ˜5Lšœ4˜4—šœ'˜'Lšœ˜Lšœ'˜'šœC˜CLšœ-˜-——L˜—˜Lšœ.˜.šœ'˜'Lšœ˜Lšœ˜šœC˜CLšœ#˜#——L˜—˜šœ$žœ˜'Lšœ$˜$Lšœ˜Lšœ˜—šœ'˜'Lšœ˜Lšœ˜šœC˜CLšœ ˜ ——L˜—˜šœ'žœ˜-Lšœ&˜&Lšœ˜Lšœ%˜%—šœ'˜'Lšœ˜Lšœ˜šœC˜CLšœ#˜#——L˜—L˜—šž˜˜ Lšžœ<˜AL˜—L˜—L˜—˜L˜—š  œž œCžœ˜išžœžœ˜!LšžœO˜TL˜—šžœžœ˜LšžœK˜PL˜—˜šœQ˜QLšœ˜—šœ_˜_Lšœ9˜9—Lšœ;˜;LšœD˜DL˜šœ‘˜!šœ˜LšœD˜Dšœ˜L˜L˜Lšžœžœ˜ Lšœ˜——šž˜˜ Lšžœ<˜AL˜——L˜—L˜—L˜L˜—š œ+˜:Jšž œžœ™$Jšœ;˜;JšœD˜Dšžœ&žœ˜.JšžœL˜QJ˜—šœ‘˜JšœT˜TJšœ@˜@J˜Lšœ*˜*šœ"˜"˜L˜L˜Lšžœžœ˜ L˜—˜J˜L˜Lšžœžœ˜ L˜——šœ#˜#šœ˜L˜L˜Lšžœžœ˜ L˜——šž˜˜ Lšžœ>˜CL˜——Jšœ˜—Lšœ˜L˜—š  œž œE˜Yšžœžœ˜LšžœG˜LL˜—šžœžœ˜!LšžœK˜PL˜—˜šœQ˜QLšœ˜—šœ_˜_Lšœ9˜9—L˜;L˜DL˜šœ‘˜šœ˜LšœD˜D˜L˜L˜Lšžœžœ˜ L˜——šž˜šœ ˜ Lšžœ>˜CLšœ˜——L˜—L˜—L˜L˜——™š  œž œžœ%žœ˜PLšœ(˜(šœžœžœžœ˜ALšœ ˜ —Lšœžœžœ˜7šœžœžœžœ$˜ALšœ!˜!—Lšœ žœžœ˜+šœ)˜)Lšœ žœžœ˜,—L˜Lšžœ ˜Lšœ˜—š œž œžœ%žœ˜MLšœ(˜(šœžœžœžœ˜ALšœ ˜ —Lšœžœžœ˜7šœ žœžœžœ$˜>Lšœ˜—Lšœžœžœ ˜%šœ)˜)Lšœžœžœ˜)—L˜Lšžœ ˜Lšœ˜—š œž œžœ%žœ˜WLšœ(˜(šœžœžœžœ˜ALšœ ˜ —Lšœžœžœ˜7šœžœžœžœ$˜HLšœ(˜(—Lšœžœžœ˜9šœ)˜)Lšœ'žœžœ˜3—L˜Lšžœ ˜Lšœ˜—š  œž œžœ%žœ˜PLšœ(˜(šœžœžœžœ˜ALšœ ˜ —Lšœžœžœ˜7šœžœžœžœ$˜ALšœ!˜!—Lšœ žœžœ˜+šœ)˜)Lšœ žœžœ˜,—L˜Lšžœ ˜Lšœ˜—š œž œžœ%žœ˜ZLšœ(˜(šœžœžœžœ˜ALšœ ˜ —Lšœžœžœ˜7šœžœžœžœ$˜KLšœ+˜+—Lšœžœžœ˜?šœ)˜)Lšœ*žœžœ˜6—L˜Lšžœ ˜Lšœ˜—š œž œžœ%žœ˜YLšœ(˜(Lšœžœžœžœ+˜NLšœžœžœ˜7šœžœžœžœ$˜JLšœ*˜*—Lšœžœžœ˜=šœ)˜)Lšœ)žœžœ˜5—L˜Lšžœ ˜Lšœ˜—š œž œžœ%žœ˜ZLšœ(˜(šœžœžœžœ˜ALšœ ˜ —Lšœžœžœ˜7šœžœžœžœ$˜KLšœ+˜+—Lšœžœžœ˜?šœ)˜)Lšœ*žœžœ˜6—L˜Lšžœ ˜Lšœ˜—š œž œžœ%žœ˜ZLšœ(˜(šœžœžœžœ˜ALšœ ˜ —Lšœžœžœ˜7šœžœžœžœ$˜KLšœ+˜+—Lšœžœžœ˜?šœ)˜)Lšœ*žœžœ˜6—L˜Lšžœ ˜Lšœ˜—š  œž œžœ%žœ˜PLšœ(˜(šœžœžœžœ˜ALšœ ˜ —Lšœžœžœ˜7šœžœžœžœ$˜ALšœ!˜!—Lšœ žœžœ˜+šœ)˜)Lšœ žœžœ˜,—L˜Lšžœ ˜Lšœ˜—š œž œžœ%žœ˜MLšœ(˜(šœžœžœžœ˜ALšœ ˜ —Lšœžœžœ˜7šœ žœžœžœ$˜>Lšœ˜—Lšœžœžœ ˜%šœ)˜)Lšœžœžœ˜)—L˜Lšžœ ˜Lšœ˜—š  œž œžœ%žœ˜PLšœ(˜(šœžœžœžœ˜ALšœ ˜ —Lšœžœžœ˜7šœžœžœžœ$˜ALšœ!˜!—Lšœ žœžœ˜+šœ)˜)Lšœ žœžœ˜,—L˜Lšžœ ˜Lšœ˜L˜—š  œž œžœ%žœ˜QLšœ(˜(šœžœžœžœ˜ALšœ ˜ —Lšœžœžœ˜7šœžœžœžœ˜3Lšœ˜—Lšœ žœžœ˜-šœ)˜)Lšœ!žœžœ˜-—L˜Lšžœ ˜Lšœ˜L˜—L™ ™šœ'žœ'˜QLšœ ˜ Lšœ˜Lšœ˜—šœ'žœ'˜QLšœ ˜ Lšœ˜Lšœ˜———K˜—J˜—…—R–mV