Home | History | Annotate | Download | only in priv
      1 
      2 /*---------------------------------------------------------------*/
      3 /*--- begin                               host_generic_regs.c ---*/
      4 /*---------------------------------------------------------------*/
      5 
      6 /*
      7    This file is part of Valgrind, a dynamic binary instrumentation
      8    framework.
      9 
     10    Copyright (C) 2004-2017 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 #include "libvex_basictypes.h"
     37 #include "libvex.h"
     38 
     39 #include "main_util.h"
     40 #include "host_generic_regs.h"
     41 
     42 
     43 /*---------------------------------------------------------*/
     44 /*--- Representing HOST REGISTERS                       ---*/
     45 /*---------------------------------------------------------*/
     46 
     47 void ppHRegClass ( HRegClass hrc )
     48 {
     49    switch (hrc) {
     50       case HRcInt32:   vex_printf("HRcInt32"); break;
     51       case HRcInt64:   vex_printf("HRcInt64"); break;
     52       case HRcFlt32:   vex_printf("HRcFlt32"); break;
     53       case HRcFlt64:   vex_printf("HRcFlt64"); break;
     54       case HRcVec64:   vex_printf("HRcVec64"); break;
     55       case HRcVec128:  vex_printf("HRcVec128"); break;
     56       default: vpanic("ppHRegClass");
     57    }
     58 }
     59 
     60 /* Generic printing for registers. */
     61 void ppHReg ( HReg r )
     62 {
     63    if (hregIsInvalid(r)) {
     64       vex_printf("HReg_INVALID");
     65       return;
     66    }
     67    const Bool   isV     = hregIsVirtual(r);
     68    const HChar* maybe_v = isV ? "v" : "";
     69    const UInt   regNN   = isV ? hregIndex(r) : hregEncoding(r);
     70    /* For real registers, we show the encoding.  But the encoding is
     71       always zero for virtual registers, so that's pointless -- hence
     72       show the index number instead. */
     73    switch (hregClass(r)) {
     74       case HRcInt32:   vex_printf("%%%sr%u", maybe_v, regNN); return;
     75       case HRcInt64:   vex_printf("%%%sR%u", maybe_v, regNN); return;
     76       case HRcFlt32:   vex_printf("%%%sF%u", maybe_v, regNN); return;
     77       case HRcFlt64:   vex_printf("%%%sD%u", maybe_v, regNN); return;
     78       case HRcVec64:   vex_printf("%%%sv%u", maybe_v, regNN); return;
     79       case HRcVec128:  vex_printf("%%%sV%u", maybe_v, regNN); return;
     80       default: vpanic("ppHReg");
     81    }
     82 }
     83 
     84 
     85 /*---------------------------------------------------------*/
     86 /*--- Real register Universes.                          ---*/
     87 /*---------------------------------------------------------*/
     88 
     89 void RRegUniverse__init ( /*OUT*/RRegUniverse* univ )
     90 {
     91    *univ = (RRegUniverse){};
     92    univ->size      = 0;
     93    univ->allocable = 0;
     94    for (UInt i = 0; i < N_RREGUNIVERSE_REGS; i++) {
     95       univ->regs[i] = INVALID_HREG;
     96    }
     97 }
     98 
     99 void RRegUniverse__check_is_sane ( const RRegUniverse* univ )
    100 {
    101    /* Check Real-Register-Universe invariants.  All of these are
    102       important. */
    103    vassert(univ->size > 0);
    104    vassert(univ->size <= N_RREGUNIVERSE_REGS);
    105    vassert(univ->allocable <= univ->size);
    106    for (UInt i = 0; i < univ->size; i++) {
    107       HReg reg = univ->regs[i];
    108       vassert(!hregIsInvalid(reg));
    109       vassert(!hregIsVirtual(reg));
    110       vassert(hregIndex(reg) == i);
    111    }
    112    for (UInt i = univ->size; i < N_RREGUNIVERSE_REGS; i++) {
    113       HReg reg = univ->regs[i];
    114       vassert(hregIsInvalid(reg));
    115    }
    116 }
    117 
    118 
    119 /*---------------------------------------------------------*/
    120 /*--- Helpers for recording reg usage (for reg-alloc)   ---*/
    121 /*---------------------------------------------------------*/
    122 
    123 void ppHRegUsage ( const RRegUniverse* univ, HRegUsage* tab )
    124 {
    125    /* This is going to fail miserably if N_RREGUNIVERSE_REGS exceeds
    126       64.  So let's cause it to fail in an obvious way. */
    127    vassert(N_RREGUNIVERSE_REGS == 64);
    128 
    129    vex_printf("HRegUsage {\n");
    130    /* First print the real regs */
    131    for (UInt i = 0; i < N_RREGUNIVERSE_REGS; i++) {
    132       Bool rRd = (tab->rRead    & (1ULL << i)) != 0;
    133       Bool rWr = (tab->rWritten & (1ULL << i)) != 0;
    134       const HChar* str = "Modify ";
    135       /**/ if (!rRd && !rWr) { continue; }
    136       else if ( rRd && !rWr) { str = "Read   "; }
    137       else if (!rRd &&  rWr) { str = "Write  "; }
    138       /* else "Modify" is correct */
    139       vex_printf("   %s ", str);
    140       ppHReg(univ->regs[i]);
    141       vex_printf("\n");
    142    }
    143    /* and now the virtual registers */
    144    for (UInt i = 0; i < tab->n_vRegs; i++) {
    145       const HChar* str = NULL;
    146       switch (tab->vMode[i]) {
    147          case HRmRead:   str = "Read   "; break;
    148          case HRmWrite:  str = "Write  "; break;
    149          case HRmModify: str = "Modify "; break;
    150          default: vpanic("ppHRegUsage");
    151       }
    152       vex_printf("   %s ", str);
    153       ppHReg(tab->vRegs[i]);
    154       vex_printf("\n");
    155    }
    156    vex_printf("}\n");
    157 }
    158 
    159 
    160 /* Add a register to a usage table.  Combines incoming read uses with
    161    existing write uses into a modify use, and vice versa.  Does not
    162    create duplicate entries -- each reg is only mentioned once.
    163 */
    164 void addHRegUse ( HRegUsage* tab, HRegMode mode, HReg reg )
    165 {
    166    /* Because real and virtual registers are represented differently,
    167       they have completely different paths here. */
    168    if (LIKELY(hregIsVirtual(reg))) {
    169       /* Virtual register */
    170       UInt i;
    171       /* Find it ... */
    172       for (i = 0; i < tab->n_vRegs; i++)
    173          if (sameHReg(tab->vRegs[i], reg))
    174             break;
    175       if (i == tab->n_vRegs) {
    176          /* Not found, add new entry. */
    177          vassert(tab->n_vRegs < N_HREGUSAGE_VREGS);
    178          tab->vRegs[tab->n_vRegs] = reg;
    179          tab->vMode[tab->n_vRegs] = mode;
    180          tab->n_vRegs++;
    181       } else {
    182          /* Found: combine or ignore. */
    183          /* This is a greatest-lower-bound operation in the poset:
    184 
    185                R   W
    186                 \ /
    187                  M
    188 
    189             Need to do: tab->mode[i] = GLB(tab->mode, mode).  In this
    190             case very simple -- if tab->mode[i] != mode then result must
    191             be M.
    192          */
    193          if (tab->vMode[i] == mode) {
    194             /* duplicate, ignore */
    195          } else {
    196             tab->vMode[i] = HRmModify;
    197          }
    198       }
    199    } else {
    200       /* Real register */
    201       UInt ix = hregIndex(reg);
    202       vassert(ix < N_RREGUNIVERSE_REGS);
    203       ULong mask = 1ULL << ix;
    204       switch (mode) {
    205          case HRmRead:   tab->rRead |= mask; break;
    206          case HRmWrite:  tab->rWritten |= mask; break;
    207          case HRmModify: tab->rRead |= mask; tab->rWritten |= mask; break;
    208          default: vassert(0);
    209       }
    210    }
    211 }
    212 
    213 Bool HRegUsage__contains ( const HRegUsage* tab, HReg reg )
    214 {
    215    vassert(!hregIsInvalid(reg));
    216    if (hregIsVirtual(reg)) {
    217       for (UInt i = 0; i < tab->n_vRegs; i++) {
    218          if (sameHReg(reg, tab->vRegs[i]))
    219             return True;
    220       }
    221       return False;
    222    } else {
    223       UInt ix = hregIndex(reg);
    224       vassert(ix < N_RREGUNIVERSE_REGS);
    225       ULong mentioned = tab->rRead | tab->rWritten;
    226       return (mentioned & (1ULL << ix)) != 0;
    227    }
    228    /*NOTREACHED*/
    229 }
    230 
    231 
    232 /*---------------------------------------------------------*/
    233 /*--- Indicating register remappings (for reg-alloc)    ---*/
    234 /*---------------------------------------------------------*/
    235 
    236 void ppHRegRemap ( HRegRemap* map )
    237 {
    238    Int   i;
    239    vex_printf("HRegRemap {\n");
    240    for (i = 0; i < map->n_used; i++) {
    241       vex_printf("   ");
    242       ppHReg(map->orig[i]);
    243       vex_printf("  -->  ");
    244       ppHReg(map->replacement[i]);
    245       vex_printf("\n");
    246    }
    247    vex_printf("}\n");
    248 }
    249 
    250 
    251 void addToHRegRemap ( HRegRemap* map, HReg orig, HReg replacement )
    252 {
    253    Int i;
    254    for (i = 0; i < map->n_used; i++)
    255       if (sameHReg(map->orig[i], orig))
    256          vpanic("addToHRegMap: duplicate entry");
    257    if (!hregIsVirtual(orig))
    258       vpanic("addToHRegMap: orig is not a vreg");
    259    if (hregIsVirtual(replacement))
    260       vpanic("addToHRegMap: replacement is a vreg");
    261 
    262    vassert(map->n_used+1 < N_HREG_REMAP);
    263    map->orig[map->n_used]        = orig;
    264    map->replacement[map->n_used] = replacement;
    265    map->n_used++;
    266 }
    267 
    268 
    269 HReg lookupHRegRemap ( HRegRemap* map, HReg orig )
    270 {
    271    Int i;
    272    if (!hregIsVirtual(orig))
    273       return orig;
    274    for (i = 0; i < map->n_used; i++)
    275       if (sameHReg(map->orig[i], orig))
    276          return map->replacement[i];
    277    vpanic("lookupHRegRemap: not found");
    278 }
    279 
    280 
    281 /*---------------------------------------------------------*/
    282 /*--- Abstract instructions                             ---*/
    283 /*---------------------------------------------------------*/
    284 
    285 HInstrArray* newHInstrArray ( void )
    286 {
    287    HInstrArray* ha = LibVEX_Alloc_inline(sizeof(HInstrArray));
    288    ha->arr_size = 4;
    289    ha->arr_used = 0;
    290    ha->arr      = LibVEX_Alloc_inline(ha->arr_size * sizeof(HInstr*));
    291    ha->n_vregs  = 0;
    292    return ha;
    293 }
    294 
    295 __attribute__((noinline))
    296 void addHInstr_SLOW ( HInstrArray* ha, HInstr* instr )
    297 {
    298    vassert(ha->arr_used == ha->arr_size);
    299    Int      i;
    300    HInstr** arr2 = LibVEX_Alloc_inline(ha->arr_size * 2 * sizeof(HInstr*));
    301    for (i = 0; i < ha->arr_size; i++) {
    302       arr2[i] = ha->arr[i];
    303    }
    304    ha->arr_size *= 2;
    305    ha->arr = arr2;
    306    addHInstr(ha, instr);
    307 }
    308 
    309 
    310 /*---------------------------------------------------------*/
    311 /*--- C-Call return-location actions                    ---*/
    312 /*---------------------------------------------------------*/
    313 
    314 void ppRetLoc ( RetLoc ska )
    315 {
    316    switch (ska.pri) {
    317       case RLPri_INVALID:
    318          vex_printf("RLPri_INVALID"); return;
    319       case RLPri_None:
    320          vex_printf("RLPri_None");    return;
    321       case RLPri_Int:
    322          vex_printf("RLPri_Int");     return;
    323       case RLPri_2Int:
    324          vex_printf("RLPri_2Int");    return;
    325       case RLPri_V128SpRel:
    326          vex_printf("RLPri_V128SpRel(%d)", ska.spOff); return;
    327       case RLPri_V256SpRel:
    328          vex_printf("RLPri_V256SpRel(%d)", ska.spOff); return;
    329       default:
    330          vpanic("ppRetLoc");
    331    }
    332 }
    333 
    334 
    335 /*---------------------------------------------------------------*/
    336 /*--- end                                 host_generic_regs.c ---*/
    337 /*---------------------------------------------------------------*/
    338