Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / native_client / src / trusted / validator / x86 / decoder / generator / modeled_nacl_inst.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 #define NEEDSNACLINSTTYPESTRING
8
9 #include "native_client/src/trusted/validator/x86/decoder/generator/modeled_nacl_inst.h"
10
11 #include <string.h>
12
13 void NaClSetOpcodeInModRm(uint8_t value, uint8_t *opcode_ext) {
14   *opcode_ext += value;
15 }
16
17 void NaClSetOpcodeInModRmRm(uint8_t value, uint8_t *opcode_ext) {
18   *opcode_ext += (value << 4);
19 }
20
21 void NaClSetOpcodePlusR(uint8_t value, uint8_t *opcode_ext) {
22   *opcode_ext += value;
23 }
24
25 /* Print the flag name if the flag is defined for the corresponding operand.
26  * Used to print out set/use/zero extend information for partial instructions.
27  */
28 static void NaClPrintAddOperandFlag(struct Gio* f,
29                                     const NaClOp* op,
30                                     NaClOpFlag flag,
31                                     const char* flag_name) {
32   if (op->flags & NACL_OPFLAG(flag)) {
33     gprintf(f, "%s", flag_name);
34   }
35 }
36
37 void NaClModeledInstPrint(struct Gio* f, const NaClModeledInst* inst) {
38   int i;
39   int count = 2;
40   /* Add prefix bytes if defined by prefix. */
41   const char* prefix = OpcodePrefixBytes(inst->prefix);
42   int prefix_len = (int) strlen(prefix);
43   gprintf(f, "  %s", prefix);
44   if (prefix_len > 0) {
45     count += prefix_len + 1;
46     gprintf(f, " ");
47   }
48
49   /* Add opcode bytes. */
50   for (i = 0; i < inst->num_opcode_bytes; ++i) {
51     if (i > 0) {
52       gprintf(f, " ");
53       ++count;
54     }
55     gprintf(f,"%02x", inst->opcode[i]);
56     count += 2;
57   }
58   if (inst->flags & NACL_IFLAG(OpcodeInModRm)) {
59     gprintf(f, " / %d", NaClGetOpcodeInModRm(inst->opcode_ext));
60     count += 4;
61   } else if (inst->flags & NACL_IFLAG(OpcodePlusR)) {
62     gprintf(f, " - r%d", NaClGetOpcodePlusR(inst->opcode_ext));
63     count += 5;
64   }
65   if (inst->flags & NACL_IFLAG(OpcodeInModRmRm)) {
66     gprintf(f, " / %d", NaClGetOpcodeInModRmRm(inst->opcode_ext));
67     count += 4;
68   }
69   while (count < 30) {
70     gprintf(f, " ");
71     ++count;
72   }
73   { /* Print out instruction type less the NACLi_ prefix. */
74     const char* name = NaClInstTypeString(inst->insttype);
75     gprintf(f, "%s ", name + strlen("NACLi_"));
76   }
77   if (inst->flags) NaClIFlagsPrint(f, inst->flags);
78   gprintf(f, "\n");
79
80   /* If instruction type is invalid, and doesn't have
81    * special translation purposes, then don't print additional
82    * (ignored) information stored in the modeled instruction.
83    */
84   if ((NACLi_INVALID != inst->insttype) ||
85       ((inst->flags & NACL_IFLAG(Opcode0F0F)))) {
86     Bool is_first = TRUE;
87     int i;
88     gprintf(f, "    ");
89
90     /* Instruction has been simplified. Print out corresponding
91      * hints to the reader, so that they know that the instruction
92      * has been simplified.
93      */
94     if (NaClHasBit(inst->flags, NACL_IFLAG(PartialInstruction))) {
95       gprintf(f, "[P] ");
96     }
97     gprintf(f, "%s", NaClMnemonicName(inst->name));
98
99     /* If an instruction has been simplified, and it illegal, communicate
100      * that in the printed modeled instruction.
101      */
102     if (NaClHasBit(inst->flags, NACL_IFLAG(NaClIllegal)) &&
103         NaClHasBit(inst->flags, NACL_IFLAG(PartialInstruction))) {
104       gprintf(f, "(illegal)");
105     }
106     for (i = 0; i < inst->num_operands; ++i) {
107       if (NULL == inst->operands[i].format_string) continue;
108       if (is_first) {
109         is_first = FALSE;
110       } else {
111         gprintf(f, ",");
112       }
113       gprintf(f, " %s", inst->operands[i].format_string);
114
115       /* If this is a partial instruction, add set/use information
116        * so that that it is more clear what was matched.
117        */
118       if (NaClHasBit(inst->flags, NACL_IFLAG(PartialInstruction))) {
119         const NaClOp* op = inst->operands + i;
120         if (NaClHasBit(op->flags, (NACL_OPFLAG(OpSet) |
121                                    NACL_OPFLAG(OpUse) |
122                                    NACL_OPFLAG(OperandZeroExtends_v)))) {
123           gprintf(f, " (");
124           NaClPrintAddOperandFlag(f, op, OpSet, "s");
125           NaClPrintAddOperandFlag(f, op, OpUse, "u");
126           NaClPrintAddOperandFlag(f, op, OperandZeroExtends_v, "z");
127           gprintf(f, ")");
128         }
129       }
130     }
131     gprintf(f, "\n");
132     /* Now print actual encoding of each operand. */
133     for (i = 0; i < inst->num_operands; ++i) {
134       gprintf(f, "      ");
135       NaClOpPrint(f, inst->operands + i);
136     }
137   }
138 }