| 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 |