1//===-- RegisterContextPOSIXProcessMonitor_mips64.h ------------*- 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#include "lldb/Target/Thread.h"
11#include "lldb/Core/RegisterValue.h"
12
13#include "RegisterContextPOSIX_mips64.h"
14#include "ProcessPOSIX.h"
15#include "RegisterContextPOSIXProcessMonitor_mips64.h"
16#include "ProcessMonitor.h"
17
18using namespace lldb_private;
19using namespace lldb;
20
21#define REG_CONTEXT_SIZE (GetGPRSize())
22
23RegisterContextPOSIXProcessMonitor_mips64::RegisterContextPOSIXProcessMonitor_mips64(Thread &thread,
24                                                                                     uint32_t concrete_frame_idx,
25                                                                                     RegisterInfoInterface *register_info)
26    : RegisterContextPOSIX_mips64(thread, concrete_frame_idx, register_info)
27{
28}
29
30ProcessMonitor &
31RegisterContextPOSIXProcessMonitor_mips64::GetMonitor()
32{
33    ProcessSP base = CalculateProcess();
34    ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
35    return process->GetMonitor();
36}
37
38bool
39RegisterContextPOSIXProcessMonitor_mips64::ReadGPR()
40{
41     ProcessMonitor &monitor = GetMonitor();
42     return monitor.ReadGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize());
43}
44
45bool
46RegisterContextPOSIXProcessMonitor_mips64::ReadFPR()
47{
48    // XXX not yet implemented
49    return false;
50}
51
52bool
53RegisterContextPOSIXProcessMonitor_mips64::WriteGPR()
54{
55    ProcessMonitor &monitor = GetMonitor();
56    return monitor.WriteGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize());
57}
58
59bool
60RegisterContextPOSIXProcessMonitor_mips64::WriteFPR()
61{
62    // XXX not yet implemented
63    return false;
64}
65
66bool
67RegisterContextPOSIXProcessMonitor_mips64::ReadRegister(const unsigned reg,
68                                                        RegisterValue &value)
69{
70    ProcessMonitor &monitor = GetMonitor();
71    return monitor.ReadRegisterValue(m_thread.GetID(),
72                                     GetRegisterOffset(reg),
73                                     GetRegisterName(reg),
74                                     GetRegisterSize(reg),
75                                     value);
76}
77
78bool
79RegisterContextPOSIXProcessMonitor_mips64::WriteRegister(const unsigned reg,
80                                                         const RegisterValue &value)
81{
82    unsigned reg_to_write = reg;
83    RegisterValue value_to_write = value;
84
85    // Check if this is a subregister of a full register.
86    const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
87    if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
88    {
89        RegisterValue full_value;
90        uint32_t full_reg = reg_info->invalidate_regs[0];
91        const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
92
93        // Read the full register.
94        if (ReadRegister(full_reg_info, full_value))
95        {
96            Error error;
97            ByteOrder byte_order = GetByteOrder();
98            uint8_t dst[RegisterValue::kMaxRegisterByteSize];
99
100            // Get the bytes for the full register.
101            const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info,
102                                                                   dst,
103                                                                   sizeof(dst),
104                                                                   byte_order,
105                                                                   error);
106            if (error.Success() && dest_size)
107            {
108                uint8_t src[RegisterValue::kMaxRegisterByteSize];
109
110                // Get the bytes for the source data.
111                const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error);
112                if (error.Success() && src_size && (src_size < dest_size))
113                {
114                    // Copy the src bytes to the destination.
115                    memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
116                    // Set this full register as the value to write.
117                    value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
118                    value_to_write.SetType(full_reg_info);
119                    reg_to_write = full_reg;
120                }
121            }
122        }
123    }
124
125    ProcessMonitor &monitor = GetMonitor();
126    return monitor.WriteRegisterValue(m_thread.GetID(),
127                                      GetRegisterOffset(reg_to_write),
128                                      GetRegisterName(reg_to_write),
129                                      value_to_write);
130}
131
132bool
133RegisterContextPOSIXProcessMonitor_mips64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
134{
135    if (!reg_info)
136        return false;
137
138    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
139
140    if (IsFPR(reg))
141    {
142        if (!ReadFPR())
143            return false;
144    }
145    else
146    {
147        uint32_t full_reg = reg;
148        bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
149
150        if (is_subreg)
151        {
152            // Read the full aligned 64-bit register.
153            full_reg = reg_info->invalidate_regs[0];
154        }
155
156        bool success = ReadRegister(full_reg, value);
157
158        if (success)
159        {
160            // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right.
161            if (is_subreg && (reg_info->byte_offset & 0x1))
162                value.SetUInt64(value.GetAsUInt64() >> 8);
163
164            // If our return byte size was greater than the return value reg size, then
165            // use the type specified by reg_info rather than the uint64_t default
166            if (value.GetByteSize() > reg_info->byte_size)
167                value.SetType(reg_info);
168        }
169        return success;
170    }
171
172    return false;
173}
174
175bool
176RegisterContextPOSIXProcessMonitor_mips64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
177{
178    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
179
180    if (IsGPR(reg))
181        return WriteRegister(reg, value);
182
183    return false;
184}
185
186bool
187RegisterContextPOSIXProcessMonitor_mips64::ReadAllRegisterValues(DataBufferSP &data_sp)
188{
189    bool success = false;
190    data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
191    if (data_sp && ReadGPR () && ReadFPR ())
192    {
193        uint8_t *dst = data_sp->GetBytes();
194        success = dst != 0;
195
196        if (success)
197        {
198            ::memcpy (dst, &m_gpr_mips64, GetGPRSize());
199            dst += GetGPRSize();
200        }
201    }
202    return success;
203}
204
205bool
206RegisterContextPOSIXProcessMonitor_mips64::WriteAllRegisterValues(const DataBufferSP &data_sp)
207{
208    bool success = false;
209    if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
210    {
211        uint8_t *src = data_sp->GetBytes();
212        if (src)
213        {
214            ::memcpy (&m_gpr_mips64, src, GetGPRSize());
215
216            if (WriteGPR())
217            {
218                src += GetGPRSize();
219            }
220        }
221    }
222    return success;
223}
224
225uint32_t
226RegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpoint(addr_t addr, size_t size,
227                                              bool read, bool write)
228{
229    const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
230    uint32_t hw_index;
231
232    for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index)
233    {
234        if (IsWatchpointVacant(hw_index))
235            return SetHardwareWatchpointWithIndex(addr, size,
236                                                  read, write,
237                                                  hw_index);
238    }
239
240    return LLDB_INVALID_INDEX32;
241}
242
243bool
244RegisterContextPOSIXProcessMonitor_mips64::ClearHardwareWatchpoint(uint32_t hw_index)
245{
246    return false;
247}
248
249bool
250RegisterContextPOSIXProcessMonitor_mips64::HardwareSingleStep(bool enable)
251{
252    return false;
253}
254
255bool
256RegisterContextPOSIXProcessMonitor_mips64::UpdateAfterBreakpoint()
257{
258    // PC points one byte past the int3 responsible for the breakpoint.
259    lldb::addr_t pc;
260
261    if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
262        return false;
263
264    SetPC(pc - 1);
265    return true;
266}
267
268unsigned
269RegisterContextPOSIXProcessMonitor_mips64::GetRegisterIndexFromOffset(unsigned offset)
270{
271    unsigned reg;
272    for (reg = 0; reg < k_num_registers_mips64; reg++)
273    {
274        if (GetRegisterInfo()[reg].byte_offset == offset)
275            break;
276    }
277    assert(reg < k_num_registers_mips64 && "Invalid register offset.");
278    return reg;
279}
280
281bool
282RegisterContextPOSIXProcessMonitor_mips64::IsWatchpointHit(uint32_t hw_index)
283{
284    return false;
285}
286
287bool
288RegisterContextPOSIXProcessMonitor_mips64::ClearWatchpointHits()
289{
290    return false;
291}
292
293addr_t
294RegisterContextPOSIXProcessMonitor_mips64::GetWatchpointAddress(uint32_t hw_index)
295{
296    return LLDB_INVALID_ADDRESS;
297}
298
299bool
300RegisterContextPOSIXProcessMonitor_mips64::IsWatchpointVacant(uint32_t hw_index)
301{
302    return false;
303}
304
305bool
306RegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpointWithIndex(addr_t addr, size_t size,
307                                                       bool read, bool write,
308                                                       uint32_t hw_index)
309{
310    return false;
311}
312
313uint32_t
314RegisterContextPOSIXProcessMonitor_mips64::NumSupportedHardwareWatchpoints()
315{
316    return 0;
317}
318
319