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

Generated by: LCOV version 1.7