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-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