aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Bramley <jacob.bramley@arm.com>2018-07-03 17:58:44 +0100
committerJacob Bramley <jacob.bramley@arm.com>2018-07-04 11:10:17 +0100
commitc919d87b7fd272eb8bfb05b395e5fc0b6dbc289c (patch)
tree41b6ee9a3d90923cbaccba06576e1e7e6d6c8b15
parentd6166b0a0c6168dddcf1529b7271c3e4b7807372 (diff)
Remove the Debugger.
The Debugger isn't well maintained, and its presence has an impact on testing and validation time. Change-Id: I9ad664ec3150e7f4ea1da2e3201682fb5684c610
-rw-r--r--examples/aarch64/debugger.cc73
-rw-r--r--examples/aarch64/examples.h2
-rw-r--r--src/aarch64/debugger-aarch64.cc1589
-rw-r--r--src/aarch64/debugger-aarch64.h109
-rw-r--r--src/aarch64/macro-assembler-aarch64.h5
-rw-r--r--test/aarch64/examples/test-examples.cc3
-rw-r--r--test/aarch64/test-assembler-aarch64.cc47
-rw-r--r--test/aarch64/test-simulator-aarch64.cc39
-rw-r--r--test/aarch64/test-trace-aarch64.cc1
-rw-r--r--test/test-runner.cc8
-rw-r--r--test/test-runner.h6
-rwxr-xr-xtools/test.py17
12 files changed, 46 insertions, 1853 deletions
diff --git a/examples/aarch64/debugger.cc b/examples/aarch64/debugger.cc
deleted file mode 100644
index 560817df..00000000
--- a/examples/aarch64/debugger.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2014, VIXL authors
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// * Neither the name of ARM Limited nor the names of its contributors may be
-// used to endorse or promote products derived from this software without
-// specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "examples.h"
-
-
-// This is an interactive example, not to be used for testing.
-#ifndef TEST_EXAMPLES
-
-#define __ masm->
-
-// The aim is to let the user "play" with the debugger. Brk will trigger the
-// debugger shell.
-void GenerateBreak(MacroAssembler* masm) {
- Label hop;
- __ Brk();
- __ Nop();
- __ B(&hop);
- __ Nop();
- __ Bind(&hop);
- __ Mov(x1, 123);
- __ Mov(x2, 456);
- __ Add(x0, x1, x2);
- __ Ret();
-}
-
-
-#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
-int main(void) {
- MacroAssembler masm;
- Decoder decoder;
- Debugger debugger(&decoder);
-
- // Generate the code for the example function.
- Label start;
- masm.Bind(&start);
- GenerateBreak(&masm);
- masm.FinalizeCode();
-
- // Run the example function.
- debugger.RunFrom(masm.GetLabelAddress<Instruction*>(&start));
- printf("Debugger example run\n");
-
- return 0;
-}
-#else
-// Without the simulator there is nothing to test.
-int main(void) { return 0; }
-#endif // VIXL_INCLUDE_SIMULATOR_AARCH64
-#endif // TEST_EXAMPLES
diff --git a/examples/aarch64/examples.h b/examples/aarch64/examples.h
index 182b8138..31e65806 100644
--- a/examples/aarch64/examples.h
+++ b/examples/aarch64/examples.h
@@ -27,8 +27,8 @@
#ifndef VIXL_EXAMPLE_EXAMPLES_H_
#define VIXL_EXAMPLE_EXAMPLES_H_
-#include "aarch64/debugger-aarch64.h"
#include "aarch64/macro-assembler-aarch64.h"
+#include "aarch64/simulator-aarch64.h"
using namespace vixl;
using namespace vixl::aarch64;
diff --git a/src/aarch64/debugger-aarch64.cc b/src/aarch64/debugger-aarch64.cc
deleted file mode 100644
index 9128bd02..00000000
--- a/src/aarch64/debugger-aarch64.cc
+++ /dev/null
@@ -1,1589 +0,0 @@
-// Copyright 2014, VIXL authors
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// * Neither the name of ARM Limited nor the names of its contributors may be
-// used to endorse or promote products derived from this software without
-// specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY ARM LIMITED AND CONTRIBUTORS "AS IS" AND ANY
-// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL ARM LIMITED BE LIABLE FOR ANY DIRECT, INDIRECT,
-// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
-// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
-// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
-
-#include "debugger-aarch64.h"
-
-namespace vixl {
-namespace aarch64 {
-
-// List of commands supported by the debugger.
-#define DEBUG_COMMAND_LIST(C) \
- C(HelpCommand) \
- C(ContinueCommand) \
- C(StepCommand) \
- C(SkipCommand) \
- C(DisasmCommand) \
- C(PrintCommand) \
- C(ExamineCommand)
-
-// Debugger command lines are broken up in token of different type to make
-// processing easier later on.
-class Token {
- public:
- virtual ~Token() {}
-
- // Token type.
- virtual bool IsRegister() const { return false; }
- virtual bool IsFPRegister() const { return false; }
- virtual bool IsIdentifier() const { return false; }
- virtual bool IsAddress() const { return false; }
- virtual bool IsInteger() const { return false; }
- virtual bool IsFormat() const { return false; }
- virtual bool IsUnknown() const { return false; }
- // Token properties.
- virtual bool CanAddressMemory() const { return false; }
- virtual uint8_t* ToAddress(Debugger* debugger) const = 0;
- virtual void Print(FILE* out = stdout) const = 0;
-
- static Token* Tokenize(const char* arg);
-};
-
-// Tokens often hold one value.
-template <typename T>
-class ValueToken : public Token {
- public:
- explicit ValueToken(T value) : value_(value) {}
- ValueToken() {}
-
- T value() const { return value_; }
-
- VIXL_NO_RETURN virtual uint8_t* ToAddress(Debugger* debugger) const
- VIXL_OVERRIDE {
- USE(debugger);
- VIXL_ABORT();
- }
-
- protected:
- T value_;
-};
-
-// Integer registers (X or W) and their aliases.
-// Format: wn or xn with 0 <= n < 32 or a name in the aliases list.
-class RegisterToken : public ValueToken<const Register> {
- public:
- explicit RegisterToken(const Register reg)
- : ValueToken<const Register>(reg) {}
-
- virtual bool IsRegister() const VIXL_OVERRIDE { return true; }
- virtual bool CanAddressMemory() const VIXL_OVERRIDE {
- return value().Is64Bits();
- }
- virtual uint8_t* ToAddress(Debugger* debugger) const VIXL_OVERRIDE;
- virtual void Print(FILE* out = stdout) const VIXL_OVERRIDE;
- const char* Name() const;
-
- static Token* Tokenize(const char* arg);
- static RegisterToken* Cast(Token* tok) {
- VIXL_ASSERT(tok->IsRegister());
- return reinterpret_cast<RegisterToken*>(tok);
- }
-
- private:
- static const int kMaxAliasNumber = 4;
- static const char* kXAliases[kNumberOfRegisters][kMaxAliasNumber];
- static const char* kWAliases[kNumberOfRegisters][kMaxAliasNumber];
-};
-
-// Floating point registers (D or S).
-// Format: sn or dn with 0 <= n < 32.
-class FPRegisterToken : public ValueToken<const FPRegister> {
- public:
- explicit FPRegisterToken(const FPRegister fpreg)
- : ValueToken<const FPRegister>(fpreg) {}
-
- virtual bool IsFPRegister() const VIXL_OVERRIDE { return true; }
- virtual void Print(FILE* out = stdout) const VIXL_OVERRIDE;
-
- static Token* Tokenize(const char* arg);
- static FPRegisterToken* Cast(Token* tok) {
- VIXL_ASSERT(tok->IsFPRegister());
- return reinterpret_cast<FPRegisterToken*>(tok);
- }
-};
-
-
-// Non-register identifiers.
-// Format: Alphanumeric string starting with a letter.
-class IdentifierToken : public ValueToken<char*> {
- public:
- explicit IdentifierToken(const char* name) {
- size_t size = strlen(name) + 1;
- value_ = new char[size];
- strncpy(value_, name, size);
- }
- virtual ~IdentifierToken() { delete[] value_; }
-
- virtual bool IsIdentifier() const VIXL_OVERRIDE { return true; }
- virtual bool CanAddressMemory() const VIXL_OVERRIDE {
- return strcmp(value(), "pc") == 0;
- }
- virtual uint8_t* ToAddress(Debugger* debugger) const VIXL_OVERRIDE;
- virtual void Print(FILE* out = stdout) const VIXL_OVERRIDE;
-
- static Token* Tokenize(const char* arg);
- static IdentifierToken* Cast(Token* tok) {
- VIXL_ASSERT(tok->IsIdentifier());
- return reinterpret_cast<IdentifierToken*>(tok);
- }
-};
-
-// 64-bit address literal.
-// Format: 0x... with up to 16 hexadecimal digits.
-class AddressToken : public ValueToken<uint8_t*> {
- public:
- explicit AddressToken(uint8_t* address) : ValueToken<uint8_t*>(address) {}
-
- virtual bool IsAddress() const VIXL_OVERRIDE { return true; }
- virtual bool CanAddressMemory() const VIXL_OVERRIDE { return true; }
- virtual uint8_t* ToAddress(Debugger* debugger) const VIXL_OVERRIDE;
- virtual void Print(FILE* out = stdout) const VIXL_OVERRIDE;
-
- static Token* Tokenize(const char* arg);
- static AddressToken* Cast(Token* tok) {
- VIXL_ASSERT(tok->IsAddress());
- return reinterpret_cast<AddressToken*>(tok);
- }
-};
-
-
-// 64-bit decimal integer literal.
-// Format: n.
-class IntegerToken : public ValueToken<int64_t> {
- public:
- explicit IntegerToken(int64_t value) : ValueToken<int64_t>(value) {}
-
- virtual bool IsInteger() const VIXL_OVERRIDE { return true; }
- virtual void Print(FILE* out = stdout) const VIXL_OVERRIDE;
-
- static Token* Tokenize(const char* arg);
- static IntegerToken* Cast(Token* tok) {
- VIXL_ASSERT(tok->IsInteger());
- return reinterpret_cast<IntegerToken*>(tok);
- }
-};
-
-// Literal describing how to print a chunk of data (up to 64 bits).
-// Format: .ln
-// where l (letter) is one of
-// * x: hexadecimal
-// * s: signed integer
-// * u: unsigned integer
-// * f: floating point
-// * i: instruction
-// and n (size) is one of 8, 16, 32 and 64. n should be omitted for
-// instructions.
-class FormatToken : public Token {
- public:
- FormatToken() {}
-
- virtual bool IsFormat() const VIXL_OVERRIDE { return true; }
- virtual int SizeOf() const = 0;
- virtual char GetTypeCode() const = 0;
- virtual void PrintData(void* data, FILE* out = stdout) const = 0;
- virtual void Print(FILE* out = stdout) const VIXL_OVERRIDE = 0;
-
- VIXL_NO_RETURN virtual uint8_t* ToAddress(Debugger* debugger) const
- VIXL_OVERRIDE {
- USE(debugger);
- VIXL_ABORT();
- }
-
- static Token* Tokenize(const char* arg);
- static FormatToken* Cast(Token* tok) {
- VIXL_ASSERT(tok->IsFormat());
- return reinterpret_cast<FormatToken*>(tok);
- }
-};
-
-
-template <typename T>
-class Format : public FormatToken {
- public:
- Format(const char* fmt, char type_code) : fmt_(fmt), type_code_(type_code) {}
-
- virtual int SizeOf() const VIXL_OVERRIDE { return sizeof(T); }
- virtual char GetTypeCode() const VIXL_OVERRIDE { return type_code_; }
- virtual void PrintData(void* data, FILE* out = stdout) const VIXL_OVERRIDE {
- T value;
- memcpy(&value, data, sizeof(value));
- fprintf(out, fmt_, value);
- }
- virtual void Print(FILE* out = stdout) const VIXL_OVERRIDE;
-
- private:
- const char* fmt_;
- char type_code_;
-};
-
-// Tokens which don't fit any of the above.
-class UnknownToken : public Token {
- public:
- explicit UnknownToken(const char* arg) {
- size_t size = strlen(arg) + 1;
- unknown_ = new char[size];
- strncpy(unknown_, arg, size);
- }
- virtual ~UnknownToken() { delete[] unknown_; }
- VIXL_NO_RETURN virtual uint8_t* ToAddress(Debugger* debugger) const
- VIXL_OVERRIDE {
- USE(debugger);
- VIXL_ABORT();
- }
-
- virtual bool IsUnknown() const VIXL_OVERRIDE { return true; }
- virtual void Print(FILE* out = stdout) const VIXL_OVERRIDE;
-
- private:
- char* unknown_;
-};
-
-
-// All debugger commands must subclass DebugCommand and implement Run, Print
-// and Build. Commands must also define kHelp and kAliases.
-class DebugCommand {
- public:
- explicit DebugCommand(Token* name) : name_(IdentifierToken::Cast(name)) {}
- DebugCommand() : name_(NULL) {}
- virtual ~DebugCommand() { delete name_; }
-
- const char* name() { return name_->value(); }
- // Run the command on the given debugger.
- // Return `true` if control should be given back to the debugger.
- virtual bool Run(Debugger* debugger) = 0;
- virtual void Print(FILE* out = stdout);
-
- static bool Match(const char* name, const char** aliases);
- static DebugCommand* Parse(char* line);
- static void PrintHelp(const char** aliases,
- const char* args,
- const char* help);
-
- private:
- IdentifierToken* name_;
-};
-
-// For all commands below see their respective kHelp and kAliases in
-// debugger-aarch64.cc
-class HelpCommand : public DebugCommand {
- public:
- explicit HelpCommand(Token* name) : DebugCommand(name) {}
-
- virtual bool Run(Debugger* debugger) VIXL_OVERRIDE;
-
- static DebugCommand* Build(std::vector<Token*> args);
-
- static const char* kHelp;
- static const char* kAliases[];
- static const char* kArguments;
-};
-
-
-class ContinueCommand : public DebugCommand {
- public:
- explicit ContinueCommand(Token* name) : DebugCommand(name) {}
-
- virtual bool Run(Debugger* debugger) VIXL_OVERRIDE;
-
- static DebugCommand* Build(std::vector<Token*> args);
-
- static const char* kHelp;
- static const char* kAliases[];
- static const char* kArguments;
-};
-
-
-class StepCommand : public DebugCommand {
- public:
- StepCommand(Token* name, IntegerToken* count)
- : DebugCommand(name), count_(count) {}
- virtual ~StepCommand() { delete count_; }
-
- int64_t count() { return count_->value(); }
- virtual bool Run(Debugger* debugger) VIXL_OVERRIDE;
- virtual void Print(FILE* out = stdout) VIXL_OVERRIDE;
-
- static DebugCommand* Build(std::vector<Token*> args);
-
- static const char* kHelp;
- static const char* kAliases[];
- static const char* kArguments;
-
- private:
- IntegerToken* count_;
-};
-
-class SkipCommand : public DebugCommand {
- public:
- SkipCommand(Token* name, IntegerToken* count)
- : DebugCommand(name), count_(count) {}
- virtual ~SkipCommand() { delete count_; }
-
- int64_t count() { return count_->value(); }
- virtual bool Run(Debugger* debugger) VIXL_OVERRIDE;
- virtual void Print(FILE* out = stdout) VIXL_OVERRIDE;
-
- static DebugCommand* Build(std::vector<Token*> args);
-
- static const char* kHelp;
- static const char* kAliases[];
- static const char* kArguments;
-
- private:
- IntegerToken* count_;
-};
-
-class DisasmCommand : public DebugCommand {
- public:
- static DebugCommand* Build(std::vector<Token*> args);
-
- static const char* kHelp;
- static const char* kAliases[];
- static const char* kArguments;
-};
-
-
-class PrintCommand : public DebugCommand {
- public:
- PrintCommand(Token* name, Token* target, FormatToken* format)
- : DebugCommand(name), target_(target), format_(format) {}
- virtual ~PrintCommand() {
- delete target_;
- delete format_;
- }
-
- Token* target() { return target_; }
- FormatToken* format() { return format_; }
- virtual bool Run(Debugger* debugger) VIXL_OVERRIDE;
- virtual void Print(FILE* out = stdout) VIXL_OVERRIDE;
-
- static DebugCommand* Build(std::vector<Token*> args);
-
- static const char* kHelp;
- static const char* kAliases[];
- static const char* kArguments;
-
- private:
- Token* target_;
- FormatToken* format_;
-};
-
-class ExamineCommand : public DebugCommand {
- public:
- ExamineCommand(Token* name,
- Token* target,
- FormatToken* format,
- IntegerToken* count)
- : DebugCommand(name), target_(target), format_(format), count_(count) {}
- virtual ~ExamineCommand() {
- delete target_;
- delete format_;
- delete count_;
- }
-
- Token* target() { return target_; }
- FormatToken* format() { return format_; }
- IntegerToken* count() { return count_; }
- virtual bool Run(Debugger* debugger) VIXL_OVERRIDE;
- virtual void Print(FILE* out = stdout) VIXL_OVERRIDE;
-
- static DebugCommand* Build(std::vector<Token*> args);
-
- static const char* kHelp;
- static const char* kAliases[];
- static const char* kArguments;
-
- private:
- Token* target_;
- FormatToken* format_;
- IntegerToken* count_;
-};
-
-// Commands which name does not match any of the known commnand.
-class UnknownCommand : public DebugCommand {
- public:
- explicit UnknownCommand(std::vector<Token*> args) : args_(args) {}
- virtual ~UnknownCommand();
-
- virtual bool Run(Debugger* debugger) VIXL_OVERRIDE;
-
- private:
- std::vector<Token*> args_;
-};
-
-// Commands which name match a known command but the syntax is invalid.
-class InvalidCommand : public DebugCommand {
- public:
- InvalidCommand(std::vector<Token*> args, int index, const char* cause)
- : args_(args), index_(index), cause_(cause) {}
- virtual ~InvalidCommand();
-
- virtual bool Run(Debugger* debugger) VIXL_OVERRIDE;
-
- private:
- std::vector<Token*> args_;
- int index_;
- const char* cause_;
-};
-
-const char* HelpCommand::kAliases[] = {"help", NULL};
-const char* HelpCommand::kArguments = NULL;
-const char* HelpCommand::kHelp = " Print this help.";
-
-const char* ContinueCommand::kAliases[] = {"continue", "c", NULL};
-const char* ContinueCommand::kArguments = NULL;
-const char* ContinueCommand::kHelp = " Resume execution.";
-
-const char* StepCommand::kAliases[] = {"stepi", "si", NULL};
-const char* StepCommand::kArguments = "[n = 1]";
-const char* StepCommand::kHelp = " Execute n next instruction(s).";
-
-const char* SkipCommand::kAliases[] = {"skip", NULL};
-const char* SkipCommand::kArguments = "[n = 1]";
-const char* SkipCommand::kHelp = " Skip the next n instruction(s).";
-
-const char* DisasmCommand::kAliases[] = {"disasm", "di", NULL};
-const char* DisasmCommand::kArguments = "[n = 10]";
-const char* DisasmCommand::kHelp =
- " Disassemble n instruction(s) at pc.\n"
- " This command is equivalent to x pc.i [n = 10].";
-
-const char* PrintCommand::kAliases[] = {"print", "p", NULL};
-const char* PrintCommand::kArguments = "<entity>[.format]";
-const char* PrintCommand::kHelp =
- " Print the given entity according to the given format.\n"
- " The format parameter only affects individual registers; it is ignored\n"
- " for other entities.\n"
- " <entity> can be one of the following:\n"
- " * A register name (such as x0, s1, ...).\n"
- " * 'regs', to print all integer (W and X) registers.\n"
- " * 'fpregs' to print all floating-point (S and D) registers.\n"
- " * 'sysregs' to print all system registers (including NZCV).\n"
- " * 'pc' to print the current program counter.\n";
-
-const char* ExamineCommand::kAliases[] = {"m", "mem", "x", NULL};
-const char* ExamineCommand::kArguments = "<addr>[.format] [n = 10]";
-const char* ExamineCommand::kHelp =
- " Examine memory. Print n items of memory at address <addr> according to\n"
- " the given [.format].\n"
- " Addr can be an immediate address, a register name or pc.\n"
- " Format is made of a type letter: 'x' (hexadecimal), 's' (signed), 'u'\n"
- " (unsigned), 'f' (floating point), i (instruction) and a size in bits\n"
- " when appropriate (8, 16, 32, 64)\n"
- " E.g 'x sp.x64' will print 10 64-bit words from the stack in\n"
- " hexadecimal format.";
-
-const char* RegisterToken::kXAliases[kNumberOfRegisters][kMaxAliasNumber] =
- {{"x0", NULL}, {"x1", NULL}, {"x2", NULL},
- {"x3", NULL}, {"x4", NULL}, {"x5", NULL},
- {"x6", NULL}, {"x7", NULL}, {"x8", NULL},
- {"x9", NULL}, {"x10", NULL}, {"x11", NULL},
- {"x12", NULL}, {"x13", NULL}, {"x14", NULL},
- {"x15", NULL}, {"ip0", "x16", NULL}, {"ip1", "x17", NULL},
- {"x18", "pr", NULL}, {"x19", NULL}, {"x20", NULL},
- {"x21", NULL}, {"x22", NULL}, {"x23", NULL},
- {"x24", NULL}, {"x25", NULL}, {"x26", NULL},
- {"x27", NULL}, {"x28", NULL}, {"fp", "x29", NULL},
- {"lr", "x30", NULL}, {"sp", NULL}};
-
-const char* RegisterToken::kWAliases[kNumberOfRegisters][kMaxAliasNumber] =
- {{"w0", NULL}, {"w1", NULL}, {"w2", NULL}, {"w3", NULL}, {"w4", NULL},
- {"w5", NULL}, {"w6", NULL}, {"w7", NULL}, {"w8", NULL}, {"w9", NULL},
- {"w10", NULL}, {"w11", NULL}, {"w12", NULL}, {"w13", NULL}, {"w14", NULL},
- {"w15", NULL}, {"w16", NULL}, {"w17", NULL}, {"w18", NULL}, {"w19", NULL},
- {"w20", NULL}, {"w21", NULL}, {"w22", NULL}, {"w23", NULL}, {"w24", NULL},
- {"w25", NULL}, {"w26", NULL}, {"w27", NULL}, {"w28", NULL}, {"w29", NULL},
- {"w30", NULL}, {"wsp", NULL}};
-
-
-Debugger::Debugger(Decoder* decoder, FILE* stream)
- : Simulator(decoder, stream),
- debugger_active_(false),
- steps_(0),
- last_command_(NULL) {
- disasm_ = new PrintDisassembler(stdout);
- printer_ = new Decoder();
- printer_->AppendVisitor(disasm_);
-}
-
-Debugger::~Debugger() {
- delete disasm_;
- delete printer_;
-}
-
-
-void Debugger::Run() {
- // Flush any written registers before executing anything, so that
- // manually-set registers are logged _before_ the first instruction.
- LogAllWrittenRegisters();
-
- while (pc_ != kEndOfSimAddress) {
- if (IsDebuggerActive()) RunDebuggerShell();
- ExecuteInstruction();
- }
-}
-
-
-void Debugger::PrintInstructions(const void* address,
- int64_t count,
- const char* prefix) {
- if (count == 0) {
- return;
- }
-
- const Instruction* from = Instruction::CastConst(address);
- if (count < 0) {
- count = -count;
- from -= (count - 1) * kInstructionSize;
- }
- const Instruction* to = from + count * kInstructionSize;
-
- for (const Instruction* current = from; current < to;
- current = current->GetNextInstruction()) {
- printf("%s", prefix);
- printer_->Decode(current);
- }
-}
-
-
-void Debugger::PrintMemory(const uint8_t* address,
- const FormatToken* format,
- int64_t count) {
- if (count == 0) {
- return;
- }
-
- const uint8_t* from = address;
- int size = format->SizeOf();
- if (count < 0) {
- count = -count;
- from -= (count - 1) * size;
- }
- const uint8_t* to = from + count * size;
-
- for (const uint8_t* current = from; current < to; current += size) {
- if (((current - from) % 8) == 0) {
- printf("\n%p: ", reinterpret_cast<const void*>(current));
- }
-
- uint64_t data = Memory::Read<uint64_t>(current);
- format->PrintData(&data);
- printf(" ");
- }
- printf("\n\n");
-}
-
-
-void Debugger::PrintRegister(const Register& target_reg,
- const char* name,
- const FormatToken* format) {
- const uint64_t reg_size = target_reg.GetSizeInBits();
- const uint64_t format_size = format->SizeOf() * 8;
- const uint64_t count = reg_size / format_size;
- const uint64_t mask = 0xffffffffffffffff >> (64 - format_size);
- const uint64_t reg_value =
- ReadRegister<uint64_t>(target_reg.GetCode(), Reg31IsStackPointer);
- VIXL_ASSERT(count > 0);
-
- printf("%s = ", name);
- for (uint64_t i = 1; i <= count; i++) {
- uint64_t data = reg_value >> (reg_size - (i * format_size));
- data &= mask;
- format->PrintData(&data);
- printf(" ");
- }
- printf("\n");
-}
-
-
-// TODO(all): fix this for vector registers.
-void Debugger::PrintFPRegister(const FPRegister& target_fpreg,
- const FormatToken* format) {
- const unsigned fpreg_size = target_fpreg.GetSizeInBits();
- const uint64_t format_size = format->SizeOf() * 8;
- const uint64_t count = fpreg_size / format_size;
- const uint64_t mask = 0xffffffffffffffff >> (64 - format_size);
- const uint64_t fpreg_value =
- ReadVRegister<uint64_t>(fpreg_size, target_fpreg.GetCode());
- VIXL_ASSERT(count > 0);
-
- if (target_fpreg.Is32Bits()) {
- printf("s%u = ", target_fpreg.GetCode());
- } else {
- printf("d%u = ", target_fpreg.GetCode());
- }
- for (uint64_t i = 1; i <= count; i++) {
- uint64_t data = fpreg_value >> (fpreg_size - (i * format_size));
- data &= mask;
- format->PrintData(&data);
- printf(" ");
- }
- printf("\n");
-}
-
-
-void Debugger::VisitException(const Instruction* instr) {
- switch (instr->Mask(ExceptionMask)) {
- case BRK:
- DoBreakpoint(instr);
- return;
- case HLT:
- VIXL_FALLTHROUGH();
- default:
- Simulator::VisitException(instr);
- }
-}
-
-
-// Read a command. A command will be at most kMaxDebugShellLine char long and
-// ends with '\n\0'.
-// TODO: Should this be a utility function?
-char* Debugger::ReadCommandLine(const char* prompt, char* buffer, int length) {
- int fgets_calls = 0;
- char* end = NULL;
-
- printf("%s", prompt);
- fflush(stdout);
-
- do {
- if (fgets(buffer, length, stdin) == NULL) {
- printf(" ** Error while reading command. **\n");
- return NULL;
- }
-
- fgets_calls++;
- end = strchr(buffer, '\n');
- } while (end == NULL);
-
- if (fgets_calls != 1) {
- printf(" ** Command too long. **\n");
- return NULL;
- }
-
- // Remove the newline from the end of the command.
- VIXL_ASSERT(end[1] == '\0');
- VIXL_ASSERT((end - buffer) < (length - 1));
- end[0] = '\0';
-
- return buffer;
-}
-
-
-void Debugger::RunDebuggerShell() {
- if (IsDebuggerActive()) {
- if (steps_ > 0) {
- // Finish stepping first.
- --steps_;
- return;
- }
-
- PrintNextInstruction();
- bool done = false;
- while (!done) {
- char buffer[kMaxDebugShellLine];
- char* line = ReadCommandLine("vixl> ", buffer, kMaxDebugShellLine);
-
- if (line == NULL) continue; // An error occurred.
-
- DebugCommand* command = DebugCommand::Parse(line);
- if (command != NULL) {
- last_command_ = command;
- }
-
- if (last_command_ != NULL) {
- done = last_command_->Run(this);
- } else {
- printf("No previous command to run!\n");
- }
- }
- }
-}
-
-
-void Debugger::DoBreakpoint(const Instruction* instr) {
- VIXL_ASSERT(instr->Mask(ExceptionMask) == BRK);
-
- printf("Hit breakpoint at pc=%p.\n", reinterpret_cast<const void*>(instr));
- ActivateDebugger();
-}
-
-
-static bool StringToUInt64(uint64_t* value, const char* line, int base = 10) {
- char* endptr = NULL;
- errno = 0; // Reset errors.
- uint64_t parsed = strtoul(line, &endptr, base);
-
- if (errno == ERANGE) {
- // Overflow.
- return false;
- }
-
- if (endptr == line) {
- // No digits were parsed.
- return false;
- }
-
- if (*endptr != '\0') {
- // Non-digit characters present at the end.
- return false;
- }
-
- *value = parsed;
- return true;
-}
-
-
-static bool StringToInt64(int64_t* value, const char* line, int base = 10) {
- char* endptr = NULL;
- errno = 0; // Reset errors.
- int64_t parsed = strtol(line, &endptr, base);
-
- if (errno == ERANGE) {
- // Overflow, undeflow.
- return false;
- }
-
- if (endptr == line) {
- // No digits were parsed.
- return false;
- }
-
- if (*endptr != '\0') {
- // Non-digit characters present at the end.
- return false;
- }
-
- *value = parsed;
- return true;
-}
-
-
-Token* Token::Tokenize(const char* arg) {
- if ((arg == NULL) || (*arg == '\0')) {
- return NULL;
- }
-
- // The order is important. For example Identifier::Tokenize would consider
- // any register to be a valid identifier.
-
- Token* token = RegisterToken::Tokenize(arg);
- if (token != NULL) {
- return token;
- }
-
- token = FPRegisterToken::Tokenize(arg);
- if (token != NULL) {
- return token;
- }
-
- token = IdentifierToken::Tokenize(arg);
- if (token != NULL) {
- return token;
- }
-
- token = AddressToken::Tokenize(arg);
- if (token != NULL) {
- return token;
- }
-
- token = IntegerToken::Tokenize(arg);
- if (token != NULL) {
- return token;
- }
-
- return new UnknownToken(arg);
-}
-
-
-uint8_t* RegisterToken::ToAddress(Debugger* debugger) const {
- VIXL_ASSERT(CanAddressMemory());
- uint64_t reg_value =
- debugger->ReadXRegister(value().GetCode(), Reg31IsStackPointer);
- uint8_t* address = NULL;
- memcpy(&address, &reg_value, sizeof(address));
- return address;
-}
-
-
-void RegisterToken::Print(FILE* out) const {
- VIXL_ASSERT(value().IsValid());
- fprintf(out, "[Register %s]", Name());
-}
-
-
-const char* RegisterToken::Name() const {
- if (value().Is32Bits()) {
- return kWAliases[value().GetCode()][0];
- } else {
- return kXAliases[value().GetCode()][0];
- }
-}
-
-
-Token* RegisterToken::Tokenize(const char* arg) {
- for (unsigned i = 0; i < kNumberOfRegisters; i++) {
- // Is it a X register or alias?
- for (const char** current = kXAliases[i]; *current != NULL; current++) {
- if (strcmp(arg, *current) == 0) {
- return new RegisterToken(Register::GetXRegFromCode(i));
- }
- }
-
- // Is it a W register or alias?
- for (const char** current = kWAliases[i]; *current != NULL; current++) {
- if (strcmp(arg, *current) == 0) {
- return new RegisterToken(Register::GetWRegFromCode(i));
- }
- }
- }
-
- return NULL;
-}
-
-
-void FPRegisterToken::Print(FILE* out) const {
- VIXL_ASSERT(value().IsValid());
- char prefix = value().Is32Bits() ? 's' : 'd';
- fprintf(out, "[FPRegister %c%" PRIu32 "]", prefix, value().GetCode());
-}
-
-
-Token* FPRegisterToken::Tokenize(const char* arg) {
- if (strlen(arg) < 2) {
- return NULL;
- }
-
- switch (*arg) {
- case 's':
- case 'd':
- const char* cursor = arg + 1;
- uint64_t code = 0;
- if (!StringToUInt64(&code, cursor)) {
- return NULL;
- }
-
- if (code > kNumberOfFPRegisters) {
- return NULL;
- }
-
- VRegister fpreg = NoVReg;
- switch (*arg) {
- case 's':
- fpreg = VRegister::GetSRegFromCode(static_cast<unsigned>(code));
- break;
- case 'd':
- fpreg = VRegister::GetDRegFromCode(static_cast<unsigned>(code));
- break;
- default:
- VIXL_UNREACHABLE();
- }
-
- return new FPRegisterToken(fpreg);
- }
-
- return NULL;
-}
-
-
-uint8_t* IdentifierToken::ToAddress(Debugger* debugger) const {
- VIXL_ASSERT(CanAddressMemory());
- const Instruction* pc_value = debugger->ReadPc();
- uint8_t* address = NULL;
- memcpy(&address, &pc_value, sizeof(address));
- return address;
-}
-
-void IdentifierToken::Print(FILE* out) const {
- fprintf(out, "[Identifier %s]", value());
-}
-
-
-Token* IdentifierToken::Tokenize(const char* arg) {
- if (!isalpha(arg[0])) {
- return NULL;
- }
-
- const char* cursor = arg + 1;
- while ((*cursor != '\0') && isalnum(*cursor)) {
- ++cursor;
- }
-
- if (*cursor == '\0') {
- return new IdentifierToken(arg);
- }
-
- return NULL;
-}
-
-
-uint8_t* AddressToken::ToAddress(Debugger* debugger) const {
- USE(debugger);
- return value();
-}
-
-
-void AddressToken::Print(FILE* out) const {
- fprintf(out, "[Address %p]", reinterpret_cast<const void*>(value()));
-}
-
-
-Token* AddressToken::Tokenize(const char* arg) {
- if ((strlen(arg) < 3) || (arg[0] != '0') || (arg[1] != 'x')) {
- return NULL;
- }
-
- uint64_t ptr = 0;
- if (!StringToUInt64(&ptr, arg, 16)) {
- return NULL;
- }
-
- uint8_t* address = reinterpret_cast<uint8_t*>(ptr);
- return new AddressToken(address);
-}
-
-
-void IntegerToken::Print(FILE* out) const {
- fprintf(out, "[Integer %" PRId64 "]", value());
-}
-
-
-Token* IntegerToken::Tokenize(const char* arg) {
- int64_t value = 0;
- if (!StringToInt64(&value, arg)) {
- return NULL;
- }
-
- return new IntegerToken(value);
-}
-
-
-Token* FormatToken::Tokenize(const char* arg) {
- size_t length = strlen(arg);
- switch (arg[0]) {
- case 'x':
- case 's':
- case 'u':
- case 'f':
- if (length == 1) return NULL;
- break;
- case 'i':
- if (length == 1) return new Format<uint32_t>("%08" PRIx32, 'i');
- VIXL_FALLTHROUGH();
- default:
- return NULL;
- }
-
- char* endptr = NULL;
- errno = 0; // Reset errors.
- uint64_t count = strtoul(arg + 1, &endptr, 10);
-
- if (errno != 0) {
- // Overflow, etc.
- return NULL;
- }
-
- if (endptr == arg) {
- // No digits were parsed.
- return NULL;
- }
-
- if (*endptr != '\0') {
- // There are unexpected (non-digit) characters after the number.
- return NULL;
- }
-
- switch (arg[0]) {
- case 'x':
- switch (count) {
- case 8:
- return new Format<uint8_t>("%02" PRIx8, 'x');
- case 16:
- return new Format<uint16_t>("%04" PRIx16, 'x');
- case 32:
- return new Format<uint32_t>("%08" PRIx32, 'x');
- case 64:
- return new Format<uint64_t>("%016" PRIx64, 'x');
- default:
- return NULL;
- }
- case 's':
- switch (count) {
- case 8:
- return new Format<int8_t>("%4" PRId8, 's');
- case 16:
- return new Format<int16_t>("%6" PRId16, 's');
- case 32:
- return new Format<int32_t>("%11" PRId32, 's');
- case 64:
- return new Format<int64_t>("%20" PRId64, 's');
- default:
- return NULL;
- }
- case 'u':
- switch (count) {
- case 8:
- return new Format<uint8_t>("%3" PRIu8, 'u');
- case 16:
- return new Format<uint16_t>("%5" PRIu16, 'u');
- case 32:
- return new Format<uint32_t>("%10" PRIu32, 'u');
- case 64:
- return new Format<uint64_t>("%20" PRIu64, 'u');
- default:
- return NULL;
- }
- case 'f':
- switch (count) {
- case 32:
- return new Format<float>("%13g", 'f');
- case 64:
- return new Format<double>("%13g", 'f');
- default:
- return NULL;
- }
- default:
- VIXL_UNREACHABLE();
- return NULL;
- }
-}
-
-
-template <typename T>
-void Format<T>::Print(FILE* out) const {
- unsigned size = sizeof(T) * 8;
- fprintf(out, "[Format %c%u - %s]", type_code_, size, fmt_);
-}
-
-
-void UnknownToken::Print(FILE* out) const {
- fprintf(out, "[Unknown %s]", unknown_);
-}
-
-
-void DebugCommand::Print(FILE* out) { fprintf(out, "%s", name()); }
-
-
-bool DebugCommand::Match(const char* name, const char** aliases) {
- for (const char** current = aliases; *current != NULL; current++) {
- if (strcmp(name, *current) == 0) {
- return true;
- }
- }
-
- return false;
-}
-
-
-DebugCommand* DebugCommand::Parse(char* line) {
- std::vector<Token*> args;
-
- for (char* chunk = strtok(line, " \t"); chunk != NULL;
- chunk = strtok(NULL, " \t")) {
- char* dot = strchr(chunk, '.');
- if (dot != NULL) {
- // 'Token.format'.
- Token* format = FormatToken::Tokenize(dot + 1);
- if (format != NULL) {
- *dot = '\0';
- args.push_back(Token::Tokenize(chunk));
- args.push_back(format);
- } else {
- // Error while parsing the format, push the UnknownToken so an error
- // can be accurately reported.
- args.push_back(Token::Tokenize(chunk));
- }
- } else {
- args.push_back(Token::Tokenize(chunk));
- }
- }
-
- if (args.size() == 0) {
- return NULL;
- }
-
- if (!args[0]->IsIdentifier()) {
- return new InvalidCommand(args, 0, "command name is not valid");
- }
-
- const char* name = IdentifierToken::Cast(args[0])->value();
-#define RETURN_IF_MATCH(Command) \
- if (Match(name, Command::kAliases)) { \
- return Command::Build(args); \
- }
- DEBUG_COMMAND_LIST(RETURN_IF_MATCH);
-#undef RETURN_IF_MATCH
-
- return new UnknownCommand(args);
-}
-
-
-void DebugCommand::PrintHelp(const char** aliases,
- const char* args,
- const char* help) {
- VIXL_ASSERT(aliases[0] != NULL);
- VIXL_ASSERT(help != NULL);
-
- printf("\n----\n\n");
- for (const char** current = aliases; *current != NULL; current++) {
- if (args != NULL) {
- printf("%s %s\n", *current, args);
- } else {
- printf("%s\n", *current);
- }
- }
- printf("\n%s\n", help);
-}
-
-
-bool HelpCommand::Run(Debugger* debugger) {
- VIXL_ASSERT(debugger->IsDebuggerActive());
- USE(debugger);
-
-#define PRINT_HELP(Command) \
- DebugCommand::PrintHelp(Command::kAliases, \
- Command::kArguments, \
- Command::kHelp);
- DEBUG_COMMAND_LIST(PRINT_HELP);
-#undef PRINT_HELP
- printf("\n----\n\n");
-
- return false;
-}
-
-
-DebugCommand* HelpCommand::Build(std::vector<Token*> args) {
- if (args.size() != 1) {
- return new InvalidCommand(args, -1, "too many arguments");
- }
-
- return new HelpCommand(args[0]);
-}
-
-
-bool ContinueCommand::Run(Debugger* debugger) {
- VIXL_ASSERT(debugger->IsDebuggerActive());
-
- debugger->DeactivateDebugger();
- return true;
-}
-
-
-DebugCommand* ContinueCommand::Build(std::vector<Token*> args) {
- if (args.size() != 1) {
- return new InvalidCommand(args, -1, "too many arguments");
- }
-
- return new ContinueCommand(args[0]);
-}
-
-
-bool StepCommand::Run(Debugger* debugger) {
- VIXL_ASSERT(debugger->IsDebuggerActive());
-
- // To avoid recursive calls to the debugger shell when hitting breakpoints
- // while stepping, stepping is implemented by telling the debugger how many
- // instructions to execute before starting the shell again.
- int64_t steps = count();
- if (steps <= 0) {
- if (steps < 0) {
- printf(" ** invalid value for steps: %" PRId64 " (<0) **\n", steps);
- }
- // Execute nothing and stay in the shell.
- return false;
- } else {
- debugger->SetSteps(steps - 1);
- // Relinquish control to the debugger. It will execute the next instruction,
- // followed by `steps - 1` instructions, before starting the shell again.
- // (Unless another breakpoint is hit in the meantime.)
- return true;
- }
-}
-
-
-void StepCommand::Print(FILE* out) {
- fprintf(out, "%s %" PRId64 "", name(), count());
-}
-
-
-DebugCommand* StepCommand::Build(std::vector<Token*> args) {
- IntegerToken* count = NULL;
- switch (args.size()) {
- case 1: { // step [1]
- count = new IntegerToken(1);
- break;
- }
- case 2: { // step n
- Token* first = args[1];
- if (!first->IsInteger()) {
- return new InvalidCommand(args, 1, "expects int");
- }
- count = IntegerToken::Cast(first);
- break;
- }
- default:
- return new InvalidCommand(args, -1, "too many arguments");
- }
-
- return new StepCommand(args[0], count);
-}
-
-
-bool SkipCommand::Run(Debugger* debugger) {
- VIXL_ASSERT(debugger->IsDebuggerActive());
-
- int64_t steps = count();
- if (steps < 0) {
- printf(" ** invalid value for steps: %" PRId64 " (<0) **\n", steps);
- } else {
- printf("Skipping over %" PRId64 " instructions:\n", steps);
- debugger->PrintInstructions(debugger->ReadPc(), steps, "Skip: ");
- debugger->WritePc(debugger->ReadPc() + steps * kInstructionSize);
- debugger->PrintNextInstruction();
- }
-
- return false;
-}
-
-
-void SkipCommand::Print(FILE* out) {
- fprintf(out, "%s %" PRId64 "", name(), count());
-}
-
-
-DebugCommand* SkipCommand::Build(std::vector<Token*> args) {
- IntegerToken* count = NULL;
- switch (args.size()) {
- case 1: { // step [1]
- count = new IntegerToken(1);
- break;
- }
- case 2: { // step n
- Token* first = args[1];
- if (!first->IsInteger()) {
- return new InvalidCommand(args, 1, "expects int");
- }
- count = IntegerToken::Cast(first);
- break;
- }
- default:
- return new InvalidCommand(args, -1, "too many arguments");
- }
-
- return new SkipCommand(args[0], count);
-}
-
-
-DebugCommand* DisasmCommand::Build(std::vector<Token*> args) {
- IntegerToken* count = NULL;
- switch (args.size()) {
- case 1: { // disasm [10]
- count = new IntegerToken(10);
- break;
- }
- case 2: { // disasm n
- Token* first = args[1];
- if (!first->IsInteger()) {
- return new InvalidCommand(args, 1, "expects int");
- }
-
- count = IntegerToken::Cast(first);
- break;
- }
- default:
- return new InvalidCommand(args, -1, "too many arguments");
- }
-
- Token* target = new IdentifierToken("pc");
- FormatToken* format = new Format<uint32_t>("%08" PRIx32, 'i');
- return new ExamineCommand(args[0], target, format, count);
-}
-
-
-void PrintCommand::Print(FILE* out) {
- fprintf(out, "%s ", name());
- target()->Print(out);
- if (format() != NULL) format()->Print(out);
-}
-
-
-bool PrintCommand::Run(Debugger* debugger) {
- VIXL_ASSERT(debugger->IsDebuggerActive());
-
- Token* tok = target();
- if (tok->IsIdentifier()) {
- char* identifier = IdentifierToken::Cast(tok)->value();
- if (strcmp(identifier, "regs") == 0) {
- debugger->PrintRegisters();
- } else if (strcmp(identifier, "fpregs") == 0) {
- debugger->PrintVRegisters();
- } else if (strcmp(identifier, "sysregs") == 0) {
- debugger->PrintSystemRegisters();
- } else if (strcmp(identifier, "pc") == 0) {
- printf("pc = %16p\n", reinterpret_cast<const void*>(debugger->ReadPc()));
- } else {
- printf(" ** Unknown identifier to print: %s **\n", identifier);
- }
-
- return false;
- }
-
- FormatToken* format_tok = format();
- VIXL_ASSERT(format_tok != NULL);
- if (format_tok->GetTypeCode() == 'i') {
- // TODO(all): Add support for instruction disassembly.
- printf(" ** unsupported format: instructions **\n");
- return false;
- }
-
- if (tok->IsRegister()) {
- RegisterToken* reg_tok = RegisterToken::Cast(tok);
- Register reg = reg_tok->value();
- debugger->PrintRegister(reg, reg_tok->Name(), format_tok);
- return false;
- }
-
- if (tok->IsFPRegister()) {
- FPRegister fpreg = FPRegisterToken::Cast(tok)->value();
- debugger->PrintFPRegister(fpreg, format_tok);
- return false;
- }
-
- VIXL_UNREACHABLE();
- return false;
-}
-
-
-DebugCommand* PrintCommand::Build(std::vector<Token*> args) {
- if (args.size() < 2) {
- return new InvalidCommand(args, -1, "too few arguments");
- }
-
- Token* target = args[1];
- if (!target->IsRegister() && !target->IsFPRegister() &&
- !target->IsIdentifier()) {
- return new InvalidCommand(args, 1, "expects reg or identifier");
- }
-
- FormatToken* format = NULL;
- int target_size = 0;
- if (target->IsRegister()) {
- Register reg = RegisterToken::Cast(target)->value();
- target_size = reg.GetSizeInBytes();
- } else if (target->IsFPRegister()) {
- FPRegister fpreg = FPRegisterToken::Cast(target)->value();
- target_size = fpreg.GetSizeInBytes();
- }
- // If the target is an identifier there must be no format. This is checked
- // in the switch statement below.
-
- switch (args.size()) {
- case 2: {
- if (target->IsRegister()) {
- switch (target_size) {
- case 4:
- format = new Format<uint32_t>("%08" PRIx32, 'x');
- break;
- case 8:
- format = new Format<uint64_t>("%016" PRIx64, 'x');
- break;
- default:
- VIXL_UNREACHABLE();
- }
- } else if (target->IsFPRegister()) {
- switch (target_size) {
- case 4:
- format = new Format<float>("%8g", 'f');
- break;
- case 8:
- format = new Format<double>("%8g", 'f');
- break;
- default:
- VIXL_UNREACHABLE();
- }
- }
- break;
- }
- case 3: {
- if (target->IsIdentifier()) {
- return new InvalidCommand(args,
- 2,
- "format is only allowed with registers");
- }
-
- Token* second = args[2];
- if (!second->IsFormat()) {
- return new InvalidCommand(args, 2, "expects format");
- }
- format = FormatToken::Cast(second);
-
- if (format->SizeOf() > target_size) {
- return new InvalidCommand(args, 2, "format too wide");
- }
-
- break;
- }
- default:
- return new InvalidCommand(args, -1, "too many arguments");
- }
-
- return new PrintCommand(args[0], target, format);
-}
-
-
-bool ExamineCommand::Run(Debugger* debugger) {
- VIXL_ASSERT(debugger->IsDebuggerActive());
-
- uint8_t* address = target()->ToAddress(debugger);
- int64_t amount = count()->value();
- if (format()->GetTypeCode() == 'i') {
- debugger->PrintInstructions(address, amount);
- } else {
- debugger->PrintMemory(address, format(), amount);
- }
-
- return false;
-}
-
-
-void ExamineCommand::Print(FILE* out) {
- fprintf(out, "%s ", name());
- format()->Print(out);
- target()->Print(out);
-}
-
-
-DebugCommand* ExamineCommand::Build(std::vector<Token*> args) {
- if (args.size() < 2) {
- return new InvalidCommand(args, -1, "too few arguments");
- }
-
- Token* target = args[1];
- if (!target->CanAddressMemory()) {
- return new InvalidCommand(args, 1, "expects address");
- }
-
- FormatToken* format = NULL;
- IntegerToken* count = NULL;
-
- switch (args.size()) {
- case 2: { // mem addr[.x64] [10]
- format = new Format<uint64_t>("%016" PRIx64, 'x');
- count = new IntegerToken(10);
- break;
- }
- case 3: { // mem addr.format [10]
- // mem addr[.x64] n
- Token* second = args[2];
- if (second->IsFormat()) {
- format = FormatToken::Cast(second);
- count = new IntegerToken(10);
- break;
- } else if (second->IsInteger()) {
- format = new Format<uint64_t>("%016" PRIx64, 'x');
- count = IntegerToken::Cast(second);
- } else {
- return new InvalidCommand(args, 2, "expects format or integer");
- }
- VIXL_UNREACHABLE();
- break;
- }
- case 4: { // mem addr.format n
- Token* second = args[2];
- Token* third = args[3];
- if (!second->IsFormat() || !third->IsInteger()) {
- return new InvalidCommand(args, -1, "expects addr[.format] [n]");
- }
- format = FormatToken::Cast(second);
- count = IntegerToken::Cast(third);
- break;
- }
- default:
- return new InvalidCommand(args, -1, "too many arguments");
- }
-
- return new ExamineCommand(args[0], target, format, count);
-}
-
-
-UnknownCommand::~UnknownCommand() {
- const size_t size = args_.size();
- for (size_t i = 0; i < size; ++i) {
- delete args_[i];
- }
-}
-
-
-bool UnknownCommand::Run(Debugger* debugger) {
- VIXL_ASSERT(debugger->IsDebuggerActive());
- USE(debugger);
-
- printf(" ** Unknown Command:");
- const size_t size = args_.size();
- for (size_t i = 0; i < size; ++i) {
- printf(" ");
- args_[i]->Print(stdout);
- }
- printf(" **\n");
-
- return false;
-}
-
-
-InvalidCommand::~InvalidCommand() {
- const size_t size = args_.size();
- for (size_t i = 0; i < size; ++i) {
- delete args_[i];
- }
-}
-
-
-bool InvalidCommand::Run(Debugger* debugger) {
- VIXL_ASSERT(debugger->IsDebuggerActive());
- USE(debugger);
-
- printf(" ** Invalid Command:");
- const size_t size = args_.size();
- for (size_t i = 0; i < size; ++i) {
- printf(" ");
- if (i == static_cast<size_t>(index_)) {
- printf(">>");
- args_[i]->Print(stdout);
- printf("<<");
- } else {
- args_[i]->Print(stdout);
- }
- }
- printf(" **\n");
- printf(" ** %s\n", cause_);
-
- return false;
-}
-
-} // namespace aarch64
-} // namespace vixl
-
-#endif // VIXL_INCLUDE_SIMULATOR_AARCH64
diff --git a/src/aarch64/debugger-aarch64.h b/src/aarch64/debugger-aarch64.h
deleted file mode 100644
index c05d530f..00000000
--- a/src/aarch64/debugger-aarch64.h
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2014, VIXL authors
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// * Neither the name of ARM Limited nor the names of its contributors may be
-// used to endorse or promote products derived from this software without
-// specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
-
-#ifndef VIXL_AARCH64_DEBUGGER_AARCH64_H_
-#define VIXL_AARCH64_DEBUGGER_AARCH64_H_
-
-#include <cctype>
-#include <cerrno>
-#include <climits>
-#include <vector>
-
-#include "../globals-vixl.h"
-#include "../utils-vixl.h"
-
-#include "constants-aarch64.h"
-#include "simulator-aarch64.h"
-
-namespace vixl {
-namespace aarch64 {
-
-// Forward declarations.
-class DebugCommand;
-class Token;
-class FormatToken;
-
-class Debugger : public Simulator {
- public:
- explicit Debugger(Decoder* decoder, FILE* stream = stdout);
- ~Debugger();
-
- virtual void Run() VIXL_OVERRIDE;
- virtual void VisitException(const Instruction* instr) VIXL_OVERRIDE;
-
- bool IsDebuggerActive() const { return debugger_active_; }
- void ActivateDebugger() { debugger_active_ = true; }
- void DeactivateDebugger() { debugger_active_ = false; }
-
- // Numbers of instructions to execute before the debugger shell is given
- // back control.
- int64_t GetSteps() const { return steps_; }
- VIXL_DEPRECATED("GetSteps", int64_t steps() const) { return GetSteps(); }
-
- void SetSteps(int64_t value) {
- VIXL_ASSERT(value >= 0);
- steps_ = value;
- }
- VIXL_DEPRECATED("SetSteps", void set_steps(int64_t value)) {
- return SetSteps(value);
- }
-
- void PrintInstructions(const void* address,
- int64_t count = 1,
- const char* prefix = "");
- void PrintNextInstruction() { PrintInstructions(ReadPc(), 1, "Next: "); }
- void PrintMemory(const uint8_t* address,
- const FormatToken* format,
- int64_t count = 1);
- void PrintRegister(const Register& target_reg,
- const char* name,
- const FormatToken* format);
- void PrintFPRegister(const FPRegister& target_fpreg,
- const FormatToken* format);
-
- private:
- char* ReadCommandLine(const char* prompt, char* buffer, int length);
- void RunDebuggerShell();
- void DoBreakpoint(const Instruction* instr);
-
- bool debugger_active_;
- int64_t steps_;
- DebugCommand* last_command_;
- PrintDisassembler* disasm_;
- Decoder* printer_;
-
- // Length of the biggest command line accepted by the debugger shell.
- static const int kMaxDebugShellLine = 256;
-};
-
-} // namespace aarch64
-} // namespace vixl
-
-#endif // VIXL_AARCH64_DEBUGGER_AARCH64_H_
-
-#endif // VIXL_INCLUDE_SIMULATOR_AARCH64
diff --git a/src/aarch64/macro-assembler-aarch64.h b/src/aarch64/macro-assembler-aarch64.h
index 072d4be8..47929c38 100644
--- a/src/aarch64/macro-assembler-aarch64.h
+++ b/src/aarch64/macro-assembler-aarch64.h
@@ -35,8 +35,11 @@
#include "../macro-assembler-interface.h"
#include "assembler-aarch64.h"
-#include "debugger-aarch64.h"
#include "instrument-aarch64.h"
+// Required for runtime call support.
+// TODO: Break this dependency. We should be able to separate out the necessary
+// parts so that we don't need to include the whole simulator header.
+#include "simulator-aarch64.h"
// Required in order to generate debugging instructions for the simulator. This
// is needed regardless of whether the simulator is included or not, since
// generating simulator specific instructions is controlled at runtime.
diff --git a/test/aarch64/examples/test-examples.cc b/test/aarch64/examples/test-examples.cc
index ef44c617..1a867988 100644
--- a/test/aarch64/examples/test-examples.cc
+++ b/test/aarch64/examples/test-examples.cc
@@ -30,7 +30,6 @@
#include "non-const-visitor.h"
#include "../test-utils-aarch64.h"
-#include "aarch64/debugger-aarch64.h"
#include "aarch64/macro-assembler-aarch64.h"
#include "aarch64/simulator-aarch64.h"
#define TEST(name) TEST_(EXAMPLE_##name)
@@ -166,7 +165,7 @@ void GenerateTestWrapper(MacroAssembler* masm, RegisterDump* regs) {
#define START() \
MacroAssembler masm; \
Decoder decoder; \
- Debugger simulator(&decoder); \
+ Simulator simulator(&decoder); \
simulator.SetColouredTrace(Test::coloured_trace()); \
PrintDisassembler* pdis = NULL; \
Instrument* inst = NULL; \
diff --git a/test/aarch64/test-assembler-aarch64.cc b/test/aarch64/test-assembler-aarch64.cc
index a399a936..aa2e4297 100644
--- a/test/aarch64/test-assembler-aarch64.cc
+++ b/test/aarch64/test-assembler-aarch64.cc
@@ -37,7 +37,6 @@
#include "aarch64/test-utils-aarch64.h"
#include "aarch64/cpu-aarch64.h"
-#include "aarch64/debugger-aarch64.h"
#include "aarch64/disasm-aarch64.h"
#include "aarch64/macro-assembler-aarch64.h"
#include "aarch64/simulator-aarch64.h"
@@ -109,24 +108,22 @@ namespace aarch64 {
MacroAssembler masm(buf, size + CodeBuffer::kDefaultCapacity, pic); \
SETUP_COMMON()
-#define SETUP_COMMON() \
- masm.SetGenerateSimulatorCode(true); \
- Decoder simulator_decoder; \
- Simulator* simulator = Test::run_debugger() \
- ? new Debugger(&simulator_decoder) \
- : new Simulator(&simulator_decoder); \
- simulator->SetColouredTrace(Test::coloured_trace()); \
- simulator->SetInstructionStats(Test::instruction_stats()); \
- Disassembler disasm; \
- Decoder disassembler_decoder; \
- disassembler_decoder.AppendVisitor(&disasm); \
- RegisterDump core; \
- ptrdiff_t offset_after_infrastructure_start; \
+#define SETUP_COMMON() \
+ masm.SetGenerateSimulatorCode(true); \
+ Decoder simulator_decoder; \
+ Simulator simulator(&simulator_decoder); \
+ simulator.SetColouredTrace(Test::coloured_trace()); \
+ simulator.SetInstructionStats(Test::instruction_stats()); \
+ Disassembler disasm; \
+ Decoder disassembler_decoder; \
+ disassembler_decoder.AppendVisitor(&disasm); \
+ RegisterDump core; \
+ ptrdiff_t offset_after_infrastructure_start; \
ptrdiff_t offset_before_infrastructure_end
#define START() \
masm.Reset(); \
- simulator->ResetState(); \
+ simulator.ResetState(); \
__ PushCalleeSavedRegisters(); \
{ \
int trace_parameters = 0; \
@@ -160,17 +157,13 @@ namespace aarch64 {
#define RUN() \
DISASSEMBLE(); \
- simulator->RunFrom(masm.GetBuffer()->GetStartAddress<Instruction*>())
+ simulator.RunFrom(masm.GetBuffer()->GetStartAddress<Instruction*>())
#define RUN_CUSTOM() RUN()
-#define TEARDOWN() TEARDOWN_COMMON()
-
-#define TEARDOWN_CUSTOM() \
- delete[] buf; \
- TEARDOWN_COMMON()
+#define TEARDOWN()
-#define TEARDOWN_COMMON() delete simulator;
+#define TEARDOWN_CUSTOM() delete[] buf;
#else // ifdef VIXL_INCLUDE_SIMULATOR_AARCH64.
// Run the test on real hardware or models.
@@ -10178,7 +10171,7 @@ static void FmaddFmsubHelper(double n,
TEST(fmadd_fmsub_double) {
// It's hard to check the result of fused operations because the only way to
- // calculate the result is using fma, which is what the simulator uses anyway.
+ // calculate the result is using fma, which is what the Simulator uses anyway.
// Basic operation.
FmaddFmsubHelper(1.0, 2.0, 3.0, 5.0, 1.0, -5.0, -1.0);
@@ -15234,8 +15227,8 @@ TEST(printf_no_preserve) {
#ifndef VIXL_INCLUDE_SIMULATOR_AARCH64
TEST(trace) {
- // The Trace helper should not generate any code unless the simulator (or
- // debugger) is being used.
+ // The Trace helper should not generate any code unless the simulator is being
+ // used.
SETUP();
START();
@@ -15253,8 +15246,8 @@ TEST(trace) {
#ifndef VIXL_INCLUDE_SIMULATOR_AARCH64
TEST(log) {
- // The Log helper should not generate any code unless the simulator (or
- // debugger) is being used.
+ // The Log helper should not generate any code unless the simulator is being
+ // used.
SETUP();
START();
diff --git a/test/aarch64/test-simulator-aarch64.cc b/test/aarch64/test-simulator-aarch64.cc
index 00d833eb..11f53c02 100644
--- a/test/aarch64/test-simulator-aarch64.cc
+++ b/test/aarch64/test-simulator-aarch64.cc
@@ -57,17 +57,16 @@ namespace aarch64 {
#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
-#define SETUP() \
- MacroAssembler masm; \
- Decoder decoder; \
- Simulator* simulator = \
- Test::run_debugger() ? new Debugger(&decoder) : new Simulator(&decoder); \
- simulator->SetColouredTrace(Test::coloured_trace()); \
- simulator->SetInstructionStats(Test::instruction_stats());
+#define SETUP() \
+ MacroAssembler masm; \
+ Decoder decoder; \
+ Simulator simulator(&decoder); \
+ simulator.SetColouredTrace(Test::coloured_trace()); \
+ simulator.SetInstructionStats(Test::instruction_stats());
#define START() \
masm.Reset(); \
- simulator->ResetState(); \
+ simulator.ResetState(); \
__ PushCalleeSavedRegisters(); \
if (Test::trace_reg()) { \
__ Trace(LOG_STATE, TRACE_ENABLE); \
@@ -92,9 +91,9 @@ namespace aarch64 {
masm.FinalizeCode()
#define RUN() \
- simulator->RunFrom(masm.GetBuffer()->GetStartAddress<Instruction*>())
+ simulator.RunFrom(masm.GetBuffer()->GetStartAddress<Instruction*>())
-#define TEARDOWN() delete simulator;
+#define TEARDOWN()
#else // VIXL_INCLUDE_SIMULATOR_AARCH64
@@ -4559,32 +4558,30 @@ TEST(RunFrom) {
// Run a function returning `void` and taking no argument.
int32_t value = 0xbad;
- simulator->RunFrom(GenerateStoreZero(&masm, &value));
+ simulator.RunFrom(GenerateStoreZero(&masm, &value));
VIXL_CHECK(value == 0);
// Run a function returning `void` and taking one argument.
int32_t argument = 0xf00d;
- simulator->RunFrom<void, int32_t>(GenerateStoreInput(&masm, &value),
- argument);
+ simulator.RunFrom<void, int32_t>(GenerateStoreInput(&masm, &value), argument);
VIXL_CHECK(value == 0xf00d);
// Run a function taking one argument and returning a value.
int64_t res_int64_t;
res_int64_t =
- simulator->RunFrom<int64_t, int64_t>(GeneratePow(&masm, 0), 0xbad);
+ simulator.RunFrom<int64_t, int64_t>(GeneratePow(&masm, 0), 0xbad);
VIXL_CHECK(res_int64_t == 1);
- res_int64_t =
- simulator->RunFrom<int64_t, int64_t>(GeneratePow(&masm, 1), 123);
+ res_int64_t = simulator.RunFrom<int64_t, int64_t>(GeneratePow(&masm, 1), 123);
VIXL_CHECK(res_int64_t == 123);
- res_int64_t = simulator->RunFrom<int64_t, int64_t>(GeneratePow(&masm, 10), 2);
+ res_int64_t = simulator.RunFrom<int64_t, int64_t>(GeneratePow(&masm, 10), 2);
VIXL_CHECK(res_int64_t == 1024);
// Run a function taking multiple arguments in registers.
double res_double =
- simulator->RunFrom<double, float, int64_t, double>(GenerateSum(&masm),
- 1.0,
- 2,
- 3.0);
+ simulator.RunFrom<double, float, int64_t, double>(GenerateSum(&masm),
+ 1.0,
+ 2,
+ 3.0);
VIXL_CHECK(res_double == 6.0);
}
#endif
diff --git a/test/aarch64/test-trace-aarch64.cc b/test/aarch64/test-trace-aarch64.cc
index 673161e8..f41dc39b 100644
--- a/test/aarch64/test-trace-aarch64.cc
+++ b/test/aarch64/test-trace-aarch64.cc
@@ -34,7 +34,6 @@
#include "test-utils-aarch64.h"
#include "aarch64/cpu-aarch64.h"
-#include "aarch64/debugger-aarch64.h"
#include "aarch64/disasm-aarch64.h"
#include "aarch64/macro-assembler-aarch64.h"
#include "aarch64/simulator-aarch64.h"
diff --git a/test/test-runner.cc b/test/test-runner.cc
index fc67b64d..b0e1d11b 100644
--- a/test/test-runner.cc
+++ b/test/test-runner.cc
@@ -36,9 +36,6 @@ vixl::Test* vixl::Test::last_ = NULL;
bool vixl::Test::verbose_ = false;
-// No debugger to start with.
-bool vixl::Test::debug_ = false;
-
// No tracing to start with.
bool vixl::Test::trace_sim_ = false;
bool vixl::Test::trace_reg_ = false;
@@ -109,7 +106,6 @@ static void PrintHelpMessage() {
"--list List all available tests.\n"
"--run_all Run all available tests.\n"
"--verbose Print verbose output when available.\n"
- "--debugger Run in the debugger.\n"
"--trace_all "
"Enable all trace options, plus --coloured_trace.\n"
"--trace_sim "
@@ -159,10 +155,6 @@ int main(int argc, char* argv[]) {
vixl::Test::set_verbose(true);
}
- if (IsInArgs("--debugger", argc, argv)) {
- vixl::Test::set_debug(true);
- }
-
if (IsInArgs("--trace-write", argc, argv)) {
vixl::Test::set_trace_write(true);
}
diff --git a/test/test-runner.h b/test/test-runner.h
index 83361054..45303cf0 100644
--- a/test/test-runner.h
+++ b/test/test-runner.h
@@ -46,8 +46,6 @@ class Test {
Test* next() { return next_; }
static bool verbose() { return verbose_; }
static void set_verbose(bool value) { verbose_ = value; }
- static bool debug() { return debug_; }
- static void set_debug(bool value) { debug_ = value; }
static bool trace_sim() { return trace_sim_; }
static void set_trace_sim(bool value) { trace_sim_ = value; }
static bool trace_reg() { return trace_reg_; }
@@ -73,9 +71,6 @@ class Test {
generate_test_trace_ = value;
}
- // The debugger is needed to trace register values.
- static bool run_debugger() { return debug_; }
-
private:
const char* name_;
TestFunction* callback_;
@@ -84,7 +79,6 @@ class Test {
static Test* last_;
Test* next_;
static bool verbose_;
- static bool debug_;
static bool trace_sim_;
static bool trace_reg_;
static bool trace_write_;
diff --git a/tools/test.py b/tools/test.py
index 8300475a..f7dbd067 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -175,17 +175,10 @@ test_build_options = [
build_option_negative_testing
]
-runtime_option_debugger = \
- RuntimeOption('debugger',
- '''Test with the specified configurations for the debugger.
- Note that this is only tested if we are using the simulator.''',
- val_test_choices=['all', 'on', 'off'])
-test_runtime_options = [
- runtime_option_debugger
-]
+test_runtime_options = []
test_options = \
- test_environment_options + test_build_options + test_runtime_options
+ test_environment_options + test_build_options + test_runtime_options
def BuildOptions():
@@ -441,7 +434,6 @@ if __name__ == '__main__':
SetFast(environment_option_compiler, args.compiler, 'clang++')
SetFast(build_option_standard, args.std, 'c++98')
SetFast(build_option_mode, args.mode, 'debug')
- SetFast(runtime_option_debugger, args.debugger, 'on')
if not args.nolint and not (args.fast or args.dry_run):
rc |= RunLinter()
@@ -451,11 +443,6 @@ if __name__ == '__main__':
rc |= RunClangFormat()
MaybeExitEarly(rc)
- # Don't try to test the debugger if we are not running with the simulator.
- if not args.simulator:
- test_runtime_options = \
- filter(lambda x: x.name != 'debugger', test_runtime_options)
-
# List all combinations of options that will be tested.
def ListCombinations(args, options):
opts_list = [