package regnum import "fmt" // The mapping between hardware registers and DWARF registers is specified // in the 64-Bit ELF V2 ABI Specification of the Power Architecture in section // 2.4 DWARF Definition // https://openpowerfoundation.org/specifications/64bitelfabi/ const ( // General Purpose Registers: from R0 to R31 PPC64LE_FIRST_GPR = 0 PPC64LE_R0 = PPC64LE_FIRST_GPR PPC64LE_LAST_GPR = 31 // Floating point registers: from F0 to F31 PPC64LE_FIRST_FPR = 32 PPC64LE_F0 = PPC64LE_FIRST_FPR PPC64LE_LAST_FPR = 63 // Vector (Altivec/VMX) registers: from V0 to V31 PPC64LE_FIRST_VMX = 64 PPC64LE_V0 = PPC64LE_FIRST_VMX PPC64LE_LAST_VMX = 95 // Vector Scalar (VSX) registers: from VS0 to VS63 PPC64LE_FIRST_VSX = 96 PPC64LE_VS0 = PPC64LE_FIRST_VSX PPC64LE_LAST_VSX = 160 // Condition Registers: from CR0 to CR7 PPC64LE_CR0 = 0 // Special registers PPC64LE_SP = 1 // Stack frame pointer: Gpr[1] PPC64LE_PC = 12 // The documentation refers to this as the CIA (Current Instruction Address) PPC64LE_LR = 65 // Link register ) func PPC64LEToName(num uint64) string { switch { case num == PPC64LE_SP: return "SP" case num == PPC64LE_PC: return "PC" case num == PPC64LE_LR: return "LR" case isGPR(num): return fmt.Sprintf("r%d", int(num-PPC64LE_FIRST_GPR)) case isFPR(num): return fmt.Sprintf("f%d", int(num-PPC64LE_FIRST_FPR)) case isVMX(num): return fmt.Sprintf("v%d", int(num-PPC64LE_FIRST_VMX)) case isVSX(num): return fmt.Sprintf("vs%d", int(num-PPC64LE_FIRST_VSX)) default: return fmt.Sprintf("unknown%d", num) } } // PPC64LEMaxRegNum is 172 registers in total, across 4 categories: // General Purpose Registers or GPR (32 GPR + 9 special registers) // Floating Point Registers or FPR (32 FPR + 1 special register) // Altivec/VMX Registers or VMX (32 VMX + 2 special registers) // VSX Registers or VSX (64 VSX) // Documentation: https://lldb.llvm.org/cpp_reference/RegisterContextPOSIX__ppc64le_8cpp_source.html func PPC64LEMaxRegNum() uint64 { return 172 } func isGPR(num uint64) bool { return num < PPC64LE_LAST_GPR } func isFPR(num uint64) bool { return num >= PPC64LE_FIRST_FPR && num <= PPC64LE_LAST_FPR } func isVMX(num uint64) bool { return num >= PPC64LE_FIRST_VMX && num <= PPC64LE_LAST_VMX } func isVSX(num uint64) bool { return num >= PPC64LE_FIRST_VSX && num <= PPC64LE_LAST_VSX } var PPC64LENameToDwarf = func() map[string]int { r := make(map[string]int) r["nip"] = PPC64LE_PC r["sp"] = PPC64LE_SP r["bp"] = PPC64LE_SP r["link"] = PPC64LE_LR // General Purpose Registers: from R0 to R31 for i := 0; i <= 31; i++ { r[fmt.Sprintf("r%d", i)] = PPC64LE_R0 + i } // Floating point registers: from F0 to F31 for i := 0; i <= 31; i++ { r[fmt.Sprintf("f%d", i)] = PPC64LE_F0 + i } // Vector (Altivec/VMX) registers: from V0 to V31 for i := 0; i <= 31; i++ { r[fmt.Sprintf("v%d", i)] = PPC64LE_V0 + i } // Vector Scalar (VSX) registers: from VS0 to VS63 for i := 0; i <= 63; i++ { r[fmt.Sprintf("vs%d", i)] = PPC64LE_VS0 + i } // Condition Registers: from CR0 to CR7 for i := 0; i <= 7; i++ { r[fmt.Sprintf("cr%d", i)] = PPC64LE_CR0 + i } return r }()