• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- mode: C; c-basic-offset: 3; -*- */
2 
3 /*---------------------------------------------------------------*/
4 /*--- begin                              guest_s390_helpers.c ---*/
5 /*---------------------------------------------------------------*/
6 
7 /*
8    This file is part of Valgrind, a dynamic binary instrumentation
9    framework.
10 
11    Copyright IBM Corp. 2010-2012
12 
13    This program is free software; you can redistribute it and/or
14    modify it under the terms of the GNU General Public License as
15    published by the Free Software Foundation; either version 2 of the
16    License, or (at your option) any later version.
17 
18    This program is distributed in the hope that it will be useful, but
19    WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    General Public License for more details.
22 
23    You should have received a copy of the GNU General Public License
24    along with this program; if not, write to the Free Software
25    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26    02110-1301, USA.
27 
28    The GNU General Public License is contained in the file COPYING.
29 */
30 
31 /* Contributed by Florian Krohm */
32 
33 #include "libvex_basictypes.h"
34 #include "libvex_emwarn.h"
35 #include "libvex_guest_s390x.h"
36 #include "libvex_ir.h"
37 #include "libvex.h"
38 #include "libvex_s390x_common.h"
39 
40 #include "main_util.h"
41 #include "guest_generic_bb_to_IR.h"
42 #include "guest_s390_defs.h"
43 
44 void
LibVEX_GuestS390X_initialise(VexGuestS390XState * state)45 LibVEX_GuestS390X_initialise(VexGuestS390XState *state)
46 {
47 /*------------------------------------------------------------*/
48 /*--- Initialise ar registers                              ---*/
49 /*------------------------------------------------------------*/
50 
51    state->guest_a0 = 0;
52    state->guest_a1 = 0;
53    state->guest_a2 = 0;
54    state->guest_a3 = 0;
55    state->guest_a4 = 0;
56    state->guest_a5 = 0;
57    state->guest_a6 = 0;
58    state->guest_a7 = 0;
59    state->guest_a8 = 0;
60    state->guest_a9 = 0;
61    state->guest_a10 = 0;
62    state->guest_a11 = 0;
63    state->guest_a12 = 0;
64    state->guest_a13 = 0;
65    state->guest_a14 = 0;
66    state->guest_a15 = 0;
67 
68 /*------------------------------------------------------------*/
69 /*--- Initialise fpr registers                             ---*/
70 /*------------------------------------------------------------*/
71 
72    state->guest_f0 = 0;
73    state->guest_f1 = 0;
74    state->guest_f2 = 0;
75    state->guest_f3 = 0;
76    state->guest_f4 = 0;
77    state->guest_f5 = 0;
78    state->guest_f6 = 0;
79    state->guest_f7 = 0;
80    state->guest_f8 = 0;
81    state->guest_f9 = 0;
82    state->guest_f10 = 0;
83    state->guest_f11 = 0;
84    state->guest_f12 = 0;
85    state->guest_f13 = 0;
86    state->guest_f14 = 0;
87    state->guest_f15 = 0;
88 
89 /*------------------------------------------------------------*/
90 /*--- Initialise gpr registers                             ---*/
91 /*------------------------------------------------------------*/
92 
93    state->guest_r0 = 0;
94    state->guest_r1 = 0;
95    state->guest_r2 = 0;
96    state->guest_r3 = 0;
97    state->guest_r4 = 0;
98    state->guest_r5 = 0;
99    state->guest_r6 = 0;
100    state->guest_r7 = 0;
101    state->guest_r8 = 0;
102    state->guest_r9 = 0;
103    state->guest_r10 = 0;
104    state->guest_r11 = 0;
105    state->guest_r12 = 0;
106    state->guest_r13 = 0;
107    state->guest_r14 = 0;
108    state->guest_r15 = 0;
109 
110 /*------------------------------------------------------------*/
111 /*--- Initialise S390 miscellaneous registers              ---*/
112 /*------------------------------------------------------------*/
113 
114    state->guest_counter = 0;
115    state->guest_fpc = 0;
116    state->guest_IA = 0;
117 
118 /*------------------------------------------------------------*/
119 /*--- Initialise S390 pseudo registers                     ---*/
120 /*------------------------------------------------------------*/
121 
122    state->guest_SYSNO = 0;
123 
124 /*------------------------------------------------------------*/
125 /*--- Initialise generic pseudo registers                  ---*/
126 /*------------------------------------------------------------*/
127 
128    state->guest_NRADDR = 0;
129    state->guest_TISTART = 0;
130    state->guest_TILEN = 0;
131    state->guest_IP_AT_SYSCALL = 0;
132    state->guest_EMWARN = EmWarn_NONE;
133    state->host_EvC_COUNTER = 0;
134    state->host_EvC_FAILADDR = 0;
135 
136 /*------------------------------------------------------------*/
137 /*--- Initialise thunk                                     ---*/
138 /*------------------------------------------------------------*/
139 
140    state->guest_CC_OP = 0;
141    state->guest_CC_DEP1 = 0;
142    state->guest_CC_DEP2 = 0;
143    state->guest_CC_NDEP = 0;
144 
145    __builtin_memset(state->padding, 0x0, sizeof(state->padding));
146 }
147 
148 
149 /* Figure out if any part of the guest state contained in minoff
150    .. maxoff requires precise memory exceptions.  If in doubt return
151    True (but this is generates significantly slower code).  */
152 Bool
guest_s390x_state_requires_precise_mem_exns(Int minoff,Int maxoff)153 guest_s390x_state_requires_precise_mem_exns(Int minoff, Int maxoff)
154 {
155    Int lr_min = S390X_GUEST_OFFSET(guest_LR);
156    Int lr_max = lr_min + 8 - 1;
157    Int sp_min = S390X_GUEST_OFFSET(guest_SP);
158    Int sp_max = sp_min + 8 - 1;
159    Int fp_min = S390X_GUEST_OFFSET(guest_FP);
160    Int fp_max = fp_min + 8 - 1;
161    Int ia_min = S390X_GUEST_OFFSET(guest_IA);
162    Int ia_max = ia_min + 8 - 1;
163 
164    if (maxoff < lr_min || minoff > lr_max) {
165       /* No overlap with LR */
166    } else {
167       return True;
168    }
169 
170    if (maxoff < sp_min || minoff > sp_max) {
171       /* No overlap with SP */
172    } else {
173       return True;
174    }
175 
176    if (maxoff < fp_min || minoff > fp_max) {
177       /* No overlap with FP */
178    } else {
179       return True;
180    }
181 
182    if (maxoff < ia_min || minoff > ia_max) {
183       /* No overlap with IA */
184    } else {
185       return True;
186    }
187 
188    return False;
189 }
190 
191 
192 #define ALWAYSDEFD(field)                             \
193     { S390X_GUEST_OFFSET(field),            \
194       (sizeof ((VexGuestS390XState*)0)->field) }
195 
196 VexGuestLayout s390xGuest_layout = {
197 
198    /* Total size of the guest state, in bytes. */
199    .total_sizeB = sizeof(VexGuestS390XState),
200 
201    /* Describe the stack pointer. */
202    .offset_SP = S390X_GUEST_OFFSET(guest_SP),
203    .sizeof_SP = 8,
204 
205    /* Describe the frame pointer. */
206    .offset_FP = S390X_GUEST_OFFSET(guest_FP),
207    .sizeof_FP = 8,
208 
209    /* Describe the instruction pointer. */
210    .offset_IP = S390X_GUEST_OFFSET(guest_IA),
211    .sizeof_IP = 8,
212 
213    /* Describe any sections to be regarded by Memcheck as
214       'always-defined'. */
215    .n_alwaysDefd = 9,
216 
217    /* Flags thunk: OP and NDEP are always defined, whereas DEP1
218       and DEP2 have to be tracked.  See detailed comment in
219       gdefs.h on meaning of thunk fields. */
220    .alwaysDefd = {
221       /*  0 */ ALWAYSDEFD(guest_CC_OP),     /* generic */
222       /*  1 */ ALWAYSDEFD(guest_CC_NDEP),   /* generic */
223       /*  2 */ ALWAYSDEFD(guest_EMWARN),    /* generic */
224       /*  3 */ ALWAYSDEFD(guest_TISTART),   /* generic */
225       /*  4 */ ALWAYSDEFD(guest_TILEN),     /* generic */
226       /*  5 */ ALWAYSDEFD(guest_IP_AT_SYSCALL), /* generic */
227       /*  6 */ ALWAYSDEFD(guest_IA),        /* control reg */
228       /*  7 */ ALWAYSDEFD(guest_fpc),       /* control reg */
229       /*  8 */ ALWAYSDEFD(guest_counter),   /* internal usage register */
230    }
231 };
232 
233 /*------------------------------------------------------------*/
234 /*--- Dirty helper for EXecute                             ---*/
235 /*------------------------------------------------------------*/
236 void
s390x_dirtyhelper_EX(ULong torun)237 s390x_dirtyhelper_EX(ULong torun)
238 {
239    last_execute_target = torun;
240 }
241 
242 
243 /*------------------------------------------------------------*/
244 /*--- Dirty helper for Clock instructions                  ---*/
245 /*------------------------------------------------------------*/
246 #if defined(VGA_s390x)
247 ULong
s390x_dirtyhelper_STCK(ULong * addr)248 s390x_dirtyhelper_STCK(ULong *addr)
249 {
250    int cc;
251 
252    asm volatile("stck %0\n"
253                 "ipm %1\n"
254                 "srl %1,28\n"
255                 : "+Q" (*addr), "=d" (cc) : : "cc");
256    return cc;
257 }
258 
259 ULong
s390x_dirtyhelper_STCKE(ULong * addr)260 s390x_dirtyhelper_STCKE(ULong *addr)
261 {
262    int cc;
263 
264    asm volatile("stcke %0\n"
265                 "ipm %1\n"
266                 "srl %1,28\n"
267                 : "+Q" (*addr), "=d" (cc) : : "cc");
268    return cc;
269 }
270 
s390x_dirtyhelper_STCKF(ULong * addr)271 ULong s390x_dirtyhelper_STCKF(ULong *addr)
272 {
273    int cc;
274 
275    asm volatile(".insn s,0xb27c0000,%0\n"
276                 "ipm %1\n"
277                 "srl %1,28\n"
278                 : "+Q" (*addr), "=d" (cc) : : "cc");
279    return cc;
280 }
281 #else
s390x_dirtyhelper_STCK(ULong * addr)282 ULong s390x_dirtyhelper_STCK(ULong *addr)  {return 3;}
s390x_dirtyhelper_STCKF(ULong * addr)283 ULong s390x_dirtyhelper_STCKF(ULong *addr) {return 3;}
s390x_dirtyhelper_STCKE(ULong * addr)284 ULong s390x_dirtyhelper_STCKE(ULong *addr) {return 3;}
285 #endif /* VGA_s390x */
286 
287 /*------------------------------------------------------------*/
288 /*--- Dirty helper for Store Facility instruction          ---*/
289 /*------------------------------------------------------------*/
290 #if defined(VGA_s390x)
291 ULong
s390x_dirtyhelper_STFLE(VexGuestS390XState * guest_state,ULong * addr)292 s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr)
293 {
294    ULong hoststfle[S390_NUM_FACILITY_DW], cc, num_dw, i;
295    register ULong reg0 asm("0") = guest_state->guest_r0 & 0xF;  /* r0[56:63] */
296 
297    /* We cannot store more than S390_NUM_FACILITY_DW
298       (and it makes not much sense to do so anyhow) */
299    if (reg0 > S390_NUM_FACILITY_DW - 1)
300       reg0 = S390_NUM_FACILITY_DW - 1;
301 
302    num_dw = reg0 + 1;  /* number of double words written */
303 
304    asm volatile(" .insn s,0xb2b00000,%0\n"   /* stfle */
305                 "ipm    %2\n"
306                 "srl    %2,28\n"
307                 : "=m" (hoststfle), "+d"(reg0), "=d"(cc) : : "cc", "memory");
308 
309    /* Update guest register 0  with what STFLE set r0 to */
310    guest_state->guest_r0 = reg0;
311 
312    for (i = 0; i < num_dw; ++i)
313       addr[i] = hoststfle[i];
314 
315    return cc;
316 }
317 
318 #else
319 
320 ULong
s390x_dirtyhelper_STFLE(VexGuestS390XState * guest_state,ULong * addr)321 s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr)
322 {
323    return 3;
324 }
325 #endif /* VGA_s390x */
326 
327 /*------------------------------------------------------------*/
328 /*--- Dirty helper for the "convert unicode" insn family.  ---*/
329 /*------------------------------------------------------------*/
330 void
s390x_dirtyhelper_CUxy(UChar * address,ULong data,ULong num_bytes)331 s390x_dirtyhelper_CUxy(UChar *address, ULong data, ULong num_bytes)
332 {
333    UInt i;
334 
335    vassert(num_bytes >= 1 && num_bytes <= 4);
336 
337    /* Store the least significant NUM_BYTES bytes in DATA left to right
338       at ADDRESS. */
339    for (i = 1; i <= num_bytes; ++i) {
340       address[num_bytes - i] = data & 0xff;
341       data >>= 8;
342    }
343 }
344 
345 
346 /*------------------------------------------------------------*/
347 /*--- Clean helper for CU21.                               ---*/
348 /*------------------------------------------------------------*/
349 
350 /* The function performs a CU21 operation. It returns three things
351    encoded in an ULong value:
352    - the converted bytes (at most 4)
353    - the number of converted bytes
354    - an indication whether LOW_SURROGATE, if any, is invalid
355 
356    64      48                16           8                       0
357     +-------+-----------------+-----------+-----------------------+
358     |  0x0  | converted bytes | num_bytes | invalid_low_surrogate |
359     +-------+-----------------+-----------+-----------------------+
360 */
361 ULong
s390_do_cu21(UInt srcval,UInt low_surrogate)362 s390_do_cu21(UInt srcval, UInt low_surrogate)
363 {
364    ULong retval = 0;   // shut up gcc
365    UInt b1, b2, b3, b4, num_bytes, invalid_low_surrogate = 0;
366 
367    srcval &= 0xffff;
368 
369    /* Determine the number of bytes in the converted value */
370    if (srcval <= 0x007f)
371       num_bytes = 1;
372    else if (srcval >= 0x0080 && srcval <= 0x07ff)
373       num_bytes = 2;
374    else if ((srcval >= 0x0800 && srcval <= 0xd7ff) ||
375             (srcval >= 0xdc00 && srcval <= 0xffff))
376       num_bytes = 3;
377    else
378       num_bytes = 4;
379 
380    /* Determine UTF-8 bytes according to calculated num_bytes */
381    switch (num_bytes){
382    case 1:
383       retval = srcval;
384       break;
385 
386    case 2:
387       /* order of bytes left to right: b1, b2 */
388       b1  = 0xc0;
389       b1 |= srcval >> 6;
390 
391       b2  = 0x80;
392       b2 |= srcval & 0x3f;
393 
394       retval = (b1 << 8) | b2;
395       break;
396 
397    case 3:
398       /* order of bytes left to right: b1, b2, b3 */
399       b1  = 0xe0;
400       b1 |= srcval >> 12;
401 
402       b2  = 0x80;
403       b2 |= (srcval >> 6) & 0x3f;
404 
405       b3  = 0x80;
406       b3 |= srcval & 0x3f;
407 
408       retval = (b1 << 16) | (b2 << 8) | b3;
409       break;
410 
411    case 4: {
412       /* order of bytes left to right: b1, b2, b3, b4 */
413       UInt high_surrogate = srcval;
414       UInt uvwxy = ((high_surrogate >> 6) & 0xf) + 1;   // abcd + 1
415 
416       b1  = 0xf0;
417       b1 |= uvwxy >> 2;     // uvw
418 
419       b2  = 0x80;
420       b2 |= (uvwxy & 0x3) << 4;           // xy
421       b2 |= (high_surrogate >> 2) & 0xf;  // efgh
422 
423       b3  = 0x80;
424       b3 |= (high_surrogate & 0x3) << 4;   // ij
425       b3 |= (low_surrogate >> 6) & 0xf;    // klmn
426 
427       b4  = 0x80;
428       b4 |= low_surrogate & 0x3f;
429 
430       retval = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
431 
432       invalid_low_surrogate = (low_surrogate & 0xfc00) != 0xdc00;
433       break;
434    }
435    }
436 
437    /* At this point RETVAL contains the converted bytes.
438       Build up the final return value. */
439    return (retval << 16) | (num_bytes << 8) | invalid_low_surrogate;
440 }
441 
442 
443 /*------------------------------------------------------------*/
444 /*--- Clean helper for CU24.                               ---*/
445 /*------------------------------------------------------------*/
446 
447 /* The function performs a CU24 operation. It returns two things
448    encoded in an ULong value:
449    - the 4 converted bytes
450    - an indication whether LOW_SURROGATE, if any, is invalid
451 
452    64     40                 8                       0
453     +------------------------+-----------------------+
454     |  0x0 | converted bytes | invalid_low_surrogate |
455     +------------------------+-----------------------+
456 */
457 ULong
s390_do_cu24(UInt srcval,UInt low_surrogate)458 s390_do_cu24(UInt srcval, UInt low_surrogate)
459 {
460    ULong retval;
461    UInt invalid_low_surrogate = 0;
462 
463    srcval &= 0xffff;
464 
465    if ((srcval >= 0x0000 && srcval <= 0xd7ff) ||
466        (srcval >= 0xdc00 && srcval <= 0xffff)) {
467       retval = srcval;
468    } else {
469       /* D800 - DBFF */
470       UInt high_surrogate = srcval;
471       UInt uvwxy  = ((high_surrogate >> 6) & 0xf) + 1;   // abcd + 1
472       UInt efghij = high_surrogate & 0x3f;
473       UInt klmnoprst = low_surrogate & 0x3ff;
474 
475       retval = (uvwxy << 16) | (efghij << 10) | klmnoprst;
476 
477       invalid_low_surrogate = (low_surrogate & 0xfc00) != 0xdc00;
478    }
479 
480    /* At this point RETVAL contains the converted bytes.
481       Build up the final return value. */
482    return (retval << 8) | invalid_low_surrogate;
483 }
484 
485 
486 /*------------------------------------------------------------*/
487 /*--- Clean helper for CU42.                               ---*/
488 /*------------------------------------------------------------*/
489 
490 /* The function performs a CU42 operation. It returns three things
491    encoded in an ULong value:
492    - the converted bytes (at most 4)
493    - the number of converted bytes (2 or 4; 0 if invalid character)
494    - an indication whether the UTF-32 character is invalid
495 
496    64      48                16           8                   0
497     +-------+-----------------+-----------+-------------------+
498     |  0x0  | converted bytes | num_bytes | invalid_character |
499     +-------+-----------------+-----------+-------------------+
500 */
501 ULong
s390_do_cu42(UInt srcval)502 s390_do_cu42(UInt srcval)
503 {
504    ULong retval;
505    UInt num_bytes, invalid_character = 0;
506 
507    if ((srcval >= 0x0000 && srcval <= 0xd7ff) ||
508        (srcval >= 0xdc00 && srcval <= 0xffff)) {
509       retval = srcval;
510       num_bytes = 2;
511    } else if (srcval >= 0x00010000 && srcval <= 0x0010FFFF) {
512       UInt uvwxy  = srcval >> 16;
513       UInt abcd   = (uvwxy - 1) & 0xf;
514       UInt efghij = (srcval >> 10) & 0x3f;
515 
516       UInt high_surrogate = (0xd8 << 8) | (abcd << 6) | efghij;
517       UInt low_surrogate  = (0xdc << 8) | (srcval & 0x3ff);
518 
519       retval = (high_surrogate << 16) | low_surrogate;
520       num_bytes = 4;
521    } else {
522       /* D800 - DBFF or 00110000 - FFFFFFFF */
523       invalid_character = 1;
524       retval = num_bytes = 0;   /* does not matter; not used */
525    }
526 
527    /* At this point RETVAL contains the converted bytes.
528       Build up the final return value. */
529    return (retval << 16) | (num_bytes << 8) | invalid_character;
530 }
531 
532 
533 /*------------------------------------------------------------*/
534 /*--- Clean helper for CU41.                               ---*/
535 /*------------------------------------------------------------*/
536 
537 /* The function performs a CU41 operation. It returns three things
538    encoded in an ULong value:
539    - the converted bytes (at most 4)
540    - the number of converted bytes (1, 2, 3, or 4; 0 if invalid character)
541    - an indication whether the UTF-32 character is invalid
542 
543    64      48                16           8                   0
544     +-------+-----------------+-----------+-------------------+
545     |  0x0  | converted bytes | num_bytes | invalid_character |
546     +-------+-----------------+-----------+-------------------+
547 */
548 ULong
s390_do_cu41(UInt srcval)549 s390_do_cu41(UInt srcval)
550 {
551    ULong retval;
552    UInt num_bytes, invalid_character = 0;
553 
554    if (srcval <= 0x7f) {
555       retval = srcval;
556       num_bytes = 1;
557    } else if (srcval >= 0x80 && srcval <= 0x7ff) {
558       UInt fghij  = srcval >> 6;
559       UInt klmnop = srcval & 0x3f;
560       UInt byte1  = (0xc0 | fghij);
561       UInt byte2  = (0x80 | klmnop);
562 
563       retval = (byte1 << 8) | byte2;
564       num_bytes = 2;
565    } else if ((srcval >= 0x800  && srcval <= 0xd7ff) ||
566               (srcval >= 0xdc00 && srcval <= 0xffff)) {
567       UInt abcd   = srcval >> 12;
568       UInt efghij = (srcval >> 6) & 0x3f;
569       UInt klmnop = srcval & 0x3f;
570       UInt byte1  = 0xe0 | abcd;
571       UInt byte2  = 0x80 | efghij;
572       UInt byte3  = 0x80 | klmnop;
573 
574       retval = (byte1 << 16) | (byte2 << 8) | byte3;
575       num_bytes = 3;
576    } else if (srcval >= 0x10000 && srcval <= 0x10ffff) {
577       UInt uvw    = (srcval >> 18) & 0x7;
578       UInt xy     = (srcval >> 16) & 0x3;
579       UInt efgh   = (srcval >> 12) & 0xf;
580       UInt ijklmn = (srcval >>  6) & 0x3f;
581       UInt opqrst = srcval & 0x3f;
582       UInt byte1  = 0xf0 | uvw;
583       UInt byte2  = 0x80 | (xy << 4) | efgh;
584       UInt byte3  = 0x80 | ijklmn;
585       UInt byte4  = 0x80 | opqrst;
586 
587       retval = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
588       num_bytes = 4;
589    } else {
590       /* d800 ... dbff or 00110000 ... ffffffff */
591       invalid_character = 1;
592 
593       retval = 0;
594       num_bytes = 0;
595    }
596 
597    /* At this point RETVAL contains the converted bytes.
598       Build up the final return value. */
599    return (retval << 16) | (num_bytes << 8) | invalid_character;
600 }
601 
602 
603 /*------------------------------------------------------------*/
604 /*--- Clean helpers for CU12.                              ---*/
605 /*------------------------------------------------------------*/
606 
607 /* The function looks at the first byte of an UTF-8 character and returns
608    two things encoded in an ULong value:
609 
610    - the number of bytes that need to be read
611    - an indication whether the UTF-8 character is invalid
612 
613    64      16           8                   0
614     +-------------------+-------------------+
615     |  0x0  | num_bytes | invalid_character |
616     +-------+-----------+-------------------+
617 */
618 ULong
s390_do_cu12_cu14_helper1(UInt byte,UInt etf3_and_m3_is_1)619 s390_do_cu12_cu14_helper1(UInt byte, UInt etf3_and_m3_is_1)
620 {
621    vassert(byte <= 0xff);
622 
623    /* Check whether the character is invalid */
624    if (byte >= 0x80 && byte <= 0xbf) return 1;
625    if (byte >= 0xf8) return 1;
626 
627    if (etf3_and_m3_is_1) {
628       if (byte == 0xc0 || byte == 0xc1) return 1;
629       if (byte >= 0xf5 && byte <= 0xf7) return 1;
630    }
631 
632    /* Character is valid */
633    if (byte <= 0x7f) return 1 << 8;   // 1 byte
634    if (byte <= 0xdf) return 2 << 8;   // 2 bytes
635    if (byte <= 0xef) return 3 << 8;   // 3 bytes
636 
637    return 4 << 8;  // 4 bytes
638 }
639 
640 /* The function performs a CU12 or CU14 operation. BYTE1, BYTE2, etc are the
641    bytes as read from the input stream, left to right. BYTE1 is a valid
642    byte. The function returns three things encoded in an ULong value:
643 
644    - the converted bytes
645    - the number of converted bytes (2 or 4; 0 if invalid character)
646    - an indication whether the UTF-16 character is invalid
647 
648    64      48                16           8                   0
649     +-------+-----------------+-----------+-------------------+
650     |  0x0  | converted bytes | num_bytes | invalid_character |
651     +-------+-----------------+-----------+-------------------+
652 */
653 static ULong
s390_do_cu12_cu14_helper2(UInt byte1,UInt byte2,UInt byte3,UInt byte4,ULong stuff,Bool is_cu12)654 s390_do_cu12_cu14_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4,
655                           ULong stuff, Bool is_cu12)
656 {
657    UInt num_src_bytes = stuff >> 1, etf3_and_m3_is_1 = stuff & 0x1;
658    UInt num_bytes = 0, invalid_character = 0;
659    ULong retval = 0;
660 
661    vassert(num_src_bytes <= 4);
662 
663    switch (num_src_bytes) {
664    case 1:
665       num_bytes = 2;
666       retval = byte1;
667       break;
668 
669    case 2: {
670       /* Test validity */
671       if (etf3_and_m3_is_1) {
672          if (byte2 < 0x80 || byte2 > 0xbf) {
673             invalid_character = 1;
674             break;
675          }
676       }
677 
678       /* OK */
679       UInt fghij  = byte1 & 0x1f;
680       UInt klmnop = byte2 & 0x3f;
681 
682       num_bytes = 2;
683       retval = (fghij << 6) | klmnop;
684       break;
685    }
686 
687    case 3: {
688       /* Test validity */
689       if (etf3_and_m3_is_1) {
690          if (byte1 == 0xe0) {
691             if ((byte2 < 0xa0 || byte2 > 0xbf) ||
692                 (byte3 < 0x80 || byte3 > 0xbf)) {
693                invalid_character = 1;
694                break;
695             }
696          }
697          if ((byte1 >= 0xe1 && byte1 <= 0xec) ||
698              byte1 == 0xee || byte1 == 0xef) {
699             if ((byte2 < 0x80 || byte2 > 0xbf) ||
700                 (byte3 < 0x80 || byte3 > 0xbf)) {
701                invalid_character = 1;
702                break;
703             }
704          }
705          if (byte1 == 0xed) {
706             if ((byte2 < 0x80 || byte2 > 0x9f) ||
707                 (byte3 < 0x80 || byte3 > 0xbf)) {
708                invalid_character = 1;
709                break;
710             }
711          }
712       }
713 
714       /* OK */
715       UInt abcd   = byte1 & 0xf;
716       UInt efghij = byte2 & 0x3f;
717       UInt klmnop = byte3 & 0x3f;
718 
719       num_bytes = 2;
720       retval = (abcd << 12) | (efghij << 6) | klmnop;
721       break;
722    }
723 
724    case 4: {
725       /* Test validity */
726       if (etf3_and_m3_is_1) {
727          if (byte1 == 0xf0) {
728             if ((byte2 < 0x90 || byte2 > 0xbf) ||
729                 (byte3 < 0x80 || byte3 > 0xbf) ||
730                 (byte4 < 0x80 || byte4 > 0xbf)) {
731                invalid_character = 1;
732                break;
733             }
734          }
735          if (byte1 == 0xf1 || byte1 == 0xf2 || byte1 == 0xf3) {
736             if ((byte2 < 0x80 || byte2 > 0xbf) ||
737                 (byte3 < 0x80 || byte3 > 0xbf) ||
738                 (byte4 < 0x80 || byte4 > 0xbf)) {
739                invalid_character = 1;
740                break;
741             }
742          }
743          if (byte1 == 0xf4) {
744             if ((byte2 < 0x80 || byte2 > 0x8f) ||
745                 (byte3 < 0x80 || byte3 > 0xbf) ||
746                 (byte4 < 0x80 || byte4 > 0xbf)) {
747                invalid_character = 1;
748                break;
749             }
750          }
751       }
752 
753       /* OK */
754       UInt uvw    = byte1 & 0x7;
755       UInt xy     = (byte2 >> 4) & 0x3;
756       UInt uvwxy  = (uvw << 2) | xy;
757       UInt efgh   = byte2 & 0xf;
758       UInt ij     = (byte3 >> 4) & 0x3;
759       UInt klmn   = byte3 & 0xf;
760       UInt opqrst = byte4 & 0x3f;
761 
762       if (is_cu12) {
763          UInt abcd = (uvwxy - 1) & 0xf;
764          UInt high_surrogate = (0xd8 << 8) | (abcd << 6) | (efgh << 2) | ij;
765          UInt low_surrogate  = (0xdc << 8) | (klmn << 6) | opqrst;
766 
767          num_bytes = 4;
768          retval = (high_surrogate << 16) | low_surrogate;
769       } else {
770          num_bytes = 4;
771          retval =
772             (uvwxy << 16) | (efgh << 12) | (ij << 10) | (klmn << 6) | opqrst;
773       }
774       break;
775    }
776    }
777 
778    if (! is_cu12) num_bytes = 4;   // for CU14, by definition
779 
780    /* At this point RETVAL contains the converted bytes.
781       Build up the final return value. */
782    return (retval << 16) | (num_bytes << 8) | invalid_character;
783 }
784 
785 ULong
s390_do_cu12_helper2(UInt byte1,UInt byte2,UInt byte3,UInt byte4,ULong stuff)786 s390_do_cu12_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4,
787                      ULong stuff)
788 {
789    return s390_do_cu12_cu14_helper2(byte1, byte2, byte3, byte4, stuff,
790                                     /* is_cu12 = */ 1);
791 }
792 
793 ULong
s390_do_cu14_helper2(UInt byte1,UInt byte2,UInt byte3,UInt byte4,ULong stuff)794 s390_do_cu14_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4,
795                      ULong stuff)
796 {
797    return s390_do_cu12_cu14_helper2(byte1, byte2, byte3, byte4, stuff,
798                                     /* is_cu12 = */ 0);
799 }
800 
801 
802 /*------------------------------------------------------------*/
803 /*--- Clean helper for "convert to binary".                ---*/
804 /*------------------------------------------------------------*/
805 #if defined(VGA_s390x)
806 UInt
s390_do_cvb(ULong decimal)807 s390_do_cvb(ULong decimal)
808 {
809    UInt binary;
810 
811    __asm__ volatile (
812         "cvb %[result],%[input]\n\t"
813           : [result] "=d"(binary)
814           : [input] "m"(decimal)
815    );
816 
817    return binary;
818 }
819 
820 #else
s390_do_cvb(ULong decimal)821 UInt s390_do_cvb(ULong decimal) { return 0; }
822 #endif
823 
824 
825 /*------------------------------------------------------------*/
826 /*--- Clean helper for "convert to decimal".                ---*/
827 /*------------------------------------------------------------*/
828 #if defined(VGA_s390x)
829 ULong
s390_do_cvd(ULong binary_in)830 s390_do_cvd(ULong binary_in)
831 {
832    UInt binary = binary_in & 0xffffffffULL;
833    ULong decimal;
834 
835    __asm__ volatile (
836         "cvd %[input],%[result]\n\t"
837           : [result] "=m"(decimal)
838           : [input] "d"(binary)
839    );
840 
841    return decimal;
842 }
843 
844 #else
s390_do_cvd(ULong binary)845 ULong s390_do_cvd(ULong binary) { return 0; }
846 #endif
847 
848 
849 /*------------------------------------------------------------*/
850 /*--- Helper for condition code.                           ---*/
851 /*------------------------------------------------------------*/
852 
853 #define S390_CC_FOR_BINARY(opcode,cc_dep1,cc_dep2) \
854 ({ \
855    __asm__ volatile ( \
856         opcode " %[op1],%[op2]\n\t" \
857         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+d"(cc_dep1) \
858                                    : [op2] "d"(cc_dep2) \
859                                    : "cc");\
860    psw >> 28;   /* cc */ \
861 })
862 
863 #define S390_CC_FOR_TERNARY_SUBB(opcode,cc_dep1,cc_dep2,cc_ndep) \
864 ({ \
865    /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
866       for rationale. */ \
867    cc_dep2 = cc_dep2 ^ cc_ndep; \
868    __asm__ volatile ( \
869 	"lghi 0,1\n\t" \
870 	"sr 0,%[op3]\n\t" /* borrow to cc */ \
871         opcode " %[op1],%[op2]\n\t" /* then redo the op */\
872         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \
873                                    : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
874                                    : "0", "cc");\
875    psw >> 28;   /* cc */ \
876 })
877 
878 #define S390_CC_FOR_TERNARY_ADDC(opcode,cc_dep1,cc_dep2,cc_ndep) \
879 ({ \
880    /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
881       for rationale. */ \
882    cc_dep2 = cc_dep2 ^ cc_ndep; \
883    __asm__ volatile ( \
884 	"lgfr 0,%[op3]\n\t" /* first load cc_ndep */ \
885 	"aghi 0,0\n\t" /* and convert it into a cc */ \
886         opcode " %[op1],%[op2]\n\t" /* then redo the op */\
887         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \
888                                    : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
889                                    : "0", "cc");\
890    psw >> 28;   /* cc */ \
891 })
892 
893 
894 #define S390_CC_FOR_BFP_RESULT(opcode,cc_dep1) \
895 ({ \
896    __asm__ volatile ( \
897         opcode " 0,%[op]\n\t" \
898         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
899                                    : [op]  "f"(cc_dep1) \
900                                    : "cc", "f0");\
901    psw >> 28;   /* cc */ \
902 })
903 
904 #define S390_CC_FOR_BFP128_RESULT(hi,lo) \
905 ({ \
906    __asm__ volatile ( \
907         "ldr   4,%[high]\n\t" \
908         "ldr   6,%[low]\n\t" \
909         "ltxbr 0,4\n\t" \
910         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
911                                    : [high] "f"(hi), [low] "f"(lo) \
912                                    : "cc", "f0", "f2", "f4", "f6");\
913    psw >> 28;   /* cc */ \
914 })
915 
916 #define S390_CC_FOR_BFP_CONVERT(opcode,cc_dep1) \
917 ({ \
918    __asm__ volatile ( \
919         opcode " 0,0,%[op]\n\t" \
920         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
921                                    : [op]  "f"(cc_dep1) \
922                                    : "cc", "r0");\
923    psw >> 28;   /* cc */ \
924 })
925 
926 #define S390_CC_FOR_BFP128_CONVERT(opcode,hi,lo) \
927 ({ \
928    __asm__ volatile ( \
929         "ldr   4,%[high]\n\t" \
930         "ldr   6,%[low]\n\t" \
931         opcode " 0,0,4\n\t" \
932         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
933                                    : [high] "f"(hi), [low] "f"(lo) \
934                                    : "cc", "r0", "f4", "f6");\
935    psw >> 28;   /* cc */ \
936 })
937 
938 #define S390_CC_FOR_BFP_TDC(opcode,cc_dep1,cc_dep2) \
939 ({ \
940    __asm__ volatile ( \
941         opcode " %[value],0(%[class])\n\t" \
942         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
943                                    : [value] "f"(cc_dep1), \
944                                      [class] "a"(cc_dep2)  \
945                                    : "cc");\
946    psw >> 28;   /* cc */ \
947 })
948 
949 #define S390_CC_FOR_BFP128_TDC(cc_dep1,cc_dep2,cc_ndep) \
950 ({ \
951    /* Recover the original DEP2 value. See comment near s390_cc_thunk_put1f128Z \
952       for rationale. */ \
953    cc_dep2 = cc_dep2 ^ cc_ndep; \
954    __asm__ volatile ( \
955         "ldr  4,%[high]\n\t" \
956         "ldr  6,%[low]\n\t" \
957         "tcxb 4,0(%[class])\n\t" \
958         "ipm  %[psw]\n\t"          : [psw] "=d"(psw) \
959                                    : [high] "f"(cc_dep1), [low] "f"(cc_dep2), \
960                                      [class] "a"(cc_ndep)  \
961                                    : "cc", "f4", "f6");\
962    psw >> 28;   /* cc */ \
963 })
964 
965 
966 /* Return the value of the condition code from the supplied thunk parameters.
967    This is not the value of the PSW. It is the value of the 2 CC bits within
968    the PSW. The returned value is thusly in the interval [0:3]. */
969 UInt
s390_calculate_cc(ULong cc_op,ULong cc_dep1,ULong cc_dep2,ULong cc_ndep)970 s390_calculate_cc(ULong cc_op, ULong cc_dep1, ULong cc_dep2, ULong cc_ndep)
971 {
972 #if defined(VGA_s390x)
973    UInt psw;
974 
975    switch (cc_op) {
976 
977    case S390_CC_OP_BITWISE:
978       return S390_CC_FOR_BINARY("ogr", cc_dep1, (ULong)0);
979 
980    case S390_CC_OP_SIGNED_COMPARE:
981       return S390_CC_FOR_BINARY("cgr", cc_dep1, cc_dep2);
982 
983    case S390_CC_OP_UNSIGNED_COMPARE:
984       return S390_CC_FOR_BINARY("clgr", cc_dep1, cc_dep2);
985 
986    case S390_CC_OP_SIGNED_ADD_64:
987       return S390_CC_FOR_BINARY("agr", cc_dep1, cc_dep2);
988 
989    case S390_CC_OP_SIGNED_ADD_32:
990       return S390_CC_FOR_BINARY("ar", cc_dep1, cc_dep2);
991 
992    case S390_CC_OP_SIGNED_SUB_64:
993       return S390_CC_FOR_BINARY("sgr", cc_dep1, cc_dep2);
994 
995    case S390_CC_OP_SIGNED_SUB_32:
996       return S390_CC_FOR_BINARY("sr", cc_dep1, cc_dep2);
997 
998    case S390_CC_OP_UNSIGNED_ADD_64:
999       return S390_CC_FOR_BINARY("algr", cc_dep1, cc_dep2);
1000 
1001    case S390_CC_OP_UNSIGNED_ADD_32:
1002       return S390_CC_FOR_BINARY("alr", cc_dep1, cc_dep2);
1003 
1004    case S390_CC_OP_UNSIGNED_ADDC_64:
1005       return S390_CC_FOR_TERNARY_ADDC("alcgr", cc_dep1, cc_dep2, cc_ndep);
1006 
1007    case S390_CC_OP_UNSIGNED_ADDC_32:
1008       return S390_CC_FOR_TERNARY_ADDC("alcr", cc_dep1, cc_dep2, cc_ndep);
1009 
1010    case S390_CC_OP_UNSIGNED_SUB_64:
1011       return S390_CC_FOR_BINARY("slgr", cc_dep1, cc_dep2);
1012 
1013    case S390_CC_OP_UNSIGNED_SUB_32:
1014       return S390_CC_FOR_BINARY("slr", cc_dep1, cc_dep2);
1015 
1016    case S390_CC_OP_UNSIGNED_SUBB_64:
1017       return S390_CC_FOR_TERNARY_SUBB("slbgr", cc_dep1, cc_dep2, cc_ndep);
1018 
1019    case S390_CC_OP_UNSIGNED_SUBB_32:
1020       return S390_CC_FOR_TERNARY_SUBB("slbr", cc_dep1, cc_dep2, cc_ndep);
1021 
1022    case S390_CC_OP_LOAD_AND_TEST:
1023       /* Like signed comparison with 0 */
1024       return S390_CC_FOR_BINARY("cgr", cc_dep1, (Long)0);
1025 
1026    case S390_CC_OP_LOAD_POSITIVE_32:
1027       __asm__ volatile (
1028            "lpr  %[result],%[op]\n\t"
1029            "ipm  %[psw]\n\t"         : [psw] "=d"(psw), [result] "=d"(cc_dep1)
1030                                      : [op] "d"(cc_dep1)
1031                                      : "cc");
1032       return psw >> 28;   /* cc */
1033 
1034    case S390_CC_OP_LOAD_POSITIVE_64:
1035       __asm__ volatile (
1036            "lpgr %[result],%[op]\n\t"
1037            "ipm  %[psw]\n\t"         : [psw] "=d"(psw), [result] "=d"(cc_dep1)
1038                                      : [op] "d"(cc_dep1)
1039                                      : "cc");
1040       return psw >> 28;   /* cc */
1041 
1042    case S390_CC_OP_TEST_UNDER_MASK_8: {
1043       UChar value  = cc_dep1;
1044       UChar mask   = cc_dep2;
1045 
1046       __asm__ volatile (
1047            "bras %%r2,1f\n\t"             /* %r2 = address of next insn */
1048            "tm %[value],0\n\t"            /* this is skipped, then EXecuted */
1049            "1: ex %[mask],0(%%r2)\n\t"    /* EXecute TM after modifying mask */
1050            "ipm %[psw]\n\t"             : [psw] "=d"(psw)
1051                                         : [value] "m"(value), [mask] "a"(mask)
1052                                         : "r2", "cc");
1053       return psw >> 28;   /* cc */
1054    }
1055 
1056    case S390_CC_OP_TEST_UNDER_MASK_16: {
1057       /* Create a TMLL insn with the mask as given by cc_dep2 */
1058       UInt insn  = (0xA701 << 16) | cc_dep2;
1059       UInt value = cc_dep1;
1060 
1061       __asm__ volatile (
1062            "lr   1,%[value]\n\t"
1063            "lhi  2,0x10\n\t"
1064            "ex   2,%[insn]\n\t"
1065            "ipm  %[psw]\n\t"       : [psw] "=d"(psw)
1066                                    : [value] "d"(value), [insn] "m"(insn)
1067                                    : "r1", "r2", "cc");
1068       return psw >> 28;   /* cc */
1069    }
1070 
1071    case S390_CC_OP_SHIFT_LEFT_32:
1072       __asm__ volatile (
1073            "sla  %[op],0(%[amount])\n\t"
1074            "ipm  %[psw]\n\t"            : [psw] "=d"(psw), [op] "+d"(cc_dep1)
1075                                         : [amount] "a"(cc_dep2)
1076                                         : "cc");
1077       return psw >> 28;   /* cc */
1078 
1079    case S390_CC_OP_SHIFT_LEFT_64: {
1080       Int high = (Int)(cc_dep1 >> 32);
1081       Int low  = (Int)(cc_dep1 & 0xFFFFFFFF);
1082 
1083       __asm__ volatile (
1084            "lr   2,%[high]\n\t"
1085            "lr   3,%[low]\n\t"
1086            "slda 2,0(%[amount])\n\t"
1087            "ipm %[psw]\n\t"             : [psw] "=d"(psw), [high] "+d"(high),
1088                                           [low] "+d"(low)
1089                                         : [amount] "a"(cc_dep2)
1090                                         : "cc", "r2", "r3");
1091       return psw >> 28;   /* cc */
1092    }
1093 
1094    case S390_CC_OP_INSERT_CHAR_MASK_32: {
1095       Int inserted = 0;
1096       Int msb = 0;
1097 
1098       if (cc_dep2 & 1) {
1099          inserted |= cc_dep1 & 0xff;
1100          msb = 0x80;
1101       }
1102       if (cc_dep2 & 2) {
1103          inserted |= cc_dep1 & 0xff00;
1104          msb = 0x8000;
1105       }
1106       if (cc_dep2 & 4) {
1107          inserted |= cc_dep1 & 0xff0000;
1108          msb = 0x800000;
1109       }
1110       if (cc_dep2 & 8) {
1111          inserted |= cc_dep1 & 0xff000000;
1112          msb = 0x80000000;
1113       }
1114 
1115       if (inserted & msb)  // MSB is 1
1116          return 1;
1117       if (inserted > 0)
1118          return 2;
1119       return 0;
1120    }
1121 
1122    case S390_CC_OP_BFP_RESULT_32:
1123       return S390_CC_FOR_BFP_RESULT("ltebr", cc_dep1);
1124 
1125    case S390_CC_OP_BFP_RESULT_64:
1126       return S390_CC_FOR_BFP_RESULT("ltdbr", cc_dep1);
1127 
1128    case S390_CC_OP_BFP_RESULT_128:
1129       return S390_CC_FOR_BFP128_RESULT(cc_dep1, cc_dep2);
1130 
1131    case S390_CC_OP_BFP_32_TO_INT_32:
1132       return S390_CC_FOR_BFP_CONVERT("cfebr", cc_dep1);
1133 
1134    case S390_CC_OP_BFP_64_TO_INT_32:
1135       return S390_CC_FOR_BFP_CONVERT("cfdbr", cc_dep1);
1136 
1137    case S390_CC_OP_BFP_128_TO_INT_32:
1138       return S390_CC_FOR_BFP128_CONVERT("cfxbr", cc_dep1, cc_dep2);
1139 
1140    case S390_CC_OP_BFP_32_TO_INT_64:
1141       return S390_CC_FOR_BFP_CONVERT("cgebr", cc_dep1);
1142 
1143    case S390_CC_OP_BFP_64_TO_INT_64:
1144       return S390_CC_FOR_BFP_CONVERT("cgdbr", cc_dep1);
1145 
1146    case S390_CC_OP_BFP_128_TO_INT_64:
1147       return S390_CC_FOR_BFP128_CONVERT("cgxbr", cc_dep1, cc_dep2);
1148 
1149    case S390_CC_OP_BFP_TDC_32:
1150       return S390_CC_FOR_BFP_TDC("tceb", cc_dep1, cc_dep2);
1151 
1152    case S390_CC_OP_BFP_TDC_64:
1153       return S390_CC_FOR_BFP_TDC("tcdb", cc_dep1, cc_dep2);
1154 
1155    case S390_CC_OP_BFP_TDC_128:
1156       return S390_CC_FOR_BFP128_TDC(cc_dep1, cc_dep2, cc_ndep);
1157 
1158    case S390_CC_OP_SET:
1159       return cc_dep1;
1160 
1161    default:
1162       break;
1163    }
1164 #endif
1165    vpanic("s390_calculate_cc");
1166 }
1167 
1168 
1169 /* Note that this does *not* return a Boolean value. The result needs to be
1170    explicitly tested against zero. */
1171 UInt
s390_calculate_cond(ULong mask,ULong op,ULong dep1,ULong dep2,ULong ndep)1172 s390_calculate_cond(ULong mask, ULong op, ULong dep1, ULong dep2, ULong ndep)
1173 {
1174    UInt cc = s390_calculate_cc(op, dep1, dep2, ndep);
1175 
1176    return ((mask << cc) & 0x8);
1177 }
1178 
1179 /*------------------------------------------------------------*/
1180 /*--- spechelper for performance                           ---*/
1181 /*------------------------------------------------------------*/
1182 
1183 
1184 /* Convenience macros */
1185 #define unop(op,a1) IRExpr_Unop((op),(a1))
1186 #define binop(op,a1,a2) IRExpr_Binop((op),(a1),(a2))
1187 #define mkU64(v) IRExpr_Const(IRConst_U64(v))
1188 #define mkU32(v) IRExpr_Const(IRConst_U32(v))
1189 #define mkU8(v)  IRExpr_Const(IRConst_U8(v))
1190 
1191 
1192 static inline Bool
isC64(IRExpr * expr)1193 isC64(IRExpr *expr)
1194 {
1195    return expr->tag == Iex_Const && expr->Iex.Const.con->tag == Ico_U64;
1196 }
1197 
1198 
1199 /* The returned expression is NULL if no specialization was found. In that
1200    case the helper function will be called. Otherwise, the expression has
1201    type Ity_I32 and a Boolean value. */
1202 IRExpr *
guest_s390x_spechelper(HChar * function_name,IRExpr ** args,IRStmt ** precedingStmts,Int n_precedingStmts)1203 guest_s390x_spechelper(HChar *function_name, IRExpr **args,
1204                        IRStmt **precedingStmts, Int n_precedingStmts)
1205 {
1206    UInt i, arity = 0;
1207 
1208    for (i = 0; args[i]; i++)
1209       arity++;
1210 
1211 #  if 0
1212    vex_printf("spec request:\n");
1213    vex_printf("   %s  ", function_name);
1214    for (i = 0; i < arity; i++) {
1215       vex_printf("  ");
1216       ppIRExpr(args[i]);
1217    }
1218    vex_printf("\n");
1219 #  endif
1220 
1221    /* --------- Specialising "s390_calculate_cond" --------- */
1222 
1223    if (vex_streq(function_name, "s390_calculate_cond")) {
1224       IRExpr *cond_expr, *cc_op_expr, *cc_dep1, *cc_dep2;
1225       ULong cond, cc_op;
1226 
1227       vassert(arity == 5);
1228 
1229       cond_expr  = args[0];
1230       cc_op_expr = args[1];
1231 
1232       /* The necessary requirement for all optimizations here is that the
1233          condition and the cc_op are constant. So check that upfront. */
1234       if (! isC64(cond_expr))  return NULL;
1235       if (! isC64(cc_op_expr)) return NULL;
1236 
1237       cond    = cond_expr->Iex.Const.con->Ico.U64;
1238       cc_op   = cc_op_expr->Iex.Const.con->Ico.U64;
1239 
1240       vassert(cond <= 15);
1241 
1242       /*
1243         +------+---+---+---+---+
1244         | cc   | 0 | 1 | 2 | 3 |
1245         | cond | 8 | 4 | 2 | 1 |
1246         +------+---+---+---+---+
1247       */
1248       cc_dep1 = args[2];
1249       cc_dep2 = args[3];
1250 
1251       /* S390_CC_OP_SIGNED_COMPARE */
1252       if (cc_op == S390_CC_OP_SIGNED_COMPARE) {
1253          /*
1254             cc == 0  --> cc_dep1 == cc_dep2   (cond == 8)
1255             cc == 1  --> cc_dep1 <  cc_dep2   (cond == 4)
1256             cc == 2  --> cc_dep1 >  cc_dep2   (cond == 2)
1257 
1258             Because cc == 3 cannot occur the rightmost bit of cond is
1259             a don't care.
1260          */
1261          if (cond == 8 || cond == 8 + 1) {
1262             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
1263          }
1264          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
1265             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
1266          }
1267          if (cond == 4 || cond == 4 + 1) {
1268             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep1, cc_dep2));
1269          }
1270          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
1271             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, cc_dep2));
1272          }
1273          /* cc_dep1 > cc_dep2  ---->  cc_dep2 < cc_dep1 */
1274          if (cond == 2 || cond == 2 + 1) {
1275             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep2, cc_dep1));
1276          }
1277          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
1278             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep2, cc_dep1));
1279          }
1280          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
1281             return mkU32(1);
1282          }
1283          /* Remaining case */
1284          return mkU32(0);
1285       }
1286 
1287       /* S390_CC_OP_UNSIGNED_COMPARE */
1288       if (cc_op == S390_CC_OP_UNSIGNED_COMPARE) {
1289          /*
1290             cc == 0  --> cc_dep1 == cc_dep2   (cond == 8)
1291             cc == 1  --> cc_dep1 <  cc_dep2   (cond == 4)
1292             cc == 2  --> cc_dep1 >  cc_dep2   (cond == 2)
1293 
1294             Because cc == 3 cannot occur the rightmost bit of cond is
1295             a don't care.
1296          */
1297          if (cond == 8 || cond == 8 + 1) {
1298             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
1299          }
1300          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
1301             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
1302          }
1303          if (cond == 4 || cond == 4 + 1) {
1304             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
1305          }
1306          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
1307             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
1308          }
1309          /* cc_dep1 > cc_dep2  ---->  cc_dep2 < cc_dep1 */
1310          if (cond == 2 || cond == 2 + 1) {
1311             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
1312          }
1313          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
1314             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
1315          }
1316          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
1317             return mkU32(1);
1318          }
1319          /* Remaining case */
1320          return mkU32(0);
1321       }
1322 
1323       /* S390_CC_OP_LOAD_AND_TEST */
1324       if (cc_op == S390_CC_OP_LOAD_AND_TEST) {
1325          /*
1326             cc == 0  --> cc_dep1 == 0   (cond == 8)
1327             cc == 1  --> cc_dep1 <  0   (cond == 4)
1328             cc == 2  --> cc_dep1 >  0   (cond == 2)
1329 
1330             Because cc == 3 cannot occur the rightmost bit of cond is
1331             a don't care.
1332          */
1333          if (cond == 8 || cond == 8 + 1) {
1334             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
1335          }
1336          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
1337             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
1338          }
1339          if (cond == 4 || cond == 4 + 1) {
1340             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep1, mkU64(0)));
1341          }
1342          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
1343             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, mkU64(0)));
1344          }
1345          /* cc_dep1 > 0  ---->  0 < cc_dep1 */
1346          if (cond == 2 || cond == 2 + 1) {
1347             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, mkU64(0), cc_dep1));
1348          }
1349          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
1350             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, mkU64(0), cc_dep1));
1351          }
1352          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
1353             return mkU32(1);
1354          }
1355          /* Remaining case */
1356          return mkU32(0);
1357       }
1358 
1359       /* S390_CC_OP_BITWISE */
1360       if (cc_op == S390_CC_OP_BITWISE) {
1361          /*
1362             cc_dep1 is the result of the boolean operation.
1363 
1364             cc == 0  --> cc_dep1 == 0   (cond == 8)
1365             cc == 1  --> cc_dep1 != 0   (cond == 4)
1366 
1367             Because cc == 2 and cc == 3 cannot occur the two rightmost bits of
1368             cond are don't cares. Therefore:
1369 
1370             cond == 00xx  -> always false
1371             cond == 01xx  -> not equal
1372             cond == 10xx  -> equal
1373             cond == 11xx  -> always true
1374          */
1375          if ((cond & (8 + 4)) == 8 + 4) {
1376             return mkU32(1);
1377          }
1378          if (cond & 8) {
1379             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
1380          }
1381          if (cond & 4) {
1382             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
1383          }
1384          /* Remaining case */
1385          return mkU32(0);
1386       }
1387 
1388       /* S390_CC_OP_INSERT_CHAR_MASK_32
1389          Since the mask comes from an immediate field in the opcode, we
1390          expect the mask to be a constant here. That simplifies matters. */
1391       if (cc_op == S390_CC_OP_INSERT_CHAR_MASK_32) {
1392          ULong mask;
1393          UInt imask = 0, shift = 0;
1394          IRExpr *word;
1395 
1396          if (! isC64(cc_dep2)) goto missed;
1397 
1398          mask = cc_dep2->Iex.Const.con->Ico.U64;
1399 
1400          /* Extract the 32-bit value from the thunk */
1401 
1402          word = unop(Iop_64to32, cc_dep1);
1403 
1404          switch (mask) {
1405          case 0:  shift =  0; imask = 0x00000000; break;
1406          case 1:  shift = 24; imask = 0x000000FF; break;
1407          case 2:  shift = 16; imask = 0x0000FF00; break;
1408          case 3:  shift = 16; imask = 0x0000FFFF; break;
1409          case 4:  shift =  8; imask = 0x00FF0000; break;
1410          case 5:  shift =  8; imask = 0x00FF00FF; break;
1411          case 6:  shift =  8; imask = 0x00FFFF00; break;
1412          case 7:  shift =  8; imask = 0x00FFFFFF; break;
1413          case 8:  shift =  0; imask = 0xFF000000; break;
1414          case 9:  shift =  0; imask = 0xFF0000FF; break;
1415          case 10: shift =  0; imask = 0xFF00FF00; break;
1416          case 11: shift =  0; imask = 0xFF00FFFF; break;
1417          case 12: shift =  0; imask = 0xFFFF0000; break;
1418          case 13: shift =  0; imask = 0xFFFF00FF; break;
1419          case 14: shift =  0; imask = 0xFFFFFF00; break;
1420          case 15: shift =  0; imask = 0xFFFFFFFF; break;
1421          }
1422 
1423          /* Select the bits that were inserted */
1424          word = binop(Iop_And32, word, mkU32(imask));
1425 
1426          /* cc == 0  --> all inserted bits zero or mask == 0   (cond == 8)
1427             cc == 1  --> leftmost inserted bit is one          (cond == 4)
1428             cc == 2  --> leftmost inserted bit is zero and not (cond == 2)
1429                          all inserted bits are zero
1430 
1431             Because cc == 0,1,2 the rightmost bit of the mask is a don't care */
1432          if (cond == 8 || cond == 8 + 1) {
1433             return unop(Iop_1Uto32, binop(Iop_CmpEQ32, word, mkU32(0)));
1434          }
1435          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
1436             return unop(Iop_1Uto32, binop(Iop_CmpNE32, word, mkU32(0)));
1437          }
1438 
1439          /* Sign extend */
1440          if (shift != 0) {
1441             word = binop(Iop_Sar32, binop(Iop_Shl32, word, mkU8(shift)),
1442                          mkU8(shift));
1443          }
1444 
1445          if (cond == 4 || cond == 4 + 1) {  /* word < 0 */
1446             return unop(Iop_1Uto32, binop(Iop_CmpLT32S, word, mkU32(0)));
1447          }
1448          if (cond == 2 || cond == 2 + 1) {  /* word > 0 */
1449             return unop(Iop_1Uto32, binop(Iop_CmpLT32S, mkU32(0), word));
1450          }
1451          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
1452             return unop(Iop_1Uto32, binop(Iop_CmpLE32S, word, mkU32(0)));
1453          }
1454          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
1455             return unop(Iop_1Uto32, binop(Iop_CmpLE32S, mkU32(0), word));
1456          }
1457          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
1458             return mkU32(1);
1459          }
1460          /* Remaining case */
1461          return mkU32(0);
1462       }
1463 
1464       /* S390_CC_OP_TEST_UNDER_MASK_8
1465          Since the mask comes from an immediate field in the opcode, we
1466          expect the mask to be a constant here. That simplifies matters. */
1467       if (cc_op == S390_CC_OP_TEST_UNDER_MASK_8) {
1468          ULong mask16;
1469 
1470          if (! isC64(cc_dep2)) goto missed;
1471 
1472          mask16 = cc_dep2->Iex.Const.con->Ico.U64;
1473 
1474          /* Get rid of the mask16 == 0 case first. Some of the simplifications
1475             below (e.g. for OVFL) only hold if mask16 == 0.  */
1476          if (mask16 == 0) {   /* cc == 0 */
1477             if (cond & 0x8) return mkU32(1);
1478             return mkU32(0);
1479          }
1480 
1481          /* cc == 2 is a don't care */
1482          if (cond == 8 || cond == 8 + 2) {
1483             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
1484                                           binop(Iop_And64, cc_dep1, cc_dep2),
1485                                           mkU64(0)));
1486          }
1487          if (cond == 7 || cond == 7 - 2) {
1488             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
1489                                           binop(Iop_And64, cc_dep1, cc_dep2),
1490                                           mkU64(0)));
1491          }
1492          if (cond == 1 || cond == 1 + 2) {
1493             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
1494                                           binop(Iop_And64, cc_dep1, cc_dep2),
1495                                           cc_dep2));
1496          }
1497          if (cond == 14 || cond == 14 - 2) {  /* ! OVFL */
1498             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
1499                                           binop(Iop_And64, cc_dep1, cc_dep2),
1500                                           cc_dep2));
1501          }
1502          goto missed;
1503       }
1504 
1505       /* S390_CC_OP_TEST_UNDER_MASK_16
1506          Since the mask comes from an immediate field in the opcode, we
1507          expect the mask to be a constant here. That simplifies matters. */
1508       if (cc_op == S390_CC_OP_TEST_UNDER_MASK_16) {
1509          ULong mask16;
1510          UInt msb;
1511 
1512          if (! isC64(cc_dep2)) goto missed;
1513 
1514          mask16 = cc_dep2->Iex.Const.con->Ico.U64;
1515 
1516          /* Get rid of the mask16 == 0 case first. Some of the simplifications
1517             below (e.g. for OVFL) only hold if mask16 == 0.  */
1518          if (mask16 == 0) {   /* cc == 0 */
1519             if (cond & 0x8) return mkU32(1);
1520             return mkU32(0);
1521          }
1522 
1523          if (cond == 8) {
1524             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
1525                                           binop(Iop_And64, cc_dep1, cc_dep2),
1526                                           mkU64(0)));
1527          }
1528          if (cond == 7) {
1529             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
1530                                           binop(Iop_And64, cc_dep1, cc_dep2),
1531                                           mkU64(0)));
1532          }
1533          if (cond == 1) {
1534             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
1535                                           binop(Iop_And64, cc_dep1, cc_dep2),
1536                                           mkU64(mask16)));
1537          }
1538          if (cond == 14) {  /* ! OVFL */
1539             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
1540                                           binop(Iop_And64, cc_dep1, cc_dep2),
1541                                           mkU64(mask16)));
1542          }
1543 
1544          /* Find MSB in mask */
1545          msb = 0x8000;
1546          while (msb > mask16)
1547             msb >>= 1;
1548 
1549          if (cond == 2) {  /* cc == 2 */
1550             IRExpr *c1, *c2;
1551 
1552             /* (cc_dep & msb) != 0 && (cc_dep & mask16) != mask16 */
1553             c1 = binop(Iop_CmpNE64,
1554                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
1555             c2 = binop(Iop_CmpNE64,
1556                        binop(Iop_And64, cc_dep1, cc_dep2),
1557                        mkU64(mask16));
1558             return binop(Iop_And32, unop(Iop_1Uto32, c1),
1559                          unop(Iop_1Uto32, c2));
1560          }
1561 
1562          if (cond == 4) {  /* cc == 1 */
1563             IRExpr *c1, *c2;
1564 
1565             /* (cc_dep & msb) == 0 && (cc_dep & mask16) != 0 */
1566             c1 = binop(Iop_CmpEQ64,
1567                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
1568             c2 = binop(Iop_CmpNE64,
1569                        binop(Iop_And64, cc_dep1, cc_dep2),
1570                        mkU64(0));
1571             return binop(Iop_And32, unop(Iop_1Uto32, c1),
1572                          unop(Iop_1Uto32, c2));
1573          }
1574 
1575          if (cond == 11) {  /* cc == 0,2,3 */
1576             IRExpr *c1, *c2;
1577 
1578             c1 = binop(Iop_CmpNE64,
1579                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
1580             c2 = binop(Iop_CmpEQ64,
1581                        binop(Iop_And64, cc_dep1, cc_dep2),
1582                        mkU64(0));
1583             return binop(Iop_Or32, unop(Iop_1Uto32, c1),
1584                          unop(Iop_1Uto32, c2));
1585          }
1586 
1587          if (cond == 3) {  /* cc == 2 || cc == 3 */
1588             return unop(Iop_1Uto32,
1589                         binop(Iop_CmpNE64,
1590                               binop(Iop_And64, cc_dep1, mkU64(msb)),
1591                               mkU64(0)));
1592          }
1593          if (cond == 12) { /* cc == 0 || cc == 1 */
1594             return unop(Iop_1Uto32,
1595                         binop(Iop_CmpEQ64,
1596                               binop(Iop_And64, cc_dep1, mkU64(msb)),
1597                               mkU64(0)));
1598          }
1599          // vex_printf("TUM mask = 0x%llx\n", mask16);
1600          goto missed;
1601       }
1602 
1603       /* S390_CC_OP_UNSIGNED_SUB_64/32 */
1604       if (cc_op == S390_CC_OP_UNSIGNED_SUB_64 ||
1605           cc_op == S390_CC_OP_UNSIGNED_SUB_32) {
1606          /*
1607             cc_dep1, cc_dep2 are the zero extended left and right operands
1608 
1609             cc == 1  --> result != 0, borrow    (cond == 4)
1610             cc == 2  --> result == 0, no borrow (cond == 2)
1611             cc == 3  --> result != 0, no borrow (cond == 1)
1612 
1613             cc = (cc_dep1 == cc_dep2) ? 2
1614                                       : (cc_dep1 > cc_dep2) ? 3 : 1;
1615 
1616             Because cc == 0 cannot occur the leftmost bit of cond is
1617             a don't care.
1618          */
1619          if (cond == 1 || cond == 1 + 8) {  /* cc == 3   op2 < op1 */
1620             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
1621          }
1622          if (cond == 2 || cond == 2 + 8) {  /* cc == 2 */
1623             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
1624          }
1625          if (cond == 4 || cond == 4 + 8) {  /* cc == 1 */
1626             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
1627          }
1628          if (cond == 3 || cond == 3 + 8) {  /* cc == 2 || cc == 3 */
1629             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
1630          }
1631          if (cond == 6 || cond == 6 + 8) {  /* cc == 2 || cc == 1 */
1632             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
1633          }
1634 
1635          if (cond == 5 || cond == 5 + 8) {  /* cc == 3 || cc == 1 */
1636             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
1637          }
1638          if (cond == 7 || cond == 7 + 8) {
1639             return mkU32(1);
1640          }
1641          /* Remaining case */
1642          return mkU32(0);
1643       }
1644 
1645       /* S390_CC_OP_UNSIGNED_ADD_64 */
1646       if (cc_op == S390_CC_OP_UNSIGNED_ADD_64) {
1647          /*
1648             cc_dep1, cc_dep2 are the zero extended left and right operands
1649 
1650             cc == 0  --> result == 0, no carry  (cond == 8)
1651             cc == 1  --> result != 0, no carry  (cond == 4)
1652             cc == 2  --> result == 0, carry     (cond == 2)
1653             cc == 3  --> result != 0, carry     (cond == 1)
1654          */
1655          if (cond == 8) { /* cc == 0 */
1656             /* Both inputs are 0 */
1657             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
1658                                           binop(Iop_Or64, cc_dep1, cc_dep2),
1659                                           mkU64(0)));
1660          }
1661          if (cond == 7) { /* cc == 1,2,3 */
1662             /* Not both inputs are 0 */
1663             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
1664                                           binop(Iop_Or64, cc_dep1, cc_dep2),
1665                                           mkU64(0)));
1666          }
1667          if (cond == 8 + 2) {  /* cc == 0,2  -> result is zero */
1668             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
1669                                           binop(Iop_Add64, cc_dep1, cc_dep2),
1670                                           mkU64(0)));
1671          }
1672          if (cond == 4 + 1) {  /* cc == 1,3  -> result is not zero */
1673             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
1674                                           binop(Iop_Add64, cc_dep1, cc_dep2),
1675                                           mkU64(0)));
1676          }
1677          goto missed;
1678       }
1679 
1680       /* S390_CC_OP_UNSIGNED_ADD_32 */
1681       if (cc_op == S390_CC_OP_UNSIGNED_ADD_32) {
1682          /*
1683             cc_dep1, cc_dep2 are the zero extended left and right operands
1684 
1685             cc == 0  --> result == 0, no carry  (cond == 8)
1686             cc == 1  --> result != 0, no carry  (cond == 4)
1687             cc == 2  --> result == 0, carry     (cond == 2)
1688             cc == 3  --> result != 0, carry     (cond == 1)
1689          */
1690          if (cond == 8) { /* cc == 0 */
1691             /* Both inputs are 0 */
1692             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
1693                                           binop(Iop_Or64, cc_dep1, cc_dep2),
1694                                           mkU64(0)));
1695          }
1696          if (cond == 7) { /* cc == 1,2,3 */
1697             /* Not both inputs are 0 */
1698             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
1699                                           binop(Iop_Or64, cc_dep1, cc_dep2),
1700                                           mkU64(0)));
1701          }
1702          if (cond == 8 + 2) {  /* cc == 0,2  -> result is zero */
1703             return unop(Iop_1Uto32, binop(Iop_CmpEQ32,
1704                                           binop(Iop_Add32,
1705                                                 unop(Iop_64to32, cc_dep1),
1706                                                 unop(Iop_64to32, cc_dep2)),
1707                                           mkU32(0)));
1708          }
1709          if (cond == 4 + 1) {  /* cc == 1,3  -> result is not zero */
1710             return unop(Iop_1Uto32, binop(Iop_CmpNE32,
1711                                           binop(Iop_Add32,
1712                                                 unop(Iop_64to32, cc_dep1),
1713                                                 unop(Iop_64to32, cc_dep2)),
1714                                           mkU32(0)));
1715          }
1716          goto missed;
1717       }
1718 
1719       /* S390_CC_OP_SET */
1720       if (cc_op == S390_CC_OP_SET) {
1721          /* cc_dep1 is the condition code
1722 
1723             Return 1, if ((cond << cc_dep1) & 0x8) != 0 */
1724 
1725         return unop(Iop_1Uto32,
1726                     binop(Iop_CmpNE64,
1727                           binop(Iop_And64,
1728                                 binop(Iop_Shl64, cond_expr,
1729                                       unop(Iop_64to8, cc_dep1)),
1730                                 mkU64(8)),
1731                           mkU64(0)));
1732       }
1733 
1734 missed:
1735       ;
1736    }
1737 
1738    return NULL;
1739 }
1740 
1741 /*---------------------------------------------------------------*/
1742 /*--- end                                guest_s390_helpers.c ---*/
1743 /*---------------------------------------------------------------*/
1744