]> git.saurik.com Git - apple/ld64.git/blobdiff - src/ld/parsers/libunwind/Registers.hpp
ld64-409.12.tar.gz
[apple/ld64.git] / src / ld / parsers / libunwind / Registers.hpp
index 7d39fd74ad9eb5b72acdaf7e4aba32425be4b585..66e66cce0c5b60dbb456af7dd9f38a1ddf69e543 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
  *
- * Copyright (c) 2007-2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2007-2011 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  *
@@ -1035,7 +1035,318 @@ inline const char* Registers_ppc::getRegisterName(int regNum)
                        return "unknown register";
        }
 
+}
+
+
+
+
+
+struct arm_thread_state64_t
+{
+       __uint64_t    __x[29];  /* General purpose registers x0-x28 */
+       __uint64_t    __fp;             /* Frame pointer x29 */
+       __uint64_t    __lr;             /* Link register x30 */
+       __uint64_t    __sp;             /* Stack pointer x31 */
+       __uint64_t    __pc;             /* Program counter */
+       __uint32_t    __cpsr;   /* Current program status register */
+       __uint32_t        padding[3]; /* round up struct size to be 0x110 */
+};
+
+
+///
+/// Registers_arm64  holds the register state of a thread in a 64-bit intel process.  
+///
+class Registers_arm64
+{
+public:        
+                                       Registers_arm64();
+                                       Registers_arm64(const void* registers); 
+
+       bool                    validRegister(int num) const;
+       uint64_t                getRegister(int num) const;
+       void                    setRegister(int num, uint64_t value);
+       bool                    validFloatRegister(int num) const;
+       double                  getFloatRegister(int num) const;
+       void                    setFloatRegister(int num, double value);
+       bool                    validVectorRegister(int num) const;
+       v128                    getVectorRegister(int num) const;
+       void                    setVectorRegister(int num, v128 value);
+       const char*             getRegisterName(int num);
+       void                    jumpto();
+       uint64_t                getSP() const                   { return fRegisters.__sp; }
+       void                    setSP(uint64_t value)   { fRegisters.__sp = value; }
+       uint64_t                getIP() const                   { return fRegisters.__pc; }
+       void                    setIP(uint64_t value)   { fRegisters.__pc = value; }
+       uint64_t                getFP() const                   { return fRegisters.__fp; }
+       void                    setFP(uint64_t value)   { fRegisters.__fp = value; }
+private:
+       arm_thread_state64_t    fRegisters;
+       double                                  fHalfVectorRegisters[32];
+       // Currently only the lower double in 128-bit vectore registers
+       // is perserved during unwinding.  We could define new register
+       // numbers (> 96) which mean whole vector registers, then this
+       // struct would need to change to contain whole vector registers.
+};
+
+inline Registers_arm64::Registers_arm64(const void* registers)
+{
+       COMPILE_TIME_ASSERT( sizeof(Registers_arm64) < sizeof(unw_context_t) );
+       fRegisters = *((arm_thread_state64_t*)registers); 
+}
+
+inline Registers_arm64::Registers_arm64()
+{
+       bzero(&fRegisters, sizeof(fRegisters)); 
+       bzero(&fRegisters, sizeof(fHalfVectorRegisters)); 
+}
+
+
+inline bool Registers_arm64::validRegister(int regNum) const
+{
+       if ( regNum == UNW_REG_IP )
+               return true;
+       if ( regNum == UNW_REG_SP )
+               return true;
+       if ( regNum < 0 )
+               return false;
+       if ( regNum > 95 )
+               return false;
+       if ( (regNum > 31) && (regNum < 64) )
+               return false;
+       return true;
+}
+
+inline uint64_t Registers_arm64::getRegister(int regNum) const
+{
+       if ( regNum == UNW_REG_IP )
+               return fRegisters.__pc;
+       if ( regNum == UNW_REG_SP )
+               return fRegisters.__sp;
+       if ( (regNum >= 0) && (regNum < 32) )
+               return fRegisters.__x[regNum];
+       ABORT("unsupported arm64 register");
+}
+
+inline void Registers_arm64::setRegister(int regNum, uint64_t value)
+{
+       if ( regNum == UNW_REG_IP )
+               fRegisters.__pc = value;
+       else if ( regNum == UNW_REG_SP )
+               fRegisters.__sp = value;
+       else if ( (regNum >= 0) && (regNum < 32) )
+               fRegisters.__x[regNum] = value;
+       else
+               ABORT("unsupported arm64 register");
+}
+
+inline const char* Registers_arm64::getRegisterName(int regNum)
+{
+       switch (regNum) {
+               case UNW_REG_IP:
+                       return "pc";
+               case UNW_REG_SP:
+                       return "sp";
+               case UNW_ARM64_X0:
+                       return "x0";
+               case UNW_ARM64_X1:
+                       return "x1";
+               case UNW_ARM64_X2:
+                       return "x2";
+               case UNW_ARM64_X3:
+                       return "x3";
+               case UNW_ARM64_X4:
+                       return "x4";
+               case UNW_ARM64_X5:
+                       return "x5";
+               case UNW_ARM64_X6:
+                       return "x6";
+               case UNW_ARM64_X7:
+                       return "x7";
+               case UNW_ARM64_X8:
+                       return "x8";
+               case UNW_ARM64_X9:
+                       return "x9";
+               case UNW_ARM64_X10:
+                       return "x10";
+               case UNW_ARM64_X11:
+                       return "x11";
+               case UNW_ARM64_X12:
+                       return "x12";
+               case UNW_ARM64_X13:
+                       return "x13";
+               case UNW_ARM64_X14:
+                       return "x14";
+               case UNW_ARM64_X15:
+                       return "x15";
+               case UNW_ARM64_X16:
+                       return "x16";
+               case UNW_ARM64_X17:
+                       return "x17";
+               case UNW_ARM64_X18:
+                       return "x18";
+               case UNW_ARM64_X19:
+                       return "x19";
+               case UNW_ARM64_X20:
+                       return "x20";
+               case UNW_ARM64_X21:
+                       return "x21";
+               case UNW_ARM64_X22:
+                       return "x22";
+               case UNW_ARM64_X23:
+                       return "x23";
+               case UNW_ARM64_X24:
+                       return "x24";
+               case UNW_ARM64_X25:
+                       return "x25";
+               case UNW_ARM64_X26:
+                       return "x26";
+               case UNW_ARM64_X27:
+                       return "x27";
+               case UNW_ARM64_X28:
+                       return "x28";
+               case UNW_ARM64_X29:
+                       return "fp";
+               case UNW_ARM64_X30:
+                       return "lr";
+               case UNW_ARM64_X31:
+                       return "sp";
+               case UNW_ARM64_D0:
+                       return "d0";
+               case UNW_ARM64_D1:
+                       return "d1";
+               case UNW_ARM64_D2:
+                       return "d2";
+               case UNW_ARM64_D3:
+                       return "d3";
+               case UNW_ARM64_D4:
+                       return "d4";
+               case UNW_ARM64_D5:
+                       return "d5";
+               case UNW_ARM64_D6:
+                       return "d6";
+               case UNW_ARM64_D7:
+                       return "d7";
+               case UNW_ARM64_D8:
+                       return "d8";
+               case UNW_ARM64_D9:
+                       return "d9";
+               case UNW_ARM64_D10:
+                       return "d10";
+               case UNW_ARM64_D11:
+                       return "d11";
+               case UNW_ARM64_D12:
+                       return "d12";
+               case UNW_ARM64_D13:
+                       return "d13";
+               case UNW_ARM64_D14:
+                       return "d14";
+               case UNW_ARM64_D15:
+                       return "d15";
+               case UNW_ARM64_D16:
+                       return "d16";
+               case UNW_ARM64_D17:
+                       return "d17";
+               case UNW_ARM64_D18:
+                       return "d18";
+               case UNW_ARM64_D19:
+                       return "d19";
+               case UNW_ARM64_D20:
+                       return "d20";
+               case UNW_ARM64_D21:
+                       return "d21";
+               case UNW_ARM64_D22:
+                       return "d22";
+               case UNW_ARM64_D23:
+                       return "d23";
+               case UNW_ARM64_D24:
+                       return "d24";
+               case UNW_ARM64_D25:
+                       return "d25";
+               case UNW_ARM64_D26:
+                       return "d26";
+               case UNW_ARM64_D27:
+                       return "d27";
+               case UNW_ARM64_D28:
+                       return "d28";
+               case UNW_ARM64_D29:
+                       return "d29";
+               case UNW_ARM64_D30:
+                       return "d30";
+               case UNW_ARM64_D31:
+                       return "d31";
+               default:
+                       return "unknown register";
+       }
+}
+
+bool Registers_arm64::validFloatRegister(int regNum) const
+{
+       if ( regNum < UNW_ARM64_D0 )
+               return false;
+       if ( regNum > UNW_ARM64_D31 )
+               return false;
+       return true;
+}
+
+
+double Registers_arm64::getFloatRegister(int regNum) const
+{
+       assert(validFloatRegister(regNum));
+       return fHalfVectorRegisters[regNum-UNW_ARM64_D0];
+}
+
+void Registers_arm64::setFloatRegister(int regNum, double value)
+{
+       assert(validFloatRegister(regNum));
+       fHalfVectorRegisters[regNum-UNW_ARM64_D0] = value;
+}
+
+inline bool Registers_arm64::validVectorRegister(int regNum) const
+{
+       return false;
+}
+
+inline v128 Registers_arm64::getVectorRegister(int regNum) const
+{
+       ABORT("no arm64 vector register support yet");
+}
+
+inline void Registers_arm64::setVectorRegister(int regNum, v128 value)
+{
+       ABORT("no arm64 vector register support yet");
+}
+
+
+///
+/// Registers_arm holds the register state of a thread in a 32-bit arm process.  
+///
+class Registers_arm {
+public:
+                Registers_arm();
+
+    bool        validRegister(int num) const;
+    uint32_t    getRegister(int num) const;
+    void        setRegister(int num, uint32_t value);
+    bool        validFloatRegister(int num) const;
+    unw_fpreg_t getFloatRegister(int num) const;
+    void        setFloatRegister(int num, unw_fpreg_t value);
+    bool        validVectorRegister(int num) const;
+    v128        getVectorRegister(int num) const;
+    void        setVectorRegister(int num, v128 value);
+    const char *getRegisterName(int num);
+    void        jumpto();
+
+    uint32_t    getSP() const         { return _registers[13]; }
+    void        setSP(uint32_t value) { _registers[13] = value; }
+    uint32_t    getIP() const         { return _registers[15]; }
+    void        setIP(uint32_t value) { _registers[15] = value; }
+
+private:
+  uint32_t    _registers[16];
+};
 
+inline Registers_arm::Registers_arm() {
+  bzero(&_registers, sizeof(_registers));
 }