1# This file is part of PeachPy package and is licensed under the Simplified BSD license. 2# See license.rst for the full text of the license. 3 4 5def check_operand(operand): 6 """Validates operand object as an instruction operand and converts it to a standard form""" 7 8 from peachpy.x86_64.registers import Register, MaskedRegister 9 from peachpy.x86_64.pseudo import Label 10 from peachpy.x86_64.function import LocalVariable 11 from peachpy.literal import Constant 12 from peachpy import Argument 13 from peachpy.util import is_int, is_int64 14 from copy import copy, deepcopy 15 if isinstance(operand, Register): 16 return copy(operand) 17 elif isinstance(operand, (MaskedRegister, MemoryOperand)): 18 return deepcopy(operand) 19 elif isinstance(operand, (Argument, RIPRelativeOffset, Label)): 20 return operand 21 elif is_int(operand): 22 if not is_int64(operand): 23 raise ValueError("The immediate operand %d is not representable as a 64-bit value") 24 return operand 25 elif isinstance(operand, list): 26 if len(operand) != 1: 27 raise ValueError("Memory operands must be represented by a list with only one element") 28 return MemoryOperand(operand[0]) 29 elif isinstance(operand, Constant): 30 from copy import copy, deepcopy 31 operand = copy(operand) 32 import peachpy.common.function 33 if peachpy.common.function.active_function: 34 operand.name = deepcopy(operand.name, peachpy.common.function.active_function._names_memo) 35 return MemoryOperand(operand) 36 elif isinstance(operand, LocalVariable): 37 return MemoryOperand(operand) 38 elif isinstance(operand, set): 39 if len(operand) != 1: 40 raise ValueError("Rounding control & suppress-all-errors operands must be represented by a set " 41 "with only one element") 42 return next(iter(operand)) 43 else: 44 raise TypeError("Unsupported operand: %s" % str(operand)) 45 46 47def get_operand_registers(operand): 48 """Returns a set of registers that comprise the operand""" 49 50 from peachpy.x86_64.registers import Register, MaskedRegister 51 if isinstance(operand, Register): 52 return [operand] 53 elif isinstance(operand, MaskedRegister): 54 return [operand.register, operand.mask.mask_register] 55 elif isinstance(operand, MemoryOperand) and isinstance(operand.address, MemoryAddress): 56 registers = list() 57 if operand.address.base is not None: 58 registers.append(operand.address.base) 59 if operand.address.index is not None: 60 registers.append(operand.address.index) 61 return registers 62 else: 63 return list() 64 65 66def format_operand(operand, assembly_format): 67 assert assembly_format in {"peachpy", "gas", "nasm", "go"}, \ 68 "Supported assembly formats are 'peachpy', 'gas', 'nasm', 'go'" 69 70 immediate_prefix_map = { 71 "peachpy": "", 72 "gas": "$", 73 "nasm": "", 74 "go": "$" 75 } 76 77 from peachpy.util import is_int64 78 if is_int64(operand): 79 return immediate_prefix_map[assembly_format] + str(operand) 80 else: 81 return operand.format(assembly_format) 82 83 84def format_operand_type(operand): 85 """Returns string representation of the operand type in assembly language""" 86 from peachpy.x86_64.registers import GeneralPurposeRegister64, GeneralPurposeRegister32, GeneralPurposeRegister16,\ 87 GeneralPurposeRegister8, MMXRegister, XMMRegister, YMMRegister, ZMMRegister, MaskedRegister, \ 88 al, ax, eax, rax, cl, xmm0 89 from peachpy.x86_64.pseudo import Label 90 from peachpy.util import is_int64, is_int32, is_int16, is_int8 91 if is_int8(operand): 92 return "imm8" 93 elif is_int16(operand): 94 return "imm16" 95 elif is_int32(operand): 96 return "imm32" 97 elif is_int64(operand): 98 return "imm64" 99 elif al == operand: 100 return "al" 101 elif ax == operand: 102 return "ax" 103 elif eax == operand: 104 return "eax" 105 elif rax == operand: 106 return "rax" 107 elif cl == operand: 108 return "cl" 109 elif xmm0 == operand: 110 return "xmm0" 111 elif isinstance(operand, GeneralPurposeRegister64): 112 return "r64" 113 elif isinstance(operand, GeneralPurposeRegister32): 114 return "r32" 115 elif isinstance(operand, GeneralPurposeRegister16): 116 return "r16" 117 elif isinstance(operand, GeneralPurposeRegister8): 118 return "r8" 119 elif isinstance(operand, MMXRegister): 120 return "mm" 121 elif isinstance(operand, XMMRegister): 122 return "xmm" 123 elif isinstance(operand, YMMRegister): 124 return "ymm" 125 elif isinstance(operand, ZMMRegister): 126 return "zmm" 127 elif isinstance(operand, MaskedRegister): 128 if operand.mask.is_zeroing: 129 return format_operand_type(operand.register) + "{k}{z}" 130 else: 131 return format_operand_type(operand.register) + "{k}" 132 elif isinstance(operand, MemoryOperand): 133 if operand.size is None: 134 return "m" 135 else: 136 if operand.mask is None: 137 return "m" + str(operand.size * 8) 138 elif operand.mask.is_zeroing: 139 return "m" + str(operand.size * 8) + "{k}{z}" 140 else: 141 return "m" + str(operand.size * 8) + "{k}" 142 elif isinstance(operand, RoundingControl): 143 return "{er}" 144 elif isinstance(operand, SuppressAllExceptions): 145 return "{sae}" 146 elif isinstance(operand, Label): 147 return "rel" 148 else: 149 return operand.__class__.__name__ 150 151 152class MemoryAddress: 153 """An address expression involving a register, e.g. rax - 10, r8d * 4.""" 154 155 def __init__(self, base=None, index=None, scale=None, displacement=0): 156 from peachpy.x86_64.registers import GeneralPurposeRegister64, \ 157 XMMRegister, YMMRegister, ZMMRegister, MaskedRegister 158 from peachpy.util import is_int, is_sint32 159 160 # Check individual arguments 161 if base is not None and not isinstance(base, GeneralPurposeRegister64): 162 raise TypeError("Base register must be a 64-bit general-purpose register") 163 if index is not None and \ 164 not isinstance(index, (GeneralPurposeRegister64, XMMRegister, YMMRegister, ZMMRegister)) and not \ 165 (isinstance(index, MaskedRegister) and 166 isinstance(index.register, (XMMRegister, YMMRegister, ZMMRegister)) and 167 not index.mask.is_zeroing): 168 raise TypeError("Index register must be a 64-bit general-purpose register or an XMM/YMM/ZMM register") 169 if scale is not None and not is_int(scale): 170 raise TypeError("Scale must be an integer") 171 if scale is not None and int(scale) not in {1, 2, 4, 8}: 172 raise TypeError("Scale must be 1, 2, 4, or 8") 173 if not is_sint32(displacement): 174 raise ValueError("Displacement value (%s) is not representable as a signed 32-bit integer" % 175 str(displacement)) 176 177 # Check relations of arguments 178 if scale is not None and index is None or scale is None and index is not None: 179 raise ValueError("Either both of neither of scale and index must be defined") 180 if index is None and base is None: 181 raise ValueError("Either base or index * scale must be specified") 182 183 self.base = base 184 self.index = index 185 self.scale = None if scale is None else int(scale) 186 self.displacement = int(displacement) 187 188 def __add__(self, addend): 189 from peachpy.x86_64.registers import GeneralPurposeRegister64 190 from peachpy.util import is_int, is_sint32 191 if is_int(addend): 192 if not is_sint32(addend): 193 raise ValueError("The addend value (%d) is not representable as a signed 32-bit integer" % addend) 194 return MemoryAddress(self.base, self.index, self.scale, self.displacement + addend) 195 elif isinstance(addend, GeneralPurposeRegister64): 196 if self.base is not None: 197 raise TypeError("Can not add a general-purpose register to a memory operand with existing base") 198 if self.index.size != addend.size: 199 raise TypeError("Index (%s) and addend (%s) registers have different size" % 200 (str(self.index), str(addend))) 201 return MemoryAddress(addend, self.index, self.scale, self.displacement) 202 elif isinstance(addend, MemoryAddress): 203 if self.base is not None and addend.base is not None: 204 raise ValueError("Can not add memory address: both address expressions use base registers") 205 if self.index is not None and addend.index is not None: 206 raise ValueError("Can not add memory address: both address expressions use index registers") 207 sum_base = self.base if self.base is not None else addend.base 208 (sum_index, sum_scale) = (self.index, self.scale) \ 209 if self.index is not None else (addend.index, addend.scale) 210 return MemoryAddress(sum_base, sum_index, sum_scale, self.displacement + addend.displacement) 211 else: 212 raise TypeError("Can not add %s: unsupported addend type" % str(addend)) 213 214 def __sub__(self, minuend): 215 from peachpy.util import is_int, is_sint32 216 if is_int(minuend): 217 if not is_sint32(-minuend): 218 raise ValueError("The addend value (%d) is not representable as a signed 32-bit integer" % minuend) 219 return MemoryAddress(self.base, self.index, self.scale, self.displacement - minuend) 220 else: 221 raise TypeError("Can not add %s: unsupported addend type" % str(minuend)) 222 223 def __str__(self): 224 parts = [] 225 if self.base is not None: 226 parts.append(str(self.base)) 227 if self.index is not None: 228 parts.append(str(self.index) + "*" + str(self.scale)) 229 if self.displacement >= 0: 230 if self.displacement > 0: 231 parts.append(str(self.displacement)) 232 return " + ".join(parts) 233 else: 234 return " + ".join(parts) + " - " + str(-self.displacement) 235 236 def __repr__(self): 237 return str(self) 238 239 240class MemoryOperand: 241 def __init__(self, address, size=None, mask=None, broadcast=None): 242 from peachpy.x86_64.registers import GeneralPurposeRegister64, \ 243 XMMRegister, YMMRegister, ZMMRegister, MaskedRegister 244 from peachpy.x86_64.function import LocalVariable 245 from peachpy.literal import Constant 246 assert isinstance(address, (GeneralPurposeRegister64, XMMRegister, YMMRegister, ZMMRegister, 247 MemoryAddress, Constant, LocalVariable)) or \ 248 isinstance(address, MaskedRegister) and \ 249 isinstance(address.register, (XMMRegister, YMMRegister, ZMMRegister)) and \ 250 not address.mask.is_zeroing, \ 251 "Only MemoryAddress, 64-bit general-purpose registers, XMM/YMM/ZMM registers, " \ 252 "and merge-masked XMM/YMM/ZMM registers may be specified as an address" 253 from peachpy.util import is_int 254 assert size is None or is_int(size) and int(size) in SizeSpecification._size_name_map, \ 255 "Unsupported size: %d" % size 256 257 self.symbol = None 258 self.size = size 259 self.mask = mask 260 self.broadcast = broadcast 261 262 if isinstance(address, MemoryAddress): 263 if isinstance(address.index, MaskedRegister): 264 self.address = MemoryAddress(address.base, address.index.register, address.scale, address.displacement) 265 assert mask is None, "Mask argument can't be used when address index is a masked XMM/YMM/ZMM register" 266 self.mask = address.index.mask 267 else: 268 self.address = address 269 elif isinstance(address, MaskedRegister): 270 self.address = MemoryAddress(index=address.register, scale=1) 271 assert mask is None, "Mask argument can't be used when address is a masked XMM/YMM/ZMM register" 272 self.mask = address.mask 273 elif isinstance(address, Constant): 274 self.address = RIPRelativeOffset(0) 275 self.symbol = address 276 self.size = address.size 277 elif isinstance(address, LocalVariable): 278 from peachpy.x86_64.registers import rsp 279 self.address = MemoryAddress(rsp, displacement=address.offset) 280 self.symbol = address 281 self.size = address.size 282 else: 283 # Convert register to memory address expression 284 self.address = MemoryAddress(address) 285 286 def __str__(self): 287 if self.size is None: 288 return "[" + str(self.address) + "]" 289 else: 290 return SizeSpecification._size_name_map[self.size] + " [" + str(self.address) + "]" 291 292 def __repr__(self): 293 return str(self) 294 295 def __call__(self, mask): 296 from peachpy.x86_64.registers import KRegister, RegisterMask 297 if not isinstance(mask, (KRegister, RegisterMask)): 298 raise SyntaxError("zmm(mask) syntax requires mask to be a KRegister or KRegister.z") 299 if self.broadcast: 300 raise ValueError("mask can not be applied to memory operands with broadcasting") 301 if isinstance(mask, KRegister): 302 mask = RegisterMask(mask) 303 return MemoryOperand(self.address, self.size, mask) 304 305 def format(self, assembly_format): 306 assert assembly_format in {"peachpy", "gas", "nasm", "go"}, \ 307 "Supported assembly formats are 'peachpy', 'gas', 'nasm', 'go'" 308 309 if assembly_format == "go": 310 text = str(self.address.displacement) 311 if self.address.base is not None: 312 text += "(" + self.address.base.format(assembly_format) + ")" 313 if self.address.index is not None: 314 text += "(%s*%d)" % (self.address.index.format(assembly_format), self.address.scale) 315 return text 316 elif assembly_format == "gas": 317 if isinstance(self.address, RIPRelativeOffset): 318 return str(self.address.offset) + "(%%rip)" 319 else: 320 base = self.address.base 321 if self.address.index is None: 322 return "{displacement}({base})".format( 323 displacement=self.address.displacement, 324 base=base.format(assembly_format)) 325 else: 326 return "{displacement}({base},{index},{scale})".format( 327 displacement=self.address.displacement, 328 base="" if base is None else base.format(assembly_format), 329 index=self.address.index, 330 scale=self.address.scale) 331 else: 332 return str(self) 333 334 @property 335 def bcode(self): 336 return int(self.broadcast is not None) 337 338 @property 339 def kcode(self): 340 if self.mask is None: 341 return 0 342 else: 343 return self.mask.kcode 344 345 @property 346 def zcode(self): 347 if self.mask is None: 348 return 0 349 else: 350 return self.mask.zcode 351 352 353class SizeSpecification: 354 _size_name_map = { 355 1: "byte", 356 2: "word", 357 4: "dword", 358 8: "qword", 359 10: "tword", 360 16: "oword", 361 32: "hword", 362 64: "zword" 363 } 364 365 def __init__(self, size): 366 from peachpy.util import is_int 367 assert is_int(size) and int(size) in SizeSpecification._size_name_map, \ 368 "Unsupported size: %d" % size 369 self.size = size 370 371 def __str__(self): 372 return SizeSpecification._size_name_map[self.size] 373 374 def __getitem__(self, address): 375 return MemoryOperand(address, self.size) 376 377 @property 378 def to2(self): 379 if self.size not in [4, 8]: 380 raise ValueError("{1to2} broadcasting is only supported for dword and qword memory locations") 381 return BroadcastSpecification(self.size, 2) 382 383 @property 384 def to4(self): 385 if self.size not in [4, 8]: 386 raise ValueError("{1to4} broadcasting is only supported for dword and qword memory locations") 387 return BroadcastSpecification(self.size, 4) 388 389 @property 390 def to8(self): 391 if self.size not in [4, 8]: 392 raise ValueError("{1to8} broadcasting is only supported for dword and qword memory locations") 393 return BroadcastSpecification(self.size, 8) 394 395 @property 396 def to16(self): 397 if self.size != 4: 398 raise ValueError("{1to16} broadcasting is only supported for dword memory locations") 399 return BroadcastSpecification(self.size, 16) 400 401 402class BroadcastSpecification: 403 def __init__(self, size, broadcast): 404 assert size in [4, 8] 405 assert broadcast in [2, 4, 8, 16] 406 assert size * broadcast in [16, 32, 64] 407 self.size = size 408 self.broadcast = broadcast 409 410 def __str__(self): 411 return SizeSpecification._size_name_map[self.size] + "{1to%d}" % self.broadcast 412 413 def __getitem__(self, address): 414 return MemoryOperand(address, self.size, broadcast=self.broadcast) 415 416 417class RIPRelativeOffset: 418 def __init__(self, offset): 419 import peachpy.util 420 if not peachpy.util.is_sint32(offset): 421 raise ValueError("RIP-relative offset must be a 32-bit signed integer") 422 self.offset = offset 423 424 def __add__(self, extra_offset): 425 return RIPRelativeOffset(self.offset + extra_offset) 426 427 def __sub__(self, extra_offset): 428 return RIPRelativeOffset(self.offset - extra_offset) 429 430 431def is_al(operand): 432 from peachpy.x86_64.registers import GeneralPurposeRegister8, al 433 return isinstance(operand, GeneralPurposeRegister8) and (operand.is_virtual or operand == al) 434 435 436def is_cl(operand): 437 from peachpy.x86_64.registers import GeneralPurposeRegister8, cl 438 return isinstance(operand, GeneralPurposeRegister8) and (operand.is_virtual or operand == cl) 439 440 441def is_ax(operand): 442 from peachpy.x86_64.registers import GeneralPurposeRegister16, ax 443 return isinstance(operand, GeneralPurposeRegister16) and (operand.is_virtual or operand == ax) 444 445 446def is_eax(operand): 447 from peachpy.x86_64.registers import GeneralPurposeRegister32, eax 448 return isinstance(operand, GeneralPurposeRegister32) and (operand.is_virtual or operand == eax) 449 450 451def is_rax(operand): 452 from peachpy.x86_64.registers import GeneralPurposeRegister64, rax 453 return isinstance(operand, GeneralPurposeRegister64) and (operand.is_virtual or operand == rax) 454 455 456def is_xmm0(operand): 457 from peachpy.x86_64.registers import XMMRegister, xmm0 458 return isinstance(operand, XMMRegister) and (operand.is_virtual or operand == xmm0) 459 460 461def is_r8(operand): 462 import peachpy.x86_64.registers 463 return isinstance(operand, peachpy.x86_64.registers.GeneralPurposeRegister8) 464 465 466def is_r8rex(operand): 467 import peachpy.x86_64.registers 468 return isinstance(operand, peachpy.x86_64.registers.GeneralPurposeRegister8) and \ 469 operand.physical_id >= 4 470 471 472def is_r8h(operand): 473 import peachpy.x86_64.registers 474 return isinstance(operand, peachpy.x86_64.registers.GeneralPurposeRegister8) and \ 475 operand.mask == peachpy.x86_64.registers.GeneralPurposeRegister8._high_mask 476 477 478def is_r16(operand): 479 import peachpy.x86_64.registers 480 return isinstance(operand, peachpy.x86_64.registers.GeneralPurposeRegister16) 481 482 483def is_r32(operand): 484 import peachpy.x86_64.registers 485 return isinstance(operand, peachpy.x86_64.registers.GeneralPurposeRegister32) 486 487 488def is_r64(operand): 489 import peachpy.x86_64.registers 490 return isinstance(operand, peachpy.x86_64.registers.GeneralPurposeRegister64) 491 492 493def is_mm(operand): 494 import peachpy.x86_64.registers 495 return isinstance(operand, peachpy.x86_64.registers.MMXRegister) 496 497 498def is_xmm(operand): 499 import peachpy.x86_64.registers 500 return isinstance(operand, peachpy.x86_64.registers.XMMRegister) and \ 501 (operand.physical_id is None or operand.physical_id < 16) 502 503 504def is_evex_xmm(operand): 505 import peachpy.x86_64.registers 506 return isinstance(operand, peachpy.x86_64.registers.XMMRegister) 507 508 509def is_xmmk(operand): 510 import peachpy.x86_64.registers 511 return isinstance(operand, peachpy.x86_64.registers.XMMRegister) or \ 512 isinstance(operand, peachpy.x86_64.registers.MaskedRegister) and \ 513 isinstance(operand.register, peachpy.x86_64.registers.XMMRegister) and \ 514 not operand.mask.is_zeroing 515 516 517def is_xmmkz(operand): 518 import peachpy.x86_64.registers 519 return isinstance(operand, peachpy.x86_64.registers.XMMRegister) or \ 520 isinstance(operand, peachpy.x86_64.registers.MaskedRegister) and \ 521 isinstance(operand.register, peachpy.x86_64.registers.XMMRegister) 522 523 524def is_ymm(operand): 525 import peachpy.x86_64.registers 526 return isinstance(operand, peachpy.x86_64.registers.YMMRegister) and \ 527 (operand.physical_id is None or operand.physical_id < 16) 528 529 530def is_evex_ymm(operand): 531 import peachpy.x86_64.registers 532 return isinstance(operand, peachpy.x86_64.registers.YMMRegister) 533 534 535def is_ymmk(operand): 536 import peachpy.x86_64.registers 537 return isinstance(operand, peachpy.x86_64.registers.YMMRegister) or \ 538 isinstance(operand, peachpy.x86_64.registers.MaskedRegister) and \ 539 isinstance(operand.register, peachpy.x86_64.registers.YMMRegister) and \ 540 not operand.mask.is_zeroing 541 542 543def is_ymmkz(operand): 544 import peachpy.x86_64.registers 545 return isinstance(operand, peachpy.x86_64.registers.YMMRegister) or \ 546 isinstance(operand, peachpy.x86_64.registers.MaskedRegister) and \ 547 isinstance(operand.register, peachpy.x86_64.registers.YMMRegister) 548 549 550def is_zmm(operand): 551 import peachpy.x86_64.registers 552 return isinstance(operand, peachpy.x86_64.registers.ZMMRegister) 553 554 555def is_zmmk(operand): 556 import peachpy.x86_64.registers 557 return isinstance(operand, peachpy.x86_64.registers.ZMMRegister) or \ 558 isinstance(operand, peachpy.x86_64.registers.MaskedRegister) and \ 559 isinstance(operand.register, peachpy.x86_64.registers.ZMMRegister) and \ 560 not operand.mask.is_zeroing 561 562 563def is_zmmkz(operand): 564 import peachpy.x86_64.registers 565 return isinstance(operand, peachpy.x86_64.registers.ZMMRegister) or \ 566 isinstance(operand, peachpy.x86_64.registers.MaskedRegister) and \ 567 isinstance(operand.register, peachpy.x86_64.registers.ZMMRegister) 568 569 570def is_k(operand): 571 import peachpy.x86_64.registers 572 return isinstance(operand, peachpy.x86_64.registers.KRegister) 573 574 575def is_kk(operand): 576 import peachpy.x86_64.registers 577 return isinstance(operand, peachpy.x86_64.registers.KRegister) or \ 578 isinstance(operand, peachpy.x86_64.registers.MaskedRegister) and \ 579 isinstance(operand.register, peachpy.x86_64.registers.KRegister) and \ 580 not operand.mask.is_zeroing 581 582 583def is_m(operand): 584 if not isinstance(operand, MemoryOperand) or operand.mask is not None or operand.broadcast is not None: 585 return False 586 # Check that the operand does not use vector index 587 from peachpy.x86_64.registers import GeneralPurposeRegister 588 return isinstance(operand.address, RIPRelativeOffset) or \ 589 operand.address.index is None or isinstance(operand.address.index, GeneralPurposeRegister) 590 591 592def is_mk(operand): 593 if not isinstance(operand, MemoryOperand) or operand.broadcast is not None: 594 return False 595 # Check that the no zero-masking applied to the operand 596 if operand.mask is not None and operand.mask.is_zeroing: 597 return False 598 # Check that the operand does not use vector index 599 from peachpy.x86_64.registers import GeneralPurposeRegister 600 return operand.address.index is None or isinstance(operand.address.index, GeneralPurposeRegister) 601 602 603def is_mkz(operand): 604 if not isinstance(operand, MemoryOperand) or operand.broadcast is not None: 605 return False 606 # Check that the operand does not use vector index 607 from peachpy.x86_64.registers import GeneralPurposeRegister 608 return operand.address.index is None or isinstance(operand.address.index, GeneralPurposeRegister) 609 610 611def is_vmx(operand): 612 from peachpy.x86_64.registers import XMMRegister 613 return isinstance(operand, MemoryOperand) and isinstance(operand.address.index, XMMRegister) and \ 614 (operand.address.index is None or operand.address.index.physical_id < 16) and \ 615 operand.mask is None 616 617 618def is_evex_vmx(operand): 619 from peachpy.x86_64.registers import XMMRegister 620 return isinstance(operand, MemoryOperand) and isinstance(operand.address.index, XMMRegister) and \ 621 operand.mask is None 622 623 624def is_vmxk(operand): 625 from peachpy.x86_64.registers import XMMRegister 626 return isinstance(operand, MemoryOperand) and isinstance(operand.address.index, XMMRegister) 627 628 629def is_vmy(operand): 630 from peachpy.x86_64.registers import YMMRegister 631 return isinstance(operand, MemoryOperand) and isinstance(operand.address.index, YMMRegister) and \ 632 (operand.address.index is None or operand.address.index.physical_id < 16) and \ 633 operand.mask is None 634 635 636def is_evex_vmy(operand): 637 from peachpy.x86_64.registers import YMMRegister 638 return isinstance(operand, MemoryOperand) and isinstance(operand.address.index, YMMRegister) and \ 639 operand.mask is None 640 641 642def is_vmyk(operand): 643 from peachpy.x86_64.registers import YMMRegister 644 return isinstance(operand, MemoryOperand) and isinstance(operand.address.index, YMMRegister) 645 646 647def is_vmz(operand): 648 from peachpy.x86_64.registers import ZMMRegister 649 return isinstance(operand, MemoryOperand) and isinstance(operand.address.index, ZMMRegister) and \ 650 operand.mask is None 651 652 653def is_vmzk(operand): 654 from peachpy.x86_64.registers import ZMMRegister 655 return isinstance(operand, MemoryOperand) and isinstance(operand.address.index, ZMMRegister) 656 657 658def is_m8(operand, strict=False): 659 return is_m(operand) and (operand.size is None and not strict or operand.size == 1) 660 661 662def is_m16(operand, strict=False): 663 import peachpy.literal 664 return is_m(operand) and (operand.size is None and not strict or operand.size == 2) or \ 665 isinstance(operand, peachpy.literal.Constant) and operand.size == 2 666 667 668def is_m16kz(operand): 669 return is_mkz(operand) and (operand.size is None or operand.size == 2) 670 671 672def is_m32(operand, strict=False): 673 import peachpy.literal 674 return is_m(operand) and (operand.size is None and not strict or operand.size == 4) or \ 675 isinstance(operand, peachpy.literal.Constant) and operand.size == 4 676 677 678def is_m32k(operand): 679 return is_mk(operand) and (operand.size is None or operand.size == 4) 680 681 682def is_m32kz(operand): 683 return is_mkz(operand) and (operand.size is None or operand.size == 4) 684 685 686def is_m64(operand, strict=False): 687 import peachpy.literal 688 return is_m(operand) and (operand.size is None and not strict or operand.size == 8) or \ 689 isinstance(operand, peachpy.literal.Constant) and operand.size == 8 690 691 692def is_m64k(operand): 693 return is_mk(operand) and (operand.size is None or operand.size == 8) 694 695 696def is_m64kz(operand): 697 return is_mkz(operand) and (operand.size is None or operand.size == 8) 698 699 700def is_m80(operand, strict=False): 701 return is_m(operand) and (operand.size is None and not strict or operand.size == 10) 702 703 704def is_m128(operand, strict=False): 705 import peachpy.literal 706 return is_m(operand) and (operand.size is None and not strict or operand.size == 16) or \ 707 isinstance(operand, peachpy.literal.Constant) and operand.size == 16 708 709 710def is_m128kz(operand): 711 return is_mkz(operand) and (operand.size is None or operand.size == 16) 712 713 714def is_m256(operand, strict=False): 715 import peachpy.literal 716 return is_m(operand) and (operand.size is None and not strict or operand.size == 32) or \ 717 isinstance(operand, peachpy.literal.Constant) and operand.size == 32 718 719 720def is_m256kz(operand): 721 return is_mkz(operand) and (operand.size is None or operand.size == 32) 722 723 724def is_m512(operand, strict=False): 725 import peachpy.literal 726 return is_m(operand) and (operand.size is None and not strict or operand.size == 64) or \ 727 isinstance(operand, peachpy.literal.Constant) and operand.size == 64 728 729 730def is_m512kz(operand): 731 return is_mkz(operand) and (operand.size is None or operand.size == 64) 732 733 734def is_m64_m32bcst(operand): 735 return is_m64(operand) or isinstance(operand, MemoryOperand) and operand.size == 4 and operand.broadcast == 2 736 737 738def is_m128_m32bcst(operand): 739 return is_m128(operand) or isinstance(operand, MemoryOperand) and operand.size == 4 and operand.broadcast == 4 740 741 742def is_m256_m32bcst(operand): 743 return is_m256(operand) or isinstance(operand, MemoryOperand) and operand.size == 4 and operand.broadcast == 8 744 745 746def is_m512_m32bcst(operand): 747 return is_m512(operand) or isinstance(operand, MemoryOperand) and operand.size == 4 and operand.broadcast == 16 748 749 750def is_m128_m64bcst(operand): 751 return is_m128(operand) or isinstance(operand, MemoryOperand) and operand.size == 8 and operand.broadcast == 2 752 753 754def is_m256_m64bcst(operand): 755 return is_m256(operand) or isinstance(operand, MemoryOperand) and operand.size == 8 and operand.broadcast == 4 756 757 758def is_m512_m64bcst(operand): 759 return is_m512(operand) or isinstance(operand, MemoryOperand) and operand.size == 8 and operand.broadcast == 8 760 761 762def is_m32bcst(operand): 763 return False 764 765 766def is_m64bcst(operand): 767 return False 768 769 770def is_imm(operand): 771 import peachpy.util 772 return peachpy.util.is_int(operand) 773 774 775def is_imm4(operand): 776 import peachpy.util 777 return peachpy.util.is_int(operand) and 0 <= operand <= 15 778 779 780def is_imm8(operand, ext_size=None): 781 import peachpy.util 782 if ext_size is None: 783 return peachpy.util.is_int8(operand) 784 else: 785 sup = 2**(8*ext_size) 786 return peachpy.util.is_int(operand) and \ 787 (-128 <= operand <= 127 or sup - 128 <= operand < sup) 788 789 790def is_imm16(operand, ext_size=None): 791 import peachpy.util 792 if ext_size is None: 793 return peachpy.util.is_int16(operand) 794 else: 795 sup = 2**(8*ext_size) 796 return peachpy.util.is_int(operand) and \ 797 (-32768 <= operand <= 32767 or sup - 32768 <= operand < sup) 798 799 800def is_imm32(operand, ext_size=None): 801 import peachpy.util 802 if ext_size is None: 803 return peachpy.util.is_int32(operand) 804 else: 805 sup = 2**(8*ext_size) 806 return peachpy.util.is_int(operand) and \ 807 (-2147483648 <= operand <= 2147483647 or sup - 2147483648 <= operand < sup) 808 809 810def is_imm64(operand): 811 import peachpy.util 812 return peachpy.util.is_int64(operand) 813 814 815def is_rel8(operand): 816 from peachpy.util import is_sint8 817 return isinstance(operand, RIPRelativeOffset) and is_sint8(operand.offset) 818 819 820def is_rel32(operand): 821 from peachpy.util import is_sint32 822 return isinstance(operand, RIPRelativeOffset) and is_sint32(operand.offset) 823 824 825def is_label(operand): 826 import peachpy.x86_64.pseudo 827 return isinstance(operand, peachpy.x86_64.pseudo.Label) 828 829 830def is_er(operand): 831 return isinstance(operand, RoundingControl) 832 833 834def is_sae(operand): 835 return isinstance(operand, SuppressAllExceptions) 836 837 838byte = SizeSpecification(1) 839word = SizeSpecification(2) 840dword = SizeSpecification(4) 841qword = SizeSpecification(8) 842tword = SizeSpecification(10) 843oword = SizeSpecification(16) 844hword = SizeSpecification(32) 845yword = SizeSpecification(32) 846zword = SizeSpecification(64) 847 848 849class RoundingControl: 850 def __init__(self, name, code): 851 self.name = name 852 self.code = code 853 854 def __hash__(self): 855 return hash(self.name) 856 857 def __eq__(self, other): 858 return isinstance(other, RoundingControl) and other.name == self.name and other.code == self.code 859 860 def __ne__(self, other): 861 return not isinstance(other, RoundingControl) or other.name != self.name or other.code != self.code 862 863 def __str__(self): 864 return "{" + self.name + "}" 865 866 867class SuppressAllExceptions: 868 def __init__(self, name): 869 self.name = name 870 871 def __hash__(self): 872 return hash(self.name) 873 874 def __eq__(self, other): 875 return isinstance(other, SuppressAllExceptions) and other.name == self.name 876 877 def __ne__(self, other): 878 return not isinstance(other, SuppressAllExceptions) or other.name != self.name 879 880 def __str__(self): 881 return "{" + self.name + "}" 882 883 884rn_sae = RoundingControl("rn-sae", 0b00) 885rz_sae = RoundingControl("rz-sae", 0b11) 886ru_sae = RoundingControl("ru-sae", 0b10) 887rd_sae = RoundingControl("rd-sae", 0b01) 888sae = SuppressAllExceptions("sae") 889