Home | History | Annotate | Download | only in priv
      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 (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 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. */
    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 
    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 
    129 static inline UInt hregNumber ( HReg r ) {
    130    return ((UInt)r) & 0x00FFFFFF;
    131 }
    132 
    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 
    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