| //===-- ABISysV_hexagon.cpp -------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "ABISysV_hexagon.h" |
| |
| // C Includes |
| // C++ Includes |
| // Other libraries and framework includes |
| #include "llvm/ADT/Triple.h" |
| #include "llvm/IR/DerivedTypes.h" |
| |
| // Project includes |
| #include "lldb/Core/Module.h" |
| #include "lldb/Core/PluginManager.h" |
| #include "lldb/Core/RegisterValue.h" |
| #include "lldb/Core/Value.h" |
| #include "lldb/Core/ValueObjectConstResult.h" |
| #include "lldb/Core/ValueObjectMemory.h" |
| #include "lldb/Core/ValueObjectRegister.h" |
| #include "lldb/Symbol/UnwindPlan.h" |
| #include "lldb/Target/Process.h" |
| #include "lldb/Target/RegisterContext.h" |
| #include "lldb/Target/StackFrame.h" |
| #include "lldb/Target/Target.h" |
| #include "lldb/Target/Thread.h" |
| #include "lldb/Utility/ConstString.h" |
| #include "lldb/Utility/DataExtractor.h" |
| #include "lldb/Utility/Log.h" |
| #include "lldb/Utility/Status.h" |
| |
| using namespace lldb; |
| using namespace lldb_private; |
| |
| static RegisterInfo g_register_infos[] = { |
| // hexagon-core.xml |
| {"r00", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {0, 0, LLDB_INVALID_REGNUM, 0, 0}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r01", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {1, 1, LLDB_INVALID_REGNUM, 1, 1}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r02", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {2, 2, LLDB_INVALID_REGNUM, 2, 2}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r03", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {3, 3, LLDB_INVALID_REGNUM, 3, 3}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r04", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {4, 4, LLDB_INVALID_REGNUM, 4, 4}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r05", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {5, 5, LLDB_INVALID_REGNUM, 5, 5}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r06", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {6, 6, LLDB_INVALID_REGNUM, 6, 6}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r07", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {7, 7, LLDB_INVALID_REGNUM, 7, 7}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r08", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {8, 8, LLDB_INVALID_REGNUM, 8, 8}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r09", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {9, 9, LLDB_INVALID_REGNUM, 9, 9}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r10", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {10, 10, LLDB_INVALID_REGNUM, 10, 10}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r11", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {11, 11, LLDB_INVALID_REGNUM, 11, 11}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r12", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {12, 12, LLDB_INVALID_REGNUM, 12, 12}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r13", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {13, 13, LLDB_INVALID_REGNUM, 13, 13}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r14", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {14, 14, LLDB_INVALID_REGNUM, 14, 14}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r15", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {15, 15, LLDB_INVALID_REGNUM, 15, 15}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r16", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {16, 16, LLDB_INVALID_REGNUM, 16, 16}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r17", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {17, 17, LLDB_INVALID_REGNUM, 17, 17}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r18", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {18, 18, LLDB_INVALID_REGNUM, 18, 18}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r19", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {19, 19, LLDB_INVALID_REGNUM, 19, 19}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r20", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {20, 20, LLDB_INVALID_REGNUM, 20, 20}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r21", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {21, 21, LLDB_INVALID_REGNUM, 21, 21}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r22", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {22, 22, LLDB_INVALID_REGNUM, 22, 22}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r23", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {23, 23, LLDB_INVALID_REGNUM, 23, 23}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r24", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {24, 24, LLDB_INVALID_REGNUM, 24, 24}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r25", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {25, 25, LLDB_INVALID_REGNUM, 25, 25}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r26", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {26, 26, LLDB_INVALID_REGNUM, 26, 26}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r27", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {27, 27, LLDB_INVALID_REGNUM, 27, 27}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"r28", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {28, 28, LLDB_INVALID_REGNUM, 28, 28}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"sp", |
| "r29", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {29, 29, LLDB_REGNUM_GENERIC_SP, 29, 29}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"fp", |
| "r30", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {30, 30, LLDB_REGNUM_GENERIC_FP, 30, 30}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"lr", |
| "r31", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {31, 31, LLDB_REGNUM_GENERIC_RA, 31, 31}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"sa0", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {32, 32, LLDB_INVALID_REGNUM, 32, 32}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"lc0", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {33, 33, LLDB_INVALID_REGNUM, 33, 33}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"sa1", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {34, 34, LLDB_INVALID_REGNUM, 34, 34}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"lc1", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {35, 35, LLDB_INVALID_REGNUM, 35, 35}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| // --> hexagon-v4/5/55/56-sim.xml |
| {"p3_0", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {36, 36, LLDB_INVALID_REGNUM, 36, 36}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| // PADDING { |
| {"p00", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {37, 37, LLDB_INVALID_REGNUM, 37, 37}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| // } |
| {"m0", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {38, 38, LLDB_INVALID_REGNUM, 38, 38}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"m1", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {39, 39, LLDB_INVALID_REGNUM, 39, 39}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"usr", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {40, 40, LLDB_INVALID_REGNUM, 40, 40}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"pc", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {41, 41, LLDB_REGNUM_GENERIC_PC, 41, 41}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"ugp", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {42, 42, LLDB_INVALID_REGNUM, 42, 42}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"gp", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {43, 43, LLDB_INVALID_REGNUM, 43, 43}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"cs0", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {44, 44, LLDB_INVALID_REGNUM, 44, 44}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"cs1", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {45, 45, LLDB_INVALID_REGNUM, 45, 45}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| // PADDING { |
| {"p01", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {46, 46, LLDB_INVALID_REGNUM, 46, 46}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p02", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {47, 47, LLDB_INVALID_REGNUM, 47, 47}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p03", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {48, 48, LLDB_INVALID_REGNUM, 48, 48}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p04", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {49, 49, LLDB_INVALID_REGNUM, 49, 49}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p05", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {50, 50, LLDB_INVALID_REGNUM, 50, 50}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p06", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {51, 51, LLDB_INVALID_REGNUM, 51, 51}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p07", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {52, 52, LLDB_INVALID_REGNUM, 52, 52}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p08", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {53, 53, LLDB_INVALID_REGNUM, 53, 53}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p09", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {54, 54, LLDB_INVALID_REGNUM, 54, 54}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p10", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {55, 55, LLDB_INVALID_REGNUM, 55, 55}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p11", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {56, 56, LLDB_INVALID_REGNUM, 56, 56}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p12", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {57, 57, LLDB_INVALID_REGNUM, 57, 57}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p13", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {58, 58, LLDB_INVALID_REGNUM, 58, 58}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p14", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {59, 59, LLDB_INVALID_REGNUM, 59, 59}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p15", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {60, 60, LLDB_INVALID_REGNUM, 60, 60}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p16", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {61, 61, LLDB_INVALID_REGNUM, 61, 61}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p17", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {62, 62, LLDB_INVALID_REGNUM, 62, 62}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p18", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {63, 63, LLDB_INVALID_REGNUM, 63, 63}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| // } |
| {"sgp0", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {64, 64, LLDB_INVALID_REGNUM, 64, 64}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| // PADDING { |
| {"p19", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {65, 65, LLDB_INVALID_REGNUM, 65, 65}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| // } |
| {"stid", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {66, 66, LLDB_INVALID_REGNUM, 66, 66}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"elr", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {67, 67, LLDB_INVALID_REGNUM, 67, 67}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"badva0", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {68, 68, LLDB_INVALID_REGNUM, 68, 68}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"badva1", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {69, 69, LLDB_INVALID_REGNUM, 69, 69}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"ssr", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {70, 70, LLDB_INVALID_REGNUM, 70, 70}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"ccr", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {71, 71, LLDB_INVALID_REGNUM, 71, 71}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"htid", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {72, 72, LLDB_INVALID_REGNUM, 72, 72}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| // PADDING { |
| {"p20", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {73, 73, LLDB_INVALID_REGNUM, 73, 73}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| // } |
| {"imask", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {74, 74, LLDB_INVALID_REGNUM, 74, 74}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| // PADDING { |
| {"p21", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {75, 75, LLDB_INVALID_REGNUM, 75, 75}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p22", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {76, 76, LLDB_INVALID_REGNUM, 76, 76}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p23", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {77, 77, LLDB_INVALID_REGNUM, 77, 77}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p24", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {78, 78, LLDB_INVALID_REGNUM, 78, 78}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"p25", |
| "", |
| 4, |
| 0, |
| eEncodingInvalid, |
| eFormatInvalid, |
| {79, 79, LLDB_INVALID_REGNUM, 79, 79}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| // } |
| {"g0", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {80, 80, LLDB_INVALID_REGNUM, 80, 80}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"g1", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {81, 81, LLDB_INVALID_REGNUM, 81, 81}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"g2", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {82, 82, LLDB_INVALID_REGNUM, 82, 82}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}, |
| {"g3", |
| "", |
| 4, |
| 0, |
| eEncodingUint, |
| eFormatAddressInfo, |
| {83, 83, LLDB_INVALID_REGNUM, 83, 83}, |
| nullptr, |
| nullptr, |
| nullptr, |
| 0}}; |
| |
| static const uint32_t k_num_register_infos = |
| sizeof(g_register_infos) / sizeof(RegisterInfo); |
| static bool g_register_info_names_constified = false; |
| |
| const lldb_private::RegisterInfo * |
| ABISysV_hexagon::GetRegisterInfoArray(uint32_t &count) { |
| // Make the C-string names and alt_names for the register infos into const |
| // C-string values by having the ConstString unique the names in the global |
| // constant C-string pool. |
| if (!g_register_info_names_constified) { |
| g_register_info_names_constified = true; |
| for (uint32_t i = 0; i < k_num_register_infos; ++i) { |
| if (g_register_infos[i].name) |
| g_register_infos[i].name = |
| ConstString(g_register_infos[i].name).GetCString(); |
| if (g_register_infos[i].alt_name) |
| g_register_infos[i].alt_name = |
| ConstString(g_register_infos[i].alt_name).GetCString(); |
| } |
| } |
| count = k_num_register_infos; |
| return g_register_infos; |
| } |
| |
| /* |
| http://en.wikipedia.org/wiki/Red_zone_%28computing%29 |
| |
| In computing, a red zone is a fixed size area in memory beyond the stack |
| pointer that has not been |
| "allocated". This region of memory is not to be modified by |
| interrupt/exception/signal handlers. |
| This allows the space to be used for temporary data without the extra |
| overhead of modifying the |
| stack pointer. The x86-64 ABI mandates a 128 byte red zone.[1] The OpenRISC |
| toolchain assumes a |
| 128 byte red zone though it is not documented. |
| */ |
| size_t ABISysV_hexagon::GetRedZoneSize() const { return 0; } |
| |
| //------------------------------------------------------------------ |
| // Static Functions |
| //------------------------------------------------------------------ |
| |
| ABISP |
| ABISysV_hexagon::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { |
| static ABISP g_abi_sp; |
| if (arch.GetTriple().getArch() == llvm::Triple::hexagon) { |
| if (!g_abi_sp) |
| g_abi_sp.reset(new ABISysV_hexagon(process_sp)); |
| return g_abi_sp; |
| } |
| return ABISP(); |
| } |
| |
| bool ABISysV_hexagon::PrepareTrivialCall(Thread &thread, lldb::addr_t sp, |
| lldb::addr_t pc, lldb::addr_t ra, |
| llvm::ArrayRef<addr_t> args) const { |
| // we don't use the traditional trivial call specialized for jit |
| return false; |
| } |
| |
| /* |
| |
| // AD: |
| // . safeguard the current stack |
| // . how can we know that the called function will create its own frame |
| properly? |
| // . we could manually make a new stack first: |
| // 2. push RA |
| // 3. push FP |
| // 4. FP = SP |
| // 5. SP = SP ( since no locals in our temp frame ) |
| |
| // AD 6/05/2014 |
| // . variable argument list parameters are not passed via registers, they are |
| passed on |
| // the stack. This presents us with a problem, since we need to know when |
| the valist |
| // starts. Currently I can find out if a function is varg, but not how many |
| // real parameters it takes. Thus I don't know when to start spilling the |
| vargs. For |
| // the time being, to progress, I will assume that it takes on real parameter |
| before |
| // the vargs list starts. |
| |
| // AD 06/05/2014 |
| // . how do we adhere to the stack alignment requirements |
| |
| // AD 06/05/2014 |
| // . handle 64bit values and their register / stack requirements |
| |
| */ |
| #define HEX_ABI_DEBUG 0 |
| bool ABISysV_hexagon::PrepareTrivialCall( |
| Thread &thread, lldb::addr_t sp, lldb::addr_t pc, lldb::addr_t ra, |
| llvm::Type &prototype, llvm::ArrayRef<ABI::CallArgument> args) const { |
| // default number of register passed arguments for varg functions |
| const int nVArgRegParams = 1; |
| Status error; |
| |
| // grab the process so we have access to the memory for spilling |
| lldb::ProcessSP proc = thread.GetProcess(); |
| |
| // get the register context for modifying all of the registers |
| RegisterContext *reg_ctx = thread.GetRegisterContext().get(); |
| if (!reg_ctx) |
| return false; |
| |
| uint32_t pc_reg = reg_ctx->ConvertRegisterKindToRegisterNumber( |
| eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); |
| if (pc_reg == LLDB_INVALID_REGNUM) |
| return false; |
| |
| uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber( |
| eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); |
| if (ra_reg == LLDB_INVALID_REGNUM) |
| return false; |
| |
| uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber( |
| eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); |
| if (sp_reg == LLDB_INVALID_REGNUM) |
| return false; |
| |
| // push host data onto target |
| for (size_t i = 0; i < args.size(); i++) { |
| const ABI::CallArgument &arg = args[i]; |
| // skip over target values |
| if (arg.type == ABI::CallArgument::TargetValue) |
| continue; |
| // round up to 8 byte multiple |
| size_t argSize = (arg.size | 0x7) + 1; |
| |
| // create space on the stack for this data |
| sp -= argSize; |
| |
| // write this argument onto the stack of the host process |
| proc->WriteMemory(sp, arg.data_ap.get(), arg.size, error); |
| if (error.Fail()) |
| return false; |
| |
| // update the argument with the target pointer |
| // XXX: This is a gross hack for getting around the const |
| *const_cast<lldb::addr_t *>(&arg.value) = sp; |
| } |
| |
| #if HEX_ABI_DEBUG |
| // print the original stack pointer |
| printf("sp : %04" PRIx64 " \n", sp); |
| #endif |
| |
| // make sure number of parameters matches prototype |
| assert(prototype.getFunctionNumParams() == args.size()); |
| |
| // check if this is a variable argument function |
| bool isVArg = prototype.isFunctionVarArg(); |
| |
| // number of arguments passed by register |
| int nRegArgs = nVArgRegParams; |
| if (!isVArg) { |
| // number of arguments is limited by [R0 : R5] space |
| nRegArgs = args.size(); |
| if (nRegArgs > 6) |
| nRegArgs = 6; |
| } |
| |
| // pass arguments that are passed via registers |
| for (int i = 0; i < nRegArgs; i++) { |
| // get the parameter as a u32 |
| uint32_t param = (uint32_t)args[i].value; |
| // write argument into register |
| if (!reg_ctx->WriteRegisterFromUnsigned(i, param)) |
| return false; |
| } |
| |
| // number of arguments to spill onto stack |
| int nSpillArgs = args.size() - nRegArgs; |
| // make space on the stack for arguments |
| sp -= 4 * nSpillArgs; |
| // align stack on an 8 byte boundary |
| if (sp & 7) |
| sp -= 4; |
| |
| // arguments that are passed on the stack |
| for (size_t i = nRegArgs, offs = 0; i < args.size(); i++) { |
| // get the parameter as a u32 |
| uint32_t param = (uint32_t)args[i].value; |
| // write argument to stack |
| proc->WriteMemory(sp + offs, (void *)¶m, sizeof(param), error); |
| if (!error.Success()) |
| return false; |
| // |
| offs += 4; |
| } |
| |
| // update registers with current function call state |
| reg_ctx->WriteRegisterFromUnsigned(pc_reg, pc); |
| reg_ctx->WriteRegisterFromUnsigned(ra_reg, ra); |
| reg_ctx->WriteRegisterFromUnsigned(sp_reg, sp); |
| |
| #if HEX_ABI_DEBUG |
| // quick and dirty stack dumper for debugging |
| for (int i = -8; i < 8; i++) { |
| uint32_t data = 0; |
| lldb::addr_t addr = sp + i * 4; |
| proc->ReadMemory(addr, (void *)&data, sizeof(data), error); |
| printf("\n0x%04" PRIx64 " 0x%08x ", addr, data); |
| if (i == 0) |
| printf("<<-- sp"); |
| } |
| printf("\n"); |
| #endif |
| |
| return true; |
| } |
| |
| bool ABISysV_hexagon::GetArgumentValues(Thread &thread, |
| ValueList &values) const { |
| return false; |
| } |
| |
| Status |
| ABISysV_hexagon::SetReturnValueObject(lldb::StackFrameSP &frame_sp, |
| lldb::ValueObjectSP &new_value_sp) { |
| Status error; |
| return error; |
| } |
| |
| ValueObjectSP ABISysV_hexagon::GetReturnValueObjectSimple( |
| Thread &thread, CompilerType &return_compiler_type) const { |
| ValueObjectSP return_valobj_sp; |
| return return_valobj_sp; |
| } |
| |
| ValueObjectSP ABISysV_hexagon::GetReturnValueObjectImpl( |
| Thread &thread, CompilerType &return_compiler_type) const { |
| ValueObjectSP return_valobj_sp; |
| return return_valobj_sp; |
| } |
| |
| // called when we are on the first instruction of a new function for hexagon |
| // the return address is in RA (R31) |
| bool ABISysV_hexagon::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) { |
| unwind_plan.Clear(); |
| unwind_plan.SetRegisterKind(eRegisterKindGeneric); |
| unwind_plan.SetReturnAddressRegister(LLDB_REGNUM_GENERIC_RA); |
| |
| UnwindPlan::RowSP row(new UnwindPlan::Row); |
| |
| // Our Call Frame Address is the stack pointer value |
| row->GetCFAValue().SetIsRegisterPlusOffset(LLDB_REGNUM_GENERIC_SP, 4); |
| row->SetOffset(0); |
| |
| // The previous PC is in the LR |
| row->SetRegisterLocationToRegister(LLDB_REGNUM_GENERIC_PC, |
| LLDB_REGNUM_GENERIC_RA, true); |
| unwind_plan.AppendRow(row); |
| |
| unwind_plan.SetSourceName("hexagon at-func-entry default"); |
| unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); |
| return true; |
| } |
| |
| bool ABISysV_hexagon::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { |
| unwind_plan.Clear(); |
| unwind_plan.SetRegisterKind(eRegisterKindGeneric); |
| |
| uint32_t fp_reg_num = LLDB_REGNUM_GENERIC_FP; |
| uint32_t sp_reg_num = LLDB_REGNUM_GENERIC_SP; |
| uint32_t pc_reg_num = LLDB_REGNUM_GENERIC_PC; |
| |
| UnwindPlan::RowSP row(new UnwindPlan::Row); |
| |
| row->GetCFAValue().SetIsRegisterPlusOffset(LLDB_REGNUM_GENERIC_FP, 8); |
| |
| row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, -8, true); |
| row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, true); |
| row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); |
| |
| unwind_plan.AppendRow(row); |
| unwind_plan.SetSourceName("hexagon default unwind plan"); |
| unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); |
| unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); |
| return true; |
| } |
| |
| /* |
| Register Usage Saved By |
| |
| R0 - R5 parameters(a) - |
| R6 - R15 Scratch(b) Caller |
| R16 - R27 Scratch Callee |
| R28 Scratch(b) Caller |
| R29 - R31 Stack Frames Callee(c) |
| P3:0 Processor State Caller |
| |
| a = the caller can change parameter values |
| b = R14 - R15 and R28 are used by the procedure linkage table |
| c = R29 - R31 are saved and restored by allocframe() and deallocframe() |
| */ |
| bool ABISysV_hexagon::RegisterIsVolatile(const RegisterInfo *reg_info) { |
| return !RegisterIsCalleeSaved(reg_info); |
| } |
| |
| bool ABISysV_hexagon::RegisterIsCalleeSaved(const RegisterInfo *reg_info) { |
| int reg = ((reg_info->byte_offset) / 4); |
| |
| bool save = (reg >= 16) && (reg <= 27); |
| save |= (reg >= 29) && (reg <= 32); |
| |
| return save; |
| } |
| |
| void ABISysV_hexagon::Initialize() { |
| PluginManager::RegisterPlugin(GetPluginNameStatic(), |
| "System V ABI for hexagon targets", |
| CreateInstance); |
| } |
| |
| void ABISysV_hexagon::Terminate() { |
| PluginManager::UnregisterPlugin(CreateInstance); |
| } |
| |
| lldb_private::ConstString ABISysV_hexagon::GetPluginNameStatic() { |
| static ConstString g_name("sysv-hexagon"); |
| return g_name; |
| } |
| |
| //------------------------------------------------------------------ |
| // PluginInterface protocol |
| //------------------------------------------------------------------ |
| |
| lldb_private::ConstString ABISysV_hexagon::GetPluginName() { |
| return GetPluginNameStatic(); |
| } |
| |
| uint32_t ABISysV_hexagon::GetPluginVersion() { return 1; } |
| |
| // get value object specialized to work with llvm IR types |
| lldb::ValueObjectSP |
| ABISysV_hexagon::GetReturnValueObjectImpl(lldb_private::Thread &thread, |
| llvm::Type &retType) const { |
| Value value; |
| ValueObjectSP vObjSP; |
| |
| // get the current register context |
| RegisterContext *reg_ctx = thread.GetRegisterContext().get(); |
| if (!reg_ctx) |
| return vObjSP; |
| |
| // for now just pop R0 to find the return value |
| const lldb_private::RegisterInfo *r0_info = |
| reg_ctx->GetRegisterInfoAtIndex(0); |
| if (r0_info == nullptr) |
| return vObjSP; |
| |
| // void return type |
| if (retType.isVoidTy()) { |
| value.GetScalar() = 0; |
| } |
| // integer / pointer return type |
| else if (retType.isIntegerTy() || retType.isPointerTy()) { |
| // read r0 register value |
| lldb_private::RegisterValue r0_value; |
| if (!reg_ctx->ReadRegister(r0_info, r0_value)) |
| return vObjSP; |
| |
| // push r0 into value |
| uint32_t r0_u32 = r0_value.GetAsUInt32(); |
| |
| // account for integer size |
| if (retType.isIntegerTy() && retType.isSized()) { |
| uint64_t size = retType.getScalarSizeInBits(); |
| uint64_t mask = (1ull << size) - 1; |
| // mask out higher order bits then the type we expect |
| r0_u32 &= mask; |
| } |
| |
| value.GetScalar() = r0_u32; |
| } |
| // unsupported return type |
| else |
| return vObjSP; |
| |
| // pack the value into a ValueObjectSP |
| vObjSP = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(), |
| value, ConstString("")); |
| return vObjSP; |
| } |