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

Unified Diff: src/trusted/validator/x86/decoder/generator/ncdecode_forms.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/generator/ncdecode_forms.c
diff --git a/src/trusted/validator/x86/decoder/generator/ncdecode_forms.c b/src/trusted/validator/x86/decoder/generator/ncdecode_forms.c
deleted file mode 100644
index 7acc975c22d36ec9d530d6ac54f6b84619449f30..0000000000000000000000000000000000000000
--- a/src/trusted/validator/x86/decoder/generator/ncdecode_forms.c
+++ /dev/null
@@ -1,1866 +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.
- */
-
-/*
- * Set of predefined instruction forms (via procedure calls), providing
- * a more concise way of specifying opcodes.
- */
-
-#ifndef NACL_TRUSTED_BUT_NOT_TCB
-#error("This file is not meant for use in the TCB")
-#endif
-
-#include "native_client/src/trusted/validator/x86/decoder/generator/ncdecode_forms.h"
-
-#include <assert.h>
-#include <ctype.h>
-
-#include "native_client/src/include/nacl_macros.h"
-#include "native_client/src/include/portability_io.h"
-#include "native_client/src/include/portability_string.h"
-#include "native_client/src/include/nacl_macros.h"
-#include "native_client/src/shared/platform/nacl_log.h"
-#include "native_client/src/trusted/validator/x86/decoder/generator/defsize64.h"
-#include "native_client/src/trusted/validator/x86/decoder/generator/lock_insts.h"
-#include "native_client/src/trusted/validator/x86/decoder/generator/long_mode.h"
-#include "native_client/src/trusted/validator/x86/decoder/generator/nacl_illegal.h"
-#include "native_client/src/trusted/validator/x86/decoder/generator/nc_def_jumps.h"
-#include "native_client/src/trusted/validator/x86/decoder/generator/nc_rep_prefix.h"
-#include "native_client/src/trusted/validator/x86/decoder/generator/ncdecode_st.h"
-#include "native_client/src/trusted/validator/x86/decoder/generator/ncdecode_tablegen.h"
-#include "native_client/src/trusted/validator/x86/decoder/generator/zero_extends.h"
-
-/* To turn on debugging of instruction decoding, change value of
- * DEBUGGING to 1.
- */
-#define DEBUGGING 0
-
-#include "native_client/src/shared/utils/debugging.h"
-
-/* Returns the name for the given enumerated value. */
-static const char* NaClInstCatName(NaClInstCat cat) {
- int i;
- static struct {
- NaClInstCat cat;
- const char* name;
- } cat_desc[] = {
- { UnarySet , "UnarySet" },
- { UnaryUpdate , "UnaryUpdate" },
- { Move , "Move" },
- { O2Move, "O2Move" },
- { Binary , "Binary" },
- { O2Binary , "O2Binary" },
- { Nary , "Nary" },
- { O1Nary, "O1Nary"},
- { O3Nary, "O3Nary"},
- { Compare , "Compare"},
- { Exchange, "Exchange" },
- { Push, "Push" },
- { Pop, "Pop" },
- { Call, "Call"},
- { SysCall, "SysCall"},
- { SysJump, "SysJump"},
- { Return, "Return"},
- { SysRet, "SysRet"},
- { Jump, "Jump" },
- { Uses, "Uses" },
- { Sets, "Sets" },
- { Lea, "Lea" },
- { Cpuid, "Cpuid" },
- { Other, "Other" },
- };
- for (i = 0; i < NACL_ARRAY_SIZE(cat_desc); ++i) {
- if (cat == cat_desc[i].cat) return cat_desc[i].name;
- }
- /* Shouldn't be reached!! */
- NaClFatal("Unrecognized category");
- /* NOT REACHED */
- return "Unspecified";
-}
-
-/* Returns the OpSet and OpUse operand flags for the destination
- * argument of the instruction, given the category of instruction. Argument
- * num_ops is the number of operands the instruction has.
- */
-static NaClOpFlags NaClGetArg1Flags(NaClInstCat icat, int num_ops) {
- DEBUG(NaClLog(LOG_INFO, "NaClGetArg1Flags(%s)\n", NaClInstCatName(icat)));
- switch (icat) {
- case Move:
- case O2Move:
- case O1Nary:
- case O3Nary:
- case Lea:
- case UnarySet:
- case Sets:
- case O2Binary:
- case Jump:
- case Return:
- case SysRet:
- case SysJump:
- case Cpuid:
- return NACL_OPFLAG(OpSet);
- case Nary:
- case Exchange:
- case Call:
- case SysCall:
- case UnaryUpdate:
- case Push:
- case Pop:
- return NACL_OPFLAG(OpSet) | NACL_OPFLAG(OpUse);
- case Binary:
- if (3 == num_ops) {
- return NACL_OPFLAG(OpSet);
- } else {
- return NACL_OPFLAG(OpSet) | NACL_OPFLAG(OpUse);
- }
- case Compare:
- case Uses:
- return NACL_OPFLAG(OpUse);
- case Other:
- return NACL_EMPTY_OPFLAGS;
- break;
- default:
- NaClFatal("NaClGetArg1Flags: unrecognized category");
- /* NOT REACHED */
- return NACL_EMPTY_OPFLAGS;
- }
-}
-
-/* Returns the OpSet, OpUse, and OpDest operand flags for the source argument(s)
- * of an instruction, given the category of instruction.
- *
- * Argument visible_index is the (1-based) index of the operand for which flags
- * are being defined. A value of zero implies the argument is not visible.
- *
- * Argument op_index is the actual index of the operand in the
- * instruction being modeled.
- */
-static NaClOpFlags NaClGetArg2PlusFlags(NaClInstCat icat,
- int visible_index,
- int op_index) {
- DEBUG(NaClLog(LOG_INFO, "NaClGetArgsPlusFlags(%s, %d)\n",
- NaClInstCatName(icat), visible_index));
- switch (icat) {
- case UnarySet:
- case UnaryUpdate:
- NaClLog(LOG_INFO, "icat = %s\n", NaClInstCatName(icat));
- NaClFatal("Illegal to use unary categorization for binary operation");
- /* NOT REACHED */
- return NACL_EMPTY_OPFLAGS;
- case Call:
- case Return:
- case O2Binary:
- if (2 == op_index) {
- return NACL_OPFLAG(OpSet) | NACL_OPFLAG(OpUse);
- } else {
- return NACL_OPFLAG(OpUse);
- }
- case O3Nary:
- if (op_index <= 3) {
- return NACL_OPFLAG(OpSet);
- } else {
- return NACL_OPFLAG(OpUse);
- }
- case Move:
- case Binary:
- case Push:
- case Jump:
- case Uses:
- case SysRet:
- case Compare:
- case Nary:
- case O1Nary:
- return NACL_OPFLAG(OpUse);
- case O2Move:
- if ((2 == op_index)) {
- return NACL_OPFLAG(OpSet);
- } else {
- return NACL_OPFLAG(OpUse);
- }
- case Exchange:
- if (op_index == 2) {
- /* The second argument is always both a set and a use. */
- if (visible_index == 2) {
- return NACL_OPFLAG(OpSet) | NACL_OPFLAG(OpUse);
- } else {
- return NACL_OPFLAG(OpSet) | NACL_OPFLAG(OpUse);
- }
- } else if (op_index == 3) {
- /* If it has a 3rd argument, it is like a cmpxchg. */
- if (visible_index == 1) {
- return NACL_OPFLAG(OpSet) | NACL_OPFLAG(OpUse);
- } else {
- return NACL_OPFLAG(OpSet) | NACL_OPFLAG(OpUse);
- }
- } else {
- return NACL_OPFLAG(OpUse);
- }
- case Pop:
- case SysCall:
- case Sets:
- return NACL_OPFLAG(OpSet);
- case SysJump:
- if (op_index <= 4) {
- return NACL_OPFLAG(OpSet);
- } else {
- return NACL_OPFLAG(OpUse);
- }
- case Lea:
- case Other:
- return NACL_EMPTY_OPFLAGS;
- case Cpuid:
- if (op_index <= 2) {
- return NACL_OPFLAG(OpSet);
- } else {
- return NACL_OPFLAG(OpSet) | NACL_OPFLAG(OpUse);
- }
- default:
- NaClFatal("NaClGetArg2PlusFlags: unrecognized category");
- /* NOT REACHED */
- return NACL_EMPTY_OPFLAGS;
- }
-}
-
-/* Returns the OpSet and OpUse operand flags for the operand
- * with the given operand_index (1-based) argument for the instruction,
- *
- * Argument icat is the instruction category of the instruction being
- * modeled.
- *
- * Argument visible_index is the (1-based) index of the operand for which flags
- * are being defined. A value of zero implies the argument is not visible.
- *
- * Argument op_index is the actual index of the operand in the
- * instruction being modeled.
- *
- * Argument num_ops is the number of operands the instruction has (base 1).
- */
-static NaClOpFlags NaClGetIcatFlags(NaClInstCat icat,
- int operand_index,
- int visible_count,
- int num_ops) {
- NaClOpFlags flags = NACL_EMPTY_OPFLAGS;
- DEBUG(NaClLog(LOG_INFO, "NaClGetIcatFlags(%s, %d, %d)\n",
- NaClInstCatName(icat), operand_index, visible_count));
- if (operand_index == 1) {
- flags = NaClGetArg1Flags(icat, num_ops);
- } else {
- flags = NaClGetArg2PlusFlags(icat, visible_count, operand_index);
- }
- return flags;
-}
-
-/* Add miscellaneous flags defined elsewhere. */
-static void NaClAddMiscellaneousFlags(void) {
- DEBUG(NaClLog(LOG_INFO, "-> Adding Miscellaneous Flags\n"));
- NaClAddZeroExtend32FlagIfApplicable();
- NaClLockableFlagIfApplicable();
- NaClAddSizeDefaultIs64();
- NaClAddLongModeIfApplicable();
- NaClAddNaClIllegalIfApplicable();
- NaClAddRepPrefixFlagsIfApplicable();
- NaClAddJumpFlagsIfApplicable();
- DEBUG(NaClLog(LOG_INFO, "<- Adding Miscellaneous Flags\n"));
-}
-
-/* Adds OpSet/OpUse flags to operands to the current instruction,
- * based on the given instruction categorization.
- */
-static void NaClSetInstCat(NaClInstCat icat) {
- int operand_index = 0; /* note: this is one-based. */
- int visible_count = 0;
- int i;
- int num_ops;
- NaClModeledInst* inst = NaClGetDefInst();
- num_ops = inst->num_operands;
- for (i = 0; i < num_ops; ++i) {
- Bool is_visible = FALSE;
- ++operand_index;
- if (NACL_EMPTY_OPFLAGS ==
- (inst->operands[i].flags & NACL_OPFLAG(OpImplicit))) {
- is_visible = TRUE;
- ++visible_count;
- }
- NaClAddOpFlags(i, NaClGetIcatFlags(
- icat, operand_index, (is_visible ? visible_count : 0), num_ops));
- }
- /* Do special fixup for binary case with 3 arguments. In such
- * cases, the first argument is only a set, rather than a set/use.
- */
- if ((Binary == icat) && (3 == num_ops)) {
- NaClRemoveOpFlags(0, NACL_OPFLAG(OpUse));
- }
- NaClAddMiscellaneousFlags();
-}
-
-/* Returns true if opcode sequence value is a SL (slash)
- * value.
- */
-static Bool IsSLValue(int16_t val) {
- return val < 0;
-}
-
-/* Returns the opcode denoted by a SL (slash) value. */
-static uint8_t SLOpcode(int16_t val) {
- return (uint8_t) ((0 - val) - 1);
-}
-
-/* Returns true if any prefix byte values, which need
- * to be considered part of the opcode sequence, is defined
- * by the given instruction. If prefix byte(s) are matched,
- * prefix_count is incremented by the number of bytes matched.
- *
- * Parameters are:
- * prefix_count - Variable to update on number of matched prefix
- * bytes.
- * inst - The instruction we are matching the opcode sequence against.
- * name_and_opcode_seq - The opcode sequence descriptor we are trying
- * to match.
- */
-static Bool NaClNameOpcodeSeqMatchesPrefixByte(
- int* prefix_count,
- NaClModeledInst* inst,
- const NaClNameOpcodeSeq* name_and_opcode_seq,
- int index) {
- int16_t prefix;
- switch (inst->prefix) {
- case PrefixF20F:
- case PrefixF20F38:
- prefix = PR(0xF2);
- break;
- case PrefixF30F:
- prefix = PR(0xF3);
- break;
- case Prefix660F:
- case Prefix660F38:
- case Prefix660F3A:
- prefix = PR(0x66);
- break;
- default:
- return TRUE;
- }
- if (prefix == name_and_opcode_seq[index].opcode_seq[0]) {
- ++(*prefix_count);
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
-Bool NaClInInstructionSet(const NaClMnemonic* names,
- size_t names_size,
- const NaClNameOpcodeSeq* name_and_opcode_seq,
- size_t name_and_opcode_seq_size) {
- size_t i;
- NaClModeledInst* inst = NaClGetDefInst();
-
- /* First handle cases where all instances of an instruction
- * mnemonic is in the set.
- */
- for (i = 0; i < names_size; ++i) {
- if (inst->name == names[i]) {
- return TRUE;
- }
- }
-
- /* How handle cases where only a specific opcode sequence of
- * an instruction mnemonic applies.
- */
- for (i = 0; i < name_and_opcode_seq_size; ++i) {
- if (inst->name == name_and_opcode_seq[i].name) {
- int j;
- int prefix_count = 0;
- Bool is_good = TRUE;
- Bool matched_slash = FALSE;
- /* First compare opcode bytes. */
- if (NaClNameOpcodeSeqMatchesPrefixByte(
- &prefix_count, inst, name_and_opcode_seq, (int) i)) {
- for (j = 0; j < inst->num_opcode_bytes; ++j) {
- if (inst->opcode[j] !=
- name_and_opcode_seq[i].opcode_seq[prefix_count + j]) {
- is_good = FALSE;
- break;
- }
- }
- } else {
- is_good = FALSE;
- }
- if (is_good) {
- /* Now compare any values that must by in modrm. */
- for (j = prefix_count + inst->num_opcode_bytes;
- j < NACL_OPCODE_SEQ_SIZE; ++j) {
- int16_t val = name_and_opcode_seq[i].opcode_seq[j];
- if (END_OPCODE_SEQ == val) {
- /* At end of descriptor. See if instruction defines an opcode
- * in the ModRm byte. If so, make sure that we matched the slash.
- */
- if (inst->flags & NACL_IFLAG(OpcodeInModRm)) {
- return matched_slash;
- } else {
- /* At end of descriptor, matched! */
- return TRUE;
- }
- }
- if (IsSLValue(val)) {
- if ((inst->flags & NACL_IFLAG(OpcodeInModRm)) &&
- (SLOpcode(val) == NaClGetOpcodeInModRm(inst->opcode_ext))) {
- /* good, continue search. */
- matched_slash = TRUE;
- } else {
- is_good = FALSE;
- break;
- }
- }
- }
- if (is_good) {
- return TRUE;
- }
- }
- }
- }
- /* If reached, couldn't match, so not in instruction set. */
- return FALSE;
-}
-
-static void NaClOperandForm_Ap(void) {
- NaClDefOp(A_Operand, NACL_OPFLAG(OperandFar) | NACL_OPFLAG(OperandRelative));
- NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OpcodeHasImmed_p));
-}
-
-static void NaClOperandForm_CdSlq(void) {
- /* Note: For Cd/q, we don't worry about the size of the
- * control registers for NaCl. Hence, for now, we ignore the
- * size constraint
- */
- NaClDefOp(C_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_DdSlq(void) {
- /* Note: For Dd/q, we don't worry about the size of the
- * debug register for NaCl. Hence, for now, we ignore the
- * size constraint.
- */
- NaClDefOp(D_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Eb(void) {
- /* For Eb, we must worry about earlier arguments, which in some cases,
- * have already specified valid effective operand sizes. If so, we must make
- * the size of the this operand be byte specific. If size hasn't been
- * specified yet, we go ahead and assume the effective operand size of the
- * instructruction as being a byte.
- */
- NaClModeledInst* inst = NaClGetDefInst();
- if (inst->flags & (NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) |
- NACL_IFLAG(OperandSize_o))) {
- NaClDefOp(Eb_Operand, NACL_EMPTY_OPFLAGS);
- } else {
- NaClDefOp(E_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_b));
- }
-}
-
-static void NaClOperandForm_Ed(void) {
- NaClDefOp(Ev_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_EdSlq(void) {
- /* Note: For Ed/q we assume that only sizes d (32) and q (64) are possible.
- * Hence, we don't allow a data 66 prefix effect the size.
- */
- NaClDefOp(E_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSize_o) |
- NACL_IFLAG(SizeIgnoresData16));
-}
-
-static void NaClOperandForm_EdSlqSld(void) {
- /* Ed/q/d is used for Ed/q when operand size is 32 bits (vs 64 bits).
- * Note: For Ed/q we assume that only sizes d (32) and q (64) are possible.
- * Hence, we don't allow a data 66 prefix effect the size.
- */
- NaClDefOp(E_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(SizeIgnoresData16));
-}
-
-static void NaClOperandForm_EdSlqSlq(void) {
- /* Ed/q/q is used for Ed/q when operand size is 64 bits (vs 32 bits).
- * Note: For Ed/q we assume that only sizes d (32) and q (64) are possible.
- * Hence, we don't allow a data 66 prefix effect the size.
- */
- NaClDefOp(E_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_o) | NACL_IFLAG(SizeIgnoresData16));
-}
-
-static void NaClOperandForm_Ev(void) {
- NaClDefOp(E_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) |
- NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_Ew(void) {
- NaClDefOp(Ew_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Fvw(void) {
- NaClDefOp(RegRFLAGS, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_w));
-}
-
-static void NaClOperandForm_Fvd(void) {
- NaClDefOp(RegRFLAGS, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_v));
-}
-
-static void NaClOperandForm_Fvq(void) {
- NaClDefOp(RegRFLAGS, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_Gb(void) {
- NaClDefOp(G_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_b));
-}
-
-static void NaClOperandForm_Gd(void) {
- NaClDefOp(Gv_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_GdQ(void) {
- /* Note: For Gd/q we assume that only sizes d (32) and q (64) are possible.
- * Hence, we don't allow a data 66 prefix effect the size.
- */
- NaClDefOp(G_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSize_o) |
- NACL_IFLAG(SizeIgnoresData16));
-}
-
-static void NaClOperandForm_Gq(void) {
- NaClDefOp(Go_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Gv(void) {
- NaClDefOp(G_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) |
- NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_Gw(void) {
- NaClDefOp(Gw_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Ib(void) {
- int i;
- NaClModeledInst* inst = NaClGetDefInst();
- /* First look to see if 1st or 2nd instance of an immediate value,
- * since different opcode flags that must be used are different.
- */
- for (i = 0; i < inst->num_operands; ++i) {
- if (I_Operand == inst->operands[i].kind) {
- /* Second instance!. */
- NaClDefOp(I2_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed2_b));
- return;
- }
- }
- /* First instance of Ib. */
- NaClDefOp(I_Operand, NACL_EMPTY_OPFLAGS);
- if (inst->flags & NACL_IFLAG(OperandSize_b)) {
- NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed));
- } else {
- NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed_b));
- }
-}
-
-static void NaClOperandForm_I2b(void) {
- NaClDefOp(I2_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed2_b));
-}
-
-static void NaClOperandForm_Iv(void) {
- NaClDefOp(I_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed) | NACL_IFLAG(OperandSize_w) |
- NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_Iw(void) {
- NaClDefOp(I_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed_w));
-}
-
-static void NaClOperandForm_Iz(void) {
- NaClDefOp(I_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed_z));
-}
-
-static void NaClOperandForm_Jb(void) {
- NaClDefOp(J_Operand,
- NACL_OPFLAG(OperandRelative) | NACL_OPFLAG(OperandNear));
- NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed) | NACL_IFLAG(OperandSize_b));
-}
-
-/* Installs Jz, except for size constraints. Assumes immediate value
- * follows z (size) conventions, unless the argument implies to define
- * immediate sizes based on v.
- */
-static void DefOperandJzBaseUseImmedV(Bool use_immed_v) {
- NaClDefOp(J_Operand,
- NACL_OPFLAG(OperandRelative) | NACL_OPFLAG(OperandNear));
- if (use_immed_v) {
- NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed_v));
- } else {
- NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed_z));
- }
-}
-
-/* Installs Jz where immediate value is based on z size. */
-static void DefOperandJzBase(void) {
- /* Note: when in 32-bit mode, the relative offset can be a 16 or 32 bit
- * immediate offset, depending on the operand size. When in 64-bit mode,
- * the relative offset is ALWAYS a 32-bit immediate value (see page
- * 76 for CALL of AMD manual (document 24594-Rev.3.14-September 2007,
- * "AMD64 Architecture Programmer's manual Volume 3: General-Purpose
- * and System Instructions").
- */
- DefOperandJzBaseUseImmedV(X86_64 == NACL_FLAGS_run_mode);
-}
-
-static void NaClOperandForm_Jz(void) {
- DefOperandJzBase();
- NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) |
- NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_Jzd(void) {
- DefOperandJzBaseUseImmedV(TRUE);
- NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_Jzw(void) {
- DefOperandJzBase();
- NaClAddIFlags(NACL_IFLAG(OperandSize_w));
- /* Note: Special case 64-bit with 66 prefix, which is not supported on
- * some Intel Chips (See Call/Jcc instructions in Intel document
- * 253666-030US - March 2009, "Intel 654 and IA-32 Architectures
- * Software Developer's Manual, Volume2A").
- */
- if (X86_64 == NACL_FLAGS_run_mode) {
- NaClAddIFlags(NACL_IFLAG(NaClIllegal));
- }
-}
-
-static void NaClOperandForm_M(void) {
- NaClDefOp(M_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OpcodeAllowsData16));
-}
-
-static void NaClOperandForm_Ma(void) {
- NaClDefOp(M_Operand, NACL_EMPTY_OPFLAGS);
- NaClDefOp(M_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v));
-}
-
-static void NaClOperandForm_Mb(void) {
- NaClDefOp(Mb_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Md(void) {
- NaClDefOp(Mv_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Mdq(void) {
- NaClDefOp(Mdq_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Mf(void) {
- NaClDefOp(M_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_MdSlq(void) {
- /* Note: For Ed/q we assume that only sizes d (32) and q (64) are possible.
- * Hence, we don't allow a data 66 prefix effect the size.
- */
- NaClDefOp(M_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSize_o) |
- NACL_IFLAG(SizeIgnoresData16));
-}
-
-static void NaClOperandForm_Mp(void) {
- /* TODO(karl) fix measurement size. */
- NaClDefOp(M_Operand, NACL_OPFLAG(OperandFar));
-}
-
-static void NaClOperandForm_Ms(void) {
- /* TODO(karl): fix size of data accessed in memory. */
- NaClDefOp(M_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Mq(void) {
- NaClDefOp(Mo_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Mv(void) {
- NaClDefOp(M_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) |
- NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_Mw(void) {
- NaClDefOp(Mw_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_MwSlRv(void) {
- /* TODO(karl) Verify that Mw/Rv as same as Ev? */
- NaClOperandForm_Ev();
-}
-
-static void NaClOperandForm_Ob(void) {
- NaClDefOp(O_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_b) | NACL_IFLAG(OpcodeHasImmed_Addr));
-}
-
-static void NaClOperandForm_Ov(void) {
- NaClDefOp(O_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed_Addr) | NACL_IFLAG(OperandSize_w) |
- NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSize_o));
-}
-
-
-static void NaClOperandForm_One(void) {
- NaClDefOp(Const_1, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_PdSlq(void) {
- /* Note: For Pd/q we assume that only sizes d (32) and q (64) are possible.
- * Hence, we don't allow a data 66 prefix effect the size.
- */
- NaClDefOp(Mmx_G_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSize_o) |
- NACL_IFLAG(SizeIgnoresData16));
-}
-
-static void NaClOperandForm_PdSlqSld(void) {
- /* Pd/q/d is used for Pd/q when operand size is 32 bits (vs 64 bits).
- * Note: For Pd/q we assume that only sizes d (32) and q (64) are possible.
- * Hence, we don't allow a data 66 prefix effect the size.
- */
- NaClDefOp(Mmx_G_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(SizeIgnoresData16));
-}
-
-static void NaClOperandForm_PdSlqSlq(void) {
- /* Pd/q/q is used for Pd/q when operand size is 64 bits (vs 32 bits).
- * Note: For Pd/q we assume that only sizes d (32) and q (64) are possible.
- * Hence, we don't allow a data 66 prefix effect the size.
- */
- NaClDefOp(Mmx_G_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_o) | NACL_IFLAG(SizeIgnoresData16));
-}
-
-static void NaClOperandForm_Pq(void) {
- /* TODO(karl) Add q size restriction. */
- NaClDefOp(Mmx_G_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_PRq(void) {
- /* Note: We ignore sizes for Mmx operands, since they
- * aren't used to compute memory addresses in NaCl.
- */
- NaClDefOp(Mmx_N_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Qd(void) {
- /* TODO(karl) add d size restriction. */
- NaClDefOp(Mmx_E_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Qq(void) {
- /* TODO(karl) add q size restriction. */
- NaClDefOp(Mmx_E_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Rd(void) {
- NaClDefOp(Ev_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(ModRmModIs0x3));
-}
-
-static void NaClOperandForm_Rq(void) {
- NaClDefOp(Eo_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(ModRmModIs0x3));
-}
-
-static void NaClOperandForm_RdSlMb(void) {
- /* Note: For Rd/Mb, we ignore the size on memory,
- * since we don't need to specify sizes on memory.
- */
- NaClDefOp(Ev_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_RdSlMw(void) {
- /* Note: For Rd/Mw, we ignore the size on memory,
- * since we don't need to specify sizes on memory for NaCl.
- */
- NaClDefOp(Ev_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_RdSlq(void) {
- /* Note: It appears that Rd/q opcodes are connected to
- * the architecture size, and only have one choice based
- * on that size.
- */
- if (X86_32 == NACL_FLAGS_run_mode) {
- NaClOperandForm_Rd();
- } else {
- NaClOperandForm_Rq();
- }
-}
-
-static void NaClOperandForm_RdSlqSlMb(void) {
- /* Note: For Rd/q/Mb, we ignore the size on memory,
- * since we don't need to specify sizes on memory for NaCl.
- */
- NaClOperandForm_EdSlq();
-}
-
-static void NaClOperandForm_RdSlqSlMw(void) {
- /* Note: For Rd/q/Mw, we ignore the size on memory,
- * since we don't need to specify sizes on memory for NaCl.
- */
- NaClOperandForm_EdSlq();
-}
-
-static void NaClOperandForm_rAXv(void) {
- NaClDefOp(RegREAX, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) |
- NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_rAXva(void) {
- NaClDefOp(RegREAXa, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_rAXvd(void) {
- NaClDefOp(RegEAX, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_v));
-}
-
-static void NaClOperandForm_rAXvq(void) {
- NaClDefOp(RegRAX, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_rAXvw(void) {
- NaClDefOp(RegAX, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_w));
-}
-
-static void NaClOperandForm_rBXv(void) {
- NaClDefOp(RegREBX, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) |
- NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_rCXv(void) {
- NaClDefOp(RegRECX, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) |
- NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_rDXv(void) {
- NaClDefOp(RegREDX, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) |
- NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_rSPv(void) {
- NaClDefOp(RegRESP, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) |
- NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_rBPv(void) {
- NaClDefOp(RegREBP, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) |
- NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_rSIv(void) {
- NaClDefOp(RegRESI, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) |
- NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_rDIv(void) {
- NaClDefOp(RegREDI, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) |
- NACL_IFLAG(OperandSize_o));
-}
-
-/* Note: The interpretation for r8b is documented in ncdecode_forms.h. That is,
- * r8 - The 8 registers AL, CL, DL, BL, AH, CH, DH, and BH if no REX prefix.
- * with A REX prefix, use the registers AL, CL, DL, BL, SPL, BPL, SIL,
- * DIL, and the optional registers r8-r15 if REX.b is set. Register
- * choice is based on the register value embedded in the opcode.
- */
-static void NaClOperandForm_r8b(void) {
- NaClDefOp(G_OpcodeBase, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_b));
-}
-
-/* Note: The interpretation for r8v is documented in ncdecode_forms.h. That is,
- * r8 - The 8 registers rAX, rCX, rDX, rBX, rSP, rBP, rSI, rDI, and the
- * optional registers r8-r15 if REX.b is set, based on the register value
- * embedded in the opcode.
- */
-static void NaClOperandForm_r8v(void) {
- NaClDefOp(G_OpcodeBase, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) |
- NACL_IFLAG(OperandSize_o));
-}
-
-/* Note: The interpretation for r8vd is documented in ncdecode_forms.h. That is,
- * r8 - The 8 registers rAX, rCX, rDX, rBX, rSP, rBP, rSI, rDI, and the
- * optional registers r8-r15 if REX.b is set, based on the register value
- * embedded in the opcode
- * vd - A doubleword only when the effective operand size matches.
- */
-static void NaClOperandForm_r8vd(void) {
- NaClDefOp(G_OpcodeBase, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_v));
-}
-
-/* Note: The interpretation for r8vq is documented in ncdecode_forms.h. That is,
- * r8 - The 8 registers rAX, rCX, rDX, rBX, rSP, rBP, rSI, rDI, and the
- * optional registers r8-r15 if REX.b is set, based on the register value
- * embedded in the opcode.
- * vq - A quadword only when the effective operand size matches.
- */
-static void NaClOperandForm_r8vq(void) {
- NaClDefOp(G_OpcodeBase, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_SGz(void) {
- NaClDefOp(Seg_G_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) |
- NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_Sw(void) {
- NaClDefOp(S_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(ModRmRegSOperand));
-}
-
-static void NaClOperandForm_Udq(void) {
- NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_UdqMd(void) {
- /* TODO: how to define size, based on register (Udq) or
- * memory (Md).
- */
- NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_UdqMq(void) {
- /* TODO: how to define size, based on register (Udq) or
- * memory (Mq).
- */
- NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_UdqMw(void) {
- /* TODO: how to define size, based on register (Udq) or
- * memory (Mw).
- */
- NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Vdq(void) {
- /* TODO(karl) Add dq size restriction. */
- NaClDefOp(Xmm_G_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_VdSlq(void) {
- /* Note: For Vd/q we assume that only sizes d (32) and q (64) are possible.
- * Hence, we don't allow a data 66 prefix effect the size.
- */
- NaClDefOp(Xmm_G_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSize_o) |
- NACL_IFLAG(SizeIgnoresData16));
-}
-
-static void NaClOperandForm_VdSlqSld(void) {
- /* Vd/q/d is used for Vd/q when operand size is 32 bits (vs 64 bits).
- * Note: For Vd/q we assume that only sizes d (32) and q (64) are possible.
- * Hence, we don't allow a data 66 prefix effect the size.
- */
- NaClDefOp(Xmm_G_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(SizeIgnoresData16));
-}
-
-static void NaClOperandForm_VdSlqSlq(void) {
- /* Vd/q/q is used for Vd/q when operand size is 64 bits (vs 32 bits).
- * Note: For Vd/q we assume that only sizes d (32) and q (64) are possible.
- * Hence, we don't allow a data 66 prefix effect the size.
- */
- NaClDefOp(Xmm_G_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_o) | NACL_IFLAG(SizeIgnoresData16));
-}
-
-static void NaClOperandForm_Vpd(void) {
- NaClDefOp(Xmm_G_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Vps(void) {
- NaClDefOp(Xmm_G_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Vq(void) {
- NaClDefOp(Xmm_Go_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Vsd(void) {
- NaClDefOp(Xmm_G_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Vss(void) {
- NaClDefOp(Xmm_G_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_VRdq(void) {
- /* Note: We ignore sizes for Mmx operands, since they
- * aren't used to compute memory addresses in NaCl.
- */
- NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(ModRmModIs0x3));
-}
-
-static void NaClOperandForm_VRps(void) {
- /* Note: We ignore sizes for Xmm operands, since they
- * aren't used to compute memory addresses in NaCl.
- */
- NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(ModRmModIs0x3));
-}
-
-static void NaClOperandForm_VRq(void) {
- /* Note: We ignore sizes for Xmm operands, since they
- * aren't used to compute memory addresses in NaCl.
- */
- NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(ModRmModIs0x3));
-}
-
-static void NaClOperandForm_VRpd(void) {
- /* Note: We ignore sizes for Xmm operands, since they
- * aren't used to compute memory addresses in NaCl.
- */
- NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(ModRmModIs0x3));
-}
-
-static void NaClOperandForm_Wdq(void) {
- /* TODO(karl) Add dq size restriction. */
- NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Wpd(void) {
- NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Wps(void) {
- NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Wq(void) {
- /* TODO(karl) Add q size restriction. */
- NaClDefOp(Xmm_Eo_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Wsd(void) {
- NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Wss(void) {
- NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS);
-}
-
-static void NaClOperandForm_Xb(void) {
- NaClDefOp(RegDS_ESI, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_b));
-}
-
-static void NaClOperandForm_Xvw(void) {
- NaClDefOp(RegDS_ESI, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_w));
-}
-
-static void NaClOperandForm_Xvd(void) {
- NaClDefOp(RegDS_ESI, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_v));
-}
-
-static void NaClOperandForm_Xvq(void) {
- NaClDefOp(RegDS_ESI, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_Xzd(void) {
- NaClDefOp(RegDS_ESI, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_Xzw(void) {
- NaClDefOp(RegDS_ESI, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_w));
-}
-
-static void NaClOperandForm_Yb(void) {
- NaClDefOp(RegES_EDI, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_b));
-}
-
-static void NaClOperandForm_Yvd(void) {
- NaClDefOp(RegES_EDI, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_v));
-}
-
-static void NaClOperandForm_Yvq(void) {
- NaClDefOp(RegES_EDI, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_Yvw(void) {
- NaClDefOp(RegES_EDI, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_w));
-}
-
-static void NaClOperandForm_Yzw(void) {
- NaClDefOp(RegES_EDI, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_w));
-}
-
-static void NaClOperandForm_Yzd(void) {
- NaClDefOp(RegES_EDI, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSize_o));
-}
-
-static void NaClOperandForm_Zvd(void) {
- NaClDefOp(RegDS_EDI, NACL_EMPTY_OPFLAGS);
- NaClAddIFlags(NACL_IFLAG(OperandSize_v));
-}
-
-/**************************************************************************
- * The following code is code that takes a opcode description string, and *
- * generates the corresponding instruction *
- * *
- * TODO(karl) Remove macro implementations once we have moved to this new *
- * implementation. *
- *************************************************************************/
-
-/* Define the (maximum) size that working buffers, for the translation code. */
-#define BUFSIZE 256
-
-/* Define the maximum number of operands that can appear in an opcode
- * description string.
- */
-#define MAX_OPERANDS 10
-
-#define MAX_DEFOPS 1000
-
-#define BUF_SIZE 1024
-
-/* The maximum number of symbol substitutions that can be applied to an
- * opcode description string. Used mainly to make sure that if a
- * substitution occurs, the code will not looop infinitely.
- */
-#define MAX_ST_SUBSTITUTIONS 100
-
-/* The current opcode string description being translated. Mainly used
- * to generate useful error messages.
- */
-static char* kCachedDesc = "???";
-
-/* The set of possible characters that can follow a symbol when doing
- * symbol substitution.
- */
-static const char* kSymbolTerminators = " :+/{},@";
-
-/* Generates a fatal error message for the given opcode description string. */
-static void NaClDefDescFatal(const char* desc, const char* message) {
- NaClLog(LOG_FATAL, "NaClDefine '%s': %s\n", desc, message);
-}
-
-/* Generates a fatal error message for the cached opcode description string. */
-static void NaClDefFatal(const char* message) {
- NaClDefDescFatal(kCachedDesc, message);
-}
-
-/* replace all occurrences of "@NAME" with the corresponding
- * value in the given symbol table.
- *
- * NOTE: only MAX_ST_SUBSTITUTIONS are allowed, to make sure
- * that we don't infinite loop.
- */
-static void NaClStExpand(char* desc, struct NaClSymbolTable* st) {
- const char* marker;
- int attempts_left = MAX_ST_SUBSTITUTIONS;
- if (NULL == st) return;
- for (marker = strchr(desc, '@');
- (NULL != marker) && attempts_left;
- marker = strchr(desc, '@')) {
- char name[BUFSIZE];
- size_t name_len = 0;
- /* Extract name */
- const char *ch_ptr = marker+1;
- while (*ch_ptr && (NULL == strchr(kSymbolTerminators, *ch_ptr))) {
- name[name_len++] = *(ch_ptr++);
- }
- name[name_len] = '\0';
- if (name_len) {
- /* Get corresponding symbol table value. */
- NaClStValue* val = NaClSymbolTableGet(name, st);
- if (NULL != val) {
- /* Substitute and update desc. */
- char buffer[BUFSIZE];
- char* buffer_ptr = buffer;
- const char* desc_ptr = desc;
- char v_buffer[BUFSIZE];
- const char* v_buffer_ptr = v_buffer;
- /* Copy text before @name. */
- while (desc_ptr != marker) {
- *(buffer_ptr++) = *(desc_ptr++);
- }
- /* Do substitution of symbol value. */
- switch (val->kind) {
- case nacl_byte:
- SNPRINTF(v_buffer, BUFSIZE, "%02"NACL_PRIx8, val->value.byte_value);
- break;
- case nacl_text:
- v_buffer_ptr = val->value.text_value;
- break;
- case nacl_int:
- SNPRINTF(v_buffer, BUFSIZE, "%d", val->value.int_value);
- break;
- default:
- NaClDefDescFatal(desc, "Unable to expand @ variable");
- break;
- }
- while (*v_buffer_ptr) {
- *(buffer_ptr++) = *(v_buffer_ptr++);
- }
- /* copy text after @name. */
- desc_ptr = ch_ptr;
- while (*desc_ptr) {
- *(buffer_ptr++) = *(desc_ptr++);
- }
- *buffer_ptr = '\0';
- strcpy(desc, buffer);
- --attempts_left;
- continue;
- }
- }
- /* If reached, unable to do substitution, stop. */
- break;
- }
-}
-
-/* Verify argument is a string describing a sequence of byte,
- * i.e. pairs of hex values (with no space inbetween), describing
- * the opcode base of an instruction.
- */
-static void NaClVerifyByteBaseAssumptions(const char* byte) {
- size_t len = strlen(byte);
- if ((len < 2) || (len % 2)) {
- NaClDefFatal("opcode (hex) base length must be divisible by 2");
- }
- if (len != strspn(byte, "0123456789aAbBcCdDeEfF")) {
- NaClDefFatal("opcode base not hex value");
- }
-}
-
-/* Given a pointer to a string describing a byte using hexidecimal values,
- * extract the corresponding byte value.
- *
- * Note: Assumes that the length of base is 2.
- */
-static uint8_t NaClExtractByte(const char* base) {
- return (uint8_t) STRTOULL(base + strlen(base) - 2, NULL, 16);
-}
-
-/* Given a string of bytes describing a prefix, return the
- * corresponding enumerated prefix value.
- */
-static NaClInstPrefix NaClExtractPrefixValue(const char* prefix_name,
- size_t prefix_size) {
- if (prefix_size == 0) {
- return NoPrefix;
- } else {
- size_t i;
- NaClInstPrefix prefix;
- char prefix_text[BUFSIZE];
- char* text_ptr;
- strcpy(prefix_text, "Prefix");
- text_ptr = prefix_text + strlen("Prefix");
- for (i = 0; i < prefix_size; ++i) {
- text_ptr[i] = toupper(prefix_name[i]);
- }
- text_ptr[prefix_size] = '\0';
- for (prefix = 0; prefix < NaClInstPrefixEnumSize; ++prefix) {
- if (0 == strcmp(NaClInstPrefixName(prefix), prefix_text)) {
- return prefix;
- }
- }
- }
- NaClDefFatal("Opcode prefix not understood");
- /* NOT REACHED */
- return NaClInstPrefixEnumSize;
-}
-
-/* Given a string of byte values, describing the opcode base
- * of an instruction, extract out the corresponding opcode
- * prefix (i.e. the prefix defined by all but the last byte in
- * the opcode base.
- *
- * Note: Assumes that NaClVerifyByteBaseAssumptions was called
- * on the given parameter.
- */
-static NaClInstPrefix NaClExtractPrefix(const char* base) {
- size_t len = strlen(base);
- if (len >= 2) {
- return NaClExtractPrefixValue(base, len - 2);
- }
- NaClDefFatal("Opcode prefix not understood");
- /* NOT REACHED */
- return NaClInstPrefixEnumSize;
-}
-
-static void NaClVerifyOctalDigit(const char* str, const char* message) {
- if ((1 != strlen(str)) || (1 != strspn(str, "01234567"))) {
- NaClDefFatal(message);
- }
-}
-
-/*
- * Given a string describing an opcode, the type of the
- * instruction, and the mnemonic associated with the instruction,
- * parse the opcode string and define the corresponding instruction.
- *
- * Note: See ??? for descriptions of legal opcode strings.
- */
-static void NaClParseOpcode(const char* opcode,
- NaClInstType insttype,
- NaClMnemonic name,
- struct NaClSymbolTable* st) {
- char buf[BUFSIZE];
- char* marker;
- char* buffer = buf;
- char* base;
- char* reg_offset = NULL;
- char* opcode_ext = NULL;
- char* opcode_3d_ext = NULL;
- char* opcode_rm_ext = NULL;
- NaClInstPrefix prefix;
- uint8_t opcode_value;
- Bool is_inst_defined = FALSE;
- strcpy(buf, opcode);
-
- /* Remove leading whitespace. */
- while(' ' == *buffer) ++buffer;
- base = buffer;
-
- /* Start by finding any valid suffix (i.e. +X or /X), and remove.
- * Put the corresponding suffix into reg_offset(+), or opcode_ext(/).
- */
- /* Try to recognize an opcode extension. */
- marker = strchr(buffer, '/');
- if (NULL != marker) {
- *marker = '\0';
- opcode_ext = buffer + strlen(base) + 1;
- marker = strchr(opcode_ext, '/');
- if (NULL != marker) {
- *marker = '\0';
- opcode_rm_ext = opcode_ext + strlen(opcode_ext) + 1;
- if (strlen(opcode_rm_ext) != 1) {
- NaClDefFatal("modrm r/m opcode extension can only be "
- "a single digit");
- }
- }
- if (strlen(opcode_ext) != 1) {
- NaClDefFatal("modrm opcode extension can only be a single digit");
- }
- } else {
- /* Try to recognize a 3dnow extension. */
- marker = strchr(buffer, '.');
- if ((NULL != marker) && (0 == strncmp(marker, "..", 2))) {
- *marker = '\0';
- opcode_3d_ext = marker + 2;
- }
- }
-
- marker = strchr(buffer, '+');
- if (NULL != marker) {
- *marker = '\0';
- reg_offset = buffer + strlen(base) + 1;
- }
-
- /* Now verify the opcode string, less the suffix, is valid. If so,
- * Pull out the instruction prefix and opcode byte.
- */
- NaClVerifyByteBaseAssumptions(base);
- if (NULL == opcode_3d_ext) {
- prefix = NaClExtractPrefix(base);
- } else {
- prefix = NaClExtractPrefixValue(base, strlen(base));
- }
- NaClDefInstPrefix(prefix);
- opcode_value = NaClExtractByte(base + strlen(base) - 2);
-
- if (reg_offset != NULL) {
- int reg = (int) STRTOULL(reg_offset, NULL, 10);
- if (reg < 0) {
- NaClDefFatal("can't add negative values to opcode");
- } else if ((reg + opcode_value) >= NCDTABLESIZE) {
- NaClDefFatal("opcode addition too large");
- }
- if (NULL == NaClSymbolTableGet("add_reg?", st)) {
- NaClVerifyOctalDigit(reg_offset, "invalid opcode register offset");
- NaClDefInst(opcode_value + reg, insttype, NACL_IFLAG(OpcodePlusR), name);
- NaClDefOpcodeRegisterValue(reg);
- }
- else {
- NaClDefInst(opcode_value + reg, insttype, NACL_EMPTY_IFLAGS, name);
- }
- is_inst_defined = TRUE;
- }
- if (opcode_ext != NULL) {
- if (0 == strcmp("r", opcode_ext)) {
- if (! is_inst_defined) {
- NaClDefInst(opcode_value, insttype, NACL_EMPTY_IFLAGS, name);
- }
- NaClAddIFlags(NACL_IFLAG(OpcodeUsesModRm));
- } else {
- int ext;
- NaClVerifyOctalDigit(opcode_ext, "invalid modrm opcode extension");
- ext = (int) STRTOULL(opcode_ext, NULL, 10);
- if (! is_inst_defined) {
- NaClDefInst(opcode_value, insttype, NACL_EMPTY_IFLAGS, name);
- }
- NaClAddIFlags(NACL_IFLAG(OpcodeInModRm));
- NaClDefOpcodeExtension(ext);
- }
- is_inst_defined = TRUE;
- if (opcode_rm_ext != NULL) {
- NaClVerifyOctalDigit(opcode_rm_ext, "invalid modrm r/m opcode extension");
- NaClDefineOpcodeModRmRmExtension((int) STRTOULL(opcode_rm_ext, NULL, 10));
- }
- }
- if (!is_inst_defined) {
- NaClIFlags flags = NACL_EMPTY_IFLAGS;
- if (opcode_3d_ext != NULL) {
- opcode_value = NaClExtractByte(opcode_3d_ext);
- }
- NaClDefInst(opcode_value, insttype, flags, name);
- }
-}
-
-/* Given the text of a mnemonic, return the corresponding mnemonic. */
-static NaClMnemonic NaClAssemName(const char* name) {
- NaClMnemonic i;
- for (i = (NaClMnemonic) 0; i < NaClMnemonicEnumSize; ++i) {
- if (0 == strcmp(NaClMnemonicName(i), name)) {
- return i;
- }
- }
- NaClDefFatal("Can't find name for mnemonic");
- /* NOT REACHED */
- return NaClMnemonicEnumSize;
-}
-
-/* Given the name of a register, define the corresponding operand on
- * the instruction being defined.
- */
-static void NaClExtractRegister(const char* reg_name) {
- char buffer[BUFSIZE];
- char* buf_ptr = buffer;
- char* reg_ptr = (char*) reg_name;
- NaClOpKind kind;
- strcpy(buf_ptr, "Reg");
- buf_ptr += strlen("Reg");
- while (*reg_ptr) {
- char ch = *(reg_ptr++);
- *(buf_ptr++) = toupper(ch);
- }
- *buf_ptr = '\0';
- for (kind = 0; kind < NaClOpKindEnumSize; ++kind) {
- if (0 == strcmp(NaClOpKindName(kind), buffer)) {
- NaClDefOp(kind, NACL_EMPTY_OPFLAGS);
- return;
- }
- }
- NaClDefFatal("Unable to find register");
-}
-
-/* Helper function to add a define operand function into
- * a symbol table.
- */
-static void NaClSymbolTablePutDefOp(const char* name,
- NaClDefOperand defop,
- struct NaClSymbolTable* st) {
- NaClStValue value;
- value.kind = nacl_defop;
- value.value.defop_value = defop;
- NaClSymbolTablePut(name, &value, st);
-}
-
-/* Given the name describing legal values for an operand,
- * call the corresponding function to define the corresponding
- * operand.
- */
-static void NaClExtractOperandForm(const char* form) {
- static struct NaClSymbolTable* defop_st = NULL;
- NaClStValue* value;
- if (NULL == defop_st) {
- defop_st = NaClSymbolTableCreate(MAX_DEFOPS, NULL);
- NaClSymbolTablePutDefOp("Ap", NaClOperandForm_Ap, defop_st);
- NaClSymbolTablePutDefOp("Cd/q", NaClOperandForm_CdSlq, defop_st);
- NaClSymbolTablePutDefOp("Dd/q", NaClOperandForm_DdSlq, defop_st);
- NaClSymbolTablePutDefOp("Eb", NaClOperandForm_Eb, defop_st);
- NaClSymbolTablePutDefOp("Ed", NaClOperandForm_Ed, defop_st);
- NaClSymbolTablePutDefOp("Ed/q", NaClOperandForm_EdSlq, defop_st);
- NaClSymbolTablePutDefOp("Ed/q/d", NaClOperandForm_EdSlqSld, defop_st);
- NaClSymbolTablePutDefOp("Ed/q/q", NaClOperandForm_EdSlqSlq, defop_st);
- NaClSymbolTablePutDefOp("Ev", NaClOperandForm_Ev, defop_st);
- NaClSymbolTablePutDefOp("Ew", NaClOperandForm_Ew, defop_st);
- NaClSymbolTablePutDefOp("Fvd", NaClOperandForm_Fvd, defop_st);
- NaClSymbolTablePutDefOp("Fvq", NaClOperandForm_Fvq, defop_st);
- NaClSymbolTablePutDefOp("Fvw", NaClOperandForm_Fvw, defop_st);
- NaClSymbolTablePutDefOp("Gb", NaClOperandForm_Gb, defop_st);
- NaClSymbolTablePutDefOp("Gd", NaClOperandForm_Gd, defop_st);
- NaClSymbolTablePutDefOp("Gd/q", NaClOperandForm_GdQ, defop_st);
- NaClSymbolTablePutDefOp("Gq", NaClOperandForm_Gq, defop_st);
- NaClSymbolTablePutDefOp("Gv", NaClOperandForm_Gv, defop_st);
- NaClSymbolTablePutDefOp("Gw", NaClOperandForm_Gw, defop_st);
- NaClSymbolTablePutDefOp("Gw", NaClOperandForm_Gw, defop_st);
- NaClSymbolTablePutDefOp("Ib", NaClOperandForm_Ib, defop_st);
- NaClSymbolTablePutDefOp("Iv", NaClOperandForm_Iv, defop_st);
- NaClSymbolTablePutDefOp("Iw", NaClOperandForm_Iw, defop_st);
- NaClSymbolTablePutDefOp("Iz", NaClOperandForm_Iz, defop_st);
- NaClSymbolTablePutDefOp("I2b", NaClOperandForm_I2b, defop_st);
- NaClSymbolTablePutDefOp("Jb", NaClOperandForm_Jb, defop_st);
- NaClSymbolTablePutDefOp("Jz", NaClOperandForm_Jz, defop_st);
- NaClSymbolTablePutDefOp("Jzd", NaClOperandForm_Jzd, defop_st);
- NaClSymbolTablePutDefOp("Jzw", NaClOperandForm_Jzw, defop_st);
- NaClSymbolTablePutDefOp("M", NaClOperandForm_M, defop_st);
- NaClSymbolTablePutDefOp("Ma", NaClOperandForm_Ma, defop_st);
- NaClSymbolTablePutDefOp("Mb", NaClOperandForm_Mb, defop_st);
- NaClSymbolTablePutDefOp("Md", NaClOperandForm_Md, defop_st);
- NaClSymbolTablePutDefOp("Md/q", NaClOperandForm_MdSlq, defop_st);
- NaClSymbolTablePutDefOp("Mdq", NaClOperandForm_Mdq, defop_st);
- NaClSymbolTablePutDefOp("Mf", NaClOperandForm_Mf, defop_st);
- NaClSymbolTablePutDefOp("Mp", NaClOperandForm_Mp, defop_st);
- NaClSymbolTablePutDefOp("Mq", NaClOperandForm_Mq, defop_st);
- NaClSymbolTablePutDefOp("Ms", NaClOperandForm_Ms, defop_st);
- NaClSymbolTablePutDefOp("Mv", NaClOperandForm_Mv, defop_st);
- NaClSymbolTablePutDefOp("Mw/Rv", NaClOperandForm_MwSlRv, defop_st);
- NaClSymbolTablePutDefOp("Mw", NaClOperandForm_Mw, defop_st);
- NaClSymbolTablePutDefOp("Ob", NaClOperandForm_Ob, defop_st);
- NaClSymbolTablePutDefOp("Ov", NaClOperandForm_Ov, defop_st);
- NaClSymbolTablePutDefOp("Pd/q", NaClOperandForm_PdSlq, defop_st);
- NaClSymbolTablePutDefOp("Pd/q/d", NaClOperandForm_PdSlqSld, defop_st);
- NaClSymbolTablePutDefOp("Pd/q/q", NaClOperandForm_PdSlqSlq, defop_st);
- NaClSymbolTablePutDefOp("Pq", NaClOperandForm_Pq, defop_st);
- NaClSymbolTablePutDefOp("PRq", NaClOperandForm_PRq, defop_st);
- NaClSymbolTablePutDefOp("Qd", NaClOperandForm_Qd, defop_st);
- NaClSymbolTablePutDefOp("Qq", NaClOperandForm_Qq, defop_st);
- NaClSymbolTablePutDefOp("Rd/q", NaClOperandForm_RdSlq, defop_st);
- NaClSymbolTablePutDefOp("Rd/q/Mb", NaClOperandForm_RdSlqSlMb, defop_st);
- NaClSymbolTablePutDefOp("Rd/q/Mw", NaClOperandForm_RdSlqSlMw, defop_st);
- NaClSymbolTablePutDefOp("Rd/Mb", NaClOperandForm_RdSlMb, defop_st);
- NaClSymbolTablePutDefOp("Rd/Mw", NaClOperandForm_RdSlMw, defop_st);
- NaClSymbolTablePutDefOp("rAXv", NaClOperandForm_rAXv, defop_st);
- NaClSymbolTablePutDefOp("rAXva", NaClOperandForm_rAXva, defop_st);
- NaClSymbolTablePutDefOp("rAXvd", NaClOperandForm_rAXvd, defop_st);
- NaClSymbolTablePutDefOp("rAXvq", NaClOperandForm_rAXvq, defop_st);
- NaClSymbolTablePutDefOp("rAXvw", NaClOperandForm_rAXvw, defop_st);
- NaClSymbolTablePutDefOp("rBXv", NaClOperandForm_rBXv, defop_st);
- NaClSymbolTablePutDefOp("rCXv", NaClOperandForm_rCXv, defop_st);
- NaClSymbolTablePutDefOp("rDXv", NaClOperandForm_rDXv, defop_st);
- NaClSymbolTablePutDefOp("rSPv", NaClOperandForm_rSPv, defop_st);
- NaClSymbolTablePutDefOp("rBPv", NaClOperandForm_rBPv, defop_st);
- NaClSymbolTablePutDefOp("rSIv", NaClOperandForm_rSIv, defop_st);
- NaClSymbolTablePutDefOp("rDIv", NaClOperandForm_rDIv, defop_st);
- NaClSymbolTablePutDefOp("r8b", NaClOperandForm_r8b, defop_st);
- NaClSymbolTablePutDefOp("r8v", NaClOperandForm_r8v, defop_st);
- NaClSymbolTablePutDefOp("r8vd", NaClOperandForm_r8vd, defop_st);
- NaClSymbolTablePutDefOp("r8vq", NaClOperandForm_r8vq, defop_st);
- NaClSymbolTablePutDefOp("SGz", NaClOperandForm_SGz, defop_st);
- NaClSymbolTablePutDefOp("Sw", NaClOperandForm_Sw, defop_st);
- NaClSymbolTablePutDefOp("Udq", NaClOperandForm_Udq, defop_st);
- NaClSymbolTablePutDefOp("Udq/Md", NaClOperandForm_UdqMd, defop_st);
- NaClSymbolTablePutDefOp("Udq/Mq", NaClOperandForm_UdqMq, defop_st);
- NaClSymbolTablePutDefOp("Udq/Mw", NaClOperandForm_UdqMw, defop_st);
- NaClSymbolTablePutDefOp("Vdq", NaClOperandForm_Vdq, defop_st);
- NaClSymbolTablePutDefOp("Vd/q", NaClOperandForm_VdSlq, defop_st);
- NaClSymbolTablePutDefOp("Vd/q/d", NaClOperandForm_VdSlqSld, defop_st);
- NaClSymbolTablePutDefOp("Vd/q/q", NaClOperandForm_VdSlqSlq, defop_st);
- NaClSymbolTablePutDefOp("Vpd", NaClOperandForm_Vpd, defop_st);
- NaClSymbolTablePutDefOp("Vps", NaClOperandForm_Vps, defop_st);
- NaClSymbolTablePutDefOp("Vq", NaClOperandForm_Vq, defop_st);
- NaClSymbolTablePutDefOp("Vsd", NaClOperandForm_Vsd, defop_st);
- NaClSymbolTablePutDefOp("Vss", NaClOperandForm_Vss, defop_st);
- NaClSymbolTablePutDefOp("VRdq", NaClOperandForm_VRdq, defop_st);
- NaClSymbolTablePutDefOp("VRpd", NaClOperandForm_VRpd, defop_st);
- NaClSymbolTablePutDefOp("VRps", NaClOperandForm_VRps, defop_st);
- NaClSymbolTablePutDefOp("VRq", NaClOperandForm_VRq, defop_st);
- NaClSymbolTablePutDefOp("Wdq", NaClOperandForm_Wdq, defop_st);
- NaClSymbolTablePutDefOp("Wpd", NaClOperandForm_Wpd, defop_st);
- NaClSymbolTablePutDefOp("Wps", NaClOperandForm_Wps, defop_st);
- NaClSymbolTablePutDefOp("Wq", NaClOperandForm_Wq, defop_st);
- NaClSymbolTablePutDefOp("Wsd", NaClOperandForm_Wsd, defop_st);
- NaClSymbolTablePutDefOp("Wss", NaClOperandForm_Wss, defop_st);
- NaClSymbolTablePutDefOp("Xb", NaClOperandForm_Xb, defop_st);
- NaClSymbolTablePutDefOp("Xvd", NaClOperandForm_Xvd, defop_st);
- NaClSymbolTablePutDefOp("Xvq", NaClOperandForm_Xvq, defop_st);
- NaClSymbolTablePutDefOp("Xvw", NaClOperandForm_Xvw, defop_st);
- NaClSymbolTablePutDefOp("Xzw", NaClOperandForm_Xzw, defop_st);
- NaClSymbolTablePutDefOp("Xzd", NaClOperandForm_Xzd, defop_st);
- NaClSymbolTablePutDefOp("Yb", NaClOperandForm_Yb, defop_st);
- NaClSymbolTablePutDefOp("Yvd", NaClOperandForm_Yvd, defop_st);
- NaClSymbolTablePutDefOp("Yvq", NaClOperandForm_Yvq, defop_st);
- NaClSymbolTablePutDefOp("Yvw", NaClOperandForm_Yvw, defop_st);
- NaClSymbolTablePutDefOp("Yzd", NaClOperandForm_Yzd, defop_st);
- NaClSymbolTablePutDefOp("Yzw", NaClOperandForm_Yzw, defop_st);
- NaClSymbolTablePutDefOp("Zvd", NaClOperandForm_Zvd, defop_st);
- }
- value = NaClSymbolTableGet(form, defop_st);
- if (NULL == value || (value->kind != nacl_defop)) {
- NaClDefFatal("Malformed $defop form");
- }
- value->value.defop_value();
-}
-
-/* Given a string describing the operand, define the corresponding
- * operand. Returns the set of operand flags that must be
- * defined for the operand, based on the contents of the operand string.
- *
- * Note: See ??? for descriptions of legal operand strings.
- */
-static NaClOpFlags NaClExtractOperand(const char* operand) {
- NaClOpFlags op_flags = NACL_EMPTY_OPFLAGS;
- switch (*operand) {
- case '{':
- if ('}' == operand[strlen(operand) - 1]) {
- char buffer[BUFSIZE];
- strcpy(buffer, operand+1);
- buffer[strlen(buffer)-1] = '\0';
- op_flags =
- NaClExtractOperand(buffer) |
- NACL_OPFLAG(OpImplicit);
- } else {
- NaClDefFatal("Malformed implicit braces");
- }
- break;
- case '1':
- if (1 == strlen(operand)) {
- NaClOperandForm_One();
- } else {
- NaClDefFatal("Malformed operand argument");
- }
- break;
- case '%':
- NaClExtractRegister(operand+1);
- break;
- case '$':
- NaClExtractOperandForm(operand+1);
- break;
- default:
- NaClDefFatal("Malformed operand argument");
- }
- return op_flags;
-}
-
-/* Given a string describing the operand, and an index corresponding
- * to the position of the operand in the corresponding opcode description
- * string, define the corresponding operand in the model being generated.
- */
-static void NaClParseOperand(const char* operand, int arg_index) {
- NaClAddOpFlags(arg_index, NaClExtractOperand(operand));
- NaClAddOpFormat(arg_index, operand);
-}
-
-void NaClBegDef(const char* desc, NaClInstType insttype,
- struct NaClSymbolTable* st) {
- char* name;
- char* arg;
- int num_args = 0;
- char buffer[BUFSIZE];
- char expanded_desc[BUFSIZE];
- char* opcode;
- char* assem_desc;
- NaClMnemonic mnemonic;
- char* old_kdesc = kCachedDesc;
- kCachedDesc = (char*) desc;
-
- /* Do symbol table substitutions. */
- strcpy(buffer, desc);
- NaClStExpand(buffer, st);
- strcpy(expanded_desc, buffer);
- kCachedDesc = expanded_desc;
-
- /* Separate the description into opcode sequence and
- * assembly description.
- */
- opcode = strtok(buffer, ":");
- if (NULL == opcode) {
- NaClDefFatal("opcode not separated from assembly description using ':'");
- }
- assem_desc = strtok(NULL, ":");
- if (NULL == assem_desc) {
- NaClDefFatal("Can't find assembly description");
- }
- if (NULL != strtok(NULL, ":")) {
- NaClDefFatal("Malformed assembly description");
- }
-
- /* extract nmemonic name of instruction. */
- name = strtok(assem_desc, " ");
- if (NULL == name) {
- NaClDefFatal("Can't find mnemonic name");
- }
- mnemonic = NaClAssemName(name);
- NaClDelaySanityChecks();
- NaClParseOpcode(opcode, insttype, mnemonic, st);
-
- /* Now extract operands. */
- while ((arg = strtok(NULL, ", "))) {
- NaClParseOperand(arg, num_args);
- ++num_args;
- if (num_args == MAX_OPERANDS) {
- NaClDefFatal("Too many operands");
- }
- }
- kCachedDesc = old_kdesc;
-}
-
-void NaClBegD32(const char* desc, NaClInstType insttype,
- struct NaClSymbolTable* st) {
- NaClBegDef(desc, insttype, st);
- NaClAddIFlags(NACL_IFLAG(Opcode32Only));
-}
-
-void NaClBegD64(const char* desc, NaClInstType insttype,
- struct NaClSymbolTable* st) {
- NaClBegDef(desc, insttype, st);
- NaClAddIFlags(NACL_IFLAG(Opcode64Only));
-}
-
-void NaClBegDefPlatform(NaClTargetPlatform platform,
- const char* desc, NaClInstType insttype,
- struct NaClSymbolTable* st) {
- switch (platform) {
- case T32:
- NaClBegD32(desc, insttype, st);
- break;
- case T64:
- NaClBegD64(desc, insttype, st);
- break;
- case Tall:
- NaClBegDef(desc, insttype, st);
- break;
- default:
- /* This shouldn't happen. */
- NaClDefFatal("Don't understand platform");
- }
-}
-
-void NaClEndDef(NaClInstCat icat) {
- NaClSetInstCat(icat);
- NaClApplySanityChecks();
- NaClResetToDefaultInstPrefix();
-}
-
-void NaClDefine(const char* desc, NaClInstType insttype,
- struct NaClSymbolTable* st, NaClInstCat cat) {
- NaClBegDef(desc, insttype, st);
- NaClEndDef(cat);
-}
-
-void NaClDef_32(const char* desc, NaClInstType insttype,
- struct NaClSymbolTable* st, NaClInstCat cat) {
- NaClBegD32(desc, insttype, st);
- NaClEndDef(cat);
-}
-
-void NaClDef_64(const char* desc, NaClInstType insttype,
- struct NaClSymbolTable* st, NaClInstCat cat) {
- NaClBegD64(desc, insttype, st);
- NaClEndDef(cat);
-}
-
-void NaClDefinePlatform(NaClTargetPlatform platform,
- const char* desc, NaClInstType insttype,
- struct NaClSymbolTable* st, NaClInstCat cat) {
- switch (platform) {
- case T32:
- NaClDef_32(desc, insttype, st, cat);
- break;
- case T64:
- NaClDef_64(desc, insttype, st, cat);
- break;
- case Tall:
- NaClDefine(desc, insttype, st, cat);
- break;
- default:
- /* This shouldn't happen. */
- NaClDefFatal("Don't understand platform");
- }
-}
-
-/* Generate an error message for the given instruction description,
- * if min <0 or max > 7.
- */
-static void NaClDefCheckRange(const char* desc, int min, int max, int cutoff) {
- if (min < 0) {
- NaClDefDescFatal(desc, "Minimum value must be >= 0");
- } else if (max > cutoff) {
- char buffer[BUF_SIZE];
- SNPRINTF(buffer, BUF_SIZE, "Maximum value must be <= %d", cutoff);
- NaClDefDescFatal(desc, buffer);
- }
-}
-
-/* Define a symbol table size that can hold a small number of
- * symbols (i.e. limit to at most 5 definitions).
- */
-#define NACL_SMALL_ST (5)
-
-void NaClDefReg(const char* desc, int min, int max,
- NaClInstType insttype, struct NaClSymbolTable* context_st,
- NaClInstCat cat) {
- int i;
- struct NaClSymbolTable* st = NaClSymbolTableCreate(NACL_SMALL_ST, context_st);
- NaClDefCheckRange(desc, min, max, kMaxRegisterIndexInOpcode);
- for (i = min; i <= max; ++i) {
- NaClSymbolTablePutInt("reg", i, st);
- NaClDefine(desc, insttype, st, cat);
- }
- NaClSymbolTableDestroy(st);
-}
-
-void NaClDefIter(const char* desc, int min, int max,
- NaClInstType insttype, struct NaClSymbolTable* context_st,
- NaClInstCat cat) {
- int i;
- struct NaClSymbolTable* st = NaClSymbolTableCreate(NACL_SMALL_ST, context_st);
- NaClDefCheckRange(desc, min, max, NCDTABLESIZE);
- NaClSymbolTablePutInt("add_reg?", 1, st);
- for (i = min; i <= max; ++i) {
- NaClSymbolTablePutInt("i", i, st);
- NaClDefine(desc, insttype, st, cat);
- }
- NaClSymbolTableDestroy(st);
-}

Powered by Google App Engine
This is Rietveld 408576698