1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
3  */
4 // Copyright 2007-2008 the V8 project authors. All rights reserved.
5 // Use of this source code is governed by a BSD-style license that can be
6 // found in the LICENSE file.
7 
8 #ifndef jit_arm_disasm_Disasm_arm_h
9 #define jit_arm_disasm_Disasm_arm_h
10 
11 #ifdef JS_DISASM_ARM
12 
13 #  include "mozilla/Assertions.h"
14 #  include "mozilla/Types.h"
15 
16 #  include <stdio.h>
17 
18 namespace js {
19 namespace jit {
20 namespace disasm {
21 
22 typedef unsigned char byte;
23 
24 // A reasonable (ie, safe) buffer size for the disassembly of a single
25 // instruction.
26 const int ReasonableBufferSize = 256;
27 
28 // Vector as used by the original code to allow for minimal modification.
29 // Functions exactly like a character array with helper methods.
30 template <typename T>
31 class V8Vector {
32  public:
V8Vector()33   V8Vector() : start_(nullptr), length_(0) {}
V8Vector(T * data,int length)34   V8Vector(T* data, int length) : start_(data), length_(length) {
35     MOZ_ASSERT(length == 0 || (length > 0 && data != nullptr));
36   }
37 
38   // Returns the length of the vector.
length()39   int length() const { return length_; }
40 
41   // Returns the pointer to the start of the data in the vector.
start()42   T* start() const { return start_; }
43 
44   // Access individual vector elements - checks bounds in debug mode.
45   T& operator[](int index) const {
46     MOZ_ASSERT(0 <= index && index < length_);
47     return start_[index];
48   }
49 
50   inline V8Vector<T> operator+(int offset) {
51     MOZ_ASSERT(offset < length_);
52     return V8Vector<T>(start_ + offset, length_ - offset);
53   }
54 
55  private:
56   T* start_;
57   int length_;
58 };
59 
60 template <typename T, int kSize>
61 class EmbeddedVector : public V8Vector<T> {
62  public:
EmbeddedVector()63   EmbeddedVector() : V8Vector<T>(buffer_, kSize) {}
64 
EmbeddedVector(T initial_value)65   explicit EmbeddedVector(T initial_value) : V8Vector<T>(buffer_, kSize) {
66     for (int i = 0; i < kSize; ++i) {
67       buffer_[i] = initial_value;
68     }
69   }
70 
71   // When copying, make underlying Vector to reference our buffer.
EmbeddedVector(const EmbeddedVector & rhs)72   EmbeddedVector(const EmbeddedVector& rhs) : V8Vector<T>(rhs) {
73     MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize);
74     this->set_start(buffer_);
75   }
76 
77   EmbeddedVector& operator=(const EmbeddedVector& rhs) {
78     if (this == &rhs) return *this;
79     V8Vector<T>::operator=(rhs);
80     MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize);
81     this->set_start(buffer_);
82     return *this;
83   }
84 
85  private:
86   T buffer_[kSize];
87 };
88 
89 // Interface and default implementation for converting addresses and
90 // register-numbers to text.  The default implementation is machine
91 // specific.
92 class NameConverter {
93  public:
~NameConverter()94   virtual ~NameConverter() {}
95   virtual const char* NameOfCPURegister(int reg) const;
96   virtual const char* NameOfByteCPURegister(int reg) const;
97   virtual const char* NameOfXMMRegister(int reg) const;
98   virtual const char* NameOfAddress(byte* addr) const;
99   virtual const char* NameOfConstant(byte* addr) const;
100   virtual const char* NameInCode(byte* addr) const;
101 
102  protected:
103   EmbeddedVector<char, 128> tmp_buffer_;
104 };
105 
106 // A generic Disassembler interface
107 class Disassembler {
108  public:
109   // Caller deallocates converter.
110   explicit Disassembler(const NameConverter& converter);
111 
112   virtual ~Disassembler();
113 
114   // Writes one disassembled instruction into 'buffer' (0-terminated).
115   // Returns the length of the disassembled machine instruction in bytes.
116   int InstructionDecode(V8Vector<char> buffer, uint8_t* instruction);
117 
118   // Returns -1 if instruction does not mark the beginning of a constant pool,
119   // or the number of entries in the constant pool beginning here.
120   int ConstantPoolSizeAt(byte* instruction);
121 
122   // Write disassembly into specified file 'f' using specified NameConverter
123   // (see constructor).
124   static void Disassemble(FILE* f, uint8_t* begin, uint8_t* end);
125 
126  private:
127   const NameConverter& converter_;
128 
129   // Disallow implicit constructors.
130   Disassembler() = delete;
131   Disassembler(const Disassembler&) = delete;
132   void operator=(const Disassembler&) = delete;
133 };
134 
135 }  // namespace disasm
136 }  // namespace jit
137 }  // namespace js
138 
139 #endif  // JS_DISASM_ARM
140 
141 #endif  // jit_arm_disasm_Disasm_arm_h
142