libvex_ir.h revision f0de28cf1a762b0d6f74c93d3532c89a230673bb
1 2/*---------------------------------------------------------------*/ 3/*--- ---*/ 4/*--- This file (libvex_ir.h) is ---*/ 5/*--- Copyright (C) OpenWorks LLP. All rights reserved. ---*/ 6/*--- ---*/ 7/*---------------------------------------------------------------*/ 8 9/* 10 This file is part of LibVEX, a library for dynamic binary 11 instrumentation and translation. 12 13 Copyright (C) 2004-2005 OpenWorks LLP. All rights reserved. 14 15 This library is made available under a dual licensing scheme. 16 17 If you link LibVEX against other code all of which is itself 18 licensed under the GNU General Public License, version 2 dated June 19 1991 ("GPL v2"), then you may use LibVEX under the terms of the GPL 20 v2, as appearing in the file LICENSE.GPL. If the file LICENSE.GPL 21 is missing, you can obtain a copy of the GPL v2 from the Free 22 Software Foundation Inc., 51 Franklin St, Fifth Floor, Boston, MA 23 02110-1301, USA. 24 25 For any other uses of LibVEX, you must first obtain a commercial 26 license from OpenWorks LLP. Please contact info@open-works.co.uk 27 for information about commercial licensing. 28 29 This software is provided by OpenWorks LLP "as is" and any express 30 or implied warranties, including, but not limited to, the implied 31 warranties of merchantability and fitness for a particular purpose 32 are disclaimed. In no event shall OpenWorks LLP be liable for any 33 direct, indirect, incidental, special, exemplary, or consequential 34 damages (including, but not limited to, procurement of substitute 35 goods or services; loss of use, data, or profits; or business 36 interruption) however caused and on any theory of liability, 37 whether in contract, strict liability, or tort (including 38 negligence or otherwise) arising in any way out of the use of this 39 software, even if advised of the possibility of such damage. 40 41 Neither the names of the U.S. Department of Energy nor the 42 University of California nor the names of its contributors may be 43 used to endorse or promote products derived from this software 44 without prior written permission. 45*/ 46 47#ifndef __LIBVEX_IR_H 48#define __LIBVEX_IR_H 49 50#include "libvex_basictypes.h" 51 52 53 54/*---------------------------------------------------------------*/ 55/*--- Type definitions for the IR ---*/ 56/*---------------------------------------------------------------*/ 57 58/* General comments about naming schemes: 59 60 All publically visible functions contain the name of the primary 61 type on which they operate (IRFoo, IRBar, etc). Hence you should 62 be able to identify these functions by grepping for "IR[A-Z]". 63 64 For some type 'IRFoo': 65 66 - ppIRFoo is the printing method for IRFoo, printing it to the 67 output channel specified in the LibVEX_Initialise call. 68 69 - eqIRFoo is a structural equality predicate for IRFoos. 70 71 - dopyIRFoo is a deep copy constructor for IRFoos. 72 It recursively traverses the entire argument tree and 73 produces a complete new tree. 74 75 - sopyIRFoo is the shallow copy constructor for IRFoos. 76 It creates a new top-level copy of the supplied object, 77 but does not copy any sub-objects. 78*/ 79 80/* ------------------ Types ------------------ */ 81 82typedef 83 enum { 84 Ity_INVALID=0x10FFF, 85 Ity_I1=0x11000, 86 Ity_I8, 87 Ity_I16, 88 Ity_I32, 89 Ity_I64, 90 Ity_I128, /* 128-bit scalar */ 91 Ity_F32, /* IEEE 754 float */ 92 Ity_F64, /* IEEE 754 double */ 93 Ity_V128 /* 128-bit SIMD */ 94 } 95 IRType; 96 97extern void ppIRType ( IRType ); 98extern Int sizeofIRType ( IRType ); 99 100 101/* ------------------ Endianness ------------------ */ 102 103typedef 104 enum { 105 Iend_LE=22, /* little endian */ 106 Iend_BE=33 /* big endian */ 107 } 108 IREndness; 109 110 111/* ------------------ Constants ------------------ */ 112 113typedef 114 enum { 115 Ico_U1=0x12000, 116 Ico_U8, 117 Ico_U16, 118 Ico_U32, 119 Ico_U64, 120 Ico_F64, /* 64-bit IEEE754 floating */ 121 Ico_F64i, /* 64-bit unsigned int to be interpreted literally 122 as a IEEE754 double value. */ 123 Ico_V128 /* 128-bit restricted vector constant, with 1 bit for 124 each of 16 byte lanes */ 125 } 126 IRConstTag; 127 128typedef 129 struct _IRConst { 130 IRConstTag tag; 131 union { 132 Bool U1; 133 UChar U8; 134 UShort U16; 135 UInt U32; 136 ULong U64; 137 Double F64; 138 ULong F64i; 139 UShort V128; 140 } Ico; 141 } 142 IRConst; 143 144extern IRConst* IRConst_U1 ( Bool ); 145extern IRConst* IRConst_U8 ( UChar ); 146extern IRConst* IRConst_U16 ( UShort ); 147extern IRConst* IRConst_U32 ( UInt ); 148extern IRConst* IRConst_U64 ( ULong ); 149extern IRConst* IRConst_F64 ( Double ); 150extern IRConst* IRConst_F64i ( ULong ); 151extern IRConst* IRConst_V128 ( UShort ); 152 153extern IRConst* dopyIRConst ( IRConst* ); 154 155extern void ppIRConst ( IRConst* ); 156extern Bool eqIRConst ( IRConst*, IRConst* ); 157 158 159/* ------------------ Call targets ------------------ */ 160 161/* Describes a helper function to call. The name part is purely for 162 pretty printing and not actually used. regparms=n tells the back 163 end that the callee has been declared 164 "__attribute__((regparm(n)))". On some targets (x86) the back end 165 will need to construct a non-standard sequence to call a function 166 declared like this. 167 168 mcx_mask is a sop to Memcheck. It indicates which args should be 169 considered 'always defined' when lazily computing definedness of 170 the result. Bit 0 of mcx_mask corresponds to args[0], bit 1 to 171 args[1], etc. If a bit is set, the corresponding arg is excluded 172 (hence "x" in "mcx") from definedness checking. 173*/ 174 175typedef 176 struct { 177 Int regparms; 178 HChar* name; 179 void* addr; 180 UInt mcx_mask; 181 } 182 IRCallee; 183 184extern IRCallee* mkIRCallee ( Int regparms, HChar* name, void* addr ); 185 186extern IRCallee* dopyIRCallee ( IRCallee* ); 187 188extern void ppIRCallee ( IRCallee* ); 189 190 191/* ------------------ Guest state arrays ------------------ */ 192 193typedef 194 struct { 195 Int base; 196 IRType elemTy; 197 Int nElems; 198 } 199 IRArray; 200 201extern IRArray* mkIRArray ( Int, IRType, Int ); 202 203extern IRArray* dopyIRArray ( IRArray* ); 204 205extern void ppIRArray ( IRArray* ); 206extern Bool eqIRArray ( IRArray*, IRArray* ); 207 208 209/* ------------------ Temporaries ------------------ */ 210 211/* The IR optimiser relies on the fact that IRTemps are 32-bit 212 ints. Do not change them to be ints of any other size. */ 213typedef UInt IRTemp; 214 215extern void ppIRTemp ( IRTemp ); 216 217#define IRTemp_INVALID ((IRTemp)0xFFFFFFFF) 218 219 220/* ------------------ Binary and unary ops ------------------ */ 221 222typedef 223 enum { 224 /* -- Do not change this ordering. The IR generators rely on 225 (eg) Iop_Add64 == IopAdd8 + 3. -- */ 226 227 Iop_INVALID=0x13000, 228 Iop_Add8, Iop_Add16, Iop_Add32, Iop_Add64, 229 Iop_Sub8, Iop_Sub16, Iop_Sub32, Iop_Sub64, 230 /* Signless mul. MullS/MullU is elsewhere. */ 231 Iop_Mul8, Iop_Mul16, Iop_Mul32, Iop_Mul64, 232 Iop_Or8, Iop_Or16, Iop_Or32, Iop_Or64, 233 Iop_And8, Iop_And16, Iop_And32, Iop_And64, 234 Iop_Xor8, Iop_Xor16, Iop_Xor32, Iop_Xor64, 235 Iop_Shl8, Iop_Shl16, Iop_Shl32, Iop_Shl64, 236 Iop_Shr8, Iop_Shr16, Iop_Shr32, Iop_Shr64, 237 Iop_Sar8, Iop_Sar16, Iop_Sar32, Iop_Sar64, 238 /* Integer comparisons. */ 239 Iop_CmpEQ8, Iop_CmpEQ16, Iop_CmpEQ32, Iop_CmpEQ64, 240 Iop_CmpNE8, Iop_CmpNE16, Iop_CmpNE32, Iop_CmpNE64, 241 /* Tags for unary ops */ 242 Iop_Not8, Iop_Not16, Iop_Not32, Iop_Not64, 243 Iop_Neg8, Iop_Neg16, Iop_Neg32, Iop_Neg64, 244 245 /* -- Ordering not important after here. -- */ 246 247 /* Widening multiplies */ 248 Iop_MullS8, Iop_MullS16, Iop_MullS32, Iop_MullS64, 249 Iop_MullU8, Iop_MullU16, Iop_MullU32, Iop_MullU64, 250 251 /* Wierdo integer stuff */ 252 Iop_Clz64, Iop_Clz32, /* count leading zeroes */ 253 Iop_Ctz64, Iop_Ctz32, /* count trailing zeros */ 254 /* Ctz64/Ctz32/Clz64/Clz32 are UNDEFINED when given arguments of 255 zero. You must ensure they are never given a zero argument. 256 */ 257 258 /* Standard integer comparisons */ 259 Iop_CmpLT32S, Iop_CmpLT64S, 260 Iop_CmpLE32S, Iop_CmpLE64S, 261 Iop_CmpLT32U, Iop_CmpLT64U, 262 Iop_CmpLE32U, Iop_CmpLE64U, 263 264 /* As a sop to Valgrind-Memcheck, the following are useful. */ 265 Iop_CmpNEZ8, Iop_CmpNEZ16, Iop_CmpNEZ32, Iop_CmpNEZ64, 266 267 /* PowerPC-style 3-way integer comparisons. Without them it is difficult 268 to simulate PPC efficiently. 269 op(x,y) | x < y = 0x8 else 270 | x > y = 0x4 else 271 | x == y = 0x2 272 */ 273 Iop_CmpORD32U, Iop_CmpORD64U, 274 Iop_CmpORD32S, Iop_CmpORD64S, 275 276 /* Division */ 277 /* TODO: clarify semantics wrt rounding, negative values, whatever */ 278 Iop_DivU32, // :: I32,I32 -> I32 (simple div, no mod) 279 Iop_DivS32, // ditto, signed 280 Iop_DivU64, // :: I64,I64 -> I64 (simple div, no mod) 281 Iop_DivS64, // ditto, signed 282 283 Iop_DivModU64to32, // :: I64,I32 -> I64 284 // of which lo half is div and hi half is mod 285 Iop_DivModS64to32, // ditto, signed 286 287 Iop_DivModU128to64, // :: V128,I64 -> V128 288 // of which lo half is div and hi half is mod 289 Iop_DivModS128to64, // ditto, signed 290 291 /* Integer conversions. Some of these are redundant (eg 292 Iop_64to8 is the same as Iop_64to32 and then Iop_32to8), but 293 having a complete set reduces the typical dynamic size of IR 294 and makes the instruction selectors easier to write. */ 295 296 /* Widening conversions */ 297 Iop_8Uto16, Iop_8Uto32, Iop_8Uto64, 298 Iop_16Uto32, Iop_16Uto64, 299 Iop_32Uto64, 300 Iop_8Sto16, Iop_8Sto32, Iop_8Sto64, 301 Iop_16Sto32, Iop_16Sto64, 302 Iop_32Sto64, 303 304 /* Narrowing conversions */ 305 Iop_64to8, Iop_32to8, Iop_64to16, 306 /* 8 <-> 16 bit conversions */ 307 Iop_16to8, // :: I16 -> I8, low half 308 Iop_16HIto8, // :: I16 -> I8, high half 309 Iop_8HLto16, // :: (I8,I8) -> I16 310 /* 16 <-> 32 bit conversions */ 311 Iop_32to16, // :: I32 -> I16, low half 312 Iop_32HIto16, // :: I32 -> I16, high half 313 Iop_16HLto32, // :: (I16,I16) -> I32 314 /* 32 <-> 64 bit conversions */ 315 Iop_64to32, // :: I64 -> I32, low half 316 Iop_64HIto32, // :: I64 -> I32, high half 317 Iop_32HLto64, // :: (I32,I32) -> I64 318 /* 64 <-> 128 bit conversions */ 319 Iop_128to64, // :: I128 -> I64, low half 320 Iop_128HIto64, // :: I128 -> I64, high half 321 Iop_64HLto128, // :: (I64,I64) -> I128 322 /* 1-bit stuff */ 323 Iop_Not1, /* :: Ity_Bit -> Ity_Bit */ 324 Iop_32to1, /* :: Ity_I32 -> Ity_Bit, just select bit[0] */ 325 Iop_64to1, /* :: Ity_I64 -> Ity_Bit, just select bit[0] */ 326 Iop_1Uto8, /* :: Ity_Bit -> Ity_I8, unsigned widen */ 327 Iop_1Uto32, /* :: Ity_Bit -> Ity_I32, unsigned widen */ 328 Iop_1Uto64, /* :: Ity_Bit -> Ity_I64, unsigned widen */ 329 Iop_1Sto8, /* :: Ity_Bit -> Ity_I8, signed widen */ 330 Iop_1Sto16, /* :: Ity_Bit -> Ity_I16, signed widen */ 331 Iop_1Sto32, /* :: Ity_Bit -> Ity_I32, signed widen */ 332 Iop_1Sto64, /* :: Ity_Bit -> Ity_I64, signed widen */ 333 334 /* ------ Floating point. We try and be IEEE754 compliant. ------ */ 335 336 /* Binary operations mandated by IEEE754. */ 337 Iop_AddF64, Iop_SubF64, Iop_MulF64, Iop_DivF64, /* Iop_RemF64, */ 338 339 /* Binary ops supported by IA32 but not mandated by 754. */ 340 Iop_AtanF64, /* FPATAN, arctan(arg1/arg2) */ 341 Iop_Yl2xF64, /* FYL2X, arg1 * log2(arg2) */ 342 Iop_Yl2xp1F64, /* FYL2XP1, arg1 * log2(arg2+1.0) */ 343 Iop_PRemF64, /* FPREM, non-IEEE remainder(arg1/arg2) */ 344 Iop_PRemC3210F64, /* C3210 flags resulting from FPREM, :: I32 */ 345 Iop_PRem1F64, /* FPREM1, IEEE remainder(arg1/arg2) */ 346 Iop_PRem1C3210F64, /* C3210 flags resulting from FPREM1, :: I32 */ 347 Iop_ScaleF64, /* FSCALE, arg1 * (2^RoundTowardsZero(arg2)) */ 348 /* Note that on x86 guest, PRem1{C3210} has the same behaviour 349 as the IEEE mandated RemF64, except it is limited in the 350 range of its operand. Hence the partialness. */ 351 352 /* Unary operations mandated by IEEE754. */ 353 Iop_NegF64, Iop_SqrtF64, 354 355 /* Unary ops supported by IA32 but not mandated by 754. */ 356 Iop_AbsF64, /* FABS */ 357 Iop_SinF64, /* FSIN */ 358 Iop_CosF64, /* FCOS */ 359 Iop_TanF64, /* FTAN */ 360 Iop_2xm1F64, /* (2^arg - 1.0) */ 361 362 /* Comparison, yielding GT/LT/EQ/UN(ordered), as per the following: 363 0x45 Unordered 364 0x01 LT 365 0x00 GT 366 0x40 EQ 367 This just happens to be the Intel encoding. The values 368 are recorded in the type IRCmpF64Result. 369 */ 370 Iop_CmpF64, 371 372 /* --- Int to/from FP conversions. --- */ 373 /* For the most part, these take a first argument :: Ity_I32 374 (as IRRoundingMode) which is an indication of the rounding 375 mode to use, as per the following encoding: 376 00b to nearest (the default) 377 01b to -infinity 378 10b to +infinity 379 11b to zero 380 This just happens to be the Intel encoding. For reference only, 381 the PPC encoding is: 382 00b to nearest (the default) 383 01b to zero 384 10b to +infinity 385 11b to -infinity 386 Any PPC -> IR front end will have to translate these PPC 387 encodings to the standard encodings. 388 389 If one of these conversions gets an out-of-range condition, 390 or a NaN, as an argument, the result is host-defined. On x86 391 the "integer indefinite" value 0x80..00 is produced. 392 On PPC it is either 0x80..00 or 0x7F..FF depending on the sign 393 of the argument. 394 395 Rounding is required whenever the destination type cannot 396 represent exactly all values of the source type. 397 */ 398 Iop_F64toI16, /* IRRoundingMode(I32) x F64 -> I16 */ 399 Iop_F64toI32, /* IRRoundingMode(I32) x F64 -> I32 */ 400 Iop_F64toI64, /* IRRoundingMode(I32) x F64 -> I64 */ 401 402 Iop_I16toF64, /* I16 -> F64 */ 403 Iop_I32toF64, /* I32 -> F64 */ 404 Iop_I64toF64, /* IRRoundingMode(I32) x I64 -> F64 */ 405 406 Iop_F32toF64, /* F32 -> F64 */ 407 Iop_F64toF32, /* IRRoundingMode(I32) x F64 -> F32 */ 408 409 /* F64 -> F64, also takes an I32 first argument encoding the 410 rounding mode. */ 411 Iop_RoundF64, 412 413 /* Reinterpretation. Take an F64 and produce an I64 with 414 the same bit pattern, or vice versa. */ 415 Iop_ReinterpF64asI64, Iop_ReinterpI64asF64, 416 Iop_ReinterpF32asI32, Iop_ReinterpI32asF32, 417 418 /* ------------------ 64-bit SIMD Integer. ------------------ */ 419 420 /* MISC (vector integer cmp != 0) */ 421 Iop_CmpNEZ8x8, Iop_CmpNEZ16x4, Iop_CmpNEZ32x2, 422 423 /* ADDITION (normal / unsigned sat / signed sat) */ 424 Iop_Add8x8, Iop_Add16x4, Iop_Add32x2, 425 Iop_QAdd8Ux8, Iop_QAdd16Ux4, 426 Iop_QAdd8Sx8, Iop_QAdd16Sx4, 427 428 /* SUBTRACTION (normal / unsigned sat / signed sat) */ 429 Iop_Sub8x8, Iop_Sub16x4, Iop_Sub32x2, 430 Iop_QSub8Ux8, Iop_QSub16Ux4, 431 Iop_QSub8Sx8, Iop_QSub16Sx4, 432 433 /* MULTIPLICATION (normal / high half of signed/unsigned) */ 434 Iop_Mul16x4, 435 Iop_MulHi16Ux4, 436 Iop_MulHi16Sx4, 437 438 /* AVERAGING: note: (arg1 + arg2 + 1) >>u 1 */ 439 Iop_Avg8Ux8, 440 Iop_Avg16Ux4, 441 442 /* MIN/MAX */ 443 Iop_Max16Sx4, 444 Iop_Max8Ux8, 445 Iop_Min16Sx4, 446 Iop_Min8Ux8, 447 448 /* COMPARISON */ 449 Iop_CmpEQ8x8, Iop_CmpEQ16x4, Iop_CmpEQ32x2, 450 Iop_CmpGT8Sx8, Iop_CmpGT16Sx4, Iop_CmpGT32Sx2, 451 452 /* VECTOR x SCALAR SHIFT (shift amt :: Ity_I8) */ 453 Iop_ShlN16x4, Iop_ShlN32x2, 454 Iop_ShrN16x4, Iop_ShrN32x2, 455 Iop_SarN16x4, Iop_SarN32x2, 456 457 /* NARROWING -- narrow 2xI64 into 1xI64, hi half from left arg */ 458 Iop_QNarrow16Ux4, 459 Iop_QNarrow16Sx4, 460 Iop_QNarrow32Sx2, 461 462 /* INTERLEAVING -- interleave lanes from low or high halves of 463 operands. Most-significant result lane is from the left 464 arg. */ 465 Iop_InterleaveHI8x8, Iop_InterleaveHI16x4, Iop_InterleaveHI32x2, 466 Iop_InterleaveLO8x8, Iop_InterleaveLO16x4, Iop_InterleaveLO32x2, 467 468 /* ------------------ 128-bit SIMD FP. ------------------ */ 469 470 /* --- 32x4 vector FP --- */ 471 472 /* binary */ 473 Iop_Add32Fx4, Iop_Sub32Fx4, Iop_Mul32Fx4, Iop_Div32Fx4, 474 Iop_Max32Fx4, Iop_Min32Fx4, 475 /* Note: For the following compares, the ppc32 front-end assumes a 476 nan in a lane of either argument returns zero for that lane. */ 477 Iop_CmpEQ32Fx4, Iop_CmpLT32Fx4, Iop_CmpLE32Fx4, Iop_CmpUN32Fx4, 478 Iop_CmpGT32Fx4, Iop_CmpGE32Fx4, 479 480 /* unary */ 481 Iop_Recip32Fx4, Iop_Sqrt32Fx4, Iop_RSqrt32Fx4, 482 483 /* --- Int to/from FP conversion --- */ 484 /* Unlike the standard fp conversions, these irops take no 485 rounding mode argument. Instead the irop trailers _R{M,P,N,Z} 486 indicate the mode: {-inf, +inf, nearest, zero} respectively. */ 487 Iop_I32UtoFx4, Iop_I32StoFx4, /* I32x4 -> F32x4 */ 488 Iop_QFtoI32Ux4_RZ, Iop_QFtoI32Sx4_RZ, /* F32x4 -> I32x4 */ 489 Iop_RoundF32x4_RM, Iop_RoundF32x4_RP, /* round to fp integer */ 490 Iop_RoundF32x4_RN, Iop_RoundF32x4_RZ, /* round to fp integer */ 491 492 /* --- 32x4 lowest-lane-only scalar FP --- */ 493 494 /* In binary cases, upper 3/4 is copied from first operand. In 495 unary cases, upper 3/4 is copied from the operand. */ 496 497 /* binary */ 498 Iop_Add32F0x4, Iop_Sub32F0x4, Iop_Mul32F0x4, Iop_Div32F0x4, 499 Iop_Max32F0x4, Iop_Min32F0x4, 500 Iop_CmpEQ32F0x4, Iop_CmpLT32F0x4, Iop_CmpLE32F0x4, Iop_CmpUN32F0x4, 501 502 /* unary */ 503 Iop_Recip32F0x4, Iop_Sqrt32F0x4, Iop_RSqrt32F0x4, 504 505 /* --- 64x2 vector FP --- */ 506 507 /* binary */ 508 Iop_Add64Fx2, Iop_Sub64Fx2, Iop_Mul64Fx2, Iop_Div64Fx2, 509 Iop_Max64Fx2, Iop_Min64Fx2, 510 Iop_CmpEQ64Fx2, Iop_CmpLT64Fx2, Iop_CmpLE64Fx2, Iop_CmpUN64Fx2, 511 512 /* unary */ 513 Iop_Recip64Fx2, Iop_Sqrt64Fx2, Iop_RSqrt64Fx2, 514 515 /* --- 64x2 lowest-lane-only scalar FP --- */ 516 517 /* In binary cases, upper half is copied from first operand. In 518 unary cases, upper half is copied from the operand. */ 519 520 /* binary */ 521 Iop_Add64F0x2, Iop_Sub64F0x2, Iop_Mul64F0x2, Iop_Div64F0x2, 522 Iop_Max64F0x2, Iop_Min64F0x2, 523 Iop_CmpEQ64F0x2, Iop_CmpLT64F0x2, Iop_CmpLE64F0x2, Iop_CmpUN64F0x2, 524 525 /* unary */ 526 Iop_Recip64F0x2, Iop_Sqrt64F0x2, Iop_RSqrt64F0x2, 527 528 /* --- pack / unpack --- */ 529 530 /* 64 <-> 128 bit vector */ 531 Iop_V128to64, // :: V128 -> I64, low half 532 Iop_V128HIto64, // :: V128 -> I64, high half 533 Iop_64HLtoV128, // :: (I64,I64) -> V128 534 535 Iop_64UtoV128, 536 Iop_SetV128lo64, 537 538 /* 32 <-> 128 bit vector */ 539 Iop_32UtoV128, 540 Iop_V128to32, // :: V128 -> I32, lowest lane 541 Iop_SetV128lo32, // :: (V128,I32) -> V128 542 543 /* ------------------ 128-bit SIMD Integer. ------------------ */ 544 545 /* BITWISE OPS */ 546 Iop_NotV128, 547 Iop_AndV128, Iop_OrV128, Iop_XorV128, 548 549 /* VECTOR SHIFT (shift amt :: Ity_I8) */ 550 Iop_ShlV128, Iop_ShrV128, 551 552 /* MISC (vector integer cmp != 0) */ 553 Iop_CmpNEZ8x16, Iop_CmpNEZ16x8, Iop_CmpNEZ32x4, Iop_CmpNEZ64x2, 554 555 /* ADDITION (normal / unsigned sat / signed sat) */ 556 Iop_Add8x16, Iop_Add16x8, Iop_Add32x4, Iop_Add64x2, 557 Iop_QAdd8Ux16, Iop_QAdd16Ux8, Iop_QAdd32Ux4, 558 Iop_QAdd8Sx16, Iop_QAdd16Sx8, Iop_QAdd32Sx4, 559 560 /* SUBTRACTION (normal / unsigned sat / signed sat) */ 561 Iop_Sub8x16, Iop_Sub16x8, Iop_Sub32x4, Iop_Sub64x2, 562 Iop_QSub8Ux16, Iop_QSub16Ux8, Iop_QSub32Ux4, 563 Iop_QSub8Sx16, Iop_QSub16Sx8, Iop_QSub32Sx4, 564 565 /* MULTIPLICATION (normal / high half of signed/unsigned) */ 566 Iop_Mul16x8, 567 Iop_MulHi16Ux8, Iop_MulHi32Ux4, 568 Iop_MulHi16Sx8, Iop_MulHi32Sx4, 569 /* (widening signed/unsigned of even lanes, with lowest lane=zero) */ 570 Iop_MullEven8Ux16, Iop_MullEven16Ux8, 571 Iop_MullEven8Sx16, Iop_MullEven16Sx8, 572 573 /* AVERAGING: note: (arg1 + arg2 + 1) >>u 1 */ 574 Iop_Avg8Ux16, Iop_Avg16Ux8, Iop_Avg32Ux4, 575 Iop_Avg8Sx16, Iop_Avg16Sx8, Iop_Avg32Sx4, 576 577 /* MIN/MAX */ 578 Iop_Max8Sx16, Iop_Max16Sx8, Iop_Max32Sx4, 579 Iop_Max8Ux16, Iop_Max16Ux8, Iop_Max32Ux4, 580 Iop_Min8Sx16, Iop_Min16Sx8, Iop_Min32Sx4, 581 Iop_Min8Ux16, Iop_Min16Ux8, Iop_Min32Ux4, 582 583 /* COMPARISON */ 584 Iop_CmpEQ8x16, Iop_CmpEQ16x8, Iop_CmpEQ32x4, 585 Iop_CmpGT8Sx16, Iop_CmpGT16Sx8, Iop_CmpGT32Sx4, 586 Iop_CmpGT8Ux16, Iop_CmpGT16Ux8, Iop_CmpGT32Ux4, 587 588 /* VECTOR x SCALAR SHIFT (shift amt :: Ity_I8) */ 589 Iop_ShlN8x16, Iop_ShlN16x8, Iop_ShlN32x4, Iop_ShlN64x2, 590 Iop_ShrN8x16, Iop_ShrN16x8, Iop_ShrN32x4, Iop_ShrN64x2, 591 Iop_SarN8x16, Iop_SarN16x8, Iop_SarN32x4, 592 593 /* VECTOR x VECTOR SHIFT / ROTATE */ 594 Iop_Shl8x16, Iop_Shl16x8, Iop_Shl32x4, 595 Iop_Shr8x16, Iop_Shr16x8, Iop_Shr32x4, 596 Iop_Sar8x16, Iop_Sar16x8, Iop_Sar32x4, 597 Iop_Rol8x16, Iop_Rol16x8, Iop_Rol32x4, 598 599 /* NARROWING -- narrow 2xV128 into 1xV128, hi half from left arg */ 600 /* Note: the 16{U,S} and 32{U,S} are the pre-narrow lane widths. */ 601 Iop_QNarrow16Ux8, Iop_QNarrow32Ux4, 602 Iop_QNarrow16Sx8, Iop_QNarrow32Sx4, 603 Iop_Narrow16x8, Iop_Narrow32x4, 604 605 /* INTERLEAVING -- interleave lanes from low or high halves of 606 operands. Most-significant result lane is from the left 607 arg. */ 608 Iop_InterleaveHI8x16, Iop_InterleaveHI16x8, 609 Iop_InterleaveHI32x4, Iop_InterleaveHI64x2, 610 Iop_InterleaveLO8x16, Iop_InterleaveLO16x8, 611 Iop_InterleaveLO32x4, Iop_InterleaveLO64x2, 612 613 /* DUPLICATING -- copy value to all lanes */ 614 Iop_Dup8x16, Iop_Dup16x8, Iop_Dup32x4, 615 616 /* PERMUTING -- copy src bytes to dst, 617 as indexed by control vector bytes: 618 for i in 0 .. 15 . result[i] = argL[ argR[i] ] 619 argR[i] values may only be in the range 0 .. 15, else behaviour 620 is undefined. */ 621 Iop_Perm8x16 622 } 623 IROp; 624 625extern void ppIROp ( IROp ); 626 627 628/* Encoding of IEEE754-specified rounding modes in Float -> Int 629 conversions. This is the same as the encoding used by Intel IA32 630 to indicate x87 rounding mode. */ 631typedef 632 enum { Irrm_NEAREST=0, Irrm_NegINF=1, Irrm_PosINF=2, Irrm_ZERO=3 } 633 IRRoundingMode; 634 635/* Floating point comparison result values, as created by Iop_CmpF64. 636 This is also derived from what IA32 does. */ 637typedef 638 enum { 639 Ircr_UN = 0x45, 640 Ircr_LT = 0x01, 641 Ircr_GT = 0x00, 642 Ircr_EQ = 0x40 643 } 644 IRCmpF64Result; 645 646 647/* ------------------ Expressions ------------------ */ 648/* 649 Some details of expression semantics: 650 651 IRExpr_GetI (also IRStmt_PutI) 652 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 653 These allow circular indexing into parts of the guest state, which 654 is essential for modelling situations where the identity of guest 655 registers is not known until run time. One example is the x87 FP 656 register stack. 657 658 The part of the guest state to be treated as a circular array is 659 described in an IRArray structure attached to the GetI/PutI. 660 IRArray holds the offset of the first element in the array, the 661 type of each element, and the number of elements. 662 663 The array index is indicated rather indirectly, in a way which 664 makes optimisation easy: as the sum of variable part (the 'ix' 665 field) and a constant offset (the 'bias' field). 666 667 Since the indexing is circular, the actual array index to use 668 is computed as (ix + bias) % number-of-elements-in-the-array. 669 670 Here's an example. The description 671 672 (96:8xF64)[t39,-7] 673 674 describes an array of 8 F64-typed values, the guest-state-offset 675 of the first being 96. This array is being indexed at 676 (t39 - 7) % 8. 677 678 It is important to get the array size/type exactly correct since IR 679 optimisation looks closely at such info in order to establish 680 aliasing/non-aliasing between seperate GetI and PutI events, which 681 is used to establish when they can be reordered, etc. Putting 682 incorrect info in will lead to obscure IR optimisation bugs. 683 684 IRExpr_CCall 685 ~~~~~~~~~~~~ 686 The name is the C helper function; the backends will call back to 687 the front ends to get the address of a host-code helper function to 688 be called. 689 690 The args are a NULL-terminated array of arguments. The stated 691 return IRType, and the implied argument types, must match that of 692 the function being called well enough so that the back end can 693 actually generate correct code for the call. 694 695 The called function **must** satisfy the following: 696 697 * no side effects -- must be a pure function, the result of which 698 depends only on the passed parameters. 699 700 * it may not look at, nor modify, any of the guest state since that 701 would hide guest state transitions from instrumenters 702 703 * it may not access guest memory, since that would hide guest 704 memory transactions from the instrumenters 705 706 This is restrictive, but makes the semantics clean, and does 707 not interfere with IR optimisation. 708 709 If you want to call a helper which can mess with guest state and/or 710 memory, instead use IRStmt_Dirty. This is a lot more flexible, but 711 you pay for that flexibility in that you have to give a bunch of 712 details about what the helper does (and you better be telling the 713 truth, otherwise any derived instrumentation will be wrong). Also 714 IRStmt_Dirty inhibits various IR optimisations and so can cause 715 quite poor code to be generated. Try to avoid it. */ 716 717/* The possible kinds of expressions are as follows: */ 718typedef 719 enum { 720 Iex_Binder, /* Used only in pattern matching. 721 Not an expression. */ 722 Iex_Get, /* read guest state, fixed offset */ 723 Iex_GetI, /* read guest state, run-time offset */ 724 Iex_Tmp, /* value of temporary */ 725 Iex_Binop, /* binary operation */ 726 Iex_Unop, /* unary operation */ 727 Iex_Load, /* read from memory */ 728 Iex_Const, /* constant-valued expression */ 729 Iex_Mux0X, /* ternary if-then-else operator (STRICT) */ 730 Iex_CCall /* call to pure (side-effect-free) helper fn */ 731 } 732 IRExprTag; 733 734typedef 735 struct _IRExpr { 736 IRExprTag tag; 737 union { 738 struct { 739 Int binder; 740 } Binder; 741 struct { 742 Int offset; 743 IRType ty; 744 } Get; 745 struct { 746 IRArray* descr; 747 struct _IRExpr* ix; 748 Int bias; 749 } GetI; 750 struct { 751 IRTemp tmp; 752 } Tmp; 753 struct { 754 IROp op; 755 struct _IRExpr* arg1; 756 struct _IRExpr* arg2; 757 } Binop; 758 struct { 759 IROp op; 760 struct _IRExpr* arg; 761 } Unop; 762 struct { 763 IREndness end; 764 IRType ty; 765 struct _IRExpr* addr; 766 } Load; 767 struct { 768 IRConst* con; 769 } Const; 770 struct { 771 IRCallee* cee; 772 IRType retty; 773 struct _IRExpr** args; 774 } CCall; 775 struct { 776 struct _IRExpr* cond; 777 struct _IRExpr* expr0; 778 struct _IRExpr* exprX; 779 } Mux0X; 780 } Iex; 781 } 782 IRExpr; 783 784extern IRExpr* IRExpr_Binder ( Int binder ); 785extern IRExpr* IRExpr_Get ( Int off, IRType ty ); 786extern IRExpr* IRExpr_GetI ( IRArray* descr, IRExpr* ix, Int bias ); 787extern IRExpr* IRExpr_Tmp ( IRTemp tmp ); 788extern IRExpr* IRExpr_Binop ( IROp op, IRExpr* arg1, IRExpr* arg2 ); 789extern IRExpr* IRExpr_Unop ( IROp op, IRExpr* arg ); 790extern IRExpr* IRExpr_Load ( IREndness end, IRType ty, IRExpr* addr ); 791extern IRExpr* IRExpr_Const ( IRConst* con ); 792extern IRExpr* IRExpr_CCall ( IRCallee* cee, IRType retty, IRExpr** args ); 793extern IRExpr* IRExpr_Mux0X ( IRExpr* cond, IRExpr* expr0, IRExpr* exprX ); 794 795extern IRExpr* dopyIRExpr ( IRExpr* ); 796 797extern void ppIRExpr ( IRExpr* ); 798 799/* NULL-terminated IRExpr expression vectors, suitable for use as arg 800 lists in clean/dirty helper calls. */ 801 802extern IRExpr** mkIRExprVec_0 ( void ); 803extern IRExpr** mkIRExprVec_1 ( IRExpr* ); 804extern IRExpr** mkIRExprVec_2 ( IRExpr*, IRExpr* ); 805extern IRExpr** mkIRExprVec_3 ( IRExpr*, IRExpr*, IRExpr* ); 806extern IRExpr** mkIRExprVec_4 ( IRExpr*, IRExpr*, IRExpr*, IRExpr* ); 807extern IRExpr** mkIRExprVec_5 ( IRExpr*, IRExpr*, 808 IRExpr*, IRExpr*, IRExpr* ); 809 810extern IRExpr** sopyIRExprVec ( IRExpr** ); 811extern IRExpr** dopyIRExprVec ( IRExpr** ); 812 813/* Make a constant expression from the given host word taking into 814 account of course the host word size. */ 815extern IRExpr* mkIRExpr_HWord ( HWord ); 816 817/* Convenience function for constructing clean helper calls. */ 818extern 819IRExpr* mkIRExprCCall ( IRType retty, 820 Int regparms, HChar* name, void* addr, 821 IRExpr** args ); 822 823 824/* Convenience functions for atoms, that is, IRExprs which 825 are either Iex_Tmp or Iex_Const. */ 826static inline Bool isIRAtom ( IRExpr* e ) { 827 return toBool(e->tag == Iex_Tmp || e->tag == Iex_Const); 828} 829 830/* Are these two IR atoms identical? Causes an assertion 831 failure if they are passed non-atoms. */ 832extern Bool eqIRAtom ( IRExpr*, IRExpr* ); 833 834 835/* ------------------ Jump kinds ------------------ */ 836 837/* This describes hints which can be passed to the dispatcher at guest 838 control-flow transfer points. 839 840 Re Ijk_Invalidate: the guest state _must_ have two 841 pseudo-registers, guest_TISTART and guest_TILEN, which specify the 842 start and length of the region to be invalidated. These are both 843 the size of a guest word. It is the responsibility of the relevant 844 toIR.c to ensure that these are filled in with suitable values 845 before issuing a jump of kind Ijk_TInval. 846*/ 847typedef 848 enum { 849 Ijk_Boring=0x14000, /* not interesting; just goto next */ 850 Ijk_Call, /* guest is doing a call */ 851 Ijk_Ret, /* guest is doing a return */ 852 Ijk_ClientReq, /* do guest client req before continuing */ 853 Ijk_Yield, /* client is yielding to thread scheduler */ 854 Ijk_EmWarn, /* report emulation warning before continuing */ 855 Ijk_NoDecode, /* next instruction cannot be decoded */ 856 Ijk_MapFail, /* Vex-provided address translation failed */ 857 Ijk_TInval, /* Invalidate translations before continuing. */ 858 /* Unfortunately, various guest-dependent syscall kinds. They 859 all mean: do a syscall before continuing. */ 860 Ijk_Sys_syscall, /* amd64 'syscall', ppc32 'sc' */ 861 Ijk_Sys_int32, /* amd64/x86 'int $0x20' */ 862 Ijk_Sys_int128, /* amd64/x86 'int $0x80' */ 863 Ijk_Sys_sysenter /* x86 'sysenter'. guest_EIP becomes 864 invalid at the point this happens. */ 865 } 866 IRJumpKind; 867 868extern void ppIRJumpKind ( IRJumpKind ); 869 870 871/* ------------------ Dirty helper calls ------------------ */ 872 873/* A dirty call is a flexible mechanism for calling a helper function 874 or procedure. The helper function may read, write or modify client 875 memory, and may read, write or modify client state. It can take 876 arguments and optionally return a value. It may return different 877 results and/or do different things when called repeated with the 878 same arguments, by means of storing private state. 879 880 If a value is returned, it is assigned to the nominated return 881 temporary. 882 883 Dirty calls are statements rather than expressions for obvious 884 reasons. If a dirty call is stated as writing guest state, any 885 values derived from the written parts of the guest state are 886 invalid. Similarly, if the dirty call is stated as writing 887 memory, any loaded values are invalidated by it. 888 889 In order that instrumentation is possible, the call must state, and 890 state correctly 891 892 * whether it reads, writes or modifies memory, and if so where 893 (only one chunk can be stated) 894 895 * whether it reads, writes or modifies guest state, and if so which 896 pieces (several pieces may be stated, and currently their extents 897 must be known at translation-time). 898 899 Normally, code is generated to pass just the args to the helper. 900 However, if .needsBBP is set, then an extra first argument is 901 passed, which is the baseblock pointer, so that the callee can 902 access the guest state. It is invalid for .nFxState to be zero 903 but .needsBBP to be True, since .nFxState==0 is a claim that the 904 call does not access guest state. 905 906 IMPORTANT NOTE re GUARDS: Dirty calls are strict, very strict. The 907 arguments are evaluated REGARDLESS of the guard value. It is 908 unspecified the relative order of arg evaluation and guard 909 evaluation. 910*/ 911 912#define VEX_N_FXSTATE 7 /* enough for FXSAVE/FXRSTOR on x86 */ 913 914typedef 915 enum { 916 Ifx_None = 0x15000, /* no effect */ 917 Ifx_Read, /* reads the resource */ 918 Ifx_Write, /* writes the resource */ 919 Ifx_Modify, /* modifies the resource */ 920 } 921 IREffect; 922 923extern void ppIREffect ( IREffect ); 924 925 926typedef 927 struct { 928 /* What to call, and details of args/results */ 929 IRCallee* cee; /* where to call */ 930 IRExpr* guard; /* :: Ity_Bit. Controls whether call happens */ 931 IRExpr** args; /* arg list, ends in NULL */ 932 IRTemp tmp; /* to assign result to, or IRTemp_INVALID if none */ 933 934 /* Mem effects; we allow only one R/W/M region to be stated */ 935 IREffect mFx; /* indicates memory effects, if any */ 936 IRExpr* mAddr; /* of access, or NULL if mFx==Ifx_None */ 937 Int mSize; /* of access, or zero if mFx==Ifx_None */ 938 939 /* Guest state effects; up to N allowed */ 940 Bool needsBBP; /* True => also pass guest state ptr to callee */ 941 Int nFxState; /* must be 0 .. VEX_N_FXSTATE */ 942 struct { 943 IREffect fx; /* read, write or modify? Ifx_None is invalid. */ 944 Int offset; 945 Int size; 946 } fxState[VEX_N_FXSTATE]; 947 } 948 IRDirty; 949 950extern void ppIRDirty ( IRDirty* ); 951extern IRDirty* emptyIRDirty ( void ); 952 953extern IRDirty* dopyIRDirty ( IRDirty* ); 954 955/* A handy function which takes some of the tedium out of constructing 956 dirty helper calls. The called function impliedly does not return 957 any value and has a constant-True guard. The call is marked as 958 accessing neither guest state nor memory (hence the "unsafe" 959 designation) -- you can mess with this later if need be. A 960 suitable IRCallee is constructed from the supplied bits. */ 961extern 962IRDirty* unsafeIRDirty_0_N ( Int regparms, HChar* name, void* addr, 963 IRExpr** args ); 964 965/* Similarly, make a zero-annotation dirty call which returns a value, 966 and assign that to the given temp. */ 967extern 968IRDirty* unsafeIRDirty_1_N ( IRTemp dst, 969 Int regparms, HChar* name, void* addr, 970 IRExpr** args ); 971 972 973/* ------------------ Statements ------------------ */ 974 975/* The possible kinds of statements are as follows. Those marked 976 OPTIONAL are hints of one kind or another, and as such do not 977 denote any change in the guest state or of IR temporaries. They 978 can therefore be omitted without changing the meaning denoted by 979 the IR. 980 981 At the moment, the only AbiHint is one which indicates that a given 982 chunk of address space has become undefined. This is used on 983 amd64-linux to pass stack-redzoning hints to whoever wants to see 984 them. 985*/ 986typedef 987 enum { 988 Ist_NoOp, /* OPTIONAL: no-op (usually resulting from IR 989 optimisation) */ 990 Ist_IMark, /* OPTIONAL: instruction mark: describe addr/len of 991 guest insn whose IR follows. */ 992 Ist_AbiHint, /* OPTIONAL: tell me something about this 993 platform's ABI */ 994 Ist_Put, /* write guest state, fixed offset */ 995 Ist_PutI, /* write guest state, run-time offset */ 996 Ist_Tmp, /* assign value to temporary */ 997 Ist_Store, /* write to memory */ 998 Ist_Dirty, /* call complex ("dirty") helper function */ 999 Ist_MFence, /* memory fence */ 1000 Ist_Exit /* conditional exit from BB */ 1001 } 1002 IRStmtTag; 1003 1004typedef 1005 struct _IRStmt { 1006 IRStmtTag tag; 1007 union { 1008 struct { 1009 } NoOp; 1010 struct { 1011 Addr64 addr; 1012 Int len; 1013 } IMark; 1014 struct { 1015 /* [base .. base+len-1] has become uninitialised */ 1016 IRExpr* base; 1017 Int len; 1018 } AbiHint; 1019 struct { 1020 Int offset; 1021 IRExpr* data; 1022 } Put; 1023 struct { 1024 IRArray* descr; 1025 IRExpr* ix; 1026 Int bias; 1027 IRExpr* data; 1028 } PutI; 1029 struct { 1030 IRTemp tmp; 1031 IRExpr* data; 1032 } Tmp; 1033 struct { 1034 IREndness end; 1035 IRExpr* addr; 1036 IRExpr* data; 1037 } Store; 1038 struct { 1039 IRDirty* details; 1040 } Dirty; 1041 struct { 1042 } MFence; 1043 struct { 1044 IRExpr* guard; 1045 IRJumpKind jk; 1046 IRConst* dst; 1047 } Exit; 1048 } Ist; 1049 } 1050 IRStmt; 1051 1052extern IRStmt* IRStmt_NoOp ( void ); 1053extern IRStmt* IRStmt_IMark ( Addr64 addr, Int len ); 1054extern IRStmt* IRStmt_AbiHint ( IRExpr* base, Int len ); 1055extern IRStmt* IRStmt_Put ( Int off, IRExpr* data ); 1056extern IRStmt* IRStmt_PutI ( IRArray* descr, IRExpr* ix, Int bias, 1057 IRExpr* data ); 1058extern IRStmt* IRStmt_Tmp ( IRTemp tmp, IRExpr* data ); 1059extern IRStmt* IRStmt_Store ( IREndness end, IRExpr* addr, IRExpr* data ); 1060extern IRStmt* IRStmt_Dirty ( IRDirty* details ); 1061extern IRStmt* IRStmt_MFence ( void ); 1062extern IRStmt* IRStmt_Exit ( IRExpr* guard, IRJumpKind jk, IRConst* dst ); 1063 1064extern IRStmt* dopyIRStmt ( IRStmt* ); 1065 1066extern void ppIRStmt ( IRStmt* ); 1067 1068 1069/* ------------------ Basic Blocks ------------------ */ 1070 1071/* A bunch of statements, expressions, etc, are incomplete without an 1072 environment indicating the type of each IRTemp. So this provides 1073 one. IR temporaries are really just unsigned ints and so this 1074 provides an array, 0 .. n_types_used-1 of them. 1075*/ 1076typedef 1077 struct { 1078 IRType* types; 1079 Int types_size; 1080 Int types_used; 1081 } 1082 IRTypeEnv; 1083 1084extern IRTemp newIRTemp ( IRTypeEnv*, IRType ); 1085extern IRTypeEnv* dopyIRTypeEnv ( IRTypeEnv* ); 1086 1087extern void ppIRTypeEnv ( IRTypeEnv* ); 1088 1089 1090/* Basic blocks contain: 1091 - A table giving a type for each temp 1092 - An expandable array of statements 1093 - An expression of type 32 or 64 bits, depending on the 1094 guest's word size, indicating the next destination. 1095 - An indication of any special actions (JumpKind) needed 1096 for this final jump. 1097*/ 1098typedef 1099 struct _IRBB { 1100 IRTypeEnv* tyenv; 1101 IRStmt** stmts; 1102 Int stmts_size; 1103 Int stmts_used; 1104 IRExpr* next; 1105 IRJumpKind jumpkind; 1106 } 1107 IRBB; 1108 1109extern IRBB* emptyIRBB ( void ); 1110 1111extern IRBB* dopyIRBB ( IRBB* ); 1112 1113extern void ppIRBB ( IRBB* ); 1114 1115extern void addStmtToIRBB ( IRBB*, IRStmt* ); 1116 1117 1118/*---------------------------------------------------------------*/ 1119/*--- Helper functions for the IR ---*/ 1120/*---------------------------------------------------------------*/ 1121 1122/* For messing with IR type environments */ 1123extern IRTypeEnv* emptyIRTypeEnv ( void ); 1124 1125/* What is the type of this expression? */ 1126extern IRType typeOfIRConst ( IRConst* ); 1127extern IRType typeOfIRTemp ( IRTypeEnv*, IRTemp ); 1128extern IRType typeOfIRExpr ( IRTypeEnv*, IRExpr* ); 1129 1130/* Sanity check a BB of IR */ 1131extern void sanityCheckIRBB ( IRBB* bb, 1132 HChar* caller, 1133 Bool require_flatness, 1134 IRType guest_word_size ); 1135extern Bool isFlatIRStmt ( IRStmt* ); 1136 1137/* Is this any value actually in the enumeration 'IRType' ? */ 1138extern Bool isPlausibleIRType ( IRType ty ); 1139 1140#endif /* ndef __LIBVEX_IR_H */ 1141 1142 1143/*---------------------------------------------------------------*/ 1144/*--- libvex_ir.h ---*/ 1145/*---------------------------------------------------------------*/ 1146