• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "berberis/backend/x86_64/machine_ir.h"
18 #include "berberis/base/logging.h"
19 #include "berberis/guest_state/guest_addr.h"
20 
21 namespace berberis {
22 
23 namespace x86_64 {
24 
25 namespace {
26 
27 constexpr MachineInsnInfo kCallImmInfo = {
28     kMachineOpCallImm,
29     26,
30     {
31         {&kRAX, MachineRegKind::kDef},   {&kRDI, MachineRegKind::kDef},
32         {&kRSI, MachineRegKind::kDef},   {&kRDX, MachineRegKind::kDef},
33         {&kRCX, MachineRegKind::kDef},   {&kR8, MachineRegKind::kDef},
34         {&kR9, MachineRegKind::kDef},    {&kR10, MachineRegKind::kDef},
35         {&kR11, MachineRegKind::kDef},   {&kXMM0, MachineRegKind::kDef},
36         {&kXMM1, MachineRegKind::kDef},  {&kXMM2, MachineRegKind::kDef},
37         {&kXMM3, MachineRegKind::kDef},  {&kXMM4, MachineRegKind::kDef},
38         {&kXMM5, MachineRegKind::kDef},  {&kXMM6, MachineRegKind::kDef},
39         {&kXMM7, MachineRegKind::kDef},  {&kXMM8, MachineRegKind::kDef},
40         {&kXMM9, MachineRegKind::kDef},  {&kXMM10, MachineRegKind::kDef},
41         {&kXMM11, MachineRegKind::kDef}, {&kXMM12, MachineRegKind::kDef},
42         {&kXMM13, MachineRegKind::kDef}, {&kXMM14, MachineRegKind::kDef},
43         {&kXMM15, MachineRegKind::kDef}, {&kFLAGS, MachineRegKind::kDef},
44     },
45     kMachineInsnSideEffects};
46 
47 constexpr MachineInsnInfo kCallImmIntArgInfo = {kMachineOpCallImmArg,
48                                                 1,
49                                                 {{&kReg64, MachineRegKind::kUse}},
50                                                 // Is implicitly part of CallImm.
51                                                 kMachineInsnSideEffects};
52 
53 constexpr MachineInsnInfo kCallImmXmmArgInfo = {kMachineOpCallImmArg,
54                                                 1,
55                                                 {{&kXmmReg, MachineRegKind::kUse}},
56                                                 // Is implicitly part of CallImm.
57                                                 kMachineInsnSideEffects};
58 
59 constexpr MachineRegKind kPseudoCondBranchInfo[] = {{&kFLAGS, MachineRegKind::kUse}};
60 
61 constexpr MachineRegKind kPseudoIndirectJumpInfo[] = {{&kGeneralReg64, MachineRegKind::kUse}};
62 
63 constexpr MachineRegKind kPseudoCopyReg32Info[] = {{&kReg32, MachineRegKind::kDef},
64                                                    {&kReg32, MachineRegKind::kUse}};
65 
66 constexpr MachineRegKind kPseudoCopyReg64Info[] = {{&kReg64, MachineRegKind::kDef},
67                                                    {&kReg64, MachineRegKind::kUse}};
68 
69 constexpr MachineRegKind kPseudoCopyXmmInfo[] = {{&kXmmReg, MachineRegKind::kDef},
70                                                  {&kXmmReg, MachineRegKind::kUse}};
71 
72 constexpr MachineRegKind kPseudoDefXmmInfo[] = {{&kXmmReg, MachineRegKind::kDef}};
73 
74 constexpr MachineRegKind kPseudoDefReg64Info[] = {{&kReg64, MachineRegKind::kDef}};
75 
76 constexpr MachineRegKind kPseudoReadFlagsInfo[] = {{&kRAX, MachineRegKind::kDef},
77                                                    {&kFLAGS, MachineRegKind::kUse}};
78 
79 constexpr MachineRegKind kPseudoWriteFlagsInfo[] = {{&kRAX, MachineRegKind::kUseDef},
80                                                     {&kFLAGS, MachineRegKind::kDef}};
81 
82 }  // namespace
83 
CallImm(uint64_t imm)84 CallImm::CallImm(uint64_t imm) : MachineInsnX86_64(&kCallImmInfo) {
85   set_imm(imm);
86 }
87 
GetIntArgIndex(int i)88 int CallImm::GetIntArgIndex(int i) {
89   constexpr int kIntArgIndex[] = {
90       1,  // RDI
91       2,  // RSI
92       3,  // RDX
93       4,  // RCX
94       5,  // R8
95       6,  // R9
96   };
97 
98   CHECK_LT(static_cast<unsigned>(i), std::size(kIntArgIndex));
99   return kIntArgIndex[i];
100 }
101 
GetXmmArgIndex(int i)102 int CallImm::GetXmmArgIndex(int i) {
103   constexpr int kXmmArgIndex[] = {
104       9,   // XMM0
105       10,  // XMM1
106       11,  // XMM2
107       12,  // XMM3
108       13,  // XMM4
109       14,  // XMM5
110       15,  // XMM6
111       16,  // XMM7
112   };
113 
114   CHECK_LT(static_cast<unsigned>(i), std::size(kXmmArgIndex));
115   return kXmmArgIndex[i];
116 }
117 
GetFlagsArgIndex()118 int CallImm::GetFlagsArgIndex() {
119   return 25;  // FLAGS
120 }
121 
IntResultAt(int i) const122 MachineReg CallImm::IntResultAt(int i) const {
123   constexpr int kIntResultIndex[] = {
124       0,  // RAX
125       3,  // RDX
126   };
127 
128   CHECK_LT(static_cast<unsigned>(i), std::size(kIntResultIndex));
129   return RegAt(kIntResultIndex[i]);
130 }
131 
XmmResultAt(int i) const132 MachineReg CallImm::XmmResultAt(int i) const {
133   constexpr int kXmmResultIndex[] = {
134       9,   // XMM0
135       10,  // XMM1
136   };
137 
138   CHECK_LT(static_cast<unsigned>(i), std::size(kXmmResultIndex));
139   return RegAt(kXmmResultIndex[i]);
140 }
141 
CallImmArg(MachineReg arg,CallImm::RegType reg_type)142 CallImmArg::CallImmArg(MachineReg arg, CallImm::RegType reg_type)
143     : MachineInsnX86_64((reg_type == CallImm::kIntRegType) ? &kCallImmIntArgInfo
144                                                            : &kCallImmXmmArgInfo) {
145   SetRegAt(0, arg);
146 }
147 
148 #include "insn-inl_x86_64.h"  // NOLINT generated file!
149 
150 }  // namespace x86_64
151 
152 const MachineOpcode PseudoBranch::kOpcode = kMachineOpPseudoBranch;
153 using Assembler = x86_64::Assembler;
154 
PseudoBranch(const MachineBasicBlock * then_bb)155 PseudoBranch::PseudoBranch(const MachineBasicBlock* then_bb)
156     : MachineInsn(kMachineOpPseudoBranch, 0, nullptr, nullptr, kMachineInsnSideEffects),
157       then_bb_(then_bb) {}
158 
159 const MachineOpcode PseudoCondBranch::kOpcode = kMachineOpPseudoCondBranch;
160 
PseudoCondBranch(Assembler::Condition cond,const MachineBasicBlock * then_bb,const MachineBasicBlock * else_bb,MachineReg eflags)161 PseudoCondBranch::PseudoCondBranch(Assembler::Condition cond,
162                                    const MachineBasicBlock* then_bb,
163                                    const MachineBasicBlock* else_bb,
164                                    MachineReg eflags)
165     : MachineInsn(kMachineOpPseudoCondBranch,
166                   1,
167                   x86_64::kPseudoCondBranchInfo,
168                   &eflags_,
169                   kMachineInsnSideEffects),
170       cond_(cond),
171       then_bb_(then_bb),
172       else_bb_(else_bb),
173       eflags_(eflags) {}
174 
PseudoJump(GuestAddr target,Kind kind)175 PseudoJump::PseudoJump(GuestAddr target, Kind kind)
176     : MachineInsn(kMachineOpPseudoJump, 0, nullptr, nullptr, kMachineInsnSideEffects),
177       target_(target),
178       kind_(kind) {}
179 
PseudoIndirectJump(MachineReg src)180 PseudoIndirectJump::PseudoIndirectJump(MachineReg src)
181     : MachineInsn(kMachineOpPseudoIndirectJump,
182                   1,
183                   x86_64::kPseudoIndirectJumpInfo,
184                   &src_,
185                   kMachineInsnSideEffects),
186       src_(src) {}
187 
188 const MachineOpcode PseudoCopy::kOpcode = kMachineOpPseudoCopy;
189 
190 // Reg class of correct size is essential for current spill/reload code!!!
PseudoCopy(MachineReg dst,MachineReg src,int size)191 PseudoCopy::PseudoCopy(MachineReg dst, MachineReg src, int size)
192     : MachineInsn(kMachineOpPseudoCopy,
193                   2,
194                   size > 8   ? x86_64::kPseudoCopyXmmInfo
195                   : size > 4 ? x86_64::kPseudoCopyReg64Info
196                              : x86_64::kPseudoCopyReg32Info,
197                   regs_,
198                   kMachineInsnCopy),
199       regs_{dst, src} {}
200 
PseudoDefXReg(MachineReg reg)201 PseudoDefXReg::PseudoDefXReg(MachineReg reg)
202     : MachineInsn(kMachineOpPseudoDefXReg,
203                   1,
204                   x86_64::kPseudoDefXmmInfo,
205                   &reg_,
206                   kMachineInsnDefault),
207       reg_{reg} {}
208 
PseudoDefReg(MachineReg reg)209 PseudoDefReg::PseudoDefReg(MachineReg reg)
210     : MachineInsn(kMachineOpPseudoDefReg,
211                   1,
212                   x86_64::kPseudoDefReg64Info,
213                   &reg_,
214                   kMachineInsnDefault),
215       reg_{reg} {}
216 
217 const MachineOpcode PseudoReadFlags::kOpcode = kMachineOpPseudoReadFlags;
218 
PseudoReadFlags(WithOverflowEnum with_overflow,MachineReg dst,MachineReg flags)219 PseudoReadFlags::PseudoReadFlags(WithOverflowEnum with_overflow, MachineReg dst, MachineReg flags)
220     : MachineInsn(kMachineOpPseudoReadFlags,
221                   2,
222                   x86_64::kPseudoReadFlagsInfo,
223                   regs_,
224                   kMachineInsnDefault),
225       regs_{dst, flags},
226       with_overflow_(with_overflow == kWithOverflow) {}
227 
228 const MachineOpcode PseudoWriteFlags::kOpcode = kMachineOpPseudoWriteFlags;
229 
PseudoWriteFlags(MachineReg src,MachineReg flags)230 PseudoWriteFlags::PseudoWriteFlags(MachineReg src, MachineReg flags)
231     : MachineInsn(kMachineOpPseudoWriteFlags,
232                   2,
233                   x86_64::kPseudoWriteFlagsInfo,
234                   regs_,
235                   kMachineInsnDefault),
236       regs_{src, flags} {}
237 
238 }  // namespace berberis
239