Annotation of mstools/samples/sdktools/image/drwatson/alpha/walk.c, revision 1.1.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.