Example #1
0
void NaClJumpValidator(NaClValidatorState* vstate) {
  NaClRememberInstructionBoundary(vstate, vstate->cur_inst_state);
  if (vstate->cur_inst->flags &
      (NACL_IFLAG(JumpInstruction) | NACL_IFLAG(ConditionalJump))) {
    NaClAddExprJumpTarget(vstate);
    if (vstate->cur_inst->name == InstCall) {
      NaClValidateCallAlignment(vstate);
    }
  }
}
/* Inspect the parsed instruction to print out the opcode sequence matched. */
static void NaClInstPrintOpcodeSeq(struct Gio* gout,
                                   const NaClInstState* state) {
  size_t count = 0;
  if (state->num_opcode_bytes == 0) {
    /* Hard coded bytes sequence for instruction. */
    gprintf(gout, "  %s", kHardCodedMessage);
    count = strlen(kHardCodedMessage) + 2;
  } else {
    /* Modeled instruction. Pull out parsed opcode bytes from parsed
     * instruction.
     */
    int i;
    gprintf(gout, " ");
    count = 1;

    /* Add prefix selector if applicable. */
    if (state->opcode_prefix) {
      gprintf(gout, " %02x", state->opcode_prefix);
      count += 3;
    }

    /* Add opcode bytes. */
    for (i = 0; i < state->num_opcode_bytes; ++i) {
      gprintf(gout, " %02x", state->bytes.byte[state->num_prefix_bytes + i]);
      count += 3;
    }
    if (state->inst->flags & NACL_IFLAG(OpcodeInModRm)) {
      gprintf(gout, " / %d", modrm_opcode(state->modrm));
      count += 4;
    } else if (state->inst->flags & NACL_IFLAG(OpcodePlusR)) {
      gprintf(gout, " - r%d",
              NaClGetOpcodePlusR(state->inst->opcode_ext));
      count += 5;
    }
    if (state->inst->flags & NACL_IFLAG(OpcodeInModRmRm)) {
      gprintf(gout, " / %d", modrm_rm(state->modrm));
      count += 4;
    }
    /* Add opcode for 0f0f instructions, where the opcode is the last
     * byte of the instruction.
     */
    if ((state->num_opcode_bytes >= 2) &&
        (0 == (state->inst->flags & NACL_IFLAG(Opcode0F0F))) &&
        (0x0F == state->bytes.byte[state->num_prefix_bytes]) &&
        (0x0F == state->bytes.byte[state->num_prefix_bytes + 1])) {
      gprintf(gout, " %02x", state->bytes.byte[state->bytes.length - 1]);
      count += 3;
    }
  }
  while (count < 30) {
    gprintf(gout, " ");
    ++count;
  }
}
void NaClAddRepPrefixFlagsIfApplicable() {
  if (NaClInInstructionSet(kAllowableRepMnemonic,
                           NACL_ARRAY_SIZE(kAllowableRepMnemonic),
                           kAllowableRepMnemonicOpseq,
                           NACL_ARRAY_SIZE(kAllowableRepMnemonicOpseq))) {
    NaClAddIFlags(NACL_IFLAG(OpcodeAllowsRep));
  }
  if (NaClInInstructionSet(kAllowableRepneMnemonic,
                           NACL_ARRAY_SIZE(kAllowableRepneMnemonic),
                           NULL, 0)) {
    NaClAddIFlags(NACL_IFLAG(OpcodeAllowsRepne));
  }
}
Example #4
0
/* 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;
      }
  }
}
Example #5
0
/* TODO(kschimpf): Delete this function if unneeded. */
static void NaClDefX87MrmNoOperands(const NaClInstPrefix prefix,
                                    const uint8_t opcode,
                                    const NaClOpKind opcode_in_modrm,
                                    const NaClMnemonic mnemonic) {
  NaClDefInstPrefix(prefix);
  NaClDefInst(opcode, NACLi_X87, NACL_IFLAG(OpcodeInModRm), mnemonic);
  NaClDefOp(opcode_in_modrm, NACL_OPFLAG(OperandExtendsOpcode));
  NaClResetToDefaultInstPrefix();
}
Example #6
0
/* Define an x87 instruction that has two operands, a memory pointer
 * and st0, and the memory pointer is defined by the value of st0.
 */
static void NaClDefX87LtC0MoveMemSt0(const NaClInstPrefix prefix,
                                     const uint8_t opcode,
                                     const NaClOpKind opcode_in_modrm,
                                     const NaClMnemonic mnemonic) {
  NaClDefInstPrefix(prefix);
  NaClDefInst(opcode, NACLi_X87, NACL_IFLAG(OpcodeLtC0InModRm), mnemonic);
  NaClDefOp(opcode_in_modrm, NACL_OPFLAG(OperandExtendsOpcode));
  NaClDefOp(M_Operand, NACL_OPFLAG(OpSet));
  NaClDefOp(RegST0, NACL_OPFLAG(OpUse));
  NaClResetToDefaultInstPrefix();
}
Example #7
0
/* Define an x87 instruction that uses a single memory pointer. */
static void NaClDefX87LtC0Mem(const NaClInstPrefix prefix,
                              const uint8_t opcode,
                              const NaClOpKind opcode_in_modrm,
                              const NaClMnemonic mnemonic,
                              const NaClOpFlags mfp_flags) {
  NaClDefInstPrefix(prefix);
  NaClDefInst(opcode, NACLi_X87, NACL_IFLAG(OpcodeLtC0InModRm), mnemonic);
  NaClDefOp(opcode_in_modrm, NACL_OPFLAG(OperandExtendsOpcode));
  NaClDefOp(M_Operand, mfp_flags);
  NaClResetToDefaultInstPrefix();
}
Example #8
0
/* TODO(kschimpf): Delete this function if unneeded. */
static void BrokenOldDefineX87St0(const NaClInstPrefix prefix,
                                  const uint8_t opcode,
                                  const NaClOpKind opcode_in_modrm,
                                  NaClMnemonic mnemonic,
                                  const NaClOpFlags st0_flags) {
  NaClDefInstPrefix(prefix);
  NaClDefInst(opcode, NACLi_X87, NACL_IFLAG(OpcodeInModRm), mnemonic);
  NaClDefOp(opcode_in_modrm, NACL_OPFLAG(OperandExtendsOpcode));
  NaClDefOp(RegST0, st0_flags);
  NaClResetToDefaultInstPrefix();
}
Example #9
0
/* Define an x87 instruction that updates sti, based on its previous value. */
static void NaClDefX87Sti(const NaClInstPrefix prefix,
                          const uint8_t opcode,
                          const int base_offset,
                          const NaClMnemonic mnemonic,
                          const NaClOpFlags sti_flags) {
  NaClDefInstPrefix(prefix);
  NaClDefInst(opcode + base_offset, NACLi_X87, NACL_IFLAG(OpcodePlusR),
              mnemonic);
  NaClDefOp(OpcodeBaseMinus0 + base_offset, NACL_OPFLAG(OperandExtendsOpcode));
  NaClDefOp(St_Operand, sti_flags);
  NaClResetToDefaultInstPrefix();
}
Example #10
0
/* Define an x87 binary instruction that has sti as its first argument,
 * and st0 as its second argument.
 */
