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: 563 372 66.1 %
Date: 2014-09-25 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : /*
       8                 :  * Translates the recognized opcode (instruction) in the instruction state
       9                 :  * into an opcode expression.
      10                 :  */
      11                 : 
      12                 : #include "native_client/src/trusted/validator/x86/decoder/nc_inst_trans.h"
      13                 : 
      14                 : #include <stdio.h>
      15                 : #include <assert.h>
      16                 : 
      17                 : #include "native_client/src/shared/platform/nacl_check.h"
      18                 : #include "native_client/src/shared/platform/nacl_log.h"
      19                 : #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state.h"
      20                 : #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_internal.h"
      21                 : #include "native_client/src/trusted/validator/x86/decoder/ncop_exps.h"
      22                 : #include "native_client/src/trusted/validator/x86/nacl_regs.h"
      23                 : 
      24                 : #include "native_client/src/trusted/validator/x86/decoder/ncop_exps_inl.c"
      25                 : #include "native_client/src/trusted/validator/x86/decoder/ncopcode_desc_inl.c"
      26                 : #include "native_client/src/trusted/validator/x86/x86_insts_inl.c"
      27                 : 
      28                 : #if NACL_TARGET_SUBARCH == 64
      29                 : # include "native_client/src/trusted/validator/x86/decoder/gen/nc_subregs_64.h"
      30                 : #else
      31                 : # include "native_client/src/trusted/validator/x86/decoder/gen/nc_subregs_32.h"
      32                 : #endif
      33                 : 
      34                 : /* To turn on debugging of instruction decoding, change value of
      35                 :  * DEBUGGING to 1.
      36                 :  */
      37                 : #define DEBUGGING 0
      38                 : 
      39                 : #include "native_client/src/shared/utils/debugging.h"
      40                 : 
      41                 : /* Return the segment register to use, based on prefix specification,
      42                 :  * or reg_default if no prefix specified.
      43                 :  */
      44                 : static NaClOpKind NaClGetSegmentPrefixReg(NaClInstState* state,
      45               1 :                                           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               1 :   if (32 == NACL_TARGET_SUBARCH) {
      50                 :     if (state->prefix_mask &
      51                 :         (kPrefixSEGCS | kPrefixSEGSS | kPrefixSEGFS |
      52               1 :          kPrefixSEGGS | kPrefixSEGES | kPrefixSEGDS)) {
      53                 :       int i;
      54               1 :       for (i = state->num_prefix_bytes - 1; (i >= 0); --i) {
      55               1 :         switch (state->bytes.byte[i]) {
      56                 :           case kValueSEGCS:
      57               0 :             return RegCS;
      58                 :           case kValueSEGSS:
      59               0 :             return RegSS;
      60                 :           case kValueSEGFS:
      61               1 :             return RegFS;
      62                 :           case kValueSEGGS:
      63               1 :             return RegGS;
      64                 :           case kValueSEGES:
      65               0 :             return RegES;
      66                 :           case kValueSEGDS:
      67               0 :             return RegDS;
      68                 :           default:
      69                 :             break;
      70                 :         }
      71               1 :       }
      72                 :     }
      73               1 :   } else if (state->prefix_mask &
      74                 :              /* Only GS and FS matter in 64-bit mode. */
      75               0 :              (kPrefixSEGGS | kPrefixSEGFS)) {
      76                 :     int i;
      77               0 :     for (i = state->num_prefix_bytes - 1; (i >= 0); --i) {
      78                 :     /* for (i = 0; i < state->num_prefix_bytes; ++i) { */
      79               0 :       switch (state->bytes.byte[i]) {
      80                 :         case kValueSEGFS:
      81               0 :           return RegFS;
      82                 :         case kValueSEGGS:
      83               0 :           return RegGS;
      84                 :         default:
      85                 :           break;
      86                 :       }
      87               0 :     }
      88                 :   }
      89               1 :   return reg_default;
      90               1 : }
      91                 : 
      92                 : /* Return the segment register to use if DS is the default. */
      93               1 : static INLINE NaClOpKind NaClGetDsSegmentReg(NaClInstState* state) {
      94               1 :   return NaClGetSegmentPrefixReg(state, RegDS);
      95               1 : }
      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               0 : }
     101                 : 
     102                 : /* Append the given expression node onto the given vector of expression
     103                 :  * nodes. Returns the appended expression node.
     104                 :  */
     105                 : static INLINE NaClExp* NaClAppendExp(NaClExpKind kind,
     106                 :                                      uint64_t value,
     107                 :                                      NaClExpFlags flags,
     108               1 :                                      NaClExpVector* vector) {
     109                 :   NaClExp* node;
     110               1 :   assert(vector->number_expr_nodes < NACL_MAX_EXPS);
     111                 :   /* If this is not a register expression, we should have specified a size. */
     112                 :   CHECK(ExprRegister == kind || (0 != (flags & (NACL_EFLAG(ExprSize8) |
     113                 :                                                 NACL_EFLAG(ExprSize16) |
     114                 :                                                 NACL_EFLAG(ExprSize32) |
     115                 :                                                 NACL_EFLAG(ExprSize48) |
     116               1 :                                                 NACL_EFLAG(ExprSize64)))));
     117               1 :   node = &vector->node[vector->number_expr_nodes++];
     118               1 :   node->kind = kind;
     119               1 :   node->value = value;
     120               1 :   node->flags = flags;
     121               1 :   return node;
     122               1 : }
     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                 : static NaClExp* NaClFatal(const char* message,
     140               0 :                           NaClInstState* state) {
     141                 :   NaClLog(LOG_ERROR,
     142                 :           "FATAL: At %"NACL_PRIxNaClPcAddress", unable to translate: %s\n",
     143               0 :           NaClInstStatePrintableAddress(state), message);
     144               0 :   exit(1);
     145                 :   /* NOT REACHED */
     146                 :   return NULL;
     147                 : }
     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                 :       break;
     167                 :   }
     168                 :   NaClFatal("Unable to determine segment regsiter from instruction name",
     169               0 :             state);
     170                 :   /* NOT REACHED */
     171               0 :   return RegUnknown;
     172               0 : }
     173                 : 
     174                 : /* Append that we don't bother to translate the instruction argument,
     175                 :  * since it is NaCl illegal. Used to handle cases where we don't implement
     176                 :  * 16-bit modrm effective addresses.
     177                 :  */
     178               1 : static INLINE NaClExp* NaClAppendNaClIllegal(NaClInstState* state) {
     179                 :   return NaClAppendExp(ExprNaClIllegal, 0,
     180               1 :                        NACL_EFLAG(ExprSize16), &state->nodes);
     181               1 : }
     182                 : 
     183                 : /* Append the given constant onto the given vector of expression
     184                 :  * nodes. Returns the appended expression node.
     185                 :  */
     186                 : static INLINE NaClExp* NaClAppendConst(uint64_t value, NaClExpFlags flags,
     187               1 :                                        NaClExpVector* vector) {
     188                 :   DEBUG(
     189                 :       NaClLog(LOG_INFO, "Append constant %"NACL_PRIx64" : ", value);
     190                 :       NaClPrintExpFlags(NaClLogGetGio(), flags);
     191               1 :       gprintf(NaClLogGetGio(), "\n"));
     192               1 :   return NaClAppendExp(ExprConstant, value, flags, vector);
     193               1 : }
     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               0 : }
     211                 : 
     212               0 : NaClOpKind NaClGet32For64BitReg(NaClOpKind reg64) {
     213               0 :   int index = NaClGpReg64Index[reg64];
     214                 :   return (index == NACL_REGISTER_UNDEFINED)
     215                 :       ? RegUnknown
     216               0 :       : NaClRegTable32[index];
     217               0 : }
     218                 : 
     219                 : Bool NaClIs64Subreg(NaClInstState* state,
     220               0 :                     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               0 : }
     234                 : 
     235               0 : Bool NaClIs32To64RegPair(NaClOpKind reg32, NaClOpKind reg64) {
     236               0 :   return reg64 == NaClGet64For32BitReg(reg32);
     237               0 : }
     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               0 : }
     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               1 : static NaClRegKind NaClGetOpKindRegKind(NaClOpKind kind) {
     318               1 :   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               1 :       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               1 :       return RegUndefined;
     364                 :   }
     365               1 : }
     366                 : 
     367                 : static NaClOpKind NaClLookupReg(NaClInstState* state,
     368               1 :                                 NaClRegKind kind, int reg_index) {
     369                 :   DEBUG(NaClLog(LOG_INFO,
     370                 :                 "Lookup register (rex=%"NACL_PRIx8") %s:%d\n",
     371               1 :                 state->rexprefix, NaClRegKindName(kind), reg_index));
     372               1 :   if (32 == NACL_TARGET_SUBARCH && kind == RegSize64) {
     373               0 :     NaClLost("Architecture doesn't define 64 bit registers");
     374               1 :   } else if (RegSize128 <= kind) {
     375               0 :     return RegUnknown;
     376                 :   }
     377               1 :   if (64 == NACL_TARGET_SUBARCH && kind == RegSize8 && state->rexprefix) {
     378               0 :     return NaClRegTable8Rex[reg_index];
     379                 :   }
     380               1 :   return (*(NaClRegTable[kind]))[reg_index];
     381               1 : }
     382                 : 
     383                 : /* Returns the (NaClExpFlag) size of the given register. */
     384               1 : static NaClExpFlags NaClGetRegSize(NaClOpKind register_name) {
     385               1 :   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               1 :     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               1 :     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               1 :     return NACL_EFLAG(ExprSize32);
     441                 :   case RegCS:
     442                 :   case RegDS:
     443                 :   case RegSS:
     444                 :   case RegES:
     445                 :   case RegFS:
     446                 :   case RegGS:
     447               1 :     return NACL_EFLAG(ExprSize16);
     448                 :   case RegEIP:
     449               1 :     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               1 :     return 0;
     471                 :   }
     472               1 : }
     473                 : 
     474                 : /* Appends the given kind of register onto the vector of expression nodes.
     475                 :  * Returns the appended register.
     476                 :  */
     477               1 : static INLINE NaClExp* NaClAppendReg(NaClOpKind r, NaClExpVector* vector) {
     478                 :   NaClExp* node;
     479               1 :   DEBUG(NaClLog(LOG_INFO, "append register %s\n", NaClOpKindName(r)));
     480               1 :   node = NaClAppendExp(ExprRegister, r, NaClGetRegSize(r), vector);
     481               1 :   return node;
     482               1 : }
     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                 : static INLINE NaClExp* NaClAppendRegKind(NaClInstState* state,
     489               1 :                                          NaClRegKind kind, int reg_index) {
     490                 :   DEBUG(NaClLog(LOG_INFO, "NaClAppendRegKind(%d, %d) = %s\n",
     491               1 :                 (int) kind, reg_index, NaClRegKindName(kind)));
     492               1 :   return NaClAppendReg(NaClLookupReg(state, kind, reg_index), &state->nodes);
     493               1 : }
     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                 : static NaClRegKind NaClExtractOpRegKind(NaClInstState* state,
     500               1 :                                         const NaClOp* operand) {
     501               1 :   NaClRegKind reg_kind = NaClGetOpKindRegKind(operand->kind);
     502               1 :   switch (reg_kind) {
     503                 :     case RegSize8:
     504                 :     case RegSize16:
     505                 :     case RegSize32:
     506                 :     case RegSize64:
     507               1 :       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               1 :       if (state->inst->flags & NACL_IFLAG(OperandSize_b)) {
     517               1 :         return RegSize8;
     518               1 :       } else if (state->operand_size == 1) {
     519               0 :         return RegSize8;
     520               1 :       } else if (state->operand_size == 4) {
     521               1 :         return RegSize32;
     522               1 :       } else if (state->operand_size == 2) {
     523               1 :         return RegSize16;
     524               0 :       } else if (state->operand_size == 8) {
     525               0 :         return RegSize64;
     526                 :       } else {
     527               0 :         return RegSize32;
     528                 :       }
     529                 :   }
     530               1 : }
     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               1 : static INLINE NaClRegKind NaClExtractAddressRegKind(NaClInstState* state) {
     536               1 :   if (state->address_size == 16) {
     537               0 :     return RegSize16;
     538               1 :   } else if (state->address_size == 64) {
     539               0 :     return RegSize64;
     540                 :   } else {
     541               1 :     return RegSize32;
     542                 :   }
     543               1 : }
     544                 : 
     545                 : /* Given we want to translate an operand (of the form G_Operand),
     546                 :  * for the given register index, generate the corresponding register
     547                 :  * expression, and append it to the vector of expression nodes.
     548                 :  * Returns the appended register.
     549                 :  */
     550                 : static NaClExp* NaClAppendOperandReg(
     551                 :     NaClInstState* state,
     552                 :     const NaClOp* operand,
     553                 :     int reg_index,
     554               1 :     NaClModRmRegKind modrm_reg_kind) {
     555               1 :   NaClRegKind reg_kind = RegSize32;
     556                 :   DEBUG(NaClLog(LOG_INFO, "modrm_reg_kind = %s\n",
     557               1 :                 g_NaClModRmRegKindName[modrm_reg_kind]));
     558               1 :   switch (modrm_reg_kind) {
     559                 :     default:
     560                 :     case ModRmGeneral:
     561               1 :       reg_kind = NaClExtractOpRegKind(state, operand);
     562               1 :       break;
     563                 :     case ModRmMmx:
     564               0 :       reg_kind = RegMMX;
     565               0 :       break;
     566                 :     case ModRmXmm:
     567               1 :       reg_kind = RegXMM;
     568               1 :       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               1 :                 reg_index, g_NaClRegKindName[reg_kind]));
     580               1 :   return NaClAppendRegKind(state, reg_kind, reg_index);
     581               1 : }
     582                 : 
     583                 : static NaClExpFlags NaClGetAddressExprSizeFlagsForState(NaClInstState* state);
     584                 : 
     585               1 : static NaClExp* NaClAppendSegmentAddress(NaClInstState* state) {
     586               1 :   NaClExpFlags flags = NaClGetAddressExprSizeFlagsForState(state);
     587               1 :   return NaClAppendExp(ExprSegmentAddress, 0, flags, &state->nodes);
     588               1 : }
     589                 : 
     590                 : /* Same as NaClAppendOperandReg, except that a segment register is combined with
     591                 :  * the indexed register to define a segment address.
     592                 :  */
     593                 : static NaClExp* NaClAppendSegmentOpReg(
     594                 :     NaClInstState* state,
     595                 :     const NaClOp* operand,
     596                 :     NaClOpKind seg_register,
     597                 :     int reg_index,
     598               0 :     NaClModRmRegKind modrm_reg_kind) {
     599               0 :   NaClExp* results = NaClAppendSegmentAddress(state);
     600               0 :   NaClAppendReg(seg_register, &state->nodes);
     601               0 :   NaClAppendOperandReg(state, operand, reg_index, modrm_reg_kind);
     602               0 :   return results;
     603               0 : }
     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               0 : }
     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               1 : static INLINE int NaClGetRexRReg(NaClInstState* state, int reg) {
     625               1 :   DEBUG(NaClLog(LOG_INFO, "Get GenRexRRegister %d\n", reg));
     626               1 :   if (NACL_TARGET_SUBARCH == 64 && (state->rexprefix & 0x4)) {
     627               0 :     reg += 8;
     628                 :   }
     629               1 :   return reg;
     630               1 : }
     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               1 : static INLINE int NaClGetRexXReg(NaClInstState* state, int reg) {
     636               1 :   DEBUG(NaClLog(LOG_INFO, "Get GenRexXRegister\n"));
     637               1 :   if (NACL_TARGET_SUBARCH == 64 && (state->rexprefix & 0x2)) {
     638               0 :     reg += 8;
     639                 :   }
     640               1 :   return reg;
     641               1 : }
     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               1 : static INLINE int NaClGetRexBReg(NaClInstState* state, int reg) {
     647               1 :   DEBUG(NaClLog(LOG_INFO, "Get GenRexBRegister\n"));
     648               1 :   if (NACL_TARGET_SUBARCH == 64 && (state->rexprefix & 0x1)) {
     649               0 :     DEBUG(NaClLog(LOG_INFO, "rexprefix == %02x\n", state->rexprefix));
     650               0 :     reg += 8;
     651                 :   }
     652               1 :   return reg;
     653               1 : }
     654                 : 
     655                 : /* Return the general purpose register associated with the modrm.reg
     656                 :  * field.
     657                 :  */
     658               1 : static INLINE int NaClGetGenRegRegister(NaClInstState* state) {
     659               1 :   DEBUG(NaClLog(LOG_INFO, "Get GenRegRegister\n"));
     660               1 :   return NaClGetRexRReg(state, modrm_regInline(state->modrm));
     661               1 : }
     662                 : 
     663                 : /* Return the general purpose register associated with the modrm.rm
     664                 :  * field.
     665                 :  */
     666               1 : static INLINE int NaClGetGenRmRegister(NaClInstState* state) {
     667               1 :   DEBUG(NaClLog(LOG_INFO, "Get GenRmRegister\n"));
     668               1 :   return NaClGetRexBReg(state, modrm_rmInline(state->modrm));
     669               1 : }
     670                 : 
     671                 : /* Get the register index from the difference of the opcode, and
     672                 :  * its opcode base.
     673                 :  */
     674                 : static NaClExp* NaClAppendOpcodeBaseReg(
     675               1 :     NaClInstState* state, const NaClOp* operand) {
     676                 :   int reg_index;
     677               1 :   reg_index = NaClGetOpcodePlusR(state->inst->opcode_ext);
     678               1 :   assert(reg_index >= 0 && reg_index < 8);
     679               1 :   DEBUG(NaClLog(LOG_INFO, "Translate opcode base register %d\n", reg_index));
     680                 :   return NaClAppendRegKind(state, NaClExtractOpRegKind(state, operand),
     681               1 :                             NaClGetRexBReg(state, reg_index));
     682               1 : }
     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               0 :   DEBUG(NaClLog(LOG_INFO, "Translate opcode base register %d\n", reg_index));
     692               0 :   return NaClAppendReg(RegST0 + reg_index, &state->nodes);
     693               0 : }
     694                 : 
     695                 : /* Model the extraction of a displacement value and the associated flags. */
     696                 : typedef struct NaClDisplacement {
     697                 :   uint64_t value;
     698                 :   NaClExpFlags flags;
     699                 : } NaClDisplacement;
     700                 : 
     701                 : static INLINE void NaClInitializeDisplacement(
     702                 :     uint64_t value, NaClExpFlags flags,
     703               1 :     NaClDisplacement* displacement) {
     704               1 :   displacement->value = value;
     705               1 :   displacement->flags = flags;
     706               1 : }
     707                 : 
     708                 : /* Extract the binary value from the specified bytes of the instruction. */
     709                 : static uint64_t NaClExtractUnsignedBinaryValue(NaClInstState* state,
     710               1 :                                                int start_byte, int num_bytes) {
     711                 :   int i;
     712               1 :   uint64_t value = 0;
     713               1 :   for (i = 0; i < num_bytes; ++i) {
     714               1 :     uint8_t byte = state->bytes.byte[start_byte + i];
     715               1 :     value += (((uint64_t) byte) << (i * 8));
     716               1 :   }
     717               1 :   return value;
     718               1 : }
     719                 : 
     720                 : static int64_t NaClExtractSignedBinaryValue(NaClInstState* state,
     721               1 :                                             int start_byte, int num_bytes) {
     722                 :   /* Assumes little endian. */
     723               1 :   uint8_t* address = &state->bytes.byte[start_byte];
     724               1 :   switch (num_bytes) {
     725                 :     case 1:
     726               1 :       return *(int8_t*) address;
     727                 :     case 2:
     728               0 :       return *(int16_t*) address;
     729                 :     case 4:
     730               1 :       return *(int32_t*) address;
     731                 :     default:
     732               0 :       CHECK(0);
     733               0 :       return -1;
     734                 :   }
     735               1 : }
     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               1 : static NaClExpFlags NaClGetExprSizeFlagForBytes(uint8_t num_bytes) {
     741               1 :   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               1 :       return NACL_EFLAG(ExprSize8);
     749                 :     case 2:
     750               1 :       return NACL_EFLAG(ExprSize16);
     751                 :     case 4:
     752               1 :       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               1 : }
     762                 : 
     763                 : /* Return the expr flag for the address size associated with the state. */
     764               1 : static NaClExpFlags NaClGetAddressExprSizeFlagsForState(NaClInstState* state) {
     765               1 :   uint8_t size = NaClInstStateAddressSize(state);
     766               1 :   return NaClGetExprSizeFlagForBytes(size / 8);
     767               1 : }
     768                 : 
     769                 : /* Given the corresponding instruction state, return the
     770                 :  * corresponding displacement value, and any expression node
     771                 :  * flags that should be associated with the displacement value.
     772                 :  */
     773                 : static void NaClExtractDisplacement(NaClInstState* state,
     774                 :                                     NaClDisplacement* displacement,
     775               1 :                                     NaClExpFlags flags) {
     776                 :   DEBUG(NaClLog(LOG_INFO, "-> Extract displacement, flags = ");
     777                 :         NaClPrintExpFlags(NaClLogGetGio(), flags);
     778               1 :         gprintf(NaClLogGetGio(), "\n"));
     779                 :   /* First compute the displacement value. */
     780                 :   displacement->value = NaClExtractUnsignedBinaryValue(state,
     781                 :                                                        state->first_disp_byte,
     782               1 :                                                        state->num_disp_bytes);
     783                 : 
     784                 :   /* Now compute any appropriate flags to be associated with the value. */
     785                 :   displacement->flags = flags |
     786               1 :       NaClGetExprSizeFlagForBytes(state->num_disp_bytes);
     787                 :   DEBUG(NaClLog(LOG_INFO,
     788                 :                 "<- value = %"NACL_PRIx64", flags = ", displacement->value);
     789                 :         NaClPrintExpFlags(NaClLogGetGio(), displacement->flags);
     790               1 :         gprintf(NaClLogGetGio(), "\n"));
     791               1 : }
     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               1 : static NaClExp* NaClAppendDisplacement(NaClInstState* state) {
     798                 :   NaClDisplacement displacement;
     799               1 :   DEBUG(NaClLog(LOG_INFO, "append displacement\n"));
     800               1 :   NaClExtractDisplacement(state, &displacement, NACL_EFLAG(ExprSignedHex));
     801               1 :   return NaClAppendConst(displacement.value, displacement.flags, &state->nodes);
     802               1 : }
     803                 : 
     804                 : /* Get the binary value denoted by the immediate bytes of the state. */
     805               1 : static uint64_t NaClExtractUnsignedImmediate(NaClInstState* state) {
     806                 :   return NaClExtractUnsignedBinaryValue(state,
     807                 :                                         state->first_imm_byte,
     808               1 :                                         state->num_imm_bytes);
     809               1 : }
     810                 : 
     811                 : /* Get the binary value denoted by the 2nd immediate bytes of the state. */
     812               1 : static uint64_t NaClExtractUnsignedImmediate2(NaClInstState* state) {
     813                 :   return NaClExtractUnsignedBinaryValue(
     814                 :       state,
     815                 :       state->first_imm_byte + state->num_imm_bytes,
     816               1 :       state->num_imm2_bytes);
     817               1 : }
     818                 : 
     819                 : /* Get the binary value denoted by the immediate bytes of the state. */
     820               1 : static int64_t NaClExtractSignedImmediate(NaClInstState* state) {
     821                 :   return NaClExtractSignedBinaryValue(state,
     822                 :                                       state->first_imm_byte,
     823               1 :                                       state->num_imm_bytes);
     824               1 : }
     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               1 : static NaClExp* NaClAppendImmed(NaClInstState* state) {
     830                 :   NaClExpFlags flags;
     831                 : 
     832                 :   /* First compute the immediate value. */
     833                 :   uint64_t value;
     834               1 :   DEBUG(NaClLog(LOG_INFO, "append immediate\n"));
     835               1 :   value = NaClExtractUnsignedImmediate(state);
     836                 : 
     837                 :   /* Now compute any appropriate flags to be associated with the immediate
     838                 :    * value.
     839                 :    */
     840                 :   flags = NACL_EFLAG(ExprUnsignedHex) |
     841               1 :       NaClGetExprSizeFlagForBytes(state->num_imm_bytes);
     842                 : 
     843                 :   /* Append the generated immediate value onto the vector. */
     844               1 :   return NaClAppendConst(value, flags, &state->nodes);
     845               1 : }
     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               1 :   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                 :   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               1 : }
     869                 : 
     870                 : /* Append an ExprMemOffset node for the given state, and return
     871                 :  * the appended ndoe.
     872                 :  */
     873               1 : static NaClExp* NaClAppendMemOffsetNode(NaClInstState* state) {
     874               1 :   NaClExpFlags flags = NaClGetAddressExprSizeFlagsForState(state);
     875               1 :   NaClExp* root = NaClAppendExp(ExprMemOffset, 0, flags, &state->nodes);
     876                 :   DEBUG(NaClLog(LOG_INFO, "Build memoffset, flags = ");
     877                 :         NaClPrintExpFlags(NaClLogGetGio(), flags);
     878               1 :         gprintf(NaClLogGetGio(), "\n"));
     879               1 :   return root;
     880               1 : }
     881                 : 
     882                 : /* Returns the segment register prefix node, or NULL if no such node is
     883                 :  * added.
     884                 :  */
     885                 : static NaClExp* NaClAppendSegmentAddressNode(NaClInstState* state,
     886               1 :                                              NaClOpKind reg_default) {
     887               1 :   NaClExp* root = NULL;
     888               1 :   NaClOpKind seg_reg = NaClGetSegmentPrefixReg(state, reg_default);
     889               1 :   if (seg_reg != RegUnknown) {
     890                 :     NaClExp* n;
     891               1 :     root = NaClAppendSegmentAddress(state);
     892               1 :     n = NaClAppendReg(seg_reg, &state->nodes);
     893               1 :     n->flags |= NACL_EFLAG(ExprUsed);
     894                 :   }
     895               1 :   return root;
     896               1 : }
     897                 : 
     898                 : /* Append the immediate value of the given instruction as the displacement
     899                 :  * of a memory offset.
     900                 :  */
     901               1 : static NaClExp* NaClAppendMemoryOffsetImmed(NaClInstState* state) {
     902                 :   NaClExpFlags flags;
     903                 :   uint64_t value;
     904                 :   NaClExp* root;
     905               1 :   DEBUG(NaClLog(LOG_INFO, "append memory offset immediate\n"));
     906               1 :   root = NaClAppendSegmentAddressNode(state, RegUnknown);
     907               1 :   if (root == NULL) {
     908               1 :     root = NaClAppendMemOffsetNode(state);
     909               1 :   } else {
     910               1 :     NaClAppendMemOffsetNode(state);
     911                 :   }
     912               1 :   NaClAppendReg(RegUnknown, &state->nodes);
     913               1 :   NaClAppendReg(RegUnknown, &state->nodes);
     914               1 :   NaClAppendConst(1, NACL_EFLAG(ExprSize8), &state->nodes);
     915               1 :   value = NaClExtractUnsignedImmediate(state);
     916               1 :   DEBUG(NaClLog(LOG_INFO, "value = 0x%016"NACL_PRIx64"\n", value));
     917                 :   flags = NACL_EFLAG(ExprUnsignedHex) |
     918               1 :       NaClGetExprSizeFlagForBytes(state->num_imm_bytes);
     919               1 :   NaClAppendConst(value, flags, &state->nodes);
     920               1 :   return root;
     921               1 : }
     922                 : 
     923               1 : static NaClExp* NaClAppendRelativeImmed(NaClInstState* state) {
     924               1 :   NaClPcNumber jump_offset = (NaClPcNumber) NaClExtractSignedImmediate(state);
     925               1 :   DEBUG(NaClLog(LOG_INFO, "append relative immediate\n"));
     926                 :   return NaClAppendConst(jump_offset,
     927                 :                          NACL_EFLAG(ExprSignedHex) |
     928                 :                          NaClGetExprSizeFlagForBytes(state->num_imm_bytes) |
     929                 :                          NACL_EFLAG(ExprJumpTarget),
     930               1 :                          &state->nodes);
     931               1 : }
     932                 : 
     933                 : /* Append a memory offset for the given memory offset defined by
     934                 :  * the formula "base + index*scale + displacement". If no index
     935                 :  * is used, its value should be RegUnknown. Argument displacement_flags
     936                 :  * are flags that should be associated with the generated displacement
     937                 :  * value
     938                 :  */
     939                 : static NaClExp* NaClAppendMemoryOffset(NaClInstState* state,
     940                 :                                        NaClOpKind base,
     941                 :                                        NaClOpKind index,
     942                 :                                        uint8_t scale,
     943               1 :                                        NaClDisplacement* displacement) {
     944               1 :   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               1 :                 displacement->flags));
     956                 : 
     957               1 :   if (32 == NACL_TARGET_SUBARCH) {
     958                 :     seg_reg_default = ((base == RegBP || base == RegEBP)
     959               1 :                        ? RegSS : NaClGetDsSegmentReg(state));
     960               1 :   } else {
     961               0 :     seg_reg_default = RegUnknown;
     962                 :   }
     963               1 :   root = NaClAppendSegmentAddressNode(state, seg_reg_default);
     964               1 :   if (NULL == root) {
     965               0 :     root = NaClAppendMemOffsetNode(state);
     966               0 :   } else {
     967               1 :     NaClAppendMemOffsetNode(state);
     968                 :   }
     969               1 :   n = NaClAppendReg(base, &state->nodes);
     970               1 :   if (base != RegUnknown) {
     971               1 :     n->flags |= NACL_EFLAG(ExprUsed);
     972                 :   }
     973               1 :   n = NaClAppendReg(index, &state->nodes);
     974               1 :   if (index == RegUnknown) {
     975                 :     /* Scale not applicable, check that value is 1. */
     976               1 :     assert(scale == 1);
     977               1 :   } else {
     978               1 :     n->flags |= NACL_EFLAG(ExprUsed);
     979                 :   }
     980               1 :   NaClAppendConst(scale, NACL_EFLAG(ExprSize8), &state->nodes);
     981               1 :   NaClAppendConst(displacement->value, displacement->flags, &state->nodes);
     982               1 :   DEBUG(NaClLog(LOG_INFO, "finished appending memory offset:\n"));
     983               1 :   DEBUG(NaClExpVectorPrint(NaClLogGetGio(), state));
     984               1 :   return root;
     985               1 : }
     986                 : 
     987                 : /* Extract the base register from the SIB byte. */
     988               1 : static NaClOpKind NaClGetSibBase(NaClInstState* state) {
     989               1 :   int base = sib_base(state->sib);
     990               1 :   NaClOpKind base_reg = RegUnknown;
     991               1 :   if (0x5 == base) {
     992               1 :     switch (modrm_modInline(state->modrm)) {
     993                 :       case 0:
     994               1 :         break;
     995                 :       case 1:
     996                 :       case 2:
     997               1 :         if (NACL_TARGET_SUBARCH == 64) {
     998               0 :           if (state->rexprefix & 0x1) {
     999               0 :             base_reg = RegR13;
    1000               0 :           } else {
    1001               0 :             base_reg = RegRBP;
    1002                 :           }
    1003               0 :         } else {
    1004               1 :           base_reg = RegEBP;
    1005                 :         }
    1006               1 :         break;
    1007                 :       default:
    1008               0 :         NaClFatal("SIB value", state);
    1009                 :     }
    1010               1 :   } else {
    1011               1 :     NaClRegKind kind = NaClExtractAddressRegKind(state);
    1012               1 :     base_reg = NaClLookupReg(state, kind, NaClGetRexBReg(state, base));
    1013                 :   }
    1014               1 :   return base_reg;
    1015               1 : }
    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               1 : static NaClExp* NaClAppendSib(NaClInstState* state) {
    1028               1 :   int index = sib_index(state->sib);
    1029               1 :   int scale = 1;
    1030               1 :   NaClRegKind kind = NaClExtractAddressRegKind(state);
    1031                 :   NaClOpKind base_reg;
    1032               1 :   NaClOpKind index_reg = RegUnknown;
    1033                 :   NaClDisplacement displacement;
    1034               1 :   DEBUG(NaClLog(LOG_INFO, "append sib: %02x\n", state->sib));
    1035               1 :   NaClInitializeDisplacement(0, 0, &displacement);
    1036               1 :   base_reg = NaClGetSibBase(state);
    1037               1 :   if (0x4 != index || NACL_TARGET_SUBARCH != 64 || (state->rexprefix & 0x2)) {
    1038               1 :     index_reg = NaClLookupReg(state, kind, NaClGetRexXReg(state, index));
    1039               1 :     scale = nacl_sib_scale[sib_ss(state->sib)];
    1040                 :   }
    1041               1 :   if (state->num_disp_bytes > 0) {
    1042                 :     NaClExtractDisplacement(state, &displacement,
    1043               1 :                         NACL_EFLAG(ExprSignedHex));
    1044               1 :   } else {
    1045               1 :     displacement.flags = NACL_EFLAG(ExprSize8);
    1046                 :   }
    1047                 :   return NaClAppendMemoryOffset(state, base_reg, index_reg,
    1048               1 :                                 scale, &displacement);
    1049               1 : }
    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                 :       NaClFatal("Address size for %EDI not correctly defined",
    1064               0 :                 state);
    1065                 :       break;
    1066                 :   }
    1067               0 : }
    1068                 : 
    1069               0 : static void NaClAppendESI(NaClInstState* state) {
    1070               0 :   switch (state->address_size) {
    1071                 :     case 16:
    1072               0 :       NaClAppendReg(RegSI, &state->nodes);
    1073               0 :       break;
    1074                 :     case 32:
    1075               0 :       NaClAppendReg(RegESI, &state->nodes);
    1076               0 :       break;
    1077                 :     case 64:
    1078               0 :       NaClAppendReg(RegRSI, &state->nodes);
    1079               0 :       break;
    1080                 :     default:
    1081               0 :       NaClFatal("Address size for %ESI not correctly defined", state);
    1082                 :       break;
    1083                 :   }
    1084               0 : }
    1085               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                 :       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               0 : }
    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               0 : }
    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               1 : }
    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               0 : }
    1133                 : 
    1134                 : /* Get the Effective address in the mod/rm byte, if the modrm.mod field
    1135                 :  * is 00, and append it to the vector of expression nodes. Operand is
    1136                 :  * the corresponding operand of the opcode associated with the instruction
    1137                 :  * of the given state that corresponds to the effective address. Returns
    1138                 :  * the root of the appended effective address.
    1139                 :  */
    1140                 : static NaClExp* NaClAppendMod00EffectiveAddress(
    1141               1 :     NaClInstState* state, const NaClOp* operand) {
    1142               1 :   DEBUG(NaClLog(LOG_INFO, "Translate modrm(%02x).mod == 00\n", state->modrm));
    1143                 :   if ((32 == NACL_TARGET_SUBARCH) &&
    1144               1 :       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               1 :     return NaClAppendNaClIllegal(state);
    1149                 :   }
    1150               1 :   switch (modrm_rmInline(state->modrm)) {
    1151                 :     case 4:
    1152               1 :       return NaClAppendSib(state);
    1153                 :     case 5:
    1154               1 :       if (NACL_TARGET_SUBARCH == 64) {
    1155                 :         NaClDisplacement displacement;
    1156                 :         NaClExtractDisplacement(state, &displacement,
    1157               0 :                                 NACL_EFLAG(ExprSignedHex));
    1158                 :         return NaClAppendMemoryOffset(state,
    1159                 :                                       RegRIP,
    1160                 :                                       RegUnknown,
    1161                 :                                       1,
    1162               0 :                                       &displacement);
    1163                 :       } else {
    1164               1 :         return NaClAppendDisplacement(state);
    1165                 :       }
    1166                 :     default: {
    1167                 :       NaClDisplacement displacement;
    1168               1 :       NaClInitializeDisplacement(0, NACL_EFLAG(ExprSize8), &displacement);
    1169                 :       return NaClAppendMemoryOffset(state,
    1170                 :                                     NaClLookupReg(
    1171                 :                                         state,
    1172                 :                                         NaClExtractAddressRegKind(state),
    1173                 :                                         NaClGetGenRmRegister(state)),
    1174                 :                                     RegUnknown,
    1175                 :                                     1,
    1176               1 :                                     &displacement);
    1177                 :     }
    1178                 :   }
    1179                 :   /* NOT REACHED */
    1180                 :   return NULL;
    1181               1 : }
    1182                 : 
    1183                 : /* Get the Effective address in the mod/rm byte, if the modrm.mod field
    1184                 :  * is 01, and append it to the vector of expression nodes. Operand is
    1185                 :  * the corresponding operand of the opcode associated with the instruction
    1186                 :  * of the given state that corresponds to the effective address. Returns
    1187                 :  * the root of the appended effective address.
    1188                 :  */
    1189                 : static NaClExp* NaClAppendMod01EffectiveAddress(
    1190               1 :     NaClInstState* state, const NaClOp* operand) {
    1191               1 :   DEBUG(NaClLog(LOG_INFO, "Translate modrm(%02x).mod == 01\n", state->modrm));
    1192                 :   if ((32 == NACL_TARGET_SUBARCH) &&
    1193               1 :       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               1 :   if (4 == modrm_rmInline(state->modrm)) {
    1200               1 :     return NaClAppendSib(state);
    1201                 :   } else {
    1202                 :     NaClDisplacement displacement;
    1203               1 :     NaClExtractDisplacement(state, &displacement, NACL_EFLAG(ExprSignedHex));
    1204                 :     return NaClAppendMemoryOffset(state,
    1205                 :                                   NaClLookupReg(
    1206                 :                                       state,
    1207                 :                                       NaClExtractAddressRegKind(state),
    1208                 :                                       NaClGetGenRmRegister(state)),
    1209                 :                                   RegUnknown,
    1210                 :                                   1,
    1211               1 :                                   &displacement);
    1212                 :   }
    1213               1 : }
    1214                 : 
    1215                 : /* Get the Effective address in the mod/rm byte, if the modrm.mod field
    1216                 :  * is 10, and append it to the vector of expression nodes. Operand is
    1217                 :  * the corresponding operand of the opcode associated with the instruction
    1218                 :  * of the given state that corresponds to the effective address. Returns
    1219                 :  * the root of the appended effective address.
    1220                 :  */
    1221                 : static NaClExp* NaClAppendMod10EffectiveAddress(
    1222               1 :     NaClInstState* state, const NaClOp* operand) {
    1223               1 :   DEBUG(NaClLog(LOG_INFO, "Translate modrm(%02x).mod == 10\n", state->modrm));
    1224                 :   if ((32 == NACL_TARGET_SUBARCH) &&
    1225               1 :       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               1 :   if (4 == modrm_rmInline(state->modrm)) {
    1232               1 :     return NaClAppendSib(state);
    1233                 :   } else {
    1234                 :     NaClDisplacement displacement;
    1235                 :     NaClOpKind base =
    1236                 :         NaClLookupReg(state,
    1237                 :                       NaClExtractAddressRegKind(state),
    1238               1 :                       NaClGetGenRmRegister(state));
    1239               1 :     NaClExtractDisplacement(state, &displacement, NACL_EFLAG(ExprSignedHex));
    1240               1 :     return NaClAppendMemoryOffset(state, base, RegUnknown, 1, &displacement);
    1241                 :   }
    1242               1 : }
    1243                 : 
    1244                 : /* Get the Effective address in the mod/rm byte, if the modrm.mod field
    1245                 :  * is 11, and append it to the vector of expression nodes. Operand is
    1246                 :  * the corresponding operand of the opcode associated with the instruction
    1247                 :  * of the given state that corresponds to the effective address. Returns
    1248                 :  * the root of the appended effective address.
    1249                 :  */
    1250                 : static NaClExp* NaClAppendMod11EffectiveAddress(
    1251                 :     NaClInstState* state, const NaClOp* operand,
    1252               1 :     NaClModRmRegKind modrm_reg_kind) {
    1253                 :   DEBUG(NaClLog(LOG_INFO, "Translate modrm(%02x).mod == 11, %s\n",
    1254               1 :                 state->modrm, g_NaClModRmRegKindName[modrm_reg_kind]));
    1255                 :   return NaClAppendOperandReg(state,
    1256                 :                               operand,
    1257               1 :                               NaClGetGenRmRegister(state), modrm_reg_kind);
    1258               1 : }
    1259                 : 
    1260                 : static NaClExp* NaClAppendBasedOnSize(NaClOpKind reg_2b,
    1261                 :                                       NaClOpKind reg_4b,
    1262                 :                                       NaClOpKind reg_8b,
    1263               1 :                                       NaClInstState* state) {
    1264               1 :   switch (state->operand_size) {
    1265                 :     case 2:
    1266               1 :       return NaClAppendReg(reg_2b, &state->nodes);
    1267                 :     case 4:
    1268               1 :       return NaClAppendReg(reg_4b, &state->nodes);
    1269                 :     case 8:
    1270               0 :       return NaClAppendReg(reg_8b, &state->nodes);
    1271                 :     default:
    1272                 :       return NaClFatal("can't translate register group: operand size not valid",
    1273               0 :                        state);
    1274                 :   }
    1275               1 : }
    1276                 : 
    1277                 : static NaClExp* NaClAppendBasedOnAddressSize(NaClOpKind reg_2b,
    1278                 :                                              NaClOpKind reg_4b,
    1279                 :                                              NaClOpKind reg_8b,
    1280               0 :                                              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                 :       return NaClFatal("can't translate register group: address size not valid",
    1290               0 :                        state);
    1291                 :   }
    1292               0 : }
    1293                 : 
    1294                 : /* Compute the effect address using the Mod/Rm and SIB bytes. */
    1295                 : static NaClExp* NaClAppendEffectiveAddress(
    1296                 :     NaClInstState* state, const NaClOp* operand,
    1297               1 :     NaClModRmRegKind modrm_reg_kind) {
    1298               1 :   switch(modrm_modInline(state->modrm)) {
    1299                 :     case 0:
    1300               1 :       return NaClAppendMod00EffectiveAddress(state, operand);
    1301                 :     case 1:
    1302               1 :       return NaClAppendMod01EffectiveAddress(state, operand);
    1303                 :     case 2:
    1304               1 :       return NaClAppendMod10EffectiveAddress(state, operand);
    1305                 :     case 3:
    1306               1 :       return NaClAppendMod11EffectiveAddress(state, operand, modrm_reg_kind);
    1307                 :     default:
    1308                 :       break;
    1309                 :   }
    1310               0 :   return NaClFatal("Operand", state);
    1311               1 : }
    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                 : static NaClExp* NaClAppendOperand(NaClInstState* state,
    1319               1 :                                   const NaClOp* operand) {
    1320                 :   DEBUG(NaClLog(LOG_INFO,
    1321               1 :                 "append operand %s\n", NaClOpKindName(operand->kind)));
    1322               1 :   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                 :         NaClExp* address =
    1341               1 :             NaClAppendEffectiveAddress(state, operand, ModRmGeneral);
    1342                 :         /* Near operands are jump addresses. Mark them as such. */
    1343               1 :         if (operand->flags & NACL_OPFLAG(OperandNear)) {
    1344               1 :           address->flags |= NACL_EFLAG(ExprJumpTarget);
    1345                 :         }
    1346               1 :         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                 :       return NaClAppendOperandReg(state, operand, NaClGetGenRegRegister(state),
    1356               1 :                                   ModRmGeneral);
    1357                 :     case Seg_G_Operand:
    1358                 :       return NaClAppendSegmentOpReg(
    1359                 :           state, operand, NaClGetMnemonicSegmentRegister(state),
    1360               0 :           NaClGetGenRegRegister(state), ModRmGeneral);
    1361                 :     case G_OpcodeBase:
    1362               1 :       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               1 :       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               1 :       return NaClAppendRelativeImmed(state);
    1379                 :     case Mmx_Gd_Operand:
    1380                 :     case Mmx_G_Operand:
    1381                 :       return NaClAppendOperandReg(state, operand, NaClGetGenRegRegister(state),
    1382               0 :                                   ModRmMmx);
    1383                 :     case Mmx_E_Operand:
    1384               0 :       return NaClAppendEffectiveAddress(state, operand, ModRmMmx);
    1385                 :     case Xmm_G_Operand:
    1386                 :     case Xmm_Go_Operand:
    1387                 :       return NaClAppendOperandReg(state, operand, NaClGetGenRegRegister(state),
    1388               1 :                                   ModRmXmm);
    1389                 :     case Xmm_E_Operand:
    1390                 :     case Xmm_Eo_Operand:
    1391               1 :       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               1 :       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               1 :       return NaClAppendReg(operand->kind, &state->nodes);
    1547                 :     case RegREIP:
    1548                 :       return NaClAppendReg(state->address_size == 64 ? RegRIP : RegEIP,
    1549               0 :                            &state->nodes);
    1550                 : 
    1551                 :     case RegREAX:
    1552               1 :       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                 :       return NaClAppendConst(1,
    1584                 :                             NACL_EFLAG(ExprSize8) | NACL_EFLAG(ExprUnsignedHex),
    1585               0 :                             &state->nodes);
    1586                 :     default:
    1587                 :       /* Give up, use the default of undefined. */
    1588                 :       break;
    1589                 :   }
    1590               0 :   return NaClFatal("Operand", state);
    1591               1 : }
    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               1 : static NaClExp* NaClAddOpSetUse(NaClExp* node, const NaClOp* operand) {
    1598               1 :   if (operand->flags & NACL_OPFLAG(OpSet)) {
    1599               1 :     node->flags |= NACL_EFLAG(ExprSet);
    1600                 :   }
    1601               1 :   if (operand->flags & NACL_OPFLAG(OpUse)) {
    1602               1 :     node->flags |= NACL_EFLAG(ExprUsed);
    1603                 :   }
    1604               1 :   if (operand->flags & NACL_OPFLAG(OpAddress)) {
    1605               1 :     node->flags |= NACL_EFLAG(ExprAddress);
    1606                 :   }
    1607               1 :   return node;
    1608               1 : }
    1609                 : 
    1610               1 : 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               1 :                 ":\n", state->inst_addr));
    1616               1 :   num_ops = NaClGetInstNumberOperandsInline(state->inst);
    1617               1 :   for (i = 0; i < num_ops; i++) {
    1618                 :     NaClExp* n;
    1619                 :     const NaClOp* op = NaClGetInstOperandInline(state->decoder_tables,
    1620               1 :                                                 state->inst, i);
    1621               1 :     DEBUG(NaClLog(LOG_INFO, "translating operand %d:\n", i));
    1622                 :     n = NaClAppendExp(OperandReference, i,
    1623                 :                       NACL_EFLAG(ExprSize8) | NACL_EFLAG(ExprUnsignedInt),
    1624               1 :                       &state->nodes);
    1625               1 :     if (op->flags & NACL_OPFLAG(OpImplicit)) {
    1626               1 :       n->flags |= NACL_EFLAG(ExprImplicit);
    1627                 :     }
    1628               1 :     NaClAddOpSetUse(NaClAppendOperand(state, op), op);
    1629               1 :     DEBUG(NaClExpVectorPrint(NaClLogGetGio(), state));
    1630               1 :   }
    1631               1 : }

Generated by: LCOV version 1.7