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); |
-} |