Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(268)

Side by Side Diff: src/mips/assembler-mips.cc

Issue 7060010: Merge bleeding edge into the GC branch up to 7948. The asserts (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/mips/assembler-mips.h ('k') | src/mips/assembler-mips-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 12 matching lines...) Expand all
23 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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 2010 the V8 project authors. All rights reserved. 33 // Copyright 2011 the V8 project authors. All rights reserved.
34 34
35 35
36 #include "v8.h" 36 #include "v8.h"
37 37
38 #if defined(V8_TARGET_ARCH_MIPS) 38 #if defined(V8_TARGET_ARCH_MIPS)
39 39
40 #include "mips/assembler-mips-inl.h" 40 #include "mips/assembler-mips-inl.h"
41 #include "serialize.h" 41 #include "serialize.h"
42 42
43 namespace v8 { 43 namespace v8 {
44 namespace internal { 44 namespace internal {
45 45
46 CpuFeatures::CpuFeatures() 46 #ifdef DEBUG
47 : supported_(0), 47 bool CpuFeatures::initialized_ = false;
48 enabled_(0), 48 #endif
49 found_by_runtime_probing_(0) { 49 unsigned CpuFeatures::supported_ = 0;
50 } 50 unsigned CpuFeatures::found_by_runtime_probing_ = 0;
51 51
52 void CpuFeatures::Probe(bool portable) { 52 void CpuFeatures::Probe() {
53 ASSERT(!initialized_);
54 #ifdef DEBUG
55 initialized_ = true;
56 #endif
53 // If the compiler is allowed to use fpu then we can use fpu too in our 57 // If the compiler is allowed to use fpu then we can use fpu too in our
54 // code generation. 58 // code generation.
55 #if !defined(__mips__) 59 #if !defined(__mips__)
56 // For the simulator=mips build, use FPU when FLAG_enable_fpu is enabled. 60 // For the simulator=mips build, use FPU when FLAG_enable_fpu is enabled.
57 if (FLAG_enable_fpu) { 61 if (FLAG_enable_fpu) {
58 supported_ |= 1u << FPU; 62 supported_ |= 1u << FPU;
59 } 63 }
60 #else 64 #else
61 if (portable && Serializer::enabled()) { 65 if (Serializer::enabled()) {
62 supported_ |= OS::CpuFeaturesImpliedByPlatform(); 66 supported_ |= OS::CpuFeaturesImpliedByPlatform();
63 return; // No features if we might serialize. 67 return; // No features if we might serialize.
64 } 68 }
65 69
66 if (OS::MipsCpuHasFeature(FPU)) { 70 if (OS::MipsCpuHasFeature(FPU)) {
67 // This implementation also sets the FPU flags if 71 // This implementation also sets the FPU flags if
68 // runtime detection of FPU returns true. 72 // runtime detection of FPU returns true.
69 supported_ |= 1u << FPU; 73 supported_ |= 1u << FPU;
70 found_by_runtime_probing_ |= 1u << FPU; 74 found_by_runtime_probing_ |= 1u << FPU;
71 } 75 }
72
73 if (!portable) found_by_runtime_probing_ = 0;
74 #endif 76 #endif
75 } 77 }
76 78
77 79
78 int ToNumber(Register reg) { 80 int ToNumber(Register reg) {
79 ASSERT(reg.is_valid()); 81 ASSERT(reg.is_valid());
80 const int kNumbers[] = { 82 const int kNumbers[] = {
81 0, // zero_reg 83 0, // zero_reg
82 1, // at 84 1, // at
83 2, // v0 85 2, // v0
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 const Instr kRtMask = kRtFieldMask; 230 const Instr kRtMask = kRtFieldMask;
229 const Instr kLwSwInstrTypeMask = 0xffe00000; 231 const Instr kLwSwInstrTypeMask = 0xffe00000;
230 const Instr kLwSwInstrArgumentMask = ~kLwSwInstrTypeMask; 232 const Instr kLwSwInstrArgumentMask = ~kLwSwInstrTypeMask;
231 const Instr kLwSwOffsetMask = kImm16Mask; 233 const Instr kLwSwOffsetMask = kImm16Mask;
232 234
233 235
234 // Spare buffer. 236 // Spare buffer.
235 static const int kMinimalBufferSize = 4 * KB; 237 static const int kMinimalBufferSize = 4 * KB;
236 238
237 239
238 Assembler::Assembler(void* buffer, int buffer_size) 240 Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size)
239 : AssemblerBase(Isolate::Current()), 241 : AssemblerBase(arg_isolate),
240 positions_recorder_(this), 242 positions_recorder_(this),
241 allow_peephole_optimization_(false) { 243 emit_debug_code_(FLAG_debug_code) {
242 // BUG(3245989): disable peephole optimization if crankshaft is enabled.
243 allow_peephole_optimization_ = FLAG_peephole_optimization;
244 if (buffer == NULL) { 244 if (buffer == NULL) {
245 // Do our own buffer management. 245 // Do our own buffer management.
246 if (buffer_size <= kMinimalBufferSize) { 246 if (buffer_size <= kMinimalBufferSize) {
247 buffer_size = kMinimalBufferSize; 247 buffer_size = kMinimalBufferSize;
248 248
249 if (isolate()->assembler_spare_buffer() != NULL) { 249 if (isolate()->assembler_spare_buffer() != NULL) {
250 buffer = isolate()->assembler_spare_buffer(); 250 buffer = isolate()->assembler_spare_buffer();
251 isolate()->set_assembler_spare_buffer(NULL); 251 isolate()->set_assembler_spare_buffer(NULL);
252 } 252 }
253 } 253 }
(...skipping 15 matching lines...) Expand all
269 269
270 // Setup buffer pointers. 270 // Setup buffer pointers.
271 ASSERT(buffer_ != NULL); 271 ASSERT(buffer_ != NULL);
272 pc_ = buffer_; 272 pc_ = buffer_;
273 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); 273 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
274 274
275 last_trampoline_pool_end_ = 0; 275 last_trampoline_pool_end_ = 0;
276 no_trampoline_pool_before_ = 0; 276 no_trampoline_pool_before_ = 0;
277 trampoline_pool_blocked_nesting_ = 0; 277 trampoline_pool_blocked_nesting_ = 0;
278 next_buffer_check_ = kMaxBranchOffset - kTrampolineSize; 278 next_buffer_check_ = kMaxBranchOffset - kTrampolineSize;
279 internal_trampoline_exception_ = false;
280 last_bound_pos_ = 0;
281
282 ast_id_for_reloc_info_ = kNoASTId;
279 } 283 }
280 284
281 285
282 Assembler::~Assembler() { 286 Assembler::~Assembler() {
283 if (own_buffer_) { 287 if (own_buffer_) {
284 if (isolate()->assembler_spare_buffer() == NULL && 288 if (isolate()->assembler_spare_buffer() == NULL &&
285 buffer_size_ == kMinimalBufferSize) { 289 buffer_size_ == kMinimalBufferSize) {
286 isolate()->set_assembler_spare_buffer(buffer_); 290 isolate()->set_assembler_spare_buffer(buffer_);
287 } else { 291 } else {
288 DeleteArray(buffer_); 292 DeleteArray(buffer_);
289 } 293 }
290 } 294 }
291 } 295 }
292 296
293 297
294 void Assembler::GetCode(CodeDesc* desc) { 298 void Assembler::GetCode(CodeDesc* desc) {
295 ASSERT(pc_ <= reloc_info_writer.pos()); // No overlap. 299 ASSERT(pc_ <= reloc_info_writer.pos()); // No overlap.
(...skipping 13 matching lines...) Expand all
309 } 313 }
310 314
311 315
312 void Assembler::CodeTargetAlign() { 316 void Assembler::CodeTargetAlign() {
313 // No advantage to aligning branch/call targets to more than 317 // No advantage to aligning branch/call targets to more than
314 // single instruction, that I am aware of. 318 // single instruction, that I am aware of.
315 Align(4); 319 Align(4);
316 } 320 }
317 321
318 322
319 Register Assembler::GetRt(Instr instr) { 323 Register Assembler::GetRtReg(Instr instr) {
320 Register rt; 324 Register rt;
321 rt.code_ = (instr & kRtMask) >> kRtShift; 325 rt.code_ = (instr & kRtFieldMask) >> kRtShift;
322 return rt; 326 return rt;
323 } 327 }
324 328
325 329
330 Register Assembler::GetRsReg(Instr instr) {
331 Register rs;
332 rs.code_ = (instr & kRsFieldMask) >> kRsShift;
333 return rs;
334 }
335
336
337 Register Assembler::GetRdReg(Instr instr) {
338 Register rd;
339 rd.code_ = (instr & kRdFieldMask) >> kRdShift;
340 return rd;
341 }
342
343
344 uint32_t Assembler::GetRt(Instr instr) {
345 return (instr & kRtFieldMask) >> kRtShift;
346 }
347
348
349 uint32_t Assembler::GetRtField(Instr instr) {
350 return instr & kRtFieldMask;
351 }
352
353
354 uint32_t Assembler::GetRs(Instr instr) {
355 return (instr & kRsFieldMask) >> kRsShift;
356 }
357
358
359 uint32_t Assembler::GetRsField(Instr instr) {
360 return instr & kRsFieldMask;
361 }
362
363
364 uint32_t Assembler::GetRd(Instr instr) {
365 return (instr & kRdFieldMask) >> kRdShift;
366 }
367
368
369 uint32_t Assembler::GetRdField(Instr instr) {
370 return instr & kRdFieldMask;
371 }
372
373
374 uint32_t Assembler::GetSa(Instr instr) {
375 return (instr & kSaFieldMask) >> kSaShift;
376 }
377
378
379 uint32_t Assembler::GetSaField(Instr instr) {
380 return instr & kSaFieldMask;
381 }
382
383
384 uint32_t Assembler::GetOpcodeField(Instr instr) {
385 return instr & kOpcodeMask;
386 }
387
388
389 uint32_t Assembler::GetImmediate16(Instr instr) {
390 return instr & kImm16Mask;
391 }
392
393
394 uint32_t Assembler::GetLabelConst(Instr instr) {
395 return instr & ~kImm16Mask;
396 }
397
398
326 bool Assembler::IsPop(Instr instr) { 399 bool Assembler::IsPop(Instr instr) {
327 return (instr & ~kRtMask) == kPopRegPattern; 400 return (instr & ~kRtMask) == kPopRegPattern;
328 } 401 }
329 402
330 403
331 bool Assembler::IsPush(Instr instr) { 404 bool Assembler::IsPush(Instr instr) {
332 return (instr & ~kRtMask) == kPushRegPattern; 405 return (instr & ~kRtMask) == kPushRegPattern;
333 } 406 }
334 407
335 408
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 440
368 // The link chain is terminated by a value in the instruction of -1, 441 // The link chain is terminated by a value in the instruction of -1,
369 // which is an otherwise illegal value (branch -1 is inf loop). 442 // which is an otherwise illegal value (branch -1 is inf loop).
370 // The instruction 16-bit offset field addresses 32-bit words, but in 443 // The instruction 16-bit offset field addresses 32-bit words, but in
371 // code is conv to an 18-bit value addressing bytes, hence the -4 value. 444 // code is conv to an 18-bit value addressing bytes, hence the -4 value.
372 445
373 const int kEndOfChain = -4; 446 const int kEndOfChain = -4;
374 447
375 448
376 bool Assembler::IsBranch(Instr instr) { 449 bool Assembler::IsBranch(Instr instr) {
377 uint32_t opcode = ((instr & kOpcodeMask)); 450 uint32_t opcode = GetOpcodeField(instr);
378 uint32_t rt_field = ((instr & kRtFieldMask)); 451 uint32_t rt_field = GetRtField(instr);
379 uint32_t rs_field = ((instr & kRsFieldMask)); 452 uint32_t rs_field = GetRsField(instr);
380 uint32_t label_constant = (instr & ~kImm16Mask); 453 uint32_t label_constant = GetLabelConst(instr);
381 // Checks if the instruction is a branch. 454 // Checks if the instruction is a branch.
382 return opcode == BEQ || 455 return opcode == BEQ ||
383 opcode == BNE || 456 opcode == BNE ||
384 opcode == BLEZ || 457 opcode == BLEZ ||
385 opcode == BGTZ || 458 opcode == BGTZ ||
386 opcode == BEQL || 459 opcode == BEQL ||
387 opcode == BNEL || 460 opcode == BNEL ||
388 opcode == BLEZL || 461 opcode == BLEZL ||
389 opcode == BGTZL|| 462 opcode == BGTZL ||
390 (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ || 463 (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ ||
391 rt_field == BLTZAL || rt_field == BGEZAL)) || 464 rt_field == BLTZAL || rt_field == BGEZAL)) ||
392 (opcode == COP1 && rs_field == BC1) || // Coprocessor branch. 465 (opcode == COP1 && rs_field == BC1) || // Coprocessor branch.
393 label_constant == 0; // Emitted label const in reg-exp engine. 466 label_constant == 0; // Emitted label const in reg-exp engine.
394 } 467 }
395 468
396 469
470 bool Assembler::IsBeq(Instr instr) {
471 return GetOpcodeField(instr) == BEQ;
472 }
473
474
475 bool Assembler::IsBne(Instr instr) {
476 return GetOpcodeField(instr) == BNE;
477 }
478
479
397 bool Assembler::IsNop(Instr instr, unsigned int type) { 480 bool Assembler::IsNop(Instr instr, unsigned int type) {
398 // See Assembler::nop(type). 481 // See Assembler::nop(type).
399 ASSERT(type < 32); 482 ASSERT(type < 32);
400 uint32_t opcode = ((instr & kOpcodeMask)); 483 uint32_t opcode = GetOpcodeField(instr);
401 uint32_t rt = ((instr & kRtFieldMask) >> kRtShift); 484 uint32_t rt = GetRt(instr);
402 uint32_t rs = ((instr & kRsFieldMask) >> kRsShift); 485 uint32_t rs = GetRs(instr);
403 uint32_t sa = ((instr & kSaFieldMask) >> kSaShift); 486 uint32_t sa = GetSa(instr);
404 487
405 // nop(type) == sll(zero_reg, zero_reg, type); 488 // nop(type) == sll(zero_reg, zero_reg, type);
406 // Technically all these values will be 0 but 489 // Technically all these values will be 0 but
407 // this makes more sense to the reader. 490 // this makes more sense to the reader.
408 491
409 bool ret = (opcode == SLL && 492 bool ret = (opcode == SLL &&
410 rt == static_cast<uint32_t>(ToNumber(zero_reg)) && 493 rt == static_cast<uint32_t>(ToNumber(zero_reg)) &&
411 rs == static_cast<uint32_t>(ToNumber(zero_reg)) && 494 rs == static_cast<uint32_t>(ToNumber(zero_reg)) &&
412 sa == type); 495 sa == type);
413 496
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 return ((instr & kOpcodeMask) == ADDIU); 541 return ((instr & kOpcodeMask) == ADDIU);
459 } 542 }
460 543
461 544
462 Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) { 545 Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) {
463 ASSERT(IsAddImmediate(instr)); 546 ASSERT(IsAddImmediate(instr));
464 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); 547 return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
465 } 548 }
466 549
467 550
551 bool Assembler::IsAndImmediate(Instr instr) {
552 return GetOpcodeField(instr) == ANDI;
553 }
554
555
468 int Assembler::target_at(int32_t pos) { 556 int Assembler::target_at(int32_t pos) {
469 Instr instr = instr_at(pos); 557 Instr instr = instr_at(pos);
470 if ((instr & ~kImm16Mask) == 0) { 558 if ((instr & ~kImm16Mask) == 0) {
471 // Emitted label constant, not part of a branch. 559 // Emitted label constant, not part of a branch.
472 if (instr == 0) { 560 if (instr == 0) {
473 return kEndOfChain; 561 return kEndOfChain;
474 } else { 562 } else {
475 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; 563 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
476 return (imm18 + pos); 564 return (imm18 + pos);
477 } 565 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 627
540 void Assembler::bind_to(Label* L, int pos) { 628 void Assembler::bind_to(Label* L, int pos) {
541 ASSERT(0 <= pos && pos <= pc_offset()); // Must have valid binding position. 629 ASSERT(0 <= pos && pos <= pc_offset()); // Must have valid binding position.
542 while (L->is_linked()) { 630 while (L->is_linked()) {
543 int32_t fixup_pos = L->pos(); 631 int32_t fixup_pos = L->pos();
544 int32_t dist = pos - fixup_pos; 632 int32_t dist = pos - fixup_pos;
545 next(L); // Call next before overwriting link with target at fixup_pos. 633 next(L); // Call next before overwriting link with target at fixup_pos.
546 if (dist > kMaxBranchOffset) { 634 if (dist > kMaxBranchOffset) {
547 do { 635 do {
548 int32_t trampoline_pos = get_trampoline_entry(fixup_pos); 636 int32_t trampoline_pos = get_trampoline_entry(fixup_pos);
637 if (kInvalidSlotPos == trampoline_pos) {
638 // Internal error.
639 return;
640 }
549 ASSERT((trampoline_pos - fixup_pos) <= kMaxBranchOffset); 641 ASSERT((trampoline_pos - fixup_pos) <= kMaxBranchOffset);
550 target_at_put(fixup_pos, trampoline_pos); 642 target_at_put(fixup_pos, trampoline_pos);
551 fixup_pos = trampoline_pos; 643 fixup_pos = trampoline_pos;
552 dist = pos - fixup_pos; 644 dist = pos - fixup_pos;
553 } while (dist > kMaxBranchOffset); 645 } while (dist > kMaxBranchOffset);
554 } else if (dist < -kMaxBranchOffset) { 646 } else if (dist < -kMaxBranchOffset) {
555 do { 647 do {
556 int32_t trampoline_pos = get_trampoline_entry(fixup_pos, false); 648 int32_t trampoline_pos = get_trampoline_entry(fixup_pos, false);
649 if (kInvalidSlotPos == trampoline_pos) {
650 // Internal error.
651 return;
652 }
557 ASSERT((trampoline_pos - fixup_pos) >= -kMaxBranchOffset); 653 ASSERT((trampoline_pos - fixup_pos) >= -kMaxBranchOffset);
558 target_at_put(fixup_pos, trampoline_pos); 654 target_at_put(fixup_pos, trampoline_pos);
559 fixup_pos = trampoline_pos; 655 fixup_pos = trampoline_pos;
560 dist = pos - fixup_pos; 656 dist = pos - fixup_pos;
561 } while (dist < -kMaxBranchOffset); 657 } while (dist < -kMaxBranchOffset);
562 }; 658 };
563 target_at_put(fixup_pos, pos); 659 target_at_put(fixup_pos, pos);
564 } 660 }
565 L->bind_to(pos); 661 L->bind_to(pos);
566 662
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
645 } 741 }
646 742
647 743
648 void Assembler::GenInstrRegister(Opcode opcode, 744 void Assembler::GenInstrRegister(Opcode opcode,
649 SecondaryField fmt, 745 SecondaryField fmt,
650 FPURegister ft, 746 FPURegister ft,
651 FPURegister fs, 747 FPURegister fs,
652 FPURegister fd, 748 FPURegister fd,
653 SecondaryField func) { 749 SecondaryField func) {
654 ASSERT(fd.is_valid() && fs.is_valid() && ft.is_valid()); 750 ASSERT(fd.is_valid() && fs.is_valid() && ft.is_valid());
655 ASSERT(isolate()->cpu_features()->IsEnabled(FPU)); 751 ASSERT(CpuFeatures::IsEnabled(FPU));
656 Instr instr = opcode | fmt | (ft.code() << kFtShift) | (fs.code() << kFsShift) 752 Instr instr = opcode | fmt | (ft.code() << kFtShift) | (fs.code() << kFsShift)
657 | (fd.code() << kFdShift) | func; 753 | (fd.code() << kFdShift) | func;
658 emit(instr); 754 emit(instr);
659 } 755 }
660 756
661 757
662 void Assembler::GenInstrRegister(Opcode opcode, 758 void Assembler::GenInstrRegister(Opcode opcode,
663 SecondaryField fmt, 759 SecondaryField fmt,
664 Register rt, 760 Register rt,
665 FPURegister fs, 761 FPURegister fs,
666 FPURegister fd, 762 FPURegister fd,
667 SecondaryField func) { 763 SecondaryField func) {
668 ASSERT(fd.is_valid() && fs.is_valid() && rt.is_valid()); 764 ASSERT(fd.is_valid() && fs.is_valid() && rt.is_valid());
669 ASSERT(isolate()->cpu_features()->IsEnabled(FPU)); 765 ASSERT(CpuFeatures::IsEnabled(FPU));
670 Instr instr = opcode | fmt | (rt.code() << kRtShift) 766 Instr instr = opcode | fmt | (rt.code() << kRtShift)
671 | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func; 767 | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
672 emit(instr); 768 emit(instr);
673 } 769 }
674 770
675 771
676 void Assembler::GenInstrRegister(Opcode opcode, 772 void Assembler::GenInstrRegister(Opcode opcode,
677 SecondaryField fmt, 773 SecondaryField fmt,
678 Register rt, 774 Register rt,
679 FPUControlRegister fs, 775 FPUControlRegister fs,
680 SecondaryField func) { 776 SecondaryField func) {
681 ASSERT(fs.is_valid() && rt.is_valid()); 777 ASSERT(fs.is_valid() && rt.is_valid());
682 ASSERT(isolate()->cpu_features()->IsEnabled(FPU)); 778 ASSERT(CpuFeatures::IsEnabled(FPU));
683 Instr instr = 779 Instr instr =
684 opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func; 780 opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func;
685 emit(instr); 781 emit(instr);
686 } 782 }
687 783
688 784
689 // Instructions with immediate value. 785 // Instructions with immediate value.
690 // Registers are in the order of the instruction encoding, from left to right. 786 // Registers are in the order of the instruction encoding, from left to right.
691 void Assembler::GenInstrImmediate(Opcode opcode, 787 void Assembler::GenInstrImmediate(Opcode opcode,
692 Register rs, 788 Register rs,
(...skipping 14 matching lines...) Expand all
707 Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask); 803 Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask);
708 emit(instr); 804 emit(instr);
709 } 805 }
710 806
711 807
712 void Assembler::GenInstrImmediate(Opcode opcode, 808 void Assembler::GenInstrImmediate(Opcode opcode,
713 Register rs, 809 Register rs,
714 FPURegister ft, 810 FPURegister ft,
715 int32_t j) { 811 int32_t j) {
716 ASSERT(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j))); 812 ASSERT(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j)));
717 ASSERT(isolate()->cpu_features()->IsEnabled(FPU)); 813 ASSERT(CpuFeatures::IsEnabled(FPU));
718 Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift) 814 Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift)
719 | (j & kImm16Mask); 815 | (j & kImm16Mask);
720 emit(instr); 816 emit(instr);
721 } 817 }
722 818
723 819
724 // Registers are in the order of the instruction encoding, from left to right. 820 // Registers are in the order of the instruction encoding, from left to right.
725 void Assembler::GenInstrJump(Opcode opcode, 821 void Assembler::GenInstrJump(Opcode opcode,
726 uint32_t address) { 822 uint32_t address) {
727 BlockTrampolinePoolScope block_trampoline_pool(this); 823 BlockTrampolinePoolScope block_trampoline_pool(this);
(...skipping 25 matching lines...) Expand all
753 } 849 }
754 } 850 }
755 } 851 }
756 return label_entry; 852 return label_entry;
757 } 853 }
758 854
759 855
760 // Returns the next free trampoline entry from the next trampoline pool. 856 // Returns the next free trampoline entry from the next trampoline pool.
761 int32_t Assembler::get_trampoline_entry(int32_t pos, bool next_pool) { 857 int32_t Assembler::get_trampoline_entry(int32_t pos, bool next_pool) {
762 int trampoline_count = trampolines_.length(); 858 int trampoline_count = trampolines_.length();
763 int32_t trampoline_entry = 0; 859 int32_t trampoline_entry = kInvalidSlotPos;
764 ASSERT(trampoline_count > 0); 860 ASSERT(trampoline_count > 0);
765 861
766 if (next_pool) { 862 if (!internal_trampoline_exception_) {
767 for (int i = 0; i < trampoline_count; i++) { 863 if (next_pool) {
768 if (trampolines_[i].start() > pos) { 864 for (int i = 0; i < trampoline_count; i++) {
769 trampoline_entry = trampolines_[i].take_slot(); 865 if (trampolines_[i].start() > pos) {
770 break; 866 trampoline_entry = trampolines_[i].take_slot();
867 break;
868 }
869 }
870 } else { // Caller needs a trampoline entry from the previous pool.
871 for (int i = trampoline_count-1; i >= 0; i--) {
872 if (trampolines_[i].end() < pos) {
873 trampoline_entry = trampolines_[i].take_slot();
874 break;
875 }
771 } 876 }
772 } 877 }
773 } else { // Caller needs a trampoline entry from the previous pool. 878 if (kInvalidSlotPos == trampoline_entry) {
774 for (int i = trampoline_count-1; i >= 0; i--) { 879 internal_trampoline_exception_ = true;
775 if (trampolines_[i].end() < pos) {
776 trampoline_entry = trampolines_[i].take_slot();
777 break;
778 }
779 } 880 }
780 } 881 }
781 return trampoline_entry; 882 return trampoline_entry;
782 } 883 }
783 884
784 885
785 int32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { 886 int32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
786 int32_t target_pos; 887 int32_t target_pos;
787 int32_t pc_offset_v = pc_offset(); 888 int32_t pc_offset_v = pc_offset();
788 889
789 if (L->is_bound()) { 890 if (L->is_bound()) {
790 target_pos = L->pos(); 891 target_pos = L->pos();
791 int32_t dist = pc_offset_v - target_pos; 892 int32_t dist = pc_offset_v - target_pos;
792 if (dist > kMaxBranchOffset) { 893 if (dist > kMaxBranchOffset) {
793 do { 894 do {
794 int32_t trampoline_pos = get_trampoline_entry(target_pos); 895 int32_t trampoline_pos = get_trampoline_entry(target_pos);
896 if (kInvalidSlotPos == trampoline_pos) {
897 // Internal error.
898 return 0;
899 }
795 ASSERT((trampoline_pos - target_pos) > 0); 900 ASSERT((trampoline_pos - target_pos) > 0);
796 ASSERT((trampoline_pos - target_pos) <= kMaxBranchOffset); 901 ASSERT((trampoline_pos - target_pos) <= kMaxBranchOffset);
797 target_at_put(trampoline_pos, target_pos); 902 target_at_put(trampoline_pos, target_pos);
798 target_pos = trampoline_pos; 903 target_pos = trampoline_pos;
799 dist = pc_offset_v - target_pos; 904 dist = pc_offset_v - target_pos;
800 } while (dist > kMaxBranchOffset); 905 } while (dist > kMaxBranchOffset);
801 } else if (dist < -kMaxBranchOffset) { 906 } else if (dist < -kMaxBranchOffset) {
802 do { 907 do {
803 int32_t trampoline_pos = get_trampoline_entry(target_pos, false); 908 int32_t trampoline_pos = get_trampoline_entry(target_pos, false);
909 if (kInvalidSlotPos == trampoline_pos) {
910 // Internal error.
911 return 0;
912 }
804 ASSERT((target_pos - trampoline_pos) > 0); 913 ASSERT((target_pos - trampoline_pos) > 0);
805 ASSERT((target_pos - trampoline_pos) <= kMaxBranchOffset); 914 ASSERT((target_pos - trampoline_pos) <= kMaxBranchOffset);
806 target_at_put(trampoline_pos, target_pos); 915 target_at_put(trampoline_pos, target_pos);
807 target_pos = trampoline_pos; 916 target_pos = trampoline_pos;
808 dist = pc_offset_v - target_pos; 917 dist = pc_offset_v - target_pos;
809 } while (dist < -kMaxBranchOffset); 918 } while (dist < -kMaxBranchOffset);
810 } 919 }
811 } else { 920 } else {
812 if (L->is_linked()) { 921 if (L->is_linked()) {
813 target_pos = L->pos(); // L's link. 922 target_pos = L->pos(); // L's link.
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
972 1081
973 // Arithmetic. 1082 // Arithmetic.
974 1083
975 void Assembler::addu(Register rd, Register rs, Register rt) { 1084 void Assembler::addu(Register rd, Register rs, Register rt) {
976 GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU); 1085 GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU);
977 } 1086 }
978 1087
979 1088
980 void Assembler::addiu(Register rd, Register rs, int32_t j) { 1089 void Assembler::addiu(Register rd, Register rs, int32_t j) {
981 GenInstrImmediate(ADDIU, rs, rd, j); 1090 GenInstrImmediate(ADDIU, rs, rd, j);
982
983 // Eliminate pattern: push(r), pop().
984 // addiu(sp, sp, Operand(-kPointerSize));
985 // sw(src, MemOperand(sp, 0);
986 // addiu(sp, sp, Operand(kPointerSize));
987 // Both instructions can be eliminated.
988 if (can_peephole_optimize(3) &&
989 // Pattern.
990 instr_at(pc_ - 1 * kInstrSize) == kPopInstruction &&
991 (instr_at(pc_ - 2 * kInstrSize) & ~kRtMask) == kPushRegPattern &&
992 (instr_at(pc_ - 3 * kInstrSize)) == kPushInstruction) {
993 pc_ -= 3 * kInstrSize;
994 if (FLAG_print_peephole_optimization) {
995 PrintF("%x push(reg)/pop() eliminated\n", pc_offset());
996 }
997 }
998
999 // Eliminate pattern: push(ry), pop(rx).
1000 // addiu(sp, sp, -kPointerSize)
1001 // sw(ry, MemOperand(sp, 0)
1002 // lw(rx, MemOperand(sp, 0)
1003 // addiu(sp, sp, kPointerSize);
1004 // Both instructions can be eliminated if ry = rx.
1005 // If ry != rx, a register copy from ry to rx is inserted
1006 // after eliminating the push and the pop instructions.
1007 if (can_peephole_optimize(4)) {
1008 Instr pre_push_sp_set = instr_at(pc_ - 4 * kInstrSize);
1009 Instr push_instr = instr_at(pc_ - 3 * kInstrSize);
1010 Instr pop_instr = instr_at(pc_ - 2 * kInstrSize);
1011 Instr post_pop_sp_set = instr_at(pc_ - 1 * kInstrSize);
1012
1013 if (IsPush(push_instr) &&
1014 IsPop(pop_instr) && pre_push_sp_set == kPushInstruction &&
1015 post_pop_sp_set == kPopInstruction) {
1016 if ((pop_instr & kRtMask) != (push_instr & kRtMask)) {
1017 // For consecutive push and pop on different registers,
1018 // we delete both the push & pop and insert a register move.
1019 // push ry, pop rx --> mov rx, ry.
1020 Register reg_pushed, reg_popped;
1021 reg_pushed = GetRt(push_instr);
1022 reg_popped = GetRt(pop_instr);
1023 pc_ -= 4 * kInstrSize;
1024 // Insert a mov instruction, which is better than a pair of push & pop.
1025 or_(reg_popped, reg_pushed, zero_reg);
1026 if (FLAG_print_peephole_optimization) {
1027 PrintF("%x push/pop (diff reg) replaced by a reg move\n",
1028 pc_offset());
1029 }
1030 } else {
1031 // For consecutive push and pop on the same register,
1032 // both the push and the pop can be deleted.
1033 pc_ -= 4 * kInstrSize;
1034 if (FLAG_print_peephole_optimization) {
1035 PrintF("%x push/pop (same reg) eliminated\n", pc_offset());
1036 }
1037 }
1038 }
1039 }
1040
1041 if (can_peephole_optimize(5)) {
1042 Instr pre_push_sp_set = instr_at(pc_ - 5 * kInstrSize);
1043 Instr mem_write_instr = instr_at(pc_ - 4 * kInstrSize);
1044 Instr lw_instr = instr_at(pc_ - 3 * kInstrSize);
1045 Instr mem_read_instr = instr_at(pc_ - 2 * kInstrSize);
1046 Instr post_pop_sp_set = instr_at(pc_ - 1 * kInstrSize);
1047
1048 if (IsPush(mem_write_instr) &&
1049 pre_push_sp_set == kPushInstruction &&
1050 IsPop(mem_read_instr) &&
1051 post_pop_sp_set == kPopInstruction) {
1052 if ((IsLwRegFpOffset(lw_instr) ||
1053 IsLwRegFpNegOffset(lw_instr))) {
1054 if ((mem_write_instr & kRtMask) ==
1055 (mem_read_instr & kRtMask)) {
1056 // Pattern: push & pop from/to same register,
1057 // with a fp+offset lw in between.
1058 //
1059 // The following:
1060 // addiu sp, sp, -4
1061 // sw rx, [sp, #0]!
1062 // lw rz, [fp, #-24]
1063 // lw rx, [sp, 0],
1064 // addiu sp, sp, 4
1065 //
1066 // Becomes:
1067 // if(rx == rz)
1068 // delete all
1069 // else
1070 // lw rz, [fp, #-24]
1071
1072 if ((mem_write_instr & kRtMask) == (lw_instr & kRtMask)) {
1073 pc_ -= 5 * kInstrSize;
1074 } else {
1075 pc_ -= 5 * kInstrSize;
1076 // Reinsert back the lw rz.
1077 emit(lw_instr);
1078 }
1079 if (FLAG_print_peephole_optimization) {
1080 PrintF("%x push/pop -dead ldr fp+offset in middle\n", pc_offset());
1081 }
1082 } else {
1083 // Pattern: push & pop from/to different registers
1084 // with a fp + offset lw in between.
1085 //
1086 // The following:
1087 // addiu sp, sp ,-4
1088 // sw rx, [sp, 0]
1089 // lw rz, [fp, #-24]
1090 // lw ry, [sp, 0]
1091 // addiu sp, sp, 4
1092 //
1093 // Becomes:
1094 // if(ry == rz)
1095 // mov ry, rx;
1096 // else if(rx != rz)
1097 // lw rz, [fp, #-24]
1098 // mov ry, rx
1099 // else if((ry != rz) || (rx == rz)) becomes:
1100 // mov ry, rx
1101 // lw rz, [fp, #-24]
1102
1103 Register reg_pushed, reg_popped;
1104 if ((mem_read_instr & kRtMask) == (lw_instr & kRtMask)) {
1105 reg_pushed = GetRt(mem_write_instr);
1106 reg_popped = GetRt(mem_read_instr);
1107 pc_ -= 5 * kInstrSize;
1108 or_(reg_popped, reg_pushed, zero_reg); // Move instruction.
1109 } else if ((mem_write_instr & kRtMask)
1110 != (lw_instr & kRtMask)) {
1111 reg_pushed = GetRt(mem_write_instr);
1112 reg_popped = GetRt(mem_read_instr);
1113 pc_ -= 5 * kInstrSize;
1114 emit(lw_instr);
1115 or_(reg_popped, reg_pushed, zero_reg); // Move instruction.
1116 } else if (((mem_read_instr & kRtMask)
1117 != (lw_instr & kRtMask)) ||
1118 ((mem_write_instr & kRtMask)
1119 == (lw_instr & kRtMask)) ) {
1120 reg_pushed = GetRt(mem_write_instr);
1121 reg_popped = GetRt(mem_read_instr);
1122 pc_ -= 5 * kInstrSize;
1123 or_(reg_popped, reg_pushed, zero_reg); // Move instruction.
1124 emit(lw_instr);
1125 }
1126 if (FLAG_print_peephole_optimization) {
1127 PrintF("%x push/pop (ldr fp+off in middle)\n", pc_offset());
1128 }
1129 }
1130 }
1131 }
1132 }
1133 } 1091 }
1134 1092
1135 1093
1136 void Assembler::subu(Register rd, Register rs, Register rt) { 1094 void Assembler::subu(Register rd, Register rs, Register rt) {
1137 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU); 1095 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU);
1138 } 1096 }
1139 1097
1140 1098
1141 void Assembler::mul(Register rd, Register rs, Register rt) { 1099 void Assembler::mul(Register rd, Register rs, Register rt) {
1142 GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL); 1100 GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL);
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
1310 } 1268 }
1311 1269
1312 1270
1313 void Assembler::lw(Register rd, const MemOperand& rs) { 1271 void Assembler::lw(Register rd, const MemOperand& rs) {
1314 if (is_int16(rs.offset_)) { 1272 if (is_int16(rs.offset_)) {
1315 GenInstrImmediate(LW, rs.rm(), rd, rs.offset_); 1273 GenInstrImmediate(LW, rs.rm(), rd, rs.offset_);
1316 } else { // Offset > 16 bits, use multiple instructions to load. 1274 } else { // Offset > 16 bits, use multiple instructions to load.
1317 LoadRegPlusOffsetToAt(rs); 1275 LoadRegPlusOffsetToAt(rs);
1318 GenInstrImmediate(LW, at, rd, 0); // Equiv to lw(rd, MemOperand(at, 0)); 1276 GenInstrImmediate(LW, at, rd, 0); // Equiv to lw(rd, MemOperand(at, 0));
1319 } 1277 }
1320
1321 if (can_peephole_optimize(2)) {
1322 Instr sw_instr = instr_at(pc_ - 2 * kInstrSize);
1323 Instr lw_instr = instr_at(pc_ - 1 * kInstrSize);
1324
1325 if ((IsSwRegFpOffset(sw_instr) &&
1326 IsLwRegFpOffset(lw_instr)) ||
1327 (IsSwRegFpNegOffset(sw_instr) &&
1328 IsLwRegFpNegOffset(lw_instr))) {
1329 if ((lw_instr & kLwSwInstrArgumentMask) ==
1330 (sw_instr & kLwSwInstrArgumentMask)) {
1331 // Pattern: Lw/sw same fp+offset, same register.
1332 //
1333 // The following:
1334 // sw rx, [fp, #-12]
1335 // lw rx, [fp, #-12]
1336 //
1337 // Becomes:
1338 // sw rx, [fp, #-12]
1339
1340 pc_ -= 1 * kInstrSize;
1341 if (FLAG_print_peephole_optimization) {
1342 PrintF("%x sw/lw (fp + same offset), same reg\n", pc_offset());
1343 }
1344 } else if ((lw_instr & kLwSwOffsetMask) ==
1345 (sw_instr & kLwSwOffsetMask)) {
1346 // Pattern: Lw/sw same fp+offset, different register.
1347 //
1348 // The following:
1349 // sw rx, [fp, #-12]
1350 // lw ry, [fp, #-12]
1351 //
1352 // Becomes:
1353 // sw rx, [fp, #-12]
1354 // mov ry, rx
1355
1356 Register reg_stored, reg_loaded;
1357 reg_stored = GetRt(sw_instr);
1358 reg_loaded = GetRt(lw_instr);
1359 pc_ -= 1 * kInstrSize;
1360 // Insert a mov instruction, which is better than lw.
1361 or_(reg_loaded, reg_stored, zero_reg); // Move instruction.
1362 if (FLAG_print_peephole_optimization) {
1363 PrintF("%x sw/lw (fp + same offset), diff reg \n", pc_offset());
1364 }
1365 }
1366 }
1367 }
1368 } 1278 }
1369 1279
1370 1280
1371 void Assembler::lwl(Register rd, const MemOperand& rs) { 1281 void Assembler::lwl(Register rd, const MemOperand& rs) {
1372 GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_); 1282 GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_);
1373 } 1283 }
1374 1284
1375 1285
1376 void Assembler::lwr(Register rd, const MemOperand& rs) { 1286 void Assembler::lwr(Register rd, const MemOperand& rs) {
1377 GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_); 1287 GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_);
(...skipping 20 matching lines...) Expand all
1398 } 1308 }
1399 1309
1400 1310
1401 void Assembler::sw(Register rd, const MemOperand& rs) { 1311 void Assembler::sw(Register rd, const MemOperand& rs) {
1402 if (is_int16(rs.offset_)) { 1312 if (is_int16(rs.offset_)) {
1403 GenInstrImmediate(SW, rs.rm(), rd, rs.offset_); 1313 GenInstrImmediate(SW, rs.rm(), rd, rs.offset_);
1404 } else { // Offset > 16 bits, use multiple instructions to store. 1314 } else { // Offset > 16 bits, use multiple instructions to store.
1405 LoadRegPlusOffsetToAt(rs); 1315 LoadRegPlusOffsetToAt(rs);
1406 GenInstrImmediate(SW, at, rd, 0); // Equiv to sw(rd, MemOperand(at, 0)); 1316 GenInstrImmediate(SW, at, rd, 0); // Equiv to sw(rd, MemOperand(at, 0));
1407 } 1317 }
1408
1409 // Eliminate pattern: pop(), push(r).
1410 // addiu sp, sp, Operand(kPointerSize);
1411 // addiu sp, sp, Operand(-kPointerSize);
1412 // -> sw r, MemOpernad(sp, 0);
1413 if (can_peephole_optimize(3) &&
1414 // Pattern.
1415 instr_at(pc_ - 1 * kInstrSize) ==
1416 (kPushRegPattern | (rd.code() << kRtShift)) &&
1417 instr_at(pc_ - 2 * kInstrSize) == kPushInstruction &&
1418 instr_at(pc_ - 3 * kInstrSize) == kPopInstruction) {
1419 pc_ -= 3 * kInstrSize;
1420 GenInstrImmediate(SW, rs.rm(), rd, rs.offset_);
1421 if (FLAG_print_peephole_optimization) {
1422 PrintF("%x pop()/push(reg) eliminated\n", pc_offset());
1423 }
1424 }
1425 } 1318 }
1426 1319
1427 1320
1428 void Assembler::swl(Register rd, const MemOperand& rs) { 1321 void Assembler::swl(Register rd, const MemOperand& rs) {
1429 GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_); 1322 GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_);
1430 } 1323 }
1431 1324
1432 1325
1433 void Assembler::swr(Register rd, const MemOperand& rs) { 1326 void Assembler::swr(Register rd, const MemOperand& rs) {
1434 GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_); 1327 GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_);
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
1538 } 1431 }
1539 1432
1540 1433
1541 void Assembler::movn(Register rd, Register rs, Register rt) { 1434 void Assembler::movn(Register rd, Register rs, Register rt) {
1542 GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVN); 1435 GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVN);
1543 } 1436 }
1544 1437
1545 1438
1546 void Assembler::movt(Register rd, Register rs, uint16_t cc) { 1439 void Assembler::movt(Register rd, Register rs, uint16_t cc) {
1547 Register rt; 1440 Register rt;
1548 rt.code_ = (cc & 0x0003) << 2 | 1; 1441 rt.code_ = (cc & 0x0007) << 2 | 1;
1549 GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI); 1442 GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
1550 } 1443 }
1551 1444
1552 1445
1553 void Assembler::movf(Register rd, Register rs, uint16_t cc) { 1446 void Assembler::movf(Register rd, Register rs, uint16_t cc) {
1554 Register rt; 1447 Register rt;
1555 rt.code_ = (cc & 0x0003) << 2 | 0; 1448 rt.code_ = (cc & 0x0007) << 2 | 0;
1556 GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI); 1449 GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
1557 } 1450 }
1558 1451
1559 1452
1560 // Bit twiddling. 1453 // Bit twiddling.
1561 void Assembler::clz(Register rd, Register rs) { 1454 void Assembler::clz(Register rd, Register rs) {
1562 // Clz instr requires same GPR number in 'rd' and 'rt' fields. 1455 // Clz instr requires same GPR number in 'rd' and 'rt' fields.
1563 GenInstrRegister(SPECIAL2, rs, rd, rd, 0, CLZ); 1456 GenInstrRegister(SPECIAL2, rs, rd, rd, 0, CLZ);
1564 } 1457 }
1565 1458
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
1809 1702
1810 1703
1811 void Assembler::cvt_d_s(FPURegister fd, FPURegister fs) { 1704 void Assembler::cvt_d_s(FPURegister fd, FPURegister fs) {
1812 GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S); 1705 GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S);
1813 } 1706 }
1814 1707
1815 1708
1816 // Conditions. 1709 // Conditions.
1817 void Assembler::c(FPUCondition cond, SecondaryField fmt, 1710 void Assembler::c(FPUCondition cond, SecondaryField fmt,
1818 FPURegister fs, FPURegister ft, uint16_t cc) { 1711 FPURegister fs, FPURegister ft, uint16_t cc) {
1819 ASSERT(isolate()->cpu_features()->IsEnabled(FPU)); 1712 ASSERT(CpuFeatures::IsEnabled(FPU));
1820 ASSERT(is_uint3(cc)); 1713 ASSERT(is_uint3(cc));
1821 ASSERT((fmt & ~(31 << kRsShift)) == 0); 1714 ASSERT((fmt & ~(31 << kRsShift)) == 0);
1822 Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift 1715 Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift
1823 | cc << 8 | 3 << 4 | cond; 1716 | cc << 8 | 3 << 4 | cond;
1824 emit(instr); 1717 emit(instr);
1825 } 1718 }
1826 1719
1827 1720
1828 void Assembler::fcmp(FPURegister src1, const double src2, 1721 void Assembler::fcmp(FPURegister src1, const double src2,
1829 FPUCondition cond) { 1722 FPUCondition cond) {
1830 ASSERT(isolate()->cpu_features()->IsSupported(FPU)); 1723 ASSERT(CpuFeatures::IsEnabled(FPU));
1831 ASSERT(src2 == 0.0); 1724 ASSERT(src2 == 0.0);
1832 mtc1(zero_reg, f14); 1725 mtc1(zero_reg, f14);
1833 cvt_d_w(f14, f14); 1726 cvt_d_w(f14, f14);
1834 c(cond, D, src1, f14, 0); 1727 c(cond, D, src1, f14, 0);
1835 } 1728 }
1836 1729
1837 1730
1838 void Assembler::bc1f(int16_t offset, uint16_t cc) { 1731 void Assembler::bc1f(int16_t offset, uint16_t cc) {
1839 ASSERT(isolate()->cpu_features()->IsEnabled(FPU)); 1732 ASSERT(CpuFeatures::IsEnabled(FPU));
1840 ASSERT(is_uint3(cc)); 1733 ASSERT(is_uint3(cc));
1841 Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask); 1734 Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask);
1842 emit(instr); 1735 emit(instr);
1843 } 1736 }
1844 1737
1845 1738
1846 void Assembler::bc1t(int16_t offset, uint16_t cc) { 1739 void Assembler::bc1t(int16_t offset, uint16_t cc) {
1847 ASSERT(isolate()->cpu_features()->IsEnabled(FPU)); 1740 ASSERT(CpuFeatures::IsEnabled(FPU));
1848 ASSERT(is_uint3(cc)); 1741 ASSERT(is_uint3(cc));
1849 Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask); 1742 Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask);
1850 emit(instr); 1743 emit(instr);
1851 } 1744 }
1852 1745
1853 1746
1854 // Debugging. 1747 // Debugging.
1855 void Assembler::RecordJSReturn() { 1748 void Assembler::RecordJSReturn() {
1856 positions_recorder()->WriteRecordedPositions(); 1749 positions_recorder()->WriteRecordedPositions();
1857 CheckBuffer(); 1750 CheckBuffer();
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1942 // These modes do not need an entry in the constant pool. 1835 // These modes do not need an entry in the constant pool.
1943 } 1836 }
1944 if (rinfo.rmode() != RelocInfo::NONE) { 1837 if (rinfo.rmode() != RelocInfo::NONE) {
1945 // Don't record external references unless the heap will be serialized. 1838 // Don't record external references unless the heap will be serialized.
1946 if (rmode == RelocInfo::EXTERNAL_REFERENCE && 1839 if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
1947 !Serializer::enabled() && 1840 !Serializer::enabled() &&
1948 !FLAG_debug_code) { 1841 !FLAG_debug_code) {
1949 return; 1842 return;
1950 } 1843 }
1951 ASSERT(buffer_space() >= kMaxRelocSize); // Too late to grow buffer here. 1844 ASSERT(buffer_space() >= kMaxRelocSize); // Too late to grow buffer here.
1952 reloc_info_writer.Write(&rinfo); 1845 if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
1846 ASSERT(ast_id_for_reloc_info_ != kNoASTId);
1847 RelocInfo reloc_info_with_ast_id(pc_, rmode, ast_id_for_reloc_info_);
1848 ast_id_for_reloc_info_ = kNoASTId;
1849 reloc_info_writer.Write(&reloc_info_with_ast_id);
1850 } else {
1851 reloc_info_writer.Write(&rinfo);
1852 }
1953 } 1853 }
1954 } 1854 }
1955 1855
1956 1856
1957 void Assembler::BlockTrampolinePoolFor(int instructions) { 1857 void Assembler::BlockTrampolinePoolFor(int instructions) {
1958 BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize); 1858 BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize);
1959 } 1859 }
1960 1860
1961 1861
1962 void Assembler::CheckTrampolinePool(bool force_emit) { 1862 void Assembler::CheckTrampolinePool(bool force_emit) {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2010 // move the check offset forward by the standard interval. 1910 // move the check offset forward by the standard interval.
2011 next_buffer_check_ = last_trampoline_pool_end_ + kMaxDistBetweenPools; 1911 next_buffer_check_ = last_trampoline_pool_end_ + kMaxDistBetweenPools;
2012 } 1912 }
2013 return; 1913 return;
2014 } 1914 }
2015 1915
2016 1916
2017 Address Assembler::target_address_at(Address pc) { 1917 Address Assembler::target_address_at(Address pc) {
2018 Instr instr1 = instr_at(pc); 1918 Instr instr1 = instr_at(pc);
2019 Instr instr2 = instr_at(pc + kInstrSize); 1919 Instr instr2 = instr_at(pc + kInstrSize);
2020 // Check we have 2 instructions generated by li. 1920 // Interpret 2 instructions generated by li: lui/ori
2021 ASSERT(((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) || 1921 if ((GetOpcodeField(instr1) == LUI) && (GetOpcodeField(instr2) == ORI)) {
2022 ((instr1 == nopInstr) && ((instr2 & kOpcodeMask) == ADDI || 1922 // Assemble the 32 bit value.
2023 (instr2 & kOpcodeMask) == ORI ||
2024 (instr2 & kOpcodeMask) == LUI)));
2025 // Interpret these 2 instructions.
2026 if (instr1 == nopInstr) {
2027 if ((instr2 & kOpcodeMask) == ADDI) {
2028 return reinterpret_cast<Address>(((instr2 & kImm16Mask) << 16) >> 16);
2029 } else if ((instr2 & kOpcodeMask) == ORI) {
2030 return reinterpret_cast<Address>(instr2 & kImm16Mask);
2031 } else if ((instr2 & kOpcodeMask) == LUI) {
2032 return reinterpret_cast<Address>((instr2 & kImm16Mask) << 16);
2033 }
2034 } else if ((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) {
2035 // 32 bit value.
2036 return reinterpret_cast<Address>( 1923 return reinterpret_cast<Address>(
2037 (instr1 & kImm16Mask) << 16 | (instr2 & kImm16Mask)); 1924 (GetImmediate16(instr1) << 16) | GetImmediate16(instr2));
2038 } 1925 }
2039 1926
2040 // We should never get here. 1927 // We should never get here, force a bad address if we do.
2041 UNREACHABLE(); 1928 UNREACHABLE();
2042 return (Address)0x0; 1929 return (Address)0x0;
2043 } 1930 }
2044 1931
2045 1932
2046 void Assembler::set_target_address_at(Address pc, Address target) { 1933 void Assembler::set_target_address_at(Address pc, Address target) {
2047 // On MIPS we need to patch the code to generate. 1934 // On MIPS we patch the address into lui/ori instruction pair.
2048 1935
2049 // First check we have a li. 1936 // First check we have an li (lui/ori pair).
2050 Instr instr2 = instr_at(pc + kInstrSize); 1937 Instr instr2 = instr_at(pc + kInstrSize);
2051 #ifdef DEBUG 1938 #ifdef DEBUG
2052 Instr instr1 = instr_at(pc); 1939 Instr instr1 = instr_at(pc);
2053 1940
2054 // Check we have indeed the result from a li with MustUseReg true. 1941 // Check we have indeed the result from a li with MustUseReg true.
2055 CHECK(((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) || 1942 CHECK((GetOpcodeField(instr1) == LUI && GetOpcodeField(instr2) == ORI));
2056 ((instr1 == 0) && ((instr2 & kOpcodeMask)== ADDIU ||
2057 (instr2 & kOpcodeMask)== ORI ||
2058 (instr2 & kOpcodeMask)== LUI)));
2059 #endif 1943 #endif
2060 1944
2061 uint32_t rt_code = (instr2 & kRtFieldMask); 1945 uint32_t rt_code = GetRtField(instr2);
2062 uint32_t* p = reinterpret_cast<uint32_t*>(pc); 1946 uint32_t* p = reinterpret_cast<uint32_t*>(pc);
2063 uint32_t itarget = reinterpret_cast<uint32_t>(target); 1947 uint32_t itarget = reinterpret_cast<uint32_t>(target);
2064 1948
2065 if (is_int16(itarget)) { 1949 // lui rt, high-16.
2066 // nop. 1950 // ori rt rt, low-16.
2067 // addiu rt zero_reg j. 1951 *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift);
2068 *p = nopInstr; 1952 *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask);
2069 *(p+1) = ADDIU | rt_code | (itarget & kImm16Mask);
2070 } else if (!(itarget & kHiMask)) {
2071 // nop.
2072 // ori rt zero_reg j.
2073 *p = nopInstr;
2074 *(p+1) = ORI | rt_code | (itarget & kImm16Mask);
2075 } else if (!(itarget & kImm16Mask)) {
2076 // nop.
2077 // lui rt (kHiMask & itarget) >> kLuiShift.
2078 *p = nopInstr;
2079 *(p+1) = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift);
2080 } else {
2081 // lui rt (kHiMask & itarget) >> kLuiShift.
2082 // ori rt rt, (kImm16Mask & itarget).
2083 *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift);
2084 *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask);
2085 }
2086 1953
2087 CPU::FlushICache(pc, 2 * sizeof(int32_t)); 1954 CPU::FlushICache(pc, 2 * sizeof(int32_t));
2088 } 1955 }
2089 1956
2090 1957
2091 } } // namespace v8::internal 1958 } } // namespace v8::internal
2092 1959
2093 #endif // V8_TARGET_ARCH_MIPS 1960 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « src/mips/assembler-mips.h ('k') | src/mips/assembler-mips-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698