diff options
author | Akira Hatanaka <ahatanaka@mips.com> | 2012-08-01 02:29:24 +0000 |
---|---|---|
committer | Akira Hatanaka <ahatanaka@mips.com> | 2012-08-01 02:29:24 +0000 |
commit | c15ad8517719a525ac3b88b6c49b451160691eaa (patch) | |
tree | 1fad43aad8c8d4650e7375db843eb9f55a072de1 | |
parent | 12648bed2873fdf2120b54c5539026ff468283fb (diff) | |
download | external_llvm-c15ad8517719a525ac3b88b6c49b451160691eaa.zip external_llvm-c15ad8517719a525ac3b88b6c49b451160691eaa.tar.gz external_llvm-c15ad8517719a525ac3b88b6c49b451160691eaa.tar.bz2 |
Implement MipsJITInfo::replaceMachineCodeForFunction.
No new test case is added.
This patch makes test JITTest.FunctionIsRecompiledAndRelinked pass on mips
platform.
Patch by Petar Jovanovic.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161098 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/Mips/MipsJITInfo.cpp | 47 | ||||
-rw-r--r-- | unittests/ExecutionEngine/JIT/JITTest.cpp | 4 |
2 files changed, 48 insertions, 3 deletions
diff --git a/lib/Target/Mips/MipsJITInfo.cpp b/lib/Target/Mips/MipsJITInfo.cpp index 150bdbb..052046a 100644 --- a/lib/Target/Mips/MipsJITInfo.cpp +++ b/lib/Target/Mips/MipsJITInfo.cpp @@ -27,7 +27,52 @@ using namespace llvm; void MipsJITInfo::replaceMachineCodeForFunction(void *Old, void *New) { - report_fatal_error("MipsJITInfo::replaceMachineCodeForFunction"); + unsigned NewAddr = (intptr_t)New; + unsigned OldAddr = (intptr_t)Old; + const unsigned NopInstr = 0x0; + + // If the functions are in the same memory segment, insert PC-region branch. + if ((NewAddr & 0xF0000000) == ((OldAddr + 4) & 0xF0000000)) { + unsigned *OldInstruction = (unsigned *)Old; + *OldInstruction = 0x08000000; + unsigned JTargetAddr = NewAddr & 0x0FFFFFFC; + + JTargetAddr >>= 2; + *OldInstruction |= JTargetAddr; + + // Insert a NOP. + OldInstruction++; + *OldInstruction = NopInstr; + + sys::Memory::InvalidateInstructionCache(Old, 2 * 4); + } else { + // We need to clear hint bits from the instruction, in case it is 'jr ra'. + const unsigned HintMask = 0xFFFFF83F, ReturnSequence = 0x03e00008; + unsigned* CurrentInstr = (unsigned*)Old; + unsigned CurrInstrHintClear = (*CurrentInstr) & HintMask; + unsigned* NextInstr = CurrentInstr + 1; + unsigned NextInstrHintClear = (*NextInstr) & HintMask; + + // Do absolute jump if there are 2 or more instructions before return from + // the old function. + if ((CurrInstrHintClear != ReturnSequence) && + (NextInstrHintClear != ReturnSequence)) { + const unsigned LuiT0Instr = 0x3c080000, AddiuT0Instr = 0x25080000; + const unsigned JrT0Instr = 0x01000008; + // lui t0, high 16 bit of the NewAddr + (*(CurrentInstr++)) = LuiT0Instr | ((NewAddr & 0xffff0000) >> 16); + // addiu t0, t0, low 16 bit of the NewAddr + (*(CurrentInstr++)) = AddiuT0Instr | (NewAddr & 0x0000ffff); + // jr t0 + (*(CurrentInstr++)) = JrT0Instr; + (*CurrentInstr) = NopInstr; + + sys::Memory::InvalidateInstructionCache(Old, 4 * 4); + } else { + // Unsupported case + report_fatal_error("MipsJITInfo::replaceMachineCodeForFunction"); + } + } } /// JITCompilerFunction - This contains the address of the JIT function used to diff --git a/unittests/ExecutionEngine/JIT/JITTest.cpp b/unittests/ExecutionEngine/JIT/JITTest.cpp index 0fde6fc..89f7e8e 100644 --- a/unittests/ExecutionEngine/JIT/JITTest.cpp +++ b/unittests/ExecutionEngine/JIT/JITTest.cpp @@ -555,10 +555,10 @@ TEST_F(JITTest, FunctionPointersOutliveTheirCreator) { #endif } -// ARM and MIPS do not have an implementation +// ARM does not have an implementation // of replaceMachineCodeForFunction(), so recompileAndRelinkFunction // doesn't work. -#if !defined(__arm__) && !defined(__mips__) +#if !defined(__arm__) TEST_F(JITTest, FunctionIsRecompiledAndRelinked) { Function *F = Function::Create(TypeBuilder<int(void), false>::get(Context), GlobalValue::ExternalLinkage, "test", M); |