typedef SH4Assembler::FPRegisterID FPRegisterID;
static const Scale ScalePtr = TimesFour;
- static const FPRegisterID fscratch = SH4Registers::fr10;
+ static const FPRegisterID fscratch = SH4Registers::dr10;
static const RegisterID stackPointerRegister = SH4Registers::sp;
static const RegisterID linkRegister = SH4Registers::pr;
static const RegisterID scratchReg3 = SH4Registers::r13;
static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value)
{
- return (value >= 0) && (value <= MaximumCompactPtrAlignedAddressOffset);
+ return (value >= 0) && (value <= MaximumCompactPtrAlignedAddressOffset) && (!(value & 3));
}
enum RelationalCondition {
void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
{
- if (src != dest)
- m_assembler.movlRegReg(src, dest);
+ move(src, dest);
add32(imm, dest);
}
void and32(TrustedImm32 imm, RegisterID dest)
{
+ if (!imm.m_value) {
+ m_assembler.movImm8(0, dest);
+ return;
+ }
+
if ((imm.m_value <= 255) && (imm.m_value >= 0) && (dest == SH4Registers::r0)) {
m_assembler.andlImm8r(imm.m_value, dest);
return;
void lshift32(RegisterID src, TrustedImm32 shiftamount, RegisterID dest)
{
- if (src != dest)
- move(src, dest);
-
+ move(src, dest);
lshift32(shiftamount, dest);
}
void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
{
- RegisterID scr = claimScratch();
- move(imm, scr);
- if (src != dest)
- move(src, dest);
- mul32(scr, dest);
- releaseScratch(scr);
+ if (src == dest) {
+ RegisterID immval = claimScratch();
+ move(imm, immval);
+ mul32(immval, dest);
+ releaseScratch(immval);
+ } else {
+ move(imm, dest);
+ mul32(src, dest);
+ }
}
void or32(RegisterID src, RegisterID dest)
void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
{
- if (src != dest)
- move(src, dest);
+ move(src, dest);
rshift32(imm, dest);
}
RegisterID result = claimScratch();
RegisterID scratchReg = claimScratch();
- m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
+ move(TrustedImmPtr(address.m_ptr), scratchReg);
m_assembler.movlMemReg(scratchReg, result);
if (m_assembler.isImmediate(-imm.m_value))
RegisterID result = claimScratch();
RegisterID scratchReg = claimScratch();
- m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
+ move(TrustedImmPtr(address.m_ptr), scratchReg);
m_assembler.movlMemReg(scratchReg, result);
if (m_assembler.isImmediate(imm.m_value))
RegisterID scr2 = claimScratch();
// Add 32-bit LSB first.
- m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scr1);
- m_assembler.movlMemReg(scr1, scr1); // scr1 = 32-bit LSB of int64 @ address
+ move(TrustedImmPtr(address.m_ptr), scratchReg3);
+ m_assembler.movlMemReg(scratchReg3, 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<uint32_t>(address.m_ptr), scr1);
- m_assembler.movlRegMem(scr2, scr1); // Update address with 32-bit LSB result.
+ m_assembler.movlRegMem(scr2, scratchReg3); // 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.addlImm8r(4, scratchReg3);
+ m_assembler.movlMemReg(scratchReg3, 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<uint32_t>(address.m_ptr) + 4, scr2);
- m_assembler.movlRegMem(scr1, scr2); // Update (address + 4) with 32-bit MSB result.
+ m_assembler.movlRegMem(scr1, scratchReg3); // Update (address + 4) with 32-bit MSB result.
releaseScratch(scr2);
releaseScratch(scr1);
return;
}
+ if (((cond == Equal) || (cond == NotEqual)) && !imm) {
+ m_assembler.testlRegReg(dst, dst);
+ return;
+ }
+
RegisterID scr = claimScratch();
m_assembler.loadConstant(imm, scr);
m_assembler.cmplRegReg(scr, dst, SH4Condition(cond));
void testImm(int imm, int offset, RegisterID base)
{
RegisterID scr = claimScratch();
- RegisterID scr1 = claimScratch();
+ load32(base, offset, scr);
- if ((offset < 0) || (offset >= 64)) {
- m_assembler.loadConstant(offset, scr);
- m_assembler.addlRegReg(base, scr);
- m_assembler.movlMemReg(scr, scr);
- } else if (offset)
- m_assembler.movlMemReg(offset >> 2, base, scr);
- else
- m_assembler.movlMemReg(base, scr);
- if (m_assembler.isImmediate(imm))
- m_assembler.movImm8(imm, scr1);
- else
- m_assembler.loadConstant(imm, scr1);
+ RegisterID scr1 = claimScratch();
+ move(TrustedImm32(imm), scr1);
m_assembler.testlRegReg(scr, scr1);
releaseScratch(scr);
void compare32(int imm, int offset, RegisterID base, RelationalCondition cond)
{
- if (!offset) {
- RegisterID scr = claimScratch();
- RegisterID scr1 = claimScratch();
- m_assembler.movlMemReg(base, scr);
- m_assembler.loadConstant(imm, scr1);
- m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
- releaseScratch(scr1);
- releaseScratch(scr);
- return;
- }
-
- if ((offset < 0) || (offset >= 64)) {
- RegisterID scr = claimScratch();
- RegisterID scr1 = claimScratch();
- m_assembler.loadConstant(offset, scr);
- m_assembler.addlRegReg(base, scr);
- m_assembler.movlMemReg(scr, scr);
- m_assembler.loadConstant(imm, scr1);
- m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
- releaseScratch(scr1);
- releaseScratch(scr);
- return;
- }
-
RegisterID scr = claimScratch();
+ load32(base, offset, scr);
+
RegisterID scr1 = claimScratch();
- m_assembler.movlMemReg(offset >> 2, base, scr);
- m_assembler.loadConstant(imm, scr1);
+ move(TrustedImm32(imm), scr1);
+
m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
+
releaseScratch(scr1);
releaseScratch(scr);
}
// Memory access operation
+ ALWAYS_INLINE void loadEffectiveAddress(BaseIndex address, RegisterID dest, int extraoffset = 0)
+ {
+ if (dest == address.base) {
+ RegisterID scaledIndex = claimScratch();
+ move(address.index, scaledIndex);
+ lshift32(TrustedImm32(address.scale), scaledIndex);
+ add32(scaledIndex, dest);
+ releaseScratch(scaledIndex);
+ } else {
+ move(address.index, dest);
+ lshift32(TrustedImm32(address.scale), dest);
+ add32(address.base, dest);
+ }
+
+ add32(TrustedImm32(address.offset + extraoffset), dest);
+ }
+
void load32(ImplicitAddress address, RegisterID dest)
{
load32(address.base, address.offset, dest);
void load32(const void* address, RegisterID dest)
{
- m_assembler.loadConstant(reinterpret_cast<uint32_t>(const_cast<void*>(address)), dest);
+ move(TrustedImmPtr(address), dest);
m_assembler.movlMemReg(dest, dest);
}
void load16Unaligned(BaseIndex address, RegisterID dest)
{
RegisterID scr = claimScratch();
- RegisterID scr1 = claimScratch();
-
- move(address.index, scr);
- lshift32(TrustedImm32(address.scale), scr);
- if (address.offset)
- add32(TrustedImm32(address.offset), scr);
+ loadEffectiveAddress(address, scr);
- add32(address.base, scr);
+ RegisterID scr1 = claimScratch();
load8PostInc(scr, scr1);
load8(scr, dest);
m_assembler.shllImm8r(8, dest);
move(address.index, scr);
lshift32(TrustedImm32(address.scale), scr);
-
- if (address.offset)
- add32(TrustedImm32(address.offset), scr);
+ add32(TrustedImm32(address.offset), scr);
if (address.base == SH4Registers::r0)
m_assembler.movwR0mr(scr, dest);
void store8(TrustedImm32 imm, void* address)
{
- RegisterID srcval = claimScratch();
+ ASSERT((imm.m_value >= -128) && (imm.m_value <= 127));
RegisterID dstptr = claimScratch();
+ move(TrustedImmPtr(address), dstptr);
+ RegisterID srcval = claimScratch();
move(imm, srcval);
- m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), dstptr);
m_assembler.movbRegMem(srcval, dstptr);
releaseScratch(dstptr);
releaseScratch(srcval);
RegisterID scr = claimScratch();
RegisterID scr1 = claimScratch();
m_assembler.loadConstant(imm.m_value, scr);
- m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr1);
+ move(TrustedImmPtr(address), scr1);
m_assembler.movlRegMem(scr, scr1);
releaseScratch(scr);
releaseScratch(scr1);
void store32(RegisterID src, void* address)
{
RegisterID scr = claimScratch();
- m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr);
+ move(TrustedImmPtr(address), scr);
m_assembler.movlRegMem(src, scr);
releaseScratch(scr);
}
DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
{
DataLabelCompact dataLabel(this);
- ASSERT(address.offset <= MaximumCompactPtrAlignedAddressOffset);
- ASSERT(address.offset >= 0);
+ ASSERT(isCompactPtrAlignedAddressOffset(address.offset));
m_assembler.movlMemRegCompact(address.offset >> 2, address.base, dest);
return dataLabel;
}
m_assembler.stsfpulReg(dest2);
}
- void moveIntsToDouble(RegisterID src1, RegisterID src2, FPRegisterID dest, FPRegisterID scratch)
+ void moveIntsToDouble(RegisterID src1, RegisterID src2, FPRegisterID dest, FPRegisterID)
{
- UNUSED_PARAM(scratch);
m_assembler.ldsrmfpul(src1);
m_assembler.fstsfpul((FPRegisterID)(dest + 1));
m_assembler.ldsrmfpul(src2);
{
RegisterID scr = claimScratch();
- move(address.index, scr);
- lshift32(TrustedImm32(address.scale), scr);
- add32(address.base, scr);
- if (address.offset)
- add32(TrustedImm32(address.offset), scr);
+ loadEffectiveAddress(address, scr);
m_assembler.fmovsReadrm(scr, dest);
releaseScratch(scr);
{
RegisterID scr = claimScratch();
- move(address.index, scr);
- lshift32(TrustedImm32(address.scale), scr);
- add32(address.base, scr);
- if (address.offset)
- add32(TrustedImm32(address.offset), scr);
+ loadEffectiveAddress(address, scr);
m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1));
m_assembler.fmovsReadrm(scr, dest);
void loadDouble(const void* address, FPRegisterID dest)
{
RegisterID scr = claimScratch();
- m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr);
+ move(TrustedImmPtr(address), scr);
m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1));
m_assembler.fmovsReadrm(scr, dest);
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);
-
+ loadEffectiveAddress(address, scr);
m_assembler.fmovsWriterm(src, scr);
-
releaseScratch(scr);
}
{
RegisterID scr = claimScratch();
- move(address.index, scr);
- lshift32(TrustedImm32(address.scale), scr);
- add32(address.base, scr);
- add32(TrustedImm32(address.offset + 8), scr);
+ loadEffectiveAddress(address, scr, 8);
m_assembler.fmovsWriterndec(src, scr);
m_assembler.fmovsWriterndec((FPRegisterID)(src + 1), scr);
if (dest != SH4Registers::r0)
move(SH4Registers::r0, scr1);
- move(address.index, scr);
- lshift32(TrustedImm32(address.scale), scr);
- add32(address.base, scr);
-
- if (address.offset)
- add32(TrustedImm32(address.offset), scr);
+ loadEffectiveAddress(address, scr);
m_assembler.ensureSpace(m_assembler.maxInstructionSize + 58, sizeof(uint32_t));
move(scr, SH4Registers::r0);
void signExtend32ToPtr(RegisterID src, RegisterID dest)
{
- if (src != dest)
- move(src, dest);
+ move(src, dest);
}
Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right)
enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful };
Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
+ {
+ Jump result;
+ truncateDoubleToInt32(src, dest);
+ RegisterID intscr = claimScratch();
+ m_assembler.loadConstant(0x7fffffff, intscr);
+ m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal));
+ m_assembler.ensureSpace(m_assembler.maxInstructionSize + 12, sizeof(uint32_t));
+ if (branchType == BranchIfTruncateFailed) {
+ m_assembler.branch(BT_OPCODE, 2);
+ m_assembler.addlImm8r(1, intscr);
+ m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal));
+ result = branchTrue();
+ } else {
+ Jump out = Jump(m_assembler.je(), SH4Assembler::JumpNear);
+ m_assembler.addlImm8r(1, intscr);
+ m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal));
+ result = branchFalse();
+ out.link(this);
+ }
+ releaseScratch(intscr);
+ return result;
+ }
+
+ void truncateDoubleToInt32(FPRegisterID src, RegisterID dest)
{
m_assembler.ftrcdrmfpul(src);
m_assembler.stsfpulReg(dest);
- m_assembler.loadConstant(0x7fffffff, scratchReg3);
- m_assembler.cmplRegReg(dest, scratchReg3, SH4Condition(Equal));
- m_assembler.ensureSpace(m_assembler.maxInstructionSize + 14, sizeof(uint32_t));
- m_assembler.branch(BT_OPCODE, 2);
- m_assembler.addlImm8r(1, scratchReg3);
- m_assembler.cmplRegReg(dest, scratchReg3, SH4Condition(Equal));
- return (branchType == BranchIfTruncateFailed) ? branchTrue() : branchFalse();
}
// Stack manipulation operations
{
RegisterID addressTempRegister = claimScratch();
- m_assembler.loadConstant(reinterpret_cast<uint32_t>(left.m_ptr), addressTempRegister);
+ move(TrustedImmPtr(left.m_ptr), addressTempRegister);
m_assembler.movlMemReg(addressTempRegister, addressTempRegister);
compare32(right.m_value, addressTempRegister, cond);
releaseScratch(addressTempRegister);
Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
{
ASSERT(!(right.m_value & 0xFFFFFF00));
- RegisterID scr = claimScratch();
+ RegisterID lefttmp = claimScratch();
- move(left.index, scr);
- lshift32(TrustedImm32(left.scale), scr);
+ loadEffectiveAddress(left, lefttmp);
- if (left.offset)
- add32(TrustedImm32(left.offset), scr);
- add32(left.base, scr);
- load8(scr, scr);
- RegisterID scr1 = claimScratch();
- m_assembler.loadConstant(right.m_value, scr1);
- releaseScratch(scr);
- releaseScratch(scr1);
+ load8(lefttmp, lefttmp);
+ RegisterID righttmp = claimScratch();
+ m_assembler.loadConstant(right.m_value, righttmp);
- return branch32(cond, scr, scr1);
+ Jump result = branch32(cond, lefttmp, righttmp);
+ releaseScratch(lefttmp);
+ releaseScratch(righttmp);
+ return result;
}
Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
{
+ ASSERT((cond == Zero) || (cond == NonZero));
+
RegisterID scr = claimScratch();
move(address.index, scr);
void jump(Address address)
{
RegisterID scr = claimScratch();
-
- if ((address.offset < 0) || (address.offset >= 64)) {
- m_assembler.loadConstant(address.offset, scr);
- m_assembler.addlRegReg(address.base, scr);
- m_assembler.movlMemReg(scr, scr);
- } else if (address.offset)
- m_assembler.movlMemReg(address.offset >> 2, address.base, scr);
- else
- m_assembler.movlMemReg(address.base, scr);
+ load32(address, scr);
m_assembler.jmpReg(scr);
-
releaseScratch(scr);
}
return branchTrue();
}
- if (cond == Signed) {
- m_assembler.addlRegReg(src, dest);
- // Check if dest is negative
- m_assembler.cmppz(dest);
- return branchFalse();
- }
+ m_assembler.addlRegReg(src, dest);
- if (cond == PositiveOrZero) {
- m_assembler.addlRegReg(src, dest);
+ if ((cond == Signed) || (cond == PositiveOrZero)) {
m_assembler.cmppz(dest);
- return branchTrue();
+ return (cond == Signed) ? branchFalse() : branchTrue();
}
- m_assembler.addlRegReg(src, dest);
compare32(0, dest, Equal);
-
- if (cond == NonZero) // NotEqual
- return branchFalse();
- return branchTrue();
+ return (cond == NonZero) ? branchFalse() : branchTrue();
}
Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
{
ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero));
- move(imm, scratchReg3);
- return branchAdd32(cond, scratchReg3, dest);
+ RegisterID immval = claimScratch();
+ move(imm, immval);
+ Jump result = branchAdd32(cond, immval, dest);
+ releaseScratch(immval);
+ return result;
}
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);
+ move(src, dest);
if (cond == Overflow) {
move(imm, scratchReg3);
add32(imm, dest);
- if (cond == Signed) {
+ if ((cond == Signed) || (cond == PositiveOrZero)) {
m_assembler.cmppz(dest);
- return branchFalse();
- }
-
- if (cond == PositiveOrZero) {
- m_assembler.cmppz(dest);
- return branchTrue();
+ return (cond == Signed) ? branchFalse() : branchTrue();
}
compare32(0, dest, Equal);
-
- if (cond == NonZero) // NotEqual
- return branchFalse();
- return branchTrue();
+ return (cond == NonZero) ? branchFalse() : branchTrue();
}
Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest)
move(imm, scratchReg3);
RegisterID destptr = claimScratch();
RegisterID destval = claimScratch();
- m_assembler.loadConstant(reinterpret_cast<uint32_t>(dest.m_ptr), destptr);
+ move(TrustedImmPtr(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) {
+ if ((cond == Signed) || (cond == PositiveOrZero)) {
m_assembler.cmppz(destval);
- result = false;
- } else if (cond == PositiveOrZero) {
- m_assembler.cmppz(destval);
- result = true;
+ result = (cond == PositiveOrZero);
} else {
- m_assembler.movImm8(0, scratchReg3);
- m_assembler.cmplRegReg(scratchReg3, destval, SH4Condition(cond));
- result = (cond == Zero);
+ m_assembler.testlRegReg(destval, destval);
+ result = (cond != NonZero);
}
}
m_assembler.movlRegMem(destval, destptr);
return branchFalse();
}
- m_assembler.imullRegReg(src, dest);
- m_assembler.stsmacl(dest);
+ mul32(src, dest);
+
if (cond == Signed) {
- // Check if dest is negative
m_assembler.cmppz(dest);
return branchFalse();
}
compare32(0, dest, static_cast<RelationalCondition>(cond));
-
- if (cond == NonZero) // NotEqual
- return branchFalse();
- return branchTrue();
+ return (cond == NonZero) ? branchFalse() : branchTrue();
}
Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
{
ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
- move(imm, scratchReg3);
- if (src != dest)
- move(src, dest);
+ if (src == dest) {
+ move(imm, scratchReg3);
+ return branchMul32(cond, scratchReg3, dest);
+ }
- return branchMul32(cond, scratchReg3, dest);
+ move(imm, dest);
+ return branchMul32(cond, src, dest);
}
Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
return branchTrue();
}
+ sub32(src, dest);
+
if (cond == Signed) {
- // Check if dest is negative
- m_assembler.sublRegReg(src, dest);
- compare32(0, dest, LessThan);
- return branchTrue();
+ m_assembler.cmppz(dest);
+ return branchFalse();
}
- sub32(src, dest);
compare32(0, dest, static_cast<RelationalCondition>(cond));
-
- if (cond == NonZero) // NotEqual
- return branchFalse();
- return branchTrue();
+ return (cond == NonZero) ? branchFalse() : branchTrue();
}
Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
{
ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
- move(imm, scratchReg3);
- return branchSub32(cond, scratchReg3, dest);
+ RegisterID immval = claimScratch();
+ move(imm, immval);
+ Jump result = branchSub32(cond, immval, dest);
+ releaseScratch(immval);
+ return result;
}
Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
{
- move(imm, scratchReg3);
- if (src != dest)
- move(src, dest);
- return branchSub32(cond, scratchReg3, dest);
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+
+ move(src, dest);
+ return branchSub32(cond, imm, dest);
}
Jump branchSub32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
{
- if (src1 != dest)
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+
+ if (src2 != dest) {
move(src1, dest);
- return branchSub32(cond, src2, dest);
+ return branchSub32(cond, src2, dest);
+ }
+
+ if (cond == Overflow) {
+ RegisterID tmpval = claimScratch();
+ move(src1, tmpval);
+ m_assembler.subvlRegReg(src2, tmpval);
+ move(tmpval, dest);
+ releaseScratch(tmpval);
+ return branchTrue();
+ }
+
+ RegisterID tmpval = claimScratch();
+ move(src1, tmpval);
+ sub32(src2, tmpval);
+ move(tmpval, dest);
+ releaseScratch(tmpval);
+
+ if (cond == Signed) {
+ m_assembler.cmppz(dest);
+ return branchFalse();
+ }
+
+ compare32(0, dest, static_cast<RelationalCondition>(cond));
+ return (cond == NonZero) ? branchFalse() : branchTrue();
}
Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
{
ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
+ or32(src, dest);
+
if (cond == Signed) {
- or32(src, dest);
- compare32(0, dest, static_cast<RelationalCondition>(LessThan));
- return branchTrue();
+ m_assembler.cmppz(dest);
+ return branchFalse();
}
- or32(src, dest);
compare32(0, dest, static_cast<RelationalCondition>(cond));
-
- if (cond == NonZero) // NotEqual
- return branchFalse();
- return branchTrue();
+ return (cond == NonZero) ? branchFalse() : branchTrue();
}
- void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp, bool negZeroCheck = true)
+ void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID, bool negZeroCheck = true)
{
- m_assembler.ftrcdrmfpul(src);
- m_assembler.stsfpulReg(dest);
+ truncateDoubleToInt32(src, dest);
convertInt32ToDouble(dest, fscratch);
failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fscratch, src));
- 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());
- }
+ if (negZeroCheck)
+ failureCases.append(branch32(Equal, dest, TrustedImm32(0)));
}
void neg32(RegisterID dst)
void urshift32(RegisterID src, TrustedImm32 shiftamount, RegisterID dest)
{
- if (src != dest)
- move(src, dest);
-
+ move(src, dest);
urshift32(shiftamount, dest);
}
void breakpoint()
{
+ m_assembler.ensureSpace(m_assembler.maxInstructionSize + 2);
m_assembler.bkpt();
m_assembler.nop();
}
return label.labelAtOffset(0);
}
- static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID, void* initialValue)
+ static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID rd, void* initialValue)
{
- SH4Assembler::revertJump(instructionStart.dataLocation(), initialValue);
+ SH4Assembler::revertJumpToMove(instructionStart.dataLocation(), rd, reinterpret_cast<int>(initialValue));
}
static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr)
};
SH4Assembler()
+ : m_claimscratchReg(0x0)
{
- m_claimscratchReg = 0x0;
}
// SH4 condition codes
oneShortOp(opc);
}
- void movlImm8r(int imm8, RegisterID dst)
- {
- ASSERT((imm8 <= 127) && (imm8 >= -128));
-
- uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, imm8);
- oneShortOp(opc);
- }
-
void loadConstant(uint32_t constant, RegisterID dst)
{
if (((int)constant <= 0x7f) && ((int)constant >= -0x80)) {
static void changePCrelativeAddress(int offset, uint16_t* instructionPtr, uint32_t newAddress)
{
+ ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE);
uint32_t address = (offset << 2) + ((reinterpret_cast<uint32_t>(instructionPtr) + 4) &(~0x3));
*reinterpret_cast<uint32_t*>(address) = newAddress;
}
static uint32_t readPCrelativeAddress(int offset, uint16_t* instructionPtr)
{
+ ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE);
uint32_t address = (offset << 2) + ((reinterpret_cast<uint32_t>(instructionPtr) + 4) &(~0x3));
return *reinterpret_cast<uint32_t*>(address);
}
braf @reg braf @reg
nop nop
*/
- ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE);
-
- offsetBits -= 4;
- if (offsetBits >= -4096 && offsetBits <= 4094) {
- *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1);
- *(++instructionPtr) = NOP_OPCODE;
- printBlockInstr(instructionPtr - 1, from.m_offset, 2);
- return;
- }
-
- changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2);
+ ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE);
+ ASSERT((instructionPtr[1] & 0xf0ff) == BRAF_OPCODE);
+ changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 6);
printInstr(*instructionPtr, from.m_offset + 2);
}
{
uint16_t* instructionPtr = getInstructionPtr(code, from.m_offset);
instructionPtr -= 3;
+ ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE);
changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(to));
}
static void linkPointer(void* code, AssemblerLabel where, void* value)
{
uint16_t* instructionPtr = getInstructionPtr(code, where.m_offset);
+ ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE);
changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(value));
}
ASSERT((((reinterpret_cast<uint32_t>(constPoolAddr) - reinterpret_cast<uint32_t>(loadAddr)) + index * 4)) < 1024);
int offset = reinterpret_cast<uint32_t>(constPoolAddr) + (index * 4) - ((reinterpret_cast<uint32_t>(instructionPtr) & ~0x03) + 4);
- instruction &=0xf00;
+ instruction &= 0x0f00;
instruction |= 0xd000;
offset &= 0x03ff;
instruction |= (offset >> 2);
static void repatchInt32(void* where, int32_t value)
{
uint16_t* instructionPtr = reinterpret_cast<uint16_t*>(where);
+ ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE);
changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, value);
}
{
uint16_t* instructionPtr = reinterpret_cast<uint16_t*>(from);
instructionPtr -= 3;
+ ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE);
changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(to));
}
if (((*instructionPtr & 0xff00) == BT_OPCODE) || ((*instructionPtr & 0xff00) == BF_OPCODE)) {
offsetBits -= 8;
instructionPtr++;
+ ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE);
changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00));
*instructionPtr = instruction;
printBlockInstr(instructionPtr, reinterpret_cast<uint32_t>(from) + 1, 3);
+ cacheFlush(instructionPtr, sizeof(SH4Word));
return;
}
- ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE);
- offsetBits -= 4;
- if (offsetBits >= -4096 && offsetBits <= 4094) {
- *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1);
- *(++instructionPtr) = NOP_OPCODE;
- printBlockInstr(instructionPtr - 2, reinterpret_cast<uint32_t>(from), 2);
- return;
- }
-
- changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2);
+ ASSERT((instructionPtr[1] & 0xf0ff) == BRAF_OPCODE);
+ changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 6);
printInstr(*instructionPtr, reinterpret_cast<uint32_t>(from));
}
{
SH4Word* instruction = reinterpret_cast<SH4Word*>(instructionStart);
intptr_t difference = reinterpret_cast<intptr_t>(to) - (reinterpret_cast<intptr_t>(instruction) + 2 * sizeof(SH4Word));
- int nbinst = 0;
- if ((difference >= -4096) && (difference <= 4094)) {
- instruction[0] = getOpcodeGroup6(BRA_OPCODE, difference >> 1);
- instruction[1] = NOP_OPCODE;
- cacheFlush(instruction, sizeof(SH4Word) * 2);
- return;
+ if ((instruction[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE) {
+ instruction[1] = (BRAF_OPCODE | (instruction[0] & 0x0f00));
+ instruction[2] = NOP_OPCODE;
+ cacheFlush(&instruction[1], 2 * sizeof(SH4Word));
+ } else {
+ instruction[0] = getOpcodeGroup3(MOVL_READ_OFFPC_OPCODE, SH4Registers::r13, 1);
+ instruction[1] = getOpcodeGroup2(BRAF_OPCODE, SH4Registers::r13);
+ instruction[2] = NOP_OPCODE;
+ cacheFlush(instruction, 3 * sizeof(SH4Word));
}
- instruction[nbinst++] = getOpcodeGroup3(MOVL_READ_OFFPC_OPCODE, scratchReg2, 1);
- instruction[nbinst++] = getOpcodeGroup2(JMP_OPCODE, scratchReg2);
- instruction[nbinst++] = NOP_OPCODE;
-
- if (!(reinterpret_cast<unsigned>(instruction) & 3))
- instruction[nbinst++] = NOP_OPCODE;
-
- instruction[nbinst++] = reinterpret_cast<unsigned>(to) & 0xffff;
- instruction[nbinst++] = reinterpret_cast<unsigned>(to) >> 16;
- cacheFlush(instruction, sizeof(SH4Word) * nbinst);
+ changePCrelativeAddress(instruction[0] & 0x00ff, instruction, difference - 2);
}
- static void revertJump(void* instructionStart, void *immptr)
+ static void revertJumpToMove(void* instructionStart, RegisterID rd, int imm)
{
SH4Word *insn = reinterpret_cast<SH4Word*>(instructionStart);
ASSERT((insn[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE);
- changePCrelativeAddress(insn[0] & 0x00ff, insn, reinterpret_cast<uint32_t>(immptr));
+
+ if ((insn[1] & 0xf000) == CMPEQ_OPCODE) {
+ insn[0] = getOpcodeGroup3(MOVL_READ_OFFPC_OPCODE, SH4Registers::r13, insn[0] & 0x00ff);
+ insn[1] = (insn[1] & 0xf00f) | (rd << 8) | (SH4Registers::r13 << 4);
+ cacheFlush(insn, 2 * sizeof(SH4Word));
+ changePCrelativeAddress(insn[0] & 0x00ff, insn, imm);
+ return;
+ }
+
+ if ((insn[0] & 0x00ff) == 1)
+ insn[1] = getOpcodeGroup6(BRA_OPCODE, 3);
+ else
+ insn[1] = NOP_OPCODE;
+
+ insn[2] = NOP_OPCODE;
+ cacheFlush(&insn[1], 2 * sizeof(SH4Word));
+
+ changePCrelativeAddress(insn[0] & 0x00ff, insn, imm);
}
void linkJump(AssemblerLabel from, AssemblerLabel to, JumpType type = JumpFar)
int offsetBits;
if (type == JumpNear) {
- ASSERT((instruction == BT_OPCODE) || (instruction == BF_OPCODE) || (instruction == BRA_OPCODE));
int offset = (codeSize() - from.m_offset) - 4;
+ ASSERT((((instruction == BT_OPCODE) || (instruction == BF_OPCODE)) && (offset >= -256) && (offset <= 254))
+ || ((instruction == BRA_OPCODE) && (offset >= -4096) && (offset <= 4094)));
*instructionPtr++ = instruction | (offset >> 1);
printInstr(*instructionPtr, from.m_offset + 2);
return;
offsetBits = (to.m_offset - from.m_offset) - 8;
instruction ^= 0x0202;
*instructionPtr++ = instruction;
- if ((*instructionPtr & 0xf000) == 0xe000) {
+ if ((*instructionPtr & 0xf000) == MOVIMM_OPCODE) {
uint32_t* addr = getLdrImmAddressOnPool(instructionPtr, m_buffer.poolAddress());
*addr = offsetBits;
} else
nop nop
*/
ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE);
- offsetBits = (to.m_offset - from.m_offset) - 4;
- if (offsetBits >= -4096 && offsetBits <= 4094) {
- *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1);
- *(++instructionPtr) = NOP_OPCODE;
- printBlockInstr(instructionPtr - 1, from.m_offset, 2);
- return;
- }
+ offsetBits = (to.m_offset - from.m_offset) - 6;
instruction = *instructionPtr;
- if ((instruction & 0xf000) == 0xe000) {
+ if ((instruction & 0xf000) == MOVIMM_OPCODE) {
uint32_t* addr = getLdrImmAddressOnPool(instructionPtr, m_buffer.poolAddress());
- *addr = offsetBits - 2;
+ *addr = offsetBits;
printInstr(*instructionPtr, from.m_offset + 2);
return;
}
- changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2);
+ ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE);
+ changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
printInstr(*instructionPtr, from.m_offset + 2);
}