diff options
Diffstat (limited to 'Source/JavaScriptCore/assembler/SH4Assembler.h')
-rw-r--r-- | Source/JavaScriptCore/assembler/SH4Assembler.h | 146 |
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); |