1// Copyright 2011 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5
6#ifndef V8_MIPS_REGEXP_MACRO_ASSEMBLER_MIPS_H_
7#define V8_MIPS_REGEXP_MACRO_ASSEMBLER_MIPS_H_
8
9#include "src/macro-assembler.h"
10#include "src/mips64/assembler-mips64-inl.h"
11#include "src/mips64/assembler-mips64.h"
12#include "src/mips64/macro-assembler-mips64.h"
13
14namespace v8 {
15namespace internal {
16
17#ifndef V8_INTERPRETED_REGEXP
18class RegExpMacroAssemblerMIPS: public NativeRegExpMacroAssembler {
19 public:
20  RegExpMacroAssemblerMIPS(Mode mode, int registers_to_save, Zone* zone);
21  virtual ~RegExpMacroAssemblerMIPS();
22  virtual int stack_limit_slack();
23  virtual void AdvanceCurrentPosition(int by);
24  virtual void AdvanceRegister(int reg, int by);
25  virtual void Backtrack();
26  virtual void Bind(Label* label);
27  virtual void CheckAtStart(Label* on_at_start);
28  virtual void CheckCharacter(uint32_t c, Label* on_equal);
29  virtual void CheckCharacterAfterAnd(uint32_t c,
30                                      uint32_t mask,
31                                      Label* on_equal);
32  virtual void CheckCharacterGT(uc16 limit, Label* on_greater);
33  virtual void CheckCharacterLT(uc16 limit, Label* on_less);
34  // A "greedy loop" is a loop that is both greedy and with a simple
35  // body. It has a particularly simple implementation.
36  virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
37  virtual void CheckNotAtStart(Label* on_not_at_start);
38  virtual void CheckNotBackReference(int start_reg, Label* on_no_match);
39  virtual void CheckNotBackReferenceIgnoreCase(int start_reg,
40                                               Label* on_no_match);
41  virtual void CheckNotCharacter(uint32_t c, Label* on_not_equal);
42  virtual void CheckNotCharacterAfterAnd(uint32_t c,
43                                         uint32_t mask,
44                                         Label* on_not_equal);
45  virtual void CheckNotCharacterAfterMinusAnd(uc16 c,
46                                              uc16 minus,
47                                              uc16 mask,
48                                              Label* on_not_equal);
49  virtual void CheckCharacterInRange(uc16 from,
50                                     uc16 to,
51                                     Label* on_in_range);
52  virtual void CheckCharacterNotInRange(uc16 from,
53                                        uc16 to,
54                                        Label* on_not_in_range);
55  virtual void CheckBitInTable(Handle<ByteArray> table, Label* on_bit_set);
56
57  // Checks whether the given offset from the current position is before
58  // the end of the string.
59  virtual void CheckPosition(int cp_offset, Label* on_outside_input);
60  virtual bool CheckSpecialCharacterClass(uc16 type,
61                                          Label* on_no_match);
62  virtual void Fail();
63  virtual Handle<HeapObject> GetCode(Handle<String> source);
64  virtual void GoTo(Label* label);
65  virtual void IfRegisterGE(int reg, int comparand, Label* if_ge);
66  virtual void IfRegisterLT(int reg, int comparand, Label* if_lt);
67  virtual void IfRegisterEqPos(int reg, Label* if_eq);
68  virtual IrregexpImplementation Implementation();
69  virtual void LoadCurrentCharacter(int cp_offset,
70                                    Label* on_end_of_input,
71                                    bool check_bounds = true,
72                                    int characters = 1);
73  virtual void PopCurrentPosition();
74  virtual void PopRegister(int register_index);
75  virtual void PushBacktrack(Label* label);
76  virtual void PushCurrentPosition();
77  virtual void PushRegister(int register_index,
78                            StackCheckFlag check_stack_limit);
79  virtual void ReadCurrentPositionFromRegister(int reg);
80  virtual void ReadStackPointerFromRegister(int reg);
81  virtual void SetCurrentPositionFromEnd(int by);
82  virtual void SetRegister(int register_index, int to);
83  virtual bool Succeed();
84  virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
85  virtual void ClearRegisters(int reg_from, int reg_to);
86  virtual void WriteStackPointerToRegister(int reg);
87  virtual bool CanReadUnaligned();
88
89  // Called from RegExp if the stack-guard is triggered.
90  // If the code object is relocated, the return address is fixed before
91  // returning.
92  static int CheckStackGuardState(Address* return_address,
93                                  Code* re_code,
94                                  Address re_frame);
95
96  void print_regexp_frame_constants();
97
98 private:
99#if defined(MIPS_ABI_N64)
100  // Offsets from frame_pointer() of function parameters and stored registers.
101  static const int kFramePointer = 0;
102
103  // Above the frame pointer - Stored registers and stack passed parameters.
104  // Registers s0 to s7, fp, and ra.
105  static const int kStoredRegisters = kFramePointer;
106  // Return address (stored from link register, read into pc on return).
107
108// TODO(plind): This 9 - is 8 s-regs (s0..s7) plus fp.
109
110  static const int kReturnAddress = kStoredRegisters + 9 * kPointerSize;
111  static const int kSecondaryReturnAddress = kReturnAddress + kPointerSize;
112  // Stack frame header.
113  static const int kStackFrameHeader = kSecondaryReturnAddress;
114  // Stack parameters placed by caller.
115  static const int kIsolate = kStackFrameHeader + kPointerSize;
116
117  // Below the frame pointer.
118  // Register parameters stored by setup code.
119  static const int kDirectCall = kFramePointer - kPointerSize;
120  static const int kStackHighEnd = kDirectCall - kPointerSize;
121  static const int kNumOutputRegisters = kStackHighEnd - kPointerSize;
122  static const int kRegisterOutput = kNumOutputRegisters - kPointerSize;
123  static const int kInputEnd = kRegisterOutput - kPointerSize;
124  static const int kInputStart = kInputEnd - kPointerSize;
125  static const int kStartIndex = kInputStart - kPointerSize;
126  static const int kInputString = kStartIndex - kPointerSize;
127  // When adding local variables remember to push space for them in
128  // the frame in GetCode.
129  static const int kSuccessfulCaptures = kInputString - kPointerSize;
130  static const int kInputStartMinusOne = kSuccessfulCaptures - kPointerSize;
131  // First register address. Following registers are below it on the stack.
132  static const int kRegisterZero = kInputStartMinusOne - kPointerSize;
133
134#elif defined(MIPS_ABI_O32)
135  // Offsets from frame_pointer() of function parameters and stored registers.
136  static const int kFramePointer = 0;
137
138  // Above the frame pointer - Stored registers and stack passed parameters.
139  // Registers s0 to s7, fp, and ra.
140  static const int kStoredRegisters = kFramePointer;
141  // Return address (stored from link register, read into pc on return).
142  static const int kReturnAddress = kStoredRegisters + 9 * kPointerSize;
143  static const int kSecondaryReturnAddress = kReturnAddress + kPointerSize;
144  // Stack frame header.
145  static const int kStackFrameHeader = kReturnAddress + kPointerSize;
146  // Stack parameters placed by caller.
147  static const int kRegisterOutput =
148      kStackFrameHeader + 4 * kPointerSize + kPointerSize;
149  static const int kNumOutputRegisters = kRegisterOutput + kPointerSize;
150  static const int kStackHighEnd = kNumOutputRegisters + kPointerSize;
151  static const int kDirectCall = kStackHighEnd + kPointerSize;
152  static const int kIsolate = kDirectCall + kPointerSize;
153
154  // Below the frame pointer.
155  // Register parameters stored by setup code.
156  static const int kInputEnd = kFramePointer - kPointerSize;
157  static const int kInputStart = kInputEnd - kPointerSize;
158  static const int kStartIndex = kInputStart - kPointerSize;
159  static const int kInputString = kStartIndex - kPointerSize;
160  // When adding local variables remember to push space for them in
161  // the frame in GetCode.
162  static const int kSuccessfulCaptures = kInputString - kPointerSize;
163  static const int kInputStartMinusOne = kSuccessfulCaptures - kPointerSize;
164  // First register address. Following registers are below it on the stack.
165  static const int kRegisterZero = kInputStartMinusOne - kPointerSize;
166
167#else
168# error "undefined MIPS ABI"
169#endif
170
171  // Initial size of code buffer.
172  static const size_t kRegExpCodeSize = 1024;
173
174  // Load a number of characters at the given offset from the
175  // current position, into the current-character register.
176  void LoadCurrentCharacterUnchecked(int cp_offset, int character_count);
177
178  // Check whether preemption has been requested.
179  void CheckPreemption();
180
181  // Check whether we are exceeding the stack limit on the backtrack stack.
182  void CheckStackLimit();
183
184
185  // Generate a call to CheckStackGuardState.
186  void CallCheckStackGuardState(Register scratch);
187
188  // The ebp-relative location of a regexp register.
189  MemOperand register_location(int register_index);
190
191  // Register holding the current input position as negative offset from
192  // the end of the string.
193  inline Register current_input_offset() { return a6; }
194
195  // The register containing the current character after LoadCurrentCharacter.
196  inline Register current_character() { return a7; }
197
198  // Register holding address of the end of the input string.
199  inline Register end_of_input_address() { return t2; }
200
201  // Register holding the frame address. Local variables, parameters and
202  // regexp registers are addressed relative to this.
203  inline Register frame_pointer() { return fp; }
204
205  // The register containing the backtrack stack top. Provides a meaningful
206  // name to the register.
207  inline Register backtrack_stackpointer() { return t0; }
208
209  // Register holding pointer to the current code object.
210  inline Register code_pointer() { return a5; }
211
212  // Byte size of chars in the string to match (decided by the Mode argument).
213  inline int char_size() { return static_cast<int>(mode_); }
214
215  // Equivalent to a conditional branch to the label, unless the label
216  // is NULL, in which case it is a conditional Backtrack.
217  void BranchOrBacktrack(Label* to,
218                         Condition condition,
219                         Register rs,
220                         const Operand& rt);
221
222  // Call and return internally in the generated code in a way that
223  // is GC-safe (i.e., doesn't leave absolute code addresses on the stack)
224  inline void SafeCall(Label* to,
225                       Condition cond,
226                       Register rs,
227                       const Operand& rt);
228  inline void SafeReturn();
229  inline void SafeCallTarget(Label* name);
230
231  // Pushes the value of a register on the backtrack stack. Decrements the
232  // stack pointer by a word size and stores the register's value there.
233  inline void Push(Register source);
234
235  // Pops a value from the backtrack stack. Reads the word at the stack pointer
236  // and increments it by a word size.
237  inline void Pop(Register target);
238
239  Isolate* isolate() const { return masm_->isolate(); }
240
241  MacroAssembler* masm_;
242
243  // Which mode to generate code for (Latin1 or UC16).
244  Mode mode_;
245
246  // One greater than maximal register index actually used.
247  int num_registers_;
248
249  // Number of registers to output at the end (the saved registers
250  // are always 0..num_saved_registers_-1).
251  int num_saved_registers_;
252
253  // Labels used internally.
254  Label entry_label_;
255  Label start_label_;
256  Label success_label_;
257  Label backtrack_label_;
258  Label exit_label_;
259  Label check_preempt_label_;
260  Label stack_overflow_label_;
261  Label internal_failure_label_;
262};
263
264#endif  // V8_INTERPRETED_REGEXP
265
266
267}}  // namespace v8::internal
268
269#endif  // V8_MIPS_REGEXP_MACRO_ASSEMBLER_MIPS_H_
270