1 // PPC code generation routines for library injection
3 #include "loadLibrary/codegen.h"
4 #include "common/h/arch-power.h"
8 using namespace Dyninst;
9 using namespace NS_power;
10 using namespace ProcControlAPI;
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.
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
23 for (auto iter = args.begin(); iter != args.end(); ++iter) {
24 generatePPC32(*iter, reg);
28 // And the call. We're going indirect, r0 -> LR -> call
29 generatePPC32(addr, 0);
31 instruction mtlr(MTLR0raw);
32 copyInt(mtlr.asInt());
34 instruction brl(BRLraw);
39 bool Codegen::generateCallPPC64(Address addr, const std::vector<Address> &args) {
40 // PPC64 is a little more complicated, because we also need a TOC register value.
45 for (auto iter = args.begin(); iter != args.end(); ++iter) {
46 generatePPC64(*iter, reg);
50 if (toc_[addr] == 0) return false;
51 generatePPC64(toc_[addr], 2);
53 generatePPC64(addr, 0);
55 instruction mtlr(MTLR0raw);
56 copyInt(mtlr.asInt());
58 instruction brl(BRLraw);
63 void Codegen::generatePPC32(Address val, unsigned reg) {
67 DFORM_OP_SET(insn, CAUop);
68 DFORM_RT_SET(insn, reg);
69 DFORM_RA_SET(insn, 0);
70 DFORM_SI_SET(insn, BOT_HI(val));
71 copyInt(insn.asInt());
74 DFORM_OP_SET(insn, ORILop);
75 DFORM_RT_SET(insn, reg);
76 DFORM_RA_SET(insn, reg);
77 DFORM_SI_SET(insn, BOT_LO(val));
78 copyInt(insn.asInt());
81 void Codegen::generatePPC64(Address val, unsigned reg) {
82 generatePPC32(val >> 32, reg);
87 MDFORM_OP_SET( insn, RLDop);
88 MDFORM_RS_SET( insn, reg);
89 MDFORM_RA_SET( insn, reg);
90 MDFORM_SH_SET( insn, shift % 32);
91 MDFORM_MB_SET( insn, (63-shift) % 32);
92 MDFORM_MB2_SET(insn, (63-shift) / 32);
93 MDFORM_XO_SET( insn, ICRxop);
94 MDFORM_SH2_SET(insn, shift / 32);
95 MDFORM_RC_SET( insn, 0);
96 copyInt(insn.asInt());
98 // Can't just reuse the 32-bit generate, since CAUop zeroes the high bits...
99 // Instead, use ORIU/ORIL
102 DFORM_OP_SET(insn, ORIUop);
103 DFORM_RT_SET(insn, reg);
104 DFORM_RA_SET(insn, reg);
105 DFORM_SI_SET(insn, BOT_HI(val));
106 copyInt(insn.asInt());
109 DFORM_OP_SET(insn, ORILop);
110 DFORM_RT_SET(insn, reg);
111 DFORM_RA_SET(insn, reg);
112 DFORM_SI_SET(insn, BOT_LO(val));
113 copyInt(insn.asInt());
117 bool Codegen::generatePreamblePPC32() {
121 DFORM_OP_SET(insn, CALop);
122 DFORM_RT_SET(insn, 1);
123 DFORM_RA_SET(insn, 1);
124 DFORM_SI_SET(insn, -STACKSKIP);
125 copyInt(insn.asInt());
130 bool Codegen::generatePreamblePPC64() {
131 return generatePreamblePPC32();