Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Unified Diff: src/trusted/validator/x86/decoder/nc_inst_trans.c

Issue 625923004: Delete old x86 validator. (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: rebase master Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/trusted/validator/x86/decoder/nc_inst_trans.c
diff --git a/src/trusted/validator/x86/decoder/nc_inst_trans.c b/src/trusted/validator/x86/decoder/nc_inst_trans.c
deleted file mode 100644
index 3e5b2189029845fdc16b27b1b8b5ac55e6738e2b..0000000000000000000000000000000000000000
--- a/src/trusted/validator/x86/decoder/nc_inst_trans.c
+++ /dev/null
@@ -1,1631 +0,0 @@
-/*
- * Copyright (c) 2012 The Native Client Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/*
- * Translates the recognized opcode (instruction) in the instruction state
- * into an opcode expression.
- */
-
-#include "native_client/src/trusted/validator/x86/decoder/nc_inst_trans.h"
-
-#include <stdio.h>
-#include <assert.h>
-
-#include "native_client/src/shared/platform/nacl_check.h"
-#include "native_client/src/shared/platform/nacl_log.h"
-#include "native_client/src/trusted/validator/x86/decoder/nc_inst_state.h"
-#include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_internal.h"
-#include "native_client/src/trusted/validator/x86/decoder/ncop_exps.h"
-#include "native_client/src/trusted/validator/x86/nacl_regs.h"
-
-#include "native_client/src/trusted/validator/x86/decoder/ncop_exps_inl.c"
-#include "native_client/src/trusted/validator/x86/decoder/ncopcode_desc_inl.c"
-#include "native_client/src/trusted/validator/x86/x86_insts_inl.c"
-
-#if NACL_TARGET_SUBARCH == 64
-# include "native_client/src/trusted/validator/x86/decoder/gen/nc_subregs_64.h"
-#else
-# include "native_client/src/trusted/validator/x86/decoder/gen/nc_subregs_32.h"
-#endif
-
-/* To turn on debugging of instruction decoding, change value of
- * DEBUGGING to 1.
- */
-#define DEBUGGING 0
-
-#include "native_client/src/shared/utils/debugging.h"
-
-/* Return the segment register to use, based on prefix specification,
- * or reg_default if no prefix specified.
- */
-static NaClOpKind NaClGetSegmentPrefixReg(NaClInstState* state,
- NaClOpKind reg_default) {
- /* Note: We need to find the LAST segment prefix byte, since it overrides
- * other segment prefix bytes, if multiple segment prefixes are specified.
- */
- if (32 == NACL_TARGET_SUBARCH) {
- if (state->prefix_mask &
- (kPrefixSEGCS | kPrefixSEGSS | kPrefixSEGFS |
- kPrefixSEGGS | kPrefixSEGES | kPrefixSEGDS)) {
- int i;
- for (i = state->num_prefix_bytes - 1; (i >= 0); --i) {
- switch (state->bytes.byte[i]) {
- case kValueSEGCS:
- return RegCS;
- case kValueSEGSS:
- return RegSS;
- case kValueSEGFS:
- return RegFS;
- case kValueSEGGS:
- return RegGS;
- case kValueSEGES:
- return RegES;
- case kValueSEGDS:
- return RegDS;
- default:
- break;
- }
- }
- }
- } else if (state->prefix_mask &
- /* Only GS and FS matter in 64-bit mode. */
- (kPrefixSEGGS | kPrefixSEGFS)) {
- int i;
- for (i = state->num_prefix_bytes - 1; (i >= 0); --i) {
- /* for (i = 0; i < state->num_prefix_bytes; ++i) { */
- switch (state->bytes.byte[i]) {
- case kValueSEGFS:
- return RegFS;
- case kValueSEGGS:
- return RegGS;
- default:
- break;
- }
- }
- }
- return reg_default;
-}
-
-/* Return the segment register to use if DS is the default. */
-static INLINE NaClOpKind NaClGetDsSegmentReg(NaClInstState* state) {
- return NaClGetSegmentPrefixReg(state, RegDS);
-}
-
-/* Return the segment register to use if ES is the default. */
-static INLINE NaClOpKind NaClGetEsSegmentReg(NaClInstState* state) {
- return NaClGetSegmentPrefixReg(state, RegES);
-}
-
-/* Append the given expression node onto the given vector of expression
- * nodes. Returns the appended expression node.
- */
-static INLINE NaClExp* NaClAppendExp(NaClExpKind kind,
- uint64_t value,
- NaClExpFlags flags,
- NaClExpVector* vector) {
- NaClExp* node;
- assert(vector->number_expr_nodes < NACL_MAX_EXPS);
- /* If this is not a register expression, we should have specified a size. */
- CHECK(ExprRegister == kind || (0 != (flags & (NACL_EFLAG(ExprSize8) |
- NACL_EFLAG(ExprSize16) |
- NACL_EFLAG(ExprSize32) |
- NACL_EFLAG(ExprSize48) |
- NACL_EFLAG(ExprSize64)))));
- node = &vector->node[vector->number_expr_nodes++];
- node->kind = kind;
- node->value = value;
- node->flags = flags;
- return node;
-}
-
-/* Report the given message and quit because we don't know
- * how to recover.
- */
-static void NaClLost(const char* message) {
- NaClLog(LOG_ERROR, "FATAL: %s\n", message);
- exit(1);
-}
-
-/* An untranslateable error has been found. report and quit.
- * Use the state to give useful information on where the
- * translator was when the error occurred.
- * Note: returns NULL of type NaClExp* so that callers can
- * make control flow happy, for those cases where the compiler
- * doesn't recognize that this function never returns.
- */
-static NaClExp* NaClFatal(const char* message,
- NaClInstState* state) {
- NaClLog(LOG_ERROR,
- "FATAL: At %"NACL_PRIxNaClPcAddress", unable to translate: %s\n",
- NaClInstStatePrintableAddress(state), message);
- exit(1);
- /* NOT REACHED */
- return NULL;
-}
-
-/* Returns the segment register encoded in the corresponding
- * mnemonic name of the corresponding instruction.
- */
-static NaClOpKind NaClGetMnemonicSegmentRegister(NaClInstState* state) {
- const NaClInst* inst = NaClInstStateInst(state);
- switch (inst->name) {
- case InstLds:
- return RegDS;
- case InstLes:
- return RegES;
- case InstLfs:
- return RegFS;
- case InstLgs:
- return RegGS;
- case InstLss:
- return RegSS;
- default:
- break;
- }
- NaClFatal("Unable to determine segment regsiter from instruction name",
- state);
- /* NOT REACHED */
- return RegUnknown;
-}
-
-/* Append that we don't bother to translate the instruction argument,
- * since it is NaCl illegal. Used to handle cases where we don't implement
- * 16-bit modrm effective addresses.
- */
-static INLINE NaClExp* NaClAppendNaClIllegal(NaClInstState* state) {
- return NaClAppendExp(ExprNaClIllegal, 0,
- NACL_EFLAG(ExprSize16), &state->nodes);
-}
-
-/* Append the given constant onto the given vector of expression
- * nodes. Returns the appended expression node.
- */
-static INLINE NaClExp* NaClAppendConst(uint64_t value, NaClExpFlags flags,
- NaClExpVector* vector) {
- DEBUG(
- NaClLog(LOG_INFO, "Append constant %"NACL_PRIx64" : ", value);
- NaClPrintExpFlags(NaClLogGetGio(), flags);
- gprintf(NaClLogGetGio(), "\n"));
- return NaClAppendExp(ExprConstant, value, flags, vector);
-}
-
-/* Define a type corresponding to the arrays NaClRegTable8,
- * NaClRegTable16, NaClRegTable32, and NaClRegTable64.
- */
-typedef const NaClOpKind NaClRegTableGroup[NACL_REG_TABLE_SIZE];
-
-NaClOpKind NaClGet64For32BitReg(NaClOpKind reg32) {
-#if NACL_TARGET_SUBARCH == 64
- int i;
- for (i = 0; i < NACL_REG_TABLE_SIZE; ++i) {
- if (reg32 == NaClRegTable32[i]) {
- return NaClRegTable64[i];
- }
- }
-#endif
- return RegUnknown;
-}
-
-NaClOpKind NaClGet32For64BitReg(NaClOpKind reg64) {
- int index = NaClGpReg64Index[reg64];
- return (index == NACL_REGISTER_UNDEFINED)
- ? RegUnknown
- : NaClRegTable32[index];
-}
-
-Bool NaClIs64Subreg(NaClInstState* state,
- NaClOpKind subreg, NaClOpKind reg64) {
- int index = NaClGpSubregIndex[subreg];
- if (index == NACL_REGISTER_UNDEFINED) {
- return FALSE;
- } else {
- int index64 = NaClGpReg64Index[reg64];
- if (index64 == NACL_REGISTER_UNDEFINED) {
- /* This shouldn't happen, so fail! */
- return FALSE;
- } else {
- return index == index64;
- }
- }
-}
-
-Bool NaClIs32To64RegPair(NaClOpKind reg32, NaClOpKind reg64) {
- return reg64 == NaClGet64For32BitReg(reg32);
-}
-
-/* Define the set of available registers, categorized by size.
- * Note: The order is important, and is based on the indexing values used
- * in the ModRm and SIB bytes (and the REX prefix if appropriate).
- */
-static NaClRegTableGroup* const NaClRegTable[] = {
- &NaClRegTable8NoRex,
- &NaClRegTable16,
- &NaClRegTable32,
- &NaClRegTable64,
- &NaClRegTableMmx,
- &NaClRegTableXmm,
- &NaClRegTableC,
- &NaClRegTableD,
-};
-
-/* Define possible register categories. */
-typedef enum NaClRegKind {
- /* Note: the following all have register tables
- * for the corresponding general purpose registers.
- */
- RegSize8,
- RegSize16,
- RegSize32,
- RegSize64,
- RegMMX,
- RegXMM,
- RegC,
- RegD,
- /* Note: sizes below this point don't define general
- * purpose registers, and hence, don't have a lookup
- * value in the register tables.
- */
- RegSize128,
- RegSizeZ,
- RegUndefined, /* Always returns RegUnknown. */
-} NaClRegKind;
-
-static const char* const g_NaClRegKindName[] = {
- "RegSize8",
- "RegSize16",
- "RegSize32",
- "RegSize64",
- "RegMMX",
- "RegXMM",
- "RegC",
- "RegD",
- "RegSize128",
- "RegSizeZ",
- "RegUndefined"
-};
-
-const char* NaClRegKindName(NaClRegKind kind) {
- return g_NaClRegKindName[kind];
-}
-
-/* Define ModRm register categories. */
-typedef enum NaClModRmRegKind {
- ModRmGeneral,
- ModRmMmx,
- ModRmXmm,
- ModRmCreg,
- ModRmDreg,
- /* Don't allow top level registers in Effective address. */
- ModRmNoTopLevelRegisters
-} NaClModRmRegKind;
-
-static const char* const g_NaClModRmRegKindName[] = {
- "ModRmGeneral",
- "ModRmMmx",
- "ModRmXmm",
- "ModRmCreg",
- "ModRmDreg",
- "ModRmNoTopLevelRegisters"
-};
-
-/* Given an operand kind, return the size specification associated with
- * the operand kind.
- */
-static NaClRegKind NaClGetOpKindRegKind(NaClOpKind kind) {
- switch (kind) {
- case Eb_Operand:
- case Gb_Operand:
- case Ib_Operand:
- case Jb_Operand:
- case Mb_Operand:
- case Ob_Operand:
- return RegSize8;
- case Ew_Operand:
- case Gw_Operand:
- case Iw_Operand:
- case Jw_Operand:
- case Mw_Operand:
- case Mpw_Operand:
- case Ow_Operand:
- return RegSize16;
- case Ev_Operand:
- case Gv_Operand:
- case Iv_Operand:
- case Jv_Operand:
- case Mv_Operand:
- case Mpv_Operand:
- case Ov_Operand:
- case Mmx_Gd_Operand:
- return RegSize32;
- case Eo_Operand:
- case Go_Operand:
- case Io_Operand:
- case Mo_Operand:
- case Mpo_Operand:
- case Oo_Operand:
- case Xmm_Eo_Operand:
- case Xmm_Go_Operand:
- case Mmx_E_Operand:
- case Mmx_G_Operand:
- return RegSize64;
- case Edq_Operand:
- case Gdq_Operand:
- case Mdq_Operand:
- case Xmm_E_Operand:
- case Xmm_G_Operand:
- return RegSize128;
- case Seg_G_Operand:
- return RegSizeZ;
- default:
- return RegUndefined;
- }
-}
-
-static NaClOpKind NaClLookupReg(NaClInstState* state,
- NaClRegKind kind, int reg_index) {
- DEBUG(NaClLog(LOG_INFO,
- "Lookup register (rex=%"NACL_PRIx8") %s:%d\n",
- state->rexprefix, NaClRegKindName(kind), reg_index));
- if (32 == NACL_TARGET_SUBARCH && kind == RegSize64) {
- NaClLost("Architecture doesn't define 64 bit registers");
- } else if (RegSize128 <= kind) {
- return RegUnknown;
- }
- if (64 == NACL_TARGET_SUBARCH && kind == RegSize8 && state->rexprefix) {
- return NaClRegTable8Rex[reg_index];
- }
- return (*(NaClRegTable[kind]))[reg_index];
-}
-
-/* Returns the (NaClExpFlag) size of the given register. */
-static NaClExpFlags NaClGetRegSize(NaClOpKind register_name) {
- switch (register_name) {
- case RegAL:
- case RegBL:
- case RegCL:
- case RegDL:
- case RegAH:
- case RegBH:
- case RegCH:
- case RegDH:
- case RegDIL:
- case RegSIL:
- case RegBPL:
- case RegSPL:
- case RegR8B:
- case RegR9B:
- case RegR10B:
- case RegR11B:
- case RegR12B:
- case RegR13B:
- case RegR14B:
- case RegR15B:
- return NACL_EFLAG(ExprSize8);
- case RegAX:
- case RegBX:
- case RegCX:
- case RegDX:
- case RegSI:
- case RegDI:
- case RegBP:
- case RegSP:
- case RegR8W:
- case RegR9W:
- case RegR10W:
- case RegR11W:
- case RegR12W:
- case RegR13W:
- case RegR14W:
- case RegR15W:
- return NACL_EFLAG(ExprSize16);
- case RegEAX:
- case RegEBX:
- case RegECX:
- case RegEDX:
- case RegESI:
- case RegEDI:
- case RegEBP:
- case RegESP:
- case RegR8D:
- case RegR9D:
- case RegR10D:
- case RegR11D:
- case RegR12D:
- case RegR13D:
- case RegR14D:
- case RegR15D:
- return NACL_EFLAG(ExprSize32);
- case RegCS:
- case RegDS:
- case RegSS:
- case RegES:
- case RegFS:
- case RegGS:
- return NACL_EFLAG(ExprSize16);
- case RegEIP:
- return NACL_EFLAG(ExprSize32);
- case RegRIP:
- return NACL_EFLAG(ExprSize64);
- case RegRAX:
- case RegRBX:
- case RegRCX:
- case RegRDX:
- case RegRSI:
- case RegRDI:
- case RegRBP:
- case RegRSP:
- case RegR8:
- case RegR9:
- case RegR10:
- case RegR11:
- case RegR12:
- case RegR13:
- case RegR14:
- case RegR15:
- return NACL_EFLAG(ExprSize64);
- default:
- return 0;
- }
-}
-
-/* Appends the given kind of register onto the vector of expression nodes.
- * Returns the appended register.
- */
-static INLINE NaClExp* NaClAppendReg(NaClOpKind r, NaClExpVector* vector) {
- NaClExp* node;
- DEBUG(NaClLog(LOG_INFO, "append register %s\n", NaClOpKindName(r)));
- node = NaClAppendExp(ExprRegister, r, NaClGetRegSize(r), vector);
- return node;
-}
-
-/* Given the given register kind, and the corresponding index, append
- * the appropriate register onto the vector of expression nodes.
- * Returns the appended register
- */
-static INLINE NaClExp* NaClAppendRegKind(NaClInstState* state,
- NaClRegKind kind, int reg_index) {
- DEBUG(NaClLog(LOG_INFO, "NaClAppendRegKind(%d, %d) = %s\n",
- (int) kind, reg_index, NaClRegKindName(kind)));
- return NaClAppendReg(NaClLookupReg(state, kind, reg_index), &state->nodes);
-}
-
-/* Given an operand of the corresponding opcode instruction of the
- * given state, return what kind of register should be used, based
- * on the operand size.
- */
-static NaClRegKind NaClExtractOpRegKind(NaClInstState* state,
- const NaClOp* operand) {
- NaClRegKind reg_kind = NaClGetOpKindRegKind(operand->kind);
- switch (reg_kind) {
- case RegSize8:
- case RegSize16:
- case RegSize32:
- case RegSize64:
- return reg_kind;
- case RegSizeZ:
- if (state->operand_size == 2) {
- return RegSize16;
- } else {
- return RegSize32;
- }
- default:
- /* Size not explicitly defined, pick up from operand size. */
- if (state->inst->flags & NACL_IFLAG(OperandSize_b)) {
- return RegSize8;
- } else if (state->operand_size == 1) {
- return RegSize8;
- } else if (state->operand_size == 4) {
- return RegSize32;
- } else if (state->operand_size == 2) {
- return RegSize16;
- } else if (state->operand_size == 8) {
- return RegSize64;
- } else {
- return RegSize32;
- }
- }
-}
-
-/* Given an address of the corresponding opcode instruction of the
- * given state, return what kind of register should be used.
- */
-static INLINE NaClRegKind NaClExtractAddressRegKind(NaClInstState* state) {
- if (state->address_size == 16) {
- return RegSize16;
- } else if (state->address_size == 64) {
- return RegSize64;
- } else {
- return RegSize32;
- }
-}
-
-/* Given we want to translate an operand (of the form G_Operand),
- * for the given register index, generate the corresponding register
- * expression, and append it to the vector of expression nodes.
- * Returns the appended register.
- */
-static NaClExp* NaClAppendOperandReg(
- NaClInstState* state,
- const NaClOp* operand,
- int reg_index,
- NaClModRmRegKind modrm_reg_kind) {
- NaClRegKind reg_kind = RegSize32;
- DEBUG(NaClLog(LOG_INFO, "modrm_reg_kind = %s\n",
- g_NaClModRmRegKindName[modrm_reg_kind]));
- switch (modrm_reg_kind) {
- default:
- case ModRmGeneral:
- reg_kind = NaClExtractOpRegKind(state, operand);
- break;
- case ModRmMmx:
- reg_kind = RegMMX;
- break;
- case ModRmXmm:
- reg_kind = RegXMM;
- break;
- case ModRmCreg:
- reg_kind = RegC;
- break;
- case ModRmDreg:
- reg_kind = RegD;
- break;
- case ModRmNoTopLevelRegisters:
- reg_kind = RegUndefined;
- }
- DEBUG(NaClLog(LOG_INFO, "Translate register %d, %s\n",
- reg_index, g_NaClRegKindName[reg_kind]));
- return NaClAppendRegKind(state, reg_kind, reg_index);
-}
-
-static NaClExpFlags NaClGetAddressExprSizeFlagsForState(NaClInstState* state);
-
-static NaClExp* NaClAppendSegmentAddress(NaClInstState* state) {
- NaClExpFlags flags = NaClGetAddressExprSizeFlagsForState(state);
- return NaClAppendExp(ExprSegmentAddress, 0, flags, &state->nodes);
-}
-
-/* Same as NaClAppendOperandReg, except that a segment register is combined with
- * the indexed register to define a segment address.
- */
-static NaClExp* NaClAppendSegmentOpReg(
- NaClInstState* state,
- const NaClOp* operand,
- NaClOpKind seg_register,
- int reg_index,
- NaClModRmRegKind modrm_reg_kind) {
- NaClExp* results = NaClAppendSegmentAddress(state);
- NaClAppendReg(seg_register, &state->nodes);
- NaClAppendOperandReg(state, operand, reg_index, modrm_reg_kind);
- return results;
-}
-
-/* Returns the corresponding segment register for the given index (0..7) */
-static NaClExp* NaClAppendModRmSegmentReg(NaClInstState* state) {
- static NaClOpKind seg[8] = {
- RegES,
- RegCS,
- RegSS,
- RegDS,
- RegFS,
- RegGS,
- /* These should not happen. */
- RegUnknown,
- RegUnknown
- };
- return NaClAppendReg(seg[modrm_regInline(state->modrm)], &state->nodes);
-}
-
-/* For the given instruction state, and the corresponding 3-bit specification
- * of a register, update it to a 4-bit specification, based on the REX.R bit.
- */
-static INLINE int NaClGetRexRReg(NaClInstState* state, int reg) {
- DEBUG(NaClLog(LOG_INFO, "Get GenRexRRegister %d\n", reg));
- if (NACL_TARGET_SUBARCH == 64 && (state->rexprefix & 0x4)) {
- reg += 8;
- }
- return reg;
-}
-
-/* For the given instruction state, and the corresponding 3-bit specification
- * of a register, update it to a 4-bit specification, based on the REX.X bit.
- */
-static INLINE int NaClGetRexXReg(NaClInstState* state, int reg) {
- DEBUG(NaClLog(LOG_INFO, "Get GenRexXRegister\n"));
- if (NACL_TARGET_SUBARCH == 64 && (state->rexprefix & 0x2)) {
- reg += 8;
- }
- return reg;
-}
-
-/* For the given instruction state, and the corresponding 3-bit specification
- * of a register, update it to a 4-bit specification, based on the REX.B bit.
- */
-static INLINE int NaClGetRexBReg(NaClInstState* state, int reg) {
- DEBUG(NaClLog(LOG_INFO, "Get GenRexBRegister\n"));
- if (NACL_TARGET_SUBARCH == 64 && (state->rexprefix & 0x1)) {
- DEBUG(NaClLog(LOG_INFO, "rexprefix == %02x\n", state->rexprefix));
- reg += 8;
- }
- return reg;
-}
-
-/* Return the general purpose register associated with the modrm.reg
- * field.
- */
-static INLINE int NaClGetGenRegRegister(NaClInstState* state) {
- DEBUG(NaClLog(LOG_INFO, "Get GenRegRegister\n"));
- return NaClGetRexRReg(state, modrm_regInline(state->modrm));
-}
-
-/* Return the general purpose register associated with the modrm.rm
- * field.
- */
-static INLINE int NaClGetGenRmRegister(NaClInstState* state) {
- DEBUG(NaClLog(LOG_INFO, "Get GenRmRegister\n"));
- return NaClGetRexBReg(state, modrm_rmInline(state->modrm));
-}
-
-/* Get the register index from the difference of the opcode, and
- * its opcode base.
- */
-static NaClExp* NaClAppendOpcodeBaseReg(
- NaClInstState* state, const NaClOp* operand) {
- int reg_index;
- reg_index = NaClGetOpcodePlusR(state->inst->opcode_ext);
- assert(reg_index >= 0 && reg_index < 8);
- DEBUG(NaClLog(LOG_INFO, "Translate opcode base register %d\n", reg_index));
- return NaClAppendRegKind(state, NaClExtractOpRegKind(state, operand),
- NaClGetRexBReg(state, reg_index));
-}
-
-/* Get the ST register defined from the difference of the opcode, and
- * its opcode base.
- */
-static NaClExp* NaClAppendStOpcodeBaseReg(NaClInstState* state) {
- int reg_index;
- reg_index = NaClGetOpcodePlusR(state->inst->opcode_ext);
- assert(reg_index >= 0 && reg_index < 8);
- DEBUG(NaClLog(LOG_INFO, "Translate opcode base register %d\n", reg_index));
- return NaClAppendReg(RegST0 + reg_index, &state->nodes);
-}
-
-/* Model the extraction of a displacement value and the associated flags. */
-typedef struct NaClDisplacement {
- uint64_t value;
- NaClExpFlags flags;
-} NaClDisplacement;
-
-static INLINE void NaClInitializeDisplacement(
- uint64_t value, NaClExpFlags flags,
- NaClDisplacement* displacement) {
- displacement->value = value;
- displacement->flags = flags;
-}
-
-/* Extract the binary value from the specified bytes of the instruction. */
-static uint64_t NaClExtractUnsignedBinaryValue(NaClInstState* state,
- int start_byte, int num_bytes) {
- int i;
- uint64_t value = 0;
- for (i = 0; i < num_bytes; ++i) {
- uint8_t byte = state->bytes.byte[start_byte + i];
- value += (((uint64_t) byte) << (i * 8));
- }
- return value;
-}
-
-static int64_t NaClExtractSignedBinaryValue(NaClInstState* state,
- int start_byte, int num_bytes) {
- /* Assumes little endian. */
- uint8_t* address = &state->bytes.byte[start_byte];
- switch (num_bytes) {
- case 1:
- return *(int8_t*) address;
- case 2:
- return *(int16_t*) address;
- case 4:
- return *(int32_t*) address;
- default:
- CHECK(0);
- return -1;
- }
-}
-
-/* Given the number of bytes for a literal constant, return the corresponding
- * expr node flags that represent the value of the parsed bytes.
- */
-static NaClExpFlags NaClGetExprSizeFlagForBytes(uint8_t num_bytes) {
- switch (num_bytes) {
- /* HACK a zero size immediate is generated for some addr16 instructions.
- * We don't allow these instructions, but we do test decompiling them.
- * TODO(ncbray) eliminate the bug or the test case.
- */
- case 0:
- case 1:
- return NACL_EFLAG(ExprSize8);
- case 2:
- return NACL_EFLAG(ExprSize16);
- case 4:
- return NACL_EFLAG(ExprSize32);
- case 6:
- return NACL_EFLAG(ExprSize48);
- case 8:
- return NACL_EFLAG(ExprSize64);
- default:
- CHECK(0);
- return 0;
- }
-}
-
-/* Return the expr flag for the address size associated with the state. */
-static NaClExpFlags NaClGetAddressExprSizeFlagsForState(NaClInstState* state) {
- uint8_t size = NaClInstStateAddressSize(state);
- return NaClGetExprSizeFlagForBytes(size / 8);
-}
-
-/* Given the corresponding instruction state, return the
- * corresponding displacement value, and any expression node
- * flags that should be associated with the displacement value.
- */
-static void NaClExtractDisplacement(NaClInstState* state,
- NaClDisplacement* displacement,
- NaClExpFlags flags) {
- DEBUG(NaClLog(LOG_INFO, "-> Extract displacement, flags = ");
- NaClPrintExpFlags(NaClLogGetGio(), flags);
- gprintf(NaClLogGetGio(), "\n"));
- /* First compute the displacement value. */
- displacement->value = NaClExtractUnsignedBinaryValue(state,
- state->first_disp_byte,
- state->num_disp_bytes);
-
- /* Now compute any appropriate flags to be associated with the value. */
- displacement->flags = flags |
- NaClGetExprSizeFlagForBytes(state->num_disp_bytes);
- DEBUG(NaClLog(LOG_INFO,
- "<- value = %"NACL_PRIx64", flags = ", displacement->value);
- NaClPrintExpFlags(NaClLogGetGio(), displacement->flags);
- gprintf(NaClLogGetGio(), "\n"));
-}
-
-/* Append the displacement value of the given instruction state
- * onto the vector of expression nodes. Returns the appended displacement
- * value.
- */
-static NaClExp* NaClAppendDisplacement(NaClInstState* state) {
- NaClDisplacement displacement;
- DEBUG(NaClLog(LOG_INFO, "append displacement\n"));
- NaClExtractDisplacement(state, &displacement, NACL_EFLAG(ExprSignedHex));
- return NaClAppendConst(displacement.value, displacement.flags, &state->nodes);
-}
-
-/* Get the binary value denoted by the immediate bytes of the state. */
-static uint64_t NaClExtractUnsignedImmediate(NaClInstState* state) {
- return NaClExtractUnsignedBinaryValue(state,
- state->first_imm_byte,
- state->num_imm_bytes);
-}
-
-/* Get the binary value denoted by the 2nd immediate bytes of the state. */
-static uint64_t NaClExtractUnsignedImmediate2(NaClInstState* state) {
- return NaClExtractUnsignedBinaryValue(
- state,
- state->first_imm_byte + state->num_imm_bytes,
- state->num_imm2_bytes);
-}
-
-/* Get the binary value denoted by the immediate bytes of the state. */
-static int64_t NaClExtractSignedImmediate(NaClInstState* state) {
- return NaClExtractSignedBinaryValue(state,
- state->first_imm_byte,
- state->num_imm_bytes);
-}
-
-/* Append the immediate value of the given instruction state onto
- * The vector of expression nodes. Returns the appended immediate value.
- */
-static NaClExp* NaClAppendImmed(NaClInstState* state) {
- NaClExpFlags flags;
-
- /* First compute the immediate value. */
- uint64_t value;
- DEBUG(NaClLog(LOG_INFO, "append immediate\n"));
- value = NaClExtractUnsignedImmediate(state);
-
- /* Now compute any appropriate flags to be associated with the immediate
- * value.
- */
- flags = NACL_EFLAG(ExprUnsignedHex) |
- NaClGetExprSizeFlagForBytes(state->num_imm_bytes);
-
- /* Append the generated immediate value onto the vector. */
- return NaClAppendConst(value, flags, &state->nodes);
-}
-
-/* Append the second immediate value of the given instruction state onto
- * the vector of expression nodes. Returns the appended immediate value.
- */
-static NaClExp* NaClAppendImmed2(NaClInstState* state) {
- NaClExpFlags flags;
-
- /* First compute the immedaite value. */
- uint64_t value;
- DEBUG(NaClLog(LOG_INFO, "append 2nd immediate\n"));
-
- value = NaClExtractUnsignedImmediate2(state);
-
- /* Now compute any appropriate flags to be associated with the immediate
- * value.
- */
- flags =
- NACL_EFLAG(ExprUnsignedHex) |
- NaClGetExprSizeFlagForBytes(state->num_imm2_bytes);
-
- /* Append the generated immediate value onto the vector. */
- return NaClAppendConst(value, flags, &state->nodes);
-}
-
-/* Append an ExprMemOffset node for the given state, and return
- * the appended ndoe.
- */
-static NaClExp* NaClAppendMemOffsetNode(NaClInstState* state) {
- NaClExpFlags flags = NaClGetAddressExprSizeFlagsForState(state);
- NaClExp* root = NaClAppendExp(ExprMemOffset, 0, flags, &state->nodes);
- DEBUG(NaClLog(LOG_INFO, "Build memoffset, flags = ");
- NaClPrintExpFlags(NaClLogGetGio(), flags);
- gprintf(NaClLogGetGio(), "\n"));
- return root;
-}
-
-/* Returns the segment register prefix node, or NULL if no such node is
- * added.
- */
-static NaClExp* NaClAppendSegmentAddressNode(NaClInstState* state,
- NaClOpKind reg_default) {
- NaClExp* root = NULL;
- NaClOpKind seg_reg = NaClGetSegmentPrefixReg(state, reg_default);
- if (seg_reg != RegUnknown) {
- NaClExp* n;
- root = NaClAppendSegmentAddress(state);
- n = NaClAppendReg(seg_reg, &state->nodes);
- n->flags |= NACL_EFLAG(ExprUsed);
- }
- return root;
-}
-
-/* Append the immediate value of the given instruction as the displacement
- * of a memory offset.
- */
-static NaClExp* NaClAppendMemoryOffsetImmed(NaClInstState* state) {
- NaClExpFlags flags;
- uint64_t value;
- NaClExp* root;
- DEBUG(NaClLog(LOG_INFO, "append memory offset immediate\n"));
- root = NaClAppendSegmentAddressNode(state, RegUnknown);
- if (root == NULL) {
- root = NaClAppendMemOffsetNode(state);
- } else {
- NaClAppendMemOffsetNode(state);
- }
- NaClAppendReg(RegUnknown, &state->nodes);
- NaClAppendReg(RegUnknown, &state->nodes);
- NaClAppendConst(1, NACL_EFLAG(ExprSize8), &state->nodes);
- value = NaClExtractUnsignedImmediate(state);
- DEBUG(NaClLog(LOG_INFO, "value = 0x%016"NACL_PRIx64"\n", value));
- flags = NACL_EFLAG(ExprUnsignedHex) |
- NaClGetExprSizeFlagForBytes(state->num_imm_bytes);
- NaClAppendConst(value, flags, &state->nodes);
- return root;
-}
-
-static NaClExp* NaClAppendRelativeImmed(NaClInstState* state) {
- NaClPcNumber jump_offset = (NaClPcNumber) NaClExtractSignedImmediate(state);
- DEBUG(NaClLog(LOG_INFO, "append relative immediate\n"));
- return NaClAppendConst(jump_offset,
- NACL_EFLAG(ExprSignedHex) |
- NaClGetExprSizeFlagForBytes(state->num_imm_bytes) |
- NACL_EFLAG(ExprJumpTarget),
- &state->nodes);
-}
-
-/* Append a memory offset for the given memory offset defined by
- * the formula "base + index*scale + displacement". If no index
- * is used, its value should be RegUnknown. Argument displacement_flags
- * are flags that should be associated with the generated displacement
- * value
- */
-static NaClExp* NaClAppendMemoryOffset(NaClInstState* state,
- NaClOpKind base,
- NaClOpKind index,
- uint8_t scale,
- NaClDisplacement* displacement) {
- NaClExp* root = NULL;
- NaClOpKind seg_reg_default;
- NaClExp* n;
-
- DEBUG(NaClLog(LOG_INFO,
- "memory offset(%s + %s * %d + %"NACL_PRId64
- " : %"NACL_PRIx32")\n",
- NaClOpKindName(base),
- NaClOpKindName(index),
- scale,
- displacement->value,
- displacement->flags));
-
- if (32 == NACL_TARGET_SUBARCH) {
- seg_reg_default = ((base == RegBP || base == RegEBP)
- ? RegSS : NaClGetDsSegmentReg(state));
- } else {
- seg_reg_default = RegUnknown;
- }
- root = NaClAppendSegmentAddressNode(state, seg_reg_default);
- if (NULL == root) {
- root = NaClAppendMemOffsetNode(state);
- } else {
- NaClAppendMemOffsetNode(state);
- }
- n = NaClAppendReg(base, &state->nodes);
- if (base != RegUnknown) {
- n->flags |= NACL_EFLAG(ExprUsed);
- }
- n = NaClAppendReg(index, &state->nodes);
- if (index == RegUnknown) {
- /* Scale not applicable, check that value is 1. */
- assert(scale == 1);
- } else {
- n->flags |= NACL_EFLAG(ExprUsed);
- }
- NaClAppendConst(scale, NACL_EFLAG(ExprSize8), &state->nodes);
- NaClAppendConst(displacement->value, displacement->flags, &state->nodes);
- DEBUG(NaClLog(LOG_INFO, "finished appending memory offset:\n"));
- DEBUG(NaClExpVectorPrint(NaClLogGetGio(), state));
- return root;
-}
-
-/* Extract the base register from the SIB byte. */
-static NaClOpKind NaClGetSibBase(NaClInstState* state) {
- int base = sib_base(state->sib);
- NaClOpKind base_reg = RegUnknown;
- if (0x5 == base) {
- switch (modrm_modInline(state->modrm)) {
- case 0:
- break;
- case 1:
- case 2:
- if (NACL_TARGET_SUBARCH == 64) {
- if (state->rexprefix & 0x1) {
- base_reg = RegR13;
- } else {
- base_reg = RegRBP;
- }
- } else {
- base_reg = RegEBP;
- }
- break;
- default:
- NaClFatal("SIB value", state);
- }
- } else {
- NaClRegKind kind = NaClExtractAddressRegKind(state);
- base_reg = NaClLookupReg(state, kind, NaClGetRexBReg(state, base));
- }
- return base_reg;
-}
-
-/* Define the possible scaling factors that can be defined in the
- * SIB byte of the parsed instruction.
- */
-static uint8_t nacl_sib_scale[4] = { 1, 2, 4, 8 };
-
-/* Extract out the expression defined by the SIB byte of the instruction
- * in the given instruction state, and append it to the vector of
- * expression nodes. Return the corresponding expression node that
- * is the root of the appended expression.
- */
-static NaClExp* NaClAppendSib(NaClInstState* state) {
- int index = sib_index(state->sib);
- int scale = 1;
- NaClRegKind kind = NaClExtractAddressRegKind(state);
- NaClOpKind base_reg;
- NaClOpKind index_reg = RegUnknown;
- NaClDisplacement displacement;
- DEBUG(NaClLog(LOG_INFO, "append sib: %02x\n", state->sib));
- NaClInitializeDisplacement(0, 0, &displacement);
- base_reg = NaClGetSibBase(state);
- if (0x4 != index || NACL_TARGET_SUBARCH != 64 || (state->rexprefix & 0x2)) {
- index_reg = NaClLookupReg(state, kind, NaClGetRexXReg(state, index));
- scale = nacl_sib_scale[sib_ss(state->sib)];
- }
- if (state->num_disp_bytes > 0) {
- NaClExtractDisplacement(state, &displacement,
- NACL_EFLAG(ExprSignedHex));
- } else {
- displacement.flags = NACL_EFLAG(ExprSize8);
- }
- return NaClAppendMemoryOffset(state, base_reg, index_reg,
- scale, &displacement);
-}
-
-static void NaClAppendEDI(NaClInstState* state) {
- switch (state->address_size) {
- case 16:
- NaClAppendReg(RegDI, &state->nodes);
- break;
- case 32:
- NaClAppendReg(RegEDI, &state->nodes);
- break;
- case 64:
- NaClAppendReg(RegRDI, &state->nodes);
- break;
- default:
- NaClFatal("Address size for %EDI not correctly defined",
- state);
- break;
- }
-}
-
-static void NaClAppendESI(NaClInstState* state) {
- switch (state->address_size) {
- case 16:
- NaClAppendReg(RegSI, &state->nodes);
- break;
- case 32:
- NaClAppendReg(RegESI, &state->nodes);
- break;
- case 64:
- NaClAppendReg(RegRSI, &state->nodes);
- break;
- default:
- NaClFatal("Address size for %ESI not correctly defined", state);
- break;
- }
-}
-static void NaClAppendEBX(NaClInstState* state) {
- switch (state->address_size) {
- case 16:
- NaClAppendReg(RegBX, &state->nodes);
- break;
- case 32:
- NaClAppendReg(RegEBX, &state->nodes);
- break;
- case 64:
- NaClAppendReg(RegRBX, &state->nodes);
- break;
- default:
- NaClFatal("Address size for %EBX not correctly defined", state);
- break;
- }
-}
-
-static NaClExp* NaClAppendDS_EDI(NaClInstState* state) {
- NaClExp* results = NaClAppendSegmentAddress(state);
- results->flags |= NACL_EFLAG(ExprDSrCase);
- NaClAppendReg(NaClGetDsSegmentReg(state), &state->nodes);
- NaClAppendEDI(state);
- return results;
-}
-
-static NaClExp* NaClAppendDS_ESI(NaClInstState* state) {
- NaClExp* results = NaClAppendSegmentAddress(state);
- results->flags |= NACL_EFLAG(ExprDSrCase);
- NaClAppendReg(NaClGetDsSegmentReg(state), &state->nodes);
- NaClAppendESI(state);
- return results;
-}
-
-static NaClExp* NaClAppendDS_EBX(NaClInstState* state) {
- NaClExp* results = NaClAppendSegmentAddress(state);
- results->flags |= NACL_EFLAG(ExprDSrCase);
- NaClAppendReg(NaClGetDsSegmentReg(state), &state->nodes);
- NaClAppendEBX(state);
- return results;
-}
-
-static NaClExp* NaClAppendES_EDI(NaClInstState* state) {
- NaClExp* results = NaClAppendSegmentAddress(state);
- results->flags |= NACL_EFLAG(ExprESrCase);
- NaClAppendReg(NaClGetEsSegmentReg(state), &state->nodes);
- NaClAppendEDI(state);
- return results;
-}
-
-/* Get the Effective address in the mod/rm byte, if the modrm.mod field
- * is 00, and append it to the vector of expression nodes. Operand is
- * the corresponding operand of the opcode associated with the instruction
- * of the given state that corresponds to the effective address. Returns
- * the root of the appended effective address.
- */
-static NaClExp* NaClAppendMod00EffectiveAddress(
- NaClInstState* state, const NaClOp* operand) {
- DEBUG(NaClLog(LOG_INFO, "Translate modrm(%02x).mod == 00\n", state->modrm));
- if ((32 == NACL_TARGET_SUBARCH) &&
- NaClHasBit(state->prefix_mask, kPrefixADDR16)) {
- /* This code doesn't know how to translate 16-bit modrm effective addresses.
- * However, such arguments are not nacl legal. Communicate this explicitly.
- */
- return NaClAppendNaClIllegal(state);
- }
- switch (modrm_rmInline(state->modrm)) {
- case 4:
- return NaClAppendSib(state);
- case 5:
- if (NACL_TARGET_SUBARCH == 64) {
- NaClDisplacement displacement;
- NaClExtractDisplacement(state, &displacement,
- NACL_EFLAG(ExprSignedHex));
- return NaClAppendMemoryOffset(state,
- RegRIP,
- RegUnknown,
- 1,
- &displacement);
- } else {
- return NaClAppendDisplacement(state);
- }
- default: {
- NaClDisplacement displacement;
- NaClInitializeDisplacement(0, NACL_EFLAG(ExprSize8), &displacement);
- return NaClAppendMemoryOffset(state,
- NaClLookupReg(
- state,
- NaClExtractAddressRegKind(state),
- NaClGetGenRmRegister(state)),
- RegUnknown,
- 1,
- &displacement);
- }
- }
- /* NOT REACHED */
- return NULL;
-}
-
-/* Get the Effective address in the mod/rm byte, if the modrm.mod field
- * is 01, and append it to the vector of expression nodes. Operand is
- * the corresponding operand of the opcode associated with the instruction
- * of the given state that corresponds to the effective address. Returns
- * the root of the appended effective address.
- */
-static NaClExp* NaClAppendMod01EffectiveAddress(
- NaClInstState* state, const NaClOp* operand) {
- DEBUG(NaClLog(LOG_INFO, "Translate modrm(%02x).mod == 01\n", state->modrm));
- if ((32 == NACL_TARGET_SUBARCH) &&
- NaClHasBit(state->prefix_mask, kPrefixADDR16)) {
- /* This code doesn't know how to translate 16-bit modrm effective addresses.
- * However, such arguments are not nacl legal. Communicate this explicitly.
- */
- return NaClAppendNaClIllegal(state);
- }
- if (4 == modrm_rmInline(state->modrm)) {
- return NaClAppendSib(state);
- } else {
- NaClDisplacement displacement;
- NaClExtractDisplacement(state, &displacement, NACL_EFLAG(ExprSignedHex));
- return NaClAppendMemoryOffset(state,
- NaClLookupReg(
- state,
- NaClExtractAddressRegKind(state),
- NaClGetGenRmRegister(state)),
- RegUnknown,
- 1,
- &displacement);
- }
-}
-
-/* Get the Effective address in the mod/rm byte, if the modrm.mod field
- * is 10, and append it to the vector of expression nodes. Operand is
- * the corresponding operand of the opcode associated with the instruction
- * of the given state that corresponds to the effective address. Returns
- * the root of the appended effective address.
- */
-static NaClExp* NaClAppendMod10EffectiveAddress(
- NaClInstState* state, const NaClOp* operand) {
- DEBUG(NaClLog(LOG_INFO, "Translate modrm(%02x).mod == 10\n", state->modrm));
- if ((32 == NACL_TARGET_SUBARCH) &&
- NaClHasBit(state->prefix_mask, kPrefixADDR16)) {
- /* This code doesn't know how to translate 16-bit modrm effective addresses.
- * However, such arguments are not nacl legal. Communicate this explicitly.
- */
- return NaClAppendNaClIllegal(state);
- }
- if (4 == modrm_rmInline(state->modrm)) {
- return NaClAppendSib(state);
- } else {
- NaClDisplacement displacement;
- NaClOpKind base =
- NaClLookupReg(state,
- NaClExtractAddressRegKind(state),
- NaClGetGenRmRegister(state));
- NaClExtractDisplacement(state, &displacement, NACL_EFLAG(ExprSignedHex));
- return NaClAppendMemoryOffset(state, base, RegUnknown, 1, &displacement);
- }
-}
-
-/* Get the Effective address in the mod/rm byte, if the modrm.mod field
- * is 11, and append it to the vector of expression nodes. Operand is
- * the corresponding operand of the opcode associated with the instruction
- * of the given state that corresponds to the effective address. Returns
- * the root of the appended effective address.
- */
-static NaClExp* NaClAppendMod11EffectiveAddress(
- NaClInstState* state, const NaClOp* operand,
- NaClModRmRegKind modrm_reg_kind) {
- DEBUG(NaClLog(LOG_INFO, "Translate modrm(%02x).mod == 11, %s\n",
- state->modrm, g_NaClModRmRegKindName[modrm_reg_kind]));
- return NaClAppendOperandReg(state,
- operand,
- NaClGetGenRmRegister(state), modrm_reg_kind);
-}
-
-static NaClExp* NaClAppendBasedOnSize(NaClOpKind reg_2b,
- NaClOpKind reg_4b,
- NaClOpKind reg_8b,
- NaClInstState* state) {
- switch (state->operand_size) {
- case 2:
- return NaClAppendReg(reg_2b, &state->nodes);
- case 4:
- return NaClAppendReg(reg_4b, &state->nodes);
- case 8:
- return NaClAppendReg(reg_8b, &state->nodes);
- default:
- return NaClFatal("can't translate register group: operand size not valid",
- state);
- }
-}
-
-static NaClExp* NaClAppendBasedOnAddressSize(NaClOpKind reg_2b,
- NaClOpKind reg_4b,
- NaClOpKind reg_8b,
- NaClInstState* state) {
- switch (state->address_size) {
- case 16:
- return NaClAppendReg(reg_2b, &state->nodes);
- case 32:
- return NaClAppendReg(reg_4b, &state->nodes);
- case 64:
- return NaClAppendReg(reg_8b, &state->nodes);
- default:
- return NaClFatal("can't translate register group: address size not valid",
- state);
- }
-}
-
-/* Compute the effect address using the Mod/Rm and SIB bytes. */
-static NaClExp* NaClAppendEffectiveAddress(
- NaClInstState* state, const NaClOp* operand,
- NaClModRmRegKind modrm_reg_kind) {
- switch(modrm_modInline(state->modrm)) {
- case 0:
- return NaClAppendMod00EffectiveAddress(state, operand);
- case 1:
- return NaClAppendMod01EffectiveAddress(state, operand);
- case 2:
- return NaClAppendMod10EffectiveAddress(state, operand);
- case 3:
- return NaClAppendMod11EffectiveAddress(state, operand, modrm_reg_kind);
- default:
- break;
- }
- return NaClFatal("Operand", state);
-}
-
-/* Given the corresponding operand of the opcode associated with the
- * instruction of the given state, append the corresponding expression
- * nodes that it corresponds to. Returns the root of the corresponding
- * appended expression tree.
- */
-static NaClExp* NaClAppendOperand(NaClInstState* state,
- const NaClOp* operand) {
- DEBUG(NaClLog(LOG_INFO,
- "append operand %s\n", NaClOpKindName(operand->kind)));
- switch (operand->kind) {
- case A_Operand:
- return NaClAppendImmed(state);
- case E_Operand:
- case Eb_Operand:
- case Ew_Operand:
- case Ev_Operand:
- case Eo_Operand:
- case Edq_Operand:
- /* TODO(karl) Should we add limitations that simple registers
- * not allowed in M_Operand cases?
- */
- case M_Operand:
- case Mb_Operand:
- case Mw_Operand:
- case Mv_Operand:
- case Mo_Operand:
- case Mdq_Operand: {
- NaClExp* address =
- NaClAppendEffectiveAddress(state, operand, ModRmGeneral);
- /* Near operands are jump addresses. Mark them as such. */
- if (operand->flags & NACL_OPFLAG(OperandNear)) {
- address->flags |= NACL_EFLAG(ExprJumpTarget);
- }
- return address;
- }
- break;
- case G_Operand:
- case Gb_Operand:
- case Gw_Operand:
- case Gv_Operand:
- case Go_Operand:
- case Gdq_Operand:
- return NaClAppendOperandReg(state, operand, NaClGetGenRegRegister(state),
- ModRmGeneral);
- case Seg_G_Operand:
- return NaClAppendSegmentOpReg(
- state, operand, NaClGetMnemonicSegmentRegister(state),
- NaClGetGenRegRegister(state), ModRmGeneral);
- case G_OpcodeBase:
- return NaClAppendOpcodeBaseReg(state, operand);
- case I_Operand:
- case Ib_Operand:
- case Iw_Operand:
- case Iv_Operand:
- case Io_Operand:
- return NaClAppendImmed(state);
- case I2_Operand:
- return NaClAppendImmed2(state);
- case J_Operand:
- case Jb_Operand:
- case Jw_Operand:
- case Jv_Operand:
- /* TODO(karl) use operand flags OperandNear and OperandRelative to decide
- * how to process the J operand (see Intel manual for call statement).
- */
- return NaClAppendRelativeImmed(state);
- case Mmx_Gd_Operand:
- case Mmx_G_Operand:
- return NaClAppendOperandReg(state, operand, NaClGetGenRegRegister(state),
- ModRmMmx);
- case Mmx_E_Operand:
- return NaClAppendEffectiveAddress(state, operand, ModRmMmx);
- case Xmm_G_Operand:
- case Xmm_Go_Operand:
- return NaClAppendOperandReg(state, operand, NaClGetGenRegRegister(state),
- ModRmXmm);
- case Xmm_E_Operand:
- case Xmm_Eo_Operand:
- return NaClAppendEffectiveAddress(state, operand, ModRmXmm);
- case C_Operand:
- return NaClAppendEffectiveAddress(state, operand, ModRmCreg);
- case D_Operand:
- return NaClAppendEffectiveAddress(state, operand, ModRmDreg);
- case O_Operand:
- case Ob_Operand:
- case Ow_Operand:
- case Ov_Operand:
- case Oo_Operand:
- return NaClAppendMemoryOffsetImmed(state);
- case St_Operand:
- return NaClAppendStOpcodeBaseReg(state);
- case RegUnknown:
- case RegAL:
- case RegBL:
- case RegCL:
- case RegDL:
- case RegAH:
- case RegBH:
- case RegCH:
- case RegDH:
- case RegDIL:
- case RegSIL:
- case RegBPL:
- case RegSPL:
- case RegR8B:
- case RegR9B:
- case RegR10B:
- case RegR11B:
- case RegR12B:
- case RegR13B:
- case RegR14B:
- case RegR15B:
- case RegAX:
- case RegBX:
- case RegCX:
- case RegDX:
- case RegSI:
- case RegDI:
- case RegBP:
- case RegSP:
- case RegR8W:
- case RegR9W:
- case RegR10W:
- case RegR11W:
- case RegR12W:
- case RegR13W:
- case RegR14W:
- case RegR15W:
- case RegEAX:
- case RegEBX:
- case RegECX:
- case RegEDX:
- case RegESI:
- case RegEDI:
- case RegEBP:
- case RegESP:
- case RegR8D:
- case RegR9D:
- case RegR10D:
- case RegR11D:
- case RegR12D:
- case RegR13D:
- case RegR14D:
- case RegR15D:
- case RegCS:
- case RegDS:
- case RegSS:
- case RegES:
- case RegFS:
- case RegGS:
- case RegCR0:
- case RegCR1:
- case RegCR2:
- case RegCR3:
- case RegCR4:
- case RegCR5:
- case RegCR6:
- case RegCR7:
- case RegCR8:
- case RegCR9:
- case RegCR10:
- case RegCR11:
- case RegCR12:
- case RegCR13:
- case RegCR14:
- case RegCR15:
- case RegDR0:
- case RegDR1:
- case RegDR2:
- case RegDR3:
- case RegDR4:
- case RegDR5:
- case RegDR6:
- case RegDR7:
- case RegDR8:
- case RegDR9:
- case RegDR10:
- case RegDR11:
- case RegDR12:
- case RegDR13:
- case RegDR14:
- case RegDR15:
- case RegEFLAGS:
- case RegRFLAGS:
- case RegEIP:
- case RegRIP:
- case RegRAX:
- case RegRBX:
- case RegRCX:
- case RegRDX:
- case RegRSI:
- case RegRDI:
- case RegRBP:
- case RegRSP:
- case RegR8:
- case RegR9:
- case RegR10:
- case RegR11:
- case RegR12:
- case RegR13:
- case RegR14:
- case RegR15:
- case RegST0:
- case RegST1:
- case RegST2:
- case RegST3:
- case RegST4:
- case RegST5:
- case RegST6:
- case RegST7:
- case RegMMX1:
- case RegMMX2:
- case RegMMX3:
- case RegMMX4:
- case RegMMX5:
- case RegMMX6:
- case RegMMX7:
- case RegXMM0:
- case RegXMM1:
- case RegXMM2:
- case RegXMM3:
- case RegXMM4:
- case RegXMM5:
- case RegXMM6:
- case RegXMM7:
- case RegXMM8:
- case RegXMM9:
- case RegXMM10:
- case RegXMM11:
- case RegXMM12:
- case RegXMM13:
- case RegXMM14:
- case RegXMM15:
- return NaClAppendReg(operand->kind, &state->nodes);
- case RegREIP:
- return NaClAppendReg(state->address_size == 64 ? RegRIP : RegEIP,
- &state->nodes);
-
- case RegREAX:
- return NaClAppendBasedOnSize(RegAX, RegEAX, RegRAX, state);
- case RegREBX:
- return NaClAppendBasedOnSize(RegBX, RegEBX, RegRBX, state);
- case RegRECX:
- return NaClAppendBasedOnSize(RegCX, RegECX, RegRCX, state);
- case RegREDX:
- return NaClAppendBasedOnSize(RegDX, RegEDX, RegRDX, state);
- case RegRESP:
- return NaClAppendBasedOnSize(RegSP, RegESP, RegRSP, state);
- case RegREBP:
- return NaClAppendBasedOnSize(RegBP, RegEBP, RegRBP, state);
- case RegRESI:
- return NaClAppendBasedOnSize(RegSI, RegESI, RegRSI, state);
- case RegREDI:
- return NaClAppendBasedOnSize(RegDI, RegEDI, RegRSI, state);
- case RegREAXa:
- return NaClAppendBasedOnAddressSize(RegAX, RegEAX, RegRAX, state);
-
- case RegDS_ESI:
- return NaClAppendDS_ESI(state);
- case RegDS_EDI:
- return NaClAppendDS_EDI(state);
- case RegDS_EBX:
- return NaClAppendDS_EBX(state);
- case RegES_EDI:
- return NaClAppendES_EDI(state);
-
- case S_Operand:
- return NaClAppendModRmSegmentReg(state);
-
- case Const_1:
- return NaClAppendConst(1,
- NACL_EFLAG(ExprSize8) | NACL_EFLAG(ExprUnsignedHex),
- &state->nodes);
- default:
- /* Give up, use the default of undefined. */
- break;
- }
- return NaClFatal("Operand", state);
-}
-
-/* Given that the given expression node is the root of the expression
- * tree generated by translating the given operand, transfer over
- * any appropriate flags (such as set/use information).
- */
-static NaClExp* NaClAddOpSetUse(NaClExp* node, const NaClOp* operand) {
- if (operand->flags & NACL_OPFLAG(OpSet)) {
- node->flags |= NACL_EFLAG(ExprSet);
- }
- if (operand->flags & NACL_OPFLAG(OpUse)) {
- node->flags |= NACL_EFLAG(ExprUsed);
- }
- if (operand->flags & NACL_OPFLAG(OpAddress)) {
- node->flags |= NACL_EFLAG(ExprAddress);
- }
- return node;
-}
-
-void NaClBuildExpVector(struct NaClInstState* state) {
- uint8_t i;
- uint8_t num_ops;
- DEBUG(NaClLog(LOG_INFO,
- "building expression vector for pc = %"NACL_PRIxNaClPcAddress
- ":\n", state->inst_addr));
- num_ops = NaClGetInstNumberOperandsInline(state->inst);
- for (i = 0; i < num_ops; i++) {
- NaClExp* n;
- const NaClOp* op = NaClGetInstOperandInline(state->decoder_tables,
- state->inst, i);
- DEBUG(NaClLog(LOG_INFO, "translating operand %d:\n", i));
- n = NaClAppendExp(OperandReference, i,
- NACL_EFLAG(ExprSize8) | NACL_EFLAG(ExprUnsignedInt),
- &state->nodes);
- if (op->flags & NACL_OPFLAG(OpImplicit)) {
- n->flags |= NACL_EFLAG(ExprImplicit);
- }
- NaClAddOpSetUse(NaClAppendOperand(state, op), op);
- DEBUG(NaClExpVectorPrint(NaClLogGetGio(), state));
- }
-}
« no previous file with comments | « src/trusted/validator/x86/decoder/nc_inst_trans.h ('k') | src/trusted/validator/x86/decoder/ncdis_decode_tables.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698