/*++ Copyright (c) 1993 Microsoft Corporation Module Name: regs.c Abstract: This file provides access to the machine's register set. Author: Miche Baker-Harvey (v-michbh) 1-May-1993 (ported from ntsd) Environment: User Mode --*/ /* // // This line keeps alpha pseudo ops from being defined in kxalpha.h #ifdef ALPHA #define HEADER_FILE #endif */ #include #include #include #include #include "drwatson.h" #include "proto.h" #include "regs.h" #include #include "strings.h" // we want the definitions of PSR_MODE, etc, which // are derived in genalpha.c by Joe for ksalpha.h. // They don't exist as separate defines anywhere else. // However, if we include ksalpha.h, we get bunches // of duplicate definitions. So for now (hack,hack), // just make a local copy of the definitions. // MBH TODO bugbug - ksalpha.h hack // #include #define PSR_USER_MODE 0x1 #define PSR_MODE 0x0 // Mode bit in PSR (bit 0) #define PSR_MODE_MASK 0x1 // Mask (1 bit) for mode in PSR #define PSR_IE 0x1 // Interrupt Enable bit in PSR (bit 1) #define PSR_IE_MASK 0x1 // Mask (1 bit) for IE in PSR #define PSR_IRQL 0x2 // IRQL in PSR (bit 2) #define PSR_IRQL_MASK 0x7 // Mask (2 bits) for IRQL in PSR CONTEXT SavedRegisterContext; extern ULONG EXPRLastExpression; // from module ntexpr.c extern ULONG EXPRLastDump; // from module ntcmd.c extern int fControlC; PUCHAR UserRegs[10] = {0}; ULONG GetIntRegNumber(ULONG); BOOLEAN UserRegTest(ULONG); BOOLEAN NeedUpper(DWORDLONG); void GetFloatingPointRegValue(PDEBUGPACKET, ULONG , PCONVERTED_DOUBLE); PUCHAR RegNameFromIndex(ULONG); ULONG GetRegString(PUCHAR); // // This is the length of an instruction, and the instruction // to be used in setting a breakpoint (common code writes the // breakpoint instruction into the memory stream. // ULONG cbBrkptLength = 4; // these are defined in alphaops.h ULONG trapInstr = CALLPAL_OP | BPT_FUNC ; ULONG breakInstrs[] = {CALLPAL_OP | BPT_FUNC, CALLPAL_OP | KBPT_FUNC, CALLPAL_OP | CALLKD_FUNC}; ULONG ContextType = CONTEXT_FULL; #define IS_FLOATING_SAVED(Register) ((SAVED_FLOATING_MASK >> Register) & 1L) #define IS_INTEGER_SAVED(Register) ((SAVED_INTEGER_MASK >> Register) & 1L) // // Define saved register masks. #define SAVED_FLOATING_MASK 0xfff00000 // saved floating registers #define SAVED_INTEGER_MASK 0xf3ffff02 // saved integer registers // // Instruction opcode values are defined in alphaops.h // // // Define stack register and zero register numbers. // #define RA 0x1a // integer register 26 #define SP 0x1e // integer register 30 #define ZERO 0x1f // integer register 31 // // Some Alpha specific register names // #define FP 0x0f // integer register 15 #define GP 0x1d // integer register 29 // // This parallels ntreg.h // PUCHAR pszReg[] = { szF0, szF1, szF2, szF3, szF4, szF5, szF6, szF7, szF8, szF9, szF10, szF11, szF12, szF13, szF14, szF15, szF16, szF17, szF18, szF19, szF20, szF21, szF22, szF23, szF24, szF25, szF26, szF27, szF28, szF29, szF30, szF31, szR0, szR1, szR2, szR3, szR4, szR5, szR6, szR7, szR8, szR9, szR10, szR11, szR12, szR13, szR14, szR15, szR16, szR17, szR18, szR19, szR20, szR21, szR22, szR23, szR24, szR25, szR26, szR27, szR28, szR29, szR30, szR31, szFpcr, szSoftFpcr, szFir, szPsr, //szIE, szFlagMode, szFlagIe, szFlagIrql, // // Currently assuming this is right since shadows alpha.h; // but know that alpha.h flag's are wrong. // szEaPReg, szExpPReg, szRaPReg, szGPReg, // psuedo-registers szU0Preg, szU1Preg, szU2Preg, szU3Preg, szU4Preg, szU5Preg, szU6Preg, szU7Preg, szU8Preg, szU9Preg }; #define REGNAMESIZE sizeof(pszReg) / sizeof(PUCHAR) // // from ntsdp.h: ULONG RegIndex, Shift, Mask; // PSR & IE definitions are from ksalpha.h // which is generated automatically. // Steal from \\bbox2\alphado\nt\public\sdk\inc\ksalpha.h // NB: our masks are already shifted: // struct Reg { char *psz; ULONG value; }; struct SubReg { ULONG regindex; ULONG shift; ULONG mask; }; struct SubReg subregname[] = { { REGPSR, PSR_MODE, PSR_MODE_MASK }, { REGPSR, PSR_IE, PSR_IE_MASK }, { REGPSR, PSR_IRQL, PSR_IRQL_MASK }, }; /*** UserRegTest - test if index is a user-defined register * * Purpose: * Test if register is user-defined for upper routines. * * Input: * index - index of register * * Returns: * TRUE if user-defined register, else FALSE * *************************************************************************/ BOOLEAN UserRegTest (ULONG index) { return (BOOLEAN)(index >= PREGU0 && index <= PREGU12); } /*** GetRegFlagValue - get register or flag value * * Purpose: * Return the value of the specified register or flag. * This routine calls GetRegValue to get the register * value and shifts and masks appropriately to extract a * flag value. * * Input: * regnum - register or flag specification * * Returns: * Value of register or flag. *************************************************************************/ DWORDLONG GetRegFlagValue ( PDEBUGPACKET dp, ULONG regnum ) { DWORDLONG value; if (regnum < FLAGBASE || regnum >= PREGBASE) { value = GetRegValue(dp, regnum); }else { regnum -= FLAGBASE; value = GetRegValue(dp, subregname[regnum].regindex); value = (value >> subregname[regnum].shift) & subregname[regnum].mask; } return value; } BOOLEAN NeedUpper( DWORDLONG value ) { // // if the high bit of the low part is set, then the // high part must be all ones, else it must be zero. // return ( ((value & 0xffffffff80000000L) != 0xffffffff80000000L) && (((value & 0x80000000L) != 0) || ((value & 0xffffffff00000000L) != 0)) ); } /*** GetRegValue - get register value * * Purpose: * Returns the value of the register from the processor * context structure. * * Input: * regnum - register specification * * Returns: * value of the register from the context structure * *************************************************************************/ DWORDLONG GetRegValue ( PDEBUGPACKET dp, ULONG regnum ) { return *(&dp->tctx->context.FltF0 + regnum); } void GetFloatingPointRegValue( PDEBUGPACKET dp, ULONG regnum, PCONVERTED_DOUBLE dv ) { dv->li.LowPart = (DWORD)(*(&dp->tctx->context.FltF0 + regnum) & 0xffffffff); dv->li.HighPart = (DWORD)(*(&dp->tctx->context.FltF0 + regnum) >> 32); } /*** GetIntRegNumber - Get a register number * * * Purpose: * Get a register number, from an index value. * There are places where we want integers to be * numbered from 0-31, and this converts into * a CONTEXT structure. * * Input: * index: integer register number, between 0 and 31 * * Output: * regnum: offset into the CONTEXT structure * * Exceptions: * None * * Notes: * This is dependent on the CONTEXT structure * ******************************************************************/ ULONG GetIntRegNumber (ULONG index) { /* if (index == 26) { return(REGRA); } if (index < 26) { return(REGBASE + index); } if (index > 26) { return(REGBASE + index - 1); } */ return(REGBASE + index); } ULONG GetRegString (PUCHAR pszString) { ULONG count; for (count = 0; count < REGNAMESIZE; count++) if (!strcmp(pszString, pszReg[count])) return count; return 0xffffffff; } void GetRegPCValue (PDEBUGPACKET dp, PDWORDLONG Address) { *Address = GetRegValue(dp, REGFIR); return; } #if 0 PULONG GetRegFPValue (PDEBUGPACKET dp) { static DWORDLONG addrFP; addrFP = GetRegValue(dp, FP_REG); return &addrFP; } #endif /*** OutputAllRegs - output all registers and present instruction * * Purpose: * Function of "r" command. * * To output the current register state of the processor. * All integer registers are output as well as processor status * registers. Important flag fields are also output separately. * OutDisCurrent is called to output the current instruction(s). * * Input: * None. * * Output: * None. * *************************************************************************/ VOID OutputAllRegs( PDEBUGPACKET dp, BOOL Show64 ) { int regindex; int regnumber; DWORDLONG regvalue; for (regindex = 0; regindex < 34; regindex++) { regnumber = GetIntRegNumber(regindex); regvalue = GetRegValue(dp, regnumber); if ( Show64 || regindex == 32 || regindex == 33) { lprintfs("%4s=%08lx %08lx", pszReg[regnumber], (ULONG)(regvalue >> 32), (ULONG)(regvalue & 0xffffffff)); if (regindex % 3 == 2) { lprintfs("\r\n"); } else { lprintfs(" "); } } else { lprintfs("%4s=%08lx%c", pszReg[regnumber], (ULONG)(regvalue & 0xfffffff), NeedUpper(regvalue) ? '*' : ' ' ); if (regindex % 5 == 4) { lprintfs("\r\n"); } else { lprintfs(" "); } } } // // print out the fpcr as 64 bits regardless, // and the FIR and Fpcr's - assuming we know they follow // the floating and integer registers. // regnumber = GetIntRegNumber(34); // Fir lprintfs("%4s=%08lx\r\n", pszReg[regnumber], (ULONG)GetRegValue(dp, regnumber)); regnumber = GetIntRegNumber(35); // Psr lprintfs("%4s=%08lx\r\n", pszReg[regnumber], (ULONG)GetRegValue(dp, regnumber)); lprintfs("mode=%1lx ie=%1lx irql=%1lx \r\n", (ULONG)GetRegFlagValue(dp, FLAGMODE), (ULONG)GetRegFlagValue(dp, FLAGIE), (ULONG)GetRegFlagValue(dp, FLAGIRQL)); } /*** OutputOneReg - output one register value * * Purpose: * Function for the "r " command. * * Output the value for the specified register or flag. * * Input: * regnum - register or flag specification * * Output: * None. * *************************************************************************/ VOID OutputOneReg ( PDEBUGPACKET dp, ULONG regnum, BOOLEAN Show64 ) { DWORDLONG value; value = GetRegFlagValue(dp, regnum); if (regnum >= FLAGBASE) { lprintfs("%lx\r\n", (ULONG)value); } else if (Show64) { lprintfs("%08lx %08lx\r\n", (ULONG)(value >> 32), (ULONG)(value & 0xffffffff)); } else { lprintfs("%08lx%s\r\n", (ULONG)value, NeedUpper(value)?"*":""); } } PUCHAR RegNameFromIndex (ULONG index) { return pszReg[index]; }