| 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); | 
| } | 
| } | 
|  | 
|  |