1 /* -*- mode: C; c-basic-offset: 3; -*- */
3 /*---------------------------------------------------------------*/
4 /*--- begin guest_s390_helpers.c ---*/
5 /*---------------------------------------------------------------*/
8 This file is part of Valgrind, a dynamic binary instrumentation
11 Copyright IBM Corp. 2010-2020
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.
29 /* Contributed by Florian Krohm */
31 #include "libvex_basictypes.h"
32 #include "libvex_emnote.h"
33 #include "libvex_guest_s390x.h"
34 #include "libvex_ir.h"
36 #include "libvex_s390x_common.h"
38 #include "main_util.h"
39 #include "main_globals.h"
40 #include "guest_generic_bb_to_IR.h"
41 #include "guest_s390_defs.h"
42 #include "s390_defs.h" /* S390_BFP_ROUND_xyzzy */
45 LibVEX_GuestS390X_initialise(VexGuestS390XState
*state
)
47 /*------------------------------------------------------------*/
48 /*--- Initialise ar registers ---*/
49 /*------------------------------------------------------------*/
68 /*------------------------------------------------------------*/
69 /*--- Initialise vr registers ---*/
70 /*------------------------------------------------------------*/
74 vr.w64[0] = vr.w64[1] = 0ULL; \
77 VRZERO(state
->guest_v0
)
78 VRZERO(state
->guest_v1
)
79 VRZERO(state
->guest_v2
)
80 VRZERO(state
->guest_v3
)
81 VRZERO(state
->guest_v4
)
82 VRZERO(state
->guest_v5
)
83 VRZERO(state
->guest_v6
)
84 VRZERO(state
->guest_v7
)
85 VRZERO(state
->guest_v8
)
86 VRZERO(state
->guest_v9
)
87 VRZERO(state
->guest_v10
)
88 VRZERO(state
->guest_v11
)
89 VRZERO(state
->guest_v12
)
90 VRZERO(state
->guest_v13
)
91 VRZERO(state
->guest_v14
)
92 VRZERO(state
->guest_v15
)
93 VRZERO(state
->guest_v16
)
94 VRZERO(state
->guest_v17
)
95 VRZERO(state
->guest_v18
)
96 VRZERO(state
->guest_v19
)
97 VRZERO(state
->guest_v20
)
98 VRZERO(state
->guest_v21
)
99 VRZERO(state
->guest_v22
)
100 VRZERO(state
->guest_v23
)
101 VRZERO(state
->guest_v24
)
102 VRZERO(state
->guest_v25
)
103 VRZERO(state
->guest_v26
)
104 VRZERO(state
->guest_v27
)
105 VRZERO(state
->guest_v28
)
106 VRZERO(state
->guest_v29
)
107 VRZERO(state
->guest_v30
)
108 VRZERO(state
->guest_v31
)
111 /*------------------------------------------------------------*/
112 /*--- Initialise gpr registers ---*/
113 /*------------------------------------------------------------*/
125 state
->guest_r10
= 0;
126 state
->guest_r11
= 0;
127 state
->guest_r12
= 0;
128 state
->guest_r13
= 0;
129 state
->guest_r14
= 0;
130 state
->guest_r15
= 0;
132 /*------------------------------------------------------------*/
133 /*--- Initialise S390 miscellaneous registers ---*/
134 /*------------------------------------------------------------*/
136 state
->guest_counter
= 0;
137 state
->guest_fpc
= 0;
140 /*------------------------------------------------------------*/
141 /*--- Initialise S390 pseudo registers ---*/
142 /*------------------------------------------------------------*/
144 state
->guest_SYSNO
= 0;
146 /*------------------------------------------------------------*/
147 /*--- Initialise generic pseudo registers ---*/
148 /*------------------------------------------------------------*/
150 state
->guest_NRADDR
= 0;
151 state
->guest_CMSTART
= 0;
152 state
->guest_CMLEN
= 0;
153 state
->guest_IP_AT_SYSCALL
= 0;
154 state
->guest_EMNOTE
= EmNote_NONE
;
155 state
->host_EvC_COUNTER
= 0;
156 state
->host_EvC_FAILADDR
= 0;
158 /*------------------------------------------------------------*/
159 /*--- Initialise thunk ---*/
160 /*------------------------------------------------------------*/
162 state
->guest_CC_OP
= 0;
163 state
->guest_CC_DEP1
= 0;
164 state
->guest_CC_DEP2
= 0;
165 state
->guest_CC_NDEP
= 0;
167 __builtin_memset(state
->padding
, 0x0, sizeof(state
->padding
));
171 /* Figure out if any part of the guest state contained in minoff
172 .. maxoff requires precise memory exceptions. If in doubt return
173 True (but this generates significantly slower code). */
175 guest_s390x_state_requires_precise_mem_exns (
176 Int minoff
, Int maxoff
, VexRegisterUpdates pxControl
179 Int lr_min
= S390X_GUEST_OFFSET(guest_LR
);
180 Int lr_max
= lr_min
+ 8 - 1;
181 Int sp_min
= S390X_GUEST_OFFSET(guest_SP
);
182 Int sp_max
= sp_min
+ 8 - 1;
183 Int fp_min
= S390X_GUEST_OFFSET(guest_FP
);
184 Int fp_max
= fp_min
+ 8 - 1;
185 Int ia_min
= S390X_GUEST_OFFSET(guest_IA
);
186 Int ia_max
= ia_min
+ 8 - 1;
188 if (maxoff
< sp_min
|| minoff
> sp_max
) {
189 /* No overlap with SP */
190 if (pxControl
== VexRegUpdSpAtMemAccess
)
191 return False
; // We only need to check stack pointer.
196 if (maxoff
< lr_min
|| minoff
> lr_max
) {
197 /* No overlap with LR */
202 if (maxoff
< fp_min
|| minoff
> fp_max
) {
203 /* No overlap with FP */
208 if (maxoff
< ia_min
|| minoff
> ia_max
) {
209 /* No overlap with IA */
218 #define ALWAYSDEFD(field) \
219 { S390X_GUEST_OFFSET(field), \
220 (sizeof ((VexGuestS390XState*)0)->field) }
222 VexGuestLayout s390xGuest_layout
= {
224 /* Total size of the guest state, in bytes. */
225 .total_sizeB
= sizeof(VexGuestS390XState
),
227 /* Describe the stack pointer. */
228 .offset_SP
= S390X_GUEST_OFFSET(guest_SP
),
231 /* Describe the frame pointer. */
232 .offset_FP
= S390X_GUEST_OFFSET(guest_FP
),
235 /* Describe the instruction pointer. */
236 .offset_IP
= S390X_GUEST_OFFSET(guest_IA
),
239 /* Describe any sections to be regarded by Memcheck as
243 /* Flags thunk: OP and NDEP are always defined, whereas DEP1
244 and DEP2 have to be tracked. See detailed comment in
245 gdefs.h on meaning of thunk fields. */
247 /* 0 */ ALWAYSDEFD(guest_CC_OP
), /* generic */
248 /* 1 */ ALWAYSDEFD(guest_CC_NDEP
), /* generic */
249 /* 2 */ ALWAYSDEFD(guest_EMNOTE
), /* generic */
250 /* 3 */ ALWAYSDEFD(guest_CMSTART
), /* generic */
251 /* 4 */ ALWAYSDEFD(guest_CMLEN
), /* generic */
252 /* 5 */ ALWAYSDEFD(guest_IP_AT_SYSCALL
), /* generic */
253 /* 6 */ ALWAYSDEFD(guest_IA
), /* control reg */
254 /* 7 */ ALWAYSDEFD(guest_fpc
), /* control reg */
255 /* 8 */ ALWAYSDEFD(guest_counter
), /* internal usage register */
259 /*------------------------------------------------------------*/
260 /*--- Dirty helper for EXecute ---*/
261 /*------------------------------------------------------------*/
263 s390x_dirtyhelper_EX(ULong torun
, Addr64 addr
)
265 last_execute_target
= torun
;
266 guest_IA_rel_base
= addr
;
270 /*------------------------------------------------------------*/
271 /*--- Dirty helper for Clock instructions ---*/
272 /*------------------------------------------------------------*/
273 #if defined(VGA_s390x)
275 s390x_dirtyhelper_STCK(ULong
*addr
)
279 asm volatile("stck %0\n"
282 : "+Q" (*addr
), "=d" (cc
) : : "cc");
287 s390x_dirtyhelper_STCKE(ULong
*addr
)
291 asm volatile("stcke %0\n"
294 : "+Q" (*addr
), "=d" (cc
) : : "cc");
298 ULong
s390x_dirtyhelper_STCKF(ULong
*addr
)
302 asm volatile(".insn s,0xb27c0000,%0\n"
305 : "+Q" (*addr
), "=d" (cc
) : : "cc");
309 ULong
s390x_dirtyhelper_STCK(ULong
*addr
) {return 3;}
310 ULong
s390x_dirtyhelper_STCKF(ULong
*addr
) {return 3;}
311 ULong
s390x_dirtyhelper_STCKE(ULong
*addr
) {return 3;}
312 #endif /* VGA_s390x */
315 /*------------------------------------------------------------*/
316 /*--- Dirty helper for the "convert unicode" insn family. ---*/
317 /*------------------------------------------------------------*/
319 s390x_dirtyhelper_CUxy(UChar
*address
, ULong data
, ULong num_bytes
)
323 vassert(num_bytes
>= 1 && num_bytes
<= 4);
325 /* Store the least significant NUM_BYTES bytes in DATA left to right
327 for (i
= 1; i
<= num_bytes
; ++i
) {
328 address
[num_bytes
- i
] = data
& 0xff;
334 /*------------------------------------------------------------*/
335 /*--- Clean helper for CU21. ---*/
336 /*------------------------------------------------------------*/
338 /* The function performs a CU21 operation. It returns three things
339 encoded in an ULong value:
340 - the converted bytes (at most 4)
341 - the number of converted bytes
342 - an indication whether LOW_SURROGATE, if any, is invalid
345 +-------+-----------------+-----------+-----------------------+
346 | 0x0 | converted bytes | num_bytes | invalid_low_surrogate |
347 +-------+-----------------+-----------+-----------------------+
350 s390_do_cu21(UInt srcval
, UInt low_surrogate
)
352 ULong retval
= 0; // shut up gcc
353 UInt b1
, b2
, b3
, b4
, num_bytes
, invalid_low_surrogate
= 0;
357 /* Determine the number of bytes in the converted value */
358 if (srcval
<= 0x007f)
360 else if (srcval
>= 0x0080 && srcval
<= 0x07ff)
362 else if ((srcval
>= 0x0800 && srcval
<= 0xd7ff) ||
363 (srcval
>= 0xdc00 && srcval
<= 0xffff))
368 /* Determine UTF-8 bytes according to calculated num_bytes */
375 /* order of bytes left to right: b1, b2 */
382 retval
= (b1
<< 8) | b2
;
386 /* order of bytes left to right: b1, b2, b3 */
391 b2
|= (srcval
>> 6) & 0x3f;
396 retval
= (b1
<< 16) | (b2
<< 8) | b3
;
400 /* order of bytes left to right: b1, b2, b3, b4 */
401 UInt high_surrogate
= srcval
;
402 UInt uvwxy
= ((high_surrogate
>> 6) & 0xf) + 1; // abcd + 1
405 b1
|= uvwxy
>> 2; // uvw
408 b2
|= (uvwxy
& 0x3) << 4; // xy
409 b2
|= (high_surrogate
>> 2) & 0xf; // efgh
412 b3
|= (high_surrogate
& 0x3) << 4; // ij
413 b3
|= (low_surrogate
>> 6) & 0xf; // klmn
416 b4
|= low_surrogate
& 0x3f;
418 retval
= (b1
<< 24) | (b2
<< 16) | (b3
<< 8) | b4
;
420 invalid_low_surrogate
= (low_surrogate
& 0xfc00) != 0xdc00;
425 /* At this point RETVAL contains the converted bytes.
426 Build up the final return value. */
427 return (retval
<< 16) | (num_bytes
<< 8) | invalid_low_surrogate
;
431 /*------------------------------------------------------------*/
432 /*--- Clean helper for CU24. ---*/
433 /*------------------------------------------------------------*/
435 /* The function performs a CU24 operation. It returns two things
436 encoded in an ULong value:
437 - the 4 converted bytes
438 - an indication whether LOW_SURROGATE, if any, is invalid
441 +------------------------+-----------------------+
442 | 0x0 | converted bytes | invalid_low_surrogate |
443 +------------------------+-----------------------+
446 s390_do_cu24(UInt srcval
, UInt low_surrogate
)
449 UInt invalid_low_surrogate
= 0;
453 if ((srcval
<= 0xd7ff) ||
454 (srcval
>= 0xdc00 && srcval
<= 0xffff)) {
458 UInt high_surrogate
= srcval
;
459 UInt uvwxy
= ((high_surrogate
>> 6) & 0xf) + 1; // abcd + 1
460 UInt efghij
= high_surrogate
& 0x3f;
461 UInt klmnoprst
= low_surrogate
& 0x3ff;
463 retval
= (uvwxy
<< 16) | (efghij
<< 10) | klmnoprst
;
465 invalid_low_surrogate
= (low_surrogate
& 0xfc00) != 0xdc00;
468 /* At this point RETVAL contains the converted bytes.
469 Build up the final return value. */
470 return (retval
<< 8) | invalid_low_surrogate
;
474 /*------------------------------------------------------------*/
475 /*--- Clean helper for CU42. ---*/
476 /*------------------------------------------------------------*/
478 /* The function performs a CU42 operation. It returns three things
479 encoded in an ULong value:
480 - the converted bytes (at most 4)
481 - the number of converted bytes (2 or 4; 0 if invalid character)
482 - an indication whether the UTF-32 character is invalid
485 +-------+-----------------+-----------+-------------------+
486 | 0x0 | converted bytes | num_bytes | invalid_character |
487 +-------+-----------------+-----------+-------------------+
490 s390_do_cu42(UInt srcval
)
493 UInt num_bytes
, invalid_character
= 0;
495 if ((srcval
>= 0x0000 && srcval
<= 0xd7ff) ||
496 (srcval
>= 0xdc00 && srcval
<= 0xffff)) {
499 } else if (srcval
>= 0x00010000 && srcval
<= 0x0010FFFF) {
500 UInt uvwxy
= srcval
>> 16;
501 UInt abcd
= (uvwxy
- 1) & 0xf;
502 UInt efghij
= (srcval
>> 10) & 0x3f;
504 UInt high_surrogate
= (0xd8 << 8) | (abcd
<< 6) | efghij
;
505 UInt low_surrogate
= (0xdc << 8) | (srcval
& 0x3ff);
507 retval
= (high_surrogate
<< 16) | low_surrogate
;
510 /* D800 - DBFF or 00110000 - FFFFFFFF */
511 invalid_character
= 1;
512 retval
= num_bytes
= 0; /* does not matter; not used */
515 /* At this point RETVAL contains the converted bytes.
516 Build up the final return value. */
517 return (retval
<< 16) | (num_bytes
<< 8) | invalid_character
;
521 /*------------------------------------------------------------*/
522 /*--- Clean helper for CU41. ---*/
523 /*------------------------------------------------------------*/
525 /* The function performs a CU41 operation. It returns three things
526 encoded in an ULong value:
527 - the converted bytes (at most 4)
528 - the number of converted bytes (1, 2, 3, or 4; 0 if invalid character)
529 - an indication whether the UTF-32 character is invalid
532 +-------+-----------------+-----------+-------------------+
533 | 0x0 | converted bytes | num_bytes | invalid_character |
534 +-------+-----------------+-----------+-------------------+
537 s390_do_cu41(UInt srcval
)
540 UInt num_bytes
, invalid_character
= 0;
542 if (srcval
<= 0x7f) {
545 } else if (srcval
>= 0x80 && srcval
<= 0x7ff) {
546 UInt fghij
= srcval
>> 6;
547 UInt klmnop
= srcval
& 0x3f;
548 UInt byte1
= (0xc0 | fghij
);
549 UInt byte2
= (0x80 | klmnop
);
551 retval
= (byte1
<< 8) | byte2
;
553 } else if ((srcval
>= 0x800 && srcval
<= 0xd7ff) ||
554 (srcval
>= 0xdc00 && srcval
<= 0xffff)) {
555 UInt abcd
= srcval
>> 12;
556 UInt efghij
= (srcval
>> 6) & 0x3f;
557 UInt klmnop
= srcval
& 0x3f;
558 UInt byte1
= 0xe0 | abcd
;
559 UInt byte2
= 0x80 | efghij
;
560 UInt byte3
= 0x80 | klmnop
;
562 retval
= (byte1
<< 16) | (byte2
<< 8) | byte3
;
564 } else if (srcval
>= 0x10000 && srcval
<= 0x10ffff) {
565 UInt uvw
= (srcval
>> 18) & 0x7;
566 UInt xy
= (srcval
>> 16) & 0x3;
567 UInt efgh
= (srcval
>> 12) & 0xf;
568 UInt ijklmn
= (srcval
>> 6) & 0x3f;
569 UInt opqrst
= srcval
& 0x3f;
570 UInt byte1
= 0xf0 | uvw
;
571 UInt byte2
= 0x80 | (xy
<< 4) | efgh
;
572 UInt byte3
= 0x80 | ijklmn
;
573 UInt byte4
= 0x80 | opqrst
;
575 retval
= (byte1
<< 24) | (byte2
<< 16) | (byte3
<< 8) | byte4
;
578 /* d800 ... dbff or 00110000 ... ffffffff */
579 invalid_character
= 1;
585 /* At this point RETVAL contains the converted bytes.
586 Build up the final return value. */
587 return (retval
<< 16) | (num_bytes
<< 8) | invalid_character
;
591 /*------------------------------------------------------------*/
592 /*--- Clean helpers for CU12. ---*/
593 /*------------------------------------------------------------*/
595 /* The function looks at the first byte of an UTF-8 character and returns
596 two things encoded in an ULong value:
598 - the number of bytes that need to be read
599 - an indication whether the UTF-8 character is invalid
602 +-------------------+-------------------+
603 | 0x0 | num_bytes | invalid_character |
604 +-------+-----------+-------------------+
607 s390_do_cu12_cu14_helper1(UInt byte
, UInt etf3_and_m3_is_1
)
609 vassert(byte
<= 0xff);
611 /* Check whether the character is invalid */
612 if (byte
>= 0x80 && byte
<= 0xbf) return 1;
613 if (byte
>= 0xf8) return 1;
615 if (etf3_and_m3_is_1
) {
616 if (byte
== 0xc0 || byte
== 0xc1) return 1;
617 if (byte
>= 0xf5 && byte
<= 0xf7) return 1;
620 /* Character is valid */
621 if (byte
<= 0x7f) return 1 << 8; // 1 byte
622 if (byte
<= 0xdf) return 2 << 8; // 2 bytes
623 if (byte
<= 0xef) return 3 << 8; // 3 bytes
625 return 4 << 8; // 4 bytes
628 /* The function performs a CU12 or CU14 operation. BYTE1, BYTE2, etc are the
629 bytes as read from the input stream, left to right. BYTE1 is a valid
630 byte. The function returns three things encoded in an ULong value:
632 - the converted bytes
633 - the number of converted bytes (2 or 4; 0 if invalid character)
634 - an indication whether the UTF-16 character is invalid
637 +-------+-----------------+-----------+-------------------+
638 | 0x0 | converted bytes | num_bytes | invalid_character |
639 +-------+-----------------+-----------+-------------------+
642 s390_do_cu12_cu14_helper2(UInt byte1
, UInt byte2
, UInt byte3
, UInt byte4
,
643 ULong stuff
, Bool is_cu12
)
645 UInt num_src_bytes
= stuff
>> 1, etf3_and_m3_is_1
= stuff
& 0x1;
646 UInt num_bytes
= 0, invalid_character
= 0;
649 vassert(num_src_bytes
<= 4);
651 switch (num_src_bytes
) {
659 if (etf3_and_m3_is_1
) {
660 if (byte2
< 0x80 || byte2
> 0xbf) {
661 invalid_character
= 1;
667 UInt fghij
= byte1
& 0x1f;
668 UInt klmnop
= byte2
& 0x3f;
671 retval
= (fghij
<< 6) | klmnop
;
677 if (etf3_and_m3_is_1
) {
679 if ((byte2
< 0xa0 || byte2
> 0xbf) ||
680 (byte3
< 0x80 || byte3
> 0xbf)) {
681 invalid_character
= 1;
685 if ((byte1
>= 0xe1 && byte1
<= 0xec) ||
686 byte1
== 0xee || byte1
== 0xef) {
687 if ((byte2
< 0x80 || byte2
> 0xbf) ||
688 (byte3
< 0x80 || byte3
> 0xbf)) {
689 invalid_character
= 1;
694 if ((byte2
< 0x80 || byte2
> 0x9f) ||
695 (byte3
< 0x80 || byte3
> 0xbf)) {
696 invalid_character
= 1;
703 UInt abcd
= byte1
& 0xf;
704 UInt efghij
= byte2
& 0x3f;
705 UInt klmnop
= byte3
& 0x3f;
708 retval
= (abcd
<< 12) | (efghij
<< 6) | klmnop
;
714 if (etf3_and_m3_is_1
) {
716 if ((byte2
< 0x90 || byte2
> 0xbf) ||
717 (byte3
< 0x80 || byte3
> 0xbf) ||
718 (byte4
< 0x80 || byte4
> 0xbf)) {
719 invalid_character
= 1;
723 if (byte1
== 0xf1 || byte1
== 0xf2 || byte1
== 0xf3) {
724 if ((byte2
< 0x80 || byte2
> 0xbf) ||
725 (byte3
< 0x80 || byte3
> 0xbf) ||
726 (byte4
< 0x80 || byte4
> 0xbf)) {
727 invalid_character
= 1;
732 if ((byte2
< 0x80 || byte2
> 0x8f) ||
733 (byte3
< 0x80 || byte3
> 0xbf) ||
734 (byte4
< 0x80 || byte4
> 0xbf)) {
735 invalid_character
= 1;
742 UInt uvw
= byte1
& 0x7;
743 UInt xy
= (byte2
>> 4) & 0x3;
744 UInt uvwxy
= (uvw
<< 2) | xy
;
745 UInt efgh
= byte2
& 0xf;
746 UInt ij
= (byte3
>> 4) & 0x3;
747 UInt klmn
= byte3
& 0xf;
748 UInt opqrst
= byte4
& 0x3f;
751 UInt abcd
= (uvwxy
- 1) & 0xf;
752 UInt high_surrogate
= (0xd8 << 8) | (abcd
<< 6) | (efgh
<< 2) | ij
;
753 UInt low_surrogate
= (0xdc << 8) | (klmn
<< 6) | opqrst
;
756 retval
= (high_surrogate
<< 16) | low_surrogate
;
760 (uvwxy
<< 16) | (efgh
<< 12) | (ij
<< 10) | (klmn
<< 6) | opqrst
;
766 if (! is_cu12
) num_bytes
= 4; // for CU14, by definition
768 /* At this point RETVAL contains the converted bytes.
769 Build up the final return value. */
770 return (retval
<< 16) | (num_bytes
<< 8) | invalid_character
;
774 s390_do_cu12_helper2(UInt byte1
, UInt byte2
, UInt byte3
, UInt byte4
,
777 return s390_do_cu12_cu14_helper2(byte1
, byte2
, byte3
, byte4
, stuff
,
782 s390_do_cu14_helper2(UInt byte1
, UInt byte2
, UInt byte3
, UInt byte4
,
785 return s390_do_cu12_cu14_helper2(byte1
, byte2
, byte3
, byte4
, stuff
,
790 /*------------------------------------------------------------*/
791 /*--- Clean helper for "convert to binary". ---*/
792 /*------------------------------------------------------------*/
793 #if defined(VGA_s390x)
795 s390_do_cvb(ULong decimal
)
800 "cvb %[result],%[input]\n\t"
801 : [result
] "=d"(binary
)
802 : [input
] "R"(decimal
)
809 UInt
s390_do_cvb(ULong decimal
) { return 0; }
813 /*------------------------------------------------------------*/
814 /*--- Clean helper for "convert to decimal". ---*/
815 /*------------------------------------------------------------*/
816 #if defined(VGA_s390x)
818 s390_do_cvd(ULong binary_in
)
820 UInt binary
= binary_in
& 0xffffffffULL
;
824 "cvd %[input],%[result]\n\t"
825 : [result
] "=m"(decimal
)
826 : [input
] "d"(binary
)
833 ULong
s390_do_cvd(ULong binary
) { return 0; }
836 /*------------------------------------------------------------*/
837 /*--- Clean helper for "Extract cache attribute". ---*/
838 /*------------------------------------------------------------*/
839 #if defined(VGA_s390x)
841 s390_do_ecag(ULong op2addr
)
845 __asm__
volatile(".insn rsy,0xEB000000004C,%[out],0,0(%[in])\n\t"
847 : [in
] "d"(op2addr
));
852 ULong
s390_do_ecag(ULong op2addr
) { return 0; }
855 /*------------------------------------------------------------*/
856 /*--- Clean helper for "Perform Floating Point Operation". ---*/
857 /*------------------------------------------------------------*/
858 #if defined(VGA_s390x)
860 s390_do_pfpo(UInt gpr0
)
863 UChar op1_ty
, op2_ty
;
866 if (rm
> 1 && rm
< 8)
867 return EmFail_S390X_invalid_PFPO_rounding_mode
;
869 op1_ty
= (gpr0
>> 16) & 0xff; // gpr0[40:47]
870 op2_ty
= (gpr0
>> 8) & 0xff; // gpr0[48:55]
871 /* Operand type must be BFP 32, 64, 128 or DFP 32, 64, 128
872 which correspond to 0x5, 0x6, 0x7, 0x8, 0x9, 0xa respectively.
873 Any other operand type value is unsupported */
874 if ((op1_ty
== op2_ty
) ||
875 (op1_ty
< 0x5 || op1_ty
> 0xa) ||
876 (op2_ty
< 0x5 || op2_ty
> 0xa))
877 return EmFail_S390X_invalid_PFPO_function
;
882 UInt
s390_do_pfpo(UInt gpr0
) { return 0; }
885 /*------------------------------------------------------------*/
886 /*--- Helper for condition code. ---*/
887 /*------------------------------------------------------------*/
889 #if defined(VGA_s390x)
890 typedef long double Float128
;
891 union s390x_F64
{ ULong i
; Double f
; };
892 union s390x_F128
{ struct { ULong hi
, lo
; } i
; Float128 f
; };
894 /* Convert an IRRoundingMode value to s390_bfp_round_t */
895 static s390_bfp_round_t
896 decode_bfp_rounding_mode(UInt irrm
)
899 case Irrm_NEAREST
: return S390_BFP_ROUND_NEAREST_EVEN
;
900 case Irrm_NegINF
: return S390_BFP_ROUND_NEGINF
;
901 case Irrm_PosINF
: return S390_BFP_ROUND_POSINF
;
902 case Irrm_ZERO
: return S390_BFP_ROUND_ZERO
;
904 vpanic("decode_bfp_rounding_mode");
907 #define S390_CC_FOR_BINARY(opcode,cc_dep1,cc_dep2) \
910 opcode " %[op1],%[op2]\n\t" \
911 "ipm %[psw]\n\t" : [psw] "=d"(psw), [op1] "+d"(cc_dep1) \
912 : [op2] "d"(cc_dep2) \
914 psw >> 28; /* cc */ \
917 #define S390_CC_FOR_TERNARY(opcode,cc_dep1,cc_dep2) \
920 opcode ",%[op1],%[op1],%[op2],0\n\t" \
921 "ipm %[psw]\n\t" : [psw] "=d"(psw), [op1] "+d"(cc_dep1) \
922 : [op2] "d"(cc_dep2) \
924 psw >> 28; /* cc */ \
927 #define S390_CC_FOR_TERNARY_SUBB(opcode,cc_dep1,cc_dep2,cc_ndep) \
929 /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
931 cc_dep2 = cc_dep2 ^ cc_ndep; \
934 "sr %[tmp],%[op3]\n\t" /* borrow to cc */ \
935 opcode " %[op1],%[op2]\n\t" /* then redo the op */\
936 "ipm %[psw]\n\t" : [psw] "=d"(psw), [op1] "+&d"(cc_dep1), \
938 : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
940 psw >> 28; /* cc */ \
943 #define S390_CC_FOR_TERNARY_ADDC(opcode,cc_dep1,cc_dep2,cc_ndep) \
945 /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
947 cc_dep2 = cc_dep2 ^ cc_ndep; \
950 "lgfr %[tmp],%[op3]\n\t" /* first load cc_ndep */ \
951 "aghi %[tmp],0\n\t" /* and convert it into a cc */ \
952 opcode " %[op1],%[op2]\n\t" /* then redo the op */\
953 "ipm %[psw]\n\t" : [psw] "=d"(psw), [op1] "+&d"(cc_dep1), \
955 : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
957 psw >> 28; /* cc */ \
961 #define S390_CC_FOR_BFP_RESULT(opcode,cc_dep1) \
963 union s390x_F64 op = { .i = cc_dep1 }; \
966 opcode " %[tmp],%[op]\n\t" \
967 "ipm %[psw]\n\t" : [psw] "=d"(psw), [tmp] "=f"(tmp) \
970 psw >> 28; /* cc */ \
973 #define S390_CC_FOR_BFP128_RESULT(hi,lo) \
975 union s390x_F128 op = { .i = { hi, lo } }; \
978 "ltxbr %[tmp],%[op]\n\t" \
979 "ipm %[psw]\n\t" : [psw] "=d"(psw), [tmp] "=f"(tmp) \
982 psw >> 28; /* cc */ \
985 #define S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,rounding_mode) \
987 union s390x_F64 op = { .i = cc_dep1 }; \
990 opcode " %[tmp]," #rounding_mode ",%[op]\n\t" \
991 "ipm %[psw]\n\t" : [psw] "=d"(psw), [tmp] "=d"(tmp) \
994 psw >> 28; /* cc */ \
997 #define S390_CC_FOR_BFP_CONVERT(opcode,cc_dep1,cc_dep2) \
1000 switch (decode_bfp_rounding_mode(cc_dep2)) { \
1001 case S390_BFP_ROUND_NEAREST_EVEN: \
1002 cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,4); \
1004 case S390_BFP_ROUND_ZERO: \
1005 cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,5); \
1007 case S390_BFP_ROUND_POSINF: \
1008 cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,6); \
1010 case S390_BFP_ROUND_NEGINF: \
1011 cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,7); \
1014 vpanic("unexpected bfp rounding mode"); \
1019 #define S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,rounding_mode) \
1021 union s390x_F64 op = { .i = cc_dep1 }; \
1023 __asm__ volatile ( \
1024 opcode ",%[tmp],%[op]," #rounding_mode ",0\n\t" \
1025 "ipm %[psw]\n\t" : [psw] "=d"(psw), [tmp] "=d"(tmp) \
1028 psw >> 28; /* cc */ \
1031 #define S390_CC_FOR_BFP_UCONVERT(opcode,cc_dep1,cc_dep2) \
1034 switch (decode_bfp_rounding_mode(cc_dep2)) { \
1035 case S390_BFP_ROUND_NEAREST_EVEN: \
1036 cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,4); \
1038 case S390_BFP_ROUND_ZERO: \
1039 cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,5); \
1041 case S390_BFP_ROUND_POSINF: \
1042 cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,6); \
1044 case S390_BFP_ROUND_NEGINF: \
1045 cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,7); \
1048 vpanic("unexpected bfp rounding mode"); \
1053 #define S390_CC_FOR_BFP128_CONVERT_AUX(opcode,hi,lo,rounding_mode) \
1055 union s390x_F128 op = { .i = { hi, lo } }; \
1057 __asm__ volatile ( \
1058 opcode " %[tmp]," #rounding_mode ",%[op]\n\t" \
1059 "ipm %[psw]\n\t" : [psw] "=d"(psw), [tmp] "=d"(tmp) \
1062 psw >> 28; /* cc */ \
1065 #define S390_CC_FOR_BFP128_CONVERT(opcode,cc_dep1,cc_dep2,cc_ndep) \
1068 /* Recover the original DEP2 value. See comment near \
1069 s390_cc_thunk_put3 for rationale. */ \
1070 cc_dep2 = cc_dep2 ^ cc_ndep; \
1071 switch (decode_bfp_rounding_mode(cc_ndep)) { \
1072 case S390_BFP_ROUND_NEAREST_EVEN: \
1073 cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,4); \
1075 case S390_BFP_ROUND_ZERO: \
1076 cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,5); \
1078 case S390_BFP_ROUND_POSINF: \
1079 cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,6); \
1081 case S390_BFP_ROUND_NEGINF: \
1082 cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,7); \
1085 vpanic("unexpected bfp rounding mode"); \
1090 #define S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,hi,lo,rounding_mode) \
1092 union s390x_F128 op = { .i = { hi, lo } }; \
1094 __asm__ volatile ( \
1095 opcode ",%[tmp],%[op]," #rounding_mode ",0\n\t" \
1096 "ipm %[psw]\n\t" : [psw] "=d"(psw), [tmp] "=d"(tmp) \
1099 psw >> 28; /* cc */ \
1102 #define S390_CC_FOR_BFP128_UCONVERT(opcode,cc_dep1,cc_dep2,cc_ndep) \
1105 /* Recover the original DEP2 value. See comment near \
1106 s390_cc_thunk_put3 for rationale. */ \
1107 cc_dep2 = cc_dep2 ^ cc_ndep; \
1108 switch (decode_bfp_rounding_mode(cc_ndep)) { \
1109 case S390_BFP_ROUND_NEAREST_EVEN: \
1110 cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,4); \
1112 case S390_BFP_ROUND_ZERO: \
1113 cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,5); \
1115 case S390_BFP_ROUND_POSINF: \
1116 cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,6); \
1118 case S390_BFP_ROUND_NEGINF: \
1119 cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,7); \
1122 vpanic("unexpected bfp rounding mode"); \
1127 #define S390_CC_FOR_BFP_TDC(opcode,cc_dep1,cc_dep2) \
1129 union s390x_F64 val = { .i = cc_dep1 }; \
1130 __asm__ volatile ( \
1131 opcode " %[value],0(%[class])\n\t" \
1132 "ipm %[psw]\n\t" : [psw] "=d"(psw) \
1133 : [value] "f"(val.f), \
1134 [class] "a"(cc_dep2) \
1136 psw >> 28; /* cc */ \
1139 #define S390_CC_FOR_BFP128_TDC(cc_dep1,cc_dep2,cc_ndep) \
1141 /* Recover the original DEP2 value. See comment near \
1142 s390_cc_thunk_put1f128Z for rationale. */ \
1143 cc_dep2 = cc_dep2 ^ cc_ndep; \
1144 union s390x_F128 val = { .i = { cc_dep1, cc_dep2 } }; \
1145 __asm__ volatile ( \
1146 "tcxb %[value],0(%[class])\n\t" \
1147 "ipm %[psw]\n\t" : [psw] "=d"(psw) \
1148 : [value] "f"(val.f), [class] "a"(cc_ndep) \
1150 psw >> 28; /* cc */ \
1153 /* Convert an IRRoundingMode value to s390_dfp_round_t */
1154 static s390_dfp_round_t
1155 decode_dfp_rounding_mode(UInt irrm
)
1159 return S390_DFP_ROUND_NEAREST_EVEN_4
;
1161 return S390_DFP_ROUND_NEGINF_7
;
1163 return S390_DFP_ROUND_POSINF_6
;
1165 return S390_DFP_ROUND_ZERO_5
;
1166 case Irrm_NEAREST_TIE_AWAY_0
:
1167 return S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1
;
1168 case Irrm_PREPARE_SHORTER
:
1169 return S390_DFP_ROUND_PREPARE_SHORT_3
;
1170 case Irrm_AWAY_FROM_ZERO
:
1171 return S390_DFP_ROUND_AWAY_0
;
1172 case Irrm_NEAREST_TIE_TOWARD_0
:
1173 return S390_DFP_ROUND_NEAREST_TIE_TOWARD_0
;
1175 vpanic("decode_dfp_rounding_mode");
1178 #define S390_CC_FOR_DFP_RESULT(cc_dep1) \
1180 union s390x_F64 op = { .i = cc_dep1 }; \
1182 __asm__ volatile ( \
1183 ".insn rre, 0xb3d60000,%[tmp],%[op]\n\t" /* LTDTR */ \
1184 "ipm %[psw]\n\t" : [psw] "=d"(psw), [tmp] "=f"(tmp) \
1187 psw >> 28; /* cc */ \
1190 #define S390_CC_FOR_DFP128_RESULT(hi,lo) \
1192 union s390x_F128 op = { .i = { hi, lo } }; \
1194 __asm__ volatile ( \
1195 ".insn rre, 0xb3de0000,%[tmp],%[op]\n\t" /* LTXTR */ \
1196 "ipm %[psw]\n\t" : [psw] "=d"(psw), [tmp] "=f"(tmp) \
1199 psw >> 28; /* cc */ \
1202 #define S390_CC_FOR_DFP_TD(opcode,cc_dep1,cc_dep2) \
1204 union s390x_F64 val = { .i = cc_dep1 }; \
1205 __asm__ volatile ( \
1206 opcode ",%[value],0(%[class])\n\t" \
1207 "ipm %[psw]\n\t" : [psw] "=d"(psw) \
1208 : [value] "f"(val.f), \
1209 [class] "a"(cc_dep2) \
1211 psw >> 28; /* cc */ \
1214 #define S390_CC_FOR_DFP128_TD(opcode,cc_dep1,cc_dep2,cc_ndep) \
1216 /* Recover the original DEP2 value. See comment near \
1217 s390_cc_thunk_put1d128Z for rationale. */ \
1218 cc_dep2 = cc_dep2 ^ cc_ndep; \
1219 union s390x_F128 val = { .i = { cc_dep1, cc_dep2 } }; \
1220 __asm__ volatile ( \
1221 opcode ",%[value],0(%[class])\n\t" \
1222 "ipm %[psw]\n\t" : [psw] "=d"(psw) \
1223 : [value] "f"(val.f), \
1224 [class] "a"(cc_ndep) \
1226 psw >> 28; /* cc */ \
1229 #define S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,rounding_mode) \
1231 union s390x_F64 op = { .i = cc_dep1 }; \
1233 __asm__ volatile ( \
1234 opcode ",%[tmp],%[op]," #rounding_mode ",0\n\t" \
1235 "ipm %[psw]\n\t" : [psw] "=d"(psw), [tmp] "=f"(tmp) \
1238 psw >> 28; /* cc */ \
1241 #define S390_CC_FOR_DFP_CONVERT(opcode,cc_dep1,cc_dep2) \
1244 switch (decode_dfp_rounding_mode(cc_dep2)) { \
1245 case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1: \
1246 case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12: \
1247 cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,1); \
1249 case S390_DFP_ROUND_PREPARE_SHORT_3: \
1250 case S390_DFP_ROUND_PREPARE_SHORT_15: \
1251 cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,3); \
1253 case S390_DFP_ROUND_NEAREST_EVEN_4: \
1254 case S390_DFP_ROUND_NEAREST_EVEN_8: \
1255 cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,4); \
1257 case S390_DFP_ROUND_ZERO_5: \
1258 case S390_DFP_ROUND_ZERO_9: \
1259 cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,5); \
1261 case S390_DFP_ROUND_POSINF_6: \
1262 case S390_DFP_ROUND_POSINF_10: \
1263 cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,6); \
1265 case S390_DFP_ROUND_NEGINF_7: \
1266 case S390_DFP_ROUND_NEGINF_11: \
1267 cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,7); \
1269 case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0: \
1270 cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,13); \
1272 case S390_DFP_ROUND_AWAY_0: \
1273 cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,14); \
1276 vpanic("unexpected dfp rounding mode"); \
1281 #define S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,rounding_mode) \
1283 union s390x_F64 op = { .i = cc_dep1 }; \
1285 __asm__ volatile ( \
1286 opcode ",%[tmp],%[op]," #rounding_mode ",0\n\t" \
1287 "ipm %[psw]\n\t" : [psw] "=d"(psw), [tmp] "=f"(tmp) \
1290 psw >> 28; /* cc */ \
1293 #define S390_CC_FOR_DFP_UCONVERT(opcode,cc_dep1,cc_dep2) \
1296 switch (decode_dfp_rounding_mode(cc_dep2)) { \
1297 case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1: \
1298 case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12: \
1299 cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,1); \
1301 case S390_DFP_ROUND_PREPARE_SHORT_3: \
1302 case S390_DFP_ROUND_PREPARE_SHORT_15: \
1303 cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,3); \
1305 case S390_DFP_ROUND_NEAREST_EVEN_4: \
1306 case S390_DFP_ROUND_NEAREST_EVEN_8: \
1307 cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,4); \
1309 case S390_DFP_ROUND_ZERO_5: \
1310 case S390_DFP_ROUND_ZERO_9: \
1311 cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,5); \
1313 case S390_DFP_ROUND_POSINF_6: \
1314 case S390_DFP_ROUND_POSINF_10: \
1315 cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,6); \
1317 case S390_DFP_ROUND_NEGINF_7: \
1318 case S390_DFP_ROUND_NEGINF_11: \
1319 cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,7); \
1321 case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0: \
1322 cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,13); \
1324 case S390_DFP_ROUND_AWAY_0: \
1325 cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,14); \
1328 vpanic("unexpected dfp rounding mode"); \
1333 #define S390_CC_FOR_DFP128_CONVERT_AUX(opcode,hi,lo,rounding_mode) \
1335 union s390x_F128 op = { .i = { hi, lo } }; \
1337 __asm__ volatile ( \
1338 opcode ",%[tmp],%[op]," #rounding_mode ",0\n\t" \
1339 "ipm %[psw]\n\t" : [psw] "=d"(psw), [tmp] "=f"(tmp) \
1342 psw >> 28; /* cc */ \
1345 #define S390_CC_FOR_DFP128_CONVERT(opcode,cc_dep1,cc_dep2,cc_ndep) \
1348 /* Recover the original DEP2 value. See comment near \
1349 s390_cc_thunk_put3 for rationale. */ \
1350 cc_dep2 = cc_dep2 ^ cc_ndep; \
1351 switch (decode_dfp_rounding_mode(cc_ndep)) { \
1352 case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1: \
1353 case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12: \
1354 cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,1); \
1356 case S390_DFP_ROUND_PREPARE_SHORT_3: \
1357 case S390_DFP_ROUND_PREPARE_SHORT_15: \
1358 cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,3); \
1360 case S390_DFP_ROUND_NEAREST_EVEN_4: \
1361 case S390_DFP_ROUND_NEAREST_EVEN_8: \
1362 cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,4); \
1364 case S390_DFP_ROUND_ZERO_5: \
1365 case S390_DFP_ROUND_ZERO_9: \
1366 cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,5); \
1368 case S390_DFP_ROUND_POSINF_6: \
1369 case S390_DFP_ROUND_POSINF_10: \
1370 cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,6); \
1372 case S390_DFP_ROUND_NEGINF_7: \
1373 case S390_DFP_ROUND_NEGINF_11: \
1374 cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,7); \
1376 case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0: \
1377 cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,13); \
1379 case S390_DFP_ROUND_AWAY_0: \
1380 cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,14); \
1383 vpanic("unexpected dfp rounding mode"); \
1388 #define S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,hi,lo,rounding_mode) \
1390 union s390x_F128 op = { .i = { hi, lo } }; \
1392 __asm__ volatile ( \
1393 opcode ",%[tmp],%[op]," #rounding_mode ",0\n\t" \
1394 "ipm %[psw]\n\t" : [psw] "=d"(psw), [tmp] "=f"(tmp) \
1397 psw >> 28; /* cc */ \
1400 #define S390_CC_FOR_DFP128_UCONVERT(opcode,cc_dep1,cc_dep2,cc_ndep) \
1403 /* Recover the original DEP2 value. See comment near \
1404 s390_cc_thunk_put3 for rationale. */ \
1405 cc_dep2 = cc_dep2 ^ cc_ndep; \
1406 switch (decode_dfp_rounding_mode(cc_ndep)) { \
1407 case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1: \
1408 case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12: \
1409 cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,1); \
1411 case S390_DFP_ROUND_PREPARE_SHORT_3: \
1412 case S390_DFP_ROUND_PREPARE_SHORT_15: \
1413 cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,3); \
1415 case S390_DFP_ROUND_NEAREST_EVEN_4: \
1416 case S390_DFP_ROUND_NEAREST_EVEN_8: \
1417 cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,4); \
1419 case S390_DFP_ROUND_ZERO_5: \
1420 case S390_DFP_ROUND_ZERO_9: \
1421 cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,5); \
1423 case S390_DFP_ROUND_POSINF_6: \
1424 case S390_DFP_ROUND_POSINF_10: \
1425 cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,6); \
1427 case S390_DFP_ROUND_NEGINF_7: \
1428 case S390_DFP_ROUND_NEGINF_11: \
1429 cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,7); \
1431 case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0: \
1432 cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,13); \
1434 case S390_DFP_ROUND_AWAY_0: \
1435 cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,14); \
1438 vpanic("unexpected dfp rounding mode"); \
1442 #endif /* VGA_s390x */
1445 /* Return the value of the condition code from the supplied thunk parameters.
1446 This is not the value of the PSW. It is the value of the 2 CC bits within
1447 the PSW. The returned value is thusly in the interval [0:3]. */
1449 s390_calculate_cc(ULong cc_op
, ULong cc_dep1
, ULong cc_dep2
, ULong cc_ndep
)
1451 #if defined(VGA_s390x)
1456 case S390_CC_OP_BITWISE
:
1457 return S390_CC_FOR_BINARY("ogr", cc_dep1
, (ULong
)0);
1459 case S390_CC_OP_SIGNED_COMPARE
:
1460 return S390_CC_FOR_BINARY("cgr", cc_dep1
, cc_dep2
);
1462 case S390_CC_OP_UNSIGNED_COMPARE
:
1463 return S390_CC_FOR_BINARY("clgr", cc_dep1
, cc_dep2
);
1465 case S390_CC_OP_SIGNED_ADD_64
:
1466 return S390_CC_FOR_BINARY("agr", cc_dep1
, cc_dep2
);
1468 case S390_CC_OP_SIGNED_ADD_32
:
1469 return S390_CC_FOR_BINARY("ar", cc_dep1
, cc_dep2
);
1471 case S390_CC_OP_SIGNED_SUB_64
:
1472 return S390_CC_FOR_BINARY("sgr", cc_dep1
, cc_dep2
);
1474 case S390_CC_OP_SIGNED_SUB_32
:
1475 return S390_CC_FOR_BINARY("sr", cc_dep1
, cc_dep2
);
1477 case S390_CC_OP_UNSIGNED_ADD_64
:
1478 return S390_CC_FOR_BINARY("algr", cc_dep1
, cc_dep2
);
1480 case S390_CC_OP_UNSIGNED_ADD_32
:
1481 return S390_CC_FOR_BINARY("alr", cc_dep1
, cc_dep2
);
1483 case S390_CC_OP_UNSIGNED_ADDC_64
:
1484 return S390_CC_FOR_TERNARY_ADDC("alcgr", cc_dep1
, cc_dep2
, cc_ndep
);
1486 case S390_CC_OP_UNSIGNED_ADDC_32
:
1487 return S390_CC_FOR_TERNARY_ADDC("alcr", cc_dep1
, cc_dep2
, cc_ndep
);
1489 case S390_CC_OP_UNSIGNED_SUB_64
:
1490 return S390_CC_FOR_BINARY("slgr", cc_dep1
, cc_dep2
);
1492 case S390_CC_OP_UNSIGNED_SUB_32
:
1493 return S390_CC_FOR_BINARY("slr", cc_dep1
, cc_dep2
);
1495 case S390_CC_OP_UNSIGNED_SUBB_64
:
1496 return S390_CC_FOR_TERNARY_SUBB("slbgr", cc_dep1
, cc_dep2
, cc_ndep
);
1498 case S390_CC_OP_UNSIGNED_SUBB_32
:
1499 return S390_CC_FOR_TERNARY_SUBB("slbr", cc_dep1
, cc_dep2
, cc_ndep
);
1501 case S390_CC_OP_LOAD_AND_TEST
:
1502 /* Like signed comparison with 0 */
1503 return S390_CC_FOR_BINARY("cgr", cc_dep1
, (Long
)0);
1505 case S390_CC_OP_LOAD_POSITIVE_32
:
1507 "lpr %[result],%[op]\n\t"
1508 "ipm %[psw]\n\t" : [psw
] "=d"(psw
), [result
] "=d"(cc_dep1
)
1511 return psw
>> 28; /* cc */
1513 case S390_CC_OP_LOAD_POSITIVE_64
:
1515 "lpgr %[result],%[op]\n\t"
1516 "ipm %[psw]\n\t" : [psw
] "=d"(psw
), [result
] "=d"(cc_dep1
)
1519 return psw
>> 28; /* cc */
1521 case S390_CC_OP_TEST_UNDER_MASK_8
: {
1522 UChar value
= cc_dep1
;
1523 UChar mask
= cc_dep2
;
1527 "bras %[pc],1f\n\t" /* pc = address of next insn */
1528 "tm %[value],0\n\t" /* this is skipped, then EXecuted */
1529 "1: ex %[mask],0(%[pc])\n\t" /* EXecute TM after modifying mask */
1530 "ipm %[psw]\n\t" : [psw
] "=d"(psw
), [pc
] "=&a"(pc
)
1531 : [value
] "Q"(value
), [mask
] "a"(mask
)
1533 return psw
>> 28; /* cc */
1536 case S390_CC_OP_TEST_UNDER_MASK_16
: {
1537 /* Create a TMLL insn with the mask as given by cc_dep2 */
1538 UInt insn
= (0xA701u
<< 16) | cc_dep2
;
1539 UInt value
= cc_dep1
;
1545 "ipm %[psw]\n\t" : [psw
] "=d"(psw
)
1546 : [value
] "d"(value
), [insn
] "R"(insn
)
1547 : "r1", "r2", "cc");
1548 return psw
>> 28; /* cc */
1551 case S390_CC_OP_SHIFT_LEFT_32
:
1553 "sla %[op],0(%[amount])\n\t"
1554 "ipm %[psw]\n\t" : [psw
] "=d"(psw
), [op
] "+d"(cc_dep1
)
1555 : [amount
] "a"(cc_dep2
)
1557 return psw
>> 28; /* cc */
1559 case S390_CC_OP_SHIFT_LEFT_64
: {
1560 Int high
= (Int
)(cc_dep1
>> 32);
1561 Int low
= (Int
)(cc_dep1
& 0xFFFFFFFF);
1566 "slda 2,0(%[amount])\n\t"
1567 "ipm %[psw]\n\t" : [psw
] "=d"(psw
), [high
] "+d"(high
),
1569 : [amount
] "a"(cc_dep2
)
1570 : "cc", "r2", "r3");
1571 return psw
>> 28; /* cc */
1574 case S390_CC_OP_INSERT_CHAR_MASK_32
: {
1579 inserted
|= cc_dep1
& 0xff;
1583 inserted
|= cc_dep1
& 0xff00;
1587 inserted
|= cc_dep1
& 0xff0000;
1591 inserted
|= cc_dep1
& 0xff000000;
1595 if (inserted
& msb
) // MSB is 1
1602 case S390_CC_OP_BFP_RESULT_32
:
1603 return S390_CC_FOR_BFP_RESULT("ltebr", cc_dep1
);
1605 case S390_CC_OP_BFP_RESULT_64
:
1606 return S390_CC_FOR_BFP_RESULT("ltdbr", cc_dep1
);
1608 case S390_CC_OP_BFP_RESULT_128
:
1609 return S390_CC_FOR_BFP128_RESULT(cc_dep1
, cc_dep2
);
1611 case S390_CC_OP_BFP_32_TO_INT_32
:
1612 return S390_CC_FOR_BFP_CONVERT("cfebr", cc_dep1
, cc_dep2
);
1614 case S390_CC_OP_BFP_64_TO_INT_32
:
1615 return S390_CC_FOR_BFP_CONVERT("cfdbr", cc_dep1
, cc_dep2
);
1617 case S390_CC_OP_BFP_128_TO_INT_32
:
1618 return S390_CC_FOR_BFP128_CONVERT("cfxbr", cc_dep1
, cc_dep2
, cc_ndep
);
1620 case S390_CC_OP_BFP_32_TO_INT_64
:
1621 return S390_CC_FOR_BFP_CONVERT("cgebr", cc_dep1
, cc_dep2
);
1623 case S390_CC_OP_BFP_64_TO_INT_64
:
1624 return S390_CC_FOR_BFP_CONVERT("cgdbr", cc_dep1
, cc_dep2
);
1626 case S390_CC_OP_BFP_128_TO_INT_64
:
1627 return S390_CC_FOR_BFP128_CONVERT("cgxbr", cc_dep1
, cc_dep2
, cc_ndep
);
1629 case S390_CC_OP_BFP_TDC_32
:
1630 return S390_CC_FOR_BFP_TDC("tceb", cc_dep1
, cc_dep2
);
1632 case S390_CC_OP_BFP_TDC_64
:
1633 return S390_CC_FOR_BFP_TDC("tcdb", cc_dep1
, cc_dep2
);
1635 case S390_CC_OP_BFP_TDC_128
:
1636 return S390_CC_FOR_BFP128_TDC(cc_dep1
, cc_dep2
, cc_ndep
);
1638 case S390_CC_OP_SET
:
1641 case S390_CC_OP_BFP_32_TO_UINT_32
:
1642 return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb39c0000", cc_dep1
, cc_dep2
);
1644 case S390_CC_OP_BFP_64_TO_UINT_32
:
1645 return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb39d0000", cc_dep1
, cc_dep2
);
1647 case S390_CC_OP_BFP_128_TO_UINT_32
:
1648 return S390_CC_FOR_BFP128_UCONVERT(".insn rrf,0xb39e0000", cc_dep1
,
1651 case S390_CC_OP_BFP_32_TO_UINT_64
:
1652 return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb3ac0000", cc_dep1
, cc_dep2
);
1654 case S390_CC_OP_BFP_64_TO_UINT_64
:
1655 return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb3ad0000", cc_dep1
, cc_dep2
);
1657 case S390_CC_OP_BFP_128_TO_UINT_64
:
1658 return S390_CC_FOR_BFP128_UCONVERT(".insn rrf,0xb3ae0000", cc_dep1
,
1661 case S390_CC_OP_DFP_RESULT_64
:
1662 return S390_CC_FOR_DFP_RESULT(cc_dep1
);
1664 case S390_CC_OP_DFP_RESULT_128
:
1665 return S390_CC_FOR_DFP128_RESULT(cc_dep1
, cc_dep2
);
1667 case S390_CC_OP_DFP_TDC_32
: /* TDCET */
1668 return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000050", cc_dep1
, cc_dep2
);
1670 case S390_CC_OP_DFP_TDC_64
: /* TDCDT */
1671 return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000054", cc_dep1
, cc_dep2
);
1673 case S390_CC_OP_DFP_TDC_128
: /* TDCXT */
1674 return S390_CC_FOR_DFP128_TD(".insn rxe, 0xed0000000058", cc_dep1
,
1677 case S390_CC_OP_DFP_TDG_32
: /* TDGET */
1678 return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000051", cc_dep1
, cc_dep2
);
1680 case S390_CC_OP_DFP_TDG_64
: /* TDGDT */
1681 return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000055", cc_dep1
, cc_dep2
);
1683 case S390_CC_OP_DFP_TDG_128
: /* TDGXT */
1684 return S390_CC_FOR_DFP128_TD(".insn rxe, 0xed0000000059", cc_dep1
,
1687 case S390_CC_OP_DFP_64_TO_INT_32
: /* CFDTR */
1688 return S390_CC_FOR_DFP_CONVERT(".insn rrf,0xb9410000", cc_dep1
, cc_dep2
);
1690 case S390_CC_OP_DFP_128_TO_INT_32
: /* CFXTR */
1691 return S390_CC_FOR_DFP128_CONVERT(".insn rrf,0xb9490000", cc_dep1
,
1694 case S390_CC_OP_DFP_64_TO_INT_64
: /* CGDTR */
1695 return S390_CC_FOR_DFP_CONVERT(".insn rrf,0xb3e10000", cc_dep1
, cc_dep2
);
1697 case S390_CC_OP_DFP_128_TO_INT_64
: /* CGXTR */
1698 return S390_CC_FOR_DFP128_CONVERT(".insn rrf,0xb3e90000", cc_dep1
,
1701 case S390_CC_OP_DFP_64_TO_UINT_32
: /* CLFDTR */
1702 return S390_CC_FOR_DFP_UCONVERT(".insn rrf,0xb9430000", cc_dep1
, cc_dep2
);
1704 case S390_CC_OP_DFP_128_TO_UINT_32
: /* CLFXTR */
1705 return S390_CC_FOR_DFP128_UCONVERT(".insn rrf,0xb94b0000", cc_dep1
,
1708 case S390_CC_OP_DFP_64_TO_UINT_64
: /* CLGDTR */
1709 return S390_CC_FOR_DFP_UCONVERT(".insn rrf,0xb9420000", cc_dep1
, cc_dep2
);
1711 case S390_CC_OP_DFP_128_TO_UINT_64
: /* CLGXTR */
1712 return S390_CC_FOR_DFP128_UCONVERT(".insn rrf,0xb94a0000", cc_dep1
,
1715 case S390_CC_OP_PFPO_32
: {
1717 "ldgr 4, %[cc_dep1]\n\t" /* Load FR from GR */
1718 "lr 0, %[cc_dep2]\n\t" /* 32 bit GR move */
1719 ".insn e,0x010a\n\t" /* PFPO */
1720 "ipm %[psw]\n\t" : [psw
] "=d"(psw
)
1721 : [cc_dep1
] "d"(cc_dep1
),
1722 [cc_dep2
] "d"(cc_dep2
)
1723 : "r0", "r1", "f4");
1724 return psw
>> 28; /* cc */
1727 case S390_CC_OP_PFPO_64
: {
1729 "ldgr 4, %[cc_dep1]\n\t"
1730 "lr 0, %[cc_dep2]\n\t" /* 32 bit register move */
1731 ".insn e,0x010a\n\t" /* PFPO */
1732 "ipm %[psw]\n\t" : [psw
] "=d"(psw
)
1733 : [cc_dep1
] "d"(cc_dep1
),
1734 [cc_dep2
] "d"(cc_dep2
)
1735 : "r0", "r1", "f4");
1736 return psw
>> 28; /* cc */
1739 case S390_CC_OP_PFPO_128
: {
1741 "ldgr 4,%[cc_dep1]\n\t"
1742 "ldgr 6,%[cc_dep2]\n\t"
1743 "lr 0,%[cc_ndep]\n\t" /* 32 bit register move */
1744 ".insn e,0x010a\n\t" /* PFPO */
1745 "ipm %[psw]\n\t" : [psw
] "=d"(psw
)
1746 : [cc_dep1
] "d"(cc_dep1
),
1747 [cc_dep2
] "d"(cc_dep2
),
1748 [cc_ndep
] "d"(cc_ndep
)
1749 : "r0", "r1", "f0", "f2", "f4", "f6");
1750 return psw
>> 28; /* cc */
1753 case S390_CC_OP_MUL_32
:
1754 return S390_CC_FOR_TERNARY(".insn rrf,0xb9fd0000", cc_dep1
, cc_dep2
);
1756 case S390_CC_OP_MUL_64
:
1757 return S390_CC_FOR_TERNARY(".insn rrf,0xb9ed0000", cc_dep1
, cc_dep2
);
1763 vpanic("s390_calculate_cc");
1767 /* Note that this does *not* return a Boolean value. The result needs to be
1768 explicitly tested against zero. */
1770 s390_calculate_cond(ULong mask
, ULong op
, ULong dep1
, ULong dep2
, ULong ndep
)
1772 UInt cc
= s390_calculate_cc(op
, dep1
, dep2
, ndep
);
1774 return ((mask
<< cc
) & 0x8);
1777 /*------------------------------------------------------------*/
1778 /*--- spechelper for performance ---*/
1779 /*------------------------------------------------------------*/
1782 /* Convenience macros */
1783 #define unop(op,a1) IRExpr_Unop((op),(a1))
1784 #define binop(op,a1,a2) IRExpr_Binop((op),(a1),(a2))
1785 #define mkU64(v) IRExpr_Const(IRConst_U64(v))
1786 #define mkU32(v) IRExpr_Const(IRConst_U32(v))
1787 #define mkU8(v) IRExpr_Const(IRConst_U8(v))
1791 isC64(const IRExpr
*expr
)
1793 return expr
->tag
== Iex_Const
&& expr
->Iex
.Const
.con
->tag
== Ico_U64
;
1797 isC64_exactly(const IRExpr
*expr
, ULong n
)
1799 return expr
->tag
== Iex_Const
&& expr
->Iex
.Const
.con
->tag
== Ico_U64
1800 && expr
->Iex
.Const
.con
->Ico
.U64
== n
;
1804 /* The returned expression is NULL if no specialization was found. In that
1805 case the helper function will be called. Otherwise, the expression has
1806 type Ity_I32 and a Boolean value. */
1808 guest_s390x_spechelper(const HChar
*function_name
, IRExpr
**args
,
1809 IRStmt
**precedingStmts
, Int n_precedingStmts
)
1813 for (i
= 0; args
[i
]; i
++)
1817 vex_printf("spec request:\n");
1818 vex_printf(" %s ", function_name
);
1819 for (i
= 0; i
< arity
; i
++) {
1826 /* --------- Specialising "s390_calculate_cond" --------- */
1828 if (vex_streq(function_name
, "s390_calculate_cond")) {
1829 IRExpr
*cond_expr
, *cc_op_expr
, *cc_dep1
, *cc_dep2
;
1832 vassert(arity
== 5);
1834 cond_expr
= args
[0];
1835 cc_op_expr
= args
[1];
1837 /* The necessary requirement for all optimizations here is that the
1838 condition and the cc_op are constant. So check that upfront. */
1839 if (! isC64(cond_expr
)) return NULL
;
1840 if (! isC64(cc_op_expr
)) return NULL
;
1842 cond
= cond_expr
->Iex
.Const
.con
->Ico
.U64
;
1843 cc_op
= cc_op_expr
->Iex
.Const
.con
->Ico
.U64
;
1845 vassert(cond
<= 15);
1848 +------+---+---+---+---+
1849 | cc | 0 | 1 | 2 | 3 |
1850 | cond | 8 | 4 | 2 | 1 |
1851 +------+---+---+---+---+
1856 /* S390_CC_OP_SIGNED_COMPARE */
1857 if (cc_op
== S390_CC_OP_SIGNED_COMPARE
) {
1859 cc == 0 --> cc_dep1 == cc_dep2 (cond == 8)
1860 cc == 1 --> cc_dep1 < cc_dep2 (cond == 4)
1861 cc == 2 --> cc_dep1 > cc_dep2 (cond == 2)
1863 Because cc == 3 cannot occur the rightmost bit of cond is
1866 if (cond
== 8 || cond
== 8 + 1) {
1867 return unop(Iop_1Uto32
, binop(Iop_CmpEQ64
, cc_dep1
, cc_dep2
));
1869 if (cond
== 4 + 2 || cond
== 4 + 2 + 1) {
1870 return unop(Iop_1Uto32
, binop(Iop_CmpNE64
, cc_dep1
, cc_dep2
));
1872 if (cond
== 4 || cond
== 4 + 1) {
1873 if (isC64_exactly(cc_dep2
, 0)) {
1875 --> m.s.bit of dep1 == 1 */
1876 return unop(Iop_64to32
,
1878 binop(Iop_Shr64
, cc_dep1
, mkU8(63)),
1881 return unop(Iop_1Uto32
, binop(Iop_CmpLT64S
, cc_dep1
, cc_dep2
));
1883 if (cond
== 8 + 4 || cond
== 8 + 4 + 1) {
1884 return unop(Iop_1Uto32
, binop(Iop_CmpLE64S
, cc_dep1
, cc_dep2
));
1886 /* cc_dep1 > cc_dep2 ----> cc_dep2 < cc_dep1 */
1887 if (cond
== 2 || cond
== 2 + 1) {
1888 /* If we ever need the counterpart of the bug387712 fix just
1889 below, then here is the place. We'll need to give an
1890 alternative expression for the case "cc_dep2 <s 0". From a
1891 bit of simple testing, I've yet to see any such cases,
1893 return unop(Iop_1Uto32
, binop(Iop_CmpLT64S
, cc_dep2
, cc_dep1
));
1895 if (cond
== 8 + 2 || cond
== 8 + 2 + 1) {
1896 if (isC64_exactly(cc_dep2
, 0)) {
1899 --> m.s.bit of dep1 == 0 */
1900 /* See bug 387712. This is an old trick from gcc to extract
1901 the most significant bit of a word. */
1902 return unop(Iop_64to32
,
1904 binop(Iop_Shr64
, cc_dep1
, mkU8(63)),
1907 return unop(Iop_1Uto32
, binop(Iop_CmpLE64S
, cc_dep2
, cc_dep1
));
1909 if (cond
== 8 + 4 + 2 || cond
== 8 + 4 + 2 + 1) {
1912 /* Remaining case */
1916 /* S390_CC_OP_UNSIGNED_COMPARE */
1917 if (cc_op
== S390_CC_OP_UNSIGNED_COMPARE
) {
1919 cc == 0 --> cc_dep1 == cc_dep2 (cond == 8)
1920 cc == 1 --> cc_dep1 < cc_dep2 (cond == 4)
1921 cc == 2 --> cc_dep1 > cc_dep2 (cond == 2)
1923 Because cc == 3 cannot occur the rightmost bit of cond is
1926 if (isC64(cc_dep2
)) {
1927 /* Avoid memcheck false positives for comparisons like `<= 0x1f',
1928 `> 0x1f', `< 0x20', or `>= 0x20', where the lower bits don't
1929 matter. Some compiler optimizations yield such comparisons when
1930 testing if any (or none) of the upper bits are set. */
1932 ULong mask
= cc_dep2
->Iex
.Const
.con
->Ico
.U64
;
1933 ULong c
= cond
& (8 + 4 + 2);
1935 if ((mask
& (mask
- 1)) == 0) {
1936 /* Transform `< 0x20' to `<= 0x1f' and
1937 `>= 0x20' to `> 0x1f' */
1941 if (mask
!= 0 && (mask
+ 1) != 0 && (mask
& (mask
+ 1)) == 0 &&
1942 (c
== 8 + 4 || c
== 2)) {
1943 IROp cmp
= c
== 8 + 4 ? Iop_CmpEQ64
: Iop_CmpNE64
;
1944 return unop(Iop_1Uto32
,
1945 binop(cmp
, binop(Iop_And64
, cc_dep1
, mkU64(~mask
)),
1949 if (cond
== 8 || cond
== 8 + 1) {
1950 return unop(Iop_1Uto32
, binop(Iop_CmpEQ64
, cc_dep1
, cc_dep2
));
1952 if (cond
== 4 + 2 || cond
== 4 + 2 + 1) {
1953 return unop(Iop_1Uto32
, binop(Iop_CmpNE64
, cc_dep1
, cc_dep2
));
1955 if (cond
== 4 || cond
== 4 + 1) {
1956 return unop(Iop_1Uto32
, binop(Iop_CmpLT64U
, cc_dep1
, cc_dep2
));
1958 if (cond
== 8 + 4 || cond
== 8 + 4 + 1) {
1959 return unop(Iop_1Uto32
, binop(Iop_CmpLE64U
, cc_dep1
, cc_dep2
));
1961 /* cc_dep1 > cc_dep2 ----> cc_dep2 < cc_dep1 */
1962 if (cond
== 2 || cond
== 2 + 1) {
1963 return unop(Iop_1Uto32
, binop(Iop_CmpLT64U
, cc_dep2
, cc_dep1
));
1965 if (cond
== 8 + 2 || cond
== 8 + 2 + 1) {
1966 return unop(Iop_1Uto32
, binop(Iop_CmpLE64U
, cc_dep2
, cc_dep1
));
1968 if (cond
== 8 + 4 + 2 || cond
== 8 + 4 + 2 + 1) {
1971 /* Remaining case */
1975 /* S390_CC_OP_LOAD_AND_TEST */
1976 if (cc_op
== S390_CC_OP_LOAD_AND_TEST
) {
1978 cc == 0 --> cc_dep1 == 0 (cond == 8)
1979 cc == 1 --> cc_dep1 < 0 (cond == 4)
1980 cc == 2 --> cc_dep1 > 0 (cond == 2)
1982 Because cc == 3 cannot occur the rightmost bit of cond is
1985 if (cond
== 8 || cond
== 8 + 1) {
1986 return unop(Iop_1Uto32
, binop(Iop_CmpEQ64
, cc_dep1
, mkU64(0)));
1988 if (cond
== 4 + 2 || cond
== 4 + 2 + 1) {
1989 return unop(Iop_1Uto32
, binop(Iop_CmpNE64
, cc_dep1
, mkU64(0)));
1991 if (cond
== 4 || cond
== 4 + 1) {
1992 /* Special case cc_dep < 0. Only check the MSB to avoid bogus
1993 memcheck complaints due to gcc magic. Fixes 343802
1995 return unop(Iop_64to32
, binop(Iop_Shr64
, cc_dep1
, mkU8(63)));
1997 if (cond
== 8 + 4 || cond
== 8 + 4 + 1) {
1998 return unop(Iop_1Uto32
, binop(Iop_CmpLE64S
, cc_dep1
, mkU64(0)));
2000 /* cc_dep1 > 0 ----> 0 < cc_dep1 */
2001 if (cond
== 2 || cond
== 2 + 1) {
2002 return unop(Iop_1Uto32
, binop(Iop_CmpLT64S
, mkU64(0), cc_dep1
));
2004 if (cond
== 8 + 2 || cond
== 8 + 2 + 1) {
2005 /* Special case cc_dep >= 0. Only check the MSB to avoid bogus
2006 memcheck complaints due to gcc magic. Fixes 308427
2008 return unop(Iop_64to32
, binop(Iop_Xor64
,
2009 binop(Iop_Shr64
, cc_dep1
, mkU8(63)),
2012 if (cond
== 8 + 4 + 2 || cond
== 8 + 4 + 2 + 1) {
2015 /* Remaining case */
2019 /* S390_CC_OP_BITWISE */
2020 if (cc_op
== S390_CC_OP_BITWISE
) {
2022 cc_dep1 is the result of the boolean operation.
2024 cc == 0 --> cc_dep1 == 0 (cond == 8)
2025 cc == 1 --> cc_dep1 != 0 (cond == 4)
2027 Because cc == 2 and cc == 3 cannot occur the two rightmost bits of
2028 cond are don't cares. Therefore:
2030 cond == 00xx -> always false
2031 cond == 01xx -> not equal
2032 cond == 10xx -> equal
2033 cond == 11xx -> always true
2035 if ((cond
& (8 + 4)) == 8 + 4) {
2039 return unop(Iop_1Uto32
, binop(Iop_CmpEQ64
, cc_dep1
, mkU64(0)));
2042 return unop(Iop_1Uto32
, binop(Iop_CmpNE64
, cc_dep1
, mkU64(0)));
2044 /* Remaining case */
2048 /* S390_CC_OP_INSERT_CHAR_MASK_32
2049 Since the mask comes from an immediate field in the opcode, we
2050 expect the mask to be a constant here. That simplifies matters. */
2051 if (cc_op
== S390_CC_OP_INSERT_CHAR_MASK_32
) {
2053 UInt imask
= 0, shift
= 0;
2056 if (! isC64(cc_dep2
)) goto missed
;
2058 mask
= cc_dep2
->Iex
.Const
.con
->Ico
.U64
;
2060 /* Extract the 32-bit value from the thunk */
2062 word
= unop(Iop_64to32
, cc_dep1
);
2065 case 0: shift
= 0; imask
= 0x00000000; break;
2066 case 1: shift
= 24; imask
= 0x000000FF; break;
2067 case 2: shift
= 16; imask
= 0x0000FF00; break;
2068 case 3: shift
= 16; imask
= 0x0000FFFF; break;
2069 case 4: shift
= 8; imask
= 0x00FF0000; break;
2070 case 5: shift
= 8; imask
= 0x00FF00FF; break;
2071 case 6: shift
= 8; imask
= 0x00FFFF00; break;
2072 case 7: shift
= 8; imask
= 0x00FFFFFF; break;
2073 case 8: shift
= 0; imask
= 0xFF000000; break;
2074 case 9: shift
= 0; imask
= 0xFF0000FF; break;
2075 case 10: shift
= 0; imask
= 0xFF00FF00; break;
2076 case 11: shift
= 0; imask
= 0xFF00FFFF; break;
2077 case 12: shift
= 0; imask
= 0xFFFF0000; break;
2078 case 13: shift
= 0; imask
= 0xFFFF00FF; break;
2079 case 14: shift
= 0; imask
= 0xFFFFFF00; break;
2080 case 15: shift
= 0; imask
= 0xFFFFFFFF; break;
2083 /* Select the bits that were inserted */
2084 word
= binop(Iop_And32
, word
, mkU32(imask
));
2086 /* cc == 0 --> all inserted bits zero or mask == 0 (cond == 8)
2087 cc == 1 --> leftmost inserted bit is one (cond == 4)
2088 cc == 2 --> leftmost inserted bit is zero and not (cond == 2)
2089 all inserted bits are zero
2091 Because cc == 0,1,2 the rightmost bit of the mask is a don't care */
2092 if (cond
== 8 || cond
== 8 + 1) {
2093 return unop(Iop_1Uto32
, binop(Iop_CmpEQ32
, word
, mkU32(0)));
2095 if (cond
== 4 + 2 || cond
== 4 + 2 + 1) {
2096 return unop(Iop_1Uto32
, binop(Iop_CmpNE32
, word
, mkU32(0)));
2101 word
= binop(Iop_Sar32
, binop(Iop_Shl32
, word
, mkU8(shift
)),
2105 if (cond
== 4 || cond
== 4 + 1) { /* word < 0 */
2106 return unop(Iop_1Uto32
, binop(Iop_CmpLT32S
, word
, mkU32(0)));
2108 if (cond
== 2 || cond
== 2 + 1) { /* word > 0 */
2109 return unop(Iop_1Uto32
, binop(Iop_CmpLT32S
, mkU32(0), word
));
2111 if (cond
== 8 + 4 || cond
== 8 + 4 + 1) {
2112 return unop(Iop_1Uto32
, binop(Iop_CmpLE32S
, word
, mkU32(0)));
2114 if (cond
== 8 + 2 || cond
== 8 + 2 + 1) {
2115 return unop(Iop_1Uto32
, binop(Iop_CmpLE32S
, mkU32(0), word
));
2117 if (cond
== 8 + 4 + 2 || cond
== 8 + 4 + 2 + 1) {
2120 /* Remaining case */
2124 /* S390_CC_OP_TEST_UNDER_MASK_8
2125 Since the mask comes from an immediate field in the opcode, we
2126 expect the mask to be a constant here. That simplifies matters. */
2127 if (cc_op
== S390_CC_OP_TEST_UNDER_MASK_8
) {
2130 if (! isC64(cc_dep2
)) goto missed
;
2132 mask16
= cc_dep2
->Iex
.Const
.con
->Ico
.U64
;
2134 /* Get rid of the mask16 == 0 case first. Some of the simplifications
2135 below (e.g. for OVFL) only hold if mask16 == 0. */
2136 if (mask16
== 0) { /* cc == 0 */
2137 if (cond
& 0x8) return mkU32(1);
2141 /* cc == 2 is a don't care */
2142 if (cond
== 8 || cond
== 8 + 2) {
2143 return unop(Iop_1Uto32
, binop(Iop_CmpEQ64
,
2144 binop(Iop_And64
, cc_dep1
, cc_dep2
),
2147 if (cond
== 7 || cond
== 7 - 2) {
2148 return unop(Iop_1Uto32
, binop(Iop_CmpNE64
,
2149 binop(Iop_And64
, cc_dep1
, cc_dep2
),
2152 if (cond
== 1 || cond
== 1 + 2) {
2153 return unop(Iop_1Uto32
, binop(Iop_CmpEQ64
,
2154 binop(Iop_And64
, cc_dep1
, cc_dep2
),
2157 if (cond
== 14 || cond
== 14 - 2) { /* ! OVFL */
2158 return unop(Iop_1Uto32
, binop(Iop_CmpNE64
,
2159 binop(Iop_And64
, cc_dep1
, cc_dep2
),
2165 /* S390_CC_OP_TEST_UNDER_MASK_16
2166 Since the mask comes from an immediate field in the opcode, we
2167 expect the mask to be a constant here. That simplifies matters. */
2168 if (cc_op
== S390_CC_OP_TEST_UNDER_MASK_16
) {
2172 if (! isC64(cc_dep2
)) goto missed
;
2174 mask16
= cc_dep2
->Iex
.Const
.con
->Ico
.U64
;
2176 /* Get rid of the mask16 == 0 case first. Some of the simplifications
2177 below (e.g. for OVFL) only hold if mask16 == 0. */
2178 if (mask16
== 0) { /* cc == 0 */
2179 if (cond
& 0x8) return mkU32(1);
2183 if (cond
== 15) return mkU32(1);
2186 return unop(Iop_1Uto32
, binop(Iop_CmpEQ64
,
2187 binop(Iop_And64
, cc_dep1
, cc_dep2
),
2191 return unop(Iop_1Uto32
, binop(Iop_CmpNE64
,
2192 binop(Iop_And64
, cc_dep1
, cc_dep2
),
2196 return unop(Iop_1Uto32
, binop(Iop_CmpEQ64
,
2197 binop(Iop_And64
, cc_dep1
, cc_dep2
),
2200 if (cond
== 14) { /* ! OVFL */
2201 return unop(Iop_1Uto32
, binop(Iop_CmpNE64
,
2202 binop(Iop_And64
, cc_dep1
, cc_dep2
),
2206 /* Find MSB in mask */
2208 while (msb
> mask16
)
2211 if (cond
== 2) { /* cc == 2 */
2214 /* (cc_dep & msb) != 0 && (cc_dep & mask16) != mask16 */
2215 c1
= binop(Iop_CmpNE64
,
2216 binop(Iop_And64
, cc_dep1
, mkU64(msb
)), mkU64(0));
2217 c2
= binop(Iop_CmpNE64
,
2218 binop(Iop_And64
, cc_dep1
, cc_dep2
),
2220 return binop(Iop_And32
, unop(Iop_1Uto32
, c1
),
2221 unop(Iop_1Uto32
, c2
));
2224 if (cond
== 4) { /* cc == 1 */
2227 /* (cc_dep & msb) == 0 && (cc_dep & mask16) != 0 */
2228 c1
= binop(Iop_CmpEQ64
,
2229 binop(Iop_And64
, cc_dep1
, mkU64(msb
)), mkU64(0));
2230 c2
= binop(Iop_CmpNE64
,
2231 binop(Iop_And64
, cc_dep1
, cc_dep2
),
2233 return binop(Iop_And32
, unop(Iop_1Uto32
, c1
),
2234 unop(Iop_1Uto32
, c2
));
2237 if (cond
== 11) { /* cc == 0,2,3 */
2240 c1
= binop(Iop_CmpNE64
,
2241 binop(Iop_And64
, cc_dep1
, mkU64(msb
)), mkU64(0));
2242 c2
= binop(Iop_CmpEQ64
,
2243 binop(Iop_And64
, cc_dep1
, cc_dep2
),
2245 return binop(Iop_Or32
, unop(Iop_1Uto32
, c1
),
2246 unop(Iop_1Uto32
, c2
));
2249 if (cond
== 3) { /* cc == 2 || cc == 3 */
2250 return unop(Iop_1Uto32
,
2252 binop(Iop_And64
, cc_dep1
, mkU64(msb
)),
2255 if (cond
== 12) { /* cc == 0 || cc == 1 */
2256 return unop(Iop_1Uto32
,
2258 binop(Iop_And64
, cc_dep1
, mkU64(msb
)),
2261 if (cond
== 13) { /* cc == 0 || cc == 1 || cc == 3 */
2264 c01
= binop(Iop_CmpEQ64
, binop(Iop_And64
, cc_dep1
, mkU64(msb
)),
2266 c3
= binop(Iop_CmpEQ64
, binop(Iop_And64
, cc_dep1
, cc_dep2
),
2268 return binop(Iop_Or32
, unop(Iop_1Uto32
, c01
),
2269 unop(Iop_1Uto32
, c3
));
2271 // fixs390: handle cond = 5,6,9,10 (the missing cases)
2272 // vex_printf("TUM mask = 0x%llx\n", mask16);
2276 /* S390_CC_OP_UNSIGNED_SUB_64/32 */
2277 if (cc_op
== S390_CC_OP_UNSIGNED_SUB_64
||
2278 cc_op
== S390_CC_OP_UNSIGNED_SUB_32
) {
2280 cc_dep1, cc_dep2 are the zero extended left and right operands
2282 cc == 1 --> result != 0, borrow (cond == 4)
2283 cc == 2 --> result == 0, no borrow (cond == 2)
2284 cc == 3 --> result != 0, no borrow (cond == 1)
2286 cc = (cc_dep1 == cc_dep2) ? 2
2287 : (cc_dep1 > cc_dep2) ? 3 : 1;
2289 Because cc == 0 cannot occur the leftmost bit of cond is
2292 if (cond
== 1 || cond
== 1 + 8) { /* cc == 3 op2 < op1 */
2293 return unop(Iop_1Uto32
, binop(Iop_CmpLT64U
, cc_dep2
, cc_dep1
));
2295 if (cond
== 2 || cond
== 2 + 8) { /* cc == 2 */
2296 return unop(Iop_1Uto32
, binop(Iop_CmpEQ64
, cc_dep1
, cc_dep2
));
2298 if (cond
== 4 || cond
== 4 + 8) { /* cc == 1 */
2299 return unop(Iop_1Uto32
, binop(Iop_CmpLT64U
, cc_dep1
, cc_dep2
));
2301 if (cond
== 3 || cond
== 3 + 8) { /* cc == 2 || cc == 3 */
2302 return unop(Iop_1Uto32
, binop(Iop_CmpLE64U
, cc_dep2
, cc_dep1
));
2304 if (cond
== 6 || cond
== 6 + 8) { /* cc == 2 || cc == 1 */
2305 return unop(Iop_1Uto32
, binop(Iop_CmpLE64U
, cc_dep1
, cc_dep2
));
2308 if (cond
== 5 || cond
== 5 + 8) { /* cc == 3 || cc == 1 */
2309 return unop(Iop_1Uto32
, binop(Iop_CmpNE64
, cc_dep1
, cc_dep2
));
2311 if (cond
== 7 || cond
== 7 + 8) {
2314 /* Remaining case */
2318 /* S390_CC_OP_UNSIGNED_ADD_64 */
2319 if (cc_op
== S390_CC_OP_UNSIGNED_ADD_64
) {
2321 cc_dep1, cc_dep2 are the zero extended left and right operands
2323 cc == 0 --> result == 0, no carry (cond == 8)
2324 cc == 1 --> result != 0, no carry (cond == 4)
2325 cc == 2 --> result == 0, carry (cond == 2)
2326 cc == 3 --> result != 0, carry (cond == 1)
2328 if (cond
== 8) { /* cc == 0 */
2329 /* Both inputs are 0 */
2330 return unop(Iop_1Uto32
, binop(Iop_CmpEQ64
,
2331 binop(Iop_Or64
, cc_dep1
, cc_dep2
),
2334 if (cond
== 7) { /* cc == 1,2,3 */
2335 /* Not both inputs are 0 */
2336 return unop(Iop_1Uto32
, binop(Iop_CmpNE64
,
2337 binop(Iop_Or64
, cc_dep1
, cc_dep2
),
2340 if (cond
== 8 + 2) { /* cc == 0,2 -> result is zero */
2341 return unop(Iop_1Uto32
, binop(Iop_CmpEQ64
,
2342 binop(Iop_Add64
, cc_dep1
, cc_dep2
),
2345 if (cond
== 4 + 1) { /* cc == 1,3 -> result is not zero */
2346 return unop(Iop_1Uto32
, binop(Iop_CmpNE64
,
2347 binop(Iop_Add64
, cc_dep1
, cc_dep2
),
2353 /* S390_CC_OP_UNSIGNED_ADD_32 */
2354 if (cc_op
== S390_CC_OP_UNSIGNED_ADD_32
) {
2356 cc_dep1, cc_dep2 are the zero extended left and right operands
2358 cc == 0 --> result == 0, no carry (cond == 8)
2359 cc == 1 --> result != 0, no carry (cond == 4)
2360 cc == 2 --> result == 0, carry (cond == 2)
2361 cc == 3 --> result != 0, carry (cond == 1)
2363 if (cond
== 8) { /* cc == 0 */
2364 /* Both inputs are 0 */
2365 return unop(Iop_1Uto32
, binop(Iop_CmpEQ64
,
2366 binop(Iop_Or64
, cc_dep1
, cc_dep2
),
2369 if (cond
== 7) { /* cc == 1,2,3 */
2370 /* Not both inputs are 0 */
2371 return unop(Iop_1Uto32
, binop(Iop_CmpNE64
,
2372 binop(Iop_Or64
, cc_dep1
, cc_dep2
),
2375 if (cond
== 8 + 2) { /* cc == 0,2 -> result is zero */
2376 return unop(Iop_1Uto32
, binop(Iop_CmpEQ32
,
2378 unop(Iop_64to32
, cc_dep1
),
2379 unop(Iop_64to32
, cc_dep2
)),
2382 if (cond
== 4 + 1) { /* cc == 1,3 -> result is not zero */
2383 return unop(Iop_1Uto32
, binop(Iop_CmpNE32
,
2385 unop(Iop_64to32
, cc_dep1
),
2386 unop(Iop_64to32
, cc_dep2
)),
2392 /* S390_CC_OP_SET */
2393 if (cc_op
== S390_CC_OP_SET
) {
2394 /* cc_dep1 is the condition code
2396 Return 1, if ((cond << cc_dep1) & 0x8) != 0 */
2398 return unop(Iop_1Uto32
,
2401 binop(Iop_Shl64
, cond_expr
,
2402 unop(Iop_64to8
, cc_dep1
)),
2410 /* --------- Specialising "s390_calculate_cc" --------- */
2412 if (vex_streq(function_name
, "s390_calculate_cc")) {
2413 IRExpr
*cc_op_expr
, *cc_dep1
;
2416 vassert(arity
== 4);
2418 cc_op_expr
= args
[0];
2420 /* The necessary requirement for all optimizations here is that
2421 cc_op is constant. So check that upfront. */
2422 if (! isC64(cc_op_expr
)) return NULL
;
2424 cc_op
= cc_op_expr
->Iex
.Const
.con
->Ico
.U64
;
2427 if (cc_op
== S390_CC_OP_BITWISE
) {
2428 return unop(Iop_1Uto32
,
2429 binop(Iop_CmpNE64
, cc_dep1
, mkU64(0)));
2432 if (cc_op
== S390_CC_OP_SET
) {
2433 return unop(Iop_64to32
, cc_dep1
);
2443 /*------------------------------------------------------------*/
2444 /*--- Dirty helper for vector instructions ---*/
2445 /*------------------------------------------------------------*/
2447 #if defined(VGA_s390x)
2449 s390x_dirtyhelper_vec_op(VexGuestS390XState
*guest_state
,
2450 const ULong serialized
)
2453 s390x_vec_op_details_t details
;
2454 const s390x_vec_op_details_t
* d
= (const s390x_vec_op_details_t
*) &details
;
2456 details
.serialized
= serialized
;
2458 vassert(d
->op
> S390_VEC_OP_INVALID
&& d
->op
< S390_VEC_OP_LAST
);
2459 static const UChar opcodes
[][2] = {
2460 {0x00, 0x00}, /* invalid */
2461 [S390_VEC_OP_VPKS
] = {0xe7, 0x97},
2462 [S390_VEC_OP_VPKLS
] = {0xe7, 0x95},
2463 [S390_VEC_OP_VCEQ
] = {0xe7, 0xf8},
2464 [S390_VEC_OP_VTM
] = {0xe7, 0xd8},
2465 [S390_VEC_OP_VGFM
] = {0xe7, 0xb4},
2466 [S390_VEC_OP_VGFMA
] = {0xe7, 0xbc},
2467 [S390_VEC_OP_VMAH
] = {0xe7, 0xab},
2468 [S390_VEC_OP_VMALH
] = {0xe7, 0xa9},
2469 [S390_VEC_OP_VCH
] = {0xe7, 0xfb},
2470 [S390_VEC_OP_VCHL
] = {0xe7, 0xf9},
2471 [S390_VEC_OP_VFTCI
] = {0xe7, 0x4a},
2472 [S390_VEC_OP_VFMIN
] = {0xe7, 0xee},
2473 [S390_VEC_OP_VFMAX
] = {0xe7, 0xef},
2474 [S390_VEC_OP_VBPERM
]= {0xe7, 0x85},
2475 [S390_VEC_OP_VMSL
] = {0xe7, 0xb8},
2476 [S390_VEC_OP_VCNF
] = {0xe6, 0x55},
2477 [S390_VEC_OP_VCLFNH
]= {0xe6, 0x56},
2478 [S390_VEC_OP_VCFN
] = {0xe6, 0x5d},
2479 [S390_VEC_OP_VCLFNL
]= {0xe6, 0x5e},
2480 [S390_VEC_OP_VCRNF
] = {0xe6, 0x75},
2485 unsigned int op1
: 8;
2486 unsigned int v1
: 4;
2487 unsigned int v2
: 4;
2488 unsigned int v3
: 4;
2490 unsigned int m5
: 4;
2492 unsigned int m4
: 4;
2493 unsigned int rxb
: 4;
2494 unsigned int op2
: 8;
2497 unsigned int op1
: 8;
2498 unsigned int v1
: 4;
2499 unsigned int v2
: 4;
2500 unsigned int v3
: 4;
2501 unsigned int m5
: 4;
2502 unsigned int m6
: 4;
2504 unsigned int v4
: 4;
2505 unsigned int rxb
: 4;
2506 unsigned int op2
: 8;
2543 the_insn
.VRR
.op1
= opcodes
[d
->op
][0];
2544 the_insn
.bytes
[1] = the_insn
.bytes
[2]
2545 = the_insn
.bytes
[3] = the_insn
.bytes
[4] = 0;
2546 the_insn
.VRR
.op2
= opcodes
[d
->op
][1];
2549 case S390_VEC_OP_VTM
:
2550 the_insn
.VRR
.v1
= 2;
2551 the_insn
.VRR
.v2
= 3;
2552 the_insn
.VRR
.rxb
= 0b1100;
2555 case S390_VEC_OP_VPKS
:
2556 case S390_VEC_OP_VPKLS
:
2557 case S390_VEC_OP_VCEQ
:
2558 case S390_VEC_OP_VGFM
:
2559 case S390_VEC_OP_VCH
:
2560 case S390_VEC_OP_VCHL
:
2561 the_insn
.VRR
.v1
= 1;
2562 the_insn
.VRR
.v2
= 2;
2563 the_insn
.VRR
.v3
= 3;
2564 the_insn
.VRR
.rxb
= 0b1110;
2565 the_insn
.VRR
.m4
= d
->m4
;
2566 the_insn
.VRR
.m5
= d
->m5
;
2569 case S390_VEC_OP_VGFMA
:
2570 case S390_VEC_OP_VMAH
:
2571 case S390_VEC_OP_VMALH
:
2572 case S390_VEC_OP_VMSL
:
2573 the_insn
.VRRd
.v1
= 1;
2574 the_insn
.VRRd
.v2
= 2;
2575 the_insn
.VRRd
.v3
= 3;
2576 the_insn
.VRRd
.v4
= 4;
2577 the_insn
.VRRd
.rxb
= 0b1111;
2578 the_insn
.VRRd
.m5
= d
->m4
;
2579 the_insn
.VRRd
.m6
= d
->m5
;
2582 case S390_VEC_OP_VFMIN
:
2583 case S390_VEC_OP_VFMAX
:
2584 case S390_VEC_OP_VBPERM
:
2585 case S390_VEC_OP_VCRNF
:
2586 the_insn
.VRRc
.v1
= 1;
2587 the_insn
.VRRc
.v2
= 2;
2588 the_insn
.VRRc
.v3
= 3;
2589 the_insn
.VRRc
.rxb
= 0b1110;
2590 the_insn
.VRRc
.m4
= d
->m4
;
2591 the_insn
.VRRc
.m5
= d
->m5
;
2592 the_insn
.VRRc
.m6
= d
->m6
;
2595 case S390_VEC_OP_VCNF
:
2596 case S390_VEC_OP_VCLFNH
:
2597 case S390_VEC_OP_VCFN
:
2598 case S390_VEC_OP_VCLFNL
:
2599 the_insn
.VRRa
.v1
= 1;
2600 the_insn
.VRRa
.v2
= 2;
2601 the_insn
.VRRa
.rxb
= 0b1100;
2602 the_insn
.VRRa
.m3
= d
->m3
;
2603 the_insn
.VRRa
.m4
= d
->m4
;
2606 case S390_VEC_OP_VFTCI
:
2607 the_insn
.VRIe
.v1
= 1;
2608 the_insn
.VRIe
.v2
= 2;
2609 the_insn
.VRIe
.rxb
= 0b1100;
2610 the_insn
.VRIe
.i3
= d
->i3
;
2611 the_insn
.VRIe
.m4
= d
->m4
;
2612 the_insn
.VRIe
.m5
= d
->m5
;
2616 vex_printf("operation = %d\n", d
->op
);
2617 vpanic("s390x_dirtyhelper_vec_op: unknown operation");
2620 const V128
* guest_v
= &(guest_state
->guest_v0
);
2622 "lgr %%r10, %[arg1]\n"
2624 "lgr %%r10, %[arg2]\n"
2626 "lgr %%r10, %[arg3]\n"
2628 "ex %[zero], %[insn]\n"
2630 "cijne %[read_only], 0, return_cc\n"
2631 "lgr %%r10, %[res]\n"
2632 VST(1, 0, a
, 000, 8)
2638 : [res
] "r" (&guest_v
[d
->v1
]),
2639 [arg1
] "r" (&guest_v
[d
->v2
]),
2640 [arg2
] "r" (&guest_v
[d
->v3
]),
2641 [arg3
] "r" (&guest_v
[d
->v4
]),
2644 [insn
] "R" (the_insn
),
2645 [read_only
] "r" (d
->read_only
)
2647 : "cc", "r10", "v16", "v17", "v18", "v19"
2650 return psw
>> 28; /* cc */
2656 s390x_dirtyhelper_vec_op(VexGuestS390XState
*guest_state
,
2657 const ULong serialized
)
2662 /*-----------------------------------------------------------------*/
2663 /*--- Dirty helper for Perform Pseudorandom number instruction ---*/
2664 /*-----------------------------------------------------------------*/
2666 /* Dummy helper that is needed to indicate load of parameter block.
2667 We have to use it because dirty helper cannot have two memory side
2670 void s390x_dirtyhelper_PPNO_sha512_load_param_block( void )
2674 #if defined(VGA_s390x)
2677 We return here bit mask where only supported functions are set to one.
2678 If you implement new functions don't forget the supported array.
2681 s390x_dirtyhelper_PPNO_query(VexGuestS390XState
*guest_state
, ULong r1
, ULong r2
)
2683 ULong supported
[2] = {0x9000000000000000ULL
, 0x0000000000000000ULL
};
2684 ULong
*result
= (ULong
*) guest_state
->guest_r1
;
2686 result
[0] = supported
[0];
2687 result
[1] = supported
[1];
2691 s390x_dirtyhelper_PPNO_sha512(VexGuestS390XState
*guest_state
, ULong r1
, ULong r2
)
2693 ULong
* op1
= (ULong
*) (((ULong
)(&guest_state
->guest_r0
)) + r1
* sizeof(ULong
));
2694 ULong
* op2
= (ULong
*) (((ULong
)(&guest_state
->guest_r0
)) + r2
* sizeof(ULong
));
2696 register ULong reg0
asm("0") = guest_state
->guest_r0
;
2697 register ULong reg1
asm("1") = guest_state
->guest_r1
;
2698 register ULong reg2
asm("2") = op1
[0];
2699 register ULong reg3
asm("3") = op1
[1];
2700 register ULong reg4
asm("4") = op2
[0];
2701 register ULong reg5
asm("5") = op2
[1];
2704 asm volatile(".insn rre, 0xb93c0000, %%r2, %%r4\n"
2707 : "+d"(reg0
), "+d"(reg1
),
2708 "+d"(reg2
), "+d"(reg3
),
2709 "+d"(reg4
), "+d"(reg5
),
2720 s390x_dirtyhelper_PPNO_query(VexGuestS390XState
*guest_state
, ULong r1
, ULong r2
)
2725 s390x_dirtyhelper_PPNO_sha512(VexGuestS390XState
*guest_state
, ULong r1
, ULong r2
)
2730 #endif /* VGA_s390x */
2731 /*---------------------------------------------------------------*/
2732 /*--- end guest_s390_helpers.c ---*/
2733 /*---------------------------------------------------------------*/