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-2013 OpenWorks LLP 11 info (at) 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 72 struct { 73 UInt reg; 74 } 75 HReg; 76 77 /* When extending this, do not use any value > 14 or < 0. */ 78 /* HRegClass describes host register classes which the instruction 79 selectors can speak about. We would not expect all of them to be 80 available on any specific host. For example on x86, the available 81 classes are: Int32, Flt64, Vec128 only. 82 83 IMPORTANT NOTE: host_generic_reg_alloc2.c needs how much space is 84 needed to spill each class of register. It allocates the following 85 amount of space: 86 87 HRcInt32 64 bits 88 HRcInt64 64 bits 89 HRcFlt32 64 bits 90 HRcFlt64 128 bits (on x86 these are spilled by fstpt/fldt and 91 so won't fit in a 64-bit slot) 92 HRcVec64 64 bits 93 HRcVec128 128 bits 94 95 If you add another regclass, you must remember to update 96 host_generic_reg_alloc2.c accordingly. 97 */ 98 typedef 99 enum { 100 HRcINVALID=1, /* NOT A VALID REGISTER CLASS */ 101 HRcInt32=3, /* 32-bit int */ 102 HRcInt64=4, /* 64-bit int */ 103 HRcFlt32=5, /* 32-bit float */ 104 HRcFlt64=6, /* 64-bit float */ 105 HRcVec64=7, /* 64-bit SIMD */ 106 HRcVec128=8 /* 128-bit SIMD */ 107 } 108 HRegClass; 109 110 extern void ppHRegClass ( HRegClass ); 111 112 113 /* Print an HReg in a generic (non-target-specific) way. */ 114 extern void ppHReg ( HReg ); 115 116 /* Construct/destruct. */ 117 static inline HReg mkHReg ( UInt regno, HRegClass rc, Bool virtual ) { 118 UInt r24 = regno & 0x00FFFFFF; 119 /* This is critical. The register number field may only 120 occupy 24 bits. */ 121 if (r24 != regno) 122 vpanic("mkHReg: regno exceeds 2^24"); 123 HReg r; 124 r.reg = regno | (((UInt)rc) << 28) | (virtual ? (1<<24) : 0); 125 return r; 126 } 127 128 static inline HRegClass hregClass ( HReg r ) { 129 UInt rc = r.reg; 130 rc = (rc >> 28) & 0x0F; 131 vassert(rc >= HRcInt32 && rc <= HRcVec128); 132 return (HRegClass)rc; 133 } 134 135 static inline UInt hregNumber ( HReg r ) { 136 return r.reg & 0x00FFFFFF; 137 } 138 139 static inline Bool hregIsVirtual ( HReg r ) { 140 return toBool(r.reg & (1<<24)); 141 } 142 143 static inline Bool sameHReg ( HReg r1, HReg r2 ) 144 { 145 return toBool(r1.reg == r2.reg); 146 } 147 148 static const HReg INVALID_HREG = { 0xFFFFFFFF }; 149 150 static inline Bool hregIsInvalid ( HReg r ) 151 { 152 return sameHReg(r, INVALID_HREG); 153 } 154 155 /*---------------------------------------------------------*/ 156 /*--- Recording register usage (for reg-alloc) ---*/ 157 /*---------------------------------------------------------*/ 158 159 typedef 160 enum { HRmRead, HRmWrite, HRmModify } 161 HRegMode; 162 163 164 /* A struct for recording the usage of registers in instructions. 165 This can get quite large, but we don't expect to allocate them 166 dynamically, so there's no problem. 167 */ 168 #define N_HREG_USAGE 25 169 170 typedef 171 struct { 172 HReg hreg[N_HREG_USAGE]; 173 HRegMode mode[N_HREG_USAGE]; 174 Int n_used; 175 } 176 HRegUsage; 177 178 extern void ppHRegUsage ( HRegUsage* ); 179 180 static inline void initHRegUsage ( HRegUsage* tab ) { 181 tab->n_used = 0; 182 } 183 184 /* Add a register to a usage table. Combine incoming read uses with 185 existing write uses into a modify use, and vice versa. Do not 186 create duplicate entries -- each reg should only be mentioned once. 187 */ 188 extern void addHRegUse ( HRegUsage*, HRegMode, HReg ); 189 190 191 192 /*---------------------------------------------------------*/ 193 /*--- Indicating register remappings (for reg-alloc) ---*/ 194 /*---------------------------------------------------------*/ 195 196 /* Note that such maps can only map virtual regs to real regs. 197 addToHRegRenap will barf if given a pair not of that form. As a 198 result, no valid HRegRemap will bind a real reg to anything, and so 199 if lookupHRegMap is given a real reg, it returns it unchanged. 200 This is precisely the behaviour that the register allocator needs 201 to impose its decisions on the instructions it processes. */ 202 203 #define N_HREG_REMAP 6 204 205 typedef 206 struct { 207 HReg orig [N_HREG_REMAP]; 208 HReg replacement[N_HREG_REMAP]; 209 Int n_used; 210 } 211 HRegRemap; 212 213 extern void ppHRegRemap ( HRegRemap* ); 214 extern void initHRegRemap ( HRegRemap* ); 215 extern void addToHRegRemap ( HRegRemap*, HReg, HReg ); 216 extern HReg lookupHRegRemap ( HRegRemap*, HReg ); 217 218 219 /*---------------------------------------------------------*/ 220 /*--- Abstract instructions ---*/ 221 /*---------------------------------------------------------*/ 222 223 /* A type is needed to refer to pointers to instructions of any 224 target. Defining it like this means that HInstr* can stand in for 225 X86Instr*, ArmInstr*, etc. */ 226 227 typedef void HInstr; 228 229 230 /* An expandable array of HInstr*'s. Handy for insn selection and 231 register allocation. n_vregs indicates the number of virtual 232 registers mentioned in the code, something that reg-alloc needs to 233 know. These are required to be numbered 0 .. n_vregs-1. 234 */ 235 typedef 236 struct { 237 HInstr** arr; 238 Int arr_size; 239 Int arr_used; 240 Int n_vregs; 241 } 242 HInstrArray; 243 244 extern HInstrArray* newHInstrArray ( void ); 245 extern void addHInstr ( HInstrArray*, HInstr* ); 246 247 248 /*---------------------------------------------------------*/ 249 /*--- C-Call return-location descriptions ---*/ 250 /*---------------------------------------------------------*/ 251 252 /* This is common to all back ends. It describes where the return 253 value from a C call is located. This is important in the case that 254 the call is conditional, since the return locations will need to be 255 set to 0x555..555 in the case that the call does not happen. */ 256 257 typedef 258 enum { 259 RLPri_INVALID, /* INVALID */ 260 RLPri_None, /* no return value (a.k.a C "void") */ 261 RLPri_Int, /* in the primary int return reg */ 262 RLPri_2Int, /* in both primary and secondary int ret regs */ 263 RLPri_V128SpRel, /* 128-bit value, on the stack */ 264 RLPri_V256SpRel /* 256-bit value, on the stack */ 265 } 266 RetLocPrimary; 267 268 typedef 269 struct { 270 /* Primary description */ 271 RetLocPrimary pri; 272 /* For .pri == RLPri_V128SpRel or RLPri_V256SpRel only, gives 273 the offset of the lowest addressed byte of the value, 274 relative to the stack pointer. For all other .how values, 275 has no meaning and should be zero. */ 276 Int spOff; 277 } 278 RetLoc; 279 280 extern void ppRetLoc ( RetLoc rloc ); 281 282 static inline RetLoc mk_RetLoc_simple ( RetLocPrimary pri ) { 283 vassert(pri >= RLPri_INVALID && pri <= RLPri_2Int); 284 return (RetLoc){pri, 0}; 285 } 286 287 static inline RetLoc mk_RetLoc_spRel ( RetLocPrimary pri, Int off ) { 288 vassert(pri >= RLPri_V128SpRel && pri <= RLPri_V256SpRel); 289 return (RetLoc){pri, off}; 290 } 291 292 static inline Bool is_sane_RetLoc ( RetLoc rloc ) { 293 switch (rloc.pri) { 294 case RLPri_None: case RLPri_Int: case RLPri_2Int: 295 return rloc.spOff == 0; 296 case RLPri_V128SpRel: case RLPri_V256SpRel: 297 return True; 298 default: 299 return False; 300 } 301 } 302 303 static inline RetLoc mk_RetLoc_INVALID ( void ) { 304 return (RetLoc){RLPri_INVALID, 0}; 305 } 306 307 static inline Bool is_RetLoc_INVALID ( RetLoc rl ) { 308 return rl.pri == RLPri_INVALID && rl.spOff == 0; 309 } 310 311 312 /*---------------------------------------------------------*/ 313 /*--- Reg alloc: TODO: move somewhere else ---*/ 314 /*---------------------------------------------------------*/ 315 316 extern 317 HInstrArray* doRegisterAllocation ( 318 319 /* Incoming virtual-registerised code. */ 320 HInstrArray* instrs_in, 321 322 /* An array listing all the real registers the allocator may use, 323 in no particular order. */ 324 HReg* available_real_regs, 325 Int n_available_real_regs, 326 327 /* Return True iff the given insn is a reg-reg move, in which 328 case also return the src and dst regs. */ 329 Bool (*isMove) (HInstr*, HReg*, HReg*), 330 331 /* Get info about register usage in this insn. */ 332 void (*getRegUsage) (HRegUsage*, HInstr*, Bool), 333 334 /* Apply a reg-reg mapping to an insn. */ 335 void (*mapRegs) (HRegRemap*, HInstr*, Bool), 336 337 /* Return insn(s) to spill/restore a real reg to a spill slot 338 offset. And optionally a function to do direct reloads. */ 339 void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool ), 340 void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool ), 341 HInstr* (*directReload) ( HInstr*, HReg, Short ), 342 Int guest_sizeB, 343 344 /* For debug printing only. */ 345 void (*ppInstr) ( HInstr*, Bool ), 346 void (*ppReg) ( HReg ), 347 348 /* 32/64bit mode */ 349 Bool mode64 350 ); 351 352 353 #endif /* ndef __VEX_HOST_GENERIC_REGS_H */ 354 355 /*---------------------------------------------------------------*/ 356 /*--- host_generic_regs.h ---*/ 357 /*---------------------------------------------------------------*/ 358