RegisterContextDarwin_arm64.cpp revision 275126
1//===-- RegisterContextDarwin_arm64.cpp ---------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#if defined(__APPLE__)
11
12#include "RegisterContextDarwin_arm64.h"
13
14// C Includes
15#include <mach/mach_types.h>
16#include <mach/thread_act.h>
17#include <sys/sysctl.h>
18
19// C++ Includes
20// Other libraries and framework includes
21#include "lldb/Core/DataBufferHeap.h"
22#include "lldb/Core/DataExtractor.h"
23#include "lldb/Core/Log.h"
24#include "lldb/Core/RegisterValue.h"
25#include "lldb/Core/Scalar.h"
26#include "lldb/Host/Endian.h"
27#include "llvm/ADT/STLExtras.h"
28#include "llvm/Support/Compiler.h"
29
30#include "Plugins/Process/Utility/InstructionUtils.h"
31
32// Support building against older versions of LLVM, this macro was added
33// recently.
34#ifndef LLVM_EXTENSION
35#define LLVM_EXTENSION
36#endif
37
38// Project includes
39#include "ARM64_GCC_Registers.h"
40#include "ARM64_DWARF_Registers.h"
41
42using namespace lldb;
43using namespace lldb_private;
44
45RegisterContextDarwin_arm64::RegisterContextDarwin_arm64(Thread &thread, uint32_t concrete_frame_idx) :
46    RegisterContext(thread, concrete_frame_idx),
47    gpr(),
48    fpu(),
49    exc()
50{
51    uint32_t i;
52    for (i=0; i<kNumErrors; i++)
53    {
54        gpr_errs[i] = -1;
55        fpu_errs[i] = -1;
56        exc_errs[i] = -1;
57    }
58}
59
60RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64()
61{
62}
63
64
65#define GPR_OFFSET(idx) ((idx) * 8)
66#define GPR_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::GPR, reg))
67
68#define FPU_OFFSET(idx) ((idx) * 16 + sizeof (RegisterContextDarwin_arm64::GPR))
69#define FPU_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::FPU, reg))
70
71#define EXC_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::EXC, reg) + sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU))
72#define DBG_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::DBG, reg) + sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU) + sizeof (RegisterContextDarwin_arm64::EXC))
73
74#define DEFINE_DBG(reg, i)  #reg, NULL, sizeof(((RegisterContextDarwin_arm64::DBG *)NULL)->reg[i]), DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, dbg_##reg##i }, NULL, NULL
75#define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU) + sizeof (RegisterContextDarwin_arm64::EXC))
76
77//-----------------------------------------------------------------------------
78// Include RegisterInfos_arm64 to declare our g_register_infos_arm64 structure.
79//-----------------------------------------------------------------------------
80#define DECLARE_REGISTER_INFOS_ARM64_STRUCT
81#include "RegisterInfos_arm64.h"
82#undef DECLARE_REGISTER_INFOS_ARM64_STRUCT
83
84// General purpose registers
85static uint32_t
86g_gpr_regnums[] =
87{
88    gpr_x0,
89    gpr_x1,
90    gpr_x2,
91    gpr_x3,
92    gpr_x4,
93    gpr_x5,
94    gpr_x6,
95    gpr_x7,
96    gpr_x8,
97    gpr_x9,
98    gpr_x10,
99    gpr_x11,
100    gpr_x12,
101    gpr_x13,
102    gpr_x14,
103    gpr_x15,
104    gpr_x16,
105    gpr_x17,
106    gpr_x18,
107    gpr_x19,
108    gpr_x20,
109    gpr_x21,
110    gpr_x22,
111    gpr_x23,
112    gpr_x24,
113    gpr_x25,
114    gpr_x26,
115    gpr_x27,
116    gpr_x28,
117    gpr_fp,
118    gpr_lr,
119    gpr_sp,
120    gpr_pc,
121    gpr_cpsr
122};
123
124// Floating point registers
125static uint32_t
126g_fpu_regnums[] =
127{
128    fpu_v0,
129    fpu_v1,
130    fpu_v2,
131    fpu_v3,
132    fpu_v4,
133    fpu_v5,
134    fpu_v6,
135    fpu_v7,
136    fpu_v8,
137    fpu_v9,
138    fpu_v10,
139    fpu_v11,
140    fpu_v12,
141    fpu_v13,
142    fpu_v14,
143    fpu_v15,
144    fpu_v16,
145    fpu_v17,
146    fpu_v18,
147    fpu_v19,
148    fpu_v20,
149    fpu_v21,
150    fpu_v22,
151    fpu_v23,
152    fpu_v24,
153    fpu_v25,
154    fpu_v26,
155    fpu_v27,
156    fpu_v28,
157    fpu_v29,
158    fpu_v30,
159    fpu_v31,
160    fpu_fpsr,
161    fpu_fpcr
162};
163
164// Exception registers
165
166static uint32_t
167g_exc_regnums[] =
168{
169    exc_far,
170    exc_esr,
171    exc_exception
172};
173
174static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos_arm64);
175
176void
177RegisterContextDarwin_arm64::InvalidateAllRegisters ()
178{
179    InvalidateAllRegisterStates();
180}
181
182
183size_t
184RegisterContextDarwin_arm64::GetRegisterCount ()
185{
186    assert(k_num_register_infos == k_num_registers);
187    return k_num_registers;
188}
189
190const RegisterInfo *
191RegisterContextDarwin_arm64::GetRegisterInfoAtIndex (size_t reg)
192{
193    assert(k_num_register_infos == k_num_registers);
194    if (reg < k_num_registers)
195        return &g_register_infos_arm64[reg];
196    return NULL;
197}
198
199size_t
200RegisterContextDarwin_arm64::GetRegisterInfosCount ()
201{
202    return k_num_register_infos;
203}
204
205const RegisterInfo *
206RegisterContextDarwin_arm64::GetRegisterInfos ()
207{
208    return g_register_infos_arm64;
209}
210
211
212// Number of registers in each register set
213const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums);
214const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
215const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
216
217//----------------------------------------------------------------------
218// Register set definitions. The first definitions at register set index
219// of zero is for all registers, followed by other registers sets. The
220// register information for the all register set need not be filled in.
221//----------------------------------------------------------------------
222static const RegisterSet g_reg_sets[] =
223{
224    { "General Purpose Registers",  "gpr",  k_num_gpr_registers,    g_gpr_regnums,      },
225    { "Floating Point Registers",   "fpu",  k_num_fpu_registers,    g_fpu_regnums       },
226    { "Exception State Registers",  "exc",  k_num_exc_registers,    g_exc_regnums       }
227};
228
229const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets);
230
231
232size_t
233RegisterContextDarwin_arm64::GetRegisterSetCount ()
234{
235    return k_num_regsets;
236}
237
238const RegisterSet *
239RegisterContextDarwin_arm64::GetRegisterSet (size_t reg_set)
240{
241    if (reg_set < k_num_regsets)
242        return &g_reg_sets[reg_set];
243    return NULL;
244}
245
246
247//----------------------------------------------------------------------
248// Register information definitions for arm64
249//----------------------------------------------------------------------
250int
251RegisterContextDarwin_arm64::GetSetForNativeRegNum (int reg)
252{
253    if (reg < fpu_v0)
254        return GPRRegSet;
255    else if (reg < exc_far)
256        return FPURegSet;
257    else if (reg < k_num_registers)
258        return EXCRegSet;
259    return -1;
260}
261
262int
263RegisterContextDarwin_arm64::ReadGPR (bool force)
264{
265    int set = GPRRegSet;
266    if (force || !RegisterSetIsCached(set))
267    {
268        SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
269    }
270    return GetError(GPRRegSet, Read);
271}
272
273int
274RegisterContextDarwin_arm64::ReadFPU (bool force)
275{
276    int set = FPURegSet;
277    if (force || !RegisterSetIsCached(set))
278    {
279        SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));
280    }
281    return GetError(FPURegSet, Read);
282}
283
284int
285RegisterContextDarwin_arm64::ReadEXC (bool force)
286{
287    int set = EXCRegSet;
288    if (force || !RegisterSetIsCached(set))
289    {
290        SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
291    }
292    return GetError(EXCRegSet, Read);
293}
294
295int
296RegisterContextDarwin_arm64::ReadDBG (bool force)
297{
298    int set = DBGRegSet;
299    if (force || !RegisterSetIsCached(set))
300    {
301        SetError(set, Read, DoReadDBG(GetThreadID(), set, dbg));
302    }
303    return GetError(DBGRegSet, Read);
304}
305
306int
307RegisterContextDarwin_arm64::WriteGPR ()
308{
309    int set = GPRRegSet;
310    if (!RegisterSetIsCached(set))
311    {
312        SetError (set, Write, -1);
313        return KERN_INVALID_ARGUMENT;
314    }
315    SetError (set, Write, DoWriteGPR(GetThreadID(), set, gpr));
316    SetError (set, Read, -1);
317    return GetError(GPRRegSet, Write);
318}
319
320int
321RegisterContextDarwin_arm64::WriteFPU ()
322{
323    int set = FPURegSet;
324    if (!RegisterSetIsCached(set))
325    {
326        SetError (set, Write, -1);
327        return KERN_INVALID_ARGUMENT;
328    }
329    SetError (set, Write, DoWriteFPU(GetThreadID(), set, fpu));
330    SetError (set, Read, -1);
331    return GetError(FPURegSet, Write);
332}
333
334int
335RegisterContextDarwin_arm64::WriteEXC ()
336{
337    int set = EXCRegSet;
338    if (!RegisterSetIsCached(set))
339    {
340        SetError (set, Write, -1);
341        return KERN_INVALID_ARGUMENT;
342    }
343    SetError (set, Write, DoWriteEXC(GetThreadID(), set, exc));
344    SetError (set, Read, -1);
345    return GetError(EXCRegSet, Write);
346}
347
348int
349RegisterContextDarwin_arm64::WriteDBG ()
350{
351    int set = DBGRegSet;
352    if (!RegisterSetIsCached(set))
353    {
354        SetError (set, Write, -1);
355        return KERN_INVALID_ARGUMENT;
356    }
357    SetError (set, Write, DoWriteDBG(GetThreadID(), set, dbg));
358    SetError (set, Read, -1);
359    return GetError(DBGRegSet, Write);
360}
361
362
363int
364RegisterContextDarwin_arm64::ReadRegisterSet (uint32_t set, bool force)
365{
366    switch (set)
367    {
368    case GPRRegSet:    return ReadGPR(force);
369    case FPURegSet:    return ReadFPU(force);
370    case EXCRegSet:    return ReadEXC(force);
371    case DBGRegSet:    return ReadDBG(force);
372    default: break;
373    }
374    return KERN_INVALID_ARGUMENT;
375}
376
377int
378RegisterContextDarwin_arm64::WriteRegisterSet (uint32_t set)
379{
380    // Make sure we have a valid context to set.
381    if (RegisterSetIsCached(set))
382    {
383        switch (set)
384        {
385        case GPRRegSet:    return WriteGPR();
386        case FPURegSet:    return WriteFPU();
387        case EXCRegSet:    return WriteEXC();
388        case DBGRegSet:    return WriteDBG();
389        default: break;
390        }
391    }
392    return KERN_INVALID_ARGUMENT;
393}
394
395void
396RegisterContextDarwin_arm64::LogDBGRegisters (Log *log, const DBG& dbg)
397{
398    if (log)
399    {
400        for (uint32_t i=0; i<16; i++)
401            log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8llx, 0x%8.8llx } WVR%-2u/WCR%-2u = { 0x%8.8llx, 0x%8.8llx }",
402                i, i, dbg.bvr[i], dbg.bcr[i],
403                i, i, dbg.wvr[i], dbg.wcr[i]);
404    }
405}
406
407
408bool
409RegisterContextDarwin_arm64::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value)
410{
411    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
412    int set = RegisterContextDarwin_arm64::GetSetForNativeRegNum (reg);
413
414    if (set == -1)
415        return false;
416
417    if (ReadRegisterSet(set, false) != KERN_SUCCESS)
418        return false;
419
420    switch (reg)
421    {
422    case gpr_x0:
423    case gpr_x1:
424    case gpr_x2:
425    case gpr_x3:
426    case gpr_x4:
427    case gpr_x5:
428    case gpr_x6:
429    case gpr_x7:
430    case gpr_x8:
431    case gpr_x9:
432    case gpr_x10:
433    case gpr_x11:
434    case gpr_x12:
435    case gpr_x13:
436    case gpr_x14:
437    case gpr_x15:
438    case gpr_x16:
439    case gpr_x17:
440    case gpr_x18:
441    case gpr_x19:
442    case gpr_x20:
443    case gpr_x21:
444    case gpr_x22:
445    case gpr_x23:
446    case gpr_x24:
447    case gpr_x25:
448    case gpr_x26:
449    case gpr_x27:
450    case gpr_x28:
451    case gpr_fp:
452    case gpr_sp:
453    case gpr_lr:
454    case gpr_pc:
455    case gpr_cpsr:
456        value.SetUInt64 (gpr.x[reg - gpr_x0]);
457        break;
458
459    case fpu_v0:
460    case fpu_v1:
461    case fpu_v2:
462    case fpu_v3:
463    case fpu_v4:
464    case fpu_v5:
465    case fpu_v6:
466    case fpu_v7:
467    case fpu_v8:
468    case fpu_v9:
469    case fpu_v10:
470    case fpu_v11:
471    case fpu_v12:
472    case fpu_v13:
473    case fpu_v14:
474    case fpu_v15:
475    case fpu_v16:
476    case fpu_v17:
477    case fpu_v18:
478    case fpu_v19:
479    case fpu_v20:
480    case fpu_v21:
481    case fpu_v22:
482    case fpu_v23:
483    case fpu_v24:
484    case fpu_v25:
485    case fpu_v26:
486    case fpu_v27:
487    case fpu_v28:
488    case fpu_v29:
489    case fpu_v30:
490    case fpu_v31:
491        value.SetBytes(fpu.v[reg].bytes, reg_info->byte_size, lldb::endian::InlHostByteOrder());
492        break;
493
494    case fpu_fpsr:
495        value.SetUInt32 (fpu.fpsr);
496        break;
497
498    case fpu_fpcr:
499        value.SetUInt32 (fpu.fpcr);
500        break;
501
502    case exc_exception:
503        value.SetUInt32 (exc.exception);
504        break;
505    case exc_esr:
506        value.SetUInt32 (exc.esr);
507        break;
508    case exc_far:
509        value.SetUInt64 (exc.far);
510        break;
511
512    default:
513        value.SetValueToInvalid();
514        return false;
515
516    }
517    return true;
518}
519
520
521bool
522RegisterContextDarwin_arm64::WriteRegister (const RegisterInfo *reg_info,
523                                        const RegisterValue &value)
524{
525    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
526    int set = GetSetForNativeRegNum (reg);
527
528    if (set == -1)
529        return false;
530
531    if (ReadRegisterSet(set, false) != KERN_SUCCESS)
532        return false;
533
534    switch (reg)
535    {
536    case gpr_x0:
537    case gpr_x1:
538    case gpr_x2:
539    case gpr_x3:
540    case gpr_x4:
541    case gpr_x5:
542    case gpr_x6:
543    case gpr_x7:
544    case gpr_x8:
545    case gpr_x9:
546    case gpr_x10:
547    case gpr_x11:
548    case gpr_x12:
549    case gpr_x13:
550    case gpr_x14:
551    case gpr_x15:
552    case gpr_x16:
553    case gpr_x17:
554    case gpr_x18:
555    case gpr_x19:
556    case gpr_x20:
557    case gpr_x21:
558    case gpr_x22:
559    case gpr_x23:
560    case gpr_x24:
561    case gpr_x25:
562    case gpr_x26:
563    case gpr_x27:
564    case gpr_x28:
565    case gpr_fp:
566    case gpr_sp:
567    case gpr_lr:
568    case gpr_pc:
569    case gpr_cpsr:
570            gpr.x[reg - gpr_x0] = value.GetAsUInt64();
571        break;
572
573    case fpu_v0:
574    case fpu_v1:
575    case fpu_v2:
576    case fpu_v3:
577    case fpu_v4:
578    case fpu_v5:
579    case fpu_v6:
580    case fpu_v7:
581    case fpu_v8:
582    case fpu_v9:
583    case fpu_v10:
584    case fpu_v11:
585    case fpu_v12:
586    case fpu_v13:
587    case fpu_v14:
588    case fpu_v15:
589    case fpu_v16:
590    case fpu_v17:
591    case fpu_v18:
592    case fpu_v19:
593    case fpu_v20:
594    case fpu_v21:
595    case fpu_v22:
596    case fpu_v23:
597    case fpu_v24:
598    case fpu_v25:
599    case fpu_v26:
600    case fpu_v27:
601    case fpu_v28:
602    case fpu_v29:
603    case fpu_v30:
604    case fpu_v31:
605        ::memcpy (fpu.v[reg].bytes, value.GetBytes(), value.GetByteSize());
606        break;
607
608    case fpu_fpsr:
609        fpu.fpsr = value.GetAsUInt32();
610        break;
611
612    case fpu_fpcr:
613        fpu.fpcr = value.GetAsUInt32();
614        break;
615
616    case exc_exception:
617        exc.exception = value.GetAsUInt32();
618        break;
619    case exc_esr:
620        exc.esr = value.GetAsUInt32();
621        break;
622    case exc_far:
623        exc.far = value.GetAsUInt64();
624        break;
625
626    default:
627        return false;
628
629    }
630    return WriteRegisterSet(set) == KERN_SUCCESS;
631}
632
633bool
634RegisterContextDarwin_arm64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
635{
636    data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
637    if (data_sp &&
638        ReadGPR (false) == KERN_SUCCESS &&
639        ReadFPU (false) == KERN_SUCCESS &&
640        ReadEXC (false) == KERN_SUCCESS)
641    {
642        uint8_t *dst = data_sp->GetBytes();
643        ::memcpy (dst, &gpr, sizeof(gpr));
644        dst += sizeof(gpr);
645
646        ::memcpy (dst, &fpu, sizeof(fpu));
647        dst += sizeof(gpr);
648
649        ::memcpy (dst, &exc, sizeof(exc));
650        return true;
651    }
652    return false;
653}
654
655bool
656RegisterContextDarwin_arm64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
657{
658    if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
659    {
660        const uint8_t *src = data_sp->GetBytes();
661        ::memcpy (&gpr, src, sizeof(gpr));
662        src += sizeof(gpr);
663
664        ::memcpy (&fpu, src, sizeof(fpu));
665        src += sizeof(gpr);
666
667        ::memcpy (&exc, src, sizeof(exc));
668        uint32_t success_count = 0;
669        if (WriteGPR() == KERN_SUCCESS)
670            ++success_count;
671        if (WriteFPU() == KERN_SUCCESS)
672            ++success_count;
673        if (WriteEXC() == KERN_SUCCESS)
674            ++success_count;
675        return success_count == 3;
676    }
677    return false;
678}
679
680uint32_t
681RegisterContextDarwin_arm64::ConvertRegisterKindToRegisterNumber (RegisterKind kind, uint32_t reg)
682{
683    if (kind == eRegisterKindGeneric)
684    {
685        switch (reg)
686        {
687        case LLDB_REGNUM_GENERIC_PC: return gpr_pc;
688        case LLDB_REGNUM_GENERIC_SP: return gpr_sp;
689        case LLDB_REGNUM_GENERIC_FP: return gpr_fp;
690        case LLDB_REGNUM_GENERIC_RA: return gpr_lr;
691        case LLDB_REGNUM_GENERIC_FLAGS: return gpr_cpsr;
692        default:
693            break;
694        }
695    }
696    else if (kind == eRegisterKindDWARF)
697    {
698        switch (reg)
699        {
700        case arm64_dwarf::x0:  return gpr_x0;
701        case arm64_dwarf::x1:  return gpr_x1;
702        case arm64_dwarf::x2:  return gpr_x2;
703        case arm64_dwarf::x3:  return gpr_x3;
704        case arm64_dwarf::x4:  return gpr_x4;
705        case arm64_dwarf::x5:  return gpr_x5;
706        case arm64_dwarf::x6:  return gpr_x6;
707        case arm64_dwarf::x7:  return gpr_x7;
708        case arm64_dwarf::x8:  return gpr_x8;
709        case arm64_dwarf::x9:  return gpr_x9;
710        case arm64_dwarf::x10: return gpr_x10;
711        case arm64_dwarf::x11: return gpr_x11;
712        case arm64_dwarf::x12: return gpr_x12;
713        case arm64_dwarf::x13: return gpr_x13;
714        case arm64_dwarf::x14: return gpr_x14;
715        case arm64_dwarf::x15: return gpr_x15;
716        case arm64_dwarf::x16: return gpr_x16;
717        case arm64_dwarf::x17: return gpr_x17;
718        case arm64_dwarf::x18: return gpr_x18;
719        case arm64_dwarf::x19: return gpr_x19;
720        case arm64_dwarf::x20: return gpr_x20;
721        case arm64_dwarf::x21: return gpr_x21;
722        case arm64_dwarf::x22: return gpr_x22;
723        case arm64_dwarf::x23: return gpr_x23;
724        case arm64_dwarf::x24: return gpr_x24;
725        case arm64_dwarf::x25: return gpr_x25;
726        case arm64_dwarf::x26: return gpr_x26;
727        case arm64_dwarf::x27: return gpr_x27;
728        case arm64_dwarf::x28: return gpr_x28;
729
730        case arm64_dwarf::fp:  return gpr_fp;
731        case arm64_dwarf::sp:  return gpr_sp;
732        case arm64_dwarf::lr:  return gpr_lr;
733        case arm64_dwarf::pc:  return gpr_pc;
734        case arm64_dwarf::cpsr: return gpr_cpsr;
735
736        case arm64_dwarf::v0:  return fpu_v0;
737        case arm64_dwarf::v1:  return fpu_v1;
738        case arm64_dwarf::v2:  return fpu_v2;
739        case arm64_dwarf::v3:  return fpu_v3;
740        case arm64_dwarf::v4:  return fpu_v4;
741        case arm64_dwarf::v5:  return fpu_v5;
742        case arm64_dwarf::v6:  return fpu_v6;
743        case arm64_dwarf::v7:  return fpu_v7;
744        case arm64_dwarf::v8:  return fpu_v8;
745        case arm64_dwarf::v9:  return fpu_v9;
746        case arm64_dwarf::v10: return fpu_v10;
747        case arm64_dwarf::v11: return fpu_v11;
748        case arm64_dwarf::v12: return fpu_v12;
749        case arm64_dwarf::v13: return fpu_v13;
750        case arm64_dwarf::v14: return fpu_v14;
751        case arm64_dwarf::v15: return fpu_v15;
752        case arm64_dwarf::v16: return fpu_v16;
753        case arm64_dwarf::v17: return fpu_v17;
754        case arm64_dwarf::v18: return fpu_v18;
755        case arm64_dwarf::v19: return fpu_v19;
756        case arm64_dwarf::v20: return fpu_v20;
757        case arm64_dwarf::v21: return fpu_v21;
758        case arm64_dwarf::v22: return fpu_v22;
759        case arm64_dwarf::v23: return fpu_v23;
760        case arm64_dwarf::v24: return fpu_v24;
761        case arm64_dwarf::v25: return fpu_v25;
762        case arm64_dwarf::v26: return fpu_v26;
763        case arm64_dwarf::v27: return fpu_v27;
764        case arm64_dwarf::v28: return fpu_v28;
765        case arm64_dwarf::v29: return fpu_v29;
766        case arm64_dwarf::v30: return fpu_v30;
767        case arm64_dwarf::v31: return fpu_v31;
768
769        default:
770            break;
771        }
772    }
773    else if (kind == eRegisterKindGCC)
774    {
775        switch (reg)
776        {
777        case arm64_gcc::x0:  return gpr_x0;
778        case arm64_gcc::x1:  return gpr_x1;
779        case arm64_gcc::x2:  return gpr_x2;
780        case arm64_gcc::x3:  return gpr_x3;
781        case arm64_gcc::x4:  return gpr_x4;
782        case arm64_gcc::x5:  return gpr_x5;
783        case arm64_gcc::x6:  return gpr_x6;
784        case arm64_gcc::x7:  return gpr_x7;
785        case arm64_gcc::x8:  return gpr_x8;
786        case arm64_gcc::x9:  return gpr_x9;
787        case arm64_gcc::x10: return gpr_x10;
788        case arm64_gcc::x11: return gpr_x11;
789        case arm64_gcc::x12: return gpr_x12;
790        case arm64_gcc::x13: return gpr_x13;
791        case arm64_gcc::x14: return gpr_x14;
792        case arm64_gcc::x15: return gpr_x15;
793        case arm64_gcc::x16: return gpr_x16;
794        case arm64_gcc::x17: return gpr_x17;
795        case arm64_gcc::x18: return gpr_x18;
796        case arm64_gcc::x19: return gpr_x19;
797        case arm64_gcc::x20: return gpr_x20;
798        case arm64_gcc::x21: return gpr_x21;
799        case arm64_gcc::x22: return gpr_x22;
800        case arm64_gcc::x23: return gpr_x23;
801        case arm64_gcc::x24: return gpr_x24;
802        case arm64_gcc::x25: return gpr_x25;
803        case arm64_gcc::x26: return gpr_x26;
804        case arm64_gcc::x27: return gpr_x27;
805        case arm64_gcc::x28: return gpr_x28;
806        case arm64_gcc::fp:   return gpr_fp;
807        case arm64_gcc::sp:   return gpr_sp;
808        case arm64_gcc::lr:   return gpr_lr;
809        case arm64_gcc::pc:   return gpr_pc;
810        case arm64_gcc::cpsr: return gpr_cpsr;
811        }
812    }
813    else if (kind == eRegisterKindLLDB)
814    {
815        return reg;
816    }
817    return LLDB_INVALID_REGNUM;
818}
819
820
821uint32_t
822RegisterContextDarwin_arm64::NumSupportedHardwareWatchpoints ()
823{
824#if defined (__arm64__) || defined (__aarch64__)
825    // autodetect how many watchpoints are supported dynamically...
826    static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX;
827    if (g_num_supported_hw_watchpoints == UINT32_MAX)
828    {
829        size_t len;
830        uint32_t n = 0;
831        len = sizeof (n);
832        if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0)
833        {
834            g_num_supported_hw_watchpoints = n;
835        }
836    }
837    return g_num_supported_hw_watchpoints;
838#else
839    // TODO: figure out remote case here!
840    return 2;
841#endif
842}
843
844
845uint32_t
846RegisterContextDarwin_arm64::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write)
847{
848//    if (log) log->Printf ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint(addr = %8.8p, size = %u, read = %u, write = %u)", addr, size, read, write);
849
850    const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
851
852    // Can't watch zero bytes
853    if (size == 0)
854        return LLDB_INVALID_INDEX32;
855
856    // We must watch for either read or write
857    if (read == false && write == false)
858        return LLDB_INVALID_INDEX32;
859
860    // Can't watch more than 4 bytes per WVR/WCR pair
861    if (size > 4)
862        return LLDB_INVALID_INDEX32;
863
864    // We can only watch up to four bytes that follow a 4 byte aligned address
865    // per watchpoint register pair. Since we have at most so we can only watch
866    // until the next 4 byte boundary and we need to make sure we can properly
867    // encode this.
868    uint32_t addr_word_offset = addr % 4;
869//    if (log) log->Printf ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() - addr_word_offset = 0x%8.8x", addr_word_offset);
870
871    uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset;
872//    if (log) log->Printf ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() - byte_mask = 0x%8.8x", byte_mask);
873    if (byte_mask > 0xfu)
874        return LLDB_INVALID_INDEX32;
875
876    // Read the debug state
877    int kret = ReadDBG (false);
878
879    if (kret == KERN_SUCCESS)
880    {
881        // Check to make sure we have the needed hardware support
882        uint32_t i = 0;
883
884        for (i=0; i<num_hw_watchpoints; ++i)
885        {
886            if ((dbg.wcr[i] & WCR_ENABLE) == 0)
887                break; // We found an available hw breakpoint slot (in i)
888        }
889
890        // See if we found an available hw breakpoint slot above
891        if (i < num_hw_watchpoints)
892        {
893            // Make the byte_mask into a valid Byte Address Select mask
894            uint32_t byte_address_select = byte_mask << 5;
895            // Make sure bits 1:0 are clear in our address
896            dbg.wvr[i] = addr & ~((lldb::addr_t)3);
897            dbg.wcr[i] =  byte_address_select |       // Which bytes that follow the IMVA that we will watch
898                                    S_USER |                    // Stop only in user mode
899                                    (read ? WCR_LOAD : 0) |     // Stop on read access?
900                                    (write ? WCR_STORE : 0) |   // Stop on write access?
901                                    WCR_ENABLE;                 // Enable this watchpoint;
902
903            kret = WriteDBG();
904//            if (log) log->Printf ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() WriteDBG() => 0x%8.8x.", kret);
905
906            if (kret == KERN_SUCCESS)
907                return i;
908        }
909        else
910        {
911//            if (log) log->Printf ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints);
912        }
913    }
914    return LLDB_INVALID_INDEX32;
915}
916
917bool
918RegisterContextDarwin_arm64::ClearHardwareWatchpoint (uint32_t hw_index)
919{
920    int kret = ReadDBG (false);
921
922    const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
923    if (kret == KERN_SUCCESS)
924    {
925        if (hw_index < num_hw_points)
926        {
927            dbg.wcr[hw_index] = 0;
928//            if (log) log->Printf ("RegisterContextDarwin_arm64::ClearHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x  WCR%u = 0x%8.8x",
929//                    hw_index,
930//                    hw_index,
931//                    dbg.wvr[hw_index],
932//                    hw_index,
933//                    dbg.wcr[hw_index]);
934
935            kret = WriteDBG();
936
937            if (kret == KERN_SUCCESS)
938                return true;
939        }
940    }
941    return false;
942}
943
944#endif
945