1ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Copyright 2013, ARM Limited
2ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// All rights reserved.
3ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
4ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Redistribution and use in source and binary forms, with or without
5ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// modification, are permitted provided that the following conditions are met:
6ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
7ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//   * Redistributions of source code must retain the above copyright notice,
8ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     this list of conditions and the following disclaimer.
9ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//   * Redistributions in binary form must reproduce the above copyright notice,
10ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     this list of conditions and the following disclaimer in the documentation
11ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     and/or other materials provided with the distribution.
12ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//   * Neither the name of ARM Limited nor the names of its contributors may be
13ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     used to endorse or promote products derived from this software without
14ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     specific prior written permission.
15ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
16ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
27ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#ifndef VIXL_A64_DEBUGGER_A64_H_
28ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#define VIXL_A64_DEBUGGER_A64_H_
29ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
30ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#include <ctype.h>
31ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#include <limits.h>
32ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#include <errno.h>
33ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#include <vector>
34ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
35bc4afbd2754e20d14114e4ba83f9035b26ab701dSerban Constantinescu#include "globals-vixl.h"
36bc4afbd2754e20d14114e4ba83f9035b26ab701dSerban Constantinescu#include "utils-vixl.h"
37ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#include "a64/constants-a64.h"
38ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#include "a64/simulator-a64.h"
39ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
40ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlnamespace vixl {
41ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
42ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Debug instructions.
43ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
44ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// VIXL's macro-assembler and debugger support a few pseudo instructions to
45ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// make debugging easier. These pseudo instructions do not exist on real
46ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// hardware.
47ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
48ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Each debug pseudo instruction is represented by a HLT instruction. The HLT
49ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// immediate field is used to identify the type of debug pseudo isntruction.
50ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Each pseudo instruction use a custom encoding for additional arguments, as
51ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// described below.
52ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
53ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Unreachable
54ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
55ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Instruction which should never be executed. This is used as a guard in parts
56ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// of the code that should not be reachable, such as in data encoded inline in
57ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// the instructions.
58ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst Instr kUnreachableOpcode = 0xdeb0;
59ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
60ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Trace
61ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//  - parameter: TraceParameter stored as a uint32_t
62ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//  - command: TraceCommand stored as a uint32_t
63ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
64ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Allow for trace management in the generated code. See the corresponding
65ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// enums for more information on permitted actions.
66ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst Instr kTraceOpcode = 0xdeb2;
67ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst unsigned kTraceParamsOffset = 1 * kInstructionSize;
68ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst unsigned kTraceCommandOffset = 2 * kInstructionSize;
69ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst unsigned kTraceLength = 3 * kInstructionSize;
70ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
71ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Log
72ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//  - parameter: TraceParameter stored as a uint32_t
73ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
74ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Output the requested information.
75ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst Instr kLogOpcode = 0xdeb3;
76ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst unsigned kLogParamsOffset = 1 * kInstructionSize;
77ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst unsigned kLogLength = 2 * kInstructionSize;
78ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
79ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Trace commands.
80ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlenum TraceCommand {
81ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  TRACE_ENABLE   = 1,
82ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  TRACE_DISABLE  = 2
83ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl};
84ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
85ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Trace parameters.
86ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlenum TraceParameters {
87ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LOG_DISASM     = 1 << 0,  // Log disassembly.
88ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LOG_REGS       = 1 << 1,  // Log general purpose registers.
89ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LOG_FP_REGS    = 1 << 2,  // Log floating-point registers.
90578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  LOG_SYS_REGS   = 1 << 3,  // Log the flags and system registers.
91ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
92578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  LOG_STATE      = LOG_REGS | LOG_FP_REGS | LOG_SYS_REGS,
93578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  LOG_ALL        = LOG_DISASM | LOG_REGS | LOG_FP_REGS | LOG_SYS_REGS
94ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl};
95ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
96ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Debugger parameters
97ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlenum DebugParameters {
98ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  DBG_ACTIVE = 1 << 0,  // The debugger is active.
99ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  DBG_BREAK  = 1 << 1   // The debugger is at a breakpoint.
100ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl};
101ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
102ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Forward declarations.
103ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlclass DebugCommand;
104ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlclass Token;
105ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlclass FormatToken;
106ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
107ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlclass Debugger : public Simulator {
108ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl public:
109ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Debugger(Decoder* decoder, FILE* stream = stdout);
110ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
111ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  virtual void Run();
112ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  void VisitException(Instruction* instr);
113ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
114ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  inline int log_parameters() {
115ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The simulator can control disassembly, so make sure that the Debugger's
116ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // log parameters agree with it.
117ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (disasm_trace()) {
118ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      log_parameters_ |= LOG_DISASM;
119ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
120ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return log_parameters_;
121ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
122ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  inline void set_log_parameters(int parameters) {
123ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    set_disasm_trace((parameters & LOG_DISASM) != 0);
124ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    log_parameters_ = parameters;
125ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
126ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    update_pending_request();
127ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
128ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
129ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  inline int debug_parameters() { return debug_parameters_; }
130ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  inline void set_debug_parameters(int parameters) {
131ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    debug_parameters_ = parameters;
132ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
133ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    update_pending_request();
134ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
135ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
136ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Numbers of instructions to execute before the debugger shell is given
137ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // back control.
138ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  inline int steps() { return steps_; }
139ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  inline void set_steps(int value) {
1401123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(value > 1);
141ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    steps_ = value;
142ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
143ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
144ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  inline bool IsDebuggerRunning() {
145ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return (debug_parameters_ & DBG_ACTIVE) != 0;
146ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
147ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
148ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  inline bool pending_request() { return pending_request_; }
149ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  inline void update_pending_request() {
150578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    const int kLoggingMask = LOG_STATE;
151ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    const bool logging = (log_parameters_ & kLoggingMask) != 0;
152ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    const bool debugging = IsDebuggerRunning();
153ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
154ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    pending_request_ = logging || debugging;
155ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
156ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
157ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  void PrintInstructions(void* address, int64_t count = 1);
158ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  void PrintMemory(const uint8_t* address,
159f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                   const FormatToken* format,
160f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                   int64_t count = 1);
161f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  void PrintRegister(const Register& target_reg,
162f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                     const char* name,
163f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                     const FormatToken* format);
164f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  void PrintFPRegister(const FPRegister& target_fpreg,
165f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                       const FormatToken* format);
166ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
167ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl private:
168578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  void LogSystemRegisters();
169ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  void LogRegisters();
170ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  void LogFPRegisters();
171ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  void LogProcessorState();
172ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  char* ReadCommandLine(const char* prompt, char* buffer, int length);
173ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  void RunDebuggerShell();
174ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  void DoBreakpoint(Instruction* instr);
175ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  void DoUnreachable(Instruction* instr);
176ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  void DoTrace(Instruction* instr);
177ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  void DoLog(Instruction* instr);
178ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
179ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int  log_parameters_;
180ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int  debug_parameters_;
181ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool pending_request_;
182ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int steps_;
183ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  DebugCommand* last_command_;
184ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PrintDisassembler* disasm_;
185ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Decoder* printer_;
186ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
187ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Length of the biggest command line accepted by the debugger shell.
188ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  static const int kMaxDebugShellLine = 256;
189ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl};
190ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
191ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}  // namespace vixl
192ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
193ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#endif  // VIXL_A64_DEBUGGER_A64_H_
194