| Index: src/mips64/assembler-mips64.h
|
| diff --git a/src/mips/assembler-mips.h b/src/mips64/assembler-mips64.h
|
| similarity index 92%
|
| copy from src/mips/assembler-mips.h
|
| copy to src/mips64/assembler-mips64.h
|
| index 2ba3ef7166f2f9023adb77c5d128dd12a51768bc..395ab77d8ace9116fb290d140da7a67d6ab468eb 100644
|
| --- a/src/mips/assembler-mips.h
|
| +++ b/src/mips64/assembler-mips64.h
|
| @@ -37,9 +37,8 @@
|
| #define V8_MIPS_ASSEMBLER_MIPS_H_
|
|
|
| #include <stdio.h>
|
| -
|
| #include "src/assembler.h"
|
| -#include "src/mips/constants-mips.h"
|
| +#include "src/mips64/constants-mips64.h"
|
| #include "src/serialize.h"
|
|
|
| namespace v8 {
|
| @@ -74,19 +73,9 @@ namespace internal {
|
| struct Register {
|
| static const int kNumRegisters = v8::internal::kNumRegisters;
|
| static const int kMaxNumAllocatableRegisters = 14; // v0 through t6 and cp.
|
| - static const int kSizeInBytes = 4;
|
| + static const int kSizeInBytes = 8;
|
| static const int kCpRegister = 23; // cp (s7) is the 23rd register.
|
|
|
| -#if defined(V8_TARGET_LITTLE_ENDIAN)
|
| - static const int kMantissaOffset = 0;
|
| - static const int kExponentOffset = 4;
|
| -#elif defined(V8_TARGET_BIG_ENDIAN)
|
| - static const int kMantissaOffset = 4;
|
| - static const int kExponentOffset = 0;
|
| -#else
|
| -#error Unknown endianness
|
| -#endif
|
| -
|
| inline static int NumAllocatableRegisters();
|
|
|
| static int ToAllocationIndex(Register reg) {
|
| @@ -113,13 +102,13 @@ struct Register {
|
| "a1",
|
| "a2",
|
| "a3",
|
| + "a4",
|
| + "a5",
|
| + "a6",
|
| + "a7",
|
| "t0",
|
| "t1",
|
| "t2",
|
| - "t3",
|
| - "t4",
|
| - "t5",
|
| - "t6",
|
| "s7",
|
| };
|
| return names[index];
|
| @@ -162,16 +151,16 @@ REGISTER(a0, 4);
|
| REGISTER(a1, 5);
|
| REGISTER(a2, 6);
|
| REGISTER(a3, 7);
|
| -// t0 - t9: Can be used without reservation, act as temporary registers and are
|
| -// allowed to be destroyed by subroutines.
|
| -REGISTER(t0, 8);
|
| -REGISTER(t1, 9);
|
| -REGISTER(t2, 10);
|
| -REGISTER(t3, 11);
|
| -REGISTER(t4, 12);
|
| -REGISTER(t5, 13);
|
| -REGISTER(t6, 14);
|
| -REGISTER(t7, 15);
|
| +// a4 - a7 t0 - t3: Can be used without reservation, act as temporary registers
|
| +// and are allowed to be destroyed by subroutines.
|
| +REGISTER(a4, 8);
|
| +REGISTER(a5, 9);
|
| +REGISTER(a6, 10);
|
| +REGISTER(a7, 11);
|
| +REGISTER(t0, 12);
|
| +REGISTER(t1, 13);
|
| +REGISTER(t2, 14);
|
| +REGISTER(t3, 15);
|
| // s0 - s7: Subroutine register variables. Subroutines that write to these
|
| // registers must restore their values before exiting so that the caller can
|
| // expect the values to be preserved.
|
| @@ -238,6 +227,7 @@ struct FPURegister {
|
| bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters ; }
|
| bool is(FPURegister creg) const { return code_ == creg.code_; }
|
| FPURegister low() const {
|
| + // TODO(plind): Create ASSERT for FR=0 mode. This usage suspect for FR=1.
|
| // Find low reg of a Double-reg pair, which is the reg itself.
|
| ASSERT(code_ % 2 == 0); // Specified Double reg must be even.
|
| FPURegister reg;
|
| @@ -246,6 +236,7 @@ struct FPURegister {
|
| return reg;
|
| }
|
| FPURegister high() const {
|
| + // TODO(plind): Create ASSERT for FR=0 mode. This usage illegal in FR=1.
|
| // Find high reg of a Doubel-reg pair, which is reg + 1.
|
| ASSERT(code_ % 2 == 0); // Specified Double reg must be even.
|
| FPURegister reg;
|
| @@ -275,7 +266,7 @@ struct FPURegister {
|
| // in pairs, starting with the even numbered register. So a double operation
|
| // on f0 really uses f0 and f1.
|
| // (Modern mips hardware also supports 32 64-bit registers, via setting
|
| -// (priviledged) Status Register FR bit to 1. This is used by the N32 ABI,
|
| +// (privileged) Status Register FR bit to 1. This is used by the N32 ABI,
|
| // but it is not in common use. Someday we will want to support this in v8.)
|
|
|
| // For O32 ABI, Floats and Doubles refer to same set of 32 32-bit registers.
|
| @@ -356,13 +347,14 @@ const FPUControlRegister FCSR = { kFCSRRegister };
|
|
|
| // -----------------------------------------------------------------------------
|
| // Machine instruction Operands.
|
| -
|
| +const int kSmiShift = kSmiTagSize + kSmiShiftSize;
|
| +const uint64_t kSmiShiftMask = (1UL << kSmiShift) - 1;
|
| // Class Operand represents a shifter operand in data processing instructions.
|
| class Operand BASE_EMBEDDED {
|
| public:
|
| // Immediate.
|
| - INLINE(explicit Operand(int32_t immediate,
|
| - RelocInfo::Mode rmode = RelocInfo::NONE32));
|
| + INLINE(explicit Operand(int64_t immediate,
|
| + RelocInfo::Mode rmode = RelocInfo::NONE64));
|
| INLINE(explicit Operand(const ExternalReference& f));
|
| INLINE(explicit Operand(const char* s));
|
| INLINE(explicit Operand(Object** opp));
|
| @@ -376,16 +368,16 @@ class Operand BASE_EMBEDDED {
|
| // Return true if this is a register operand.
|
| INLINE(bool is_reg() const);
|
|
|
| - inline int32_t immediate() const {
|
| + inline int64_t immediate() const {
|
| ASSERT(!is_reg());
|
| - return imm32_;
|
| + return imm64_;
|
| }
|
|
|
| Register rm() const { return rm_; }
|
|
|
| private:
|
| Register rm_;
|
| - int32_t imm32_; // Valid if rm_ == no_reg.
|
| + int64_t imm64_; // Valid if rm_ == no_reg.
|
| RelocInfo::Mode rmode_;
|
|
|
| friend class Assembler;
|
| @@ -403,8 +395,8 @@ class MemOperand : public Operand {
|
| offset_zero = 0
|
| };
|
|
|
| - explicit MemOperand(Register rn, int32_t offset = 0);
|
| - explicit MemOperand(Register rn, int32_t unit, int32_t multiplier,
|
| + explicit MemOperand(Register rn, int64_t offset = 0);
|
| + explicit MemOperand(Register rn, int64_t unit, int64_t multiplier,
|
| OffsetAddend offset_addend = offset_zero);
|
| int32_t offset() const { return offset_; }
|
|
|
| @@ -470,7 +462,7 @@ class Assembler : public AssemblerBase {
|
| ASSERT((o & 3) == 0); // Assert the offset is aligned.
|
| return o >> 2;
|
| }
|
| - uint32_t jump_address(Label* L);
|
| + uint64_t jump_address(Label* L);
|
|
|
| // Puts a labels target address at the given position.
|
| // The high 8 bits are set to zero.
|
| @@ -521,7 +513,7 @@ class Assembler : public AssemblerBase {
|
| inline static void deserialization_set_special_target_at(
|
| Address instruction_payload, Code* code, Address target) {
|
| set_target_address_at(
|
| - instruction_payload - kInstructionsFor32BitConstant * kInstrSize,
|
| + instruction_payload - kInstructionsFor64BitConstant * kInstrSize,
|
| code,
|
| target);
|
| }
|
| @@ -540,7 +532,7 @@ class Assembler : public AssemblerBase {
|
| // a target is resolved and written.
|
| static const int kSpecialTargetSize = 0;
|
|
|
| - // Number of consecutive instructions used to store 32bit constant.
|
| + // Number of consecutive instructions used to store 32bit/64bit constant.
|
| // Before jump-optimizations, this constant was used in
|
| // RelocInfo::target_address_address() function to tell serializer address of
|
| // the instruction that follows LUI/ORI instruction pair. Now, with new jump
|
| @@ -548,10 +540,11 @@ class Assembler : public AssemblerBase {
|
| // follows LUI/ORI pair is substituted with J/JAL, this constant equals
|
| // to 3 instructions (LUI+ORI+J/JAL/JR/JALR).
|
| static const int kInstructionsFor32BitConstant = 3;
|
| + static const int kInstructionsFor64BitConstant = 5;
|
|
|
| // Distance between the instruction referring to the address of the call
|
| // target and the return address.
|
| - static const int kCallTargetAddressOffset = 4 * kInstrSize;
|
| + static const int kCallTargetAddressOffset = 6 * kInstrSize;
|
|
|
| // Distance between start of patched return sequence and the emitted address
|
| // to jump to.
|
| @@ -565,12 +558,12 @@ class Assembler : public AssemblerBase {
|
| // register.
|
| static const int kPcLoadDelta = 4;
|
|
|
| - static const int kPatchDebugBreakSlotReturnOffset = 4 * kInstrSize;
|
| + static const int kPatchDebugBreakSlotReturnOffset = 6 * kInstrSize;
|
|
|
| // Number of instructions used for the JS return sequence. The constant is
|
| // used by the debugger to patch the JS return sequence.
|
| static const int kJSReturnSequenceInstructions = 7;
|
| - static const int kDebugBreakSlotInstructions = 4;
|
| + static const int kDebugBreakSlotInstructions = 6;
|
| static const int kDebugBreakSlotLength =
|
| kDebugBreakSlotInstructions * kInstrSize;
|
|
|
| @@ -638,12 +631,12 @@ class Assembler : public AssemblerBase {
|
| // instead of using the Label* version.
|
|
|
| // Jump targets must be in the current 256 MB-aligned region. i.e. 28 bits.
|
| - void j(int32_t target);
|
| - void jal(int32_t target);
|
| + void j(int64_t target);
|
| + void jal(int64_t target);
|
| void jalr(Register rs, Register rd = ra);
|
| void jr(Register target);
|
| - void j_or_jr(int32_t target, Register rs);
|
| - void jal_or_jalr(int32_t target, Register rs);
|
| + void j_or_jr(int64_t target, Register rs);
|
| + void jal_or_jalr(int64_t target, Register rs);
|
|
|
|
|
| // -------Data-processing-instructions---------
|
| @@ -656,8 +649,15 @@ class Assembler : public AssemblerBase {
|
| void div(Register rs, Register rt);
|
| void divu(Register rs, Register rt);
|
| void mul(Register rd, Register rs, Register rt);
|
| + void daddu(Register rd, Register rs, Register rt);
|
| + void dsubu(Register rd, Register rs, Register rt);
|
| + void dmult(Register rs, Register rt);
|
| + void dmultu(Register rs, Register rt);
|
| + void ddiv(Register rs, Register rt);
|
| + void ddivu(Register rs, Register rt);
|
|
|
| void addiu(Register rd, Register rs, int32_t j);
|
| + void daddiu(Register rd, Register rs, int32_t j);
|
|
|
| // Logical.
|
| void and_(Register rd, Register rs, Register rt);
|
| @@ -682,6 +682,17 @@ class Assembler : public AssemblerBase {
|
| void srav(Register rt, Register rd, Register rs);
|
| void rotr(Register rd, Register rt, uint16_t sa);
|
| void rotrv(Register rd, Register rt, Register rs);
|
| + void dsll(Register rd, Register rt, uint16_t sa);
|
| + void dsllv(Register rd, Register rt, Register rs);
|
| + void dsrl(Register rd, Register rt, uint16_t sa);
|
| + void dsrlv(Register rd, Register rt, Register rs);
|
| + void drotr(Register rd, Register rt, uint16_t sa);
|
| + void drotrv(Register rd, Register rt, Register rs);
|
| + void dsra(Register rt, Register rd, uint16_t sa);
|
| + void dsrav(Register rd, Register rt, Register rs);
|
| + void dsll32(Register rt, Register rd, uint16_t sa);
|
| + void dsrl32(Register rt, Register rd, uint16_t sa);
|
| + void dsra32(Register rt, Register rd, uint16_t sa);
|
|
|
|
|
| // ------------Memory-instructions-------------
|
| @@ -691,6 +702,7 @@ class Assembler : public AssemblerBase {
|
| void lh(Register rd, const MemOperand& rs);
|
| void lhu(Register rd, const MemOperand& rs);
|
| void lw(Register rd, const MemOperand& rs);
|
| + void lwu(Register rd, const MemOperand& rs);
|
| void lwl(Register rd, const MemOperand& rs);
|
| void lwr(Register rd, const MemOperand& rs);
|
| void sb(Register rd, const MemOperand& rs);
|
| @@ -698,6 +710,12 @@ class Assembler : public AssemblerBase {
|
| void sw(Register rd, const MemOperand& rs);
|
| void swl(Register rd, const MemOperand& rs);
|
| void swr(Register rd, const MemOperand& rs);
|
| + void ldl(Register rd, const MemOperand& rs);
|
| + void ldr(Register rd, const MemOperand& rs);
|
| + void sdl(Register rd, const MemOperand& rs);
|
| + void sdr(Register rd, const MemOperand& rs);
|
| + void ld(Register rd, const MemOperand& rs);
|
| + void sd(Register rd, const MemOperand& rs);
|
|
|
|
|
| // ----------------Prefetch--------------------
|
| @@ -748,7 +766,12 @@ class Assembler : public AssemblerBase {
|
| void sdc1(FPURegister fs, const MemOperand& dst);
|
|
|
| void mtc1(Register rt, FPURegister fs);
|
| + void mthc1(Register rt, FPURegister fs);
|
| + void dmtc1(Register rt, FPURegister fs);
|
| +
|
| void mfc1(Register rt, FPURegister fs);
|
| + void mfhc1(Register rt, FPURegister fs);
|
| + void dmfc1(Register rt, FPURegister fs);
|
|
|
| void ctc1(Register rt, FPUControlRegister fs);
|
| void cfc1(Register rt, FPUControlRegister fs);
|
| @@ -977,13 +1000,13 @@ class Assembler : public AssemblerBase {
|
| // the relocation info.
|
| TypeFeedbackId recorded_ast_id_;
|
|
|
| - int32_t buffer_space() const { return reloc_info_writer.pos() - pc_; }
|
| + int64_t buffer_space() const { return reloc_info_writer.pos() - pc_; }
|
|
|
| // Decode branch instruction at pos and return branch target pos.
|
| - int target_at(int32_t pos);
|
| + int64_t target_at(int64_t pos);
|
|
|
| // Patch branch instruction at pos to branch to given branch target pos.
|
| - void target_at_put(int32_t pos, int32_t target_pos);
|
| + void target_at_put(int64_t pos, int64_t target_pos);
|
|
|
| // Say if we need to relocate with this mode.
|
| bool MustUseReg(RelocInfo::Mode rmode);
|
| @@ -1077,6 +1100,7 @@ class Assembler : public AssemblerBase {
|
| inline void CheckBuffer();
|
| void GrowBuffer();
|
| inline void emit(Instr x);
|
| + inline void emit(uint64_t x);
|
| inline void CheckTrampolinePoolQuick();
|
|
|
| // Instruction generation.
|
| @@ -1213,7 +1237,7 @@ class Assembler : public AssemblerBase {
|
| // branch instruction generation, where we use jump instructions rather
|
| // than regular branch instructions.
|
| bool trampoline_emitted_;
|
| - static const int kTrampolineSlotsSize = 4 * kInstrSize;
|
| + static const int kTrampolineSlotsSize = 6 * kInstrSize;
|
| static const int kMaxBranchOffset = (1 << (18 - 1)) - 1;
|
| static const int kInvalidSlotPos = -1;
|
|
|
|
|