Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / native_client / src / trusted / validator / x86 / decoder / generator / ncdecode_tablegen.c
1 /*
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.
5  */
6
7 /*
8  * New table driven generator for a decoder of x86 code.
9  *
10  * Note: Most of the organization of this document is based on the
11  * NaClOpcode Map appendix of one of the following documents:
12
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)".
16  *
17  * (2) "Intel 80386 Reference Programmer's Manual" (document
18  * http://pdos.csail.mit.edu/6.828/2004/readings/i386/toc.htm).
19  */
20
21 #ifndef NACL_TRUSTED_BUT_NOT_TCB
22 #error("This file is not meant for use in the TCB")
23 #endif
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <assert.h>
28 #include <string.h>
29
30 #include "native_client/src/trusted/validator/x86/decoder/generator/ncdecode_tablegen.h"
31
32
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"
44
45 /* To turn on debugging of instruction decoding, change value of
46  * DEBUGGING to 1.
47  */
48 #define DEBUGGING 0
49
50 #include "native_client/src/shared/utils/debugging.h"
51
52 /* Define the default buffer size to use. */
53 #define BUFFER_SIZE 256
54
55 /* Model an NaClInst, sorted by OpcodeInModRm values. */
56 typedef struct NaClMrmInst {
57   NaClModeledInst inst;
58   struct NaClMrmInst* next;
59 } NaClMrmInst;
60
61 /* Note: in general all errors in this module will be fatal.
62  * To debug: use gdb or your favorite debugger.
63  */
64 void NaClFatal(const char* s) {
65   NaClLog(LOG_FATAL, "Error: %s\n", s);
66   NaClLog(LOG_FATAL, "Fatal: cannot recover\n");
67   exit(-1);
68 }
69
70 /* Returns the print name of the given run mode. */
71 static const char* NaClRunModeName(NaClRunMode mode) {
72   switch (mode) {
73     case X86_32: return "x86-32 bit mode";
74     case X86_64: return "x86-64 bit mode";
75     default: assert(0);
76   }
77
78   /* NOTREACHED */
79   return NULL;
80 }
81
82 /* Defines if we should simplify the instructions to
83  * what is needed by the validator.
84  */
85 static Bool NACL_FLAGS_validator_decoder = FALSE;
86
87 /* Defines the run mode files that should be generated. */
88 NaClRunMode NACL_FLAGS_run_mode = NaClRunModeSize;
89
90 /* Defines whether the output of the instruction set should
91  * be as a header file, or human readable (for documentation).
92  */
93 static Bool NACL_FLAGS_human_readable = FALSE;
94
95 /* Defines whether the output should be instruction modeling tables,
96  * or hardware registers.
97  */
98 static Bool NACL_FLAGS_nacl_subregs = FALSE;
99
100 /* Holds the current instruction prefix. */
101 static NaClInstPrefix current_opcode_prefix = NoPrefix;
102
103 /* Holds the default instruction prefix. */
104 static NaClInstPrefix default_opcode_prefix = NoPrefix;
105
106 /* Holds the current instruction being built. */
107 static NaClModeledInst* current_inst = NULL;
108
109 /* Holds the current opcode sequence to be associated with the next
110  * defined opcode.
111  */
112 static NaClModeledInstNode* current_inst_node = NULL;
113
114 /* Holds the candidate for the current_inst_node, when
115  * NaClDefInst is called.
116  */
117 static NaClModeledInstNode* current_cand_inst_node = NULL;
118
119 /* Holds the current instruction with mrm extention being built. */
120 static NaClMrmInst* current_inst_mrm = NULL;
121
122 /* Holds tables used to generate/compress the modeled instructions. */
123 NaClInstTables tables;
124
125 /* True if we are to apply sanity checks as we define operantions. */
126 static Bool apply_sanity_checks = TRUE;
127
128 #define NACL_DEFAULT_CHOICE_COUNT (-1)
129
130 #define NACL_NO_MODRM_OPCODE 8
131
132 #define NACL_MODRM_OPCODE_SIZE (NACL_NO_MODRM_OPCODE + 1)
133
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.
137  */
138 static int NaClInstCount[NCDTABLESIZE]
139           [NaClInstPrefixEnumSize][NACL_MODRM_OPCODE_SIZE];
140
141 static NaClMrmInst* NaClInstMrmTable[NCDTABLESIZE]
142           [NaClInstPrefixEnumSize][NACL_MODRM_OPCODE_SIZE];
143
144 /* Holds encodings of prefix bytes. */
145 static const char* NaClPrefixTable[NCDTABLESIZE];
146
147
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.
151  */
152 static void NaClFatalInst(const char* message) {
153   NaClLog(LOG_INFO, "Prefix: %s\n", NaClInstPrefixName(current_opcode_prefix));
154   NaClModeledInstPrint(NaClLogGetGio(), current_inst);
155   NaClFatal(message);
156 }
157
158 /* Prints out what operand is currently being defined, followed by the given
159  * error message. Then aborts the execution of the program.
160  */
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));
165   } else {
166     NaClLog(LOG_ERROR, "On operand %d:\n", index);
167   }
168   NaClFatalInst(message);
169 }
170
171 /* Advance the buffer/buffer_size values by count characters. */
172 static void CharAdvance(char** buffer, size_t* buffer_size, size_t count) {
173   *buffer += count;
174   *buffer_size += count;
175 }
176
177 /* Generates a (malloc allocated) string describing the form for the
178  * operands.
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.
182  */
183 static void NaClFillOperandDescs(NaClModeledInst* inst) {
184   char buffer[BUFFER_SIZE];
185   int i;
186
187   /* Make sure inst is defined before trying to fix. */
188   if (NULL == inst) return;
189
190   for (i = 0; i < inst->num_operands; ++i) {
191     char* buf = buffer;
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;
196
197     if (NULL != inst->operands[i].format_string) continue;
198
199     buffer[0] = '\0';  /* just in case there isn't any operands. */
200     if (is_implicit) {
201       CharAdvance(&buf, &buf_size,
202                   SNPRINTF(buf, buf_size, "{"));
203     }
204     switch (kind) {
205       case A_Operand:
206         CharAdvance(&buf, &buf_size,
207                     SNPRINTF(buf, buf_size, "$A"));
208         break;
209       case E_Operand:
210       case Eb_Operand:
211       case Ew_Operand:
212       case Ev_Operand:
213       case Eo_Operand:
214       case Edq_Operand:
215         CharAdvance(&buf, &buf_size,
216                     SNPRINTF(buf, buf_size, "$E"));
217         break;
218       case G_Operand:
219       case Gb_Operand:
220       case Gw_Operand:
221       case Gv_Operand:
222       case Go_Operand:
223       case Gdq_Operand:
224         CharAdvance(&buf, &buf_size,
225                     SNPRINTF(buf, buf_size, "$G"));
226         break;
227       case Seg_G_Operand:
228         CharAdvance(&buf, &buf_size,
229                     SNPRINTF(buf, buf_size, "$SegG"));
230         break;
231       case G_OpcodeBase:
232         CharAdvance(&buf, &buf_size,
233                     SNPRINTF(buf, buf_size, "$/r"));
234         break;
235       case I_Operand:
236       case Ib_Operand:
237       case Iw_Operand:
238       case Iv_Operand:
239       case Io_Operand:
240       case I2_Operand:
241       case J_Operand:
242       case Jb_Operand:
243       case Jw_Operand:
244       case Jv_Operand:
245         CharAdvance(&buf, &buf_size,
246                     SNPRINTF(buf, buf_size, "$I"));
247         break;
248       case M_Operand:
249       case Mb_Operand:
250       case Mw_Operand:
251       case Mv_Operand:
252       case Mo_Operand:
253       case Mdq_Operand:
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. */
258           continue;
259         } else {
260           CharAdvance(&buf, &buf_size,
261                       SNPRINTF(buf, buf_size, "$M"));
262         }
263         break;
264       case Mpw_Operand:
265         CharAdvance(&buf, &buf_size,
266                     SNPRINTF(buf, buf_size, "m16:16"));
267         break;
268       case Mpv_Operand:
269         CharAdvance(&buf, &buf_size,
270                     SNPRINTF(buf, buf_size, "m16:32"));
271         break;
272       case Mpo_Operand:
273         CharAdvance(&buf, &buf_size,
274                     SNPRINTF(buf, buf_size, "m16:64"));
275         break;
276       case Mmx_E_Operand:
277       case Mmx_N_Operand:
278         CharAdvance(&buf, &buf_size,
279                     SNPRINTF(buf, buf_size, "$E(mmx)"));
280         break;
281       case Mmx_G_Operand:
282       case Mmx_Gd_Operand:
283         CharAdvance(&buf, &buf_size,
284                     SNPRINTF(buf, buf_size, "$G(mmx)"));
285         break;
286       case Xmm_E_Operand:
287       case Xmm_Eo_Operand:
288         CharAdvance(&buf, &buf_size,
289                     SNPRINTF(buf, buf_size, "$E(xmm)"));
290         break;
291       case Xmm_G_Operand:
292       case Xmm_Go_Operand:
293         CharAdvance(&buf, &buf_size,
294                     SNPRINTF(buf, buf_size, "$G(xmm)"));
295         break;
296       case O_Operand:
297       case Ob_Operand:
298       case Ow_Operand:
299       case Ov_Operand:
300       case Oo_Operand:
301         CharAdvance(&buf, &buf_size,
302                     SNPRINTF(buf, buf_size, "$O"));
303         break;
304       case S_Operand:
305         CharAdvance(&buf, &buf_size,
306                     SNPRINTF(buf, buf_size, "%%Sreg"));
307         break;
308       case C_Operand:
309         CharAdvance(&buf, &buf_size,
310                     SNPRINTF(buf, buf_size, "%%Creg"));
311         break;
312       case D_Operand:
313         CharAdvance(&buf, &buf_size,
314                     SNPRINTF(buf, buf_size, "%%Dreg"));
315         break;
316       case St_Operand:
317         CharAdvance(&buf, &buf_size,
318                     SNPRINTF(buf, buf_size, "%%st"));
319         break;
320       case RegAL:
321       case RegBL:
322       case RegCL:
323       case RegDL:
324       case RegAH:
325       case RegBH:
326       case RegCH:
327       case RegDH:
328       case RegDIL:
329       case RegSIL:
330       case RegBPL:
331       case RegSPL:
332       case RegR8B:
333       case RegR9B:
334       case RegR10B:
335       case RegR11B:
336       case RegR12B:
337       case RegR13B:
338       case RegR14B:
339       case RegR15B:
340       case RegAX:
341       case RegBX:
342       case RegCX:
343       case RegDX:
344       case RegSI:
345       case RegDI:
346       case RegBP:
347       case RegSP:
348       case RegR8W:
349       case RegR9W:
350       case RegR10W:
351       case RegR11W:
352       case RegR12W:
353       case RegR13W:
354       case RegR14W:
355       case RegR15W:
356       case RegEAX:
357       case RegEBX:
358       case RegECX:
359       case RegEDX:
360       case RegESI:
361       case RegEDI:
362       case RegEBP:
363       case RegESP:
364       case RegR8D:
365       case RegR9D:
366       case RegR10D:
367       case RegR11D:
368       case RegR12D:
369       case RegR13D:
370       case RegR14D:
371       case RegR15D:
372       case RegCS:
373       case RegDS:
374       case RegSS:
375       case RegES:
376       case RegFS:
377       case RegGS:
378       case RegEFLAGS:
379       case RegRFLAGS:
380       case RegEIP:
381       case RegRIP:
382       case RegRAX:
383       case RegRBX:
384       case RegRCX:
385       case RegRDX:
386       case RegRSI:
387       case RegRDI:
388       case RegRBP:
389       case RegRSP:
390       case RegR8:
391       case RegR9:
392       case RegR10:
393       case RegR11:
394       case RegR12:
395       case RegR13:
396       case RegR14:
397       case RegR15:
398       case RegREIP:
399       case RegREAX:
400       case RegREBX:
401       case RegRECX:
402       case RegREDX:
403       case RegRESP:
404       case RegREBP:
405       case RegRESI:
406       case RegREDI:
407       case RegDS_EDI:
408       case RegDS_EBX:
409       case RegES_EDI:
410       case RegST0:
411       case RegST1:
412       case RegST2:
413       case RegST3:
414       case RegST4:
415       case RegST5:
416       case RegST6:
417       case RegST7:
418       case RegMMX0:
419       case RegMMX1:
420       case RegMMX2:
421       case RegMMX3:
422       case RegMMX4:
423       case RegMMX5:
424       case RegMMX6:
425       case RegMMX7:
426       case RegXMM0:
427       case RegXMM1:
428       case RegXMM2:
429       case RegXMM3:
430       case RegXMM4:
431       case RegXMM5:
432       case RegXMM6:
433       case RegXMM7:
434       case RegXMM8:
435       case RegXMM9:
436       case RegXMM10:
437       case RegXMM11:
438       case RegXMM12:
439       case RegXMM13:
440       case RegXMM14:
441       case RegXMM15:
442         CharAdvance(&buf, &buf_size,
443                     SNPRINTF(buf, buf_size, "%%%s",
444                              NaClOpKindName(kind) + strlen("Reg")));
445         break;
446       case Const_1:
447         CharAdvance(&buf, &buf_size,
448                     SNPRINTF(buf, buf_size, "1"));
449         break;
450       default:
451         CharAdvance(&buf, &buf_size,
452                     SNPRINTF(buf, buf_size, "???"));
453         break;
454     }
455     if (is_implicit) {
456       CharAdvance(&buf, &buf_size,
457                   SNPRINTF(buf, buf_size, "}"));
458     }
459     *((char**)(inst->operands[i].format_string)) = strdup(buffer);
460   }
461 }
462
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;
468   }
469 }
470
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);
474 }
475
476 /* Change the current opcode prefix to the given value. */
477 void NaClDefInstPrefix(const NaClInstPrefix prefix) {
478   current_opcode_prefix = prefix;
479 }
480
481 void NaClResetToDefaultInstPrefix(void) {
482   NaClDefInstPrefix(default_opcode_prefix);
483 }
484
485 NaClModeledInst* NaClGetDefInst(void) {
486   return current_inst;
487 }
488
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.
492  */
493 static void NaClCheckIfERepeated(int index) {
494   int i;
495   for (i = 0; i < index; ++i) {
496     const NaClOp* operand = &current_inst->operands[i];
497     switch (operand->kind) {
498       case Mmx_E_Operand:
499       case Xmm_E_Operand:
500       case Xmm_Eo_Operand:
501       case E_Operand:
502       case Eb_Operand:
503       case Ew_Operand:
504       case Ev_Operand:
505       case Eo_Operand:
506       case Edq_Operand:
507         NaClFatalOp(index, "Can't use E Operand more than once");
508         break;
509       default:
510         break;
511     }
512   }
513 }
514
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.
518  */
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)))) {
523     NaClFatalOp(index,
524                  "Can't use G Operand, bits being used for opcode in modrm");
525   }
526 }
527
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.
531  */
532 static void NaClCheckIfGRepeated(int index) {
533   int i;
534   for (i = 0; i < index; ++i) {
535     const NaClOp* operand = &current_inst->operands[i];
536     switch (operand->kind) {
537       case Mmx_G_Operand:
538       case Xmm_G_Operand:
539       case Xmm_Go_Operand:
540       case G_Operand:
541       case Gb_Operand:
542       case Gw_Operand:
543       case Gv_Operand:
544       case Go_Operand:
545       case Gdq_Operand:
546         NaClFatalOp(index, "Can't use G Operand more than once");
547         break;
548       default:
549         break;
550     }
551   }
552 }
553
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
557  * and terminate.
558  */
559 static void NaClCheckIfIRepeated(int index) {
560   int i;
561   for (i = 0; i < index; ++i) {
562     const NaClOp* operand = &current_inst->operands[i];
563     switch (operand->kind) {
564       case I_Operand:
565       case Ib_Operand:
566       case Iw_Operand:
567       case Iv_Operand:
568       case Io_Operand:
569         NaClFatalOp(index, "Can't use I_Operand more than once");
570         break;
571       case J_Operand:
572       case Jb_Operand:
573       case Jv_Operand:
574         NaClFatalOp(index, "Can't use both I_Operand and J_Operand");
575         break;
576       default:
577         break;
578     }
579   }
580 }
581
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);
594   }
595   return flags;
596 }
597
598 /* Check that the operand being defined (via the given index), does not
599  * specify any inconsistent flags.
600  */
601 static void NaClApplySanityChecksToOp(int index) {
602   const NaClOp* operand = &current_inst->operands[index];
603   const NaClIFlags operand_sizes = NaClOperandSizes(current_inst);
604
605   if (!apply_sanity_checks) return;
606
607   /* Check that operand is consistent with other operands defined, or flags
608    * defined on the opcode.
609    */
610   switch (operand->kind) {
611     case E_Operand:
612       NaClCheckIfERepeated(index);
613       break;
614     case Eb_Operand:
615       if (NACL_IFLAG(OperandSize_b) == operand_sizes) {
616         /* Singlton set already specifies size, so no need for extra
617          * size specification.
618          */
619         NaClFatalOp(index,
620                      "Size implied by OperandSize_b, use E_Operand instead");
621       }
622       NaClCheckIfERepeated(index);
623       break;
624     case Ew_Operand:
625       if (NACL_IFLAG(OperandSize_w) == operand_sizes) {
626         /* Singlton set already specifies size, so no need for extra
627          * size specification.
628          */
629         NaClFatalOp(index,
630                      "Size implied by OperandSize_w, use E_Operand instead");
631       }
632       NaClCheckIfERepeated(index);
633       break;
634     case Ev_Operand:
635       if (NACL_IFLAG(OperandSize_v) == operand_sizes) {
636         /* Singlton set already specifies size, so no need for extra
637          * size specification.
638          */
639         NaClFatalOp(index,
640                      "Size implied by OperandSize_v, use E_Operand instead");
641       }
642       NaClCheckIfERepeated(index);
643       break;
644     case Eo_Operand:
645       if (NACL_IFLAG(OperandSize_o) == operand_sizes) {
646         /* Singlton set already specifies size, so no need for extra
647          * size specification.
648          */
649         NaClFatalOp(index,
650                      "Size implied by OperandSize_o, use E_Operand instead");
651       }
652       NaClCheckIfERepeated(index);
653       break;
654     case Edq_Operand:
655       NaClCheckIfERepeated(index);
656       break;
657     case Mmx_E_Operand:
658     case Xmm_E_Operand:
659       NaClCheckIfERepeated(index);
660       break;
661     case Xmm_Eo_Operand:
662       if (NACL_IFLAG(OperandSize_o) == operand_sizes) {
663         /* Singlton set already specifies size, so no need for extra
664          * size specification.
665          */
666         NaClFatalOp
667             (index,
668              "Size implied by OperandSize_o, use Xmm_E_Operand instead");
669       }
670       NaClCheckIfERepeated(index);
671       break;
672     case G_Operand:
673       NaClCheckIfGRepeated(index);
674       NaClCheckIfOpcodeInModRm(index);
675       break;
676     case Gb_Operand:
677       if (NACL_IFLAG(OperandSize_b) == operand_sizes) {
678         /* Singlton set already specifies size, so no need for extra
679          * size specification.
680          */
681         NaClFatalOp(index,
682                      "Size implied by OperandSize_b, use G_Operand instead");
683       }
684       NaClCheckIfGRepeated(index);
685       NaClCheckIfOpcodeInModRm(index);
686       break;
687     case Gw_Operand:
688       if (NACL_IFLAG(OperandSize_w) == operand_sizes) {
689         /* Singlton set already specifies size, so no need for extra
690          * size specification.
691          */
692         NaClFatalOp(index,
693                      "Size implied by OperandSize_w, use G_Operand instead");
694       }
695       NaClCheckIfGRepeated(index);
696       NaClCheckIfOpcodeInModRm(index);
697       break;
698     case Gv_Operand:
699       if (NACL_IFLAG(OperandSize_v) == operand_sizes) {
700         /* Singlton set already specifies size, so no need for extra
701          * size specification.
702          */
703         NaClFatalOp(index,
704                      "Size implied by OperandSize_v, use G_Operand instead");
705       }
706       NaClCheckIfGRepeated(index);
707       NaClCheckIfOpcodeInModRm(index);
708       break;
709     case Go_Operand:
710       if (NACL_IFLAG(OperandSize_o) == operand_sizes) {
711         /* Singlton set already specifies size, so no need for extra
712          * size specification.
713          */
714         NaClFatalOp(index,
715                      "Size implied by OperandSize_o, use G_Operand instead");
716       }
717       NaClCheckIfGRepeated(index);
718       NaClCheckIfOpcodeInModRm(index);
719       break;
720     case Gdq_Operand:
721       NaClCheckIfGRepeated(index);
722       NaClCheckIfOpcodeInModRm(index);
723       break;
724     case Mmx_G_Operand:
725     case Xmm_G_Operand:
726       NaClCheckIfGRepeated(index);
727       NaClCheckIfOpcodeInModRm(index);
728       break;
729     case Xmm_Go_Operand:
730       if (NACL_IFLAG(OperandSize_o) == operand_sizes) {
731         /* Singlton set already specifies size, so no need for extra
732          * size specification.
733          */
734         NaClFatalOp
735             (index,
736              "Size implied by OperandSize_o, use Xmm_G_Operand instead");
737       }
738       NaClCheckIfGRepeated(index);
739       NaClCheckIfOpcodeInModRm(index);
740       break;
741     case I_Operand:
742       NaClCheckIfIRepeated(index);
743       break;
744     case Ib_Operand:
745       if (NACL_IFLAG(OperandSize_b) == operand_sizes) {
746         /* Singlton set already specifies size, so no need for extra
747          * size specification.
748          */
749         NaClFatalOp(index,
750                      "Size implied by OperandSize_b, use I_Operand instead");
751       }
752       if (current_inst->flags & NACL_IFLAG(OpcodeHasImmed_b)) {
753         NaClFatalOp(index,
754                      "Size implied by OpcodeHasImmed_b, use I_Operand instead");
755       }
756       NaClCheckIfIRepeated(index);
757       break;
758     case Iw_Operand:
759       if (NACL_IFLAG(OperandSize_w) == operand_sizes) {
760         /* Singlton set already specifies size, so no need for extra
761          * size specification.
762          */
763         NaClFatalOp(index,
764                      "Size implied by OperandSize_w, use I_Operand instead");
765       }
766       if (current_inst->flags & NACL_IFLAG(OpcodeHasImmed_w)) {
767         NaClFatalOp(index,
768                      "Size implied by OpcodeHasImmed_w, use I_Operand instead");
769       }
770       NaClCheckIfIRepeated(index);
771       break;
772     case Iv_Operand:
773       if (NACL_IFLAG(OperandSize_v) == operand_sizes) {
774         /* Singlton set already specifies size, so no need for extra
775          * size specification.
776          */
777         NaClFatalOp(index,
778                      "Size implied by OperandSize_v, use I_Operand instead");
779       }
780       if (current_inst->flags & NACL_IFLAG(OpcodeHasImmed_v)) {
781         NaClFatalOp(index,
782                      "Size implied by OpcodeHasImmed_v, use I_Operand instead");
783       }
784       NaClCheckIfIRepeated(index);
785       break;
786     case Io_Operand:
787       if (NACL_IFLAG(OperandSize_o) == operand_sizes) {
788         /* Singlton set already specifies size, so no need for extra
789          * size specification.
790          */
791         NaClFatalOp(index,
792                      "Size implied by OperandSize_o, use I_Operand instead");
793       }
794       if (current_inst->flags & NACL_IFLAG(OpcodeHasImmed_o)) {
795         NaClFatalOp(index,
796                      "Size implied by OpcodeHasImmed_o, use I_Operand instead");
797       }
798       NaClCheckIfIRepeated(index);
799       break;
800     default:
801       break;
802   }
803 }
804
805 /* Define the next operand of the current opcode to have
806  * the given kind and flags.
807  */
808 static void NaClDefOpInternal(NaClOpKind kind, NaClOpFlags flags) {
809   int index;
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!");
814   }
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;
820 }
821
822 static void NaClInstallCurrentIntoOpcodeMrm(const NaClInstPrefix prefix,
823                                             const uint8_t opcode,
824                                             int mrm_index) {
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;
829   } else {
830     NaClMrmInst* next = NaClInstMrmTable[opcode][prefix][mrm_index];
831     while (NULL != next->next) {
832       next = next->next;
833     }
834     next->next = current_inst_mrm;
835   }
836 }
837
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.
841  */
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! */
849       if (NULL == prev) {
850         tables.inst_table[opcode][current_inst->prefix] = next->next_rule;
851       } else {
852         prev->next_rule = next->next_rule;
853       }
854       return;
855     } else  {
856       prev = next;
857       next = next->next_rule;
858     }
859   }
860 }
861
862 /* Removes the current_inst_mrm from the corresponding
863  * NaClInstMrmTable.
864  *
865  * Used when Opcode32Only or Opcode64Only flag is added, and
866  * the flag doesn't match the subarchitecture being modeled.
867  */
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.
872    */
873   int mrm_opcode = NACL_NO_MODRM_OPCODE;
874   if (current_inst->flags & NACL_IFLAG(OpcodeInModRm)) {
875     mrm_opcode = NaClGetOpcodeInModRm(current_inst->opcode_ext);
876   }
877
878   while (1) {
879     uint8_t opcode = current_inst->opcode[current_inst->num_opcode_bytes - 1];
880     NaClMrmInst* prev = NULL;
881     NaClMrmInst* next =
882         NaClInstMrmTable[opcode][current_inst->prefix][mrm_opcode];
883     DEBUG(NaClLog(LOG_INFO, "Removing [%02x][%s][%d]?",
884                   opcode, NaClInstPrefixName(current_inst->prefix),
885                   mrm_opcode));
886     while (NULL != next) {
887       if (current_inst_mrm == next) {
888         /* Found - remove! */
889         if (NULL == prev) {
890           NaClInstMrmTable[opcode][current_inst->prefix][mrm_opcode] =
891               next->next;
892         } else {
893           prev->next = next->next;
894         }
895         return;
896       } else {
897         prev = next;
898         next = next->next;
899       }
900     }
901     if (mrm_opcode == NACL_NO_MODRM_OPCODE) return;
902     mrm_opcode = NACL_NO_MODRM_OPCODE;
903   }
904 }
905
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;
910   NaClMrmInst* next =
911       NaClInstMrmTable[opcode][current_opcode_prefix]
912                       [NACL_NO_MODRM_OPCODE];
913   while (current_inst_mrm != next) {
914     if (next == NULL) return;
915     prev = next;
916     next = next->next;
917   }
918   if (NULL == prev) {
919     NaClInstMrmTable[opcode][current_opcode_prefix]
920                     [NACL_NO_MODRM_OPCODE] =
921         next->next;
922   } else {
923     prev->next = next->next;
924   }
925   current_inst_mrm = next;
926   current_inst_mrm->next = NULL;
927   NaClInstallCurrentIntoOpcodeMrm(current_opcode_prefix, opcode, mrm_index);
928 }
929
930 static void NaClPrintlnOpFlags(struct Gio* g, NaClOpFlags flags) {
931   int i;
932   for (i = 0; i < NaClOpFlagEnumSize; ++i) {
933     if (flags & NACL_OPFLAG(i)) {
934       gprintf(g, " %s", NaClOpFlagName(i));
935     }
936   }
937   gprintf(g, "\n");
938 }
939
940 static void NaClApplySanityChecksToInst(void);
941
942 void NaClDefOpcodeExtension(int opcode) {
943   uint8_t byte_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]");
947   }
948   if (NACL_EMPTY_IFLAGS ==
949       (current_inst->flags & NACL_IFLAG(OpcodeInModRm))) {
950     NaClFatalInst(
951         "Opcode extension in [0..7], but not OpcodeInModRm");
952   }
953   DEBUG(NaClLog(LOG_INFO, "Defining opcode extension %d\n", opcode));
954   NaClMoveCurrentToMrmIndex(byte_opcode);
955   NaClSetOpcodeInModRm(byte_opcode, &current_inst->opcode_ext);
956 }
957
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]");
963   }
964   if (NACL_EMPTY_IFLAGS ==
965       (current_inst->flags & NACL_IFLAG(OpcodeInModRm))) {
966     NaClFatalInst(
967         "Opcode modrm rm extension in [0..7], but not OpcodeInModRm");
968   }
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, &current_inst->opcode_ext);
973   } else {
974     NaClFatalInst("No room for opcode modrm rm extension");
975   }
976 }
977
978 void NaClDefOpcodeRegisterValue(int r) {
979   uint8_t byte_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]");
984   }
985   if (NACL_EMPTY_IFLAGS ==
986       (current_inst->flags & NACL_IFLAG(OpcodePlusR))) {
987     NaClFatalInst(
988         "Attempted to define opcode register value when not OpcodePlusR");
989   }
990   NaClSetOpcodePlusR(byte_r, &current_inst->opcode_ext);
991 }
992
993 /* Same as previous function, except that sanity checks
994  * are applied to see if inconsistent information is
995  * being defined.
996  */
997 void NaClDefOp(
998     NaClOpKind kind,
999     NaClOpFlags flags) {
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.
1010    */
1011   switch (kind) {
1012     case M_Operand:
1013     case Mb_Operand:
1014     case Mw_Operand:
1015     case Mv_Operand:
1016     case Mo_Operand:
1017     case Mdq_Operand:
1018     case Mpw_Operand:
1019     case Mpv_Operand:
1020     case Mpo_Operand:
1021       NaClAddIFlags(NACL_IFLAG(OpcodeUsesModRm) | NACL_IFLAG(ModRmModIsnt0x3));
1022       break;
1023     case Mmx_N_Operand:
1024       kind = Mmx_E_Operand;
1025       NaClAddIFlags(NACL_IFLAG(OpcodeUsesModRm) | NACL_IFLAG(ModRmModIs0x3));
1026       /* Automatically fall to the next case. */
1027     case E_Operand:
1028     case Eb_Operand:
1029     case Ew_Operand:
1030     case Ev_Operand:
1031     case Eo_Operand:
1032     case Edq_Operand:
1033     case G_Operand:
1034     case Gb_Operand:
1035     case Gw_Operand:
1036     case Gv_Operand:
1037     case Go_Operand:
1038     case Gdq_Operand:
1039     case Mmx_G_Operand:
1040     case Mmx_Gd_Operand:
1041     case Xmm_E_Operand:
1042     case Xmm_Eo_Operand:
1043     case Xmm_G_Operand:
1044     case Xmm_Go_Operand:
1045       NaClAddIFlags(NACL_IFLAG(OpcodeUsesModRm));
1046       break;
1047     default:
1048       break;
1049   }
1050   /* Define and apply sanity checks. */
1051   NaClDefOpInternal(kind, flags);
1052   NaClApplySanityChecksToOp(index);
1053 }
1054
1055 void NaClAddOpFlags(uint8_t operand_index, NaClOpFlags more_flags) {
1056   DEBUG(
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);
1063   } else {
1064     NaClFatalOp((int) operand_index, "NaClAddOpFlags: index out of range\n");
1065   }
1066 }
1067
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);
1074   } else {
1075     NaClFatalOp((int) operand_index, "NaClRemoveOpFlags: index out of range\n");
1076   }
1077 }
1078
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 =
1084         strdup(format);
1085   } else {
1086     NaClFatalOp((int) operand_index, "NaClAddOpFormat: index out of range\n");
1087   }
1088 }
1089
1090 /* Returns true if the given opcode flags are consistent
1091  * with the value of NACL_FLAGS_run_mode.
1092  */
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");
1097     }
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;
1103   } else {
1104     return TRUE;
1105   }
1106 }
1107
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");
1115   }
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));
1120   }
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)))) {
1127     NaClFatalInst(
1128         "Can't specify other operand sizes when specifying OperandSize_b");
1129   }
1130   if ((current_inst->flags & NACL_IFLAG(OpcodeInModRm)) &&
1131       (current_inst->flags & NACL_IFLAG(OpcodePlusR))) {
1132     NaClFatalInst(
1133         "Can't specify both OpcodeInModRm and OpcodePlusR");
1134   }
1135   if ((current_inst->flags & NACL_IFLAG(OpcodeHasImmed_b)) &&
1136       (operand_sizes == NACL_IFLAG(OperandSize_b))) {
1137     NaClFatalInst(
1138         "Size implied by OperandSize_b, use OpcodeHasImmed "
1139         "rather than OpcodeHasImmed_b");
1140   }
1141   if ((current_inst->flags & NACL_IFLAG(OpcodeHasImmed_w)) &&
1142       (operand_sizes == NACL_IFLAG(OperandSize_w))) {
1143     NaClFatalInst(
1144         "Size implied by OperandSize_w, use OpcodeHasImmed "
1145         "rather than OpcodeHasImmed_w");
1146   }
1147   if ((current_inst->flags & NACL_IFLAG(OpcodeHasImmed_v)) &&
1148       (operand_sizes == NACL_IFLAG(OperandSize_v))) {
1149     NaClFatalInst(
1150         "Size implied by OperandSize_v, use OpcodeHasImmed "
1151         "rather than OpcodeHasImmed_v");
1152   }
1153   if ((current_inst->flags & NACL_IFLAG(ModRmModIs0x3)) &&
1154       (NACL_EMPTY_IFLAGS == (current_inst->flags &
1155                              (NACL_IFLAG(OpcodeUsesModRm) |
1156                               NACL_IFLAG(OpcodeInModRm))))) {
1157     NaClFatalInst(
1158         "Can't specify ModRmModIs0x3 unless Opcode has modrm byte");
1159   }
1160   if ((current_inst->flags & NACL_IFLAG(ModRmModIs0x3)) &&
1161       (current_inst->flags & NACL_IFLAG(ModRmModIsnt0x3))) {
1162     NaClFatalInst(
1163         "Can't specify ModRmModIs0x3 and ModRmModIsnt0x3");
1164   }
1165 }
1166
1167 static void NaClDefBytes(uint8_t opcode) {
1168   uint8_t index;
1169   current_inst->prefix = current_opcode_prefix;
1170
1171   /* Start by clearing all entries. */
1172   for (index = 0; index < NACL_MAX_ALL_OPCODE_BYTES; ++index) {
1173     current_inst->opcode[index] = 0x00;
1174   }
1175
1176   /* Now fill in non-final bytes. */
1177   index = 0;
1178   switch (current_opcode_prefix) {
1179     case NoPrefix:
1180       break;
1181     case Prefix0F:
1182     case Prefix660F:
1183     case PrefixF20F:
1184     case PrefixF30F:
1185       current_inst->opcode[0] = 0x0F;
1186       index = 1;
1187       break;
1188     case Prefix0F0F:
1189       current_inst->opcode[0] = 0x0F;
1190       current_inst->opcode[1] = 0x0F;
1191       index = 2;
1192       break;
1193     case Prefix0F38:
1194     case Prefix660F38:
1195     case PrefixF20F38:
1196       current_inst->opcode[0] = 0x0F;
1197       current_inst->opcode[1] = 0x38;
1198       index = 2;
1199       break;
1200     case Prefix0F3A:
1201     case Prefix660F3A:
1202       current_inst->opcode[0] = 0x0F;
1203       current_inst->opcode[1] = 0x3A;
1204       index = 2;
1205       break;
1206     case PrefixD8:
1207       current_inst->opcode[0] = 0xD8;
1208       index = 1;
1209       break;
1210     case PrefixD9:
1211       current_inst->opcode[0] = 0xD9;
1212       index = 1;
1213       break;
1214     case PrefixDA:
1215       current_inst->opcode[0] = 0xDA;
1216       index = 1;
1217       break;
1218     case PrefixDB:
1219       current_inst->opcode[0] = 0xDB;
1220       index = 1;
1221       break;
1222     case PrefixDC:
1223       current_inst->opcode[0] = 0xDC;
1224       index = 1;
1225       break;
1226     case PrefixDD:
1227       current_inst->opcode[0] = 0xDD;
1228       index = 1;
1229       break;
1230     case PrefixDE:
1231       current_inst->opcode[0] = 0xDE;
1232       index = 1;
1233       break;
1234     case PrefixDF:
1235       current_inst->opcode[0] = 0xDF;
1236       index = 1;
1237       break;
1238     default:
1239       NaClFatal("Unrecognized opcode prefix in NaClDefBytes");
1240       break;
1241   }
1242
1243   /* Now add final byte. */
1244   current_inst->opcode[index] = opcode;
1245   current_inst->num_opcode_bytes = index + 1;
1246 }
1247
1248 static void NaClPrintInstDescriptor(struct Gio* out,
1249                                     const NaClInstPrefix prefix,
1250                                     const int opcode,
1251                                     const int modrm_index) {
1252   if (NACL_NO_MODRM_OPCODE == modrm_index) {
1253     gprintf(out, "%s 0x%02x: ",
1254             NaClInstPrefixName(prefix), opcode);
1255   } else {
1256     gprintf(out, "%s 0x%02x /%x: ",
1257             NaClInstPrefixName(prefix), opcode, modrm_index);
1258   }
1259 }
1260
1261 static void VerifyModRmOpcodeRange(NaClInstPrefix prefix,
1262                                    uint8_t opcode,
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");
1267   }
1268 }
1269
1270 void NaClDefPrefixInstMrmChoices_32_64(const NaClInstPrefix prefix,
1271                                        const uint8_t opcode,
1272                                        const uint8_t modrm_opcode,
1273                                        const int count_32,
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");
1280   }
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;
1285   }
1286 }
1287
1288 void NaClDefPrefixInstChoices(const NaClInstPrefix prefix,
1289                               const uint8_t opcode,
1290                               const int count) {
1291   NaClDefPrefixInstChoices_32_64(prefix, opcode, count, count);
1292 }
1293
1294 void NaClDefPrefixInstMrmChoices(const NaClInstPrefix prefix,
1295                                  const uint8_t opcode,
1296                                  const uint8_t modrm_opcode,
1297                                  const int count) {
1298   NaClDefPrefixInstMrmChoices_32_64(prefix, opcode, modrm_opcode,
1299                                          count, count);
1300 }
1301
1302 void NaClDefPrefixInstChoices_32_64(const NaClInstPrefix prefix,
1303                                     const uint8_t opcode,
1304                                     const int count_32,
1305                                     const int count_64) {
1306   NaClDefPrefixInstMrmChoices_32_64(prefix, opcode, NACL_NO_MODRM_OPCODE,
1307                                     count_32, count_64);
1308 }
1309
1310 /* Adds opcode flags corresponding to REP/REPNE flags if defined by
1311  * the prefix.
1312  */
1313 static void NaClAddRepPrefixFlagsIfApplicable(void) {
1314   switch (current_opcode_prefix) {
1315     case Prefix660F:
1316     case Prefix660F38:
1317     case Prefix660F3A:
1318       NaClAddBits(current_inst->flags, NACL_IFLAG(OpcodeAllowsData16) |
1319                   NACL_IFLAG(SizeIgnoresData16));
1320       break;
1321     case PrefixF20F:
1322     case PrefixF20F38:
1323       NaClAddBits(current_inst->flags, NACL_IFLAG(OpcodeAllowsRepne));
1324       break;
1325     case PrefixF30F:
1326       NaClAddBits(current_inst->flags, NACL_IFLAG(OpcodeAllowsRep));
1327       break;
1328     default:
1329       break;
1330   }
1331 }
1332
1333 /* Define the next opcode (instruction), initializing with
1334  * no operands.
1335  */
1336 static void NaClDefInstInternal(
1337     const uint8_t opcode,
1338     const NaClInstType insttype,
1339     NaClIFlags flags,
1340     const NaClMnemonic name,
1341     Bool no_install) {
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.
1347    */
1348
1349   /* Before starting, install an opcode sequence if applicable. */
1350   if (NULL != current_cand_inst_node) {
1351     current_inst_node = current_cand_inst_node;
1352   }
1353   current_cand_inst_node = NULL;
1354
1355   /* Before starting, expand appropriate implicit flag assumnptions. */
1356   if (flags & NACL_IFLAG(OpcodeLtC0InModRm)) {
1357     NaClAddBits(flags, NACL_IFLAG(OpcodeInModRm) | NACL_IFLAG(ModRmModIsnt0x3));
1358   }
1359
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));
1364
1365   if (NaClMnemonicEnumSize <= name) {
1366     NaClFatal("Badly defined mnemonic name");
1367   }
1368
1369   if (kNaClInstTypeRange <= insttype) {
1370     NaClFatal("Badly defined inst type");
1371   }
1372
1373   /* Create opcode and initialize */
1374   current_inst_mrm = (NaClMrmInst*) malloc(sizeof(NaClMrmInst));
1375   if (NULL == current_inst_mrm) {
1376     NaClFatal("NaClDefInst: malloc failed");
1377   }
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;
1388
1389   /* undefine all operands. */
1390   current_inst->num_operands = 0;
1391   current_inst->operands = tables.operands + tables.operands_size;
1392
1393   NaClAddIFlags(flags);
1394
1395   NaClAddRepPrefixFlagsIfApplicable();
1396
1397   NaClApplySanityChecksToInst();
1398
1399   if (no_install || !NaClIFlagsMatchesRunMode(flags)) {
1400     return;
1401   }
1402
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;
1408     } else {
1409       NaClModeledInst* next = tables.inst_table[opcode][current_opcode_prefix];
1410       while (NULL != next->next_rule) {
1411         next = next->next_rule;
1412       }
1413       next->next_rule = current_inst;
1414     }
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;
1421   } else {
1422     NaClFatalInst(
1423         "Can't define more than one opcode for the same opcode sequence");
1424   }
1425 }
1426
1427 void NaClDefInst(
1428     const uint8_t opcode,
1429     const NaClInstType insttype,
1430     NaClIFlags flags,
1431     const NaClMnemonic name) {
1432   NaClDefInstInternal(opcode, insttype, flags, name, FALSE);
1433 }
1434
1435 /* Simple (fast hack) routine to extract a byte value from a character string.
1436  */
1437 static int NaClExtractByte(const char* chars, const char* opcode_seq) {
1438   char buffer[3];
1439   int i;
1440   for (i = 0; i < 2; ++i) {
1441     char ch = *(chars++);
1442     if ('\0' == ch) {
1443       NaClLog(LOG_ERROR,
1444               "Odd number of characters in opcode sequence: '%s'\n",
1445               opcode_seq);
1446       NaClFatal("Fix before continuing!");
1447     }
1448     buffer[i] = ch;
1449   }
1450   buffer[2] = '\0';
1451   return strtoul(buffer, NULL, 16);
1452 }
1453
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;
1460   root->fail = NULL;
1461   return root;
1462 }
1463
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.
1468    */
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.
1472    */
1473   NaClModeledInstNode* last = NULL;
1474   /* Index is the position of the next byte in the opcode sequence. */
1475   int index = 0;
1476
1477   /* First check that opcode sequence not defined twice without a corresponding
1478    * call to NaClDefInst.
1479    */
1480   if (NULL != current_cand_inst_node) {
1481     NaClLog(LOG_ERROR,
1482             "Multiple definitions for opcode sequence: '%s'\n", opcode_seq);
1483     NaClFatal("Fix before continuing!");
1484   }
1485
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) {
1490       NaClLog(LOG_ERROR,
1491               "Too many bytes specified for opcode sequence: '%s'\n",
1492               opcode_seq);
1493       NaClFatal("Fix before continuing!\n");
1494     }
1495     if ((NULL == *next) || (byte < (*next)->matching_byte)) {
1496       /* byte not in trie, add. */
1497       NaClModeledInstNode* node = NaClNewInstNode(byte);
1498       node->fail = *next;
1499       *next = node;
1500     }
1501     if (byte == (*next)->matching_byte) {
1502       last = *next;
1503       next = &((*next)->success);
1504       index += 2;
1505     } else {
1506       next = &((*next)->fail);
1507     }
1508   }
1509   /* Last points to matching node, make it candidate instruction. */
1510   current_cand_inst_node = last;
1511 }
1512
1513 /* Apply checks to current instruction flags, and update model as
1514  * appropriate.
1515  */
1516 static void NaClRecheckIFlags(void) {
1517   if (!NaClIFlagsMatchesRunMode(current_inst->flags)) {
1518     NaClRemoveCurrentInstMrmFromInstTable();
1519     NaClRemoveCurrentInstMrmFromInstMrmTable();
1520   }
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));
1524   }
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));
1530   }
1531   /* If the instruction uses the modrm rm field as an opcode value,
1532    * it also requires that the modrm mod field is 0x3.
1533    */
1534   if (current_inst->flags & NACL_IFLAG(OpcodeInModRmRm)) {
1535     NaClAddBits(current_inst->flags, NACL_IFLAG(ModRmModIs0x3));
1536   }
1537   NaClApplySanityChecksToInst();
1538 }
1539
1540 void NaClAddIFlags(NaClIFlags more_flags) {
1541   DEBUG(
1542       struct Gio* g = NaClLogGetGio();
1543       NaClLog(LOG_INFO, "Adding instruction flags: ");
1544       NaClIFlagsPrint(g, more_flags);
1545       gprintf(g, "\n"));
1546   NaClAddBits(current_inst->flags, more_flags);
1547   NaClRecheckIFlags();
1548 }
1549
1550 void NaClRemoveIFlags(NaClIFlags less_flags) {
1551   DEBUG(
1552       struct Gio* g = NaClLogGetGio();
1553       NaClLog(LOG_INFO, "Removing instruction flags: ");
1554       NaClIFlagsPrint(g, less_flags);
1555       gprintf(g, "\n"));
1556   NaClRemoveBits(current_inst->flags, less_flags);
1557   NaClRecheckIFlags();
1558 }
1559
1560 void NaClDelaySanityChecks(void) {
1561   apply_sanity_checks = FALSE;
1562 }
1563
1564 void NaClApplySanityChecks(void) {
1565   apply_sanity_checks = TRUE;
1566   if (NULL != current_inst) {
1567     int i;
1568     NaClApplySanityChecksToInst();
1569     for (i = 0; i < current_inst->num_operands; i++) {
1570       NaClApplySanityChecksToOp(i);
1571     }
1572   }
1573 }
1574
1575 static void NaClInitInstTables(void) {
1576   int i;
1577   NaClInstPrefix prefix;
1578   int j;
1579   /* Before starting, verify that we have defined NaClOpcodeFlags
1580    * and NaClOpFlags big enough to hold the flags associated with it.
1581    */
1582   assert(NaClIFlagEnumSize <= sizeof(NaClIFlags) * 8);
1583   assert(NaClOpFlagEnumSize <= sizeof(NaClOpFlags) * 8);
1584   assert(NaClDisallowsFlagEnumSize <= sizeof(NaClDisallowsFlags) * 8);
1585
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;
1591       }
1592     }
1593     NaClPrefixTable[i] = "0";
1594   }
1595   NaClDefInstPrefix(NoPrefix);
1596   NaClDefInstInternal(0x0, NACLi_INVALID, 0, InstInvalid, TRUE);
1597   tables.undefined_inst = current_inst;
1598 }
1599
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");
1612
1613   if (NACL_FLAGS_run_mode == X86_64) {
1614     int i;
1615     for (i = 0; i < 16; ++i) {
1616       NaClEncodePrefixName(0x40+i, "kPrefixREX");
1617     }
1618   }
1619 }
1620
1621 /* Define the given character sequence, associated with the given byte
1622  * opcode and instruction mnemonic, as a nop.
1623  */
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);
1628 }
1629
1630 /* Define the given character sequence, associated with the given byte
1631  * opcode, as a nop.
1632  */
1633 static void NaClDefNopSeq(const char* sequence, uint8_t opcode) {
1634   NaClDefNopLikeSeq(sequence, opcode, InstNop);
1635 }
1636
1637 static void NaClDefNops(void) {
1638   /* Note: The following could be recognized as nops, but are already
1639    * parsed and accepted by the validator.
1640    *
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]
1648    * 0f 1f 00                                     nop
1649    * 0f 1f 40 00                                  nop
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
1653    */
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.
1660    */
1661   /* nop */
1662   NaClDefNopSeq("90", 0x90);
1663   NaClDefNopSeq("6690", 0x90);
1664   NaClDefNopLikeSeq("f390", 0x90, InstPause);
1665   /* nop [%[re]ax] */
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);
1691   /* UD2 */
1692   NaClDefNopLikeSeq("0f0b", 0x0b, InstUd2);
1693 }
1694
1695 /* Build the set of x64 opcode (instructions). */
1696 static void NaClBuildInstTables(void) {
1697   struct NaClSymbolTable* st = NaClSymbolTableCreate(5, NULL);
1698
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);
1706
1707   NaClInitInstTables();
1708   NaClDefPrefixBytes();
1709   NaClDefOneByteInsts(st);
1710   NaClDef0FInsts(st);
1711   NaClDefSseInsts(st);
1712   NaClDefX87Insts(st);
1713   NaClDefNops();
1714
1715   NaClSymbolTableDestroy(st);
1716 }
1717
1718 static int NaClInstMrmListLength(NaClMrmInst* next) {
1719   int count = 0;
1720   while (NULL != next) {
1721     ++count;
1722     next = next->next;
1723   }
1724   return count;
1725 }
1726
1727 static void NaClFatalChoiceCount(const int expected,
1728                                  const int found,
1729                                  const NaClInstPrefix prefix,
1730                                  const int opcode,
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;
1739   }
1740   NaClFatal("fix before continuing...\n");
1741 }
1742
1743 /* Verify that the number of possible choies for each prefix:opcode matches
1744  * what was explicitly defined.
1745  */
1746 static void NaClVerifyInstCounts(void) {
1747   int i, j;
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) {
1756           if (found > 1) {
1757             NaClFatalChoiceCount(1, found, prefix, i, j, insts);
1758           }
1759         } else if (expected != found) {
1760           NaClFatalChoiceCount(expected, found, prefix, i, j, insts);
1761         }
1762       }
1763     }
1764   }
1765 }
1766
1767 /* Removes X86-32 specific flags from the given instruction. */
1768 static void NaClInstRemove32Stuff(NaClModeledInst* inst) {
1769   NaClRemoveBits(inst->flags, NACL_IFLAG(Opcode32Only));
1770 }
1771
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));
1783 }
1784
1785 /* Simplifies the instructions if possible. Mostly removes flags that
1786  * don't correspond to the run mode.
1787  */
1788 static void NaClSimplifyIfApplicable(void) {
1789   int i;
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);
1797         }
1798         if (X86_32 != NACL_FLAGS_run_mode) {
1799           NaClInstRemove32Stuff(next);
1800         }
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;
1805       }
1806     }
1807   }
1808 }
1809
1810 /* Prints out the set of defined instruction flags. */
1811 static void NaClIFlagsPrintInternal(struct Gio* f, NaClIFlags flags) {
1812   if (flags) {
1813     int i;
1814     Bool first = TRUE;
1815     for (i = 0; i < NaClIFlagEnumSize; ++i) {
1816       if (flags & NACL_IFLAG(i)) {
1817         if (first) {
1818           first = FALSE;
1819         } else {
1820           gprintf(f, " | ");
1821         }
1822         gprintf(f, "NACL_IFLAG(%s)", NaClIFlagName(i));
1823       }
1824     }
1825   } else {
1826     gprintf(f, "NACL_EMPTY_IFLAGS");
1827   }
1828 }
1829
1830 /* Prints out the set of defined Operand flags. */
1831 static void NaClOpFlagsPrintInternal(struct Gio* f, NaClOpFlags flags) {
1832   if (flags) {
1833     NaClOpFlag i;
1834     Bool first = TRUE;
1835     for (i = 0; i < NaClOpFlagEnumSize; ++i) {
1836       if (flags & NACL_OPFLAG(i)) {
1837         if (first) {
1838           first = FALSE;
1839         } else {
1840           gprintf(f, " | ");
1841         }
1842         gprintf(f, "NACL_OPFLAG(%s)", NaClOpFlagName(i));
1843       }
1844     }
1845   } else {
1846     gprintf(f, "NACL_EMPTY_OPFLAGS");
1847   }
1848 }
1849
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);
1854   gprintf(f, ", ");
1855   if (NULL == operand->format_string) {
1856     gprintf(f, "NULL");
1857   } else {
1858     gprintf(f, "\"%s\"", operand->format_string);
1859   }
1860   gprintf(f, " },\n");
1861 }
1862
1863 /* Converts the (compressed) operand to the corresponding
1864  * index in tables.ops_compressed.
1865  */
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
1869    * generator.
1870    */
1871   size_t i;
1872   for (i = 0; i <= tables.ops_compressed_size; ++i) {
1873     if (op == (tables.ops_compressed + i)) return i;
1874   }
1875   /* If reached, we have a bug! */
1876   NaClFatal("Can't find offset for operand");
1877   /* NOT REACHED */
1878   return 0;
1879 }
1880
1881 static void NaClPrintInstIndex(struct Gio* f,
1882                                size_t index) {
1883   if (NACL_OPCODE_NULL_OFFSET == index) {
1884     gprintf(f, "NACL_OPCODE_NULL_OFFSET");
1885   } else {
1886     gprintf(f, "%d", index);
1887   }
1888 }
1889
1890 /* Print out the given opcode offset value corresponding to the
1891  * given instruction.
1892  */
1893 static void NaClPrintInstOffset(struct Gio* f,
1894                                 const NaClModeledInst* inst) {
1895   NaClPrintInstIndex(f, NaClFindInstIndex(&tables, inst));
1896 }
1897
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.
1904  */
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));
1909   gprintf(f, "    ");
1910   NaClIFlagsPrintInternal(f, inst->flags);
1911   gprintf(f, ",\n");
1912   gprintf(f, "    Inst%s, 0x%02x, ", NaClMnemonicName(inst->name),
1913           inst->opcode_ext);
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 ? ',' : ';');
1918 }
1919
1920 /* Generate header information, based on the executable name in argv0,
1921  * and the file to be generated (defined by fname).
1922  */
1923 static void NaClPrintHeader(struct Gio* f, const char* argv0,
1924                             const char* fname) {
1925   gprintf(f, "/*\n");
1926   gprintf(f, " * THIS FILE IS AUTO-GENERATED. DO NOT EDIT.\n");
1927   gprintf(f, " * Compiled for %s.\n", NaClRunModeName(NACL_FLAGS_run_mode));
1928   gprintf(f, " *\n");
1929   gprintf(f, " * You must include ncopcode_desc.h before this file.\n");
1930   gprintf(f, " */\n\n");
1931 }
1932
1933 /* Print out which bytes correspond to prefix bytes. */
1934 static void NaClPrintPrefixTable(struct Gio* f) {
1935   int opc;
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);
1940     }
1941     gprintf(f, "%s, ", NaClPrefixTable[opc]);
1942   }
1943   gprintf(f, "\n};\n\n");
1944 }
1945
1946 static int NaClCountInstNodes(const NaClModeledInstNode* root) {
1947   if (NULL == root) {
1948     return 0;
1949   } else {
1950     int count = 1;
1951     count += NaClCountInstNodes(root->success);
1952     count += NaClCountInstNodes(root->fail);
1953     return count;
1954   }
1955 }
1956
1957 static void NaClPrintInstTrieEdge(const NaClModeledInstNode* edge,
1958                                   int* edge_index,
1959                                   struct Gio* f) {
1960   gprintf(f, "    ");
1961   if (NULL == edge) {
1962     gprintf(f, "NULL");
1963   }
1964   else {
1965     gprintf(f, "g_OpcodeSeq + %d", *edge_index);
1966     *edge_index += NaClCountInstNodes(edge);
1967   }
1968   gprintf(f, ",\n");
1969 }
1970
1971 static void NaClPrintInstTrieNode(const NaClModeledInstNode* root,
1972                                   int root_index, struct Gio* f) {
1973   if (NULL == root) {
1974     return;
1975   } else {
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);
1980     gprintf(f, ",\n");
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);
1988   }
1989 }
1990
1991 /* Prints out the contents of the opcode sequence overrides into the
1992  * given file.
1993  */
1994 static void NaClPrintInstSeqTrie(const NaClModeledInstNode* root,
1995                                  struct Gio* f) {
1996   /* Make sure trie isn't empty, since empty arrays create warning messages. */
1997   int num_trie_nodes;
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);
2002   gprintf(f, "};\n");
2003 }
2004
2005 /* Prints out the array of (compressed) operands. */
2006 static void NaClPrintOperandTable(struct Gio* f) {
2007   size_t i;
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);
2013   }
2014   gprintf(f, "};\n\n");
2015 }
2016
2017 static const size_t NaClOffsetsPerLine = 10;
2018
2019 /* Print out instruction table. */
2020 static void NaClPrintInstTable(struct Gio* f) {
2021   size_t i;
2022   gprintf(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);
2028   }
2029   gprintf(f, "};\n\n");
2030 }
2031
2032 /* Print lookup table of rules, based on prefix and opcode byte. */
2033 static void NaClPrintLookupTable(struct Gio* f) {
2034   size_t i;
2035   NaClInstPrefix prefix;
2036
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);
2042     }
2043     NaClPrintInstIndex(f, tables.opcode_lookup[i]);
2044     gprintf(f, ", ");
2045   }
2046   gprintf(f, "};\n\n");
2047
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]);
2056   }
2057   gprintf(f, "};\n\n");
2058 }
2059
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);
2067 }
2068
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) {
2072   int i;
2073   for (i = 0; i < length; ++i) {
2074     if (i > 0) gprintf(f, " ");
2075     gprintf(f, "%02x", inst_sequence[i]);
2076   }
2077 }
2078
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.
2083  */
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;
2089   ++length;
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");
2096   }
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);
2102     gprintf(f, "\n");
2103   }
2104   PrintHardCodedInstructionsNode(f, node->success, inst_sequence, length);
2105   PrintHardCodedInstructionsNode(f, node->fail, inst_sequence, length-1);
2106 }
2107
2108 /* Walks over specifically encoded instruction trie, and prints
2109  * out corresponding implemented instructions.
2110  */
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);
2114 }
2115
2116 /* Prints out documentation on the modeled instruction set. */
2117 static void NaClPrintInstructionSet(struct Gio* f) {
2118   NaClInstPrefix prefix;
2119   int i;
2120   gprintf(f, "*** Automatically generated file, do not edit! ***\n");
2121   gprintf(f, "\n");
2122   gprintf(f, "Target: %s\n", NaClRunModeName(NACL_FLAGS_run_mode));
2123   gprintf(f, "\n");
2124   gprintf(f, "*** Hard coded instructions ***\n");
2125   gprintf(f, "\n");
2126   NaClPrintHardCodedInstructions(f);
2127
2128   for (prefix = NoPrefix; prefix < NaClInstPrefixEnumSize;  ++prefix) {
2129     Bool printed_rules = FALSE;
2130     gprintf(f, "*** %s ***\n", NaClInstPrefixName(prefix));
2131     gprintf(f, "\n");
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) {
2136         if (is_first) {
2137           gprintf(f, "  --- %02x ---\n", i);
2138           is_first = FALSE;
2139         }
2140         NaClModeledInstPrint(f, inst);
2141         printed_rules = TRUE;
2142         inst = inst->next_rule;
2143       }
2144     }
2145     if (printed_rules) gprintf(f, "\n");
2146   }
2147 }
2148
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");
2155   }
2156 }
2157
2158 /* Recognizes flags in argv, processes them, and then removes them.
2159  * Returns the updated value for argc.
2160  */
2161 static int NaClGrokFlags(int argc, const char* argv[]) {
2162   int i;
2163   int new_argc;
2164   if (argc == 0) return 0;
2165   new_argc = 1;
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)) {
2177       continue;
2178     } else {
2179       argv[new_argc++] = argv[i];
2180     }
2181   }
2182   return new_argc;
2183 }
2184
2185 static void GenerateTables(struct Gio* f, const char* cmd,
2186                            const char* filename) {
2187   if (NACL_FLAGS_human_readable) {
2188     NaClPrintInstructionSet(f);
2189   } else {
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);
2195       } else {
2196         NaClPrintGpRegisterIndexes_32(f);
2197       }
2198     } else {
2199       NaClPrintDecodeTables(f);
2200     }
2201   }
2202 }
2203
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.
2207  */
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);
2215 }
2216
2217 /* Define the operands description field of each modeled
2218  * opcode instruction, if it hasn't explicitly been defined.
2219  */
2220 static void FillInMissingOperandsDescs(void) {
2221   int i;
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;
2229       }
2230     }
2231   }
2232   FillInTrieMissingOperandsDescs(tables.inst_node_root);
2233 }
2234
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;
2242 }
2243
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)) {
2251     fprintf(stderr,
2252             "ERROR: usage: ncdecode_tablegen <architecture_flag> "
2253             "[-documentation | -validator_decoder -nacl_subregs] [file]\n");
2254     return -1;
2255   }
2256   InitTables();
2257   NaClLogModuleInit();
2258   NaClBuildInstTables();
2259   NaClSimplifyIfApplicable();
2260   NaClVerifyInstCounts();
2261   FillInMissingOperandsDescs();
2262
2263   if (NACL_FLAGS_validator_decoder)
2264     NaClNcvalInstSimplify(&tables);
2265
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.
2271    */
2272   if (!NACL_FLAGS_human_readable) {
2273     NaClOpCompress(&tables);
2274   }
2275
2276   if (new_argc == 1) {
2277     GioFileRefCtor(&gfile, stdout);
2278     GenerateTables(g, argv[0], "<stdout>");
2279   } else {
2280     NaClMustOpen(&gfile, argv[1], "w");
2281     GenerateTables(g, argv[0], argv[1]);
2282   }
2283   NaClLogModuleFini();
2284   GioFileDtor(g);
2285   return 0;
2286 }