summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/assembler/SH4Assembler.h
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@digia.com>2013-11-29 16:08:31 +0100
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2013-11-29 16:08:31 +0100
commitc242216d99f76443f3fe9160d15d78f06f7ff406 (patch)
treeb55b470c20bda9f9d9f9052fc5a02bccbabc4d56 /Source/JavaScriptCore/assembler/SH4Assembler.h
parentc617e2a25aca6cb95ab9d1a7cc55b363a12e861e (diff)
parent48c1382c33b77b002c1b295b9d2d6c4987526add (diff)
downloadqtwebkit-c242216d99f76443f3fe9160d15d78f06f7ff406.tar.gz
Merge remote-tracking branch 'origin/stable' into dev
Conflicts: .qmake.conf Change-Id: I9f566e48b319664f2783788572935da39749c91c
Diffstat (limited to 'Source/JavaScriptCore/assembler/SH4Assembler.h')
-rw-r--r--Source/JavaScriptCore/assembler/SH4Assembler.h146
1 files changed, 56 insertions, 90 deletions
diff --git a/Source/JavaScriptCore/assembler/SH4Assembler.h b/Source/JavaScriptCore/assembler/SH4Assembler.h
index 55f974a29..f9f70ad26 100644
--- a/Source/JavaScriptCore/assembler/SH4Assembler.h
+++ b/Source/JavaScriptCore/assembler/SH4Assembler.h
@@ -1241,19 +1241,19 @@ public:
{
RegisterID scr = claimScratch();
m_buffer.ensureSpace(maxInstructionSize + 4, sizeof(uint32_t));
- AssemblerLabel label = m_buffer.label();
loadConstantUnReusable(0x0, scr);
branch(BRAF_OPCODE, scr);
nop();
releaseScratch(scr);
- return label;
+ return m_buffer.label();
}
- void extraInstrForBranch(RegisterID dst)
+ AssemblerLabel extraInstrForBranch(RegisterID dst)
{
loadConstantUnReusable(0x0, dst);
+ branch(BRAF_OPCODE, dst);
nop();
- nop();
+ return m_buffer.label();
}
AssemblerLabel jmp(RegisterID dst)
@@ -1271,23 +1271,20 @@ public:
AssemblerLabel jne()
{
- AssemblerLabel label = m_buffer.label();
branch(BF_OPCODE, 0);
- return label;
+ return m_buffer.label();
}
AssemblerLabel je()
{
- AssemblerLabel label = m_buffer.label();
branch(BT_OPCODE, 0);
- return label;
+ return m_buffer.label();
}
AssemblerLabel bra()
{
- AssemblerLabel label = m_buffer.label();
branch(BRA_OPCODE, 0);
- return label;
+ return m_buffer.label();
}
void ret()
@@ -1361,33 +1358,16 @@ public:
{
ASSERT(from.isSet());
- uint16_t* instructionPtr = getInstructionPtr(code, from.m_offset);
- uint16_t instruction = *instructionPtr;
+ uint16_t* instructionPtr = getInstructionPtr(code, from.m_offset) - 3;
int offsetBits = (reinterpret_cast<uint32_t>(to) - reinterpret_cast<uint32_t>(code)) - from.m_offset;
- if (((instruction & 0xff00) == BT_OPCODE) || ((instruction & 0xff00) == BF_OPCODE)) {
- /* BT label ==> BF 2
- nop LDR reg
- nop braf @reg
- nop nop
- */
- offsetBits -= 8;
- instruction ^= 0x0202;
- *instructionPtr++ = instruction;
- changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
- instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00));
- *instructionPtr = instruction;
- printBlockInstr(instructionPtr - 2, from.m_offset, 3);
- return;
- }
-
- /* MOV #imm, reg => LDR reg
- braf @reg braf @reg
- nop nop
- */
+ /* MOV #imm, reg => LDR reg
+ braf @reg braf @reg
+ nop nop
+ */
ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE);
ASSERT((instructionPtr[1] & 0xf0ff) == BRAF_OPCODE);
- changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 6);
+ changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
printInstr(*instructionPtr, from.m_offset + 2);
}
@@ -1473,10 +1453,17 @@ public:
static void repatchCompact(void* where, int32_t value)
{
+ uint16_t* instructionPtr = reinterpret_cast<uint16_t*>(where);
ASSERT(value >= 0);
ASSERT(value <= 60);
- *reinterpret_cast<uint16_t*>(where) = ((*reinterpret_cast<uint16_t*>(where) & 0xfff0) | (value >> 2));
- cacheFlush(reinterpret_cast<uint16_t*>(where), sizeof(uint16_t));
+
+ // Handle the uncommon case where a flushConstantPool occurred in movlMemRegCompact.
+ if ((instructionPtr[0] & 0xf000) == BRA_OPCODE)
+ instructionPtr += (instructionPtr[0] & 0x0fff) + 2;
+
+ ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFRM_OPCODE);
+ instructionPtr[0] = (instructionPtr[0] & 0xfff0) | (value >> 2);
+ cacheFlush(instructionPtr, sizeof(uint16_t));
}
static void relinkCall(void* from, void* to)
@@ -1490,24 +1477,10 @@ public:
static void relinkJump(void* from, void* to)
{
uint16_t* instructionPtr = reinterpret_cast<uint16_t*> (from);
- uint16_t instruction = *instructionPtr;
- int32_t offsetBits = (reinterpret_cast<uint32_t>(to) - reinterpret_cast<uint32_t>(from));
-
- 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;
- }
-
+ instructionPtr -= 3;
+ ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE);
ASSERT((instructionPtr[1] & 0xf0ff) == BRAF_OPCODE);
- changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 6);
- printInstr(*instructionPtr, reinterpret_cast<uint32_t>(from));
+ changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(to) - reinterpret_cast<uint32_t>(from));
}
// Linking & patching
@@ -1520,9 +1493,13 @@ public:
static void replaceWithJump(void *instructionStart, void *to)
{
SH4Word* instruction = reinterpret_cast<SH4Word*>(instructionStart);
- intptr_t difference = reinterpret_cast<intptr_t>(to) - (reinterpret_cast<intptr_t>(instruction) + 2 * sizeof(SH4Word));
+ intptr_t difference = reinterpret_cast<intptr_t>(to) - (reinterpret_cast<intptr_t>(instruction) + 3 * sizeof(SH4Word));
if ((instruction[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE) {
+ // We have an entry in constant pool and we potentially replace a branchPtrWithPatch, so let's backup what would be the
+ // condition (CMP/xx and Bx opcodes) for later use in revertJumpReplacementToBranchPtrWithPatch before putting the jump.
+ instruction[4] = instruction[1];
+ instruction[5] = instruction[2];
instruction[1] = (BRAF_OPCODE | (instruction[0] & 0x0f00));
instruction[2] = NOP_OPCODE;
cacheFlush(&instruction[1], 2 * sizeof(SH4Word));
@@ -1533,22 +1510,32 @@ public:
cacheFlush(instruction, 3 * sizeof(SH4Word));
}
- changePCrelativeAddress(instruction[0] & 0x00ff, instruction, difference - 2);
+ changePCrelativeAddress(instruction[0] & 0x00ff, instruction, difference);
}
- static void revertJumpToMove(void* instructionStart, RegisterID rd, int imm)
+ static void revertJumpReplacementToBranchPtrWithPatch(void* instructionStart, RegisterID rd, int imm)
{
SH4Word *insn = reinterpret_cast<SH4Word*>(instructionStart);
ASSERT((insn[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE);
-
- if ((insn[1] & 0xf000) == CMPEQ_OPCODE) {
- insn[0] = getOpcodeGroup3(MOVL_READ_OFFPC_OPCODE, SH4Registers::r13, insn[0] & 0x00ff);
+ ASSERT((insn[0] & 0x00ff) != 1);
+
+ insn[0] = getOpcodeGroup3(MOVL_READ_OFFPC_OPCODE, SH4Registers::r13, insn[0] & 0x00ff);
+ if ((insn[1] & 0xf0ff) == BRAF_OPCODE) {
+ insn[1] = (insn[4] & 0xf00f) | (rd << 8) | (SH4Registers::r13 << 4); // Restore CMP/xx opcode.
+ insn[2] = insn[5];
+ ASSERT(((insn[2] & 0xff00) == BT_OPCODE) || ((insn[2] & 0xff00) == BF_OPCODE));
+ ASSERT((insn[3] & 0xf000) == MOVL_READ_OFFPC_OPCODE);
+ insn[4] = (BRAF_OPCODE | (insn[3] & 0x0f00));
+ insn[5] = NOP_OPCODE;
+ cacheFlush(insn, 6 * sizeof(SH4Word));
+ } else {
+ // The branchPtrWithPatch has already been restored, so we just patch the immediate value and ASSERT all is as expected.
+ ASSERT((insn[1] & 0xf000) == 0x3000);
insn[1] = (insn[1] & 0xf00f) | (rd << 8) | (SH4Registers::r13 << 4);
cacheFlush(insn, 2 * sizeof(SH4Word));
- } else {
- insn[1] = getOpcodeGroup6(BRA_OPCODE, 3);
- insn[2] = NOP_OPCODE;
- cacheFlush(&insn[1], 2 * sizeof(SH4Word));
+ ASSERT(((insn[2] & 0xff00) == BT_OPCODE) || ((insn[2] & 0xff00) == BF_OPCODE));
+ ASSERT((insn[3] & 0xf000) == MOVL_READ_OFFPC_OPCODE);
+ ASSERT(insn[5] == NOP_OPCODE);
}
changePCrelativeAddress(insn[0] & 0x00ff, insn, imm);
@@ -1559,12 +1546,12 @@ public:
ASSERT(to.isSet());
ASSERT(from.isSet());
- uint16_t* instructionPtr = getInstructionPtr(data(), from.m_offset);
- uint16_t instruction = *instructionPtr;
- int offsetBits;
+ uint16_t* instructionPtr = getInstructionPtr(data(), from.m_offset) - 1;
+ int offsetBits = (to.m_offset - from.m_offset);
if (type == JumpNear) {
- int offset = (codeSize() - from.m_offset) - 4;
+ uint16_t instruction = instructionPtr[0];
+ int offset = (offsetBits - 2);
ASSERT((((instruction == BT_OPCODE) || (instruction == BF_OPCODE)) && (offset >= -256) && (offset <= 254))
|| ((instruction == BRA_OPCODE) && (offset >= -4096) && (offset <= 4094)));
*instructionPtr++ = instruction | (offset >> 1);
@@ -1572,35 +1559,14 @@ public:
return;
}
- if (((instruction & 0xff00) == BT_OPCODE) || ((instruction & 0xff00) == BF_OPCODE)) {
- /* BT label => BF 2
- nop LDR reg
- nop braf @reg
- nop nop
- */
- offsetBits = (to.m_offset - from.m_offset) - 8;
- instruction ^= 0x0202;
- *instructionPtr++ = instruction;
- if ((*instructionPtr & 0xf000) == MOVIMM_OPCODE) {
- uint32_t* addr = getLdrImmAddressOnPool(instructionPtr, m_buffer.poolAddress());
- *addr = offsetBits;
- } else
- changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
- instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00));
- *instructionPtr = instruction;
- printBlockInstr(instructionPtr - 2, from.m_offset, 3);
- return;
- }
-
/* MOV # imm, reg => LDR reg
braf @reg braf @reg
nop nop
*/
- ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE);
- offsetBits = (to.m_offset - from.m_offset) - 6;
+ instructionPtr -= 2;
+ ASSERT((instructionPtr[1] & 0xf0ff) == BRAF_OPCODE);
- instruction = *instructionPtr;
- if ((instruction & 0xf000) == MOVIMM_OPCODE) {
+ if ((instructionPtr[0] & 0xf000) == MOVIMM_OPCODE) {
uint32_t* addr = getLdrImmAddressOnPool(instructionPtr, m_buffer.poolAddress());
*addr = offsetBits;
printInstr(*instructionPtr, from.m_offset + 2);