10b57cec5SDimitry Andric //===-- RegisterContextDarwin_i386.h ----------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
95ffd83dbSDimitry Andric #ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_I386_H
105ffd83dbSDimitry Andric #define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_I386_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "lldb/Target/RegisterContext.h"
130b57cec5SDimitry Andric #include "lldb/lldb-private.h"
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric class RegisterContextDarwin_i386 : public lldb_private::RegisterContext {
160b57cec5SDimitry Andric public:
170b57cec5SDimitry Andric   RegisterContextDarwin_i386(lldb_private::Thread &thread,
180b57cec5SDimitry Andric                              uint32_t concrete_frame_idx);
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric   ~RegisterContextDarwin_i386() override;
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric   void InvalidateAllRegisters() override;
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric   size_t GetRegisterCount() override;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric   const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override;
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric   size_t GetRegisterSetCount() override;
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric   const lldb_private::RegisterSet *GetRegisterSet(size_t set) override;
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric   bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
330b57cec5SDimitry Andric                     lldb_private::RegisterValue &value) override;
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric   bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
360b57cec5SDimitry Andric                      const lldb_private::RegisterValue &value) override;
370b57cec5SDimitry Andric 
3881ad6265SDimitry Andric   bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric   bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric   uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
430b57cec5SDimitry Andric                                                uint32_t num) override;
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric   bool HardwareSingleStep(bool enable) override;
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric   struct GPR {
480b57cec5SDimitry Andric     uint32_t eax;
490b57cec5SDimitry Andric     uint32_t ebx;
500b57cec5SDimitry Andric     uint32_t ecx;
510b57cec5SDimitry Andric     uint32_t edx;
520b57cec5SDimitry Andric     uint32_t edi;
530b57cec5SDimitry Andric     uint32_t esi;
540b57cec5SDimitry Andric     uint32_t ebp;
550b57cec5SDimitry Andric     uint32_t esp;
560b57cec5SDimitry Andric     uint32_t ss;
570b57cec5SDimitry Andric     uint32_t eflags;
580b57cec5SDimitry Andric     uint32_t eip;
590b57cec5SDimitry Andric     uint32_t cs;
600b57cec5SDimitry Andric     uint32_t ds;
610b57cec5SDimitry Andric     uint32_t es;
620b57cec5SDimitry Andric     uint32_t fs;
630b57cec5SDimitry Andric     uint32_t gs;
640b57cec5SDimitry Andric   };
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric   struct MMSReg {
670b57cec5SDimitry Andric     uint8_t bytes[10];
680b57cec5SDimitry Andric     uint8_t pad[6];
690b57cec5SDimitry Andric   };
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   struct XMMReg {
720b57cec5SDimitry Andric     uint8_t bytes[16];
730b57cec5SDimitry Andric   };
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   struct FPU {
760b57cec5SDimitry Andric     uint32_t pad[2];
770b57cec5SDimitry Andric     uint16_t fcw;
780b57cec5SDimitry Andric     uint16_t fsw;
790b57cec5SDimitry Andric     uint8_t ftw;
800b57cec5SDimitry Andric     uint8_t pad1;
810b57cec5SDimitry Andric     uint16_t fop;
820b57cec5SDimitry Andric     uint32_t ip;
830b57cec5SDimitry Andric     uint16_t cs;
840b57cec5SDimitry Andric     uint16_t pad2;
850b57cec5SDimitry Andric     uint32_t dp;
860b57cec5SDimitry Andric     uint16_t ds;
870b57cec5SDimitry Andric     uint16_t pad3;
880b57cec5SDimitry Andric     uint32_t mxcsr;
890b57cec5SDimitry Andric     uint32_t mxcsrmask;
900b57cec5SDimitry Andric     MMSReg stmm[8];
910b57cec5SDimitry Andric     XMMReg xmm[8];
920b57cec5SDimitry Andric     uint8_t pad4[14 * 16];
930b57cec5SDimitry Andric     int pad5;
940b57cec5SDimitry Andric   };
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   struct EXC {
970b57cec5SDimitry Andric     uint32_t trapno;
980b57cec5SDimitry Andric     uint32_t err;
990b57cec5SDimitry Andric     uint32_t faultvaddr;
1000b57cec5SDimitry Andric   };
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric protected:
1030b57cec5SDimitry Andric   enum { GPRRegSet = 1, FPURegSet = 2, EXCRegSet = 3 };
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   enum {
1060b57cec5SDimitry Andric     GPRWordCount = sizeof(GPR) / sizeof(uint32_t),
1070b57cec5SDimitry Andric     FPUWordCount = sizeof(FPU) / sizeof(uint32_t),
1080b57cec5SDimitry Andric     EXCWordCount = sizeof(EXC) / sizeof(uint32_t)
1090b57cec5SDimitry Andric   };
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   enum { Read = 0, Write = 1, kNumErrors = 2 };
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   GPR gpr;
1140b57cec5SDimitry Andric   FPU fpu;
1150b57cec5SDimitry Andric   EXC exc;
1160b57cec5SDimitry Andric   int gpr_errs[2]; // Read/Write errors
1170b57cec5SDimitry Andric   int fpu_errs[2]; // Read/Write errors
1180b57cec5SDimitry Andric   int exc_errs[2]; // Read/Write errors
1190b57cec5SDimitry Andric 
InvalidateAllRegisterStates()1200b57cec5SDimitry Andric   void InvalidateAllRegisterStates() {
1210b57cec5SDimitry Andric     SetError(GPRRegSet, Read, -1);
1220b57cec5SDimitry Andric     SetError(FPURegSet, Read, -1);
1230b57cec5SDimitry Andric     SetError(EXCRegSet, Read, -1);
1240b57cec5SDimitry Andric   }
1250b57cec5SDimitry Andric 
GetError(int flavor,uint32_t err_idx)1260b57cec5SDimitry Andric   int GetError(int flavor, uint32_t err_idx) const {
1270b57cec5SDimitry Andric     if (err_idx < kNumErrors) {
1280b57cec5SDimitry Andric       switch (flavor) {
1290b57cec5SDimitry Andric       // When getting all errors, just OR all values together to see if
1300b57cec5SDimitry Andric       // we got any kind of error.
1310b57cec5SDimitry Andric       case GPRRegSet:
1320b57cec5SDimitry Andric         return gpr_errs[err_idx];
1330b57cec5SDimitry Andric       case FPURegSet:
1340b57cec5SDimitry Andric         return fpu_errs[err_idx];
1350b57cec5SDimitry Andric       case EXCRegSet:
1360b57cec5SDimitry Andric         return exc_errs[err_idx];
1370b57cec5SDimitry Andric       default:
1380b57cec5SDimitry Andric         break;
1390b57cec5SDimitry Andric       }
1400b57cec5SDimitry Andric     }
1410b57cec5SDimitry Andric     return -1;
1420b57cec5SDimitry Andric   }
1430b57cec5SDimitry Andric 
SetError(int flavor,uint32_t err_idx,int err)1440b57cec5SDimitry Andric   bool SetError(int flavor, uint32_t err_idx, int err) {
1450b57cec5SDimitry Andric     if (err_idx < kNumErrors) {
1460b57cec5SDimitry Andric       switch (flavor) {
1470b57cec5SDimitry Andric       case GPRRegSet:
1480b57cec5SDimitry Andric         gpr_errs[err_idx] = err;
1490b57cec5SDimitry Andric         return true;
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric       case FPURegSet:
1520b57cec5SDimitry Andric         fpu_errs[err_idx] = err;
1530b57cec5SDimitry Andric         return true;
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric       case EXCRegSet:
1560b57cec5SDimitry Andric         exc_errs[err_idx] = err;
1570b57cec5SDimitry Andric         return true;
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric       default:
1600b57cec5SDimitry Andric         break;
1610b57cec5SDimitry Andric       }
1620b57cec5SDimitry Andric     }
1630b57cec5SDimitry Andric     return false;
1640b57cec5SDimitry Andric   }
1650b57cec5SDimitry Andric 
RegisterSetIsCached(int set)1660b57cec5SDimitry Andric   bool RegisterSetIsCached(int set) const { return GetError(set, Read) == 0; }
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   void LogGPR(lldb_private::Log *log, const char *title);
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric   int ReadGPR(bool force);
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   int ReadFPU(bool force);
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric   int ReadEXC(bool force);
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric   int WriteGPR();
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric   int WriteFPU();
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   int WriteEXC();
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   // Subclasses override these to do the actual reading.
1830b57cec5SDimitry Andric   virtual int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) = 0;
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric   virtual int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) = 0;
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric   virtual int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) = 0;
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   virtual int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) = 0;
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   virtual int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) = 0;
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   virtual int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) = 0;
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric   int ReadRegisterSet(uint32_t set, bool force);
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   int WriteRegisterSet(uint32_t set);
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric   static uint32_t GetRegisterNumber(uint32_t reg_kind, uint32_t reg_num);
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric   static int GetSetForNativeRegNum(int reg_num);
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric   static size_t GetRegisterInfosCount();
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric   static const lldb_private::RegisterInfo *GetRegisterInfos();
2060b57cec5SDimitry Andric };
2070b57cec5SDimitry Andric 
2085ffd83dbSDimitry Andric #endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_I386_H
209