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

Generated by: LCOV version 1.7