static void NaClDefX87BinopStiSt0(const NaClInstPrefix prefix,
                                  const uint8_t opcode,
                                  const int base_offset,
                                  const NaClMnemonic mnemonic) {
  NaClDefInstPrefix(prefix);
  NaClDefInst(opcode + base_offset, NACLi_X87, NACL_IFLAG(OpcodePlusR),
              mnemonic);
  NaClDefOp(OpcodeBaseMinus0 + base_offset, NACL_OPFLAG(OperandExtendsOpcode));
  NaClDefOp(St_Operand, NACL_OPFLAG(OpSet) | NACL_OPFLAG(OpUse));
  NaClDefOp(RegST0, NACL_OPFLAG(OpUse));
  NaClResetToDefaultInstPrefix();
}
/* Print instruction flags using a simplified (i.e. more human readable) form */
void NaClIFlagsPrint(struct Gio* f, NaClIFlags flags) {
  int i;
  Bool first = TRUE;
  for (i = 0; i < NaClIFlagEnumSize; ++i) {
    if (flags & NACL_IFLAG(i)) {
      if (first) {
        first = FALSE;
      } else {
        gprintf(f, " ");
      }
      gprintf(f, "%s", NaClIFlagName(i));
    }
  }
}
/* Add OperandZeroExtends_v to instruction, if it can hold
 * a 32 bit operand.
 */
static void AddZeroExtendToOpDestArgs(NaClModeledInst* inst) {
  if (inst->flags & NACL_IFLAG(OperandSize_v)) {
    int i;
    for (i = 0; i < inst->num_operands; ++i) {
      /* Note: we currently don't allow zero extends for
       * implicit arguments. This is done just to be extra
       * cautious on what we allow to be masks in the
       * NaCl x64-64 validator.
       */
      if ((inst->operands[i].flags & NACL_OPFLAG(OpSet)) &&
          (NACL_EMPTY_OPFLAGS ==
           (inst->operands[i].flags & NACL_OPFLAG(OpImplicit)))) {
        NaClAddOpFlags(i, NACL_OPFLAG(OperandZeroExtends_v));
      }
    }
  }
}
static void NaCl3DNow0F0FInsts(struct NaClSymbolTable* st) {
  /* All 3DNOW instructions of form: 0f 0f [modrm] [sib] [displacement]
   *      imm8_opcode
   *
   * These instructions encode into "OP Pq, Qq", based on the value of
   * imm8_opcode. We decode these instructions in two steps. The first
   * step uses a OF0F instruction to read in the bytes of the instruction.
   * These bytes are then inspected, and is replaced by the corresponding
   * 3DNOW instruction in the OFOF prefix table. If no such entry is found,
   * The original match is left so that the bytes are marked as an
   * invalid 3dnow instruction.
   *
   * Note: 3DNow instructions are defined in document 21928G/0-March 2000:
   * "3DNow!(TM) Technology Manual".
   */
  NaClBegDef("     0f0f:     Invalid $Pq, $Qq, $Ib",
                                                   NACLi_INVALID,   st);
  NaClAddIFlags(NACL_IFLAG(Opcode0F0F));
  NaClEndDef(                                                         Other);
  NaClDefine("     0f0f..0c: Pi2fw $Pq, $Qq",      NACLi_E3DNOW,  st, Move);
  NaClDefine("     0f0f..0d: Pi2fd $Pq, $Qq",      NACLi_3DNOW,   st, Move);
  NaClDefine("     0f0f..1c: Pf2iw $Pq, $Qq",      NACLi_E3DNOW,  st, Move);
  NaClDefine("     0f0f..1d: Pf2id $Pq, $Qq",      NACLi_3DNOW,   st, Move);
  NaClDefine("     0f0f..8a: Pfnacc $Pq, $Qq",     NACLi_E3DNOW,  st, Binary);
  NaClDefine("     0f0f..8e: Pfpnacc $Pq, $Qq",    NACLi_E3DNOW,  st, Binary);
  NaClDefine("     0f0f..90: Pfcmpge $Pq, $Qq",    NACLi_3DNOW,   st, Binary);
  NaClDefine("     0f0f..94: Pfmin $Pq, $Qq",      NACLi_3DNOW,   st, Binary);
  NaClDefine("     0f0f..96: Pfrcp $Pq, $Qq",      NACLi_3DNOW,   st, Move);
  NaClDefine("     0f0f..97: Pfrsqrt $Pq, $Qq",    NACLi_3DNOW,   st, Move);
  NaClDefine("     0f0f..9a: Pfsub $Pq, $Qq",      NACLi_3DNOW,   st, Binary);
  NaClDefine("     0f0f..9e: Pfadd $Pq, $Qq",      NACLi_3DNOW,   st, Binary);
  NaClDefine("     0f0f..a0: Pfcmpgt $Pq, $Qq",    NACLi_3DNOW,   st, Binary);
  NaClDefine("     0f0f..a4: Pfmax $Pq, $Qq",      NACLi_3DNOW,   st, Binary);
  NaClDefine("     0f0f..a6: Pfrcpit1 $Pq, $Qq",   NACLi_3DNOW,   st, Binary);
  NaClDefine("     0f0f..a7: Pfrsqit1 $Pq, $Qq",   NACLi_3DNOW,   st, Binary);
  NaClDefine("     0f0f..aa: Pfsubr $Pq, $Qq",     NACLi_3DNOW,   st, Binary);
  NaClDefine("     0f0f..ae: Pfacc $Pq, $Qq",      NACLi_3DNOW,   st, Binary);
  NaClDefine("     0f0f..b0: Pfcmpeq $Pq, $Qq",    NACLi_3DNOW,   st, Binary);
  NaClDefine("     0f0f..b4: Pfmul $Pq, $Qq",      NACLi_3DNOW,   st, Binary);
  NaClDefine("     0f0f..b6: Pfrcpit2 $Pq, $Qq",   NACLi_3DNOW,   st, Binary);
  NaClDefine("     0f0f..b7: Pmulhrw $Pq, $Qq",    NACLi_3DNOW,   st, Binary);
  NaClDefine("     0f0f..bb: Pswapd $Pq, $Qq",     NACLi_E3DNOW,  st, Move);
  NaClDefine("     0f0f..bf: Pavgusb $Pq, $Qq",    NACLi_3DNOW,   st, Binary);
}
Example #14
0
/* Print the given instruction opcode of the give state, to the
 * given file.
 */
