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