2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
16 #ifndef incl_HPHP_VM_PHYSREG_H_
17 #define incl_HPHP_VM_PHYSREG_H_
19 #include "hphp/util/asm-x64.h"
20 #include "hphp/util/bitops.h"
22 namespace HPHP
{ namespace Transl
{
24 //////////////////////////////////////////////////////////////////////
27 * PhysReg represents a physical machine register. (Currently it only
28 * knows how to do GPRs.)
30 * To make it possible to use it with the assembler conveniently, it
31 * can be implicitly converted to and from Reg64. If you want to use
32 * it as a 32 bit register call r32(physReg).
34 * The implicit conversion to RegNumber is historical: it exists
35 * for backward-compatability with the old-style asm-x64.h api
36 * (e.g. store_reg##_disp_reg##).
39 explicit constexpr PhysReg(int n
= -1) : n(n
) {}
40 constexpr /* implicit */ PhysReg(Reg64 r
) : n(int(r
)) {}
41 explicit constexpr PhysReg(Reg32 r
) : n(int(RegNumber(r
))) {}
43 explicit constexpr PhysReg(RegNumber r
) : n(int(r
)) {}
45 constexpr /* implicit */ operator Reg64() const { return Reg64(n
); }
46 constexpr /* implicit */ operator RegNumber() const { return RegNumber(n
); }
48 explicit constexpr operator int() const { return n
; }
49 constexpr bool operator==(PhysReg r
) const { return n
== r
.n
; }
50 constexpr bool operator!=(PhysReg r
) const { return n
!= r
.n
; }
51 constexpr bool operator==(Reg64 r
) const { return Reg64(n
) == r
; }
52 constexpr bool operator!=(Reg64 r
) const { return Reg64(n
) != r
; }
53 constexpr bool operator==(Reg32 r
) const { return Reg32(n
) == r
; }
54 constexpr bool operator!=(Reg32 r
) const { return Reg32(n
) != r
; }
56 MemoryRef
operator[](intptr_t p
) const { return *(*this + p
); }
57 IndexedMemoryRef
operator[](Reg64 i
) const { return *(*this + i
); }
58 IndexedMemoryRef
operator[](ScaledIndex s
) const { return *(*this + s
); }
59 IndexedMemoryRef
operator[](ScaledIndexDisp s
) const {
60 return *(*this + s
.si
+ s
.disp
);
62 IndexedMemoryRef
operator[](DispReg dr
) const {
63 return *(*this + ScaledIndex(dr
.base
, 0x1) + dr
.disp
);
70 constexpr PhysReg InvalidReg
;
75 * This type is guaranteed to be a standard layout class with a
76 * trivial destructor. (This makes it usable in classes that are
79 * Zero-initializing this class is guaranteed to produce an empty set.
82 explicit RegSet() : m_bits(0) {}
83 explicit RegSet(PhysReg pr
) : m_bits(1 << int(pr
)) {}
86 RegSet
operator|(const RegSet
& rhs
) const {
88 retval
.m_bits
= m_bits
| rhs
.m_bits
;
92 RegSet
& operator|=(const RegSet
& rhs
) {
98 RegSet
operator&(const RegSet
& rhs
) const {
100 retval
.m_bits
= m_bits
& rhs
.m_bits
;
104 RegSet
& operator&=(const RegSet
& rhs
) {
105 m_bits
&= rhs
.m_bits
;
110 bool operator==(const RegSet
& rhs
) const {
111 return m_bits
== rhs
.m_bits
;
114 bool operator!=(const RegSet
& rhs
) const {
115 return !(*this == rhs
);
119 RegSet
operator-(const RegSet
& rhs
) const {
121 retval
.m_bits
= m_bits
& ~rhs
.m_bits
;
125 RegSet
& operator-=(const RegSet
& rhs
) {
135 return __builtin_popcount(m_bits
);
138 RegSet
& add(PhysReg pr
) {
139 if (pr
!= InvalidReg
) {
145 RegSet
& remove(PhysReg pr
) {
146 if (pr
!= InvalidReg
) {
147 m_bits
= m_bits
& ~(1 << int(pr
));
152 bool contains(PhysReg pr
) const {
153 return bool(m_bits
& (1 << int(pr
)));
161 * Can be used for iterating over present registers, in forward or
164 * while (regSet.findFirst(reg)) {
165 * regSet.remove(reg);
169 * while (regSet.findLast(reg)) {
170 * regSet.remove(reg);
174 * Consider forEach if you don't want to mutate your register set.
176 bool findFirst(PhysReg
& reg
) {
178 bool retval
= ffs64(m_bits
, out
);
180 assert(!retval
|| (int(reg
) >= 0 && int(reg
) < 64));
184 bool findLast(PhysReg
& reg
) {
186 bool retval
= fls64(m_bits
, out
);
188 assert(!retval
|| (int(reg
) >= 0 && int(reg
) < 64));
193 * Do something for each register in the set, in either forward or
198 void forEach(Fun f
) const {
201 while (cpy
.findFirst(r
)) {
208 void forEachR(Fun f
) const {
211 while (cpy
.findLast(r
)) {
221 static_assert(std::has_trivial_destructor
<RegSet
>::value
,
222 "RegSet must have a trivial destructor");
224 //////////////////////////////////////////////////////////////////////
226 struct PhysRegSaverParity
{
227 PhysRegSaverParity(int parity
, X64Assembler
& as
, RegSet regs
);
228 ~PhysRegSaverParity();
230 PhysRegSaverParity(const PhysRegSaverParity
&) = delete;
231 PhysRegSaverParity(PhysRegSaverParity
&&) = default;
232 PhysRegSaverParity
& operator=(const PhysRegSaverParity
&) = delete;
233 PhysRegSaverParity
& operator=(PhysRegSaverParity
&&) = default;
235 int rspAdjustment() const;
236 void bytesPushed(int64_t bytes
);
244 struct PhysRegSaverStub
: public PhysRegSaverParity
{
245 PhysRegSaverStub(X64Assembler
& as
, RegSet regs
)
246 : PhysRegSaverParity(0, as
, regs
)
250 struct PhysRegSaver
: public PhysRegSaverParity
{
251 PhysRegSaver(X64Assembler
& as
, RegSet regs
)
252 : PhysRegSaverParity(1, as
, regs
)
256 //////////////////////////////////////////////////////////////////////