| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef VM_ASSEMBLER_MIPS_H_ | 5 #ifndef VM_ASSEMBLER_MIPS_H_ |
| 6 #define VM_ASSEMBLER_MIPS_H_ | 6 #define VM_ASSEMBLER_MIPS_H_ |
| 7 | 7 |
| 8 #ifndef VM_ASSEMBLER_H_ | 8 #ifndef VM_ASSEMBLER_H_ |
| 9 #error Do not include assembler_mips.h directly; use assembler.h instead. | 9 #error Do not include assembler_mips.h directly; use assembler.h instead. |
| 10 #endif | 10 #endif |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 ASSERT(delay_slot_available_); | 223 ASSERT(delay_slot_available_); |
| 224 ASSERT(buffer_.Load<int32_t>(buffer_.GetPosition() - sizeof(int32_t)) == | 224 ASSERT(buffer_.Load<int32_t>(buffer_.GetPosition() - sizeof(int32_t)) == |
| 225 Instr::kNopInstruction); | 225 Instr::kNopInstruction); |
| 226 buffer_.Remit<int32_t>(); | 226 buffer_.Remit<int32_t>(); |
| 227 delay_slot_available_ = false; | 227 delay_slot_available_ = false; |
| 228 in_delay_slot_ = true; | 228 in_delay_slot_ = true; |
| 229 return this; | 229 return this; |
| 230 } | 230 } |
| 231 | 231 |
| 232 // CPU instructions in alphabetical order. | 232 // CPU instructions in alphabetical order. |
| 233 void addd(FRegister fd, FRegister fs, FRegister ft) { | 233 void addd(DRegister dd, DRegister ds, DRegister dt) { |
| 234 ASSERT(EvenFPURegister(fd)); | 234 // DRegisters start at the even FRegisters. |
| 235 ASSERT(EvenFPURegister(fs)); | 235 FRegister fd = static_cast<FRegister>(dd * 2); |
| 236 ASSERT(EvenFPURegister(ft)); | 236 FRegister fs = static_cast<FRegister>(ds * 2); |
| 237 FRegister ft = static_cast<FRegister>(dt * 2); |
| 237 EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_ADD); | 238 EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_ADD); |
| 238 } | 239 } |
| 239 | 240 |
| 240 void addiu(Register rt, Register rs, const Immediate& imm) { | 241 void addiu(Register rt, Register rs, const Immediate& imm) { |
| 241 ASSERT(Utils::IsInt(kImmBits, imm.value())); | 242 ASSERT(Utils::IsInt(kImmBits, imm.value())); |
| 242 const uint16_t imm_value = static_cast<uint16_t>(imm.value()); | 243 const uint16_t imm_value = static_cast<uint16_t>(imm.value()); |
| 243 EmitIType(ADDIU, rs, rt, imm_value); | 244 EmitIType(ADDIU, rs, rt, imm_value); |
| 244 } | 245 } |
| 245 | 246 |
| 246 void addu(Register rd, Register rs, Register rt) { | 247 void addu(Register rd, Register rs, Register rt) { |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 } | 372 } |
| 372 | 373 |
| 373 void break_(int32_t code) { | 374 void break_(int32_t code) { |
| 374 ASSERT(Utils::IsUint(20, code)); | 375 ASSERT(Utils::IsUint(20, code)); |
| 375 Emit(SPECIAL << kOpcodeShift | | 376 Emit(SPECIAL << kOpcodeShift | |
| 376 code << kBreakCodeShift | | 377 code << kBreakCodeShift | |
| 377 BREAK << kFunctionShift); | 378 BREAK << kFunctionShift); |
| 378 } | 379 } |
| 379 | 380 |
| 380 // FPU compare, always false. | 381 // FPU compare, always false. |
| 381 void cfd(FRegister fs, FRegister ft) { | 382 void cfd(DRegister ds, DRegister dt) { |
| 382 ASSERT(EvenFPURegister(fs)); | 383 FRegister fs = static_cast<FRegister>(ds * 2); |
| 383 ASSERT(EvenFPURegister(ft)); | 384 FRegister ft = static_cast<FRegister>(dt * 2); |
| 384 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_F); | 385 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_F); |
| 385 } | 386 } |
| 386 | 387 |
| 387 // FPU compare, true if unordered, i.e. one is NaN. | 388 // FPU compare, true if unordered, i.e. one is NaN. |
| 388 void cund(FRegister fs, FRegister ft) { | 389 void cund(DRegister ds, DRegister dt) { |
| 389 ASSERT(EvenFPURegister(fs)); | 390 FRegister fs = static_cast<FRegister>(ds * 2); |
| 390 ASSERT(EvenFPURegister(ft)); | 391 FRegister ft = static_cast<FRegister>(dt * 2); |
| 391 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_UN); | 392 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_UN); |
| 392 } | 393 } |
| 393 | 394 |
| 394 // FPU compare, true if equal. | 395 // FPU compare, true if equal. |
| 395 void ceqd(FRegister fs, FRegister ft) { | 396 void ceqd(DRegister ds, DRegister dt) { |
| 396 ASSERT(EvenFPURegister(fs)); | 397 FRegister fs = static_cast<FRegister>(ds * 2); |
| 397 ASSERT(EvenFPURegister(ft)); | 398 FRegister ft = static_cast<FRegister>(dt * 2); |
| 398 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_EQ); | 399 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_EQ); |
| 399 } | 400 } |
| 400 | 401 |
| 401 // FPU compare, true if unordered or equal. | 402 // FPU compare, true if unordered or equal. |
| 402 void cueqd(FRegister fs, FRegister ft) { | 403 void cueqd(DRegister ds, DRegister dt) { |
| 403 ASSERT(EvenFPURegister(fs)); | 404 FRegister fs = static_cast<FRegister>(ds * 2); |
| 404 ASSERT(EvenFPURegister(ft)); | 405 FRegister ft = static_cast<FRegister>(dt * 2); |
| 405 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_UEQ); | 406 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_UEQ); |
| 406 } | 407 } |
| 407 | 408 |
| 408 // FPU compare, true if less than. | 409 // FPU compare, true if less than. |
| 409 void coltd(FRegister fs, FRegister ft) { | 410 void coltd(DRegister ds, DRegister dt) { |
| 410 ASSERT(EvenFPURegister(fs)); | 411 FRegister fs = static_cast<FRegister>(ds * 2); |
| 411 ASSERT(EvenFPURegister(ft)); | 412 FRegister ft = static_cast<FRegister>(dt * 2); |
| 412 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_OLT); | 413 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_OLT); |
| 413 } | 414 } |
| 414 | 415 |
| 415 // FPU compare, true if unordered or less than. | 416 // FPU compare, true if unordered or less than. |
| 416 void cultd(FRegister fs, FRegister ft) { | 417 void cultd(DRegister ds, DRegister dt) { |
| 417 ASSERT(EvenFPURegister(fs)); | 418 FRegister fs = static_cast<FRegister>(ds * 2); |
| 418 ASSERT(EvenFPURegister(ft)); | 419 FRegister ft = static_cast<FRegister>(dt * 2); |
| 419 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_ULT); | 420 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_ULT); |
| 420 } | 421 } |
| 421 | 422 |
| 422 // FPU compare, true if less or equal. | 423 // FPU compare, true if less or equal. |
| 423 void coled(FRegister fs, FRegister ft) { | 424 void coled(DRegister ds, DRegister dt) { |
| 424 ASSERT(EvenFPURegister(fs)); | 425 FRegister fs = static_cast<FRegister>(ds * 2); |
| 425 ASSERT(EvenFPURegister(ft)); | 426 FRegister ft = static_cast<FRegister>(dt * 2); |
| 426 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_OLE); | 427 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_OLE); |
| 427 } | 428 } |
| 428 | 429 |
| 429 // FPU compare, true if unordered or less or equal. | 430 // FPU compare, true if unordered or less or equal. |
| 430 void culed(FRegister fs, FRegister ft) { | 431 void culed(DRegister ds, DRegister dt) { |
| 431 ASSERT(EvenFPURegister(fs)); | 432 FRegister fs = static_cast<FRegister>(ds * 2); |
| 432 ASSERT(EvenFPURegister(ft)); | 433 FRegister ft = static_cast<FRegister>(dt * 2); |
| 433 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_ULE); | 434 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_ULE); |
| 434 } | 435 } |
| 435 | 436 |
| 436 void clo(Register rd, Register rs) { | 437 void clo(Register rd, Register rs) { |
| 437 EmitRType(SPECIAL2, rs, rd, rd, 0, CLO); | 438 EmitRType(SPECIAL2, rs, rd, rd, 0, CLO); |
| 438 } | 439 } |
| 439 | 440 |
| 440 void clz(Register rd, Register rs) { | 441 void clz(Register rd, Register rs) { |
| 441 EmitRType(SPECIAL2, rs, rd, rd, 0, CLZ); | 442 EmitRType(SPECIAL2, rs, rd, rd, 0, CLZ); |
| 442 } | 443 } |
| 443 | 444 |
| 444 // Converts a 32-bit signed int in fs to a double in fd. | 445 // Converts a 32-bit signed int in fs to a double in fd. |
| 445 void cvtdw(FRegister fd, FRegister fs) { | 446 void cvtdw(DRegister dd, FRegister fs) { |
| 446 ASSERT(EvenFPURegister(fd)); | 447 FRegister fd = static_cast<FRegister>(dd * 2); |
| 447 EmitFpuRType(COP1, FMT_W, F0, fs, fd, COP1_CVT_D); | 448 EmitFpuRType(COP1, FMT_W, F0, fs, fd, COP1_CVT_D); |
| 448 } | 449 } |
| 449 | 450 |
| 450 // Converts a 64-bit signed int in fs to a double in fd. | 451 // Converts a 64-bit signed int in fs to a double in fd. |
| 451 void cvtdl(FRegister fd, FRegister fs) { | 452 void cvtdl(DRegister dd, DRegister ds) { |
| 452 ASSERT(EvenFPURegister(fs)); | 453 FRegister fs = static_cast<FRegister>(ds * 2); |
| 453 ASSERT(EvenFPURegister(fd)); | 454 FRegister fd = static_cast<FRegister>(dd * 2); |
| 454 EmitFpuRType(COP1, FMT_L, F0, fs, fd, COP1_CVT_D); | 455 EmitFpuRType(COP1, FMT_L, F0, fs, fd, COP1_CVT_D); |
| 455 } | 456 } |
| 456 | 457 |
| 457 void cvtwd(FRegister fd, FRegister fs) { | 458 void cvtwd(FRegister fd, DRegister ds) { |
| 458 ASSERT(EvenFPURegister(fs)); | 459 FRegister fs = static_cast<FRegister>(ds * 2); |
| 459 ASSERT(EvenFPURegister(fd)); | |
| 460 EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_CVT_W); | 460 EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_CVT_W); |
| 461 } | 461 } |
| 462 | 462 |
| 463 void div(Register rs, Register rt) { | 463 void div(Register rs, Register rt) { |
| 464 EmitRType(SPECIAL, rs, rt, R0, 0, DIV); | 464 EmitRType(SPECIAL, rs, rt, R0, 0, DIV); |
| 465 } | 465 } |
| 466 | 466 |
| 467 void divd(FRegister fd, FRegister fs, FRegister ft) { | 467 void divd(DRegister dd, DRegister ds, DRegister dt) { |
| 468 ASSERT(EvenFPURegister(fd)); | 468 FRegister fd = static_cast<FRegister>(dd * 2); |
| 469 ASSERT(EvenFPURegister(fs)); | 469 FRegister fs = static_cast<FRegister>(ds * 2); |
| 470 ASSERT(EvenFPURegister(ft)); | 470 FRegister ft = static_cast<FRegister>(dt * 2); |
| 471 EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_DIV); | 471 EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_DIV); |
| 472 } | 472 } |
| 473 | 473 |
| 474 void divu(Register rs, Register rt) { | 474 void divu(Register rs, Register rt) { |
| 475 EmitRType(SPECIAL, rs, rt, R0, 0, DIVU); | 475 EmitRType(SPECIAL, rs, rt, R0, 0, DIVU); |
| 476 } | 476 } |
| 477 | 477 |
| 478 void jalr(Register rs, Register rd = RA) { | 478 void jalr(Register rs, Register rd = RA) { |
| 479 ASSERT(rs != rd); | 479 ASSERT(rs != rd); |
| 480 ASSERT(!in_delay_slot_); // Jump within a delay slot is not supported. | 480 ASSERT(!in_delay_slot_); // Jump within a delay slot is not supported. |
| 481 EmitRType(SPECIAL, rs, R0, rd, 0, JALR); | 481 EmitRType(SPECIAL, rs, R0, rd, 0, JALR); |
| 482 EmitBranchDelayNop(); | 482 EmitBranchDelayNop(); |
| 483 } | 483 } |
| 484 | 484 |
| 485 void jr(Register rs) { | 485 void jr(Register rs) { |
| 486 ASSERT(!in_delay_slot_); // Jump within a delay slot is not supported. | 486 ASSERT(!in_delay_slot_); // Jump within a delay slot is not supported. |
| 487 EmitRType(SPECIAL, rs, R0, R0, 0, JR); | 487 EmitRType(SPECIAL, rs, R0, R0, 0, JR); |
| 488 EmitBranchDelayNop(); | 488 EmitBranchDelayNop(); |
| 489 } | 489 } |
| 490 | 490 |
| 491 void lb(Register rt, const Address& addr) { | 491 void lb(Register rt, const Address& addr) { |
| 492 EmitLoadStore(LB, rt, addr); | 492 EmitLoadStore(LB, rt, addr); |
| 493 } | 493 } |
| 494 | 494 |
| 495 void lbu(Register rt, const Address& addr) { | 495 void lbu(Register rt, const Address& addr) { |
| 496 EmitLoadStore(LBU, rt, addr); | 496 EmitLoadStore(LBU, rt, addr); |
| 497 } | 497 } |
| 498 | 498 |
| 499 void ldc1(FRegister ft, const Address& addr) { | 499 void ldc1(DRegister dt, const Address& addr) { |
| 500 ASSERT(EvenFPURegister(ft)); | 500 FRegister ft = static_cast<FRegister>(dt * 2); |
| 501 EmitFpuLoadStore(LDC1, ft, addr); | 501 EmitFpuLoadStore(LDC1, ft, addr); |
| 502 } | 502 } |
| 503 | 503 |
| 504 void lh(Register rt, const Address& addr) { | 504 void lh(Register rt, const Address& addr) { |
| 505 EmitLoadStore(LH, rt, addr); | 505 EmitLoadStore(LH, rt, addr); |
| 506 } | 506 } |
| 507 | 507 |
| 508 void lhu(Register rt, const Address& addr) { | 508 void lhu(Register rt, const Address& addr) { |
| 509 EmitLoadStore(LHU, rt, addr); | 509 EmitLoadStore(LHU, rt, addr); |
| 510 } | 510 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 535 } | 535 } |
| 536 | 536 |
| 537 void mflo(Register rd) { | 537 void mflo(Register rd) { |
| 538 EmitRType(SPECIAL, R0, R0, rd, 0, MFLO); | 538 EmitRType(SPECIAL, R0, R0, rd, 0, MFLO); |
| 539 } | 539 } |
| 540 | 540 |
| 541 void mov(Register rd, Register rs) { | 541 void mov(Register rd, Register rs) { |
| 542 or_(rd, rs, ZR); | 542 or_(rd, rs, ZR); |
| 543 } | 543 } |
| 544 | 544 |
| 545 void movd(FRegister fd, FRegister fs) { | 545 void movd(DRegister dd, DRegister ds) { |
| 546 ASSERT(EvenFPURegister(fd)); | 546 FRegister fd = static_cast<FRegister>(dd * 2); |
| 547 ASSERT(EvenFPURegister(fs)); | 547 FRegister fs = static_cast<FRegister>(ds * 2); |
| 548 EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_MOV); | 548 EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_MOV); |
| 549 } | 549 } |
| 550 | 550 |
| 551 void movn(Register rd, Register rs, Register rt) { | 551 void movn(Register rd, Register rs, Register rt) { |
| 552 EmitRType(SPECIAL, rs, rt, rd, 0, MOVN); | 552 EmitRType(SPECIAL, rs, rt, rd, 0, MOVN); |
| 553 } | 553 } |
| 554 | 554 |
| 555 void movz(Register rd, Register rs, Register rt) { | 555 void movz(Register rd, Register rs, Register rt) { |
| 556 EmitRType(SPECIAL, rs, rt, rd, 0, MOVZ); | 556 EmitRType(SPECIAL, rs, rt, rd, 0, MOVZ); |
| 557 } | 557 } |
| 558 | 558 |
| 559 void movs(FRegister fd, FRegister fs) { | 559 void movs(FRegister fd, FRegister fs) { |
| 560 EmitFpuRType(COP1, FMT_S, F0, fs, fd, COP1_MOV); | 560 EmitFpuRType(COP1, FMT_S, F0, fs, fd, COP1_MOV); |
| 561 } | 561 } |
| 562 | 562 |
| 563 void mtc1(Register rt, FRegister fs) { | 563 void mtc1(Register rt, FRegister fs) { |
| 564 Emit(COP1 << kOpcodeShift | | 564 Emit(COP1 << kOpcodeShift | |
| 565 COP1_MT << kCop1SubShift | | 565 COP1_MT << kCop1SubShift | |
| 566 rt << kRtShift | | 566 rt << kRtShift | |
| 567 fs << kFsShift); | 567 fs << kFsShift); |
| 568 } | 568 } |
| 569 | 569 |
| 570 void muld(FRegister fd, FRegister fs, FRegister ft) { | 570 void muld(DRegister dd, DRegister ds, DRegister dt) { |
| 571 ASSERT(EvenFPURegister(fd)); | 571 FRegister fd = static_cast<FRegister>(dd * 2); |
| 572 ASSERT(EvenFPURegister(fs)); | 572 FRegister fs = static_cast<FRegister>(ds * 2); |
| 573 ASSERT(EvenFPURegister(ft)); | 573 FRegister ft = static_cast<FRegister>(dt * 2); |
| 574 EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_MUL); | 574 EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_MUL); |
| 575 } | 575 } |
| 576 | 576 |
| 577 void mult(Register rs, Register rt) { | 577 void mult(Register rs, Register rt) { |
| 578 EmitRType(SPECIAL, rs, rt, R0, 0, MULT); | 578 EmitRType(SPECIAL, rs, rt, R0, 0, MULT); |
| 579 } | 579 } |
| 580 | 580 |
| 581 void multu(Register rs, Register rt) { | 581 void multu(Register rs, Register rt) { |
| 582 EmitRType(SPECIAL, rs, rt, R0, 0, MULTU); | 582 EmitRType(SPECIAL, rs, rt, R0, 0, MULTU); |
| 583 } | 583 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 597 void ori(Register rt, Register rs, const Immediate& imm) { | 597 void ori(Register rt, Register rs, const Immediate& imm) { |
| 598 ASSERT(Utils::IsUint(kImmBits, imm.value())); | 598 ASSERT(Utils::IsUint(kImmBits, imm.value())); |
| 599 uint16_t imm_value = static_cast<uint16_t>(imm.value()); | 599 uint16_t imm_value = static_cast<uint16_t>(imm.value()); |
| 600 EmitIType(ORI, rs, rt, imm_value); | 600 EmitIType(ORI, rs, rt, imm_value); |
| 601 } | 601 } |
| 602 | 602 |
| 603 void sb(Register rt, const Address& addr) { | 603 void sb(Register rt, const Address& addr) { |
| 604 EmitLoadStore(SB, rt, addr); | 604 EmitLoadStore(SB, rt, addr); |
| 605 } | 605 } |
| 606 | 606 |
| 607 void sdc1(FRegister ft, const Address& addr) { | 607 void sdc1(DRegister dt, const Address& addr) { |
| 608 ASSERT(EvenFPURegister(ft)); | 608 FRegister ft = static_cast<FRegister>(dt * 2); |
| 609 EmitFpuLoadStore(SDC1, ft, addr); | 609 EmitFpuLoadStore(SDC1, ft, addr); |
| 610 } | 610 } |
| 611 | 611 |
| 612 void sh(Register rt, const Address& addr) { | 612 void sh(Register rt, const Address& addr) { |
| 613 EmitLoadStore(SH, rt, addr); | 613 EmitLoadStore(SH, rt, addr); |
| 614 } | 614 } |
| 615 | 615 |
| 616 void sll(Register rd, Register rt, int sa) { | 616 void sll(Register rd, Register rt, int sa) { |
| 617 EmitRType(SPECIAL, R0, rt, rd, sa, SLL); | 617 EmitRType(SPECIAL, R0, rt, rd, sa, SLL); |
| 618 } | 618 } |
| 619 | 619 |
| 620 void sllv(Register rd, Register rt, Register rs) { | 620 void sllv(Register rd, Register rt, Register rs) { |
| 621 EmitRType(SPECIAL, rs, rt, rd, 0, SLLV); | 621 EmitRType(SPECIAL, rs, rt, rd, 0, SLLV); |
| 622 } | 622 } |
| 623 | 623 |
| 624 void slt(Register rd, Register rs, Register rt) { | 624 void slt(Register rd, Register rs, Register rt) { |
| 625 EmitRType(SPECIAL, rs, rt, rd, 0, SLT); | 625 EmitRType(SPECIAL, rs, rt, rd, 0, SLT); |
| 626 } | 626 } |
| 627 | 627 |
| 628 void slti(Register rt, Register rs, const Immediate& imm) { |
| 629 ASSERT(Utils::IsInt(kImmBits, imm.value())); |
| 630 int16_t imm_value = static_cast<int16_t>(imm.value()); |
| 631 EmitIType(SLTI, rs, rt, imm_value); |
| 632 } |
| 633 |
| 634 void sltiu(Register rt, Register rs, const Immediate& imm) { |
| 635 ASSERT(Utils::IsUint(kImmBits, imm.value())); |
| 636 uint16_t imm_value = static_cast<uint16_t>(imm.value()); |
| 637 EmitIType(SLTIU, rs, rt, imm_value); |
| 638 } |
| 639 |
| 628 void sltu(Register rd, Register rs, Register rt) { | 640 void sltu(Register rd, Register rs, Register rt) { |
| 629 EmitRType(SPECIAL, rs, rt, rd, 0, SLTU); | 641 EmitRType(SPECIAL, rs, rt, rd, 0, SLTU); |
| 630 } | 642 } |
| 631 | 643 |
| 632 void sqrtd(FRegister fd, FRegister fs) { | 644 void sqrtd(DRegister dd, DRegister ds) { |
| 633 ASSERT(EvenFPURegister(fd)); | 645 FRegister fd = static_cast<FRegister>(dd * 2); |
| 634 ASSERT(EvenFPURegister(fs)); | 646 FRegister fs = static_cast<FRegister>(ds * 2); |
| 635 EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_SQRT); | 647 EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_SQRT); |
| 636 } | 648 } |
| 637 | 649 |
| 638 void sra(Register rd, Register rt, int sa) { | 650 void sra(Register rd, Register rt, int sa) { |
| 639 EmitRType(SPECIAL, R0, rt, rd, sa, SRA); | 651 EmitRType(SPECIAL, R0, rt, rd, sa, SRA); |
| 640 } | 652 } |
| 641 | 653 |
| 642 void srav(Register rd, Register rt, Register rs) { | 654 void srav(Register rd, Register rt, Register rs) { |
| 643 EmitRType(SPECIAL, rs, rt, rd, 0, SRAV); | 655 EmitRType(SPECIAL, rs, rt, rd, 0, SRAV); |
| 644 } | 656 } |
| 645 | 657 |
| 646 void srl(Register rd, Register rt, int sa) { | 658 void srl(Register rd, Register rt, int sa) { |
| 647 EmitRType(SPECIAL, R0, rt, rd, sa, SRL); | 659 EmitRType(SPECIAL, R0, rt, rd, sa, SRL); |
| 648 } | 660 } |
| 649 | 661 |
| 650 void srlv(Register rd, Register rt, Register rs) { | 662 void srlv(Register rd, Register rt, Register rs) { |
| 651 EmitRType(SPECIAL, rs, rt, rd, 0, SRLV); | 663 EmitRType(SPECIAL, rs, rt, rd, 0, SRLV); |
| 652 } | 664 } |
| 653 | 665 |
| 654 void subd(FRegister fd, FRegister fs, FRegister ft) { | 666 void subd(DRegister dd, DRegister ds, DRegister dt) { |
| 655 ASSERT(EvenFPURegister(fd)); | 667 FRegister fd = static_cast<FRegister>(dd * 2); |
| 656 ASSERT(EvenFPURegister(fs)); | 668 FRegister fs = static_cast<FRegister>(ds * 2); |
| 657 ASSERT(EvenFPURegister(ft)); | 669 FRegister ft = static_cast<FRegister>(dt * 2); |
| 658 EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_SUB); | 670 EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_SUB); |
| 659 } | 671 } |
| 660 | 672 |
| 661 void subu(Register rd, Register rs, Register rt) { | 673 void subu(Register rd, Register rs, Register rt) { |
| 662 EmitRType(SPECIAL, rs, rt, rd, 0, SUBU); | 674 EmitRType(SPECIAL, rs, rt, rd, 0, SUBU); |
| 663 } | 675 } |
| 664 | 676 |
| 665 void sw(Register rt, const Address& addr) { | 677 void sw(Register rt, const Address& addr) { |
| 666 EmitLoadStore(SW, rt, addr); | 678 EmitLoadStore(SW, rt, addr); |
| 667 } | 679 } |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 753 if (Utils::IsInt(kImmBits, value)) { | 765 if (Utils::IsInt(kImmBits, value)) { |
| 754 addiu(rd, ZR, Immediate(value)); | 766 addiu(rd, ZR, Immediate(value)); |
| 755 } else { | 767 } else { |
| 756 const uint16_t low = Utils::Low16Bits(value); | 768 const uint16_t low = Utils::Low16Bits(value); |
| 757 const uint16_t high = Utils::High16Bits(value); | 769 const uint16_t high = Utils::High16Bits(value); |
| 758 lui(rd, Immediate(high)); | 770 lui(rd, Immediate(high)); |
| 759 ori(rd, rd, Immediate(low)); | 771 ori(rd, rd, Immediate(low)); |
| 760 } | 772 } |
| 761 } | 773 } |
| 762 | 774 |
| 763 void LoadImmediate(FRegister rd, double value) { | 775 void LoadImmediate(DRegister rd, double value) { |
| 764 ASSERT(EvenFPURegister(rd)); | 776 FRegister frd = static_cast<FRegister>(rd * 2); |
| 765 const int64_t ival = bit_cast<uint64_t, double>(value); | 777 const int64_t ival = bit_cast<uint64_t, double>(value); |
| 766 const int32_t low = Utils::Low32Bits(ival); | 778 const int32_t low = Utils::Low32Bits(ival); |
| 767 const int32_t high = Utils::High32Bits(ival); | 779 const int32_t high = Utils::High32Bits(ival); |
| 768 if (low != 0) { | 780 if (low != 0) { |
| 769 LoadImmediate(TMP1, low); | 781 LoadImmediate(TMP1, low); |
| 770 mtc1(TMP1, rd); | 782 mtc1(TMP1, frd); |
| 771 } else { | 783 } else { |
| 772 mtc1(ZR, rd); | 784 mtc1(ZR, frd); |
| 773 } | 785 } |
| 774 | 786 |
| 775 if (high != 0) { | 787 if (high != 0) { |
| 776 LoadImmediate(TMP1, high); | 788 LoadImmediate(TMP1, high); |
| 777 mtc1(TMP1, static_cast<FRegister>(rd + 1)); | 789 mtc1(TMP1, static_cast<FRegister>(frd + 1)); |
| 778 } else { | 790 } else { |
| 779 mtc1(ZR, static_cast<FRegister>(rd + 1)); | 791 mtc1(ZR, static_cast<FRegister>(frd + 1)); |
| 780 } | 792 } |
| 781 } | 793 } |
| 782 | 794 |
| 783 void LoadImmediate(FRegister rd, float value) { | 795 void LoadImmediate(FRegister rd, float value) { |
| 784 const int32_t ival = bit_cast<int32_t, float>(value); | 796 const int32_t ival = bit_cast<int32_t, float>(value); |
| 785 if (ival == 0) { | 797 if (ival == 0) { |
| 786 mtc1(ZR, rd); | 798 mtc1(ZR, rd); |
| 787 } else { | 799 } else { |
| 788 LoadImmediate(TMP1, ival); | 800 LoadImmediate(TMP1, ival); |
| 789 mtc1(TMP1, rd); | 801 mtc1(TMP1, rd); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 846 LoadImmediate(CMPRES, value); | 858 LoadImmediate(CMPRES, value); |
| 847 BranchUnsignedGreater(rd, CMPRES, l); | 859 BranchUnsignedGreater(rd, CMPRES, l); |
| 848 } | 860 } |
| 849 | 861 |
| 850 void BranchSignedGreaterEqual(Register rd, Register rs, Label* l) { | 862 void BranchSignedGreaterEqual(Register rd, Register rs, Label* l) { |
| 851 slt(CMPRES, rd, rs); // CMPRES = rd < rs ? 1 : 0. | 863 slt(CMPRES, rd, rs); // CMPRES = rd < rs ? 1 : 0. |
| 852 beq(CMPRES, ZR, l); // If CMPRES = 0, then rd >= rs. | 864 beq(CMPRES, ZR, l); // If CMPRES = 0, then rd >= rs. |
| 853 } | 865 } |
| 854 | 866 |
| 855 void BranchSignedGreaterEqual(Register rd, int32_t value, Label* l) { | 867 void BranchSignedGreaterEqual(Register rd, int32_t value, Label* l) { |
| 856 LoadImmediate(CMPRES, value); | 868 if (Utils::IsInt(kImmBits, value)) { |
| 857 BranchSignedGreaterEqual(rd, CMPRES, l); | 869 slti(CMPRES, rd, Immediate(value)); |
| 870 beq(CMPRES, ZR, l); |
| 871 } else { |
| 872 LoadImmediate(CMPRES, value); |
| 873 BranchSignedGreaterEqual(rd, CMPRES, l); |
| 874 } |
| 858 } | 875 } |
| 859 | 876 |
| 860 void BranchUnsignedGreaterEqual(Register rd, Register rs, Label* l) { | 877 void BranchUnsignedGreaterEqual(Register rd, Register rs, Label* l) { |
| 861 sltu(CMPRES, rd, rs); // CMPRES = rd < rs ? 1 : 0. | 878 sltu(CMPRES, rd, rs); // CMPRES = rd < rs ? 1 : 0. |
| 862 beq(CMPRES, ZR, l); | 879 beq(CMPRES, ZR, l); |
| 863 } | 880 } |
| 864 | 881 |
| 865 void BranchUnsignedGreaterEqual(Register rd, int32_t value, Label* l) { | 882 void BranchUnsignedGreaterEqual(Register rd, int32_t value, Label* l) { |
| 866 LoadImmediate(CMPRES, value); | 883 if (Utils::IsUint(kImmBits, value)) { |
| 867 BranchUnsignedGreaterEqual(rd, CMPRES, l); | 884 sltiu(CMPRES, rd, Immediate(value)); |
| 885 beq(CMPRES, ZR, l); |
| 886 } else { |
| 887 LoadImmediate(CMPRES, value); |
| 888 BranchUnsignedGreaterEqual(rd, CMPRES, l); |
| 889 } |
| 868 } | 890 } |
| 869 | 891 |
| 870 void BranchSignedLess(Register rd, Register rs, Label* l) { | 892 void BranchSignedLess(Register rd, Register rs, Label* l) { |
| 871 BranchSignedGreater(rs, rd, l); | 893 BranchSignedGreater(rs, rd, l); |
| 872 } | 894 } |
| 873 | 895 |
| 874 void BranchSignedLess(Register rd, int32_t value, Label* l) { | 896 void BranchSignedLess(Register rd, int32_t value, Label* l) { |
| 875 LoadImmediate(CMPRES, value); | 897 if (Utils::IsInt(kImmBits, value)) { |
| 876 BranchSignedGreater(CMPRES, rd, l); | 898 slti(CMPRES, rd, Immediate(value)); |
| 899 bne(CMPRES, ZR, l); |
| 900 } else { |
| 901 LoadImmediate(CMPRES, value); |
| 902 BranchSignedGreater(CMPRES, rd, l); |
| 903 } |
| 877 } | 904 } |
| 878 | 905 |
| 879 void BranchUnsignedLess(Register rd, Register rs, Label* l) { | 906 void BranchUnsignedLess(Register rd, Register rs, Label* l) { |
| 880 BranchUnsignedGreater(rs, rd, l); | 907 BranchUnsignedGreater(rs, rd, l); |
| 881 } | 908 } |
| 882 | 909 |
| 883 void BranchUnsignedLess(Register rd, int32_t value, Label* l) { | 910 void BranchUnsignedLess(Register rd, int32_t value, Label* l) { |
| 884 LoadImmediate(CMPRES, value); | 911 if (Utils::IsUint(kImmBits, value)) { |
| 885 BranchUnsignedGreater(CMPRES, rd, l); | 912 sltiu(CMPRES, rd, Immediate(value)); |
| 913 bne(CMPRES, ZR, l); |
| 914 } else { |
| 915 LoadImmediate(CMPRES, value); |
| 916 BranchUnsignedGreater(CMPRES, rd, l); |
| 917 } |
| 886 } | 918 } |
| 887 | 919 |
| 888 void BranchSignedLessEqual(Register rd, Register rs, Label* l) { | 920 void BranchSignedLessEqual(Register rd, Register rs, Label* l) { |
| 889 BranchSignedGreaterEqual(rs, rd, l); | 921 BranchSignedGreaterEqual(rs, rd, l); |
| 890 } | 922 } |
| 891 | 923 |
| 892 void BranchSignedLessEqual(Register rd, int32_t value, Label* l) { | 924 void BranchSignedLessEqual(Register rd, int32_t value, Label* l) { |
| 893 LoadImmediate(CMPRES, value); | 925 LoadImmediate(CMPRES, value); |
| 894 BranchSignedGreaterEqual(CMPRES, rd, l); | 926 BranchSignedGreaterEqual(CMPRES, rd, l); |
| 895 } | 927 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 930 // Create a frame for calling into runtime that preserves all volatile | 962 // Create a frame for calling into runtime that preserves all volatile |
| 931 // registers. Frame's SP is guaranteed to be correctly aligned and | 963 // registers. Frame's SP is guaranteed to be correctly aligned and |
| 932 // frame_space bytes are reserved under it. | 964 // frame_space bytes are reserved under it. |
| 933 void EnterCallRuntimeFrame(intptr_t frame_space); | 965 void EnterCallRuntimeFrame(intptr_t frame_space); |
| 934 void LeaveCallRuntimeFrame(); | 966 void LeaveCallRuntimeFrame(); |
| 935 | 967 |
| 936 void LoadWordFromPoolOffset(Register rd, int32_t offset); | 968 void LoadWordFromPoolOffset(Register rd, int32_t offset); |
| 937 void LoadObject(Register rd, const Object& object); | 969 void LoadObject(Register rd, const Object& object); |
| 938 void PushObject(const Object& object); | 970 void PushObject(const Object& object); |
| 939 | 971 |
| 940 // Sets register rd to zero if the object is equal to register rn, | 972 // Compares rn with the object. Returns results in rd1 and rd2. |
| 941 // sets it to non-zero otherwise. | 973 // rd1 is 1 if rn < object. rd2 is 1 if object < rn. Since both cannot be |
| 942 void CompareObject(Register rd, Register rn, const Object& object); | 974 // 1, rd1 == rd2 (== 0) iff rn == object. |
| 975 void CompareObject(Register rd1, Register rd2, |
| 976 Register rn, const Object& object); |
| 943 | 977 |
| 944 void LoadClassId(Register result, Register object); | 978 void LoadClassId(Register result, Register object); |
| 945 void LoadClassById(Register result, Register class_id); | 979 void LoadClassById(Register result, Register class_id); |
| 946 void LoadClass(Register result, Register object); | 980 void LoadClass(Register result, Register object); |
| 947 | 981 |
| 948 void StoreIntoObject(Register object, // Object we are storing into. | 982 void StoreIntoObject(Register object, // Object we are storing into. |
| 949 const Address& dest, // Where we are storing into. | 983 const Address& dest, // Where we are storing into. |
| 950 Register value, // Value we are storing. | 984 Register value, // Value we are storing. |
| 951 bool can_value_be_smi = true); | 985 bool can_value_be_smi = true); |
| 952 | 986 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 986 | 1020 |
| 987 private: | 1021 private: |
| 988 intptr_t pc_offset_; | 1022 intptr_t pc_offset_; |
| 989 const String& comment_; | 1023 const String& comment_; |
| 990 | 1024 |
| 991 DISALLOW_COPY_AND_ASSIGN(CodeComment); | 1025 DISALLOW_COPY_AND_ASSIGN(CodeComment); |
| 992 }; | 1026 }; |
| 993 | 1027 |
| 994 GrowableArray<CodeComment*> comments_; | 1028 GrowableArray<CodeComment*> comments_; |
| 995 | 1029 |
| 996 bool EvenFPURegister(FRegister reg) { | |
| 997 return (static_cast<int>(reg) & 1) == 0; | |
| 998 } | |
| 999 | |
| 1000 void Emit(int32_t value) { | 1030 void Emit(int32_t value) { |
| 1001 // Emitting an instruction clears the delay slot state. | 1031 // Emitting an instruction clears the delay slot state. |
| 1002 in_delay_slot_ = false; | 1032 in_delay_slot_ = false; |
| 1003 delay_slot_available_ = false; | 1033 delay_slot_available_ = false; |
| 1004 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1034 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1005 buffer_.Emit<int32_t>(value); | 1035 buffer_.Emit<int32_t>(value); |
| 1006 } | 1036 } |
| 1007 | 1037 |
| 1008 // Encode CPU instructions according to the types specified in | 1038 // Encode CPU instructions according to the types specified in |
| 1009 // Figures 4-1, 4-2 and 4-3 in VolI-A. | 1039 // Figures 4-1, 4-2 and 4-3 in VolI-A. |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1141 Register value, | 1171 Register value, |
| 1142 Label* no_update); | 1172 Label* no_update); |
| 1143 | 1173 |
| 1144 DISALLOW_ALLOCATION(); | 1174 DISALLOW_ALLOCATION(); |
| 1145 DISALLOW_COPY_AND_ASSIGN(Assembler); | 1175 DISALLOW_COPY_AND_ASSIGN(Assembler); |
| 1146 }; | 1176 }; |
| 1147 | 1177 |
| 1148 } // namespace dart | 1178 } // namespace dart |
| 1149 | 1179 |
| 1150 #endif // VM_ASSEMBLER_MIPS_H_ | 1180 #endif // VM_ASSEMBLER_MIPS_H_ |
| OLD | NEW |