static void NaClPrintDisassembled(struct Gio* file,
                                  NaClInstState* state,
                                  const NaClInst* inst) {
  uint32_t tree_index = 0;
  Bool is_first = TRUE;
  Bool not_printed_prefix_segment = TRUE;
  NaClExp* node;
  NaClExpVector* vector = NaClInstStateExpVector(state);

  /* Print the name of the instruction. */
  if (NaClHasBit(inst->flags, NACL_IFLAG(PartialInstruction))) {
    /* Instruction has been simplified. Print out corresponding
     * hints to the reader, so that they know that the instruction
     * has been simplified.
     */
    gprintf(file, "[P] ");
    NaClPrintLower(file, (char*) NaClMnemonicName(inst->name));
    if (NaClHasBit(inst->flags, NACL_IFLAG(NaClIllegal))) {
      gprintf(file, "(illegal)");
    }
  } else {
    NaClPrintLower(file, (char*) NaClMnemonicName(inst->name));
  }

  /* Use the generated expression tree to print out (non-implicit) operands
   * of the instruction.
   */
  while (tree_index < vector->number_expr_nodes) {
    node = &vector->node[tree_index];
    if (node->kind != OperandReference ||
        (NACL_EMPTY_EFLAGS == (node->flags & NACL_EFLAG(ExprImplicit)))) {
      if (is_first) {
        gprintf(file, " ");
        is_first = FALSE;
      } else {
        gprintf(file, ", ");
      }
      NaClPrintDisassembledExp(file, state, tree_index);

      /* If this is a partial instruction, add set/use information
       * so that that it is more clear what was matched.
       */
      if (NaClHasBit(inst->flags, NACL_IFLAG(PartialInstruction)) &&
          node->kind == OperandReference) {
        const NaClOp* op =
            NaClGetInstOperandInline(state->decoder_tables,
                                     inst,
                                     (uint8_t) NaClGetExprUnsignedValue(node));
        if (NaClHasBit(op->flags, (NACL_OPFLAG(OpSet) |
                                   NACL_OPFLAG(OpUse) |
                                   NACL_OPFLAG(OperandZeroExtends_v)))) {
          gprintf(file, " (");
          NaClPrintAddOperandFlag(file, op, OpSet, "s");
          NaClPrintAddOperandFlag(file, op, OpUse, "u");
          NaClPrintAddOperandFlag(file, op, OperandZeroExtends_v, "z");
          gprintf(file, ")");
        }
      }
    } else if (not_printed_prefix_segment &&
               (OperandReference == node->kind) &&
               (node->flags & NACL_EFLAG(ExprImplicit))) {
      /* Print out segment override of implicit segment address, if
       * applicable.
       */
      if (OperandReference == node->kind) {
        int seg_addr_index = tree_index + 1;
        if (ExprSegmentAddress == vector->node[seg_addr_index].kind) {
          if (NaClHasSegmentOverride(vector, seg_addr_index,
                                     ExprDSrCase, RegDS)) {
            NaClPrintSegmentOverride(file, &is_first, state, vector,
                                     seg_addr_index);
          } else if (NaClHasSegmentOverride(vector, seg_addr_index,
                                            ExprESrCase, RegES)) {
            NaClPrintSegmentOverride(file, &is_first, state, vector,
                                     seg_addr_index);
          }
        }
      }
    }
    /* Skip over expression to next expresssion. */
    tree_index += NaClExpWidth(vector, tree_index);
  }
}
static void NaClAddJumpFlags(NaClIFlag flag, const NaClMnemonic* name,
                             size_t name_size) {
  if (NaClInInstructionSet(name, name_size, NULL, 0)) {
    NaClGetDefInst()->flags |= NACL_IFLAG(flag);
  }
}
Example #16
0
/* Add LongMode instruction flag if applicable. */
void NaClAddLongModeIfApplicable() {
  if (NaClInInstructionSet(kLongModeOp, NACL_ARRAY_SIZE(kLongModeOp),
                           NULL, 0)) {
    NaClAddIFlags(NACL_IFLAG(LongMode));
  }
}
void NaClCpuCheck(struct NaClValidatorState* state,
                  struct NaClInstIter* iter) {
  Bool squash_me = FALSE;
  switch (state->cur_inst->insttype) {
    case NACLi_X87:
    case NACLi_X87_FSINCOS:
      NaClCheckFeature(NaClCPUFeatureX86_x87, state, &squash_me);
      break;
    case NACLi_SFENCE_CLFLUSH:
      /* TODO(bradchen): distinguish between SFENCE and CLFLUSH */
      NaClCheckFeature(NaClCPUFeatureX86_CLFLUSH, state, &squash_me);
      NaClCheckFeature(NaClCPUFeatureX86_FXSR, state, &squash_me);
      break;
    case NACLi_CMPXCHG8B:
      NaClCheckFeature(NaClCPUFeatureX86_CX8, state, &squash_me);
      break;
    case NACLi_CMPXCHG16B:
      NaClCheckFeature(NaClCPUFeatureX86_CX16, state, &squash_me);
      break;
    case NACLi_CMOV:
      NaClCheckFeature(NaClCPUFeatureX86_CMOV, state, &squash_me);
      break;
    case NACLi_FCMOV:
      if (!(NaClGetCPUFeatureX86(&state->cpu_features,
                                 NaClCPUFeatureX86_CMOV) &&
            NaClGetCPUFeatureX86(&state->cpu_features,
                                 NaClCPUFeatureX86_x87))) {
        if (!state->cpu_checks.f_CMOV_and_x87) {
          NaClValidatorInstMessage(
              LOG_WARNING, state, state->cur_inst_state,
              "CPU model does not support CMOV and x87 instructions.\n");
          state->cpu_checks.f_CMOV_and_x87 = TRUE;
        }
        squash_me = TRUE;
      }
      break;
    case NACLi_RDTSC:
      NaClCheckFeature(NaClCPUFeatureX86_TSC, state, &squash_me);
      break;
    case NACLi_MMX:
      NaClCheckFeature(NaClCPUFeatureX86_MMX, state, &squash_me);
      break;
    case NACLi_MMXSSE2:
      /* Note: We accept these instructions if either MMX or SSE2 bits */
      /* are set, in case MMX instructions go away someday...          */
      if (!(NaClGetCPUFeatureX86(&state->cpu_features,
                                 NaClCPUFeatureX86_MMX) ||
            NaClGetCPUFeatureX86(&state->cpu_features,
                                 NaClCPUFeatureX86_SSE2))) {
        if (!state->cpu_checks.f_MMX_or_SSE2) {
          NaClValidatorInstMessage(
              LOG_WARNING, state, state->cur_inst_state,
              "CPU model does not support MMX or SSE2 instructions.\n");
          state->cpu_checks.f_MMX_or_SSE2 = TRUE;
        }
      }
      squash_me = TRUE;
      break;
    case NACLi_SSE:
      NaClCheckFeature(NaClCPUFeatureX86_SSE, state, &squash_me);
      break;
    case NACLi_SSE2:
      NaClCheckFeature(NaClCPUFeatureX86_SSE2, state, &squash_me);
      break;
    case NACLi_SSE3:
      NaClCheckFeature(NaClCPUFeatureX86_SSE3, state, &squash_me);
      break;
    case NACLi_SSE4A:
      NaClCheckFeature(NaClCPUFeatureX86_SSE4A, state, &squash_me);
      break;
    case NACLi_SSE41:
      NaClCheckFeature(NaClCPUFeatureX86_SSE41, state, &squash_me);
      break;
    case NACLi_SSE42:
      NaClCheckFeature(NaClCPUFeatureX86_SSE42, state, &squash_me);
      break;
    case NACLi_MOVBE:
      NaClCheckFeature(NaClCPUFeatureX86_MOVBE, state, &squash_me);
      break;
    case NACLi_POPCNT:
      NaClCheckFeature(NaClCPUFeatureX86_POPCNT, state, &squash_me);
      break;
    case NACLi_LZCNT:
      NaClCheckFeature(NaClCPUFeatureX86_LZCNT, state, &squash_me);
      break;
    case NACLi_SSSE3:
      NaClCheckFeature(NaClCPUFeatureX86_SSSE3, state, &squash_me);
      break;
    case NACLi_3DNOW:
      NaClCheckFeature(NaClCPUFeatureX86_3DNOW, state, &squash_me);
      break;
    case NACLi_E3DNOW:
      NaClCheckFeature(NaClCPUFeatureX86_E3DNOW, state, &squash_me);
      break;
    case NACLi_LONGMODE:
      /* TODO(karl): Remove this when NACLi_LONGMODE is no longer needed */
      NaClCheckFeature(NaClCPUFeatureX86_LM, state, &squash_me);
      break;
    case NACLi_SSE2x:
      /* This case requires CPUID checking code */
      /* DATA16 prefix required */
      if (!(state->cur_inst_state->prefix_mask & kPrefixDATA16)) {
        NaClValidatorInstMessage(
            LOG_ERROR, state, state->cur_inst_state,
            "SSEx instruction must use prefix 0x66.\n");
      }
      NaClCheckFeature(NaClCPUFeatureX86_SSE2, state, &squash_me);
      break;
    default:
      /* This instruction could be either legal or illegal, but if we
       * get here it is not CPU-dependent.
       */
      break;
  }
  if (state->cur_inst->flags & NACL_IFLAG(LongMode)) {
    NaClCheckFeature(NaClCPUFeatureX86_LM, state, &squash_me);
  }
  if (squash_me) {
    if (state->readonly_text) {
      NaClValidatorInstMessage(
          LOG_ERROR, state, state->cur_inst_state,
          "Read-only text: cannot squash unsupported instruction.\n");
    } else {
      /* Replace all bytes of the instruction with the HLT instruction. */
      NCStubOutMem(state, NaClInstIterGetInstMemoryInline(iter),
                   NaClInstStateLength(state->cur_inst_state));
    }
  }
}
static void NaClInstLayoutCheck(NaClValidatorState* vstate) {
  NaClPcAddress start;
  NaClPcAddress end;
  NaClPcAddress i;
  if (NULL == vstate->cur_inst_state) return;

  DEBUG(NaClLog(LOG_INFO, "Jump layout check: ");
        NaClInstStateInstPrint(NaClLogGetGio(), vstate->cur_inst_state));

  /* Check basic block boundaries. */
  start = vstate->cur_inst_state->inst_addr;

  /* Check that if first instruction in a basic block, it isn't in the
   * middle of a pattern.
   */
  if ((0 == (start & vstate->bundle_mask)) &&
      NaClAddressSetContains(vstate->jump_sets.removed_targets,
                             start, vstate)) {
    NaClValidatorInstMessage(
        LOG_ERROR, vstate, vstate->cur_inst_state,
        "Instruction begins basic block, but in middle of nacl pattern\n");
  }

  /* Check that instruction doesn't cross block boundaries. */
  end = (NaClPcAddress) (start + vstate->cur_inst_state->bytes.length);
  for (i = start + 1; i < end; ++i) {
    if (0 == (i & vstate->bundle_mask)) {
      NaClValidatorInstMessage(
          LOG_ERROR, vstate, vstate->cur_inst_state,
          "Instruction crosses basic block alignment\n");
    }
  }

  /* Check jump targets. */
  if (NaClHasBit(vstate->cur_inst_state->inst->flags,
                 NACL_IFLAG(JumpInstruction) | NACL_IFLAG(ConditionalJump))) {
    uint32_t i;
    NaClExpVector* vector = NaClInstStateExpVector(vstate->cur_inst_state);
    for (i = 0; i < vector->number_expr_nodes; ++i) {
      NaClExp* node = &vector->node[i];
      if (NaClHasBit(node->flags, NACL_EFLAG(ExprJumpTarget))
          && node->kind == ExprConstant) {
        /* Explicit jump value. Check if legal! */
        NaClPcAddress target = end +
            (NaClPcNumber) NaClGetExprSignedValue(node);
        /* Don't report targets that are out of range. They should have
         * been reported in the first pass!
         */
        if (NaClCheckAddressRange(target, vstate)) {
          if (NaClAddressSetContains(vstate->jump_sets.possible_targets,
                                     target, vstate)) {
            if (NaClAddressSetContains(vstate->jump_sets.removed_targets,
                                       target, vstate)) {
              NaClValidatorInstMessage(
                  LOG_ERROR, vstate, vstate->cur_inst_state,
                  "Jumps into middle of nacl pattern\n");
            }
          } else {
            NaClValidatorInstMessage(
                LOG_ERROR, vstate, vstate->cur_inst_state,
                "Doesn't jump to instruction address\n");
          }
        }
      }
    }
  }
}
void NaClDef0FInsts(struct NaClSymbolTable* st) {
  int i;
  NaClDefPrefixInstMrmChoices(Prefix0F, 0x01, 1, 4);
  NaClDefPrefixInstMrmChoices(Prefix0F, 0x01, 3, 9);
  NaClDefPrefixInstMrmChoices_32_64(Prefix0F, 0x01, 7, 2, 4);
  NaClDefPrefixInstMrmChoices_32_64(Prefix0F, 0xc7, 1, 1, 2);
  NaClDefPrefixInstMrmChoices(Prefix0F, 0xae, 5, 8);
  NaClDefPrefixInstMrmChoices(Prefix0F, 0xae, 6, 8);
  NaClDefPrefixInstMrmChoices(Prefix0F, 0xae, 7, 9);

  NaClDefine("     0f00/0:   Sldt $Mw/Rv",         NACLi_SYSTEM,  st, Sets);
  NaClDefine("     0f00/1:   Str   $Mw/Rv",        NACLi_SYSTEM,  st, Sets);
  NaClDefine("     0f00/2:   Lldt $Ew",            NACLi_SYSTEM,  st, Uses);
  NaClDefine("     0f00/3:   Ltr $Ew",             NACLi_SYSTEM,  st, Uses);
  NaClDefine("     0f00/4:   Verr $Ew",            NACLi_SYSTEM,  st, Other);
  NaClDefine("     0f00/5:   Verw $Ew",            NACLi_SYSTEM,  st, Other);
  NaClDefIter("    0f00/@i:  Invalid", 6, 7,       NACLi_INVALID, st, Other);
  NaClDefine("     0f01/0:   Sgdt $Ms",            NACLi_SYSTEM,  st, Sets);
  NaClDefine("     0f01/1:   Sidt $Ms",            NACLi_SYSTEM,  st, Sets);
  NaClDefine("     0f01/1/0: Monitor %reax, %ecx, %edx",
                                                   NACLi_SYSTEM,  st, Uses);
  NaClDefine("     0f01/1/1: Mwait %eax, %ecx",    NACLi_SYSTEM,  st, Other);
  NaClDefine("     0f01/1:   Invalid",             NACLi_INVALID, st, Other);
  NaClDefine("     0f01/2:   Lgdt $Ms",            NACLi_SYSTEM,  st, Uses);
  NaClDefine("     0f01/3:   Lidt $Ms",            NACLi_SYSTEM,  st, Uses);
  NaClDef_64("     0f01/3/0: Vmrun $rAXva",        NACLi_SVM,     st, Uses);
  NaClDefine("     0f01/3/1: Vmmcall",             NACLi_SVM,     st, Other);
  NaClDefine("     0f01/3/2: Vmload $rAXva",       NACLi_SVM,     st, Uses);
  NaClDefine("     0f01/3/3: Vmsave $rAXva",       NACLi_SVM,     st, Uses);
  NaClDefine("     0f01/3/4: Stgi",                NACLi_SVM,     st, Other);
  NaClDefine("     0f01/3/5: Clgi",                NACLi_SVM,     st, Other);
  NaClDefine("     0f01/3/6: Skinit {%eip}, %eax", NACLi_SVM,     st, Jump);
  NaClDefine("     0f01/3/7: Invlpga $rAXva, %ecx",
                                                   NACLi_SVM,     st, Uses);
  NaClDef_32("     0f01/3:   Invalid",             NACLi_INVALID, st, Other);
  NaClDefine("     0f01/4:   Smsw $Mw/Rv",         NACLi_SYSTEM,  st, Sets);
  NaClDefine("     0f01/5:   Invalid",             NACLi_INVALID, st, Other);
  NaClDefine("     0f01/6:   Lmsw $Ew",            NACLi_INVALID, st, Uses);
  NaClDefine("     0f01/7:   Invlpg $Mb",          NACLi_SYSTEM,  st, Uses);
  NaClDef_64("     0f01/7/0: Swapgs {%gs}",        NACLi_SYSTEM,  st, Sets);
  NaClDef_64("     0f01/7/1: Rdtscp {%rdx}, {%rax}, {%rcx}",
                                                   NACLi_RDTSCP,  st, Sets);
  NaClDefine("     0f01/7:   Invalid",             NACLi_INVALID, st, Other);
  /* Note: Xed appears to use Ev for second argument for Lar aand Lsl. */
  NaClDefine("     0f02:     Lar $Gv, $Ew",        NACLi_SYSTEM,  st, Other);
  NaClDefine("     0f03:     Lsl $Gv, $Ew",        NACLi_SYSTEM,  st, Other);
  NaClDefine("     0f04:     Invalid",             NACLi_INVALID, st, Other);
  NaClDef_64("     0f05:     Syscall {%rip}, {%rcx}",
                                                   NACLi_SYSCALL, st, SysCall);
  NaClDefine("     0f06:     Clts",                NACLi_SYSTEM,  st, Other);
  NaClDef_64("     0f07:     Sysret {%rip}, {%rcx}",
                                                   NACLi_SYSTEM,  st, SysRet);
  NaClDefine("     0f08:     Invd",                NACLi_SYSTEM,  st, Other);
  NaClDefine("     0f09:     Wbinvd",              NACLi_SYSTEM,  st, Other);
  NaClDefine("     0f0a:     Invalid",             NACLi_INVALID, st, Other);
  /* Note: ud2 with no prefix bytes is currently understood as a NOP sequence.
   * The definition here only applies to cases where prefix bytes are added.
   */
  NaClDefine("     0f0b:     Ud2",                 NACLi_386,     st, Other);
  NaClDefine("     0f0c:     Invalid",             NACLi_INVALID, st, Other);
  NaClDefine("     0f0d/0:   Prefetch_exclusive $Mb",
                                                   NACLi_3DNOW,   st, Other);
  NaClDefine("     0f0d/1:   Prefetch_modified $Mb",
                                                   NACLi_3DNOW,   st, Other);
  NaClDefine("     0f0d/2:   Prefetch_reserved $Mb",
                                                   NACLi_3DNOW,   st, Other);
  NaClDefine("     0f0d/3:   Prefetch_modified $Mb",
                                                   NACLi_3DNOW,   st, Other);
  NaClDefine("     0f0d/4:   Prefetch_reserved $Mb",
                                                   NACLi_3DNOW,   st, Other);
  NaClDefine("     0f0d/5:   Prefetch_reserved $Mb",
                                                   NACLi_3DNOW,   st, Other);
  NaClDefine("     0f0d/6:   Prefetch_reserved $Mb",
                                                   NACLi_3DNOW,   st, Other);
  NaClDefine("     0f0d/7:   Prefetch_reserved $Mb",
                                                   NACLi_3DNOW,   st, Other);
  NaClDefine("     0f0e:     Femms",               NACLi_3DNOW,   st, Other);
  NaCl3DNow0F0FInsts(st);
  NaClDefIter("  f20f13+@i:  Invalid", 0, 4,       NACLi_INVALID, st, Other);
  NaClDefine("     0f18/0:   Prefetchnta $Mb",     NACLi_MMX,     st, Other);
  NaClDefine("     0f18/1:   Prefetcht0 $Mb",      NACLi_MMX,     st, Other);
  NaClDefine("     0f18/2:   Prefetcht1 $Mb",      NACLi_MMX,     st, Other);
  NaClDefine("     0f18/3:   Prefetcht2 $Mb",      NACLi_MMX,     st, Other);
  /* The following 4 are reserved for future prefetch instructions. */
  NaClDefIter("    0f18/@i:  Invalid", 4, 7,       NACLi_INVALID, st, Other);
  NaClDefine("     0f1f/0:   Nop",                 NACLi_386,     st, Other);
  NaClDefIter("    0f19+@i/r: Nop", 0, 6,          NACLi_386,     st, Other);
  NaClDefine("     0f20:     Mov $Rd/q, $Cd/q",    NACLi_SYSTEM,  st, Move);
  NaClDefine("     0f21:     Mov $Rd/q, $Dd/q",    NACLi_SYSTEM,  st, Move);
  NaClDefine("     0f22:     Mov $Cd/q, $Rd/q",    NACLi_SYSTEM,  st, Move);
  NaClDefine("     0f23:     Mov $Dd/q, $Rd/q",    NACLi_SYSTEM,  st, Move);
  NaClDefIter("    0f24+@i:  Invalid", 0, 3,       NACLi_INVALID, st, Other);
  NaClDefine("     0f30:     Wrmsr {%eax}, {%edx}, {%ecx}",
                                                   NACLi_RDMSR,   st, Uses);
  NaClDefine("     0f31:     Rdtsc {%eax}, {%edx}",
                                                   NACLi_RDTSC,   st, Sets);
  NaClDefine("     0f32:     Rdmsr {%eax}, {%edx}, {%ecx}",
                                                   NACLi_RDMSR,   st, O2Move);
  NaClDefine("     0f33:     Rdpmc {%eax}, {%edx}, {%ecx}",
                                                   NACLi_SYSTEM,  st, O2Move);
  NaClDefine("     0f34:     Sysenter {%eip}, {%esp}, {%cs}, {%ss}",
                                                   NACLi_SYSENTER,st, SysJump);
  NaClDefine("     0f35:     Sysexit {%eip}, {%esp}, {%cs}, {%ss}, "
                                 "{%edx}, {%ecx}", NACLi_SYSENTER,st, SysJump);
  NaClDefIter("    0f36+@i:  Invalid", 0, 9,       NACLi_INVALID, st, Other);
  NaClDefine("     0f40:     Cmovo $Gv, $Ev",      NACLi_CMOV,    st, Move);
  NaClDefine("     0f41:     Cmovno $Gv, $Ev",     NACLi_CMOV,    st, Move);
  NaClDefine("     0f42:     Cmovb $Gv, $Ev",      NACLi_CMOV,    st, Move);
  NaClDefine("     0f43:     Cmovnb $Gv, $Ev",     NACLi_CMOV,    st, Move);
  NaClDefine("     0f44:     Cmovz $Gv, $Ev",      NACLi_CMOV,    st, Move);
  NaClDefine("     0f45:     Cmovnz $Gv, $Ev",     NACLi_CMOV,    st, Move);
  NaClDefine("     0f46:     Cmovbe $Gv, $Ev",     NACLi_CMOV,    st, Move);
  NaClDefine("     0f47:     Cmovnbe $Gv, $Ev",    NACLi_CMOV,    st, Move);
  NaClDefine("     0f48:     Cmovs $Gv, $Ev",      NACLi_CMOV,    st, Move);
  NaClDefine("     0f49:     Cmovns $Gv, $Ev",     NACLi_CMOV,    st, Move);
  NaClDefine("     0f4a:     Cmovp $Gv, $Ev",      NACLi_CMOV,    st, Move);
  NaClDefine("     0f4b:     Cmovnp $Gv, $Ev",     NACLi_CMOV,    st, Move);
  NaClDefine("     0f4c:     Cmovl $Gv, $Ev",      NACLi_CMOV,    st, Move);
  NaClDefine("     0f4d:     Cmovnl $Gv, $Ev",     NACLi_CMOV,    st, Move);
  NaClDefine("     0f4e:     Cmovle $Gv, $Ev",     NACLi_CMOV,    st, Move);
  NaClDefine("     0f4f:     Cmovnle $Gv, $Ev",    NACLi_CMOV,    st, Move);
  /* Note: We special case the 66 prefix on direct conditional jumps, by
   * explicitly disallowing 16-bit direct jumps. This is done partly because
   * some versions (within x86-64) are not supported in such cases. However,
   * NaCl also doesn't want to allow 16-bit direct jumps.
   */
  NaClDefine("     0f80:     Jo {%@ip}, $Jzd",     NACLi_386,     st, Jump);
  NaClDefine("     0f81:     Jno {%@ip}, $Jzd",    NACLi_386,     st, Jump);
  NaClDefine("     0f82:     Jb {%@ip}, $Jzd",     NACLi_386,     st, Jump);
  NaClDefine("     0f83:     Jnb {%@ip}, $Jzd",    NACLi_386,     st, Jump);
  NaClDefine("     0f84:     Jz {%@ip}, $Jzd",     NACLi_386,     st, Jump);
  NaClDefine("     0f85:     Jnz {%@ip}, $Jzd",    NACLi_386,     st, Jump);
  NaClDefine("     0f86:     Jbe {%@ip}, $Jzd",    NACLi_386,     st, Jump);
  NaClDefine("     0f87:     Jnbe {%@ip}, $Jzd",   NACLi_386,     st, Jump);
  NaClDefine("     0f88:     Js {%@ip}, $Jzd",     NACLi_386,     st, Jump);
  NaClDefine("     0f89:     Jns {%@ip}, $Jzd",    NACLi_386,     st, Jump);
  NaClDefine("     0f8a:     Jp {%@ip}, $Jzd",     NACLi_386,     st, Jump);
  NaClDefine("     0f8b:     Jnp {%@ip}, $Jzd",    NACLi_386,     st, Jump);
  NaClDefine("     0f8c:     Jl {%@ip}, $Jzd",     NACLi_386,     st, Jump);
  NaClDefine("     0f8d:     Jnl {%@ip}, $Jzd",    NACLi_386,     st, Jump);
  NaClDefine("     0f8e:     Jle {%@ip}, $Jzd",    NACLi_386,     st, Jump);
  NaClDefine("     0f8f:     Jnle {%@ip}, $Jzd",   NACLi_386,     st, Jump);
  NaClDefine("     0f90:     Seto $Eb",            NACLi_386,     st, Sets);
  NaClDefine("     0f91:     Setno $Eb",           NACLi_386,     st, Sets);
  NaClDefine("     0f92:     Setb $Eb",            NACLi_386,     st, Sets);
  NaClDefine("     0f93:     Setnb $Eb",           NACLi_386,     st, Sets);
  NaClDefine("     0f94:     Setz $Eb",            NACLi_386,     st, Sets);
  NaClDefine("     0f95:     Setnz $Eb",           NACLi_386,     st, Sets);
  NaClDefine("     0f96:     Setbe $Eb",           NACLi_386,     st, Sets);
  NaClDefine("     0f97:     Setnbe $Eb",          NACLi_386,     st, Sets);
  NaClDefine("     0f98:     Sets $Eb",            NACLi_386,     st, Sets);
  NaClDefine("     0f99:     Setns $Eb",           NACLi_386,     st, Sets);
  NaClDefine("     0f9a:     Setp $Eb",            NACLi_386,     st, Sets);
  NaClDefine("     0f9b:     Setnp $Eb",           NACLi_386,     st, Sets);
  NaClDefine("     0f9c:     Setl $Eb",            NACLi_386,     st, Sets);
  NaClDefine("     0f9d:     Setnl $Eb",           NACLi_386,     st, Sets);
  NaClDefine("     0f9e:     Setle $Eb",           NACLi_386,     st, Sets);
  NaClDefine("     0f9f:     Setnle $Eb",          NACLi_386,     st, Sets);
  NaClDefine("     0fa0:     Push {%@sp}, %fs",    NACLi_386,     st, Push);
  NaClDefine("     0fa1:     Pop {%@sp}, %fs",     NACLi_386,     st, Pop);
  NaClDefine("     0fa2:     Cpuid {%ebx}, {%edx}, {%eax}, {%ecx}",
                                                   NACLi_386,     st, Cpuid);
  NaClDefine("     0fa3:     Bt $Ev, $Gv",         NACLi_386,     st, Compare);
  NaClDefine("     0fa4:     Shld $Ev, $Gv, $Ib",  NACLi_386,     st, Binary);
  NaClDefine("     0fa5:     Shld $Ev, $Gv, %cl",  NACLi_386,     st, Binary);
  NaClDefIter("    0fa6+@i:  Invalid", 0, 1,       NACLi_INVALID, st, Other);
  NaClDefine("     0fa8:     Push {%@sp}, %gs",    NACLi_386,     st, Push);
  NaClDefine("     0fa9:     Pop {%@sp}, %gs",     NACLi_386,     st, Pop);
  NaClDefine("     0faa:     Rsm",                 NACLi_SYSTEM,  st, Other);
  NaClDefine("     0fab:     Bts $Ev, $Gv",        NACLi_386,     st, Binary);
  NaClDefine("     0fac:     Shrd $Ev, $Gv, $Ib",  NACLi_386,     st, Nary);
  NaClDefine("     0fad:     Shrd $Ev, $Gv, %cl",  NACLi_386,     st, Nary);

  NaClDefine("     0fae/0:   Fxsave $Mf",          NACLi_FXSAVE,  st, Sets);
  NaClDefine("     0fae/1:   Fxrstor $Mf",         NACLi_FXSAVE,  st, Uses);
  NaClDefine("     0fae/2:   Ldmxcsr $Md",         NACLi_SSE,     st, Uses);
  NaClDefine("     0fae/3:   Stmxcsr $Md",         NACLi_SSE,     st, Sets);
  NaClDefine("     0fae/4:   Invalid",             NACLi_INVALID, st, Other);
  NaClDefine("     0fae/5/0: Lfence",              NACLi_SSE2,    st, Other);
  NaClDefine("     0fae/6/0: Mfence",              NACLi_SSE2,    st, Other);
  NaClDefine("     0fae/7/0: Sfence",              NACLi_SFENCE_CLFLUSH,
                                                                  st, Other);
  NaClDefIter("    0fae/5/@i: Invalid", 1, 7,      NACLi_INVALID, st, Other);
  NaClDefIter("    0fae/6/@i: Invalid", 1, 7,      NACLi_INVALID, st, Other);
  NaClDefIter("    0fae/7/@i: Invalid", 1, 7,      NACLi_INVALID, st, Other);
  NaClDefine("     0fae/7:   Clflush $Mb",         NACLi_SFENCE_CLFLUSH,
                                                                  st, Uses);

  NaClDefine("   f20fae:     Invalid",             NACLi_INVALID, st, Other);
  NaClDefine("   660fae:     Invalid",             NACLi_INVALID, st, Other);
  NaClDefine("     0faf:     Imul $Gv, $Ev",       NACLi_386,     st, Binary);
  NaClDefine("     0fb0:     Cmpxchg {%al}, $Eb, $Gb",
                                                   NACLi_386,     st, Exchange);
  NaClDefine("     0fb1:     Cmpxchg {$rAXv}, $Ev, $Gv",
                                                   NACLi_386,     st, Exchange);
  NaClDefine("     0fb2:     Lss $SGz, $Mp",       NACLi_386,     st, Lea);
  NaClDefine("     0fb3:     Btr $Ev, $Gv",        NACLi_386,     st, Binary);
  NaClDefine("     0fb4:     Lfs $SGz, $Mp",       NACLi_386,     st, Lea);
  NaClDefine("     0fb5:     Lgs $SGz, $Mp",       NACLi_386,     st, Lea);
  NaClDefine("     0fb6:     Movzx $Gv, $Eb",      NACLi_386,     st, Move);
  NaClDefine("     0fb7:     Movzx $Gv, $Ew",      NACLi_386,     st, Move);

  NaClDefine("     0fb8:     Invalid",             NACLi_INVALID, st, Other);
  NaClDefine("     0fb9/r:   Invalid",             NACLi_INVALID, st, Other);
  NaClDefine("     0fba/4:   Bt $Ev, $Ib",         NACLi_386,     st, Compare);
  NaClDefine("     0fba/5:   Bts $Ev, $Ib",        NACLi_386,     st, Binary);
  NaClDefine("     0fba/6:   Btr $Ev, $Ib",        NACLi_386,     st, Binary);
  NaClDefine("     0fba/7:   Btc $Ev, $Ib",        NACLi_386,     st, Binary);
  NaClDefine("     0fba/r:   Invalid",             NACLi_INVALID, st, Other);
  NaClDefine("     0fbb:     Btc $Ev, $Gv",        NACLi_386,     st, Binary);
  NaClDefine("     0fbc:     Bsf $Gv, $Ev",        NACLi_386,     st, Move);
  NaClDefine("     0fbd:     Bsr $Gv, $Ev",        NACLi_386,     st, Move);
  NaClDefine("     0fbe:     Movsx $Gv, $Eb",      NACLi_386,     st, Move);
  NaClDefine("     0fbf:     Movsx $Gv, $Ew",      NACLi_386,     st, Move);
  NaClDefine("     0fc0:     Xadd $Eb, $Gb",       NACLi_386,     st, Exchange);
  NaClDefine("     0fc1:     Xadd $Ev, $Gv",       NACLi_386,     st, Exchange);
  NaClBegDef("     0fc7/1:   Cmpxchg8b {%edx}, {%eax}, $Mq",
                                                   NACLi_CMPXCHG8B, st);
  NaClAddIFlags(NACL_IFLAG(OperandSize_v));
  NaClEndDef(                                                         Exchange);
  NaClBegD64("     0fc7/1:   Cmpxchg16b {%rdx}, {%eax}, $Mdq",
                                                   NACLi_CMPXCHG16B, st);
  NaClAddIFlags(NACL_IFLAG(OperandSize_o));
  NaClEndDef(                                                         Exchange);
  NaClDefine("     0fc7/r:   Invalid",             NACLi_INVALID, st, Other);
  for (i = 0; i <= 7; ++i) {
    NaClDefPrefixInstChoices(Prefix0F, 0xc8 + i, 2);
  }
  NaClDefReg("     0fc8+@reg:  Bswap $r8vd", 0, 7, NACLi_386,     st,
                                                                  UnaryUpdate);
  NaClDefReg("     0fc8+@reg:  Bswap $r8vq", 0, 7,  NACLi_386,    st,
                                                                  UnaryUpdate);
}