Index: src/mips/macro-assembler-mips.cc |
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc |
index fc78eeca3bbfbae42c7d623ced1d906bd103b37c..9312eed02f8ae702853d80ef5ff91b4d5fa37043 100644 |
--- a/src/mips/macro-assembler-mips.cc |
+++ b/src/mips/macro-assembler-mips.cc |
@@ -1354,6 +1354,252 @@ void MacroAssembler::MultiPopReversedFPU(RegList regs) { |
addiu(sp, sp, stack_offset); |
} |
+void MacroAssembler::AddPair(Register dst_low, Register dst_high, |
+ Register left_low, Register left_high, |
+ Register right_low, Register right_high) { |
+ Label no_overflow; |
+ Register kScratchReg = s3; |
+ Register kScratchReg2 = s4; |
+ // Add lower word |
+ Addu(dst_low, left_low, right_low); |
+ Addu(dst_high, left_high, right_high); |
+ // Check for lower word unsigned overflow |
+ Sltu(kScratchReg, dst_low, left_low); |
+ Sltu(kScratchReg2, dst_low, right_low); |
+ Or(kScratchReg, kScratchReg2, kScratchReg); |
+ Branch(&no_overflow, eq, kScratchReg, Operand(zero_reg)); |
+ // Increment higher word if there was overflow |
+ Addu(dst_high, dst_high, 0x1); |
+ bind(&no_overflow); |
+} |
+ |
+void MacroAssembler::SubPair(Register dst_low, Register dst_high, |
+ Register left_low, Register left_high, |
+ Register right_low, Register right_high) { |
+ Label no_overflow; |
+ Register kScratchReg = s3; |
+ // Subtract lower word |
+ Subu(dst_low, left_low, right_low); |
+ Subu(dst_high, left_high, right_high); |
+ // Check for lower word unsigned underflow |
+ Sltu(kScratchReg, left_low, right_low); |
+ Branch(&no_overflow, eq, kScratchReg, Operand(zero_reg)); |
+ // Decrement higher word if there was underflow |
+ Subu(dst_high, dst_high, 0x1); |
+ bind(&no_overflow); |
+} |
+ |
+void MacroAssembler::ShlPair(Register dst_low, Register dst_high, |
+ Register src_low, Register src_high, |
+ Register shift) { |
+ Label less_than_32; |
+ Label zero_shift; |
+ Label word_shift; |
+ Label done; |
+ Register kScratchReg = s3; |
+ And(shift, shift, 0x3F); |
+ li(kScratchReg, 0x20); |
+ Branch(&less_than_32, lt, shift, Operand(kScratchReg)); |
+ |
+ Branch(&word_shift, eq, shift, Operand(kScratchReg)); |
+ // Shift more than 32 |
+ Subu(kScratchReg, shift, kScratchReg); |
+ mov(dst_low, zero_reg); |
+ sllv(dst_high, src_low, kScratchReg); |
+ Branch(&done); |
+ // Word shift |
+ bind(&word_shift); |
+ mov(dst_low, zero_reg); |
+ mov(dst_high, src_low); |
+ Branch(&done); |
+ |
+ bind(&less_than_32); |
+ // Check if zero shift |
+ Branch(&zero_shift, eq, shift, Operand(zero_reg)); |
+ // Shift less than 32 |
+ Subu(kScratchReg, kScratchReg, shift); |
+ sllv(dst_high, src_high, shift); |
+ sllv(dst_low, src_low, shift); |
+ srlv(kScratchReg, src_low, kScratchReg); |
+ Or(dst_high, dst_high, kScratchReg); |
+ Branch(&done); |
+ // Zero shift |
+ bind(&zero_shift); |
+ mov(dst_low, src_low); |
+ mov(dst_high, src_high); |
+ bind(&done); |
+} |
+ |
+void MacroAssembler::ShlPair(Register dst_low, Register dst_high, |
+ Register src_low, Register src_high, |
+ uint32_t shift) { |
+ Register kScratchReg = s3; |
+ shift = shift & 0x3F; |
+ if (shift < 32) { |
+ if (shift == 0) { |
+ mov(dst_low, src_low); |
+ mov(dst_high, src_high); |
+ } else { |
+ sll(dst_high, src_high, shift); |
+ sll(dst_low, src_low, shift); |
+ shift = 32 - shift; |
+ srl(kScratchReg, src_low, shift); |
+ Or(dst_high, dst_high, kScratchReg); |
+ } |
+ } else { |
+ if (shift == 32) { |
+ mov(dst_low, zero_reg); |
+ mov(dst_high, src_low); |
+ } else { |
+ shift = shift - 32; |
+ mov(dst_low, zero_reg); |
+ sll(dst_high, src_low, shift); |
+ } |
+ } |
+} |
+ |
+void MacroAssembler::ShrPair(Register dst_low, Register dst_high, |
+ Register src_low, Register src_high, |
+ Register shift) { |
+ Label less_than_32; |
+ Label zero_shift; |
+ Label word_shift; |
+ Label done; |
+ Register kScratchReg = s3; |
+ And(shift, shift, 0x3F); |
+ li(kScratchReg, 0x20); |
+ Branch(&less_than_32, lt, shift, Operand(kScratchReg)); |
+ |
+ Branch(&word_shift, eq, shift, Operand(kScratchReg)); |
+ // Shift more than 32 |
+ Subu(kScratchReg, shift, kScratchReg); |
+ mov(dst_high, zero_reg); |
+ srlv(dst_low, src_high, kScratchReg); |
+ Branch(&done); |
+ // Word shift |
+ bind(&word_shift); |
+ mov(dst_high, zero_reg); |
+ mov(dst_low, src_high); |
+ Branch(&done); |
+ |
+ bind(&less_than_32); |
+ // Check if zero shift |
+ Branch(&zero_shift, eq, shift, Operand(zero_reg)); |
+ // Shift less than 32 |
+ Subu(kScratchReg, kScratchReg, shift); |
+ srlv(dst_high, src_high, shift); |
+ srlv(dst_low, src_low, shift); |
+ sllv(kScratchReg, src_high, kScratchReg); |
+ Or(dst_low, dst_low, kScratchReg); |
+ Branch(&done); |
+ // Zero shift |
+ bind(&zero_shift); |
+ mov(dst_low, src_low); |
+ mov(dst_high, src_high); |
+ bind(&done); |
+} |
+ |
+void MacroAssembler::ShrPair(Register dst_low, Register dst_high, |
+ Register src_low, Register src_high, |
+ uint32_t shift) { |
+ Register kScratchReg = s3; |
+ shift = shift & 0x3F; |
+ if (shift < 32) { |
+ if (shift == 0) { |
+ mov(dst_low, src_low); |
+ mov(dst_high, src_high); |
+ } else { |
+ srl(dst_high, src_high, shift); |
+ srl(dst_low, src_low, shift); |
+ shift = 32 - shift; |
+ sll(kScratchReg, src_high, shift); |
+ Or(dst_low, dst_low, kScratchReg); |
+ } |
+ } else { |
+ if (shift == 32) { |
+ mov(dst_high, zero_reg); |
+ mov(dst_low, src_high); |
+ } else { |
+ shift = shift - 32; |
+ mov(dst_high, zero_reg); |
+ srl(dst_low, src_high, shift); |
+ } |
+ } |
+} |
+ |
+void MacroAssembler::SarPair(Register dst_low, Register dst_high, |
+ Register src_low, Register src_high, |
+ Register shift) { |
+ Label less_than_32; |
+ Label zero_shift; |
+ Label word_shift; |
+ Label done; |
+ Register kScratchReg = s3; |
+ Register kScratchReg2 = s4; |
+ And(shift, shift, 0x3F); |
+ li(kScratchReg, 0x20); |
+ Branch(&less_than_32, lt, shift, Operand(kScratchReg)); |
+ |
+ Branch(&word_shift, eq, shift, Operand(kScratchReg)); |
+ |
+ // Shift more than 32 |
+ li(kScratchReg2, 0x1F); |
+ Subu(kScratchReg, shift, kScratchReg); |
+ srav(dst_high, src_high, kScratchReg2); |
+ srav(dst_low, src_high, kScratchReg); |
+ Branch(&done); |
+ // Word shift |
+ bind(&word_shift); |
+ li(kScratchReg2, 0x1F); |
+ srav(dst_high, src_high, kScratchReg2); |
+ mov(dst_low, src_high); |
+ Branch(&done); |
+ |
+ bind(&less_than_32); |
+ // Check if zero shift |
+ Branch(&zero_shift, eq, shift, Operand(zero_reg)); |
+ |
+ // Shift less than 32 |
+ Subu(kScratchReg, kScratchReg, shift); |
+ srav(dst_high, src_high, shift); |
+ srlv(dst_low, src_low, shift); |
+ sllv(kScratchReg, src_high, kScratchReg); |
+ Or(dst_low, dst_low, kScratchReg); |
+ Branch(&done); |
+ // Zero shift |
+ bind(&zero_shift); |
+ mov(dst_low, src_low); |
+ mov(dst_high, src_high); |
+ bind(&done); |
+} |
+ |
+void MacroAssembler::SarPair(Register dst_low, Register dst_high, |
+ Register src_low, Register src_high, |
+ uint32_t shift) { |
+ Register kScratchReg = s3; |
+ shift = shift & 0x3F; |
+ if (shift < 32) { |
+ if (shift == 0) { |
+ mov(dst_low, src_low); |
+ mov(dst_high, src_high); |
+ } else { |
+ sra(dst_high, src_high, shift); |
+ srl(dst_low, src_low, shift); |
+ shift = 32 - shift; |
+ sll(kScratchReg, src_high, shift); |
+ Or(dst_low, dst_low, kScratchReg); |
+ } |
+ } else { |
+ if (shift == 32) { |
+ sra(dst_high, src_high, 31); |
+ mov(dst_low, src_high); |
+ } else { |
+ shift = shift - 32; |
+ sra(dst_high, src_high, 31); |
+ sra(dst_low, src_high, shift); |
+ } |
+ } |
+} |
void MacroAssembler::Ext(Register rt, |
Register rs, |