1) Cmake support for PPC64LE builds
[dyninst.git] / proccontrol / src / loadLibrary / codegen-ppc.C
1 // PPC code generation routines for library injection
2
3 #include "loadLibrary/codegen.h"
4 #include "common/src/arch-power.h"
5 #include <iostream>
6
7
8 using namespace Dyninst;
9 using namespace NS_power;
10 using namespace ProcControlAPI;
11 using namespace std;
12
13 // User code can use up to 228 bytes under the stack pointer;
14 // we skip past this so that we don't mess things up. 
15 #define STACKSKIP 228
16
17 bool Codegen::generateCallPPC32(Address addr, const std::vector<Address> &args) {
18    // PPC32 on Linux is basically the same thing as x86; we do indirect because
19    // we can
20
21    // First, arguments
22    unsigned reg = 3;
23    for (auto iter = args.begin(); iter != args.end(); ++iter) {
24       generatePPC32(*iter, reg);
25       reg++;      
26    }
27
28    // And the call. We're going indirect, r0 -> LR -> call
29    generatePPC32(addr, 0);
30
31    instruction mtlr(MTLR0raw);
32    copyInt(mtlr.asInt());
33
34    instruction brl(BRLraw);
35    copyInt(brl.asInt());
36    return true;
37 }
38
39 bool Codegen::generateCallPPC64(Address addr, const std::vector<Address> &args) 
40 {
41    // PPC64 is a little more complicated, because we also need a TOC register value.
42    // That... is tricky. 
43    //
44    // Enter PPC64LE and ABIv2... The LittleEndian version of PPC64 requires ABIv2
45    // and PPC64 will run with both ABIv1 and ABIv2.
46    //
47    // The main implication for this code is that ABIv2 no longer uses function
48    // descriptors and no longer needs to be concerned with the TOC register.
49    // Instead, ABIv2-compliant callers need place the address of the global
50    // entry point to the function being called in r12 before jumping to the
51    // function's global entry point.  The called function will then be able to
52    // derive the TOC using the value stored in r12.
53    //
54    // ABIv1 compiant calls still needs to find and manipulate the TOC.
55
56    // First, arguments
57    unsigned reg = 3;
58    for (auto iter = args.begin(); iter != args.end(); ++iter) {
59       generatePPC64(*iter, reg);
60       reg++;      
61    }
62
63    if (abiversion_ < 2) {
64       if (toc_[addr] == 0) return false;
65       generatePPC64(toc_[addr], 2);
66       generatePPC64(addr, 0);
67       instruction mtlr(MTLR0raw); copyInt(mtlr.asInt());
68       instruction brl(BRLraw); copyInt(brl.asInt());
69    }
70    else {
71       generatePPC64(addr, 12);
72       instruction mtctr(MR12CTR); copyInt(mtctr.asInt());
73       instruction bctrl(BCTRLraw); copyInt(bctrl.asInt());
74    }
75
76    return true;
77 }
78
79 void Codegen::generatePPC32(Address val, unsigned reg) {
80
81       instruction insn;
82       insn.clear();
83       DFORM_OP_SET(insn, CAUop);
84       DFORM_RT_SET(insn, reg);
85       DFORM_RA_SET(insn, 0);
86       DFORM_SI_SET(insn, BOT_HI(val));
87       copyInt(insn.asInt());
88
89       insn.clear();
90       DFORM_OP_SET(insn, ORILop);
91       DFORM_RT_SET(insn, reg);
92       DFORM_RA_SET(insn, reg);
93       DFORM_SI_SET(insn, BOT_LO(val));
94       copyInt(insn.asInt());
95 }
96
97 void Codegen::generatePPC64(Address val, unsigned reg) {
98    generatePPC32((uint64_t)val >> 32, reg);
99
100    instruction insn;
101    insn.clear();
102    int shift = 32;
103    MDFORM_OP_SET( insn, RLDop);
104    MDFORM_RS_SET( insn, reg);
105    MDFORM_RA_SET( insn, reg);
106    MDFORM_SH_SET( insn, shift % 32);
107    MDFORM_MB_SET( insn, (63-shift) % 32);
108    MDFORM_MB2_SET(insn, (63-shift) / 32);
109    MDFORM_XO_SET( insn, ICRxop);
110    MDFORM_SH2_SET(insn, shift / 32);
111    MDFORM_RC_SET( insn, 0);
112    copyInt(insn.asInt());
113
114    // Can't just reuse the 32-bit generate, since CAUop zeroes the high bits...
115    // Instead, use ORIU/ORIL
116
117    insn.clear();
118    DFORM_OP_SET(insn, ORIUop);
119    DFORM_RT_SET(insn, reg);
120    DFORM_RA_SET(insn, reg);
121    DFORM_SI_SET(insn, BOT_HI(val));
122    copyInt(insn.asInt());
123    
124    insn.clear();
125    DFORM_OP_SET(insn, ORILop);
126    DFORM_RT_SET(insn, reg);
127    DFORM_RA_SET(insn, reg);
128    DFORM_SI_SET(insn, BOT_LO(val));
129    copyInt(insn.asInt());
130
131 }
132
133 bool Codegen::generatePreamblePPC32() {
134   instruction insn;
135   insn.clear();
136
137   DFORM_OP_SET(insn, CALop);
138   DFORM_RT_SET(insn, 1);
139   DFORM_RA_SET(insn, 1);
140   DFORM_SI_SET(insn, -STACKSKIP);
141   copyInt(insn.asInt());
142
143   return true;
144 }
145
146 bool Codegen::generatePreamblePPC64() {
147   return generatePreamblePPC32();
148 }