X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/4e4e5a6f2694187498445a6ac6f1634ce8141119..4be4e30906bcb8ee30b4d189205cb70bad6707ce:/assembler/MacroAssemblerMIPS.h diff --git a/assembler/MacroAssemblerMIPS.h b/assembler/MacroAssemblerMIPS.h index 9853c34..298a25c 100644 --- a/assembler/MacroAssemblerMIPS.h +++ b/assembler/MacroAssemblerMIPS.h @@ -36,12 +36,18 @@ namespace JSC { class MacroAssemblerMIPS : public AbstractMacroAssembler { public: + typedef MIPSRegisters::FPRegisterID FPRegisterID; MacroAssemblerMIPS() : m_fixedWidth(false) { } + static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value) + { + return value >= -2147483647 - 1 && value <= 2147483647; + } + static const Scale ScalePtr = TimesFour; // For storing immediate number @@ -56,7 +62,9 @@ public: // FP temp register static const FPRegisterID fpTempRegister = MIPSRegisters::f16; - enum Condition { + static const int MaximumCompactPtrAlignedAddressOffset = 0x7FFFFFFF; + + enum RelationalCondition { Equal, NotEqual, Above, @@ -66,9 +74,13 @@ public: GreaterThan, GreaterThanOrEqual, LessThan, - LessThanOrEqual, + LessThanOrEqual + }; + + enum ResultCondition { Overflow, Signed, + PositiveOrZero, Zero, NonZero }; @@ -94,7 +106,7 @@ public: // Integer arithmetic operations: // // Operations are typically two operand - operation(source, srcDst) - // For many operations the source may be an Imm32, the srcDst operand + // For many operations the source may be an TrustedImm32, the srcDst operand // may often be a memory location (explictly described using an Address // object). @@ -103,14 +115,19 @@ public: m_assembler.addu(dest, dest, src); } - void add32(Imm32 imm, RegisterID dest) + void add32(RegisterID op1, RegisterID op2, RegisterID dest) + { + m_assembler.addu(dest, op1, op2); + } + + void add32(TrustedImm32 imm, RegisterID dest) { add32(imm, dest, dest); } - void add32(Imm32 imm, RegisterID src, RegisterID dest) + void add32(TrustedImm32 imm, RegisterID src, RegisterID dest) { - if (!imm.m_isPointer && imm.m_value >= -32768 && imm.m_value <= 32767 + if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth) { /* addiu dest, src, imm @@ -126,7 +143,12 @@ public: } } - void add32(Imm32 imm, Address address) + void add32(RegisterID src, TrustedImm32 imm, RegisterID dest) + { + add32(imm, src, dest); + } + + void add32(TrustedImm32 imm, Address address) { if (address.offset >= -32768 && address.offset <= 32767 && !m_fixedWidth) { @@ -137,15 +159,12 @@ public: sw dataTemp, offset(base) */ m_assembler.lw(dataTempRegister, address.base, address.offset); - if (!imm.m_isPointer - && imm.m_value >= -32768 && imm.m_value <= 32767 + if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth) - m_assembler.addiu(dataTempRegister, dataTempRegister, - imm.m_value); + m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value); else { move(imm, immTempRegister); - m_assembler.addu(dataTempRegister, dataTempRegister, - immTempRegister); + m_assembler.addu(dataTempRegister, dataTempRegister, immTempRegister); } m_assembler.sw(dataTempRegister, address.base, address.offset); } else { @@ -162,12 +181,10 @@ public: m_assembler.lw(dataTempRegister, addrTempRegister, address.offset); if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth) - m_assembler.addiu(dataTempRegister, dataTempRegister, - imm.m_value); + m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value); else { move(imm, immTempRegister); - m_assembler.addu(dataTempRegister, dataTempRegister, - immTempRegister); + m_assembler.addu(dataTempRegister, dataTempRegister, immTempRegister); } m_assembler.sw(dataTempRegister, addrTempRegister, address.offset); } @@ -179,6 +196,12 @@ public: add32(dataTempRegister, dest); } + void add32(AbsoluteAddress src, RegisterID dest) + { + load32(src.m_ptr, dataTempRegister); + add32(dataTempRegister, dest); + } + void add32(RegisterID src, Address dest) { if (dest.offset >= -32768 && dest.offset <= 32767 && !m_fixedWidth) { @@ -206,38 +229,66 @@ public: } } - void add32(Imm32 imm, AbsoluteAddress address) + void add32(TrustedImm32 imm, AbsoluteAddress address) { /* li addrTemp, address li immTemp, imm - lw dataTemp, 0(addrTemp) - addu dataTemp, dataTemp, immTemp + lw cmpTemp, 0(addrTemp) + addu dataTemp, cmpTemp, immTemp sw dataTemp, 0(addrTemp) */ - move(ImmPtr(address.m_ptr), addrTempRegister); - m_assembler.lw(dataTempRegister, addrTempRegister, 0); - if (!imm.m_isPointer && imm.m_value >= -32768 && imm.m_value <= 32767 - && !m_fixedWidth) - m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value); + move(TrustedImmPtr(address.m_ptr), addrTempRegister); + m_assembler.lw(cmpTempRegister, addrTempRegister, 0); + if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth) + m_assembler.addiu(dataTempRegister, cmpTempRegister, imm.m_value); else { move(imm, immTempRegister); - m_assembler.addu(dataTempRegister, dataTempRegister, immTempRegister); + m_assembler.addu(dataTempRegister, cmpTempRegister, immTempRegister); } m_assembler.sw(dataTempRegister, addrTempRegister, 0); } + void add64(TrustedImm32 imm, AbsoluteAddress address) + { + /* + add32(imm, address) + sltu immTemp, dataTemp, cmpTemp # set carry-in bit + lw dataTemp, 4(addrTemp) + addiu dataTemp, imm.m_value >> 31 ? -1 : 0 + addu dataTemp, dataTemp, immTemp + sw dataTemp, 4(addrTemp) + */ + add32(imm, address); + m_assembler.sltu(immTempRegister, dataTempRegister, cmpTempRegister); + m_assembler.lw(dataTempRegister, addrTempRegister, 4); + if (imm.m_value >> 31) + m_assembler.addiu(dataTempRegister, dataTempRegister, -1); + m_assembler.addu(dataTempRegister, dataTempRegister, immTempRegister); + m_assembler.sw(dataTempRegister, addrTempRegister, 4); + } + + void and32(Address src, RegisterID dest) + { + load32(src, dataTempRegister); + and32(dataTempRegister, dest); + } + void and32(RegisterID src, RegisterID dest) { m_assembler.andInsn(dest, dest, src); } - void and32(Imm32 imm, RegisterID dest) + void and32(RegisterID op1, RegisterID op2, RegisterID dest) { - if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) + m_assembler.andInsn(dest, op1, op2); + } + + void and32(TrustedImm32 imm, RegisterID dest) + { + if (!imm.m_value && !m_fixedWidth) move(MIPSRegisters::zero, dest); - else if (!imm.m_isPointer && imm.m_value > 0 && imm.m_value < 65535 - && !m_fixedWidth) + else if (imm.m_value > 0 && imm.m_value < 65535 && !m_fixedWidth) m_assembler.andi(dest, dest, imm.m_value); else { /* @@ -249,9 +300,16 @@ public: } } - void lshift32(Imm32 imm, RegisterID dest) + void and32(TrustedImm32 imm, RegisterID src, RegisterID dest) { - m_assembler.sll(dest, dest, imm.m_value); + if (!imm.m_value && !m_fixedWidth) + move(MIPSRegisters::zero, dest); + else if (imm.m_value > 0 && imm.m_value < 65535 && !m_fixedWidth) + m_assembler.andi(dest, src, imm.m_value); + else { + move(imm, immTempRegister); + m_assembler.andInsn(dest, src, immTempRegister); + } } void lshift32(RegisterID shiftAmount, RegisterID dest) @@ -259,16 +317,38 @@ public: m_assembler.sllv(dest, dest, shiftAmount); } + void lshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest) + { + m_assembler.sllv(dest, src, shiftAmount); + } + + void lshift32(TrustedImm32 imm, RegisterID dest) + { + move(imm, immTempRegister); + m_assembler.sllv(dest, dest, immTempRegister); + } + + void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) + { + move(imm, immTempRegister); + m_assembler.sllv(dest, src, immTempRegister); + } + void mul32(RegisterID src, RegisterID dest) { m_assembler.mul(dest, dest, src); } - void mul32(Imm32 imm, RegisterID src, RegisterID dest) + void mul32(RegisterID op1, RegisterID op2, RegisterID dest) + { + m_assembler.mul(dest, op1, op2); + } + + void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest) { - if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) + if (!imm.m_value && !m_fixedWidth) move(MIPSRegisters::zero, dest); - else if (!imm.m_isPointer && imm.m_value == 1 && !m_fixedWidth) + else if (imm.m_value == 1 && !m_fixedWidth) move(src, dest); else { /* @@ -280,9 +360,9 @@ public: } } - void not32(RegisterID srcDest) + void neg32(RegisterID srcDest) { - m_assembler.nor(srcDest, srcDest, MIPSRegisters::zero); + m_assembler.subu(srcDest, MIPSRegisters::zero, srcDest); } void or32(RegisterID src, RegisterID dest) @@ -290,12 +370,17 @@ public: m_assembler.orInsn(dest, dest, src); } - void or32(Imm32 imm, RegisterID dest) + void or32(RegisterID op1, RegisterID op2, RegisterID dest) + { + m_assembler.orInsn(dest, op1, op2); + } + + void or32(TrustedImm32 imm, RegisterID dest) { - if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) + if (!imm.m_value && !m_fixedWidth) return; - if (!imm.m_isPointer && imm.m_value > 0 && imm.m_value < 65535 + if (imm.m_value > 0 && imm.m_value < 65535 && !m_fixedWidth) { m_assembler.ori(dest, dest, imm.m_value); return; @@ -309,24 +394,84 @@ public: m_assembler.orInsn(dest, dest, dataTempRegister); } + void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) + { + if (!imm.m_value && !m_fixedWidth) + return; + + if (imm.m_value > 0 && imm.m_value < 65535 && !m_fixedWidth) { + m_assembler.ori(dest, src, imm.m_value); + return; + } + + /* + li dataTemp, imm + or dest, src, dataTemp + */ + move(imm, dataTempRegister); + m_assembler.orInsn(dest, src, dataTempRegister); + } + + void or32(RegisterID src, AbsoluteAddress dest) + { + load32(dest.m_ptr, dataTempRegister); + m_assembler.orInsn(dataTempRegister, dataTempRegister, src); + store32(dataTempRegister, dest.m_ptr); + } + void rshift32(RegisterID shiftAmount, RegisterID dest) { m_assembler.srav(dest, dest, shiftAmount); } - void rshift32(Imm32 imm, RegisterID dest) + void rshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest) + { + m_assembler.srav(dest, src, shiftAmount); + } + + void rshift32(TrustedImm32 imm, RegisterID dest) { m_assembler.sra(dest, dest, imm.m_value); } + void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) + { + m_assembler.sra(dest, src, imm.m_value); + } + + void urshift32(RegisterID shiftAmount, RegisterID dest) + { + m_assembler.srlv(dest, dest, shiftAmount); + } + + void urshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest) + { + m_assembler.srlv(dest, src, shiftAmount); + } + + void urshift32(TrustedImm32 imm, RegisterID dest) + { + m_assembler.srl(dest, dest, imm.m_value); + } + + void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) + { + m_assembler.srl(dest, src, imm.m_value); + } + void sub32(RegisterID src, RegisterID dest) { m_assembler.subu(dest, dest, src); } - void sub32(Imm32 imm, RegisterID dest) + void sub32(RegisterID op1, RegisterID op2, RegisterID dest) + { + m_assembler.subu(dest, op1, op2); + } + + void sub32(TrustedImm32 imm, RegisterID dest) { - if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768 + if (imm.m_value >= -32767 && imm.m_value <= 32768 && !m_fixedWidth) { /* addiu dest, src, imm @@ -342,7 +487,25 @@ public: } } - void sub32(Imm32 imm, Address address) + void sub32(RegisterID src, TrustedImm32 imm, RegisterID dest) + { + if (imm.m_value >= -32767 && imm.m_value <= 32768 + && !m_fixedWidth) { + /* + addiu dest, src, imm + */ + m_assembler.addiu(dest, src, -imm.m_value); + } else { + /* + li immTemp, imm + subu dest, src, immTemp + */ + move(imm, immTempRegister); + m_assembler.subu(dest, src, immTempRegister); + } + } + + void sub32(TrustedImm32 imm, Address address) { if (address.offset >= -32768 && address.offset <= 32767 && !m_fixedWidth) { @@ -353,15 +516,11 @@ public: sw dataTemp, offset(base) */ m_assembler.lw(dataTempRegister, address.base, address.offset); - if (!imm.m_isPointer - && imm.m_value >= -32767 && imm.m_value <= 32768 - && !m_fixedWidth) - m_assembler.addiu(dataTempRegister, dataTempRegister, - -imm.m_value); + if (imm.m_value >= -32767 && imm.m_value <= 32768 && !m_fixedWidth) + m_assembler.addiu(dataTempRegister, dataTempRegister, -imm.m_value); else { move(imm, immTempRegister); - m_assembler.subu(dataTempRegister, dataTempRegister, - immTempRegister); + m_assembler.subu(dataTempRegister, dataTempRegister, immTempRegister); } m_assembler.sw(dataTempRegister, address.base, address.offset); } else { @@ -377,15 +536,12 @@ public: m_assembler.addu(addrTempRegister, addrTempRegister, address.base); m_assembler.lw(dataTempRegister, addrTempRegister, address.offset); - if (!imm.m_isPointer - && imm.m_value >= -32767 && imm.m_value <= 32768 + if (imm.m_value >= -32767 && imm.m_value <= 32768 && !m_fixedWidth) - m_assembler.addiu(dataTempRegister, dataTempRegister, - -imm.m_value); + m_assembler.addiu(dataTempRegister, dataTempRegister, -imm.m_value); else { move(imm, immTempRegister); - m_assembler.subu(dataTempRegister, dataTempRegister, - immTempRegister); + m_assembler.subu(dataTempRegister, dataTempRegister, immTempRegister); } m_assembler.sw(dataTempRegister, addrTempRegister, address.offset); } @@ -397,7 +553,7 @@ public: sub32(dataTempRegister, dest); } - void sub32(Imm32 imm, AbsoluteAddress address) + void sub32(TrustedImm32 imm, AbsoluteAddress address) { /* li addrTemp, address @@ -406,14 +562,12 @@ public: subu dataTemp, dataTemp, immTemp sw dataTemp, 0(addrTemp) */ - move(ImmPtr(address.m_ptr), addrTempRegister); + move(TrustedImmPtr(address.m_ptr), addrTempRegister); m_assembler.lw(dataTempRegister, addrTempRegister, 0); - if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768 - && !m_fixedWidth) { - m_assembler.addiu(dataTempRegister, dataTempRegister, - -imm.m_value); - } else { + if (imm.m_value >= -32767 && imm.m_value <= 32768 && !m_fixedWidth) + m_assembler.addiu(dataTempRegister, dataTempRegister, -imm.m_value); + else { move(imm, immTempRegister); m_assembler.subu(dataTempRegister, dataTempRegister, immTempRegister); } @@ -425,8 +579,18 @@ public: m_assembler.xorInsn(dest, dest, src); } - void xor32(Imm32 imm, RegisterID dest) + void xor32(RegisterID op1, RegisterID op2, RegisterID dest) + { + m_assembler.xorInsn(dest, op1, op2); + } + + void xor32(TrustedImm32 imm, RegisterID dest) { + if (imm.m_value == -1) { + m_assembler.nor(dest, dest, MIPSRegisters::zero); + return; + } + /* li immTemp, imm xor dest, dest, immTemp @@ -435,10 +599,49 @@ public: m_assembler.xorInsn(dest, dest, immTempRegister); } + void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest) + { + if (imm.m_value == -1) { + m_assembler.nor(dest, src, MIPSRegisters::zero); + return; + } + + /* + li immTemp, imm + xor dest, dest, immTemp + */ + move(imm, immTempRegister); + m_assembler.xorInsn(dest, src, immTempRegister); + } + + void sqrtDouble(FPRegisterID src, FPRegisterID dst) + { + m_assembler.sqrtd(dst, src); + } + + void absDouble(FPRegisterID, FPRegisterID) + { + RELEASE_ASSERT_NOT_REACHED(); + } + + ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest) + { + ConvertibleLoadLabel result(this); + /* + lui addrTemp, (offset + 0x8000) >> 16 + addu addrTemp, addrTemp, base + lw dest, (offset & 0xffff)(addrTemp) + */ + m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lw(dest, addrTempRegister, address.offset); + return result; + } + // Memory access operations: // // Loads are of the form load(address, destination) and stores of the form - // store(source, address). The source for a store may be an Imm32. Address + // store(source, address). The source for a store may be an TrustedImm32. Address // operand objects to loads and store will be implicitly constructed if a // register is passed. @@ -460,6 +663,62 @@ public: } } + void load8(BaseIndex address, RegisterID dest) + { + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lbu dest, address.offset(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lbu(dest, addrTempRegister, address.offset); + } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lui immTemp, (address.offset + 0x8000) >> 16 + addu addrTemp, addrTemp, immTemp + lbu dest, (address.offset & 0xffff)(at) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); + m_assembler.lbu(dest, addrTempRegister, address.offset); + } + } + + void load8Signed(BaseIndex address, RegisterID dest) + { + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lb dest, address.offset(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lb(dest, addrTempRegister, address.offset); + } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lui immTemp, (address.offset + 0x8000) >> 16 + addu addrTemp, addrTemp, immTemp + lb dest, (address.offset & 0xffff)(at) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); + m_assembler.lb(dest, addrTempRegister, address.offset); + } + } + void load32(ImplicitAddress address, RegisterID dest) { if (address.offset >= -32768 && address.offset <= 32767 @@ -500,12 +759,16 @@ public: m_assembler.sll(addrTempRegister, address.index, address.scale); m_assembler.addu(addrTempRegister, addrTempRegister, address.base); m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); - m_assembler.addu(addrTempRegister, addrTempRegister, - immTempRegister); + m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); m_assembler.lw(dest, addrTempRegister, address.offset); } } + void load16Unaligned(BaseIndex address, RegisterID dest) + { + load16(address, dest); + } + void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest) { if (address.offset >= -32768 && address.offset <= 32764 @@ -548,8 +811,7 @@ public: m_assembler.addu(addrTempRegister, addrTempRegister, address.base); m_assembler.lui(immTempRegister, address.offset >> 16); m_assembler.ori(immTempRegister, immTempRegister, address.offset); - m_assembler.addu(addrTempRegister, addrTempRegister, - immTempRegister); + m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); #if CPU(BIG_ENDIAN) m_assembler.lwl(dest, addrTempRegister, 0); m_assembler.lwr(dest, addrTempRegister, 3); @@ -560,13 +822,13 @@ public: } } - void load32(void* address, RegisterID dest) + void load32(const void* address, RegisterID dest) { /* li addrTemp, address lw dest, 0(addrTemp) */ - move(ImmPtr(address), addrTempRegister); + move(TrustedImmPtr(address), addrTempRegister); m_assembler.lw(dest, addrTempRegister, 0); } @@ -580,33 +842,36 @@ public: lw dest, 0(addrTemp) */ DataLabel32 dataLabel(this); - move(Imm32(address.offset), addrTempRegister); + move(TrustedImm32(address.offset), addrTempRegister); m_assembler.addu(addrTempRegister, addrTempRegister, address.base); m_assembler.lw(dest, addrTempRegister, 0); m_fixedWidth = false; return dataLabel; } - - Label loadPtrWithPatchToLEA(Address address, RegisterID dest) + + DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest) { - m_fixedWidth = true; - /* - lui addrTemp, address.offset >> 16 - ori addrTemp, addrTemp, address.offset & 0xffff - addu addrTemp, addrTemp, address.base - lw dest, 0(addrTemp) - */ - Label label(this); - move(Imm32(address.offset), addrTempRegister); - m_assembler.addu(addrTempRegister, addrTempRegister, address.base); - m_assembler.lw(dest, addrTempRegister, 0); - m_fixedWidth = false; - return label; + DataLabelCompact dataLabel(this); + load32WithAddressOffsetPatch(address, dest); + return dataLabel; } - Label loadPtrWithAddressOffsetPatch(Address address, RegisterID dest) + /* Need to use zero-extened load half-word for load16. */ + void load16(ImplicitAddress address, RegisterID dest) { - return loadPtrWithPatchToLEA(address, dest); + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) + m_assembler.lhu(dest, address.base, address.offset); + else { + /* + lui addrTemp, (offset + 0x8000) >> 16 + addu addrTemp, addrTemp, base + lhu dest, (offset & 0xffff)(addrTemp) + */ + m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lhu(dest, addrTempRegister, address.offset); + } } /* Need to use zero-extened load half-word for load16. */ @@ -633,12 +898,39 @@ public: m_assembler.sll(addrTempRegister, address.index, address.scale); m_assembler.addu(addrTempRegister, addrTempRegister, address.base); m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); - m_assembler.addu(addrTempRegister, addrTempRegister, - immTempRegister); + m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); m_assembler.lhu(dest, addrTempRegister, address.offset); } } + void load16Signed(BaseIndex address, RegisterID dest) + { + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lh dest, address.offset(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lh(dest, addrTempRegister, address.offset); + } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lui immTemp, (address.offset + 0x8000) >> 16 + addu addrTemp, addrTemp, immTemp + lh dest, (address.offset & 0xffff)(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); + m_assembler.lh(dest, addrTempRegister, address.offset); + } + } + DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address) { m_fixedWidth = true; @@ -649,71 +941,142 @@ public: sw src, 0(addrTemp) */ DataLabel32 dataLabel(this); - move(Imm32(address.offset), addrTempRegister); + move(TrustedImm32(address.offset), addrTempRegister); m_assembler.addu(addrTempRegister, addrTempRegister, address.base); m_assembler.sw(src, addrTempRegister, 0); m_fixedWidth = false; return dataLabel; } - void store32(RegisterID src, ImplicitAddress address) - { - if (address.offset >= -32768 && address.offset <= 32767 - && !m_fixedWidth) - m_assembler.sw(src, address.base, address.offset); - else { - /* - lui addrTemp, (offset + 0x8000) >> 16 - addu addrTemp, addrTemp, base - sw src, (offset & 0xffff)(addrTemp) - */ - m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); - m_assembler.addu(addrTempRegister, addrTempRegister, address.base); - m_assembler.sw(src, addrTempRegister, address.offset); - } - } - - void store32(RegisterID src, BaseIndex address) + void store8(RegisterID src, BaseIndex address) { if (address.offset >= -32768 && address.offset <= 32767 && !m_fixedWidth) { /* sll addrTemp, address.index, address.scale addu addrTemp, addrTemp, address.base - sw src, address.offset(addrTemp) + sb src, address.offset(addrTemp) */ m_assembler.sll(addrTempRegister, address.index, address.scale); m_assembler.addu(addrTempRegister, addrTempRegister, address.base); - m_assembler.sw(src, addrTempRegister, address.offset); + m_assembler.sb(src, addrTempRegister, address.offset); } else { /* sll addrTemp, address.index, address.scale addu addrTemp, addrTemp, address.base lui immTemp, (address.offset + 0x8000) >> 16 addu addrTemp, addrTemp, immTemp - sw src, (address.offset & 0xffff)(at) + sb src, (address.offset & 0xffff)(at) */ m_assembler.sll(addrTempRegister, address.index, address.scale); m_assembler.addu(addrTempRegister, addrTempRegister, address.base); m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); - m_assembler.addu(addrTempRegister, addrTempRegister, - immTempRegister); - m_assembler.sw(src, addrTempRegister, address.offset); + m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); + m_assembler.sb(src, addrTempRegister, address.offset); + } + } + + void store8(TrustedImm32 imm, void* address) + { + /* + li immTemp, imm + li addrTemp, address + sb src, 0(addrTemp) + */ + if (!imm.m_value && !m_fixedWidth) { + move(TrustedImmPtr(address), addrTempRegister); + m_assembler.sb(MIPSRegisters::zero, addrTempRegister, 0); + } else { + move(imm, immTempRegister); + move(TrustedImmPtr(address), addrTempRegister); + m_assembler.sb(immTempRegister, addrTempRegister, 0); } } - void store32(Imm32 imm, ImplicitAddress address) + void store16(RegisterID src, BaseIndex address) { if (address.offset >= -32768 && address.offset <= 32767 && !m_fixedWidth) { - if (!imm.m_isPointer && !imm.m_value) - m_assembler.sw(MIPSRegisters::zero, address.base, - address.offset); - else { - move(imm, immTempRegister); - m_assembler.sw(immTempRegister, address.base, address.offset); - } - } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + sh src, address.offset(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.sh(src, addrTempRegister, address.offset); + } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lui immTemp, (address.offset + 0x8000) >> 16 + addu addrTemp, addrTemp, immTemp + sh src, (address.offset & 0xffff)(at) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); + m_assembler.sh(src, addrTempRegister, address.offset); + } + } + + void store32(RegisterID src, ImplicitAddress address) + { + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) + m_assembler.sw(src, address.base, address.offset); + else { + /* + lui addrTemp, (offset + 0x8000) >> 16 + addu addrTemp, addrTemp, base + sw src, (offset & 0xffff)(addrTemp) + */ + m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.sw(src, addrTempRegister, address.offset); + } + } + + void store32(RegisterID src, BaseIndex address) + { + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + sw src, address.offset(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.sw(src, addrTempRegister, address.offset); + } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lui immTemp, (address.offset + 0x8000) >> 16 + addu addrTemp, addrTemp, immTemp + sw src, (address.offset & 0xffff)(at) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); + m_assembler.sw(src, addrTempRegister, address.offset); + } + } + + void store32(TrustedImm32 imm, ImplicitAddress address) + { + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + if (!imm.m_value) + m_assembler.sw(MIPSRegisters::zero, address.base, address.offset); + else { + move(imm, immTempRegister); + m_assembler.sw(immTempRegister, address.base, address.offset); + } + } else { /* lui addrTemp, (offset + 0x8000) >> 16 addu addrTemp, addrTemp, base @@ -721,47 +1084,83 @@ public: */ m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); m_assembler.addu(addrTempRegister, addrTempRegister, address.base); - if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) - m_assembler.sw(MIPSRegisters::zero, addrTempRegister, - address.offset); + if (!imm.m_value && !m_fixedWidth) + m_assembler.sw(MIPSRegisters::zero, addrTempRegister, address.offset); + else { + move(imm, immTempRegister); + m_assembler.sw(immTempRegister, addrTempRegister, address.offset); + } + } + } + + void store32(TrustedImm32 imm, BaseIndex address) + { + if (address.offset >= -32768 && address.offset <= 32767 && !m_fixedWidth) { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + sw src, address.offset(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + if (!imm.m_value) + m_assembler.sw(MIPSRegisters::zero, addrTempRegister, address.offset); + else { + move(imm, immTempRegister); + m_assembler.sw(immTempRegister, addrTempRegister, address.offset); + } + } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lui immTemp, (address.offset + 0x8000) >> 16 + addu addrTemp, addrTemp, immTemp + sw src, (address.offset & 0xffff)(at) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); + if (!imm.m_value && !m_fixedWidth) + m_assembler.sw(MIPSRegisters::zero, addrTempRegister, address.offset); else { move(imm, immTempRegister); - m_assembler.sw(immTempRegister, addrTempRegister, - address.offset); + m_assembler.sw(immTempRegister, addrTempRegister, address.offset); } } } - void store32(RegisterID src, void* address) + + void store32(RegisterID src, const void* address) { /* li addrTemp, address sw src, 0(addrTemp) */ - move(ImmPtr(address), addrTempRegister); + move(TrustedImmPtr(address), addrTempRegister); m_assembler.sw(src, addrTempRegister, 0); } - void store32(Imm32 imm, void* address) + void store32(TrustedImm32 imm, const void* address) { /* li immTemp, imm li addrTemp, address sw src, 0(addrTemp) */ - if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) { - move(ImmPtr(address), addrTempRegister); + if (!imm.m_value && !m_fixedWidth) { + move(TrustedImmPtr(address), addrTempRegister); m_assembler.sw(MIPSRegisters::zero, addrTempRegister, 0); } else { move(imm, immTempRegister); - move(ImmPtr(address), addrTempRegister); + move(TrustedImmPtr(address), addrTempRegister); m_assembler.sw(immTempRegister, addrTempRegister, 0); } } // Floating-point operations: - bool supportsFloatingPoint() const + static bool supportsFloatingPoint() { #if WTF_MIPS_DOUBLE_FLOAT return true; @@ -770,7 +1169,16 @@ public: #endif } - bool supportsFloatingPointTruncate() const + static bool supportsFloatingPointTruncate() + { +#if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2) + return true; +#else + return false; +#endif + } + + static bool supportsFloatingPointSqrt() { #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2) return true; @@ -778,13 +1186,14 @@ public: return false; #endif } + static bool supportsFloatingPointAbs() { return false; } // Stack manipulation operations: // // The ABI is assumed to provide a stack abstraction to memory, - // containing machine word sized units of data. Push and pop + // containing machine word sized units of data. Push and pop // operations add and remove a single register sized unit of data - // to or from the stack. Peek and poke operations read or write + // to or from the stack. Peek and poke operations read or write // values on the stack, without moving the current stack position. void pop(RegisterID dest) @@ -805,7 +1214,7 @@ public: push(dataTempRegister); } - void push(Imm32 imm) + void push(TrustedImm32 imm) { move(imm, immTempRegister); push(immTempRegister); @@ -815,11 +1224,11 @@ public: // // Move values in registers. - void move(Imm32 imm, RegisterID dest) + void move(TrustedImm32 imm, RegisterID dest) { - if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) + if (!imm.m_value && !m_fixedWidth) move(MIPSRegisters::zero, dest); - else if (imm.m_isPointer || m_fixedWidth) { + else if (m_fixedWidth) { m_assembler.lui(dest, imm.m_value >> 16); m_assembler.ori(dest, dest, imm.m_value); } else @@ -832,9 +1241,9 @@ public: m_assembler.move(dest, src); } - void move(ImmPtr imm, RegisterID dest) + void move(TrustedImmPtr imm, RegisterID dest) { - move(Imm32(imm), dest); + move(TrustedImm32(imm), dest); } void swap(RegisterID reg1, RegisterID reg2) @@ -868,26 +1277,45 @@ public: // used (representing the names 'below' and 'above'). // // Operands to the comparision are provided in the expected order, e.g. - // jle32(reg1, Imm32(5)) will branch if the value held in reg1, when + // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when // treated as a signed 32bit value, is less than or equal to 5. // // jz and jnz test whether the first operand is equal to zero, and take // an optional second operand of a mask under which to perform the test. - Jump branch8(Condition cond, Address left, Imm32 right) + Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right) + { + // Make sure the immediate value is unsigned 8 bits. + ASSERT(!(right.m_value & 0xFFFFFF00)); + load8(left, dataTempRegister); + move(right, immTempRegister); + return branch32(cond, dataTempRegister, immTempRegister); + } + + void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest) { // Make sure the immediate value is unsigned 8 bits. ASSERT(!(right.m_value & 0xFFFFFF00)); load8(left, dataTempRegister); move(right, immTempRegister); + compare32(cond, dataTempRegister, immTempRegister, dest); + } + + Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right) + { + ASSERT(!(right.m_value & 0xFFFFFF00)); + load8(left, dataTempRegister); + // Be careful that the previous load8() uses immTempRegister. + // So, we need to put move() after load8(). + move(right, immTempRegister); return branch32(cond, dataTempRegister, immTempRegister); } - Jump branch32(Condition cond, RegisterID left, RegisterID right) + Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right) { - if (cond == Equal || cond == Zero) + if (cond == Equal) return branchEqual(left, right); - if (cond == NotEqual || cond == NonZero) + if (cond == NotEqual) return branchNotEqual(left, right); if (cond == Above) { m_assembler.sltu(cmpTempRegister, right, left); @@ -921,70 +1349,37 @@ public: m_assembler.slt(cmpTempRegister, right, left); return branchEqual(cmpTempRegister, MIPSRegisters::zero); } - if (cond == Overflow) { - /* - xor cmpTemp, left, right - bgez No_overflow, cmpTemp # same sign bit -> no overflow - nop - subu cmpTemp, left, right - xor cmpTemp, cmpTemp, left - bgez No_overflow, cmpTemp # same sign bit -> no overflow - nop - b Overflow - nop - nop - nop - nop - nop - No_overflow: - */ - m_assembler.xorInsn(cmpTempRegister, left, right); - m_assembler.bgez(cmpTempRegister, 11); - m_assembler.nop(); - m_assembler.subu(cmpTempRegister, left, right); - m_assembler.xorInsn(cmpTempRegister, cmpTempRegister, left); - m_assembler.bgez(cmpTempRegister, 7); - m_assembler.nop(); - return jump(); - } - if (cond == Signed) { - m_assembler.subu(cmpTempRegister, left, right); - // Check if the result is negative. - m_assembler.slt(cmpTempRegister, cmpTempRegister, - MIPSRegisters::zero); - return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); - } ASSERT(0); return Jump(); } - Jump branch32(Condition cond, RegisterID left, Imm32 right) + Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right) { move(right, immTempRegister); return branch32(cond, left, immTempRegister); } - Jump branch32(Condition cond, RegisterID left, Address right) + Jump branch32(RelationalCondition cond, RegisterID left, Address right) { load32(right, dataTempRegister); return branch32(cond, left, dataTempRegister); } - Jump branch32(Condition cond, Address left, RegisterID right) + Jump branch32(RelationalCondition cond, Address left, RegisterID right) { load32(left, dataTempRegister); return branch32(cond, dataTempRegister, right); } - Jump branch32(Condition cond, Address left, Imm32 right) + Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right) { load32(left, dataTempRegister); move(right, immTempRegister); return branch32(cond, dataTempRegister, immTempRegister); } - Jump branch32(Condition cond, BaseIndex left, Imm32 right) + Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right) { load32(left, dataTempRegister); // Be careful that the previous load32() uses immTempRegister. @@ -993,7 +1388,7 @@ public: return branch32(cond, dataTempRegister, immTempRegister); } - Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right) + Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right) { load32WithUnalignedHalfWords(left, dataTempRegister); // Be careful that the previous load32WithUnalignedHalfWords() @@ -1003,36 +1398,20 @@ public: return branch32(cond, dataTempRegister, immTempRegister); } - Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right) + Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right) { load32(left.m_ptr, dataTempRegister); return branch32(cond, dataTempRegister, right); } - Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right) + Jump branch32(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right) { load32(left.m_ptr, dataTempRegister); move(right, immTempRegister); return branch32(cond, dataTempRegister, immTempRegister); } - Jump branch16(Condition cond, BaseIndex left, RegisterID right) - { - load16(left, dataTempRegister); - return branch32(cond, dataTempRegister, right); - } - - Jump branch16(Condition cond, BaseIndex left, Imm32 right) - { - ASSERT(!(right.m_value & 0xFFFF0000)); - load16(left, dataTempRegister); - // Be careful that the previous load16() uses immTempRegister. - // So, we need to put move() after load16(). - move(right, immTempRegister); - return branch32(cond, dataTempRegister, immTempRegister); - } - - Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask) + Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask) { ASSERT((cond == Zero) || (cond == NonZero)); m_assembler.andInsn(cmpTempRegister, reg, mask); @@ -1041,7 +1420,7 @@ public: return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); } - Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1)) + Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1)) { ASSERT((cond == Zero) || (cond == NonZero)); if (mask.m_value == -1 && !m_fixedWidth) { @@ -1053,24 +1432,31 @@ public: return branchTest32(cond, reg, immTempRegister); } - Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1)) + Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) { load32(address, dataTempRegister); return branchTest32(cond, dataTempRegister, mask); } - Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1)) + Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) { load32(address, dataTempRegister); return branchTest32(cond, dataTempRegister, mask); } - Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1)) + Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) { load8(address, dataTempRegister); return branchTest32(cond, dataTempRegister, mask); } + Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1)) + { + move(TrustedImmPtr(address.m_ptr), dataTempRegister); + load8(Address(dataTempRegister), dataTempRegister); + return branchTest32(cond, dataTempRegister, mask); + } + Jump jump() { return branchEqual(MIPSRegisters::zero, MIPSRegisters::zero); @@ -1078,7 +1464,8 @@ public: void jump(RegisterID target) { - m_assembler.jr(target); + move(target, MIPSRegisters::t9); + m_assembler.jr(MIPSRegisters::t9); m_assembler.nop(); } @@ -1091,19 +1478,39 @@ public: m_fixedWidth = false; } + void jump(AbsoluteAddress address) + { + m_fixedWidth = true; + load32(address.m_ptr, MIPSRegisters::t9); + m_assembler.jr(MIPSRegisters::t9); + m_assembler.nop(); + m_fixedWidth = false; + } + + void moveDoubleToInts(FPRegisterID src, RegisterID dest1, RegisterID dest2) + { + m_assembler.vmov(dest1, dest2, src); + } + + void moveIntsToDouble(RegisterID src1, RegisterID src2, FPRegisterID dest, FPRegisterID scratch) + { + UNUSED_PARAM(scratch); + m_assembler.vmov(dest, src1, src2); + } + // Arithmetic control flow operations: // // This set of conditional branch operations branch based - // on the result of an arithmetic operation. The operation + // on the result of an arithmetic operation. The operation // is performed as normal, storing the result. // // * jz operations branch if the result is zero. // * jo operations branch if the (signed) arithmetic // operation caused an overflow to occur. - Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest) + Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest) { - ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero)); if (cond == Overflow) { /* move dest, dataTemp @@ -1136,6 +1543,12 @@ public: m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); } + if (cond == PositiveOrZero) { + add32(src, dest); + // Check if dest is not negative. + m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); + return branchEqual(cmpTempRegister, MIPSRegisters::zero); + } if (cond == Zero) { add32(src, dest); return branchEqual(dest, MIPSRegisters::zero); @@ -1148,22 +1561,17 @@ public: return Jump(); } - Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest) - { - move(imm, immTempRegister); - return branchAdd32(cond, immTempRegister, dest); - } - - Jump branchMul32(Condition cond, RegisterID src, RegisterID dest) + Jump branchAdd32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest) { - ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero)); if (cond == Overflow) { /* - mult src, dest - mfhi dataTemp - mflo dest - sra addrTemp, dest, 31 - beq dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow + move dataTemp, op1 + xor cmpTemp, dataTemp, op2 + bltz cmpTemp, No_overflow # diff sign bit -> no overflow + addu dest, dataTemp, op2 + xor cmpTemp, dest, dataTemp + bgez cmpTemp, No_overflow # same sign big -> no overflow nop b Overflow nop @@ -1173,50 +1581,64 @@ public: nop No_overflow: */ - m_assembler.mult(src, dest); - m_assembler.mfhi(dataTempRegister); - m_assembler.mflo(dest); - m_assembler.sra(addrTempRegister, dest, 31); - m_assembler.beq(dataTempRegister, addrTempRegister, 7); + move(op1, dataTempRegister); + m_assembler.xorInsn(cmpTempRegister, dataTempRegister, op2); + m_assembler.bltz(cmpTempRegister, 10); + m_assembler.addu(dest, dataTempRegister, op2); + m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister); + m_assembler.bgez(cmpTempRegister, 7); m_assembler.nop(); return jump(); } if (cond == Signed) { - mul32(src, dest); + add32(op1, op2, dest); // Check if dest is negative. m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); } + if (cond == PositiveOrZero) { + add32(op1, op2, dest); + // Check if dest is not negative. + m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); + return branchEqual(cmpTempRegister, MIPSRegisters::zero); + } if (cond == Zero) { - mul32(src, dest); + add32(op1, op2, dest); return branchEqual(dest, MIPSRegisters::zero); } if (cond == NonZero) { - mul32(src, dest); + add32(op1, op2, dest); return branchNotEqual(dest, MIPSRegisters::zero); } ASSERT(0); return Jump(); } - Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest) + Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest) + { + move(imm, immTempRegister); + return branchAdd32(cond, immTempRegister, dest); + } + + Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest) { move(imm, immTempRegister); move(src, dest); - return branchMul32(cond, immTempRegister, dest); + return branchAdd32(cond, immTempRegister, dest); } - Jump branchSub32(Condition cond, RegisterID src, RegisterID dest) + Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest) { - ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero)); if (cond == Overflow) { /* + move dataTemp, dest + xori cmpTemp, dataTemp, imm + bltz cmpTemp, No_overflow # diff sign bit -> no overflow + addiu dataTemp, dataTemp, imm move dest, dataTemp - xor cmpTemp, dataTemp, src - bgez cmpTemp, No_overflow # same sign bit -> no overflow - subu dest, dataTemp, src - xor cmpTemp, dest, dataTemp - bgez cmpTemp, No_overflow # same sign bit -> no overflow + xori cmpTemp, dataTemp, imm + bgez cmpTemp, No_overflow # same sign big -> no overflow nop b Overflow nop @@ -1226,70 +1648,311 @@ public: nop No_overflow: */ - move(dest, dataTempRegister); - m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src); - m_assembler.bgez(cmpTempRegister, 10); - m_assembler.subu(dest, dataTempRegister, src); - m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister); - m_assembler.bgez(cmpTempRegister, 7); - m_assembler.nop(); + if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth) { + load32(dest.m_ptr, dataTempRegister); + m_assembler.xori(cmpTempRegister, dataTempRegister, imm.m_value); + m_assembler.bltz(cmpTempRegister, 10); + m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value); + store32(dataTempRegister, dest.m_ptr); + m_assembler.xori(cmpTempRegister, dataTempRegister, imm.m_value); + m_assembler.bgez(cmpTempRegister, 7); + m_assembler.nop(); + } else { + load32(dest.m_ptr, dataTempRegister); + move(imm, immTempRegister); + m_assembler.xorInsn(cmpTempRegister, dataTempRegister, immTempRegister); + m_assembler.bltz(cmpTempRegister, 10); + m_assembler.addiu(dataTempRegister, dataTempRegister, immTempRegister); + store32(dataTempRegister, dest.m_ptr); + m_assembler.xori(cmpTempRegister, dataTempRegister, immTempRegister); + m_assembler.bgez(cmpTempRegister, 7); + m_assembler.nop(); + } return jump(); } + move(imm, immTempRegister); + load32(dest.m_ptr, dataTempRegister); + add32(immTempRegister, dataTempRegister); + store32(dataTempRegister, dest.m_ptr); if (cond == Signed) { - sub32(src, dest); // Check if dest is negative. - m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); + m_assembler.slt(cmpTempRegister, dataTempRegister, MIPSRegisters::zero); return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); } - if (cond == Zero) { - sub32(src, dest); - return branchEqual(dest, MIPSRegisters::zero); - } - if (cond == NonZero) { - sub32(src, dest); - return branchNotEqual(dest, MIPSRegisters::zero); + if (cond == PositiveOrZero) { + // Check if dest is not negative. + m_assembler.slt(cmpTempRegister, dataTempRegister, MIPSRegisters::zero); + return branchEqual(cmpTempRegister, MIPSRegisters::zero); } + if (cond == Zero) + return branchEqual(dataTempRegister, MIPSRegisters::zero); + if (cond == NonZero) + return branchNotEqual(dataTempRegister, MIPSRegisters::zero); ASSERT(0); return Jump(); } - Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest) - { - move(imm, immTempRegister); - return branchSub32(cond, immTempRegister, dest); - } - - // Miscellaneous operations: - - void breakpoint() - { - m_assembler.bkpt(); - } - - Call nearCall() + Jump branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest) { - /* We need two words for relaxation. */ - m_assembler.nop(); - m_assembler.nop(); - m_assembler.jal(); - m_assembler.nop(); - return Call(m_assembler.newJmpSrc(), Call::LinkableNear); - } - - Call call() + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + if (cond == Overflow) { + /* + mult src, dest + mfhi dataTemp + mflo dest + sra addrTemp, dest, 31 + beq dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow + nop + b Overflow + nop + nop + nop + nop + nop + No_overflow: + */ + m_assembler.mult(src1, src2); + m_assembler.mfhi(dataTempRegister); + m_assembler.mflo(dest); + m_assembler.sra(addrTempRegister, dest, 31); + m_assembler.beq(dataTempRegister, addrTempRegister, 7); + m_assembler.nop(); + return jump(); + } + if (cond == Signed) { + mul32(src1, src2, dest); + // Check if dest is negative. + m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + } + if (cond == Zero) { + mul32(src1, src2, dest); + return branchEqual(dest, MIPSRegisters::zero); + } + if (cond == NonZero) { + mul32(src1, src2, dest); + return branchNotEqual(dest, MIPSRegisters::zero); + } + ASSERT(0); + return Jump(); + } + + Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + if (cond == Overflow) { + /* + mult src, dest + mfhi dataTemp + mflo dest + sra addrTemp, dest, 31 + beq dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow + nop + b Overflow + nop + nop + nop + nop + nop + No_overflow: + */ + m_assembler.mult(src, dest); + m_assembler.mfhi(dataTempRegister); + m_assembler.mflo(dest); + m_assembler.sra(addrTempRegister, dest, 31); + m_assembler.beq(dataTempRegister, addrTempRegister, 7); + m_assembler.nop(); + return jump(); + } + if (cond == Signed) { + mul32(src, dest); + // Check if dest is negative. + m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + } + if (cond == Zero) { + mul32(src, dest); + return branchEqual(dest, MIPSRegisters::zero); + } + if (cond == NonZero) { + mul32(src, dest); + return branchNotEqual(dest, MIPSRegisters::zero); + } + ASSERT(0); + return Jump(); + } + + Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest) + { + move(imm, immTempRegister); + return branchMul32(cond, immTempRegister, src, dest); + } + + Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + if (cond == Overflow) { + /* + move dest, dataTemp + xor cmpTemp, dataTemp, src + bgez cmpTemp, No_overflow # same sign bit -> no overflow + subu dest, dataTemp, src + xor cmpTemp, dest, dataTemp + bgez cmpTemp, No_overflow # same sign bit -> no overflow + nop + b Overflow + nop + nop + nop + nop + nop + No_overflow: + */ + move(dest, dataTempRegister); + m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src); + m_assembler.bgez(cmpTempRegister, 10); + m_assembler.subu(dest, dataTempRegister, src); + m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister); + m_assembler.bgez(cmpTempRegister, 7); + m_assembler.nop(); + return jump(); + } + if (cond == Signed) { + sub32(src, dest); + // Check if dest is negative. + m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + } + if (cond == Zero) { + sub32(src, dest); + return branchEqual(dest, MIPSRegisters::zero); + } + if (cond == NonZero) { + sub32(src, dest); + return branchNotEqual(dest, MIPSRegisters::zero); + } + ASSERT(0); + return Jump(); + } + + Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest) + { + move(imm, immTempRegister); + return branchSub32(cond, immTempRegister, dest); + } + + Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest) + { + move(imm, immTempRegister); + return branchSub32(cond, src, immTempRegister, dest); + } + + Jump branchSub32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + if (cond == Overflow) { + /* + move dataTemp, op1 + xor cmpTemp, dataTemp, op2 + bgez cmpTemp, No_overflow # same sign bit -> no overflow + subu dest, dataTemp, op2 + xor cmpTemp, dest, dataTemp + bgez cmpTemp, No_overflow # same sign bit -> no overflow + nop + b Overflow + nop + nop + nop + nop + nop + No_overflow: + */ + move(op1, dataTempRegister); + m_assembler.xorInsn(cmpTempRegister, dataTempRegister, op2); + m_assembler.bgez(cmpTempRegister, 10); + m_assembler.subu(dest, dataTempRegister, op2); + m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister); + m_assembler.bgez(cmpTempRegister, 7); + m_assembler.nop(); + return jump(); + } + if (cond == Signed) { + sub32(op1, op2, dest); + // Check if dest is negative. + m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + } + if (cond == Zero) { + sub32(op1, op2, dest); + return branchEqual(dest, MIPSRegisters::zero); + } + if (cond == NonZero) { + sub32(op1, op2, dest); + return branchNotEqual(dest, MIPSRegisters::zero); + } + ASSERT(0); + return Jump(); + } + + Jump branchNeg32(ResultCondition cond, RegisterID srcDest) + { + m_assembler.li(dataTempRegister, -1); + return branchMul32(cond, dataTempRegister, srcDest); + } + + Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest) + { + ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero)); + if (cond == Signed) { + or32(src, dest); + // Check if dest is negative. + m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + } + if (cond == Zero) { + or32(src, dest); + return branchEqual(dest, MIPSRegisters::zero); + } + if (cond == NonZero) { + or32(src, dest); + return branchNotEqual(dest, MIPSRegisters::zero); + } + ASSERT(0); + return Jump(); + } + + // Miscellaneous operations: + + void breakpoint() + { + m_assembler.bkpt(); + } + + Call nearCall() + { + /* We need two words for relaxation. */ + m_assembler.nop(); + m_assembler.nop(); + m_assembler.jal(); + m_assembler.nop(); + return Call(m_assembler.label(), Call::LinkableNear); + } + + Call call() { m_assembler.lui(MIPSRegisters::t9, 0); m_assembler.ori(MIPSRegisters::t9, MIPSRegisters::t9, 0); m_assembler.jalr(MIPSRegisters::t9); m_assembler.nop(); - return Call(m_assembler.newJmpSrc(), Call::Linkable); + return Call(m_assembler.label(), Call::Linkable); } Call call(RegisterID target) { - m_assembler.jalr(target); + move(target, MIPSRegisters::t9); + m_assembler.jalr(MIPSRegisters::t9); m_assembler.nop(); - return Call(m_assembler.newJmpSrc(), Call::None); + return Call(m_assembler.label(), Call::None); } Call call(Address address) @@ -1299,7 +1962,7 @@ public: m_assembler.jalr(MIPSRegisters::t9); m_assembler.nop(); m_fixedWidth = false; - return Call(m_assembler.newJmpSrc(), Call::None); + return Call(m_assembler.label(), Call::None); } void ret() @@ -1308,12 +1971,12 @@ public: m_assembler.nop(); } - void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest) + void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest) { - if (cond == Equal || cond == Zero) { + if (cond == Equal) { m_assembler.xorInsn(dest, left, right); m_assembler.sltiu(dest, dest, 1); - } else if (cond == NotEqual || cond == NonZero) { + } else if (cond == NotEqual) { m_assembler.xorInsn(dest, left, right); m_assembler.sltu(dest, MIPSRegisters::zero, dest); } else if (cond == Above) @@ -1336,36 +1999,16 @@ public: else if (cond == LessThanOrEqual) { m_assembler.slt(dest, right, left); m_assembler.xori(dest, dest, 1); - } else if (cond == Overflow) { - /* - xor cmpTemp, left, right - bgez Done, cmpTemp # same sign bit -> no overflow - move dest, 0 - subu cmpTemp, left, right - xor cmpTemp, cmpTemp, left # diff sign bit -> overflow - slt dest, cmpTemp, 0 - Done: - */ - m_assembler.xorInsn(cmpTempRegister, left, right); - m_assembler.bgez(cmpTempRegister, 4); - m_assembler.move(dest, MIPSRegisters::zero); - m_assembler.subu(cmpTempRegister, left, right); - m_assembler.xorInsn(cmpTempRegister, cmpTempRegister, left); - m_assembler.slt(dest, cmpTempRegister, MIPSRegisters::zero); - } else if (cond == Signed) { - m_assembler.subu(dest, left, right); - // Check if the result is negative. - m_assembler.slt(dest, dest, MIPSRegisters::zero); } } - void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest) + void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest) { move(right, immTempRegister); - set32(cond, left, immTempRegister, dest); + compare32(cond, left, immTempRegister, dest); } - void setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest) + void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest) { ASSERT((cond == Zero) || (cond == NonZero)); load8(address, dataTempRegister); @@ -1376,8 +2019,7 @@ public: m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister); } else { move(mask, immTempRegister); - m_assembler.andInsn(cmpTempRegister, dataTempRegister, - immTempRegister); + m_assembler.andInsn(cmpTempRegister, dataTempRegister, immTempRegister); if (cond == Zero) m_assembler.sltiu(dest, cmpTempRegister, 1); else @@ -1385,7 +2027,7 @@ public: } } - void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest) + void test32(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest) { ASSERT((cond == Zero) || (cond == NonZero)); load32(address, dataTempRegister); @@ -1396,8 +2038,7 @@ public: m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister); } else { move(mask, immTempRegister); - m_assembler.andInsn(cmpTempRegister, dataTempRegister, - immTempRegister); + m_assembler.andInsn(cmpTempRegister, dataTempRegister, immTempRegister); if (cond == Zero) m_assembler.sltiu(dest, cmpTempRegister, 1); else @@ -1405,7 +2046,7 @@ public: } } - DataLabel32 moveWithPatch(Imm32 imm, RegisterID dest) + DataLabel32 moveWithPatch(TrustedImm32 imm, RegisterID dest) { m_fixedWidth = true; DataLabel32 label(this); @@ -1414,7 +2055,7 @@ public: return label; } - DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest) + DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest) { m_fixedWidth = true; DataLabelPtr label(this); @@ -1423,7 +2064,7 @@ public: return label; } - Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0)) + Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) { m_fixedWidth = true; dataLabel = moveWithPatch(initialRightValue, immTempRegister); @@ -1432,7 +2073,7 @@ public: return temp; } - Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0)) + Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) { m_fixedWidth = true; load32(left, dataTempRegister); @@ -1442,7 +2083,7 @@ public: return temp; } - DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address) + DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address) { m_fixedWidth = true; DataLabelPtr dataLabel = moveWithPatch(initialValue, dataTempRegister); @@ -1453,18 +2094,18 @@ public: DataLabelPtr storePtrWithPatch(ImplicitAddress address) { - return storePtrWithPatch(ImmPtr(0), address); + return storePtrWithPatch(TrustedImmPtr(0), address); } Call tailRecursiveCall() { // Like a normal call, but don't update the returned address register m_fixedWidth = true; - move(Imm32(0), MIPSRegisters::t9); + move(TrustedImm32(0), MIPSRegisters::t9); m_assembler.jr(MIPSRegisters::t9); m_assembler.nop(); m_fixedWidth = false; - return Call(m_assembler.newJmpSrc(), Call::Linkable); + return Call(m_assembler.label(), Call::Linkable); } Call makeTailRecursiveCall(Jump oldJump) @@ -1473,6 +2114,34 @@ public: return tailRecursiveCall(); } + void loadFloat(BaseIndex address, FPRegisterID dest) + { + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lwc1 dest, address.offset(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lwc1(dest, addrTempRegister, address.offset); + } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lui immTemp, (address.offset + 0x8000) >> 16 + addu addrTemp, addrTemp, immTemp + lwc1 dest, (address.offset & 0xffff)(at) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); + m_assembler.lwc1(dest, addrTempRegister, address.offset); + } + } + void loadDouble(ImplicitAddress address, FPRegisterID dest) { #if WTF_MIPS_ISA(1) @@ -1482,7 +2151,7 @@ public: lwc1 dest, 0(addrTemp) lwc1 dest+1, 4(addrTemp) */ - move(Imm32(address.offset), addrTempRegister); + move(TrustedImm32(address.offset), addrTempRegister); m_assembler.addu(addrTempRegister, addrTempRegister, address.base); m_assembler.lwc1(dest, addrTempRegister, 0); m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4); @@ -1503,6 +2172,114 @@ public: #endif } + void loadDouble(BaseIndex address, FPRegisterID dest) + { +#if WTF_MIPS_ISA(1) + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lwc1 dest, address.offset(addrTemp) + lwc1 dest+1, (address.offset+4)(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lwc1(dest, addrTempRegister, address.offset); + m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, address.offset + 4); + } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lui immTemp, (address.offset + 0x8000) >> 16 + addu addrTemp, addrTemp, immTemp + lwc1 dest, (address.offset & 0xffff)(at) + lwc1 dest+1, (address.offset & 0xffff + 4)(at) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); + m_assembler.lwc1(dest, addrTempRegister, address.offset); + m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, address.offset + 4); + } +#else + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + ldc1 dest, address.offset(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.ldc1(dest, addrTempRegister, address.offset); + } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lui immTemp, (address.offset + 0x8000) >> 16 + addu addrTemp, addrTemp, immTemp + ldc1 dest, (address.offset & 0xffff)(at) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); + m_assembler.ldc1(dest, addrTempRegister, address.offset); + } +#endif + } + + void loadDouble(const void* address, FPRegisterID dest) + { +#if WTF_MIPS_ISA(1) + /* + li addrTemp, address + lwc1 dest, 0(addrTemp) + lwc1 dest+1, 4(addrTemp) + */ + move(TrustedImmPtr(address), addrTempRegister); + m_assembler.lwc1(dest, addrTempRegister, 0); + m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4); +#else + /* + li addrTemp, address + ldc1 dest, 0(addrTemp) + */ + move(TrustedImmPtr(address), addrTempRegister); + m_assembler.ldc1(dest, addrTempRegister, 0); +#endif + } + + void storeFloat(FPRegisterID src, BaseIndex address) + { + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + swc1 src, address.offset(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.swc1(src, addrTempRegister, address.offset); + } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lui immTemp, (address.offset + 0x8000) >> 16 + addu addrTemp, addrTemp, immTemp + swc1 src, (address.offset & 0xffff)(at) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); + m_assembler.swc1(src, addrTempRegister, address.offset); + } + } + void storeDouble(FPRegisterID src, ImplicitAddress address) { #if WTF_MIPS_ISA(1) @@ -1512,7 +2289,7 @@ public: swc1 dest, 0(addrTemp) swc1 dest+1, 4(addrTemp) */ - move(Imm32(address.offset), addrTempRegister); + move(TrustedImm32(address.offset), addrTempRegister); m_assembler.addu(addrTempRegister, addrTempRegister, address.base); m_assembler.swc1(src, addrTempRegister, 0); m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, 4); @@ -1533,22 +2310,122 @@ public: #endif } + void storeDouble(FPRegisterID src, BaseIndex address) + { +#if WTF_MIPS_ISA(1) + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + swc1 src, address.offset(addrTemp) + swc1 src+1, (address.offset + 4)(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.swc1(src, addrTempRegister, address.offset); + m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, address.offset + 4); + } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lui immTemp, (address.offset + 0x8000) >> 16 + addu addrTemp, addrTemp, immTemp + swc1 src, (address.offset & 0xffff)(at) + swc1 src+1, (address.offset & 0xffff + 4)(at) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); + m_assembler.swc1(src, addrTempRegister, address.offset); + m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, address.offset + 4); + } +#else + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + sdc1 src, address.offset(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.sdc1(src, addrTempRegister, address.offset); + } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lui immTemp, (address.offset + 0x8000) >> 16 + addu addrTemp, addrTemp, immTemp + sdc1 src, (address.offset & 0xffff)(at) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); + m_assembler.sdc1(src, addrTempRegister, address.offset); + } +#endif + } + + void storeDouble(FPRegisterID src, const void* address) + { +#if WTF_MIPS_ISA(1) + move(TrustedImmPtr(address), addrTempRegister); + m_assembler.swc1(src, addrTempRegister, 0); + m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, 4); +#else + move(TrustedImmPtr(address), addrTempRegister); + m_assembler.sdc1(src, addrTempRegister, 0); +#endif + } + + void moveDouble(FPRegisterID src, FPRegisterID dest) + { + if (src != dest || m_fixedWidth) + m_assembler.movd(dest, src); + } + + void swapDouble(FPRegisterID fr1, FPRegisterID fr2) + { + moveDouble(fr1, fpTempRegister); + moveDouble(fr2, fr1); + moveDouble(fpTempRegister, fr2); + } + void addDouble(FPRegisterID src, FPRegisterID dest) { m_assembler.addd(dest, dest, src); } + void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) + { + m_assembler.addd(dest, op1, op2); + } + void addDouble(Address src, FPRegisterID dest) { loadDouble(src, fpTempRegister); m_assembler.addd(dest, dest, fpTempRegister); } + void addDouble(AbsoluteAddress address, FPRegisterID dest) + { + loadDouble(address.m_ptr, fpTempRegister); + m_assembler.addd(dest, dest, fpTempRegister); + } + void subDouble(FPRegisterID src, FPRegisterID dest) { m_assembler.subd(dest, dest, src); } + void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) + { + m_assembler.subd(dest, op1, op2); + } + void subDouble(Address src, FPRegisterID dest) { loadDouble(src, fpTempRegister); @@ -1566,12 +2443,62 @@ public: m_assembler.muld(dest, dest, fpTempRegister); } + void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) + { + m_assembler.muld(dest, op1, op2); + } + + void divDouble(FPRegisterID src, FPRegisterID dest) + { + m_assembler.divd(dest, dest, src); + } + + void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) + { + m_assembler.divd(dest, op1, op2); + } + + void divDouble(Address src, FPRegisterID dest) + { + loadDouble(src, fpTempRegister); + m_assembler.divd(dest, dest, fpTempRegister); + } + + void negateDouble(FPRegisterID src, FPRegisterID dest) + { + m_assembler.negd(dest, src); + } + void convertInt32ToDouble(RegisterID src, FPRegisterID dest) { m_assembler.mtc1(src, fpTempRegister); m_assembler.cvtdw(dest, fpTempRegister); } + void convertInt32ToDouble(Address src, FPRegisterID dest) + { + load32(src, dataTempRegister); + m_assembler.mtc1(dataTempRegister, fpTempRegister); + m_assembler.cvtdw(dest, fpTempRegister); + } + + void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest) + { + load32(src.m_ptr, dataTempRegister); + m_assembler.mtc1(dataTempRegister, fpTempRegister); + m_assembler.cvtdw(dest, fpTempRegister); + } + + void convertFloatToDouble(FPRegisterID src, FPRegisterID dst) + { + m_assembler.cvtds(dst, src); + } + + void convertDoubleToFloat(FPRegisterID src, FPRegisterID dst) + { + m_assembler.cvtsd(dst, src); + } + void insertRelaxationWords() { /* We need four words for relaxation. */ @@ -1587,7 +2514,7 @@ public: m_assembler.bc1t(); m_assembler.nop(); insertRelaxationWords(); - return Jump(m_assembler.newJmpSrc()); + return Jump(m_assembler.label()); } Jump branchFalse() @@ -1596,25 +2523,29 @@ public: m_assembler.bc1f(); m_assembler.nop(); insertRelaxationWords(); - return Jump(m_assembler.newJmpSrc()); + return Jump(m_assembler.label()); } Jump branchEqual(RegisterID rs, RegisterID rt) { + m_assembler.nop(); + m_assembler.nop(); m_assembler.appendJump(); m_assembler.beq(rs, rt, 0); m_assembler.nop(); insertRelaxationWords(); - return Jump(m_assembler.newJmpSrc()); + return Jump(m_assembler.label()); } Jump branchNotEqual(RegisterID rs, RegisterID rt) { + m_assembler.nop(); + m_assembler.nop(); m_assembler.appendJump(); m_assembler.bne(rs, rt, 0); m_assembler.nop(); insertRelaxationWords(); - return Jump(m_assembler.newJmpSrc()); + return Jump(m_assembler.label()); } Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right) @@ -1624,7 +2555,7 @@ public: return branchTrue(); } if (cond == DoubleNotEqual) { - m_assembler.ceqd(left, right); + m_assembler.cueqd(left, right); return branchFalse(); // false } if (cond == DoubleGreaterThan) { @@ -1632,7 +2563,7 @@ public: return branchFalse(); // false } if (cond == DoubleGreaterThanOrEqual) { - m_assembler.cnged(right, left); + m_assembler.cnged(left, right); return branchFalse(); // false } if (cond == DoubleLessThan) { @@ -1647,6 +2578,10 @@ public: m_assembler.cueqd(left, right); return branchTrue(); } + if (cond == DoubleNotEqualOrUnordered) { + m_assembler.ceqd(left, right); + return branchFalse(); // false + } if (cond == DoubleGreaterThanOrUnordered) { m_assembler.coled(left, right); return branchFalse(); // false @@ -1672,13 +2607,137 @@ public: // If the result is not representable as a 32 bit value, branch. // May also branch for some values that are representable in 32 bits // (specifically, in this case, INT_MAX 0x7fffffff). - Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest) + enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful }; + Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed) + { + m_assembler.truncwd(fpTempRegister, src); + m_assembler.mfc1(dest, fpTempRegister); + return branch32(branchType == BranchIfTruncateFailed ? Equal : NotEqual, dest, TrustedImm32(0x7fffffff)); + } + + Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed) { m_assembler.truncwd(fpTempRegister, src); m_assembler.mfc1(dest, fpTempRegister); - return branch32(Equal, dest, Imm32(0x7fffffff)); + return branch32(branchType == BranchIfTruncateFailed ? Equal : NotEqual, dest, TrustedImm32(0)); } + // Result is undefined if the value is outside of the integer range. + void truncateDoubleToInt32(FPRegisterID src, RegisterID dest) + { + m_assembler.truncwd(fpTempRegister, src); + m_assembler.mfc1(dest, fpTempRegister); + } + + // Result is undefined if src > 2^31 + void truncateDoubleToUint32(FPRegisterID src, RegisterID dest) + { + m_assembler.truncwd(fpTempRegister, src); + m_assembler.mfc1(dest, fpTempRegister); + } + + // Convert 'src' to an integer, and places the resulting 'dest'. + // If the result is not representable as a 32 bit value, branch. + // May also branch for some values that are representable in 32 bits + // (specifically, in this case, 0). + void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp, bool negZeroCheck = true) + { + m_assembler.cvtwd(fpTempRegister, src); + m_assembler.mfc1(dest, fpTempRegister); + + // If the result is zero, it might have been -0.0, and the double comparison won't catch this! + if (negZeroCheck) + failureCases.append(branch32(Equal, dest, MIPSRegisters::zero)); + + // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump. + convertInt32ToDouble(dest, fpTemp); + failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fpTemp, src)); + } + + Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch) + { + m_assembler.vmov(scratch, MIPSRegisters::zero, MIPSRegisters::zero); + return branchDouble(DoubleNotEqual, reg, scratch); + } + + Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch) + { + m_assembler.vmov(scratch, MIPSRegisters::zero, MIPSRegisters::zero); + return branchDouble(DoubleEqualOrUnordered, reg, scratch); + } + + // Invert a relational condition, e.g. == becomes !=, < becomes >=, etc. + static RelationalCondition invert(RelationalCondition cond) + { + RelationalCondition r; + if (cond == Equal) + r = NotEqual; + else if (cond == NotEqual) + r = Equal; + else if (cond == Above) + r = BelowOrEqual; + else if (cond == AboveOrEqual) + r = Below; + else if (cond == Below) + r = AboveOrEqual; + else if (cond == BelowOrEqual) + r = Above; + else if (cond == GreaterThan) + r = LessThanOrEqual; + else if (cond == GreaterThanOrEqual) + r = LessThan; + else if (cond == LessThan) + r = GreaterThanOrEqual; + else if (cond == LessThanOrEqual) + r = GreaterThan; + return r; + } + + void nop() + { + m_assembler.nop(); + } + + static FunctionPtr readCallTarget(CodeLocationCall call) + { + return FunctionPtr(reinterpret_cast(MIPSAssembler::readCallTarget(call.dataLocation()))); + } + + static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination) + { + MIPSAssembler::replaceWithJump(instructionStart.dataLocation(), destination.dataLocation()); + } + + static ptrdiff_t maxJumpReplacementSize() + { + MIPSAssembler::maxJumpReplacementSize(); + return 0; + } + + static bool canJumpReplacePatchableBranchPtrWithPatch() { return false; } + + static CodeLocationLabel startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label) + { + return label.labelAtOffset(0); + } + + static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID, void* initialValue) + { + MIPSAssembler::revertJumpToMove(instructionStart.dataLocation(), immTempRegister, reinterpret_cast(initialValue) & 0xffff); + } + + static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr) + { + UNREACHABLE_FOR_PLATFORM(); + return CodeLocationLabel(); + } + + static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel instructionStart, Address, void* initialValue) + { + UNREACHABLE_FOR_PLATFORM(); + } + + private: // If m_fixedWidth is true, we will generate a fixed number of instructions. // Otherwise, we can emit any number of instructions. @@ -1689,7 +2748,7 @@ private: static void linkCall(void* code, Call call, FunctionPtr function) { - MIPSAssembler::linkCall(code, call.m_jmp, function.value()); + MIPSAssembler::linkCall(code, call.m_label, function.value()); } static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)