/*++
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 <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "drwatson.h"
#include "proto.h"
#include "regs.h"
#include <alphaops.h>
#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 <ksalpha.h>
#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 <regname>" 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];
}