1257752Semaste//===-- RegisterContextPOSIXProcessMonitor_mips64.h ------------*- C++ -*-===//
2257752Semaste//
3257752Semaste//                     The LLVM Compiler Infrastructure
4257752Semaste//
5257752Semaste// This file is distributed under the University of Illinois Open Source
6257752Semaste// License. See LICENSE.TXT for details.
7257752Semaste//
8257752Semaste//===---------------------------------------------------------------------===//
9257752Semaste
10257752Semaste#include "lldb/Target/Thread.h"
11257752Semaste#include "lldb/Core/RegisterValue.h"
12257752Semaste
13257752Semaste#include "RegisterContextPOSIX_mips64.h"
14257752Semaste#include "ProcessPOSIX.h"
15257752Semaste#include "RegisterContextPOSIXProcessMonitor_mips64.h"
16257752Semaste#include "ProcessMonitor.h"
17257752Semaste
18257752Semasteusing namespace lldb_private;
19257752Semasteusing namespace lldb;
20257752Semaste
21257752Semaste#define REG_CONTEXT_SIZE (GetGPRSize())
22257752Semaste
23257752SemasteRegisterContextPOSIXProcessMonitor_mips64::RegisterContextPOSIXProcessMonitor_mips64(Thread &thread,
24257752Semaste                                                                                     uint32_t concrete_frame_idx,
25257752Semaste                                                                                     RegisterInfoInterface *register_info)
26257752Semaste    : RegisterContextPOSIX_mips64(thread, concrete_frame_idx, register_info)
27257752Semaste{
28257752Semaste}
29257752Semaste
30257752SemasteProcessMonitor &
31257752SemasteRegisterContextPOSIXProcessMonitor_mips64::GetMonitor()
32257752Semaste{
33257752Semaste    ProcessSP base = CalculateProcess();
34257752Semaste    ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
35257752Semaste    return process->GetMonitor();
36257752Semaste}
37257752Semaste
38257752Semastebool
39257752SemasteRegisterContextPOSIXProcessMonitor_mips64::ReadGPR()
40257752Semaste{
41257752Semaste     ProcessMonitor &monitor = GetMonitor();
42257752Semaste     return monitor.ReadGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize());
43257752Semaste}
44257752Semaste
45257752Semastebool
46257752SemasteRegisterContextPOSIXProcessMonitor_mips64::ReadFPR()
47257752Semaste{
48257752Semaste    // XXX not yet implemented
49257752Semaste    return false;
50257752Semaste}
51257752Semaste
52257752Semastebool
53257752SemasteRegisterContextPOSIXProcessMonitor_mips64::WriteGPR()
54257752Semaste{
55257752Semaste    ProcessMonitor &monitor = GetMonitor();
56257752Semaste    return monitor.WriteGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize());
57257752Semaste}
58257752Semaste
59257752Semastebool
60257752SemasteRegisterContextPOSIXProcessMonitor_mips64::WriteFPR()
61257752Semaste{
62257752Semaste    // XXX not yet implemented
63257752Semaste    return false;
64257752Semaste}
65257752Semaste
66257752Semastebool
67257752SemasteRegisterContextPOSIXProcessMonitor_mips64::ReadRegister(const unsigned reg,
68257752Semaste                                                        RegisterValue &value)
69257752Semaste{
70257752Semaste    ProcessMonitor &monitor = GetMonitor();
71257752Semaste    return monitor.ReadRegisterValue(m_thread.GetID(),
72257752Semaste                                     GetRegisterOffset(reg),
73257752Semaste                                     GetRegisterName(reg),
74257752Semaste                                     GetRegisterSize(reg),
75257752Semaste                                     value);
76257752Semaste}
77257752Semaste
78257752Semastebool
79257752SemasteRegisterContextPOSIXProcessMonitor_mips64::WriteRegister(const unsigned reg,
80257752Semaste                                                         const RegisterValue &value)
81257752Semaste{
82257752Semaste    unsigned reg_to_write = reg;
83257752Semaste    RegisterValue value_to_write = value;
84257752Semaste
85257752Semaste    // Check if this is a subregister of a full register.
86257752Semaste    const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
87257752Semaste    if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
88257752Semaste    {
89257752Semaste        RegisterValue full_value;
90257752Semaste        uint32_t full_reg = reg_info->invalidate_regs[0];
91257752Semaste        const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
92257752Semaste
93257752Semaste        // Read the full register.
94257752Semaste        if (ReadRegister(full_reg_info, full_value))
95257752Semaste        {
96257752Semaste            Error error;
97257752Semaste            ByteOrder byte_order = GetByteOrder();
98257752Semaste            uint8_t dst[RegisterValue::kMaxRegisterByteSize];
99257752Semaste
100257752Semaste            // Get the bytes for the full register.
101257752Semaste            const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info,
102257752Semaste                                                                   dst,
103257752Semaste                                                                   sizeof(dst),
104257752Semaste                                                                   byte_order,
105257752Semaste                                                                   error);
106257752Semaste            if (error.Success() && dest_size)
107257752Semaste            {
108257752Semaste                uint8_t src[RegisterValue::kMaxRegisterByteSize];
109257752Semaste
110257752Semaste                // Get the bytes for the source data.
111257752Semaste                const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error);
112257752Semaste                if (error.Success() && src_size && (src_size < dest_size))
113257752Semaste                {
114257752Semaste                    // Copy the src bytes to the destination.
115257752Semaste                    memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
116257752Semaste                    // Set this full register as the value to write.
117257752Semaste                    value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
118257752Semaste                    value_to_write.SetType(full_reg_info);
119257752Semaste                    reg_to_write = full_reg;
120257752Semaste                }
121257752Semaste            }
122257752Semaste        }
123257752Semaste    }
124257752Semaste
125257752Semaste    ProcessMonitor &monitor = GetMonitor();
126257752Semaste    return monitor.WriteRegisterValue(m_thread.GetID(),
127257752Semaste                                      GetRegisterOffset(reg_to_write),
128257752Semaste                                      GetRegisterName(reg_to_write),
129257752Semaste                                      value_to_write);
130257752Semaste}
131257752Semaste
132257752Semastebool
133257752SemasteRegisterContextPOSIXProcessMonitor_mips64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
134257752Semaste{
135257752Semaste    if (!reg_info)
136257752Semaste        return false;
137257752Semaste
138257752Semaste    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
139257752Semaste
140257752Semaste    if (IsFPR(reg))
141257752Semaste    {
142257752Semaste        if (!ReadFPR())
143257752Semaste            return false;
144257752Semaste    }
145257752Semaste    else
146257752Semaste    {
147257752Semaste        uint32_t full_reg = reg;
148257752Semaste        bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
149257752Semaste
150257752Semaste        if (is_subreg)
151257752Semaste        {
152257752Semaste            // Read the full aligned 64-bit register.
153257752Semaste            full_reg = reg_info->invalidate_regs[0];
154257752Semaste        }
155257752Semaste
156257752Semaste        bool success = ReadRegister(full_reg, value);
157257752Semaste
158257752Semaste        if (success)
159257752Semaste        {
160257752Semaste            // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right.
161257752Semaste            if (is_subreg && (reg_info->byte_offset & 0x1))
162257752Semaste                value.SetUInt64(value.GetAsUInt64() >> 8);
163257752Semaste
164257752Semaste            // If our return byte size was greater than the return value reg size, then
165257752Semaste            // use the type specified by reg_info rather than the uint64_t default
166257752Semaste            if (value.GetByteSize() > reg_info->byte_size)
167257752Semaste                value.SetType(reg_info);
168257752Semaste        }
169257752Semaste        return success;
170257752Semaste    }
171257752Semaste
172257752Semaste    return false;
173257752Semaste}
174257752Semaste
175257752Semastebool
176257752SemasteRegisterContextPOSIXProcessMonitor_mips64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
177257752Semaste{
178257752Semaste    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
179257752Semaste
180257752Semaste    if (IsGPR(reg))
181257752Semaste        return WriteRegister(reg, value);
182257752Semaste
183257752Semaste    return false;
184257752Semaste}
185257752Semaste
186257752Semastebool
187257752SemasteRegisterContextPOSIXProcessMonitor_mips64::ReadAllRegisterValues(DataBufferSP &data_sp)
188257752Semaste{
189257752Semaste    bool success = false;
190257752Semaste    data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
191257752Semaste    if (data_sp && ReadGPR () && ReadFPR ())
192257752Semaste    {
193257752Semaste        uint8_t *dst = data_sp->GetBytes();
194257752Semaste        success = dst != 0;
195257752Semaste
196257752Semaste        if (success)
197257752Semaste        {
198257752Semaste            ::memcpy (dst, &m_gpr_mips64, GetGPRSize());
199257752Semaste            dst += GetGPRSize();
200257752Semaste        }
201257752Semaste    }
202257752Semaste    return success;
203257752Semaste}
204257752Semaste
205257752Semastebool
206257752SemasteRegisterContextPOSIXProcessMonitor_mips64::WriteAllRegisterValues(const DataBufferSP &data_sp)
207257752Semaste{
208257752Semaste    bool success = false;
209257752Semaste    if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
210257752Semaste    {
211257752Semaste        uint8_t *src = data_sp->GetBytes();
212257752Semaste        if (src)
213257752Semaste        {
214257752Semaste            ::memcpy (&m_gpr_mips64, src, GetGPRSize());
215257752Semaste
216257752Semaste            if (WriteGPR())
217257752Semaste            {
218257752Semaste                src += GetGPRSize();
219257752Semaste            }
220257752Semaste        }
221257752Semaste    }
222257752Semaste    return success;
223257752Semaste}
224257752Semaste
225257752Semasteuint32_t
226257752SemasteRegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpoint(addr_t addr, size_t size,
227257752Semaste                                              bool read, bool write)
228257752Semaste{
229257752Semaste    const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
230257752Semaste    uint32_t hw_index;
231257752Semaste
232257752Semaste    for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index)
233257752Semaste    {
234257752Semaste        if (IsWatchpointVacant(hw_index))
235257752Semaste            return SetHardwareWatchpointWithIndex(addr, size,
236257752Semaste                                                  read, write,
237257752Semaste                                                  hw_index);
238257752Semaste    }
239257752Semaste
240257752Semaste    return LLDB_INVALID_INDEX32;
241257752Semaste}
242257752Semaste
243257752Semastebool
244257752SemasteRegisterContextPOSIXProcessMonitor_mips64::ClearHardwareWatchpoint(uint32_t hw_index)
245257752Semaste{
246257752Semaste    return false;
247257752Semaste}
248257752Semaste
249257752Semastebool
250257752SemasteRegisterContextPOSIXProcessMonitor_mips64::HardwareSingleStep(bool enable)
251257752Semaste{
252257752Semaste    return false;
253257752Semaste}
254257752Semaste
255257752Semastebool
256257752SemasteRegisterContextPOSIXProcessMonitor_mips64::UpdateAfterBreakpoint()
257257752Semaste{
258257752Semaste    // PC points one byte past the int3 responsible for the breakpoint.
259257752Semaste    lldb::addr_t pc;
260257752Semaste
261257752Semaste    if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
262257752Semaste        return false;
263257752Semaste
264257752Semaste    SetPC(pc - 1);
265257752Semaste    return true;
266257752Semaste}
267257752Semaste
268257752Semasteunsigned
269257752SemasteRegisterContextPOSIXProcessMonitor_mips64::GetRegisterIndexFromOffset(unsigned offset)
270257752Semaste{
271257752Semaste    unsigned reg;
272257752Semaste    for (reg = 0; reg < k_num_registers_mips64; reg++)
273257752Semaste    {
274257752Semaste        if (GetRegisterInfo()[reg].byte_offset == offset)
275257752Semaste            break;
276257752Semaste    }
277257752Semaste    assert(reg < k_num_registers_mips64 && "Invalid register offset.");
278257752Semaste    return reg;
279257752Semaste}
280257752Semaste
281257752Semastebool
282257752SemasteRegisterContextPOSIXProcessMonitor_mips64::IsWatchpointHit(uint32_t hw_index)
283257752Semaste{
284257752Semaste    return false;
285257752Semaste}
286257752Semaste
287257752Semastebool
288257752SemasteRegisterContextPOSIXProcessMonitor_mips64::ClearWatchpointHits()
289257752Semaste{
290257752Semaste    return false;
291257752Semaste}
292257752Semaste
293257752Semasteaddr_t
294257752SemasteRegisterContextPOSIXProcessMonitor_mips64::GetWatchpointAddress(uint32_t hw_index)
295257752Semaste{
296257752Semaste    return LLDB_INVALID_ADDRESS;
297257752Semaste}
298257752Semaste
299257752Semastebool
300257752SemasteRegisterContextPOSIXProcessMonitor_mips64::IsWatchpointVacant(uint32_t hw_index)
301257752Semaste{
302257752Semaste    return false;
303257752Semaste}
304257752Semaste
305257752Semastebool
306257752SemasteRegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpointWithIndex(addr_t addr, size_t size,
307257752Semaste                                                       bool read, bool write,
308257752Semaste                                                       uint32_t hw_index)
309257752Semaste{
310257752Semaste    return false;
311257752Semaste}
312257752Semaste
313257752Semasteuint32_t
314257752SemasteRegisterContextPOSIXProcessMonitor_mips64::NumSupportedHardwareWatchpoints()
315257752Semaste{
316257752Semaste    return 0;
317257752Semaste}
318257752Semaste
319