blob: 0fde5ae822b5d88dd563ed3e4936b5f1b197ad4f [file] [log] [blame]
sewardjc97096c2004-06-30 09:28:04 +00001
2/*---------------------------------------------------------------*/
sewardj752f9062010-05-03 21:38:49 +00003/*--- begin host_generic_regs.h ---*/
sewardjc97096c2004-06-30 09:28:04 +00004/*---------------------------------------------------------------*/
5
sewardjf8ed9d82004-11-12 17:40:23 +00006/*
sewardj752f9062010-05-03 21:38:49 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjf8ed9d82004-11-12 17:40:23 +00009
sewardje6c53e02011-10-23 07:33:43 +000010 Copyright (C) 2004-2011 OpenWorks LLP
sewardj752f9062010-05-03 21:38:49 +000011 info@open-works.net
sewardjf8ed9d82004-11-12 17:40:23 +000012
sewardj752f9062010-05-03 21:38:49 +000013 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.
sewardjf8ed9d82004-11-12 17:40:23 +000017
sewardj752f9062010-05-03 21:38:49 +000018 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
sewardj7bd6ffe2005-08-03 16:07:36 +000026 02110-1301, USA.
27
sewardj752f9062010-05-03 21:38:49 +000028 The GNU General Public License is contained in the file COPYING.
sewardjf8ed9d82004-11-12 17:40:23 +000029
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.
sewardjf8ed9d82004-11-12 17:40:23 +000034*/
35
sewardjcef7d3e2009-07-02 12:21:59 +000036#ifndef __VEX_HOST_GENERIC_REGS_H
37#define __VEX_HOST_GENERIC_REGS_H
sewardjc97096c2004-06-30 09:28:04 +000038
sewardj887a11a2004-07-05 17:26:47 +000039#include "libvex_basictypes.h"
sewardj35421a32004-07-05 13:12:34 +000040
sewardjc97096c2004-06-30 09:28:04 +000041
sewardj8bc26ee2004-07-01 18:30:32 +000042/*---------------------------------------------------------*/
43/*--- Representing HOST REGISTERS ---*/
44/*---------------------------------------------------------*/
45
sewardjc97096c2004-06-30 09:28:04 +000046/* 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
sewardjaf5a5222004-07-01 23:14:42 +000054 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.
sewardjc97096c2004-06-30 09:28:04 +000065
sewardj6c299f32009-12-31 18:00:12 +000066 There are currently 6 register classes:
sewardjc97096c2004-06-30 09:28:04 +000067
sewardj6c299f32009-12-31 18:00:12 +000068 int32 int64 float32 float64 simd64 simd128
sewardjc97096c2004-06-30 09:28:04 +000069*/
70
71typedef UInt HReg;
72
sewardjaf5a5222004-07-01 23:14:42 +000073/* When extending this, do not use any value > 14 or < 0. */
sewardj4a31b262004-12-01 02:24:44 +000074/* 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.
sewardj1e6ad742004-12-02 16:16:11 +000078
sewardj6c299f32009-12-31 18:00:12 +000079 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:
sewardj7fb65eb2007-03-25 04:14:58 +000082
sewardj6c299f32009-12-31 18:00:12 +000083 HRcInt32 64 bits
sewardj7fb65eb2007-03-25 04:14:58 +000084 HRcInt64 64 bits
sewardj6c299f32009-12-31 18:00:12 +000085 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)
sewardj7fb65eb2007-03-25 04:14:58 +000088 HRcVec64 64 bits
89 HRcVec128 128 bits
90
91 If you add another regclass, you must remember to update
sewardj6c299f32009-12-31 18:00:12 +000092 host_generic_reg_alloc2.c accordingly.
sewardj4a31b262004-12-01 02:24:44 +000093*/
sewardjc97096c2004-06-30 09:28:04 +000094typedef
sewardj4a31b262004-12-01 02:24:44 +000095 enum {
96 HRcINVALID=1, /* NOT A VALID REGISTER CLASS */
sewardj6c299f32009-12-31 18:00:12 +000097 HRcInt32=3, /* 32-bit int */
98 HRcInt64=4, /* 64-bit int */
99 HRcFlt32=5, /* 32-bit float */
sewardj4a31b262004-12-01 02:24:44 +0000100 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
sewardj6c299f32009-12-31 18:00:12 +0000261 /* Return insn(s) to spill/restore a real reg to a spill slot
sewardjfb7373a2007-08-25 21:29:03 +0000262 offset. And optionally a function to do direct reloads. */
sewardj6c299f32009-12-31 18:00:12 +0000263 void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool ),
264 void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool ),
sewardjfb7373a2007-08-25 21:29:03 +0000265 HInstr* (*directReload) ( HInstr*, HReg, Short ),
sewardj81ec4182004-10-25 23:15:52 +0000266 Int guest_sizeB,
sewardj2b515872004-07-05 20:50:45 +0000267
268 /* For debug printing only. */
cerion92b64362005-12-13 12:02:26 +0000269 void (*ppInstr) ( HInstr*, Bool ),
270 void (*ppReg) ( HReg ),
271
272 /* 32/64bit mode */
273 Bool mode64
sewardj2cd80dc2004-07-02 15:20:40 +0000274);
275
276
sewardjcef7d3e2009-07-02 12:21:59 +0000277#endif /* ndef __VEX_HOST_GENERIC_REGS_H */
sewardj2cd80dc2004-07-02 15:20:40 +0000278
sewardj8bc26ee2004-07-01 18:30:32 +0000279/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +0000280/*--- host_generic_regs.h ---*/
sewardj8bc26ee2004-07-01 18:30:32 +0000281/*---------------------------------------------------------------*/