LCOV - code coverage report
Current view: directory - src/trusted/validator/x86/decoder - nc_inst_trans.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 589 495 84.0 %
Date: 2014-06-18 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : /*
       8                 :  * Translates the recognized opcode (instruction) in the instruction state
       9                 :  * into an opcode expression.
      10                 :  */
      11                 : 
      12                 : #include "native_client/src/trusted/validator/x86/decoder/nc_inst_trans.h"
      13                 : 
      14                 : #include <stdio.h>
      15                 : #include <assert.h>
      16                 : 
      17                 : #include "native_client/src/shared/platform/nacl_check.h"
      18                 : #include "native_client/src/shared/platform/nacl_log.h"
      19                 : #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state.h"
      20                 : #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_internal.h"
      21                 : #include "native_client/src/trusted/validator/x86/decoder/ncop_exps.h"
      22                 : #include "native_client/src/trusted/validator/x86/nacl_regs.h"
      23                 : 
      24                 : #include "native_client/src/trusted/validator/x86/decoder/ncop_exps_inl.c"
      25                 : #include "native_client/src/trusted/validator/x86/decoder/ncopcode_desc_inl.c"
      26                 : #include "native_client/src/trusted/validator/x86/x86_insts_inl.c"
      27                 : 
      28                 : #if NACL_TARGET_SUBARCH == 64
      29                 : # include "native_client/src/trusted/validator/x86/decoder/gen/nc_subregs_64.h"
      30                 : #else
      31                 : # include "native_client/src/trusted/validator/x86/decoder/gen/nc_subregs_32.h"
      32                 : #endif
      33                 : 
      34                 : /* To turn on debugging of instruction decoding, change value of
      35                 :  * DEBUGGING to 1.
      36                 :  */
      37                 : #define DEBUGGING 0
      38                 : 
      39                 : #include "native_client/src/shared/utils/debugging.h"
      40                 : 
      41                 : /* Return the segment register to use, based on prefix specification,
      42                 :  * or reg_default if no prefix specified.
      43                 :  */
      44            1913 : static NaClOpKind NaClGetSegmentPrefixReg(NaClInstState* state,
      45            1913 :                                           NaClOpKind reg_default) {
      46                 :   /* Note: We need to find the LAST segment prefix byte, since it overrides
      47                 :    * other segment prefix bytes, if multiple segment prefixes are specified.
      48                 :    */
      49                 :   if (32 == NACL_TARGET_SUBARCH) {
      50                 :     if (state->prefix_mask &
      51                 :         (kPrefixSEGCS | kPrefixSEGSS | kPrefixSEGFS |
      52                 :          kPrefixSEGGS | kPrefixSEGES | kPrefixSEGDS)) {
      53                 :       int i;
      54                 :       for (i = state->num_prefix_bytes - 1; (i >= 0); --i) {
      55                 :         switch (state->bytes.byte[i]) {
      56                 :           case kValueSEGCS:
      57                 :             return RegCS;
      58                 :           case kValueSEGSS:
      59                 :             return RegSS;
      60                 :           case kValueSEGFS:
      61                 :             return RegFS;
      62                 :           case kValueSEGGS:
      63                 :             return RegGS;
      64                 :           case kValueSEGES:
      65                 :             return RegES;
      66                 :           case kValueSEGDS:
      67                 :             return RegDS;
      68                 :           default:
      69                 :             break;
      70                 :         }
      71                 :       }
      72                 :     }
      73            1913 :   } else if (state->prefix_mask &
      74                 :              /* Only GS and FS matter in 64-bit mode. */
      75                 :              (kPrefixSEGGS | kPrefixSEGFS)) {
      76              47 :     int i;
      77             140 :     for (i = state->num_prefix_bytes - 1; (i >= 0); --i) {
      78                 :     /* for (i = 0; i < state->num_prefix_bytes; ++i) { */
      79              70 :       switch (state->bytes.byte[i]) {
      80                 :         case kValueSEGFS:
      81              37 :           return RegFS;
      82                 :         case kValueSEGGS:
      83              10 :           return RegGS;
      84                 :         default:
      85              23 :           break;
      86                 :       }
      87              23 :     }
      88               0 :   }
      89            1866 :   return reg_default;
      90            1913 : }
      91                 : 
      92                 : /* Return the segment register to use if DS is the default. */
      93             135 : static INLINE NaClOpKind NaClGetDsSegmentReg(NaClInstState* state) {
      94             135 :   return NaClGetSegmentPrefixReg(state, RegDS);
      95                 : }
      96                 : 
      97                 : /* Return the segment register to use if ES is the default. */
      98             295 : static INLINE NaClOpKind NaClGetEsSegmentReg(NaClInstState* state) {
      99             295 :   return NaClGetSegmentPrefixReg(state, RegES);
     100                 : }
     101                 : 
     102                 : /* Append the given expression node onto the given vector of expression
     103                 :  * nodes. Returns the appended expression node.
     104                 :  */
     105           24868 : static INLINE NaClExp* NaClAppendExp(NaClExpKind kind,
     106           24868 :                                      uint64_t value,
     107           24868 :                                      NaClExpFlags flags,
     108           24868 :                                      NaClExpVector* vector) {
     109           24868 :   NaClExp* node;
     110           49736 :   assert(vector->number_expr_nodes < NACL_MAX_EXPS);
     111                 :   /* If this is not a register expression, we should have specified a size. */
     112           89367 :   CHECK(ExprRegister == kind || (0 != (flags & (NACL_EFLAG(ExprSize8) |
     113                 :                                                 NACL_EFLAG(ExprSize16) |
     114                 :                                                 NACL_EFLAG(ExprSize32) |
     115                 :                                                 NACL_EFLAG(ExprSize48) |
     116                 :                                                 NACL_EFLAG(ExprSize64)))));
     117           24868 :   node = &vector->node[vector->number_expr_nodes++];
     118           24868 :   node->kind = kind;
     119           24868 :   node->value = value;
     120           24868 :   node->flags = flags;
     121           24868 :   return node;
     122                 : }
     123                 : 
     124                 : /* Report the given message and quit because we don't know
     125                 :  * how to recover.
     126                 :  */
     127                 : static void NaClLost(const char* message) {
     128                 :   NaClLog(LOG_ERROR, "FATAL: %s\n", message);
     129                 :   exit(1);
     130                 : }
     131                 : 
     132                 : /* An untranslateable error has been found. report and quit.
     133                 :  * Use the state to give useful information on where the
     134                 :  * translator was when the error occurred.
     135                 :  * Note: returns NULL of type NaClExp* so that callers can
     136                 :  * make control flow happy, for those cases where the compiler
     137                 :  * doesn't recognize that this function never returns.
     138                 :  */
     139               0 : static NaClExp* NaClFatal(const char* message,
     140               0 :                           NaClInstState* state) {
     141               0 :   NaClLog(LOG_ERROR,
     142                 :           "FATAL: At %"NACL_PRIxNaClPcAddress", unable to translate: %s\n",
     143               0 :           NaClInstStatePrintableAddress(state), message);
     144               0 :   exit(1);
     145                 :   /* NOT REACHED */
     146                 :   return NULL;
     147               0 : }
     148                 : 
     149                 : /* Returns the segment register encoded in the corresponding
     150                 :  * mnemonic name of the corresponding instruction.
     151                 :  */
     152               0 : static NaClOpKind NaClGetMnemonicSegmentRegister(NaClInstState* state) {
     153               0 :   const NaClInst* inst = NaClInstStateInst(state);
     154               0 :   switch (inst->name) {
     155                 :     case InstLds:
     156               0 :       return RegDS;
     157                 :     case InstLes:
     158               0 :       return RegES;
     159                 :     case InstLfs:
     160               0 :       return RegFS;
     161                 :     case InstLgs:
     162               0 :       return RegGS;
     163                 :     case InstLss:
     164               0 :       return RegSS;
     165                 :     default:
     166               0 :       break;
     167                 :   }
     168               0 :   NaClFatal("Unable to determine segment regsiter from instruction name",
     169                 :             state);
     170                 :   /* NOT REACHED */
     171               0 :   return RegUnknown;
     172               0 : }
     173                 : 
     174                 : /* Append that we don't bother to translate the instruction argument,
     175                 :  * since it is NaCl illegal. Used to handle cases where we don't implement
     176                 :  * 16-bit modrm effective addresses.
     177                 :  */
     178                 : static INLINE NaClExp* NaClAppendNaClIllegal(NaClInstState* state) {
     179                 :   return NaClAppendExp(ExprNaClIllegal, 0,
     180                 :                        NACL_EFLAG(ExprSize16), &state->nodes);
     181                 : }
     182                 : 
     183                 : /* Append the given constant onto the given vector of expression
     184                 :  * nodes. Returns the appended expression node.
     185                 :  */
     186            3812 : static INLINE NaClExp* NaClAppendConst(uint64_t value, NaClExpFlags flags,
     187            3812 :                                        NaClExpVector* vector) {
     188            7624 :   DEBUG(
     189                 :       NaClLog(LOG_INFO, "Append constant %"NACL_PRIx64" : ", value);
     190                 :       NaClPrintExpFlags(NaClLogGetGio(), flags);
     191                 :       gprintf(NaClLogGetGio(), "\n"));
     192            3812 :   return NaClAppendExp(ExprConstant, value, flags, vector);
     193                 : }
     194                 : 
     195                 : /* Define a type corresponding to the arrays NaClRegTable8,
     196                 :  * NaClRegTable16, NaClRegTable32, and NaClRegTable64.
     197                 :  */
     198                 : typedef const NaClOpKind NaClRegTableGroup[NACL_REG_TABLE_SIZE];
     199                 : 
     200              41 : NaClOpKind NaClGet64For32BitReg(NaClOpKind reg32) {
     201                 : #if NACL_TARGET_SUBARCH == 64
     202              41 :   int i;
     203             280 :   for (i = 0; i < NACL_REG_TABLE_SIZE; ++i) {
     204             140 :     if (reg32 == NaClRegTable32[i]) {
     205              41 :       return NaClRegTable64[i];
     206                 :     }
     207              99 :   }
     208                 : #endif
     209               0 :   return RegUnknown;
     210              41 : }
     211                 : 
     212             225 : NaClOpKind NaClGet32For64BitReg(NaClOpKind reg64) {
     213             225 :   int index = NaClGpReg64Index[reg64];
     214             675 :   return (index == NACL_REGISTER_UNDEFINED)
     215                 :       ? RegUnknown
     216                 :       : NaClRegTable32[index];
     217                 : }
     218                 : 
     219            3485 : Bool NaClIs64Subreg(NaClInstState* state,
     220            3485 :                     NaClOpKind subreg, NaClOpKind reg64) {
     221            3485 :   int index = NaClGpSubregIndex[subreg];
     222            3485 :   if (index == NACL_REGISTER_UNDEFINED) {
     223            1791 :     return FALSE;
     224                 :   } else {
     225            1694 :     int index64 = NaClGpReg64Index[reg64];
     226            1694 :     if (index64 == NACL_REGISTER_UNDEFINED) {
     227                 :       /* This shouldn't happen, so fail! */
     228               0 :       return FALSE;
     229                 :     } else {
     230            1694 :       return index == index64;
     231                 :     }
     232                 :   }
     233            3485 : }
     234                 : 
     235               0 : Bool NaClIs32To64RegPair(NaClOpKind reg32, NaClOpKind reg64) {
     236               0 :   return reg64 == NaClGet64For32BitReg(reg32);
     237                 : }
     238                 : 
     239                 : /* Define the set of available registers, categorized by size.
     240                 :  * Note: The order is important, and is based on the indexing values used
     241                 :  * in the ModRm and SIB bytes (and the REX prefix if appropriate).
     242                 :  */
     243                 : static NaClRegTableGroup* const NaClRegTable[] = {
     244                 :   &NaClRegTable8NoRex,
     245                 :   &NaClRegTable16,
     246                 :   &NaClRegTable32,
     247                 :   &NaClRegTable64,
     248                 :   &NaClRegTableMmx,
     249                 :   &NaClRegTableXmm,
     250                 :   &NaClRegTableC,
     251                 :   &NaClRegTableD,
     252                 : };
     253                 : 
     254                 : /* Define possible register categories. */
     255                 : typedef enum NaClRegKind {
     256                 :   /* Note: the following all have register tables
     257                 :    * for the corresponding general purpose registers.
     258                 :    */
     259                 :   RegSize8,
     260                 :   RegSize16,
     261                 :   RegSize32,
     262                 :   RegSize64,
     263                 :   RegMMX,
     264                 :   RegXMM,
     265                 :   RegC,
     266                 :   RegD,
     267                 :   /* Note: sizes below this point don't define general
     268                 :    * purpose registers, and hence, don't have a lookup
     269                 :    * value in the register tables.
     270                 :    */
     271                 :   RegSize128,
     272                 :   RegSizeZ,
     273                 :   RegUndefined,   /* Always returns RegUnknown. */
     274                 : } NaClRegKind;
     275                 : 
     276                 : static const char* const g_NaClRegKindName[] = {
     277                 :   "RegSize8",
     278                 :   "RegSize16",
     279                 :   "RegSize32",
     280                 :   "RegSize64",
     281                 :   "RegMMX",
     282                 :   "RegXMM",
     283                 :   "RegC",
     284                 :   "RegD",
     285                 :   "RegSize128",
     286                 :   "RegSizeZ",
     287                 :   "RegUndefined"
     288                 : };
     289                 : 
     290               0 : const char* NaClRegKindName(NaClRegKind kind) {
     291               0 :   return g_NaClRegKindName[kind];
     292                 : }
     293                 : 
     294                 : /* Define ModRm register categories. */
     295                 : typedef enum NaClModRmRegKind {
     296                 :   ModRmGeneral,
     297                 :   ModRmMmx,
     298                 :   ModRmXmm,
     299                 :   ModRmCreg,
     300                 :   ModRmDreg,
     301                 :   /* Don't allow top level registers in Effective address. */
     302                 :   ModRmNoTopLevelRegisters
     303                 : } NaClModRmRegKind;
     304                 : 
     305                 : static const char* const g_NaClModRmRegKindName[] = {
     306                 :   "ModRmGeneral",
     307                 :   "ModRmMmx",
     308                 :   "ModRmXmm",
     309                 :   "ModRmCreg",
     310                 :   "ModRmDreg",
     311                 :   "ModRmNoTopLevelRegisters"
     312                 : };
     313                 : 
     314                 : /* Given an operand kind, return the size specification associated with
     315                 :  * the operand kind.
     316                 :  */
     317            3733 : static NaClRegKind NaClGetOpKindRegKind(NaClOpKind kind) {
     318            3733 :   switch (kind) {
     319                 :     case Eb_Operand:
     320                 :     case Gb_Operand:
     321                 :     case Ib_Operand:
     322                 :     case Jb_Operand:
     323                 :     case Mb_Operand:
     324                 :     case Ob_Operand:
     325               6 :       return RegSize8;
     326                 :     case Ew_Operand:
     327                 :     case Gw_Operand:
     328                 :     case Iw_Operand:
     329                 :     case Jw_Operand:
     330                 :     case Mw_Operand:
     331                 :     case Mpw_Operand:
     332                 :     case Ow_Operand:
     333               2 :       return RegSize16;
     334                 :     case Ev_Operand:
     335                 :     case Gv_Operand:
     336                 :     case Iv_Operand:
     337                 :     case Jv_Operand:
     338                 :     case Mv_Operand:
     339                 :     case Mpv_Operand:
     340                 :     case Ov_Operand:
     341                 :     case Mmx_Gd_Operand:
     342              40 :       return RegSize32;
     343                 :     case Eo_Operand:
     344                 :     case Go_Operand:
     345                 :     case Io_Operand:
     346                 :     case Mo_Operand:
     347                 :     case Mpo_Operand:
     348                 :     case Oo_Operand:
     349                 :     case Xmm_Eo_Operand:
     350                 :     case Xmm_Go_Operand:
     351                 :     case Mmx_E_Operand:
     352                 :     case Mmx_G_Operand:
     353               8 :       return RegSize64;
     354                 :     case Edq_Operand:
     355                 :     case Gdq_Operand:
     356                 :     case Mdq_Operand:
     357                 :     case Xmm_E_Operand:
     358                 :     case Xmm_G_Operand:
     359               0 :       return RegSize128;
     360                 :     case Seg_G_Operand:
     361               0 :       return RegSizeZ;
     362                 :     default:
     363            3677 :       return RegUndefined;
     364                 :   }
     365            3733 : }
     366                 : 
     367            6610 : static NaClOpKind NaClLookupReg(NaClInstState* state,
     368            6610 :                                 NaClRegKind kind, int reg_index) {
     369           13220 :   DEBUG(NaClLog(LOG_INFO,
     370                 :                 "Lookup register (rex=%"NACL_PRIx8") %s:%d\n",
     371                 :                 state->rexprefix, NaClRegKindName(kind), reg_index));
     372                 :   if (32 == NACL_TARGET_SUBARCH && kind == RegSize64) {
     373                 :     NaClLost("Architecture doesn't define 64 bit registers");
     374            6610 :   } else if (RegSize128 <= kind) {
     375               0 :     return RegUnknown;
     376                 :   }
     377            6849 :   if (64 == NACL_TARGET_SUBARCH && kind == RegSize8 && state->rexprefix) {
     378              30 :     return NaClRegTable8Rex[reg_index];
     379                 :   }
     380            6580 :   return (*(NaClRegTable[kind]))[reg_index];
     381            6610 : }
     382                 : 
     383                 : /* Returns the (NaClExpFlag) size of the given register. */
     384           10105 : static NaClExpFlags NaClGetRegSize(NaClOpKind register_name) {
     385           10105 :   switch (register_name) {
     386                 :   case RegAL:
     387                 :   case RegBL:
     388                 :   case RegCL:
     389                 :   case RegDL:
     390                 :   case RegAH:
     391                 :   case RegBH:
     392                 :   case RegCH:
     393                 :   case RegDH:
     394                 :   case RegDIL:
     395                 :   case RegSIL:
     396                 :   case RegBPL:
     397                 :   case RegSPL:
     398                 :   case RegR8B:
     399                 :   case RegR9B:
     400                 :   case RegR10B:
     401                 :   case RegR11B:
     402                 :   case RegR12B:
     403                 :   case RegR13B:
     404                 :   case RegR14B:
     405                 :   case RegR15B:
     406             376 :     return NACL_EFLAG(ExprSize8);
     407                 :   case RegAX:
     408                 :   case RegBX:
     409                 :   case RegCX:
     410                 :   case RegDX:
     411                 :   case RegSI:
     412                 :   case RegDI:
     413                 :   case RegBP:
     414                 :   case RegSP:
     415                 :   case RegR8W:
     416                 :   case RegR9W:
     417                 :   case RegR10W:
     418                 :   case RegR11W:
     419                 :   case RegR12W:
     420                 :   case RegR13W:
     421                 :   case RegR14W:
     422                 :   case RegR15W:
     423             406 :     return NACL_EFLAG(ExprSize16);
     424                 :   case RegEAX:
     425                 :   case RegEBX:
     426                 :   case RegECX:
     427                 :   case RegEDX:
     428                 :   case RegESI:
     429                 :   case RegEDI:
     430                 :   case RegEBP:
     431                 :   case RegESP:
     432                 :   case RegR8D:
     433                 :   case RegR9D:
     434                 :   case RegR10D:
     435                 :   case RegR11D:
     436                 :   case RegR12D:
     437                 :   case RegR13D:
     438                 :   case RegR14D:
     439                 :   case RegR15D:
     440            2372 :     return NACL_EFLAG(ExprSize32);
     441                 :   case RegCS:
     442                 :   case RegDS:
     443                 :   case RegSS:
     444                 :   case RegES:
     445                 :   case RegFS:
     446                 :   case RegGS:
     447             490 :     return NACL_EFLAG(ExprSize16);
     448                 :   case RegEIP:
     449               2 :     return NACL_EFLAG(ExprSize32);
     450                 :   case RegRIP:
     451             509 :     return NACL_EFLAG(ExprSize64);
     452                 :   case RegRAX:
     453                 :   case RegRBX:
     454                 :   case RegRCX:
     455                 :   case RegRDX:
     456                 :   case RegRSI:
     457                 :   case RegRDI:
     458                 :   case RegRBP:
     459                 :   case RegRSP:
     460                 :   case RegR8:
     461                 :   case RegR9:
     462                 :   case RegR10:
     463                 :   case RegR11:
     464                 :   case RegR12:
     465                 :   case RegR13:
     466                 :   case RegR14:
     467                 :   case RegR15:
     468            3891 :     return NACL_EFLAG(ExprSize64);
     469                 :   default:
     470            2059 :     return 0;
     471                 :   }
     472           10105 : }
     473                 : 
     474                 : /* Appends the given kind of register onto the vector of expression nodes.
     475                 :  * Returns the appended register.
     476                 :  */
     477           10105 : static INLINE NaClExp* NaClAppendReg(NaClOpKind r, NaClExpVector* vector) {
     478           10105 :   NaClExp* node;
     479           20210 :   DEBUG(NaClLog(LOG_INFO, "append register %s\n", NaClOpKindName(r)));
     480           10105 :   node = NaClAppendExp(ExprRegister, r, NaClGetRegSize(r), vector);
     481           10105 :   return node;
     482                 : }
     483                 : 
     484                 : /* Given the given register kind, and the corresponding index, append
     485                 :  * the appropriate register onto the vector of expression nodes.
     486                 :  * Returns the appended register
     487                 :  */
     488            4737 : static INLINE NaClExp* NaClAppendRegKind(NaClInstState* state,
     489            4737 :                                          NaClRegKind kind, int reg_index) {
     490            9474 :   DEBUG(NaClLog(LOG_INFO, "NaClAppendRegKind(%d, %d) = %s\n",
     491                 :                 (int) kind, reg_index, NaClRegKindName(kind)));
     492            4737 :   return NaClAppendReg(NaClLookupReg(state, kind, reg_index), &state->nodes);
     493                 : }
     494                 : 
     495                 : /* Given an operand of the corresponding opcode instruction of the
     496                 :  * given state, return what kind of register should be used, based
     497                 :  * on the operand size.
     498                 :  */
     499            3733 : static NaClRegKind NaClExtractOpRegKind(NaClInstState* state,
     500            3733 :                                         const NaClOp* operand) {
     501            3733 :   NaClRegKind reg_kind = NaClGetOpKindRegKind(operand->kind);
     502            3733 :   switch (reg_kind) {
     503                 :     case RegSize8:
     504                 :     case RegSize16:
     505                 :     case RegSize32:
     506                 :     case RegSize64:
     507              56 :       return reg_kind;
     508                 :     case RegSizeZ:
     509               0 :       if (state->operand_size == 2) {
     510               0 :         return RegSize16;
     511                 :       } else {
     512               0 :         return RegSize32;
     513                 :       }
     514                 :     default:
     515                 :       /* Size not explicitly defined, pick up from operand size. */
     516            3677 :       if (state->inst->flags & NACL_IFLAG(OperandSize_b)) {
     517             233 :         return RegSize8;
     518            3444 :       } else if (state->operand_size == 1) {
     519               0 :         return RegSize8;
     520            3444 :       } else if (state->operand_size == 4) {
     521            1891 :         return RegSize32;
     522            1553 :       } else if (state->operand_size == 2) {
     523             254 :         return RegSize16;
     524            1299 :       } else if (state->operand_size == 8) {
     525            1299 :         return RegSize64;
     526                 :       } else {
     527               0 :         return RegSize32;
     528                 :       }
     529                 :   }
     530            3733 : }
     531                 : 
     532                 : /* Given an address of the corresponding opcode instruction of the
     533                 :  * given state, return what kind of register should be used.
     534                 :  */
     535            2248 : static INLINE NaClRegKind NaClExtractAddressRegKind(NaClInstState* state) {
     536            2248 :   if (state->address_size == 16) {
     537               0 :     return RegSize16;
     538            2248 :   } else if (state->address_size == 64) {
     539            2065 :     return RegSize64;
     540                 :   } else {
     541             183 :     return RegSize32;
     542                 :   }
     543            2248 : }
     544                 : 
     545                 : /* Given we want to translate an operand (of the form G_Operand),
     546                 :  * for the given register index, generate the corresponding register
     547                 :  * expression, and append it to the vector of expression nodes.
     548                 :  * Returns the appended register.
     549                 :  */
     550                 : static NaClExp* NaClAppendOperandReg(
     551            4586 :     NaClInstState* state,
     552            4586 :     const NaClOp* operand,
     553            4586 :     int reg_index,
     554            4586 :     NaClModRmRegKind modrm_reg_kind) {
     555            4586 :   NaClRegKind reg_kind = RegSize32;
     556            9172 :   DEBUG(NaClLog(LOG_INFO, "modrm_reg_kind = %s\n",
     557                 :                 g_NaClModRmRegKindName[modrm_reg_kind]));
     558            4586 :   switch (modrm_reg_kind) {
     559                 :     default:
     560                 :     case ModRmGeneral:
     561            3582 :       reg_kind = NaClExtractOpRegKind(state, operand);
     562            3582 :       break;
     563                 :     case ModRmMmx:
     564             256 :       reg_kind = RegMMX;
     565             256 :       break;
     566                 :     case ModRmXmm:
     567             740 :       reg_kind = RegXMM;
     568             740 :       break;
     569                 :     case ModRmCreg:
     570               4 :       reg_kind = RegC;
     571               4 :       break;
     572                 :     case ModRmDreg:
     573               4 :       reg_kind = RegD;
     574               4 :       break;
     575                 :     case ModRmNoTopLevelRegisters:
     576               0 :       reg_kind = RegUndefined;
     577               0 :   }
     578            9172 :   DEBUG(NaClLog(LOG_INFO, "Translate register %d, %s\n",
     579                 :                 reg_index, g_NaClRegKindName[reg_kind]));
     580            4586 :   return NaClAppendRegKind(state, reg_kind, reg_index);
     581                 : }
     582                 : 
     583                 : static NaClExpFlags NaClGetAddressExprSizeFlagsForState(NaClInstState* state);
     584                 : 
     585             475 : static NaClExp* NaClAppendSegmentAddress(NaClInstState* state) {
     586             475 :   NaClExpFlags flags = NaClGetAddressExprSizeFlagsForState(state);
     587             475 :   return NaClAppendExp(ExprSegmentAddress, 0, flags, &state->nodes);
     588                 : }
     589                 : 
     590                 : /* Same as NaClAppendOperandReg, except that a segment register is combined with
     591                 :  * the indexed register to define a segment address.
     592                 :  */
     593                 : static NaClExp* NaClAppendSegmentOpReg(
     594               0 :     NaClInstState* state,
     595               0 :     const NaClOp* operand,
     596               0 :     NaClOpKind seg_register,
     597               0 :     int reg_index,
     598               0 :     NaClModRmRegKind modrm_reg_kind) {
     599               0 :   NaClExp* results = NaClAppendSegmentAddress(state);
     600               0 :   NaClAppendReg(seg_register, &state->nodes);
     601               0 :   NaClAppendOperandReg(state, operand, reg_index, modrm_reg_kind);
     602               0 :   return results;
     603                 : }
     604                 : 
     605                 : /* Returns the corresponding segment register for the given index (0..7) */
     606              13 : static NaClExp* NaClAppendModRmSegmentReg(NaClInstState* state) {
     607                 :   static NaClOpKind seg[8] = {
     608                 :     RegES,
     609                 :     RegCS,
     610                 :     RegSS,
     611                 :     RegDS,
     612                 :     RegFS,
     613                 :     RegGS,
     614                 :     /* These should not happen. */
     615                 :     RegUnknown,
     616                 :     RegUnknown
     617                 :   };
     618              13 :   return NaClAppendReg(seg[modrm_regInline(state->modrm)], &state->nodes);
     619                 : }
     620                 : 
     621                 : /* For the given instruction state, and the corresponding 3-bit specification
     622                 :  * of a register, update it to a 4-bit specification, based on the REX.R bit.
     623                 :  */
     624            2473 : static INLINE int NaClGetRexRReg(NaClInstState* state, int reg) {
     625            4946 :   DEBUG(NaClLog(LOG_INFO, "Get GenRexRRegister %d\n", reg));
     626            2473 :   if (NACL_TARGET_SUBARCH == 64 && (state->rexprefix & 0x4)) {
     627             300 :     reg += 8;
     628             300 :   }
     629            2473 :   return reg;
     630                 : }
     631                 : 
     632                 : /* For the given instruction state, and the corresponding 3-bit specification
     633                 :  * of a register, update it to a 4-bit specification, based on the REX.X bit.
     634                 :  */
     635             652 : static INLINE int NaClGetRexXReg(NaClInstState* state, int reg) {
     636            1304 :   DEBUG(NaClLog(LOG_INFO, "Get GenRexXRegister\n"));
     637             652 :   if (NACL_TARGET_SUBARCH == 64 && (state->rexprefix & 0x2)) {
     638              94 :     reg += 8;
     639              94 :   }
     640             652 :   return reg;
     641                 : }
     642                 : 
     643                 : /* For the given instruction state, and the corresponding 3-bit specification
     644                 :  * of a register, update it to a 4-bit specification, based on the REX.B bit.
     645                 :  */
     646            3485 : static INLINE int NaClGetRexBReg(NaClInstState* state, int reg) {
     647            6970 :   DEBUG(NaClLog(LOG_INFO, "Get GenRexBRegister\n"));
     648            3485 :   if (NACL_TARGET_SUBARCH == 64 && (state->rexprefix & 0x1)) {
     649            1274 :     DEBUG(NaClLog(LOG_INFO, "rexprefix == %02x\n", state->rexprefix));
     650             637 :     reg += 8;
     651             637 :   }
     652            3485 :   return reg;
     653                 : }
     654                 : 
     655                 : /* Return the general purpose register associated with the modrm.reg
     656                 :  * field.
     657                 :  */
     658            2473 : static INLINE int NaClGetGenRegRegister(NaClInstState* state) {
     659            4946 :   DEBUG(NaClLog(LOG_INFO, "Get GenRegRegister\n"));
     660            2473 :   return NaClGetRexRReg(state, modrm_regInline(state->modrm));
     661                 : }
     662                 : 
     663                 : /* Return the general purpose register associated with the modrm.rm
     664                 :  * field.
     665                 :  */
     666            2426 : static INLINE int NaClGetGenRmRegister(NaClInstState* state) {
     667            4852 :   DEBUG(NaClLog(LOG_INFO, "Get GenRmRegister\n"));
     668            2426 :   return NaClGetRexBReg(state, modrm_rmInline(state->modrm));
     669                 : }
     670                 : 
     671                 : /* Get the register index from the difference of the opcode, and
     672                 :  * its opcode base.
     673                 :  */
     674                 : static NaClExp* NaClAppendOpcodeBaseReg(
     675             151 :     NaClInstState* state, const NaClOp* operand) {
     676             151 :   int reg_index;
     677             151 :   reg_index = NaClGetOpcodePlusR(state->inst->opcode_ext);
     678             453 :   assert(reg_index >= 0 && reg_index < 8);
     679             302 :   DEBUG(NaClLog(LOG_INFO, "Translate opcode base register %d\n", reg_index));
     680             302 :   return NaClAppendRegKind(state, NaClExtractOpRegKind(state, operand),
     681             151 :                             NaClGetRexBReg(state, reg_index));
     682                 : }
     683                 : 
     684                 : /* Get the ST register defined from the difference of the opcode, and
     685                 :  * its opcode base.
     686                 :  */
     687               0 : static NaClExp* NaClAppendStOpcodeBaseReg(NaClInstState* state) {
     688               0 :   int reg_index;
     689               0 :   reg_index = NaClGetOpcodePlusR(state->inst->opcode_ext);
     690               0 :   assert(reg_index >= 0 && reg_index < 8);
     691               0 :   DEBUG(NaClLog(LOG_INFO, "Translate opcode base register %d\n", reg_index));
     692               0 :   return NaClAppendReg(RegST0 + reg_index, &state->nodes);
     693                 : }
     694                 : 
     695                 : /* Model the extraction of a displacement value and the associated flags. */
     696                 : typedef struct NaClDisplacement {
     697                 :   uint64_t value;
     698                 :   NaClExpFlags flags;
     699                 : } NaClDisplacement;
     700                 : 
     701                 : static INLINE void NaClInitializeDisplacement(
     702            1224 :     uint64_t value, NaClExpFlags flags,
     703            1224 :     NaClDisplacement* displacement) {
     704            1224 :   displacement->value = value;
     705            1224 :   displacement->flags = flags;
     706            1224 : }
     707                 : 
     708                 : /* Extract the binary value from the specified bytes of the instruction. */
     709            1046 : static uint64_t NaClExtractUnsignedBinaryValue(NaClInstState* state,
     710            1046 :                                                int start_byte, int num_bytes) {
     711            1046 :   int i;
     712            1046 :   uint64_t value = 0;
     713            6612 :   for (i = 0; i < num_bytes; ++i) {
     714            2260 :     uint8_t byte = state->bytes.byte[start_byte + i];
     715            2260 :     value += (((uint64_t) byte) << (i * 8));
     716            2260 :   }
     717            1046 :   return value;
     718                 : }
     719                 : 
     720             275 : static int64_t NaClExtractSignedBinaryValue(NaClInstState* state,
     721             275 :                                             int start_byte, int num_bytes) {
     722                 :   /* Assumes little endian. */
     723             275 :   uint8_t* address = &state->bytes.byte[start_byte];
     724             275 :   switch (num_bytes) {
     725                 :     case 1:
     726             167 :       return *(int8_t*) address;
     727                 :     case 2:
     728               0 :       return *(int16_t*) address;
     729                 :     case 4:
     730             108 :       return *(int32_t*) address;
     731                 :     default:
     732               0 :       CHECK(0);
     733               0 :       return -1;
     734                 :   }
     735             275 : }
     736                 : 
     737                 : /* Given the number of bytes for a literal constant, return the corresponding
     738                 :  * expr node flags that represent the value of the parsed bytes.
     739                 :  */
     740            3279 : static NaClExpFlags NaClGetExprSizeFlagForBytes(uint8_t num_bytes) {
     741            3279 :   switch (num_bytes) {
     742                 :     /* HACK a zero size immediate is generated for some addr16 instructions.
     743                 :      * We don't allow these instructions, but we do test decompiling them.
     744                 :      * TODO(ncbray) eliminate the bug or the test case.
     745                 :      */
     746                 :     case 0:
     747                 :     case 1:
     748             853 :       return NACL_EFLAG(ExprSize8);
     749                 :     case 2:
     750              19 :       return NACL_EFLAG(ExprSize16);
     751                 :     case 4:
     752             558 :       return NACL_EFLAG(ExprSize32);
     753                 :     case 6:
     754               0 :       return NACL_EFLAG(ExprSize48);
     755                 :     case 8:
     756            1849 :       return NACL_EFLAG(ExprSize64);
     757                 :     default:
     758               0 :       CHECK(0);
     759               0 :       return 0;
     760                 :   }
     761            3279 : }
     762                 : 
     763                 : /* Return the expr flag for the address size associated with the state. */
     764            1958 : static NaClExpFlags NaClGetAddressExprSizeFlagsForState(NaClInstState* state) {
     765            1958 :   uint8_t size = NaClInstStateAddressSize(state);
     766            1958 :   return NaClGetExprSizeFlagForBytes(size / 8);
     767                 : }
     768                 : 
     769                 : /* Given the corresponding instruction state, return the
     770                 :  * corresponding displacement value, and any expression node
     771                 :  * flags that should be associated with the displacement value.
     772                 :  */
     773             454 : static void NaClExtractDisplacement(NaClInstState* state,
     774             454 :                                     NaClDisplacement* displacement,
     775             454 :                                     NaClExpFlags flags) {
     776             908 :   DEBUG(NaClLog(LOG_INFO, "-> Extract displacement, flags = ");
     777                 :         NaClPrintExpFlags(NaClLogGetGio(), flags);
     778                 :         gprintf(NaClLogGetGio(), "\n"));
     779                 :   /* First compute the displacement value. */
     780             454 :   displacement->value = NaClExtractUnsignedBinaryValue(state,
     781                 :                                                        state->first_disp_byte,
     782                 :                                                        state->num_disp_bytes);
     783                 : 
     784                 :   /* Now compute any appropriate flags to be associated with the value. */
     785             454 :   displacement->flags = flags |
     786             454 :       NaClGetExprSizeFlagForBytes(state->num_disp_bytes);
     787             908 :   DEBUG(NaClLog(LOG_INFO,
     788                 :                 "<- value = %"NACL_PRIx64", flags = ", displacement->value);
     789                 :         NaClPrintExpFlags(NaClLogGetGio(), displacement->flags);
     790                 :         gprintf(NaClLogGetGio(), "\n"));
     791             454 : }
     792                 : 
     793                 : /* Append the displacement value of the given instruction state
     794                 :  * onto the vector of expression nodes. Returns the appended displacement
     795                 :  * value.
     796                 :  */
     797                 : static NaClExp* NaClAppendDisplacement(NaClInstState* state) {
     798                 :   NaClDisplacement displacement;
     799                 :   DEBUG(NaClLog(LOG_INFO, "append displacement\n"));
     800                 :   NaClExtractDisplacement(state, &displacement, NACL_EFLAG(ExprSignedHex));
     801                 :   return NaClAppendConst(displacement.value, displacement.flags, &state->nodes);
     802                 : }
     803                 : 
     804                 : /* Get the binary value denoted by the immediate bytes of the state. */
     805             566 : static uint64_t NaClExtractUnsignedImmediate(NaClInstState* state) {
     806             566 :   return NaClExtractUnsignedBinaryValue(state,
     807                 :                                         state->first_imm_byte,
     808                 :                                         state->num_imm_bytes);
     809                 : }
     810                 : 
     811                 : /* Get the binary value denoted by the 2nd immediate bytes of the state. */
     812              26 : static uint64_t NaClExtractUnsignedImmediate2(NaClInstState* state) {
     813              26 :   return NaClExtractUnsignedBinaryValue(
     814                 :       state,
     815                 :       state->first_imm_byte + state->num_imm_bytes,
     816                 :       state->num_imm2_bytes);
     817                 : }
     818                 : 
     819                 : /* Get the binary value denoted by the immediate bytes of the state. */
     820             275 : static int64_t NaClExtractSignedImmediate(NaClInstState* state) {
     821             275 :   return NaClExtractSignedBinaryValue(state,
     822                 :                                       state->first_imm_byte,
     823                 :                                       state->num_imm_bytes);
     824                 : }
     825                 : 
     826                 : /* Append the immediate value of the given instruction state onto
     827                 :  * The vector of expression nodes. Returns the appended immediate value.
     828                 :  */
     829             539 : static NaClExp* NaClAppendImmed(NaClInstState* state) {
     830             539 :   NaClExpFlags flags;
     831                 : 
     832                 :   /* First compute the immediate value. */
     833             539 :   uint64_t value;
     834            1078 :   DEBUG(NaClLog(LOG_INFO, "append immediate\n"));
     835             539 :   value = NaClExtractUnsignedImmediate(state);
     836                 : 
     837                 :   /* Now compute any appropriate flags to be associated with the immediate
     838                 :    * value.
     839                 :    */
     840                 :   flags = NACL_EFLAG(ExprUnsignedHex) |
     841             539 :       NaClGetExprSizeFlagForBytes(state->num_imm_bytes);
     842                 : 
     843                 :   /* Append the generated immediate value onto the vector. */
     844             539 :   return NaClAppendConst(value, flags, &state->nodes);
     845                 : }
     846                 : 
     847                 : /* Append the second immediate value of the given instruction state onto
     848                 :  * the vector of expression nodes. Returns the appended immediate value.
     849                 :  */
     850              26 : static NaClExp* NaClAppendImmed2(NaClInstState* state) {
     851              26 :   NaClExpFlags flags;
     852                 : 
     853                 :   /* First compute the immedaite value. */
     854              26 :   uint64_t value;
     855              52 :   DEBUG(NaClLog(LOG_INFO, "append 2nd immediate\n"));
     856                 : 
     857              26 :   value = NaClExtractUnsignedImmediate2(state);
     858                 : 
     859                 :   /* Now compute any appropriate flags to be associated with the immediate
     860                 :    * value.
     861                 :    */
     862                 :   flags =
     863                 :       NACL_EFLAG(ExprUnsignedHex) |
     864              26 :       NaClGetExprSizeFlagForBytes(state->num_imm2_bytes);
     865                 : 
     866                 :   /* Append the generated immediate value onto the vector. */
     867              26 :   return NaClAppendConst(value, flags, &state->nodes);
     868                 : }
     869                 : 
     870                 : /* Append an ExprMemOffset node for the given state, and return
     871                 :  * the appended ndoe.
     872                 :  */
     873            1483 : static NaClExp* NaClAppendMemOffsetNode(NaClInstState* state) {
     874            1483 :   NaClExpFlags flags = NaClGetAddressExprSizeFlagsForState(state);
     875            1483 :   NaClExp* root = NaClAppendExp(ExprMemOffset, 0, flags, &state->nodes);
     876            2966 :   DEBUG(NaClLog(LOG_INFO, "Build memoffset, flags = ");
     877                 :         NaClPrintExpFlags(NaClLogGetGio(), flags);
     878                 :         gprintf(NaClLogGetGio(), "\n"));
     879            1483 :   return root;
     880                 : }
     881                 : 
     882                 : /* Returns the segment register prefix node, or NULL if no such node is
     883                 :  * added.
     884                 :  */
     885            1483 : static NaClExp* NaClAppendSegmentAddressNode(NaClInstState* state,
     886            1483 :                                              NaClOpKind reg_default) {
     887            1483 :   NaClExp* root = NULL;
     888            1483 :   NaClOpKind seg_reg = NaClGetSegmentPrefixReg(state, reg_default);
     889            1483 :   if (seg_reg != RegUnknown) {
     890              45 :     NaClExp* n;
     891              45 :     root = NaClAppendSegmentAddress(state);
     892              45 :     n = NaClAppendReg(seg_reg, &state->nodes);
     893              45 :     n->flags |= NACL_EFLAG(ExprUsed);
     894              45 :   }
     895            1483 :   return root;
     896                 : }
     897                 : 
     898                 : /* Append the immediate value of the given instruction as the displacement
     899                 :  * of a memory offset.
     900                 :  */
     901              27 : static NaClExp* NaClAppendMemoryOffsetImmed(NaClInstState* state) {
     902              27 :   NaClExpFlags flags;
     903              27 :   uint64_t value;
     904              27 :   NaClExp* root;
     905              54 :   DEBUG(NaClLog(LOG_INFO, "append memory offset immediate\n"));
     906              27 :   root = NaClAppendSegmentAddressNode(state, RegUnknown);
     907              27 :   if (root == NULL) {
     908              23 :     root = NaClAppendMemOffsetNode(state);
     909              23 :   } else {
     910               4 :     NaClAppendMemOffsetNode(state);
     911                 :   }
     912              27 :   NaClAppendReg(RegUnknown, &state->nodes);
     913              27 :   NaClAppendReg(RegUnknown, &state->nodes);
     914              27 :   NaClAppendConst(1, NACL_EFLAG(ExprSize8), &state->nodes);
     915              27 :   value = NaClExtractUnsignedImmediate(state);
     916              54 :   DEBUG(NaClLog(LOG_INFO, "value = 0x%016"NACL_PRIx64"\n", value));
     917                 :   flags = NACL_EFLAG(ExprUnsignedHex) |
     918              27 :       NaClGetExprSizeFlagForBytes(state->num_imm_bytes);
     919              27 :   NaClAppendConst(value, flags, &state->nodes);
     920              27 :   return root;
     921                 : }
     922                 : 
     923             275 : static NaClExp* NaClAppendRelativeImmed(NaClInstState* state) {
     924             275 :   NaClPcNumber jump_offset = (NaClPcNumber) NaClExtractSignedImmediate(state);
     925             550 :   DEBUG(NaClLog(LOG_INFO, "append relative immediate\n"));
     926             550 :   return NaClAppendConst(jump_offset,
     927                 :                          NACL_EFLAG(ExprSignedHex) |
     928             275 :                          NaClGetExprSizeFlagForBytes(state->num_imm_bytes) |
     929                 :                          NACL_EFLAG(ExprJumpTarget),
     930                 :                          &state->nodes);
     931                 : }
     932                 : 
     933                 : /* Append a memory offset for the given memory offset defined by
     934                 :  * the formula "base + index*scale + displacement". If no index
     935                 :  * is used, its value should be RegUnknown. Argument displacement_flags
     936                 :  * are flags that should be associated with the generated displacement
     937                 :  * value
     938                 :  */
     939            1456 : static NaClExp* NaClAppendMemoryOffset(NaClInstState* state,
     940            1456 :                                        NaClOpKind base,
     941            1456 :                                        NaClOpKind index,
     942            1456 :                                        uint8_t scale,
     943            1456 :                                        NaClDisplacement* displacement) {
     944            1456 :   NaClExp* root = NULL;
     945            1456 :   NaClOpKind seg_reg_default;
     946            1456 :   NaClExp* n;
     947                 : 
     948            2912 :   DEBUG(NaClLog(LOG_INFO,
     949                 :                 "memory offset(%s + %s * %d +  %"NACL_PRId64
     950                 :                 " : %"NACL_PRIx32")\n",
     951                 :                 NaClOpKindName(base),
     952                 :                 NaClOpKindName(index),
     953                 :                 scale,
     954                 :                 displacement->value,
     955                 :                 displacement->flags));
     956                 : 
     957                 :   if (32 == NACL_TARGET_SUBARCH) {
     958                 :     seg_reg_default = ((base == RegBP || base == RegEBP)
     959                 :                        ? RegSS : NaClGetDsSegmentReg(state));
     960                 :   } else {
     961            1456 :     seg_reg_default = RegUnknown;
     962                 :   }
     963            1456 :   root = NaClAppendSegmentAddressNode(state, seg_reg_default);
     964            1456 :   if (NULL == root) {
     965            1415 :     root = NaClAppendMemOffsetNode(state);
     966            1415 :   } else {
     967              41 :     NaClAppendMemOffsetNode(state);
     968                 :   }
     969            1456 :   n = NaClAppendReg(base, &state->nodes);
     970            1456 :   if (base != RegUnknown) {
     971            1413 :     n->flags |= NACL_EFLAG(ExprUsed);
     972            1413 :   }
     973            1456 :   n = NaClAppendReg(index, &state->nodes);
     974            1456 :   if (index == RegUnknown) {
     975                 :     /* Scale not applicable, check that value is 1. */
     976            1608 :     assert(scale == 1);
     977             804 :   } else {
     978             652 :     n->flags |= NACL_EFLAG(ExprUsed);
     979                 :   }
     980            1456 :   NaClAppendConst(scale, NACL_EFLAG(ExprSize8), &state->nodes);
     981            1456 :   NaClAppendConst(displacement->value, displacement->flags, &state->nodes);
     982            2912 :   DEBUG(NaClLog(LOG_INFO, "finished appending memory offset:\n"));
     983            2912 :   DEBUG(NaClExpVectorPrint(NaClLogGetGio(), state));
     984            1456 :   return root;
     985                 : }
     986                 : 
     987                 : /* Extract the base register from the SIB byte. */
     988            1027 : static NaClOpKind NaClGetSibBase(NaClInstState* state) {
     989            1027 :   int base = sib_base(state->sib);
     990            1027 :   NaClOpKind base_reg = RegUnknown;
     991            1027 :   if (0x5 == base) {
     992             119 :     switch (modrm_modInline(state->modrm)) {
     993                 :       case 0:
     994              43 :         break;
     995                 :       case 1:
     996                 :       case 2:
     997                 :         if (NACL_TARGET_SUBARCH == 64) {
     998              76 :           if (state->rexprefix & 0x1) {
     999              11 :             base_reg = RegR13;
    1000              11 :           } else {
    1001              65 :             base_reg = RegRBP;
    1002                 :           }
    1003                 :         } else {
    1004                 :           base_reg = RegEBP;
    1005                 :         }
    1006              76 :         break;
    1007                 :       default:
    1008               0 :         NaClFatal("SIB value", state);
    1009               0 :     }
    1010             119 :   } else {
    1011             908 :     NaClRegKind kind = NaClExtractAddressRegKind(state);
    1012             908 :     base_reg = NaClLookupReg(state, kind, NaClGetRexBReg(state, base));
    1013                 :   }
    1014            1027 :   return base_reg;
    1015                 : }
    1016                 : 
    1017                 : /* Define the possible scaling factors that can be defined in the
    1018                 :  * SIB byte of the parsed instruction.
    1019                 :  */
    1020                 : static uint8_t nacl_sib_scale[4] = { 1, 2, 4, 8 };
    1021                 : 
    1022                 : /* Extract out the expression defined by the SIB byte of the instruction
    1023                 :  * in the given instruction state, and append it to the vector of
    1024                 :  * expression nodes. Return the corresponding expression node that
    1025                 :  * is the root of the appended expression.
    1026                 :  */
    1027            1027 : static NaClExp* NaClAppendSib(NaClInstState* state) {
    1028            1027 :   int index = sib_index(state->sib);
    1029            1027 :   int scale = 1;
    1030            1027 :   NaClRegKind kind = NaClExtractAddressRegKind(state);
    1031            1027 :   NaClOpKind base_reg;
    1032            1027 :   NaClOpKind index_reg = RegUnknown;
    1033            1027 :   NaClDisplacement displacement;
    1034            2054 :   DEBUG(NaClLog(LOG_INFO, "append sib: %02x\n", state->sib));
    1035            1027 :   NaClInitializeDisplacement(0, 0, &displacement);
    1036            1027 :   base_reg = NaClGetSibBase(state);
    1037            1412 :   if (0x4 != index || NACL_TARGET_SUBARCH != 64 || (state->rexprefix & 0x2)) {
    1038             652 :     index_reg = NaClLookupReg(state, kind, NaClGetRexXReg(state, index));
    1039             652 :     scale = nacl_sib_scale[sib_ss(state->sib)];
    1040             652 :   }
    1041            1027 :   if (state->num_disp_bytes > 0) {
    1042             222 :     NaClExtractDisplacement(state, &displacement,
    1043                 :                         NACL_EFLAG(ExprSignedHex));
    1044             222 :   } else {
    1045             805 :     displacement.flags = NACL_EFLAG(ExprSize8);
    1046                 :   }
    1047            1027 :   return NaClAppendMemoryOffset(state, base_reg, index_reg,
    1048                 :                                 scale, &displacement);
    1049                 : }
    1050                 : 
    1051             301 : static void NaClAppendEDI(NaClInstState* state) {
    1052             301 :   switch (state->address_size) {
    1053                 :     case 16:
    1054               0 :       NaClAppendReg(RegDI, &state->nodes);
    1055               0 :       break;
    1056                 :     case 32:
    1057              19 :       NaClAppendReg(RegEDI, &state->nodes);
    1058              19 :       break;
    1059                 :     case 64:
    1060             282 :       NaClAppendReg(RegRDI, &state->nodes);
    1061             282 :       break;
    1062                 :     default:
    1063               0 :       NaClFatal("Address size for %EDI not correctly defined",
    1064                 :                 state);
    1065               0 :       break;
    1066                 :   }
    1067             301 : }
    1068                 : 
    1069             121 : static void NaClAppendESI(NaClInstState* state) {
    1070             121 :   switch (state->address_size) {
    1071                 :     case 16:
    1072               0 :       NaClAppendReg(RegSI, &state->nodes);
    1073               0 :       break;
    1074                 :     case 32:
    1075               0 :       NaClAppendReg(RegESI, &state->nodes);
    1076               0 :       break;
    1077                 :     case 64:
    1078             121 :       NaClAppendReg(RegRSI, &state->nodes);
    1079             121 :       break;
    1080                 :     default:
    1081               0 :       NaClFatal("Address size for %ESI not correctly defined", state);
    1082               0 :       break;
    1083                 :   }
    1084             121 : }
    1085               8 : static void NaClAppendEBX(NaClInstState* state) {
    1086               8 :   switch (state->address_size) {
    1087                 :     case 16:
    1088               0 :       NaClAppendReg(RegBX, &state->nodes);
    1089               0 :       break;
    1090                 :     case 32:
    1091               0 :       NaClAppendReg(RegEBX, &state->nodes);
    1092               0 :       break;
    1093                 :     case 64:
    1094               8 :       NaClAppendReg(RegRBX, &state->nodes);
    1095               8 :       break;
    1096                 :     default:
    1097               0 :       NaClFatal("Address size for %EBX not correctly defined", state);
    1098               0 :       break;
    1099                 :   }
    1100               8 : }
    1101                 : 
    1102               6 : static NaClExp* NaClAppendDS_EDI(NaClInstState* state) {
    1103               6 :   NaClExp* results = NaClAppendSegmentAddress(state);
    1104               6 :   results->flags |= NACL_EFLAG(ExprDSrCase);
    1105               6 :   NaClAppendReg(NaClGetDsSegmentReg(state),  &state->nodes);
    1106               6 :   NaClAppendEDI(state);
    1107               6 :   return results;
    1108                 : }
    1109                 : 
    1110             121 : static NaClExp* NaClAppendDS_ESI(NaClInstState* state) {
    1111             121 :   NaClExp* results = NaClAppendSegmentAddress(state);
    1112             121 :   results->flags |= NACL_EFLAG(ExprDSrCase);
    1113             121 :   NaClAppendReg(NaClGetDsSegmentReg(state),  &state->nodes);
    1114             121 :   NaClAppendESI(state);
    1115             121 :   return results;
    1116                 : }
    1117                 : 
    1118               8 : static NaClExp* NaClAppendDS_EBX(NaClInstState* state) {
    1119               8 :   NaClExp* results = NaClAppendSegmentAddress(state);
    1120               8 :   results->flags |= NACL_EFLAG(ExprDSrCase);
    1121               8 :   NaClAppendReg(NaClGetDsSegmentReg(state),  &state->nodes);
    1122               8 :   NaClAppendEBX(state);
    1123               8 :   return results;
    1124                 : }
    1125                 : 
    1126             295 : static NaClExp* NaClAppendES_EDI(NaClInstState* state) {
    1127             295 :   NaClExp* results = NaClAppendSegmentAddress(state);
    1128             295 :   results->flags |= NACL_EFLAG(ExprESrCase);
    1129             295 :   NaClAppendReg(NaClGetEsSegmentReg(state),  &state->nodes);
    1130             295 :   NaClAppendEDI(state);
    1131             295 :   return results;
    1132                 : }
    1133                 : 
    1134                 : /* Get the Effective address in the mod/rm byte, if the modrm.mod field
    1135                 :  * is 00, and append it to the vector of expression nodes. Operand is
    1136                 :  * the corresponding operand of the opcode associated with the instruction
    1137                 :  * of the given state that corresponds to the effective address. Returns
    1138                 :  * the root of the appended effective address.
    1139                 :  */
    1140                 : static NaClExp* NaClAppendMod00EffectiveAddress(
    1141            1161 :     NaClInstState* state, const NaClOp* operand) {
    1142            2322 :   DEBUG(NaClLog(LOG_INFO, "Translate modrm(%02x).mod == 00\n", state->modrm));
    1143                 :   if ((32 == NACL_TARGET_SUBARCH) &&
    1144                 :       NaClHasBit(state->prefix_mask, kPrefixADDR16)) {
    1145                 :     /* This code doesn't know how to translate 16-bit modrm effective addresses.
    1146                 :      * However, such arguments are not nacl legal. Communicate this explicitly.
    1147                 :      */
    1148                 :     return NaClAppendNaClIllegal(state);
    1149                 :   }
    1150            1161 :   switch (modrm_rmInline(state->modrm)) {
    1151                 :     case 4:
    1152             848 :       return NaClAppendSib(state);
    1153                 :     case 5:
    1154                 :       if (NACL_TARGET_SUBARCH == 64) {
    1155             116 :         NaClDisplacement displacement;
    1156             116 :         NaClExtractDisplacement(state, &displacement,
    1157                 :                                 NACL_EFLAG(ExprSignedHex));
    1158             116 :         return NaClAppendMemoryOffset(state,
    1159                 :                                       RegRIP,
    1160                 :                                       RegUnknown,
    1161                 :                                       1,
    1162                 :                                       &displacement);
    1163                 :       } else {
    1164                 :         return NaClAppendDisplacement(state);
    1165                 :       }
    1166                 :     default: {
    1167             197 :       NaClDisplacement displacement;
    1168             197 :       NaClInitializeDisplacement(0, NACL_EFLAG(ExprSize8), &displacement);
    1169             394 :       return NaClAppendMemoryOffset(state,
    1170             394 :                                     NaClLookupReg(
    1171                 :                                         state,
    1172             197 :                                         NaClExtractAddressRegKind(state),
    1173             197 :                                         NaClGetGenRmRegister(state)),
    1174                 :                                     RegUnknown,
    1175                 :                                     1,
    1176                 :                                     &displacement);
    1177                 :     }
    1178                 :   }
    1179                 :   /* NOT REACHED */
    1180                 :   return NULL;
    1181            1161 : }
    1182                 : 
    1183                 : /* Get the Effective address in the mod/rm byte, if the modrm.mod field
    1184                 :  * is 01, and append it to the vector of expression nodes. Operand is
    1185                 :  * the corresponding operand of the opcode associated with the instruction
    1186                 :  * of the given state that corresponds to the effective address. Returns
    1187                 :  * the root of the appended effective address.
    1188                 :  */
    1189                 : static NaClExp* NaClAppendMod01EffectiveAddress(
    1190             234 :     NaClInstState* state, const NaClOp* operand) {
    1191             468 :   DEBUG(NaClLog(LOG_INFO, "Translate modrm(%02x).mod == 01\n", state->modrm));
    1192                 :   if ((32 == NACL_TARGET_SUBARCH) &&
    1193                 :       NaClHasBit(state->prefix_mask, kPrefixADDR16)) {
    1194                 :     /* This code doesn't know how to translate 16-bit modrm effective addresses.
    1195                 :      * However, such arguments are not nacl legal. Communicate this explicitly.
    1196                 :      */
    1197                 :     return NaClAppendNaClIllegal(state);
    1198                 :   }
    1199             234 :   if (4 == modrm_rmInline(state->modrm)) {
    1200             146 :     return NaClAppendSib(state);
    1201                 :   } else {
    1202              88 :     NaClDisplacement displacement;
    1203              88 :     NaClExtractDisplacement(state, &displacement, NACL_EFLAG(ExprSignedHex));
    1204             176 :     return NaClAppendMemoryOffset(state,
    1205             176 :                                   NaClLookupReg(
    1206                 :                                       state,
    1207              88 :                                       NaClExtractAddressRegKind(state),
    1208              88 :                                       NaClGetGenRmRegister(state)),
    1209                 :                                   RegUnknown,
    1210                 :                                   1,
    1211                 :                                   &displacement);
    1212                 :   }
    1213             234 : }
    1214                 : 
    1215                 : /* Get the Effective address in the mod/rm byte, if the modrm.mod field
    1216                 :  * is 10, and append it to the vector of expression nodes. Operand is
    1217                 :  * the corresponding operand of the opcode associated with the instruction
    1218                 :  * of the given state that corresponds to the effective address. Returns
    1219                 :  * the root of the appended effective address.
    1220                 :  */
    1221                 : static NaClExp* NaClAppendMod10EffectiveAddress(
    1222              61 :     NaClInstState* state, const NaClOp* operand) {
    1223             122 :   DEBUG(NaClLog(LOG_INFO, "Translate modrm(%02x).mod == 10\n", state->modrm));
    1224                 :   if ((32 == NACL_TARGET_SUBARCH) &&
    1225                 :       NaClHasBit(state->prefix_mask, kPrefixADDR16)) {
    1226                 :     /* This code doesn't know how to translate 16-bit modrm effective addresses.
    1227                 :      * However, such arguments are not nacl legal. Communicate this explicitly.
    1228                 :      */
    1229                 :     return NaClAppendNaClIllegal(state);
    1230                 :   }
    1231              61 :   if (4 == modrm_rmInline(state->modrm)) {
    1232              33 :     return NaClAppendSib(state);
    1233                 :   } else {
    1234              28 :     NaClDisplacement displacement;
    1235              28 :     NaClOpKind base =
    1236              56 :         NaClLookupReg(state,
    1237              28 :                       NaClExtractAddressRegKind(state),
    1238              28 :                       NaClGetGenRmRegister(state));
    1239              28 :     NaClExtractDisplacement(state, &displacement, NACL_EFLAG(ExprSignedHex));
    1240              28 :     return NaClAppendMemoryOffset(state, base, RegUnknown, 1, &displacement);
    1241                 :   }
    1242              61 : }
    1243                 : 
    1244                 : /* Get the Effective address in the mod/rm byte, if the modrm.mod field
    1245                 :  * is 11, and append it to the vector of expression nodes. Operand is
    1246                 :  * the corresponding operand of the opcode associated with the instruction
    1247                 :  * of the given state that corresponds to the effective address. Returns
    1248                 :  * the root of the appended effective address.
    1249                 :  */
    1250                 : static NaClExp* NaClAppendMod11EffectiveAddress(
    1251            2113 :     NaClInstState* state, const NaClOp* operand,
    1252            2113 :     NaClModRmRegKind modrm_reg_kind) {
    1253            4226 :   DEBUG(NaClLog(LOG_INFO, "Translate modrm(%02x).mod == 11, %s\n",
    1254                 :                 state->modrm, g_NaClModRmRegKindName[modrm_reg_kind]));
    1255            4226 :   return NaClAppendOperandReg(state,
    1256                 :                               operand,
    1257            2113 :                               NaClGetGenRmRegister(state), modrm_reg_kind);
    1258                 : }
    1259                 : 
    1260             166 : static NaClExp* NaClAppendBasedOnSize(NaClOpKind reg_2b,
    1261             166 :                                       NaClOpKind reg_4b,
    1262             166 :                                       NaClOpKind reg_8b,
    1263             166 :                                       NaClInstState* state) {
    1264             166 :   switch (state->operand_size) {
    1265                 :     case 2:
    1266              48 :       return NaClAppendReg(reg_2b, &state->nodes);
    1267                 :     case 4:
    1268              86 :       return NaClAppendReg(reg_4b, &state->nodes);
    1269                 :     case 8:
    1270              32 :       return NaClAppendReg(reg_8b, &state->nodes);
    1271                 :     default:
    1272               0 :       return NaClFatal("can't translate register group: operand size not valid",
    1273                 :                        state);
    1274                 :   }
    1275             166 : }
    1276                 : 
    1277               8 : static NaClExp* NaClAppendBasedOnAddressSize(NaClOpKind reg_2b,
    1278               8 :                                              NaClOpKind reg_4b,
    1279               8 :                                              NaClOpKind reg_8b,
    1280               8 :                                              NaClInstState* state) {
    1281               8 :   switch (state->address_size) {
    1282                 :     case 16:
    1283               0 :       return NaClAppendReg(reg_2b, &state->nodes);
    1284                 :     case 32:
    1285               0 :       return NaClAppendReg(reg_4b, &state->nodes);
    1286                 :     case 64:
    1287               8 :       return NaClAppendReg(reg_8b, &state->nodes);
    1288                 :     default:
    1289               0 :       return NaClFatal("can't translate register group: address size not valid",
    1290                 :                        state);
    1291                 :   }
    1292               8 : }
    1293                 : 
    1294                 : /* Compute the effect address using the Mod/Rm and SIB bytes. */
    1295                 : static NaClExp* NaClAppendEffectiveAddress(
    1296            3569 :     NaClInstState* state, const NaClOp* operand,
    1297            3569 :     NaClModRmRegKind modrm_reg_kind) {
    1298            3569 :   switch(modrm_modInline(state->modrm)) {
    1299                 :     case 0:
    1300            1161 :       return NaClAppendMod00EffectiveAddress(state, operand);
    1301                 :     case 1:
    1302             234 :       return NaClAppendMod01EffectiveAddress(state, operand);
    1303                 :     case 2:
    1304              61 :       return NaClAppendMod10EffectiveAddress(state, operand);
    1305                 :     case 3:
    1306            2113 :       return NaClAppendMod11EffectiveAddress(state, operand, modrm_reg_kind);
    1307                 :     default:
    1308               0 :       break;
    1309                 :   }
    1310               0 :   return NaClFatal("Operand", state);
    1311            3569 : }
    1312                 : 
    1313                 : /* Given the corresponding operand of the opcode associated with the
    1314                 :  * instruction of the given state, append the corresponding expression
    1315                 :  * nodes that it corresponds to. Returns the root of the corresponding
    1316                 :  * appended expression tree.
    1317                 :  */
    1318            8993 : static NaClExp* NaClAppendOperand(NaClInstState* state,
    1319            8993 :                                   const NaClOp* operand) {
    1320           17986 :   DEBUG(NaClLog(LOG_INFO,
    1321                 :                 "append operand %s\n", NaClOpKindName(operand->kind)));
    1322            8993 :   switch (operand->kind) {
    1323                 :     case A_Operand:
    1324               0 :       return NaClAppendImmed(state);
    1325                 :     case E_Operand:
    1326                 :     case Eb_Operand:
    1327                 :     case Ew_Operand:
    1328                 :     case Ev_Operand:
    1329                 :     case Eo_Operand:
    1330                 :     case Edq_Operand:
    1331                 :       /* TODO(karl) Should we add limitations that simple registers
    1332                 :        * not allowed in M_Operand cases?
    1333                 :        */
    1334                 :     case M_Operand:
    1335                 :     case Mb_Operand:
    1336                 :     case Mw_Operand:
    1337                 :     case Mv_Operand:
    1338                 :     case Mo_Operand:
    1339                 :     case Mdq_Operand: {
    1340            2880 :         NaClExp* address =
    1341            2880 :             NaClAppendEffectiveAddress(state, operand, ModRmGeneral);
    1342                 :         /* Near operands are jump addresses. Mark them as such. */
    1343            2880 :         if (operand->flags & NACL_OPFLAG(OperandNear)) {
    1344             103 :           address->flags |= NACL_EFLAG(ExprJumpTarget);
    1345             103 :         }
    1346            2880 :         return address;
    1347                 :       }
    1348                 :       break;
    1349                 :     case G_Operand:
    1350                 :     case Gb_Operand:
    1351                 :     case Gw_Operand:
    1352                 :     case Gv_Operand:
    1353                 :     case Go_Operand:
    1354                 :     case Gdq_Operand:
    1355            2012 :       return NaClAppendOperandReg(state, operand, NaClGetGenRegRegister(state),
    1356                 :                                   ModRmGeneral);
    1357                 :     case Seg_G_Operand:
    1358               0 :       return NaClAppendSegmentOpReg(
    1359               0 :           state, operand, NaClGetMnemonicSegmentRegister(state),
    1360               0 :           NaClGetGenRegRegister(state), ModRmGeneral);
    1361                 :     case G_OpcodeBase:
    1362             151 :       return NaClAppendOpcodeBaseReg(state, operand);
    1363                 :     case I_Operand:
    1364                 :     case Ib_Operand:
    1365                 :     case Iw_Operand:
    1366                 :     case Iv_Operand:
    1367                 :     case Io_Operand:
    1368             539 :       return NaClAppendImmed(state);
    1369                 :     case I2_Operand:
    1370              26 :       return NaClAppendImmed2(state);
    1371                 :     case J_Operand:
    1372                 :     case Jb_Operand:
    1373                 :     case Jw_Operand:
    1374                 :     case Jv_Operand:
    1375                 :       /* TODO(karl) use operand flags OperandNear and OperandRelative to decide
    1376                 :        * how to process the J operand (see Intel manual for call statement).
    1377                 :        */
    1378             275 :       return NaClAppendRelativeImmed(state);
    1379                 :     case Mmx_Gd_Operand:
    1380                 :     case Mmx_G_Operand:
    1381             124 :       return NaClAppendOperandReg(state, operand, NaClGetGenRegRegister(state),
    1382                 :                                   ModRmMmx);
    1383                 :     case Mmx_E_Operand:
    1384             168 :       return NaClAppendEffectiveAddress(state, operand, ModRmMmx);
    1385                 :     case Xmm_G_Operand:
    1386                 :     case Xmm_Go_Operand:
    1387             337 :       return NaClAppendOperandReg(state, operand, NaClGetGenRegRegister(state),
    1388                 :                                   ModRmXmm);
    1389                 :     case Xmm_E_Operand:
    1390                 :     case Xmm_Eo_Operand:
    1391             513 :       return NaClAppendEffectiveAddress(state, operand, ModRmXmm);
    1392                 :     case C_Operand:
    1393               4 :       return NaClAppendEffectiveAddress(state, operand, ModRmCreg);
    1394                 :     case D_Operand:
    1395               4 :       return NaClAppendEffectiveAddress(state, operand, ModRmDreg);
    1396                 :     case O_Operand:
    1397                 :     case Ob_Operand:
    1398                 :     case Ow_Operand:
    1399                 :     case Ov_Operand:
    1400                 :     case Oo_Operand:
    1401              27 :       return NaClAppendMemoryOffsetImmed(state);
    1402                 :     case St_Operand:
    1403               0 :       return NaClAppendStOpcodeBaseReg(state);
    1404                 :     case RegUnknown:
    1405                 :     case RegAL:
    1406                 :     case RegBL:
    1407                 :     case RegCL:
    1408                 :     case RegDL:
    1409                 :     case RegAH:
    1410                 :     case RegBH:
    1411                 :     case RegCH:
    1412                 :     case RegDH:
    1413                 :     case RegDIL:
    1414                 :     case RegSIL:
    1415                 :     case RegBPL:
    1416                 :     case RegSPL:
    1417                 :     case RegR8B:
    1418                 :     case RegR9B:
    1419                 :     case RegR10B:
    1420                 :     case RegR11B:
    1421                 :     case RegR12B:
    1422                 :     case RegR13B:
    1423                 :     case RegR14B:
    1424                 :     case RegR15B:
    1425                 :     case RegAX:
    1426                 :     case RegBX:
    1427                 :     case RegCX:
    1428                 :     case RegDX:
    1429                 :     case RegSI:
    1430                 :     case RegDI:
    1431                 :     case RegBP:
    1432                 :     case RegSP:
    1433                 :     case RegR8W:
    1434                 :     case RegR9W:
    1435                 :     case RegR10W:
    1436                 :     case RegR11W:
    1437                 :     case RegR12W:
    1438                 :     case RegR13W:
    1439                 :     case RegR14W:
    1440                 :     case RegR15W:
    1441                 :     case RegEAX:
    1442                 :     case RegEBX:
    1443                 :     case RegECX:
    1444                 :     case RegEDX:
    1445                 :     case RegESI:
    1446                 :     case RegEDI:
    1447                 :     case RegEBP:
    1448                 :     case RegESP:
    1449                 :     case RegR8D:
    1450                 :     case RegR9D:
    1451                 :     case RegR10D:
    1452                 :     case RegR11D:
    1453                 :     case RegR12D:
    1454                 :     case RegR13D:
    1455                 :     case RegR14D:
    1456                 :     case RegR15D:
    1457                 :     case RegCS:
    1458                 :     case RegDS:
    1459                 :     case RegSS:
    1460                 :     case RegES:
    1461                 :     case RegFS:
    1462                 :     case RegGS:
    1463                 :     case RegCR0:
    1464                 :     case RegCR1:
    1465                 :     case RegCR2:
    1466                 :     case RegCR3:
    1467                 :     case RegCR4:
    1468                 :     case RegCR5:
    1469                 :     case RegCR6:
    1470                 :     case RegCR7:
    1471                 :     case RegCR8:
    1472                 :     case RegCR9:
    1473                 :     case RegCR10:
    1474                 :     case RegCR11:
    1475                 :     case RegCR12:
    1476                 :     case RegCR13:
    1477                 :     case RegCR14:
    1478                 :     case RegCR15:
    1479                 :     case RegDR0:
    1480                 :     case RegDR1:
    1481                 :     case RegDR2:
    1482                 :     case RegDR3:
    1483                 :     case RegDR4:
    1484                 :     case RegDR5:
    1485                 :     case RegDR6:
    1486                 :     case RegDR7:
    1487                 :     case RegDR8:
    1488                 :     case RegDR9:
    1489                 :     case RegDR10:
    1490                 :     case RegDR11:
    1491                 :     case RegDR12:
    1492                 :     case RegDR13:
    1493                 :     case RegDR14:
    1494                 :     case RegDR15:
    1495                 :     case RegEFLAGS:
    1496                 :     case RegRFLAGS:
    1497                 :     case RegEIP:
    1498                 :     case RegRIP:
    1499                 :     case RegRAX:
    1500                 :     case RegRBX:
    1501                 :     case RegRCX:
    1502                 :     case RegRDX:
    1503                 :     case RegRSI:
    1504                 :     case RegRDI:
    1505                 :     case RegRBP:
    1506                 :     case RegRSP:
    1507                 :     case RegR8:
    1508                 :     case RegR9:
    1509                 :     case RegR10:
    1510                 :     case RegR11:
    1511                 :     case RegR12:
    1512                 :     case RegR13:
    1513                 :     case RegR14:
    1514                 :     case RegR15:
    1515                 :     case RegST0:
    1516                 :     case RegST1:
    1517                 :     case RegST2:
    1518                 :     case RegST3:
    1519                 :     case RegST4:
    1520                 :     case RegST5:
    1521                 :     case RegST6:
    1522                 :     case RegST7:
    1523                 :     case RegMMX1:
    1524                 :     case RegMMX2:
    1525                 :     case RegMMX3:
    1526                 :     case RegMMX4:
    1527                 :     case RegMMX5:
    1528                 :     case RegMMX6:
    1529                 :     case RegMMX7:
    1530                 :     case RegXMM0:
    1531                 :     case RegXMM1:
    1532                 :     case RegXMM2:
    1533                 :     case RegXMM3:
    1534                 :     case RegXMM4:
    1535                 :     case RegXMM5:
    1536                 :     case RegXMM6:
    1537                 :     case RegXMM7:
    1538                 :     case RegXMM8:
    1539                 :     case RegXMM9:
    1540                 :     case RegXMM10:
    1541                 :     case RegXMM11:
    1542                 :     case RegXMM12:
    1543                 :     case RegXMM13:
    1544                 :     case RegXMM14:
    1545                 :     case RegXMM15:
    1546            1310 :       return NaClAppendReg(operand->kind, &state->nodes);
    1547                 :     case RegREIP:
    1548               0 :       return NaClAppendReg(state->address_size == 64 ? RegRIP : RegEIP,
    1549                 :                            &state->nodes);
    1550                 : 
    1551                 :     case RegREAX:
    1552             116 :       return NaClAppendBasedOnSize(RegAX, RegEAX, RegRAX, state);
    1553                 :     case RegREBX:
    1554               0 :       return NaClAppendBasedOnSize(RegBX, RegEBX, RegRBX, state);
    1555                 :     case RegRECX:
    1556               6 :       return NaClAppendBasedOnSize(RegCX, RegECX, RegRCX, state);
    1557                 :     case RegREDX:
    1558              44 :       return NaClAppendBasedOnSize(RegDX, RegEDX, RegRDX, state);
    1559                 :     case RegRESP:
    1560               0 :       return NaClAppendBasedOnSize(RegSP, RegESP, RegRSP, state);
    1561                 :     case RegREBP:
    1562               0 :       return NaClAppendBasedOnSize(RegBP, RegEBP, RegRBP, state);
    1563                 :     case RegRESI:
    1564               0 :       return NaClAppendBasedOnSize(RegSI, RegESI, RegRSI, state);
    1565                 :     case RegREDI:
    1566               0 :       return NaClAppendBasedOnSize(RegDI, RegEDI, RegRSI, state);
    1567                 :     case RegREAXa:
    1568               8 :       return NaClAppendBasedOnAddressSize(RegAX, RegEAX, RegRAX, state);
    1569                 : 
    1570                 :     case RegDS_ESI:
    1571             121 :       return NaClAppendDS_ESI(state);
    1572                 :     case RegDS_EDI:
    1573               6 :       return NaClAppendDS_EDI(state);
    1574                 :     case RegDS_EBX:
    1575               8 :       return NaClAppendDS_EBX(state);
    1576                 :     case RegES_EDI:
    1577             295 :       return NaClAppendES_EDI(state);
    1578                 : 
    1579                 :     case S_Operand:
    1580              13 :       return NaClAppendModRmSegmentReg(state);
    1581                 : 
    1582                 :     case Const_1:
    1583               6 :       return NaClAppendConst(1,
    1584                 :                             NACL_EFLAG(ExprSize8) | NACL_EFLAG(ExprUnsignedHex),
    1585                 :                             &state->nodes);
    1586                 :     default:
    1587                 :       /* Give up, use the default of undefined. */
    1588               0 :       break;
    1589                 :   }
    1590               0 :   return NaClFatal("Operand", state);
    1591            8993 : }
    1592                 : 
    1593                 : /* Given that the given expression node is the root of the expression
    1594                 :  * tree generated by translating the given operand, transfer over
    1595                 :  * any appropriate flags (such as set/use information).
    1596                 :  */
    1597            8993 : static NaClExp* NaClAddOpSetUse(NaClExp* node, const NaClOp* operand) {
    1598            8993 :   if (operand->flags & NACL_OPFLAG(OpSet)) {
    1599            4407 :     node->flags |= NACL_EFLAG(ExprSet);
    1600            4407 :   }
    1601            8993 :   if (operand->flags & NACL_OPFLAG(OpUse)) {
    1602            6113 :     node->flags |= NACL_EFLAG(ExprUsed);
    1603            6113 :   }
    1604            8993 :   if (operand->flags & NACL_OPFLAG(OpAddress)) {
    1605             378 :     node->flags |= NACL_EFLAG(ExprAddress);
    1606             378 :   }
    1607            8993 :   return node;
    1608                 : }
    1609                 : 
    1610            8475 : void NaClBuildExpVector(struct NaClInstState* state) {
    1611            8475 :   uint8_t i;
    1612            8475 :   uint8_t num_ops;
    1613           16950 :   DEBUG(NaClLog(LOG_INFO,
    1614                 :                 "building expression vector for pc = %"NACL_PRIxNaClPcAddress
    1615                 :                 ":\n", state->inst_addr));
    1616            8475 :   num_ops = NaClGetInstNumberOperandsInline(state->inst);
    1617           34936 :   for (i = 0; i < num_ops; i++) {
    1618            8993 :     NaClExp* n;
    1619            8993 :     const NaClOp* op = NaClGetInstOperandInline(state->decoder_tables,
    1620                 :                                                 state->inst, i);
    1621           17986 :     DEBUG(NaClLog(LOG_INFO, "translating operand %d:\n", i));
    1622            8993 :     n = NaClAppendExp(OperandReference, i,
    1623                 :                       NACL_EFLAG(ExprSize8) | NACL_EFLAG(ExprUnsignedInt),
    1624                 :                       &state->nodes);
    1625            8993 :     if (op->flags & NACL_OPFLAG(OpImplicit)) {
    1626             963 :       n->flags |= NACL_EFLAG(ExprImplicit);
    1627             963 :     }
    1628            8993 :     NaClAddOpSetUse(NaClAppendOperand(state, op), op);
    1629           17986 :     DEBUG(NaClExpVectorPrint(NaClLogGetGio(), state));
    1630            8993 :   }
    1631            8475 : }

Generated by: LCOV version 1.7