OLD | NEW |
1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
2 // All Rights Reserved. | 2 // All Rights Reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
10 // | 10 // |
(...skipping 19 matching lines...) Expand all Loading... |
30 | 30 |
31 // The original source code covered by the above license above has been | 31 // The original source code covered by the above license above has been |
32 // modified significantly by Google Inc. | 32 // modified significantly by Google Inc. |
33 // Copyright 2012 the V8 project authors. All rights reserved. | 33 // Copyright 2012 the V8 project authors. All rights reserved. |
34 | 34 |
35 | 35 |
36 #ifndef V8_MIPS_ASSEMBLER_MIPS_H_ | 36 #ifndef V8_MIPS_ASSEMBLER_MIPS_H_ |
37 #define V8_MIPS_ASSEMBLER_MIPS_H_ | 37 #define V8_MIPS_ASSEMBLER_MIPS_H_ |
38 | 38 |
39 #include <stdio.h> | 39 #include <stdio.h> |
40 | |
41 #include "src/assembler.h" | 40 #include "src/assembler.h" |
42 #include "src/mips/constants-mips.h" | 41 #include "src/mips64/constants-mips64.h" |
43 #include "src/serialize.h" | 42 #include "src/serialize.h" |
44 | 43 |
45 namespace v8 { | 44 namespace v8 { |
46 namespace internal { | 45 namespace internal { |
47 | 46 |
48 // CPU Registers. | 47 // CPU Registers. |
49 // | 48 // |
50 // 1) We would prefer to use an enum, but enum values are assignment- | 49 // 1) We would prefer to use an enum, but enum values are assignment- |
51 // compatible with int, which has caused code-generation bugs. | 50 // compatible with int, which has caused code-generation bugs. |
52 // | 51 // |
(...skipping 14 matching lines...) Expand all Loading... |
67 // and best performance in optimized code. | 66 // and best performance in optimized code. |
68 | 67 |
69 | 68 |
70 // ----------------------------------------------------------------------------- | 69 // ----------------------------------------------------------------------------- |
71 // Implementation of Register and FPURegister. | 70 // Implementation of Register and FPURegister. |
72 | 71 |
73 // Core register. | 72 // Core register. |
74 struct Register { | 73 struct Register { |
75 static const int kNumRegisters = v8::internal::kNumRegisters; | 74 static const int kNumRegisters = v8::internal::kNumRegisters; |
76 static const int kMaxNumAllocatableRegisters = 14; // v0 through t6 and cp. | 75 static const int kMaxNumAllocatableRegisters = 14; // v0 through t6 and cp. |
77 static const int kSizeInBytes = 4; | 76 static const int kSizeInBytes = 8; |
78 static const int kCpRegister = 23; // cp (s7) is the 23rd register. | 77 static const int kCpRegister = 23; // cp (s7) is the 23rd register. |
79 | 78 |
80 #if defined(V8_TARGET_LITTLE_ENDIAN) | |
81 static const int kMantissaOffset = 0; | |
82 static const int kExponentOffset = 4; | |
83 #elif defined(V8_TARGET_BIG_ENDIAN) | |
84 static const int kMantissaOffset = 4; | |
85 static const int kExponentOffset = 0; | |
86 #else | |
87 #error Unknown endianness | |
88 #endif | |
89 | |
90 inline static int NumAllocatableRegisters(); | 79 inline static int NumAllocatableRegisters(); |
91 | 80 |
92 static int ToAllocationIndex(Register reg) { | 81 static int ToAllocationIndex(Register reg) { |
93 ASSERT((reg.code() - 2) < (kMaxNumAllocatableRegisters - 1) || | 82 ASSERT((reg.code() - 2) < (kMaxNumAllocatableRegisters - 1) || |
94 reg.is(from_code(kCpRegister))); | 83 reg.is(from_code(kCpRegister))); |
95 return reg.is(from_code(kCpRegister)) ? | 84 return reg.is(from_code(kCpRegister)) ? |
96 kMaxNumAllocatableRegisters - 1 : // Return last index for 'cp'. | 85 kMaxNumAllocatableRegisters - 1 : // Return last index for 'cp'. |
97 reg.code() - 2; // zero_reg and 'at' are skipped. | 86 reg.code() - 2; // zero_reg and 'at' are skipped. |
98 } | 87 } |
99 | 88 |
100 static Register FromAllocationIndex(int index) { | 89 static Register FromAllocationIndex(int index) { |
101 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); | 90 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); |
102 return index == kMaxNumAllocatableRegisters - 1 ? | 91 return index == kMaxNumAllocatableRegisters - 1 ? |
103 from_code(kCpRegister) : // Last index is always the 'cp' register. | 92 from_code(kCpRegister) : // Last index is always the 'cp' register. |
104 from_code(index + 2); // zero_reg and 'at' are skipped. | 93 from_code(index + 2); // zero_reg and 'at' are skipped. |
105 } | 94 } |
106 | 95 |
107 static const char* AllocationIndexToString(int index) { | 96 static const char* AllocationIndexToString(int index) { |
108 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); | 97 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); |
109 const char* const names[] = { | 98 const char* const names[] = { |
110 "v0", | 99 "v0", |
111 "v1", | 100 "v1", |
112 "a0", | 101 "a0", |
113 "a1", | 102 "a1", |
114 "a2", | 103 "a2", |
115 "a3", | 104 "a3", |
| 105 "a4", |
| 106 "a5", |
| 107 "a6", |
| 108 "a7", |
116 "t0", | 109 "t0", |
117 "t1", | 110 "t1", |
118 "t2", | 111 "t2", |
119 "t3", | |
120 "t4", | |
121 "t5", | |
122 "t6", | |
123 "s7", | 112 "s7", |
124 }; | 113 }; |
125 return names[index]; | 114 return names[index]; |
126 } | 115 } |
127 | 116 |
128 static Register from_code(int code) { | 117 static Register from_code(int code) { |
129 Register r = { code }; | 118 Register r = { code }; |
130 return r; | 119 return r; |
131 } | 120 } |
132 | 121 |
(...skipping 22 matching lines...) Expand all Loading... |
155 // at: Reserved for synthetic instructions. | 144 // at: Reserved for synthetic instructions. |
156 REGISTER(at, 1); | 145 REGISTER(at, 1); |
157 // v0, v1: Used when returning multiple values from subroutines. | 146 // v0, v1: Used when returning multiple values from subroutines. |
158 REGISTER(v0, 2); | 147 REGISTER(v0, 2); |
159 REGISTER(v1, 3); | 148 REGISTER(v1, 3); |
160 // a0 - a4: Used to pass non-FP parameters. | 149 // a0 - a4: Used to pass non-FP parameters. |
161 REGISTER(a0, 4); | 150 REGISTER(a0, 4); |
162 REGISTER(a1, 5); | 151 REGISTER(a1, 5); |
163 REGISTER(a2, 6); | 152 REGISTER(a2, 6); |
164 REGISTER(a3, 7); | 153 REGISTER(a3, 7); |
165 // t0 - t9: Can be used without reservation, act as temporary registers and are | 154 // a4 - a7 t0 - t3: Can be used without reservation, act as temporary registers |
166 // allowed to be destroyed by subroutines. | 155 // and are allowed to be destroyed by subroutines. |
167 REGISTER(t0, 8); | 156 REGISTER(a4, 8); |
168 REGISTER(t1, 9); | 157 REGISTER(a5, 9); |
169 REGISTER(t2, 10); | 158 REGISTER(a6, 10); |
170 REGISTER(t3, 11); | 159 REGISTER(a7, 11); |
171 REGISTER(t4, 12); | 160 REGISTER(t0, 12); |
172 REGISTER(t5, 13); | 161 REGISTER(t1, 13); |
173 REGISTER(t6, 14); | 162 REGISTER(t2, 14); |
174 REGISTER(t7, 15); | 163 REGISTER(t3, 15); |
175 // s0 - s7: Subroutine register variables. Subroutines that write to these | 164 // s0 - s7: Subroutine register variables. Subroutines that write to these |
176 // registers must restore their values before exiting so that the caller can | 165 // registers must restore their values before exiting so that the caller can |
177 // expect the values to be preserved. | 166 // expect the values to be preserved. |
178 REGISTER(s0, 16); | 167 REGISTER(s0, 16); |
179 REGISTER(s1, 17); | 168 REGISTER(s1, 17); |
180 REGISTER(s2, 18); | 169 REGISTER(s2, 18); |
181 REGISTER(s3, 19); | 170 REGISTER(s3, 19); |
182 REGISTER(s4, 20); | 171 REGISTER(s4, 20); |
183 REGISTER(s5, 21); | 172 REGISTER(s5, 21); |
184 REGISTER(s6, 22); | 173 REGISTER(s6, 22); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 } | 220 } |
232 | 221 |
233 static FPURegister from_code(int code) { | 222 static FPURegister from_code(int code) { |
234 FPURegister r = { code }; | 223 FPURegister r = { code }; |
235 return r; | 224 return r; |
236 } | 225 } |
237 | 226 |
238 bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters ; } | 227 bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters ; } |
239 bool is(FPURegister creg) const { return code_ == creg.code_; } | 228 bool is(FPURegister creg) const { return code_ == creg.code_; } |
240 FPURegister low() const { | 229 FPURegister low() const { |
| 230 // TODO(plind): Create ASSERT for FR=0 mode. This usage suspect for FR=1. |
241 // Find low reg of a Double-reg pair, which is the reg itself. | 231 // Find low reg of a Double-reg pair, which is the reg itself. |
242 ASSERT(code_ % 2 == 0); // Specified Double reg must be even. | 232 ASSERT(code_ % 2 == 0); // Specified Double reg must be even. |
243 FPURegister reg; | 233 FPURegister reg; |
244 reg.code_ = code_; | 234 reg.code_ = code_; |
245 ASSERT(reg.is_valid()); | 235 ASSERT(reg.is_valid()); |
246 return reg; | 236 return reg; |
247 } | 237 } |
248 FPURegister high() const { | 238 FPURegister high() const { |
| 239 // TODO(plind): Create ASSERT for FR=0 mode. This usage illegal in FR=1. |
249 // Find high reg of a Doubel-reg pair, which is reg + 1. | 240 // Find high reg of a Doubel-reg pair, which is reg + 1. |
250 ASSERT(code_ % 2 == 0); // Specified Double reg must be even. | 241 ASSERT(code_ % 2 == 0); // Specified Double reg must be even. |
251 FPURegister reg; | 242 FPURegister reg; |
252 reg.code_ = code_ + 1; | 243 reg.code_ = code_ + 1; |
253 ASSERT(reg.is_valid()); | 244 ASSERT(reg.is_valid()); |
254 return reg; | 245 return reg; |
255 } | 246 } |
256 | 247 |
257 int code() const { | 248 int code() const { |
258 ASSERT(is_valid()); | 249 ASSERT(is_valid()); |
259 return code_; | 250 return code_; |
260 } | 251 } |
261 int bit() const { | 252 int bit() const { |
262 ASSERT(is_valid()); | 253 ASSERT(is_valid()); |
263 return 1 << code_; | 254 return 1 << code_; |
264 } | 255 } |
265 void setcode(int f) { | 256 void setcode(int f) { |
266 code_ = f; | 257 code_ = f; |
267 ASSERT(is_valid()); | 258 ASSERT(is_valid()); |
268 } | 259 } |
269 // Unfortunately we can't make this private in a struct. | 260 // Unfortunately we can't make this private in a struct. |
270 int code_; | 261 int code_; |
271 }; | 262 }; |
272 | 263 |
273 // V8 now supports the O32 ABI, and the FPU Registers are organized as 32 | 264 // V8 now supports the O32 ABI, and the FPU Registers are organized as 32 |
274 // 32-bit registers, f0 through f31. When used as 'double' they are used | 265 // 32-bit registers, f0 through f31. When used as 'double' they are used |
275 // in pairs, starting with the even numbered register. So a double operation | 266 // in pairs, starting with the even numbered register. So a double operation |
276 // on f0 really uses f0 and f1. | 267 // on f0 really uses f0 and f1. |
277 // (Modern mips hardware also supports 32 64-bit registers, via setting | 268 // (Modern mips hardware also supports 32 64-bit registers, via setting |
278 // (priviledged) Status Register FR bit to 1. This is used by the N32 ABI, | 269 // (privileged) Status Register FR bit to 1. This is used by the N32 ABI, |
279 // but it is not in common use. Someday we will want to support this in v8.) | 270 // but it is not in common use. Someday we will want to support this in v8.) |
280 | 271 |
281 // For O32 ABI, Floats and Doubles refer to same set of 32 32-bit registers. | 272 // For O32 ABI, Floats and Doubles refer to same set of 32 32-bit registers. |
282 typedef FPURegister DoubleRegister; | 273 typedef FPURegister DoubleRegister; |
283 typedef FPURegister FloatRegister; | 274 typedef FPURegister FloatRegister; |
284 | 275 |
285 const FPURegister no_freg = { -1 }; | 276 const FPURegister no_freg = { -1 }; |
286 | 277 |
287 const FPURegister f0 = { 0 }; // Return value in hard float mode. | 278 const FPURegister f0 = { 0 }; // Return value in hard float mode. |
288 const FPURegister f1 = { 1 }; | 279 const FPURegister f1 = { 1 }; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 // Unfortunately we can't make this private in a struct. | 340 // Unfortunately we can't make this private in a struct. |
350 int code_; | 341 int code_; |
351 }; | 342 }; |
352 | 343 |
353 const FPUControlRegister no_fpucreg = { kInvalidFPUControlRegister }; | 344 const FPUControlRegister no_fpucreg = { kInvalidFPUControlRegister }; |
354 const FPUControlRegister FCSR = { kFCSRRegister }; | 345 const FPUControlRegister FCSR = { kFCSRRegister }; |
355 | 346 |
356 | 347 |
357 // ----------------------------------------------------------------------------- | 348 // ----------------------------------------------------------------------------- |
358 // Machine instruction Operands. | 349 // Machine instruction Operands. |
359 | 350 const int kSmiShift = kSmiTagSize + kSmiShiftSize; |
| 351 const uint64_t kSmiShiftMask = (1UL << kSmiShift) - 1; |
360 // Class Operand represents a shifter operand in data processing instructions. | 352 // Class Operand represents a shifter operand in data processing instructions. |
361 class Operand BASE_EMBEDDED { | 353 class Operand BASE_EMBEDDED { |
362 public: | 354 public: |
363 // Immediate. | 355 // Immediate. |
364 INLINE(explicit Operand(int32_t immediate, | 356 INLINE(explicit Operand(int64_t immediate, |
365 RelocInfo::Mode rmode = RelocInfo::NONE32)); | 357 RelocInfo::Mode rmode = RelocInfo::NONE64)); |
366 INLINE(explicit Operand(const ExternalReference& f)); | 358 INLINE(explicit Operand(const ExternalReference& f)); |
367 INLINE(explicit Operand(const char* s)); | 359 INLINE(explicit Operand(const char* s)); |
368 INLINE(explicit Operand(Object** opp)); | 360 INLINE(explicit Operand(Object** opp)); |
369 INLINE(explicit Operand(Context** cpp)); | 361 INLINE(explicit Operand(Context** cpp)); |
370 explicit Operand(Handle<Object> handle); | 362 explicit Operand(Handle<Object> handle); |
371 INLINE(explicit Operand(Smi* value)); | 363 INLINE(explicit Operand(Smi* value)); |
372 | 364 |
373 // Register. | 365 // Register. |
374 INLINE(explicit Operand(Register rm)); | 366 INLINE(explicit Operand(Register rm)); |
375 | 367 |
376 // Return true if this is a register operand. | 368 // Return true if this is a register operand. |
377 INLINE(bool is_reg() const); | 369 INLINE(bool is_reg() const); |
378 | 370 |
379 inline int32_t immediate() const { | 371 inline int64_t immediate() const { |
380 ASSERT(!is_reg()); | 372 ASSERT(!is_reg()); |
381 return imm32_; | 373 return imm64_; |
382 } | 374 } |
383 | 375 |
384 Register rm() const { return rm_; } | 376 Register rm() const { return rm_; } |
385 | 377 |
386 private: | 378 private: |
387 Register rm_; | 379 Register rm_; |
388 int32_t imm32_; // Valid if rm_ == no_reg. | 380 int64_t imm64_; // Valid if rm_ == no_reg. |
389 RelocInfo::Mode rmode_; | 381 RelocInfo::Mode rmode_; |
390 | 382 |
391 friend class Assembler; | 383 friend class Assembler; |
392 friend class MacroAssembler; | 384 friend class MacroAssembler; |
393 }; | 385 }; |
394 | 386 |
395 | 387 |
396 // On MIPS we have only one adressing mode with base_reg + offset. | 388 // On MIPS we have only one adressing mode with base_reg + offset. |
397 // Class MemOperand represents a memory operand in load and store instructions. | 389 // Class MemOperand represents a memory operand in load and store instructions. |
398 class MemOperand : public Operand { | 390 class MemOperand : public Operand { |
399 public: | 391 public: |
400 // Immediate value attached to offset. | 392 // Immediate value attached to offset. |
401 enum OffsetAddend { | 393 enum OffsetAddend { |
402 offset_minus_one = -1, | 394 offset_minus_one = -1, |
403 offset_zero = 0 | 395 offset_zero = 0 |
404 }; | 396 }; |
405 | 397 |
406 explicit MemOperand(Register rn, int32_t offset = 0); | 398 explicit MemOperand(Register rn, int64_t offset = 0); |
407 explicit MemOperand(Register rn, int32_t unit, int32_t multiplier, | 399 explicit MemOperand(Register rn, int64_t unit, int64_t multiplier, |
408 OffsetAddend offset_addend = offset_zero); | 400 OffsetAddend offset_addend = offset_zero); |
409 int32_t offset() const { return offset_; } | 401 int32_t offset() const { return offset_; } |
410 | 402 |
411 bool OffsetIsInt16Encodable() const { | 403 bool OffsetIsInt16Encodable() const { |
412 return is_int16(offset_); | 404 return is_int16(offset_); |
413 } | 405 } |
414 | 406 |
415 private: | 407 private: |
416 int32_t offset_; | 408 int32_t offset_; |
417 | 409 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 | 455 |
464 // Returns the branch offset to the given label from the current code | 456 // Returns the branch offset to the given label from the current code |
465 // position. Links the label to the current position if it is still unbound. | 457 // position. Links the label to the current position if it is still unbound. |
466 // Manages the jump elimination optimization if the second parameter is true. | 458 // Manages the jump elimination optimization if the second parameter is true. |
467 int32_t branch_offset(Label* L, bool jump_elimination_allowed); | 459 int32_t branch_offset(Label* L, bool jump_elimination_allowed); |
468 int32_t shifted_branch_offset(Label* L, bool jump_elimination_allowed) { | 460 int32_t shifted_branch_offset(Label* L, bool jump_elimination_allowed) { |
469 int32_t o = branch_offset(L, jump_elimination_allowed); | 461 int32_t o = branch_offset(L, jump_elimination_allowed); |
470 ASSERT((o & 3) == 0); // Assert the offset is aligned. | 462 ASSERT((o & 3) == 0); // Assert the offset is aligned. |
471 return o >> 2; | 463 return o >> 2; |
472 } | 464 } |
473 uint32_t jump_address(Label* L); | 465 uint64_t jump_address(Label* L); |
474 | 466 |
475 // Puts a labels target address at the given position. | 467 // Puts a labels target address at the given position. |
476 // The high 8 bits are set to zero. | 468 // The high 8 bits are set to zero. |
477 void label_at_put(Label* L, int at_offset); | 469 void label_at_put(Label* L, int at_offset); |
478 | 470 |
479 // Read/Modify the code target address in the branch/call instruction at pc. | 471 // Read/Modify the code target address in the branch/call instruction at pc. |
480 static Address target_address_at(Address pc); | 472 static Address target_address_at(Address pc); |
481 static void set_target_address_at(Address pc, | 473 static void set_target_address_at(Address pc, |
482 Address target, | 474 Address target, |
483 ICacheFlushMode icache_flush_mode = | 475 ICacheFlushMode icache_flush_mode = |
(...skipping 30 matching lines...) Expand all Loading... |
514 static void JumpLabelToJumpRegister(Address pc); | 506 static void JumpLabelToJumpRegister(Address pc); |
515 | 507 |
516 static void QuietNaN(HeapObject* nan); | 508 static void QuietNaN(HeapObject* nan); |
517 | 509 |
518 // This sets the branch destination (which gets loaded at the call address). | 510 // This sets the branch destination (which gets loaded at the call address). |
519 // This is for calls and branches within generated code. The serializer | 511 // This is for calls and branches within generated code. The serializer |
520 // has already deserialized the lui/ori instructions etc. | 512 // has already deserialized the lui/ori instructions etc. |
521 inline static void deserialization_set_special_target_at( | 513 inline static void deserialization_set_special_target_at( |
522 Address instruction_payload, Code* code, Address target) { | 514 Address instruction_payload, Code* code, Address target) { |
523 set_target_address_at( | 515 set_target_address_at( |
524 instruction_payload - kInstructionsFor32BitConstant * kInstrSize, | 516 instruction_payload - kInstructionsFor64BitConstant * kInstrSize, |
525 code, | 517 code, |
526 target); | 518 target); |
527 } | 519 } |
528 | 520 |
529 // Size of an instruction. | 521 // Size of an instruction. |
530 static const int kInstrSize = sizeof(Instr); | 522 static const int kInstrSize = sizeof(Instr); |
531 | 523 |
532 // Difference between address of current opcode and target address offset. | 524 // Difference between address of current opcode and target address offset. |
533 static const int kBranchPCOffset = 4; | 525 static const int kBranchPCOffset = 4; |
534 | 526 |
535 // Here we are patching the address in the LUI/ORI instruction pair. | 527 // Here we are patching the address in the LUI/ORI instruction pair. |
536 // These values are used in the serialization process and must be zero for | 528 // These values are used in the serialization process and must be zero for |
537 // MIPS platform, as Code, Embedded Object or External-reference pointers | 529 // MIPS platform, as Code, Embedded Object or External-reference pointers |
538 // are split across two consecutive instructions and don't exist separately | 530 // are split across two consecutive instructions and don't exist separately |
539 // in the code, so the serializer should not step forwards in memory after | 531 // in the code, so the serializer should not step forwards in memory after |
540 // a target is resolved and written. | 532 // a target is resolved and written. |
541 static const int kSpecialTargetSize = 0; | 533 static const int kSpecialTargetSize = 0; |
542 | 534 |
543 // Number of consecutive instructions used to store 32bit constant. | 535 // Number of consecutive instructions used to store 32bit/64bit constant. |
544 // Before jump-optimizations, this constant was used in | 536 // Before jump-optimizations, this constant was used in |
545 // RelocInfo::target_address_address() function to tell serializer address of | 537 // RelocInfo::target_address_address() function to tell serializer address of |
546 // the instruction that follows LUI/ORI instruction pair. Now, with new jump | 538 // the instruction that follows LUI/ORI instruction pair. Now, with new jump |
547 // optimization, where jump-through-register instruction that usually | 539 // optimization, where jump-through-register instruction that usually |
548 // follows LUI/ORI pair is substituted with J/JAL, this constant equals | 540 // follows LUI/ORI pair is substituted with J/JAL, this constant equals |
549 // to 3 instructions (LUI+ORI+J/JAL/JR/JALR). | 541 // to 3 instructions (LUI+ORI+J/JAL/JR/JALR). |
550 static const int kInstructionsFor32BitConstant = 3; | 542 static const int kInstructionsFor32BitConstant = 3; |
| 543 static const int kInstructionsFor64BitConstant = 5; |
551 | 544 |
552 // Distance between the instruction referring to the address of the call | 545 // Distance between the instruction referring to the address of the call |
553 // target and the return address. | 546 // target and the return address. |
554 static const int kCallTargetAddressOffset = 4 * kInstrSize; | 547 static const int kCallTargetAddressOffset = 6 * kInstrSize; |
555 | 548 |
556 // Distance between start of patched return sequence and the emitted address | 549 // Distance between start of patched return sequence and the emitted address |
557 // to jump to. | 550 // to jump to. |
558 static const int kPatchReturnSequenceAddressOffset = 0; | 551 static const int kPatchReturnSequenceAddressOffset = 0; |
559 | 552 |
560 // Distance between start of patched debug break slot and the emitted address | 553 // Distance between start of patched debug break slot and the emitted address |
561 // to jump to. | 554 // to jump to. |
562 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize; | 555 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize; |
563 | 556 |
564 // Difference between address of current opcode and value read from pc | 557 // Difference between address of current opcode and value read from pc |
565 // register. | 558 // register. |
566 static const int kPcLoadDelta = 4; | 559 static const int kPcLoadDelta = 4; |
567 | 560 |
568 static const int kPatchDebugBreakSlotReturnOffset = 4 * kInstrSize; | 561 static const int kPatchDebugBreakSlotReturnOffset = 6 * kInstrSize; |
569 | 562 |
570 // Number of instructions used for the JS return sequence. The constant is | 563 // Number of instructions used for the JS return sequence. The constant is |
571 // used by the debugger to patch the JS return sequence. | 564 // used by the debugger to patch the JS return sequence. |
572 static const int kJSReturnSequenceInstructions = 7; | 565 static const int kJSReturnSequenceInstructions = 7; |
573 static const int kDebugBreakSlotInstructions = 4; | 566 static const int kDebugBreakSlotInstructions = 6; |
574 static const int kDebugBreakSlotLength = | 567 static const int kDebugBreakSlotLength = |
575 kDebugBreakSlotInstructions * kInstrSize; | 568 kDebugBreakSlotInstructions * kInstrSize; |
576 | 569 |
577 | 570 |
578 // --------------------------------------------------------------------------- | 571 // --------------------------------------------------------------------------- |
579 // Code generation. | 572 // Code generation. |
580 | 573 |
581 // Insert the smallest number of nop instructions | 574 // Insert the smallest number of nop instructions |
582 // possible to align the pc offset to a multiple | 575 // possible to align the pc offset to a multiple |
583 // of m. m must be a power of 2 (>= 4). | 576 // of m. m must be a power of 2 (>= 4). |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
631 void bltzal(Register rs, int16_t offset); | 624 void bltzal(Register rs, int16_t offset); |
632 void bne(Register rs, Register rt, int16_t offset); | 625 void bne(Register rs, Register rt, int16_t offset); |
633 void bne(Register rs, Register rt, Label* L) { | 626 void bne(Register rs, Register rt, Label* L) { |
634 bne(rs, rt, branch_offset(L, false)>>2); | 627 bne(rs, rt, branch_offset(L, false)>>2); |
635 } | 628 } |
636 | 629 |
637 // Never use the int16_t b(l)cond version with a branch offset | 630 // Never use the int16_t b(l)cond version with a branch offset |
638 // instead of using the Label* version. | 631 // instead of using the Label* version. |
639 | 632 |
640 // Jump targets must be in the current 256 MB-aligned region. i.e. 28 bits. | 633 // Jump targets must be in the current 256 MB-aligned region. i.e. 28 bits. |
641 void j(int32_t target); | 634 void j(int64_t target); |
642 void jal(int32_t target); | 635 void jal(int64_t target); |
643 void jalr(Register rs, Register rd = ra); | 636 void jalr(Register rs, Register rd = ra); |
644 void jr(Register target); | 637 void jr(Register target); |
645 void j_or_jr(int32_t target, Register rs); | 638 void j_or_jr(int64_t target, Register rs); |
646 void jal_or_jalr(int32_t target, Register rs); | 639 void jal_or_jalr(int64_t target, Register rs); |
647 | 640 |
648 | 641 |
649 // -------Data-processing-instructions--------- | 642 // -------Data-processing-instructions--------- |
650 | 643 |
651 // Arithmetic. | 644 // Arithmetic. |
652 void addu(Register rd, Register rs, Register rt); | 645 void addu(Register rd, Register rs, Register rt); |
653 void subu(Register rd, Register rs, Register rt); | 646 void subu(Register rd, Register rs, Register rt); |
654 void mult(Register rs, Register rt); | 647 void mult(Register rs, Register rt); |
655 void multu(Register rs, Register rt); | 648 void multu(Register rs, Register rt); |
656 void div(Register rs, Register rt); | 649 void div(Register rs, Register rt); |
657 void divu(Register rs, Register rt); | 650 void divu(Register rs, Register rt); |
658 void mul(Register rd, Register rs, Register rt); | 651 void mul(Register rd, Register rs, Register rt); |
| 652 void daddu(Register rd, Register rs, Register rt); |
| 653 void dsubu(Register rd, Register rs, Register rt); |
| 654 void dmult(Register rs, Register rt); |
| 655 void dmultu(Register rs, Register rt); |
| 656 void ddiv(Register rs, Register rt); |
| 657 void ddivu(Register rs, Register rt); |
659 | 658 |
660 void addiu(Register rd, Register rs, int32_t j); | 659 void addiu(Register rd, Register rs, int32_t j); |
| 660 void daddiu(Register rd, Register rs, int32_t j); |
661 | 661 |
662 // Logical. | 662 // Logical. |
663 void and_(Register rd, Register rs, Register rt); | 663 void and_(Register rd, Register rs, Register rt); |
664 void or_(Register rd, Register rs, Register rt); | 664 void or_(Register rd, Register rs, Register rt); |
665 void xor_(Register rd, Register rs, Register rt); | 665 void xor_(Register rd, Register rs, Register rt); |
666 void nor(Register rd, Register rs, Register rt); | 666 void nor(Register rd, Register rs, Register rt); |
667 | 667 |
668 void andi(Register rd, Register rs, int32_t j); | 668 void andi(Register rd, Register rs, int32_t j); |
669 void ori(Register rd, Register rs, int32_t j); | 669 void ori(Register rd, Register rs, int32_t j); |
670 void xori(Register rd, Register rs, int32_t j); | 670 void xori(Register rd, Register rs, int32_t j); |
671 void lui(Register rd, int32_t j); | 671 void lui(Register rd, int32_t j); |
672 | 672 |
673 // Shifts. | 673 // Shifts. |
674 // Please note: sll(zero_reg, zero_reg, x) instructions are reserved as nop | 674 // Please note: sll(zero_reg, zero_reg, x) instructions are reserved as nop |
675 // and may cause problems in normal code. coming_from_nop makes sure this | 675 // and may cause problems in normal code. coming_from_nop makes sure this |
676 // doesn't happen. | 676 // doesn't happen. |
677 void sll(Register rd, Register rt, uint16_t sa, bool coming_from_nop = false); | 677 void sll(Register rd, Register rt, uint16_t sa, bool coming_from_nop = false); |
678 void sllv(Register rd, Register rt, Register rs); | 678 void sllv(Register rd, Register rt, Register rs); |
679 void srl(Register rd, Register rt, uint16_t sa); | 679 void srl(Register rd, Register rt, uint16_t sa); |
680 void srlv(Register rd, Register rt, Register rs); | 680 void srlv(Register rd, Register rt, Register rs); |
681 void sra(Register rt, Register rd, uint16_t sa); | 681 void sra(Register rt, Register rd, uint16_t sa); |
682 void srav(Register rt, Register rd, Register rs); | 682 void srav(Register rt, Register rd, Register rs); |
683 void rotr(Register rd, Register rt, uint16_t sa); | 683 void rotr(Register rd, Register rt, uint16_t sa); |
684 void rotrv(Register rd, Register rt, Register rs); | 684 void rotrv(Register rd, Register rt, Register rs); |
| 685 void dsll(Register rd, Register rt, uint16_t sa); |
| 686 void dsllv(Register rd, Register rt, Register rs); |
| 687 void dsrl(Register rd, Register rt, uint16_t sa); |
| 688 void dsrlv(Register rd, Register rt, Register rs); |
| 689 void drotr(Register rd, Register rt, uint16_t sa); |
| 690 void drotrv(Register rd, Register rt, Register rs); |
| 691 void dsra(Register rt, Register rd, uint16_t sa); |
| 692 void dsrav(Register rd, Register rt, Register rs); |
| 693 void dsll32(Register rt, Register rd, uint16_t sa); |
| 694 void dsrl32(Register rt, Register rd, uint16_t sa); |
| 695 void dsra32(Register rt, Register rd, uint16_t sa); |
685 | 696 |
686 | 697 |
687 // ------------Memory-instructions------------- | 698 // ------------Memory-instructions------------- |
688 | 699 |
689 void lb(Register rd, const MemOperand& rs); | 700 void lb(Register rd, const MemOperand& rs); |
690 void lbu(Register rd, const MemOperand& rs); | 701 void lbu(Register rd, const MemOperand& rs); |
691 void lh(Register rd, const MemOperand& rs); | 702 void lh(Register rd, const MemOperand& rs); |
692 void lhu(Register rd, const MemOperand& rs); | 703 void lhu(Register rd, const MemOperand& rs); |
693 void lw(Register rd, const MemOperand& rs); | 704 void lw(Register rd, const MemOperand& rs); |
| 705 void lwu(Register rd, const MemOperand& rs); |
694 void lwl(Register rd, const MemOperand& rs); | 706 void lwl(Register rd, const MemOperand& rs); |
695 void lwr(Register rd, const MemOperand& rs); | 707 void lwr(Register rd, const MemOperand& rs); |
696 void sb(Register rd, const MemOperand& rs); | 708 void sb(Register rd, const MemOperand& rs); |
697 void sh(Register rd, const MemOperand& rs); | 709 void sh(Register rd, const MemOperand& rs); |
698 void sw(Register rd, const MemOperand& rs); | 710 void sw(Register rd, const MemOperand& rs); |
699 void swl(Register rd, const MemOperand& rs); | 711 void swl(Register rd, const MemOperand& rs); |
700 void swr(Register rd, const MemOperand& rs); | 712 void swr(Register rd, const MemOperand& rs); |
| 713 void ldl(Register rd, const MemOperand& rs); |
| 714 void ldr(Register rd, const MemOperand& rs); |
| 715 void sdl(Register rd, const MemOperand& rs); |
| 716 void sdr(Register rd, const MemOperand& rs); |
| 717 void ld(Register rd, const MemOperand& rs); |
| 718 void sd(Register rd, const MemOperand& rs); |
701 | 719 |
702 | 720 |
703 // ----------------Prefetch-------------------- | 721 // ----------------Prefetch-------------------- |
704 | 722 |
705 void pref(int32_t hint, const MemOperand& rs); | 723 void pref(int32_t hint, const MemOperand& rs); |
706 | 724 |
707 | 725 |
708 // -------------Misc-instructions-------------- | 726 // -------------Misc-instructions-------------- |
709 | 727 |
710 // Break / Trap instructions. | 728 // Break / Trap instructions. |
(...skipping 30 matching lines...) Expand all Loading... |
741 // --------Coprocessor-instructions---------------- | 759 // --------Coprocessor-instructions---------------- |
742 | 760 |
743 // Load, store, and move. | 761 // Load, store, and move. |
744 void lwc1(FPURegister fd, const MemOperand& src); | 762 void lwc1(FPURegister fd, const MemOperand& src); |
745 void ldc1(FPURegister fd, const MemOperand& src); | 763 void ldc1(FPURegister fd, const MemOperand& src); |
746 | 764 |
747 void swc1(FPURegister fs, const MemOperand& dst); | 765 void swc1(FPURegister fs, const MemOperand& dst); |
748 void sdc1(FPURegister fs, const MemOperand& dst); | 766 void sdc1(FPURegister fs, const MemOperand& dst); |
749 | 767 |
750 void mtc1(Register rt, FPURegister fs); | 768 void mtc1(Register rt, FPURegister fs); |
| 769 void mthc1(Register rt, FPURegister fs); |
| 770 void dmtc1(Register rt, FPURegister fs); |
| 771 |
751 void mfc1(Register rt, FPURegister fs); | 772 void mfc1(Register rt, FPURegister fs); |
| 773 void mfhc1(Register rt, FPURegister fs); |
| 774 void dmfc1(Register rt, FPURegister fs); |
752 | 775 |
753 void ctc1(Register rt, FPUControlRegister fs); | 776 void ctc1(Register rt, FPUControlRegister fs); |
754 void cfc1(Register rt, FPUControlRegister fs); | 777 void cfc1(Register rt, FPUControlRegister fs); |
755 | 778 |
756 // Arithmetic. | 779 // Arithmetic. |
757 void add_d(FPURegister fd, FPURegister fs, FPURegister ft); | 780 void add_d(FPURegister fd, FPURegister fs, FPURegister ft); |
758 void sub_d(FPURegister fd, FPURegister fs, FPURegister ft); | 781 void sub_d(FPURegister fd, FPURegister fs, FPURegister ft); |
759 void mul_d(FPURegister fd, FPURegister fs, FPURegister ft); | 782 void mul_d(FPURegister fd, FPURegister fs, FPURegister ft); |
760 void madd_d(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft); | 783 void madd_d(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft); |
761 void div_d(FPURegister fd, FPURegister fs, FPURegister ft); | 784 void div_d(FPURegister fd, FPURegister fs, FPURegister ft); |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
970 | 993 |
971 // Generate the constant pool for the generated code. | 994 // Generate the constant pool for the generated code. |
972 void PopulateConstantPool(ConstantPoolArray* constant_pool); | 995 void PopulateConstantPool(ConstantPoolArray* constant_pool); |
973 | 996 |
974 protected: | 997 protected: |
975 // Relocation for a type-recording IC has the AST id added to it. This | 998 // Relocation for a type-recording IC has the AST id added to it. This |
976 // member variable is a way to pass the information from the call site to | 999 // member variable is a way to pass the information from the call site to |
977 // the relocation info. | 1000 // the relocation info. |
978 TypeFeedbackId recorded_ast_id_; | 1001 TypeFeedbackId recorded_ast_id_; |
979 | 1002 |
980 int32_t buffer_space() const { return reloc_info_writer.pos() - pc_; } | 1003 int64_t buffer_space() const { return reloc_info_writer.pos() - pc_; } |
981 | 1004 |
982 // Decode branch instruction at pos and return branch target pos. | 1005 // Decode branch instruction at pos and return branch target pos. |
983 int target_at(int32_t pos); | 1006 int64_t target_at(int64_t pos); |
984 | 1007 |
985 // Patch branch instruction at pos to branch to given branch target pos. | 1008 // Patch branch instruction at pos to branch to given branch target pos. |
986 void target_at_put(int32_t pos, int32_t target_pos); | 1009 void target_at_put(int64_t pos, int64_t target_pos); |
987 | 1010 |
988 // Say if we need to relocate with this mode. | 1011 // Say if we need to relocate with this mode. |
989 bool MustUseReg(RelocInfo::Mode rmode); | 1012 bool MustUseReg(RelocInfo::Mode rmode); |
990 | 1013 |
991 // Record reloc info for current pc_. | 1014 // Record reloc info for current pc_. |
992 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); | 1015 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); |
993 | 1016 |
994 // Block the emission of the trampoline pool before pc_offset. | 1017 // Block the emission of the trampoline pool before pc_offset. |
995 void BlockTrampolinePoolBefore(int pc_offset) { | 1018 void BlockTrampolinePoolBefore(int pc_offset) { |
996 if (no_trampoline_pool_before_ < pc_offset) | 1019 if (no_trampoline_pool_before_ < pc_offset) |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1070 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; | 1093 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; |
1071 RelocInfoWriter reloc_info_writer; | 1094 RelocInfoWriter reloc_info_writer; |
1072 | 1095 |
1073 // The bound position, before this we cannot do instruction elimination. | 1096 // The bound position, before this we cannot do instruction elimination. |
1074 int last_bound_pos_; | 1097 int last_bound_pos_; |
1075 | 1098 |
1076 // Code emission. | 1099 // Code emission. |
1077 inline void CheckBuffer(); | 1100 inline void CheckBuffer(); |
1078 void GrowBuffer(); | 1101 void GrowBuffer(); |
1079 inline void emit(Instr x); | 1102 inline void emit(Instr x); |
| 1103 inline void emit(uint64_t x); |
1080 inline void CheckTrampolinePoolQuick(); | 1104 inline void CheckTrampolinePoolQuick(); |
1081 | 1105 |
1082 // Instruction generation. | 1106 // Instruction generation. |
1083 // We have 3 different kind of encoding layout on MIPS. | 1107 // We have 3 different kind of encoding layout on MIPS. |
1084 // However due to many different types of objects encoded in the same fields | 1108 // However due to many different types of objects encoded in the same fields |
1085 // we have quite a few aliases for each mode. | 1109 // we have quite a few aliases for each mode. |
1086 // Using the same structure to refer to Register and FPURegister would spare a | 1110 // Using the same structure to refer to Register and FPURegister would spare a |
1087 // few aliases, but mixing both does not look clean to me. | 1111 // few aliases, but mixing both does not look clean to me. |
1088 // Anyway we could surely implement this differently. | 1112 // Anyway we could surely implement this differently. |
1089 | 1113 |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1206 }; | 1230 }; |
1207 | 1231 |
1208 int32_t get_trampoline_entry(int32_t pos); | 1232 int32_t get_trampoline_entry(int32_t pos); |
1209 int unbound_labels_count_; | 1233 int unbound_labels_count_; |
1210 // If trampoline is emitted, generated code is becoming large. As this is | 1234 // If trampoline is emitted, generated code is becoming large. As this is |
1211 // already a slow case which can possibly break our code generation for the | 1235 // already a slow case which can possibly break our code generation for the |
1212 // extreme case, we use this information to trigger different mode of | 1236 // extreme case, we use this information to trigger different mode of |
1213 // branch instruction generation, where we use jump instructions rather | 1237 // branch instruction generation, where we use jump instructions rather |
1214 // than regular branch instructions. | 1238 // than regular branch instructions. |
1215 bool trampoline_emitted_; | 1239 bool trampoline_emitted_; |
1216 static const int kTrampolineSlotsSize = 4 * kInstrSize; | 1240 static const int kTrampolineSlotsSize = 6 * kInstrSize; |
1217 static const int kMaxBranchOffset = (1 << (18 - 1)) - 1; | 1241 static const int kMaxBranchOffset = (1 << (18 - 1)) - 1; |
1218 static const int kInvalidSlotPos = -1; | 1242 static const int kInvalidSlotPos = -1; |
1219 | 1243 |
1220 Trampoline trampoline_; | 1244 Trampoline trampoline_; |
1221 bool internal_trampoline_exception_; | 1245 bool internal_trampoline_exception_; |
1222 | 1246 |
1223 friend class RegExpMacroAssemblerMIPS; | 1247 friend class RegExpMacroAssemblerMIPS; |
1224 friend class RelocInfo; | 1248 friend class RelocInfo; |
1225 friend class CodePatcher; | 1249 friend class CodePatcher; |
1226 friend class BlockTrampolinePoolScope; | 1250 friend class BlockTrampolinePoolScope; |
1227 | 1251 |
1228 PositionsRecorder positions_recorder_; | 1252 PositionsRecorder positions_recorder_; |
1229 friend class PositionsRecorder; | 1253 friend class PositionsRecorder; |
1230 friend class EnsureSpace; | 1254 friend class EnsureSpace; |
1231 }; | 1255 }; |
1232 | 1256 |
1233 | 1257 |
1234 class EnsureSpace BASE_EMBEDDED { | 1258 class EnsureSpace BASE_EMBEDDED { |
1235 public: | 1259 public: |
1236 explicit EnsureSpace(Assembler* assembler) { | 1260 explicit EnsureSpace(Assembler* assembler) { |
1237 assembler->CheckBuffer(); | 1261 assembler->CheckBuffer(); |
1238 } | 1262 } |
1239 }; | 1263 }; |
1240 | 1264 |
1241 } } // namespace v8::internal | 1265 } } // namespace v8::internal |
1242 | 1266 |
1243 #endif // V8_ARM_ASSEMBLER_MIPS_H_ | 1267 #endif // V8_ARM_ASSEMBLER_MIPS_H_ |
OLD | NEW |