Nate Begeman | eb883af | 2006-08-23 21:08:52 +0000 | [diff] [blame] | 1 | //===-- PPCMachOWriter.cpp - Emit a Mach-O file for the PowerPC backend ---===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file was developed by Nate Begeman and is distributed under |
| 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file implements a Mach-O writer for the PowerPC backend. The public |
| 11 | // interface to this file is the createPPCMachOObjectWriterPass function. |
| 12 | // |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 15 | #include "PPCRelocations.h" |
Nate Begeman | eb883af | 2006-08-23 21:08:52 +0000 | [diff] [blame] | 16 | #include "PPCTargetMachine.h" |
| 17 | #include "llvm/PassManager.h" |
| 18 | #include "llvm/CodeGen/MachOWriter.h" |
Chris Lattner | a4f0b3a | 2006-08-27 12:54:02 +0000 | [diff] [blame] | 19 | #include "llvm/Support/Compiler.h" |
Nate Begeman | eb883af | 2006-08-23 21:08:52 +0000 | [diff] [blame] | 20 | using namespace llvm; |
| 21 | |
| 22 | namespace { |
| 23 | class VISIBILITY_HIDDEN PPCMachOWriter : public MachOWriter { |
| 24 | public: |
| 25 | PPCMachOWriter(std::ostream &O, PPCTargetMachine &TM) : MachOWriter(O, TM) { |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 26 | if (TM.getTargetData()->getPointerSizeInBits() == 64) { |
| 27 | Header.cputype = MachOHeader::CPU_TYPE_POWERPC64; |
| 28 | } else { |
| 29 | Header.cputype = MachOHeader::CPU_TYPE_POWERPC; |
| 30 | } |
Nate Begeman | eb883af | 2006-08-23 21:08:52 +0000 | [diff] [blame] | 31 | Header.cpusubtype = MachOHeader::CPU_SUBTYPE_POWERPC_ALL; |
| 32 | } |
| 33 | |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 34 | virtual void GetTargetRelocation(MachOSection &MOS, MachineRelocation &MR, |
| 35 | uint64_t Addr); |
| 36 | |
| 37 | // Constants for the relocation r_type field. |
| 38 | // see <mach-o/ppc/reloc.h> |
| 39 | enum { PPC_RELOC_VANILLA, // generic relocation |
| 40 | PPC_RELOC_PAIR, // the second relocation entry of a pair |
| 41 | PPC_RELOC_BR14, // 14 bit branch displacement to word address |
| 42 | PPC_RELOC_BR24, // 24 bit branch displacement to word address |
| 43 | PPC_RELOC_HI16, // a PAIR follows with the low 16 bits |
| 44 | PPC_RELOC_LO16, // a PAIR follows with the high 16 bits |
| 45 | PPC_RELOC_HA16, // a PAIR follows, which is sign extended to 32b |
| 46 | PPC_RELOC_LO14 // LO16 with low 2 bits implicitly zero |
| 47 | }; |
Nate Begeman | eb883af | 2006-08-23 21:08:52 +0000 | [diff] [blame] | 48 | }; |
| 49 | } |
| 50 | |
| 51 | /// addPPCMachOObjectWriterPass - Returns a pass that outputs the generated code |
| 52 | /// as a Mach-O object file. |
| 53 | /// |
Chris Lattner | 1911fd4 | 2006-09-04 04:14:57 +0000 | [diff] [blame] | 54 | void llvm::addPPCMachOObjectWriterPass(FunctionPassManager &FPM, |
Nate Begeman | eb883af | 2006-08-23 21:08:52 +0000 | [diff] [blame] | 55 | std::ostream &O, PPCTargetMachine &TM) { |
| 56 | PPCMachOWriter *EW = new PPCMachOWriter(O, TM); |
| 57 | FPM.add(EW); |
| 58 | FPM.add(createPPCCodeEmitterPass(TM, EW->getMachineCodeEmitter())); |
| 59 | } |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 60 | |
| 61 | /// GetTargetRelocation - For the MachineRelocation MR, convert it to one or |
| 62 | /// more PowerPC MachORelocation(s), add the new relocations to the |
| 63 | /// MachOSection, and rewrite the instruction at the section offset if required |
| 64 | /// by that relocation type. |
| 65 | void PPCMachOWriter::GetTargetRelocation(MachOSection &MOS, |
| 66 | MachineRelocation &MR, |
| 67 | uint64_t Addr) { |
| 68 | // Keep track of whether or not this is an externally defined relocation. |
| 69 | uint32_t index = MOS.Index; |
| 70 | bool isExtern = false; |
| 71 | |
| 72 | // Get the address of the instruction to rewrite |
| 73 | unsigned char *RelocPos = &MOS.SectionData[0] + MR.getMachineCodeOffset(); |
| 74 | |
| 75 | // Get the address of whatever it is we're relocating, if possible. |
| 76 | if (MR.isGlobalValue()) { |
| 77 | // determine whether or not its external and then figure out what section |
| 78 | // we put it in if it's a locally defined symbol. |
| 79 | } else if (MR.isString()) { |
| 80 | // lookup in global values? |
| 81 | } else { |
| 82 | assert((MR.isConstantPoolIndex() || MR.isJumpTableIndex()) && |
| 83 | "Unhandled MachineRelocation type!"); |
| 84 | } |
| 85 | |
| 86 | switch ((PPC::RelocationType)MR.getRelocationType()) { |
| 87 | default: assert(0 && "Unknown PPC relocation type!"); |
| 88 | case PPC::reloc_pcrel_bx: |
| 89 | case PPC::reloc_pcrel_bcx: |
| 90 | case PPC::reloc_absolute_low_ix: |
| 91 | assert(0 && "Unhandled PPC relocation type!"); |
| 92 | break; |
| 93 | case PPC::reloc_absolute_high: |
| 94 | { |
| 95 | MachORelocation HA16(MR.getMachineCodeOffset(), index, false, 2, isExtern, |
| 96 | PPC_RELOC_HA16); |
| 97 | MachORelocation PAIR(Addr & 0xFFFF, 0xFFFFFF, false, 2, isExtern, |
| 98 | PPC_RELOC_PAIR); |
| 99 | outword(RelocBuffer, HA16.r_address); |
| 100 | outword(RelocBuffer, HA16.getPackedFields()); |
| 101 | outword(RelocBuffer, PAIR.r_address); |
| 102 | outword(RelocBuffer, PAIR.getPackedFields()); |
| 103 | } |
| 104 | MOS.nreloc += 2; |
| 105 | Addr += 0x8000; |
| 106 | *(unsigned *)RelocPos &= 0xFFFF0000; |
| 107 | *(unsigned *)RelocPos |= ((Addr >> 16) & 0xFFFF); |
| 108 | break; |
| 109 | case PPC::reloc_absolute_low: |
| 110 | { |
| 111 | MachORelocation LO16(MR.getMachineCodeOffset(), index, false, 2, isExtern, |
| 112 | PPC_RELOC_LO16); |
| 113 | MachORelocation PAIR(Addr >> 16, 0xFFFFFF, false, 2, isExtern, |
| 114 | PPC_RELOC_PAIR); |
| 115 | outword(RelocBuffer, LO16.r_address); |
| 116 | outword(RelocBuffer, LO16.getPackedFields()); |
| 117 | outword(RelocBuffer, PAIR.r_address); |
| 118 | outword(RelocBuffer, PAIR.getPackedFields()); |
| 119 | } |
| 120 | MOS.nreloc += 2; |
| 121 | *(unsigned *)RelocPos &= 0xFFFF0000; |
| 122 | *(unsigned *)RelocPos |= (Addr & 0xFFFF); |
| 123 | break; |
| 124 | } |
| 125 | } |