/*++ Copyright (c) 1992 Microsoft Corporation Module Name: mipsmach.c Abstract: This file contains the MIPS specific code for dealing with machine dependent issues that invlove registers, instruction disassembly, function calling and other interesting things. Author: Jim Schaad (jimsch) Environment: Win32 - User Notes: --*/ #include "precomp.h" extern LPDM_MSG LpDmMsg; extern CRITICAL_SECTION csContinueQueue; typedef enum _MIPS_InstrType { mips_itype_Imm, mips_itype_Jump, mips_itype_Reg, mips_itype_dont_care } MIPS_InstrType; BOOL IsRet( HTHDX hthd, LPADDR addr ) { DWORD instr; DWORD cBytes; if (!AddrReadMemory( hthd->hprc, hthd, addr, &instr, 4, &cBytes )) { return FALSE; } return (instr == 0x03e00008); // JR r31 } void IsCall ( HTHDX hthd, LPADDR lpaddr, LPINT lpf, BOOL fStepOver ) /*++ Routine Description: IsCall Arguments: hthd - Supplies the handle to the thread lpaddr - Supplies the address to be check for a call instruction lpf - Returns class of instruction: CALL BREAKPOINT_INSTRUCTION SOFTWARE_INTERRUPT FALSE Return Value: None. --*/ { ULONG opcode; ADDR firaddr = *lpaddr; DWORD length; ULONGLONG *regArray = &hthd->context.XIntZero; INSTR disinstr; BOOL r; if (hthd->fIsCallDone) { *lpaddr = hthd->addrIsCall; *lpf = hthd->iInstrIsCall; return; } /* * Assume that this is not a call instruction */ *lpf = FALSE; /* * Read in the dword which contains the instruction under * inspection. */ r = AddrReadMemory(hthd->hprc, hthd, &firaddr, &disinstr.instruction, sizeof(DWORD), &length ); if (!r || length != sizeof(DWORD)) { goto done; } /* * Assume that this is a jump instruction and get the opcode. * This is the top 6 bits of the instruction dword. */ opcode = disinstr.jump_instr.Opcode; /* * The first thing to check for is the SPECIAL instruction. * BREAK and JALR */ if (opcode == 0x00L) { /* * There are one opcode in the SPECIAL range which need to * be treaded specially. * BREAK: * If the value is 0x16 then this was a "breakpoint" set * by the debugger. Other values represent different * exceptions which were programmed in by the code writer. */ if (disinstr.break_instr.Function == 0x0D) { if (disinstr.break_instr.Code == 0x16) { *lpf = INSTR_BREAKPOINT; } else { *lpf = INSTR_SOFT_INTERRUPT; } } else if (disinstr.special_instr.Funct == 0x09L) { *lpf = INSTR_IS_CALL; } } /* * Next item is REGIMM * BLTZAL, BGEZAL, BLTZALL, BGEZALL */ else if (opcode == 0x01L) { if (((disinstr.immed_instr.RT & ~0x3) == 0x10) && ((((LONGLONG)regArray[disinstr.immed_instr.RS]) >= 0) == (BOOL)(disinstr.immed_instr.RT & 0x01))) { *lpf = INSTR_IS_CALL; } } /* * Next item is JAL */ else if (opcode == 0x03) { *lpf = INSTR_IS_CALL; } DPRINT(1, ("(IsCall?) FIR=%08x Type=%s\n", GetAddrOff(firaddr), (*lpf==INSTR_IS_CALL? "CALL": (*lpf==INSTR_BREAKPOINT? "BREAKPOINT": (*lpf==INSTR_SOFT_INTERRUPT? "INTERRUPT": "NORMAL"))) ) ); done: if (*lpf==INSTR_IS_CALL) { lpaddr->addr.off += BP_SIZE + DELAYED_BRANCH_SLOT_SIZE; hthd->addrIsCall = *lpaddr; } else if ( *lpf==INSTR_SOFT_INTERRUPT ) { lpaddr->addr.off += BP_SIZE; } hthd->iInstrIsCall = *lpf; return; } /* IsCall() */ #if 0 ULONG GetNextOffset ( HTHDX hthd, BOOL fStep ) /*++ Routine Description: From a limited disassembly of the instruction pointed by the FIR register, compute the offset of the next instruction for either a trace or step operation. Arguments: hthd - Supplies the handle to the thread to get the next offset for fStep - Supplies TRUE for STEP offset and FALSE for trace offset Return Value: Offset to place breakpoint at for doing a STEP or TRACE --*/ { ULONG returnvalue; ULONG opcode; ADDR firaddr; DWORD length; ULONGLONG *regArray = &hthd->context.XIntZero; INSTR disinstr; BOOL r; AddrFromHthdx(&firaddr, hthd); r = AddrReadMemory(hthd->hprc, hthd, &firaddr, &disinstr.instruction, sizeof(DWORD), &length); if (!r || length != sizeof(DWORD)) { DPRINT(1, ("GetNextOffset: AddrReadMemory failed %I64x\n", GetAddrOff(firaddr)) ); assert(FALSE); return 4; } opcode = disinstr.jump_instr.Opcode; returnvalue = firaddr.addr.off + sizeof(ULONG) * 2; /* assume delay slot */ if (disinstr.instruction == 0x0000000c) { // stepping over a syscall instruction must set the breakpoint // at the caller's return address, not the inst after the syscall returnvalue = (DWORD)hthd->context.XIntRa; } else if (opcode == 0x00L /* SPECIAL */ && (disinstr.special_instr.Funct & ~0x01L) == 0x08L) { /* jr/jalr only */ if (disinstr.special_instr.Funct == 0x08L || !fStep) /* jr or trace */ returnvalue = (DWORD)regArray[disinstr.special_instr.RS]; } else if (opcode == 0x01L) { /* * For BCOND opcode, RT values 0x00 - 0x03, 0x10 - 0x13 * are defined as conditional jumps. A 16-bit relative * offset is taken if: * (RT is even and (RS) < 0 (0x00 = BLTZ, 0x02 = BLTZL, * 0x10 = BLTZAL, 0x12 = BLTZALL) * OR * RT is odd and (RS) >= 0 (0x01 = BGEZ, 0x03 = BGEZL * 0x11 = BGEZAL, 0x13 = BGEZALL)) * AND * (RT is 0x00 to 0x03 (BLTZ BGEZ BLTZL BGEZL non-linking) * OR * fStep is FALSE (linking and not stepping over)) */ if (((disinstr.immed_instr.RT & ~0x13) == 0x00) && (((LONGLONG)regArray[disinstr.immed_instr.RS] >= 0) == (BOOL)(disinstr.immed_instr.RT & 0x01)) && (((disinstr.immed_instr.RT & 0x10) == 0x00) || !fStep)) returnvalue = ((LONG)(SHORT)disinstr.immed_instr.Value << 2) + firaddr.addr.off + sizeof(ULONG); } else if ((opcode & ~0x01L) == 0x02) { /* * J and JAL opcodes (0x02 and 0x03). Target is * 26-bit absolute offset using high four bits of the * instruction location. Return target if J opcode or * not stepping over JAL. */ if (opcode == 0x02 || !fStep) returnvalue = (disinstr.jump_instr.Target << 2) + (firaddr.addr.off & 0xf0000000); } else if ((opcode & ~0x11L) == 0x04) { /* BEQ, BNE, BEQL, BNEL opcodes (0x04, 0x05, 0x14, 0x15). * Target is 16-bit relative offset to next instruction. * Return target if (BEQ or BEQL) and (RS) == (RT), * or (BNE or BNEL) and (RS) != (RT). */ if ((BOOL)(opcode & 0x01) == (BOOL)(regArray[disinstr.immed_instr.RS] != regArray[disinstr.immed_instr.RT])) returnvalue = ((LONG)(SHORT)disinstr.immed_instr.Value << 2) + firaddr.addr.off + sizeof(ULONG); } else if ((opcode & ~0x11L) == 0x06) { /* BLEZ, BGTZ, BLEZL, BGTZL opcodes (0x06, 0x07, 0x16, 0x17). * Target is 16-bit relative offset to next instruction. * Return target if (BLEZ or BLEZL) and (RS) <= 0, * or (BGTZ or BGTZL) and (RS) > 0. */ if ((BOOL)(opcode & 0x01) == (BOOL)((LONGLONG)regArray[disinstr.immed_instr.RS] > 0)) returnvalue = ((LONG)(SHORT)disinstr.immed_instr.Value << 2) + firaddr.addr.off + sizeof(ULONG); } else if (opcode == 0x11L && (disinstr.immed_instr.RS & ~0x04L) == 0x08L && (disinstr.immed_instr.RT & ~0x03L) == 0x00L) { /* COP1 opcode (0x11) with (RS) == 0x08 or (RS) == 0x0c and * (RT) == 0x00 to 0x03, producing BC1F, BC1T, BC1FL, BC1TL * instructions. Return target if (BC1F or BC1FL) and floating * point condition is FALSE or if (BC1T or BC1TL) and condition TRUE. * NOTENOTE - JLS -- I don't know that this is correct. rs = 0x3 * will also use CP3 */ // if ((disinstr.immed_instr.RT & 0x01) == GetRegFlagValue(FLAGFPC)) if ((disinstr.immed_instr.RT & 0x01) == ((hthd->context.XFsr>>23)&1)) { returnvalue = ((LONG)(SHORT)disinstr.immed_instr.Value << 2) + firaddr.addr.off + sizeof(ULONG); } } else { returnvalue -= sizeof(ULONG); /* remove delay slot */ } return returnvalue; } /* GetNextOffset() */ #endif // 0 XOSD SetupFunctionCall( LPEXECUTE_OBJECT_DM lpeo, LPEXECUTE_STRUCT lpes ) { /* * Can only execute functions on the current stopped thread. Therefore * assert that the current thread is stopped. */ assert(lpeo->hthd->tstate & ts_stopped); if (!(lpeo->hthd->tstate & ts_stopped)) { #ifdef OSDEBUG4 return xosdBadThread; #else return xosdInvalidThread; #endif } /* * Now get the current stack offset. */ lpeo->addrStack.addr.off = (DWORD)lpeo->hthd->context.XIntSp; /* * Now place the return address correctly */ lpeo->hthd->context.XFir = (LONG)lpeo->addrStart.addr.off; lpeo->hthd->context.XIntRa = (LONG)lpeo->addrStart.addr.off; /* * Set the instruction pointer to the starting addresses * and write the context back out */ lpeo->hthd->context.XFir = (LONG)lpeo->addrStart.addr.off; lpeo->hthd->fContextDirty = TRUE; return xosdNone; } BOOL CompareStacks( LPEXECUTE_OBJECT_DM lpeo ) /*++ Routine Description: This routine is used to determine if the stack pointers are currect for terminating function evaluation. Arguments: lpeo - Supplies the pointer to the DM Execute Object description Return Value: TRUE if the evaluation is to be terminated and FALSE otherwise --*/ { if (lpeo->addrStack.addr.off <= (DWORD)lpeo->hthd->context.XIntSp) { return TRUE; } return FALSE; } /* CompareStacks() */ #ifndef KERNEL UOFFSET GetSPFromNLGDest( HTHDX hthd, LPNLG_DESTINATION pNlgDest ) { UOFFSET dwRet; switch (pNlgDest->dwCode) { case NLG_CATCH_ENTER: // Catch handler case NLG_EXCEPT_ENTER: // Exception handler case NLG_FILTER_ENTER: // Exception filter case NLG_CATCH_LEAVE: // Return from Catch case NLG_FINALLY_ENTER: // Termination handlers case NLG_DESTRUCTOR_ENTER: // -GX handler case NLG_LONGJMPEX: // Exception safe longjmp dwRet = pNlgDest->uoffFramePointer; break; case NLG_LONGJMP: dwRet = pNlgDest->uoffFramePointer+1; break; default: dwRet = STACK_POINTER(hthd)+1; // emulate Virtual FP? break; } return dwRet; } PVOID InfoExceptionDuringStep( HTHDX hthd ) { Unreferenced(hthd); // Information that needs to be propagated from the step location // to the action handler when an exception occurs is passed in the // void * returned by this function. In case of Mips no information // needs to be passed currently. return NULL; } DWORDLONG GetFunctionResult( PCALLSTRUCT pcs ) { return pcs->context.XIntV0; } VOID vCallFunctionHelper( HTHDX hthd, FARPROC lpFunction, int cArgs, va_list vargs ) { int i; assert(Is64PtrSE(lpFunction)); for (i = 0; i < cArgs; i++) { (&hthd->context.XIntA0)[i] = va_arg(vargs, DWORD); } hthd->context.XIntRa = PC(hthd); Set_PC(hthd, lpFunction); hthd->fContextDirty = TRUE; } BOOL GetWndProcMessage( HTHDX hthd, UINT* pmsg ) /*++ Routine Description: This function is used to get the current Windows message (WM_CREATE, etc) when execution has been stopped at a wndproc. Return Value: False on failure; True otherwise. --*/ { *pmsg = (UINT)hthd->context.XIntA1; return TRUE; } #endif BOOL ProcessFrameStackWalkNextCmd( HPRCX hprc, HTHDX hthd, PCONTEXT context, LPVOID pctxPtrs ) { return FALSE; } #if 0 DWORD BranchUnassemble( void *Memory, ADDR *Addr, BOOL *IsBranch, BOOL *TargetKnown, BOOL *IsCall, BOOL *IsTable, ADDR *Target ) { ULONG OpCode; INSTR *Instr; UOFF32 Offset; UOFF32 TargetOffset; MIPS_InstrType itype = mips_itype_dont_care; assert( Memory ); assert( IsBranch ); assert( TargetKnown ); assert( IsCall ); assert( Target ); Offset = GetAddrOff( *Addr ); TargetOffset = 0; *IsBranch = FALSE; *IsTable = FALSE; Instr = (INSTR *)Memory; OpCode = Instr->jump_instr.Opcode; switch ( OpCode ) { case 0x00L: // Special switch ( Instr->special_instr.Funct ) { case 0x09L: // JALR *IsBranch = TRUE; *IsCall = TRUE; *TargetKnown = FALSE; itype = mips_itype_dont_care; break; case 0x08L: // JR *IsBranch = TRUE; *IsCall = FALSE; *TargetKnown = FALSE; itype = mips_itype_dont_care; break; } break; case 0x03: // JAL *IsBranch = TRUE; *IsCall = TRUE; *TargetKnown = TRUE; itype = mips_itype_Jump; break; case 0x02: // J *IsBranch = TRUE; *IsCall = FALSE; *TargetKnown = TRUE; itype = mips_itype_Jump; break; case 0x10: case 0x11: case 0x12: case 0x13: // BCz *IsBranch = TRUE; *IsCall = FALSE; *TargetKnown = TRUE; itype = mips_itype_Imm; break; case 0x04: // BEQ case 0x14: // BEQL case 0x05: // BNE case 0x15: // BNEL *IsBranch = TRUE; *IsCall = FALSE; *TargetKnown = TRUE; itype = mips_itype_Imm; break; case 0x01: // REGIMM itype = mips_itype_Imm; switch ( Instr->immed_instr.RT ) { case 0x00: // BLTZ case 0x01: // BGEZ case 0x02: // BLTZL case 0x03: // BGEZL *IsBranch = TRUE; *IsCall = FALSE; *TargetKnown = TRUE; break; case 0x10: // BLTZAL case 0x11: // BGEZAL case 0x12: // BLTZALL case 0x13: // BGEZALL *IsBranch = TRUE; *IsCall = TRUE; *TargetKnown = TRUE; break; } break; case 0x07: // BGTZ ? case 0x17: // BGTZL ? case 0x06: // BLEZ ? case 0x16: // BLEZL ? if ( Instr->immed_instr.RT == 0x00 ) { *IsBranch = TRUE; *IsCall = FALSE; *TargetKnown = TRUE; itype = mips_itype_Imm; } break; default: break; } if (*TargetKnown) { switch (itype) { default: case (mips_itype_Reg): case (mips_itype_dont_care): break; case (mips_itype_Imm): TargetOffset = (UOFF32)(LONG)((SHORT)Instr->immed_instr.Value << 2 ) + (Offset + sizeof(DWORD)); break; case (mips_itype_Jump): TargetOffset = (UOFF32)(Instr->jump_instr.Target << 2 ) | ((Offset + sizeof(DWORD)) & 0xF0000000); break; } } AddrInit( Target, 0, 0, TargetOffset, TRUE, TRUE, FALSE, FALSE ); return sizeof( DWORD ); } #endif /* note: "z" refers to a co-processor, with value = 0, 1, 2, or 3 instr opcode rs/rt/imm (Imm) mnemonic op type mnemonic rs/rt/rd/sa/fn (Reg) -------- -- ---- -------- --/--/--/--/--- ADD 00 Reg SPECIAL xx/xx/xx/00/20 ADDI 08 Imm ADDI xx/xx/xxxx ADDIU 09 Imm ADDIU xx/xx/xxxx ADDU 00 Reg SPECIAL xx/xx/xx/00/21 AND 00 Reg SPECIAL xx/xx/xx/00/24 ANDI 0a Imm ANDI xx/xx/xxxx * BCzF 1z Imm COPz 08/00/xxxx * BCzFL 1z Imm COPz 08/02/xxxx * BCzT 1z Imm COPz 08/01/xxxx * BCzTL 1z Imm COPz 08/03/xxxx * BEQ 04 Imm BEQ xx/xx/xxxx * BEQL 14 Imm BEQL xx/xx/xxxx * BGEZ 01 Imm REGIMM xx/01/xxxx * BGEZAL 01 Imm REGIMM xx/11/xxxx * BGEZALL 01 Imm REGIMM xx/13/xxxx * BGEZL 01 Imm REGIMM xx/03/xxxx * BGTZ 07 Imm BGTZ xx/00/xxxx * BGTZL 17 Imm BGTZL xx/00/xxxx * BLEZ 06 Imm BLEZ xx/00/xxxx * BLEZL 16 Imm BLEZL xx/00/xxxx * BLTZ 01 Imm REGIMM xx/00/xxxx * BLTZAL 01 Imm REGIMM xx/10/xxxx * BLTZALL 01 Imm REGIMM xx/12/xxxx * BLTZL 01 Imm REGIMM xx/02/xxxx * BNE 05 Imm BNE xx/xx/xxxx * BNEL 15 Imm BNEL xx/xx/xxxx BREAK 00 ? SPECIAL xx/xx/xx/xx/0c CACHE 2f Imm CACHE xx/xx/xxxx CFCz 1z ? COPz 02/xx/xx/xx/00 ? COPz 1z ? COPz 1x/xx/xxxx CTCz 1z Imm COPz 06/xx/xx/??/00 DADD 00 Reg SPECIAL xx/xx/xx/00/2c DADDI 18 Imm DADDI xx/xx/xxxx DADDIU 19 Imm DADDIU xx/xx/xxxx DADDU 00 Reg SPECIAL xx/xx/xx/00/2d DDIV 00 Reg SPECIAL xx/xx/00/00/1e DDIVU 00 Reg SPECIAL xx/xx/00/00/1f DIV 00 Reg SPECIAL xx/xx/00/00/1a DIVU 00 Imm SPECIAL xx/xx/00/00/1b DMFC0 10 Reg COP0 01/xx/xx/00/00 DMFC0 10 Reg COP0 05/xx/xx/00/00 DMULT 00 Reg SPECIAL xx/xx/00/00/1c DMULTU 00 Reg SPECIAL xx/xx/00/00/1d DSLL 00 Reg SPECIAL 00/xx/xx/xx/38 DSLLV 00 Reg SPECIAL 00/xx/xx/xx/14 DSLL32 00 Reg SPECIAL 00/xx/xx/xx/3c DSRA 00 Reg SPECIAL 00/xx/xx/xx/3b DSRAV 00 Reg SPECIAL 00/xx/xx/xx/17 DSRA32 00 Reg SPECIAL 00/xx/xx/xx/3f DSRL 00 Reg SPECIAL 00/xx/xx/xx/3a DSRLV 00 Reg SPECIAL 00/xx/xx/xx/16 DSRL32 00 Reg SPECIAL 00/xx/xx/xx/3e DSUB 00 Reg SPECIAL xx/xx/xx/00/2e DSUBU 00 Reg SPECIAL xx/xx/xx/00/2f ERET 10 Reg COP0 10/00/00/00/28 * J 02 Jump J xxxxxxx * JAL 03 Jump JAL xxxxxxx * JALR 00 Reg SPECIAL xx/00/xx/00/09 * JR 00 Reg SPECIAL xx/00/00/00/08 LB 30 Imm LB xx/xx/xxxx LBU 34 Imm LBU xx/xx/xxxx LD 37 Imm LD xx/xx/xxxx LDCz 3? Imm LDCz xx/xx/xxxx LDL 1a Imm LDL xx/xx/xxxx LDR 1b Imm LDR xx/xx/xxxx LH 21 Imm LH xx/xx/xxxx LHU 25 Imm LHU xx/xx/xxxx LL 30 Imm LL xx/xx/xxxx LLD 34 Imm LLD xx/xx/xxxx LUI 1f Imm LUI 00/xx/xxxx LW 23 Imm LW xx/xx/xxxx LWCz 3z Imm LWCz xx/xx/xxxx LWL 22 Imm LWL xx/xx/xxxx LWR 25 Imm LWR xx/xx/xxxx LWU 2f Imm LWU xx/xx/xxxx MFC0 10 Reg COP0 00/xx/xx/00/00 MFCz 1z Reg COPz 00/xx/xx/00/00 MFHI 00 Reg SPECIAL 00/00/xx/00/10 MFLO 00 Reg SPECIAL 00/00/xx/00/12 MTC0 10 Reg COP0 04/xx/xx/00/00 MTCz 1z Reg COPz 04/xx/xx/00/00 MTHI 00 Reg SPECIAL xx/00/00/00/11 MTLO 00 Reg SPECIAL xx/00/00/00/13 MULT 00 Reg SPECIAL xx/xx/00/00/18 MULTU 00 Reg SPECIAL xx/xx/00/00/19 NOR 00 Reg SPECIAL xx/xx/xx/00/37 OR 00 Reg SPECIAL xx/xx/xx/00/35 ORI 0d Imm ORI xx/xx/xxxx SB 28 Imm SB xx/xx/xxxx SC 38 Imm SC xx/xx/xxxx SCD 3c Imm SCD xx/xx/xxxx SCDz 3? Imm SCDz xx/xx/xxxx SDL 2c Imm SDL xx/xx/xxxx SDR 2d Imm SDR xx/xx/xxxx SH 29 Imm SH xx/xx/xxxx SLL 00 Reg SPECIAL xx/xx/xx/xx/00 SLLV 00 Reg SPECIAL xx/xx/xx/xx/04 SLT 00 Reg SPECIAL xx/xx/xx/xx/2a SLTI 0a Imm SLTI xx/xx/xxxx SLTIU 0b Imm SLTIU xx/xx/xxxx SLTU 00 Reg SPECIAL xx/xx/xx/xx/2b SRA 00 Reg SPECIAL 00/xx/xx/xx/03 SRAV 00 Reg SPECIAL xx/xx/xx/00/07 SRL 00 Reg SPECIAL 00/xx/xx/xx/02 SRLV 00 Reg SPECIAL xx/xx/xx/00/06 SUB 00 Reg SPECIAL xx/xx/xx/00/22 SUBU 00 Reg SPECIAL xx/xx/xx/00/23 SW 2b Imm SW xx/xx/xxxx SWCz 3? Imm SWCz xx/xx/xxxx SWL 2a Reg SWL xx/xx/xxxx SWR 2d Reg SWR xx/xx/xxxx SYNC 00 Reg SPECIAL 00/00/00/00/0f SYSCALL 00 Reg SPECIAL xx/xx/xx/xx/0c TEQ 00 Reg SPECIAL xx/xx/xx/xx/36 TEQI 01 Imm REGIMM xx/0c/xxxx TGE 00 Reg SPECIAL xx/xx/xx/xx/30 TGEI 01 Reg REGIMM xx/08/xxxx TGEIU 01 Imm REGIMM xx/09/xxxx TGEU 00 Reg SPECIAL xx/xx/xx/xx/31 TLBP 10 Reg COP0 10/00/00/00/08 TLBR 10 Reg COP0 10/00/00/00/01 TLBWI 10 Reg COP0 10/00/00/00/02 TLBWR 10 Reg COP0 10/00/00/00/06 TLT 00 Reg SPECIAL xx/xx/xx/xx/32 TLTI 01 Imm REGIMM xx/0a/xxxx TLTIU 01 Imm REGIMM xx/0b/xxxx TLTU 00 Reg SPECIAL xx/xx/xx/xx/33 TNE 00 Reg SPECIAL xx/xx/xx/xx/3c TNEI 01 Imm REGIMM xx/0e/xxxx XOR 00 Reg SPECIAL xx/xx/xx/00/26 XORI 0c Imm XORI xx/xx/xxxx */ BOOL DecodeSingleStepEvent( HTHDX hthd, DEBUG_EVENT64 *de, PDWORD eventCode, PDWORD subClass ) /*++ Routine Description: Arguments: hthd - Supplies thread that has a single step exception pending de - Supplies the DEBUG_EVENT64 structure for the exception eventCode - Returns the remapped debug event id subClass - Returns the remapped subClass id Return Value: TRUE if event was a real single step or was successfully mapped to a breakpoint. FALSE if a register breakpoint occurred which was not expected. --*/ { return FALSE; } BOOL CoerceContext64To32( PCONTEXT pContext ) { PULONGLONG Src; PULONG Dst; ULONG Index; // If the target system is running a kernel with 64-bit addressing // enabled in user mode, then coerce the 64-bit context to 32-bits. DPRINT(1, ("ConvertContext64To32: ContextFlags == %08x\n", pContext->ContextFlags)); if ((pContext->ContextFlags & CONTEXT_EXTENDED_INTEGER) == CONTEXT_EXTENDED_INTEGER) { DPRINT(1, ("ConvertContext64To32: Ra == %016Lx\n", pContext->XIntRa)); Src = &pContext->XIntZero; Dst = &pContext->IntZero; for (Index = 0; Index < 32; Index += 1) { *Dst++ = (ULONG)*Src++; } pContext->ContextFlags &= ~CONTEXT_EXTENDED_INTEGER; pContext->ContextFlags |= CONTEXT_INTEGER; return TRUE; } return FALSE; } BOOL CoerceContext32To64 ( PCONTEXT pContext ) { PULONG Src; PULONGLONG Dst; ULONG Index; // If the target system is running a kernel with 64-bit addressing // enabled in user mode, then coerce the 32-bit context to 64-bits. DPRINT(1, ("ConvertContext32To64: ContextFlags == %08x\n", pContext->ContextFlags)); if ((pContext->ContextFlags & CONTEXT_EXTENDED_INTEGER) != CONTEXT_EXTENDED_INTEGER) { DPRINT(1, ("ConvertContext32To64: Ra == %08x\n", pContext->IntRa)); Dst = &pContext->XIntZero; Src = &pContext->IntZero; for (Index = 0; Index < 32; Index += 1) { *Dst++ = (LONG)*Src++; } pContext->ContextFlags |= CONTEXT_EXTENDED_INTEGER; return TRUE; } return FALSE; } ULONGLONG GetRegValue( PCONTEXT regs, int cvindex ) { if (cvindex < (CV_M4_IntZERO+32)) { return ((®s->XIntZero)[cvindex - CV_M4_IntZERO]); } switch (cvindex) { case CV_M4_IntLO: return regs->XIntLo; case CV_M4_IntHI: return regs->XIntHi; case CV_M4_Fir: return regs->XFir; case CV_M4_Psr: return regs->XPsr; default: assert(!"GetRegValue called with unrecognized index"); return (ULONGLONG)0 - 1; } }