1 //===-- DNBArchImplI386.cpp -------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Created by Greg Clayton on 6/25/07.
12 //===----------------------------------------------------------------------===//
14 #if defined(__i386__) || defined(__x86_64__)
16 #include <sys/cdefs.h>
19 #include "MacOSX/i386/DNBArchImplI386.h"
20 #include "MachProcess.h"
21 #include "MachThread.h"
23 extern "C" bool CPUHasAVX(); // Defined over in DNBArchImplX86_64.cpp
24 extern "C" bool CPUHasAVX512f(); // Defined over in DNBArchImplX86_64.cpp
25 #if defined(LLDB_DEBUGSERVER_RELEASE) || defined(LLDB_DEBUGSERVER_DEBUG)
26 enum debugState { debugStateUnknown, debugStateOff, debugStateOn };
28 static debugState sFPUDebugState = debugStateUnknown;
29 static debugState sAVXForceState = debugStateUnknown;
31 static bool DebugFPURegs() {
32 if (sFPUDebugState == debugStateUnknown) {
33 if (getenv("DNB_DEBUG_FPU_REGS"))
34 sFPUDebugState = debugStateOn;
36 sFPUDebugState = debugStateOff;
39 return (sFPUDebugState == debugStateOn);
42 static bool ForceAVXRegs() {
43 if (sFPUDebugState == debugStateUnknown) {
44 if (getenv("DNB_DEBUG_X86_FORCE_AVX_REGS"))
45 sAVXForceState = debugStateOn;
47 sAVXForceState = debugStateOff;
50 return (sAVXForceState == debugStateOn);
53 #define DEBUG_FPU_REGS (DebugFPURegs())
54 #define FORCE_AVX_REGS (ForceAVXRegs())
56 #define DEBUG_FPU_REGS (0)
57 #define FORCE_AVX_REGS (0)
176 // On i386 Darwin the eh_frame register numbers for ebp and esp are reversed
178 // It's due to an ancient compiler bug in the output of the eh_frame.
179 // Specifically, on i386 darwin eh_frame, 4 is ebp, 5 is esp.
180 // On i386 darwin debug_frame (and debug_info), 4 is esp, 5 is ebp.
216 dwarf_ymm0 = dwarf_xmm0,
217 dwarf_ymm1 = dwarf_xmm1,
218 dwarf_ymm2 = dwarf_xmm2,
219 dwarf_ymm3 = dwarf_xmm3,
220 dwarf_ymm4 = dwarf_xmm4,
221 dwarf_ymm5 = dwarf_xmm5,
222 dwarf_ymm6 = dwarf_xmm6,
223 dwarf_ymm7 = dwarf_xmm7,
224 dwarf_zmm0 = dwarf_xmm0,
225 dwarf_zmm1 = dwarf_xmm1,
226 dwarf_zmm2 = dwarf_xmm2,
227 dwarf_zmm3 = dwarf_xmm3,
228 dwarf_zmm4 = dwarf_xmm4,
229 dwarf_zmm5 = dwarf_xmm5,
230 dwarf_zmm6 = dwarf_xmm6,
231 dwarf_zmm7 = dwarf_xmm7,
252 debugserver_eflags = 9,
259 debugserver_stmm0 = 16,
260 debugserver_stmm1 = 17,
261 debugserver_stmm2 = 18,
262 debugserver_stmm3 = 19,
263 debugserver_stmm4 = 20,
264 debugserver_stmm5 = 21,
265 debugserver_stmm6 = 22,
266 debugserver_stmm7 = 23,
267 debugserver_fctrl = 24,
268 debugserver_fcw = debugserver_fctrl,
269 debugserver_fstat = 25,
270 debugserver_fsw = debugserver_fstat,
271 debugserver_ftag = 26,
272 debugserver_ftw = debugserver_ftag,
273 debugserver_fiseg = 27,
274 debugserver_fpu_cs = debugserver_fiseg,
275 debugserver_fioff = 28,
276 debugserver_ip = debugserver_fioff,
277 debugserver_foseg = 29,
278 debugserver_fpu_ds = debugserver_foseg,
279 debugserver_fooff = 30,
280 debugserver_dp = debugserver_fooff,
281 debugserver_fop = 31,
282 debugserver_xmm0 = 32,
283 debugserver_xmm1 = 33,
284 debugserver_xmm2 = 34,
285 debugserver_xmm3 = 35,
286 debugserver_xmm4 = 36,
287 debugserver_xmm5 = 37,
288 debugserver_xmm6 = 38,
289 debugserver_xmm7 = 39,
290 debugserver_mxcsr = 40,
291 debugserver_mm0 = 41,
292 debugserver_mm1 = 42,
293 debugserver_mm2 = 43,
294 debugserver_mm3 = 44,
295 debugserver_mm4 = 45,
296 debugserver_mm5 = 46,
297 debugserver_mm6 = 47,
298 debugserver_mm7 = 48,
299 debugserver_ymm0 = debugserver_xmm0,
300 debugserver_ymm1 = debugserver_xmm1,
301 debugserver_ymm2 = debugserver_xmm2,
302 debugserver_ymm3 = debugserver_xmm3,
303 debugserver_ymm4 = debugserver_xmm4,
304 debugserver_ymm5 = debugserver_xmm5,
305 debugserver_ymm6 = debugserver_xmm6,
306 debugserver_ymm7 = debugserver_xmm7,
307 debugserver_zmm0 = debugserver_xmm0,
308 debugserver_zmm1 = debugserver_xmm1,
309 debugserver_zmm2 = debugserver_xmm2,
310 debugserver_zmm3 = debugserver_xmm3,
311 debugserver_zmm4 = debugserver_xmm4,
312 debugserver_zmm5 = debugserver_xmm5,
313 debugserver_zmm6 = debugserver_xmm6,
314 debugserver_zmm7 = debugserver_xmm7,
315 debugserver_k0 = 118,
316 debugserver_k1 = 119,
317 debugserver_k2 = 120,
318 debugserver_k3 = 121,
319 debugserver_k4 = 122,
320 debugserver_k5 = 123,
321 debugserver_k6 = 124,
322 debugserver_k7 = 125,
325 uint64_t DNBArchImplI386::GetPC(uint64_t failValue) {
326 // Get program counter
327 if (GetGPRState(false) == KERN_SUCCESS)
328 return m_state.context.gpr.__eip;
332 kern_return_t DNBArchImplI386::SetPC(uint64_t value) {
333 // Get program counter
334 kern_return_t err = GetGPRState(false);
335 if (err == KERN_SUCCESS) {
336 m_state.context.gpr.__eip = static_cast<uint32_t>(value);
339 return err == KERN_SUCCESS;
342 uint64_t DNBArchImplI386::GetSP(uint64_t failValue) {
344 if (GetGPRState(false) == KERN_SUCCESS)
345 return m_state.context.gpr.__esp;
349 // Uncomment the value below to verify the values in the debugger.
350 //#define DEBUG_GPR_VALUES 1 // DO NOT CHECK IN WITH THIS DEFINE ENABLED
351 //#define SET_GPR(reg) m_state.context.gpr.__##reg = gpr_##reg
353 kern_return_t DNBArchImplI386::GetGPRState(bool force) {
354 if (force || m_state.GetError(e_regSetGPR, Read)) {
372 m_state.SetError(e_regSetGPR, Read, 0);
374 mach_msg_type_number_t count = e_regSetWordSizeGPR;
377 ::thread_get_state(m_thread->MachPortNumber(), __i386_THREAD_STATE,
378 (thread_state_t)&m_state.context.gpr, &count));
381 return m_state.GetError(e_regSetGPR, Read);
384 // Uncomment the value below to verify the values in the debugger.
385 //#define DEBUG_FPU_VALUES 1 // DO NOT CHECK IN WITH THIS DEFINE ENABLED
387 kern_return_t DNBArchImplI386::GetFPUState(bool force) {
388 if (force || m_state.GetError(e_regSetFPU, Read)) {
389 if (DEBUG_FPU_REGS) {
391 m_state.context.fpu.no_avx.__fpu_reserved[0] = -1;
392 m_state.context.fpu.no_avx.__fpu_reserved[1] = -1;
393 *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fcw) = 0x1234;
394 *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fsw) = 0x5678;
395 m_state.context.fpu.no_avx.__fpu_ftw = 1;
396 m_state.context.fpu.no_avx.__fpu_rsrv1 = UINT8_MAX;
397 m_state.context.fpu.no_avx.__fpu_fop = 2;
398 m_state.context.fpu.no_avx.__fpu_ip = 3;
399 m_state.context.fpu.no_avx.__fpu_cs = 4;
400 m_state.context.fpu.no_avx.__fpu_rsrv2 = 5;
401 m_state.context.fpu.no_avx.__fpu_dp = 6;
402 m_state.context.fpu.no_avx.__fpu_ds = 7;
403 m_state.context.fpu.no_avx.__fpu_rsrv3 = UINT16_MAX;
404 m_state.context.fpu.no_avx.__fpu_mxcsr = 8;
405 m_state.context.fpu.no_avx.__fpu_mxcsrmask = 9;
406 for (int i = 0; i < 16; ++i) {
408 m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = 'a';
409 m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = 'b';
410 m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = 'c';
411 m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = 'd';
412 m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = 'e';
413 m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = 'f';
414 m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = 'g';
415 m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = 'h';
417 m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN;
418 m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN;
419 m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN;
420 m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN;
421 m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN;
422 m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN;
423 m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN;
424 m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN;
427 m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg[i] = '0';
428 m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg[i] = '1';
429 m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg[i] = '2';
430 m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg[i] = '3';
431 m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg[i] = '4';
432 m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg[i] = '5';
433 m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg[i] = '6';
434 m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg[i] = '7';
436 for (int i = 0; i < sizeof(m_state.context.fpu.no_avx.__fpu_rsrv4); ++i)
437 m_state.context.fpu.no_avx.__fpu_rsrv4[i] = INT8_MIN;
438 m_state.context.fpu.no_avx.__fpu_reserved1 = -1;
440 if (CPUHasAVX() || FORCE_AVX_REGS) {
441 for (int i = 0; i < sizeof(m_state.context.fpu.avx.__avx_reserved1);
443 m_state.context.fpu.avx.__avx_reserved1[i] = INT8_MIN;
445 for (int i = 0; i < 16; ++i) {
446 m_state.context.fpu.avx.__fpu_ymmh0.__xmm_reg[i] = '0';
447 m_state.context.fpu.avx.__fpu_ymmh1.__xmm_reg[i] = '1';
448 m_state.context.fpu.avx.__fpu_ymmh2.__xmm_reg[i] = '2';
449 m_state.context.fpu.avx.__fpu_ymmh3.__xmm_reg[i] = '3';
450 m_state.context.fpu.avx.__fpu_ymmh4.__xmm_reg[i] = '4';
451 m_state.context.fpu.avx.__fpu_ymmh5.__xmm_reg[i] = '5';
452 m_state.context.fpu.avx.__fpu_ymmh6.__xmm_reg[i] = '6';
453 m_state.context.fpu.avx.__fpu_ymmh7.__xmm_reg[i] = '7';
456 if (CPUHasAVX512f() || FORCE_AVX_REGS) {
457 for (int i = 0; i < 8; ++i) {
458 m_state.context.fpu.avx512f.__fpu_k0.__opmask_reg[i] = '0';
459 m_state.context.fpu.avx512f.__fpu_k1.__opmask_reg[i] = '1';
460 m_state.context.fpu.avx512f.__fpu_k2.__opmask_reg[i] = '2';
461 m_state.context.fpu.avx512f.__fpu_k3.__opmask_reg[i] = '3';
462 m_state.context.fpu.avx512f.__fpu_k4.__opmask_reg[i] = '4';
463 m_state.context.fpu.avx512f.__fpu_k5.__opmask_reg[i] = '5';
464 m_state.context.fpu.avx512f.__fpu_k6.__opmask_reg[i] = '6';
465 m_state.context.fpu.avx512f.__fpu_k7.__opmask_reg[i] = '7';
468 for (int i = 0; i < 32; ++i) {
469 m_state.context.fpu.avx512f.__fpu_zmmh0.__ymm_reg[i] = '0';
470 m_state.context.fpu.avx512f.__fpu_zmmh1.__ymm_reg[i] = '1';
471 m_state.context.fpu.avx512f.__fpu_zmmh2.__ymm_reg[i] = '2';
472 m_state.context.fpu.avx512f.__fpu_zmmh3.__ymm_reg[i] = '3';
473 m_state.context.fpu.avx512f.__fpu_zmmh4.__ymm_reg[i] = '4';
474 m_state.context.fpu.avx512f.__fpu_zmmh5.__ymm_reg[i] = '5';
475 m_state.context.fpu.avx512f.__fpu_zmmh6.__ymm_reg[i] = '6';
476 m_state.context.fpu.avx512f.__fpu_zmmh7.__ymm_reg[i] = '7';
479 m_state.SetError(e_regSetFPU, Read, 0);
481 mach_msg_type_number_t count = e_regSetWordSizeFPU;
482 int flavor = __i386_FLOAT_STATE;
484 // On a machine with the AVX512 register set, a process only gets a
485 // full AVX512 register context after it uses the AVX512 registers;
486 // if the process has not yet triggered this change, trying to fetch
487 // the AVX512 registers will fail. Fall through to fetching the AVX
489 if (CPUHasAVX512f() || FORCE_AVX_REGS) {
490 count = e_regSetWordSizeAVX512f;
491 flavor = __i386_AVX512F_STATE;
492 m_state.SetError(e_regSetFPU, Read,
493 ::thread_get_state(m_thread->MachPortNumber(), flavor,
494 (thread_state_t)&m_state.context.fpu,
496 DNBLogThreadedIf(LOG_THREAD,
497 "::thread_get_state (0x%4.4x, %u, &fpu, %u => 0x%8.8x",
498 m_thread->MachPortNumber(), flavor, (uint32_t)count,
499 m_state.GetError(e_regSetFPU, Read));
500 if (m_state.GetError(e_regSetFPU, Read) == KERN_SUCCESS)
501 return m_state.GetError(e_regSetFPU, Read);
504 count = e_regSetWordSizeAVX;
505 flavor = __i386_AVX_STATE;
507 m_state.SetError(e_regSetFPU, Read,
508 ::thread_get_state(m_thread->MachPortNumber(), flavor,
509 (thread_state_t)&m_state.context.fpu,
511 DNBLogThreadedIf(LOG_THREAD,
512 "::thread_get_state (0x%4.4x, %u, &fpu, %u => 0x%8.8x",
513 m_thread->MachPortNumber(), flavor, (uint32_t)count,
514 m_state.GetError(e_regSetFPU, Read));
517 return m_state.GetError(e_regSetFPU, Read);
520 kern_return_t DNBArchImplI386::GetEXCState(bool force) {
521 if (force || m_state.GetError(e_regSetEXC, Read)) {
522 mach_msg_type_number_t count = e_regSetWordSizeEXC;
525 ::thread_get_state(m_thread->MachPortNumber(), __i386_EXCEPTION_STATE,
526 (thread_state_t)&m_state.context.exc, &count));
528 return m_state.GetError(e_regSetEXC, Read);
531 kern_return_t DNBArchImplI386::SetGPRState() {
532 kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber());
534 LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u "
535 "(SetGPRState() for stop_count = %u)",
536 m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount());
538 m_state.SetError(e_regSetGPR, Write,
539 ::thread_set_state(m_thread->MachPortNumber(),
541 (thread_state_t)&m_state.context.gpr,
542 e_regSetWordSizeGPR));
543 return m_state.GetError(e_regSetGPR, Write);
546 kern_return_t DNBArchImplI386::SetFPUState() {
547 if (DEBUG_FPU_REGS) {
548 m_state.SetError(e_regSetFPU, Write, 0);
549 return m_state.GetError(e_regSetFPU, Write);
551 int flavor = __i386_FLOAT_STATE;
552 mach_msg_type_number_t count = e_regSetWordSizeFPU;
553 if (CPUHasAVX512f() || FORCE_AVX_REGS) {
554 flavor = __i386_AVX512F_STATE;
555 count = e_regSetWordSizeAVX512f;
558 flavor = __i386_AVX_STATE;
559 count = e_regSetWordSizeAVX;
562 m_state.SetError(e_regSetFPU, Write,
563 ::thread_set_state(m_thread->MachPortNumber(), flavor,
564 (thread_state_t)&m_state.context.fpu,
566 return m_state.GetError(e_regSetFPU, Write);
570 kern_return_t DNBArchImplI386::SetEXCState() {
571 m_state.SetError(e_regSetEXC, Write,
572 ::thread_set_state(m_thread->MachPortNumber(),
573 __i386_EXCEPTION_STATE,
574 (thread_state_t)&m_state.context.exc,
575 e_regSetWordSizeEXC));
576 return m_state.GetError(e_regSetEXC, Write);
579 kern_return_t DNBArchImplI386::GetDBGState(bool force) {
580 if (force || m_state.GetError(e_regSetDBG, Read)) {
581 mach_msg_type_number_t count = e_regSetWordSizeDBG;
584 ::thread_get_state(m_thread->MachPortNumber(), __i386_DEBUG_STATE,
585 (thread_state_t)&m_state.context.dbg, &count));
587 return m_state.GetError(e_regSetDBG, Read);
590 kern_return_t DNBArchImplI386::SetDBGState(bool also_set_on_task) {
591 m_state.SetError(e_regSetDBG, Write,
592 ::thread_set_state(m_thread->MachPortNumber(),
594 (thread_state_t)&m_state.context.dbg,
595 e_regSetWordSizeDBG));
596 if (also_set_on_task) {
597 kern_return_t kret = ::task_set_state(
598 m_thread->Process()->Task().TaskPort(), __i386_DEBUG_STATE,
599 (thread_state_t)&m_state.context.dbg, e_regSetWordSizeDBG);
600 if (kret != KERN_SUCCESS)
601 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::SetDBGState failed "
602 "to set debug control register state: "
606 return m_state.GetError(e_regSetDBG, Write);
609 void DNBArchImplI386::ThreadWillResume() {
610 // Do we need to step this thread? If so, let the mach thread tell us so.
611 if (m_thread->IsStepping()) {
612 // This is the primary thread, let the arch do anything it needs
613 EnableHardwareSingleStep(true);
616 // Reset the debug status register, if necessary, before we resume.
617 kern_return_t kret = GetDBGState(false);
620 "DNBArchImplI386::ThreadWillResume() GetDBGState() => 0x%8.8x.", kret);
621 if (kret != KERN_SUCCESS)
624 DBG &debug_state = m_state.context.dbg;
625 bool need_reset = false;
626 uint32_t i, num = NumSupportedHardwareWatchpoints();
627 for (i = 0; i < num; ++i)
628 if (IsWatchpointHit(debug_state, i))
632 ClearWatchpointHits(debug_state);
633 kret = SetDBGState(false);
636 "DNBArchImplI386::ThreadWillResume() SetDBGState() => 0x%8.8x.", kret);
640 bool DNBArchImplI386::ThreadDidStop() {
643 m_state.InvalidateAllRegisterStates();
645 // Are we stepping a single instruction?
646 if (GetGPRState(true) == KERN_SUCCESS) {
647 // We are single stepping, was this the primary thread?
648 if (m_thread->IsStepping()) {
649 // This was the primary thread, we need to clear the trace
651 success = EnableHardwareSingleStep(false) == KERN_SUCCESS;
653 // The MachThread will automatically restore the suspend count
654 // in ThreadDidStop(), so we don't need to do anything here if
655 // we weren't the primary thread the last time
661 bool DNBArchImplI386::NotifyException(MachException::Data &exc) {
662 switch (exc.exc_type) {
665 case EXC_BAD_INSTRUCTION:
674 if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 2) {
675 // exc_code = EXC_I386_BPT
677 nub_addr_t pc = GetPC(INVALID_NUB_ADDRESS);
678 if (pc != INVALID_NUB_ADDRESS && pc > 0) {
680 // Check for a breakpoint at one byte prior to the current PC value
681 // since the PC will be just past the trap.
684 m_thread->Process()->Breakpoints().FindByAddress(pc);
686 // Backup the PC for i386 since the trap was taken and the PC
687 // is at the address following the single byte trap instruction.
688 if (m_state.context.gpr.__eip > 0) {
689 m_state.context.gpr.__eip = static_cast<uint32_t>(pc);
690 // Write the new PC back out
696 } else if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 1) {
697 // exc_code = EXC_I386_SGL
699 // Check whether this corresponds to a watchpoint hit event.
700 // If yes, set the exc_sub_code to the data break address.
702 uint32_t hw_index = GetHardwareWatchpointHit(addr);
703 if (hw_index != INVALID_NUB_HW_INDEX) {
704 exc.exc_data[1] = addr;
705 // Piggyback the hw_index in the exc.data.
706 exc.exc_data.push_back(hw_index);
714 case EXC_MACH_SYSCALL:
722 uint32_t DNBArchImplI386::NumSupportedHardwareWatchpoints() {
723 // Available debug address registers: dr0, dr1, dr2, dr3.
727 static uint32_t size_and_rw_bits(nub_size_t size, bool read, bool write) {
730 rw = 0x3; // READ or READ/WRITE
734 assert(0 && "read and write cannot both be false");
741 return (0x1 << 2) | rw;
743 return (0x3 << 2) | rw;
745 return (0x2 << 2) | rw;
747 assert(0 && "invalid size, must be one of 1, 2, 4, or 8");
751 void DNBArchImplI386::SetWatchpoint(DBG &debug_state, uint32_t hw_index,
752 nub_addr_t addr, nub_size_t size, bool read,
754 // Set both dr7 (debug control register) and dri (debug address register).
756 // dr7{7-0} encodes the local/gloabl enable bits:
757 // global enable --. .-- local enable
765 // dr7{31-16} encodes the rw/len bits:
766 // b_x+3, b_x+2, b_x+1, b_x
767 // where bits{x+1, x} => rw
768 // 0b00: execute, 0b01: write, 0b11: read-or-write, 0b10: io
769 // read-or-write (unused)
770 // and bits{x+3, x+2} => len
771 // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte
773 // dr0 -> bits{19-16}
774 // dr1 -> bits{23-20}
775 // dr2 -> bits{27-24}
776 // dr3 -> bits{31-28}
778 (1 << (2 * hw_index) |
779 size_and_rw_bits(size, read, write) << (16 + 4 * hw_index));
780 uint32_t addr_32 = addr & 0xffffffff;
783 debug_state.__dr0 = addr_32;
786 debug_state.__dr1 = addr_32;
789 debug_state.__dr2 = addr_32;
792 debug_state.__dr3 = addr_32;
796 "invalid hardware register index, must be one of 0, 1, 2, or 3");
801 void DNBArchImplI386::ClearWatchpoint(DBG &debug_state, uint32_t hw_index) {
802 debug_state.__dr7 &= ~(3 << (2 * hw_index));
805 debug_state.__dr0 = 0;
808 debug_state.__dr1 = 0;
811 debug_state.__dr2 = 0;
814 debug_state.__dr3 = 0;
818 "invalid hardware register index, must be one of 0, 1, 2, or 3");
823 bool DNBArchImplI386::IsWatchpointVacant(const DBG &debug_state,
825 // Check dr7 (debug control register) for local/global enable bits:
826 // global enable --. .-- local enable
833 return (debug_state.__dr7 & (3 << (2 * hw_index))) == 0;
836 // Resets local copy of debug status register to wait for the next debug
838 void DNBArchImplI386::ClearWatchpointHits(DBG &debug_state) {
839 // See also IsWatchpointHit().
840 debug_state.__dr6 = 0;
844 bool DNBArchImplI386::IsWatchpointHit(const DBG &debug_state,
846 // Check dr6 (debug status register) whether a watchpoint hits:
847 // is watchpoint hit?
854 return (debug_state.__dr6 & (1 << hw_index));
857 nub_addr_t DNBArchImplI386::GetWatchAddress(const DBG &debug_state,
861 return debug_state.__dr0;
863 return debug_state.__dr1;
865 return debug_state.__dr2;
867 return debug_state.__dr3;
869 assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3");
873 bool DNBArchImplI386::StartTransForHWP() {
874 if (m_2pc_trans_state != Trans_Done && m_2pc_trans_state != Trans_Rolled_Back)
875 DNBLogError("%s inconsistent state detected, expected %d or %d, got: %d",
876 __FUNCTION__, Trans_Done, Trans_Rolled_Back, m_2pc_trans_state);
877 m_2pc_dbg_checkpoint = m_state.context.dbg;
878 m_2pc_trans_state = Trans_Pending;
881 bool DNBArchImplI386::RollbackTransForHWP() {
882 m_state.context.dbg = m_2pc_dbg_checkpoint;
883 if (m_2pc_trans_state != Trans_Pending)
884 DNBLogError("%s inconsistent state detected, expected %d, got: %d",
885 __FUNCTION__, Trans_Pending, m_2pc_trans_state);
886 m_2pc_trans_state = Trans_Rolled_Back;
887 kern_return_t kret = SetDBGState(false);
890 "DNBArchImplI386::RollbackTransForHWP() SetDBGState() => 0x%8.8x.", kret);
892 if (kret == KERN_SUCCESS)
897 bool DNBArchImplI386::FinishTransForHWP() {
898 m_2pc_trans_state = Trans_Done;
901 DNBArchImplI386::DBG DNBArchImplI386::GetDBGCheckpoint() {
902 return m_2pc_dbg_checkpoint;
905 uint32_t DNBArchImplI386::EnableHardwareWatchpoint(nub_addr_t addr,
906 nub_size_t size, bool read,
908 bool also_set_on_task) {
909 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::EnableHardwareWatchpoint("
910 "addr = 0x%llx, size = %llu, read = %u, "
912 (uint64_t)addr, (uint64_t)size, read, write);
914 const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
916 // Can only watch 1, 2, 4, or 8 bytes.
917 if (!(size == 1 || size == 2 || size == 4 || size == 8))
918 return INVALID_NUB_HW_INDEX;
920 // We must watch for either read or write
921 if (read == false && write == false)
922 return INVALID_NUB_HW_INDEX;
924 // Read the debug state
925 kern_return_t kret = GetDBGState(false);
927 if (kret == KERN_SUCCESS) {
928 // Check to make sure we have the needed hardware support
931 DBG &debug_state = m_state.context.dbg;
932 for (i = 0; i < num_hw_watchpoints; ++i) {
933 if (IsWatchpointVacant(debug_state, i))
937 // See if we found an available hw breakpoint slot above
938 if (i < num_hw_watchpoints) {
941 // Modify our local copy of the debug state, first.
942 SetWatchpoint(debug_state, i, addr, size, read, write);
943 // Now set the watch point in the inferior.
944 kret = SetDBGState(also_set_on_task);
945 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::"
946 "EnableHardwareWatchpoint() "
947 "SetDBGState() => 0x%8.8x.",
950 if (kret == KERN_SUCCESS)
952 else // Revert to the previous debug state voluntarily. The transaction
953 // coordinator knows that we have failed.
954 m_state.context.dbg = GetDBGCheckpoint();
956 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::"
957 "EnableHardwareWatchpoint(): All "
958 "hardware resources (%u) are in use.",
962 return INVALID_NUB_HW_INDEX;
965 bool DNBArchImplI386::DisableHardwareWatchpoint(uint32_t hw_index,
966 bool also_set_on_task) {
967 kern_return_t kret = GetDBGState(false);
969 const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
970 if (kret == KERN_SUCCESS) {
971 DBG &debug_state = m_state.context.dbg;
972 if (hw_index < num_hw_points &&
973 !IsWatchpointVacant(debug_state, hw_index)) {
976 // Modify our local copy of the debug state, first.
977 ClearWatchpoint(debug_state, hw_index);
978 // Now disable the watch point in the inferior.
979 kret = SetDBGState(also_set_on_task);
980 DNBLogThreadedIf(LOG_WATCHPOINTS,
981 "DNBArchImplI386::DisableHardwareWatchpoint( %u )",
984 if (kret == KERN_SUCCESS)
986 else // Revert to the previous debug state voluntarily. The transaction
987 // coordinator knows that we have failed.
988 m_state.context.dbg = GetDBGCheckpoint();
994 // Iterate through the debug status register; return the index of the first hit.
995 uint32_t DNBArchImplI386::GetHardwareWatchpointHit(nub_addr_t &addr) {
996 // Read the debug state
997 kern_return_t kret = GetDBGState(true);
1000 "DNBArchImplI386::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.",
1002 if (kret == KERN_SUCCESS) {
1003 DBG &debug_state = m_state.context.dbg;
1004 uint32_t i, num = NumSupportedHardwareWatchpoints();
1005 for (i = 0; i < num; ++i) {
1006 if (IsWatchpointHit(debug_state, i)) {
1007 addr = GetWatchAddress(debug_state, i);
1008 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::"
1009 "GetHardwareWatchpointHit() found => "
1010 "%u (addr = 0x%llx).",
1016 return INVALID_NUB_HW_INDEX;
1019 // Set the single step bit in the processor status register.
1020 kern_return_t DNBArchImplI386::EnableHardwareSingleStep(bool enable) {
1021 if (GetGPRState(false) == KERN_SUCCESS) {
1022 const uint32_t trace_bit = 0x100u;
1024 m_state.context.gpr.__eflags |= trace_bit;
1026 m_state.context.gpr.__eflags &= ~trace_bit;
1027 return SetGPRState();
1029 return m_state.GetError(e_regSetGPR, Read);
1032 //----------------------------------------------------------------------
1033 // Register information definitions
1034 //----------------------------------------------------------------------
1036 #define DEFINE_GPR_PSEUDO_16(reg16, reg32) \
1038 e_regSetGPR, gpr_##reg16, #reg16, NULL, Uint, Hex, 2, 0, \
1039 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \
1040 INVALID_NUB_REGNUM, g_contained_##reg32, g_invalidate_##reg32 \
1042 #define DEFINE_GPR_PSEUDO_8H(reg8, reg32) \
1044 e_regSetGPR, gpr_##reg8, #reg8, NULL, Uint, Hex, 1, 1, INVALID_NUB_REGNUM, \
1045 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \
1046 g_contained_##reg32, g_invalidate_##reg32 \
1048 #define DEFINE_GPR_PSEUDO_8L(reg8, reg32) \
1050 e_regSetGPR, gpr_##reg8, #reg8, NULL, Uint, Hex, 1, 0, INVALID_NUB_REGNUM, \
1051 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \
1052 g_contained_##reg32, g_invalidate_##reg32 \
1055 #define GPR_OFFSET(reg) (offsetof(DNBArchImplI386::GPR, __##reg))
1056 #define FPU_OFFSET(reg) \
1057 (offsetof(DNBArchImplI386::FPU, __fpu_##reg) + \
1058 offsetof(DNBArchImplI386::Context, fpu.no_avx))
1059 #define AVX_OFFSET(reg) \
1060 (offsetof(DNBArchImplI386::AVX, __fpu_##reg) + \
1061 offsetof(DNBArchImplI386::Context, fpu.avx))
1062 #define AVX512F_OFFSET(reg) \
1063 (offsetof(DNBArchImplI386::AVX512F, __fpu_##reg) + \
1064 offsetof(DNBArchImplI386::Context, fpu.avx512f))
1065 #define EXC_OFFSET(reg) \
1066 (offsetof(DNBArchImplI386::EXC, __##reg) + \
1067 offsetof(DNBArchImplI386::Context, exc))
1069 #define GPR_SIZE(reg) (sizeof(((DNBArchImplI386::GPR *)NULL)->__##reg))
1070 #define FPU_SIZE_UINT(reg) (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg))
1071 #define FPU_SIZE_MMST(reg) \
1072 (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg.__mmst_reg))
1073 #define FPU_SIZE_XMM(reg) \
1074 (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg.__xmm_reg))
1075 #define FPU_SIZE_YMM(reg) (32)
1076 #define FPU_SIZE_ZMM(reg) (64)
1077 #define EXC_SIZE(reg) (sizeof(((DNBArchImplI386::EXC *)NULL)->__##reg))
1079 // This does not accurately identify the location of ymm0...7 in
1080 // Context.fpu.avx. That is because there is a bunch of padding
1081 // in Context.fpu.avx that we don't need. Offset macros lay out
1082 // the register state that Debugserver transmits to the debugger
1083 // -- not to interpret the thread_get_state info.
1084 #define AVX_OFFSET_YMM(n) (AVX_OFFSET(xmm7) + FPU_SIZE_XMM(xmm7) + (32 * n))
1086 // TODO: Test this and come back.
1087 #define AVX512F_OFFSET_ZMM(n) (AVX_OFFSET_YMM(7) + FPU_SIZE_XMM(xmm7) + (64 * n))
1089 // These macros will auto define the register name, alt name, register size,
1090 // register offset, encoding, format and native register. This ensures that
1091 // the register state structures are defined correctly and have the correct
1092 // sizes and offsets.
1094 const char *g_contained_eax[] = {"eax", NULL};
1095 const char *g_contained_ebx[] = {"ebx", NULL};
1096 const char *g_contained_ecx[] = {"ecx", NULL};
1097 const char *g_contained_edx[] = {"edx", NULL};
1098 const char *g_contained_edi[] = {"edi", NULL};
1099 const char *g_contained_esi[] = {"esi", NULL};
1100 const char *g_contained_ebp[] = {"ebp", NULL};
1101 const char *g_contained_esp[] = {"esp", NULL};
1103 const char *g_invalidate_eax[] = {"eax", "ax", "ah", "al", NULL};
1104 const char *g_invalidate_ebx[] = {"ebx", "bx", "bh", "bl", NULL};
1105 const char *g_invalidate_ecx[] = {"ecx", "cx", "ch", "cl", NULL};
1106 const char *g_invalidate_edx[] = {"edx", "dx", "dh", "dl", NULL};
1107 const char *g_invalidate_edi[] = {"edi", "di", "dil", NULL};
1108 const char *g_invalidate_esi[] = {"esi", "si", "sil", NULL};
1109 const char *g_invalidate_ebp[] = {"ebp", "bp", "bpl", NULL};
1110 const char *g_invalidate_esp[] = {"esp", "sp", "spl", NULL};
1112 // General purpose registers for 64 bit
1113 const DNBRegisterInfo DNBArchImplI386::g_gpr_registers[] = {
1114 {e_regSetGPR, gpr_eax, "eax", NULL, Uint, Hex, GPR_SIZE(eax),
1115 GPR_OFFSET(eax), ehframe_eax, dwarf_eax, INVALID_NUB_REGNUM,
1116 debugserver_eax, NULL, g_invalidate_eax},
1117 {e_regSetGPR, gpr_ebx, "ebx", NULL, Uint, Hex, GPR_SIZE(ebx),
1118 GPR_OFFSET(ebx), ehframe_ebx, dwarf_ebx, INVALID_NUB_REGNUM,
1119 debugserver_ebx, NULL, g_invalidate_ebx},
1120 {e_regSetGPR, gpr_ecx, "ecx", NULL, Uint, Hex, GPR_SIZE(ecx),
1121 GPR_OFFSET(ecx), ehframe_ecx, dwarf_ecx, INVALID_NUB_REGNUM,
1122 debugserver_ecx, NULL, g_invalidate_ecx},
1123 {e_regSetGPR, gpr_edx, "edx", NULL, Uint, Hex, GPR_SIZE(edx),
1124 GPR_OFFSET(edx), ehframe_edx, dwarf_edx, INVALID_NUB_REGNUM,
1125 debugserver_edx, NULL, g_invalidate_edx},
1126 {e_regSetGPR, gpr_edi, "edi", NULL, Uint, Hex, GPR_SIZE(edi),
1127 GPR_OFFSET(edi), ehframe_edi, dwarf_edi, INVALID_NUB_REGNUM,
1128 debugserver_edi, NULL, g_invalidate_edi},
1129 {e_regSetGPR, gpr_esi, "esi", NULL, Uint, Hex, GPR_SIZE(esi),
1130 GPR_OFFSET(esi), ehframe_esi, dwarf_esi, INVALID_NUB_REGNUM,
1131 debugserver_esi, NULL, g_invalidate_esi},
1132 {e_regSetGPR, gpr_ebp, "ebp", "fp", Uint, Hex, GPR_SIZE(ebp),
1133 GPR_OFFSET(ebp), ehframe_ebp, dwarf_ebp, GENERIC_REGNUM_FP,
1134 debugserver_ebp, NULL, g_invalidate_ebp},
1135 {e_regSetGPR, gpr_esp, "esp", "sp", Uint, Hex, GPR_SIZE(esp),
1136 GPR_OFFSET(esp), ehframe_esp, dwarf_esp, GENERIC_REGNUM_SP,
1137 debugserver_esp, NULL, g_invalidate_esp},
1138 {e_regSetGPR, gpr_ss, "ss", NULL, Uint, Hex, GPR_SIZE(ss), GPR_OFFSET(ss),
1139 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_ss,
1141 {e_regSetGPR, gpr_eflags, "eflags", "flags", Uint, Hex, GPR_SIZE(eflags),
1142 GPR_OFFSET(eflags), ehframe_eflags, dwarf_eflags, GENERIC_REGNUM_FLAGS,
1143 debugserver_eflags, NULL, NULL},
1144 {e_regSetGPR, gpr_eip, "eip", "pc", Uint, Hex, GPR_SIZE(eip),
1145 GPR_OFFSET(eip), ehframe_eip, dwarf_eip, GENERIC_REGNUM_PC,
1146 debugserver_eip, NULL, NULL},
1147 {e_regSetGPR, gpr_cs, "cs", NULL, Uint, Hex, GPR_SIZE(cs), GPR_OFFSET(cs),
1148 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_cs,
1150 {e_regSetGPR, gpr_ds, "ds", NULL, Uint, Hex, GPR_SIZE(ds), GPR_OFFSET(ds),
1151 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_ds,
1153 {e_regSetGPR, gpr_es, "es", NULL, Uint, Hex, GPR_SIZE(es), GPR_OFFSET(es),
1154 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_es,
1156 {e_regSetGPR, gpr_fs, "fs", NULL, Uint, Hex, GPR_SIZE(fs), GPR_OFFSET(fs),
1157 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_fs,
1159 {e_regSetGPR, gpr_gs, "gs", NULL, Uint, Hex, GPR_SIZE(gs), GPR_OFFSET(gs),
1160 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_gs,
1162 DEFINE_GPR_PSEUDO_16(ax, eax),
1163 DEFINE_GPR_PSEUDO_16(bx, ebx),
1164 DEFINE_GPR_PSEUDO_16(cx, ecx),
1165 DEFINE_GPR_PSEUDO_16(dx, edx),
1166 DEFINE_GPR_PSEUDO_16(di, edi),
1167 DEFINE_GPR_PSEUDO_16(si, esi),
1168 DEFINE_GPR_PSEUDO_16(bp, ebp),
1169 DEFINE_GPR_PSEUDO_16(sp, esp),
1170 DEFINE_GPR_PSEUDO_8H(ah, eax),
1171 DEFINE_GPR_PSEUDO_8H(bh, ebx),
1172 DEFINE_GPR_PSEUDO_8H(ch, ecx),
1173 DEFINE_GPR_PSEUDO_8H(dh, edx),
1174 DEFINE_GPR_PSEUDO_8L(al, eax),
1175 DEFINE_GPR_PSEUDO_8L(bl, ebx),
1176 DEFINE_GPR_PSEUDO_8L(cl, ecx),
1177 DEFINE_GPR_PSEUDO_8L(dl, edx),
1178 DEFINE_GPR_PSEUDO_8L(dil, edi),
1179 DEFINE_GPR_PSEUDO_8L(sil, esi),
1180 DEFINE_GPR_PSEUDO_8L(bpl, ebp),
1181 DEFINE_GPR_PSEUDO_8L(spl, esp)};
1183 const DNBRegisterInfo DNBArchImplI386::g_fpu_registers_no_avx[] = {
1184 {e_regSetFPU, fpu_fcw, "fctrl", NULL, Uint, Hex, FPU_SIZE_UINT(fcw),
1185 FPU_OFFSET(fcw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1186 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1187 {e_regSetFPU, fpu_fsw, "fstat", NULL, Uint, Hex, FPU_SIZE_UINT(fsw),
1188 FPU_OFFSET(fsw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1189 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1190 {e_regSetFPU, fpu_ftw, "ftag", NULL, Uint, Hex, 2 /* sizeof __fpu_ftw + sizeof __fpu_rsrv1 */,
1191 FPU_OFFSET(ftw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1192 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1193 {e_regSetFPU, fpu_fop, "fop", NULL, Uint, Hex, FPU_SIZE_UINT(fop),
1194 FPU_OFFSET(fop), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1195 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1196 {e_regSetFPU, fpu_ip, "fioff", NULL, Uint, Hex, FPU_SIZE_UINT(ip),
1197 FPU_OFFSET(ip), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1198 INVALID_NUB_REGNUM, NULL, NULL},
1199 {e_regSetFPU, fpu_cs, "fiseg", NULL, Uint, Hex, FPU_SIZE_UINT(cs),
1200 FPU_OFFSET(cs), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1201 INVALID_NUB_REGNUM, NULL, NULL},
1202 {e_regSetFPU, fpu_dp, "fooff", NULL, Uint, Hex, FPU_SIZE_UINT(dp),
1203 FPU_OFFSET(dp), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1204 INVALID_NUB_REGNUM, NULL, NULL},
1205 {e_regSetFPU, fpu_ds, "foseg", NULL, Uint, Hex, FPU_SIZE_UINT(ds),
1206 FPU_OFFSET(ds), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1207 INVALID_NUB_REGNUM, NULL, NULL},
1208 {e_regSetFPU, fpu_mxcsr, "mxcsr", NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr),
1209 FPU_OFFSET(mxcsr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1210 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1211 {e_regSetFPU, fpu_mxcsrmask, "mxcsrmask", NULL, Uint, Hex,
1212 FPU_SIZE_UINT(mxcsrmask), FPU_OFFSET(mxcsrmask), INVALID_NUB_REGNUM,
1213 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1215 {e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8,
1216 FPU_SIZE_MMST(stmm0), FPU_OFFSET(stmm0), INVALID_NUB_REGNUM, dwarf_stmm0,
1217 INVALID_NUB_REGNUM, debugserver_stmm0, NULL, NULL},
1218 {e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8,
1219 FPU_SIZE_MMST(stmm1), FPU_OFFSET(stmm1), INVALID_NUB_REGNUM, dwarf_stmm1,
1220 INVALID_NUB_REGNUM, debugserver_stmm1, NULL, NULL},
1221 {e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8,
1222 FPU_SIZE_MMST(stmm2), FPU_OFFSET(stmm2), INVALID_NUB_REGNUM, dwarf_stmm2,
1223 INVALID_NUB_REGNUM, debugserver_stmm2, NULL, NULL},
1224 {e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8,
1225 FPU_SIZE_MMST(stmm3), FPU_OFFSET(stmm3), INVALID_NUB_REGNUM, dwarf_stmm3,
1226 INVALID_NUB_REGNUM, debugserver_stmm3, NULL, NULL},
1227 {e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8,
1228 FPU_SIZE_MMST(stmm4), FPU_OFFSET(stmm4), INVALID_NUB_REGNUM, dwarf_stmm4,
1229 INVALID_NUB_REGNUM, debugserver_stmm4, NULL, NULL},
1230 {e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8,
1231 FPU_SIZE_MMST(stmm5), FPU_OFFSET(stmm5), INVALID_NUB_REGNUM, dwarf_stmm5,
1232 INVALID_NUB_REGNUM, debugserver_stmm5, NULL, NULL},
1233 {e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8,
1234 FPU_SIZE_MMST(stmm6), FPU_OFFSET(stmm6), INVALID_NUB_REGNUM, dwarf_stmm6,
1235 INVALID_NUB_REGNUM, debugserver_stmm6, NULL, NULL},
1236 {e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8,
1237 FPU_SIZE_MMST(stmm7), FPU_OFFSET(stmm7), INVALID_NUB_REGNUM, dwarf_stmm7,
1238 INVALID_NUB_REGNUM, debugserver_stmm7, NULL, NULL},
1240 {e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8,
1241 FPU_SIZE_XMM(xmm0), FPU_OFFSET(xmm0), INVALID_NUB_REGNUM, dwarf_xmm0,
1242 INVALID_NUB_REGNUM, debugserver_xmm0, NULL, NULL},
1243 {e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8,
1244 FPU_SIZE_XMM(xmm1), FPU_OFFSET(xmm1), INVALID_NUB_REGNUM, dwarf_xmm1,
1245 INVALID_NUB_REGNUM, debugserver_xmm1, NULL, NULL},
1246 {e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8,
1247 FPU_SIZE_XMM(xmm2), FPU_OFFSET(xmm2), INVALID_NUB_REGNUM, dwarf_xmm2,
1248 INVALID_NUB_REGNUM, debugserver_xmm2, NULL, NULL},
1249 {e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8,
1250 FPU_SIZE_XMM(xmm3), FPU_OFFSET(xmm3), INVALID_NUB_REGNUM, dwarf_xmm3,
1251 INVALID_NUB_REGNUM, debugserver_xmm3, NULL, NULL},
1252 {e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8,
1253 FPU_SIZE_XMM(xmm4), FPU_OFFSET(xmm4), INVALID_NUB_REGNUM, dwarf_xmm4,
1254 INVALID_NUB_REGNUM, debugserver_xmm4, NULL, NULL},
1255 {e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8,
1256 FPU_SIZE_XMM(xmm5), FPU_OFFSET(xmm5), INVALID_NUB_REGNUM, dwarf_xmm5,
1257 INVALID_NUB_REGNUM, debugserver_xmm5, NULL, NULL},
1258 {e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8,
1259 FPU_SIZE_XMM(xmm6), FPU_OFFSET(xmm6), INVALID_NUB_REGNUM, dwarf_xmm6,
1260 INVALID_NUB_REGNUM, debugserver_xmm6, NULL, NULL},
1261 {e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8,
1262 FPU_SIZE_XMM(xmm7), FPU_OFFSET(xmm7), INVALID_NUB_REGNUM, dwarf_xmm7,
1263 INVALID_NUB_REGNUM, debugserver_xmm7, NULL, NULL}};
1265 static const char *g_contained_ymm0[] = {"ymm0", NULL};
1266 static const char *g_contained_ymm1[] = {"ymm1", NULL};
1267 static const char *g_contained_ymm2[] = {"ymm2", NULL};
1268 static const char *g_contained_ymm3[] = {"ymm3", NULL};
1269 static const char *g_contained_ymm4[] = {"ymm4", NULL};
1270 static const char *g_contained_ymm5[] = {"ymm5", NULL};
1271 static const char *g_contained_ymm6[] = {"ymm6", NULL};
1272 static const char *g_contained_ymm7[] = {"ymm7", NULL};
1274 const DNBRegisterInfo DNBArchImplI386::g_fpu_registers_avx[] = {
1275 {e_regSetFPU, fpu_fcw, "fctrl", NULL, Uint, Hex, FPU_SIZE_UINT(fcw),
1276 AVX_OFFSET(fcw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1277 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1278 {e_regSetFPU, fpu_fsw, "fstat", NULL, Uint, Hex, FPU_SIZE_UINT(fsw),
1279 AVX_OFFSET(fsw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1280 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1281 {e_regSetFPU, fpu_ftw, "ftag", NULL, Uint, Hex, 2 /* sizeof __fpu_ftw + sizeof __fpu_rsrv1 */,
1282 AVX_OFFSET(ftw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1283 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1284 {e_regSetFPU, fpu_fop, "fop", NULL, Uint, Hex, FPU_SIZE_UINT(fop),
1285 AVX_OFFSET(fop), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1286 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1287 {e_regSetFPU, fpu_ip, "fioff", NULL, Uint, Hex, FPU_SIZE_UINT(ip),
1288 AVX_OFFSET(ip), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1289 INVALID_NUB_REGNUM, NULL, NULL},
1290 {e_regSetFPU, fpu_cs, "fiseg", NULL, Uint, Hex, FPU_SIZE_UINT(cs),
1291 AVX_OFFSET(cs), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1292 INVALID_NUB_REGNUM, NULL, NULL},
1293 {e_regSetFPU, fpu_dp, "fooff", NULL, Uint, Hex, FPU_SIZE_UINT(dp),
1294 AVX_OFFSET(dp), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1295 INVALID_NUB_REGNUM, NULL, NULL},
1296 {e_regSetFPU, fpu_ds, "foseg", NULL, Uint, Hex, FPU_SIZE_UINT(ds),
1297 AVX_OFFSET(ds), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1298 INVALID_NUB_REGNUM, NULL, NULL},
1299 {e_regSetFPU, fpu_mxcsr, "mxcsr", NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr),
1300 AVX_OFFSET(mxcsr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1301 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1302 {e_regSetFPU, fpu_mxcsrmask, "mxcsrmask", NULL, Uint, Hex,
1303 FPU_SIZE_UINT(mxcsrmask), AVX_OFFSET(mxcsrmask), INVALID_NUB_REGNUM,
1304 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1306 {e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8,
1307 FPU_SIZE_MMST(stmm0), AVX_OFFSET(stmm0), INVALID_NUB_REGNUM, dwarf_stmm0,
1308 INVALID_NUB_REGNUM, debugserver_stmm0, NULL, NULL},
1309 {e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8,
1310 FPU_SIZE_MMST(stmm1), AVX_OFFSET(stmm1), INVALID_NUB_REGNUM, dwarf_stmm1,
1311 INVALID_NUB_REGNUM, debugserver_stmm1, NULL, NULL},
1312 {e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8,
1313 FPU_SIZE_MMST(stmm2), AVX_OFFSET(stmm2), INVALID_NUB_REGNUM, dwarf_stmm2,
1314 INVALID_NUB_REGNUM, debugserver_stmm2, NULL, NULL},
1315 {e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8,
1316 FPU_SIZE_MMST(stmm3), AVX_OFFSET(stmm3), INVALID_NUB_REGNUM, dwarf_stmm3,
1317 INVALID_NUB_REGNUM, debugserver_stmm3, NULL, NULL},
1318 {e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8,
1319 FPU_SIZE_MMST(stmm4), AVX_OFFSET(stmm4), INVALID_NUB_REGNUM, dwarf_stmm4,
1320 INVALID_NUB_REGNUM, debugserver_stmm4, NULL, NULL},
1321 {e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8,
1322 FPU_SIZE_MMST(stmm5), AVX_OFFSET(stmm5), INVALID_NUB_REGNUM, dwarf_stmm5,
1323 INVALID_NUB_REGNUM, debugserver_stmm5, NULL, NULL},
1324 {e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8,
1325 FPU_SIZE_MMST(stmm6), AVX_OFFSET(stmm6), INVALID_NUB_REGNUM, dwarf_stmm6,
1326 INVALID_NUB_REGNUM, debugserver_stmm6, NULL, NULL},
1327 {e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8,
1328 FPU_SIZE_MMST(stmm7), AVX_OFFSET(stmm7), INVALID_NUB_REGNUM, dwarf_stmm7,
1329 INVALID_NUB_REGNUM, debugserver_stmm7, NULL, NULL},
1331 {e_regSetFPU, fpu_ymm0, "ymm0", NULL, Vector, VectorOfUInt8,
1332 FPU_SIZE_YMM(ymm0), AVX_OFFSET_YMM(0), INVALID_NUB_REGNUM, dwarf_ymm0,
1333 INVALID_NUB_REGNUM, debugserver_ymm0, NULL, NULL},
1334 {e_regSetFPU, fpu_ymm1, "ymm1", NULL, Vector, VectorOfUInt8,
1335 FPU_SIZE_YMM(ymm1), AVX_OFFSET_YMM(1), INVALID_NUB_REGNUM, dwarf_ymm1,
1336 INVALID_NUB_REGNUM, debugserver_ymm1, NULL, NULL},
1337 {e_regSetFPU, fpu_ymm2, "ymm2", NULL, Vector, VectorOfUInt8,
1338 FPU_SIZE_YMM(ymm2), AVX_OFFSET_YMM(2), INVALID_NUB_REGNUM, dwarf_ymm2,
1339 INVALID_NUB_REGNUM, debugserver_ymm2, NULL, NULL},
1340 {e_regSetFPU, fpu_ymm3, "ymm3", NULL, Vector, VectorOfUInt8,
1341 FPU_SIZE_YMM(ymm3), AVX_OFFSET_YMM(3), INVALID_NUB_REGNUM, dwarf_ymm3,
1342 INVALID_NUB_REGNUM, debugserver_ymm3, NULL, NULL},
1343 {e_regSetFPU, fpu_ymm4, "ymm4", NULL, Vector, VectorOfUInt8,
1344 FPU_SIZE_YMM(ymm4), AVX_OFFSET_YMM(4), INVALID_NUB_REGNUM, dwarf_ymm4,
1345 INVALID_NUB_REGNUM, debugserver_ymm4, NULL, NULL},
1346 {e_regSetFPU, fpu_ymm5, "ymm5", NULL, Vector, VectorOfUInt8,
1347 FPU_SIZE_YMM(ymm5), AVX_OFFSET_YMM(5), INVALID_NUB_REGNUM, dwarf_ymm5,
1348 INVALID_NUB_REGNUM, debugserver_ymm5, NULL, NULL},
1349 {e_regSetFPU, fpu_ymm6, "ymm6", NULL, Vector, VectorOfUInt8,
1350 FPU_SIZE_YMM(ymm6), AVX_OFFSET_YMM(6), INVALID_NUB_REGNUM, dwarf_ymm6,
1351 INVALID_NUB_REGNUM, debugserver_ymm6, NULL, NULL},
1352 {e_regSetFPU, fpu_ymm7, "ymm7", NULL, Vector, VectorOfUInt8,
1353 FPU_SIZE_YMM(ymm7), AVX_OFFSET_YMM(7), INVALID_NUB_REGNUM, dwarf_ymm7,
1354 INVALID_NUB_REGNUM, debugserver_ymm7, NULL, NULL},
1356 {e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8,
1357 FPU_SIZE_XMM(xmm0), 0, INVALID_NUB_REGNUM, dwarf_xmm0, INVALID_NUB_REGNUM,
1358 debugserver_xmm0, g_contained_ymm0, NULL},
1359 {e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8,
1360 FPU_SIZE_XMM(xmm1), 0, INVALID_NUB_REGNUM, dwarf_xmm1, INVALID_NUB_REGNUM,
1361 debugserver_xmm1, g_contained_ymm1, NULL},
1362 {e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8,
1363 FPU_SIZE_XMM(xmm2), 0, INVALID_NUB_REGNUM, dwarf_xmm2, INVALID_NUB_REGNUM,
1364 debugserver_xmm2, g_contained_ymm2, NULL},
1365 {e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8,
1366 FPU_SIZE_XMM(xmm3), 0, INVALID_NUB_REGNUM, dwarf_xmm3, INVALID_NUB_REGNUM,
1367 debugserver_xmm3, g_contained_ymm3, NULL},
1368 {e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8,
1369 FPU_SIZE_XMM(xmm4), 0, INVALID_NUB_REGNUM, dwarf_xmm4, INVALID_NUB_REGNUM,
1370 debugserver_xmm4, g_contained_ymm4, NULL},
1371 {e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8,
1372 FPU_SIZE_XMM(xmm5), 0, INVALID_NUB_REGNUM, dwarf_xmm5, INVALID_NUB_REGNUM,
1373 debugserver_xmm5, g_contained_ymm5, NULL},
1374 {e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8,
1375 FPU_SIZE_XMM(xmm6), 0, INVALID_NUB_REGNUM, dwarf_xmm6, INVALID_NUB_REGNUM,
1376 debugserver_xmm6, g_contained_ymm6, NULL},
1377 {e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8,
1378 FPU_SIZE_XMM(xmm7), 0, INVALID_NUB_REGNUM, dwarf_xmm7, INVALID_NUB_REGNUM,
1379 debugserver_xmm7, g_contained_ymm7, NULL},
1386 #define ZMM_REG_DEF(reg) \
1388 e_regSetFPU, fpu_zmm##reg, STR(zmm##reg), NULL, Vector, VectorOfUInt8, \
1389 FPU_SIZE_ZMM(zmm##reg), AVX512F_OFFSET_ZMM(reg), INVALID_NUB_REGNUM, \
1390 dwarf_zmm##reg, INVALID_NUB_REGNUM, debugserver_zmm##reg, NULL, NULL \
1393 #define YMM_REG_ALIAS(reg) \
1395 e_regSetFPU, fpu_ymm##reg, STR(ymm##reg), NULL, Vector, VectorOfUInt8, \
1396 FPU_SIZE_YMM(ymm##reg), 0, INVALID_NUB_REGNUM, dwarf_ymm##reg, \
1397 INVALID_NUB_REGNUM, debugserver_ymm##reg, g_contained_zmm##reg, NULL \
1400 #define XMM_REG_ALIAS(reg) \
1402 e_regSetFPU, fpu_xmm##reg, STR(xmm##reg), NULL, Vector, VectorOfUInt8, \
1403 FPU_SIZE_XMM(xmm##reg), 0, INVALID_NUB_REGNUM, dwarf_xmm##reg, \
1404 INVALID_NUB_REGNUM, debugserver_xmm##reg, g_contained_zmm##reg, NULL \
1407 #define AVX512_K_REG_DEF(reg) \
1409 e_regSetFPU, fpu_k##reg, STR(k##reg), NULL, Vector, VectorOfUInt8, 8, \
1410 AVX512F_OFFSET(k##reg), dwarf_k##reg, dwarf_k##reg, -1U, \
1411 debugserver_k##reg, NULL, NULL \
1414 static const char *g_contained_zmm0[] = {"zmm0", NULL};
1415 static const char *g_contained_zmm1[] = {"zmm1", NULL};
1416 static const char *g_contained_zmm2[] = {"zmm2", NULL};
1417 static const char *g_contained_zmm3[] = {"zmm3", NULL};
1418 static const char *g_contained_zmm4[] = {"zmm4", NULL};
1419 static const char *g_contained_zmm5[] = {"zmm5", NULL};
1420 static const char *g_contained_zmm6[] = {"zmm6", NULL};
1421 static const char *g_contained_zmm7[] = {"zmm7", NULL};
1423 const DNBRegisterInfo DNBArchImplI386::g_fpu_registers_avx512f[] = {
1424 {e_regSetFPU, fpu_fcw, "fctrl", NULL, Uint, Hex, FPU_SIZE_UINT(fcw),
1425 AVX_OFFSET(fcw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1426 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1427 {e_regSetFPU, fpu_fsw, "fstat", NULL, Uint, Hex, FPU_SIZE_UINT(fsw),
1428 AVX_OFFSET(fsw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1429 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1430 {e_regSetFPU, fpu_ftw, "ftag", NULL, Uint, Hex, 2 /* sizeof __fpu_ftw + sizeof __fpu_rsrv1 */,
1431 FPU_OFFSET(ftw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1432 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1433 {e_regSetFPU, fpu_fop, "fop", NULL, Uint, Hex, FPU_SIZE_UINT(fop),
1434 AVX_OFFSET(fop), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1435 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1436 {e_regSetFPU, fpu_ip, "fioff", NULL, Uint, Hex, FPU_SIZE_UINT(ip),
1437 AVX_OFFSET(ip), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1438 INVALID_NUB_REGNUM, NULL, NULL},
1439 {e_regSetFPU, fpu_cs, "fiseg", NULL, Uint, Hex, FPU_SIZE_UINT(cs),
1440 AVX_OFFSET(cs), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1441 INVALID_NUB_REGNUM, NULL, NULL},
1442 {e_regSetFPU, fpu_dp, "fooff", NULL, Uint, Hex, FPU_SIZE_UINT(dp),
1443 AVX_OFFSET(dp), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1444 INVALID_NUB_REGNUM, NULL, NULL},
1445 {e_regSetFPU, fpu_ds, "foseg", NULL, Uint, Hex, FPU_SIZE_UINT(ds),
1446 AVX_OFFSET(ds), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1447 INVALID_NUB_REGNUM, NULL, NULL},
1448 {e_regSetFPU, fpu_mxcsr, "mxcsr", NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr),
1449 AVX_OFFSET(mxcsr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1450 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1451 {e_regSetFPU, fpu_mxcsrmask, "mxcsrmask", NULL, Uint, Hex,
1452 FPU_SIZE_UINT(mxcsrmask), AVX_OFFSET(mxcsrmask), INVALID_NUB_REGNUM,
1453 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1455 {e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8,
1456 FPU_SIZE_MMST(stmm0), AVX_OFFSET(stmm0), INVALID_NUB_REGNUM, dwarf_stmm0,
1457 INVALID_NUB_REGNUM, debugserver_stmm0, NULL, NULL},
1458 {e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8,
1459 FPU_SIZE_MMST(stmm1), AVX_OFFSET(stmm1), INVALID_NUB_REGNUM, dwarf_stmm1,
1460 INVALID_NUB_REGNUM, debugserver_stmm1, NULL, NULL},
1461 {e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8,
1462 FPU_SIZE_MMST(stmm2), AVX_OFFSET(stmm2), INVALID_NUB_REGNUM, dwarf_stmm2,
1463 INVALID_NUB_REGNUM, debugserver_stmm2, NULL, NULL},
1464 {e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8,
1465 FPU_SIZE_MMST(stmm3), AVX_OFFSET(stmm3), INVALID_NUB_REGNUM, dwarf_stmm3,
1466 INVALID_NUB_REGNUM, debugserver_stmm3, NULL, NULL},
1467 {e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8,
1468 FPU_SIZE_MMST(stmm4), AVX_OFFSET(stmm4), INVALID_NUB_REGNUM, dwarf_stmm4,
1469 INVALID_NUB_REGNUM, debugserver_stmm4, NULL, NULL},
1470 {e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8,
1471 FPU_SIZE_MMST(stmm5), AVX_OFFSET(stmm5), INVALID_NUB_REGNUM, dwarf_stmm5,
1472 INVALID_NUB_REGNUM, debugserver_stmm5, NULL, NULL},
1473 {e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8,
1474 FPU_SIZE_MMST(stmm6), AVX_OFFSET(stmm6), INVALID_NUB_REGNUM, dwarf_stmm6,
1475 INVALID_NUB_REGNUM, debugserver_stmm6, NULL, NULL},
1476 {e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8,
1477 FPU_SIZE_MMST(stmm7), AVX_OFFSET(stmm7), INVALID_NUB_REGNUM, dwarf_stmm7,
1478 INVALID_NUB_REGNUM, debugserver_stmm7, NULL, NULL},
1480 AVX512_K_REG_DEF(0),
1481 AVX512_K_REG_DEF(1),
1482 AVX512_K_REG_DEF(2),
1483 AVX512_K_REG_DEF(3),
1484 AVX512_K_REG_DEF(4),
1485 AVX512_K_REG_DEF(5),
1486 AVX512_K_REG_DEF(6),
1487 AVX512_K_REG_DEF(7),
1518 const DNBRegisterInfo DNBArchImplI386::g_exc_registers[] = {
1519 {e_regSetEXC, exc_trapno, "trapno", NULL, Uint, Hex, EXC_SIZE(trapno),
1520 EXC_OFFSET(trapno), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1521 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1522 {e_regSetEXC, exc_err, "err", NULL, Uint, Hex, EXC_SIZE(err),
1523 EXC_OFFSET(err), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1524 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1525 {e_regSetEXC, exc_faultvaddr, "faultvaddr", NULL, Uint, Hex,
1526 EXC_SIZE(faultvaddr), EXC_OFFSET(faultvaddr), INVALID_NUB_REGNUM,
1527 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}};
1529 // Number of registers in each register set
1530 const size_t DNBArchImplI386::k_num_gpr_registers =
1531 sizeof(g_gpr_registers) / sizeof(DNBRegisterInfo);
1532 const size_t DNBArchImplI386::k_num_fpu_registers_no_avx =
1533 sizeof(g_fpu_registers_no_avx) / sizeof(DNBRegisterInfo);
1534 const size_t DNBArchImplI386::k_num_fpu_registers_avx =
1535 sizeof(g_fpu_registers_avx) / sizeof(DNBRegisterInfo);
1536 const size_t DNBArchImplI386::k_num_fpu_registers_avx512f =
1537 sizeof(g_fpu_registers_avx512f) / sizeof(DNBRegisterInfo);
1538 const size_t DNBArchImplI386::k_num_exc_registers =
1539 sizeof(g_exc_registers) / sizeof(DNBRegisterInfo);
1540 const size_t DNBArchImplI386::k_num_all_registers_no_avx =
1541 k_num_gpr_registers + k_num_fpu_registers_no_avx + k_num_exc_registers;
1542 const size_t DNBArchImplI386::k_num_all_registers_avx =
1543 k_num_gpr_registers + k_num_fpu_registers_avx + k_num_exc_registers;
1544 const size_t DNBArchImplI386::k_num_all_registers_avx512f =
1545 k_num_gpr_registers + k_num_fpu_registers_avx512f + k_num_exc_registers;
1547 //----------------------------------------------------------------------
1548 // Register set definitions. The first definitions at register set index
1549 // of zero is for all registers, followed by other registers sets. The
1550 // register information for the all register set need not be filled in.
1551 //----------------------------------------------------------------------
1552 const DNBRegisterSetInfo DNBArchImplI386::g_reg_sets_no_avx[] = {
1553 {"i386 Registers", NULL, k_num_all_registers_no_avx},
1554 {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers},
1555 {"Floating Point Registers", g_fpu_registers_no_avx,
1556 k_num_fpu_registers_no_avx},
1557 {"Exception State Registers", g_exc_registers, k_num_exc_registers}};
1559 const DNBRegisterSetInfo DNBArchImplI386::g_reg_sets_avx[] = {
1560 {"i386 Registers", NULL, k_num_all_registers_avx},
1561 {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers},
1562 {"Floating Point Registers", g_fpu_registers_avx, k_num_fpu_registers_avx},
1563 {"Exception State Registers", g_exc_registers, k_num_exc_registers}};
1565 const DNBRegisterSetInfo DNBArchImplI386::g_reg_sets_avx512f[] = {
1566 {"i386 Registers", NULL, k_num_all_registers_avx512f},
1567 {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers},
1568 {"Floating Point Registers", g_fpu_registers_avx512f,
1569 k_num_fpu_registers_avx512f},
1570 {"Exception State Registers", g_exc_registers, k_num_exc_registers}};
1572 // Total number of register sets for this architecture
1573 const size_t DNBArchImplI386::k_num_register_sets =
1574 sizeof(g_reg_sets_avx) / sizeof(DNBRegisterSetInfo);
1576 DNBArchProtocol *DNBArchImplI386::Create(MachThread *thread) {
1577 DNBArchImplI386 *obj = new DNBArchImplI386(thread);
1581 const uint8_t *DNBArchImplI386::SoftwareBreakpointOpcode(nub_size_t byte_size) {
1582 static const uint8_t g_breakpoint_opcode[] = {0xCC};
1584 return g_breakpoint_opcode;
1588 const DNBRegisterSetInfo *
1589 DNBArchImplI386::GetRegisterSetInfo(nub_size_t *num_reg_sets) {
1590 *num_reg_sets = k_num_register_sets;
1591 if (CPUHasAVX512f() || FORCE_AVX_REGS)
1592 return g_reg_sets_avx512f;
1594 return g_reg_sets_avx;
1596 return g_reg_sets_no_avx;
1599 void DNBArchImplI386::Initialize() {
1600 DNBArchPluginInfo arch_plugin_info = {
1601 CPU_TYPE_I386, DNBArchImplI386::Create,
1602 DNBArchImplI386::GetRegisterSetInfo,
1603 DNBArchImplI386::SoftwareBreakpointOpcode};
1605 // Register this arch plug-in with the main protocol class
1606 DNBArchProtocol::RegisterArchPlugin(arch_plugin_info);
1609 bool DNBArchImplI386::GetRegisterValue(uint32_t set, uint32_t reg,
1610 DNBRegisterValue *value) {
1611 if (set == REGISTER_SET_GENERIC) {
1613 case GENERIC_REGNUM_PC: // Program Counter
1618 case GENERIC_REGNUM_SP: // Stack Pointer
1623 case GENERIC_REGNUM_FP: // Frame Pointer
1628 case GENERIC_REGNUM_FLAGS: // Processor flags register
1633 case GENERIC_REGNUM_RA: // Return Address
1639 if (GetRegisterState(set, false) != KERN_SUCCESS)
1642 const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
1644 value->info = *regInfo;
1647 if (reg < k_num_gpr_registers) {
1648 value->value.uint32 = ((uint32_t *)(&m_state.context.gpr))[reg];
1654 if (reg > fpu_xmm7 && !(CPUHasAVX() || FORCE_AVX_REGS))
1656 if (reg > fpu_ymm7 && !(CPUHasAVX512f() || FORCE_AVX_REGS))
1660 value->value.uint16 =
1661 *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw));
1664 value->value.uint16 =
1665 *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw));
1668 memcpy (&value->value.uint16, &m_state.context.fpu.no_avx.__fpu_ftw, 2);
1671 value->value.uint16 = m_state.context.fpu.no_avx.__fpu_fop;
1674 value->value.uint32 = m_state.context.fpu.no_avx.__fpu_ip;
1677 value->value.uint16 = m_state.context.fpu.no_avx.__fpu_cs;
1680 value->value.uint32 = m_state.context.fpu.no_avx.__fpu_dp;
1683 value->value.uint16 = m_state.context.fpu.no_avx.__fpu_ds;
1686 value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsr;
1689 value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsrmask;
1693 memcpy(&value->value.uint8,
1694 m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg, 10);
1697 memcpy(&value->value.uint8,
1698 m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg, 10);
1701 memcpy(&value->value.uint8,
1702 m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg, 10);
1705 memcpy(&value->value.uint8,
1706 m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg, 10);
1709 memcpy(&value->value.uint8,
1710 m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg, 10);
1713 memcpy(&value->value.uint8,
1714 m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg, 10);
1717 memcpy(&value->value.uint8,
1718 m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg, 10);
1721 memcpy(&value->value.uint8,
1722 m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg, 10);
1726 memcpy(&value->value.uint8,
1727 m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg, 16);
1730 memcpy(&value->value.uint8,
1731 m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg, 16);
1734 memcpy(&value->value.uint8,
1735 m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg, 16);
1738 memcpy(&value->value.uint8,
1739 m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg, 16);
1742 memcpy(&value->value.uint8,
1743 m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg, 16);
1746 memcpy(&value->value.uint8,
1747 m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg, 16);
1750 memcpy(&value->value.uint8,
1751 m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg, 16);
1754 memcpy(&value->value.uint8,
1755 m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg, 16);
1758 #define MEMCPY_YMM(n) \
1759 memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm##n.__xmm_reg, \
1761 memcpy((&value->value.uint8) + 16, \
1762 m_state.context.fpu.avx.__fpu_ymmh##n.__xmm_reg, 16);
1797 memcpy((&value->value.uint8),
1798 &m_state.context.fpu.avx512f.__fpu_k0 + (reg - fpu_k0), 8);
1808 memcpy(&value->value.uint8,
1809 &m_state.context.fpu.avx512f.__fpu_xmm0 + (reg - fpu_zmm0), 16);
1810 memcpy(&value->value.uint8 + 16,
1811 &m_state.context.fpu.avx512f.__fpu_ymmh0 + (reg - fpu_zmm0), 16);
1812 memcpy(&value->value.uint8 + 32,
1813 &m_state.context.fpu.avx512f.__fpu_zmmh0 + (reg - fpu_zmm0), 32);
1819 if (reg < k_num_exc_registers) {
1820 value->value.uint32 = (&m_state.context.exc.__trapno)[reg];
1829 bool DNBArchImplI386::SetRegisterValue(uint32_t set, uint32_t reg,
1830 const DNBRegisterValue *value) {
1831 if (set == REGISTER_SET_GENERIC) {
1833 case GENERIC_REGNUM_PC: // Program Counter
1838 case GENERIC_REGNUM_SP: // Stack Pointer
1843 case GENERIC_REGNUM_FP: // Frame Pointer
1848 case GENERIC_REGNUM_FLAGS: // Processor flags register
1853 case GENERIC_REGNUM_RA: // Return Address
1859 if (GetRegisterState(set, false) != KERN_SUCCESS)
1862 bool success = false;
1863 const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
1867 if (reg < k_num_gpr_registers) {
1868 ((uint32_t *)(&m_state.context.gpr))[reg] = value->value.uint32;
1874 if (reg > fpu_xmm7 && !(CPUHasAVX() || FORCE_AVX_REGS))
1876 if (reg > fpu_ymm7 && !(CPUHasAVX512f() || FORCE_AVX_REGS))
1880 *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)) =
1881 value->value.uint16;
1885 *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)) =
1886 value->value.uint16;
1890 memcpy (&m_state.context.fpu.no_avx.__fpu_ftw, &value->value.uint16, 2);
1894 m_state.context.fpu.no_avx.__fpu_fop = value->value.uint16;
1898 m_state.context.fpu.no_avx.__fpu_ip = value->value.uint32;
1902 m_state.context.fpu.no_avx.__fpu_cs = value->value.uint16;
1906 m_state.context.fpu.no_avx.__fpu_dp = value->value.uint32;
1910 m_state.context.fpu.no_avx.__fpu_ds = value->value.uint16;
1914 m_state.context.fpu.no_avx.__fpu_mxcsr = value->value.uint32;
1918 m_state.context.fpu.no_avx.__fpu_mxcsrmask = value->value.uint32;
1923 memcpy(m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg,
1924 &value->value.uint8, 10);
1928 memcpy(m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg,
1929 &value->value.uint8, 10);
1933 memcpy(m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg,
1934 &value->value.uint8, 10);
1938 memcpy(m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg,
1939 &value->value.uint8, 10);
1943 memcpy(m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg,
1944 &value->value.uint8, 10);
1948 memcpy(m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg,
1949 &value->value.uint8, 10);
1953 memcpy(m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg,
1954 &value->value.uint8, 10);
1958 memcpy(m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg,
1959 &value->value.uint8, 10);
1964 memcpy(m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg,
1965 &value->value.uint8, 16);
1969 memcpy(m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg,
1970 &value->value.uint8, 16);
1974 memcpy(m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg,
1975 &value->value.uint8, 16);
1979 memcpy(m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg,
1980 &value->value.uint8, 16);
1984 memcpy(m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg,
1985 &value->value.uint8, 16);
1989 memcpy(m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg,
1990 &value->value.uint8, 16);
1994 memcpy(m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg,
1995 &value->value.uint8, 16);
1999 memcpy(m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg,
2000 &value->value.uint8, 16);
2004 #define MEMCPY_YMM(n) \
2005 memcpy(m_state.context.fpu.avx.__fpu_xmm##n.__xmm_reg, &value->value.uint8, \
2007 memcpy(m_state.context.fpu.avx.__fpu_ymmh##n.__xmm_reg, \
2008 (&value->value.uint8) + 16, 16);
2043 memcpy(&m_state.context.fpu.avx512f.__fpu_k0 + (reg - fpu_k0),
2044 &value->value.uint8, 8);
2054 memcpy(&m_state.context.fpu.avx512f.__fpu_xmm0 + (reg - fpu_zmm0),
2055 &value->value.uint8, 16);
2056 memcpy(&m_state.context.fpu.avx512f.__fpu_ymmh0 + (reg - fpu_zmm0),
2057 &value->value.uint8 + 16, 16);
2058 memcpy(&m_state.context.fpu.avx512f.__fpu_zmmh0 + (reg - fpu_zmm0),
2059 &value->value.uint8 + 32, 32);
2065 if (reg < k_num_exc_registers) {
2066 (&m_state.context.exc.__trapno)[reg] = value->value.uint32;
2074 return SetRegisterState(set) == KERN_SUCCESS;
2078 uint32_t DNBArchImplI386::GetRegisterContextSize() {
2079 static uint32_t g_cached_size = 0;
2080 if (g_cached_size == 0) {
2081 if(CPUHasAVX512f() || FORCE_AVX_REGS) {
2082 for (size_t i = 0; i < k_num_fpu_registers_avx512f; ++i) {
2083 if (g_fpu_registers_avx512f[i].value_regs == NULL)
2084 g_cached_size += g_fpu_registers_avx512f[i].size;
2088 for (size_t i = 0; i < k_num_fpu_registers_avx; ++i) {
2089 if (g_fpu_registers_avx[i].value_regs == NULL)
2090 g_cached_size += g_fpu_registers_avx[i].size;
2093 for (size_t i = 0; i < k_num_fpu_registers_no_avx; ++i) {
2094 if (g_fpu_registers_no_avx[i].value_regs == NULL)
2095 g_cached_size += g_fpu_registers_no_avx[i].size;
2098 DNBLogThreaded("DNBArchImplX86_64::GetRegisterContextSize() - GPR = %zu, "
2099 "FPU = %u, EXC = %zu",
2100 sizeof(GPR), g_cached_size, sizeof(EXC));
2101 g_cached_size += sizeof(GPR);
2102 g_cached_size += sizeof(EXC);
2104 "DNBArchImplX86_64::GetRegisterContextSize() - GPR + FPU + EXC = %u",
2107 return g_cached_size;
2110 nub_size_t DNBArchImplI386::GetRegisterContext(void *buf, nub_size_t buf_len) {
2111 uint32_t size = GetRegisterContextSize();
2113 if (buf && buf_len) {
2115 size = static_cast<uint32_t>(buf_len);
2119 if ((kret = GetGPRState(force)) != KERN_SUCCESS) {
2120 DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = "
2121 "%p, len = %llu) error: GPR regs failed to "
2123 buf, (uint64_t)buf_len, kret);
2125 } else if ((kret = GetFPUState(force)) != KERN_SUCCESS) {
2127 LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = %p, len = "
2128 "%llu) error: %s regs failed to read: %u",
2129 buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret);
2131 } else if ((kret = GetEXCState(force)) != KERN_SUCCESS) {
2132 DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = "
2133 "%p, len = %llu) error: EXC regs failed to "
2135 buf, (uint64_t)buf_len, kret);
2138 uint8_t *p = (uint8_t *)buf;
2139 // Copy the GPR registers
2140 memcpy(p, &m_state.context.gpr, sizeof(GPR));
2143 // Walk around the gaps in the FPU regs
2144 memcpy(p, &m_state.context.fpu.no_avx.__fpu_fcw, 5);
2146 memcpy(p, &m_state.context.fpu.no_avx.__fpu_fop, 8);
2148 memcpy(p, &m_state.context.fpu.no_avx.__fpu_dp, 6);
2150 memcpy(p, &m_state.context.fpu.no_avx.__fpu_mxcsr, 8);
2153 // Work around the padding between the stmm registers as they are 16
2154 // byte structs with 10 bytes of the value in each
2155 for (size_t i = 0; i < 8; ++i) {
2156 memcpy(p, &m_state.context.fpu.no_avx.__fpu_stmm0 + i, 10);
2160 if (CPUHasAVX512f() || FORCE_AVX_REGS) {
2161 for (size_t i = 0; i < 8; ++i) {
2162 memcpy(p, &m_state.context.fpu.avx512f.__fpu_k0 + i, 8);
2167 if (CPUHasAVX() || FORCE_AVX_REGS) {
2168 // Interleave the XMM and YMMH registers to make the YMM registers
2169 for (size_t i = 0; i < 8; ++i) {
2170 memcpy(p, &m_state.context.fpu.avx.__fpu_xmm0 + i, 16);
2172 memcpy(p, &m_state.context.fpu.avx.__fpu_ymmh0 + i, 16);
2175 if(CPUHasAVX512f() || FORCE_AVX_REGS) {
2176 for (size_t i = 0; i < 8; ++i) {
2177 memcpy(p, &m_state.context.fpu.avx512f.__fpu_zmmh0 + i, 32);
2182 // Copy the XMM registers in a single block
2183 memcpy(p, &m_state.context.fpu.no_avx.__fpu_xmm0, 8 * 16);
2187 // Copy the exception registers
2188 memcpy(p, &m_state.context.exc, sizeof(EXC));
2191 // make sure we end up with exactly what we think we should have
2192 size_t bytes_written = p - (uint8_t *)buf;
2193 UNUSED_IF_ASSERT_DISABLED(bytes_written);
2194 assert(bytes_written == size);
2199 "DNBArchImplI386::GetRegisterContext (buf = %p, len = %llu) => %llu", buf,
2200 (uint64_t)buf_len, (uint64_t)size);
2201 // Return the size of the register context even if NULL was passed in
2205 nub_size_t DNBArchImplI386::SetRegisterContext(const void *buf,
2206 nub_size_t buf_len) {
2207 nub_size_t size = sizeof(m_state.context);
2208 if (buf == NULL || buf_len == 0)
2215 const uint8_t *p = (const uint8_t *)buf;
2216 // Copy the GPR registers
2217 memcpy(&m_state.context.gpr, p, sizeof(GPR));
2220 // Copy fcw through mxcsrmask as there is no padding
2221 memcpy(&m_state.context.fpu.no_avx.__fpu_fcw, p, 5);
2223 memcpy(&m_state.context.fpu.no_avx.__fpu_fop, p, 8);
2225 memcpy(&m_state.context.fpu.no_avx.__fpu_dp, p, 6);
2227 memcpy(&m_state.context.fpu.no_avx.__fpu_mxcsr, p, 8);
2230 // Work around the padding between the stmm registers as they are 16
2231 // byte structs with 10 bytes of the value in each
2232 for (size_t i = 0; i < 8; ++i) {
2233 memcpy(&m_state.context.fpu.no_avx.__fpu_stmm0 + i, p, 10);
2237 if(CPUHasAVX512f() || FORCE_AVX_REGS) {
2238 for (size_t i = 0; i < 8; ++i) {
2239 memcpy(&m_state.context.fpu.avx512f.__fpu_k0 + i, p, 8);
2244 if (CPUHasAVX() || FORCE_AVX_REGS) {
2245 // Interleave the XMM and YMMH registers to make the YMM registers
2246 for (size_t i = 0; i < 8; ++i) {
2247 memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + i, p, 16);
2249 memcpy(&m_state.context.fpu.avx.__fpu_ymmh0 + i, p, 16);
2253 if(CPUHasAVX512f() || FORCE_AVX_REGS) {
2254 for (size_t i = 0; i < 8; ++i) {
2255 memcpy(&m_state.context.fpu.avx512f.__fpu_zmmh0 + i, p, 32);
2260 // Copy the XMM registers in a single block
2261 memcpy(&m_state.context.fpu.no_avx.__fpu_xmm0, p, 8 * 16);
2265 // Copy the exception registers
2266 memcpy(&m_state.context.exc, p, sizeof(EXC));
2269 // make sure we end up with exactly what we think we should have
2270 size_t bytes_written = p - (const uint8_t *)buf;
2271 UNUSED_IF_ASSERT_DISABLED(bytes_written);
2272 assert(bytes_written == size);
2274 if ((kret = SetGPRState()) != KERN_SUCCESS)
2275 DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = "
2276 "%p, len = %llu) error: GPR regs failed to "
2278 buf, (uint64_t)buf_len, kret);
2279 if ((kret = SetFPUState()) != KERN_SUCCESS)
2281 LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = %p, len = "
2282 "%llu) error: %s regs failed to write: %u",
2283 buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret);
2284 if ((kret = SetEXCState()) != KERN_SUCCESS)
2285 DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = "
2286 "%p, len = %llu) error: EXP regs failed to "
2288 buf, (uint64_t)buf_len, kret);
2292 "DNBArchImplI386::SetRegisterContext (buf = %p, len = %llu) => %llu", buf,
2293 (uint64_t)buf_len, (uint64_t)size);
2297 uint32_t DNBArchImplI386::SaveRegisterState() {
2298 kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber());
2300 LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u "
2301 "(SetGPRState() for stop_count = %u)",
2302 m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount());
2306 if ((kret = GetGPRState(force)) != KERN_SUCCESS) {
2307 DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::SaveRegisterState () error: "
2308 "GPR regs failed to read: %u ",
2310 } else if ((kret = GetFPUState(force)) != KERN_SUCCESS) {
2311 DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::SaveRegisterState () error: "
2312 "%s regs failed to read: %u",
2313 CPUHasAVX() ? "AVX" : "FPU", kret);
2315 const uint32_t save_id = GetNextRegisterStateSaveID();
2316 m_saved_register_states[save_id] = m_state.context;
2321 bool DNBArchImplI386::RestoreRegisterState(uint32_t save_id) {
2322 SaveRegisterStates::iterator pos = m_saved_register_states.find(save_id);
2323 if (pos != m_saved_register_states.end()) {
2324 m_state.context.gpr = pos->second.gpr;
2325 m_state.context.fpu = pos->second.fpu;
2326 m_state.context.exc = pos->second.exc;
2327 m_state.SetError(e_regSetGPR, Read, 0);
2328 m_state.SetError(e_regSetFPU, Read, 0);
2329 m_state.SetError(e_regSetEXC, Read, 0);
2331 bool success = true;
2332 if ((kret = SetGPRState()) != KERN_SUCCESS) {
2333 DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::RestoreRegisterState "
2334 "(save_id = %u) error: GPR regs failed to "
2338 } else if ((kret = SetFPUState()) != KERN_SUCCESS) {
2339 DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::RestoreRegisterState "
2340 "(save_id = %u) error: %s regs failed to "
2342 save_id, CPUHasAVX() ? "AVX" : "FPU", kret);
2345 m_saved_register_states.erase(pos);
2351 kern_return_t DNBArchImplI386::GetRegisterState(int set, bool force) {
2354 return GetGPRState(force) | GetFPUState(force) | GetEXCState(force);
2356 return GetGPRState(force);
2358 return GetFPUState(force);
2360 return GetEXCState(force);
2364 return KERN_INVALID_ARGUMENT;
2367 kern_return_t DNBArchImplI386::SetRegisterState(int set) {
2368 // Make sure we have a valid context to set.
2369 if (RegisterSetStateIsValid(set)) {
2372 return SetGPRState() | SetFPUState() | SetEXCState();
2374 return SetGPRState();
2376 return SetFPUState();
2378 return SetEXCState();
2383 return KERN_INVALID_ARGUMENT;
2386 bool DNBArchImplI386::RegisterSetStateIsValid(int set) const {
2387 return m_state.RegsAreValid(set);
2390 #endif // #if defined (__i386__)