| Index: src/mips64/assembler-mips64.cc
|
| diff --git a/src/mips64/assembler-mips64.cc b/src/mips64/assembler-mips64.cc
|
| index b35b166a2e3a1a75898d280d3ae7f412a70e5a53..09a19169d677454b241592a05424405c46729680 100644
|
| --- a/src/mips64/assembler-mips64.cc
|
| +++ b/src/mips64/assembler-mips64.cc
|
| @@ -1940,19 +1940,42 @@ void Assembler::dlsa(Register rd, Register rt, Register rs, uint8_t sa) {
|
| void Assembler::LoadRegPlusOffsetToAt(const MemOperand& src) {
|
| DCHECK(!src.rm().is(at));
|
| DCHECK(is_int32(src.offset_));
|
| - daddiu(at, zero_reg, (src.offset_ >> kLuiShift) & kImm16Mask);
|
| - dsll(at, at, kLuiShift);
|
| + lui(at, (src.offset_ >> kLuiShift) & kImm16Mask);
|
| ori(at, at, src.offset_ & kImm16Mask); // Load 32-bit offset.
|
| daddu(at, at, src.rm()); // Add base register.
|
| }
|
|
|
| +// Helper for base-reg + upper part of offset, when offset is larger than int16.
|
| +// Loads higher part of the offset to AT register.
|
| +// Returns lower part of the offset to be used as offset
|
| +// in Load/Store instructions
|
| +int32_t Assembler::LoadRegPlusUpperOffsetPartToAt(const MemOperand& src) {
|
| + DCHECK(!src.rm().is(at));
|
| + DCHECK(is_int32(src.offset_));
|
| + int32_t hi = (src.offset_ >> kLuiShift) & kImm16Mask;
|
| + // If the highest bit of the lower part of the offset is 1, this would make
|
| + // the offset in the load/store instruction negative. We need to compensate
|
| + // for this by adding 1 to the upper part of the offset.
|
| + if (src.offset_ & kNegOffset) {
|
| + if ((hi & kNegOffset) != ((hi + 1) & kNegOffset)) {
|
| + LoadRegPlusOffsetToAt(src);
|
| + return 0;
|
| + }
|
| +
|
| + hi += 1;
|
| + }
|
| +
|
| + lui(at, hi);
|
| + daddu(at, at, src.rm());
|
| + return (src.offset_ & kImm16Mask);
|
| +}
|
|
|
| void Assembler::lb(Register rd, const MemOperand& rs) {
|
| if (is_int16(rs.offset_)) {
|
| GenInstrImmediate(LB, rs.rm(), rd, rs.offset_);
|
| } else { // Offset > 16 bits, use multiple instructions to load.
|
| - LoadRegPlusOffsetToAt(rs);
|
| - GenInstrImmediate(LB, at, rd, 0); // Equiv to lb(rd, MemOperand(at, 0));
|
| + int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
|
| + GenInstrImmediate(LB, at, rd, off16);
|
| }
|
| }
|
|
|
| @@ -1961,8 +1984,8 @@ void Assembler::lbu(Register rd, const MemOperand& rs) {
|
| if (is_int16(rs.offset_)) {
|
| GenInstrImmediate(LBU, rs.rm(), rd, rs.offset_);
|
| } else { // Offset > 16 bits, use multiple instructions to load.
|
| - LoadRegPlusOffsetToAt(rs);
|
| - GenInstrImmediate(LBU, at, rd, 0); // Equiv to lbu(rd, MemOperand(at, 0));
|
| + int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
|
| + GenInstrImmediate(LBU, at, rd, off16);
|
| }
|
| }
|
|
|
| @@ -1971,8 +1994,8 @@ void Assembler::lh(Register rd, const MemOperand& rs) {
|
| if (is_int16(rs.offset_)) {
|
| GenInstrImmediate(LH, rs.rm(), rd, rs.offset_);
|
| } else { // Offset > 16 bits, use multiple instructions to load.
|
| - LoadRegPlusOffsetToAt(rs);
|
| - GenInstrImmediate(LH, at, rd, 0); // Equiv to lh(rd, MemOperand(at, 0));
|
| + int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
|
| + GenInstrImmediate(LH, at, rd, off16);
|
| }
|
| }
|
|
|
| @@ -1981,8 +2004,8 @@ void Assembler::lhu(Register rd, const MemOperand& rs) {
|
| if (is_int16(rs.offset_)) {
|
| GenInstrImmediate(LHU, rs.rm(), rd, rs.offset_);
|
| } else { // Offset > 16 bits, use multiple instructions to load.
|
| - LoadRegPlusOffsetToAt(rs);
|
| - GenInstrImmediate(LHU, at, rd, 0); // Equiv to lhu(rd, MemOperand(at, 0));
|
| + int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
|
| + GenInstrImmediate(LHU, at, rd, off16);
|
| }
|
| }
|
|
|
| @@ -1991,8 +2014,8 @@ void Assembler::lw(Register rd, const MemOperand& rs) {
|
| if (is_int16(rs.offset_)) {
|
| GenInstrImmediate(LW, rs.rm(), rd, rs.offset_);
|
| } else { // Offset > 16 bits, use multiple instructions to load.
|
| - LoadRegPlusOffsetToAt(rs);
|
| - GenInstrImmediate(LW, at, rd, 0); // Equiv to lw(rd, MemOperand(at, 0));
|
| + int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
|
| + GenInstrImmediate(LW, at, rd, off16);
|
| }
|
| }
|
|
|
| @@ -2001,8 +2024,8 @@ void Assembler::lwu(Register rd, const MemOperand& rs) {
|
| if (is_int16(rs.offset_)) {
|
| GenInstrImmediate(LWU, rs.rm(), rd, rs.offset_);
|
| } else { // Offset > 16 bits, use multiple instructions to load.
|
| - LoadRegPlusOffsetToAt(rs);
|
| - GenInstrImmediate(LWU, at, rd, 0); // Equiv to lwu(rd, MemOperand(at, 0));
|
| + int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
|
| + GenInstrImmediate(LWU, at, rd, off16);
|
| }
|
| }
|
|
|
| @@ -2025,8 +2048,8 @@ void Assembler::sb(Register rd, const MemOperand& rs) {
|
| if (is_int16(rs.offset_)) {
|
| GenInstrImmediate(SB, rs.rm(), rd, rs.offset_);
|
| } else { // Offset > 16 bits, use multiple instructions to store.
|
| - LoadRegPlusOffsetToAt(rs);
|
| - GenInstrImmediate(SB, at, rd, 0); // Equiv to sb(rd, MemOperand(at, 0));
|
| + int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
|
| + GenInstrImmediate(SB, at, rd, off16);
|
| }
|
| }
|
|
|
| @@ -2035,8 +2058,8 @@ void Assembler::sh(Register rd, const MemOperand& rs) {
|
| if (is_int16(rs.offset_)) {
|
| GenInstrImmediate(SH, rs.rm(), rd, rs.offset_);
|
| } else { // Offset > 16 bits, use multiple instructions to store.
|
| - LoadRegPlusOffsetToAt(rs);
|
| - GenInstrImmediate(SH, at, rd, 0); // Equiv to sh(rd, MemOperand(at, 0));
|
| + int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
|
| + GenInstrImmediate(SH, at, rd, off16);
|
| }
|
| }
|
|
|
| @@ -2045,8 +2068,8 @@ void Assembler::sw(Register rd, const MemOperand& rs) {
|
| if (is_int16(rs.offset_)) {
|
| GenInstrImmediate(SW, rs.rm(), rd, rs.offset_);
|
| } else { // Offset > 16 bits, use multiple instructions to store.
|
| - LoadRegPlusOffsetToAt(rs);
|
| - GenInstrImmediate(SW, at, rd, 0); // Equiv to sw(rd, MemOperand(at, 0));
|
| + int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
|
| + GenInstrImmediate(SW, at, rd, off16);
|
| }
|
| }
|
|
|
| @@ -2130,8 +2153,8 @@ void Assembler::ld(Register rd, const MemOperand& rs) {
|
| if (is_int16(rs.offset_)) {
|
| GenInstrImmediate(LD, rs.rm(), rd, rs.offset_);
|
| } else { // Offset > 16 bits, use multiple instructions to load.
|
| - LoadRegPlusOffsetToAt(rs);
|
| - GenInstrImmediate(LD, at, rd, 0); // Equiv to lw(rd, MemOperand(at, 0));
|
| + int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
|
| + GenInstrImmediate(LD, at, rd, off16);
|
| }
|
| }
|
|
|
| @@ -2140,8 +2163,8 @@ void Assembler::sd(Register rd, const MemOperand& rs) {
|
| if (is_int16(rs.offset_)) {
|
| GenInstrImmediate(SD, rs.rm(), rd, rs.offset_);
|
| } else { // Offset > 16 bits, use multiple instructions to store.
|
| - LoadRegPlusOffsetToAt(rs);
|
| - GenInstrImmediate(SD, at, rd, 0); // Equiv to sw(rd, MemOperand(at, 0));
|
| + int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
|
| + GenInstrImmediate(SD, at, rd, off16);
|
| }
|
| }
|
|
|
| @@ -2551,8 +2574,8 @@ void Assembler::lwc1(FPURegister fd, const MemOperand& src) {
|
| if (is_int16(src.offset_)) {
|
| GenInstrImmediate(LWC1, src.rm(), fd, src.offset_);
|
| } else { // Offset > 16 bits, use multiple instructions to load.
|
| - LoadRegPlusOffsetToAt(src);
|
| - GenInstrImmediate(LWC1, at, fd, 0);
|
| + int32_t off16 = LoadRegPlusUpperOffsetPartToAt(src);
|
| + GenInstrImmediate(LWC1, at, fd, off16);
|
| }
|
| }
|
|
|
| @@ -2561,8 +2584,8 @@ void Assembler::ldc1(FPURegister fd, const MemOperand& src) {
|
| if (is_int16(src.offset_)) {
|
| GenInstrImmediate(LDC1, src.rm(), fd, src.offset_);
|
| } else { // Offset > 16 bits, use multiple instructions to load.
|
| - LoadRegPlusOffsetToAt(src);
|
| - GenInstrImmediate(LDC1, at, fd, 0);
|
| + int32_t off16 = LoadRegPlusUpperOffsetPartToAt(src);
|
| + GenInstrImmediate(LDC1, at, fd, off16);
|
| }
|
| }
|
|
|
| @@ -2571,8 +2594,8 @@ void Assembler::swc1(FPURegister fd, const MemOperand& src) {
|
| if (is_int16(src.offset_)) {
|
| GenInstrImmediate(SWC1, src.rm(), fd, src.offset_);
|
| } else { // Offset > 16 bits, use multiple instructions to load.
|
| - LoadRegPlusOffsetToAt(src);
|
| - GenInstrImmediate(SWC1, at, fd, 0);
|
| + int32_t off16 = LoadRegPlusUpperOffsetPartToAt(src);
|
| + GenInstrImmediate(SWC1, at, fd, off16);
|
| }
|
| }
|
|
|
| @@ -2582,8 +2605,8 @@ void Assembler::sdc1(FPURegister fd, const MemOperand& src) {
|
| if (is_int16(src.offset_)) {
|
| GenInstrImmediate(SDC1, src.rm(), fd, src.offset_);
|
| } else { // Offset > 16 bits, use multiple instructions to load.
|
| - LoadRegPlusOffsetToAt(src);
|
| - GenInstrImmediate(SDC1, at, fd, 0);
|
| + int32_t off16 = LoadRegPlusUpperOffsetPartToAt(src);
|
| + GenInstrImmediate(SDC1, at, fd, off16);
|
| }
|
| }
|
|
|
|
|