diff options
| author | Stephen Hines <srhines@google.com> | 2012-08-23 19:08:53 -0700 |
|---|---|---|
| committer | Stephen Hines <srhines@google.com> | 2012-08-23 19:08:53 -0700 |
| commit | 31675153bd2d7617db8cb6aeb58054934c7b9f73 (patch) | |
| tree | c1970fcebc736d4f731db0559a79a7ac5cb0f8bf /lib/Target/Mips/MipsJITInfo.cpp | |
| parent | 416bb6a168a9316547db6ce3909c515f70a84f52 (diff) | |
| parent | 75dd7f0c4a2b3fb9e9d4d5a0517591810c57ed92 (diff) | |
| download | external_llvm-31675153bd2d7617db8cb6aeb58054934c7b9f73.zip external_llvm-31675153bd2d7617db8cb6aeb58054934c7b9f73.tar.gz external_llvm-31675153bd2d7617db8cb6aeb58054934c7b9f73.tar.bz2 | |
Merge branch 'upstream' into merge_2
Conflicts:
lib/Target/ARM/ARMCodeEmitter.cpp
Change-Id: I6702d340c733e9721499b5d85b13b96ad9c14eb5
Diffstat (limited to 'lib/Target/Mips/MipsJITInfo.cpp')
| -rw-r--r-- | lib/Target/Mips/MipsJITInfo.cpp | 47 |
1 files changed, 46 insertions, 1 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 |
