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

Side by Side Diff: src/trusted/validator/x86/decoder/generator/ncdecode_tablegen.c

Issue 625923004: Delete old x86 validator. (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: rebase master Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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_tab legen.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_dis allows.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_for ms.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_simpli fy.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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698