Moved the GetTargetRelocation method from PPCMachOWriter to here. It uses
[oota-llvm.git] / lib / Target / PowerPC / PPCMachOWriterInfo.cpp
1 //===-- PPCMachOWriterInfo.cpp - Mach-O Writer Info for the PowerPC -------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Bill Wendling and is distributed under the
6 // University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements Mach-O writer information for the PowerPC backend.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "PPCMachOWriterInfo.h"
15 #include "PPCRelocations.h"
16 #include "PPCTargetMachine.h"
17 #include "llvm/CodeGen/MachORelocation.h"
18 #include "llvm/Support/OutputBuffer.h"
19 using namespace llvm;
20
21 PPCMachOWriterInfo::PPCMachOWriterInfo(const PPCTargetMachine &TM)
22   : TargetMachOWriterInfo(TM.getTargetData()->getPointerSizeInBits() == 64 ?
23                           HDR_CPU_TYPE_POWERPC64 :
24                           HDR_CPU_TYPE_POWERPC,
25                           HDR_CPU_SUBTYPE_POWERPC_ALL) {}
26 PPCMachOWriterInfo::~PPCMachOWriterInfo() {}
27
28
29 /// GetTargetRelocation - For the MachineRelocation MR, convert it to one or
30 /// more PowerPC MachORelocation(s), add the new relocations to the
31 /// MachOSection, and rewrite the instruction at the section offset if required
32 /// by that relocation type.
33 unsigned PPCMachOWriterInfo::GetTargetRelocation(MachineRelocation &MR,
34                                                  unsigned FromIdx,
35                                                  unsigned ToAddr,
36                                                  unsigned ToIdx,
37                                                  OutputBuffer &RelocOut,
38                                                  OutputBuffer &SecOut,
39                                                  bool Scattered) const {
40   unsigned NumRelocs = 0;
41   uint64_t Addr = 0;
42
43   // Keep track of whether or not this is an externally defined relocation.
44   bool     isExtern = false;
45
46   // Get the address of whatever it is we're relocating, if possible.
47   if (!isExtern)
48     Addr = (uintptr_t)MR.getResultPointer() + ToAddr;
49
50   switch ((PPC::RelocationType)MR.getRelocationType()) {
51   default: assert(0 && "Unknown PPC relocation type!");
52   case PPC::reloc_absolute_low_ix:
53     assert(0 && "Unhandled PPC relocation type!");
54     break;
55   case PPC::reloc_vanilla:
56     {
57       // FIXME: need to handle 64 bit vanilla relocs
58       MachORelocation VANILLA(MR.getMachineCodeOffset(), ToIdx,
59                               false, 2, isExtern,
60                               PPC_RELOC_VANILLA,
61                               Scattered, (intptr_t)MR.getResultPointer());
62       ++NumRelocs;
63
64       if (Scattered) {
65         RelocOut.outword(VANILLA.getPackedFields());
66         RelocOut.outword(VANILLA.getAddress());
67       } else {
68         RelocOut.outword(VANILLA.getAddress());
69         RelocOut.outword(VANILLA.getPackedFields());
70       }
71       
72       intptr_t SymbolOffset;
73
74       if (Scattered)
75         SymbolOffset = Addr + MR.getConstantVal();
76       else
77         SymbolOffset = Addr;
78
79       printf("vanilla fixup: sec_%x[%x] = %x\n", FromIdx,
80              unsigned(MR.getMachineCodeOffset()),
81              unsigned(SymbolOffset));
82       SecOut.fixword(SymbolOffset, MR.getMachineCodeOffset());
83     }
84     break;
85   case PPC::reloc_pcrel_bx:
86     {
87       Addr -= MR.getMachineCodeOffset();
88       Addr >>= 2;
89       Addr &= 0xFFFFFF;
90       Addr <<= 2;
91       Addr |= (SecOut[MR.getMachineCodeOffset()] << 24);
92
93       SecOut.fixword(Addr, MR.getMachineCodeOffset());
94       break;
95     }
96   case PPC::reloc_pcrel_bcx:
97     {
98       Addr -= MR.getMachineCodeOffset();
99       Addr &= 0xFFFC;
100
101       SecOut.fixhalf(Addr, MR.getMachineCodeOffset() + 2);
102       break;
103     }
104   case PPC::reloc_absolute_high:
105     {
106       MachORelocation HA16(MR.getMachineCodeOffset(), ToIdx, false, 2,
107                            isExtern, PPC_RELOC_HA16);
108       MachORelocation PAIR(Addr & 0xFFFF, 0xFFFFFF, false, 2, isExtern,
109                            PPC_RELOC_PAIR);
110       NumRelocs = 2;
111
112       RelocOut.outword(HA16.getRawAddress());
113       RelocOut.outword(HA16.getPackedFields());
114       RelocOut.outword(PAIR.getRawAddress());
115       RelocOut.outword(PAIR.getPackedFields());
116
117       Addr += 0x8000;
118
119       SecOut.fixhalf(Addr >> 16, MR.getMachineCodeOffset() + 2);
120       break;
121     }
122   case PPC::reloc_absolute_low:
123     {
124       MachORelocation LO16(MR.getMachineCodeOffset(), ToIdx, false, 2,
125                            isExtern, PPC_RELOC_LO16);
126       MachORelocation PAIR(Addr >> 16, 0xFFFFFF, false, 2, isExtern,
127                            PPC_RELOC_PAIR);
128       NumRelocs = 2;
129
130       RelocOut.outword(LO16.getRawAddress());
131       RelocOut.outword(LO16.getPackedFields());
132       RelocOut.outword(PAIR.getRawAddress());
133       RelocOut.outword(PAIR.getPackedFields());
134
135       SecOut.fixhalf(Addr, MR.getMachineCodeOffset() + 2);
136       break;
137     }
138   }
139
140   return NumRelocs;
141 }