blob: 8575191731d6b15542566ea48ebc1a3b6a150328 [file] [log] [blame]
sewardjc97096c2004-06-30 09:28:04 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
sewardj38a3f862005-01-13 15:06:51 +00004/*--- This file (h_generic_regs.h) is ---*/
sewardjdbcfae72005-08-02 11:14:04 +00005/*--- Copyright (C) OpenWorks LLP. All rights reserved. ---*/
sewardjc97096c2004-06-30 09:28:04 +00006/*--- ---*/
7/*---------------------------------------------------------------*/
8
sewardjf8ed9d82004-11-12 17:40:23 +00009/*
10 This file is part of LibVEX, a library for dynamic binary
11 instrumentation and translation.
12
sewardj7bd6ffe2005-08-03 16:07:36 +000013 Copyright (C) 2004-2005 OpenWorks LLP. All rights reserved.
sewardjf8ed9d82004-11-12 17:40:23 +000014
sewardj7bd6ffe2005-08-03 16:07:36 +000015 This library is made available under a dual licensing scheme.
sewardjf8ed9d82004-11-12 17:40:23 +000016
sewardj7bd6ffe2005-08-03 16:07:36 +000017 If you link LibVEX against other code all of which is itself
18 licensed under the GNU General Public License, version 2 dated June
19 1991 ("GPL v2"), then you may use LibVEX under the terms of the GPL
20 v2, as appearing in the file LICENSE.GPL. If the file LICENSE.GPL
21 is missing, you can obtain a copy of the GPL v2 from the Free
22 Software Foundation Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 02110-1301, USA.
24
25 For any other uses of LibVEX, you must first obtain a commercial
26 license from OpenWorks LLP. Please contact info@open-works.co.uk
27 for information about commercial licensing.
28
29 This software is provided by OpenWorks LLP "as is" and any express
30 or implied warranties, including, but not limited to, the implied
31 warranties of merchantability and fitness for a particular purpose
32 are disclaimed. In no event shall OpenWorks LLP be liable for any
33 direct, indirect, incidental, special, exemplary, or consequential
34 damages (including, but not limited to, procurement of substitute
35 goods or services; loss of use, data, or profits; or business
36 interruption) however caused and on any theory of liability,
37 whether in contract, strict liability, or tort (including
38 negligence or otherwise) arising in any way out of the use of this
39 software, even if advised of the possibility of such damage.
sewardjf8ed9d82004-11-12 17:40:23 +000040
41 Neither the names of the U.S. Department of Energy nor the
42 University of California nor the names of its contributors may be
43 used to endorse or promote products derived from this software
44 without prior written permission.
sewardjf8ed9d82004-11-12 17:40:23 +000045*/
46
sewardj38a3f862005-01-13 15:06:51 +000047#ifndef __H_GENERIC_REGS_H
48#define __H_GENERIC_REGS_H
sewardjc97096c2004-06-30 09:28:04 +000049
sewardj887a11a2004-07-05 17:26:47 +000050#include "libvex_basictypes.h"
sewardj35421a32004-07-05 13:12:34 +000051
sewardjc97096c2004-06-30 09:28:04 +000052
sewardj8bc26ee2004-07-01 18:30:32 +000053/*---------------------------------------------------------*/
54/*--- Representing HOST REGISTERS ---*/
55/*---------------------------------------------------------*/
56
sewardjc97096c2004-06-30 09:28:04 +000057/* Host registers. Stuff to represent:
58
59 - The register number
60 - The register class
61 - Whether or not the register is a virtual reg.
62
63 Registers are a 32-bit Int, thusly:
64
sewardjaf5a5222004-07-01 23:14:42 +000065 bits 31-28 are the register class.
66 bits 27-23 are 0000b for real register, 0001b for virtual register
67 bits 23-0 register number
68
69 Note (importantly) that by arranging that the class field is never
70 0000b, any valid register looks like an extremely large int -- at
71 least 2^28 -- and so there is little chance of confusing it with an
72 integer array index in the register allocator.
73
74 Note further that since the class field is never 1111b, no valid
75 register can have the value INVALID_HREG.
sewardjc97096c2004-06-30 09:28:04 +000076
sewardj6485f252005-07-04 09:21:19 +000077 There are currently 5 register classes:
sewardjc97096c2004-06-30 09:28:04 +000078
sewardj6485f252005-07-04 09:21:19 +000079 int32 int64 float64 simd64 simd128
sewardjc97096c2004-06-30 09:28:04 +000080*/
81
82typedef UInt HReg;
83
sewardjaf5a5222004-07-01 23:14:42 +000084/* When extending this, do not use any value > 14 or < 0. */
sewardj4a31b262004-12-01 02:24:44 +000085/* HRegClass describes host register classes which the instruction
86 selectors can speak about. We would not expect all of them to be
87 available on any specific host. For example on x86, the available
88 classes are: Int32, Flt64, Vec128 only.
sewardj1e6ad742004-12-02 16:16:11 +000089
90 IMPORTANT NOTE: Vec128 is the only >= 128-bit-sized class, and
91 reg_alloc2.c handles it specially when assigning spill slots. If
92 you add another 128-bit or larger regclass, you must remember to
93 update reg_alloc2.c accordingly.
sewardj4a31b262004-12-01 02:24:44 +000094*/
sewardjc97096c2004-06-30 09:28:04 +000095typedef
sewardj4a31b262004-12-01 02:24:44 +000096 enum {
97 HRcINVALID=1, /* NOT A VALID REGISTER CLASS */
98 HRcInt32=4, /* 32-bit int */
99 HRcInt64=5, /* 64-bit int */
100 HRcFlt64=6, /* 64-bit float */
101 HRcVec64=7, /* 64-bit SIMD */
102 HRcVec128=8 /* 128-bit SIMD */
sewardjb3d4ce72004-07-02 07:09:23 +0000103 }
sewardjc97096c2004-06-30 09:28:04 +0000104 HRegClass;
105
sewardj35421a32004-07-05 13:12:34 +0000106extern void ppHRegClass ( HRegClass );
sewardjaf5a5222004-07-01 23:14:42 +0000107
sewardjc97096c2004-06-30 09:28:04 +0000108
109/* Print an HReg in a generic (non-target-specific) way. */
sewardj35421a32004-07-05 13:12:34 +0000110extern void ppHReg ( HReg );
sewardjc97096c2004-06-30 09:28:04 +0000111
112/* Construct/destruct. */
sewardj666fbac2004-10-14 10:42:15 +0000113static 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}
sewardjc97096c2004-06-30 09:28:04 +0000121
sewardj1f40a0a2004-07-21 12:28:07 +0000122static inline HRegClass hregClass ( HReg r ) {
123 UInt rc = r;
124 rc = (rc >> 28) & 0x0F;
sewardjb5749b02004-12-29 19:23:49 +0000125 vassert(rc >= HRcInt32 && rc <= HRcVec128);
sewardj1f40a0a2004-07-21 12:28:07 +0000126 return (HRegClass)rc;
127}
128
129static inline UInt hregNumber ( HReg r ) {
130 return ((UInt)r) & 0x00FFFFFF;
131}
132
133static inline Bool hregIsVirtual ( HReg r ) {
sewardj58277842005-02-07 03:11:17 +0000134 return toBool(((UInt)r) & (1<<24));
sewardj1f40a0a2004-07-21 12:28:07 +0000135}
136
137
sewardjc97096c2004-06-30 09:28:04 +0000138
sewardjaf5a5222004-07-01 23:14:42 +0000139
sewardj8bc26ee2004-07-01 18:30:32 +0000140#define INVALID_HREG ((HReg)0xFFFFFFFF)
141
142
143/*---------------------------------------------------------*/
144/*--- Recording register usage (for reg-alloc) ---*/
145/*---------------------------------------------------------*/
146
147typedef
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*/
sewardj1001dc42005-02-21 08:25:55 +0000156#define N_HREG_USAGE 25
sewardj8bc26ee2004-07-01 18:30:32 +0000157
158typedef
159 struct {
160 HReg hreg[N_HREG_USAGE];
161 HRegMode mode[N_HREG_USAGE];
162 Int n_used;
163 }
164 HRegUsage;
165
sewardj35421a32004-07-05 13:12:34 +0000166extern void ppHRegUsage ( HRegUsage* );
sewardj8bc26ee2004-07-01 18:30:32 +0000167
sewardj666fbac2004-10-14 10:42:15 +0000168static inline void initHRegUsage ( HRegUsage* tab ) {
169 tab->n_used = 0;
170}
sewardj8bc26ee2004-07-01 18:30:32 +0000171
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*/
sewardj53f85a92004-07-02 13:45:17 +0000176extern void addHRegUse ( HRegUsage*, HRegMode, HReg );
sewardj8bc26ee2004-07-01 18:30:32 +0000177
178
179
180/*---------------------------------------------------------*/
181/*--- Indicating register remappings (for reg-alloc) ---*/
182/*---------------------------------------------------------*/
183
sewardj0ec33252004-07-03 13:30:00 +0000184/* 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
sewardj40c80262006-02-08 19:30:46 +0000191#define N_HREG_REMAP 5
sewardj8bc26ee2004-07-01 18:30:32 +0000192
193typedef
194 struct {
195 HReg orig [N_HREG_REMAP];
196 HReg replacement[N_HREG_REMAP];
197 Int n_used;
198 }
199 HRegRemap;
200
sewardj35421a32004-07-05 13:12:34 +0000201extern void ppHRegRemap ( HRegRemap* );
sewardj8bc26ee2004-07-01 18:30:32 +0000202extern void initHRegRemap ( HRegRemap* );
203extern void addToHRegRemap ( HRegRemap*, HReg, HReg );
204extern HReg lookupHRegRemap ( HRegRemap*, HReg );
205
sewardjc97096c2004-06-30 09:28:04 +0000206
sewardjaf5a5222004-07-01 23:14:42 +0000207/*---------------------------------------------------------*/
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
215typedef void HInstr;
216
217
sewardj194d54a2004-07-03 19:08:18 +0000218/* 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*/
sewardj2cd80dc2004-07-02 15:20:40 +0000223typedef
224 struct {
225 HInstr** arr;
226 Int arr_size;
227 Int arr_used;
sewardj194d54a2004-07-03 19:08:18 +0000228 Int n_vregs;
sewardj2cd80dc2004-07-02 15:20:40 +0000229 }
230 HInstrArray;
231
232extern HInstrArray* newHInstrArray ( void );
sewardj2cd80dc2004-07-02 15:20:40 +0000233extern void addHInstr ( HInstrArray*, HInstr* );
234
sewardjaf5a5222004-07-01 23:14:42 +0000235
sewardj2cd80dc2004-07-02 15:20:40 +0000236/*---------------------------------------------------------*/
237/*--- Reg alloc: TODO: move somewhere else ---*/
238/*---------------------------------------------------------*/
239
240extern
241HInstrArray* doRegisterAllocation (
242
243 /* Incoming virtual-registerised code. */
244 HInstrArray* instrs_in,
sewardj2cd80dc2004-07-02 15:20:40 +0000245
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. */
cerion92b64362005-12-13 12:02:26 +0000256 void (*getRegUsage) (HRegUsage*, HInstr*, Bool),
sewardj2cd80dc2004-07-02 15:20:40 +0000257
258 /* Apply a reg-reg mapping to an insn. */
cerion92b64362005-12-13 12:02:26 +0000259 void (*mapRegs) (HRegRemap*, HInstr*, Bool),
sewardj2cd80dc2004-07-02 15:20:40 +0000260
261 /* Return an insn to spill/restore a real reg to a spill slot
262 offset. */
cerion92b64362005-12-13 12:02:26 +0000263 HInstr* (*genSpill) ( HReg, Int, Bool ),
264 HInstr* (*genReload) ( HReg, Int, Bool ),
sewardj81ec4182004-10-25 23:15:52 +0000265 Int guest_sizeB,
sewardj2b515872004-07-05 20:50:45 +0000266
267 /* For debug printing only. */
cerion92b64362005-12-13 12:02:26 +0000268 void (*ppInstr) ( HInstr*, Bool ),
269 void (*ppReg) ( HReg ),
270
271 /* 32/64bit mode */
272 Bool mode64
sewardj2cd80dc2004-07-02 15:20:40 +0000273);
274
275
sewardj38a3f862005-01-13 15:06:51 +0000276#endif /* ndef __H_GENERIC_REGS_H */
sewardj2cd80dc2004-07-02 15:20:40 +0000277
sewardj8bc26ee2004-07-01 18:30:32 +0000278/*---------------------------------------------------------------*/
sewardj38a3f862005-01-13 15:06:51 +0000279/*--- h_generic_regs.h ---*/
sewardj8bc26ee2004-07-01 18:30:32 +0000280/*---------------------------------------------------------------*/