X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/14957cd040308e3eeec43d26bae5d76da13fcd85..cb9aa2694aba0ae4f946ed34b8e0f6c99c1cfe44:/assembler/MacroAssemblerMIPS.h diff --git a/assembler/MacroAssemblerMIPS.h b/assembler/MacroAssemblerMIPS.h index 9cdfffc..71b5fa9 100644 --- a/assembler/MacroAssemblerMIPS.h +++ b/assembler/MacroAssemblerMIPS.h @@ -29,8 +29,8 @@ #if ENABLE(ASSEMBLER) && CPU(MIPS) -#include "MIPSAssembler.h" #include "AbstractMacroAssembler.h" +#include "MIPSAssembler.h" namespace JSC { @@ -43,6 +43,11 @@ public: { } + static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value) + { + return value >= -2147483647 - 1 && value <= 2147483647; + } + static const Scale ScalePtr = TimesFour; // For storing immediate number @@ -75,6 +80,7 @@ public: enum ResultCondition { Overflow, Signed, + PositiveOrZero, Zero, NonZero }; @@ -95,6 +101,7 @@ public: }; static const RegisterID stackPointerRegister = MIPSRegisters::sp; + static const RegisterID framePointerRegister = MIPSRegisters::fp; static const RegisterID returnAddressRegister = MIPSRegisters::ra; // Integer arithmetic operations: @@ -109,6 +116,11 @@ public: m_assembler.addu(dest, dest, src); } + void add32(RegisterID op1, RegisterID op2, RegisterID dest) + { + m_assembler.addu(dest, op1, op2); + } + void add32(TrustedImm32 imm, RegisterID dest) { add32(imm, dest, dest); @@ -116,7 +128,7 @@ public: 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 @@ -132,6 +144,11 @@ public: } } + 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 @@ -143,15 +160,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 { @@ -168,12 +182,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); } @@ -185,6 +197,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) { @@ -217,33 +235,61 @@ public: /* 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(TrustedImmPtr(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); + 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(RegisterID op1, RegisterID op2, RegisterID dest) + { + m_assembler.andInsn(dest, op1, op2); + } + void and32(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 && 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 { /* @@ -255,9 +301,16 @@ public: } } - void lshift32(TrustedImm32 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) @@ -265,16 +318,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(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 { /* @@ -291,22 +366,22 @@ public: m_assembler.subu(srcDest, MIPSRegisters::zero, srcDest); } - void not32(RegisterID srcDest) + void or32(RegisterID src, RegisterID dest) { - m_assembler.nor(srcDest, srcDest, MIPSRegisters::zero); + m_assembler.orInsn(dest, dest, src); } - void or32(RegisterID src, RegisterID dest) + void or32(RegisterID op1, RegisterID op2, RegisterID dest) { - m_assembler.orInsn(dest, dest, src); + 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; @@ -320,34 +395,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(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(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 @@ -363,6 +488,24 @@ public: } } + 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 @@ -374,15 +517,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 { @@ -398,15 +537,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); } @@ -430,11 +566,9 @@ public: 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); } @@ -446,8 +580,18 @@ public: m_assembler.xorInsn(dest, dest, src); } + 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 @@ -456,15 +600,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 TrustedImm32. 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. @@ -486,6 +664,77 @@ 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); + } + } + + ALWAYS_INLINE void load8(AbsoluteAddress address, RegisterID dest) + { + load8(address.m_ptr, dest); + } + + void load8(const void* address, RegisterID dest) + { + /* + li addrTemp, address + lbu dest, 0(addrTemp) + */ + move(TrustedImmPtr(address), addrTempRegister); + m_assembler.lbu(dest, addrTempRegister, 0); + } + + 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 @@ -526,12 +775,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 @@ -574,8 +827,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); @@ -662,12 +914,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; @@ -685,112 +964,225 @@ public: 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 store32(TrustedImm32 imm, ImplicitAddress 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 { - /* - lui addrTemp, (offset + 0x8000) >> 16 - addu addrTemp, addrTemp, base - sw immTemp, (offset & 0xffff)(addrTemp) - */ - 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); - else { - move(imm, immTempRegister); - m_assembler.sw(immTempRegister, addrTempRegister, - address.offset); - } - } - } - - void store32(RegisterID src, const void* address) + void store8(RegisterID src, void* address) { - /* - li addrTemp, address - sw src, 0(addrTemp) - */ move(TrustedImmPtr(address), addrTempRegister); - m_assembler.sw(src, addrTempRegister, 0); + m_assembler.sb(src, addrTempRegister, 0); } - void store32(TrustedImm32 imm, const void* address) + void store8(TrustedImm32 imm, void* address) { /* li immTemp, imm li addrTemp, address - sw src, 0(addrTemp) + sb src, 0(addrTemp) */ - if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) { + if (!imm.m_value && !m_fixedWidth) { move(TrustedImmPtr(address), addrTempRegister); - m_assembler.sw(MIPSRegisters::zero, addrTempRegister, 0); + m_assembler.sb(MIPSRegisters::zero, addrTempRegister, 0); } else { move(imm, immTempRegister); move(TrustedImmPtr(address), addrTempRegister); - m_assembler.sw(immTempRegister, addrTempRegister, 0); + m_assembler.sb(immTempRegister, addrTempRegister, 0); + } + } + + void store16(RegisterID src, BaseIndex address) + { + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + /* + 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 + sw immTemp, (offset & 0xffff)(addrTemp) + */ + m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + 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); + } + } + } + + + void store32(RegisterID src, const void* address) + { + /* + li addrTemp, address + sw src, 0(addrTemp) + */ + move(TrustedImmPtr(address), addrTempRegister); + m_assembler.sw(src, addrTempRegister, 0); + } + + void store32(TrustedImm32 imm, const void* address) + { + /* + li immTemp, imm + li addrTemp, address + sw src, 0(addrTemp) + */ + if (!imm.m_value && !m_fixedWidth) { + move(TrustedImmPtr(address), addrTempRegister); + m_assembler.sw(MIPSRegisters::zero, addrTempRegister, 0); + } else { + move(imm, immTempRegister); + 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; @@ -799,7 +1191,7 @@ public: #endif } - bool supportsFloatingPointTruncate() const + static bool supportsFloatingPointTruncate() { #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2) return true; @@ -808,7 +1200,7 @@ public: #endif } - bool supportsFloatingPointSqrt() const + static bool supportsFloatingPointSqrt() { #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2) return true; @@ -816,13 +1208,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) @@ -855,9 +1248,9 @@ public: 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 @@ -921,6 +1314,34 @@ public: return branch32(cond, dataTempRegister, immTempRegister); } + Jump branch8(RelationalCondition cond, AbsoluteAddress 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(RelationalCondition cond, RegisterID left, RegisterID right) { if (cond == Equal) @@ -1021,22 +1442,6 @@ public: return branch32(cond, dataTempRegister, immTempRegister); } - Jump branch16(RelationalCondition cond, BaseIndex left, RegisterID right) - { - load16(left, dataTempRegister); - return branch32(cond, dataTempRegister, right); - } - - Jump branch16(RelationalCondition cond, BaseIndex left, TrustedImm32 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(ResultCondition cond, RegisterID reg, RegisterID mask) { ASSERT((cond == Zero) || (cond == NonZero)); @@ -1070,12 +1475,25 @@ public: return branchTest32(cond, dataTempRegister, mask); } + Jump branchTest8(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) + { + load8(address, dataTempRegister); + return branchTest32(cond, dataTempRegister, mask); + } + 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); @@ -1083,7 +1501,8 @@ public: void jump(RegisterID target) { - m_assembler.jr(target); + move(target, MIPSRegisters::t9); + m_assembler.jr(MIPSRegisters::t9); m_assembler.nop(); } @@ -1096,10 +1515,30 @@ 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. @@ -1108,7 +1547,7 @@ public: 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 @@ -1141,6 +1580,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); @@ -1153,12 +1598,182 @@ public: return Jump(); } + Jump branchAdd32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero)); + if (cond == 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 + nop + nop + nop + nop + No_overflow: + */ + 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) { + 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) { + add32(op1, op2, dest); + return branchEqual(dest, MIPSRegisters::zero); + } + if (cond == NonZero) { + add32(op1, op2, dest); + return branchNotEqual(dest, MIPSRegisters::zero); + } + ASSERT(0); + return Jump(); + } + 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 branchAdd32(cond, immTempRegister, dest); + } + + Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest) + { + 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 + xori cmpTemp, dataTemp, imm + bgez cmpTemp, No_overflow # same sign big -> no overflow + nop + b Overflow + nop + nop + nop + nop + nop + No_overflow: + */ + 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) { + // Check if dest is negative. + m_assembler.slt(cmpTempRegister, dataTempRegister, MIPSRegisters::zero); + return branchNotEqual(cmpTempRegister, 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 branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, 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(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)); @@ -1204,22 +1819,80 @@ public: return Jump(); } - Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest) + 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); - move(src, dest); - return branchMul32(cond, immTempRegister, dest); + return branchSub32(cond, immTempRegister, dest); } - Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID 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 dest, dataTemp - xor cmpTemp, dataTemp, src + move dataTemp, op1 + xor cmpTemp, dataTemp, op2 bgez cmpTemp, No_overflow # same sign bit -> no overflow - subu dest, dataTemp, src + subu dest, dataTemp, op2 xor cmpTemp, dest, dataTemp bgez cmpTemp, No_overflow # same sign bit -> no overflow nop @@ -1231,37 +1904,37 @@ public: nop No_overflow: */ - move(dest, dataTempRegister); - m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src); + move(op1, dataTempRegister); + m_assembler.xorInsn(cmpTempRegister, dataTempRegister, op2); m_assembler.bgez(cmpTempRegister, 10); - m_assembler.subu(dest, dataTempRegister, src); + 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(src, dest); + 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(src, dest); + sub32(op1, op2, dest); return branchEqual(dest, MIPSRegisters::zero); } if (cond == NonZero) { - sub32(src, dest); + sub32(op1, op2, dest); return branchNotEqual(dest, MIPSRegisters::zero); } ASSERT(0); return Jump(); } - Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest) + Jump branchNeg32(ResultCondition cond, RegisterID srcDest) { - move(imm, immTempRegister); - return branchSub32(cond, immTempRegister, dest); + m_assembler.li(dataTempRegister, -1); + return branchMul32(cond, dataTempRegister, srcDest); } Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest) @@ -1294,7 +1967,7 @@ public: Call nearCall() { - /* We need two words for relaxation. */ + /* We need two words for relaxation. */ m_assembler.nop(); m_assembler.nop(); m_assembler.jal(); @@ -1313,7 +1986,8 @@ public: Call call(RegisterID target) { - m_assembler.jalr(target); + move(target, MIPSRegisters::t9); + m_assembler.jalr(MIPSRegisters::t9); m_assembler.nop(); return Call(m_assembler.label(), Call::None); } @@ -1382,8 +2056,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 @@ -1402,8 +2075,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 @@ -1479,6 +2151,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) @@ -1509,7 +2209,66 @@ public: #endif } - void loadDouble(const void* address, FPRegisterID dest) + 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(TrustedImmPtr address, FPRegisterID dest) { #if WTF_MIPS_ISA(1) /* @@ -1517,7 +2276,7 @@ public: lwc1 dest, 0(addrTemp) lwc1 dest+1, 4(addrTemp) */ - move(TrustedImmPtr(address), addrTempRegister); + move(address, addrTempRegister); m_assembler.lwc1(dest, addrTempRegister, 0); m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4); #else @@ -1525,11 +2284,38 @@ public: li addrTemp, address ldc1 dest, 0(addrTemp) */ - move(TrustedImmPtr(address), addrTempRegister); + move(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) { @@ -1561,22 +2347,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, TrustedImmPtr address) + { +#if WTF_MIPS_ISA(1) + move(address, addrTempRegister); + m_assembler.swc1(src, addrTempRegister, 0); + m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, 4); +#else + move(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(TrustedImmPtr(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); @@ -1594,11 +2480,32 @@ 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); @@ -1619,6 +2526,16 @@ public: 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. */ @@ -1648,6 +2565,8 @@ public: Jump branchEqual(RegisterID rs, RegisterID rt) { + m_assembler.nop(); + m_assembler.nop(); m_assembler.appendJump(); m_assembler.beq(rs, rt, 0); m_assembler.nop(); @@ -1657,6 +2576,8 @@ public: Jump branchNotEqual(RegisterID rs, RegisterID rt) { + m_assembler.nop(); + m_assembler.nop(); m_assembler.appendJump(); m_assembler.bne(rs, rt, 0); m_assembler.nop(); @@ -1723,24 +2644,47 @@ 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(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); - return branch32(Equal, dest, TrustedImm32(0x7fffffff)); } // 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) + 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! - failureCases.append(branch32(Equal, dest, MIPSRegisters::zero)); + 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); @@ -1749,33 +2693,93 @@ public: Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch) { -#if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64 - m_assembler.mtc1(MIPSRegisters::zero, scratch); - m_assembler.mthc1(MIPSRegisters::zero, scratch); -#else - m_assembler.mtc1(MIPSRegisters::zero, scratch); - m_assembler.mtc1(MIPSRegisters::zero, FPRegisterID(scratch + 1)); -#endif + m_assembler.vmov(scratch, MIPSRegisters::zero, MIPSRegisters::zero); return branchDouble(DoubleNotEqual, reg, scratch); } Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch) { -#if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64 - m_assembler.mtc1(MIPSRegisters::zero, scratch); - m_assembler.mthc1(MIPSRegisters::zero, scratch); -#else - m_assembler.mtc1(MIPSRegisters::zero, scratch); - m_assembler.mtc1(MIPSRegisters::zero, FPRegisterID(scratch + 1)); -#endif + 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(); } + void memoryFence() + { + m_assembler.sync(); + } + + 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, Address, void*) + { + 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. @@ -1786,7 +2790,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)