libvex_ir.h revision 4b21c3de6dabbe17c7f4cc1c4748c5491267c158
1 2/*---------------------------------------------------------------*/ 3/*--- begin libvex_ir.h ---*/ 4/*---------------------------------------------------------------*/ 5 6/* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2004-2013 OpenWorks LLP 11 info@open-works.net 12 13 This program is free software; you can redistribute it and/or 14 modify it under the terms of the GNU General Public License as 15 published by the Free Software Foundation; either version 2 of the 16 License, or (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 26 02110-1301, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29 30 Neither the names of the U.S. Department of Energy nor the 31 University of California nor the names of its contributors may be 32 used to endorse or promote products derived from this software 33 without prior written permission. 34*/ 35 36#ifndef __LIBVEX_IR_H 37#define __LIBVEX_IR_H 38 39#include "libvex_basictypes.h" 40 41 42/*---------------------------------------------------------------*/ 43/*--- High-level IR description ---*/ 44/*---------------------------------------------------------------*/ 45 46/* Vex IR is an architecture-neutral intermediate representation. 47 Unlike some IRs in systems similar to Vex, it is not like assembly 48 language (ie. a list of instructions). Rather, it is more like the 49 IR that might be used in a compiler. 50 51 Code blocks 52 ~~~~~~~~~~~ 53 The code is broken into small code blocks ("superblocks", type: 54 'IRSB'). Each code block typically represents from 1 to perhaps 50 55 instructions. IRSBs are single-entry, multiple-exit code blocks. 56 Each IRSB contains three things: 57 - a type environment, which indicates the type of each temporary 58 value present in the IRSB 59 - a list of statements, which represent code 60 - a jump that exits from the end the IRSB 61 Because the blocks are multiple-exit, there can be additional 62 conditional exit statements that cause control to leave the IRSB 63 before the final exit. Also because of this, IRSBs can cover 64 multiple non-consecutive sequences of code (up to 3). These are 65 recorded in the type VexGuestExtents (see libvex.h). 66 67 Statements and expressions 68 ~~~~~~~~~~~~~~~~~~~~~~~~~~ 69 Statements (type 'IRStmt') represent operations with side-effects, 70 eg. guest register writes, stores, and assignments to temporaries. 71 Expressions (type 'IRExpr') represent operations without 72 side-effects, eg. arithmetic operations, loads, constants. 73 Expressions can contain sub-expressions, forming expression trees, 74 eg. (3 + (4 * load(addr1)). 75 76 Storage of guest state 77 ~~~~~~~~~~~~~~~~~~~~~~ 78 The "guest state" contains the guest registers of the guest machine 79 (ie. the machine that we are simulating). It is stored by default 80 in a block of memory supplied by the user of the VEX library, 81 generally referred to as the guest state (area). To operate on 82 these registers, one must first read ("Get") them from the guest 83 state into a temporary value. Afterwards, one can write ("Put") 84 them back into the guest state. 85 86 Get and Put are characterised by a byte offset into the guest 87 state, a small integer which effectively gives the identity of the 88 referenced guest register, and a type, which indicates the size of 89 the value to be transferred. 90 91 The basic "Get" and "Put" operations are sufficient to model normal 92 fixed registers on the guest. Selected areas of the guest state 93 can be treated as a circular array of registers (type: 94 'IRRegArray'), which can be indexed at run-time. This is done with 95 the "GetI" and "PutI" primitives. This is necessary to describe 96 rotating register files, for example the x87 FPU stack, SPARC 97 register windows, and the Itanium register files. 98 99 Examples, and flattened vs. unflattened code 100 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 101 For example, consider this x86 instruction: 102 103 addl %eax, %ebx 104 105 One Vex IR translation for this code would be this: 106 107 ------ IMark(0x24F275, 7, 0) ------ 108 t3 = GET:I32(0) # get %eax, a 32-bit integer 109 t2 = GET:I32(12) # get %ebx, a 32-bit integer 110 t1 = Add32(t3,t2) # addl 111 PUT(0) = t1 # put %eax 112 113 (For simplicity, this ignores the effects on the condition codes, and 114 the update of the instruction pointer.) 115 116 The "IMark" is an IR statement that doesn't represent actual code. 117 Instead it indicates the address and length of the original 118 instruction. The numbers 0 and 12 are offsets into the guest state 119 for %eax and %ebx. The full list of offsets for an architecture 120 <ARCH> can be found in the type VexGuest<ARCH>State in the file 121 VEX/pub/libvex_guest_<ARCH>.h. 122 123 The five statements in this example are: 124 - the IMark 125 - three assignments to temporaries 126 - one register write (put) 127 128 The six expressions in this example are: 129 - two register reads (gets) 130 - one arithmetic (add) operation 131 - three temporaries (two nested within the Add32, one in the PUT) 132 133 The above IR is "flattened", ie. all sub-expressions are "atoms", 134 either constants or temporaries. An equivalent, unflattened version 135 would be: 136 137 PUT(0) = Add32(GET:I32(0), GET:I32(12)) 138 139 IR is guaranteed to be flattened at instrumentation-time. This makes 140 instrumentation easier. Equivalent flattened and unflattened IR 141 typically results in the same generated code. 142 143 Another example, this one showing loads and stores: 144 145 addl %edx,4(%eax) 146 147 This becomes (again ignoring condition code and instruction pointer 148 updates): 149 150 ------ IMark(0x4000ABA, 3, 0) ------ 151 t3 = Add32(GET:I32(0),0x4:I32) 152 t2 = LDle:I32(t3) 153 t1 = GET:I32(8) 154 t0 = Add32(t2,t1) 155 STle(t3) = t0 156 157 The "le" in "LDle" and "STle" is short for "little-endian". 158 159 No need for deallocations 160 ~~~~~~~~~~~~~~~~~~~~~~~~~ 161 Although there are allocation functions for various data structures 162 in this file, there are no deallocation functions. This is because 163 Vex uses a memory allocation scheme that automatically reclaims the 164 memory used by allocated structures once translation is completed. 165 This makes things easier for tools that instruments/transforms code 166 blocks. 167 168 SSAness and typing 169 ~~~~~~~~~~~~~~~~~~ 170 The IR is fully typed. For every IRSB (IR block) it is possible to 171 say unambiguously whether or not it is correctly typed. 172 Incorrectly typed IR has no meaning and the VEX will refuse to 173 process it. At various points during processing VEX typechecks the 174 IR and aborts if any violations are found. This seems overkill but 175 makes it a great deal easier to build a reliable JIT. 176 177 IR also has the SSA property. SSA stands for Static Single 178 Assignment, and what it means is that each IR temporary may be 179 assigned to only once. This idea became widely used in compiler 180 construction in the mid to late 90s. It makes many IR-level 181 transformations/code improvements easier, simpler and faster. 182 Whenever it typechecks an IR block, VEX also checks the SSA 183 property holds, and will abort if not so. So SSAness is 184 mechanically and rigidly enforced. 185*/ 186 187/*---------------------------------------------------------------*/ 188/*--- Type definitions for the IR ---*/ 189/*---------------------------------------------------------------*/ 190 191/* General comments about naming schemes: 192 193 All publically visible functions contain the name of the primary 194 type on which they operate (IRFoo, IRBar, etc). Hence you should 195 be able to identify these functions by grepping for "IR[A-Z]". 196 197 For some type 'IRFoo': 198 199 - ppIRFoo is the printing method for IRFoo, printing it to the 200 output channel specified in the LibVEX_Initialise call. 201 202 - eqIRFoo is a structural equality predicate for IRFoos. 203 204 - deepCopyIRFoo is a deep copy constructor for IRFoos. 205 It recursively traverses the entire argument tree and 206 produces a complete new tree. All types have a deep copy 207 constructor. 208 209 - shallowCopyIRFoo is the shallow copy constructor for IRFoos. 210 It creates a new top-level copy of the supplied object, 211 but does not copy any sub-objects. Only some types have a 212 shallow copy constructor. 213*/ 214 215/* ------------------ Types ------------------ */ 216 217/* A type indicates the size of a value, and whether it's an integer, a 218 float, or a vector (SIMD) value. */ 219typedef 220 enum { 221 Ity_INVALID=0x1100, 222 Ity_I1, 223 Ity_I8, 224 Ity_I16, 225 Ity_I32, 226 Ity_I64, 227 Ity_I128, /* 128-bit scalar */ 228 Ity_F16, /* 16 bit float */ 229 Ity_F32, /* IEEE 754 float */ 230 Ity_F64, /* IEEE 754 double */ 231 Ity_D32, /* 32-bit Decimal floating point */ 232 Ity_D64, /* 64-bit Decimal floating point */ 233 Ity_D128, /* 128-bit Decimal floating point */ 234 Ity_F128, /* 128-bit floating point; implementation defined */ 235 Ity_V128, /* 128-bit SIMD */ 236 Ity_V256 /* 256-bit SIMD */ 237 } 238 IRType; 239 240/* Pretty-print an IRType */ 241extern void ppIRType ( IRType ); 242 243/* Get the size (in bytes) of an IRType */ 244extern Int sizeofIRType ( IRType ); 245 246/* Translate 1/2/4/8 into Ity_I{8,16,32,64} respectively. Asserts on 247 any other input. */ 248extern IRType integerIRTypeOfSize ( Int szB ); 249 250 251/* ------------------ Endianness ------------------ */ 252 253/* IREndness is used in load IRExprs and store IRStmts. */ 254typedef 255 enum { 256 Iend_LE=0x1200, /* little endian */ 257 Iend_BE /* big endian */ 258 } 259 IREndness; 260 261 262/* ------------------ Constants ------------------ */ 263 264/* IRConsts are used within 'Const' and 'Exit' IRExprs. */ 265 266/* The various kinds of constant. */ 267typedef 268 enum { 269 Ico_U1=0x1300, 270 Ico_U8, 271 Ico_U16, 272 Ico_U32, 273 Ico_U64, 274 Ico_F32, /* 32-bit IEEE754 floating */ 275 Ico_F32i, /* 32-bit unsigned int to be interpreted literally 276 as a IEEE754 single value. */ 277 Ico_F64, /* 64-bit IEEE754 floating */ 278 Ico_F64i, /* 64-bit unsigned int to be interpreted literally 279 as a IEEE754 double value. */ 280 Ico_V128, /* 128-bit restricted vector constant, with 1 bit 281 (repeated 8 times) for each of the 16 x 1-byte lanes */ 282 Ico_V256 /* 256-bit restricted vector constant, with 1 bit 283 (repeated 8 times) for each of the 32 x 1-byte lanes */ 284 } 285 IRConstTag; 286 287/* A constant. Stored as a tagged union. 'tag' indicates what kind of 288 constant this is. 'Ico' is the union that holds the fields. If an 289 IRConst 'c' has c.tag equal to Ico_U32, then it's a 32-bit constant, 290 and its value can be accessed with 'c.Ico.U32'. */ 291typedef 292 struct _IRConst { 293 IRConstTag tag; 294 union { 295 Bool U1; 296 UChar U8; 297 UShort U16; 298 UInt U32; 299 ULong U64; 300 Float F32; 301 UInt F32i; 302 Double F64; 303 ULong F64i; 304 UShort V128; /* 16-bit value; see Ico_V128 comment above */ 305 UInt V256; /* 32-bit value; see Ico_V256 comment above */ 306 } Ico; 307 } 308 IRConst; 309 310/* IRConst constructors */ 311extern IRConst* IRConst_U1 ( Bool ); 312extern IRConst* IRConst_U8 ( UChar ); 313extern IRConst* IRConst_U16 ( UShort ); 314extern IRConst* IRConst_U32 ( UInt ); 315extern IRConst* IRConst_U64 ( ULong ); 316extern IRConst* IRConst_F32 ( Float ); 317extern IRConst* IRConst_F32i ( UInt ); 318extern IRConst* IRConst_F64 ( Double ); 319extern IRConst* IRConst_F64i ( ULong ); 320extern IRConst* IRConst_V128 ( UShort ); 321extern IRConst* IRConst_V256 ( UInt ); 322 323/* Deep-copy an IRConst */ 324extern IRConst* deepCopyIRConst ( const IRConst* ); 325 326/* Pretty-print an IRConst */ 327extern void ppIRConst ( const IRConst* ); 328 329/* Compare two IRConsts for equality */ 330extern Bool eqIRConst ( const IRConst*, const IRConst* ); 331 332 333/* ------------------ Call targets ------------------ */ 334 335/* Describes a helper function to call. The name part is purely for 336 pretty printing and not actually used. regparms=n tells the back 337 end that the callee has been declared 338 "__attribute__((regparm(n)))", although indirectly using the 339 VEX_REGPARM(n) macro. On some targets (x86) the back end will need 340 to construct a non-standard sequence to call a function declared 341 like this. 342 343 mcx_mask is a sop to Memcheck. It indicates which args should be 344 considered 'always defined' when lazily computing definedness of 345 the result. Bit 0 of mcx_mask corresponds to args[0], bit 1 to 346 args[1], etc. If a bit is set, the corresponding arg is excluded 347 (hence "x" in "mcx") from definedness checking. 348*/ 349 350typedef 351 struct { 352 Int regparms; 353 const HChar* name; 354 void* addr; 355 UInt mcx_mask; 356 } 357 IRCallee; 358 359/* Create an IRCallee. */ 360extern IRCallee* mkIRCallee ( Int regparms, const HChar* name, void* addr ); 361 362/* Deep-copy an IRCallee. */ 363extern IRCallee* deepCopyIRCallee ( const IRCallee* ); 364 365/* Pretty-print an IRCallee. */ 366extern void ppIRCallee ( const IRCallee* ); 367 368 369/* ------------------ Guest state arrays ------------------ */ 370 371/* This describes a section of the guest state that we want to 372 be able to index at run time, so as to be able to describe 373 indexed or rotating register files on the guest. */ 374typedef 375 struct { 376 Int base; /* guest state offset of start of indexed area */ 377 IRType elemTy; /* type of each element in the indexed area */ 378 Int nElems; /* number of elements in the indexed area */ 379 } 380 IRRegArray; 381 382extern IRRegArray* mkIRRegArray ( Int, IRType, Int ); 383 384extern IRRegArray* deepCopyIRRegArray ( const IRRegArray* ); 385 386extern void ppIRRegArray ( const IRRegArray* ); 387extern Bool eqIRRegArray ( const IRRegArray*, const IRRegArray* ); 388 389 390/* ------------------ Temporaries ------------------ */ 391 392/* This represents a temporary, eg. t1. The IR optimiser relies on the 393 fact that IRTemps are 32-bit ints. Do not change them to be ints of 394 any other size. */ 395typedef UInt IRTemp; 396 397/* Pretty-print an IRTemp. */ 398extern void ppIRTemp ( IRTemp ); 399 400#define IRTemp_INVALID ((IRTemp)0xFFFFFFFF) 401 402 403/* --------------- Primops (arity 1,2,3 and 4) --------------- */ 404 405/* Primitive operations that are used in Unop, Binop, Triop and Qop 406 IRExprs. Once we take into account integer, floating point and SIMD 407 operations of all the different sizes, there are quite a lot of them. 408 Most instructions supported by the architectures that Vex supports 409 (x86, PPC, etc) are represented. Some more obscure ones (eg. cpuid) 410 are not; they are instead handled with dirty helpers that emulate 411 their functionality. Such obscure ones are thus not directly visible 412 in the IR, but their effects on guest state (memory and registers) 413 are made visible via the annotations in IRDirty structures. 414*/ 415typedef 416 enum { 417 /* -- Do not change this ordering. The IR generators rely on 418 (eg) Iop_Add64 == IopAdd8 + 3. -- */ 419 420 Iop_INVALID=0x1400, 421 Iop_Add8, Iop_Add16, Iop_Add32, Iop_Add64, 422 Iop_Sub8, Iop_Sub16, Iop_Sub32, Iop_Sub64, 423 /* Signless mul. MullS/MullU is elsewhere. */ 424 Iop_Mul8, Iop_Mul16, Iop_Mul32, Iop_Mul64, 425 Iop_Or8, Iop_Or16, Iop_Or32, Iop_Or64, 426 Iop_And8, Iop_And16, Iop_And32, Iop_And64, 427 Iop_Xor8, Iop_Xor16, Iop_Xor32, Iop_Xor64, 428 Iop_Shl8, Iop_Shl16, Iop_Shl32, Iop_Shl64, 429 Iop_Shr8, Iop_Shr16, Iop_Shr32, Iop_Shr64, 430 Iop_Sar8, Iop_Sar16, Iop_Sar32, Iop_Sar64, 431 /* Integer comparisons. */ 432 Iop_CmpEQ8, Iop_CmpEQ16, Iop_CmpEQ32, Iop_CmpEQ64, 433 Iop_CmpNE8, Iop_CmpNE16, Iop_CmpNE32, Iop_CmpNE64, 434 /* Tags for unary ops */ 435 Iop_Not8, Iop_Not16, Iop_Not32, Iop_Not64, 436 437 /* Exactly like CmpEQ8/16/32/64, but carrying the additional 438 hint that these compute the success/failure of a CAS 439 operation, and hence are almost certainly applied to two 440 copies of the same value, which in turn has implications for 441 Memcheck's instrumentation. */ 442 Iop_CasCmpEQ8, Iop_CasCmpEQ16, Iop_CasCmpEQ32, Iop_CasCmpEQ64, 443 Iop_CasCmpNE8, Iop_CasCmpNE16, Iop_CasCmpNE32, Iop_CasCmpNE64, 444 445 /* Exactly like CmpNE8/16/32/64, but carrying the additional 446 hint that these needs expensive definedness tracking. */ 447 Iop_ExpCmpNE8, Iop_ExpCmpNE16, Iop_ExpCmpNE32, Iop_ExpCmpNE64, 448 449 /* -- Ordering not important after here. -- */ 450 451 /* Widening multiplies */ 452 Iop_MullS8, Iop_MullS16, Iop_MullS32, Iop_MullS64, 453 Iop_MullU8, Iop_MullU16, Iop_MullU32, Iop_MullU64, 454 455 /* Wierdo integer stuff */ 456 Iop_Clz64, Iop_Clz32, /* count leading zeroes */ 457 Iop_Ctz64, Iop_Ctz32, /* count trailing zeros */ 458 /* Ctz64/Ctz32/Clz64/Clz32 are UNDEFINED when given arguments of 459 zero. You must ensure they are never given a zero argument. 460 */ 461 462 /* Standard integer comparisons */ 463 Iop_CmpLT32S, Iop_CmpLT64S, 464 Iop_CmpLE32S, Iop_CmpLE64S, 465 Iop_CmpLT32U, Iop_CmpLT64U, 466 Iop_CmpLE32U, Iop_CmpLE64U, 467 468 /* As a sop to Valgrind-Memcheck, the following are useful. */ 469 Iop_CmpNEZ8, Iop_CmpNEZ16, Iop_CmpNEZ32, Iop_CmpNEZ64, 470 Iop_CmpwNEZ32, Iop_CmpwNEZ64, /* all-0s -> all-Os; other -> all-1s */ 471 Iop_Left8, Iop_Left16, Iop_Left32, Iop_Left64, /* \x -> x | -x */ 472 Iop_Max32U, /* unsigned max */ 473 474 /* PowerPC-style 3-way integer comparisons. Without them it is 475 difficult to simulate PPC efficiently. 476 op(x,y) | x < y = 0x8 else 477 | x > y = 0x4 else 478 | x == y = 0x2 479 */ 480 Iop_CmpORD32U, Iop_CmpORD64U, 481 Iop_CmpORD32S, Iop_CmpORD64S, 482 483 /* Division */ 484 /* TODO: clarify semantics wrt rounding, negative values, whatever */ 485 Iop_DivU32, // :: I32,I32 -> I32 (simple div, no mod) 486 Iop_DivS32, // ditto, signed 487 Iop_DivU64, // :: I64,I64 -> I64 (simple div, no mod) 488 Iop_DivS64, // ditto, signed 489 Iop_DivU64E, // :: I64,I64 -> I64 (dividend is 64-bit arg (hi) 490 // concat with 64 0's (low)) 491 Iop_DivS64E, // ditto, signed 492 Iop_DivU32E, // :: I32,I32 -> I32 (dividend is 32-bit arg (hi) 493 // concat with 32 0's (low)) 494 Iop_DivS32E, // ditto, signed 495 496 Iop_DivModU64to32, // :: I64,I32 -> I64 497 // of which lo half is div and hi half is mod 498 Iop_DivModS64to32, // ditto, signed 499 500 Iop_DivModU128to64, // :: V128,I64 -> V128 501 // of which lo half is div and hi half is mod 502 Iop_DivModS128to64, // ditto, signed 503 504 Iop_DivModS64to64, // :: I64,I64 -> I128 505 // of which lo half is div and hi half is mod 506 507 /* Integer conversions. Some of these are redundant (eg 508 Iop_64to8 is the same as Iop_64to32 and then Iop_32to8), but 509 having a complete set reduces the typical dynamic size of IR 510 and makes the instruction selectors easier to write. */ 511 512 /* Widening conversions */ 513 Iop_8Uto16, Iop_8Uto32, Iop_8Uto64, 514 Iop_16Uto32, Iop_16Uto64, 515 Iop_32Uto64, 516 Iop_8Sto16, Iop_8Sto32, Iop_8Sto64, 517 Iop_16Sto32, Iop_16Sto64, 518 Iop_32Sto64, 519 520 /* Narrowing conversions */ 521 Iop_64to8, Iop_32to8, Iop_64to16, 522 /* 8 <-> 16 bit conversions */ 523 Iop_16to8, // :: I16 -> I8, low half 524 Iop_16HIto8, // :: I16 -> I8, high half 525 Iop_8HLto16, // :: (I8,I8) -> I16 526 /* 16 <-> 32 bit conversions */ 527 Iop_32to16, // :: I32 -> I16, low half 528 Iop_32HIto16, // :: I32 -> I16, high half 529 Iop_16HLto32, // :: (I16,I16) -> I32 530 /* 32 <-> 64 bit conversions */ 531 Iop_64to32, // :: I64 -> I32, low half 532 Iop_64HIto32, // :: I64 -> I32, high half 533 Iop_32HLto64, // :: (I32,I32) -> I64 534 /* 64 <-> 128 bit conversions */ 535 Iop_128to64, // :: I128 -> I64, low half 536 Iop_128HIto64, // :: I128 -> I64, high half 537 Iop_64HLto128, // :: (I64,I64) -> I128 538 /* 1-bit stuff */ 539 Iop_Not1, /* :: Ity_Bit -> Ity_Bit */ 540 Iop_32to1, /* :: Ity_I32 -> Ity_Bit, just select bit[0] */ 541 Iop_64to1, /* :: Ity_I64 -> Ity_Bit, just select bit[0] */ 542 Iop_1Uto8, /* :: Ity_Bit -> Ity_I8, unsigned widen */ 543 Iop_1Uto32, /* :: Ity_Bit -> Ity_I32, unsigned widen */ 544 Iop_1Uto64, /* :: Ity_Bit -> Ity_I64, unsigned widen */ 545 Iop_1Sto8, /* :: Ity_Bit -> Ity_I8, signed widen */ 546 Iop_1Sto16, /* :: Ity_Bit -> Ity_I16, signed widen */ 547 Iop_1Sto32, /* :: Ity_Bit -> Ity_I32, signed widen */ 548 Iop_1Sto64, /* :: Ity_Bit -> Ity_I64, signed widen */ 549 550 /* ------ Floating point. We try to be IEEE754 compliant. ------ */ 551 552 /* --- Simple stuff as mandated by 754. --- */ 553 554 /* Binary operations, with rounding. */ 555 /* :: IRRoundingMode(I32) x F64 x F64 -> F64 */ 556 Iop_AddF64, Iop_SubF64, Iop_MulF64, Iop_DivF64, 557 558 /* :: IRRoundingMode(I32) x F32 x F32 -> F32 */ 559 Iop_AddF32, Iop_SubF32, Iop_MulF32, Iop_DivF32, 560 561 /* Variants of the above which produce a 64-bit result but which 562 round their result to a IEEE float range first. */ 563 /* :: IRRoundingMode(I32) x F64 x F64 -> F64 */ 564 Iop_AddF64r32, Iop_SubF64r32, Iop_MulF64r32, Iop_DivF64r32, 565 566 /* Unary operations, without rounding. */ 567 /* :: F64 -> F64 */ 568 Iop_NegF64, Iop_AbsF64, 569 570 /* :: F32 -> F32 */ 571 Iop_NegF32, Iop_AbsF32, 572 573 /* Unary operations, with rounding. */ 574 /* :: IRRoundingMode(I32) x F64 -> F64 */ 575 Iop_SqrtF64, 576 577 /* :: IRRoundingMode(I32) x F32 -> F32 */ 578 Iop_SqrtF32, 579 580 /* Comparison, yielding GT/LT/EQ/UN(ordered), as per the following: 581 0x45 Unordered 582 0x01 LT 583 0x00 GT 584 0x40 EQ 585 This just happens to be the Intel encoding. The values 586 are recorded in the type IRCmpF64Result. 587 */ 588 /* :: F64 x F64 -> IRCmpF64Result(I32) */ 589 Iop_CmpF64, 590 Iop_CmpF32, 591 Iop_CmpF128, 592 593 /* --- Int to/from FP conversions. --- */ 594 595 /* For the most part, these take a first argument :: Ity_I32 (as 596 IRRoundingMode) which is an indication of the rounding mode 597 to use, as per the following encoding ("the standard 598 encoding"): 599 00b to nearest (the default) 600 01b to -infinity 601 10b to +infinity 602 11b to zero 603 This just happens to be the Intel encoding. For reference only, 604 the PPC encoding is: 605 00b to nearest (the default) 606 01b to zero 607 10b to +infinity 608 11b to -infinity 609 Any PPC -> IR front end will have to translate these PPC 610 encodings, as encoded in the guest state, to the standard 611 encodings, to pass to the primops. 612 For reference only, the ARM VFP encoding is: 613 00b to nearest 614 01b to +infinity 615 10b to -infinity 616 11b to zero 617 Again, this will have to be converted to the standard encoding 618 to pass to primops. 619 620 If one of these conversions gets an out-of-range condition, 621 or a NaN, as an argument, the result is host-defined. On x86 622 the "integer indefinite" value 0x80..00 is produced. On PPC 623 it is either 0x80..00 or 0x7F..FF depending on the sign of 624 the argument. 625 626 On ARMvfp, when converting to a signed integer result, the 627 overflow result is 0x80..00 for negative args and 0x7F..FF 628 for positive args. For unsigned integer results it is 629 0x00..00 and 0xFF..FF respectively. 630 631 Rounding is required whenever the destination type cannot 632 represent exactly all values of the source type. 633 */ 634 Iop_F64toI16S, /* IRRoundingMode(I32) x F64 -> signed I16 */ 635 Iop_F64toI32S, /* IRRoundingMode(I32) x F64 -> signed I32 */ 636 Iop_F64toI64S, /* IRRoundingMode(I32) x F64 -> signed I64 */ 637 Iop_F64toI64U, /* IRRoundingMode(I32) x F64 -> unsigned I64 */ 638 639 Iop_F64toI32U, /* IRRoundingMode(I32) x F64 -> unsigned I32 */ 640 641 Iop_I32StoF64, /* signed I32 -> F64 */ 642 Iop_I64StoF64, /* IRRoundingMode(I32) x signed I64 -> F64 */ 643 Iop_I64UtoF64, /* IRRoundingMode(I32) x unsigned I64 -> F64 */ 644 Iop_I64UtoF32, /* IRRoundingMode(I32) x unsigned I64 -> F32 */ 645 646 Iop_I32UtoF32, /* IRRoundingMode(I32) x unsigned I32 -> F32 */ 647 Iop_I32UtoF64, /* unsigned I32 -> F64 */ 648 649 Iop_F32toI32S, /* IRRoundingMode(I32) x F32 -> signed I32 */ 650 Iop_F32toI64S, /* IRRoundingMode(I32) x F32 -> signed I64 */ 651 Iop_F32toI32U, /* IRRoundingMode(I32) x F32 -> unsigned I32 */ 652 Iop_F32toI64U, /* IRRoundingMode(I32) x F32 -> unsigned I64 */ 653 654 Iop_I32StoF32, /* IRRoundingMode(I32) x signed I32 -> F32 */ 655 Iop_I64StoF32, /* IRRoundingMode(I32) x signed I64 -> F32 */ 656 657 /* Conversion between floating point formats */ 658 Iop_F32toF64, /* F32 -> F64 */ 659 Iop_F64toF32, /* IRRoundingMode(I32) x F64 -> F32 */ 660 661 /* Reinterpretation. Take an F64 and produce an I64 with 662 the same bit pattern, or vice versa. */ 663 Iop_ReinterpF64asI64, Iop_ReinterpI64asF64, 664 Iop_ReinterpF32asI32, Iop_ReinterpI32asF32, 665 666 /* Support for 128-bit floating point */ 667 Iop_F64HLtoF128,/* (high half of F128,low half of F128) -> F128 */ 668 Iop_F128HItoF64,/* F128 -> high half of F128 into a F64 register */ 669 Iop_F128LOtoF64,/* F128 -> low half of F128 into a F64 register */ 670 671 /* :: IRRoundingMode(I32) x F128 x F128 -> F128 */ 672 Iop_AddF128, Iop_SubF128, Iop_MulF128, Iop_DivF128, 673 674 /* :: F128 -> F128 */ 675 Iop_NegF128, Iop_AbsF128, 676 677 /* :: IRRoundingMode(I32) x F128 -> F128 */ 678 Iop_SqrtF128, 679 680 Iop_I32StoF128, /* signed I32 -> F128 */ 681 Iop_I64StoF128, /* signed I64 -> F128 */ 682 Iop_I32UtoF128, /* unsigned I32 -> F128 */ 683 Iop_I64UtoF128, /* unsigned I64 -> F128 */ 684 Iop_F32toF128, /* F32 -> F128 */ 685 Iop_F64toF128, /* F64 -> F128 */ 686 687 Iop_F128toI32S, /* IRRoundingMode(I32) x F128 -> signed I32 */ 688 Iop_F128toI64S, /* IRRoundingMode(I32) x F128 -> signed I64 */ 689 Iop_F128toI32U, /* IRRoundingMode(I32) x F128 -> unsigned I32 */ 690 Iop_F128toI64U, /* IRRoundingMode(I32) x F128 -> unsigned I64 */ 691 Iop_F128toF64, /* IRRoundingMode(I32) x F128 -> F64 */ 692 Iop_F128toF32, /* IRRoundingMode(I32) x F128 -> F32 */ 693 694 /* --- guest x86/amd64 specifics, not mandated by 754. --- */ 695 696 /* Binary ops, with rounding. */ 697 /* :: IRRoundingMode(I32) x F64 x F64 -> F64 */ 698 Iop_AtanF64, /* FPATAN, arctan(arg1/arg2) */ 699 Iop_Yl2xF64, /* FYL2X, arg1 * log2(arg2) */ 700 Iop_Yl2xp1F64, /* FYL2XP1, arg1 * log2(arg2+1.0) */ 701 Iop_PRemF64, /* FPREM, non-IEEE remainder(arg1/arg2) */ 702 Iop_PRemC3210F64, /* C3210 flags resulting from FPREM, :: I32 */ 703 Iop_PRem1F64, /* FPREM1, IEEE remainder(arg1/arg2) */ 704 Iop_PRem1C3210F64, /* C3210 flags resulting from FPREM1, :: I32 */ 705 Iop_ScaleF64, /* FSCALE, arg1 * (2^RoundTowardsZero(arg2)) */ 706 /* Note that on x86 guest, PRem1{C3210} has the same behaviour 707 as the IEEE mandated RemF64, except it is limited in the 708 range of its operand. Hence the partialness. */ 709 710 /* Unary ops, with rounding. */ 711 /* :: IRRoundingMode(I32) x F64 -> F64 */ 712 Iop_SinF64, /* FSIN */ 713 Iop_CosF64, /* FCOS */ 714 Iop_TanF64, /* FTAN */ 715 Iop_2xm1F64, /* (2^arg - 1.0) */ 716 Iop_RoundF64toInt, /* F64 value to nearest integral value (still 717 as F64) */ 718 Iop_RoundF32toInt, /* F32 value to nearest integral value (still 719 as F32) */ 720 721 /* --- guest s390 specifics, not mandated by 754. --- */ 722 723 /* Fused multiply-add/sub */ 724 /* :: IRRoundingMode(I32) x F32 x F32 x F32 -> F32 725 (computes arg2 * arg3 +/- arg4) */ 726 Iop_MAddF32, Iop_MSubF32, 727 728 /* --- guest ppc32/64 specifics, not mandated by 754. --- */ 729 730 /* Ternary operations, with rounding. */ 731 /* Fused multiply-add/sub, with 112-bit intermediate 732 precision for ppc. 733 Also used to implement fused multiply-add/sub for s390. */ 734 /* :: IRRoundingMode(I32) x F64 x F64 x F64 -> F64 735 (computes arg2 * arg3 +/- arg4) */ 736 Iop_MAddF64, Iop_MSubF64, 737 738 /* Variants of the above which produce a 64-bit result but which 739 round their result to a IEEE float range first. */ 740 /* :: IRRoundingMode(I32) x F64 x F64 x F64 -> F64 */ 741 Iop_MAddF64r32, Iop_MSubF64r32, 742 743 /* :: F64 -> F64 */ 744 Iop_RSqrtEst5GoodF64, /* reciprocal square root estimate, 5 good bits */ 745 Iop_RoundF64toF64_NEAREST, /* frin */ 746 Iop_RoundF64toF64_NegINF, /* frim */ 747 Iop_RoundF64toF64_PosINF, /* frip */ 748 Iop_RoundF64toF64_ZERO, /* friz */ 749 750 /* :: F64 -> F32 */ 751 Iop_TruncF64asF32, /* do F64->F32 truncation as per 'fsts' */ 752 753 /* :: IRRoundingMode(I32) x F64 -> F64 */ 754 Iop_RoundF64toF32, /* round F64 to nearest F32 value (still as F64) */ 755 /* NB: pretty much the same as Iop_F64toF32, except no change 756 of type. */ 757 758 /* --- guest arm64 specifics, not mandated by 754. --- */ 759 760 Iop_RecpExpF64, /* FRECPX d :: IRRoundingMode(I32) x F64 -> F64 */ 761 Iop_RecpExpF32, /* FRECPX s :: IRRoundingMode(I32) x F32 -> F32 */ 762 763 /* ------------------ 16-bit scalar FP ------------------ */ 764 765 Iop_F16toF64, /* F16 -> F64 */ 766 Iop_F64toF16, /* IRRoundingMode(I32) x F64 -> F16 */ 767 768 Iop_F16toF32, /* F16 -> F32 */ 769 Iop_F32toF16, /* IRRoundingMode(I32) x F32 -> F16 */ 770 771 /* ------------------ 32-bit SIMD Integer ------------------ */ 772 773 /* 32x1 saturating add/sub (ok, well, not really SIMD :) */ 774 Iop_QAdd32S, 775 Iop_QSub32S, 776 777 /* 16x2 add/sub, also signed/unsigned saturating variants */ 778 Iop_Add16x2, Iop_Sub16x2, 779 Iop_QAdd16Sx2, Iop_QAdd16Ux2, 780 Iop_QSub16Sx2, Iop_QSub16Ux2, 781 782 /* 16x2 signed/unsigned halving add/sub. For each lane, these 783 compute bits 16:1 of (eg) sx(argL) + sx(argR), 784 or zx(argL) - zx(argR) etc. */ 785 Iop_HAdd16Ux2, Iop_HAdd16Sx2, 786 Iop_HSub16Ux2, Iop_HSub16Sx2, 787 788 /* 8x4 add/sub, also signed/unsigned saturating variants */ 789 Iop_Add8x4, Iop_Sub8x4, 790 Iop_QAdd8Sx4, Iop_QAdd8Ux4, 791 Iop_QSub8Sx4, Iop_QSub8Ux4, 792 793 /* 8x4 signed/unsigned halving add/sub. For each lane, these 794 compute bits 8:1 of (eg) sx(argL) + sx(argR), 795 or zx(argL) - zx(argR) etc. */ 796 Iop_HAdd8Ux4, Iop_HAdd8Sx4, 797 Iop_HSub8Ux4, Iop_HSub8Sx4, 798 799 /* 8x4 sum of absolute unsigned differences. */ 800 Iop_Sad8Ux4, 801 802 /* MISC (vector integer cmp != 0) */ 803 Iop_CmpNEZ16x2, Iop_CmpNEZ8x4, 804 805 /* ------------------ 64-bit SIMD FP ------------------------ */ 806 807 /* Convertion to/from int */ 808 Iop_I32UtoFx2, Iop_I32StoFx2, /* I32x4 -> F32x4 */ 809 Iop_FtoI32Ux2_RZ, Iop_FtoI32Sx2_RZ, /* F32x4 -> I32x4 */ 810 /* Fixed32 format is floating-point number with fixed number of fraction 811 bits. The number of fraction bits is passed as a second argument of 812 type I8. */ 813 Iop_F32ToFixed32Ux2_RZ, Iop_F32ToFixed32Sx2_RZ, /* fp -> fixed-point */ 814 Iop_Fixed32UToF32x2_RN, Iop_Fixed32SToF32x2_RN, /* fixed-point -> fp */ 815 816 /* Binary operations */ 817 Iop_Max32Fx2, Iop_Min32Fx2, 818 /* Pairwise Min and Max. See integer pairwise operations for more 819 details. */ 820 Iop_PwMax32Fx2, Iop_PwMin32Fx2, 821 /* Note: For the following compares, the arm front-end assumes a 822 nan in a lane of either argument returns zero for that lane. */ 823 Iop_CmpEQ32Fx2, Iop_CmpGT32Fx2, Iop_CmpGE32Fx2, 824 825 /* Vector Reciprocal Estimate finds an approximate reciprocal of each 826 element in the operand vector, and places the results in the destination 827 vector. */ 828 Iop_RecipEst32Fx2, 829 830 /* Vector Reciprocal Step computes (2.0 - arg1 * arg2). 831 Note, that if one of the arguments is zero and another one is infinity 832 of arbitrary sign the result of the operation is 2.0. */ 833 Iop_RecipStep32Fx2, 834 835 /* Vector Reciprocal Square Root Estimate finds an approximate reciprocal 836 square root of each element in the operand vector. */ 837 Iop_RSqrtEst32Fx2, 838 839 /* Vector Reciprocal Square Root Step computes (3.0 - arg1 * arg2) / 2.0. 840 Note, that of one of the arguments is zero and another one is infiinty 841 of arbitrary sign the result of the operation is 1.5. */ 842 Iop_RSqrtStep32Fx2, 843 844 /* Unary */ 845 Iop_Neg32Fx2, Iop_Abs32Fx2, 846 847 /* ------------------ 64-bit SIMD Integer. ------------------ */ 848 849 /* MISC (vector integer cmp != 0) */ 850 Iop_CmpNEZ8x8, Iop_CmpNEZ16x4, Iop_CmpNEZ32x2, 851 852 /* ADDITION (normal / unsigned sat / signed sat) */ 853 Iop_Add8x8, Iop_Add16x4, Iop_Add32x2, 854 Iop_QAdd8Ux8, Iop_QAdd16Ux4, Iop_QAdd32Ux2, Iop_QAdd64Ux1, 855 Iop_QAdd8Sx8, Iop_QAdd16Sx4, Iop_QAdd32Sx2, Iop_QAdd64Sx1, 856 857 /* PAIRWISE operations */ 858 /* Iop_PwFoo16x4( [a,b,c,d], [e,f,g,h] ) = 859 [Foo16(a,b), Foo16(c,d), Foo16(e,f), Foo16(g,h)] */ 860 Iop_PwAdd8x8, Iop_PwAdd16x4, Iop_PwAdd32x2, 861 Iop_PwMax8Sx8, Iop_PwMax16Sx4, Iop_PwMax32Sx2, 862 Iop_PwMax8Ux8, Iop_PwMax16Ux4, Iop_PwMax32Ux2, 863 Iop_PwMin8Sx8, Iop_PwMin16Sx4, Iop_PwMin32Sx2, 864 Iop_PwMin8Ux8, Iop_PwMin16Ux4, Iop_PwMin32Ux2, 865 /* Longening variant is unary. The resulting vector contains two times 866 less elements than operand, but they are two times wider. 867 Example: 868 Iop_PAddL16Ux4( [a,b,c,d] ) = [a+b,c+d] 869 where a+b and c+d are unsigned 32-bit values. */ 870 Iop_PwAddL8Ux8, Iop_PwAddL16Ux4, Iop_PwAddL32Ux2, 871 Iop_PwAddL8Sx8, Iop_PwAddL16Sx4, Iop_PwAddL32Sx2, 872 873 /* SUBTRACTION (normal / unsigned sat / signed sat) */ 874 Iop_Sub8x8, Iop_Sub16x4, Iop_Sub32x2, 875 Iop_QSub8Ux8, Iop_QSub16Ux4, Iop_QSub32Ux2, Iop_QSub64Ux1, 876 Iop_QSub8Sx8, Iop_QSub16Sx4, Iop_QSub32Sx2, Iop_QSub64Sx1, 877 878 /* ABSOLUTE VALUE */ 879 Iop_Abs8x8, Iop_Abs16x4, Iop_Abs32x2, 880 881 /* MULTIPLICATION (normal / high half of signed/unsigned / plynomial ) */ 882 Iop_Mul8x8, Iop_Mul16x4, Iop_Mul32x2, 883 Iop_Mul32Fx2, 884 Iop_MulHi16Ux4, 885 Iop_MulHi16Sx4, 886 /* Plynomial multiplication treats it's arguments as coefficients of 887 polynoms over {0, 1}. */ 888 Iop_PolynomialMul8x8, 889 890 /* Vector Saturating Doubling Multiply Returning High Half and 891 Vector Saturating Rounding Doubling Multiply Returning High Half */ 892 /* These IROp's multiply corresponding elements in two vectors, double 893 the results, and place the most significant half of the final results 894 in the destination vector. The results are truncated or rounded. If 895 any of the results overflow, they are saturated. */ 896 Iop_QDMulHi16Sx4, Iop_QDMulHi32Sx2, 897 Iop_QRDMulHi16Sx4, Iop_QRDMulHi32Sx2, 898 899 /* AVERAGING: note: (arg1 + arg2 + 1) >>u 1 */ 900 Iop_Avg8Ux8, 901 Iop_Avg16Ux4, 902 903 /* MIN/MAX */ 904 Iop_Max8Sx8, Iop_Max16Sx4, Iop_Max32Sx2, 905 Iop_Max8Ux8, Iop_Max16Ux4, Iop_Max32Ux2, 906 Iop_Min8Sx8, Iop_Min16Sx4, Iop_Min32Sx2, 907 Iop_Min8Ux8, Iop_Min16Ux4, Iop_Min32Ux2, 908 909 /* COMPARISON */ 910 Iop_CmpEQ8x8, Iop_CmpEQ16x4, Iop_CmpEQ32x2, 911 Iop_CmpGT8Ux8, Iop_CmpGT16Ux4, Iop_CmpGT32Ux2, 912 Iop_CmpGT8Sx8, Iop_CmpGT16Sx4, Iop_CmpGT32Sx2, 913 914 /* COUNT ones / leading zeroes / leading sign bits (not including topmost 915 bit) */ 916 Iop_Cnt8x8, 917 Iop_Clz8x8, Iop_Clz16x4, Iop_Clz32x2, 918 Iop_Cls8x8, Iop_Cls16x4, Iop_Cls32x2, 919 Iop_Clz64x2, 920 921 /* VECTOR x VECTOR SHIFT / ROTATE */ 922 Iop_Shl8x8, Iop_Shl16x4, Iop_Shl32x2, 923 Iop_Shr8x8, Iop_Shr16x4, Iop_Shr32x2, 924 Iop_Sar8x8, Iop_Sar16x4, Iop_Sar32x2, 925 Iop_Sal8x8, Iop_Sal16x4, Iop_Sal32x2, Iop_Sal64x1, 926 927 /* VECTOR x SCALAR SHIFT (shift amt :: Ity_I8) */ 928 Iop_ShlN8x8, Iop_ShlN16x4, Iop_ShlN32x2, 929 Iop_ShrN8x8, Iop_ShrN16x4, Iop_ShrN32x2, 930 Iop_SarN8x8, Iop_SarN16x4, Iop_SarN32x2, 931 932 /* VECTOR x VECTOR SATURATING SHIFT */ 933 Iop_QShl8x8, Iop_QShl16x4, Iop_QShl32x2, Iop_QShl64x1, 934 Iop_QSal8x8, Iop_QSal16x4, Iop_QSal32x2, Iop_QSal64x1, 935 /* VECTOR x INTEGER SATURATING SHIFT */ 936 Iop_QShlNsatSU8x8, Iop_QShlNsatSU16x4, 937 Iop_QShlNsatSU32x2, Iop_QShlNsatSU64x1, 938 Iop_QShlNsatUU8x8, Iop_QShlNsatUU16x4, 939 Iop_QShlNsatUU32x2, Iop_QShlNsatUU64x1, 940 Iop_QShlNsatSS8x8, Iop_QShlNsatSS16x4, 941 Iop_QShlNsatSS32x2, Iop_QShlNsatSS64x1, 942 943 /* NARROWING (binary) 944 -- narrow 2xI64 into 1xI64, hi half from left arg */ 945 /* For saturated narrowing, I believe there are 4 variants of 946 the basic arithmetic operation, depending on the signedness 947 of argument and result. Here are examples that exemplify 948 what I mean: 949 950 QNarrow16Uto8U ( UShort x ) if (x >u 255) x = 255; 951 return x[7:0]; 952 953 QNarrow16Sto8S ( Short x ) if (x <s -128) x = -128; 954 if (x >s 127) x = 127; 955 return x[7:0]; 956 957 QNarrow16Uto8S ( UShort x ) if (x >u 127) x = 127; 958 return x[7:0]; 959 960 QNarrow16Sto8U ( Short x ) if (x <s 0) x = 0; 961 if (x >s 255) x = 255; 962 return x[7:0]; 963 */ 964 Iop_QNarrowBin16Sto8Ux8, 965 Iop_QNarrowBin16Sto8Sx8, Iop_QNarrowBin32Sto16Sx4, 966 Iop_NarrowBin16to8x8, Iop_NarrowBin32to16x4, 967 968 /* INTERLEAVING */ 969 /* Interleave lanes from low or high halves of 970 operands. Most-significant result lane is from the left 971 arg. */ 972 Iop_InterleaveHI8x8, Iop_InterleaveHI16x4, Iop_InterleaveHI32x2, 973 Iop_InterleaveLO8x8, Iop_InterleaveLO16x4, Iop_InterleaveLO32x2, 974 /* Interleave odd/even lanes of operands. Most-significant result lane 975 is from the left arg. Note that Interleave{Odd,Even}Lanes32x2 are 976 identical to Interleave{HI,LO}32x2 and so are omitted.*/ 977 Iop_InterleaveOddLanes8x8, Iop_InterleaveEvenLanes8x8, 978 Iop_InterleaveOddLanes16x4, Iop_InterleaveEvenLanes16x4, 979 980 /* CONCATENATION -- build a new value by concatenating either 981 the even or odd lanes of both operands. Note that 982 Cat{Odd,Even}Lanes32x2 are identical to Interleave{HI,LO}32x2 983 and so are omitted. */ 984 Iop_CatOddLanes8x8, Iop_CatOddLanes16x4, 985 Iop_CatEvenLanes8x8, Iop_CatEvenLanes16x4, 986 987 /* GET / SET elements of VECTOR 988 GET is binop (I64, I8) -> I<elem_size> 989 SET is triop (I64, I8, I<elem_size>) -> I64 */ 990 /* Note: the arm back-end handles only constant second argument */ 991 Iop_GetElem8x8, Iop_GetElem16x4, Iop_GetElem32x2, 992 Iop_SetElem8x8, Iop_SetElem16x4, Iop_SetElem32x2, 993 994 /* DUPLICATING -- copy value to all lanes */ 995 Iop_Dup8x8, Iop_Dup16x4, Iop_Dup32x2, 996 997 /* SLICE -- produces the lowest 64 bits of (arg1:arg2) >> (8 * arg3). 998 arg3 is a shift amount in bytes and may be between 0 and 8 999 inclusive. When 0, the result is arg2; when 8, the result is arg1. 1000 Not all back ends handle all values. The arm32 and arm64 back 1001 ends handle only immediate arg3 values. */ 1002 Iop_Slice64, // (I64, I64, I8) -> I64 1003 1004 /* REVERSE the order of chunks in vector lanes. Chunks must be 1005 smaller than the vector lanes (obviously) and so may be 8-, 1006 16- and 32-bit in size. */ 1007 /* Examples: 1008 Reverse8sIn16_x4([a,b,c,d,e,f,g,h]) = [b,a,d,c,f,e,h,g] 1009 Reverse8sIn32_x2([a,b,c,d,e,f,g,h]) = [d,c,b,a,h,g,f,e] 1010 Reverse8sIn64_x1([a,b,c,d,e,f,g,h]) = [h,g,f,e,d,c,b,a] */ 1011 Iop_Reverse8sIn16_x4, 1012 Iop_Reverse8sIn32_x2, Iop_Reverse16sIn32_x2, 1013 Iop_Reverse8sIn64_x1, Iop_Reverse16sIn64_x1, Iop_Reverse32sIn64_x1, 1014 1015 /* PERMUTING -- copy src bytes to dst, 1016 as indexed by control vector bytes: 1017 for i in 0 .. 7 . result[i] = argL[ argR[i] ] 1018 argR[i] values may only be in the range 0 .. 7, else behaviour 1019 is undefined. */ 1020 Iop_Perm8x8, 1021 1022 /* MISC CONVERSION -- get high bits of each byte lane, a la 1023 x86/amd64 pmovmskb */ 1024 Iop_GetMSBs8x8, /* I64 -> I8 */ 1025 1026 /* Vector Reciprocal Estimate and Vector Reciprocal Square Root Estimate 1027 See floating-point equivalents for details. */ 1028 Iop_RecipEst32Ux2, Iop_RSqrtEst32Ux2, 1029 1030 /* ------------------ Decimal Floating Point ------------------ */ 1031 1032 /* ARITHMETIC INSTRUCTIONS 64-bit 1033 ---------------------------------- 1034 IRRoundingMode(I32) X D64 X D64 -> D64 1035 */ 1036 Iop_AddD64, Iop_SubD64, Iop_MulD64, Iop_DivD64, 1037 1038 /* ARITHMETIC INSTRUCTIONS 128-bit 1039 ---------------------------------- 1040 IRRoundingMode(I32) X D128 X D128 -> D128 1041 */ 1042 Iop_AddD128, Iop_SubD128, Iop_MulD128, Iop_DivD128, 1043 1044 /* SHIFT SIGNIFICAND INSTRUCTIONS 1045 * The DFP significand is shifted by the number of digits specified 1046 * by the U8 operand. Digits shifted out of the leftmost digit are 1047 * lost. Zeros are supplied to the vacated positions on the right. 1048 * The sign of the result is the same as the sign of the original 1049 * operand. 1050 * 1051 * D64 x U8 -> D64 left shift and right shift respectively */ 1052 Iop_ShlD64, Iop_ShrD64, 1053 1054 /* D128 x U8 -> D128 left shift and right shift respectively */ 1055 Iop_ShlD128, Iop_ShrD128, 1056 1057 1058 /* FORMAT CONVERSION INSTRUCTIONS 1059 * D32 -> D64 1060 */ 1061 Iop_D32toD64, 1062 1063 /* D64 -> D128 */ 1064 Iop_D64toD128, 1065 1066 /* I32S -> D128 */ 1067 Iop_I32StoD128, 1068 1069 /* I32U -> D128 */ 1070 Iop_I32UtoD128, 1071 1072 /* I64S -> D128 */ 1073 Iop_I64StoD128, 1074 1075 /* I64U -> D128 */ 1076 Iop_I64UtoD128, 1077 1078 /* IRRoundingMode(I32) x D64 -> D32 */ 1079 Iop_D64toD32, 1080 1081 /* IRRoundingMode(I32) x D128 -> D64 */ 1082 Iop_D128toD64, 1083 1084 /* I32S -> D64 */ 1085 Iop_I32StoD64, 1086 1087 /* I32U -> D64 */ 1088 Iop_I32UtoD64, 1089 1090 /* IRRoundingMode(I32) x I64 -> D64 */ 1091 Iop_I64StoD64, 1092 1093 /* IRRoundingMode(I32) x I64 -> D64 */ 1094 Iop_I64UtoD64, 1095 1096 /* IRRoundingMode(I32) x D64 -> I32 */ 1097 Iop_D64toI32S, 1098 1099 /* IRRoundingMode(I32) x D64 -> I32 */ 1100 Iop_D64toI32U, 1101 1102 /* IRRoundingMode(I32) x D64 -> I64 */ 1103 Iop_D64toI64S, 1104 1105 /* IRRoundingMode(I32) x D64 -> I64 */ 1106 Iop_D64toI64U, 1107 1108 /* IRRoundingMode(I32) x D128 -> I32 */ 1109 Iop_D128toI32S, 1110 1111 /* IRRoundingMode(I32) x D128 -> I32 */ 1112 Iop_D128toI32U, 1113 1114 /* IRRoundingMode(I32) x D128 -> I64 */ 1115 Iop_D128toI64S, 1116 1117 /* IRRoundingMode(I32) x D128 -> I64 */ 1118 Iop_D128toI64U, 1119 1120 /* IRRoundingMode(I32) x F32 -> D32 */ 1121 Iop_F32toD32, 1122 1123 /* IRRoundingMode(I32) x F32 -> D64 */ 1124 Iop_F32toD64, 1125 1126 /* IRRoundingMode(I32) x F32 -> D128 */ 1127 Iop_F32toD128, 1128 1129 /* IRRoundingMode(I32) x F64 -> D32 */ 1130 Iop_F64toD32, 1131 1132 /* IRRoundingMode(I32) x F64 -> D64 */ 1133 Iop_F64toD64, 1134 1135 /* IRRoundingMode(I32) x F64 -> D128 */ 1136 Iop_F64toD128, 1137 1138 /* IRRoundingMode(I32) x F128 -> D32 */ 1139 Iop_F128toD32, 1140 1141 /* IRRoundingMode(I32) x F128 -> D64 */ 1142 Iop_F128toD64, 1143 1144 /* IRRoundingMode(I32) x F128 -> D128 */ 1145 Iop_F128toD128, 1146 1147 /* IRRoundingMode(I32) x D32 -> F32 */ 1148 Iop_D32toF32, 1149 1150 /* IRRoundingMode(I32) x D32 -> F64 */ 1151 Iop_D32toF64, 1152 1153 /* IRRoundingMode(I32) x D32 -> F128 */ 1154 Iop_D32toF128, 1155 1156 /* IRRoundingMode(I32) x D64 -> F32 */ 1157 Iop_D64toF32, 1158 1159 /* IRRoundingMode(I32) x D64 -> F64 */ 1160 Iop_D64toF64, 1161 1162 /* IRRoundingMode(I32) x D64 -> F128 */ 1163 Iop_D64toF128, 1164 1165 /* IRRoundingMode(I32) x D128 -> F32 */ 1166 Iop_D128toF32, 1167 1168 /* IRRoundingMode(I32) x D128 -> F64 */ 1169 Iop_D128toF64, 1170 1171 /* IRRoundingMode(I32) x D128 -> F128 */ 1172 Iop_D128toF128, 1173 1174 /* ROUNDING INSTRUCTIONS 1175 * IRRoundingMode(I32) x D64 -> D64 1176 * The D64 operand, if a finite number, it is rounded to a 1177 * floating point integer value, i.e. no fractional part. 1178 */ 1179 Iop_RoundD64toInt, 1180 1181 /* IRRoundingMode(I32) x D128 -> D128 */ 1182 Iop_RoundD128toInt, 1183 1184 /* COMPARE INSTRUCTIONS 1185 * D64 x D64 -> IRCmpD64Result(I32) */ 1186 Iop_CmpD64, 1187 1188 /* D128 x D128 -> IRCmpD128Result(I32) */ 1189 Iop_CmpD128, 1190 1191 /* COMPARE BIASED EXPONENET INSTRUCTIONS 1192 * D64 x D64 -> IRCmpD64Result(I32) */ 1193 Iop_CmpExpD64, 1194 1195 /* D128 x D128 -> IRCmpD128Result(I32) */ 1196 Iop_CmpExpD128, 1197 1198 /* QUANTIZE AND ROUND INSTRUCTIONS 1199 * The source operand is converted and rounded to the form with the 1200 * immediate exponent specified by the rounding and exponent parameter. 1201 * 1202 * The second operand is converted and rounded to the form 1203 * of the first operand's exponent and the rounded based on the specified 1204 * rounding mode parameter. 1205 * 1206 * IRRoundingMode(I32) x D64 x D64-> D64 */ 1207 Iop_QuantizeD64, 1208 1209 /* IRRoundingMode(I32) x D128 x D128 -> D128 */ 1210 Iop_QuantizeD128, 1211 1212 /* IRRoundingMode(I32) x I8 x D64 -> D64 1213 * The Decimal Floating point operand is rounded to the requested 1214 * significance given by the I8 operand as specified by the rounding 1215 * mode. 1216 */ 1217 Iop_SignificanceRoundD64, 1218 1219 /* IRRoundingMode(I32) x I8 x D128 -> D128 */ 1220 Iop_SignificanceRoundD128, 1221 1222 /* EXTRACT AND INSERT INSTRUCTIONS 1223 * D64 -> I64 1224 * The exponent of the D32 or D64 operand is extracted. The 1225 * extracted exponent is converted to a 64-bit signed binary integer. 1226 */ 1227 Iop_ExtractExpD64, 1228 1229 /* D128 -> I64 */ 1230 Iop_ExtractExpD128, 1231 1232 /* D64 -> I64 1233 * The number of significand digits of the D64 operand is extracted. 1234 * The number is stored as a 64-bit signed binary integer. 1235 */ 1236 Iop_ExtractSigD64, 1237 1238 /* D128 -> I64 */ 1239 Iop_ExtractSigD128, 1240 1241 /* I64 x D64 -> D64 1242 * The exponent is specified by the first I64 operand the signed 1243 * significand is given by the second I64 value. The result is a D64 1244 * value consisting of the specified significand and exponent whose 1245 * sign is that of the specified significand. 1246 */ 1247 Iop_InsertExpD64, 1248 1249 /* I64 x D128 -> D128 */ 1250 Iop_InsertExpD128, 1251 1252 /* Support for 128-bit DFP type */ 1253 Iop_D64HLtoD128, Iop_D128HItoD64, Iop_D128LOtoD64, 1254 1255 /* I64 -> I64 1256 * Convert 50-bit densely packed BCD string to 60 bit BCD string 1257 */ 1258 Iop_DPBtoBCD, 1259 1260 /* I64 -> I64 1261 * Convert 60 bit BCD string to 50-bit densely packed BCD string 1262 */ 1263 Iop_BCDtoDPB, 1264 1265 /* BCD arithmetic instructions, (V128, V128) -> V128 1266 * The BCD format is the same as that used in the BCD<->DPB conversion 1267 * routines, except using 124 digits (vs 60) plus the trailing 4-bit 1268 * signed code. */ 1269 Iop_BCDAdd, Iop_BCDSub, 1270 1271 /* Conversion I64 -> D64 */ 1272 Iop_ReinterpI64asD64, 1273 1274 /* Conversion D64 -> I64 */ 1275 Iop_ReinterpD64asI64, 1276 1277 /* ------------------ 128-bit SIMD FP. ------------------ */ 1278 1279 /* --- 32x4 vector FP --- */ 1280 1281 /* ternary :: IRRoundingMode(I32) x V128 x V128 -> V128 */ 1282 Iop_Add32Fx4, Iop_Sub32Fx4, Iop_Mul32Fx4, Iop_Div32Fx4, 1283 1284 /* binary */ 1285 Iop_Max32Fx4, Iop_Min32Fx4, 1286 Iop_Add32Fx2, Iop_Sub32Fx2, 1287 /* Note: For the following compares, the ppc and arm front-ends assume a 1288 nan in a lane of either argument returns zero for that lane. */ 1289 Iop_CmpEQ32Fx4, Iop_CmpLT32Fx4, Iop_CmpLE32Fx4, Iop_CmpUN32Fx4, 1290 Iop_CmpGT32Fx4, Iop_CmpGE32Fx4, 1291 1292 /* Pairwise Max and Min. See integer pairwise operations for details. */ 1293 Iop_PwMax32Fx4, Iop_PwMin32Fx4, 1294 1295 /* unary */ 1296 Iop_Abs32Fx4, 1297 Iop_Neg32Fx4, 1298 1299 /* binary :: IRRoundingMode(I32) x V128 -> V128 */ 1300 Iop_Sqrt32Fx4, 1301 1302 /* Vector Reciprocal Estimate finds an approximate reciprocal of each 1303 element in the operand vector, and places the results in the 1304 destination vector. */ 1305 Iop_RecipEst32Fx4, 1306 1307 /* Vector Reciprocal Step computes (2.0 - arg1 * arg2). 1308 Note, that if one of the arguments is zero and another one is infinity 1309 of arbitrary sign the result of the operation is 2.0. */ 1310 Iop_RecipStep32Fx4, 1311 1312 /* Vector Reciprocal Square Root Estimate finds an approximate reciprocal 1313 square root of each element in the operand vector. */ 1314 Iop_RSqrtEst32Fx4, 1315 1316 /* Vector Reciprocal Square Root Step computes (3.0 - arg1 * arg2) / 2.0. 1317 Note, that of one of the arguments is zero and another one is infiinty 1318 of arbitrary sign the result of the operation is 1.5. */ 1319 Iop_RSqrtStep32Fx4, 1320 1321 /* --- Int to/from FP conversion --- */ 1322 /* Unlike the standard fp conversions, these irops take no 1323 rounding mode argument. Instead the irop trailers _R{M,P,N,Z} 1324 indicate the mode: {-inf, +inf, nearest, zero} respectively. */ 1325 Iop_I32UtoFx4, Iop_I32StoFx4, /* I32x4 -> F32x4 */ 1326 Iop_FtoI32Ux4_RZ, Iop_FtoI32Sx4_RZ, /* F32x4 -> I32x4 */ 1327 Iop_QFtoI32Ux4_RZ, Iop_QFtoI32Sx4_RZ, /* F32x4 -> I32x4 (saturating) */ 1328 Iop_RoundF32x4_RM, Iop_RoundF32x4_RP, /* round to fp integer */ 1329 Iop_RoundF32x4_RN, Iop_RoundF32x4_RZ, /* round to fp integer */ 1330 /* Fixed32 format is floating-point number with fixed number of fraction 1331 bits. The number of fraction bits is passed as a second argument of 1332 type I8. */ 1333 Iop_F32ToFixed32Ux4_RZ, Iop_F32ToFixed32Sx4_RZ, /* fp -> fixed-point */ 1334 Iop_Fixed32UToF32x4_RN, Iop_Fixed32SToF32x4_RN, /* fixed-point -> fp */ 1335 1336 /* --- Single to/from half conversion --- */ 1337 /* FIXME: what kind of rounding in F32x4 -> F16x4 case? */ 1338 Iop_F32toF16x4, Iop_F16toF32x4, /* F32x4 <-> F16x4 */ 1339 1340 /* --- 32x4 lowest-lane-only scalar FP --- */ 1341 1342 /* In binary cases, upper 3/4 is copied from first operand. In 1343 unary cases, upper 3/4 is copied from the operand. */ 1344 1345 /* binary */ 1346 Iop_Add32F0x4, Iop_Sub32F0x4, Iop_Mul32F0x4, Iop_Div32F0x4, 1347 Iop_Max32F0x4, Iop_Min32F0x4, 1348 Iop_CmpEQ32F0x4, Iop_CmpLT32F0x4, Iop_CmpLE32F0x4, Iop_CmpUN32F0x4, 1349 1350 /* unary */ 1351 Iop_RecipEst32F0x4, Iop_Sqrt32F0x4, Iop_RSqrtEst32F0x4, 1352 1353 /* --- 64x2 vector FP --- */ 1354 1355 /* ternary :: IRRoundingMode(I32) x V128 x V128 -> V128 */ 1356 Iop_Add64Fx2, Iop_Sub64Fx2, Iop_Mul64Fx2, Iop_Div64Fx2, 1357 1358 /* binary */ 1359 Iop_Max64Fx2, Iop_Min64Fx2, 1360 Iop_CmpEQ64Fx2, Iop_CmpLT64Fx2, Iop_CmpLE64Fx2, Iop_CmpUN64Fx2, 1361 1362 /* unary */ 1363 Iop_Abs64Fx2, 1364 Iop_Neg64Fx2, 1365 1366 /* binary :: IRRoundingMode(I32) x V128 -> V128 */ 1367 Iop_Sqrt64Fx2, 1368 1369 /* see 32Fx4 variants for description */ 1370 Iop_RecipEst64Fx2, // unary 1371 Iop_RecipStep64Fx2, // binary 1372 Iop_RSqrtEst64Fx2, // unary 1373 Iop_RSqrtStep64Fx2, // binary 1374 1375 /* --- 64x2 lowest-lane-only scalar FP --- */ 1376 1377 /* In binary cases, upper half is copied from first operand. In 1378 unary cases, upper half is copied from the operand. */ 1379 1380 /* binary */ 1381 Iop_Add64F0x2, Iop_Sub64F0x2, Iop_Mul64F0x2, Iop_Div64F0x2, 1382 Iop_Max64F0x2, Iop_Min64F0x2, 1383 Iop_CmpEQ64F0x2, Iop_CmpLT64F0x2, Iop_CmpLE64F0x2, Iop_CmpUN64F0x2, 1384 1385 /* unary */ 1386 Iop_Sqrt64F0x2, 1387 1388 /* --- pack / unpack --- */ 1389 1390 /* 64 <-> 128 bit vector */ 1391 Iop_V128to64, // :: V128 -> I64, low half 1392 Iop_V128HIto64, // :: V128 -> I64, high half 1393 Iop_64HLtoV128, // :: (I64,I64) -> V128 1394 1395 Iop_64UtoV128, 1396 Iop_SetV128lo64, 1397 1398 /* Copies lower 64/32/16/8 bits, zeroes out the rest. */ 1399 Iop_ZeroHI64ofV128, // :: V128 -> V128 1400 Iop_ZeroHI96ofV128, // :: V128 -> V128 1401 Iop_ZeroHI112ofV128, // :: V128 -> V128 1402 Iop_ZeroHI120ofV128, // :: V128 -> V128 1403 1404 /* 32 <-> 128 bit vector */ 1405 Iop_32UtoV128, 1406 Iop_V128to32, // :: V128 -> I32, lowest lane 1407 Iop_SetV128lo32, // :: (V128,I32) -> V128 1408 1409 /* ------------------ 128-bit SIMD Integer. ------------------ */ 1410 1411 /* BITWISE OPS */ 1412 Iop_NotV128, 1413 Iop_AndV128, Iop_OrV128, Iop_XorV128, 1414 1415 /* VECTOR SHIFT (shift amt :: Ity_I8) */ 1416 Iop_ShlV128, Iop_ShrV128, 1417 1418 /* MISC (vector integer cmp != 0) */ 1419 Iop_CmpNEZ8x16, Iop_CmpNEZ16x8, Iop_CmpNEZ32x4, Iop_CmpNEZ64x2, 1420 1421 /* ADDITION (normal / U->U sat / S->S sat) */ 1422 Iop_Add8x16, Iop_Add16x8, Iop_Add32x4, Iop_Add64x2, 1423 Iop_QAdd8Ux16, Iop_QAdd16Ux8, Iop_QAdd32Ux4, Iop_QAdd64Ux2, 1424 Iop_QAdd8Sx16, Iop_QAdd16Sx8, Iop_QAdd32Sx4, Iop_QAdd64Sx2, 1425 1426 /* ADDITION, ARM64 specific saturating variants. */ 1427 /* Unsigned widen left arg, signed widen right arg, add, saturate S->S. 1428 This corresponds to SUQADD. */ 1429 Iop_QAddExtUSsatSS8x16, Iop_QAddExtUSsatSS16x8, 1430 Iop_QAddExtUSsatSS32x4, Iop_QAddExtUSsatSS64x2, 1431 /* Signed widen left arg, unsigned widen right arg, add, saturate U->U. 1432 This corresponds to USQADD. */ 1433 Iop_QAddExtSUsatUU8x16, Iop_QAddExtSUsatUU16x8, 1434 Iop_QAddExtSUsatUU32x4, Iop_QAddExtSUsatUU64x2, 1435 1436 /* SUBTRACTION (normal / unsigned sat / signed sat) */ 1437 Iop_Sub8x16, Iop_Sub16x8, Iop_Sub32x4, Iop_Sub64x2, 1438 Iop_QSub8Ux16, Iop_QSub16Ux8, Iop_QSub32Ux4, Iop_QSub64Ux2, 1439 Iop_QSub8Sx16, Iop_QSub16Sx8, Iop_QSub32Sx4, Iop_QSub64Sx2, 1440 1441 /* MULTIPLICATION (normal / high half of signed/unsigned) */ 1442 Iop_Mul8x16, Iop_Mul16x8, Iop_Mul32x4, 1443 Iop_MulHi16Ux8, Iop_MulHi32Ux4, 1444 Iop_MulHi16Sx8, Iop_MulHi32Sx4, 1445 /* (widening signed/unsigned of even lanes, with lowest lane=zero) */ 1446 Iop_MullEven8Ux16, Iop_MullEven16Ux8, Iop_MullEven32Ux4, 1447 Iop_MullEven8Sx16, Iop_MullEven16Sx8, Iop_MullEven32Sx4, 1448 1449 /* Widening multiplies, all of the form (I64, I64) -> V128 */ 1450 Iop_Mull8Ux8, Iop_Mull8Sx8, 1451 Iop_Mull16Ux4, Iop_Mull16Sx4, 1452 Iop_Mull32Ux2, Iop_Mull32Sx2, 1453 1454 /* Signed doubling saturating widening multiplies, (I64, I64) -> V128 */ 1455 Iop_QDMull16Sx4, Iop_QDMull32Sx2, 1456 1457 /* Vector Saturating Doubling Multiply Returning High Half and 1458 Vector Saturating Rounding Doubling Multiply Returning High Half. 1459 These IROps multiply corresponding elements in two vectors, double 1460 the results, and place the most significant half of the final results 1461 in the destination vector. The results are truncated or rounded. If 1462 any of the results overflow, they are saturated. To be more precise, 1463 for each lane, the computed result is: 1464 QDMulHi: 1465 hi-half( sign-extend(laneL) *q sign-extend(laneR) *q 2 ) 1466 QRDMulHi: 1467 hi-half( sign-extend(laneL) *q sign-extend(laneR) *q 2 1468 +q (1 << (lane-width-in-bits - 1)) ) 1469 */ 1470 Iop_QDMulHi16Sx8, Iop_QDMulHi32Sx4, /* (V128, V128) -> V128 */ 1471 Iop_QRDMulHi16Sx8, Iop_QRDMulHi32Sx4, /* (V128, V128) -> V128 */ 1472 1473 /* Polynomial multiplication treats its arguments as 1474 coefficients of polynomials over {0, 1}. */ 1475 Iop_PolynomialMul8x16, /* (V128, V128) -> V128 */ 1476 Iop_PolynomialMull8x8, /* (I64, I64) -> V128 */ 1477 1478 /* Vector Polynomial multiplication add. (V128, V128) -> V128 1479 1480 *** Below is the algorithm for the instructions. These Iops could 1481 be emulated to get this functionality, but the emulation would 1482 be long and messy. 1483 1484 Example for polynomial multiply add for vector of bytes 1485 do i = 0 to 15 1486 prod[i].bit[0:14] <- 0 1487 srcA <- VR[argL].byte[i] 1488 srcB <- VR[argR].byte[i] 1489 do j = 0 to 7 1490 do k = 0 to j 1491 gbit <- srcA.bit[k] & srcB.bit[j-k] 1492 prod[i].bit[j] <- prod[i].bit[j] ^ gbit 1493 end 1494 end 1495 1496 do j = 8 to 14 1497 do k = j-7 to 7 1498 gbit <- (srcA.bit[k] & srcB.bit[j-k]) 1499 prod[i].bit[j] <- prod[i].bit[j] ^ gbit 1500 end 1501 end 1502 end 1503 1504 do i = 0 to 7 1505 VR[dst].hword[i] <- 0b0 || (prod[2×i] ^ prod[2×i+1]) 1506 end 1507 */ 1508 Iop_PolynomialMulAdd8x16, Iop_PolynomialMulAdd16x8, 1509 Iop_PolynomialMulAdd32x4, Iop_PolynomialMulAdd64x2, 1510 1511 /* PAIRWISE operations */ 1512 /* Iop_PwFoo16x4( [a,b,c,d], [e,f,g,h] ) = 1513 [Foo16(a,b), Foo16(c,d), Foo16(e,f), Foo16(g,h)] */ 1514 Iop_PwAdd8x16, Iop_PwAdd16x8, Iop_PwAdd32x4, 1515 Iop_PwAdd32Fx2, 1516 /* Longening variant is unary. The resulting vector contains two times 1517 less elements than operand, but they are two times wider. 1518 Example: 1519 Iop_PwAddL16Ux4( [a,b,c,d] ) = [a+b,c+d] 1520 where a+b and c+d are unsigned 32-bit values. */ 1521 Iop_PwAddL8Ux16, Iop_PwAddL16Ux8, Iop_PwAddL32Ux4, 1522 Iop_PwAddL8Sx16, Iop_PwAddL16Sx8, Iop_PwAddL32Sx4, 1523 1524 /* Other unary pairwise ops */ 1525 1526 /* Vector bit matrix transpose. (V128) -> V128 */ 1527 /* For each doubleword element of the source vector, an 8-bit x 8-bit 1528 * matrix transpose is performed. */ 1529 Iop_PwBitMtxXpose64x2, 1530 1531 /* ABSOLUTE VALUE */ 1532 Iop_Abs8x16, Iop_Abs16x8, Iop_Abs32x4, Iop_Abs64x2, 1533 1534 /* AVERAGING: note: (arg1 + arg2 + 1) >>u 1 */ 1535 Iop_Avg8Ux16, Iop_Avg16Ux8, Iop_Avg32Ux4, 1536 Iop_Avg8Sx16, Iop_Avg16Sx8, Iop_Avg32Sx4, 1537 1538 /* MIN/MAX */ 1539 Iop_Max8Sx16, Iop_Max16Sx8, Iop_Max32Sx4, Iop_Max64Sx2, 1540 Iop_Max8Ux16, Iop_Max16Ux8, Iop_Max32Ux4, Iop_Max64Ux2, 1541 Iop_Min8Sx16, Iop_Min16Sx8, Iop_Min32Sx4, Iop_Min64Sx2, 1542 Iop_Min8Ux16, Iop_Min16Ux8, Iop_Min32Ux4, Iop_Min64Ux2, 1543 1544 /* COMPARISON */ 1545 Iop_CmpEQ8x16, Iop_CmpEQ16x8, Iop_CmpEQ32x4, Iop_CmpEQ64x2, 1546 Iop_CmpGT8Sx16, Iop_CmpGT16Sx8, Iop_CmpGT32Sx4, Iop_CmpGT64Sx2, 1547 Iop_CmpGT8Ux16, Iop_CmpGT16Ux8, Iop_CmpGT32Ux4, Iop_CmpGT64Ux2, 1548 1549 /* COUNT ones / leading zeroes / leading sign bits (not including topmost 1550 bit) */ 1551 Iop_Cnt8x16, 1552 Iop_Clz8x16, Iop_Clz16x8, Iop_Clz32x4, 1553 Iop_Cls8x16, Iop_Cls16x8, Iop_Cls32x4, 1554 1555 /* VECTOR x SCALAR SHIFT (shift amt :: Ity_I8) */ 1556 Iop_ShlN8x16, Iop_ShlN16x8, Iop_ShlN32x4, Iop_ShlN64x2, 1557 Iop_ShrN8x16, Iop_ShrN16x8, Iop_ShrN32x4, Iop_ShrN64x2, 1558 Iop_SarN8x16, Iop_SarN16x8, Iop_SarN32x4, Iop_SarN64x2, 1559 1560 /* VECTOR x VECTOR SHIFT / ROTATE */ 1561 /* FIXME: I'm pretty sure the ARM32 front/back ends interpret these 1562 differently from all other targets. The intention is that 1563 the shift amount (2nd arg) is interpreted as unsigned and 1564 only the lowest log2(lane-bits) bits are relevant. But the 1565 ARM32 versions treat the shift amount as an 8 bit signed 1566 number. The ARM32 uses should be replaced by the relevant 1567 vector x vector bidirectional shifts instead. */ 1568 Iop_Shl8x16, Iop_Shl16x8, Iop_Shl32x4, Iop_Shl64x2, 1569 Iop_Shr8x16, Iop_Shr16x8, Iop_Shr32x4, Iop_Shr64x2, 1570 Iop_Sar8x16, Iop_Sar16x8, Iop_Sar32x4, Iop_Sar64x2, 1571 Iop_Sal8x16, Iop_Sal16x8, Iop_Sal32x4, Iop_Sal64x2, 1572 Iop_Rol8x16, Iop_Rol16x8, Iop_Rol32x4, Iop_Rol64x2, 1573 1574 /* VECTOR x VECTOR SATURATING SHIFT */ 1575 Iop_QShl8x16, Iop_QShl16x8, Iop_QShl32x4, Iop_QShl64x2, 1576 Iop_QSal8x16, Iop_QSal16x8, Iop_QSal32x4, Iop_QSal64x2, 1577 /* VECTOR x INTEGER SATURATING SHIFT */ 1578 Iop_QShlNsatSU8x16, Iop_QShlNsatSU16x8, 1579 Iop_QShlNsatSU32x4, Iop_QShlNsatSU64x2, 1580 Iop_QShlNsatUU8x16, Iop_QShlNsatUU16x8, 1581 Iop_QShlNsatUU32x4, Iop_QShlNsatUU64x2, 1582 Iop_QShlNsatSS8x16, Iop_QShlNsatSS16x8, 1583 Iop_QShlNsatSS32x4, Iop_QShlNsatSS64x2, 1584 1585 /* VECTOR x VECTOR BIDIRECTIONAL SATURATING (& MAYBE ROUNDING) SHIFT */ 1586 /* All of type (V128, V128) -> V256. */ 1587 /* The least significant 8 bits of each lane of the second 1588 operand are used as the shift amount, and interpreted signedly. 1589 Positive values mean a shift left, negative a shift right. The 1590 result is signedly or unsignedly saturated. There are also 1591 rounding variants, which add 2^(shift_amount-1) to the value before 1592 shifting, but only in the shift-right case. Vacated positions 1593 are filled with zeroes. IOW, it's either SHR or SHL, but not SAR. 1594 1595 These operations return 129 bits: one bit ("Q") indicating whether 1596 saturation occurred, and the shift result. The result type is V256, 1597 of which the lower V128 is the shift result, and Q occupies the 1598 least significant bit of the upper V128. All other bits of the 1599 upper V128 are zero. */ 1600 // Unsigned saturation, no rounding 1601 Iop_QandUQsh8x16, Iop_QandUQsh16x8, 1602 Iop_QandUQsh32x4, Iop_QandUQsh64x2, 1603 // Signed saturation, no rounding 1604 Iop_QandSQsh8x16, Iop_QandSQsh16x8, 1605 Iop_QandSQsh32x4, Iop_QandSQsh64x2, 1606 1607 // Unsigned saturation, rounding 1608 Iop_QandUQRsh8x16, Iop_QandUQRsh16x8, 1609 Iop_QandUQRsh32x4, Iop_QandUQRsh64x2, 1610 // Signed saturation, rounding 1611 Iop_QandSQRsh8x16, Iop_QandSQRsh16x8, 1612 Iop_QandSQRsh32x4, Iop_QandSQRsh64x2, 1613 1614 /* VECTOR x VECTOR BIDIRECTIONAL (& MAYBE ROUNDING) SHIFT */ 1615 /* All of type (V128, V128) -> V128 */ 1616 /* The least significant 8 bits of each lane of the second 1617 operand are used as the shift amount, and interpreted signedly. 1618 Positive values mean a shift left, negative a shift right. 1619 There are also rounding variants, which add 2^(shift_amount-1) 1620 to the value before shifting, but only in the shift-right case. 1621 1622 For left shifts, the vacated places are filled with zeroes. 1623 For right shifts, the vacated places are filled with zeroes 1624 for the U variants and sign bits for the S variants. */ 1625 // Signed and unsigned, non-rounding 1626 Iop_Sh8Sx16, Iop_Sh16Sx8, Iop_Sh32Sx4, Iop_Sh64Sx2, 1627 Iop_Sh8Ux16, Iop_Sh16Ux8, Iop_Sh32Ux4, Iop_Sh64Ux2, 1628 1629 // Signed and unsigned, rounding 1630 Iop_Rsh8Sx16, Iop_Rsh16Sx8, Iop_Rsh32Sx4, Iop_Rsh64Sx2, 1631 Iop_Rsh8Ux16, Iop_Rsh16Ux8, Iop_Rsh32Ux4, Iop_Rsh64Ux2, 1632 1633 /* The least significant 8 bits of each lane of the second 1634 operand are used as the shift amount, and interpreted signedly. 1635 Positive values mean a shift left, negative a shift right. The 1636 result is signedly or unsignedly saturated. There are also 1637 rounding variants, which add 2^(shift_amount-1) to the value before 1638 shifting, but only in the shift-right case. Vacated positions 1639 are filled with zeroes. IOW, it's either SHR or SHL, but not SAR. 1640 */ 1641 1642 /* VECTOR x SCALAR SATURATING (& MAYBE ROUNDING) NARROWING SHIFT RIGHT */ 1643 /* All of type (V128, I8) -> V128 */ 1644 /* The first argument is shifted right, then narrowed to half the width 1645 by saturating it. The second argument is a scalar shift amount that 1646 applies to all lanes, and must be a value in the range 1 to lane_width. 1647 The shift may be done signedly (Sar variants) or unsignedly (Shr 1648 variants). The saturation is done according to the two signedness 1649 indicators at the end of the name. For example 64Sto32U means a 1650 signed 64 bit value is saturated into an unsigned 32 bit value. 1651 Additionally, the QRS variants do rounding, that is, they add the 1652 value (1 << (shift_amount-1)) to each source lane before shifting. 1653 1654 These operations return 65 bits: one bit ("Q") indicating whether 1655 saturation occurred, and the shift result. The result type is V128, 1656 of which the lower half is the shift result, and Q occupies the 1657 least significant bit of the upper half. All other bits of the 1658 upper half are zero. */ 1659 // No rounding, sat U->U 1660 Iop_QandQShrNnarrow16Uto8Ux8, 1661 Iop_QandQShrNnarrow32Uto16Ux4, Iop_QandQShrNnarrow64Uto32Ux2, 1662 // No rounding, sat S->S 1663 Iop_QandQSarNnarrow16Sto8Sx8, 1664 Iop_QandQSarNnarrow32Sto16Sx4, Iop_QandQSarNnarrow64Sto32Sx2, 1665 // No rounding, sat S->U 1666 Iop_QandQSarNnarrow16Sto8Ux8, 1667 Iop_QandQSarNnarrow32Sto16Ux4, Iop_QandQSarNnarrow64Sto32Ux2, 1668 1669 // Rounding, sat U->U 1670 Iop_QandQRShrNnarrow16Uto8Ux8, 1671 Iop_QandQRShrNnarrow32Uto16Ux4, Iop_QandQRShrNnarrow64Uto32Ux2, 1672 // Rounding, sat S->S 1673 Iop_QandQRSarNnarrow16Sto8Sx8, 1674 Iop_QandQRSarNnarrow32Sto16Sx4, Iop_QandQRSarNnarrow64Sto32Sx2, 1675 // Rounding, sat S->U 1676 Iop_QandQRSarNnarrow16Sto8Ux8, 1677 Iop_QandQRSarNnarrow32Sto16Ux4, Iop_QandQRSarNnarrow64Sto32Ux2, 1678 1679 /* NARROWING (binary) 1680 -- narrow 2xV128 into 1xV128, hi half from left arg */ 1681 /* See comments above w.r.t. U vs S issues in saturated narrowing. */ 1682 Iop_QNarrowBin16Sto8Ux16, Iop_QNarrowBin32Sto16Ux8, 1683 Iop_QNarrowBin16Sto8Sx16, Iop_QNarrowBin32Sto16Sx8, 1684 Iop_QNarrowBin16Uto8Ux16, Iop_QNarrowBin32Uto16Ux8, 1685 Iop_NarrowBin16to8x16, Iop_NarrowBin32to16x8, 1686 Iop_QNarrowBin64Sto32Sx4, Iop_QNarrowBin64Uto32Ux4, 1687 Iop_NarrowBin64to32x4, 1688 1689 /* NARROWING (unary) -- narrow V128 into I64 */ 1690 Iop_NarrowUn16to8x8, Iop_NarrowUn32to16x4, Iop_NarrowUn64to32x2, 1691 /* Saturating narrowing from signed source to signed/unsigned 1692 destination */ 1693 Iop_QNarrowUn16Sto8Sx8, Iop_QNarrowUn32Sto16Sx4, Iop_QNarrowUn64Sto32Sx2, 1694 Iop_QNarrowUn16Sto8Ux8, Iop_QNarrowUn32Sto16Ux4, Iop_QNarrowUn64Sto32Ux2, 1695 /* Saturating narrowing from unsigned source to unsigned destination */ 1696 Iop_QNarrowUn16Uto8Ux8, Iop_QNarrowUn32Uto16Ux4, Iop_QNarrowUn64Uto32Ux2, 1697 1698 /* WIDENING -- sign or zero extend each element of the argument 1699 vector to the twice original size. The resulting vector consists of 1700 the same number of elements but each element and the vector itself 1701 are twice as wide. 1702 All operations are I64->V128. 1703 Example 1704 Iop_Widen32Sto64x2( [a, b] ) = [c, d] 1705 where c = Iop_32Sto64(a) and d = Iop_32Sto64(b) */ 1706 Iop_Widen8Uto16x8, Iop_Widen16Uto32x4, Iop_Widen32Uto64x2, 1707 Iop_Widen8Sto16x8, Iop_Widen16Sto32x4, Iop_Widen32Sto64x2, 1708 1709 /* INTERLEAVING */ 1710 /* Interleave lanes from low or high halves of 1711 operands. Most-significant result lane is from the left 1712 arg. */ 1713 Iop_InterleaveHI8x16, Iop_InterleaveHI16x8, 1714 Iop_InterleaveHI32x4, Iop_InterleaveHI64x2, 1715 Iop_InterleaveLO8x16, Iop_InterleaveLO16x8, 1716 Iop_InterleaveLO32x4, Iop_InterleaveLO64x2, 1717 /* Interleave odd/even lanes of operands. Most-significant result lane 1718 is from the left arg. */ 1719 Iop_InterleaveOddLanes8x16, Iop_InterleaveEvenLanes8x16, 1720 Iop_InterleaveOddLanes16x8, Iop_InterleaveEvenLanes16x8, 1721 Iop_InterleaveOddLanes32x4, Iop_InterleaveEvenLanes32x4, 1722 1723 /* CONCATENATION -- build a new value by concatenating either 1724 the even or odd lanes of both operands. Note that 1725 Cat{Odd,Even}Lanes64x2 are identical to Interleave{HI,LO}64x2 1726 and so are omitted. */ 1727 Iop_CatOddLanes8x16, Iop_CatOddLanes16x8, Iop_CatOddLanes32x4, 1728 Iop_CatEvenLanes8x16, Iop_CatEvenLanes16x8, Iop_CatEvenLanes32x4, 1729 1730 /* GET elements of VECTOR 1731 GET is binop (V128, I8) -> I<elem_size> */ 1732 /* Note: the arm back-end handles only constant second argument. */ 1733 Iop_GetElem8x16, Iop_GetElem16x8, Iop_GetElem32x4, Iop_GetElem64x2, 1734 1735 /* DUPLICATING -- copy value to all lanes */ 1736 Iop_Dup8x16, Iop_Dup16x8, Iop_Dup32x4, 1737 1738 /* SLICE -- produces the lowest 128 bits of (arg1:arg2) >> (8 * arg3). 1739 arg3 is a shift amount in bytes and may be between 0 and 16 1740 inclusive. When 0, the result is arg2; when 16, the result is arg1. 1741 Not all back ends handle all values. The arm64 back 1742 end handles only immediate arg3 values. */ 1743 Iop_SliceV128, // (V128, V128, I8) -> V128 1744 1745 /* REVERSE the order of chunks in vector lanes. Chunks must be 1746 smaller than the vector lanes (obviously) and so may be 8-, 1747 16- and 32-bit in size. See definitions of 64-bit SIMD 1748 versions above for examples. */ 1749 Iop_Reverse8sIn16_x8, 1750 Iop_Reverse8sIn32_x4, Iop_Reverse16sIn32_x4, 1751 Iop_Reverse8sIn64_x2, Iop_Reverse16sIn64_x2, Iop_Reverse32sIn64_x2, 1752 Iop_Reverse1sIn8_x16, /* Reverse bits in each byte lane. */ 1753 1754 /* PERMUTING -- copy src bytes to dst, 1755 as indexed by control vector bytes: 1756 for i in 0 .. 15 . result[i] = argL[ argR[i] ] 1757 argR[i] values may only be in the range 0 .. 15, else behaviour 1758 is undefined. */ 1759 Iop_Perm8x16, 1760 Iop_Perm32x4, /* ditto, except argR values are restricted to 0 .. 3 */ 1761 1762 /* MISC CONVERSION -- get high bits of each byte lane, a la 1763 x86/amd64 pmovmskb */ 1764 Iop_GetMSBs8x16, /* V128 -> I16 */ 1765 1766 /* Vector Reciprocal Estimate and Vector Reciprocal Square Root Estimate 1767 See floating-point equivalents for details. */ 1768 Iop_RecipEst32Ux4, Iop_RSqrtEst32Ux4, 1769 1770 /* ------------------ 256-bit SIMD Integer. ------------------ */ 1771 1772 /* Pack/unpack */ 1773 Iop_V256to64_0, // V256 -> I64, extract least significant lane 1774 Iop_V256to64_1, 1775 Iop_V256to64_2, 1776 Iop_V256to64_3, // V256 -> I64, extract most significant lane 1777 1778 Iop_64x4toV256, // (I64,I64,I64,I64)->V256 1779 // first arg is most significant lane 1780 1781 Iop_V256toV128_0, // V256 -> V128, less significant lane 1782 Iop_V256toV128_1, // V256 -> V128, more significant lane 1783 Iop_V128HLtoV256, // (V128,V128)->V256, first arg is most signif 1784 1785 Iop_AndV256, 1786 Iop_OrV256, 1787 Iop_XorV256, 1788 Iop_NotV256, 1789 1790 /* MISC (vector integer cmp != 0) */ 1791 Iop_CmpNEZ8x32, Iop_CmpNEZ16x16, Iop_CmpNEZ32x8, Iop_CmpNEZ64x4, 1792 1793 Iop_Add8x32, Iop_Add16x16, Iop_Add32x8, Iop_Add64x4, 1794 Iop_Sub8x32, Iop_Sub16x16, Iop_Sub32x8, Iop_Sub64x4, 1795 1796 Iop_CmpEQ8x32, Iop_CmpEQ16x16, Iop_CmpEQ32x8, Iop_CmpEQ64x4, 1797 Iop_CmpGT8Sx32, Iop_CmpGT16Sx16, Iop_CmpGT32Sx8, Iop_CmpGT64Sx4, 1798 1799 Iop_ShlN16x16, Iop_ShlN32x8, Iop_ShlN64x4, 1800 Iop_ShrN16x16, Iop_ShrN32x8, Iop_ShrN64x4, 1801 Iop_SarN16x16, Iop_SarN32x8, 1802 1803 Iop_Max8Sx32, Iop_Max16Sx16, Iop_Max32Sx8, 1804 Iop_Max8Ux32, Iop_Max16Ux16, Iop_Max32Ux8, 1805 Iop_Min8Sx32, Iop_Min16Sx16, Iop_Min32Sx8, 1806 Iop_Min8Ux32, Iop_Min16Ux16, Iop_Min32Ux8, 1807 1808 Iop_Mul16x16, Iop_Mul32x8, 1809 Iop_MulHi16Ux16, Iop_MulHi16Sx16, 1810 1811 Iop_QAdd8Ux32, Iop_QAdd16Ux16, 1812 Iop_QAdd8Sx32, Iop_QAdd16Sx16, 1813 Iop_QSub8Ux32, Iop_QSub16Ux16, 1814 Iop_QSub8Sx32, Iop_QSub16Sx16, 1815 1816 Iop_Avg8Ux32, Iop_Avg16Ux16, 1817 1818 Iop_Perm32x8, 1819 1820 /* (V128, V128) -> V128 */ 1821 Iop_CipherV128, Iop_CipherLV128, Iop_CipherSV128, 1822 Iop_NCipherV128, Iop_NCipherLV128, 1823 1824 /* Hash instructions, Federal Information Processing Standards 1825 * Publication 180-3 Secure Hash Standard. */ 1826 /* (V128, I8) -> V128; The I8 input arg is (ST | SIX), where ST and 1827 * SIX are fields from the insn. See ISA 2.07 description of 1828 * vshasigmad and vshasigmaw insns.*/ 1829 Iop_SHA512, Iop_SHA256, 1830 1831 /* ------------------ 256-bit SIMD FP. ------------------ */ 1832 1833 /* ternary :: IRRoundingMode(I32) x V256 x V256 -> V256 */ 1834 Iop_Add64Fx4, Iop_Sub64Fx4, Iop_Mul64Fx4, Iop_Div64Fx4, 1835 Iop_Add32Fx8, Iop_Sub32Fx8, Iop_Mul32Fx8, Iop_Div32Fx8, 1836 1837 Iop_Sqrt32Fx8, 1838 Iop_Sqrt64Fx4, 1839 Iop_RSqrtEst32Fx8, 1840 Iop_RecipEst32Fx8, 1841 1842 Iop_Max32Fx8, Iop_Min32Fx8, 1843 Iop_Max64Fx4, Iop_Min64Fx4, 1844 Iop_LAST /* must be the last enumerator */ 1845 } 1846 IROp; 1847 1848/* Pretty-print an op. */ 1849extern void ppIROp ( IROp ); 1850 1851 1852/* Encoding of IEEE754-specified rounding modes. 1853 Note, various front and back ends rely on the actual numerical 1854 values of these, so do not change them. */ 1855typedef 1856 enum { 1857 Irrm_NEAREST = 0, // Round to nearest, ties to even 1858 Irrm_NegINF = 1, // Round to negative infinity 1859 Irrm_PosINF = 2, // Round to positive infinity 1860 Irrm_ZERO = 3, // Round toward zero 1861 Irrm_NEAREST_TIE_AWAY_0 = 4, // Round to nearest, ties away from 0 1862 Irrm_PREPARE_SHORTER = 5, // Round to prepare for shorter 1863 // precision 1864 Irrm_AWAY_FROM_ZERO = 6, // Round to away from 0 1865 Irrm_NEAREST_TIE_TOWARD_0 = 7 // Round to nearest, ties towards 0 1866 } 1867 IRRoundingMode; 1868 1869/* Binary floating point comparison result values. 1870 This is also derived from what IA32 does. */ 1871typedef 1872 enum { 1873 Ircr_UN = 0x45, 1874 Ircr_LT = 0x01, 1875 Ircr_GT = 0x00, 1876 Ircr_EQ = 0x40 1877 } 1878 IRCmpFResult; 1879 1880typedef IRCmpFResult IRCmpF32Result; 1881typedef IRCmpFResult IRCmpF64Result; 1882typedef IRCmpFResult IRCmpF128Result; 1883 1884/* Decimal floating point result values. */ 1885typedef IRCmpFResult IRCmpDResult; 1886typedef IRCmpDResult IRCmpD64Result; 1887typedef IRCmpDResult IRCmpD128Result; 1888 1889/* ------------------ Expressions ------------------ */ 1890 1891typedef struct _IRQop IRQop; /* forward declaration */ 1892typedef struct _IRTriop IRTriop; /* forward declaration */ 1893 1894 1895/* The different kinds of expressions. Their meaning is explained below 1896 in the comments for IRExpr. */ 1897typedef 1898 enum { 1899 Iex_Binder=0x1900, 1900 Iex_Get, 1901 Iex_GetI, 1902 Iex_RdTmp, 1903 Iex_Qop, 1904 Iex_Triop, 1905 Iex_Binop, 1906 Iex_Unop, 1907 Iex_Load, 1908 Iex_Const, 1909 Iex_ITE, 1910 Iex_CCall, 1911 Iex_VECRET, 1912 Iex_BBPTR 1913 } 1914 IRExprTag; 1915 1916/* An expression. Stored as a tagged union. 'tag' indicates what kind 1917 of expression this is. 'Iex' is the union that holds the fields. If 1918 an IRExpr 'e' has e.tag equal to Iex_Load, then it's a load 1919 expression, and the fields can be accessed with 1920 'e.Iex.Load.<fieldname>'. 1921 1922 For each kind of expression, we show what it looks like when 1923 pretty-printed with ppIRExpr(). 1924*/ 1925typedef 1926 struct _IRExpr 1927 IRExpr; 1928 1929struct _IRExpr { 1930 IRExprTag tag; 1931 union { 1932 /* Used only in pattern matching within Vex. Should not be seen 1933 outside of Vex. */ 1934 struct { 1935 Int binder; 1936 } Binder; 1937 1938 /* Read a guest register, at a fixed offset in the guest state. 1939 ppIRExpr output: GET:<ty>(<offset>), eg. GET:I32(0) 1940 */ 1941 struct { 1942 Int offset; /* Offset into the guest state */ 1943 IRType ty; /* Type of the value being read */ 1944 } Get; 1945 1946 /* Read a guest register at a non-fixed offset in the guest 1947 state. This allows circular indexing into parts of the guest 1948 state, which is essential for modelling situations where the 1949 identity of guest registers is not known until run time. One 1950 example is the x87 FP register stack. 1951 1952 The part of the guest state to be treated as a circular array 1953 is described in the IRRegArray 'descr' field. It holds the 1954 offset of the first element in the array, the type of each 1955 element, and the number of elements. 1956 1957 The array index is indicated rather indirectly, in a way 1958 which makes optimisation easy: as the sum of variable part 1959 (the 'ix' field) and a constant offset (the 'bias' field). 1960 1961 Since the indexing is circular, the actual array index to use 1962 is computed as (ix + bias) % num-of-elems-in-the-array. 1963 1964 Here's an example. The description 1965 1966 (96:8xF64)[t39,-7] 1967 1968 describes an array of 8 F64-typed values, the 1969 guest-state-offset of the first being 96. This array is 1970 being indexed at (t39 - 7) % 8. 1971 1972 It is important to get the array size/type exactly correct 1973 since IR optimisation looks closely at such info in order to 1974 establish aliasing/non-aliasing between seperate GetI and 1975 PutI events, which is used to establish when they can be 1976 reordered, etc. Putting incorrect info in will lead to 1977 obscure IR optimisation bugs. 1978 1979 ppIRExpr output: GETI<descr>[<ix>,<bias] 1980 eg. GETI(128:8xI8)[t1,0] 1981 */ 1982 struct { 1983 IRRegArray* descr; /* Part of guest state treated as circular */ 1984 IRExpr* ix; /* Variable part of index into array */ 1985 Int bias; /* Constant offset part of index into array */ 1986 } GetI; 1987 1988 /* The value held by a temporary. 1989 ppIRExpr output: t<tmp>, eg. t1 1990 */ 1991 struct { 1992 IRTemp tmp; /* The temporary number */ 1993 } RdTmp; 1994 1995 /* A quaternary operation. 1996 ppIRExpr output: <op>(<arg1>, <arg2>, <arg3>, <arg4>), 1997 eg. MAddF64r32(t1, t2, t3, t4) 1998 */ 1999 struct { 2000 IRQop* details; 2001 } Qop; 2002 2003 /* A ternary operation. 2004 ppIRExpr output: <op>(<arg1>, <arg2>, <arg3>), 2005 eg. MulF64(1, 2.0, 3.0) 2006 */ 2007 struct { 2008 IRTriop* details; 2009 } Triop; 2010 2011 /* A binary operation. 2012 ppIRExpr output: <op>(<arg1>, <arg2>), eg. Add32(t1,t2) 2013 */ 2014 struct { 2015 IROp op; /* op-code */ 2016 IRExpr* arg1; /* operand 1 */ 2017 IRExpr* arg2; /* operand 2 */ 2018 } Binop; 2019 2020 /* A unary operation. 2021 ppIRExpr output: <op>(<arg>), eg. Neg8(t1) 2022 */ 2023 struct { 2024 IROp op; /* op-code */ 2025 IRExpr* arg; /* operand */ 2026 } Unop; 2027 2028 /* A load from memory -- a normal load, not a load-linked. 2029 Load-Linkeds (and Store-Conditionals) are instead represented 2030 by IRStmt.LLSC since Load-Linkeds have side effects and so 2031 are not semantically valid IRExpr's. 2032 ppIRExpr output: LD<end>:<ty>(<addr>), eg. LDle:I32(t1) 2033 */ 2034 struct { 2035 IREndness end; /* Endian-ness of the load */ 2036 IRType ty; /* Type of the loaded value */ 2037 IRExpr* addr; /* Address being loaded from */ 2038 } Load; 2039 2040 /* A constant-valued expression. 2041 ppIRExpr output: <con>, eg. 0x4:I32 2042 */ 2043 struct { 2044 IRConst* con; /* The constant itself */ 2045 } Const; 2046 2047 /* A call to a pure (no side-effects) helper C function. 2048 2049 With the 'cee' field, 'name' is the function's name. It is 2050 only used for pretty-printing purposes. The address to call 2051 (host address, of course) is stored in the 'addr' field 2052 inside 'cee'. 2053 2054 The 'args' field is a NULL-terminated array of arguments. 2055 The stated return IRType, and the implied argument types, 2056 must match that of the function being called well enough so 2057 that the back end can actually generate correct code for the 2058 call. 2059 2060 The called function **must** satisfy the following: 2061 2062 * no side effects -- must be a pure function, the result of 2063 which depends only on the passed parameters. 2064 2065 * it may not look at, nor modify, any of the guest state 2066 since that would hide guest state transitions from 2067 instrumenters 2068 2069 * it may not access guest memory, since that would hide 2070 guest memory transactions from the instrumenters 2071 2072 * it must not assume that arguments are being evaluated in a 2073 particular order. The oder of evaluation is unspecified. 2074 2075 This is restrictive, but makes the semantics clean, and does 2076 not interfere with IR optimisation. 2077 2078 If you want to call a helper which can mess with guest state 2079 and/or memory, instead use Ist_Dirty. This is a lot more 2080 flexible, but you have to give a bunch of details about what 2081 the helper does (and you better be telling the truth, 2082 otherwise any derived instrumentation will be wrong). Also 2083 Ist_Dirty inhibits various IR optimisations and so can cause 2084 quite poor code to be generated. Try to avoid it. 2085 2086 In principle it would be allowable to have the arg vector 2087 contain an IRExpr_VECRET(), although not IRExpr_BBPTR(). However, 2088 at the moment there is no requirement for clean helper calls to 2089 be able to return V128 or V256 values. Hence this is not allowed. 2090 2091 ppIRExpr output: <cee>(<args>):<retty> 2092 eg. foo{0x80489304}(t1, t2):I32 2093 */ 2094 struct { 2095 IRCallee* cee; /* Function to call. */ 2096 IRType retty; /* Type of return value. */ 2097 IRExpr** args; /* Vector of argument expressions. */ 2098 } CCall; 2099 2100 /* A ternary if-then-else operator. It returns iftrue if cond is 2101 nonzero, iffalse otherwise. Note that it is STRICT, ie. both 2102 iftrue and iffalse are evaluated in all cases. 2103 2104 ppIRExpr output: ITE(<cond>,<iftrue>,<iffalse>), 2105 eg. ITE(t6,t7,t8) 2106 */ 2107 struct { 2108 IRExpr* cond; /* Condition */ 2109 IRExpr* iftrue; /* True expression */ 2110 IRExpr* iffalse; /* False expression */ 2111 } ITE; 2112 } Iex; 2113}; 2114 2115/* Expression auxiliaries: a ternary expression. */ 2116struct _IRTriop { 2117 IROp op; /* op-code */ 2118 IRExpr* arg1; /* operand 1 */ 2119 IRExpr* arg2; /* operand 2 */ 2120 IRExpr* arg3; /* operand 3 */ 2121}; 2122 2123/* Expression auxiliaries: a quarternary expression. */ 2124struct _IRQop { 2125 IROp op; /* op-code */ 2126 IRExpr* arg1; /* operand 1 */ 2127 IRExpr* arg2; /* operand 2 */ 2128 IRExpr* arg3; /* operand 3 */ 2129 IRExpr* arg4; /* operand 4 */ 2130}; 2131 2132 2133/* Two special kinds of IRExpr, which can ONLY be used in 2134 argument lists for dirty helper calls (IRDirty.args) and in NO 2135 OTHER PLACES. And then only in very limited ways. */ 2136 2137/* Denotes an argument which (in the helper) takes a pointer to a 2138 (naturally aligned) V128 or V256, into which the helper is expected 2139 to write its result. Use of IRExpr_VECRET() is strictly 2140 controlled. If the helper returns a V128 or V256 value then 2141 IRExpr_VECRET() must appear exactly once in the arg list, although 2142 it can appear anywhere, and the helper must have a C 'void' return 2143 type. If the helper returns any other type, IRExpr_VECRET() may 2144 not appear in the argument list. */ 2145 2146/* Denotes an void* argument which is passed to the helper, which at 2147 run time will point to the thread's guest state area. This can 2148 only appear at most once in an argument list, and it may not appear 2149 at all in argument lists for clean helper calls. */ 2150 2151static inline Bool is_IRExpr_VECRET_or_BBPTR ( const IRExpr* e ) { 2152 return e->tag == Iex_VECRET || e->tag == Iex_BBPTR; 2153} 2154 2155 2156/* Expression constructors. */ 2157extern IRExpr* IRExpr_Binder ( Int binder ); 2158extern IRExpr* IRExpr_Get ( Int off, IRType ty ); 2159extern IRExpr* IRExpr_GetI ( IRRegArray* descr, IRExpr* ix, Int bias ); 2160extern IRExpr* IRExpr_RdTmp ( IRTemp tmp ); 2161extern IRExpr* IRExpr_Qop ( IROp op, IRExpr* arg1, IRExpr* arg2, 2162 IRExpr* arg3, IRExpr* arg4 ); 2163extern IRExpr* IRExpr_Triop ( IROp op, IRExpr* arg1, 2164 IRExpr* arg2, IRExpr* arg3 ); 2165extern IRExpr* IRExpr_Binop ( IROp op, IRExpr* arg1, IRExpr* arg2 ); 2166extern IRExpr* IRExpr_Unop ( IROp op, IRExpr* arg ); 2167extern IRExpr* IRExpr_Load ( IREndness end, IRType ty, IRExpr* addr ); 2168extern IRExpr* IRExpr_Const ( IRConst* con ); 2169extern IRExpr* IRExpr_CCall ( IRCallee* cee, IRType retty, IRExpr** args ); 2170extern IRExpr* IRExpr_ITE ( IRExpr* cond, IRExpr* iftrue, IRExpr* iffalse ); 2171extern IRExpr* IRExpr_VECRET ( void ); 2172extern IRExpr* IRExpr_BBPTR ( void ); 2173 2174/* Deep-copy an IRExpr. */ 2175extern IRExpr* deepCopyIRExpr ( const IRExpr* ); 2176 2177/* Pretty-print an IRExpr. */ 2178extern void ppIRExpr ( const IRExpr* ); 2179 2180/* NULL-terminated IRExpr vector constructors, suitable for 2181 use as arg lists in clean/dirty helper calls. */ 2182extern IRExpr** mkIRExprVec_0 ( void ); 2183extern IRExpr** mkIRExprVec_1 ( IRExpr* ); 2184extern IRExpr** mkIRExprVec_2 ( IRExpr*, IRExpr* ); 2185extern IRExpr** mkIRExprVec_3 ( IRExpr*, IRExpr*, IRExpr* ); 2186extern IRExpr** mkIRExprVec_4 ( IRExpr*, IRExpr*, IRExpr*, IRExpr* ); 2187extern IRExpr** mkIRExprVec_5 ( IRExpr*, IRExpr*, IRExpr*, IRExpr*, 2188 IRExpr* ); 2189extern IRExpr** mkIRExprVec_6 ( IRExpr*, IRExpr*, IRExpr*, IRExpr*, 2190 IRExpr*, IRExpr* ); 2191extern IRExpr** mkIRExprVec_7 ( IRExpr*, IRExpr*, IRExpr*, IRExpr*, 2192 IRExpr*, IRExpr*, IRExpr* ); 2193extern IRExpr** mkIRExprVec_8 ( IRExpr*, IRExpr*, IRExpr*, IRExpr*, 2194 IRExpr*, IRExpr*, IRExpr*, IRExpr*); 2195 2196/* IRExpr copiers: 2197 - shallowCopy: shallow-copy (ie. create a new vector that shares the 2198 elements with the original). 2199 - deepCopy: deep-copy (ie. create a completely new vector). */ 2200extern IRExpr** shallowCopyIRExprVec ( IRExpr** ); 2201extern IRExpr** deepCopyIRExprVec ( IRExpr *const * ); 2202 2203/* Make a constant expression from the given host word taking into 2204 account (of course) the host word size. */ 2205extern IRExpr* mkIRExpr_HWord ( HWord ); 2206 2207/* Convenience function for constructing clean helper calls. */ 2208extern 2209IRExpr* mkIRExprCCall ( IRType retty, 2210 Int regparms, const HChar* name, void* addr, 2211 IRExpr** args ); 2212 2213 2214/* Convenience functions for atoms (IRExprs which are either Iex_Tmp or 2215 * Iex_Const). */ 2216static inline Bool isIRAtom ( const IRExpr* e ) { 2217 return toBool(e->tag == Iex_RdTmp || e->tag == Iex_Const); 2218} 2219 2220/* Are these two IR atoms identical? Causes an assertion 2221 failure if they are passed non-atoms. */ 2222extern Bool eqIRAtom ( const IRExpr*, const IRExpr* ); 2223 2224 2225/* ------------------ Jump kinds ------------------ */ 2226 2227/* This describes hints which can be passed to the dispatcher at guest 2228 control-flow transfer points. 2229 2230 Re Ijk_InvalICache and Ijk_FlushDCache: the guest state _must_ have 2231 two pseudo-registers, guest_CMSTART and guest_CMLEN, which specify 2232 the start and length of the region to be invalidated. CM stands 2233 for "Cache Management". These are both the size of a guest word. 2234 It is the responsibility of the relevant toIR.c to ensure that 2235 these are filled in with suitable values before issuing a jump of 2236 kind Ijk_InvalICache or Ijk_FlushDCache. 2237 2238 Ijk_InvalICache requests invalidation of translations taken from 2239 the requested range. Ijk_FlushDCache requests flushing of the D 2240 cache for the specified range. 2241 2242 Re Ijk_EmWarn and Ijk_EmFail: the guest state must have a 2243 pseudo-register guest_EMNOTE, which is 32-bits regardless of the 2244 host or guest word size. That register should be made to hold a 2245 VexEmNote value to indicate the reason for the exit. 2246 2247 In the case of Ijk_EmFail, the exit is fatal (Vex-generated code 2248 cannot continue) and so the jump destination can be anything. 2249 2250 Re Ijk_Sys_ (syscall jumps): the guest state must have a 2251 pseudo-register guest_IP_AT_SYSCALL, which is the size of a guest 2252 word. Front ends should set this to be the IP at the most recently 2253 executed kernel-entering (system call) instruction. This makes it 2254 very much easier (viz, actually possible at all) to back up the 2255 guest to restart a syscall that has been interrupted by a signal. 2256*/ 2257typedef 2258 enum { 2259 Ijk_INVALID=0x1A00, 2260 Ijk_Boring, /* not interesting; just goto next */ 2261 Ijk_Call, /* guest is doing a call */ 2262 Ijk_Ret, /* guest is doing a return */ 2263 Ijk_ClientReq, /* do guest client req before continuing */ 2264 Ijk_Yield, /* client is yielding to thread scheduler */ 2265 Ijk_EmWarn, /* report emulation warning before continuing */ 2266 Ijk_EmFail, /* emulation critical (FATAL) error; give up */ 2267 Ijk_NoDecode, /* current instruction cannot be decoded */ 2268 Ijk_MapFail, /* Vex-provided address translation failed */ 2269 Ijk_InvalICache, /* Inval icache for range [CMSTART, +CMLEN) */ 2270 Ijk_FlushDCache, /* Flush dcache for range [CMSTART, +CMLEN) */ 2271 Ijk_NoRedir, /* Jump to un-redirected guest addr */ 2272 Ijk_SigILL, /* current instruction synths SIGILL */ 2273 Ijk_SigTRAP, /* current instruction synths SIGTRAP */ 2274 Ijk_SigSEGV, /* current instruction synths SIGSEGV */ 2275 Ijk_SigBUS, /* current instruction synths SIGBUS */ 2276 Ijk_SigFPE_IntDiv, /* current instruction synths SIGFPE - IntDiv */ 2277 Ijk_SigFPE_IntOvf, /* current instruction synths SIGFPE - IntOvf */ 2278 /* Unfortunately, various guest-dependent syscall kinds. They 2279 all mean: do a syscall before continuing. */ 2280 Ijk_Sys_syscall, /* amd64/x86 'syscall', ppc 'sc', arm 'svc #0' */ 2281 Ijk_Sys_int32, /* amd64/x86 'int $0x20' */ 2282 Ijk_Sys_int128, /* amd64/x86 'int $0x80' */ 2283 Ijk_Sys_int129, /* amd64/x86 'int $0x81' */ 2284 Ijk_Sys_int130, /* amd64/x86 'int $0x82' */ 2285 Ijk_Sys_sysenter /* x86 'sysenter'. guest_EIP becomes 2286 invalid at the point this happens. */ 2287 } 2288 IRJumpKind; 2289 2290extern void ppIRJumpKind ( IRJumpKind ); 2291 2292 2293/* ------------------ Dirty helper calls ------------------ */ 2294 2295/* A dirty call is a flexible mechanism for calling (possibly 2296 conditionally) a helper function or procedure. The helper function 2297 may read, write or modify client memory, and may read, write or 2298 modify client state. It can take arguments and optionally return a 2299 value. It may return different results and/or do different things 2300 when called repeatedly with the same arguments, by means of storing 2301 private state. 2302 2303 If a value is returned, it is assigned to the nominated return 2304 temporary. 2305 2306 Dirty calls are statements rather than expressions for obvious 2307 reasons. If a dirty call is marked as writing guest state, any 2308 pre-existing values derived from the written parts of the guest 2309 state are invalid. Similarly, if the dirty call is stated as 2310 writing memory, any pre-existing loaded values are invalidated by 2311 it. 2312 2313 In order that instrumentation is possible, the call must state, and 2314 state correctly: 2315 2316 * Whether it reads, writes or modifies memory, and if so where. 2317 2318 * Whether it reads, writes or modifies guest state, and if so which 2319 pieces. Several pieces may be stated, and their extents must be 2320 known at translation-time. Each piece is allowed to repeat some 2321 number of times at a fixed interval, if required. 2322 2323 Normally, code is generated to pass just the args to the helper. 2324 However, if IRExpr_BBPTR() is present in the argument list (at most 2325 one instance is allowed), then the baseblock pointer is passed for 2326 that arg, so that the callee can access the guest state. It is 2327 invalid for .nFxState to be zero but IRExpr_BBPTR() to be present, 2328 since .nFxState==0 is a claim that the call does not access guest 2329 state. 2330 2331 IMPORTANT NOTE re GUARDS: Dirty calls are strict, very strict. The 2332 arguments and 'mFx' are evaluated REGARDLESS of the guard value. 2333 The order of argument evaluation is unspecified. The guard 2334 expression is evaluated AFTER the arguments and 'mFx' have been 2335 evaluated. 'mFx' is expected (by Memcheck) to be a defined value 2336 even if the guard evaluates to false. 2337*/ 2338 2339#define VEX_N_FXSTATE 7 /* enough for FXSAVE/FXRSTOR on x86 */ 2340 2341/* Effects on resources (eg. registers, memory locations) */ 2342typedef 2343 enum { 2344 Ifx_None=0x1B00, /* no effect */ 2345 Ifx_Read, /* reads the resource */ 2346 Ifx_Write, /* writes the resource */ 2347 Ifx_Modify, /* modifies the resource */ 2348 } 2349 IREffect; 2350 2351/* Pretty-print an IREffect */ 2352extern void ppIREffect ( IREffect ); 2353 2354typedef 2355 struct _IRDirty { 2356 /* What to call, and details of args/results. .guard must be 2357 non-NULL. If .tmp is not IRTemp_INVALID, then the call 2358 returns a result which is placed in .tmp. If at runtime the 2359 guard evaluates to false, .tmp has an 0x555..555 bit pattern 2360 written to it. Hence conditional calls that assign .tmp are 2361 allowed. */ 2362 IRCallee* cee; /* where to call */ 2363 IRExpr* guard; /* :: Ity_Bit. Controls whether call happens */ 2364 /* The args vector may contain IRExpr_BBPTR() and/or 2365 IRExpr_VECRET(), in both cases, at most once. */ 2366 IRExpr** args; /* arg vector, ends in NULL. */ 2367 IRTemp tmp; /* to assign result to, or IRTemp_INVALID if none */ 2368 2369 /* Mem effects; we allow only one R/W/M region to be stated */ 2370 IREffect mFx; /* indicates memory effects, if any */ 2371 IRExpr* mAddr; /* of access, or NULL if mFx==Ifx_None */ 2372 Int mSize; /* of access, or zero if mFx==Ifx_None */ 2373 2374 /* Guest state effects; up to N allowed */ 2375 Int nFxState; /* must be 0 .. VEX_N_FXSTATE */ 2376 struct { 2377 IREffect fx:16; /* read, write or modify? Ifx_None is invalid. */ 2378 UShort offset; 2379 UShort size; 2380 UChar nRepeats; 2381 UChar repeatLen; 2382 } fxState[VEX_N_FXSTATE]; 2383 /* The access can be repeated, as specified by nRepeats and 2384 repeatLen. To describe only a single access, nRepeats and 2385 repeatLen should be zero. Otherwise, repeatLen must be a 2386 multiple of size and greater than size. */ 2387 /* Overall, the parts of the guest state denoted by (offset, 2388 size, nRepeats, repeatLen) is 2389 [offset, +size) 2390 and, if nRepeats > 0, 2391 for (i = 1; i <= nRepeats; i++) 2392 [offset + i * repeatLen, +size) 2393 A convenient way to enumerate all segments is therefore 2394 for (i = 0; i < 1 + nRepeats; i++) 2395 [offset + i * repeatLen, +size) 2396 */ 2397 } 2398 IRDirty; 2399 2400/* Pretty-print a dirty call */ 2401extern void ppIRDirty ( const IRDirty* ); 2402 2403/* Allocate an uninitialised dirty call */ 2404extern IRDirty* emptyIRDirty ( void ); 2405 2406/* Deep-copy a dirty call */ 2407extern IRDirty* deepCopyIRDirty ( const IRDirty* ); 2408 2409/* A handy function which takes some of the tedium out of constructing 2410 dirty helper calls. The called function impliedly does not return 2411 any value and has a constant-True guard. The call is marked as 2412 accessing neither guest state nor memory (hence the "unsafe" 2413 designation) -- you can change this marking later if need be. A 2414 suitable IRCallee is constructed from the supplied bits. */ 2415extern 2416IRDirty* unsafeIRDirty_0_N ( Int regparms, const HChar* name, void* addr, 2417 IRExpr** args ); 2418 2419/* Similarly, make a zero-annotation dirty call which returns a value, 2420 and assign that to the given temp. */ 2421extern 2422IRDirty* unsafeIRDirty_1_N ( IRTemp dst, 2423 Int regparms, const HChar* name, void* addr, 2424 IRExpr** args ); 2425 2426 2427/* --------------- Memory Bus Events --------------- */ 2428 2429typedef 2430 enum { 2431 Imbe_Fence=0x1C00, 2432 /* Needed only on ARM. It cancels a reservation made by a 2433 preceding Linked-Load, and needs to be handed through to the 2434 back end, just as LL and SC themselves are. */ 2435 Imbe_CancelReservation 2436 } 2437 IRMBusEvent; 2438 2439extern void ppIRMBusEvent ( IRMBusEvent ); 2440 2441 2442/* --------------- Compare and Swap --------------- */ 2443 2444/* This denotes an atomic compare and swap operation, either 2445 a single-element one or a double-element one. 2446 2447 In the single-element case: 2448 2449 .addr is the memory address. 2450 .end is the endianness with which memory is accessed 2451 2452 If .addr contains the same value as .expdLo, then .dataLo is 2453 written there, else there is no write. In both cases, the 2454 original value at .addr is copied into .oldLo. 2455 2456 Types: .expdLo, .dataLo and .oldLo must all have the same type. 2457 It may be any integral type, viz: I8, I16, I32 or, for 64-bit 2458 guests, I64. 2459 2460 .oldHi must be IRTemp_INVALID, and .expdHi and .dataHi must 2461 be NULL. 2462 2463 In the double-element case: 2464 2465 .addr is the memory address. 2466 .end is the endianness with which memory is accessed 2467 2468 The operation is the same: 2469 2470 If .addr contains the same value as .expdHi:.expdLo, then 2471 .dataHi:.dataLo is written there, else there is no write. In 2472 both cases the original value at .addr is copied into 2473 .oldHi:.oldLo. 2474 2475 Types: .expdHi, .expdLo, .dataHi, .dataLo, .oldHi, .oldLo must 2476 all have the same type, which may be any integral type, viz: I8, 2477 I16, I32 or, for 64-bit guests, I64. 2478 2479 The double-element case is complicated by the issue of 2480 endianness. In all cases, the two elements are understood to be 2481 located adjacently in memory, starting at the address .addr. 2482 2483 If .end is Iend_LE, then the .xxxLo component is at the lower 2484 address and the .xxxHi component is at the higher address, and 2485 each component is itself stored little-endianly. 2486 2487 If .end is Iend_BE, then the .xxxHi component is at the lower 2488 address and the .xxxLo component is at the higher address, and 2489 each component is itself stored big-endianly. 2490 2491 This allows representing more cases than most architectures can 2492 handle. For example, x86 cannot do DCAS on 8- or 16-bit elements. 2493 2494 How to know if the CAS succeeded? 2495 2496 * if .oldLo == .expdLo (resp. .oldHi:.oldLo == .expdHi:.expdLo), 2497 then the CAS succeeded, .dataLo (resp. .dataHi:.dataLo) is now 2498 stored at .addr, and the original value there was .oldLo (resp 2499 .oldHi:.oldLo). 2500 2501 * if .oldLo != .expdLo (resp. .oldHi:.oldLo != .expdHi:.expdLo), 2502 then the CAS failed, and the original value at .addr was .oldLo 2503 (resp. .oldHi:.oldLo). 2504 2505 Hence it is easy to know whether or not the CAS succeeded. 2506*/ 2507typedef 2508 struct { 2509 IRTemp oldHi; /* old value of *addr is written here */ 2510 IRTemp oldLo; 2511 IREndness end; /* endianness of the data in memory */ 2512 IRExpr* addr; /* store address */ 2513 IRExpr* expdHi; /* expected old value at *addr */ 2514 IRExpr* expdLo; 2515 IRExpr* dataHi; /* new value for *addr */ 2516 IRExpr* dataLo; 2517 } 2518 IRCAS; 2519 2520extern void ppIRCAS ( const IRCAS* cas ); 2521 2522extern IRCAS* mkIRCAS ( IRTemp oldHi, IRTemp oldLo, 2523 IREndness end, IRExpr* addr, 2524 IRExpr* expdHi, IRExpr* expdLo, 2525 IRExpr* dataHi, IRExpr* dataLo ); 2526 2527extern IRCAS* deepCopyIRCAS ( const IRCAS* ); 2528 2529 2530/* ------------------ Circular Array Put ------------------ */ 2531 2532typedef 2533 struct { 2534 IRRegArray* descr; /* Part of guest state treated as circular */ 2535 IRExpr* ix; /* Variable part of index into array */ 2536 Int bias; /* Constant offset part of index into array */ 2537 IRExpr* data; /* The value to write */ 2538 } IRPutI; 2539 2540extern void ppIRPutI ( const IRPutI* puti ); 2541 2542extern IRPutI* mkIRPutI ( IRRegArray* descr, IRExpr* ix, 2543 Int bias, IRExpr* data ); 2544 2545extern IRPutI* deepCopyIRPutI ( const IRPutI* ); 2546 2547 2548/* --------------- Guarded loads and stores --------------- */ 2549 2550/* Conditional stores are straightforward. They are the same as 2551 normal stores, with an extra 'guard' field :: Ity_I1 that 2552 determines whether or not the store actually happens. If not, 2553 memory is unmodified. 2554 2555 The semantics of this is that 'addr' and 'data' are fully evaluated 2556 even in the case where 'guard' evaluates to zero (false). 2557*/ 2558typedef 2559 struct { 2560 IREndness end; /* Endianness of the store */ 2561 IRExpr* addr; /* store address */ 2562 IRExpr* data; /* value to write */ 2563 IRExpr* guard; /* Guarding value */ 2564 } 2565 IRStoreG; 2566 2567/* Conditional loads are a little more complex. 'addr' is the 2568 address, 'guard' is the guarding condition. If the load takes 2569 place, the loaded value is placed in 'dst'. If it does not take 2570 place, 'alt' is copied to 'dst'. However, the loaded value is not 2571 placed directly in 'dst' -- it is first subjected to the conversion 2572 specified by 'cvt'. 2573 2574 For example, imagine doing a conditional 8-bit load, in which the 2575 loaded value is zero extended to 32 bits. Hence: 2576 * 'dst' and 'alt' must have type I32 2577 * 'cvt' must be a unary op which converts I8 to I32. In this 2578 example, it would be ILGop_8Uto32. 2579 2580 There is no explicit indication of the type at which the load is 2581 done, since that is inferrable from the arg type of 'cvt'. Note 2582 that the types of 'alt' and 'dst' and the result type of 'cvt' must 2583 all be the same. 2584 2585 Semantically, 'addr' is evaluated even in the case where 'guard' 2586 evaluates to zero (false), and 'alt' is evaluated even when 'guard' 2587 evaluates to one (true). That is, 'addr' and 'alt' are always 2588 evaluated. 2589*/ 2590typedef 2591 enum { 2592 ILGop_INVALID=0x1D00, 2593 ILGop_Ident64, /* 64 bit, no conversion */ 2594 ILGop_Ident32, /* 32 bit, no conversion */ 2595 ILGop_16Uto32, /* 16 bit load, Z-widen to 32 */ 2596 ILGop_16Sto32, /* 16 bit load, S-widen to 32 */ 2597 ILGop_8Uto32, /* 8 bit load, Z-widen to 32 */ 2598 ILGop_8Sto32 /* 8 bit load, S-widen to 32 */ 2599 } 2600 IRLoadGOp; 2601 2602typedef 2603 struct { 2604 IREndness end; /* Endianness of the load */ 2605 IRLoadGOp cvt; /* Conversion to apply to the loaded value */ 2606 IRTemp dst; /* Destination (LHS) of assignment */ 2607 IRExpr* addr; /* Address being loaded from */ 2608 IRExpr* alt; /* Value if load is not done. */ 2609 IRExpr* guard; /* Guarding value */ 2610 } 2611 IRLoadG; 2612 2613extern void ppIRStoreG ( const IRStoreG* sg ); 2614 2615extern void ppIRLoadGOp ( IRLoadGOp cvt ); 2616 2617extern void ppIRLoadG ( const IRLoadG* lg ); 2618 2619extern IRStoreG* mkIRStoreG ( IREndness end, 2620 IRExpr* addr, IRExpr* data, 2621 IRExpr* guard ); 2622 2623extern IRLoadG* mkIRLoadG ( IREndness end, IRLoadGOp cvt, 2624 IRTemp dst, IRExpr* addr, IRExpr* alt, 2625 IRExpr* guard ); 2626 2627 2628/* ------------------ Statements ------------------ */ 2629 2630/* The different kinds of statements. Their meaning is explained 2631 below in the comments for IRStmt. 2632 2633 Those marked META do not represent code, but rather extra 2634 information about the code. These statements can be removed 2635 without affecting the functional behaviour of the code, however 2636 they are required by some IR consumers such as tools that 2637 instrument the code. 2638*/ 2639 2640typedef 2641 enum { 2642 Ist_NoOp=0x1E00, 2643 Ist_IMark, /* META */ 2644 Ist_AbiHint, /* META */ 2645 Ist_Put, 2646 Ist_PutI, 2647 Ist_WrTmp, 2648 Ist_Store, 2649 Ist_LoadG, 2650 Ist_StoreG, 2651 Ist_CAS, 2652 Ist_LLSC, 2653 Ist_Dirty, 2654 Ist_MBE, 2655 Ist_Exit 2656 } 2657 IRStmtTag; 2658 2659/* A statement. Stored as a tagged union. 'tag' indicates what kind 2660 of expression this is. 'Ist' is the union that holds the fields. 2661 If an IRStmt 'st' has st.tag equal to Iex_Store, then it's a store 2662 statement, and the fields can be accessed with 2663 'st.Ist.Store.<fieldname>'. 2664 2665 For each kind of statement, we show what it looks like when 2666 pretty-printed with ppIRStmt(). 2667*/ 2668typedef 2669 struct _IRStmt { 2670 IRStmtTag tag; 2671 union { 2672 /* A no-op (usually resulting from IR optimisation). Can be 2673 omitted without any effect. 2674 2675 ppIRStmt output: IR-NoOp 2676 */ 2677 struct { 2678 } NoOp; 2679 2680 /* META: instruction mark. Marks the start of the statements 2681 that represent a single machine instruction (the end of 2682 those statements is marked by the next IMark or the end of 2683 the IRSB). Contains the address and length of the 2684 instruction. 2685 2686 It also contains a delta value. The delta must be 2687 subtracted from a guest program counter value before 2688 attempting to establish, by comparison with the address 2689 and length values, whether or not that program counter 2690 value refers to this instruction. For x86, amd64, ppc32, 2691 ppc64 and arm, the delta value is zero. For Thumb 2692 instructions, the delta value is one. This is because, on 2693 Thumb, guest PC values (guest_R15T) are encoded using the 2694 top 31 bits of the instruction address and a 1 in the lsb; 2695 hence they appear to be (numerically) 1 past the start of 2696 the instruction they refer to. IOW, guest_R15T on ARM 2697 holds a standard ARM interworking address. 2698 2699 ppIRStmt output: ------ IMark(<addr>, <len>, <delta>) ------, 2700 eg. ------ IMark(0x4000792, 5, 0) ------, 2701 */ 2702 struct { 2703 Addr addr; /* instruction address */ 2704 UInt len; /* instruction length */ 2705 UChar delta; /* addr = program counter as encoded in guest state 2706 - delta */ 2707 } IMark; 2708 2709 /* META: An ABI hint, which says something about this 2710 platform's ABI. 2711 2712 At the moment, the only AbiHint is one which indicates 2713 that a given chunk of address space, [base .. base+len-1], 2714 has become undefined. This is used on amd64-linux and 2715 some ppc variants to pass stack-redzoning hints to whoever 2716 wants to see them. It also indicates the address of the 2717 next (dynamic) instruction that will be executed. This is 2718 to help Memcheck to origin tracking. 2719 2720 ppIRStmt output: ====== AbiHint(<base>, <len>, <nia>) ====== 2721 eg. ====== AbiHint(t1, 16, t2) ====== 2722 */ 2723 struct { 2724 IRExpr* base; /* Start of undefined chunk */ 2725 Int len; /* Length of undefined chunk */ 2726 IRExpr* nia; /* Address of next (guest) insn */ 2727 } AbiHint; 2728 2729 /* Write a guest register, at a fixed offset in the guest state. 2730 ppIRStmt output: PUT(<offset>) = <data>, eg. PUT(60) = t1 2731 */ 2732 struct { 2733 Int offset; /* Offset into the guest state */ 2734 IRExpr* data; /* The value to write */ 2735 } Put; 2736 2737 /* Write a guest register, at a non-fixed offset in the guest 2738 state. See the comment for GetI expressions for more 2739 information. 2740 2741 ppIRStmt output: PUTI<descr>[<ix>,<bias>] = <data>, 2742 eg. PUTI(64:8xF64)[t5,0] = t1 2743 */ 2744 struct { 2745 IRPutI* details; 2746 } PutI; 2747 2748 /* Assign a value to a temporary. Note that SSA rules require 2749 each tmp is only assigned to once. IR sanity checking will 2750 reject any block containing a temporary which is not assigned 2751 to exactly once. 2752 2753 ppIRStmt output: t<tmp> = <data>, eg. t1 = 3 2754 */ 2755 struct { 2756 IRTemp tmp; /* Temporary (LHS of assignment) */ 2757 IRExpr* data; /* Expression (RHS of assignment) */ 2758 } WrTmp; 2759 2760 /* Write a value to memory. This is a normal store, not a 2761 Store-Conditional. To represent a Store-Conditional, 2762 instead use IRStmt.LLSC. 2763 ppIRStmt output: ST<end>(<addr>) = <data>, eg. STle(t1) = t2 2764 */ 2765 struct { 2766 IREndness end; /* Endianness of the store */ 2767 IRExpr* addr; /* store address */ 2768 IRExpr* data; /* value to write */ 2769 } Store; 2770 2771 /* Guarded store. Note that this is defined to evaluate all 2772 expression fields (addr, data) even if the guard evaluates 2773 to false. 2774 ppIRStmt output: 2775 if (<guard>) ST<end>(<addr>) = <data> */ 2776 struct { 2777 IRStoreG* details; 2778 } StoreG; 2779 2780 /* Guarded load. Note that this is defined to evaluate all 2781 expression fields (addr, alt) even if the guard evaluates 2782 to false. 2783 ppIRStmt output: 2784 t<tmp> = if (<guard>) <cvt>(LD<end>(<addr>)) else <alt> */ 2785 struct { 2786 IRLoadG* details; 2787 } LoadG; 2788 2789 /* Do an atomic compare-and-swap operation. Semantics are 2790 described above on a comment at the definition of IRCAS. 2791 2792 ppIRStmt output: 2793 t<tmp> = CAS<end>(<addr> :: <expected> -> <new>) 2794 eg 2795 t1 = CASle(t2 :: t3->Add32(t3,1)) 2796 which denotes a 32-bit atomic increment 2797 of a value at address t2 2798 2799 A double-element CAS may also be denoted, in which case <tmp>, 2800 <expected> and <new> are all pairs of items, separated by 2801 commas. 2802 */ 2803 struct { 2804 IRCAS* details; 2805 } CAS; 2806 2807 /* Either Load-Linked or Store-Conditional, depending on 2808 STOREDATA. 2809 2810 If STOREDATA is NULL then this is a Load-Linked, meaning 2811 that data is loaded from memory as normal, but a 2812 'reservation' for the address is also lodged in the 2813 hardware. 2814 2815 result = Load-Linked(addr, end) 2816 2817 The data transfer type is the type of RESULT (I32, I64, 2818 etc). ppIRStmt output: 2819 2820 result = LD<end>-Linked(<addr>), eg. LDbe-Linked(t1) 2821 2822 If STOREDATA is not NULL then this is a Store-Conditional, 2823 hence: 2824 2825 result = Store-Conditional(addr, storedata, end) 2826 2827 The data transfer type is the type of STOREDATA and RESULT 2828 has type Ity_I1. The store may fail or succeed depending 2829 on the state of a previously lodged reservation on this 2830 address. RESULT is written 1 if the store succeeds and 0 2831 if it fails. eg ppIRStmt output: 2832 2833 result = ( ST<end>-Cond(<addr>) = <storedata> ) 2834 eg t3 = ( STbe-Cond(t1, t2) ) 2835 2836 In all cases, the address must be naturally aligned for 2837 the transfer type -- any misaligned addresses should be 2838 caught by a dominating IR check and side exit. This 2839 alignment restriction exists because on at least some 2840 LL/SC platforms (ppc), stwcx. etc will trap w/ SIGBUS on 2841 misaligned addresses, and we have to actually generate 2842 stwcx. on the host, and we don't want it trapping on the 2843 host. 2844 2845 Summary of rules for transfer type: 2846 STOREDATA == NULL (LL): 2847 transfer type = type of RESULT 2848 STOREDATA != NULL (SC): 2849 transfer type = type of STOREDATA, and RESULT :: Ity_I1 2850 */ 2851 struct { 2852 IREndness end; 2853 IRTemp result; 2854 IRExpr* addr; 2855 IRExpr* storedata; /* NULL => LL, non-NULL => SC */ 2856 } LLSC; 2857 2858 /* Call (possibly conditionally) a C function that has side 2859 effects (ie. is "dirty"). See the comments above the 2860 IRDirty type declaration for more information. 2861 2862 ppIRStmt output: 2863 t<tmp> = DIRTY <guard> <effects> 2864 ::: <callee>(<args>) 2865 eg. 2866 t1 = DIRTY t27 RdFX-gst(16,4) RdFX-gst(60,4) 2867 ::: foo{0x380035f4}(t2) 2868 */ 2869 struct { 2870 IRDirty* details; 2871 } Dirty; 2872 2873 /* A memory bus event - a fence, or acquisition/release of the 2874 hardware bus lock. IR optimisation treats all these as fences 2875 across which no memory references may be moved. 2876 ppIRStmt output: MBusEvent-Fence, 2877 MBusEvent-BusLock, MBusEvent-BusUnlock. 2878 */ 2879 struct { 2880 IRMBusEvent event; 2881 } MBE; 2882 2883 /* Conditional exit from the middle of an IRSB. 2884 ppIRStmt output: if (<guard>) goto {<jk>} <dst> 2885 eg. if (t69) goto {Boring} 0x4000AAA:I32 2886 If <guard> is true, the guest state is also updated by 2887 PUT-ing <dst> at <offsIP>. This is done because a 2888 taken exit must update the guest program counter. 2889 */ 2890 struct { 2891 IRExpr* guard; /* Conditional expression */ 2892 IRConst* dst; /* Jump target (constant only) */ 2893 IRJumpKind jk; /* Jump kind */ 2894 Int offsIP; /* Guest state offset for IP */ 2895 } Exit; 2896 } Ist; 2897 } 2898 IRStmt; 2899 2900/* Statement constructors. */ 2901extern IRStmt* IRStmt_NoOp ( void ); 2902extern IRStmt* IRStmt_IMark ( Addr addr, UInt len, UChar delta ); 2903extern IRStmt* IRStmt_AbiHint ( IRExpr* base, Int len, IRExpr* nia ); 2904extern IRStmt* IRStmt_Put ( Int off, IRExpr* data ); 2905extern IRStmt* IRStmt_PutI ( IRPutI* details ); 2906extern IRStmt* IRStmt_WrTmp ( IRTemp tmp, IRExpr* data ); 2907extern IRStmt* IRStmt_Store ( IREndness end, IRExpr* addr, IRExpr* data ); 2908extern IRStmt* IRStmt_StoreG ( IREndness end, IRExpr* addr, IRExpr* data, 2909 IRExpr* guard ); 2910extern IRStmt* IRStmt_LoadG ( IREndness end, IRLoadGOp cvt, IRTemp dst, 2911 IRExpr* addr, IRExpr* alt, IRExpr* guard ); 2912extern IRStmt* IRStmt_CAS ( IRCAS* details ); 2913extern IRStmt* IRStmt_LLSC ( IREndness end, IRTemp result, 2914 IRExpr* addr, IRExpr* storedata ); 2915extern IRStmt* IRStmt_Dirty ( IRDirty* details ); 2916extern IRStmt* IRStmt_MBE ( IRMBusEvent event ); 2917extern IRStmt* IRStmt_Exit ( IRExpr* guard, IRJumpKind jk, IRConst* dst, 2918 Int offsIP ); 2919 2920/* Deep-copy an IRStmt. */ 2921extern IRStmt* deepCopyIRStmt ( const IRStmt* ); 2922 2923/* Pretty-print an IRStmt. */ 2924extern void ppIRStmt ( const IRStmt* ); 2925 2926 2927/* ------------------ Basic Blocks ------------------ */ 2928 2929/* Type environments: a bunch of statements, expressions, etc, are 2930 incomplete without an environment indicating the type of each 2931 IRTemp. So this provides one. IR temporaries are really just 2932 unsigned ints and so this provides an array, 0 .. n_types_used-1 of 2933 them. 2934*/ 2935typedef 2936 struct { 2937 IRType* types; 2938 Int types_size; 2939 Int types_used; 2940 } 2941 IRTypeEnv; 2942 2943/* Obtain a new IRTemp */ 2944extern IRTemp newIRTemp ( IRTypeEnv*, IRType ); 2945 2946/* Deep-copy a type environment */ 2947extern IRTypeEnv* deepCopyIRTypeEnv ( const IRTypeEnv* ); 2948 2949/* Pretty-print a type environment */ 2950extern void ppIRTypeEnv ( const IRTypeEnv* ); 2951 2952 2953/* Code blocks, which in proper compiler terminology are superblocks 2954 (single entry, multiple exit code sequences) contain: 2955 2956 - A table giving a type for each temp (the "type environment") 2957 - An expandable array of statements 2958 - An expression of type 32 or 64 bits, depending on the 2959 guest's word size, indicating the next destination if the block 2960 executes all the way to the end, without a side exit 2961 - An indication of any special actions (JumpKind) needed 2962 for this final jump. 2963 - Offset of the IP field in the guest state. This will be 2964 updated before the final jump is done. 2965 2966 "IRSB" stands for "IR Super Block". 2967*/ 2968typedef 2969 struct { 2970 IRTypeEnv* tyenv; 2971 IRStmt** stmts; 2972 Int stmts_size; 2973 Int stmts_used; 2974 IRExpr* next; 2975 IRJumpKind jumpkind; 2976 Int offsIP; 2977 } 2978 IRSB; 2979 2980/* Allocate a new, uninitialised IRSB */ 2981extern IRSB* emptyIRSB ( void ); 2982 2983/* Deep-copy an IRSB */ 2984extern IRSB* deepCopyIRSB ( const IRSB* ); 2985 2986/* Deep-copy an IRSB, except for the statements list, which set to be 2987 a new, empty, list of statements. */ 2988extern IRSB* deepCopyIRSBExceptStmts ( const IRSB* ); 2989 2990/* Pretty-print an IRSB */ 2991extern void ppIRSB ( const IRSB* ); 2992 2993/* Append an IRStmt to an IRSB */ 2994extern void addStmtToIRSB ( IRSB*, IRStmt* ); 2995 2996 2997/*---------------------------------------------------------------*/ 2998/*--- Helper functions for the IR ---*/ 2999/*---------------------------------------------------------------*/ 3000 3001/* For messing with IR type environments */ 3002extern IRTypeEnv* emptyIRTypeEnv ( void ); 3003 3004/* What is the type of this expression? */ 3005extern IRType typeOfIRConst ( const IRConst* ); 3006extern IRType typeOfIRTemp ( const IRTypeEnv*, IRTemp ); 3007extern IRType typeOfIRExpr ( const IRTypeEnv*, const IRExpr* ); 3008 3009/* What are the arg and result type for this IRLoadGOp? */ 3010extern void typeOfIRLoadGOp ( IRLoadGOp cvt, 3011 /*OUT*/IRType* t_res, 3012 /*OUT*/IRType* t_arg ); 3013 3014/* Sanity check a BB of IR */ 3015extern void sanityCheckIRSB ( const IRSB* bb, 3016 const HChar* caller, 3017 Bool require_flatness, 3018 IRType guest_word_size ); 3019extern Bool isFlatIRStmt ( const IRStmt* ); 3020 3021/* Is this any value actually in the enumeration 'IRType' ? */ 3022extern Bool isPlausibleIRType ( IRType ty ); 3023 3024 3025/*---------------------------------------------------------------*/ 3026/*--- IR injection ---*/ 3027/*---------------------------------------------------------------*/ 3028 3029void vex_inject_ir(IRSB *, IREndness); 3030 3031 3032#endif /* ndef __LIBVEX_IR_H */ 3033 3034/*---------------------------------------------------------------*/ 3035/*--- libvex_ir.h ---*/ 3036/*---------------------------------------------------------------*/ 3037