OLD | NEW |
| (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 #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 } | |
OLD | NEW |