Annotation of mstools/samples/sdktools/image/drwatson/alpha/walk.c, revision 1.1

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1993  Microsoft Corporation
        !             4: 
        !             5: Module Name:
        !             6: 
        !             7:     walk.c
        !             8: 
        !             9: Abstract:
        !            10: 
        !            11:     This file provides support for stack walking.
        !            12: 
        !            13: Author:
        !            14: 
        !            15:     Miche Baker-Harvey (v-michbh) 1-May-1993  (ported from ntsd)
        !            16: 
        !            17: Environment:
        !            18: 
        !            19:     User Mode
        !            20: 
        !            21: --*/
        !            22: 
        !            23: #include <windows.h>
        !            24: 
        !            25: #include <stdlib.h>
        !            26: #include <stdio.h>
        !            27: #include <string.h>
        !            28: 
        !            29: #include "drwatson.h"
        !            30: #include "proto.h"
        !            31: 
        !            32: #include <alphaops.h>
        !            33: #include "disasm.h"
        !            34: 
        !            35: DWORD VirtualUnwind (PDEBUGPACKET, DWORD, PRUNTIME_FUNCTION, PCONTEXT);
        !            36: 
        !            37: ALPHA_INSTRUCTION disinstr;
        !            38: 
        !            39: #define DPRINT(a,b)
        !            40: 
        !            41: BOOL
        !            42: StackWalkInit( PSTACKWALK pstk,
        !            43:                   PDEBUGPACKET dp)
        !            44: {
        !            45:     pstk->pc        = dp->tctx->context.Fir;
        !            46:     pstk->frame     = dp->tctx->context.IntSp;
        !            47:     pstk->params[0] = dp->tctx->context.IntA0;
        !            48:     pstk->params[1] = dp->tctx->context.IntA1;
        !            49:     pstk->params[2] = dp->tctx->context.IntA2;
        !            50:     pstk->params[3] = dp->tctx->context.IntA3;
        !            51: 
        !            52:     return TRUE;
        !            53: }                                      /* ProcessStackWalkInitCmd() */
        !            54: 
        !            55: BOOL
        !            56: StackWalkNext( PSTACKWALK pstk,
        !            57:                          PDEBUGPACKET dp)
        !            58: {
        !            59:     DWORD               fir;
        !            60:     LONG                begin=0, end, test;
        !            61:     PRUNTIME_FUNCTION   rf;
        !            62:     CONTEXT             context;
        !            63:     DWORD               dwRa;
        !            64:     DWORD               cb;
        !            65:     PMODULEINFO         mi;
        !            66: 
        !            67:     fir = pstk->pc;
        !            68: 
        !            69:     mi = GetModuleForPC( dp, fir );
        !            70:     if (mi == NULL) {
        !            71:          return FALSE;
        !            72:     }
        !            73: 
        !            74:     //
        !            75:     // Do a binary search to determine which function contains this FIR
        !            76:     //
        !            77: 
        !            78: 
        !            79:     for(end=mi->dwEntries,test=(begin+end)/2; begin<=end; test=(begin+end)/2) {
        !            80:         if (fir<mi->pExceptionData[test].BeginAddress) {
        !            81:             end = test-1;
        !            82:         }
        !            83:         else
        !            84:         if (fir>=mi->pExceptionData[test].EndAddress) {
        !            85:             begin = test+1;
        !            86:         }
        !            87:         else {
        !            88:             break;
        !            89:         }
        !            90:     }
        !            91: 
        !            92:     //
        !            93:     // No function was found to include this FIR
        !            94:     // Therefore this is a leaf function
        !            95:     //
        !            96: 
        !            97:     if (begin>end) {
        !            98:         dp->tctx->stackBase = dp->tctx->context.IntSp;
        !            99:         dp->tctx->stackRA   = dp->tctx->context.IntRa;
        !           100: 
        !           101:         pstk->frame = dp->tctx->context.IntSp;
        !           102:         pstk->pc    = dp->tctx->context.IntRa;
        !           103: //
        !           104: // MBH - bugbug
        !           105: // This is hopeless: the arguments aren't normally homed on ALPHA
        !           106: //
        !           107:        if (!ReadProcessMemory( dp->hProcess,
        !           108:                                (LPVOID)pstk->frame,
        !           109:                                (LPVOID)pstk->params,
        !           110:                                12,
        !           111:                                NULL
        !           112:                               )) {
        !           113:            pstk->params[0] =
        !           114:            pstk->params[1] =
        !           115:            pstk->params[2] = 0;
        !           116:        }
        !           117:        return TRUE;
        !           118: 
        !           119:     }
        !           120: 
        !           121: 
        !           122:     //
        !           123:     // Virtually unwind the stack to determine base and caller
        !           124:     //
        !           125: 
        !           126:     context = dp->tctx->context;
        !           127:     context.IntSp = pstk->frame;
        !           128: 
        !           129:     dwRa = VirtualUnwind(dp, fir, &mi->pExceptionData[test], &context);
        !           130: 
        !           131:     //
        !           132:     // The Ra value coming out of mainCRTStartup is set by some RTL
        !           133:     // routines to be "1"; return out of mainCRTStartup is actually
        !           134:     // done through Jump/Unwind, so this serves to cause an error if
        !           135:     // someone actually does a return.  That's why we check here for
        !           136:     // dwRa == 1 - this happens when in the frame for CRTStartup.
        !           137:     //
        !           138:     // We test for (1-4) because on ALPHA, the value returned by
        !           139:     // VirtualUnwind is the value to be passed to the next call to
        !           140:     // VirtualUnwind, which is NOT the same as the Ra - it's sometimes
        !           141:     // decremented by four - this gives the faulting instruction -
        !           142:     // in particular, we want the fault instruction so we can get the
        !           143:     // correct scope in the case of an exception.
        !           144:     //
        !           145: 
        !           146:     if (((dp->tctx->stackBase == context.IntSp) && (dwRa == dp->tctx->stackRA)) ||
        !           147:         (dwRa == (1) ) ||
        !           148:         (dwRa == (1-4) ) ||
        !           149:         (dwRa == 0) ) {
        !           150:         return FALSE;
        !           151: 
        !           152:     }
        !           153: 
        !           154:     dp->tctx->stackBase = context.IntSp;
        !           155:     dp->tctx->stackRA   = dwRa;
        !           156: 
        !           157:     pstk->frame = context.IntSp;
        !           158:     pstk->pc = dwRa;
        !           159: 
        !           160:     if (!ReadProcessMemory( dp->hProcess,
        !           161:                             (LPVOID)pstk->frame,
        !           162:                             (LPVOID)pstk->params,
        !           163:                             12,
        !           164:                             NULL
        !           165:                            )) {
        !           166:         pstk->params[0] =
        !           167:         pstk->params[1] =
        !           168:         pstk->params[2] = 0;
        !           169:     }
        !           170: 
        !           171:     return TRUE;
        !           172: }
        !           173: 
        !           174: //
        !           175: // MBH - beginning of new VirtualUnwind code
        !           176: 
        !           177: 
        !           178: 
        !           179: #ifdef DBG
        !           180: 
        !           181: ULONG RtlDebugFlags = 0;
        !           182: #define RTL_DBG_VIRTUAL_UNWIND 1
        !           183: #define RTL_DBG_VIRTUAL_UNWIND_DETAIL 2
        !           184: 
        !           185: //
        !           186: // Define an array of symbolic names for the integer registers.
        !           187: //
        !           188: 
        !           189: PCHAR RtlpIntegerRegisterNames[32] = {
        !           190:     "v0",  "t0",  "t1",  "t2",  "t3",  "t4",  "t5",  "t6",      // 0 - 7
        !           191:     "t7",  "s0",  "s1",  "s2",  "s3",  "s4",  "s5",  "fp",      // 8 - 15
        !           192:     "a0",  "a1",  "a2",  "a3",  "a4",  "a5",  "t8",  "t9",      // 16 - 23
        !           193:     "t10", "t11", "ra",  "t12", "at",  "gp",  "sp",  "zero",    // 24 - 31
        !           194: };
        !           195: 
        !           196: //
        !           197: // This function disassembles the instruction at the given address. It is
        !           198: // only used for debugging and recognizes only those few instructions that
        !           199: // are relevant during reverse execution of the prologue by virtual unwind.
        !           200: //
        !           201: 
        !           202: VOID
        !           203: _RtlpDebugDisassemble (
        !           204:     IN ULONG ControlPc,
        !           205:     IN PCONTEXT ContextRecord
        !           206:     )
        !           207: {
        !           208:     UCHAR Comments[50];
        !           209:     PULONG FloatingRegister;
        !           210: //    PUQUAD FloatingRegister;
        !           211:     ULONG Function;
        !           212:     ULONG Hint;
        !           213:     ULONG Literal8;
        !           214:     ALPHA_INSTRUCTION Instruction;
        !           215: //    PUQUAD IntegerRegister;
        !           216:     PULONG IntegerRegister;
        !           217:     LONG Offset16;
        !           218:     UCHAR Operands[20];
        !           219:     ULONG Opcode;
        !           220:     PCHAR OpName;
        !           221:     ULONG Ra;
        !           222:     ULONG Rb;
        !           223:     ULONG Rc;
        !           224:     PCHAR RaName;
        !           225:     PCHAR RbName;
        !           226:     PCHAR RcName;
        !           227: 
        !           228:     if (RtlDebugFlags & RTL_DBG_VIRTUAL_UNWIND_DETAIL) {
        !           229:         Instruction.Long = *((PULONG)ControlPc);
        !           230:         Hint = Instruction.Jump.Hint;
        !           231:         Literal8 = Instruction.OpLit.Literal;
        !           232:         Offset16 = Instruction.Memory.MemDisp;
        !           233:         Opcode = Instruction.Memory.Opcode;
        !           234:         Ra = Instruction.OpReg.Ra;
        !           235:         RaName = RtlpIntegerRegisterNames[Ra];
        !           236:         Rb = Instruction.OpReg.Rb;
        !           237:         RbName = RtlpIntegerRegisterNames[Rb];
        !           238:         Rc = Instruction.OpReg.Rc;
        !           239:         RcName = RtlpIntegerRegisterNames[Rc];
        !           240: 
        !           241:         IntegerRegister = &ContextRecord->IntV0;
        !           242:         FloatingRegister = &ContextRecord->FltF0;
        !           243: 
        !           244:         OpName = NULL;
        !           245:         switch (Opcode) {
        !           246:         case JMP_OP :
        !           247:             if (Instruction.Jump.Function == RET_FUNC) {
        !           248:                 OpName = "ret";
        !           249:                 sprintf(Operands, "%s, (%s), %04lx", RaName, RbName, Hint);
        !           250:                 sprintf(Comments, "%s = %Lx", RbName, IntegerRegister[Rb]);
        !           251:             }
        !           252:             break;
        !           253: 
        !           254:         case LDAH_OP :
        !           255:         case LDA_OP :
        !           256:         case STQ_OP :
        !           257:             if (Opcode == LDA_OP) {
        !           258:                 OpName = "lda";
        !           259: 
        !           260:             } else if (Opcode == LDAH_OP) {
        !           261:                 OpName = "ldah";
        !           262: 
        !           263:             } else if (Opcode == STQ_OP) {
        !           264:                 OpName = "stq";
        !           265:             }
        !           266:             sprintf(Operands, "%s, $%d(%s)", RaName, Offset16, RbName);
        !           267:             sprintf(Comments, "%s = %Lx", RaName, IntegerRegister[Ra]);
        !           268:             break;
        !           269: 
        !           270:         case ARITH_OP :
        !           271:         case BIT_OP :
        !           272:             Function = Instruction.OpReg.Function;
        !           273:             if ((Opcode == ARITH_OP) && (Function == ADDQ_FUNC)) {
        !           274:                     OpName = "addq";
        !           275: 
        !           276:             } else if ((Opcode == ARITH_OP) && (Function == SUBQ_FUNC)) {
        !           277:                     OpName = "subq";
        !           278: 
        !           279:             } else if ((Opcode == BIT_OP) && (Function == BIS_FUNC)) {
        !           280:                     OpName = "bis";
        !           281: 
        !           282:             } else {
        !           283:                 break;
        !           284:             }
        !           285:             if (Instruction.OpReg.RbvType == RBV_REGISTER_FORMAT) {
        !           286:                 sprintf(Operands, "%s, %s, %s", RaName, RbName, RcName);
        !           287: 
        !           288:             } else {
        !           289:                 sprintf(Operands, "%s, $%d, %s", RaName, Literal8, RcName);
        !           290:             }
        !           291:             sprintf(Comments, "%s = %Lx", RcName, IntegerRegister[Rc]);
        !           292:             break;
        !           293: 
        !           294:         case FPOP_OP :
        !           295:             if (Instruction.FpOp.Function == CPYS_FUNC) {
        !           296:                 OpName = "cpys";
        !           297:                 sprintf(Operands, "f%d, f%d, f%d", Ra, Rb, Rc);
        !           298:                 sprintf(Comments, "f%d = %Lx", Rc, FloatingRegister[Rc]);
        !           299:             }
        !           300:             break;
        !           301: 
        !           302:         case STT_OP :
        !           303:             OpName = "stt";
        !           304:             sprintf(Operands, "f%d, $%d(%s)", Ra, Offset16, RbName);
        !           305:             sprintf(Comments, "f%d = %Lx", Ra, FloatingRegister[Ra]);
        !           306:             break;
        !           307:         }
        !           308:         if (OpName == NULL) {
        !           309:             OpName = "???";
        !           310:             sprintf(Operands, "...");
        !           311:             sprintf(Comments, "Unknown to virtual unwind.");
        !           312:         }
        !           313:         DbgPrint("    %08lx: %08lx  %-5s %-16s // %s\n",
        !           314:                  ControlPc, Instruction.Long, OpName, Operands, Comments);
        !           315:     }
        !           316:     return;
        !           317: }
        !           318: 
        !           319: #define _RtlpFoundTrapFrame(NextPc) \
        !           320:     if (RtlDebugFlags & RTL_DBG_VIRTUAL_UNWIND) { \
        !           321:         DbgPrint("    *** Looks like a trap frame (fake prologue), Fir = %lx\n", \
        !           322:                  NextPc); \
        !           323:     }
        !           324: 
        !           325: 
        !           326: #else
        !           327: 
        !           328: #define _RtlpDebugDisassemble(ControlPc, ContextRecord)
        !           329: #define _RtlpFoundTrapFrame(NextPc)
        !           330: 
        !           331: #endif
        !           332: 
        !           333: 
        !           334: /*++
        !           335: 
        !           336: Routine Description:
        !           337: 
        !           338:     Read longword at addr into value.
        !           339: 
        !           340: Arguments:
        !           341: 
        !           342:     addr  - address at which to read
        !           343:     value - where to put the result
        !           344: 
        !           345: 
        !           346: --*/
        !           347: 
        !           348: BOOLEAN
        !           349: LocalDoMemoryRead(PDEBUGPACKET dp, ULONG addr, PULONG pvalue)
        !           350: {
        !           351:     ULONG cb;
        !           352: 
        !           353:     if (!ReadProcessMemory(dp->hProcess,
        !           354:                            (LPVOID)addr,
        !           355:                            (LPVOID)pvalue,
        !           356:                            sizeof(*pvalue),
        !           357:                            &cb)) {
        !           358:          DPRINT(1, ("LocalDoMemoryRead: Can't read at %08x\n", addr));
        !           359:          return(FALSE);
        !           360:     }
        !           361:     if (cb != sizeof(*pvalue)) {
        !           362:          DPRINT(1, ("LocalDoMemoryRead: Count wrong at %08x\n", addr));
        !           363:          return(FALSE);
        !           364:     }
        !           365:     return(TRUE);
        !           366: }
        !           367: 
        !           368: //
        !           369: // MBH - this value is redefined in windbg common code to be IntSp.
        !           370: //
        !           371: #define SP_REG 30
        !           372: 
        !           373: 
        !           374: DWORD
        !           375: VirtualUnwind (
        !           376:     PDEBUGPACKET dp,
        !           377:     DWORD ControlPc,
        !           378:     PRUNTIME_FUNCTION FunctionEntry,
        !           379:     PCONTEXT ContextRecord
        !           380:     )
        !           381: 
        !           382: /*++
        !           383: 
        !           384: Routine Description:
        !           385: 
        !           386:     This function virtually unwinds the specified function by executing its
        !           387:     prologue code backwards. Given the current context and the instructions
        !           388:     that preserve registers in the prologue, it is possible to recreate the
        !           389:     nonvolatile context at the point the function was called.
        !           390: 
        !           391:     If the function is a leaf function, then the address where control left
        !           392:     the previous frame is obtained from the context record. If the function
        !           393:     is a nested function, but not an exception or interrupt frame, then the
        !           394:     prologue code is executed backwards and the address where control left
        !           395:     the previous frame is obtained from the updated context record.
        !           396: 
        !           397:     Otherwise, an exception or interrupt entry to the system is being unwound
        !           398:     and a specially coded prologue restores the return address twice. Once
        !           399:     from the fault instruction address and once from the saved return address
        !           400:     register. The first restore is returned as the function value and the
        !           401:     second restore is placed in the updated context record.
        !           402: 
        !           403:     During the unwind, the virtual and real frame pointers for the function
        !           404:     are calculated and returned in the given frame pointers structure.
        !           405: 
        !           406:     If a context pointers record is specified, then the address where each
        !           407:     register is restored from is recorded in the appropriate element of the
        !           408:     context pointers record.
        !           409: 
        !           410: Arguments:
        !           411: 
        !           412:     ControlPc - Supplies the address where control left the specified
        !           413:         function.
        !           414: 
        !           415:     FunctionEntry - Supplies the address of the function table entry for the
        !           416:         specified function.
        !           417: 
        !           418:     ContextRecord - Supplies the address of a context record.
        !           419: 
        !           420: 
        !           421: Return Value:
        !           422: 
        !           423:     The address where control left the previous frame is returned as the
        !           424:     function value.
        !           425: 
        !           426: Implementation Notes:
        !           427: 
        !           428:     N.B. "where control left" is not the "return address" of the call in the
        !           429:     previous frame. For normal frames, NextPc points to the last instruction
        !           430:     that completed in the previous frame (the JSR/BSR). The difference between
        !           431:     NextPc and NextPc + 4 (return address) is important for correct behavior
        !           432:     in boundary cases of exception addresses and scope tables.
        !           433: 
        !           434:     For exception and interrupt frames, NextPc is obtained from the trap frame
        !           435:     contination address (Fir). For faults and synchronous traps, NextPc is both
        !           436:     the last instruction to execute in the previous frame and the next
        !           437:     instruction to execute if the function were to return. For asynchronous
        !           438:     traps, NextPc is the continuation address. It is the responsibility of the
        !           439:     compiler to insert TRAPB instructions to insure asynchronous traps do not
        !           440:     occur outside the scope from the instruction(s) that caused them.
        !           441: 
        !           442:     N.B. in this and other files where RtlVirtualUnwind is used, the variable
        !           443:     named NextPc is perhaps more accurately, LastPc - the last PC value in
        !           444:     the previous frame, or CallPc - the address of the call instruction, or
        !           445:     ControlPc - the address where control left the previous frame. Instead
        !           446:     think of NextPc as the next PC to use in another call to virtual unwind.
        !           447: 
        !           448:     The Alpha version of virtual unwind is similar in design, but slightly
        !           449:     more complex than the Mips version. This is because Alpha compilers
        !           450:     are given more flexibility to optimize generated code and instruction
        !           451:     sequences, including within procedure prologues. And also because of
        !           452:     compiler design issues, the function must manage both virtual and real
        !           453:     frame pointers.
        !           454: 
        !           455: Version Information:  This version was taken from exdspatch.c@v37 (Feb 1993)
        !           456: 
        !           457: --*/
        !           458: 
        !           459: {
        !           460: 
        !           461:     ULONG Address;
        !           462:     ULONG DecrementOffset;
        !           463:     ULONG DecrementRegister;
        !           464:     ALPHA_INSTRUCTION FollowingInstruction;
        !           465: //    PUQUAD FloatingRegister;
        !           466:     PULONG FloatingRegister;
        !           467:     ULONG FrameSize;
        !           468:     ULONG Function;
        !           469:     ALPHA_INSTRUCTION Instruction;
        !           470: //    PUQUAD IntegerRegister;
        !           471:     PULONG IntegerRegister;
        !           472:     ULONG Literal8;
        !           473:     ULONG NextPc;
        !           474:     LONG Offset16;
        !           475:     ULONG Opcode;
        !           476:     ULONG Ra;
        !           477:     ULONG Rb;
        !           478:     ULONG Rc;
        !           479:     BOOLEAN RestoredRa;
        !           480:     BOOLEAN RestoredSp;
        !           481: 
        !           482: #ifdef DBG
        !           483:     if (RtlDebugFlags & RTL_DBG_VIRTUAL_UNWIND) {
        !           484:         DbgPrint("\nRtlVirtualUnwind(ControlPc = %lx, FunctionEntry = %lx,) sp = %lx\n",
        !           485:                  ControlPc, FunctionEntry, ContextRecord->IntSp);
        !           486:     }
        !           487: #endif
        !           488: #ifdef DBG
        !           489:     if ((FunctionEntry == NULL) || (ControlPc & 0x3) ||
        !           490:         (FunctionEntry->BeginAddress >= FunctionEntry->EndAddress) ||
        !           491:         (FunctionEntry->PrologEndAddress < FunctionEntry->BeginAddress) ||
        !           492:         (FunctionEntry->PrologEndAddress >= FunctionEntry->EndAddress)) {
        !           493:         DbgPrint("\n****** Warning - invalid PC or function table entry (virtual unwind).\n");
        !           494:         return ControlPc;
        !           495:     }
        !           496: #endif
        !           497:     //
        !           498:     // Set the base address of the integer and floating register arrays within
        !           499:     // the context record. Each set of 32 registers is known to be contiguous.
        !           500:     //
        !           501: 
        !           502: // MBH - assuming that quad values are together in context.
        !           503: // Do we really need 64 bit values?
        !           504: 
        !           505:     IntegerRegister = &ContextRecord->IntV0;
        !           506:     FloatingRegister = &ContextRecord->FltF0;
        !           507: 
        !           508:     //
        !           509:     // Handle the epilogue case where the next instruction is a return.
        !           510:     //
        !           511:     // Exception handlers cannot be called if the ControlPc is within the
        !           512:     // epilogue because exception handlers expect to operate with a current
        !           513:     // stack frame. The value of SP is not current within the epilogue.
        !           514:     //
        !           515: 
        !           516: //MBH
        !           517:     if (! LocalDoMemoryRead(dp, ControlPc, &Instruction.Long))  {
        !           518:         return(0);
        !           519:     }
        !           520: 
        !           521: //    Instruction.Long = *((PULONG)ControlPc);
        !           522: //MBH
        !           523:     if (IS_RETURN_0001_INSTRUCTION(Instruction.Long)) {
        !           524:         Rb = Instruction.Jump.Rb;
        !           525:         NextPc = (ULONG)IntegerRegister[Rb] - 4;
        !           526: 
        !           527:         //
        !           528:         // The instruction at the point where control left the specified
        !           529:         // function is a return, so any saved registers have already been
        !           530:         // restored, and the stack pointer has already been adjusted. The
        !           531:         // stack does not need to be unwound in this case and the saved
        !           532:         // return address register is returned as the function value.
        !           533:         //
        !           534:         // In fact, reverse execution of the prologue is not possible in
        !           535:         // this case: the stack pointer has already been incremented and
        !           536:         // so, for this frame, neither a valid stack pointer nor frame
        !           537:         // pointer exists from which to begin reverse execution of the
        !           538:         // prologue. In addition, the integrity of any data on the stack
        !           539:         // below the stack pointer is never guaranteed (due to interrupts
        !           540:         // and exceptions).
        !           541:         //
        !           542:         // The epilogue instruction sequence is:
        !           543:         //
        !           544:         // ==>  ret   zero, (Ra), 1     // return
        !           545:         // or
        !           546:         //
        !           547:         //      mov   ra, Rx            // save return address
        !           548:         //      ...
        !           549:         // ==>  ret   zero, (Rx), 1     // return
        !           550:         //
        !           551: 
        !           552: //        EstablisherFrame->Real = 0;
        !           553: //        EstablisherFrame->Virtual = (ULONG)ContextRecord->IntSp;
        !           554: //        *InFunction = FALSE;
        !           555:         _RtlpDebugDisassemble(ControlPc, ContextRecord);
        !           556: //        _RtlpVirtualUnwindExit(NextPc, ContextRecord);
        !           557:         return NextPc;
        !           558:     }
        !           559: 
        !           560:     //
        !           561:     // Handle the epilogue case where the next two instructions are a stack
        !           562:     // frame deallocation and a return.
        !           563:     //
        !           564: 
        !           565: // MBH
        !           566:     if (!LocalDoMemoryRead(dp,
        !           567:                            ControlPc+4,
        !           568:                            &FollowingInstruction.Long))
        !           569:           return (0);
        !           570: 
        !           571: //    FollowingInstruction.Long = *((PULONG)(ControlPc + 4));
        !           572: // MBH
        !           573:     if (IS_RETURN_0001_INSTRUCTION(FollowingInstruction.Long)) {
        !           574:         Rb = FollowingInstruction.Jump.Rb;
        !           575:         NextPc = (ULONG)IntegerRegister[Rb] - 4;
        !           576: 
        !           577:         //
        !           578:         // The second instruction following the point where control
        !           579:         // left the specified function is a return. If the instruction
        !           580:         // before the return is a stack increment instruction, then all
        !           581:         // saved registers have already been restored except for SP.
        !           582:         // The value of the stack pointer register cannot be recovered
        !           583:         // through reverse execution of the prologue because in order
        !           584:         // to begin reverse execution either the stack pointer or the
        !           585:         // frame pointer (if any) must still be valid.
        !           586:         //
        !           587:         // Instead, the effect that the stack increment instruction
        !           588:         // would have had on the context is manually applied to the
        !           589:         // current context. This is forward execution of the epilogue
        !           590:         // rather than reverse execution of the prologue.
        !           591:         //
        !           592:         // In an epilogue, as in a prologue, the stack pointer is always
        !           593:         // adjusted with a single instruction: either an immediate-value
        !           594:         // (lda) or a register-value (addq) add instruction.
        !           595:         //
        !           596: 
        !           597:         Function = Instruction.OpReg.Function;
        !           598:         Offset16 = Instruction.Memory.MemDisp;
        !           599:         Opcode = Instruction.OpReg.Opcode;
        !           600:         Ra = Instruction.OpReg.Ra;
        !           601:         Rb = Instruction.OpReg.Rb;
        !           602:         Rc = Instruction.OpReg.Rc;
        !           603: 
        !           604:         if ((Opcode == LDA_OP) && (Ra == SP_REG)) {
        !           605: 
        !           606:             //
        !           607:             // Load Address instruction.
        !           608:             //
        !           609:             // Since the destination (Ra) register is SP, an immediate-
        !           610:             // value stack deallocation operation is being performed. The
        !           611:             // displacement value should be added to SP. The displacement
        !           612:             // value is assumed to be positive. The amount of stack
        !           613:             // deallocation possible using this instruction ranges from
        !           614:             // 16 to 32752 (32768 - 16) bytes. The base register (Rb) is
        !           615:             // usually SP, but may be another register.
        !           616:             //
        !           617:             // The epilogue instruction sequence is:
        !           618:             //
        !           619:             // ==>  lda   sp, +N(sp)        // deallocate stack frame
        !           620:             //      ret   zero, (ra)        // return
        !           621:             // or
        !           622:             //
        !           623:             // ==>  lda   sp, +N(Rx)        // restore SP and deallocate frame
        !           624:             //      ret   zero, (ra)        // return
        !           625:             //
        !           626: 
        !           627:             ContextRecord->IntSp = Offset16 + IntegerRegister[Rb];
        !           628: //            EstablisherFrame->Real = 0;
        !           629: //            EstablisherFrame->Virtual = (ULONG)ContextRecord->IntSp;
        !           630: //            *InFunction = FALSE;
        !           631:             _RtlpDebugDisassemble(ControlPc, ContextRecord);
        !           632:             _RtlpDebugDisassemble(ControlPc + 4, ContextRecord);
        !           633: //            _RtlpVirtualUnwindExit(NextPc, ContextRecord);
        !           634:             return NextPc;
        !           635: 
        !           636:         } else if ((Opcode == ARITH_OP) && (Function == ADDQ_FUNC) &&
        !           637:                    (Rc == SP_REG) &&
        !           638:                    (Instruction.OpReg.RbvType == RBV_REGISTER_FORMAT)) {
        !           639: 
        !           640:             //
        !           641:             // Add Quadword instruction.
        !           642:             //
        !           643:             // Since both source operands are registers, and the
        !           644:             // destination register is SP, a register-value stack
        !           645:             // deallocation is being performed. The value of the two
        !           646:             // source registers should be added and this is the new
        !           647:             // value of SP. One of the source registers is usually SP,
        !           648:             // but may be another register.
        !           649:             //
        !           650:             // The epilogue instruction sequence is:
        !           651:             //
        !           652:             //      ldiq  Rx, N             // set [large] frame size
        !           653:             //      ...
        !           654:             // ==>  addq  sp, Rx, sp        // deallocate stack frame
        !           655:             //      ret   zero, (ra)        // return
        !           656:             // or
        !           657:             //
        !           658:             // ==>  addq  Rx, Ry, sp        // restore SP and deallocate frame
        !           659:             //      ret   zero, (ra)        // return
        !           660:             //
        !           661: 
        !           662:             ContextRecord->IntSp = IntegerRegister[Ra] + IntegerRegister[Rb];
        !           663: //            EstablisherFrame->Real = 0;
        !           664: //            EstablisherFrame->Virtual = (ULONG)ContextRecord->IntSp;
        !           665: //            *InFunction = FALSE;
        !           666:             _RtlpDebugDisassemble(ControlPc, ContextRecord);
        !           667:             _RtlpDebugDisassemble(ControlPc + 4, ContextRecord);
        !           668: //            _RtlpVirtualUnwindExit(NextPc, ContextRecord);
        !           669:             return NextPc;
        !           670:         }
        !           671:     }
        !           672: 
        !           673:     //
        !           674:     // By default set the frame pointers to the current value of SP.
        !           675:     //
        !           676:     // When a procedure is called, the value of SP before the stack
        !           677:     // allocation instruction is the virtual frame pointer. When reverse
        !           678:     // executing instructions in the prologue, the value of SP before the
        !           679:     // stack allocation instruction is encountered is the real frame
        !           680:     // pointer. This is the current value of SP unless the procedure uses
        !           681:     // a frame pointer (e.g., FP_REG).
        !           682:     //
        !           683: 
        !           684: //    EstablisherFrame->Real = (ULONG)ContextRecord->IntSp;
        !           685: //    EstablisherFrame->Virtual = (ULONG)ContextRecord->IntSp;
        !           686: 
        !           687:     //
        !           688:     // If the address where control left the specified function is beyond
        !           689:     // the end of the prologue, then the control PC is considered to be
        !           690:     // within the function and the control address is set to the end of
        !           691:     // the prologue. Otherwise, the control PC is not considered to be
        !           692:     // within the function (i.e., the prologue).
        !           693:     //
        !           694:     // N.B. PrologEndAddress is equal to BeginAddress for a leaf function.
        !           695:     //
        !           696:     // The low-order two bits of PrologEndAddress are reserved for the IEEE
        !           697:     // exception mode and so must be masked out.
        !           698:     //
        !           699: 
        !           700:     if ((ControlPc < FunctionEntry->BeginAddress) ||
        !           701:         (ControlPc >= FunctionEntry->PrologEndAddress)) {
        !           702: //        *InFunction = TRUE;
        !           703:         ControlPc = (FunctionEntry->PrologEndAddress & (~0x3));
        !           704: 
        !           705:     } else {
        !           706: //        *InFunction = FALSE;
        !           707:     }
        !           708: 
        !           709:     //
        !           710:     // Scan backward through the prologue to reload callee saved registers
        !           711:     // that were stored or copied and to increment the stack pointer if it
        !           712:     // was decremented.
        !           713:     //
        !           714: 
        !           715:     DecrementRegister = ZERO_REG;
        !           716:     NextPc = (ULONG)ContextRecord->IntRa - 4;
        !           717:     RestoredRa = FALSE;
        !           718:     RestoredSp = FALSE;
        !           719:     while (ControlPc > FunctionEntry->BeginAddress) {
        !           720: 
        !           721:         //
        !           722:         // Get instruction value, decode fields, case on opcode value, and
        !           723:         // reverse register store and stack decrement operations.
        !           724:         // N.B. The location of Opcode, Ra, Rb, and Rc is the same across
        !           725:         // all opcode formats. The same is not true for Function.
        !           726:         //
        !           727: 
        !           728:         ControlPc -= 4;
        !           729: //MBH
        !           730:         if (!LocalDoMemoryRead(dp, ControlPc, &Instruction.Long)) {
        !           731:              return(0);
        !           732:         }
        !           733: //        Instruction.Long = *((PULONG)ControlPc);
        !           734: //MBH
        !           735:         Function = Instruction.OpReg.Function;
        !           736:         Literal8 = Instruction.OpLit.Literal;
        !           737:         Offset16 = Instruction.Memory.MemDisp;
        !           738:         Opcode = Instruction.OpReg.Opcode;
        !           739:         Ra = Instruction.OpReg.Ra;
        !           740:         Rb = Instruction.OpReg.Rb;
        !           741:         Rc = Instruction.OpReg.Rc;
        !           742: 
        !           743:         //
        !           744:         // Compare against each instruction type that will affect the context
        !           745:         // and that is allowed in a prologue. Any other instructions found
        !           746:         // in the prologue will be ignored since they are assumed to have no
        !           747:         // effect on the context.
        !           748:         //
        !           749: 
        !           750:         switch (Opcode) {
        !           751: 
        !           752:         case STQ_OP :
        !           753: 
        !           754:             //
        !           755:             // Store Quad instruction.
        !           756:             //
        !           757:             // If the base register is SP, then reload the source register
        !           758:             // value from the value stored on the stack.
        !           759:             //
        !           760:             // The prologue instruction sequence is:
        !           761:             //
        !           762:             // ==>  stq   Rx, N(sp)         // save integer register Rx
        !           763:             //
        !           764: 
        !           765:             if ((Rb == SP_REG) && (Ra != ZERO_REG)) {
        !           766: 
        !           767:                 //
        !           768:                 // Reload the register by retrieving the value previously
        !           769:                 // stored on the stack.
        !           770:                 //
        !           771: 
        !           772:                 Address = Offset16 + ContextRecord->IntSp;
        !           773: // MBH
        !           774:                 if (!LocalDoMemoryRead(dp,
        !           775:                                        Address,
        !           776:                                        &IntegerRegister[Ra])) {
        !           777:                     return(0);
        !           778:                 }
        !           779: //                IntegerRegister[Ra] = *((PULONG)Address);
        !           780: // MBH
        !           781: 
        !           782:                 //
        !           783:                 // If the destination register is RA and this is the first
        !           784:                 // time that RA is being restored, then set the address of
        !           785:                 // where control left the previous frame. Otherwise, if this
        !           786:                 // is the second time RA is being restored, then the first
        !           787:                 // one was an interrupt or exception address and the return
        !           788:                 // PC should not have been biased by 4.
        !           789:                 //
        !           790: 
        !           791:                 if (Ra == RA_REG) {
        !           792:                     if (RestoredRa == FALSE) {
        !           793:                         NextPc = (ULONG)ContextRecord->IntRa - 4;
        !           794:                         RestoredRa = TRUE;
        !           795: 
        !           796:                     } else {
        !           797:                         NextPc += 4;
        !           798:                         _RtlpFoundTrapFrame(NextPc);
        !           799:                     }
        !           800: 
        !           801:                 //
        !           802:                 // Otherwise, if the destination register is SP and this is
        !           803:                 // the first time that SP is being restored, then set the
        !           804:                 // establisher frame pointers.
        !           805:                 //
        !           806: 
        !           807:                 } else if ((Ra == SP_REG) && (RestoredSp == FALSE)) {
        !           808:                     RestoredSp = TRUE;
        !           809:                 }
        !           810: 
        !           811:                 //
        !           812:                 // If a context pointer record is specified, then record
        !           813:                 // the address where the destination register contents
        !           814:                 // are stored.
        !           815:                 //
        !           816: 
        !           817:                 _RtlpDebugDisassemble(ControlPc, ContextRecord);
        !           818:             }
        !           819:             break;
        !           820: 
        !           821:         case LDAH_OP :
        !           822:             Offset16 <<= 16;
        !           823: 
        !           824:         case LDA_OP :
        !           825: 
        !           826:             //
        !           827:             // Load Address High, Load Address instruction.
        !           828:             //
        !           829:             // There are several cases where the lda and/or ldah instructions
        !           830:             // are used: one to decrement the stack pointer directly, and the
        !           831:             // others to load immediate values into another register and that
        !           832:             // register is then used to decrement the stack pointer.
        !           833:             //
        !           834:             // In the examples below, as a single instructions or as a pair,
        !           835:             // a lda may be substituted for a ldah and visa-versa.
        !           836:             //
        !           837: 
        !           838:             if (Ra == SP_REG) {
        !           839:                 if (Rb == SP_REG) {
        !           840: 
        !           841:                     //
        !           842:                     // If both the destination (Ra) and base (Rb) registers
        !           843:                     // are SP, then a standard stack allocation was performed
        !           844:                     // and the negated displacement value is the stack frame
        !           845:                     // size. The amount of stack allocation possible using
        !           846:                     // the lda instruction ranges from 16 to 32768 bytes and
        !           847:                     // the amount of stack allocation possible using the ldah
        !           848:                     // instruction ranges from 65536 to 2GB in multiples of
        !           849:                     // 65536 bytes. It is rare for the ldah instruction to be
        !           850:                     // used in this manner.
        !           851:                     //
        !           852:                     // The prologue instruction sequence is:
        !           853:                     //
        !           854:                     // ==>  lda   sp, -N(sp)    // allocate stack frame
        !           855:                     //
        !           856: 
        !           857:                     FrameSize = -Offset16;
        !           858:                     goto StackAllocation;
        !           859: 
        !           860:                 } else {
        !           861: 
        !           862:                     //
        !           863:                     // The destination register is SP and the base register
        !           864:                     // is not SP, so this instruction must be the second
        !           865:                     // half of an instruction pair to allocate a large size
        !           866:                     // (>32768 bytes) stack frame. Save the displacement value
        !           867:                     // as the partial decrement value and postpone adjusting
        !           868:                     // the value of SP until the first instruction of the pair
        !           869:                     // is encountered.
        !           870:                     //
        !           871:                     // The prologue instruction sequence is:
        !           872:                     //
        !           873:                     //      ldah  Rx, -N(sp)    // prepare new SP (upper)
        !           874:                     // ==>  lda   sp, sN(Rx)    // allocate stack frame
        !           875:                     //
        !           876: 
        !           877:                     DecrementRegister = Rb;
        !           878:                     DecrementOffset = Offset16;
        !           879:                     _RtlpDebugDisassemble(ControlPc, ContextRecord);
        !           880:                 }
        !           881: 
        !           882:             } else if (Ra == DecrementRegister) {
        !           883:                 if (Rb == DecrementRegister) {
        !           884: 
        !           885:                     //
        !           886:                     // Both the destination and base registers are the
        !           887:                     // decrement register, so this instruction exists as the
        !           888:                     // second half of a two instruction pair to load a
        !           889:                     // 31-bit immediate value into the decrement register.
        !           890:                     // Save the displacement value as the partial decrement
        !           891:                     // value.
        !           892:                     //
        !           893:                     // The prologue instruction sequence is:
        !           894:                     //
        !           895:                     //      ldah  Rx, +N(zero)      // set frame size (upper)
        !           896:                     // ==>  lda   Rx, sN(Rx)        // set frame size (+lower)
        !           897:                     //      ...
        !           898:                     //      subq  sp, Rx, sp        // allocate stack frame
        !           899:                     //
        !           900: 
        !           901:                     DecrementOffset += Offset16;
        !           902:                     _RtlpDebugDisassemble(ControlPc, ContextRecord);
        !           903: 
        !           904:                 } else if (Rb == ZERO_REG) {
        !           905: 
        !           906:                     //
        !           907:                     // The destination register is the decrement register and
        !           908:                     // the base register is zero, so this instruction exists
        !           909:                     // to load an immediate value into the decrement register.
        !           910:                     // The stack frame size is the new displacement value added
        !           911:                     // to the previous displacement value, if any.
        !           912:                     //
        !           913:                     // The prologue instruction sequence is:
        !           914:                     //
        !           915:                     // ==>  lda   Rx, +N(zero)      // set frame size
        !           916:                     //      ...
        !           917:                     //      subq  sp, Rx, sp        // allocate stack frame
        !           918:                     // or
        !           919:                     //
        !           920:                     // ==>  ldah  Rx, +N(zero)      // set frame size (upper)
        !           921:                     //      lda   Rx, sN(Rx)        // set frame size (+lower)
        !           922:                     //      ...
        !           923:                     //      subq  sp, Rx, sp        // allocate stack frame
        !           924:                     //
        !           925: 
        !           926:                     FrameSize = (Offset16 + DecrementOffset);
        !           927:                     goto StackAllocation;
        !           928: 
        !           929:                 } else if (Rb == SP_REG) {
        !           930: 
        !           931:                     //
        !           932:                     // The destination (Ra) register is SP and the base (Rb)
        !           933:                     // register is the decrement register, so a two
        !           934:                     // instruction, large size (>32768 bytes) stack frame
        !           935:                     // allocation was performed. Add the new displacement
        !           936:                     // value to the previous displacement value. The negated
        !           937:                     // displacement value is the stack frame size.
        !           938:                     //
        !           939:                     // The prologue instruction sequence is:
        !           940:                     //
        !           941:                     // ==>  ldah  Rx, -N(sp)    // prepare new SP (upper)
        !           942:                     //      lda   sp, sN(Rx)    // allocate stack frame
        !           943:                     //
        !           944: 
        !           945:                     FrameSize = -(Offset16 + (LONG)DecrementOffset);
        !           946:                     goto StackAllocation;
        !           947:                 }
        !           948:             }
        !           949:             break;
        !           950: 
        !           951:         case ARITH_OP :
        !           952: 
        !           953:             if ((Function == ADDQ_FUNC) &&
        !           954:                 (Instruction.OpReg.RbvType != RBV_REGISTER_FORMAT)) {
        !           955: 
        !           956:                 //
        !           957:                 // Add Quadword (immediate) instruction.
        !           958:                 //
        !           959:                 // If the first source register is zero, and the second
        !           960:                 // operand is a literal, and the destination register is
        !           961:                 // the decrement register, then the instruction exists
        !           962:                 // to load an unsigned immediate value less than 256 into
        !           963:                 // the decrement register. The immediate value is the stack
        !           964:                 // frame size.
        !           965:                 //
        !           966:                 // The prologue instruction sequence is:
        !           967:                 //
        !           968:                 // ==>  addq  zero, N, Rx       // set frame size
        !           969:                 //      ...
        !           970:                 //      subq  sp, Rx, sp        // allocate stack frame
        !           971:                 //
        !           972: 
        !           973:                 if ((Ra == ZERO_REG) && (Rc == DecrementRegister)) {
        !           974:                     FrameSize = Literal8;
        !           975:                     goto StackAllocation;
        !           976:                 }
        !           977: 
        !           978:             } else if ((Function == SUBQ_FUNC) &&
        !           979:                        (Instruction.OpReg.RbvType == RBV_REGISTER_FORMAT)) {
        !           980: 
        !           981:                 //
        !           982:                 // Subtract Quadword (register) instruction.
        !           983:                 //
        !           984:                 // If both source operands are registers and the first
        !           985:                 // source (minuend) register and the destination
        !           986:                 // (difference) register are both SP, then a register value
        !           987:                 // stack allocation was performed and the second source
        !           988:                 // (subtrahend) register value will be added to SP when its
        !           989:                 // value is known. Until that time save the register number of
        !           990:                 // this decrement register.
        !           991:                 //
        !           992:                 // The prologue instruction sequence is:
        !           993:                 //
        !           994:                 //      ldiq  Rx, N             // set frame size
        !           995:                 //      ...
        !           996:                 // ==>  subq  sp, Rx, sp        // allocate stack frame
        !           997:                 //
        !           998: 
        !           999:                 if ((Ra == SP_REG) && (Rc == SP_REG)) {
        !          1000:                     DecrementRegister = Rb;
        !          1001:                     DecrementOffset = 0;
        !          1002:                     _RtlpDebugDisassemble(ControlPc, ContextRecord);
        !          1003:                 }
        !          1004:             }
        !          1005:             break;
        !          1006: 
        !          1007:         case BIT_OP :
        !          1008: 
        !          1009:             //
        !          1010:             // If the second operand is a register the bit set instruction
        !          1011:             // may be a register move instruction, otherwise if the second
        !          1012:             // operand is a literal, the bit set instruction may be a load
        !          1013:             // immediate value instruction.
        !          1014:             //
        !          1015: 
        !          1016:             if ((Function == BIS_FUNC) && (Rc != ZERO_REG)) {
        !          1017:                 if (Instruction.OpReg.RbvType == RBV_REGISTER_FORMAT) {
        !          1018: 
        !          1019:                     //
        !          1020:                     // Bit Set (register move) instruction.
        !          1021:                     //
        !          1022:                     // If both source registers are the same register, or
        !          1023:                     // one of the source registers is zero, then this is a
        !          1024:                     // register move operation. Restore the value of the
        !          1025:                     // source register by copying the current destination
        !          1026:                     // register value back to the source register.
        !          1027:                     //
        !          1028:                     // The prologue instruction sequence is:
        !          1029:                     //
        !          1030:                     // ==>  bis   Rx, Rx, Ry        // copy register Rx
        !          1031:                     // or
        !          1032:                     //
        !          1033:                     // ==>  bis   Rx, zero, Ry      // copy register Rx
        !          1034:                     // or
        !          1035:                     //
        !          1036:                     // ==>  bis   zero, Rx, Ry      // copy register Rx
        !          1037:                     //
        !          1038: 
        !          1039:                     if (Ra == ZERO_REG) {
        !          1040: 
        !          1041:                         //
        !          1042:                         // Map the third case above to the first case.
        !          1043:                         //
        !          1044: 
        !          1045:                         Ra = Rb;
        !          1046: 
        !          1047:                     } else if (Rb == ZERO_REG) {
        !          1048: 
        !          1049:                         //
        !          1050:                         // Map the second case above to the first case.
        !          1051:                         //
        !          1052: 
        !          1053:                         Rb = Ra;
        !          1054:                     }
        !          1055: 
        !          1056:                     if ((Ra == Rb) && (Ra != ZERO_REG)) {
        !          1057:                         IntegerRegister[Ra] = IntegerRegister[Rc];
        !          1058: 
        !          1059: 
        !          1060:                         //
        !          1061:                         // If the destination register is RA and this is the
        !          1062:                         // first time that RA is being restored, then set the
        !          1063:                         // address of where control left the previous frame.
        !          1064:                         // Otherwise, if this is the second time RA is being
        !          1065:                         // restored, then the first one was an interrupt or
        !          1066:                         // exception address and the return PC should not
        !          1067:                         // have been biased by 4.
        !          1068:                         //
        !          1069: 
        !          1070:                         if (Ra == RA_REG) {
        !          1071:                             if (RestoredRa == FALSE) {
        !          1072:                                 NextPc = (ULONG)ContextRecord->IntRa - 4;
        !          1073:                                 RestoredRa = TRUE;
        !          1074: 
        !          1075:                             } else {
        !          1076:                                 NextPc += 4;
        !          1077:                                 _RtlpFoundTrapFrame(NextPc);
        !          1078:                             }
        !          1079:                         }
        !          1080: 
        !          1081:                         //
        !          1082:                         // If the source register is SP and this is the first
        !          1083:                         // time SP is set, then this is a frame pointer set
        !          1084:                         // instruction. Reset the frame pointers to this new
        !          1085:                         // value of SP.
        !          1086:                         //
        !          1087: 
        !          1088:                         if ((Ra == SP_REG) && (RestoredSp == FALSE)) {
        !          1089: //                            EstablisherFrame->Virtual = (ULONG)ContextRecord->IntSp;
        !          1090: //                            EstablisherFrame->Real = (ULONG)ContextRecord->IntSp;
        !          1091:                             RestoredSp = TRUE;
        !          1092:                         }
        !          1093:                         _RtlpDebugDisassemble(ControlPc, ContextRecord);
        !          1094:                     }
        !          1095: 
        !          1096:                 } else {
        !          1097: 
        !          1098:                     //
        !          1099:                     // Bit Set (load immediate) instruction.
        !          1100:                     //
        !          1101:                     // If the first source register is zero, and the second
        !          1102:                     // operand is a literal, and the destination register is
        !          1103:                     // the decrement register, then this instruction exists
        !          1104:                     // to load an unsigned immediate value less than 256 into
        !          1105:                     // the decrement register. The decrement register value is
        !          1106:                     // the stack frame size.
        !          1107:                     //
        !          1108:                     // The prologue instruction sequence is:
        !          1109:                     //
        !          1110:                     // ==>  bis   zero, N, Rx       // set frame size
        !          1111:                     //      ...
        !          1112:                     //      subq  sp, Rx, sp        // allocate stack frame
        !          1113:                     //
        !          1114: 
        !          1115:                     if ((Ra == ZERO_REG) && (Rc == DecrementRegister)) {
        !          1116:                         FrameSize = Literal8;
        !          1117: StackAllocation:
        !          1118:                         //
        !          1119:                         // Add the frame size to SP to reverse the stack frame
        !          1120:                         // allocation, leave the real frame pointer as is, set
        !          1121:                         // the virtual frame pointer with the updated SP value,
        !          1122:                         // and clear the decrement register.
        !          1123:                         //
        !          1124: 
        !          1125:                         ContextRecord->IntSp += FrameSize;
        !          1126: //                        EstablisherFrame->Virtual = (ULONG)ContextRecord->IntSp;
        !          1127:                         DecrementRegister = ZERO_REG;
        !          1128:                         _RtlpDebugDisassemble(ControlPc, ContextRecord);
        !          1129:                     }
        !          1130:                 }
        !          1131:             }
        !          1132:             break;
        !          1133: 
        !          1134:         case STT_OP :
        !          1135: 
        !          1136:             //
        !          1137:             // Store T-Floating (quadword integer) instruction.
        !          1138:             //
        !          1139:             // If the base register is SP, then reload the source register
        !          1140:             // value from the value stored on the stack.
        !          1141:             //
        !          1142:             // The prologue instruction sequence is:
        !          1143:             //
        !          1144:             // ==>  stt   Fx, N(sp)         // save floating register Fx
        !          1145:             //
        !          1146: 
        !          1147:             if ((Rb == SP_REG) && (Ra != FZERO_REG)) {
        !          1148: 
        !          1149:                 //
        !          1150:                 // Reload the register by retrieving the value previously
        !          1151:                 // stored on the stack.
        !          1152:                 //
        !          1153: 
        !          1154:                 Address = Offset16 + ContextRecord->IntSp;
        !          1155: // MBH
        !          1156:                 if (!LocalDoMemoryRead(dp,
        !          1157:                                        Address,
        !          1158:                                        &FloatingRegister[Ra])) {
        !          1159:                     return(0);
        !          1160:                 }
        !          1161: //                FloatingRegister[Ra] = *((PUQUAD)Address);
        !          1162: // MBH
        !          1163: 
        !          1164:                 //
        !          1165:                 // If a context pointer record is specified, then record
        !          1166:                 // the address where the destination register contents are
        !          1167:                 // stored.
        !          1168:                 //
        !          1169: 
        !          1170:                 _RtlpDebugDisassemble(ControlPc, ContextRecord);
        !          1171:             }
        !          1172:             break;
        !          1173: 
        !          1174:         case FPOP_OP :
        !          1175: 
        !          1176:             //
        !          1177:             // N.B. The floating operate function field is not the same as
        !          1178:             // the integer operate nor the jump function fields.
        !          1179:             //
        !          1180: 
        !          1181:             if (Instruction.FpOp.Function == CPYS_FUNC) {
        !          1182: 
        !          1183:                 //
        !          1184:                 // Copy Sign (floating-point move) instruction.
        !          1185:                 //
        !          1186:                 // If both source registers are the same register, then this is
        !          1187:                 // a floating-point register move operation. Restore the value
        !          1188:                 // of the source register by copying the current destination
        !          1189:                 // register value to the source register.
        !          1190:                 //
        !          1191:                 // The prologue instruction sequence is:
        !          1192:                 //
        !          1193:                 // ==>  cpys  Fx, Fx, Fy        // copy floating register Fx
        !          1194:                 //
        !          1195: 
        !          1196:                 if ((Ra == Rb) && (Ra != FZERO_REG)) {
        !          1197:                     FloatingRegister[Ra] = FloatingRegister[Rc];
        !          1198:                     _RtlpDebugDisassemble(ControlPc, ContextRecord);
        !          1199:                 }
        !          1200:             }
        !          1201: 
        !          1202:         default :
        !          1203:             break;
        !          1204:         }
        !          1205:     }
        !          1206: 
        !          1207: //    _RtlpVirtualUnwindExit(NextPc, ContextRecord);
        !          1208:     return NextPc;
        !          1209: }
        !          1210: 
        !          1211: 
        !          1212: 
        !          1213: 
        !          1214: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.