1
2 /*---------------------------------------------------------------*/
3 /*--- begin host_generic_regs.h ---*/
4 /*---------------------------------------------------------------*/
5
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
10 Copyright (C) 2004-2012 OpenWorks LLP
11 info@open-works.net
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 02110-1301, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29
30 Neither the names of the U.S. Department of Energy nor the
31 University of California nor the names of its contributors may be
32 used to endorse or promote products derived from this software
33 without prior written permission.
34 */
35
36 #ifndef __VEX_HOST_GENERIC_REGS_H
37 #define __VEX_HOST_GENERIC_REGS_H
38
39 #include "libvex_basictypes.h"
40
41
42 /*---------------------------------------------------------*/
43 /*--- Representing HOST REGISTERS ---*/
44 /*---------------------------------------------------------*/
45
46 /* Host registers. Stuff to represent:
47
48 - The register number
49 - The register class
50 - Whether or not the register is a virtual reg.
51
52 Registers are a 32-bit Int, thusly:
53
54 bits 31-28 are the register class.
55 bits 27-23 are 0000b for real register, 0001b for virtual register
56 bits 23-0 register number
57
58 Note (importantly) that by arranging that the class field is never
59 0000b, any valid register looks like an extremely large int -- at
60 least 2^28 -- and so there is little chance of confusing it with an
61 integer array index in the register allocator.
62
63 Note further that since the class field is never 1111b, no valid
64 register can have the value INVALID_HREG.
65
66 There are currently 6 register classes:
67
68 int32 int64 float32 float64 simd64 simd128
69 */
70
71 typedef UInt HReg;
72
73 /* When extending this, do not use any value > 14 or < 0. */
74 /* HRegClass describes host register classes which the instruction
75 selectors can speak about. We would not expect all of them to be
76 available on any specific host. For example on x86, the available
77 classes are: Int32, Flt64, Vec128 only.
78
79 IMPORTANT NOTE: host_generic_reg_alloc2.c needs how much space is
80 needed to spill each class of register. It allocates the following
81 amount of space:
82
83 HRcInt32 64 bits
84 HRcInt64 64 bits
85 HRcFlt32 64 bits
86 HRcFlt64 128 bits (on x86 these are spilled by fstpt/fldt and
87 so won't fit in a 64-bit slot)
88 HRcVec64 64 bits
89 HRcVec128 128 bits
90
91 If you add another regclass, you must remember to update
92 host_generic_reg_alloc2.c accordingly.
93 */
94 typedef
95 enum {
96 HRcINVALID=1, /* NOT A VALID REGISTER CLASS */
97 HRcInt32=3, /* 32-bit int */
98 HRcInt64=4, /* 64-bit int */
99 HRcFlt32=5, /* 32-bit float */
100 HRcFlt64=6, /* 64-bit float */
101 HRcVec64=7, /* 64-bit SIMD */
102 HRcVec128=8 /* 128-bit SIMD */
103 }
104 HRegClass;
105
106 extern void ppHRegClass ( HRegClass );
107
108
109 /* Print an HReg in a generic (non-target-specific) way. */
110 extern void ppHReg ( HReg );
111
112 /* Construct/destruct. */
mkHReg(UInt regno,HRegClass rc,Bool virtual)113 static inline HReg mkHReg ( UInt regno, HRegClass rc, Bool virtual ) {
114 UInt r24 = regno & 0x00FFFFFF;
115 /* This is critical. The register number field may only
116 occupy 24 bits. */
117 if (r24 != regno)
118 vpanic("mkHReg: regno exceeds 2^24");
119 return regno | (((UInt)rc) << 28) | (virtual ? (1<<24) : 0);
120 }
121
hregClass(HReg r)122 static inline HRegClass hregClass ( HReg r ) {
123 UInt rc = r;
124 rc = (rc >> 28) & 0x0F;
125 vassert(rc >= HRcInt32 && rc <= HRcVec128);
126 return (HRegClass)rc;
127 }
128
hregNumber(HReg r)129 static inline UInt hregNumber ( HReg r ) {
130 return ((UInt)r) & 0x00FFFFFF;
131 }
132
hregIsVirtual(HReg r)133 static inline Bool hregIsVirtual ( HReg r ) {
134 return toBool(((UInt)r) & (1<<24));
135 }
136
137
138
139
140 #define INVALID_HREG ((HReg)0xFFFFFFFF)
141
142
143 /*---------------------------------------------------------*/
144 /*--- Recording register usage (for reg-alloc) ---*/
145 /*---------------------------------------------------------*/
146
147 typedef
148 enum { HRmRead, HRmWrite, HRmModify }
149 HRegMode;
150
151
152 /* A struct for recording the usage of registers in instructions.
153 This can get quite large, but we don't expect to allocate them
154 dynamically, so there's no problem.
155 */
156 #define N_HREG_USAGE 25
157
158 typedef
159 struct {
160 HReg hreg[N_HREG_USAGE];
161 HRegMode mode[N_HREG_USAGE];
162 Int n_used;
163 }
164 HRegUsage;
165
166 extern void ppHRegUsage ( HRegUsage* );
167
initHRegUsage(HRegUsage * tab)168 static inline void initHRegUsage ( HRegUsage* tab ) {
169 tab->n_used = 0;
170 }
171
172 /* Add a register to a usage table. Combine incoming read uses with
173 existing write uses into a modify use, and vice versa. Do not
174 create duplicate entries -- each reg should only be mentioned once.
175 */
176 extern void addHRegUse ( HRegUsage*, HRegMode, HReg );
177
178
179
180 /*---------------------------------------------------------*/
181 /*--- Indicating register remappings (for reg-alloc) ---*/
182 /*---------------------------------------------------------*/
183
184 /* Note that such maps can only map virtual regs to real regs.
185 addToHRegRenap will barf if given a pair not of that form. As a
186 result, no valid HRegRemap will bind a real reg to anything, and so
187 if lookupHRegMap is given a real reg, it returns it unchanged.
188 This is precisely the behaviour that the register allocator needs
189 to impose its decisions on the instructions it processes. */
190
191 #define N_HREG_REMAP 6
192
193 typedef
194 struct {
195 HReg orig [N_HREG_REMAP];
196 HReg replacement[N_HREG_REMAP];
197 Int n_used;
198 }
199 HRegRemap;
200
201 extern void ppHRegRemap ( HRegRemap* );
202 extern void initHRegRemap ( HRegRemap* );
203 extern void addToHRegRemap ( HRegRemap*, HReg, HReg );
204 extern HReg lookupHRegRemap ( HRegRemap*, HReg );
205
206
207 /*---------------------------------------------------------*/
208 /*--- Abstract instructions ---*/
209 /*---------------------------------------------------------*/
210
211 /* A type is needed to refer to pointers to instructions of any
212 target. Defining it like this means that HInstr* can stand in for
213 X86Instr*, ArmInstr*, etc. */
214
215 typedef void HInstr;
216
217
218 /* An expandable array of HInstr*'s. Handy for insn selection and
219 register allocation. n_vregs indicates the number of virtual
220 registers mentioned in the code, something that reg-alloc needs to
221 know. These are required to be numbered 0 .. n_vregs-1.
222 */
223 typedef
224 struct {
225 HInstr** arr;
226 Int arr_size;
227 Int arr_used;
228 Int n_vregs;
229 }
230 HInstrArray;
231
232 extern HInstrArray* newHInstrArray ( void );
233 extern void addHInstr ( HInstrArray*, HInstr* );
234
235
236 /*---------------------------------------------------------*/
237 /*--- Reg alloc: TODO: move somewhere else ---*/
238 /*---------------------------------------------------------*/
239
240 extern
241 HInstrArray* doRegisterAllocation (
242
243 /* Incoming virtual-registerised code. */
244 HInstrArray* instrs_in,
245
246 /* An array listing all the real registers the allocator may use,
247 in no particular order. */
248 HReg* available_real_regs,
249 Int n_available_real_regs,
250
251 /* Return True iff the given insn is a reg-reg move, in which
252 case also return the src and dst regs. */
253 Bool (*isMove) (HInstr*, HReg*, HReg*),
254
255 /* Get info about register usage in this insn. */
256 void (*getRegUsage) (HRegUsage*, HInstr*, Bool),
257
258 /* Apply a reg-reg mapping to an insn. */
259 void (*mapRegs) (HRegRemap*, HInstr*, Bool),
260
261 /* Return insn(s) to spill/restore a real reg to a spill slot
262 offset. And optionally a function to do direct reloads. */
263 void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool ),
264 void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool ),
265 HInstr* (*directReload) ( HInstr*, HReg, Short ),
266 Int guest_sizeB,
267
268 /* For debug printing only. */
269 void (*ppInstr) ( HInstr*, Bool ),
270 void (*ppReg) ( HReg ),
271
272 /* 32/64bit mode */
273 Bool mode64
274 );
275
276
277 #endif /* ndef __VEX_HOST_GENERIC_REGS_H */
278
279 /*---------------------------------------------------------------*/
280 /*--- host_generic_regs.h ---*/
281 /*---------------------------------------------------------------*/
282