OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2012 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 * Set of predefined instruction forms (via procedure calls), providing | |
9 * a more concise way of specifying opcodes. | |
10 */ | |
11 | |
12 #ifndef NACL_TRUSTED_BUT_NOT_TCB | |
13 #error("This file is not meant for use in the TCB") | |
14 #endif | |
15 | |
16 #include "native_client/src/trusted/validator/x86/decoder/generator/ncdecode_for
ms.h" | |
17 | |
18 #include <assert.h> | |
19 #include <ctype.h> | |
20 | |
21 #include "native_client/src/include/nacl_macros.h" | |
22 #include "native_client/src/include/portability_io.h" | |
23 #include "native_client/src/include/portability_string.h" | |
24 #include "native_client/src/include/nacl_macros.h" | |
25 #include "native_client/src/shared/platform/nacl_log.h" | |
26 #include "native_client/src/trusted/validator/x86/decoder/generator/defsize64.h" | |
27 #include "native_client/src/trusted/validator/x86/decoder/generator/lock_insts.h
" | |
28 #include "native_client/src/trusted/validator/x86/decoder/generator/long_mode.h" | |
29 #include "native_client/src/trusted/validator/x86/decoder/generator/nacl_illegal
.h" | |
30 #include "native_client/src/trusted/validator/x86/decoder/generator/nc_def_jumps
.h" | |
31 #include "native_client/src/trusted/validator/x86/decoder/generator/nc_rep_prefi
x.h" | |
32 #include "native_client/src/trusted/validator/x86/decoder/generator/ncdecode_st.
h" | |
33 #include "native_client/src/trusted/validator/x86/decoder/generator/ncdecode_tab
legen.h" | |
34 #include "native_client/src/trusted/validator/x86/decoder/generator/zero_extends
.h" | |
35 | |
36 /* To turn on debugging of instruction decoding, change value of | |
37 * DEBUGGING to 1. | |
38 */ | |
39 #define DEBUGGING 0 | |
40 | |
41 #include "native_client/src/shared/utils/debugging.h" | |
42 | |
43 /* Returns the name for the given enumerated value. */ | |
44 static const char* NaClInstCatName(NaClInstCat cat) { | |
45 int i; | |
46 static struct { | |
47 NaClInstCat cat; | |
48 const char* name; | |
49 } cat_desc[] = { | |
50 { UnarySet , "UnarySet" }, | |
51 { UnaryUpdate , "UnaryUpdate" }, | |
52 { Move , "Move" }, | |
53 { O2Move, "O2Move" }, | |
54 { Binary , "Binary" }, | |
55 { O2Binary , "O2Binary" }, | |
56 { Nary , "Nary" }, | |
57 { O1Nary, "O1Nary"}, | |
58 { O3Nary, "O3Nary"}, | |
59 { Compare , "Compare"}, | |
60 { Exchange, "Exchange" }, | |
61 { Push, "Push" }, | |
62 { Pop, "Pop" }, | |
63 { Call, "Call"}, | |
64 { SysCall, "SysCall"}, | |
65 { SysJump, "SysJump"}, | |
66 { Return, "Return"}, | |
67 { SysRet, "SysRet"}, | |
68 { Jump, "Jump" }, | |
69 { Uses, "Uses" }, | |
70 { Sets, "Sets" }, | |
71 { Lea, "Lea" }, | |
72 { Cpuid, "Cpuid" }, | |
73 { Other, "Other" }, | |
74 }; | |
75 for (i = 0; i < NACL_ARRAY_SIZE(cat_desc); ++i) { | |
76 if (cat == cat_desc[i].cat) return cat_desc[i].name; | |
77 } | |
78 /* Shouldn't be reached!! */ | |
79 NaClFatal("Unrecognized category"); | |
80 /* NOT REACHED */ | |
81 return "Unspecified"; | |
82 } | |
83 | |
84 /* Returns the OpSet and OpUse operand flags for the destination | |
85 * argument of the instruction, given the category of instruction. Argument | |
86 * num_ops is the number of operands the instruction has. | |
87 */ | |
88 static NaClOpFlags NaClGetArg1Flags(NaClInstCat icat, int num_ops) { | |
89 DEBUG(NaClLog(LOG_INFO, "NaClGetArg1Flags(%s)\n", NaClInstCatName(icat))); | |
90 switch (icat) { | |
91 case Move: | |
92 case O2Move: | |
93 case O1Nary: | |
94 case O3Nary: | |
95 case Lea: | |
96 case UnarySet: | |
97 case Sets: | |
98 case O2Binary: | |
99 case Jump: | |
100 case Return: | |
101 case SysRet: | |
102 case SysJump: | |
103 case Cpuid: | |
104 return NACL_OPFLAG(OpSet); | |
105 case Nary: | |
106 case Exchange: | |
107 case Call: | |
108 case SysCall: | |
109 case UnaryUpdate: | |
110 case Push: | |
111 case Pop: | |
112 return NACL_OPFLAG(OpSet) | NACL_OPFLAG(OpUse); | |
113 case Binary: | |
114 if (3 == num_ops) { | |
115 return NACL_OPFLAG(OpSet); | |
116 } else { | |
117 return NACL_OPFLAG(OpSet) | NACL_OPFLAG(OpUse); | |
118 } | |
119 case Compare: | |
120 case Uses: | |
121 return NACL_OPFLAG(OpUse); | |
122 case Other: | |
123 return NACL_EMPTY_OPFLAGS; | |
124 break; | |
125 default: | |
126 NaClFatal("NaClGetArg1Flags: unrecognized category"); | |
127 /* NOT REACHED */ | |
128 return NACL_EMPTY_OPFLAGS; | |
129 } | |
130 } | |
131 | |
132 /* Returns the OpSet, OpUse, and OpDest operand flags for the source argument(s) | |
133 * of an instruction, given the category of instruction. | |
134 * | |
135 * Argument visible_index is the (1-based) index of the operand for which flags | |
136 * are being defined. A value of zero implies the argument is not visible. | |
137 * | |
138 * Argument op_index is the actual index of the operand in the | |
139 * instruction being modeled. | |
140 */ | |
141 static NaClOpFlags NaClGetArg2PlusFlags(NaClInstCat icat, | |
142 int visible_index, | |
143 int op_index) { | |
144 DEBUG(NaClLog(LOG_INFO, "NaClGetArgsPlusFlags(%s, %d)\n", | |
145 NaClInstCatName(icat), visible_index)); | |
146 switch (icat) { | |
147 case UnarySet: | |
148 case UnaryUpdate: | |
149 NaClLog(LOG_INFO, "icat = %s\n", NaClInstCatName(icat)); | |
150 NaClFatal("Illegal to use unary categorization for binary operation"); | |
151 /* NOT REACHED */ | |
152 return NACL_EMPTY_OPFLAGS; | |
153 case Call: | |
154 case Return: | |
155 case O2Binary: | |
156 if (2 == op_index) { | |
157 return NACL_OPFLAG(OpSet) | NACL_OPFLAG(OpUse); | |
158 } else { | |
159 return NACL_OPFLAG(OpUse); | |
160 } | |
161 case O3Nary: | |
162 if (op_index <= 3) { | |
163 return NACL_OPFLAG(OpSet); | |
164 } else { | |
165 return NACL_OPFLAG(OpUse); | |
166 } | |
167 case Move: | |
168 case Binary: | |
169 case Push: | |
170 case Jump: | |
171 case Uses: | |
172 case SysRet: | |
173 case Compare: | |
174 case Nary: | |
175 case O1Nary: | |
176 return NACL_OPFLAG(OpUse); | |
177 case O2Move: | |
178 if ((2 == op_index)) { | |
179 return NACL_OPFLAG(OpSet); | |
180 } else { | |
181 return NACL_OPFLAG(OpUse); | |
182 } | |
183 case Exchange: | |
184 if (op_index == 2) { | |
185 /* The second argument is always both a set and a use. */ | |
186 if (visible_index == 2) { | |
187 return NACL_OPFLAG(OpSet) | NACL_OPFLAG(OpUse); | |
188 } else { | |
189 return NACL_OPFLAG(OpSet) | NACL_OPFLAG(OpUse); | |
190 } | |
191 } else if (op_index == 3) { | |
192 /* If it has a 3rd argument, it is like a cmpxchg. */ | |
193 if (visible_index == 1) { | |
194 return NACL_OPFLAG(OpSet) | NACL_OPFLAG(OpUse); | |
195 } else { | |
196 return NACL_OPFLAG(OpSet) | NACL_OPFLAG(OpUse); | |
197 } | |
198 } else { | |
199 return NACL_OPFLAG(OpUse); | |
200 } | |
201 case Pop: | |
202 case SysCall: | |
203 case Sets: | |
204 return NACL_OPFLAG(OpSet); | |
205 case SysJump: | |
206 if (op_index <= 4) { | |
207 return NACL_OPFLAG(OpSet); | |
208 } else { | |
209 return NACL_OPFLAG(OpUse); | |
210 } | |
211 case Lea: | |
212 case Other: | |
213 return NACL_EMPTY_OPFLAGS; | |
214 case Cpuid: | |
215 if (op_index <= 2) { | |
216 return NACL_OPFLAG(OpSet); | |
217 } else { | |
218 return NACL_OPFLAG(OpSet) | NACL_OPFLAG(OpUse); | |
219 } | |
220 default: | |
221 NaClFatal("NaClGetArg2PlusFlags: unrecognized category"); | |
222 /* NOT REACHED */ | |
223 return NACL_EMPTY_OPFLAGS; | |
224 } | |
225 } | |
226 | |
227 /* Returns the OpSet and OpUse operand flags for the operand | |
228 * with the given operand_index (1-based) argument for the instruction, | |
229 * | |
230 * Argument icat is the instruction category of the instruction being | |
231 * modeled. | |
232 * | |
233 * Argument visible_index is the (1-based) index of the operand for which flags | |
234 * are being defined. A value of zero implies the argument is not visible. | |
235 * | |
236 * Argument op_index is the actual index of the operand in the | |
237 * instruction being modeled. | |
238 * | |
239 * Argument num_ops is the number of operands the instruction has (base 1). | |
240 */ | |
241 static NaClOpFlags NaClGetIcatFlags(NaClInstCat icat, | |
242 int operand_index, | |
243 int visible_count, | |
244 int num_ops) { | |
245 NaClOpFlags flags = NACL_EMPTY_OPFLAGS; | |
246 DEBUG(NaClLog(LOG_INFO, "NaClGetIcatFlags(%s, %d, %d)\n", | |
247 NaClInstCatName(icat), operand_index, visible_count)); | |
248 if (operand_index == 1) { | |
249 flags = NaClGetArg1Flags(icat, num_ops); | |
250 } else { | |
251 flags = NaClGetArg2PlusFlags(icat, visible_count, operand_index); | |
252 } | |
253 return flags; | |
254 } | |
255 | |
256 /* Add miscellaneous flags defined elsewhere. */ | |
257 static void NaClAddMiscellaneousFlags(void) { | |
258 DEBUG(NaClLog(LOG_INFO, "-> Adding Miscellaneous Flags\n")); | |
259 NaClAddZeroExtend32FlagIfApplicable(); | |
260 NaClLockableFlagIfApplicable(); | |
261 NaClAddSizeDefaultIs64(); | |
262 NaClAddLongModeIfApplicable(); | |
263 NaClAddNaClIllegalIfApplicable(); | |
264 NaClAddRepPrefixFlagsIfApplicable(); | |
265 NaClAddJumpFlagsIfApplicable(); | |
266 DEBUG(NaClLog(LOG_INFO, "<- Adding Miscellaneous Flags\n")); | |
267 } | |
268 | |
269 /* Adds OpSet/OpUse flags to operands to the current instruction, | |
270 * based on the given instruction categorization. | |
271 */ | |
272 static void NaClSetInstCat(NaClInstCat icat) { | |
273 int operand_index = 0; /* note: this is one-based. */ | |
274 int visible_count = 0; | |
275 int i; | |
276 int num_ops; | |
277 NaClModeledInst* inst = NaClGetDefInst(); | |
278 num_ops = inst->num_operands; | |
279 for (i = 0; i < num_ops; ++i) { | |
280 Bool is_visible = FALSE; | |
281 ++operand_index; | |
282 if (NACL_EMPTY_OPFLAGS == | |
283 (inst->operands[i].flags & NACL_OPFLAG(OpImplicit))) { | |
284 is_visible = TRUE; | |
285 ++visible_count; | |
286 } | |
287 NaClAddOpFlags(i, NaClGetIcatFlags( | |
288 icat, operand_index, (is_visible ? visible_count : 0), num_ops)); | |
289 } | |
290 /* Do special fixup for binary case with 3 arguments. In such | |
291 * cases, the first argument is only a set, rather than a set/use. | |
292 */ | |
293 if ((Binary == icat) && (3 == num_ops)) { | |
294 NaClRemoveOpFlags(0, NACL_OPFLAG(OpUse)); | |
295 } | |
296 NaClAddMiscellaneousFlags(); | |
297 } | |
298 | |
299 /* Returns true if opcode sequence value is a SL (slash) | |
300 * value. | |
301 */ | |
302 static Bool IsSLValue(int16_t val) { | |
303 return val < 0; | |
304 } | |
305 | |
306 /* Returns the opcode denoted by a SL (slash) value. */ | |
307 static uint8_t SLOpcode(int16_t val) { | |
308 return (uint8_t) ((0 - val) - 1); | |
309 } | |
310 | |
311 /* Returns true if any prefix byte values, which need | |
312 * to be considered part of the opcode sequence, is defined | |
313 * by the given instruction. If prefix byte(s) are matched, | |
314 * prefix_count is incremented by the number of bytes matched. | |
315 * | |
316 * Parameters are: | |
317 * prefix_count - Variable to update on number of matched prefix | |
318 * bytes. | |
319 * inst - The instruction we are matching the opcode sequence against. | |
320 * name_and_opcode_seq - The opcode sequence descriptor we are trying | |
321 * to match. | |
322 */ | |
323 static Bool NaClNameOpcodeSeqMatchesPrefixByte( | |
324 int* prefix_count, | |
325 NaClModeledInst* inst, | |
326 const NaClNameOpcodeSeq* name_and_opcode_seq, | |
327 int index) { | |
328 int16_t prefix; | |
329 switch (inst->prefix) { | |
330 case PrefixF20F: | |
331 case PrefixF20F38: | |
332 prefix = PR(0xF2); | |
333 break; | |
334 case PrefixF30F: | |
335 prefix = PR(0xF3); | |
336 break; | |
337 case Prefix660F: | |
338 case Prefix660F38: | |
339 case Prefix660F3A: | |
340 prefix = PR(0x66); | |
341 break; | |
342 default: | |
343 return TRUE; | |
344 } | |
345 if (prefix == name_and_opcode_seq[index].opcode_seq[0]) { | |
346 ++(*prefix_count); | |
347 return TRUE; | |
348 } else { | |
349 return FALSE; | |
350 } | |
351 } | |
352 | |
353 Bool NaClInInstructionSet(const NaClMnemonic* names, | |
354 size_t names_size, | |
355 const NaClNameOpcodeSeq* name_and_opcode_seq, | |
356 size_t name_and_opcode_seq_size) { | |
357 size_t i; | |
358 NaClModeledInst* inst = NaClGetDefInst(); | |
359 | |
360 /* First handle cases where all instances of an instruction | |
361 * mnemonic is in the set. | |
362 */ | |
363 for (i = 0; i < names_size; ++i) { | |
364 if (inst->name == names[i]) { | |
365 return TRUE; | |
366 } | |
367 } | |
368 | |
369 /* How handle cases where only a specific opcode sequence of | |
370 * an instruction mnemonic applies. | |
371 */ | |
372 for (i = 0; i < name_and_opcode_seq_size; ++i) { | |
373 if (inst->name == name_and_opcode_seq[i].name) { | |
374 int j; | |
375 int prefix_count = 0; | |
376 Bool is_good = TRUE; | |
377 Bool matched_slash = FALSE; | |
378 /* First compare opcode bytes. */ | |
379 if (NaClNameOpcodeSeqMatchesPrefixByte( | |
380 &prefix_count, inst, name_and_opcode_seq, (int) i)) { | |
381 for (j = 0; j < inst->num_opcode_bytes; ++j) { | |
382 if (inst->opcode[j] != | |
383 name_and_opcode_seq[i].opcode_seq[prefix_count + j]) { | |
384 is_good = FALSE; | |
385 break; | |
386 } | |
387 } | |
388 } else { | |
389 is_good = FALSE; | |
390 } | |
391 if (is_good) { | |
392 /* Now compare any values that must by in modrm. */ | |
393 for (j = prefix_count + inst->num_opcode_bytes; | |
394 j < NACL_OPCODE_SEQ_SIZE; ++j) { | |
395 int16_t val = name_and_opcode_seq[i].opcode_seq[j]; | |
396 if (END_OPCODE_SEQ == val) { | |
397 /* At end of descriptor. See if instruction defines an opcode | |
398 * in the ModRm byte. If so, make sure that we matched the slash. | |
399 */ | |
400 if (inst->flags & NACL_IFLAG(OpcodeInModRm)) { | |
401 return matched_slash; | |
402 } else { | |
403 /* At end of descriptor, matched! */ | |
404 return TRUE; | |
405 } | |
406 } | |
407 if (IsSLValue(val)) { | |
408 if ((inst->flags & NACL_IFLAG(OpcodeInModRm)) && | |
409 (SLOpcode(val) == NaClGetOpcodeInModRm(inst->opcode_ext))) { | |
410 /* good, continue search. */ | |
411 matched_slash = TRUE; | |
412 } else { | |
413 is_good = FALSE; | |
414 break; | |
415 } | |
416 } | |
417 } | |
418 if (is_good) { | |
419 return TRUE; | |
420 } | |
421 } | |
422 } | |
423 } | |
424 /* If reached, couldn't match, so not in instruction set. */ | |
425 return FALSE; | |
426 } | |
427 | |
428 static void NaClOperandForm_Ap(void) { | |
429 NaClDefOp(A_Operand, NACL_OPFLAG(OperandFar) | NACL_OPFLAG(OperandRelative)); | |
430 NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OpcodeHasImmed_p)); | |
431 } | |
432 | |
433 static void NaClOperandForm_CdSlq(void) { | |
434 /* Note: For Cd/q, we don't worry about the size of the | |
435 * control registers for NaCl. Hence, for now, we ignore the | |
436 * size constraint | |
437 */ | |
438 NaClDefOp(C_Operand, NACL_EMPTY_OPFLAGS); | |
439 } | |
440 | |
441 static void NaClOperandForm_DdSlq(void) { | |
442 /* Note: For Dd/q, we don't worry about the size of the | |
443 * debug register for NaCl. Hence, for now, we ignore the | |
444 * size constraint. | |
445 */ | |
446 NaClDefOp(D_Operand, NACL_EMPTY_OPFLAGS); | |
447 } | |
448 | |
449 static void NaClOperandForm_Eb(void) { | |
450 /* For Eb, we must worry about earlier arguments, which in some cases, | |
451 * have already specified valid effective operand sizes. If so, we must make | |
452 * the size of the this operand be byte specific. If size hasn't been | |
453 * specified yet, we go ahead and assume the effective operand size of the | |
454 * instructruction as being a byte. | |
455 */ | |
456 NaClModeledInst* inst = NaClGetDefInst(); | |
457 if (inst->flags & (NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) | | |
458 NACL_IFLAG(OperandSize_o))) { | |
459 NaClDefOp(Eb_Operand, NACL_EMPTY_OPFLAGS); | |
460 } else { | |
461 NaClDefOp(E_Operand, NACL_EMPTY_OPFLAGS); | |
462 NaClAddIFlags(NACL_IFLAG(OperandSize_b)); | |
463 } | |
464 } | |
465 | |
466 static void NaClOperandForm_Ed(void) { | |
467 NaClDefOp(Ev_Operand, NACL_EMPTY_OPFLAGS); | |
468 } | |
469 | |
470 static void NaClOperandForm_EdSlq(void) { | |
471 /* Note: For Ed/q we assume that only sizes d (32) and q (64) are possible. | |
472 * Hence, we don't allow a data 66 prefix effect the size. | |
473 */ | |
474 NaClDefOp(E_Operand, NACL_EMPTY_OPFLAGS); | |
475 NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSize_o) | | |
476 NACL_IFLAG(SizeIgnoresData16)); | |
477 } | |
478 | |
479 static void NaClOperandForm_EdSlqSld(void) { | |
480 /* Ed/q/d is used for Ed/q when operand size is 32 bits (vs 64 bits). | |
481 * Note: For Ed/q we assume that only sizes d (32) and q (64) are possible. | |
482 * Hence, we don't allow a data 66 prefix effect the size. | |
483 */ | |
484 NaClDefOp(E_Operand, NACL_EMPTY_OPFLAGS); | |
485 NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(SizeIgnoresData16)); | |
486 } | |
487 | |
488 static void NaClOperandForm_EdSlqSlq(void) { | |
489 /* Ed/q/q is used for Ed/q when operand size is 64 bits (vs 32 bits). | |
490 * Note: For Ed/q we assume that only sizes d (32) and q (64) are possible. | |
491 * Hence, we don't allow a data 66 prefix effect the size. | |
492 */ | |
493 NaClDefOp(E_Operand, NACL_EMPTY_OPFLAGS); | |
494 NaClAddIFlags(NACL_IFLAG(OperandSize_o) | NACL_IFLAG(SizeIgnoresData16)); | |
495 } | |
496 | |
497 static void NaClOperandForm_Ev(void) { | |
498 NaClDefOp(E_Operand, NACL_EMPTY_OPFLAGS); | |
499 NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) | | |
500 NACL_IFLAG(OperandSize_o)); | |
501 } | |
502 | |
503 static void NaClOperandForm_Ew(void) { | |
504 NaClDefOp(Ew_Operand, NACL_EMPTY_OPFLAGS); | |
505 } | |
506 | |
507 static void NaClOperandForm_Fvw(void) { | |
508 NaClDefOp(RegRFLAGS, NACL_EMPTY_OPFLAGS); | |
509 NaClAddIFlags(NACL_IFLAG(OperandSize_w)); | |
510 } | |
511 | |
512 static void NaClOperandForm_Fvd(void) { | |
513 NaClDefOp(RegRFLAGS, NACL_EMPTY_OPFLAGS); | |
514 NaClAddIFlags(NACL_IFLAG(OperandSize_v)); | |
515 } | |
516 | |
517 static void NaClOperandForm_Fvq(void) { | |
518 NaClDefOp(RegRFLAGS, NACL_EMPTY_OPFLAGS); | |
519 NaClAddIFlags(NACL_IFLAG(OperandSize_o)); | |
520 } | |
521 | |
522 static void NaClOperandForm_Gb(void) { | |
523 NaClDefOp(G_Operand, NACL_EMPTY_OPFLAGS); | |
524 NaClAddIFlags(NACL_IFLAG(OperandSize_b)); | |
525 } | |
526 | |
527 static void NaClOperandForm_Gd(void) { | |
528 NaClDefOp(Gv_Operand, NACL_EMPTY_OPFLAGS); | |
529 } | |
530 | |
531 static void NaClOperandForm_GdQ(void) { | |
532 /* Note: For Gd/q we assume that only sizes d (32) and q (64) are possible. | |
533 * Hence, we don't allow a data 66 prefix effect the size. | |
534 */ | |
535 NaClDefOp(G_Operand, NACL_EMPTY_OPFLAGS); | |
536 NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSize_o) | | |
537 NACL_IFLAG(SizeIgnoresData16)); | |
538 } | |
539 | |
540 static void NaClOperandForm_Gq(void) { | |
541 NaClDefOp(Go_Operand, NACL_EMPTY_OPFLAGS); | |
542 } | |
543 | |
544 static void NaClOperandForm_Gv(void) { | |
545 NaClDefOp(G_Operand, NACL_EMPTY_OPFLAGS); | |
546 NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) | | |
547 NACL_IFLAG(OperandSize_o)); | |
548 } | |
549 | |
550 static void NaClOperandForm_Gw(void) { | |
551 NaClDefOp(Gw_Operand, NACL_EMPTY_OPFLAGS); | |
552 } | |
553 | |
554 static void NaClOperandForm_Ib(void) { | |
555 int i; | |
556 NaClModeledInst* inst = NaClGetDefInst(); | |
557 /* First look to see if 1st or 2nd instance of an immediate value, | |
558 * since different opcode flags that must be used are different. | |
559 */ | |
560 for (i = 0; i < inst->num_operands; ++i) { | |
561 if (I_Operand == inst->operands[i].kind) { | |
562 /* Second instance!. */ | |
563 NaClDefOp(I2_Operand, NACL_EMPTY_OPFLAGS); | |
564 NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed2_b)); | |
565 return; | |
566 } | |
567 } | |
568 /* First instance of Ib. */ | |
569 NaClDefOp(I_Operand, NACL_EMPTY_OPFLAGS); | |
570 if (inst->flags & NACL_IFLAG(OperandSize_b)) { | |
571 NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed)); | |
572 } else { | |
573 NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed_b)); | |
574 } | |
575 } | |
576 | |
577 static void NaClOperandForm_I2b(void) { | |
578 NaClDefOp(I2_Operand, NACL_EMPTY_OPFLAGS); | |
579 NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed2_b)); | |
580 } | |
581 | |
582 static void NaClOperandForm_Iv(void) { | |
583 NaClDefOp(I_Operand, NACL_EMPTY_OPFLAGS); | |
584 NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed) | NACL_IFLAG(OperandSize_w) | | |
585 NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSize_o)); | |
586 } | |
587 | |
588 static void NaClOperandForm_Iw(void) { | |
589 NaClDefOp(I_Operand, NACL_EMPTY_OPFLAGS); | |
590 NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed_w)); | |
591 } | |
592 | |
593 static void NaClOperandForm_Iz(void) { | |
594 NaClDefOp(I_Operand, NACL_EMPTY_OPFLAGS); | |
595 NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed_z)); | |
596 } | |
597 | |
598 static void NaClOperandForm_Jb(void) { | |
599 NaClDefOp(J_Operand, | |
600 NACL_OPFLAG(OperandRelative) | NACL_OPFLAG(OperandNear)); | |
601 NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed) | NACL_IFLAG(OperandSize_b)); | |
602 } | |
603 | |
604 /* Installs Jz, except for size constraints. Assumes immediate value | |
605 * follows z (size) conventions, unless the argument implies to define | |
606 * immediate sizes based on v. | |
607 */ | |
608 static void DefOperandJzBaseUseImmedV(Bool use_immed_v) { | |
609 NaClDefOp(J_Operand, | |
610 NACL_OPFLAG(OperandRelative) | NACL_OPFLAG(OperandNear)); | |
611 if (use_immed_v) { | |
612 NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed_v)); | |
613 } else { | |
614 NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed_z)); | |
615 } | |
616 } | |
617 | |
618 /* Installs Jz where immediate value is based on z size. */ | |
619 static void DefOperandJzBase(void) { | |
620 /* Note: when in 32-bit mode, the relative offset can be a 16 or 32 bit | |
621 * immediate offset, depending on the operand size. When in 64-bit mode, | |
622 * the relative offset is ALWAYS a 32-bit immediate value (see page | |
623 * 76 for CALL of AMD manual (document 24594-Rev.3.14-September 2007, | |
624 * "AMD64 Architecture Programmer's manual Volume 3: General-Purpose | |
625 * and System Instructions"). | |
626 */ | |
627 DefOperandJzBaseUseImmedV(X86_64 == NACL_FLAGS_run_mode); | |
628 } | |
629 | |
630 static void NaClOperandForm_Jz(void) { | |
631 DefOperandJzBase(); | |
632 NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) | | |
633 NACL_IFLAG(OperandSize_o)); | |
634 } | |
635 | |
636 static void NaClOperandForm_Jzd(void) { | |
637 DefOperandJzBaseUseImmedV(TRUE); | |
638 NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSize_o)); | |
639 } | |
640 | |
641 static void NaClOperandForm_Jzw(void) { | |
642 DefOperandJzBase(); | |
643 NaClAddIFlags(NACL_IFLAG(OperandSize_w)); | |
644 /* Note: Special case 64-bit with 66 prefix, which is not supported on | |
645 * some Intel Chips (See Call/Jcc instructions in Intel document | |
646 * 253666-030US - March 2009, "Intel 654 and IA-32 Architectures | |
647 * Software Developer's Manual, Volume2A"). | |
648 */ | |
649 if (X86_64 == NACL_FLAGS_run_mode) { | |
650 NaClAddIFlags(NACL_IFLAG(NaClIllegal)); | |
651 } | |
652 } | |
653 | |
654 static void NaClOperandForm_M(void) { | |
655 NaClDefOp(M_Operand, NACL_EMPTY_OPFLAGS); | |
656 NaClAddIFlags(NACL_IFLAG(OpcodeAllowsData16)); | |
657 } | |
658 | |
659 static void NaClOperandForm_Ma(void) { | |
660 NaClDefOp(M_Operand, NACL_EMPTY_OPFLAGS); | |
661 NaClDefOp(M_Operand, NACL_EMPTY_OPFLAGS); | |
662 NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v)); | |
663 } | |
664 | |
665 static void NaClOperandForm_Mb(void) { | |
666 NaClDefOp(Mb_Operand, NACL_EMPTY_OPFLAGS); | |
667 } | |
668 | |
669 static void NaClOperandForm_Md(void) { | |
670 NaClDefOp(Mv_Operand, NACL_EMPTY_OPFLAGS); | |
671 } | |
672 | |
673 static void NaClOperandForm_Mdq(void) { | |
674 NaClDefOp(Mdq_Operand, NACL_EMPTY_OPFLAGS); | |
675 } | |
676 | |
677 static void NaClOperandForm_Mf(void) { | |
678 NaClDefOp(M_Operand, NACL_EMPTY_OPFLAGS); | |
679 } | |
680 | |
681 static void NaClOperandForm_MdSlq(void) { | |
682 /* Note: For Ed/q we assume that only sizes d (32) and q (64) are possible. | |
683 * Hence, we don't allow a data 66 prefix effect the size. | |
684 */ | |
685 NaClDefOp(M_Operand, NACL_EMPTY_OPFLAGS); | |
686 NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSize_o) | | |
687 NACL_IFLAG(SizeIgnoresData16)); | |
688 } | |
689 | |
690 static void NaClOperandForm_Mp(void) { | |
691 /* TODO(karl) fix measurement size. */ | |
692 NaClDefOp(M_Operand, NACL_OPFLAG(OperandFar)); | |
693 } | |
694 | |
695 static void NaClOperandForm_Ms(void) { | |
696 /* TODO(karl): fix size of data accessed in memory. */ | |
697 NaClDefOp(M_Operand, NACL_EMPTY_OPFLAGS); | |
698 } | |
699 | |
700 static void NaClOperandForm_Mq(void) { | |
701 NaClDefOp(Mo_Operand, NACL_EMPTY_OPFLAGS); | |
702 } | |
703 | |
704 static void NaClOperandForm_Mv(void) { | |
705 NaClDefOp(M_Operand, NACL_EMPTY_OPFLAGS); | |
706 NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) | | |
707 NACL_IFLAG(OperandSize_o)); | |
708 } | |
709 | |
710 static void NaClOperandForm_Mw(void) { | |
711 NaClDefOp(Mw_Operand, NACL_EMPTY_OPFLAGS); | |
712 } | |
713 | |
714 static void NaClOperandForm_MwSlRv(void) { | |
715 /* TODO(karl) Verify that Mw/Rv as same as Ev? */ | |
716 NaClOperandForm_Ev(); | |
717 } | |
718 | |
719 static void NaClOperandForm_Ob(void) { | |
720 NaClDefOp(O_Operand, NACL_EMPTY_OPFLAGS); | |
721 NaClAddIFlags(NACL_IFLAG(OperandSize_b) | NACL_IFLAG(OpcodeHasImmed_Addr)); | |
722 } | |
723 | |
724 static void NaClOperandForm_Ov(void) { | |
725 NaClDefOp(O_Operand, NACL_EMPTY_OPFLAGS); | |
726 NaClAddIFlags(NACL_IFLAG(OpcodeHasImmed_Addr) | NACL_IFLAG(OperandSize_w) | | |
727 NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSize_o)); | |
728 } | |
729 | |
730 | |
731 static void NaClOperandForm_One(void) { | |
732 NaClDefOp(Const_1, NACL_EMPTY_OPFLAGS); | |
733 } | |
734 | |
735 static void NaClOperandForm_PdSlq(void) { | |
736 /* Note: For Pd/q we assume that only sizes d (32) and q (64) are possible. | |
737 * Hence, we don't allow a data 66 prefix effect the size. | |
738 */ | |
739 NaClDefOp(Mmx_G_Operand, NACL_EMPTY_OPFLAGS); | |
740 NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSize_o) | | |
741 NACL_IFLAG(SizeIgnoresData16)); | |
742 } | |
743 | |
744 static void NaClOperandForm_PdSlqSld(void) { | |
745 /* Pd/q/d is used for Pd/q when operand size is 32 bits (vs 64 bits). | |
746 * Note: For Pd/q we assume that only sizes d (32) and q (64) are possible. | |
747 * Hence, we don't allow a data 66 prefix effect the size. | |
748 */ | |
749 NaClDefOp(Mmx_G_Operand, NACL_EMPTY_OPFLAGS); | |
750 NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(SizeIgnoresData16)); | |
751 } | |
752 | |
753 static void NaClOperandForm_PdSlqSlq(void) { | |
754 /* Pd/q/q is used for Pd/q when operand size is 64 bits (vs 32 bits). | |
755 * Note: For Pd/q we assume that only sizes d (32) and q (64) are possible. | |
756 * Hence, we don't allow a data 66 prefix effect the size. | |
757 */ | |
758 NaClDefOp(Mmx_G_Operand, NACL_EMPTY_OPFLAGS); | |
759 NaClAddIFlags(NACL_IFLAG(OperandSize_o) | NACL_IFLAG(SizeIgnoresData16)); | |
760 } | |
761 | |
762 static void NaClOperandForm_Pq(void) { | |
763 /* TODO(karl) Add q size restriction. */ | |
764 NaClDefOp(Mmx_G_Operand, NACL_EMPTY_OPFLAGS); | |
765 } | |
766 | |
767 static void NaClOperandForm_PRq(void) { | |
768 /* Note: We ignore sizes for Mmx operands, since they | |
769 * aren't used to compute memory addresses in NaCl. | |
770 */ | |
771 NaClDefOp(Mmx_N_Operand, NACL_EMPTY_OPFLAGS); | |
772 } | |
773 | |
774 static void NaClOperandForm_Qd(void) { | |
775 /* TODO(karl) add d size restriction. */ | |
776 NaClDefOp(Mmx_E_Operand, NACL_EMPTY_OPFLAGS); | |
777 } | |
778 | |
779 static void NaClOperandForm_Qq(void) { | |
780 /* TODO(karl) add q size restriction. */ | |
781 NaClDefOp(Mmx_E_Operand, NACL_EMPTY_OPFLAGS); | |
782 } | |
783 | |
784 static void NaClOperandForm_Rd(void) { | |
785 NaClDefOp(Ev_Operand, NACL_EMPTY_OPFLAGS); | |
786 NaClAddIFlags(NACL_IFLAG(ModRmModIs0x3)); | |
787 } | |
788 | |
789 static void NaClOperandForm_Rq(void) { | |
790 NaClDefOp(Eo_Operand, NACL_EMPTY_OPFLAGS); | |
791 NaClAddIFlags(NACL_IFLAG(ModRmModIs0x3)); | |
792 } | |
793 | |
794 static void NaClOperandForm_RdSlMb(void) { | |
795 /* Note: For Rd/Mb, we ignore the size on memory, | |
796 * since we don't need to specify sizes on memory. | |
797 */ | |
798 NaClDefOp(Ev_Operand, NACL_EMPTY_OPFLAGS); | |
799 } | |
800 | |
801 static void NaClOperandForm_RdSlMw(void) { | |
802 /* Note: For Rd/Mw, we ignore the size on memory, | |
803 * since we don't need to specify sizes on memory for NaCl. | |
804 */ | |
805 NaClDefOp(Ev_Operand, NACL_EMPTY_OPFLAGS); | |
806 } | |
807 | |
808 static void NaClOperandForm_RdSlq(void) { | |
809 /* Note: It appears that Rd/q opcodes are connected to | |
810 * the architecture size, and only have one choice based | |
811 * on that size. | |
812 */ | |
813 if (X86_32 == NACL_FLAGS_run_mode) { | |
814 NaClOperandForm_Rd(); | |
815 } else { | |
816 NaClOperandForm_Rq(); | |
817 } | |
818 } | |
819 | |
820 static void NaClOperandForm_RdSlqSlMb(void) { | |
821 /* Note: For Rd/q/Mb, we ignore the size on memory, | |
822 * since we don't need to specify sizes on memory for NaCl. | |
823 */ | |
824 NaClOperandForm_EdSlq(); | |
825 } | |
826 | |
827 static void NaClOperandForm_RdSlqSlMw(void) { | |
828 /* Note: For Rd/q/Mw, we ignore the size on memory, | |
829 * since we don't need to specify sizes on memory for NaCl. | |
830 */ | |
831 NaClOperandForm_EdSlq(); | |
832 } | |
833 | |
834 static void NaClOperandForm_rAXv(void) { | |
835 NaClDefOp(RegREAX, NACL_EMPTY_OPFLAGS); | |
836 NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) | | |
837 NACL_IFLAG(OperandSize_o)); | |
838 } | |
839 | |
840 static void NaClOperandForm_rAXva(void) { | |
841 NaClDefOp(RegREAXa, NACL_EMPTY_OPFLAGS); | |
842 } | |
843 | |
844 static void NaClOperandForm_rAXvd(void) { | |
845 NaClDefOp(RegEAX, NACL_EMPTY_OPFLAGS); | |
846 NaClAddIFlags(NACL_IFLAG(OperandSize_v)); | |
847 } | |
848 | |
849 static void NaClOperandForm_rAXvq(void) { | |
850 NaClDefOp(RegRAX, NACL_EMPTY_OPFLAGS); | |
851 NaClAddIFlags(NACL_IFLAG(OperandSize_o)); | |
852 } | |
853 | |
854 static void NaClOperandForm_rAXvw(void) { | |
855 NaClDefOp(RegAX, NACL_EMPTY_OPFLAGS); | |
856 NaClAddIFlags(NACL_IFLAG(OperandSize_w)); | |
857 } | |
858 | |
859 static void NaClOperandForm_rBXv(void) { | |
860 NaClDefOp(RegREBX, NACL_EMPTY_OPFLAGS); | |
861 NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) | | |
862 NACL_IFLAG(OperandSize_o)); | |
863 } | |
864 | |
865 static void NaClOperandForm_rCXv(void) { | |
866 NaClDefOp(RegRECX, NACL_EMPTY_OPFLAGS); | |
867 NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) | | |
868 NACL_IFLAG(OperandSize_o)); | |
869 } | |
870 | |
871 static void NaClOperandForm_rDXv(void) { | |
872 NaClDefOp(RegREDX, NACL_EMPTY_OPFLAGS); | |
873 NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) | | |
874 NACL_IFLAG(OperandSize_o)); | |
875 } | |
876 | |
877 static void NaClOperandForm_rSPv(void) { | |
878 NaClDefOp(RegRESP, NACL_EMPTY_OPFLAGS); | |
879 NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) | | |
880 NACL_IFLAG(OperandSize_o)); | |
881 } | |
882 | |
883 static void NaClOperandForm_rBPv(void) { | |
884 NaClDefOp(RegREBP, NACL_EMPTY_OPFLAGS); | |
885 NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) | | |
886 NACL_IFLAG(OperandSize_o)); | |
887 } | |
888 | |
889 static void NaClOperandForm_rSIv(void) { | |
890 NaClDefOp(RegRESI, NACL_EMPTY_OPFLAGS); | |
891 NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) | | |
892 NACL_IFLAG(OperandSize_o)); | |
893 } | |
894 | |
895 static void NaClOperandForm_rDIv(void) { | |
896 NaClDefOp(RegREDI, NACL_EMPTY_OPFLAGS); | |
897 NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) | | |
898 NACL_IFLAG(OperandSize_o)); | |
899 } | |
900 | |
901 /* Note: The interpretation for r8b is documented in ncdecode_forms.h. That is, | |
902 * r8 - The 8 registers AL, CL, DL, BL, AH, CH, DH, and BH if no REX prefix. | |
903 * with A REX prefix, use the registers AL, CL, DL, BL, SPL, BPL, SIL, | |
904 * DIL, and the optional registers r8-r15 if REX.b is set. Register | |
905 * choice is based on the register value embedded in the opcode. | |
906 */ | |
907 static void NaClOperandForm_r8b(void) { | |
908 NaClDefOp(G_OpcodeBase, NACL_EMPTY_OPFLAGS); | |
909 NaClAddIFlags(NACL_IFLAG(OperandSize_b)); | |
910 } | |
911 | |
912 /* Note: The interpretation for r8v is documented in ncdecode_forms.h. That is, | |
913 * r8 - The 8 registers rAX, rCX, rDX, rBX, rSP, rBP, rSI, rDI, and the | |
914 * optional registers r8-r15 if REX.b is set, based on the register value | |
915 * embedded in the opcode. | |
916 */ | |
917 static void NaClOperandForm_r8v(void) { | |
918 NaClDefOp(G_OpcodeBase, NACL_EMPTY_OPFLAGS); | |
919 NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) | | |
920 NACL_IFLAG(OperandSize_o)); | |
921 } | |
922 | |
923 /* Note: The interpretation for r8vd is documented in ncdecode_forms.h. That is, | |
924 * r8 - The 8 registers rAX, rCX, rDX, rBX, rSP, rBP, rSI, rDI, and the | |
925 * optional registers r8-r15 if REX.b is set, based on the register value | |
926 * embedded in the opcode | |
927 * vd - A doubleword only when the effective operand size matches. | |
928 */ | |
929 static void NaClOperandForm_r8vd(void) { | |
930 NaClDefOp(G_OpcodeBase, NACL_EMPTY_OPFLAGS); | |
931 NaClAddIFlags(NACL_IFLAG(OperandSize_v)); | |
932 } | |
933 | |
934 /* Note: The interpretation for r8vq is documented in ncdecode_forms.h. That is, | |
935 * r8 - The 8 registers rAX, rCX, rDX, rBX, rSP, rBP, rSI, rDI, and the | |
936 * optional registers r8-r15 if REX.b is set, based on the register value | |
937 * embedded in the opcode. | |
938 * vq - A quadword only when the effective operand size matches. | |
939 */ | |
940 static void NaClOperandForm_r8vq(void) { | |
941 NaClDefOp(G_OpcodeBase, NACL_EMPTY_OPFLAGS); | |
942 NaClAddIFlags(NACL_IFLAG(OperandSize_o)); | |
943 } | |
944 | |
945 static void NaClOperandForm_SGz(void) { | |
946 NaClDefOp(Seg_G_Operand, NACL_EMPTY_OPFLAGS); | |
947 NaClAddIFlags(NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) | | |
948 NACL_IFLAG(OperandSize_o)); | |
949 } | |
950 | |
951 static void NaClOperandForm_Sw(void) { | |
952 NaClDefOp(S_Operand, NACL_EMPTY_OPFLAGS); | |
953 NaClAddIFlags(NACL_IFLAG(ModRmRegSOperand)); | |
954 } | |
955 | |
956 static void NaClOperandForm_Udq(void) { | |
957 NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS); | |
958 } | |
959 | |
960 static void NaClOperandForm_UdqMd(void) { | |
961 /* TODO: how to define size, based on register (Udq) or | |
962 * memory (Md). | |
963 */ | |
964 NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS); | |
965 } | |
966 | |
967 static void NaClOperandForm_UdqMq(void) { | |
968 /* TODO: how to define size, based on register (Udq) or | |
969 * memory (Mq). | |
970 */ | |
971 NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS); | |
972 } | |
973 | |
974 static void NaClOperandForm_UdqMw(void) { | |
975 /* TODO: how to define size, based on register (Udq) or | |
976 * memory (Mw). | |
977 */ | |
978 NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS); | |
979 } | |
980 | |
981 static void NaClOperandForm_Vdq(void) { | |
982 /* TODO(karl) Add dq size restriction. */ | |
983 NaClDefOp(Xmm_G_Operand, NACL_EMPTY_OPFLAGS); | |
984 } | |
985 | |
986 static void NaClOperandForm_VdSlq(void) { | |
987 /* Note: For Vd/q we assume that only sizes d (32) and q (64) are possible. | |
988 * Hence, we don't allow a data 66 prefix effect the size. | |
989 */ | |
990 NaClDefOp(Xmm_G_Operand, NACL_EMPTY_OPFLAGS); | |
991 NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSize_o) | | |
992 NACL_IFLAG(SizeIgnoresData16)); | |
993 } | |
994 | |
995 static void NaClOperandForm_VdSlqSld(void) { | |
996 /* Vd/q/d is used for Vd/q when operand size is 32 bits (vs 64 bits). | |
997 * Note: For Vd/q we assume that only sizes d (32) and q (64) are possible. | |
998 * Hence, we don't allow a data 66 prefix effect the size. | |
999 */ | |
1000 NaClDefOp(Xmm_G_Operand, NACL_EMPTY_OPFLAGS); | |
1001 NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(SizeIgnoresData16)); | |
1002 } | |
1003 | |
1004 static void NaClOperandForm_VdSlqSlq(void) { | |
1005 /* Vd/q/q is used for Vd/q when operand size is 64 bits (vs 32 bits). | |
1006 * Note: For Vd/q we assume that only sizes d (32) and q (64) are possible. | |
1007 * Hence, we don't allow a data 66 prefix effect the size. | |
1008 */ | |
1009 NaClDefOp(Xmm_G_Operand, NACL_EMPTY_OPFLAGS); | |
1010 NaClAddIFlags(NACL_IFLAG(OperandSize_o) | NACL_IFLAG(SizeIgnoresData16)); | |
1011 } | |
1012 | |
1013 static void NaClOperandForm_Vpd(void) { | |
1014 NaClDefOp(Xmm_G_Operand, NACL_EMPTY_OPFLAGS); | |
1015 } | |
1016 | |
1017 static void NaClOperandForm_Vps(void) { | |
1018 NaClDefOp(Xmm_G_Operand, NACL_EMPTY_OPFLAGS); | |
1019 } | |
1020 | |
1021 static void NaClOperandForm_Vq(void) { | |
1022 NaClDefOp(Xmm_Go_Operand, NACL_EMPTY_OPFLAGS); | |
1023 } | |
1024 | |
1025 static void NaClOperandForm_Vsd(void) { | |
1026 NaClDefOp(Xmm_G_Operand, NACL_EMPTY_OPFLAGS); | |
1027 } | |
1028 | |
1029 static void NaClOperandForm_Vss(void) { | |
1030 NaClDefOp(Xmm_G_Operand, NACL_EMPTY_OPFLAGS); | |
1031 } | |
1032 | |
1033 static void NaClOperandForm_VRdq(void) { | |
1034 /* Note: We ignore sizes for Mmx operands, since they | |
1035 * aren't used to compute memory addresses in NaCl. | |
1036 */ | |
1037 NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS); | |
1038 NaClAddIFlags(NACL_IFLAG(ModRmModIs0x3)); | |
1039 } | |
1040 | |
1041 static void NaClOperandForm_VRps(void) { | |
1042 /* Note: We ignore sizes for Xmm operands, since they | |
1043 * aren't used to compute memory addresses in NaCl. | |
1044 */ | |
1045 NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS); | |
1046 NaClAddIFlags(NACL_IFLAG(ModRmModIs0x3)); | |
1047 } | |
1048 | |
1049 static void NaClOperandForm_VRq(void) { | |
1050 /* Note: We ignore sizes for Xmm operands, since they | |
1051 * aren't used to compute memory addresses in NaCl. | |
1052 */ | |
1053 NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS); | |
1054 NaClAddIFlags(NACL_IFLAG(ModRmModIs0x3)); | |
1055 } | |
1056 | |
1057 static void NaClOperandForm_VRpd(void) { | |
1058 /* Note: We ignore sizes for Xmm operands, since they | |
1059 * aren't used to compute memory addresses in NaCl. | |
1060 */ | |
1061 NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS); | |
1062 NaClAddIFlags(NACL_IFLAG(ModRmModIs0x3)); | |
1063 } | |
1064 | |
1065 static void NaClOperandForm_Wdq(void) { | |
1066 /* TODO(karl) Add dq size restriction. */ | |
1067 NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS); | |
1068 } | |
1069 | |
1070 static void NaClOperandForm_Wpd(void) { | |
1071 NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS); | |
1072 } | |
1073 | |
1074 static void NaClOperandForm_Wps(void) { | |
1075 NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS); | |
1076 } | |
1077 | |
1078 static void NaClOperandForm_Wq(void) { | |
1079 /* TODO(karl) Add q size restriction. */ | |
1080 NaClDefOp(Xmm_Eo_Operand, NACL_EMPTY_OPFLAGS); | |
1081 } | |
1082 | |
1083 static void NaClOperandForm_Wsd(void) { | |
1084 NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS); | |
1085 } | |
1086 | |
1087 static void NaClOperandForm_Wss(void) { | |
1088 NaClDefOp(Xmm_E_Operand, NACL_EMPTY_OPFLAGS); | |
1089 } | |
1090 | |
1091 static void NaClOperandForm_Xb(void) { | |
1092 NaClDefOp(RegDS_ESI, NACL_EMPTY_OPFLAGS); | |
1093 NaClAddIFlags(NACL_IFLAG(OperandSize_b)); | |
1094 } | |
1095 | |
1096 static void NaClOperandForm_Xvw(void) { | |
1097 NaClDefOp(RegDS_ESI, NACL_EMPTY_OPFLAGS); | |
1098 NaClAddIFlags(NACL_IFLAG(OperandSize_w)); | |
1099 } | |
1100 | |
1101 static void NaClOperandForm_Xvd(void) { | |
1102 NaClDefOp(RegDS_ESI, NACL_EMPTY_OPFLAGS); | |
1103 NaClAddIFlags(NACL_IFLAG(OperandSize_v)); | |
1104 } | |
1105 | |
1106 static void NaClOperandForm_Xvq(void) { | |
1107 NaClDefOp(RegDS_ESI, NACL_EMPTY_OPFLAGS); | |
1108 NaClAddIFlags(NACL_IFLAG(OperandSize_o)); | |
1109 } | |
1110 | |
1111 static void NaClOperandForm_Xzd(void) { | |
1112 NaClDefOp(RegDS_ESI, NACL_EMPTY_OPFLAGS); | |
1113 NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSize_o)); | |
1114 } | |
1115 | |
1116 static void NaClOperandForm_Xzw(void) { | |
1117 NaClDefOp(RegDS_ESI, NACL_EMPTY_OPFLAGS); | |
1118 NaClAddIFlags(NACL_IFLAG(OperandSize_w)); | |
1119 } | |
1120 | |
1121 static void NaClOperandForm_Yb(void) { | |
1122 NaClDefOp(RegES_EDI, NACL_EMPTY_OPFLAGS); | |
1123 NaClAddIFlags(NACL_IFLAG(OperandSize_b)); | |
1124 } | |
1125 | |
1126 static void NaClOperandForm_Yvd(void) { | |
1127 NaClDefOp(RegES_EDI, NACL_EMPTY_OPFLAGS); | |
1128 NaClAddIFlags(NACL_IFLAG(OperandSize_v)); | |
1129 } | |
1130 | |
1131 static void NaClOperandForm_Yvq(void) { | |
1132 NaClDefOp(RegES_EDI, NACL_EMPTY_OPFLAGS); | |
1133 NaClAddIFlags(NACL_IFLAG(OperandSize_o)); | |
1134 } | |
1135 | |
1136 static void NaClOperandForm_Yvw(void) { | |
1137 NaClDefOp(RegES_EDI, NACL_EMPTY_OPFLAGS); | |
1138 NaClAddIFlags(NACL_IFLAG(OperandSize_w)); | |
1139 } | |
1140 | |
1141 static void NaClOperandForm_Yzw(void) { | |
1142 NaClDefOp(RegES_EDI, NACL_EMPTY_OPFLAGS); | |
1143 NaClAddIFlags(NACL_IFLAG(OperandSize_w)); | |
1144 } | |
1145 | |
1146 static void NaClOperandForm_Yzd(void) { | |
1147 NaClDefOp(RegES_EDI, NACL_EMPTY_OPFLAGS); | |
1148 NaClAddIFlags(NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSize_o)); | |
1149 } | |
1150 | |
1151 static void NaClOperandForm_Zvd(void) { | |
1152 NaClDefOp(RegDS_EDI, NACL_EMPTY_OPFLAGS); | |
1153 NaClAddIFlags(NACL_IFLAG(OperandSize_v)); | |
1154 } | |
1155 | |
1156 /************************************************************************** | |
1157 * The following code is code that takes a opcode description string, and * | |
1158 * generates the corresponding instruction * | |
1159 * * | |
1160 * TODO(karl) Remove macro implementations once we have moved to this new * | |
1161 * implementation. * | |
1162 *************************************************************************/ | |
1163 | |
1164 /* Define the (maximum) size that working buffers, for the translation code. */ | |
1165 #define BUFSIZE 256 | |
1166 | |
1167 /* Define the maximum number of operands that can appear in an opcode | |
1168 * description string. | |
1169 */ | |
1170 #define MAX_OPERANDS 10 | |
1171 | |
1172 #define MAX_DEFOPS 1000 | |
1173 | |
1174 #define BUF_SIZE 1024 | |
1175 | |
1176 /* The maximum number of symbol substitutions that can be applied to an | |
1177 * opcode description string. Used mainly to make sure that if a | |
1178 * substitution occurs, the code will not looop infinitely. | |
1179 */ | |
1180 #define MAX_ST_SUBSTITUTIONS 100 | |
1181 | |
1182 /* The current opcode string description being translated. Mainly used | |
1183 * to generate useful error messages. | |
1184 */ | |
1185 static char* kCachedDesc = "???"; | |
1186 | |
1187 /* The set of possible characters that can follow a symbol when doing | |
1188 * symbol substitution. | |
1189 */ | |
1190 static const char* kSymbolTerminators = " :+/{},@"; | |
1191 | |
1192 /* Generates a fatal error message for the given opcode description string. */ | |
1193 static void NaClDefDescFatal(const char* desc, const char* message) { | |
1194 NaClLog(LOG_FATAL, "NaClDefine '%s': %s\n", desc, message); | |
1195 } | |
1196 | |
1197 /* Generates a fatal error message for the cached opcode description string. */ | |
1198 static void NaClDefFatal(const char* message) { | |
1199 NaClDefDescFatal(kCachedDesc, message); | |
1200 } | |
1201 | |
1202 /* replace all occurrences of "@NAME" with the corresponding | |
1203 * value in the given symbol table. | |
1204 * | |
1205 * NOTE: only MAX_ST_SUBSTITUTIONS are allowed, to make sure | |
1206 * that we don't infinite loop. | |
1207 */ | |
1208 static void NaClStExpand(char* desc, struct NaClSymbolTable* st) { | |
1209 const char* marker; | |
1210 int attempts_left = MAX_ST_SUBSTITUTIONS; | |
1211 if (NULL == st) return; | |
1212 for (marker = strchr(desc, '@'); | |
1213 (NULL != marker) && attempts_left; | |
1214 marker = strchr(desc, '@')) { | |
1215 char name[BUFSIZE]; | |
1216 size_t name_len = 0; | |
1217 /* Extract name */ | |
1218 const char *ch_ptr = marker+1; | |
1219 while (*ch_ptr && (NULL == strchr(kSymbolTerminators, *ch_ptr))) { | |
1220 name[name_len++] = *(ch_ptr++); | |
1221 } | |
1222 name[name_len] = '\0'; | |
1223 if (name_len) { | |
1224 /* Get corresponding symbol table value. */ | |
1225 NaClStValue* val = NaClSymbolTableGet(name, st); | |
1226 if (NULL != val) { | |
1227 /* Substitute and update desc. */ | |
1228 char buffer[BUFSIZE]; | |
1229 char* buffer_ptr = buffer; | |
1230 const char* desc_ptr = desc; | |
1231 char v_buffer[BUFSIZE]; | |
1232 const char* v_buffer_ptr = v_buffer; | |
1233 /* Copy text before @name. */ | |
1234 while (desc_ptr != marker) { | |
1235 *(buffer_ptr++) = *(desc_ptr++); | |
1236 } | |
1237 /* Do substitution of symbol value. */ | |
1238 switch (val->kind) { | |
1239 case nacl_byte: | |
1240 SNPRINTF(v_buffer, BUFSIZE, "%02"NACL_PRIx8, val->value.byte_value); | |
1241 break; | |
1242 case nacl_text: | |
1243 v_buffer_ptr = val->value.text_value; | |
1244 break; | |
1245 case nacl_int: | |
1246 SNPRINTF(v_buffer, BUFSIZE, "%d", val->value.int_value); | |
1247 break; | |
1248 default: | |
1249 NaClDefDescFatal(desc, "Unable to expand @ variable"); | |
1250 break; | |
1251 } | |
1252 while (*v_buffer_ptr) { | |
1253 *(buffer_ptr++) = *(v_buffer_ptr++); | |
1254 } | |
1255 /* copy text after @name. */ | |
1256 desc_ptr = ch_ptr; | |
1257 while (*desc_ptr) { | |
1258 *(buffer_ptr++) = *(desc_ptr++); | |
1259 } | |
1260 *buffer_ptr = '\0'; | |
1261 strcpy(desc, buffer); | |
1262 --attempts_left; | |
1263 continue; | |
1264 } | |
1265 } | |
1266 /* If reached, unable to do substitution, stop. */ | |
1267 break; | |
1268 } | |
1269 } | |
1270 | |
1271 /* Verify argument is a string describing a sequence of byte, | |
1272 * i.e. pairs of hex values (with no space inbetween), describing | |
1273 * the opcode base of an instruction. | |
1274 */ | |
1275 static void NaClVerifyByteBaseAssumptions(const char* byte) { | |
1276 size_t len = strlen(byte); | |
1277 if ((len < 2) || (len % 2)) { | |
1278 NaClDefFatal("opcode (hex) base length must be divisible by 2"); | |
1279 } | |
1280 if (len != strspn(byte, "0123456789aAbBcCdDeEfF")) { | |
1281 NaClDefFatal("opcode base not hex value"); | |
1282 } | |
1283 } | |
1284 | |
1285 /* Given a pointer to a string describing a byte using hexidecimal values, | |
1286 * extract the corresponding byte value. | |
1287 * | |
1288 * Note: Assumes that the length of base is 2. | |
1289 */ | |
1290 static uint8_t NaClExtractByte(const char* base) { | |
1291 return (uint8_t) STRTOULL(base + strlen(base) - 2, NULL, 16); | |
1292 } | |
1293 | |
1294 /* Given a string of bytes describing a prefix, return the | |
1295 * corresponding enumerated prefix value. | |
1296 */ | |
1297 static NaClInstPrefix NaClExtractPrefixValue(const char* prefix_name, | |
1298 size_t prefix_size) { | |
1299 if (prefix_size == 0) { | |
1300 return NoPrefix; | |
1301 } else { | |
1302 size_t i; | |
1303 NaClInstPrefix prefix; | |
1304 char prefix_text[BUFSIZE]; | |
1305 char* text_ptr; | |
1306 strcpy(prefix_text, "Prefix"); | |
1307 text_ptr = prefix_text + strlen("Prefix"); | |
1308 for (i = 0; i < prefix_size; ++i) { | |
1309 text_ptr[i] = toupper(prefix_name[i]); | |
1310 } | |
1311 text_ptr[prefix_size] = '\0'; | |
1312 for (prefix = 0; prefix < NaClInstPrefixEnumSize; ++prefix) { | |
1313 if (0 == strcmp(NaClInstPrefixName(prefix), prefix_text)) { | |
1314 return prefix; | |
1315 } | |
1316 } | |
1317 } | |
1318 NaClDefFatal("Opcode prefix not understood"); | |
1319 /* NOT REACHED */ | |
1320 return NaClInstPrefixEnumSize; | |
1321 } | |
1322 | |
1323 /* Given a string of byte values, describing the opcode base | |
1324 * of an instruction, extract out the corresponding opcode | |
1325 * prefix (i.e. the prefix defined by all but the last byte in | |
1326 * the opcode base. | |
1327 * | |
1328 * Note: Assumes that NaClVerifyByteBaseAssumptions was called | |
1329 * on the given parameter. | |
1330 */ | |
1331 static NaClInstPrefix NaClExtractPrefix(const char* base) { | |
1332 size_t len = strlen(base); | |
1333 if (len >= 2) { | |
1334 return NaClExtractPrefixValue(base, len - 2); | |
1335 } | |
1336 NaClDefFatal("Opcode prefix not understood"); | |
1337 /* NOT REACHED */ | |
1338 return NaClInstPrefixEnumSize; | |
1339 } | |
1340 | |
1341 static void NaClVerifyOctalDigit(const char* str, const char* message) { | |
1342 if ((1 != strlen(str)) || (1 != strspn(str, "01234567"))) { | |
1343 NaClDefFatal(message); | |
1344 } | |
1345 } | |
1346 | |
1347 /* | |
1348 * Given a string describing an opcode, the type of the | |
1349 * instruction, and the mnemonic associated with the instruction, | |
1350 * parse the opcode string and define the corresponding instruction. | |
1351 * | |
1352 * Note: See ??? for descriptions of legal opcode strings. | |
1353 */ | |
1354 static void NaClParseOpcode(const char* opcode, | |
1355 NaClInstType insttype, | |
1356 NaClMnemonic name, | |
1357 struct NaClSymbolTable* st) { | |
1358 char buf[BUFSIZE]; | |
1359 char* marker; | |
1360 char* buffer = buf; | |
1361 char* base; | |
1362 char* reg_offset = NULL; | |
1363 char* opcode_ext = NULL; | |
1364 char* opcode_3d_ext = NULL; | |
1365 char* opcode_rm_ext = NULL; | |
1366 NaClInstPrefix prefix; | |
1367 uint8_t opcode_value; | |
1368 Bool is_inst_defined = FALSE; | |
1369 strcpy(buf, opcode); | |
1370 | |
1371 /* Remove leading whitespace. */ | |
1372 while(' ' == *buffer) ++buffer; | |
1373 base = buffer; | |
1374 | |
1375 /* Start by finding any valid suffix (i.e. +X or /X), and remove. | |
1376 * Put the corresponding suffix into reg_offset(+), or opcode_ext(/). | |
1377 */ | |
1378 /* Try to recognize an opcode extension. */ | |
1379 marker = strchr(buffer, '/'); | |
1380 if (NULL != marker) { | |
1381 *marker = '\0'; | |
1382 opcode_ext = buffer + strlen(base) + 1; | |
1383 marker = strchr(opcode_ext, '/'); | |
1384 if (NULL != marker) { | |
1385 *marker = '\0'; | |
1386 opcode_rm_ext = opcode_ext + strlen(opcode_ext) + 1; | |
1387 if (strlen(opcode_rm_ext) != 1) { | |
1388 NaClDefFatal("modrm r/m opcode extension can only be " | |
1389 "a single digit"); | |
1390 } | |
1391 } | |
1392 if (strlen(opcode_ext) != 1) { | |
1393 NaClDefFatal("modrm opcode extension can only be a single digit"); | |
1394 } | |
1395 } else { | |
1396 /* Try to recognize a 3dnow extension. */ | |
1397 marker = strchr(buffer, '.'); | |
1398 if ((NULL != marker) && (0 == strncmp(marker, "..", 2))) { | |
1399 *marker = '\0'; | |
1400 opcode_3d_ext = marker + 2; | |
1401 } | |
1402 } | |
1403 | |
1404 marker = strchr(buffer, '+'); | |
1405 if (NULL != marker) { | |
1406 *marker = '\0'; | |
1407 reg_offset = buffer + strlen(base) + 1; | |
1408 } | |
1409 | |
1410 /* Now verify the opcode string, less the suffix, is valid. If so, | |
1411 * Pull out the instruction prefix and opcode byte. | |
1412 */ | |
1413 NaClVerifyByteBaseAssumptions(base); | |
1414 if (NULL == opcode_3d_ext) { | |
1415 prefix = NaClExtractPrefix(base); | |
1416 } else { | |
1417 prefix = NaClExtractPrefixValue(base, strlen(base)); | |
1418 } | |
1419 NaClDefInstPrefix(prefix); | |
1420 opcode_value = NaClExtractByte(base + strlen(base) - 2); | |
1421 | |
1422 if (reg_offset != NULL) { | |
1423 int reg = (int) STRTOULL(reg_offset, NULL, 10); | |
1424 if (reg < 0) { | |
1425 NaClDefFatal("can't add negative values to opcode"); | |
1426 } else if ((reg + opcode_value) >= NCDTABLESIZE) { | |
1427 NaClDefFatal("opcode addition too large"); | |
1428 } | |
1429 if (NULL == NaClSymbolTableGet("add_reg?", st)) { | |
1430 NaClVerifyOctalDigit(reg_offset, "invalid opcode register offset"); | |
1431 NaClDefInst(opcode_value + reg, insttype, NACL_IFLAG(OpcodePlusR), name); | |
1432 NaClDefOpcodeRegisterValue(reg); | |
1433 } | |
1434 else { | |
1435 NaClDefInst(opcode_value + reg, insttype, NACL_EMPTY_IFLAGS, name); | |
1436 } | |
1437 is_inst_defined = TRUE; | |
1438 } | |
1439 if (opcode_ext != NULL) { | |
1440 if (0 == strcmp("r", opcode_ext)) { | |
1441 if (! is_inst_defined) { | |
1442 NaClDefInst(opcode_value, insttype, NACL_EMPTY_IFLAGS, name); | |
1443 } | |
1444 NaClAddIFlags(NACL_IFLAG(OpcodeUsesModRm)); | |
1445 } else { | |
1446 int ext; | |
1447 NaClVerifyOctalDigit(opcode_ext, "invalid modrm opcode extension"); | |
1448 ext = (int) STRTOULL(opcode_ext, NULL, 10); | |
1449 if (! is_inst_defined) { | |
1450 NaClDefInst(opcode_value, insttype, NACL_EMPTY_IFLAGS, name); | |
1451 } | |
1452 NaClAddIFlags(NACL_IFLAG(OpcodeInModRm)); | |
1453 NaClDefOpcodeExtension(ext); | |
1454 } | |
1455 is_inst_defined = TRUE; | |
1456 if (opcode_rm_ext != NULL) { | |
1457 NaClVerifyOctalDigit(opcode_rm_ext, "invalid modrm r/m opcode extension"); | |
1458 NaClDefineOpcodeModRmRmExtension((int) STRTOULL(opcode_rm_ext, NULL, 10)); | |
1459 } | |
1460 } | |
1461 if (!is_inst_defined) { | |
1462 NaClIFlags flags = NACL_EMPTY_IFLAGS; | |
1463 if (opcode_3d_ext != NULL) { | |
1464 opcode_value = NaClExtractByte(opcode_3d_ext); | |
1465 } | |
1466 NaClDefInst(opcode_value, insttype, flags, name); | |
1467 } | |
1468 } | |
1469 | |
1470 /* Given the text of a mnemonic, return the corresponding mnemonic. */ | |
1471 static NaClMnemonic NaClAssemName(const char* name) { | |
1472 NaClMnemonic i; | |
1473 for (i = (NaClMnemonic) 0; i < NaClMnemonicEnumSize; ++i) { | |
1474 if (0 == strcmp(NaClMnemonicName(i), name)) { | |
1475 return i; | |
1476 } | |
1477 } | |
1478 NaClDefFatal("Can't find name for mnemonic"); | |
1479 /* NOT REACHED */ | |
1480 return NaClMnemonicEnumSize; | |
1481 } | |
1482 | |
1483 /* Given the name of a register, define the corresponding operand on | |
1484 * the instruction being defined. | |
1485 */ | |
1486 static void NaClExtractRegister(const char* reg_name) { | |
1487 char buffer[BUFSIZE]; | |
1488 char* buf_ptr = buffer; | |
1489 char* reg_ptr = (char*) reg_name; | |
1490 NaClOpKind kind; | |
1491 strcpy(buf_ptr, "Reg"); | |
1492 buf_ptr += strlen("Reg"); | |
1493 while (*reg_ptr) { | |
1494 char ch = *(reg_ptr++); | |
1495 *(buf_ptr++) = toupper(ch); | |
1496 } | |
1497 *buf_ptr = '\0'; | |
1498 for (kind = 0; kind < NaClOpKindEnumSize; ++kind) { | |
1499 if (0 == strcmp(NaClOpKindName(kind), buffer)) { | |
1500 NaClDefOp(kind, NACL_EMPTY_OPFLAGS); | |
1501 return; | |
1502 } | |
1503 } | |
1504 NaClDefFatal("Unable to find register"); | |
1505 } | |
1506 | |
1507 /* Helper function to add a define operand function into | |
1508 * a symbol table. | |
1509 */ | |
1510 static void NaClSymbolTablePutDefOp(const char* name, | |
1511 NaClDefOperand defop, | |
1512 struct NaClSymbolTable* st) { | |
1513 NaClStValue value; | |
1514 value.kind = nacl_defop; | |
1515 value.value.defop_value = defop; | |
1516 NaClSymbolTablePut(name, &value, st); | |
1517 } | |
1518 | |
1519 /* Given the name describing legal values for an operand, | |
1520 * call the corresponding function to define the corresponding | |
1521 * operand. | |
1522 */ | |
1523 static void NaClExtractOperandForm(const char* form) { | |
1524 static struct NaClSymbolTable* defop_st = NULL; | |
1525 NaClStValue* value; | |
1526 if (NULL == defop_st) { | |
1527 defop_st = NaClSymbolTableCreate(MAX_DEFOPS, NULL); | |
1528 NaClSymbolTablePutDefOp("Ap", NaClOperandForm_Ap, defop_st); | |
1529 NaClSymbolTablePutDefOp("Cd/q", NaClOperandForm_CdSlq, defop_st); | |
1530 NaClSymbolTablePutDefOp("Dd/q", NaClOperandForm_DdSlq, defop_st); | |
1531 NaClSymbolTablePutDefOp("Eb", NaClOperandForm_Eb, defop_st); | |
1532 NaClSymbolTablePutDefOp("Ed", NaClOperandForm_Ed, defop_st); | |
1533 NaClSymbolTablePutDefOp("Ed/q", NaClOperandForm_EdSlq, defop_st); | |
1534 NaClSymbolTablePutDefOp("Ed/q/d", NaClOperandForm_EdSlqSld, defop_st); | |
1535 NaClSymbolTablePutDefOp("Ed/q/q", NaClOperandForm_EdSlqSlq, defop_st); | |
1536 NaClSymbolTablePutDefOp("Ev", NaClOperandForm_Ev, defop_st); | |
1537 NaClSymbolTablePutDefOp("Ew", NaClOperandForm_Ew, defop_st); | |
1538 NaClSymbolTablePutDefOp("Fvd", NaClOperandForm_Fvd, defop_st); | |
1539 NaClSymbolTablePutDefOp("Fvq", NaClOperandForm_Fvq, defop_st); | |
1540 NaClSymbolTablePutDefOp("Fvw", NaClOperandForm_Fvw, defop_st); | |
1541 NaClSymbolTablePutDefOp("Gb", NaClOperandForm_Gb, defop_st); | |
1542 NaClSymbolTablePutDefOp("Gd", NaClOperandForm_Gd, defop_st); | |
1543 NaClSymbolTablePutDefOp("Gd/q", NaClOperandForm_GdQ, defop_st); | |
1544 NaClSymbolTablePutDefOp("Gq", NaClOperandForm_Gq, defop_st); | |
1545 NaClSymbolTablePutDefOp("Gv", NaClOperandForm_Gv, defop_st); | |
1546 NaClSymbolTablePutDefOp("Gw", NaClOperandForm_Gw, defop_st); | |
1547 NaClSymbolTablePutDefOp("Gw", NaClOperandForm_Gw, defop_st); | |
1548 NaClSymbolTablePutDefOp("Ib", NaClOperandForm_Ib, defop_st); | |
1549 NaClSymbolTablePutDefOp("Iv", NaClOperandForm_Iv, defop_st); | |
1550 NaClSymbolTablePutDefOp("Iw", NaClOperandForm_Iw, defop_st); | |
1551 NaClSymbolTablePutDefOp("Iz", NaClOperandForm_Iz, defop_st); | |
1552 NaClSymbolTablePutDefOp("I2b", NaClOperandForm_I2b, defop_st); | |
1553 NaClSymbolTablePutDefOp("Jb", NaClOperandForm_Jb, defop_st); | |
1554 NaClSymbolTablePutDefOp("Jz", NaClOperandForm_Jz, defop_st); | |
1555 NaClSymbolTablePutDefOp("Jzd", NaClOperandForm_Jzd, defop_st); | |
1556 NaClSymbolTablePutDefOp("Jzw", NaClOperandForm_Jzw, defop_st); | |
1557 NaClSymbolTablePutDefOp("M", NaClOperandForm_M, defop_st); | |
1558 NaClSymbolTablePutDefOp("Ma", NaClOperandForm_Ma, defop_st); | |
1559 NaClSymbolTablePutDefOp("Mb", NaClOperandForm_Mb, defop_st); | |
1560 NaClSymbolTablePutDefOp("Md", NaClOperandForm_Md, defop_st); | |
1561 NaClSymbolTablePutDefOp("Md/q", NaClOperandForm_MdSlq, defop_st); | |
1562 NaClSymbolTablePutDefOp("Mdq", NaClOperandForm_Mdq, defop_st); | |
1563 NaClSymbolTablePutDefOp("Mf", NaClOperandForm_Mf, defop_st); | |
1564 NaClSymbolTablePutDefOp("Mp", NaClOperandForm_Mp, defop_st); | |
1565 NaClSymbolTablePutDefOp("Mq", NaClOperandForm_Mq, defop_st); | |
1566 NaClSymbolTablePutDefOp("Ms", NaClOperandForm_Ms, defop_st); | |
1567 NaClSymbolTablePutDefOp("Mv", NaClOperandForm_Mv, defop_st); | |
1568 NaClSymbolTablePutDefOp("Mw/Rv", NaClOperandForm_MwSlRv, defop_st); | |
1569 NaClSymbolTablePutDefOp("Mw", NaClOperandForm_Mw, defop_st); | |
1570 NaClSymbolTablePutDefOp("Ob", NaClOperandForm_Ob, defop_st); | |
1571 NaClSymbolTablePutDefOp("Ov", NaClOperandForm_Ov, defop_st); | |
1572 NaClSymbolTablePutDefOp("Pd/q", NaClOperandForm_PdSlq, defop_st); | |
1573 NaClSymbolTablePutDefOp("Pd/q/d", NaClOperandForm_PdSlqSld, defop_st); | |
1574 NaClSymbolTablePutDefOp("Pd/q/q", NaClOperandForm_PdSlqSlq, defop_st); | |
1575 NaClSymbolTablePutDefOp("Pq", NaClOperandForm_Pq, defop_st); | |
1576 NaClSymbolTablePutDefOp("PRq", NaClOperandForm_PRq, defop_st); | |
1577 NaClSymbolTablePutDefOp("Qd", NaClOperandForm_Qd, defop_st); | |
1578 NaClSymbolTablePutDefOp("Qq", NaClOperandForm_Qq, defop_st); | |
1579 NaClSymbolTablePutDefOp("Rd/q", NaClOperandForm_RdSlq, defop_st); | |
1580 NaClSymbolTablePutDefOp("Rd/q/Mb", NaClOperandForm_RdSlqSlMb, defop_st); | |
1581 NaClSymbolTablePutDefOp("Rd/q/Mw", NaClOperandForm_RdSlqSlMw, defop_st); | |
1582 NaClSymbolTablePutDefOp("Rd/Mb", NaClOperandForm_RdSlMb, defop_st); | |
1583 NaClSymbolTablePutDefOp("Rd/Mw", NaClOperandForm_RdSlMw, defop_st); | |
1584 NaClSymbolTablePutDefOp("rAXv", NaClOperandForm_rAXv, defop_st); | |
1585 NaClSymbolTablePutDefOp("rAXva", NaClOperandForm_rAXva, defop_st); | |
1586 NaClSymbolTablePutDefOp("rAXvd", NaClOperandForm_rAXvd, defop_st); | |
1587 NaClSymbolTablePutDefOp("rAXvq", NaClOperandForm_rAXvq, defop_st); | |
1588 NaClSymbolTablePutDefOp("rAXvw", NaClOperandForm_rAXvw, defop_st); | |
1589 NaClSymbolTablePutDefOp("rBXv", NaClOperandForm_rBXv, defop_st); | |
1590 NaClSymbolTablePutDefOp("rCXv", NaClOperandForm_rCXv, defop_st); | |
1591 NaClSymbolTablePutDefOp("rDXv", NaClOperandForm_rDXv, defop_st); | |
1592 NaClSymbolTablePutDefOp("rSPv", NaClOperandForm_rSPv, defop_st); | |
1593 NaClSymbolTablePutDefOp("rBPv", NaClOperandForm_rBPv, defop_st); | |
1594 NaClSymbolTablePutDefOp("rSIv", NaClOperandForm_rSIv, defop_st); | |
1595 NaClSymbolTablePutDefOp("rDIv", NaClOperandForm_rDIv, defop_st); | |
1596 NaClSymbolTablePutDefOp("r8b", NaClOperandForm_r8b, defop_st); | |
1597 NaClSymbolTablePutDefOp("r8v", NaClOperandForm_r8v, defop_st); | |
1598 NaClSymbolTablePutDefOp("r8vd", NaClOperandForm_r8vd, defop_st); | |
1599 NaClSymbolTablePutDefOp("r8vq", NaClOperandForm_r8vq, defop_st); | |
1600 NaClSymbolTablePutDefOp("SGz", NaClOperandForm_SGz, defop_st); | |
1601 NaClSymbolTablePutDefOp("Sw", NaClOperandForm_Sw, defop_st); | |
1602 NaClSymbolTablePutDefOp("Udq", NaClOperandForm_Udq, defop_st); | |
1603 NaClSymbolTablePutDefOp("Udq/Md", NaClOperandForm_UdqMd, defop_st); | |
1604 NaClSymbolTablePutDefOp("Udq/Mq", NaClOperandForm_UdqMq, defop_st); | |
1605 NaClSymbolTablePutDefOp("Udq/Mw", NaClOperandForm_UdqMw, defop_st); | |
1606 NaClSymbolTablePutDefOp("Vdq", NaClOperandForm_Vdq, defop_st); | |
1607 NaClSymbolTablePutDefOp("Vd/q", NaClOperandForm_VdSlq, defop_st); | |
1608 NaClSymbolTablePutDefOp("Vd/q/d", NaClOperandForm_VdSlqSld, defop_st); | |
1609 NaClSymbolTablePutDefOp("Vd/q/q", NaClOperandForm_VdSlqSlq, defop_st); | |
1610 NaClSymbolTablePutDefOp("Vpd", NaClOperandForm_Vpd, defop_st); | |
1611 NaClSymbolTablePutDefOp("Vps", NaClOperandForm_Vps, defop_st); | |
1612 NaClSymbolTablePutDefOp("Vq", NaClOperandForm_Vq, defop_st); | |
1613 NaClSymbolTablePutDefOp("Vsd", NaClOperandForm_Vsd, defop_st); | |
1614 NaClSymbolTablePutDefOp("Vss", NaClOperandForm_Vss, defop_st); | |
1615 NaClSymbolTablePutDefOp("VRdq", NaClOperandForm_VRdq, defop_st); | |
1616 NaClSymbolTablePutDefOp("VRpd", NaClOperandForm_VRpd, defop_st); | |
1617 NaClSymbolTablePutDefOp("VRps", NaClOperandForm_VRps, defop_st); | |
1618 NaClSymbolTablePutDefOp("VRq", NaClOperandForm_VRq, defop_st); | |
1619 NaClSymbolTablePutDefOp("Wdq", NaClOperandForm_Wdq, defop_st); | |
1620 NaClSymbolTablePutDefOp("Wpd", NaClOperandForm_Wpd, defop_st); | |
1621 NaClSymbolTablePutDefOp("Wps", NaClOperandForm_Wps, defop_st); | |
1622 NaClSymbolTablePutDefOp("Wq", NaClOperandForm_Wq, defop_st); | |
1623 NaClSymbolTablePutDefOp("Wsd", NaClOperandForm_Wsd, defop_st); | |
1624 NaClSymbolTablePutDefOp("Wss", NaClOperandForm_Wss, defop_st); | |
1625 NaClSymbolTablePutDefOp("Xb", NaClOperandForm_Xb, defop_st); | |
1626 NaClSymbolTablePutDefOp("Xvd", NaClOperandForm_Xvd, defop_st); | |
1627 NaClSymbolTablePutDefOp("Xvq", NaClOperandForm_Xvq, defop_st); | |
1628 NaClSymbolTablePutDefOp("Xvw", NaClOperandForm_Xvw, defop_st); | |
1629 NaClSymbolTablePutDefOp("Xzw", NaClOperandForm_Xzw, defop_st); | |
1630 NaClSymbolTablePutDefOp("Xzd", NaClOperandForm_Xzd, defop_st); | |
1631 NaClSymbolTablePutDefOp("Yb", NaClOperandForm_Yb, defop_st); | |
1632 NaClSymbolTablePutDefOp("Yvd", NaClOperandForm_Yvd, defop_st); | |
1633 NaClSymbolTablePutDefOp("Yvq", NaClOperandForm_Yvq, defop_st); | |
1634 NaClSymbolTablePutDefOp("Yvw", NaClOperandForm_Yvw, defop_st); | |
1635 NaClSymbolTablePutDefOp("Yzd", NaClOperandForm_Yzd, defop_st); | |
1636 NaClSymbolTablePutDefOp("Yzw", NaClOperandForm_Yzw, defop_st); | |
1637 NaClSymbolTablePutDefOp("Zvd", NaClOperandForm_Zvd, defop_st); | |
1638 } | |
1639 value = NaClSymbolTableGet(form, defop_st); | |
1640 if (NULL == value || (value->kind != nacl_defop)) { | |
1641 NaClDefFatal("Malformed $defop form"); | |
1642 } | |
1643 value->value.defop_value(); | |
1644 } | |
1645 | |
1646 /* Given a string describing the operand, define the corresponding | |
1647 * operand. Returns the set of operand flags that must be | |
1648 * defined for the operand, based on the contents of the operand string. | |
1649 * | |
1650 * Note: See ??? for descriptions of legal operand strings. | |
1651 */ | |
1652 static NaClOpFlags NaClExtractOperand(const char* operand) { | |
1653 NaClOpFlags op_flags = NACL_EMPTY_OPFLAGS; | |
1654 switch (*operand) { | |
1655 case '{': | |
1656 if ('}' == operand[strlen(operand) - 1]) { | |
1657 char buffer[BUFSIZE]; | |
1658 strcpy(buffer, operand+1); | |
1659 buffer[strlen(buffer)-1] = '\0'; | |
1660 op_flags = | |
1661 NaClExtractOperand(buffer) | | |
1662 NACL_OPFLAG(OpImplicit); | |
1663 } else { | |
1664 NaClDefFatal("Malformed implicit braces"); | |
1665 } | |
1666 break; | |
1667 case '1': | |
1668 if (1 == strlen(operand)) { | |
1669 NaClOperandForm_One(); | |
1670 } else { | |
1671 NaClDefFatal("Malformed operand argument"); | |
1672 } | |
1673 break; | |
1674 case '%': | |
1675 NaClExtractRegister(operand+1); | |
1676 break; | |
1677 case '$': | |
1678 NaClExtractOperandForm(operand+1); | |
1679 break; | |
1680 default: | |
1681 NaClDefFatal("Malformed operand argument"); | |
1682 } | |
1683 return op_flags; | |
1684 } | |
1685 | |
1686 /* Given a string describing the operand, and an index corresponding | |
1687 * to the position of the operand in the corresponding opcode description | |
1688 * string, define the corresponding operand in the model being generated. | |
1689 */ | |
1690 static void NaClParseOperand(const char* operand, int arg_index) { | |
1691 NaClAddOpFlags(arg_index, NaClExtractOperand(operand)); | |
1692 NaClAddOpFormat(arg_index, operand); | |
1693 } | |
1694 | |
1695 void NaClBegDef(const char* desc, NaClInstType insttype, | |
1696 struct NaClSymbolTable* st) { | |
1697 char* name; | |
1698 char* arg; | |
1699 int num_args = 0; | |
1700 char buffer[BUFSIZE]; | |
1701 char expanded_desc[BUFSIZE]; | |
1702 char* opcode; | |
1703 char* assem_desc; | |
1704 NaClMnemonic mnemonic; | |
1705 char* old_kdesc = kCachedDesc; | |
1706 kCachedDesc = (char*) desc; | |
1707 | |
1708 /* Do symbol table substitutions. */ | |
1709 strcpy(buffer, desc); | |
1710 NaClStExpand(buffer, st); | |
1711 strcpy(expanded_desc, buffer); | |
1712 kCachedDesc = expanded_desc; | |
1713 | |
1714 /* Separate the description into opcode sequence and | |
1715 * assembly description. | |
1716 */ | |
1717 opcode = strtok(buffer, ":"); | |
1718 if (NULL == opcode) { | |
1719 NaClDefFatal("opcode not separated from assembly description using ':'"); | |
1720 } | |
1721 assem_desc = strtok(NULL, ":"); | |
1722 if (NULL == assem_desc) { | |
1723 NaClDefFatal("Can't find assembly description"); | |
1724 } | |
1725 if (NULL != strtok(NULL, ":")) { | |
1726 NaClDefFatal("Malformed assembly description"); | |
1727 } | |
1728 | |
1729 /* extract nmemonic name of instruction. */ | |
1730 name = strtok(assem_desc, " "); | |
1731 if (NULL == name) { | |
1732 NaClDefFatal("Can't find mnemonic name"); | |
1733 } | |
1734 mnemonic = NaClAssemName(name); | |
1735 NaClDelaySanityChecks(); | |
1736 NaClParseOpcode(opcode, insttype, mnemonic, st); | |
1737 | |
1738 /* Now extract operands. */ | |
1739 while ((arg = strtok(NULL, ", "))) { | |
1740 NaClParseOperand(arg, num_args); | |
1741 ++num_args; | |
1742 if (num_args == MAX_OPERANDS) { | |
1743 NaClDefFatal("Too many operands"); | |
1744 } | |
1745 } | |
1746 kCachedDesc = old_kdesc; | |
1747 } | |
1748 | |
1749 void NaClBegD32(const char* desc, NaClInstType insttype, | |
1750 struct NaClSymbolTable* st) { | |
1751 NaClBegDef(desc, insttype, st); | |
1752 NaClAddIFlags(NACL_IFLAG(Opcode32Only)); | |
1753 } | |
1754 | |
1755 void NaClBegD64(const char* desc, NaClInstType insttype, | |
1756 struct NaClSymbolTable* st) { | |
1757 NaClBegDef(desc, insttype, st); | |
1758 NaClAddIFlags(NACL_IFLAG(Opcode64Only)); | |
1759 } | |
1760 | |
1761 void NaClBegDefPlatform(NaClTargetPlatform platform, | |
1762 const char* desc, NaClInstType insttype, | |
1763 struct NaClSymbolTable* st) { | |
1764 switch (platform) { | |
1765 case T32: | |
1766 NaClBegD32(desc, insttype, st); | |
1767 break; | |
1768 case T64: | |
1769 NaClBegD64(desc, insttype, st); | |
1770 break; | |
1771 case Tall: | |
1772 NaClBegDef(desc, insttype, st); | |
1773 break; | |
1774 default: | |
1775 /* This shouldn't happen. */ | |
1776 NaClDefFatal("Don't understand platform"); | |
1777 } | |
1778 } | |
1779 | |
1780 void NaClEndDef(NaClInstCat icat) { | |
1781 NaClSetInstCat(icat); | |
1782 NaClApplySanityChecks(); | |
1783 NaClResetToDefaultInstPrefix(); | |
1784 } | |
1785 | |
1786 void NaClDefine(const char* desc, NaClInstType insttype, | |
1787 struct NaClSymbolTable* st, NaClInstCat cat) { | |
1788 NaClBegDef(desc, insttype, st); | |
1789 NaClEndDef(cat); | |
1790 } | |
1791 | |
1792 void NaClDef_32(const char* desc, NaClInstType insttype, | |
1793 struct NaClSymbolTable* st, NaClInstCat cat) { | |
1794 NaClBegD32(desc, insttype, st); | |
1795 NaClEndDef(cat); | |
1796 } | |
1797 | |
1798 void NaClDef_64(const char* desc, NaClInstType insttype, | |
1799 struct NaClSymbolTable* st, NaClInstCat cat) { | |
1800 NaClBegD64(desc, insttype, st); | |
1801 NaClEndDef(cat); | |
1802 } | |
1803 | |
1804 void NaClDefinePlatform(NaClTargetPlatform platform, | |
1805 const char* desc, NaClInstType insttype, | |
1806 struct NaClSymbolTable* st, NaClInstCat cat) { | |
1807 switch (platform) { | |
1808 case T32: | |
1809 NaClDef_32(desc, insttype, st, cat); | |
1810 break; | |
1811 case T64: | |
1812 NaClDef_64(desc, insttype, st, cat); | |
1813 break; | |
1814 case Tall: | |
1815 NaClDefine(desc, insttype, st, cat); | |
1816 break; | |
1817 default: | |
1818 /* This shouldn't happen. */ | |
1819 NaClDefFatal("Don't understand platform"); | |
1820 } | |
1821 } | |
1822 | |
1823 /* Generate an error message for the given instruction description, | |
1824 * if min <0 or max > 7. | |
1825 */ | |
1826 static void NaClDefCheckRange(const char* desc, int min, int max, int cutoff) { | |
1827 if (min < 0) { | |
1828 NaClDefDescFatal(desc, "Minimum value must be >= 0"); | |
1829 } else if (max > cutoff) { | |
1830 char buffer[BUF_SIZE]; | |
1831 SNPRINTF(buffer, BUF_SIZE, "Maximum value must be <= %d", cutoff); | |
1832 NaClDefDescFatal(desc, buffer); | |
1833 } | |
1834 } | |
1835 | |
1836 /* Define a symbol table size that can hold a small number of | |
1837 * symbols (i.e. limit to at most 5 definitions). | |
1838 */ | |
1839 #define NACL_SMALL_ST (5) | |
1840 | |
1841 void NaClDefReg(const char* desc, int min, int max, | |
1842 NaClInstType insttype, struct NaClSymbolTable* context_st, | |
1843 NaClInstCat cat) { | |
1844 int i; | |
1845 struct NaClSymbolTable* st = NaClSymbolTableCreate(NACL_SMALL_ST, context_st); | |
1846 NaClDefCheckRange(desc, min, max, kMaxRegisterIndexInOpcode); | |
1847 for (i = min; i <= max; ++i) { | |
1848 NaClSymbolTablePutInt("reg", i, st); | |
1849 NaClDefine(desc, insttype, st, cat); | |
1850 } | |
1851 NaClSymbolTableDestroy(st); | |
1852 } | |
1853 | |
1854 void NaClDefIter(const char* desc, int min, int max, | |
1855 NaClInstType insttype, struct NaClSymbolTable* context_st, | |
1856 NaClInstCat cat) { | |
1857 int i; | |
1858 struct NaClSymbolTable* st = NaClSymbolTableCreate(NACL_SMALL_ST, context_st); | |
1859 NaClDefCheckRange(desc, min, max, NCDTABLESIZE); | |
1860 NaClSymbolTablePutInt("add_reg?", 1, st); | |
1861 for (i = min; i <= max; ++i) { | |
1862 NaClSymbolTablePutInt("i", i, st); | |
1863 NaClDefine(desc, insttype, st, cat); | |
1864 } | |
1865 NaClSymbolTableDestroy(st); | |
1866 } | |
OLD | NEW |