X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/14957cd040308e3eeec43d26bae5d76da13fcd85..8b637bb680022adfddad653280734877951535a9:/assembler/MacroAssemblerSH4.h?ds=sidebyside diff --git a/assembler/MacroAssemblerSH4.h b/assembler/MacroAssemblerSH4.h index 8bed14c..a09c9a0 100644 --- a/assembler/MacroAssemblerSH4.h +++ b/assembler/MacroAssemblerSH4.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2013 Cisco Systems, Inc. All rights reserved. * Copyright (C) 2009-2011 STMicroelectronics. All rights reserved. * Copyright (C) 2008 Apple Inc. All rights reserved. * @@ -29,8 +30,8 @@ #if ENABLE(ASSEMBLER) && CPU(SH4) -#include "AbstractMacroAssembler.h" #include "SH4Assembler.h" +#include "AbstractMacroAssembler.h" #include namespace JSC { @@ -45,7 +46,12 @@ public: static const RegisterID linkRegister = SH4Registers::pr; static const RegisterID scratchReg3 = SH4Registers::r13; - static const int MaximumCompactPtrAlignedAddressOffset = 0x7FFFFFFF; + static const int MaximumCompactPtrAlignedAddressOffset = 60; + + static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value) + { + return (value >= 0) && (value <= MaximumCompactPtrAlignedAddressOffset); + } enum RelationalCondition { Equal = SH4Assembler::EQ, @@ -63,6 +69,7 @@ public: enum ResultCondition { Overflow = SH4Assembler::OF, Signed = SH4Assembler::SI, + PositiveOrZero = SH4Assembler::NS, Zero = SH4Assembler::EQ, NonZero = SH4Assembler::NE }; @@ -103,6 +110,9 @@ public: void add32(TrustedImm32 imm, RegisterID dest) { + if (!imm.m_value) + return; + if (m_assembler.isImmediate(imm.m_value)) { m_assembler.addlImm8r(imm.m_value, dest); return; @@ -123,6 +133,9 @@ public: void add32(TrustedImm32 imm, Address address) { + if (!imm.m_value) + return; + RegisterID scr = claimScratch(); load32(address, scr); add32(imm, scr); @@ -138,6 +151,14 @@ public: releaseScratch(scr); } + void add32(AbsoluteAddress src, RegisterID dest) + { + RegisterID scr = claimScratch(); + load32(src.m_ptr, scr); + m_assembler.addlRegReg(scr, dest); + releaseScratch(scr); + } + void and32(RegisterID src, RegisterID dest) { m_assembler.andlRegReg(src, dest); @@ -151,35 +172,54 @@ public: } RegisterID scr = claimScratch(); - m_assembler.loadConstant((imm.m_value), scr); + m_assembler.loadConstant(imm.m_value, scr); m_assembler.andlRegReg(scr, dest); releaseScratch(scr); } - void lshift32(RegisterID shiftamount, RegisterID dest) + void and32(TrustedImm32 imm, RegisterID src, RegisterID dest) { - m_assembler.shllRegReg(dest, shiftamount); + if (src != dest) { + move(imm, dest); + and32(src, dest); + return; + } + + and32(imm, dest); } - void rshift32(int imm, RegisterID dest) + void lshift32(RegisterID shiftamount, RegisterID dest) { - RegisterID scr = claimScratch(); - m_assembler.loadConstant(-imm, scr); - m_assembler.shaRegReg(dest, scr); - releaseScratch(scr); + RegisterID shiftTmp = claimScratch(); + m_assembler.loadConstant(0x1f, shiftTmp); + m_assembler.andlRegReg(shiftamount, shiftTmp); + m_assembler.shldRegReg(dest, shiftTmp); + releaseScratch(shiftTmp); } void lshift32(TrustedImm32 imm, RegisterID dest) { - if ((imm.m_value == 1) || (imm.m_value == 2) || (imm.m_value == 8) || (imm.m_value == 16)) { - m_assembler.shllImm8r(imm.m_value, dest); + int immMasked = imm.m_value & 0x1f; + if (!immMasked) + return; + + if ((immMasked == 1) || (immMasked == 2) || (immMasked == 8) || (immMasked == 16)) { + m_assembler.shllImm8r(immMasked, dest); return; } - RegisterID scr = claimScratch(); - m_assembler.loadConstant(imm.m_value, scr); - m_assembler.shllRegReg(dest, scr); - releaseScratch(scr); + RegisterID shiftTmp = claimScratch(); + m_assembler.loadConstant(immMasked, shiftTmp); + m_assembler.shldRegReg(dest, shiftTmp); + releaseScratch(shiftTmp); + } + + void lshift32(RegisterID src, TrustedImm32 shiftamount, RegisterID dest) + { + if (src != dest) + move(src, dest); + + lshift32(shiftamount, dest); } void mul32(RegisterID src, RegisterID dest) @@ -192,17 +232,12 @@ public: { RegisterID scr = claimScratch(); move(imm, scr); - if (src != dest) + if (src != dest) move(src, dest); - mul32(scr, dest); + mul32(scr, dest); releaseScratch(scr); } - void not32(RegisterID src, RegisterID dest) - { - m_assembler.notlReg(src, dest); - } - void or32(RegisterID src, RegisterID dest) { m_assembler.orlRegReg(src, dest); @@ -221,46 +256,84 @@ public: releaseScratch(scr); } - void rshift32(RegisterID shiftamount, RegisterID dest) + void or32(RegisterID op1, RegisterID op2, RegisterID dest) { - compare32(32, shiftamount, Equal); - m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4); - m_assembler.branch(BT_OPCODE, 1); - m_assembler.neg(shiftamount, shiftamount); - m_assembler.shaRegReg(dest, shiftamount); + if (op1 == op2) + move(op1, dest); + else if (op1 == dest) + or32(op2, dest); + else { + move(op2, dest); + or32(op1, dest); + } } - void rshift32(TrustedImm32 imm, RegisterID dest) + void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) { - if (imm.m_value & 0x1f) - rshift32(imm.m_value & 0x1f, dest); + if (src != dest) { + move(imm, dest); + or32(src, dest); + return; + } + + or32(imm, dest); } - void sub32(RegisterID src, RegisterID dest) + void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest) { - m_assembler.sublRegReg(src, dest); + if (src != dest) { + move(imm, dest); + xor32(src, dest); + return; + } + + xor32(imm, dest); } - void sub32(TrustedImm32 imm, AbsoluteAddress address, RegisterID scratchReg) + void rshift32(RegisterID shiftamount, RegisterID dest) { - RegisterID result = claimScratch(); + RegisterID shiftTmp = claimScratch(); + m_assembler.loadConstant(0x1f, shiftTmp); + m_assembler.andlRegReg(shiftamount, shiftTmp); + m_assembler.neg(shiftTmp, shiftTmp); + m_assembler.shadRegReg(dest, shiftTmp); + releaseScratch(shiftTmp); + } - m_assembler.loadConstant(reinterpret_cast(address.m_ptr), scratchReg); - m_assembler.movlMemReg(scratchReg, result); + void rshift32(TrustedImm32 imm, RegisterID dest) + { + int immMasked = imm.m_value & 0x1f; + if (!immMasked) + return; - if (m_assembler.isImmediate(-imm.m_value)) - m_assembler.addlImm8r(-imm.m_value, result); - else { - m_assembler.loadConstant(imm.m_value, scratchReg3); - m_assembler.sublRegReg(scratchReg3, result); + if (immMasked == 1) { + m_assembler.sharImm8r(immMasked, dest); + return; } - store32(result, scratchReg); - releaseScratch(result); + RegisterID shiftTmp = claimScratch(); + m_assembler.loadConstant(-immMasked, shiftTmp); + m_assembler.shadRegReg(dest, shiftTmp); + releaseScratch(shiftTmp); + } + + void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) + { + if (src != dest) + move(src, dest); + rshift32(imm, dest); + } + + void sub32(RegisterID src, RegisterID dest) + { + m_assembler.sublRegReg(src, dest); } void sub32(TrustedImm32 imm, AbsoluteAddress address) { + if (!imm.m_value) + return; + RegisterID result = claimScratch(); RegisterID scratchReg = claimScratch(); @@ -279,26 +352,11 @@ public: releaseScratch(scratchReg); } - void add32(TrustedImm32 imm, AbsoluteAddress address, RegisterID scratchReg) - { - RegisterID result = claimScratch(); - - m_assembler.loadConstant(reinterpret_cast(address.m_ptr), scratchReg); - m_assembler.movlMemReg(scratchReg, result); - - if (m_assembler.isImmediate(imm.m_value)) - m_assembler.addlImm8r(imm.m_value, result); - else { - m_assembler.loadConstant(imm.m_value, scratchReg3); - m_assembler.addlRegReg(scratchReg3, result); - } - - store32(result, scratchReg); - releaseScratch(result); - } - void add32(TrustedImm32 imm, AbsoluteAddress address) { + if (!imm.m_value) + return; + RegisterID result = claimScratch(); RegisterID scratchReg = claimScratch(); @@ -317,8 +375,39 @@ public: releaseScratch(scratchReg); } + void add64(TrustedImm32 imm, AbsoluteAddress address) + { + RegisterID scr1 = claimScratch(); + RegisterID scr2 = claimScratch(); + + // Add 32-bit LSB first. + m_assembler.loadConstant(reinterpret_cast(address.m_ptr), scr1); + m_assembler.movlMemReg(scr1, scr1); // scr1 = 32-bit LSB of int64 @ address + m_assembler.loadConstant(imm.m_value, scr2); + m_assembler.clrt(); + m_assembler.addclRegReg(scr1, scr2); + m_assembler.loadConstant(reinterpret_cast(address.m_ptr), scr1); + m_assembler.movlRegMem(scr2, scr1); // Update address with 32-bit LSB result. + + // Then add 32-bit MSB. + m_assembler.addlImm8r(4, scr1); + m_assembler.movlMemReg(scr1, scr1); // scr1 = 32-bit MSB of int64 @ address + m_assembler.movt(scr2); + if (imm.m_value < 0) + m_assembler.addlImm8r(-1, scr2); // Sign extend imm value if needed. + m_assembler.addvlRegReg(scr2, scr1); + m_assembler.loadConstant(reinterpret_cast(address.m_ptr) + 4, scr2); + m_assembler.movlRegMem(scr1, scr2); // Update (address + 4) with 32-bit MSB result. + + releaseScratch(scr2); + releaseScratch(scr1); + } + void sub32(TrustedImm32 imm, RegisterID dest) { + if (!imm.m_value) + return; + if (m_assembler.isImmediate(-imm.m_value)) { m_assembler.addlImm8r(-imm.m_value, dest); return; @@ -345,9 +434,14 @@ public: void xor32(TrustedImm32 imm, RegisterID srcDest) { + if (imm.m_value == -1) { + m_assembler.notlReg(srcDest, srcDest); + return; + } + if ((srcDest != SH4Registers::r0) || (imm.m_value > 255) || (imm.m_value < 0)) { RegisterID scr = claimScratch(); - m_assembler.loadConstant((imm.m_value), scr); + m_assembler.loadConstant(imm.m_value, scr); m_assembler.xorlRegReg(scr, srcDest); releaseScratch(scr); return; @@ -502,6 +596,32 @@ public: load8(address.base, address.offset, dest); } + void load8(BaseIndex address, RegisterID dest) + { + RegisterID scr = claimScratch(); + move(address.index, scr); + lshift32(TrustedImm32(address.scale), scr); + add32(address.base, scr); + load8(scr, address.offset, dest); + releaseScratch(scr); + } + + void load8PostInc(RegisterID base, RegisterID dest) + { + m_assembler.movbMemRegIn(base, dest); + m_assembler.extub(dest, dest); + } + + void load8Signed(BaseIndex address, RegisterID dest) + { + RegisterID scr = claimScratch(); + move(address.index, scr); + lshift32(TrustedImm32(address.scale), scr); + add32(address.base, scr); + load8Signed(scr, address.offset, dest); + releaseScratch(scr); + } + void load32(BaseIndex address, RegisterID dest) { RegisterID scr = claimScratch(); @@ -512,9 +632,9 @@ public: releaseScratch(scr); } - void load32(void* address, RegisterID dest) + void load32(const void* address, RegisterID dest) { - m_assembler.loadConstant(reinterpret_cast(address), dest); + m_assembler.loadConstant(reinterpret_cast(const_cast(address)), dest); m_assembler.movlMemReg(dest, dest); } @@ -530,55 +650,50 @@ public: return; } - if ((dest == SH4Registers::r0) && (dest != base)) { - m_assembler.loadConstant((offset), dest); - m_assembler.movlR0mr(base, dest); - return; - } + RegisterID scr = (dest == base) ? claimScratch() : dest; - RegisterID scr; - if (dest == base) - scr = claimScratch(); - else - scr = dest; - m_assembler.loadConstant((offset), scr); - m_assembler.addlRegReg(base, scr); - m_assembler.movlMemReg(scr, dest); + m_assembler.loadConstant(offset, scr); + if (base == SH4Registers::r0) + m_assembler.movlR0mr(scr, dest); + else { + m_assembler.addlRegReg(base, scr); + m_assembler.movlMemReg(scr, dest); + } if (dest == base) releaseScratch(scr); } - void load8(RegisterID base, int offset, RegisterID dest) + void load8Signed(RegisterID base, int offset, RegisterID dest) { if (!offset) { m_assembler.movbMemReg(base, dest); return; } - if ((offset > 0) && (offset < 64) && (dest == SH4Registers::r0)) { + if ((offset > 0) && (offset <= 15) && (dest == SH4Registers::r0)) { m_assembler.movbMemReg(offset, base, dest); return; } - if (base != dest) { - m_assembler.loadConstant((offset), dest); - m_assembler.addlRegReg(base, dest); - m_assembler.movbMemReg(dest, dest); - return; + RegisterID scr = (dest == base) ? claimScratch() : dest; + + m_assembler.loadConstant(offset, scr); + if (base == SH4Registers::r0) + m_assembler.movbR0mr(scr, dest); + else { + m_assembler.addlRegReg(base, scr); + m_assembler.movbMemReg(scr, dest); } - RegisterID scr = claimScratch(); - m_assembler.loadConstant((offset), scr); - m_assembler.addlRegReg(base, scr); - m_assembler.movbMemReg(scr, dest); - releaseScratch(scr); + if (dest == base) + releaseScratch(scr); } - void load32(RegisterID r0, RegisterID src, RegisterID dst) + void load8(RegisterID base, int offset, RegisterID dest) { - ASSERT(r0 == SH4Registers::r0); - m_assembler.movlR0mr(src, dst); + load8Signed(base, offset, dest); + m_assembler.extub(dest, dest); } void load32(RegisterID src, RegisterID dst) @@ -590,40 +705,76 @@ public: { if (!address.offset) { m_assembler.movwMemReg(address.base, dest); + m_assembler.extuw(dest, dest); return; } - if ((address.offset > 0) && (address.offset < 64) && (dest == SH4Registers::r0)) { - m_assembler.movwMemReg(address.offset, address.base, dest); + if ((address.offset > 0) && (address.offset <= 30) && (dest == SH4Registers::r0)) { + m_assembler.movwMemReg(address.offset >> 1, address.base, dest); + m_assembler.extuw(dest, dest); return; } - if (address.base != dest) { - m_assembler.loadConstant((address.offset), dest); - m_assembler.addlRegReg(address.base, dest); - m_assembler.movwMemReg(dest, dest); - return; + RegisterID scr = (dest == address.base) ? claimScratch() : dest; + + m_assembler.loadConstant(address.offset, scr); + if (address.base == SH4Registers::r0) + m_assembler.movwR0mr(scr, dest); + else { + m_assembler.addlRegReg(address.base, scr); + m_assembler.movwMemReg(scr, dest); } + m_assembler.extuw(dest, dest); + + if (dest == address.base) + releaseScratch(scr); + } + void load16Unaligned(BaseIndex address, RegisterID dest) + { RegisterID scr = claimScratch(); - m_assembler.loadConstant((address.offset), scr); - m_assembler.addlRegReg(address.base, scr); - m_assembler.movwMemReg(scr, dest); + RegisterID scr1 = claimScratch(); + + move(address.index, scr); + lshift32(TrustedImm32(address.scale), scr); + + if (address.offset) + add32(TrustedImm32(address.offset), scr); + + add32(address.base, scr); + load8PostInc(scr, scr1); + load8(scr, dest); + m_assembler.shllImm8r(8, dest); + or32(scr1, dest); + releaseScratch(scr); + releaseScratch(scr1); } void load16(RegisterID src, RegisterID dest) { m_assembler.movwMemReg(src, dest); + m_assembler.extuw(dest, dest); } - void load16(RegisterID r0, RegisterID src, RegisterID dest) + void load16Signed(RegisterID src, RegisterID dest) { - ASSERT(r0 == SH4Registers::r0); - m_assembler.movwR0mr(src, dest); + m_assembler.movwMemReg(src, dest); } void load16(BaseIndex address, RegisterID dest) + { + load16Signed(address, dest); + m_assembler.extuw(dest, dest); + } + + void load16PostInc(RegisterID base, RegisterID dest) + { + m_assembler.movwMemRegIn(base, dest); + m_assembler.extuw(dest, dest); + } + + void load16Signed(BaseIndex address, RegisterID dest) { RegisterID scr = claimScratch(); @@ -632,50 +783,74 @@ public: if (address.offset) add32(TrustedImm32(address.offset), scr); - if (scr == SH4Registers::r0) - m_assembler.movwR0mr(address.base, scr); + + if (address.base == SH4Registers::r0) + m_assembler.movwR0mr(scr, dest); else { add32(address.base, scr); - load16(scr, scr); + load16Signed(scr, dest); } - extuw(scr, dest); releaseScratch(scr); } - void store32(RegisterID src, ImplicitAddress address) + void store8(RegisterID src, BaseIndex address) { RegisterID scr = claimScratch(); - store32(src, address.offset, address.base, scr); + + move(address.index, scr); + lshift32(TrustedImm32(address.scale), scr); + add32(TrustedImm32(address.offset), scr); + + if (address.base == SH4Registers::r0) + m_assembler.movbRegMemr0(src, scr); + else { + add32(address.base, scr); + m_assembler.movbRegMem(src, scr); + } + releaseScratch(scr); } - void store32(RegisterID src, int offset, RegisterID base, RegisterID scr) + void store16(RegisterID src, BaseIndex address) { - if (!offset) { - m_assembler.movlRegMem(src, base); - return; + RegisterID scr = claimScratch(); + + move(address.index, scr); + lshift32(TrustedImm32(address.scale), scr); + add32(TrustedImm32(address.offset), scr); + + if (address.base == SH4Registers::r0) + m_assembler.movwRegMemr0(src, scr); + else { + add32(address.base, scr); + m_assembler.movwRegMem(src, scr); } - if ((offset >=0) && (offset < 64)) { - m_assembler.movlRegMem(src, offset >> 2, base); + releaseScratch(scr); + } + + void store32(RegisterID src, ImplicitAddress address) + { + if (!address.offset) { + m_assembler.movlRegMem(src, address.base); return; } - m_assembler.loadConstant((offset), scr); - if (scr == SH4Registers::r0) { - m_assembler.movlRegMemr0(src, base); + if ((address.offset >= 0) && (address.offset < 64)) { + m_assembler.movlRegMem(src, address.offset >> 2, address.base); return; } - m_assembler.addlRegReg(base, scr); - m_assembler.movlRegMem(src, scr); - } - - void store32(RegisterID src, RegisterID offset, RegisterID base) - { - ASSERT(offset == SH4Registers::r0); - m_assembler.movlRegMemr0(src, base); + RegisterID scr = claimScratch(); + m_assembler.loadConstant(address.offset, scr); + if (address.base == SH4Registers::r0) + m_assembler.movlRegMemr0(src, scr); + else { + m_assembler.addlRegReg(address.base, scr); + m_assembler.movlRegMem(src, scr); + } + releaseScratch(scr); } void store32(RegisterID src, RegisterID dst) @@ -686,11 +861,9 @@ public: void store32(TrustedImm32 imm, ImplicitAddress address) { RegisterID scr = claimScratch(); - RegisterID scr1 = claimScratch(); - m_assembler.loadConstant((imm.m_value), scr); - store32(scr, address.offset, address.base, scr1); + m_assembler.loadConstant(imm.m_value, scr); + store32(scr, address); releaseScratch(scr); - releaseScratch(scr1); } void store32(RegisterID src, BaseIndex address) @@ -709,9 +882,9 @@ public: { RegisterID scr = claimScratch(); RegisterID scr1 = claimScratch(); - m_assembler.loadConstant((imm.m_value), scr); + m_assembler.loadConstant(imm.m_value, scr); m_assembler.loadConstant(reinterpret_cast(address), scr1); - m_assembler.movlMemReg(scr, scr1); + m_assembler.movlRegMem(scr, scr1); releaseScratch(scr); releaseScratch(scr1); } @@ -720,7 +893,7 @@ public: { RegisterID scr = claimScratch(); m_assembler.loadConstant(reinterpret_cast(address), scr); - m_assembler.movlMemReg(src, scr); + m_assembler.movlRegMem(src, scr); releaseScratch(scr); } @@ -735,33 +908,99 @@ public: return label; } - DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest) + DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address) { RegisterID scr = claimScratch(); - DataLabelCompact label(this); + DataLabel32 label(this); m_assembler.loadConstantUnReusable(address.offset, scr); m_assembler.addlRegReg(address.base, scr); - m_assembler.movlMemReg(scr, dest); + m_assembler.movlRegMem(src, scr); releaseScratch(scr); return label; } - DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address) + DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest) { + DataLabelCompact dataLabel(this); + ASSERT(address.offset <= MaximumCompactPtrAlignedAddressOffset); + ASSERT(address.offset >= 0); + m_assembler.movlMemRegCompact(address.offset >> 2, address.base, dest); + return dataLabel; + } + + ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest) + { + ConvertibleLoadLabel result(this); + RegisterID scr = claimScratch(); - DataLabel32 label(this); - m_assembler.loadConstantUnReusable(address.offset, scr); + m_assembler.movImm8(address.offset, scr); m_assembler.addlRegReg(address.base, scr); - m_assembler.movlRegMem(src, scr); + m_assembler.movlMemReg(scr, dest); releaseScratch(scr); - return label; + + return result; } - // Floating-point operations + // Floating-point operations + + static bool supportsFloatingPoint() { return true; } + static bool supportsFloatingPointTruncate() { return true; } + static bool supportsFloatingPointSqrt() { return true; } + static bool supportsFloatingPointAbs() { return true; } + + void moveDoubleToInts(FPRegisterID src, RegisterID dest1, RegisterID dest2) + { + m_assembler.fldsfpul((FPRegisterID)(src + 1)); + m_assembler.stsfpulReg(dest1); + m_assembler.fldsfpul(src); + m_assembler.stsfpulReg(dest2); + } - bool supportsFloatingPoint() const { return true; } - bool supportsFloatingPointTruncate() const { return true; } - bool supportsFloatingPointSqrt() const { return true; } + void moveIntsToDouble(RegisterID src1, RegisterID src2, FPRegisterID dest, FPRegisterID scratch) + { + UNUSED_PARAM(scratch); + m_assembler.ldsrmfpul(src1); + m_assembler.fstsfpul((FPRegisterID)(dest + 1)); + m_assembler.ldsrmfpul(src2); + m_assembler.fstsfpul(dest); + } + + void moveDouble(FPRegisterID src, FPRegisterID dest) + { + if (src != dest) { + m_assembler.fmovsRegReg((FPRegisterID)(src + 1), (FPRegisterID)(dest + 1)); + m_assembler.fmovsRegReg(src, dest); + } + } + + void loadFloat(BaseIndex address, FPRegisterID dest) + { + RegisterID scr = claimScratch(); + + move(address.index, scr); + lshift32(TrustedImm32(address.scale), scr); + add32(address.base, scr); + if (address.offset) + add32(TrustedImm32(address.offset), scr); + + m_assembler.fmovsReadrm(scr, dest); + releaseScratch(scr); + } + + void loadDouble(BaseIndex address, FPRegisterID dest) + { + RegisterID scr = claimScratch(); + + move(address.index, scr); + lshift32(TrustedImm32(address.scale), scr); + add32(address.base, scr); + if (address.offset) + add32(TrustedImm32(address.offset), scr); + + m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1)); + m_assembler.fmovsReadrm(scr, dest); + releaseScratch(scr); + } void loadDouble(ImplicitAddress address, FPRegisterID dest) { @@ -791,22 +1030,67 @@ public: releaseScratch(scr); } + void storeFloat(FPRegisterID src, BaseIndex address) + { + RegisterID scr = claimScratch(); + + move(address.index, scr); + lshift32(TrustedImm32(address.scale), scr); + add32(address.base, scr); + if (address.offset) + add32(TrustedImm32(address.offset), scr); + + m_assembler.fmovsWriterm(src, scr); + + releaseScratch(scr); + } + void storeDouble(FPRegisterID src, ImplicitAddress address) { RegisterID scr = claimScratch(); - m_assembler.loadConstant(address.offset, scr); + m_assembler.loadConstant(address.offset + 8, scr); m_assembler.addlRegReg(address.base, scr); - m_assembler.fmovsWriterm((FPRegisterID)(src + 1), scr); - m_assembler.addlImm8r(4, scr); - m_assembler.fmovsWriterm(src, scr); + m_assembler.fmovsWriterndec(src, scr); + m_assembler.fmovsWriterndec((FPRegisterID)(src + 1), scr); + releaseScratch(scr); + } + + void storeDouble(FPRegisterID src, BaseIndex address) + { + RegisterID scr = claimScratch(); + + move(address.index, scr); + lshift32(TrustedImm32(address.scale), scr); + add32(address.base, scr); + add32(TrustedImm32(address.offset + 8), scr); + + m_assembler.fmovsWriterndec(src, scr); + m_assembler.fmovsWriterndec((FPRegisterID)(src + 1), scr); + releaseScratch(scr); } + void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) + { + if (op1 == dest) + addDouble(op2, dest); + else { + moveDouble(op2, dest); + addDouble(op1, dest); + } + } + void addDouble(FPRegisterID src, FPRegisterID dest) { m_assembler.daddRegReg(src, dest); } + void addDouble(AbsoluteAddress address, FPRegisterID dest) + { + loadDouble(address.m_ptr, fscratch); + addDouble(fscratch, dest); + } + void addDouble(Address address, FPRegisterID dest) { loadDouble(address, fscratch); @@ -840,6 +1124,18 @@ public: m_assembler.ddivRegReg(src, dest); } + void convertFloatToDouble(FPRegisterID src, FPRegisterID dst) + { + m_assembler.fldsfpul(src); + m_assembler.dcnvsd(dst); + } + + void convertDoubleToFloat(FPRegisterID src, FPRegisterID dst) + { + m_assembler.dcnvds(src); + m_assembler.fstsfpul(dst); + } + void convertInt32ToDouble(RegisterID src, FPRegisterID dest) { m_assembler.ldsrmfpul(src); @@ -849,7 +1145,7 @@ public: void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest) { RegisterID scr = claimScratch(); - m_assembler.loadConstant(reinterpret_cast(src.m_ptr), scr); + load32(src.m_ptr, scr); convertInt32ToDouble(scr, dest); releaseScratch(scr); } @@ -865,6 +1161,12 @@ public: void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest) { RegisterID scr = claimScratch(); + RegisterID scr1 = claimScratch(); + Jump m_jump; + JumpList end; + + if (dest != SH4Registers::r0) + move(SH4Registers::r0, scr1); move(address.index, scr); lshift32(TrustedImm32(address.scale), scr); @@ -873,13 +1175,40 @@ public: if (address.offset) add32(TrustedImm32(address.offset), scr); - RegisterID scr1 = claimScratch(); - load16(scr, scr1); - add32(TrustedImm32(2), scr); + m_assembler.ensureSpace(m_assembler.maxInstructionSize + 58, sizeof(uint32_t)); + move(scr, SH4Registers::r0); + m_assembler.testlImm8r(0x3, SH4Registers::r0); + m_jump = Jump(m_assembler.jne(), SH4Assembler::JumpNear); + + if (dest != SH4Registers::r0) + move(scr1, SH4Registers::r0); + + load32(scr, dest); + end.append(Jump(m_assembler.bra(), SH4Assembler::JumpNear)); + m_assembler.nop(); + m_jump.link(this); + m_assembler.testlImm8r(0x1, SH4Registers::r0); + + if (dest != SH4Registers::r0) + move(scr1, SH4Registers::r0); + + m_jump = Jump(m_assembler.jne(), SH4Assembler::JumpNear); + load16PostInc(scr, scr1); load16(scr, dest); - move(TrustedImm32(16), scr); - m_assembler.shllRegReg(dest, scr); + m_assembler.shllImm8r(16, dest); + or32(scr1, dest); + end.append(Jump(m_assembler.bra(), SH4Assembler::JumpNear)); + m_assembler.nop(); + m_jump.link(this); + load8PostInc(scr, scr1); + load16PostInc(scr, dest); + m_assembler.shllImm8r(8, dest); + or32(dest, scr1); + load8(scr, dest); + m_assembler.shllImm8r(8, dest); + m_assembler.shllImm8r(16, dest); or32(scr1, dest); + end.link(this); releaseScratch(scr); releaseScratch(scr1); @@ -921,20 +1250,16 @@ public: } if (cond == DoubleNotEqual) { - RegisterID scr = claimScratch(); - m_assembler.loadConstant(0x7fbfffff, scratchReg3); - m_assembler.dcnvds(right); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); + JumpList end; + m_assembler.dcmppeq(left, left); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 8); - m_assembler.dcnvds(left); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 4); + end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); + m_assembler.dcmppeq(right, right); + end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); m_assembler.dcmppeq(right, left); - releaseScratch(scr); - return branchFalse(); + Jump m_jump = branchFalse(); + end.link(this); + return m_jump; } if (cond == DoubleGreaterThan) { @@ -943,8 +1268,16 @@ public: } if (cond == DoubleGreaterThanOrEqual) { + JumpList end; + m_assembler.dcmppeq(left, left); + m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); + end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); + m_assembler.dcmppeq(right, right); + end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); m_assembler.dcmppgt(left, right); - return branchFalse(); + Jump m_jump = branchFalse(); + end.link(this); + return m_jump; } if (cond == DoubleLessThan) { @@ -953,109 +1286,72 @@ public: } if (cond == DoubleLessThanOrEqual) { + JumpList end; + m_assembler.dcmppeq(left, left); + m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); + end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); + m_assembler.dcmppeq(right, right); + end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); m_assembler.dcmppgt(right, left); - return branchFalse(); + Jump m_jump = branchFalse(); + end.link(this); + return m_jump; } if (cond == DoubleEqualOrUnordered) { - RegisterID scr = claimScratch(); - m_assembler.loadConstant(0x7fbfffff, scratchReg3); - m_assembler.dcnvds(right); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); + JumpList takeBranch; + m_assembler.dcmppeq(left, left); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 5); - m_assembler.dcnvds(left); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 1); + takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); + m_assembler.dcmppeq(right, right); + takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); m_assembler.dcmppeq(left, right); - releaseScratch(scr); - return branchTrue(); + Jump m_jump = Jump(m_assembler.je()); + takeBranch.link(this); + m_assembler.extraInstrForBranch(scratchReg3); + return m_jump; } if (cond == DoubleGreaterThanOrUnordered) { - RegisterID scr = claimScratch(); - m_assembler.loadConstant(0x7fbfffff, scratchReg3); - m_assembler.dcnvds(right); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); + JumpList takeBranch; + m_assembler.dcmppeq(left, left); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 5); - m_assembler.dcnvds(left); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 1); + takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); + m_assembler.dcmppeq(right, right); + takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); m_assembler.dcmppgt(right, left); - releaseScratch(scr); - return branchTrue(); + Jump m_jump = Jump(m_assembler.je()); + takeBranch.link(this); + m_assembler.extraInstrForBranch(scratchReg3); + return m_jump; } if (cond == DoubleGreaterThanOrEqualOrUnordered) { - RegisterID scr = claimScratch(); - m_assembler.loadConstant(0x7fbfffff, scratchReg3); - m_assembler.dcnvds(right); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 5); - m_assembler.dcnvds(left); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 1); m_assembler.dcmppgt(left, right); - releaseScratch(scr); return branchFalse(); } if (cond == DoubleLessThanOrUnordered) { - RegisterID scr = claimScratch(); - m_assembler.loadConstant(0x7fbfffff, scratchReg3); - m_assembler.dcnvds(right); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); + JumpList takeBranch; + m_assembler.dcmppeq(left, left); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 5); - m_assembler.dcnvds(left); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 1); + takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); + m_assembler.dcmppeq(right, right); + takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); m_assembler.dcmppgt(left, right); - releaseScratch(scr); - return branchTrue(); + Jump m_jump = Jump(m_assembler.je()); + takeBranch.link(this); + m_assembler.extraInstrForBranch(scratchReg3); + return m_jump; } if (cond == DoubleLessThanOrEqualOrUnordered) { - RegisterID scr = claimScratch(); - m_assembler.loadConstant(0x7fbfffff, scratchReg3); - m_assembler.dcnvds(right); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 5); - m_assembler.dcnvds(left); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 1); m_assembler.dcmppgt(right, left); - releaseScratch(scr); return branchFalse(); } ASSERT(cond == DoubleNotEqualOrUnordered); - RegisterID scr = claimScratch(); - m_assembler.loadConstant(0x7fbfffff, scratchReg3); - m_assembler.dcnvds(right); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 5); - m_assembler.dcnvds(left); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 1); m_assembler.dcmppeq(right, left); - releaseScratch(scr); return branchFalse(); } @@ -1063,9 +1359,7 @@ public: { m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t)); Jump m_jump = Jump(m_assembler.je()); - m_assembler.loadConstantUnReusable(0x0, scratchReg3); - m_assembler.nop(); - m_assembler.nop(); + m_assembler.extraInstrForBranch(scratchReg3); return m_jump; } @@ -1073,9 +1367,7 @@ public: { m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t)); Jump m_jump = Jump(m_assembler.jne()); - m_assembler.loadConstantUnReusable(0x0, scratchReg3); - m_assembler.nop(); - m_assembler.nop(); + m_assembler.extraInstrForBranch(scratchReg3); return m_jump; } @@ -1096,10 +1388,15 @@ public: void sqrtDouble(FPRegisterID src, FPRegisterID dest) { - if (dest != src) - m_assembler.dmovRegReg(src, dest); + moveDouble(src, dest); m_assembler.dsqrt(dest); } + + void absDouble(FPRegisterID src, FPRegisterID dest) + { + moveDouble(src, dest); + m_assembler.dabs(dest); + } Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) { @@ -1110,6 +1407,16 @@ public: return jmp; } + Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1)) + { + RegisterID addressTempRegister = claimScratch(); + move(TrustedImmPtr(address.m_ptr), addressTempRegister); + load8(Address(addressTempRegister), addressTempRegister); + Jump jmp = branchTest32(cond, addressTempRegister, mask); + releaseScratch(addressTempRegister); + return jmp; + } + void signExtend32ToPtr(RegisterID src, RegisterID dest) { if (src != dest) @@ -1125,7 +1432,16 @@ public: return jmp; } - Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest) + void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest) + { + RegisterID addressTempRegister = claimScratch(); + load8(left, addressTempRegister); + compare32(cond, addressTempRegister, right, dest); + releaseScratch(addressTempRegister); + } + + enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful }; + Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed) { m_assembler.ftrcdrmfpul(src); m_assembler.stsfpulReg(dest); @@ -1135,7 +1451,7 @@ public: m_assembler.branch(BT_OPCODE, 2); m_assembler.addlImm8r(1, scratchReg3); m_assembler.cmplRegReg(dest, scratchReg3, SH4Condition(Equal)); - return branchTrue(); + return (branchType == BranchIfTruncateFailed) ? branchTrue() : branchFalse(); } // Stack manipulation operations @@ -1150,27 +1466,6 @@ public: m_assembler.pushReg(src); } - void push(Address address) - { - if (!address.offset) { - push(address.base); - return; - } - - if ((address.offset < 0) || (address.offset >= 64)) { - RegisterID scr = claimScratch(); - m_assembler.loadConstant(address.offset, scr); - m_assembler.addlRegReg(address.base, scr); - m_assembler.movlMemReg(scr, SH4Registers::sp); - m_assembler.addlImm8r(-4, SH4Registers::sp); - releaseScratch(scr); - return; - } - - m_assembler.movlMemReg(address.offset >> 2, address.base, SH4Registers::sp); - m_assembler.addlImm8r(-4, SH4Registers::sp); - } - void push(TrustedImm32 imm) { RegisterID scr = claimScratch(); @@ -1188,14 +1483,16 @@ public: DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest) { + m_assembler.ensureSpace(m_assembler.maxInstructionSize, sizeof(uint32_t)); DataLabelPtr dataLabel(this); - m_assembler.loadConstantUnReusable(reinterpret_cast(initialValue.m_value), dest, true); + m_assembler.loadConstantUnReusable(reinterpret_cast(initialValue.m_value), dest); return dataLabel; } void move(RegisterID src, RegisterID dest) { - m_assembler.movlRegReg(src, dest); + if (src != dest) + m_assembler.movlRegReg(src, dest); } void move(TrustedImmPtr imm, RegisterID dest) @@ -1203,11 +1500,6 @@ public: m_assembler.loadConstant(imm.asIntptr(), dest); } - void extuw(RegisterID src, RegisterID dst) - { - m_assembler.extuw(src, dst); - } - void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest) { m_assembler.cmplRegReg(right, left, SH4Condition(cond)); @@ -1317,7 +1609,7 @@ public: { RegisterID scr = claimScratch(); - move(TrustedImm32(reinterpret_cast(left.m_ptr)), scr); + load32(left.m_ptr, scr); m_assembler.cmplRegReg(right, scr, SH4Condition(cond)); releaseScratch(scr); @@ -1340,25 +1632,9 @@ public: return branchTrue(); } - Jump branch16(RelationalCondition cond, BaseIndex left, RegisterID right) - { - RegisterID scr = claimScratch(); - - move(left.index, scr); - lshift32(TrustedImm32(left.scale), scr); - - if (left.offset) - add32(TrustedImm32(left.offset), scr); - add32(left.base, scr); - load16(scr, scr); - extuw(scr, scr); - releaseScratch(scr); - - return branch32(cond, scr, right); - } - - Jump branch16(RelationalCondition cond, BaseIndex left, TrustedImm32 right) + Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right) { + ASSERT(!(right.m_value & 0xFFFFFF00)); RegisterID scr = claimScratch(); move(left.index, scr); @@ -1367,8 +1643,7 @@ public: if (left.offset) add32(TrustedImm32(left.offset), scr); add32(left.base, scr); - load16(scr, scr); - extuw(scr, scr); + load8(scr, scr); RegisterID scr1 = claimScratch(); m_assembler.loadConstant(right.m_value, scr1); releaseScratch(scr); @@ -1383,7 +1658,7 @@ public: m_assembler.testlRegReg(reg, mask); - if (cond == NotEqual) + if (cond == NonZero) // NotEqual return branchFalse(); return branchTrue(); } @@ -1397,7 +1672,7 @@ public: else testlImm(mask.m_value, reg); - if (cond == NotEqual) + if (cond == NonZero) // NotEqual return branchFalse(); return branchTrue(); } @@ -1411,7 +1686,7 @@ public: else testImm(mask.m_value, address.offset, address.base); - if (cond == NotEqual) + if (cond == NonZero) // NotEqual return branchFalse(); return branchTrue(); } @@ -1432,7 +1707,7 @@ public: releaseScratch(scr); - if (cond == NotEqual) + if (cond == NonZero) // NotEqual return branchFalse(); return branchTrue(); } @@ -1468,7 +1743,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) { m_assembler.addvlRegReg(src, dest); @@ -1482,38 +1757,109 @@ public: return branchFalse(); } + if (cond == PositiveOrZero) { + m_assembler.addlRegReg(src, dest); + m_assembler.cmppz(dest); + return branchTrue(); + } + m_assembler.addlRegReg(src, dest); compare32(0, dest, Equal); - if (cond == NotEqual) + if (cond == NonZero) // NotEqual return branchFalse(); return branchTrue(); } Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest) { - ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero)); move(imm, scratchReg3); return branchAdd32(cond, scratchReg3, dest); } + Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero)); + + if (src != dest) + move(src, dest); + + if (cond == Overflow) { + move(imm, scratchReg3); + m_assembler.addvlRegReg(scratchReg3, dest); + return branchTrue(); + } + + add32(imm, dest); + + if (cond == Signed) { + m_assembler.cmppz(dest); + return branchFalse(); + } + + if (cond == PositiveOrZero) { + m_assembler.cmppz(dest); + return branchTrue(); + } + + compare32(0, dest, Equal); + + if (cond == NonZero) // NotEqual + return branchFalse(); + return branchTrue(); + } + + Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero)); + bool result; + + move(imm, scratchReg3); + RegisterID destptr = claimScratch(); + RegisterID destval = claimScratch(); + m_assembler.loadConstant(reinterpret_cast(dest.m_ptr), destptr); + m_assembler.movlMemReg(destptr, destval); + if (cond == Overflow) { + m_assembler.addvlRegReg(scratchReg3, destval); + result = true; + } else { + m_assembler.addlRegReg(scratchReg3, destval); + if (cond == Signed) { + m_assembler.cmppz(destval); + result = false; + } else if (cond == PositiveOrZero) { + m_assembler.cmppz(destval); + result = true; + } else { + m_assembler.movImm8(0, scratchReg3); + m_assembler.cmplRegReg(scratchReg3, destval, SH4Condition(cond)); + result = (cond == Zero); + } + } + m_assembler.movlRegMem(destval, destptr); + releaseScratch(destval); + releaseScratch(destptr); + return result ? branchTrue() : branchFalse(); + } + Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest) { ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); if (cond == Overflow) { - RegisterID scr1 = claimScratch(); - RegisterID scr = claimScratch(); - m_assembler.dmullRegReg(src, dest); + RegisterID scrsign = claimScratch(); + RegisterID msbres = claimScratch(); + m_assembler.dmulslRegReg(src, dest); m_assembler.stsmacl(dest); - m_assembler.movImm8(-31, scr); - m_assembler.movlRegReg(dest, scr1); - m_assembler.shaRegReg(scr1, scr); - m_assembler.stsmach(scr); - m_assembler.cmplRegReg(scr, scr1, SH4Condition(Equal)); - releaseScratch(scr1); - releaseScratch(scr); + m_assembler.cmppz(dest); + m_assembler.movt(scrsign); + m_assembler.addlImm8r(-1, scrsign); + m_assembler.stsmach(msbres); + m_assembler.cmplRegReg(msbres, scrsign, SH4Condition(Equal)); + releaseScratch(msbres); + releaseScratch(scrsign); return branchFalse(); } @@ -1527,7 +1873,7 @@ public: compare32(0, dest, static_cast(cond)); - if (cond == NotEqual) + if (cond == NonZero) // NotEqual return branchFalse(); return branchTrue(); } @@ -1562,7 +1908,7 @@ public: sub32(src, dest); compare32(0, dest, static_cast(cond)); - if (cond == NotEqual) + if (cond == NonZero) // NotEqual return branchFalse(); return branchTrue(); } @@ -1575,6 +1921,21 @@ public: return branchSub32(cond, scratchReg3, dest); } + Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest) + { + move(imm, scratchReg3); + if (src != dest) + move(src, dest); + return branchSub32(cond, scratchReg3, dest); + } + + Jump branchSub32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest) + { + if (src1 != dest) + move(src1, dest); + return branchSub32(cond, src2, dest); + } + Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest) { ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero)); @@ -1588,25 +1949,27 @@ public: or32(src, dest); compare32(0, dest, static_cast(cond)); - if (cond == NotEqual) + if (cond == NonZero) // NotEqual return branchFalse(); return branchTrue(); } - 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.ftrcdrmfpul(src); m_assembler.stsfpulReg(dest); convertInt32ToDouble(dest, fscratch); failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fscratch, src)); - if (dest == SH4Registers::r0) - m_assembler.cmpEqImmR0(0, dest); - else { - m_assembler.movImm8(0, scratchReg3); - m_assembler.cmplRegReg(scratchReg3, dest, SH4Condition(Equal)); + if (negZeroCheck) { + if (dest == SH4Registers::r0) + m_assembler.cmpEqImmR0(0, dest); + else { + m_assembler.movImm8(0, scratchReg3); + m_assembler.cmplRegReg(scratchReg3, dest, SH4Condition(Equal)); + } + failureCases.append(branchTrue()); } - failureCases.append(branchTrue()); } void neg32(RegisterID dst) @@ -1614,26 +1977,39 @@ public: m_assembler.neg(dst, dst); } - void not32(RegisterID dst) + void urshift32(RegisterID shiftamount, RegisterID dest) { - m_assembler.notlReg(dst, dst); + RegisterID shiftTmp = claimScratch(); + m_assembler.loadConstant(0x1f, shiftTmp); + m_assembler.andlRegReg(shiftamount, shiftTmp); + m_assembler.neg(shiftTmp, shiftTmp); + m_assembler.shldRegReg(dest, shiftTmp); + releaseScratch(shiftTmp); } - void urshift32(RegisterID shiftamount, RegisterID dest) + void urshift32(TrustedImm32 imm, RegisterID dest) { - compare32(32, shiftamount, Equal); - m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4); - m_assembler.branch(BT_OPCODE, 1); - m_assembler.neg(shiftamount, shiftamount); - m_assembler.shllRegReg(dest, shiftamount); + int immMasked = imm.m_value & 0x1f; + if (!immMasked) + return; + + if ((immMasked == 1) || (immMasked == 2) || (immMasked == 8) || (immMasked == 16)) { + m_assembler.shlrImm8r(immMasked, dest); + return; + } + + RegisterID shiftTmp = claimScratch(); + m_assembler.loadConstant(-immMasked, shiftTmp); + m_assembler.shldRegReg(dest, shiftTmp); + releaseScratch(shiftTmp); } - void urshift32(TrustedImm32 imm, RegisterID dest) + void urshift32(RegisterID src, TrustedImm32 shiftamount, RegisterID dest) { - RegisterID scr = claimScratch(); - m_assembler.loadConstant(-(imm.m_value), scr); - m_assembler.shaRegReg(dest, scr); - releaseScratch(scr); + if (src != dest) + move(src, dest); + + urshift32(shiftamount, dest); } Call call() @@ -1740,6 +2116,44 @@ public: m_assembler.nop(); } + static FunctionPtr readCallTarget(CodeLocationCall call) + { + return FunctionPtr(reinterpret_cast(SH4Assembler::readCallTarget(call.dataLocation()))); + } + + static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination) + { + SH4Assembler::replaceWithJump(instructionStart.dataLocation(), destination.dataLocation()); + } + + static ptrdiff_t maxJumpReplacementSize() + { + return SH4Assembler::maxJumpReplacementSize(); + } + + static bool canJumpReplacePatchableBranchPtrWithPatch() { return false; } + + static CodeLocationLabel startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label) + { + return label.labelAtOffset(0); + } + + static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID, void* initialValue) + { + SH4Assembler::revertJump(instructionStart.dataLocation(), initialValue); + } + + static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr) + { + UNREACHABLE_FOR_PLATFORM(); + return CodeLocationLabel(); + } + + static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel instructionStart, Address, void* initialValue) + { + UNREACHABLE_FOR_PLATFORM(); + } + protected: SH4Assembler::Condition SH4Condition(RelationalCondition cond) { @@ -1754,9 +2168,20 @@ private: friend class LinkBuffer; friend class RepatchBuffer; - static void linkCall(void*, Call, FunctionPtr); - static void repatchCall(CodeLocationCall, CodeLocationLabel); - static void repatchCall(CodeLocationCall, FunctionPtr); + static void linkCall(void* code, Call call, FunctionPtr function) + { + SH4Assembler::linkCall(code, call.m_label, function.value()); + } + + static void repatchCall(CodeLocationCall call, CodeLocationLabel destination) + { + SH4Assembler::relinkCall(call.dataLocation(), destination.executableAddress()); + } + + static void repatchCall(CodeLocationCall call, FunctionPtr destination) + { + SH4Assembler::relinkCall(call.dataLocation(), destination.executableAddress()); + } }; } // namespace JSC