2 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
8 * New table driven generator for a decoder of x86 code.
10 * Note: Most of the organization of this document is based on the
11 * NaClOpcode Map appendix of one of the following documents:
13 * (1) "Intel 64 and IA-32 Architectures
14 * Software Developer's Manual (volumes 1, 2a, and 2b; documents
15 * 253665.pdf, 253666.pdf, and 253667.pdf)".
17 * (2) "Intel 80386 Reference Programmer's Manual" (document
18 * http://pdos.csail.mit.edu/6.828/2004/readings/i386/toc.htm).
21 #ifndef NACL_TRUSTED_BUT_NOT_TCB
22 #error("This file is not meant for use in the TCB")
30 #include "native_client/src/trusted/validator/x86/decoder/generator/ncdecode_tablegen.h"
33 #include "native_client/src/include/portability.h"
34 #include "native_client/src/include/portability_io.h"
35 #include "native_client/src/shared/utils/flags.h"
36 #include "native_client/src/shared/platform/nacl_log.h"
37 #include "native_client/src/trusted/validator/x86/x86_insts.h"
38 #include "native_client/src/trusted/validator/x86/decoder/generator/gen/nacl_disallows.h"
39 #include "native_client/src/trusted/validator/x86/decoder/generator/nacl_regsgen.h"
40 #include "native_client/src/trusted/validator/x86/decoder/generator/ncdecode_forms.h"
41 #include "native_client/src/trusted/validator/x86/decoder/generator/ncdecode_st.h"
42 #include "native_client/src/trusted/validator/x86/decoder/generator/ncval_simplify.h"
43 #include "native_client/src/trusted/validator/x86/decoder/generator/nc_compress.h"
45 /* To turn on debugging of instruction decoding, change value of
50 #include "native_client/src/shared/utils/debugging.h"
52 /* Define the default buffer size to use. */
53 #define BUFFER_SIZE 256
55 /* Model an NaClInst, sorted by OpcodeInModRm values. */
56 typedef struct NaClMrmInst {
58 struct NaClMrmInst* next;
61 /* Note: in general all errors in this module will be fatal.
62 * To debug: use gdb or your favorite debugger.
64 void NaClFatal(const char* s) {
65 NaClLog(LOG_FATAL, "Error: %s\n", s);
66 NaClLog(LOG_FATAL, "Fatal: cannot recover\n");
70 /* Returns the print name of the given run mode. */
71 static const char* NaClRunModeName(NaClRunMode mode) {
73 case X86_32: return "x86-32 bit mode";
74 case X86_64: return "x86-64 bit mode";
82 /* Defines if we should simplify the instructions to
83 * what is needed by the validator.
85 static Bool NACL_FLAGS_validator_decoder = FALSE;
87 /* Defines the run mode files that should be generated. */
88 NaClRunMode NACL_FLAGS_run_mode = NaClRunModeSize;
90 /* Defines whether the output of the instruction set should
91 * be as a header file, or human readable (for documentation).
93 static Bool NACL_FLAGS_human_readable = FALSE;
95 /* Defines whether the output should be instruction modeling tables,
96 * or hardware registers.
98 static Bool NACL_FLAGS_nacl_subregs = FALSE;
100 /* Holds the current instruction prefix. */
101 static NaClInstPrefix current_opcode_prefix = NoPrefix;
103 /* Holds the default instruction prefix. */
104 static NaClInstPrefix default_opcode_prefix = NoPrefix;
106 /* Holds the current instruction being built. */
107 static NaClModeledInst* current_inst = NULL;
109 /* Holds the current opcode sequence to be associated with the next
112 static NaClModeledInstNode* current_inst_node = NULL;
114 /* Holds the candidate for the current_inst_node, when
115 * NaClDefInst is called.
117 static NaClModeledInstNode* current_cand_inst_node = NULL;
119 /* Holds the current instruction with mrm extention being built. */
120 static NaClMrmInst* current_inst_mrm = NULL;
122 /* Holds tables used to generate/compress the modeled instructions. */
123 NaClInstTables tables;
125 /* True if we are to apply sanity checks as we define operantions. */
126 static Bool apply_sanity_checks = TRUE;
128 #define NACL_DEFAULT_CHOICE_COUNT (-1)
130 #define NACL_NO_MODRM_OPCODE 8
132 #define NACL_MODRM_OPCODE_SIZE (NACL_NO_MODRM_OPCODE + 1)
134 /* Holds the expected number of entries in the defined instructions.
135 * Note: the last index corresponds to the modrm opcode, or
136 * NACL_NO_MODRM_OPCODE if no modrm opcode.
138 static int NaClInstCount[NCDTABLESIZE]
139 [NaClInstPrefixEnumSize][NACL_MODRM_OPCODE_SIZE];
141 static NaClMrmInst* NaClInstMrmTable[NCDTABLESIZE]
142 [NaClInstPrefixEnumSize][NACL_MODRM_OPCODE_SIZE];
144 /* Holds encodings of prefix bytes. */
145 static const char* NaClPrefixTable[NCDTABLESIZE];
148 /* Prints out the opcode prefix being defined, the opcode pattern
149 * being defined, and the given error message. Then aborts the
150 * execution of the program.
152 static void NaClFatalInst(const char* message) {
153 NaClLog(LOG_INFO, "Prefix: %s\n", NaClInstPrefixName(current_opcode_prefix));
154 NaClModeledInstPrint(NaClLogGetGio(), current_inst);
158 /* Prints out what operand is currently being defined, followed by the given
159 * error message. Then aborts the execution of the program.
161 static void NaClFatalOp(int index, const char* message) {
162 if (0 <= index && index <= current_inst->num_operands) {
163 NaClLog(LOG_ERROR, "On operand %d: %s\n", index,
164 NaClOpKindName(current_inst->operands[index].kind));
166 NaClLog(LOG_ERROR, "On operand %d:\n", index);
168 NaClFatalInst(message);
171 /* Advance the buffer/buffer_size values by count characters. */
172 static void CharAdvance(char** buffer, size_t* buffer_size, size_t count) {
174 *buffer_size += count;
177 /* Generates a (malloc allocated) string describing the form for the
179 * Note: This code used to be part of the validator (runtime) library.
180 * By moving it here, we remove this code, and runtime cost, from
181 * the validator runtime.
183 static void NaClFillOperandDescs(NaClModeledInst* inst) {
184 char buffer[BUFFER_SIZE];
187 /* Make sure inst is defined before trying to fix. */
188 if (NULL == inst) return;
190 for (i = 0; i < inst->num_operands; ++i) {
192 size_t buf_size = BUFFER_SIZE;
193 Bool is_implicit = (NACL_EMPTY_OPFLAGS != (inst->operands[i].flags &
194 NACL_OPFLAG(OpImplicit)));
195 NaClOpKind kind = inst->operands[i].kind;
197 if (NULL != inst->operands[i].format_string) continue;
199 buffer[0] = '\0'; /* just in case there isn't any operands. */
201 CharAdvance(&buf, &buf_size,
202 SNPRINTF(buf, buf_size, "{"));
206 CharAdvance(&buf, &buf_size,
207 SNPRINTF(buf, buf_size, "$A"));
215 CharAdvance(&buf, &buf_size,
216 SNPRINTF(buf, buf_size, "$E"));
224 CharAdvance(&buf, &buf_size,
225 SNPRINTF(buf, buf_size, "$G"));
228 CharAdvance(&buf, &buf_size,
229 SNPRINTF(buf, buf_size, "$SegG"));
232 CharAdvance(&buf, &buf_size,
233 SNPRINTF(buf, buf_size, "$/r"));
245 CharAdvance(&buf, &buf_size,
246 SNPRINTF(buf, buf_size, "$I"));
254 /* Special case $Ma, which adds two operands. */
255 if ((i > 0) && (NULL != inst->operands[i-1].format_string) &&
256 (0 == strcmp(inst->operands[i-1].format_string, "$Ma"))) {
257 /* Don't add a format string in this case. */
260 CharAdvance(&buf, &buf_size,
261 SNPRINTF(buf, buf_size, "$M"));
265 CharAdvance(&buf, &buf_size,
266 SNPRINTF(buf, buf_size, "m16:16"));
269 CharAdvance(&buf, &buf_size,
270 SNPRINTF(buf, buf_size, "m16:32"));
273 CharAdvance(&buf, &buf_size,
274 SNPRINTF(buf, buf_size, "m16:64"));
278 CharAdvance(&buf, &buf_size,
279 SNPRINTF(buf, buf_size, "$E(mmx)"));
283 CharAdvance(&buf, &buf_size,
284 SNPRINTF(buf, buf_size, "$G(mmx)"));
288 CharAdvance(&buf, &buf_size,
289 SNPRINTF(buf, buf_size, "$E(xmm)"));
293 CharAdvance(&buf, &buf_size,
294 SNPRINTF(buf, buf_size, "$G(xmm)"));
301 CharAdvance(&buf, &buf_size,
302 SNPRINTF(buf, buf_size, "$O"));
305 CharAdvance(&buf, &buf_size,
306 SNPRINTF(buf, buf_size, "%%Sreg"));
309 CharAdvance(&buf, &buf_size,
310 SNPRINTF(buf, buf_size, "%%Creg"));
313 CharAdvance(&buf, &buf_size,
314 SNPRINTF(buf, buf_size, "%%Dreg"));
317 CharAdvance(&buf, &buf_size,
318 SNPRINTF(buf, buf_size, "%%st"));
442 CharAdvance(&buf, &buf_size,
443 SNPRINTF(buf, buf_size, "%%%s",
444 NaClOpKindName(kind) + strlen("Reg")));
447 CharAdvance(&buf, &buf_size,
448 SNPRINTF(buf, buf_size, "1"));
451 CharAdvance(&buf, &buf_size,
452 SNPRINTF(buf, buf_size, "???"));
456 CharAdvance(&buf, &buf_size,
457 SNPRINTF(buf, buf_size, "}"));
459 *((char**)(inst->operands[i].format_string)) = strdup(buffer);
463 /* Define the prefix name for the given opcode, for the given run mode. */
464 static void NaClEncodeModedPrefixName(const uint8_t byte, const char* name,
465 const NaClRunMode mode) {
466 if (NACL_FLAGS_run_mode == mode) {
467 NaClPrefixTable[byte] = name;
471 /* Define the prefix name for the given opcode, for all run modes. */
472 static void NaClEncodePrefixName(const uint8_t byte, const char* name) {
473 NaClEncodeModedPrefixName(byte, name, NACL_FLAGS_run_mode);
476 /* Change the current opcode prefix to the given value. */
477 void NaClDefInstPrefix(const NaClInstPrefix prefix) {
478 current_opcode_prefix = prefix;
481 void NaClResetToDefaultInstPrefix(void) {
482 NaClDefInstPrefix(default_opcode_prefix);
485 NaClModeledInst* NaClGetDefInst(void) {
489 /* Check if an E_Operand operand has been repeated, since it should
490 * never appear for more than one argument. If repeated, generate an
491 * appropriate error message and terminate.
493 static void NaClCheckIfERepeated(int index) {
495 for (i = 0; i < index; ++i) {
496 const NaClOp* operand = ¤t_inst->operands[i];
497 switch (operand->kind) {
507 NaClFatalOp(index, "Can't use E Operand more than once");
515 /* Called if operand is a G_Operand. Checks that the opcode doesn't specify
516 * that the REG field of modrm is an opcode, since G_Operand doesn't make
517 * sense in such cases.
519 static void NaClCheckIfOpcodeInModRm(int index) {
520 if ((current_inst->flags & NACL_IFLAG(OpcodeInModRm)) &&
521 (NACL_EMPTY_OPFLAGS == (current_inst->operands[index].flags &
522 NACL_IFLAG(AllowGOperandWithOpcodeInModRm)))) {
524 "Can't use G Operand, bits being used for opcode in modrm");
528 /* Check if an G_Operand operand has been repeated, since it should
529 * never appear for more than one argument. If repeated, generate an
530 * appropriate error message and terminate.
532 static void NaClCheckIfGRepeated(int index) {
534 for (i = 0; i < index; ++i) {
535 const NaClOp* operand = ¤t_inst->operands[i];
536 switch (operand->kind) {
546 NaClFatalOp(index, "Can't use G Operand more than once");
554 /* Check if an I_Operand/J_OPerand operand has been repeated, since it should
555 * never appear for more than one argument (both come from the immediate field
556 * of the instruction). If repeated, generate an appropriate error message
559 static void NaClCheckIfIRepeated(int index) {
561 for (i = 0; i < index; ++i) {
562 const NaClOp* operand = ¤t_inst->operands[i];
563 switch (operand->kind) {
569 NaClFatalOp(index, "Can't use I_Operand more than once");
574 NaClFatalOp(index, "Can't use both I_Operand and J_Operand");
582 /* Returns the set of operand size flags defined for the given instruction. */
583 NaClIFlags NaClOperandSizes(NaClModeledInst* inst) {
584 NaClIFlags flags = inst->flags & (NACL_IFLAG(OperandSize_b) |
585 NACL_IFLAG(OperandSize_w) |
586 NACL_IFLAG(OperandSize_v) |
587 NACL_IFLAG(OperandSize_o));
588 /* Note: if no sizes specified, assume all sizes possible. */
589 if (NACL_EMPTY_IFLAGS == flags) {
590 flags = NACL_IFLAG(OperandSize_b) |
591 NACL_IFLAG(OperandSize_w) |
592 NACL_IFLAG(OperandSize_v) |
593 NACL_IFLAG(OperandSize_o);
598 /* Check that the operand being defined (via the given index), does not
599 * specify any inconsistent flags.
601 static void NaClApplySanityChecksToOp(int index) {
602 const NaClOp* operand = ¤t_inst->operands[index];
603 const NaClIFlags operand_sizes = NaClOperandSizes(current_inst);
605 if (!apply_sanity_checks) return;
607 /* Check that operand is consistent with other operands defined, or flags
608 * defined on the opcode.
610 switch (operand->kind) {
612 NaClCheckIfERepeated(index);
615 if (NACL_IFLAG(OperandSize_b) == operand_sizes) {
616 /* Singlton set already specifies size, so no need for extra
617 * size specification.
620 "Size implied by OperandSize_b, use E_Operand instead");
622 NaClCheckIfERepeated(index);
625 if (NACL_IFLAG(OperandSize_w) == operand_sizes) {
626 /* Singlton set already specifies size, so no need for extra
627 * size specification.
630 "Size implied by OperandSize_w, use E_Operand instead");
632 NaClCheckIfERepeated(index);
635 if (NACL_IFLAG(OperandSize_v) == operand_sizes) {
636 /* Singlton set already specifies size, so no need for extra
637 * size specification.
640 "Size implied by OperandSize_v, use E_Operand instead");
642 NaClCheckIfERepeated(index);
645 if (NACL_IFLAG(OperandSize_o) == operand_sizes) {
646 /* Singlton set already specifies size, so no need for extra
647 * size specification.
650 "Size implied by OperandSize_o, use E_Operand instead");
652 NaClCheckIfERepeated(index);
655 NaClCheckIfERepeated(index);
659 NaClCheckIfERepeated(index);
662 if (NACL_IFLAG(OperandSize_o) == operand_sizes) {
663 /* Singlton set already specifies size, so no need for extra
664 * size specification.
668 "Size implied by OperandSize_o, use Xmm_E_Operand instead");
670 NaClCheckIfERepeated(index);
673 NaClCheckIfGRepeated(index);
674 NaClCheckIfOpcodeInModRm(index);
677 if (NACL_IFLAG(OperandSize_b) == operand_sizes) {
678 /* Singlton set already specifies size, so no need for extra
679 * size specification.
682 "Size implied by OperandSize_b, use G_Operand instead");
684 NaClCheckIfGRepeated(index);
685 NaClCheckIfOpcodeInModRm(index);
688 if (NACL_IFLAG(OperandSize_w) == operand_sizes) {
689 /* Singlton set already specifies size, so no need for extra
690 * size specification.
693 "Size implied by OperandSize_w, use G_Operand instead");
695 NaClCheckIfGRepeated(index);
696 NaClCheckIfOpcodeInModRm(index);
699 if (NACL_IFLAG(OperandSize_v) == operand_sizes) {
700 /* Singlton set already specifies size, so no need for extra
701 * size specification.
704 "Size implied by OperandSize_v, use G_Operand instead");
706 NaClCheckIfGRepeated(index);
707 NaClCheckIfOpcodeInModRm(index);
710 if (NACL_IFLAG(OperandSize_o) == operand_sizes) {
711 /* Singlton set already specifies size, so no need for extra
712 * size specification.
715 "Size implied by OperandSize_o, use G_Operand instead");
717 NaClCheckIfGRepeated(index);
718 NaClCheckIfOpcodeInModRm(index);
721 NaClCheckIfGRepeated(index);
722 NaClCheckIfOpcodeInModRm(index);
726 NaClCheckIfGRepeated(index);
727 NaClCheckIfOpcodeInModRm(index);
730 if (NACL_IFLAG(OperandSize_o) == operand_sizes) {
731 /* Singlton set already specifies size, so no need for extra
732 * size specification.
736 "Size implied by OperandSize_o, use Xmm_G_Operand instead");
738 NaClCheckIfGRepeated(index);
739 NaClCheckIfOpcodeInModRm(index);
742 NaClCheckIfIRepeated(index);
745 if (NACL_IFLAG(OperandSize_b) == operand_sizes) {
746 /* Singlton set already specifies size, so no need for extra
747 * size specification.
750 "Size implied by OperandSize_b, use I_Operand instead");
752 if (current_inst->flags & NACL_IFLAG(OpcodeHasImmed_b)) {
754 "Size implied by OpcodeHasImmed_b, use I_Operand instead");
756 NaClCheckIfIRepeated(index);
759 if (NACL_IFLAG(OperandSize_w) == operand_sizes) {
760 /* Singlton set already specifies size, so no need for extra
761 * size specification.
764 "Size implied by OperandSize_w, use I_Operand instead");
766 if (current_inst->flags & NACL_IFLAG(OpcodeHasImmed_w)) {
768 "Size implied by OpcodeHasImmed_w, use I_Operand instead");
770 NaClCheckIfIRepeated(index);
773 if (NACL_IFLAG(OperandSize_v) == operand_sizes) {
774 /* Singlton set already specifies size, so no need for extra
775 * size specification.
778 "Size implied by OperandSize_v, use I_Operand instead");
780 if (current_inst->flags & NACL_IFLAG(OpcodeHasImmed_v)) {
782 "Size implied by OpcodeHasImmed_v, use I_Operand instead");
784 NaClCheckIfIRepeated(index);
787 if (NACL_IFLAG(OperandSize_o) == operand_sizes) {
788 /* Singlton set already specifies size, so no need for extra
789 * size specification.
792 "Size implied by OperandSize_o, use I_Operand instead");
794 if (current_inst->flags & NACL_IFLAG(OpcodeHasImmed_o)) {
796 "Size implied by OpcodeHasImmed_o, use I_Operand instead");
798 NaClCheckIfIRepeated(index);
805 /* Define the next operand of the current opcode to have
806 * the given kind and flags.
808 static void NaClDefOpInternal(NaClOpKind kind, NaClOpFlags flags) {
810 assert(NULL != current_inst);
811 if (tables.operands_size >= NACL_MAX_OPERANDS_TOTAL) {
812 NaClFatal("Out of operand space. "
813 "Increase size of NACL_MAX_OPERANDS_TOTAL!");
815 tables.operands_size++;
816 index = current_inst->num_operands++;
817 current_inst->operands[index].kind = kind;
818 current_inst->operands[index].flags = flags;
819 current_inst->operands[index].format_string = NULL;
822 static void NaClInstallCurrentIntoOpcodeMrm(const NaClInstPrefix prefix,
823 const uint8_t opcode,
825 DEBUG(NaClLog(LOG_INFO, " Installing into [%x][%s][%d]\n",
826 opcode, NaClInstPrefixName(prefix), mrm_index));
827 if (NULL == NaClInstMrmTable[opcode][prefix][mrm_index]) {
828 NaClInstMrmTable[opcode][prefix][mrm_index] = current_inst_mrm;
830 NaClMrmInst* next = NaClInstMrmTable[opcode][prefix][mrm_index];
831 while (NULL != next->next) {
834 next->next = current_inst_mrm;
838 /* Removes the current_inst_mrm from the corresponding instruction table.
839 * Used when Opcode32Only or Opcode64Only flag is added, and
840 * the flag doesn't match the subarchitecture being modeled.
842 static void NaClRemoveCurrentInstMrmFromInstTable(void) {
843 uint8_t opcode = current_inst->opcode[current_inst->num_opcode_bytes - 1];
844 NaClModeledInst* prev = NULL;
845 NaClModeledInst* next = tables.inst_table[opcode][current_inst->prefix];
846 while (NULL != next) {
847 if (current_inst == next) {
848 /* Found - remove! */
850 tables.inst_table[opcode][current_inst->prefix] = next->next_rule;
852 prev->next_rule = next->next_rule;
857 next = next->next_rule;
862 /* Removes the current_inst_mrm from the corresponding
865 * Used when Opcode32Only or Opcode64Only flag is added, and
866 * the flag doesn't match the subarchitecture being modeled.
868 static void NaClRemoveCurrentInstMrmFromInstMrmTable(void) {
869 /* Be sure to try opcode in first operand (if applicable),
870 * and the default list NACL_NO_MODRM_OPCODE, in case
871 * the operand hasn't been processed yet.
873 int mrm_opcode = NACL_NO_MODRM_OPCODE;
874 if (current_inst->flags & NACL_IFLAG(OpcodeInModRm)) {
875 mrm_opcode = NaClGetOpcodeInModRm(current_inst->opcode_ext);
879 uint8_t opcode = current_inst->opcode[current_inst->num_opcode_bytes - 1];
880 NaClMrmInst* prev = NULL;
882 NaClInstMrmTable[opcode][current_inst->prefix][mrm_opcode];
883 DEBUG(NaClLog(LOG_INFO, "Removing [%02x][%s][%d]?",
884 opcode, NaClInstPrefixName(current_inst->prefix),
886 while (NULL != next) {
887 if (current_inst_mrm == next) {
888 /* Found - remove! */
890 NaClInstMrmTable[opcode][current_inst->prefix][mrm_opcode] =
893 prev->next = next->next;
901 if (mrm_opcode == NACL_NO_MODRM_OPCODE) return;
902 mrm_opcode = NACL_NO_MODRM_OPCODE;
906 static void NaClMoveCurrentToMrmIndex(int mrm_index) {
907 /* First remove from default location. */
908 uint8_t opcode = current_inst->opcode[current_inst->num_opcode_bytes - 1];
909 NaClMrmInst* prev = NULL;
911 NaClInstMrmTable[opcode][current_opcode_prefix]
912 [NACL_NO_MODRM_OPCODE];
913 while (current_inst_mrm != next) {
914 if (next == NULL) return;
919 NaClInstMrmTable[opcode][current_opcode_prefix]
920 [NACL_NO_MODRM_OPCODE] =
923 prev->next = next->next;
925 current_inst_mrm = next;
926 current_inst_mrm->next = NULL;
927 NaClInstallCurrentIntoOpcodeMrm(current_opcode_prefix, opcode, mrm_index);
930 static void NaClPrintlnOpFlags(struct Gio* g, NaClOpFlags flags) {
932 for (i = 0; i < NaClOpFlagEnumSize; ++i) {
933 if (flags & NACL_OPFLAG(i)) {
934 gprintf(g, " %s", NaClOpFlagName(i));
940 static void NaClApplySanityChecksToInst(void);
942 void NaClDefOpcodeExtension(int opcode) {
944 byte_opcode = (uint8_t) opcode;
945 if ((opcode < 0) || (opcode > 7)) {
946 NaClFatalInst("Attempted to define opcode extension not in range [0..7]");
948 if (NACL_EMPTY_IFLAGS ==
949 (current_inst->flags & NACL_IFLAG(OpcodeInModRm))) {
951 "Opcode extension in [0..7], but not OpcodeInModRm");
953 DEBUG(NaClLog(LOG_INFO, "Defining opcode extension %d\n", opcode));
954 NaClMoveCurrentToMrmIndex(byte_opcode);
955 NaClSetOpcodeInModRm(byte_opcode, ¤t_inst->opcode_ext);
958 void NaClDefineOpcodeModRmRmExtension(int value) {
959 uint8_t byte_opcode = (uint8_t) value;
960 if ((value < 0) || (value > 7)) {
961 NaClFatalInst("Attempted to defined Opcode modrm rm extension "
962 "not in range [0..7]");
964 if (NACL_EMPTY_IFLAGS ==
965 (current_inst->flags & NACL_IFLAG(OpcodeInModRm))) {
967 "Opcode modrm rm extension in [0..7], but not OpcodeInModRm");
969 DEBUG(NaClLog(LOG_INFO, "Defining modrm r/m opcode extension %d", value));
970 NaClAddIFlags(NACL_IFLAG(OpcodeInModRmRm));
971 if (current_inst->num_opcode_bytes + 1 < NACL_MAX_ALL_OPCODE_BYTES) {
972 NaClSetOpcodeInModRmRm(byte_opcode, ¤t_inst->opcode_ext);
974 NaClFatalInst("No room for opcode modrm rm extension");
978 void NaClDefOpcodeRegisterValue(int r) {
980 byte_r = (uint8_t) r;
981 if ((r < 0) || (r > 7)) {
982 NaClFatalInst("Attempted to define an embedded opcode register value "
983 "not in range [0.. 7]");
985 if (NACL_EMPTY_IFLAGS ==
986 (current_inst->flags & NACL_IFLAG(OpcodePlusR))) {
988 "Attempted to define opcode register value when not OpcodePlusR");
990 NaClSetOpcodePlusR(byte_r, ¤t_inst->opcode_ext);
993 /* Same as previous function, except that sanity checks
994 * are applied to see if inconsistent information is
1000 int index = current_inst->num_operands;
1001 DEBUG(NaClLog(LOG_INFO, " %s:", NaClOpKindName(kind));
1002 NaClPrintlnOpFlags(NaClLogGetGio(), flags));
1003 /* If one of the M_Operands, make sure that the ModRm mod field isn't 0x3,
1004 * so that we don't return registers.
1005 * If one specifies an operand that implies the use of a ModRm byte, add
1006 * the corresponding flag.
1007 * Note: See section A.2.5 of Intel manual (above) for an explanation of the
1008 * ModRm mod field being any value except 0x3, for values having an
1009 * explicit memory operand.
1021 NaClAddIFlags(NACL_IFLAG(OpcodeUsesModRm) | NACL_IFLAG(ModRmModIsnt0x3));
1024 kind = Mmx_E_Operand;
1025 NaClAddIFlags(NACL_IFLAG(OpcodeUsesModRm) | NACL_IFLAG(ModRmModIs0x3));
1026 /* Automatically fall to the next case. */
1040 case Mmx_Gd_Operand:
1042 case Xmm_Eo_Operand:
1044 case Xmm_Go_Operand:
1045 NaClAddIFlags(NACL_IFLAG(OpcodeUsesModRm));
1050 /* Define and apply sanity checks. */
1051 NaClDefOpInternal(kind, flags);
1052 NaClApplySanityChecksToOp(index);
1055 void NaClAddOpFlags(uint8_t operand_index, NaClOpFlags more_flags) {
1057 struct Gio* g = NaClLogGetGio();
1058 gprintf(g, "Adding flags:");
1059 NaClPrintlnOpFlags(g, more_flags));
1060 if (operand_index < current_inst->num_operands) {
1061 NaClAddBits(current_inst->operands[operand_index].flags, more_flags);
1062 NaClApplySanityChecksToOp(operand_index);
1064 NaClFatalOp((int) operand_index, "NaClAddOpFlags: index out of range\n");
1068 void NaClRemoveOpFlags(uint8_t operand_index, NaClOpFlags more_flags) {
1069 DEBUG(NaClLog(LOG_INFO, "Removing flags:");
1070 NaClPrintlnOpFlags(NaClLogGetGio(), more_flags));
1071 if (operand_index < current_inst->num_operands) {
1072 NaClRemoveBits(current_inst->operands[operand_index].flags, more_flags);
1073 NaClApplySanityChecksToOp(operand_index);
1075 NaClFatalOp((int) operand_index, "NaClRemoveOpFlags: index out of range\n");
1079 void NaClAddOpFormat(uint8_t operand_index, const char* format) {
1080 DEBUG(NaClLog(LOG_INFO, "Adding format[%"NACL_PRIu8"]: '%s'\n",
1081 operand_index, format));
1082 if (operand_index < current_inst->num_operands) {
1083 current_inst->operands[operand_index].format_string =
1086 NaClFatalOp((int) operand_index, "NaClAddOpFormat: index out of range\n");
1090 /* Returns true if the given opcode flags are consistent
1091 * with the value of NACL_FLAGS_run_mode.
1093 static Bool NaClIFlagsMatchesRunMode(NaClIFlags flags) {
1094 if (flags & NACL_IFLAG(Opcode32Only)) {
1095 if (flags & NACL_IFLAG(Opcode64Only)) {
1096 NaClFatal("Can't specify both Opcode32Only and Opcode64Only");
1098 return NACL_FLAGS_run_mode == X86_32;
1099 } else if (flags & NACL_IFLAG(Opcode64Only)) {
1100 return NACL_FLAGS_run_mode == X86_64;
1101 } else if (flags & NACL_IFLAG(Opcode32Only)) {
1102 return NACL_FLAGS_run_mode == X86_32;
1108 /* Check that the flags defined for an opcode make sense. */
1109 static void NaClApplySanityChecksToInst(void) {
1110 const NaClIFlags operand_sizes = NaClOperandSizes(current_inst);
1111 if (!apply_sanity_checks) return;
1112 if ((current_inst->flags & NACL_IFLAG(Opcode32Only)) &&
1113 (current_inst->flags & NACL_IFLAG(Opcode64Only))) {
1114 NaClFatalInst("Can't be both Opcode32Only and Opcode64Only");
1116 /* Fix case where both OperandSize_w and SizeIgnoresData16 are specified. */
1117 if ((current_inst->flags & NACL_IFLAG(OperandSize_w)) &&
1118 (current_inst->flags & NACL_IFLAG(SizeIgnoresData16))) {
1119 NaClRemoveBits(current_inst->flags, NACL_IFLAG(OperandSize_w));
1121 if ((current_inst->flags & NACL_IFLAG(OperandSize_b)) &&
1122 (current_inst->flags & (NACL_IFLAG(OperandSize_w) |
1123 NACL_IFLAG(OperandSize_v) |
1124 NACL_IFLAG(OperandSize_o) |
1125 NACL_IFLAG(OperandSizeDefaultIs64) |
1126 NACL_IFLAG(OperandSizeForce64)))) {
1128 "Can't specify other operand sizes when specifying OperandSize_b");
1130 if ((current_inst->flags & NACL_IFLAG(OpcodeInModRm)) &&
1131 (current_inst->flags & NACL_IFLAG(OpcodePlusR))) {
1133 "Can't specify both OpcodeInModRm and OpcodePlusR");
1135 if ((current_inst->flags & NACL_IFLAG(OpcodeHasImmed_b)) &&
1136 (operand_sizes == NACL_IFLAG(OperandSize_b))) {
1138 "Size implied by OperandSize_b, use OpcodeHasImmed "
1139 "rather than OpcodeHasImmed_b");
1141 if ((current_inst->flags & NACL_IFLAG(OpcodeHasImmed_w)) &&
1142 (operand_sizes == NACL_IFLAG(OperandSize_w))) {
1144 "Size implied by OperandSize_w, use OpcodeHasImmed "
1145 "rather than OpcodeHasImmed_w");
1147 if ((current_inst->flags & NACL_IFLAG(OpcodeHasImmed_v)) &&
1148 (operand_sizes == NACL_IFLAG(OperandSize_v))) {
1150 "Size implied by OperandSize_v, use OpcodeHasImmed "
1151 "rather than OpcodeHasImmed_v");
1153 if ((current_inst->flags & NACL_IFLAG(ModRmModIs0x3)) &&
1154 (NACL_EMPTY_IFLAGS == (current_inst->flags &
1155 (NACL_IFLAG(OpcodeUsesModRm) |
1156 NACL_IFLAG(OpcodeInModRm))))) {
1158 "Can't specify ModRmModIs0x3 unless Opcode has modrm byte");
1160 if ((current_inst->flags & NACL_IFLAG(ModRmModIs0x3)) &&
1161 (current_inst->flags & NACL_IFLAG(ModRmModIsnt0x3))) {
1163 "Can't specify ModRmModIs0x3 and ModRmModIsnt0x3");
1167 static void NaClDefBytes(uint8_t opcode) {
1169 current_inst->prefix = current_opcode_prefix;
1171 /* Start by clearing all entries. */
1172 for (index = 0; index < NACL_MAX_ALL_OPCODE_BYTES; ++index) {
1173 current_inst->opcode[index] = 0x00;
1176 /* Now fill in non-final bytes. */
1178 switch (current_opcode_prefix) {
1185 current_inst->opcode[0] = 0x0F;
1189 current_inst->opcode[0] = 0x0F;
1190 current_inst->opcode[1] = 0x0F;
1196 current_inst->opcode[0] = 0x0F;
1197 current_inst->opcode[1] = 0x38;
1202 current_inst->opcode[0] = 0x0F;
1203 current_inst->opcode[1] = 0x3A;
1207 current_inst->opcode[0] = 0xD8;
1211 current_inst->opcode[0] = 0xD9;
1215 current_inst->opcode[0] = 0xDA;
1219 current_inst->opcode[0] = 0xDB;
1223 current_inst->opcode[0] = 0xDC;
1227 current_inst->opcode[0] = 0xDD;
1231 current_inst->opcode[0] = 0xDE;
1235 current_inst->opcode[0] = 0xDF;
1239 NaClFatal("Unrecognized opcode prefix in NaClDefBytes");
1243 /* Now add final byte. */
1244 current_inst->opcode[index] = opcode;
1245 current_inst->num_opcode_bytes = index + 1;
1248 static void NaClPrintInstDescriptor(struct Gio* out,
1249 const NaClInstPrefix prefix,
1251 const int modrm_index) {
1252 if (NACL_NO_MODRM_OPCODE == modrm_index) {
1253 gprintf(out, "%s 0x%02x: ",
1254 NaClInstPrefixName(prefix), opcode);
1256 gprintf(out, "%s 0x%02x /%x: ",
1257 NaClInstPrefixName(prefix), opcode, modrm_index);
1261 static void VerifyModRmOpcodeRange(NaClInstPrefix prefix,
1263 uint8_t modrm_opcode) {
1264 if (modrm_opcode > NACL_NO_MODRM_OPCODE) {
1265 NaClPrintInstDescriptor(NaClLogGetGio(), prefix, opcode, modrm_opcode);
1266 NaClFatal("Illegal modrm opcode specification when defined opcode choices");
1270 void NaClDefPrefixInstMrmChoices_32_64(const NaClInstPrefix prefix,
1271 const uint8_t opcode,
1272 const uint8_t modrm_opcode,
1274 const int count_64) {
1275 VerifyModRmOpcodeRange(prefix, opcode, modrm_opcode);
1276 if (NaClInstCount[opcode][prefix][modrm_opcode] !=
1277 NACL_DEFAULT_CHOICE_COUNT) {
1278 NaClPrintInstDescriptor(NaClLogGetGio(), prefix, opcode, modrm_opcode);
1279 NaClFatal("Redefining NaClOpcode choice count");
1281 if (NACL_FLAGS_run_mode == X86_32) {
1282 NaClInstCount[opcode][prefix][modrm_opcode] = count_32;
1283 } else if (NACL_FLAGS_run_mode == X86_64) {
1284 NaClInstCount[opcode][prefix][modrm_opcode] = count_64;
1288 void NaClDefPrefixInstChoices(const NaClInstPrefix prefix,
1289 const uint8_t opcode,
1291 NaClDefPrefixInstChoices_32_64(prefix, opcode, count, count);
1294 void NaClDefPrefixInstMrmChoices(const NaClInstPrefix prefix,
1295 const uint8_t opcode,
1296 const uint8_t modrm_opcode,
1298 NaClDefPrefixInstMrmChoices_32_64(prefix, opcode, modrm_opcode,
1302 void NaClDefPrefixInstChoices_32_64(const NaClInstPrefix prefix,
1303 const uint8_t opcode,
1305 const int count_64) {
1306 NaClDefPrefixInstMrmChoices_32_64(prefix, opcode, NACL_NO_MODRM_OPCODE,
1307 count_32, count_64);
1310 /* Adds opcode flags corresponding to REP/REPNE flags if defined by
1313 static void NaClAddRepPrefixFlagsIfApplicable(void) {
1314 switch (current_opcode_prefix) {
1318 NaClAddBits(current_inst->flags, NACL_IFLAG(OpcodeAllowsData16) |
1319 NACL_IFLAG(SizeIgnoresData16));
1323 NaClAddBits(current_inst->flags, NACL_IFLAG(OpcodeAllowsRepne));
1326 NaClAddBits(current_inst->flags, NACL_IFLAG(OpcodeAllowsRep));
1333 /* Define the next opcode (instruction), initializing with
1336 static void NaClDefInstInternal(
1337 const uint8_t opcode,
1338 const NaClInstType insttype,
1340 const NaClMnemonic name,
1342 /* TODO(karl) If we can deduce a more specific prefix that
1343 * must be used, due to the flags associated with the opcode,
1344 * then put on the more specific prefix list. This will make
1345 * the defining of instructions easier, in that the caller doesn't
1346 * need to specify the prefix to use.
1349 /* Before starting, install an opcode sequence if applicable. */
1350 if (NULL != current_cand_inst_node) {
1351 current_inst_node = current_cand_inst_node;
1353 current_cand_inst_node = NULL;
1355 /* Before starting, expand appropriate implicit flag assumnptions. */
1356 if (flags & NACL_IFLAG(OpcodeLtC0InModRm)) {
1357 NaClAddBits(flags, NACL_IFLAG(OpcodeInModRm) | NACL_IFLAG(ModRmModIsnt0x3));
1360 DEBUG(NaClLog(LOG_INFO, "Define %s %"NACL_PRIx8": %s(%02x)\n",
1361 NaClInstPrefixName(current_opcode_prefix),
1362 opcode, NaClMnemonicName(name), name);
1363 NaClIFlagsPrint(NaClLogGetGio(), flags));
1365 if (NaClMnemonicEnumSize <= name) {
1366 NaClFatal("Badly defined mnemonic name");
1369 if (kNaClInstTypeRange <= insttype) {
1370 NaClFatal("Badly defined inst type");
1373 /* Create opcode and initialize */
1374 current_inst_mrm = (NaClMrmInst*) malloc(sizeof(NaClMrmInst));
1375 if (NULL == current_inst_mrm) {
1376 NaClFatal("NaClDefInst: malloc failed");
1378 DEBUG(NaClLog(LOG_INFO,
1379 "current = %p\n", (void*) current_inst_mrm));
1380 current_inst_mrm->next = NULL;
1381 current_inst = &(current_inst_mrm->inst);
1382 NaClDefBytes(opcode);
1383 current_inst->insttype = insttype;
1384 current_inst->flags = NACL_EMPTY_IFLAGS;
1385 current_inst->name = name;
1386 current_inst->opcode_ext = 0;
1387 current_inst->next_rule = NULL;
1389 /* undefine all operands. */
1390 current_inst->num_operands = 0;
1391 current_inst->operands = tables.operands + tables.operands_size;
1393 NaClAddIFlags(flags);
1395 NaClAddRepPrefixFlagsIfApplicable();
1397 NaClApplySanityChecksToInst();
1399 if (no_install || !NaClIFlagsMatchesRunMode(flags)) {
1403 if (NULL == current_inst_node) {
1404 /* Install NaClOpcode. */
1405 DEBUG(NaClLog(LOG_INFO, " standard install\n"));
1406 if (NULL == tables.inst_table[opcode][current_opcode_prefix]) {
1407 tables.inst_table[opcode][current_opcode_prefix] = current_inst;
1409 NaClModeledInst* next = tables.inst_table[opcode][current_opcode_prefix];
1410 while (NULL != next->next_rule) {
1411 next = next->next_rule;
1413 next->next_rule = current_inst;
1415 /* Install assuming no modrm opcode. Let NaClDefOp move if needed. */
1416 NaClInstallCurrentIntoOpcodeMrm(current_opcode_prefix, opcode,
1417 NACL_NO_MODRM_OPCODE);
1418 } else if (NULL == current_inst_node->matching_inst) {
1419 DEBUG(NaClLog(LOG_INFO, " instruction sequence install\n"));
1420 current_inst_node->matching_inst = current_inst;
1423 "Can't define more than one opcode for the same opcode sequence");
1428 const uint8_t opcode,
1429 const NaClInstType insttype,
1431 const NaClMnemonic name) {
1432 NaClDefInstInternal(opcode, insttype, flags, name, FALSE);
1435 /* Simple (fast hack) routine to extract a byte value from a character string.
1437 static int NaClExtractByte(const char* chars, const char* opcode_seq) {
1440 for (i = 0; i < 2; ++i) {
1441 char ch = *(chars++);
1444 "Odd number of characters in opcode sequence: '%s'\n",
1446 NaClFatal("Fix before continuing!");
1451 return strtoul(buffer, NULL, 16);
1454 static NaClModeledInstNode* NaClNewInstNode(uint8_t byte) {
1455 NaClModeledInstNode* root =
1456 (NaClModeledInstNode*) malloc(sizeof(NaClModeledInstNode));
1457 root->matching_byte = byte;
1458 root->matching_inst = NULL;
1459 root->success = NULL;
1464 /* Install an opcode sequence into the instruction trie. */
1465 static void NaClDefInstSeq(const char* opcode_seq) {
1466 /* Next is a (reference) pointer to the next node. The reference
1467 * is used so that we can easily update the trie when we add nodes.
1469 NaClModeledInstNode** next = &tables.inst_node_root;
1470 /* Last is the last visited node in trie that is still matching
1471 * the opcode sequence being added.
1473 NaClModeledInstNode* last = NULL;
1474 /* Index is the position of the next byte in the opcode sequence. */
1477 /* First check that opcode sequence not defined twice without a corresponding
1478 * call to NaClDefInst.
1480 if (NULL != current_cand_inst_node) {
1482 "Multiple definitions for opcode sequence: '%s'\n", opcode_seq);
1483 NaClFatal("Fix before continuing!");
1486 /* Now install into lookup trie. */
1487 while (opcode_seq[index]) {
1488 uint8_t byte = (uint8_t) NaClExtractByte(opcode_seq + index, opcode_seq);
1489 if (index >= 2 * NACL_MAX_BYTES_PER_X86_INSTRUCTION) {
1491 "Too many bytes specified for opcode sequence: '%s'\n",
1493 NaClFatal("Fix before continuing!\n");
1495 if ((NULL == *next) || (byte < (*next)->matching_byte)) {
1496 /* byte not in trie, add. */
1497 NaClModeledInstNode* node = NaClNewInstNode(byte);
1501 if (byte == (*next)->matching_byte) {
1503 next = &((*next)->success);
1506 next = &((*next)->fail);
1509 /* Last points to matching node, make it candidate instruction. */
1510 current_cand_inst_node = last;
1513 /* Apply checks to current instruction flags, and update model as
1516 static void NaClRecheckIFlags(void) {
1517 if (!NaClIFlagsMatchesRunMode(current_inst->flags)) {
1518 NaClRemoveCurrentInstMrmFromInstTable();
1519 NaClRemoveCurrentInstMrmFromInstMrmTable();
1521 /* If the instruction has an opcode in modrm, then it uses modrm. */
1522 if (NACL_EMPTY_IFLAGS != (current_inst->flags & NACL_IFLAG(OpcodeInModRm))) {
1523 NaClAddBits(current_inst->flags, NACL_IFLAG(OpcodeUsesModRm));
1525 /* If the instruction allows a two byte value, add DATA16 flag. */
1526 if (NACL_EMPTY_IFLAGS != (current_inst->flags &
1527 (NACL_IFLAG(OperandSize_w) |
1528 NACL_IFLAG(OpcodeHasImmed_z)))) {
1529 NaClAddBits(current_inst->flags, NACL_IFLAG(OpcodeAllowsData16));
1531 /* If the instruction uses the modrm rm field as an opcode value,
1532 * it also requires that the modrm mod field is 0x3.
1534 if (current_inst->flags & NACL_IFLAG(OpcodeInModRmRm)) {
1535 NaClAddBits(current_inst->flags, NACL_IFLAG(ModRmModIs0x3));
1537 NaClApplySanityChecksToInst();
1540 void NaClAddIFlags(NaClIFlags more_flags) {
1542 struct Gio* g = NaClLogGetGio();
1543 NaClLog(LOG_INFO, "Adding instruction flags: ");
1544 NaClIFlagsPrint(g, more_flags);
1546 NaClAddBits(current_inst->flags, more_flags);
1547 NaClRecheckIFlags();
1550 void NaClRemoveIFlags(NaClIFlags less_flags) {
1552 struct Gio* g = NaClLogGetGio();
1553 NaClLog(LOG_INFO, "Removing instruction flags: ");
1554 NaClIFlagsPrint(g, less_flags);
1556 NaClRemoveBits(current_inst->flags, less_flags);
1557 NaClRecheckIFlags();
1560 void NaClDelaySanityChecks(void) {
1561 apply_sanity_checks = FALSE;
1564 void NaClApplySanityChecks(void) {
1565 apply_sanity_checks = TRUE;
1566 if (NULL != current_inst) {
1568 NaClApplySanityChecksToInst();
1569 for (i = 0; i < current_inst->num_operands; i++) {
1570 NaClApplySanityChecksToOp(i);
1575 static void NaClInitInstTables(void) {
1577 NaClInstPrefix prefix;
1579 /* Before starting, verify that we have defined NaClOpcodeFlags
1580 * and NaClOpFlags big enough to hold the flags associated with it.
1582 assert(NaClIFlagEnumSize <= sizeof(NaClIFlags) * 8);
1583 assert(NaClOpFlagEnumSize <= sizeof(NaClOpFlags) * 8);
1584 assert(NaClDisallowsFlagEnumSize <= sizeof(NaClDisallowsFlags) * 8);
1586 for (i = 0; i < NCDTABLESIZE; ++i) {
1587 for (prefix = NoPrefix; prefix < NaClInstPrefixEnumSize; ++prefix) {
1588 tables.inst_table[i][prefix] = NULL;
1589 for (j = 0; j <= NACL_NO_MODRM_OPCODE; ++j) {
1590 NaClInstCount[i][prefix][j] = NACL_DEFAULT_CHOICE_COUNT;
1593 NaClPrefixTable[i] = "0";
1595 NaClDefInstPrefix(NoPrefix);
1596 NaClDefInstInternal(0x0, NACLi_INVALID, 0, InstInvalid, TRUE);
1597 tables.undefined_inst = current_inst;
1600 static void NaClDefPrefixBytes(void) {
1601 NaClEncodePrefixName(kValueSEGES, "kPrefixSEGES");
1602 NaClEncodePrefixName(kValueSEGCS, "kPrefixSEGCS");
1603 NaClEncodePrefixName(kValueSEGSS, "kPrefixSEGSS");
1604 NaClEncodePrefixName(kValueSEGDS, "kPrefixSEGDS");
1605 NaClEncodePrefixName(kValueSEGFS, "kPrefixSEGFS");
1606 NaClEncodePrefixName(kValueSEGGS, "kPrefixSEGGS");
1607 NaClEncodePrefixName(kValueDATA16, "kPrefixDATA16");
1608 NaClEncodePrefixName(kValueADDR16, "kPrefixADDR16");
1609 NaClEncodePrefixName(kValueLOCK, "kPrefixLOCK");
1610 NaClEncodePrefixName(kValueREPNE, "kPrefixREPNE");
1611 NaClEncodePrefixName(kValueREP, "kPrefixREP");
1613 if (NACL_FLAGS_run_mode == X86_64) {
1615 for (i = 0; i < 16; ++i) {
1616 NaClEncodePrefixName(0x40+i, "kPrefixREX");
1621 /* Define the given character sequence, associated with the given byte
1622 * opcode and instruction mnemonic, as a nop.
1624 static void NaClDefNopLikeSeq(const char* sequence, uint8_t opcode,
1625 NaClMnemonic name ) {
1626 NaClDefInstSeq(sequence);
1627 NaClDefInst(opcode, NACLi_386, NACL_EMPTY_IFLAGS, name);
1630 /* Define the given character sequence, associated with the given byte
1633 static void NaClDefNopSeq(const char* sequence, uint8_t opcode) {
1634 NaClDefNopLikeSeq(sequence, opcode, InstNop);
1637 static void NaClDefNops(void) {
1638 /* Note: The following could be recognized as nops, but are already
1639 * parsed and accepted by the validator.
1641 * 89 f6 mov %esi, %esi
1642 * 8d742600 lea %esi, [%rsi]
1643 * 8d7600 lea %esi, [%rsi]
1644 * 8d b6 00 00 00 00 lea %esi, [%rsi]
1645 * 8d b4 26 00 00 00 00 lea %esi, [%rsi]
1646 * 8d bc 27 00 00 00 00 lea %edi, [%rdi]
1647 * 8d bf 00 00 00 00 lea %edi, [%rdi]
1650 * 0f 1f 44 00 00 nop
1651 * 0f 1f 80 00 00 00 00 nop
1652 * 0f 1f 84 00 00 00 00 00 nop
1654 /* Note: For performance reasons, the function NaClMaybeHardCodedNop in
1655 * src/trusted/validator/x86/decoder/nc_inst_state.c
1656 * has been tuned to not look for these Nop instructions, unless
1657 * the opcode byte sequence is one of "90", "0f1f", or "0f0b". If you add
1658 * any nop instruction that doesn't meet this criteria, be sure
1659 * to update NaClMaybeHardCodedNop accordingly.
1662 NaClDefNopSeq("90", 0x90);
1663 NaClDefNopSeq("6690", 0x90);
1664 NaClDefNopLikeSeq("f390", 0x90, InstPause);
1666 NaClDefNopSeq("0f1f00", 0x1f);
1667 /* nop [%[re]ax+0] */
1668 NaClDefNopSeq("0f1f4000", 0x1f);
1669 /* nop [%[re]ax*1+0] */
1670 NaClDefNopSeq("0f1f440000", 0x1f);
1671 /* nop [%[re]ax+%[re]ax*1+0] */
1672 NaClDefNopSeq("660f1f440000", 0x1f);
1673 /* nop [%[re]ax+0] */
1674 NaClDefNopSeq("0f1f8000000000", 0x1f);
1675 /* nop [%[re]ax+%[re]ax*1+0] */
1676 NaClDefNopSeq("0f1f840000000000", 0x1f);
1677 /* nop [%[re]ax+%[re]ax+1+0] */
1678 NaClDefNopSeq("660f1f840000000000", 0x1f);
1679 /* nop %cs:[%re]ax+%[re]ax*1+0] */
1680 NaClDefNopSeq("662e0f1f840000000000", 0x1f);
1681 /* nop %cs:[%re]ax+%[re]ax*1+0] */
1682 NaClDefNopSeq("66662e0f1f840000000000", 0x1f);
1683 /* nop %cs:[%re]ax+%[re]ax*1+0] */
1684 NaClDefNopSeq("6666662e0f1f840000000000", 0x1f);
1685 /* nop %cs:[%re]ax+%[re]ax*1+0] */
1686 NaClDefNopSeq("666666662e0f1f840000000000", 0x1f);
1687 /* nop %cs:[%re]ax+%[re]ax*1+0] */
1688 NaClDefNopSeq("66666666662e0f1f840000000000", 0x1f);
1689 /* nop %cs:[%re]ax+%[re]ax*1+0] */
1690 NaClDefNopSeq("6666666666662e0f1f840000000000", 0x1f);
1692 NaClDefNopLikeSeq("0f0b", 0x0b, InstUd2);
1695 /* Build the set of x64 opcode (instructions). */
1696 static void NaClBuildInstTables(void) {
1697 struct NaClSymbolTable* st = NaClSymbolTableCreate(5, NULL);
1699 /* Create common (global) symbol table with instruction set presumptions. */
1700 NaClSymbolTablePutText(
1701 "sp", ((X86_32 == NACL_FLAGS_run_mode) ? "esp" : "rsp"), st);
1702 NaClSymbolTablePutText(
1703 "ip", ((X86_32 == NACL_FLAGS_run_mode) ? "eip" : "rip"), st);
1704 NaClSymbolTablePutText(
1705 "bp", ((X86_32 == NACL_FLAGS_run_mode) ? "ebp" : "rbp"), st);
1707 NaClInitInstTables();
1708 NaClDefPrefixBytes();
1709 NaClDefOneByteInsts(st);
1711 NaClDefSseInsts(st);
1712 NaClDefX87Insts(st);
1715 NaClSymbolTableDestroy(st);
1718 static int NaClInstMrmListLength(NaClMrmInst* next) {
1720 while (NULL != next) {
1727 static void NaClFatalChoiceCount(const int expected,
1729 const NaClInstPrefix prefix,
1731 const int modrm_index,
1732 NaClMrmInst* insts) {
1733 struct Gio* g = NaClLogGetGio();
1734 NaClPrintInstDescriptor(g, prefix, opcode, modrm_index);
1735 NaClLog(LOG_ERROR, "Expected %d rules but found %d:\n", expected, found);
1736 while (NULL != insts) {
1737 NaClModeledInstPrint(g, &(insts->inst));
1738 insts = insts->next;
1740 NaClFatal("fix before continuing...\n");
1743 /* Verify that the number of possible choies for each prefix:opcode matches
1744 * what was explicitly defined.
1746 static void NaClVerifyInstCounts(void) {
1748 NaClInstPrefix prefix;
1749 for (i = 0; i < NCDTABLESIZE; ++i) {
1750 for (prefix = NoPrefix; prefix < NaClInstPrefixEnumSize; ++prefix) {
1751 for (j = 0; j < NACL_MODRM_OPCODE_SIZE; ++j) {
1752 NaClMrmInst* insts = NaClInstMrmTable[i][prefix][j];
1753 int found = NaClInstMrmListLength(insts);
1754 int expected = NaClInstCount[i][prefix][j];
1755 if (expected == NACL_DEFAULT_CHOICE_COUNT) {
1757 NaClFatalChoiceCount(1, found, prefix, i, j, insts);
1759 } else if (expected != found) {
1760 NaClFatalChoiceCount(expected, found, prefix, i, j, insts);
1767 /* Removes X86-32 specific flags from the given instruction. */
1768 static void NaClInstRemove32Stuff(NaClModeledInst* inst) {
1769 NaClRemoveBits(inst->flags, NACL_IFLAG(Opcode32Only));
1772 /* Removes X86-64 specific flags from the given instruction. */
1773 static void NaClInstRemove64Stuff(NaClModeledInst* inst) {
1774 NaClRemoveBits(inst->flags,
1775 NACL_IFLAG(OpcodeRex) |
1776 NACL_IFLAG(OpcodeUsesRexW) |
1777 NACL_IFLAG(OpcodeHasRexR) |
1778 NACL_IFLAG(Opcode64Only) |
1779 NACL_IFLAG(OperandSize_o) |
1780 NACL_IFLAG(AddressSize_o) |
1781 NACL_IFLAG(OperandSizeDefaultIs64) |
1782 NACL_IFLAG(OperandSizeForce64));
1785 /* Simplifies the instructions if possible. Mostly removes flags that
1786 * don't correspond to the run mode.
1788 static void NaClSimplifyIfApplicable(void) {
1790 for (i = 0; i < NCDTABLESIZE; ++i) {
1791 NaClInstPrefix prefix;
1792 for (prefix = NoPrefix; prefix < NaClInstPrefixEnumSize; ++prefix) {
1793 NaClModeledInst* next = tables.inst_table[i][prefix];
1794 while (NULL != next) {
1795 if (X86_64 != NACL_FLAGS_run_mode) {
1796 NaClInstRemove64Stuff(next);
1798 if (X86_32 != NACL_FLAGS_run_mode) {
1799 NaClInstRemove32Stuff(next);
1801 /* Remove size only flags, since already compiled into tables. */
1802 NaClRemoveBits(next->flags,
1803 NACL_IFLAG(Opcode64Only) | NACL_IFLAG(Opcode32Only));
1804 next = next->next_rule;
1810 /* Prints out the set of defined instruction flags. */
1811 static void NaClIFlagsPrintInternal(struct Gio* f, NaClIFlags flags) {
1815 for (i = 0; i < NaClIFlagEnumSize; ++i) {
1816 if (flags & NACL_IFLAG(i)) {
1822 gprintf(f, "NACL_IFLAG(%s)", NaClIFlagName(i));
1826 gprintf(f, "NACL_EMPTY_IFLAGS");
1830 /* Prints out the set of defined Operand flags. */
1831 static void NaClOpFlagsPrintInternal(struct Gio* f, NaClOpFlags flags) {
1835 for (i = 0; i < NaClOpFlagEnumSize; ++i) {
1836 if (flags & NACL_OPFLAG(i)) {
1842 gprintf(f, "NACL_OPFLAG(%s)", NaClOpFlagName(i));
1846 gprintf(f, "NACL_EMPTY_OPFLAGS");
1850 /* Print out the opcode operand. */
1851 static void NaClOpPrintInternal(struct Gio* f, const NaClOp* operand) {
1852 gprintf(f, "{ %s, ", NaClOpKindName(operand->kind));
1853 NaClOpFlagsPrintInternal(f, operand->flags);
1855 if (NULL == operand->format_string) {
1858 gprintf(f, "\"%s\"", operand->format_string);
1860 gprintf(f, " },\n");
1863 /* Converts the (compressed) operand to the corresponding
1864 * index in tables.ops_compressed.
1866 size_t NaClOpOffset(const NaClOp* op) {
1867 /* Note: This function is innefficient, but doesn't slow things down
1868 * enough to worry about. Especially since this only effects the
1872 for (i = 0; i <= tables.ops_compressed_size; ++i) {
1873 if (op == (tables.ops_compressed + i)) return i;
1875 /* If reached, we have a bug! */
1876 NaClFatal("Can't find offset for operand");
1881 static void NaClPrintInstIndex(struct Gio* f,
1883 if (NACL_OPCODE_NULL_OFFSET == index) {
1884 gprintf(f, "NACL_OPCODE_NULL_OFFSET");
1886 gprintf(f, "%d", index);
1890 /* Print out the given opcode offset value corresponding to the
1891 * given instruction.
1893 static void NaClPrintInstOffset(struct Gio* f,
1894 const NaClModeledInst* inst) {
1895 NaClPrintInstIndex(f, NaClFindInstIndex(&tables, inst));
1898 /* Prints out the given instruction to the given file. If index >= 0,
1899 * print out a comment, with the value of index, before the printed
1900 * instruction. Lookahead is used to convert the next_rule pointer into
1901 * a symbolic reference using the name "g_Opcodes", plus the index defined by
1902 * the lookahead. Argument as_array_element is true if the element is
1903 * assumed to be in an array static initializer.
1905 static void NaClInstPrintInternal(struct Gio* f, Bool as_array_element,
1906 size_t index, const NaClModeledInst* inst) {
1907 gprintf(f, " /* %d */\n", index);
1908 gprintf(f, " { %s,\n", NaClInstTypeString(inst->insttype));
1910 NaClIFlagsPrintInternal(f, inst->flags);
1912 gprintf(f, " Inst%s, 0x%02x, ", NaClMnemonicName(inst->name),
1914 gprintf(f, "%u, %"NACL_PRIuS", ",
1915 inst->num_operands, NaClOpOffset(inst->operands));
1916 NaClPrintInstOffset(f, inst->next_rule);
1917 gprintf(f, " }%c\n", as_array_element ? ',' : ';');
1920 /* Generate header information, based on the executable name in argv0,
1921 * and the file to be generated (defined by fname).
1923 static void NaClPrintHeader(struct Gio* f, const char* argv0,
1924 const char* fname) {
1926 gprintf(f, " * THIS FILE IS AUTO-GENERATED. DO NOT EDIT.\n");
1927 gprintf(f, " * Compiled for %s.\n", NaClRunModeName(NACL_FLAGS_run_mode));
1929 gprintf(f, " * You must include ncopcode_desc.h before this file.\n");
1930 gprintf(f, " */\n\n");
1933 /* Print out which bytes correspond to prefix bytes. */
1934 static void NaClPrintPrefixTable(struct Gio* f) {
1936 gprintf(f, "static const uint32_t kNaClPrefixTable[NCDTABLESIZE] = {");
1937 for (opc = 0; opc < NCDTABLESIZE; opc++) {
1938 if (0 == opc % 16) {
1939 gprintf(f, "\n /* 0x%02x-0x%02x */\n ", opc, opc + 15);
1941 gprintf(f, "%s, ", NaClPrefixTable[opc]);
1943 gprintf(f, "\n};\n\n");
1946 static int NaClCountInstNodes(const NaClModeledInstNode* root) {
1951 count += NaClCountInstNodes(root->success);
1952 count += NaClCountInstNodes(root->fail);
1957 static void NaClPrintInstTrieEdge(const NaClModeledInstNode* edge,
1965 gprintf(f, "g_OpcodeSeq + %d", *edge_index);
1966 *edge_index += NaClCountInstNodes(edge);
1971 static void NaClPrintInstTrieNode(const NaClModeledInstNode* root,
1972 int root_index, struct Gio* f) {
1976 int next_index = root_index + 1;
1977 gprintf(f, " /* %d */\n", root_index);
1978 gprintf(f, " { 0x%02x,\n ", root->matching_byte);
1979 NaClPrintInstOffset(f, root->matching_inst);
1981 NaClPrintInstTrieEdge(root->success, &next_index, f);
1982 NaClPrintInstTrieEdge(root->fail, &next_index, f);
1983 gprintf(f, " },\n");
1984 next_index = root_index + 1;
1985 NaClPrintInstTrieNode(root->success, next_index, f);
1986 next_index += NaClCountInstNodes(root->success);
1987 NaClPrintInstTrieNode(root->fail, next_index, f);
1991 /* Prints out the contents of the opcode sequence overrides into the
1994 static void NaClPrintInstSeqTrie(const NaClModeledInstNode* root,
1996 /* Make sure trie isn't empty, since empty arrays create warning messages. */
1998 if (root == NULL) root = NaClNewInstNode(0);
1999 num_trie_nodes = NaClCountInstNodes(root);
2000 gprintf(f, "static const NaClInstNode g_OpcodeSeq[%d] = {\n", num_trie_nodes);
2001 NaClPrintInstTrieNode(root, 0, f);
2005 /* Prints out the array of (compressed) operands. */
2006 static void NaClPrintOperandTable(struct Gio* f) {
2008 gprintf(f, "static const NaClOp g_Operands[%"NACL_PRIuS"] = {\n",
2009 tables.ops_compressed_size);
2010 for (i = 0; i < tables.ops_compressed_size; ++i) {
2011 gprintf(f," /* %"NACL_PRIuS" */ ", i);
2012 NaClOpPrintInternal(f, tables.ops_compressed+i);
2014 gprintf(f, "};\n\n");
2017 static const size_t NaClOffsetsPerLine = 10;
2019 /* Print out instruction table. */
2020 static void NaClPrintInstTable(struct Gio* f) {
2023 "static const NaClInst g_Opcodes[%d] = {\n",
2024 tables.inst_compressed_size);
2025 for (i = 0; i < tables.inst_compressed_size; ++i) {
2026 const NaClModeledInst* next = tables.inst_compressed[i];
2027 NaClInstPrintInternal(f, TRUE, i, next);
2029 gprintf(f, "};\n\n");
2032 /* Print lookup table of rules, based on prefix and opcode byte. */
2033 static void NaClPrintLookupTable(struct Gio* f) {
2035 NaClInstPrefix prefix;
2037 gprintf(f, "static const NaClPrefixOpcodeArrayOffset g_LookupTable[%d] = {",
2038 (int) tables.opcode_lookup_size);
2039 for (i = 0; i < tables.opcode_lookup_size; ++i) {
2040 if (0 == (i % NaClOffsetsPerLine)) {
2041 gprintf(f, "\n /* %5d */ ", (int) i);
2043 NaClPrintInstIndex(f, tables.opcode_lookup[i]);
2046 gprintf(f, "};\n\n");
2048 gprintf(f, "static const NaClPrefixOpcodeSelector "
2049 "g_PrefixOpcode[NaClInstPrefixEnumSize] = {\n");
2050 for (prefix = NoPrefix; prefix < NaClInstPrefixEnumSize; ++prefix) {
2051 gprintf(f, " /* %20s */ { %d , 0x%02x, 0x%02x },\n",
2052 NaClInstPrefixName(prefix),
2053 tables.opcode_lookup_entry[prefix],
2054 tables.opcode_lookup_first[prefix],
2055 tables.opcode_lookup_last[prefix]);
2057 gprintf(f, "};\n\n");
2060 /* Print out the contents of the defined instructions into the given file. */
2061 static void NaClPrintDecodeTables(struct Gio* f) {
2062 NaClPrintOperandTable(f);
2063 NaClPrintInstTable(f);
2064 NaClPrintLookupTable(f);
2065 NaClPrintPrefixTable(f);
2066 NaClPrintInstSeqTrie(tables.inst_node_root, f);
2069 /* Print out the sequence of bytes used to encode an instruction sequence. */
2070 static void PrintInstructionSequence(
2071 struct Gio* f, uint8_t* inst_sequence, int length) {
2073 for (i = 0; i < length; ++i) {
2074 if (i > 0) gprintf(f, " ");
2075 gprintf(f, "%02x", inst_sequence[i]);
2079 /* Print out instruction sequences defined for the given (Trie) node,
2080 * and all of its descendants.
2081 * Note: To keep recursive base cases simple, we allow one more byte
2082 * in the instruction sequence that is actually possible.
2084 static void PrintHardCodedInstructionsNode(
2085 struct Gio* f, const NaClModeledInstNode* node,
2086 uint8_t inst_sequence[NACL_MAX_BYTES_PER_X86_INSTRUCTION+1], int length) {
2087 if (NULL == node) return;
2088 inst_sequence[length] = node->matching_byte;
2090 if (NACL_MAX_BYTES_PER_X86_INSTRUCTION < length) {
2091 struct Gio* glog = NaClLogGetGio();
2092 NaClLog(LOG_ERROR, "%s", "");
2093 PrintInstructionSequence(glog, inst_sequence, length);
2094 gprintf(glog, "\n");
2095 NaClFatal("Hard coded instruction too long, aborting\n");
2097 if (NULL != node->matching_inst) {
2098 gprintf(f, " --- ");
2099 PrintInstructionSequence(f, inst_sequence, length);
2100 gprintf(f, " ---\n");
2101 NaClModeledInstPrint(f, node->matching_inst);
2104 PrintHardCodedInstructionsNode(f, node->success, inst_sequence, length);
2105 PrintHardCodedInstructionsNode(f, node->fail, inst_sequence, length-1);
2108 /* Walks over specifically encoded instruction trie, and prints
2109 * out corresponding implemented instructions.
2111 static void NaClPrintHardCodedInstructions(struct Gio* f) {
2112 uint8_t inst_sequence[NACL_MAX_BYTES_PER_X86_INSTRUCTION+1];
2113 PrintHardCodedInstructionsNode(f, tables.inst_node_root, inst_sequence, 0);
2116 /* Prints out documentation on the modeled instruction set. */
2117 static void NaClPrintInstructionSet(struct Gio* f) {
2118 NaClInstPrefix prefix;
2120 gprintf(f, "*** Automatically generated file, do not edit! ***\n");
2122 gprintf(f, "Target: %s\n", NaClRunModeName(NACL_FLAGS_run_mode));
2124 gprintf(f, "*** Hard coded instructions ***\n");
2126 NaClPrintHardCodedInstructions(f);
2128 for (prefix = NoPrefix; prefix < NaClInstPrefixEnumSize; ++prefix) {
2129 Bool printed_rules = FALSE;
2130 gprintf(f, "*** %s ***\n", NaClInstPrefixName(prefix));
2132 for (i = 0; i < NCDTABLESIZE; ++i) {
2133 Bool is_first = TRUE;
2134 const NaClModeledInst* inst = tables.inst_table[i][prefix];
2135 while (NULL != inst) {
2137 gprintf(f, " --- %02x ---\n", i);
2140 NaClModeledInstPrint(f, inst);
2141 printed_rules = TRUE;
2142 inst = inst->next_rule;
2145 if (printed_rules) gprintf(f, "\n");
2149 /* Open the given file using the given directives (how). */
2150 static void NaClMustOpen(struct GioFile* g,
2151 const char* fname, const char* how) {
2152 if (!GioFileCtor(g, fname, how)) {
2153 NaClLog(LOG_ERROR, "could not fopen(%s, %s)\n", fname, how);
2154 NaClFatal("exiting now");
2158 /* Recognizes flags in argv, processes them, and then removes them.
2159 * Returns the updated value for argc.
2161 static int NaClGrokFlags(int argc, const char* argv[]) {
2164 if (argc == 0) return 0;
2166 for (i = 1; i < argc; ++i) {
2167 if (0 == strcmp("-m32", argv[i])) {
2168 NACL_FLAGS_run_mode = X86_32;
2169 } else if (0 == strcmp("-m64", argv[i])) {
2170 NACL_FLAGS_run_mode = X86_64;
2171 } else if (GrokBoolFlag("-documentation", argv[i],
2172 &NACL_FLAGS_human_readable) ||
2173 GrokBoolFlag("-validator_decoder", argv[i],
2174 &NACL_FLAGS_validator_decoder) ||
2175 GrokBoolFlag("-nacl_subregs", argv[i],
2176 &NACL_FLAGS_nacl_subregs)) {
2179 argv[new_argc++] = argv[i];
2185 static void GenerateTables(struct Gio* f, const char* cmd,
2186 const char* filename) {
2187 if (NACL_FLAGS_human_readable) {
2188 NaClPrintInstructionSet(f);
2190 /* Generate header file defining instruction set. */
2191 NaClPrintHeader(f, cmd, filename);
2192 if (NACL_FLAGS_nacl_subregs) {
2193 if (NACL_FLAGS_run_mode == X86_64) {
2194 NaClPrintGpRegisterIndexes_64(f);
2196 NaClPrintGpRegisterIndexes_32(f);
2199 NaClPrintDecodeTables(f);
2204 /* Walk the trie of explicitly defined opcode sequences, and
2205 * fill in the operands description field if it hasn't been
2206 * explicitly defined.
2208 static void FillInTrieMissingOperandsDescs(NaClModeledInstNode* node) {
2209 NaClModeledInst* inst;
2210 if (NULL == node) return;
2211 inst = node->matching_inst;
2212 NaClFillOperandDescs(inst);
2213 FillInTrieMissingOperandsDescs(node->success);
2214 FillInTrieMissingOperandsDescs(node->fail);
2217 /* Define the operands description field of each modeled
2218 * opcode instruction, if it hasn't explicitly been defined.
2220 static void FillInMissingOperandsDescs(void) {
2222 NaClInstPrefix prefix;
2223 for (prefix = NoPrefix; prefix < NaClInstPrefixEnumSize; ++prefix) {
2224 for (i = 0; i < NCDTABLESIZE; ++i) {
2225 NaClModeledInst* next = tables.inst_table[i][prefix];
2226 while (NULL != next) {
2227 NaClFillOperandDescs(next);
2228 next = next->next_rule;
2232 FillInTrieMissingOperandsDescs(tables.inst_node_root);
2235 static void InitTables(void) {
2236 tables.inst_node_root = NULL;
2237 tables.operands_size = 0;
2238 tables.ops_compressed_size = 0;
2239 tables.opcode_lookup_size = 0;
2240 tables.inst_compressed_size = 0;
2241 tables.undefined_inst = 0;
2244 int main(const int argc, const char* argv[]) {
2245 struct GioFile gfile;
2246 struct Gio* g = (struct Gio*) &gfile;
2247 int new_argc = NaClGrokFlags(argc, argv);
2248 if ((new_argc < 1) || (new_argc > 2) ||
2249 (NACL_FLAGS_human_readable && NACL_FLAGS_nacl_subregs) ||
2250 (NACL_FLAGS_run_mode == NaClRunModeSize)) {
2252 "ERROR: usage: ncdecode_tablegen <architecture_flag> "
2253 "[-documentation | -validator_decoder -nacl_subregs] [file]\n");
2257 NaClLogModuleInit();
2258 NaClBuildInstTables();
2259 NaClSimplifyIfApplicable();
2260 NaClVerifyInstCounts();
2261 FillInMissingOperandsDescs();
2263 if (NACL_FLAGS_validator_decoder)
2264 NaClNcvalInstSimplify(&tables);
2266 /* Don't compress if output is to be readable! Compression
2267 * ignores extra (redundant) data used by print routines of
2268 * modeled instructions, since this data is not needed at
2269 * runtime when the corresponding data is defined in the
2270 * parsed instruction.
2272 if (!NACL_FLAGS_human_readable) {
2273 NaClOpCompress(&tables);
2276 if (new_argc == 1) {
2277 GioFileRefCtor(&gfile, stdout);
2278 GenerateTables(g, argv[0], "<stdout>");
2280 NaClMustOpen(&gfile, argv[1], "w");
2281 GenerateTables(g, argv[0], argv[1]);
2283 NaClLogModuleFini();