Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

744 lines
19 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Disassembly portions of Alpha machine implementation.
  4. //
  5. // Copyright (C) Microsoft Corporation, 2000-2001.
  6. //
  7. //----------------------------------------------------------------------------
  8. // TODO:
  9. // (3) Should registers be treated as 64 or 32bit? Note that Fregs are
  10. // 64bits only. -- All registers should be treated as 64bit values
  11. // since LDQ/EXTB is done for byte fetches (stores); the intermediate
  12. // values could be hidden.
  13. #include "ntsdp.hpp"
  14. #include "alpha_dis.h"
  15. #include "alpha_optable.h"
  16. // See Get/SetRegVal comments in machine.hpp.
  17. #define RegValError Do_not_use_GetSetRegVal_in_machine_implementations
  18. #define GetRegVal(index, val) RegValError
  19. #define GetRegVal32(index) RegValError
  20. #define GetRegVal64(index) RegValError
  21. #define SetRegVal(index, val) RegValError
  22. #define SetRegVal32(index, val) RegValError
  23. #define SetRegVal64(index, val) RegValError
  24. ADDR g_AlphaEffAddr;
  25. ALPHA_INSTRUCTION g_AlphaDisinstr;
  26. // these are defined in alphaops.h
  27. #define NUMBER_OF_BREAK_INSTRUCTIONS 3
  28. #define ALPHA_BP_LEN 4
  29. ULONG g_AlphaTrapInstr = CALLPAL_OP | BPT_FUNC;
  30. ULONG g_AlphaBreakInstrs[NUMBER_OF_BREAK_INSTRUCTIONS] =
  31. {
  32. CALLPAL_OP | BPT_FUNC,
  33. CALLPAL_OP | KBPT_FUNC,
  34. CALLPAL_OP | CALLKD_FUNC
  35. };
  36. #define OPRNDCOL 27 // Column for first operand
  37. #define EACOL 40 // column for effective address
  38. #define FPTYPECOL 40 // .. for the type of FP instruction
  39. BOOL
  40. AlphaMachineInfo::Disassemble (
  41. PADDR poffset,
  42. PSTR bufptr,
  43. BOOL fEAout
  44. )
  45. {
  46. ULONG opcode;
  47. ULONG64 Ea; // Effective Address
  48. POPTBLENTRY pEntry;
  49. m_BufStart = m_Buf = bufptr;
  50. sprintAddr(&m_Buf, poffset);
  51. *m_Buf++ = ':';
  52. *m_Buf++ = ' ';
  53. if (!GetMemDword(poffset, &g_AlphaDisinstr.Long)) {
  54. BufferString("???????? ????\n");
  55. *m_Buf = '\0';
  56. return(FALSE);
  57. }
  58. BufferHex(g_AlphaDisinstr.Long, 8, FALSE); // Output instruction in Hex
  59. *m_Buf++ = ' ';
  60. opcode = g_AlphaDisinstr.Memory.Opcode; // Select disassembly procedure from
  61. pEntry = findOpCodeEntry(opcode); // Get non-func entry for this code
  62. switch (pEntry->iType) {
  63. case ALPHA_UNKNOWN:
  64. BufferString(pEntry->pszAlphaName);
  65. break;
  66. case ALPHA_MEMORY:
  67. BufferString(pEntry->pszAlphaName);
  68. BufferBlanks(OPRNDCOL);
  69. BufferReg(g_AlphaDisinstr.Memory.Ra);
  70. *m_Buf++ = ',';
  71. BufferHex(g_AlphaDisinstr.Memory.MemDisp, (WIDTH_MEM_DISP + 3)/4, TRUE );
  72. *m_Buf++ = '(';
  73. BufferReg(g_AlphaDisinstr.Memory.Rb);
  74. *m_Buf++ = ')';
  75. break;
  76. case ALPHA_FP_MEMORY:
  77. BufferString(pEntry->pszAlphaName);
  78. BufferBlanks(OPRNDCOL);
  79. BufferFReg(g_AlphaDisinstr.Memory.Ra);
  80. *m_Buf++ = ',';
  81. BufferHex(g_AlphaDisinstr.Memory.MemDisp, (WIDTH_MEM_DISP + 3)/4, TRUE );
  82. *m_Buf++ = '(';
  83. BufferReg(g_AlphaDisinstr.Memory.Rb);
  84. *m_Buf++ = ')';
  85. break;
  86. case ALPHA_MEMSPC:
  87. BufferString(findFuncName(pEntry, g_AlphaDisinstr.Memory.MemDisp & BITS_MEM_DISP));
  88. //
  89. // Some memory special instructions have an operand
  90. //
  91. switch (g_AlphaDisinstr.Memory.MemDisp & BITS_MEM_DISP) {
  92. case FETCH_FUNC:
  93. case FETCH_M_FUNC:
  94. // one operand, in Rb
  95. BufferBlanks(OPRNDCOL);
  96. *m_Buf++ = '0';
  97. *m_Buf++ = '(';
  98. BufferReg(g_AlphaDisinstr.Memory.Rb);
  99. *m_Buf++ = ')';
  100. break;
  101. case RS_FUNC:
  102. case RC_FUNC:
  103. case RPCC_FUNC:
  104. // one operand, in Ra
  105. BufferBlanks(OPRNDCOL);
  106. BufferReg(g_AlphaDisinstr.Memory.Ra);
  107. break;
  108. case MB_FUNC:
  109. case WMB_FUNC:
  110. case MB2_FUNC:
  111. case MB3_FUNC:
  112. case TRAPB_FUNC:
  113. case EXCB_FUNC:
  114. // no operands
  115. break;
  116. default:
  117. printf("we shouldn't get here \n");
  118. break;
  119. }
  120. break;
  121. case ALPHA_JUMP:
  122. BufferString(findFuncName(pEntry, g_AlphaDisinstr.Jump.Function));
  123. BufferBlanks(OPRNDCOL);
  124. BufferReg(g_AlphaDisinstr.Jump.Ra);
  125. *m_Buf++ = ',';
  126. *m_Buf++ = '(';
  127. BufferReg(g_AlphaDisinstr.Jump.Rb);
  128. *m_Buf++ = ')';
  129. *m_Buf++ = ',';
  130. BufferHex(g_AlphaDisinstr.Jump.Hint, (WIDTH_HINT + 3)/4, TRUE);
  131. Ea = GetReg64(GetIntRegNumber(g_AlphaDisinstr.Jump.Rb)) & (~3);
  132. BufferEffectiveAddress(Ea);
  133. break;
  134. case ALPHA_BRANCH:
  135. BufferString(pEntry->pszAlphaName);
  136. BufferBlanks(OPRNDCOL);
  137. BufferReg(g_AlphaDisinstr.Branch.Ra);
  138. *m_Buf++ = ',';
  139. //
  140. // The next line might be a call to GetNextOffset, but
  141. // GetNextOffset assumes that it should work from FIR.
  142. //
  143. Ea = Flat(*poffset) +
  144. sizeof(ULONG) +
  145. (g_AlphaDisinstr.Branch.BranchDisp * 4);
  146. BufferHex(Ea, 16, FALSE);
  147. BufferEffectiveAddress(Ea);
  148. break;
  149. case ALPHA_FP_BRANCH:
  150. BufferString(pEntry->pszAlphaName);
  151. BufferBlanks(OPRNDCOL);
  152. BufferFReg(g_AlphaDisinstr.Branch.Ra);
  153. *m_Buf++ = ',';
  154. //
  155. // The next line might be a call to GetNextOffset, but
  156. // GetNextOffset assumes that it should work from FIR.
  157. //
  158. Ea = Flat(*poffset) +
  159. sizeof(ULONG) +
  160. (g_AlphaDisinstr.Branch.BranchDisp * 4);
  161. BufferHex(Ea, 16, FALSE);
  162. BufferEffectiveAddress(Ea);
  163. break;
  164. case ALPHA_OPERATE:
  165. BufferString(findFuncName(pEntry, g_AlphaDisinstr.OpReg.Function));
  166. BufferBlanks(OPRNDCOL);
  167. if (g_AlphaDisinstr.OpReg.Opcode != SEXT_OP) {
  168. BufferReg(g_AlphaDisinstr.OpReg.Ra);
  169. *m_Buf++ = ',';
  170. }
  171. if (g_AlphaDisinstr.OpReg.RbvType) {
  172. *m_Buf++ = '#';
  173. BufferHex(g_AlphaDisinstr.OpLit.Literal, (WIDTH_LIT + 3)/4, TRUE);
  174. } else {
  175. BufferReg(g_AlphaDisinstr.OpReg.Rb);
  176. }
  177. *m_Buf++ = ',';
  178. BufferReg(g_AlphaDisinstr.OpReg.Rc);
  179. break;
  180. case ALPHA_FP_OPERATE:
  181. {
  182. ULONG Function;
  183. ULONG Flags;
  184. Flags = g_AlphaDisinstr.FpOp.Function & MSK_FP_FLAGS;
  185. Function = g_AlphaDisinstr.FpOp.Function & MSK_FP_OP;
  186. #if 0
  187. if (fVerboseBuffer) {
  188. dprintf("In FP_OPERATE: Flags %08x Function %08x\n",
  189. Flags, Function);
  190. dprintf("opcode %d \n", opcode);
  191. }
  192. #endif
  193. //
  194. // CVTST and CVTST/S are different: they look like
  195. // CVTTS with some flags set
  196. //
  197. if (Function == CVTTS_FUNC) {
  198. if (g_AlphaDisinstr.FpOp.Function == CVTST_S_FUNC) {
  199. Function = CVTST_S_FUNC;
  200. Flags = NONE_FLAGS;
  201. }
  202. if (g_AlphaDisinstr.FpOp.Function == CVTST_FUNC) {
  203. Function = CVTST_FUNC;
  204. Flags = NONE_FLAGS;
  205. }
  206. }
  207. BufferString(findFuncName(pEntry, Function));
  208. //
  209. // Append the opcode qualifier, if any, to the opcode name.
  210. //
  211. if ( (opcode == IEEEFP_OP) || (opcode == VAXFP_OP)
  212. || (Function == CVTQL_FUNC) ) {
  213. BufferString(findFlagName(Flags, Function));
  214. }
  215. BufferBlanks(OPRNDCOL);
  216. //
  217. // If this is a convert instruction, only Rb and Rc are used
  218. //
  219. if (strncmp("cvt", findFuncName(pEntry, Function), 3) != 0) {
  220. BufferFReg(g_AlphaDisinstr.FpOp.Fa);
  221. *m_Buf++ = ',';
  222. }
  223. BufferFReg(g_AlphaDisinstr.FpOp.Fb);
  224. *m_Buf++ = ',';
  225. BufferFReg(g_AlphaDisinstr.FpOp.Fc);
  226. break;
  227. }
  228. case ALPHA_FP_CONVERT:
  229. BufferString(pEntry->pszAlphaName);
  230. BufferBlanks(OPRNDCOL);
  231. BufferFReg(g_AlphaDisinstr.FpOp.Fa);
  232. *m_Buf++ = ',';
  233. BufferFReg(g_AlphaDisinstr.FpOp.Fb);
  234. break;
  235. case ALPHA_CALLPAL:
  236. BufferString(findFuncName(pEntry, g_AlphaDisinstr.Pal.Function));
  237. break;
  238. case ALPHA_EV4_PR:
  239. if ((g_AlphaDisinstr.Long & MSK_EV4_PR) == 0)
  240. {
  241. BufferString("NOP");
  242. }
  243. else
  244. {
  245. BufferString(pEntry->pszAlphaName);
  246. BufferBlanks(OPRNDCOL);
  247. BufferReg(g_AlphaDisinstr.EV4_PR.Ra);
  248. *m_Buf++ = ',';
  249. if(g_AlphaDisinstr.EV4_PR.Ra != g_AlphaDisinstr.EV4_PR.Rb)
  250. {
  251. BufferReg(g_AlphaDisinstr.EV4_PR.Rb);
  252. *m_Buf++ = ',';
  253. }
  254. BufferString(findFuncName(pEntry, (g_AlphaDisinstr.Long & MSK_EV4_PR)));
  255. }
  256. break;
  257. case ALPHA_EV4_MEM:
  258. BufferString(pEntry->pszAlphaName);
  259. BufferBlanks(OPRNDCOL);
  260. BufferReg(g_AlphaDisinstr.EV4_MEM.Ra);
  261. *m_Buf++ = ',';
  262. BufferReg(g_AlphaDisinstr.EV4_MEM.Rb);
  263. break;
  264. case ALPHA_EV4_REI:
  265. BufferString(pEntry->pszAlphaName);
  266. break;
  267. default:
  268. BufferString("Invalid type");
  269. break;
  270. }
  271. Off(*poffset) += sizeof(ULONG);
  272. NotFlat(*poffset);
  273. ComputeFlatAddress(poffset, NULL);
  274. *m_Buf++ = '\n';
  275. *m_Buf = '\0';
  276. return(TRUE);
  277. }
  278. void
  279. AlphaMachineInfo::BufferReg (ULONG regnum)
  280. {
  281. BufferString(RegNameFromIndex(GetIntRegNumber(regnum)));
  282. }
  283. void
  284. AlphaMachineInfo::BufferFReg (ULONG regnum)
  285. {
  286. *m_Buf++ = 'f';
  287. if (regnum > 9)
  288. *m_Buf++ = (UCHAR)('0' + regnum / 10);
  289. *m_Buf++ = (UCHAR)('0' + regnum % 10);
  290. }
  291. /*** BufferEffectiveAddress - Print EA symbolically
  292. *
  293. * Purpose:
  294. * Given the effective address (for a branch, jump or
  295. * memory instruction, print it symbolically, if
  296. * symbols are available.
  297. *
  298. * Input:
  299. * offset - computed by the caller as
  300. * for jumps, the value in Rb
  301. * for branches, func(PC, displacement)
  302. * for memory, func(PC, displacement)
  303. *
  304. * Returns:
  305. * None
  306. *
  307. *************************************************************************/
  308. void
  309. AlphaMachineInfo::BufferEffectiveAddress(
  310. ULONG64 offset
  311. )
  312. {
  313. CHAR chAddrBuffer[MAX_SYMBOL_LEN];
  314. ULONG64 displacement;
  315. PCHAR pszTemp;
  316. UCHAR ch;
  317. //
  318. // MBH - i386 compiler bug with fast calling standard.
  319. // If "chAddrBuffer is used as a calling argument to
  320. // GetSymbol, it believes (here, but not in the other
  321. // uses of GetSymbol that the size is 60+8=68.
  322. //
  323. PCHAR pch = chAddrBuffer;
  324. BufferBlanks(EACOL);
  325. GetSymbolStdCall(offset, pch, sizeof(chAddrBuffer), &displacement, NULL);
  326. if (chAddrBuffer[0])
  327. {
  328. pszTemp = chAddrBuffer;
  329. while (ch = *pszTemp++)
  330. {
  331. *m_Buf++ = ch;
  332. }
  333. if (displacement)
  334. {
  335. *m_Buf++ = '+';
  336. BufferHex(displacement, 8, TRUE);
  337. }
  338. }
  339. else
  340. {
  341. BufferHex(offset, 16, FALSE);
  342. }
  343. // Save EA.
  344. ADDRFLAT(&g_AlphaEffAddr, offset);
  345. }
  346. BOOL
  347. AlphaMachineInfo::IsBreakpointInstruction(PADDR Addr)
  348. {
  349. UCHAR Instr[ALPHA_BP_LEN];
  350. if (GetMemString(Addr, Instr, ALPHA_BP_LEN) != ALPHA_BP_LEN)
  351. {
  352. return FALSE;
  353. }
  354. LONG index;
  355. //
  356. // ALPHA has several breakpoint instructions - see
  357. // if we have hit any of them.
  358. //
  359. index = 0;
  360. do
  361. {
  362. if (!memcmp(Instr, (PUCHAR)&g_AlphaBreakInstrs[index], ALPHA_BP_LEN))
  363. {
  364. return TRUE;
  365. }
  366. }
  367. while (++index < NUMBER_OF_BREAK_INSTRUCTIONS);
  368. return FALSE;
  369. }
  370. HRESULT
  371. AlphaMachineInfo::InsertBreakpointInstruction(PUSER_DEBUG_SERVICES Services,
  372. ULONG64 Process,
  373. ULONG64 Offset,
  374. PUCHAR SaveInstr,
  375. PULONG64 ChangeStart,
  376. PULONG ChangeLen)
  377. {
  378. *ChangeStart = Offset;
  379. *ChangeLen = ALPHA_BP_LEN;
  380. ULONG Done;
  381. HRESULT Status;
  382. Status = Services->ReadVirtual(Process, Offset, SaveInstr,
  383. ALPHA_BP_LEN, &Done);
  384. if (Status == S_OK && Done != ALPHA_BP_LEN)
  385. {
  386. Status = HRESULT_FROM_WIN32(ERROR_READ_FAULT);
  387. }
  388. if (Status == S_OK)
  389. {
  390. Status = Services->WriteVirtual(Process, Offset, &g_AlphaTrapInstr,
  391. ALPHA_BP_LEN, &Done);
  392. if (Status == S_OK && Done != ALPHA_BP_LEN)
  393. {
  394. Status = HRESULT_FROM_WIN32(ERROR_WRITE_FAULT);
  395. }
  396. }
  397. return Status;
  398. }
  399. HRESULT
  400. AlphaMachineInfo::RemoveBreakpointInstruction(PUSER_DEBUG_SERVICES Services,
  401. ULONG64 Process,
  402. ULONG64 Offset,
  403. PUCHAR SaveInstr,
  404. PULONG64 ChangeStart,
  405. PULONG ChangeLen)
  406. {
  407. *ChangeStart = Offset;
  408. *ChangeLen = ALPHA_BP_LEN;
  409. ULONG Done;
  410. HRESULT Status;
  411. Status = Services->WriteVirtual(Process, Offset, SaveInstr,
  412. ALPHA_BP_LEN, &Done);
  413. if (Status == S_OK && Done != ALPHA_BP_LEN)
  414. {
  415. Status = HRESULT_FROM_WIN32(ERROR_WRITE_FAULT);
  416. }
  417. return Status;
  418. }
  419. void
  420. AlphaMachineInfo::AdjustPCPastBreakpointInstruction(PADDR Addr,
  421. ULONG BreakType)
  422. {
  423. DBG_ASSERT(BreakType == DEBUG_BREAKPOINT_CODE);
  424. SetPC(AddrAdd(Addr, ALPHA_BP_LEN));
  425. }
  426. BOOL
  427. AlphaMachineInfo::IsCallDisasm(PCSTR Disasm)
  428. {
  429. return strstr(Disasm, " jsr") != NULL;
  430. }
  431. BOOL
  432. AlphaMachineInfo::IsReturnDisasm(PCSTR Disasm)
  433. {
  434. return strstr(Disasm, " ret ") != NULL && strstr(Disasm, " ra") != NULL;
  435. }
  436. BOOL
  437. AlphaMachineInfo::IsSystemCallDisasm(PCSTR Disasm)
  438. {
  439. return strstr(Disasm, " CallSys") != NULL;
  440. }
  441. BOOL
  442. AlphaMachineInfo::IsDelayInstruction(PADDR Addr)
  443. {
  444. return(FALSE);
  445. }
  446. void
  447. AlphaMachineInfo::GetEffectiveAddr(PADDR Addr)
  448. {
  449. *Addr = g_AlphaEffAddr;
  450. }
  451. void
  452. AlphaMachineInfo::GetNextOffset(BOOL StepOver,
  453. PADDR NextAddr, PULONG NextMachine)
  454. {
  455. ULONG64 rv;
  456. ULONG opcode;
  457. ULONG64 firaddr;
  458. ULONG64 updatedpc;
  459. ULONG64 branchTarget;
  460. ADDR fir;
  461. // Canonical form to shorten tests; Abs is absolute value
  462. LONG Can, Abs;
  463. LARGE_INTEGER Rav;
  464. LARGE_INTEGER Rbv;
  465. LARGE_INTEGER Fav;
  466. // NextMachine is always the same.
  467. *NextMachine = m_ExecTypes[0];
  468. //
  469. // Get current address
  470. //
  471. firaddr = GetReg64(ALPHA_FIR);
  472. //
  473. // relative addressing updates PC first
  474. // Assume next sequential instruction is next offset
  475. //
  476. updatedpc = firaddr + sizeof(ULONG);
  477. rv = updatedpc;
  478. ADDRFLAT( &fir, firaddr);
  479. GetMemDword(&fir, &(g_AlphaDisinstr.Long)); // Get current instruction
  480. opcode = g_AlphaDisinstr.Memory.Opcode;
  481. switch(findOpCodeEntry(opcode)->iType)
  482. {
  483. case ALPHA_JUMP:
  484. switch(g_AlphaDisinstr.Jump.Function)
  485. {
  486. case JSR_FUNC:
  487. case JSR_CO_FUNC:
  488. if (StepOver)
  489. {
  490. //
  491. // Step over the subroutine call;
  492. //
  493. break;
  494. }
  495. //
  496. // fall through
  497. //
  498. case JMP_FUNC:
  499. case RET_FUNC:
  500. Rbv.QuadPart = GetReg64(GetIntRegNumber(g_AlphaDisinstr.Jump.Rb));
  501. if (m_Ptr64)
  502. {
  503. rv = (Rbv.QuadPart & (~3));
  504. }
  505. else
  506. {
  507. rv = EXTEND64(Rbv.LowPart & (~3));
  508. }
  509. break;
  510. }
  511. break;
  512. case ALPHA_BRANCH:
  513. branchTarget = (updatedpc + (g_AlphaDisinstr.Branch.BranchDisp * 4));
  514. Rav.QuadPart = GetReg64(GetIntRegNumber(g_AlphaDisinstr.Branch.Ra));
  515. //
  516. // set up a canonical value for computing the branch test
  517. // - works with ALPHA, MIPS and 386 hosts
  518. //
  519. Can = Rav.LowPart & 1;
  520. if ((LONG)Rav.HighPart < 0)
  521. {
  522. Can |= 0x80000000;
  523. }
  524. if ((Rav.LowPart & 0xfffffffe) || (Rav.HighPart & 0x7fffffff))
  525. {
  526. Can |= 2;
  527. }
  528. #if 0
  529. VerbOut("Rav High %08lx Low %08lx Canonical %08lx\n",
  530. Rav.HighPart, Rav.LowPart, Can);
  531. VerbOut("returnvalue %08lx branchTarget %08lx\n",
  532. rv, branchTarget);
  533. #endif
  534. switch(opcode)
  535. {
  536. case BR_OP: rv = branchTarget; break;
  537. case BSR_OP: if (!StepOver) rv = branchTarget; break;
  538. case BEQ_OP: if (Can == 0) rv = branchTarget; break;
  539. case BLT_OP: if (Can < 0) rv = branchTarget; break;
  540. case BLE_OP: if (Can <= 0) rv = branchTarget; break;
  541. case BNE_OP: if (Can != 0) rv = branchTarget; break;
  542. case BGE_OP: if (Can >= 0) rv = branchTarget; break;
  543. case BGT_OP: if (Can > 0) rv = branchTarget; break;
  544. case BLBC_OP: if ((Can & 0x1) == 0) rv = branchTarget; break;
  545. case BLBS_OP: if ((Can & 0x1) == 1) rv = branchTarget; break;
  546. }
  547. break;
  548. case ALPHA_FP_BRANCH:
  549. branchTarget = (updatedpc + (g_AlphaDisinstr.Branch.BranchDisp * 4));
  550. Fav.QuadPart = GetReg64(g_AlphaDisinstr.Branch.Ra);
  551. //
  552. // Set up a canonical value for computing the branch test
  553. //
  554. Can = Fav.HighPart & 0x80000000;
  555. //
  556. // The absolute value is needed -0 and non-zero computation
  557. //
  558. Abs = Fav.LowPart || (Fav.HighPart & 0x7fffffff);
  559. if (Can && (Abs == 0x0))
  560. {
  561. //
  562. // negative 0 should be considered as zero
  563. //
  564. Can = 0x0;
  565. }
  566. else
  567. {
  568. Can |= Abs;
  569. }
  570. #if 0
  571. VerbOut("Fav High %08lx Low %08lx Canonical %08lx Absolute %08lx\n",
  572. Fav.HighPart, Fav.LowPart, Can, Abs);
  573. VerbOut("returnvalue %08lx branchTarget %08lx\n",
  574. rv, branchTarget);
  575. #endif
  576. switch(opcode)
  577. {
  578. case FBEQ_OP: if (Can == 0) rv = branchTarget; break;
  579. case FBLT_OP: if (Can < 0) rv = branchTarget; break;
  580. case FBNE_OP: if (Can != 0) rv = branchTarget; break;
  581. case FBLE_OP: if (Can <= 0) rv = branchTarget; break;
  582. case FBGE_OP: if (Can >= 0) rv = branchTarget; break;
  583. case FBGT_OP: if (Can > 0) rv = branchTarget; break;
  584. }
  585. break;
  586. }
  587. #if 0
  588. VerbOut("GetNextOffset returning %08lx\n", rv);
  589. #endif
  590. ADDRFLAT( NextAddr, rv );
  591. }
  592. void
  593. AlphaMachineInfo::IncrementBySmallestInstruction(PADDR Addr)
  594. {
  595. AddrAdd(Addr, 4);
  596. }
  597. void
  598. AlphaMachineInfo::DecrementBySmallestInstruction(PADDR Addr)
  599. {
  600. AddrSub(Addr, 4);
  601. }
  602. void
  603. AlphaMachineInfo::PrintStackFrameAddresses(ULONG Flags,
  604. PDEBUG_STACK_FRAME StackFrame)
  605. {
  606. //
  607. // this is pure hack...
  608. // Alpha's "return address" is really the address of the
  609. // instruction where control left the frame. Show the address of
  610. // the next instruction, to make it easy to set a BP on the
  611. // return site. It will still be wrong sometimes, but it will
  612. // be right more often this way.
  613. //
  614. DEBUG_STACK_FRAME AlphaStackFrame = *StackFrame;
  615. if (AlphaStackFrame.ReturnOffset)
  616. {
  617. AlphaStackFrame.ReturnOffset += 4;
  618. }
  619. MachineInfo::PrintStackFrameAddresses(Flags, &AlphaStackFrame);
  620. }