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