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-2013
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_emnote.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 "main_globals.h"
42 #include "guest_generic_bb_to_IR.h"
43 #include "guest_s390_defs.h"
44 #include "s390_defs.h"               /* S390_BFP_ROUND_xyzzy */
45 
46 void
LibVEX_GuestS390X_initialise(VexGuestS390XState * state)47 LibVEX_GuestS390X_initialise(VexGuestS390XState *state)
48 {
49 /*------------------------------------------------------------*/
50 /*--- Initialise ar registers                              ---*/
51 /*------------------------------------------------------------*/
52 
53    state->guest_a0 = 0;
54    state->guest_a1 = 0;
55    state->guest_a2 = 0;
56    state->guest_a3 = 0;
57    state->guest_a4 = 0;
58    state->guest_a5 = 0;
59    state->guest_a6 = 0;
60    state->guest_a7 = 0;
61    state->guest_a8 = 0;
62    state->guest_a9 = 0;
63    state->guest_a10 = 0;
64    state->guest_a11 = 0;
65    state->guest_a12 = 0;
66    state->guest_a13 = 0;
67    state->guest_a14 = 0;
68    state->guest_a15 = 0;
69 
70 /*------------------------------------------------------------*/
71 /*--- Initialise fpr registers                             ---*/
72 /*------------------------------------------------------------*/
73 
74    state->guest_f0 = 0;
75    state->guest_f1 = 0;
76    state->guest_f2 = 0;
77    state->guest_f3 = 0;
78    state->guest_f4 = 0;
79    state->guest_f5 = 0;
80    state->guest_f6 = 0;
81    state->guest_f7 = 0;
82    state->guest_f8 = 0;
83    state->guest_f9 = 0;
84    state->guest_f10 = 0;
85    state->guest_f11 = 0;
86    state->guest_f12 = 0;
87    state->guest_f13 = 0;
88    state->guest_f14 = 0;
89    state->guest_f15 = 0;
90 
91 /*------------------------------------------------------------*/
92 /*--- Initialise gpr registers                             ---*/
93 /*------------------------------------------------------------*/
94 
95    state->guest_r0 = 0;
96    state->guest_r1 = 0;
97    state->guest_r2 = 0;
98    state->guest_r3 = 0;
99    state->guest_r4 = 0;
100    state->guest_r5 = 0;
101    state->guest_r6 = 0;
102    state->guest_r7 = 0;
103    state->guest_r8 = 0;
104    state->guest_r9 = 0;
105    state->guest_r10 = 0;
106    state->guest_r11 = 0;
107    state->guest_r12 = 0;
108    state->guest_r13 = 0;
109    state->guest_r14 = 0;
110    state->guest_r15 = 0;
111 
112 /*------------------------------------------------------------*/
113 /*--- Initialise S390 miscellaneous registers              ---*/
114 /*------------------------------------------------------------*/
115 
116    state->guest_counter = 0;
117    state->guest_fpc = 0;
118    state->guest_IA = 0;
119 
120 /*------------------------------------------------------------*/
121 /*--- Initialise S390 pseudo registers                     ---*/
122 /*------------------------------------------------------------*/
123 
124    state->guest_SYSNO = 0;
125 
126 /*------------------------------------------------------------*/
127 /*--- Initialise generic pseudo registers                  ---*/
128 /*------------------------------------------------------------*/
129 
130    state->guest_NRADDR = 0;
131    state->guest_CMSTART = 0;
132    state->guest_CMLEN = 0;
133    state->guest_IP_AT_SYSCALL = 0;
134    state->guest_EMNOTE = EmNote_NONE;
135    state->host_EvC_COUNTER = 0;
136    state->host_EvC_FAILADDR = 0;
137 
138 /*------------------------------------------------------------*/
139 /*--- Initialise thunk                                     ---*/
140 /*------------------------------------------------------------*/
141 
142    state->guest_CC_OP = 0;
143    state->guest_CC_DEP1 = 0;
144    state->guest_CC_DEP2 = 0;
145    state->guest_CC_NDEP = 0;
146 
147    __builtin_memset(state->padding, 0x0, sizeof(state->padding));
148 }
149 
150 
151 /* Figure out if any part of the guest state contained in minoff
152    .. maxoff requires precise memory exceptions.  If in doubt return
153    True (but this generates significantly slower code).  */
154 Bool
guest_s390x_state_requires_precise_mem_exns(Int minoff,Int maxoff,VexRegisterUpdates pxControl)155 guest_s390x_state_requires_precise_mem_exns (
156    Int minoff, Int maxoff, VexRegisterUpdates pxControl
157 )
158 {
159    Int lr_min = S390X_GUEST_OFFSET(guest_LR);
160    Int lr_max = lr_min + 8 - 1;
161    Int sp_min = S390X_GUEST_OFFSET(guest_SP);
162    Int sp_max = sp_min + 8 - 1;
163    Int fp_min = S390X_GUEST_OFFSET(guest_FP);
164    Int fp_max = fp_min + 8 - 1;
165    Int ia_min = S390X_GUEST_OFFSET(guest_IA);
166    Int ia_max = ia_min + 8 - 1;
167 
168    if (maxoff < sp_min || minoff > sp_max) {
169       /* No overlap with SP */
170       if (pxControl == VexRegUpdSpAtMemAccess)
171          return False; // We only need to check stack pointer.
172    } else {
173       return True;
174    }
175 
176    if (maxoff < lr_min || minoff > lr_max) {
177       /* No overlap with LR */
178    } else {
179       return True;
180    }
181 
182    if (maxoff < fp_min || minoff > fp_max) {
183       /* No overlap with FP */
184    } else {
185       return True;
186    }
187 
188    if (maxoff < ia_min || minoff > ia_max) {
189       /* No overlap with IA */
190    } else {
191       return True;
192    }
193 
194    return False;
195 }
196 
197 
198 #define ALWAYSDEFD(field)                             \
199     { S390X_GUEST_OFFSET(field),            \
200       (sizeof ((VexGuestS390XState*)0)->field) }
201 
202 VexGuestLayout s390xGuest_layout = {
203 
204    /* Total size of the guest state, in bytes. */
205    .total_sizeB = sizeof(VexGuestS390XState),
206 
207    /* Describe the stack pointer. */
208    .offset_SP = S390X_GUEST_OFFSET(guest_SP),
209    .sizeof_SP = 8,
210 
211    /* Describe the frame pointer. */
212    .offset_FP = S390X_GUEST_OFFSET(guest_FP),
213    .sizeof_FP = 8,
214 
215    /* Describe the instruction pointer. */
216    .offset_IP = S390X_GUEST_OFFSET(guest_IA),
217    .sizeof_IP = 8,
218 
219    /* Describe any sections to be regarded by Memcheck as
220       'always-defined'. */
221    .n_alwaysDefd = 9,
222 
223    /* Flags thunk: OP and NDEP are always defined, whereas DEP1
224       and DEP2 have to be tracked.  See detailed comment in
225       gdefs.h on meaning of thunk fields. */
226    .alwaysDefd = {
227       /*  0 */ ALWAYSDEFD(guest_CC_OP),     /* generic */
228       /*  1 */ ALWAYSDEFD(guest_CC_NDEP),   /* generic */
229       /*  2 */ ALWAYSDEFD(guest_EMNOTE),    /* generic */
230       /*  3 */ ALWAYSDEFD(guest_CMSTART),   /* generic */
231       /*  4 */ ALWAYSDEFD(guest_CMLEN),     /* generic */
232       /*  5 */ ALWAYSDEFD(guest_IP_AT_SYSCALL), /* generic */
233       /*  6 */ ALWAYSDEFD(guest_IA),        /* control reg */
234       /*  7 */ ALWAYSDEFD(guest_fpc),       /* control reg */
235       /*  8 */ ALWAYSDEFD(guest_counter),   /* internal usage register */
236    }
237 };
238 
239 /*------------------------------------------------------------*/
240 /*--- Dirty helper for EXecute                             ---*/
241 /*------------------------------------------------------------*/
242 void
s390x_dirtyhelper_EX(ULong torun)243 s390x_dirtyhelper_EX(ULong torun)
244 {
245    last_execute_target = torun;
246 }
247 
248 
249 /*------------------------------------------------------------*/
250 /*--- Dirty helper for Clock instructions                  ---*/
251 /*------------------------------------------------------------*/
252 #if defined(VGA_s390x)
253 ULong
s390x_dirtyhelper_STCK(ULong * addr)254 s390x_dirtyhelper_STCK(ULong *addr)
255 {
256    UInt cc;
257 
258    asm volatile("stck %0\n"
259                 "ipm %1\n"
260                 "srl %1,28\n"
261                 : "+Q" (*addr), "=d" (cc) : : "cc");
262    return cc;
263 }
264 
265 ULong
s390x_dirtyhelper_STCKE(ULong * addr)266 s390x_dirtyhelper_STCKE(ULong *addr)
267 {
268    UInt cc;
269 
270    asm volatile("stcke %0\n"
271                 "ipm %1\n"
272                 "srl %1,28\n"
273                 : "+Q" (*addr), "=d" (cc) : : "cc");
274    return cc;
275 }
276 
s390x_dirtyhelper_STCKF(ULong * addr)277 ULong s390x_dirtyhelper_STCKF(ULong *addr)
278 {
279    UInt cc;
280 
281    asm volatile(".insn s,0xb27c0000,%0\n"
282                 "ipm %1\n"
283                 "srl %1,28\n"
284                 : "+Q" (*addr), "=d" (cc) : : "cc");
285    return cc;
286 }
287 #else
s390x_dirtyhelper_STCK(ULong * addr)288 ULong s390x_dirtyhelper_STCK(ULong *addr)  {return 3;}
s390x_dirtyhelper_STCKF(ULong * addr)289 ULong s390x_dirtyhelper_STCKF(ULong *addr) {return 3;}
s390x_dirtyhelper_STCKE(ULong * addr)290 ULong s390x_dirtyhelper_STCKE(ULong *addr) {return 3;}
291 #endif /* VGA_s390x */
292 
293 /*------------------------------------------------------------*/
294 /*--- Dirty helper for Store Facility instruction          ---*/
295 /*------------------------------------------------------------*/
296 #if defined(VGA_s390x)
297 static void
s390_set_facility_bit(ULong * addr,UInt bitno,UInt value)298 s390_set_facility_bit(ULong *addr, UInt bitno, UInt value)
299 {
300    addr  += bitno / 64;
301    bitno  = bitno % 64;
302 
303    ULong mask = 1;
304    mask <<= (63 - bitno);
305 
306    if (value == 1) {
307       *addr |= mask;   // set
308    } else {
309       *addr &= ~mask;  // clear
310    }
311 }
312 
313 ULong
s390x_dirtyhelper_STFLE(VexGuestS390XState * guest_state,ULong * addr)314 s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr)
315 {
316    ULong hoststfle[S390_NUM_FACILITY_DW], cc, num_dw, i;
317    register ULong reg0 asm("0") = guest_state->guest_r0 & 0xF;  /* r0[56:63] */
318 
319    /* We cannot store more than S390_NUM_FACILITY_DW
320       (and it makes not much sense to do so anyhow) */
321    if (reg0 > S390_NUM_FACILITY_DW - 1)
322       reg0 = S390_NUM_FACILITY_DW - 1;
323 
324    num_dw = reg0 + 1;  /* number of double words written */
325 
326    asm volatile(" .insn s,0xb2b00000,%0\n"   /* stfle */
327                 "ipm    %2\n"
328                 "srl    %2,28\n"
329                 : "=m" (hoststfle), "+d"(reg0), "=d"(cc) : : "cc", "memory");
330 
331    /* Update guest register 0  with what STFLE set r0 to */
332    guest_state->guest_r0 = reg0;
333 
334    /* Set default: VM facilities = host facilities */
335    for (i = 0; i < num_dw; ++i)
336       addr[i] = hoststfle[i];
337 
338    /* Now adjust the VM facilities according to what the VM supports */
339    s390_set_facility_bit(addr, S390_FAC_LDISP,  1);
340    s390_set_facility_bit(addr, S390_FAC_EIMM,   1);
341    s390_set_facility_bit(addr, S390_FAC_ETF2,   1);
342    s390_set_facility_bit(addr, S390_FAC_ETF3,   1);
343    s390_set_facility_bit(addr, S390_FAC_GIE,    1);
344    s390_set_facility_bit(addr, S390_FAC_EXEXT,  1);
345    s390_set_facility_bit(addr, S390_FAC_HIGHW,  1);
346 
347    s390_set_facility_bit(addr, S390_FAC_HFPMAS, 0);
348    s390_set_facility_bit(addr, S390_FAC_HFPUNX, 0);
349    s390_set_facility_bit(addr, S390_FAC_XCPUT,  0);
350    s390_set_facility_bit(addr, S390_FAC_MSA,    0);
351    s390_set_facility_bit(addr, S390_FAC_PENH,   0);
352    s390_set_facility_bit(addr, S390_FAC_DFP,    0);
353    s390_set_facility_bit(addr, S390_FAC_PFPO,   0);
354    s390_set_facility_bit(addr, S390_FAC_DFPZC,  0);
355    s390_set_facility_bit(addr, S390_FAC_MISC,   0);
356    s390_set_facility_bit(addr, S390_FAC_CTREXE, 0);
357    s390_set_facility_bit(addr, S390_FAC_TREXE,  0);
358    s390_set_facility_bit(addr, S390_FAC_MSA4,   0);
359 
360    return cc;
361 }
362 
363 #else
364 
365 ULong
s390x_dirtyhelper_STFLE(VexGuestS390XState * guest_state,ULong * addr)366 s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr)
367 {
368    return 3;
369 }
370 #endif /* VGA_s390x */
371 
372 /*------------------------------------------------------------*/
373 /*--- Dirty helper for the "convert unicode" insn family.  ---*/
374 /*------------------------------------------------------------*/
375 void
s390x_dirtyhelper_CUxy(UChar * address,ULong data,ULong num_bytes)376 s390x_dirtyhelper_CUxy(UChar *address, ULong data, ULong num_bytes)
377 {
378    UInt i;
379 
380    vassert(num_bytes >= 1 && num_bytes <= 4);
381 
382    /* Store the least significant NUM_BYTES bytes in DATA left to right
383       at ADDRESS. */
384    for (i = 1; i <= num_bytes; ++i) {
385       address[num_bytes - i] = data & 0xff;
386       data >>= 8;
387    }
388 }
389 
390 
391 /*------------------------------------------------------------*/
392 /*--- Clean helper for CU21.                               ---*/
393 /*------------------------------------------------------------*/
394 
395 /* The function performs a CU21 operation. It returns three things
396    encoded in an ULong value:
397    - the converted bytes (at most 4)
398    - the number of converted bytes
399    - an indication whether LOW_SURROGATE, if any, is invalid
400 
401    64      48                16           8                       0
402     +-------+-----------------+-----------+-----------------------+
403     |  0x0  | converted bytes | num_bytes | invalid_low_surrogate |
404     +-------+-----------------+-----------+-----------------------+
405 */
406 ULong
s390_do_cu21(UInt srcval,UInt low_surrogate)407 s390_do_cu21(UInt srcval, UInt low_surrogate)
408 {
409    ULong retval = 0;   // shut up gcc
410    UInt b1, b2, b3, b4, num_bytes, invalid_low_surrogate = 0;
411 
412    srcval &= 0xffff;
413 
414    /* Determine the number of bytes in the converted value */
415    if (srcval <= 0x007f)
416       num_bytes = 1;
417    else if (srcval >= 0x0080 && srcval <= 0x07ff)
418       num_bytes = 2;
419    else if ((srcval >= 0x0800 && srcval <= 0xd7ff) ||
420             (srcval >= 0xdc00 && srcval <= 0xffff))
421       num_bytes = 3;
422    else
423       num_bytes = 4;
424 
425    /* Determine UTF-8 bytes according to calculated num_bytes */
426    switch (num_bytes){
427    case 1:
428       retval = srcval;
429       break;
430 
431    case 2:
432       /* order of bytes left to right: b1, b2 */
433       b1  = 0xc0;
434       b1 |= srcval >> 6;
435 
436       b2  = 0x80;
437       b2 |= srcval & 0x3f;
438 
439       retval = (b1 << 8) | b2;
440       break;
441 
442    case 3:
443       /* order of bytes left to right: b1, b2, b3 */
444       b1  = 0xe0;
445       b1 |= srcval >> 12;
446 
447       b2  = 0x80;
448       b2 |= (srcval >> 6) & 0x3f;
449 
450       b3  = 0x80;
451       b3 |= srcval & 0x3f;
452 
453       retval = (b1 << 16) | (b2 << 8) | b3;
454       break;
455 
456    case 4: {
457       /* order of bytes left to right: b1, b2, b3, b4 */
458       UInt high_surrogate = srcval;
459       UInt uvwxy = ((high_surrogate >> 6) & 0xf) + 1;   // abcd + 1
460 
461       b1  = 0xf0;
462       b1 |= uvwxy >> 2;     // uvw
463 
464       b2  = 0x80;
465       b2 |= (uvwxy & 0x3) << 4;           // xy
466       b2 |= (high_surrogate >> 2) & 0xf;  // efgh
467 
468       b3  = 0x80;
469       b3 |= (high_surrogate & 0x3) << 4;   // ij
470       b3 |= (low_surrogate >> 6) & 0xf;    // klmn
471 
472       b4  = 0x80;
473       b4 |= low_surrogate & 0x3f;
474 
475       retval = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
476 
477       invalid_low_surrogate = (low_surrogate & 0xfc00) != 0xdc00;
478       break;
479    }
480    }
481 
482    /* At this point RETVAL contains the converted bytes.
483       Build up the final return value. */
484    return (retval << 16) | (num_bytes << 8) | invalid_low_surrogate;
485 }
486 
487 
488 /*------------------------------------------------------------*/
489 /*--- Clean helper for CU24.                               ---*/
490 /*------------------------------------------------------------*/
491 
492 /* The function performs a CU24 operation. It returns two things
493    encoded in an ULong value:
494    - the 4 converted bytes
495    - an indication whether LOW_SURROGATE, if any, is invalid
496 
497    64     40                 8                       0
498     +------------------------+-----------------------+
499     |  0x0 | converted bytes | invalid_low_surrogate |
500     +------------------------+-----------------------+
501 */
502 ULong
s390_do_cu24(UInt srcval,UInt low_surrogate)503 s390_do_cu24(UInt srcval, UInt low_surrogate)
504 {
505    ULong retval;
506    UInt invalid_low_surrogate = 0;
507 
508    srcval &= 0xffff;
509 
510    if ((srcval >= 0x0000 && srcval <= 0xd7ff) ||
511        (srcval >= 0xdc00 && srcval <= 0xffff)) {
512       retval = srcval;
513    } else {
514       /* D800 - DBFF */
515       UInt high_surrogate = srcval;
516       UInt uvwxy  = ((high_surrogate >> 6) & 0xf) + 1;   // abcd + 1
517       UInt efghij = high_surrogate & 0x3f;
518       UInt klmnoprst = low_surrogate & 0x3ff;
519 
520       retval = (uvwxy << 16) | (efghij << 10) | klmnoprst;
521 
522       invalid_low_surrogate = (low_surrogate & 0xfc00) != 0xdc00;
523    }
524 
525    /* At this point RETVAL contains the converted bytes.
526       Build up the final return value. */
527    return (retval << 8) | invalid_low_surrogate;
528 }
529 
530 
531 /*------------------------------------------------------------*/
532 /*--- Clean helper for CU42.                               ---*/
533 /*------------------------------------------------------------*/
534 
535 /* The function performs a CU42 operation. It returns three things
536    encoded in an ULong value:
537    - the converted bytes (at most 4)
538    - the number of converted bytes (2 or 4; 0 if invalid character)
539    - an indication whether the UTF-32 character is invalid
540 
541    64      48                16           8                   0
542     +-------+-----------------+-----------+-------------------+
543     |  0x0  | converted bytes | num_bytes | invalid_character |
544     +-------+-----------------+-----------+-------------------+
545 */
546 ULong
s390_do_cu42(UInt srcval)547 s390_do_cu42(UInt srcval)
548 {
549    ULong retval;
550    UInt num_bytes, invalid_character = 0;
551 
552    if ((srcval >= 0x0000 && srcval <= 0xd7ff) ||
553        (srcval >= 0xdc00 && srcval <= 0xffff)) {
554       retval = srcval;
555       num_bytes = 2;
556    } else if (srcval >= 0x00010000 && srcval <= 0x0010FFFF) {
557       UInt uvwxy  = srcval >> 16;
558       UInt abcd   = (uvwxy - 1) & 0xf;
559       UInt efghij = (srcval >> 10) & 0x3f;
560 
561       UInt high_surrogate = (0xd8 << 8) | (abcd << 6) | efghij;
562       UInt low_surrogate  = (0xdc << 8) | (srcval & 0x3ff);
563 
564       retval = (high_surrogate << 16) | low_surrogate;
565       num_bytes = 4;
566    } else {
567       /* D800 - DBFF or 00110000 - FFFFFFFF */
568       invalid_character = 1;
569       retval = num_bytes = 0;   /* does not matter; not used */
570    }
571 
572    /* At this point RETVAL contains the converted bytes.
573       Build up the final return value. */
574    return (retval << 16) | (num_bytes << 8) | invalid_character;
575 }
576 
577 
578 /*------------------------------------------------------------*/
579 /*--- Clean helper for CU41.                               ---*/
580 /*------------------------------------------------------------*/
581 
582 /* The function performs a CU41 operation. It returns three things
583    encoded in an ULong value:
584    - the converted bytes (at most 4)
585    - the number of converted bytes (1, 2, 3, or 4; 0 if invalid character)
586    - an indication whether the UTF-32 character is invalid
587 
588    64      48                16           8                   0
589     +-------+-----------------+-----------+-------------------+
590     |  0x0  | converted bytes | num_bytes | invalid_character |
591     +-------+-----------------+-----------+-------------------+
592 */
593 ULong
s390_do_cu41(UInt srcval)594 s390_do_cu41(UInt srcval)
595 {
596    ULong retval;
597    UInt num_bytes, invalid_character = 0;
598 
599    if (srcval <= 0x7f) {
600       retval = srcval;
601       num_bytes = 1;
602    } else if (srcval >= 0x80 && srcval <= 0x7ff) {
603       UInt fghij  = srcval >> 6;
604       UInt klmnop = srcval & 0x3f;
605       UInt byte1  = (0xc0 | fghij);
606       UInt byte2  = (0x80 | klmnop);
607 
608       retval = (byte1 << 8) | byte2;
609       num_bytes = 2;
610    } else if ((srcval >= 0x800  && srcval <= 0xd7ff) ||
611               (srcval >= 0xdc00 && srcval <= 0xffff)) {
612       UInt abcd   = srcval >> 12;
613       UInt efghij = (srcval >> 6) & 0x3f;
614       UInt klmnop = srcval & 0x3f;
615       UInt byte1  = 0xe0 | abcd;
616       UInt byte2  = 0x80 | efghij;
617       UInt byte3  = 0x80 | klmnop;
618 
619       retval = (byte1 << 16) | (byte2 << 8) | byte3;
620       num_bytes = 3;
621    } else if (srcval >= 0x10000 && srcval <= 0x10ffff) {
622       UInt uvw    = (srcval >> 18) & 0x7;
623       UInt xy     = (srcval >> 16) & 0x3;
624       UInt efgh   = (srcval >> 12) & 0xf;
625       UInt ijklmn = (srcval >>  6) & 0x3f;
626       UInt opqrst = srcval & 0x3f;
627       UInt byte1  = 0xf0 | uvw;
628       UInt byte2  = 0x80 | (xy << 4) | efgh;
629       UInt byte3  = 0x80 | ijklmn;
630       UInt byte4  = 0x80 | opqrst;
631 
632       retval = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
633       num_bytes = 4;
634    } else {
635       /* d800 ... dbff or 00110000 ... ffffffff */
636       invalid_character = 1;
637 
638       retval = 0;
639       num_bytes = 0;
640    }
641 
642    /* At this point RETVAL contains the converted bytes.
643       Build up the final return value. */
644    return (retval << 16) | (num_bytes << 8) | invalid_character;
645 }
646 
647 
648 /*------------------------------------------------------------*/
649 /*--- Clean helpers for CU12.                              ---*/
650 /*------------------------------------------------------------*/
651 
652 /* The function looks at the first byte of an UTF-8 character and returns
653    two things encoded in an ULong value:
654 
655    - the number of bytes that need to be read
656    - an indication whether the UTF-8 character is invalid
657 
658    64      16           8                   0
659     +-------------------+-------------------+
660     |  0x0  | num_bytes | invalid_character |
661     +-------+-----------+-------------------+
662 */
663 ULong
s390_do_cu12_cu14_helper1(UInt byte,UInt etf3_and_m3_is_1)664 s390_do_cu12_cu14_helper1(UInt byte, UInt etf3_and_m3_is_1)
665 {
666    vassert(byte <= 0xff);
667 
668    /* Check whether the character is invalid */
669    if (byte >= 0x80 && byte <= 0xbf) return 1;
670    if (byte >= 0xf8) return 1;
671 
672    if (etf3_and_m3_is_1) {
673       if (byte == 0xc0 || byte == 0xc1) return 1;
674       if (byte >= 0xf5 && byte <= 0xf7) return 1;
675    }
676 
677    /* Character is valid */
678    if (byte <= 0x7f) return 1 << 8;   // 1 byte
679    if (byte <= 0xdf) return 2 << 8;   // 2 bytes
680    if (byte <= 0xef) return 3 << 8;   // 3 bytes
681 
682    return 4 << 8;  // 4 bytes
683 }
684 
685 /* The function performs a CU12 or CU14 operation. BYTE1, BYTE2, etc are the
686    bytes as read from the input stream, left to right. BYTE1 is a valid
687    byte. The function returns three things encoded in an ULong value:
688 
689    - the converted bytes
690    - the number of converted bytes (2 or 4; 0 if invalid character)
691    - an indication whether the UTF-16 character is invalid
692 
693    64      48                16           8                   0
694     +-------+-----------------+-----------+-------------------+
695     |  0x0  | converted bytes | num_bytes | invalid_character |
696     +-------+-----------------+-----------+-------------------+
697 */
698 static ULong
s390_do_cu12_cu14_helper2(UInt byte1,UInt byte2,UInt byte3,UInt byte4,ULong stuff,Bool is_cu12)699 s390_do_cu12_cu14_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4,
700                           ULong stuff, Bool is_cu12)
701 {
702    UInt num_src_bytes = stuff >> 1, etf3_and_m3_is_1 = stuff & 0x1;
703    UInt num_bytes = 0, invalid_character = 0;
704    ULong retval = 0;
705 
706    vassert(num_src_bytes <= 4);
707 
708    switch (num_src_bytes) {
709    case 1:
710       num_bytes = 2;
711       retval = byte1;
712       break;
713 
714    case 2: {
715       /* Test validity */
716       if (etf3_and_m3_is_1) {
717          if (byte2 < 0x80 || byte2 > 0xbf) {
718             invalid_character = 1;
719             break;
720          }
721       }
722 
723       /* OK */
724       UInt fghij  = byte1 & 0x1f;
725       UInt klmnop = byte2 & 0x3f;
726 
727       num_bytes = 2;
728       retval = (fghij << 6) | klmnop;
729       break;
730    }
731 
732    case 3: {
733       /* Test validity */
734       if (etf3_and_m3_is_1) {
735          if (byte1 == 0xe0) {
736             if ((byte2 < 0xa0 || byte2 > 0xbf) ||
737                 (byte3 < 0x80 || byte3 > 0xbf)) {
738                invalid_character = 1;
739                break;
740             }
741          }
742          if ((byte1 >= 0xe1 && byte1 <= 0xec) ||
743              byte1 == 0xee || byte1 == 0xef) {
744             if ((byte2 < 0x80 || byte2 > 0xbf) ||
745                 (byte3 < 0x80 || byte3 > 0xbf)) {
746                invalid_character = 1;
747                break;
748             }
749          }
750          if (byte1 == 0xed) {
751             if ((byte2 < 0x80 || byte2 > 0x9f) ||
752                 (byte3 < 0x80 || byte3 > 0xbf)) {
753                invalid_character = 1;
754                break;
755             }
756          }
757       }
758 
759       /* OK */
760       UInt abcd   = byte1 & 0xf;
761       UInt efghij = byte2 & 0x3f;
762       UInt klmnop = byte3 & 0x3f;
763 
764       num_bytes = 2;
765       retval = (abcd << 12) | (efghij << 6) | klmnop;
766       break;
767    }
768 
769    case 4: {
770       /* Test validity */
771       if (etf3_and_m3_is_1) {
772          if (byte1 == 0xf0) {
773             if ((byte2 < 0x90 || byte2 > 0xbf) ||
774                 (byte3 < 0x80 || byte3 > 0xbf) ||
775                 (byte4 < 0x80 || byte4 > 0xbf)) {
776                invalid_character = 1;
777                break;
778             }
779          }
780          if (byte1 == 0xf1 || byte1 == 0xf2 || byte1 == 0xf3) {
781             if ((byte2 < 0x80 || byte2 > 0xbf) ||
782                 (byte3 < 0x80 || byte3 > 0xbf) ||
783                 (byte4 < 0x80 || byte4 > 0xbf)) {
784                invalid_character = 1;
785                break;
786             }
787          }
788          if (byte1 == 0xf4) {
789             if ((byte2 < 0x80 || byte2 > 0x8f) ||
790                 (byte3 < 0x80 || byte3 > 0xbf) ||
791                 (byte4 < 0x80 || byte4 > 0xbf)) {
792                invalid_character = 1;
793                break;
794             }
795          }
796       }
797 
798       /* OK */
799       UInt uvw    = byte1 & 0x7;
800       UInt xy     = (byte2 >> 4) & 0x3;
801       UInt uvwxy  = (uvw << 2) | xy;
802       UInt efgh   = byte2 & 0xf;
803       UInt ij     = (byte3 >> 4) & 0x3;
804       UInt klmn   = byte3 & 0xf;
805       UInt opqrst = byte4 & 0x3f;
806 
807       if (is_cu12) {
808          UInt abcd = (uvwxy - 1) & 0xf;
809          UInt high_surrogate = (0xd8 << 8) | (abcd << 6) | (efgh << 2) | ij;
810          UInt low_surrogate  = (0xdc << 8) | (klmn << 6) | opqrst;
811 
812          num_bytes = 4;
813          retval = (high_surrogate << 16) | low_surrogate;
814       } else {
815          num_bytes = 4;
816          retval =
817             (uvwxy << 16) | (efgh << 12) | (ij << 10) | (klmn << 6) | opqrst;
818       }
819       break;
820    }
821    }
822 
823    if (! is_cu12) num_bytes = 4;   // for CU14, by definition
824 
825    /* At this point RETVAL contains the converted bytes.
826       Build up the final return value. */
827    return (retval << 16) | (num_bytes << 8) | invalid_character;
828 }
829 
830 ULong
s390_do_cu12_helper2(UInt byte1,UInt byte2,UInt byte3,UInt byte4,ULong stuff)831 s390_do_cu12_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4,
832                      ULong stuff)
833 {
834    return s390_do_cu12_cu14_helper2(byte1, byte2, byte3, byte4, stuff,
835                                     /* is_cu12 = */ 1);
836 }
837 
838 ULong
s390_do_cu14_helper2(UInt byte1,UInt byte2,UInt byte3,UInt byte4,ULong stuff)839 s390_do_cu14_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4,
840                      ULong stuff)
841 {
842    return s390_do_cu12_cu14_helper2(byte1, byte2, byte3, byte4, stuff,
843                                     /* is_cu12 = */ 0);
844 }
845 
846 
847 /*------------------------------------------------------------*/
848 /*--- Clean helper for "convert to binary".                ---*/
849 /*------------------------------------------------------------*/
850 #if defined(VGA_s390x)
851 UInt
s390_do_cvb(ULong decimal)852 s390_do_cvb(ULong decimal)
853 {
854    UInt binary;
855 
856    __asm__ volatile (
857         "cvb %[result],%[input]\n\t"
858           : [result] "=d"(binary)
859           : [input] "m"(decimal)
860    );
861 
862    return binary;
863 }
864 
865 #else
s390_do_cvb(ULong decimal)866 UInt s390_do_cvb(ULong decimal) { return 0; }
867 #endif
868 
869 
870 /*------------------------------------------------------------*/
871 /*--- Clean helper for "convert to decimal".                ---*/
872 /*------------------------------------------------------------*/
873 #if defined(VGA_s390x)
874 ULong
s390_do_cvd(ULong binary_in)875 s390_do_cvd(ULong binary_in)
876 {
877    UInt binary = binary_in & 0xffffffffULL;
878    ULong decimal;
879 
880    __asm__ volatile (
881         "cvd %[input],%[result]\n\t"
882           : [result] "=m"(decimal)
883           : [input] "d"(binary)
884    );
885 
886    return decimal;
887 }
888 
889 #else
s390_do_cvd(ULong binary)890 ULong s390_do_cvd(ULong binary) { return 0; }
891 #endif
892 
893 /*------------------------------------------------------------*/
894 /*--- Clean helper for "Extract cache attribute".          ---*/
895 /*------------------------------------------------------------*/
896 #if defined(VGA_s390x)
897 ULong
s390_do_ecag(ULong op2addr)898 s390_do_ecag(ULong op2addr)
899 {
900    ULong result;
901 
902    __asm__ volatile(".insn rsy,0xEB000000004C,%[out],0,0(%[in])\n\t"
903                     : [out] "=d"(result)
904                     : [in] "d"(op2addr));
905    return result;
906 }
907 
908 #else
s390_do_ecag(ULong op2addr)909 ULong s390_do_ecag(ULong op2addr) { return 0; }
910 #endif
911 
912 /*------------------------------------------------------------*/
913 /*--- Clean helper for "Perform Floating Point Operation". ---*/
914 /*------------------------------------------------------------*/
915 #if defined(VGA_s390x)
916 UInt
s390_do_pfpo(UInt gpr0)917 s390_do_pfpo(UInt gpr0)
918 {
919    UChar rm;
920    UChar op1_ty, op2_ty;
921 
922    rm  = gpr0 & 0xf;
923    if (rm > 1 && rm < 8)
924       return EmFail_S390X_invalid_PFPO_rounding_mode;
925 
926    op1_ty = (gpr0 >> 16) & 0xff; // gpr0[40:47]
927    op2_ty = (gpr0 >> 8)  & 0xff; // gpr0[48:55]
928    /* Operand type must be BFP 32, 64, 128 or DFP 32, 64, 128
929       which correspond to 0x5, 0x6, 0x7, 0x8, 0x9, 0xa respectively.
930       Any other operand type value is unsupported */
931    if ((op1_ty == op2_ty) ||
932        (op1_ty < 0x5 || op1_ty > 0xa) ||
933        (op2_ty < 0x5 || op2_ty > 0xa))
934       return EmFail_S390X_invalid_PFPO_function;
935 
936    return EmNote_NONE;
937 }
938 #else
s390_do_pfpo(UInt gpr0)939 UInt s390_do_pfpo(UInt gpr0) { return 0; }
940 #endif
941 
942 /*------------------------------------------------------------*/
943 /*--- Helper for condition code.                           ---*/
944 /*------------------------------------------------------------*/
945 
946 /* Convert an IRRoundingMode value to s390_bfp_round_t */
947 #if defined(VGA_s390x)
948 static s390_bfp_round_t
decode_bfp_rounding_mode(UInt irrm)949 decode_bfp_rounding_mode(UInt irrm)
950 {
951    switch (irrm) {
952    case Irrm_NEAREST: return S390_BFP_ROUND_NEAREST_EVEN;
953    case Irrm_NegINF:  return S390_BFP_ROUND_NEGINF;
954    case Irrm_PosINF:  return S390_BFP_ROUND_POSINF;
955    case Irrm_ZERO:    return S390_BFP_ROUND_ZERO;
956    }
957    vpanic("decode_bfp_rounding_mode");
958 }
959 #endif
960 
961 
962 #define S390_CC_FOR_BINARY(opcode,cc_dep1,cc_dep2) \
963 ({ \
964    __asm__ volatile ( \
965         opcode " %[op1],%[op2]\n\t" \
966         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+d"(cc_dep1) \
967                                    : [op2] "d"(cc_dep2) \
968                                    : "cc");\
969    psw >> 28;   /* cc */ \
970 })
971 
972 #define S390_CC_FOR_TERNARY_SUBB(opcode,cc_dep1,cc_dep2,cc_ndep) \
973 ({ \
974    /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
975       for rationale. */ \
976    cc_dep2 = cc_dep2 ^ cc_ndep; \
977    __asm__ volatile ( \
978 	"lghi 0,1\n\t" \
979 	"sr 0,%[op3]\n\t" /* borrow to cc */ \
980         opcode " %[op1],%[op2]\n\t" /* then redo the op */\
981         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \
982                                    : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
983                                    : "0", "cc");\
984    psw >> 28;   /* cc */ \
985 })
986 
987 #define S390_CC_FOR_TERNARY_ADDC(opcode,cc_dep1,cc_dep2,cc_ndep) \
988 ({ \
989    /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
990       for rationale. */ \
991    cc_dep2 = cc_dep2 ^ cc_ndep; \
992    __asm__ volatile ( \
993 	"lgfr 0,%[op3]\n\t" /* first load cc_ndep */ \
994 	"aghi 0,0\n\t" /* and convert it into a cc */ \
995         opcode " %[op1],%[op2]\n\t" /* then redo the op */\
996         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \
997                                    : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
998                                    : "0", "cc");\
999    psw >> 28;   /* cc */ \
1000 })
1001 
1002 
1003 #define S390_CC_FOR_BFP_RESULT(opcode,cc_dep1) \
1004 ({ \
1005    __asm__ volatile ( \
1006         opcode " 0,%[op]\n\t" \
1007         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
1008                                    : [op]  "f"(cc_dep1) \
1009                                    : "cc", "f0");\
1010    psw >> 28;   /* cc */ \
1011 })
1012 
1013 #define S390_CC_FOR_BFP128_RESULT(hi,lo) \
1014 ({ \
1015    __asm__ volatile ( \
1016         "ldr   4,%[high]\n\t" \
1017         "ldr   6,%[low]\n\t" \
1018         "ltxbr 0,4\n\t" \
1019         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
1020                                    : [high] "f"(hi), [low] "f"(lo) \
1021                                    : "cc", "f0", "f2", "f4", "f6");\
1022    psw >> 28;   /* cc */ \
1023 })
1024 
1025 #define S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,rounding_mode) \
1026 ({ \
1027    __asm__ volatile ( \
1028         opcode " 0," #rounding_mode ",%[op]\n\t" \
1029         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
1030                                    : [op]  "f"(cc_dep1) \
1031                                    : "cc", "r0");\
1032    psw >> 28;   /* cc */ \
1033 })
1034 
1035 #define S390_CC_FOR_BFP_CONVERT(opcode,cc_dep1,cc_dep2)   \
1036 ({                                                        \
1037    UInt cc;                                               \
1038    switch (decode_bfp_rounding_mode(cc_dep2)) {           \
1039    case S390_BFP_ROUND_NEAREST_EVEN:                      \
1040       cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,4); \
1041       break;                                              \
1042    case S390_BFP_ROUND_ZERO:                              \
1043       cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,5); \
1044       break;                                              \
1045    case S390_BFP_ROUND_POSINF:                            \
1046       cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,6); \
1047       break;                                              \
1048    case S390_BFP_ROUND_NEGINF:                            \
1049       cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,7); \
1050       break;                                              \
1051    default:                                               \
1052       vpanic("unexpected bfp rounding mode");             \
1053    }                                                      \
1054    cc;                                                    \
1055 })
1056 
1057 #define S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,rounding_mode) \
1058 ({ \
1059    __asm__ volatile ( \
1060         opcode ",0,%[op]," #rounding_mode ",0\n\t" \
1061         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
1062                                    : [op]  "f"(cc_dep1) \
1063                                    : "cc", "r0");\
1064    psw >> 28;   /* cc */ \
1065 })
1066 
1067 #define S390_CC_FOR_BFP_UCONVERT(opcode,cc_dep1,cc_dep2)   \
1068 ({                                                         \
1069    UInt cc;                                                \
1070    switch (decode_bfp_rounding_mode(cc_dep2)) {            \
1071    case S390_BFP_ROUND_NEAREST_EVEN:                       \
1072       cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,4); \
1073       break;                                               \
1074    case S390_BFP_ROUND_ZERO:                               \
1075       cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,5); \
1076       break;                                               \
1077    case S390_BFP_ROUND_POSINF:                             \
1078       cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,6); \
1079       break;                                               \
1080    case S390_BFP_ROUND_NEGINF:                             \
1081       cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,7); \
1082       break;                                               \
1083    default:                                                \
1084       vpanic("unexpected bfp rounding mode");              \
1085    }                                                       \
1086    cc;                                                     \
1087 })
1088 
1089 #define S390_CC_FOR_BFP128_CONVERT_AUX(opcode,hi,lo,rounding_mode) \
1090 ({ \
1091    __asm__ volatile ( \
1092         "ldr   4,%[high]\n\t" \
1093         "ldr   6,%[low]\n\t" \
1094         opcode " 0," #rounding_mode ",4\n\t" \
1095         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
1096                                    : [high] "f"(hi), [low] "f"(lo) \
1097                                    : "cc", "r0", "f4", "f6");\
1098    psw >> 28;   /* cc */ \
1099 })
1100 
1101 #define S390_CC_FOR_BFP128_CONVERT(opcode,cc_dep1,cc_dep2,cc_ndep)   \
1102 ({                                                                   \
1103    UInt cc;                                                          \
1104    /* Recover the original DEP2 value. See comment near              \
1105       s390_cc_thunk_put3 for rationale. */                           \
1106    cc_dep2 = cc_dep2 ^ cc_ndep;                                      \
1107    switch (decode_bfp_rounding_mode(cc_ndep)) {                      \
1108    case S390_BFP_ROUND_NEAREST_EVEN:                                 \
1109       cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,4); \
1110       break;                                                         \
1111    case S390_BFP_ROUND_ZERO:                                         \
1112       cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,5); \
1113       break;                                                         \
1114    case S390_BFP_ROUND_POSINF:                                       \
1115       cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,6); \
1116       break;                                                         \
1117    case S390_BFP_ROUND_NEGINF:                                       \
1118       cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,7); \
1119       break;                                                         \
1120    default:                                                          \
1121       vpanic("unexpected bfp rounding mode");                        \
1122    }                                                                 \
1123    cc;                                                               \
1124 })
1125 
1126 #define S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,hi,lo,rounding_mode) \
1127 ({ \
1128    __asm__ volatile ( \
1129         "ldr   4,%[high]\n\t" \
1130         "ldr   6,%[low]\n\t" \
1131         opcode ",0,4," #rounding_mode ",0\n\t" \
1132         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
1133                                    : [high] "f"(hi), [low] "f"(lo) \
1134                                    : "cc", "r0", "f4", "f6");\
1135    psw >> 28;   /* cc */ \
1136 })
1137 
1138 #define S390_CC_FOR_BFP128_UCONVERT(opcode,cc_dep1,cc_dep2,cc_ndep)   \
1139 ({                                                                    \
1140    UInt cc;                                                           \
1141    /* Recover the original DEP2 value. See comment near               \
1142       s390_cc_thunk_put3 for rationale. */                            \
1143    cc_dep2 = cc_dep2 ^ cc_ndep;                                       \
1144    switch (decode_bfp_rounding_mode(cc_ndep)) {                       \
1145    case S390_BFP_ROUND_NEAREST_EVEN:                                  \
1146       cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,4); \
1147       break;                                                          \
1148    case S390_BFP_ROUND_ZERO:                                          \
1149       cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,5); \
1150       break;                                                          \
1151    case S390_BFP_ROUND_POSINF:                                        \
1152       cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,6); \
1153       break;                                                          \
1154    case S390_BFP_ROUND_NEGINF:                                        \
1155       cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,7); \
1156       break;                                                          \
1157    default:                                                           \
1158       vpanic("unexpected bfp rounding mode");                         \
1159    }                                                                  \
1160    cc;                                                                \
1161 })
1162 
1163 #define S390_CC_FOR_BFP_TDC(opcode,cc_dep1,cc_dep2) \
1164 ({ \
1165    __asm__ volatile ( \
1166         opcode " %[value],0(%[class])\n\t" \
1167         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
1168                                    : [value] "f"(cc_dep1), \
1169                                      [class] "a"(cc_dep2)  \
1170                                    : "cc");\
1171    psw >> 28;   /* cc */ \
1172 })
1173 
1174 #define S390_CC_FOR_BFP128_TDC(cc_dep1,cc_dep2,cc_ndep) \
1175 ({ \
1176    /* Recover the original DEP2 value. See comment near \
1177       s390_cc_thunk_put1f128Z for rationale. */ \
1178    cc_dep2 = cc_dep2 ^ cc_ndep; \
1179    __asm__ volatile ( \
1180         "ldr  4,%[high]\n\t" \
1181         "ldr  6,%[low]\n\t" \
1182         "tcxb 4,0(%[class])\n\t" \
1183         "ipm  %[psw]\n\t"          : [psw] "=d"(psw) \
1184                                    : [high] "f"(cc_dep1), [low] "f"(cc_dep2), \
1185                                      [class] "a"(cc_ndep)  \
1186                                    : "cc", "f4", "f6");\
1187    psw >> 28;   /* cc */ \
1188 })
1189 
1190 /* Convert an IRRoundingMode value to s390_dfp_round_t */
1191 #if defined(VGA_s390x)
1192 static s390_dfp_round_t
decode_dfp_rounding_mode(UInt irrm)1193 decode_dfp_rounding_mode(UInt irrm)
1194 {
1195    switch (irrm) {
1196    case Irrm_NEAREST:
1197       return S390_DFP_ROUND_NEAREST_EVEN_4;
1198    case Irrm_NegINF:
1199       return S390_DFP_ROUND_NEGINF_7;
1200    case Irrm_PosINF:
1201       return S390_DFP_ROUND_POSINF_6;
1202    case Irrm_ZERO:
1203       return S390_DFP_ROUND_ZERO_5;
1204    case Irrm_NEAREST_TIE_AWAY_0:
1205       return S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1;
1206    case Irrm_PREPARE_SHORTER:
1207       return S390_DFP_ROUND_PREPARE_SHORT_3;
1208    case Irrm_AWAY_FROM_ZERO:
1209       return S390_DFP_ROUND_AWAY_0;
1210    case Irrm_NEAREST_TIE_TOWARD_0:
1211       return S390_DFP_ROUND_NEAREST_TIE_TOWARD_0;
1212    }
1213    vpanic("decode_dfp_rounding_mode");
1214 }
1215 #endif
1216 
1217 #define S390_CC_FOR_DFP_RESULT(cc_dep1) \
1218 ({ \
1219    __asm__ volatile ( \
1220         ".insn rre, 0xb3d60000,0,%[op]\n\t"              /* LTDTR */ \
1221         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
1222                                    : [op]  "f"(cc_dep1) \
1223                                    : "cc", "f0"); \
1224    psw >> 28;   /* cc */ \
1225 })
1226 
1227 #define S390_CC_FOR_DFP128_RESULT(hi,lo) \
1228 ({ \
1229    __asm__ volatile ( \
1230         "ldr   4,%[high]\n\t"                                           \
1231         "ldr   6,%[low]\n\t"                                            \
1232         ".insn rre, 0xb3de0000,0,4\n\t"    /* LTXTR */                  \
1233         "ipm %[psw]\n\t"           : [psw] "=d"(psw)                    \
1234                                    : [high] "f"(hi), [low] "f"(lo)      \
1235                                    : "cc", "f0", "f2", "f4", "f6");     \
1236    psw >> 28;   /* cc */                                                \
1237 })
1238 
1239 #define S390_CC_FOR_DFP_TD(opcode,cc_dep1,cc_dep2)                      \
1240 ({                                                                      \
1241    __asm__ volatile (                                                   \
1242         opcode ",%[value],0(%[class])\n\t"                              \
1243         "ipm %[psw]\n\t"           : [psw] "=d"(psw)                    \
1244                                    : [value] "f"(cc_dep1),              \
1245                                      [class] "a"(cc_dep2)               \
1246                                    : "cc");                             \
1247    psw >> 28;   /* cc */                                                \
1248 })
1249 
1250 #define S390_CC_FOR_DFP128_TD(opcode,cc_dep1,cc_dep2,cc_ndep)           \
1251 ({                                                                      \
1252    /* Recover the original DEP2 value. See comment near                 \
1253       s390_cc_thunk_put1d128Z for rationale. */                         \
1254    cc_dep2 = cc_dep2 ^ cc_ndep;                                         \
1255    __asm__ volatile (                                                   \
1256         "ldr  4,%[high]\n\t"                                            \
1257         "ldr  6,%[low]\n\t"                                             \
1258         opcode ",4,0(%[class])\n\t"                                     \
1259         "ipm  %[psw]\n\t"          : [psw] "=d"(psw)                    \
1260                                    : [high] "f"(cc_dep1), [low] "f"(cc_dep2), \
1261                                      [class] "a"(cc_ndep)               \
1262                                    : "cc", "f4", "f6");                 \
1263    psw >> 28;   /* cc */                                                \
1264 })
1265 
1266 #define S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,rounding_mode)       \
1267    ({                                                                   \
1268       __asm__ volatile (                                                \
1269                         opcode ",0,%[op]," #rounding_mode ",0\n\t"      \
1270                         "ipm %[psw]\n\t"           : [psw] "=d"(psw)    \
1271                         : [op] "f"(cc_dep1)                             \
1272                         : "cc", "r0");                                  \
1273       psw >> 28;   /* cc */                                             \
1274    })
1275 
1276 #define S390_CC_FOR_DFP_CONVERT(opcode,cc_dep1,cc_dep2)                 \
1277    ({                                                                   \
1278       UInt cc;                                                          \
1279       switch (decode_dfp_rounding_mode(cc_dep2)) {                      \
1280       case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1:                         \
1281       case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12:                        \
1282          cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,1);            \
1283          break;                                                         \
1284       case S390_DFP_ROUND_PREPARE_SHORT_3:                              \
1285       case S390_DFP_ROUND_PREPARE_SHORT_15:                             \
1286          cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,3);            \
1287          break;                                                         \
1288       case S390_DFP_ROUND_NEAREST_EVEN_4:                               \
1289       case S390_DFP_ROUND_NEAREST_EVEN_8:                               \
1290          cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,4);            \
1291          break;                                                         \
1292       case S390_DFP_ROUND_ZERO_5:                                       \
1293       case S390_DFP_ROUND_ZERO_9:                                       \
1294          cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,5);            \
1295          break;                                                         \
1296       case S390_DFP_ROUND_POSINF_6:                                     \
1297       case S390_DFP_ROUND_POSINF_10:                                    \
1298          cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,6);            \
1299          break;                                                         \
1300       case S390_DFP_ROUND_NEGINF_7:                                     \
1301       case S390_DFP_ROUND_NEGINF_11:                                    \
1302          cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,7);            \
1303          break;                                                         \
1304       case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0:                         \
1305          cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,13);           \
1306          break;                                                         \
1307       case S390_DFP_ROUND_AWAY_0:                                       \
1308          cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,14);           \
1309          break;                                                         \
1310       default:                                                          \
1311          vpanic("unexpected dfp rounding mode");                        \
1312       }                                                                 \
1313       cc;                                                               \
1314    })
1315 
1316 #define S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,rounding_mode)      \
1317    ({                                                                   \
1318       __asm__ volatile (                                                \
1319                         opcode ",0,%[op]," #rounding_mode ",0\n\t"      \
1320                         "ipm %[psw]\n\t"           : [psw] "=d"(psw)    \
1321                         : [op] "f"(cc_dep1)                             \
1322                         : "cc", "r0");                                  \
1323       psw >> 28;   /* cc */                                             \
1324    })
1325 
1326 #define S390_CC_FOR_DFP_UCONVERT(opcode,cc_dep1,cc_dep2)                \
1327    ({                                                                   \
1328       UInt cc;                                                          \
1329       switch (decode_dfp_rounding_mode(cc_dep2)) {                      \
1330       case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1:                         \
1331       case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12:                        \
1332          cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,1);           \
1333          break;                                                         \
1334       case S390_DFP_ROUND_PREPARE_SHORT_3:                              \
1335       case S390_DFP_ROUND_PREPARE_SHORT_15:                             \
1336          cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,3);           \
1337          break;                                                         \
1338       case S390_DFP_ROUND_NEAREST_EVEN_4:                               \
1339       case S390_DFP_ROUND_NEAREST_EVEN_8:                               \
1340          cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,4);           \
1341          break;                                                         \
1342       case S390_DFP_ROUND_ZERO_5:                                       \
1343       case S390_DFP_ROUND_ZERO_9:                                       \
1344          cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,5);           \
1345          break;                                                         \
1346       case S390_DFP_ROUND_POSINF_6:                                     \
1347       case S390_DFP_ROUND_POSINF_10:                                    \
1348          cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,6);           \
1349          break;                                                         \
1350       case S390_DFP_ROUND_NEGINF_7:                                     \
1351       case S390_DFP_ROUND_NEGINF_11:                                    \
1352          cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,7);           \
1353          break;                                                         \
1354       case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0:                         \
1355          cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,13);          \
1356          break;                                                         \
1357       case S390_DFP_ROUND_AWAY_0:                                       \
1358          cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,14);          \
1359          break;                                                         \
1360       default:                                                          \
1361          vpanic("unexpected dfp rounding mode");                        \
1362       }                                                                 \
1363       cc;                                                               \
1364    })
1365 
1366 #define S390_CC_FOR_DFP128_CONVERT_AUX(opcode,hi,lo,rounding_mode)      \
1367    ({                                                                   \
1368       __asm__ volatile (                                                \
1369                         "ldr   4,%[high]\n\t"                           \
1370                         "ldr   6,%[low]\n\t"                            \
1371                         opcode ",0,4," #rounding_mode ",0\n\t"          \
1372                         "ipm %[psw]\n\t"           : [psw] "=d"(psw)    \
1373                         : [high] "f"(hi), [low] "f"(lo)                 \
1374                         : "cc", "r0", "f4", "f6");                      \
1375       psw >> 28;   /* cc */                                             \
1376    })
1377 
1378 #define S390_CC_FOR_DFP128_CONVERT(opcode,cc_dep1,cc_dep2,cc_ndep)       \
1379    ({                                                                    \
1380       UInt cc;                                                           \
1381       /* Recover the original DEP2 value. See comment near               \
1382          s390_cc_thunk_put3 for rationale. */                            \
1383       cc_dep2 = cc_dep2 ^ cc_ndep;                                       \
1384       switch (decode_dfp_rounding_mode(cc_ndep)) {                       \
1385       case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1:                          \
1386       case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12:                         \
1387          cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,1);  \
1388          break;                                                          \
1389       case S390_DFP_ROUND_PREPARE_SHORT_3:                               \
1390       case S390_DFP_ROUND_PREPARE_SHORT_15:                              \
1391          cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,3);  \
1392          break;                                                          \
1393       case S390_DFP_ROUND_NEAREST_EVEN_4:                                \
1394       case S390_DFP_ROUND_NEAREST_EVEN_8:                                \
1395          cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,4);  \
1396          break;                                                          \
1397       case S390_DFP_ROUND_ZERO_5:                                        \
1398       case S390_DFP_ROUND_ZERO_9:                                        \
1399          cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,5);  \
1400          break;                                                          \
1401       case S390_DFP_ROUND_POSINF_6:                                      \
1402       case S390_DFP_ROUND_POSINF_10:                                     \
1403          cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,6);  \
1404          break;                                                          \
1405       case S390_DFP_ROUND_NEGINF_7:                                      \
1406       case S390_DFP_ROUND_NEGINF_11:                                     \
1407          cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,7);  \
1408          break;                                                          \
1409       case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0:                          \
1410          cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,13); \
1411          break;                                                          \
1412       case S390_DFP_ROUND_AWAY_0:                                        \
1413          cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,14); \
1414          break;                                                          \
1415       default:                                                           \
1416          vpanic("unexpected dfp rounding mode");                         \
1417       }                                                                  \
1418       cc;                                                                \
1419    })
1420 
1421 #define S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,hi,lo,rounding_mode)      \
1422    ({                                                                    \
1423       __asm__ volatile (                                                 \
1424                         "ldr   4,%[high]\n\t"                            \
1425                         "ldr   6,%[low]\n\t"                             \
1426                         opcode ",0,4," #rounding_mode ",0\n\t"           \
1427                         "ipm %[psw]\n\t"           : [psw] "=d"(psw)     \
1428                         : [high] "f"(hi), [low] "f"(lo)                  \
1429                         : "cc", "r0", "f4", "f6");                       \
1430       psw >> 28;   /* cc */                                              \
1431    })
1432 
1433 #define S390_CC_FOR_DFP128_UCONVERT(opcode,cc_dep1,cc_dep2,cc_ndep)       \
1434    ({                                                                     \
1435       UInt cc;                                                            \
1436       /* Recover the original DEP2 value. See comment near                \
1437          s390_cc_thunk_put3 for rationale. */                             \
1438       cc_dep2 = cc_dep2 ^ cc_ndep;                                        \
1439       switch (decode_dfp_rounding_mode(cc_ndep)) {                        \
1440       case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1:                           \
1441       case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12:                          \
1442          cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,1);  \
1443          break;                                                           \
1444       case S390_DFP_ROUND_PREPARE_SHORT_3:                                \
1445       case S390_DFP_ROUND_PREPARE_SHORT_15:                               \
1446          cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,3);  \
1447          break;                                                           \
1448       case S390_DFP_ROUND_NEAREST_EVEN_4:                                 \
1449       case S390_DFP_ROUND_NEAREST_EVEN_8:                                 \
1450          cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,4);  \
1451          break;                                                           \
1452       case S390_DFP_ROUND_ZERO_5:                                         \
1453       case S390_DFP_ROUND_ZERO_9:                                         \
1454          cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,5);  \
1455          break;                                                           \
1456       case S390_DFP_ROUND_POSINF_6:                                       \
1457       case S390_DFP_ROUND_POSINF_10:                                      \
1458          cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,6);  \
1459          break;                                                           \
1460       case S390_DFP_ROUND_NEGINF_7:                                       \
1461       case S390_DFP_ROUND_NEGINF_11:                                      \
1462          cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,7);  \
1463          break;                                                           \
1464       case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0:                           \
1465          cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,13); \
1466          break;                                                           \
1467       case S390_DFP_ROUND_AWAY_0:                                         \
1468          cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,14); \
1469          break;                                                           \
1470       default:                                                            \
1471          vpanic("unexpected dfp rounding mode");                          \
1472       }                                                                   \
1473       cc;                                                                 \
1474    })
1475 
1476 
1477 /* Return the value of the condition code from the supplied thunk parameters.
1478    This is not the value of the PSW. It is the value of the 2 CC bits within
1479    the PSW. The returned value is thusly in the interval [0:3]. */
1480 UInt
s390_calculate_cc(ULong cc_op,ULong cc_dep1,ULong cc_dep2,ULong cc_ndep)1481 s390_calculate_cc(ULong cc_op, ULong cc_dep1, ULong cc_dep2, ULong cc_ndep)
1482 {
1483 #if defined(VGA_s390x)
1484    UInt psw;
1485 
1486    switch (cc_op) {
1487 
1488    case S390_CC_OP_BITWISE:
1489       return S390_CC_FOR_BINARY("ogr", cc_dep1, (ULong)0);
1490 
1491    case S390_CC_OP_SIGNED_COMPARE:
1492       return S390_CC_FOR_BINARY("cgr", cc_dep1, cc_dep2);
1493 
1494    case S390_CC_OP_UNSIGNED_COMPARE:
1495       return S390_CC_FOR_BINARY("clgr", cc_dep1, cc_dep2);
1496 
1497    case S390_CC_OP_SIGNED_ADD_64:
1498       return S390_CC_FOR_BINARY("agr", cc_dep1, cc_dep2);
1499 
1500    case S390_CC_OP_SIGNED_ADD_32:
1501       return S390_CC_FOR_BINARY("ar", cc_dep1, cc_dep2);
1502 
1503    case S390_CC_OP_SIGNED_SUB_64:
1504       return S390_CC_FOR_BINARY("sgr", cc_dep1, cc_dep2);
1505 
1506    case S390_CC_OP_SIGNED_SUB_32:
1507       return S390_CC_FOR_BINARY("sr", cc_dep1, cc_dep2);
1508 
1509    case S390_CC_OP_UNSIGNED_ADD_64:
1510       return S390_CC_FOR_BINARY("algr", cc_dep1, cc_dep2);
1511 
1512    case S390_CC_OP_UNSIGNED_ADD_32:
1513       return S390_CC_FOR_BINARY("alr", cc_dep1, cc_dep2);
1514 
1515    case S390_CC_OP_UNSIGNED_ADDC_64:
1516       return S390_CC_FOR_TERNARY_ADDC("alcgr", cc_dep1, cc_dep2, cc_ndep);
1517 
1518    case S390_CC_OP_UNSIGNED_ADDC_32:
1519       return S390_CC_FOR_TERNARY_ADDC("alcr", cc_dep1, cc_dep2, cc_ndep);
1520 
1521    case S390_CC_OP_UNSIGNED_SUB_64:
1522       return S390_CC_FOR_BINARY("slgr", cc_dep1, cc_dep2);
1523 
1524    case S390_CC_OP_UNSIGNED_SUB_32:
1525       return S390_CC_FOR_BINARY("slr", cc_dep1, cc_dep2);
1526 
1527    case S390_CC_OP_UNSIGNED_SUBB_64:
1528       return S390_CC_FOR_TERNARY_SUBB("slbgr", cc_dep1, cc_dep2, cc_ndep);
1529 
1530    case S390_CC_OP_UNSIGNED_SUBB_32:
1531       return S390_CC_FOR_TERNARY_SUBB("slbr", cc_dep1, cc_dep2, cc_ndep);
1532 
1533    case S390_CC_OP_LOAD_AND_TEST:
1534       /* Like signed comparison with 0 */
1535       return S390_CC_FOR_BINARY("cgr", cc_dep1, (Long)0);
1536 
1537    case S390_CC_OP_LOAD_POSITIVE_32:
1538       __asm__ volatile (
1539            "lpr  %[result],%[op]\n\t"
1540            "ipm  %[psw]\n\t"         : [psw] "=d"(psw), [result] "=d"(cc_dep1)
1541                                      : [op] "d"(cc_dep1)
1542                                      : "cc");
1543       return psw >> 28;   /* cc */
1544 
1545    case S390_CC_OP_LOAD_POSITIVE_64:
1546       __asm__ volatile (
1547            "lpgr %[result],%[op]\n\t"
1548            "ipm  %[psw]\n\t"         : [psw] "=d"(psw), [result] "=d"(cc_dep1)
1549                                      : [op] "d"(cc_dep1)
1550                                      : "cc");
1551       return psw >> 28;   /* cc */
1552 
1553    case S390_CC_OP_TEST_UNDER_MASK_8: {
1554       UChar value  = cc_dep1;
1555       UChar mask   = cc_dep2;
1556 
1557       __asm__ volatile (
1558            "bras %%r2,1f\n\t"             /* %r2 = address of next insn */
1559            "tm %[value],0\n\t"            /* this is skipped, then EXecuted */
1560            "1: ex %[mask],0(%%r2)\n\t"    /* EXecute TM after modifying mask */
1561            "ipm %[psw]\n\t"             : [psw] "=d"(psw)
1562                                         : [value] "m"(value), [mask] "a"(mask)
1563                                         : "r2", "cc");
1564       return psw >> 28;   /* cc */
1565    }
1566 
1567    case S390_CC_OP_TEST_UNDER_MASK_16: {
1568       /* Create a TMLL insn with the mask as given by cc_dep2 */
1569       UInt insn  = (0xA701u << 16) | cc_dep2;
1570       UInt value = cc_dep1;
1571 
1572       __asm__ volatile (
1573            "lr   1,%[value]\n\t"
1574            "lhi  2,0x10\n\t"
1575            "ex   2,%[insn]\n\t"
1576            "ipm  %[psw]\n\t"       : [psw] "=d"(psw)
1577                                    : [value] "d"(value), [insn] "m"(insn)
1578                                    : "r1", "r2", "cc");
1579       return psw >> 28;   /* cc */
1580    }
1581 
1582    case S390_CC_OP_SHIFT_LEFT_32:
1583       __asm__ volatile (
1584            "sla  %[op],0(%[amount])\n\t"
1585            "ipm  %[psw]\n\t"            : [psw] "=d"(psw), [op] "+d"(cc_dep1)
1586                                         : [amount] "a"(cc_dep2)
1587                                         : "cc");
1588       return psw >> 28;   /* cc */
1589 
1590    case S390_CC_OP_SHIFT_LEFT_64: {
1591       Int high = (Int)(cc_dep1 >> 32);
1592       Int low  = (Int)(cc_dep1 & 0xFFFFFFFF);
1593 
1594       __asm__ volatile (
1595            "lr   2,%[high]\n\t"
1596            "lr   3,%[low]\n\t"
1597            "slda 2,0(%[amount])\n\t"
1598            "ipm %[psw]\n\t"             : [psw] "=d"(psw), [high] "+d"(high),
1599                                           [low] "+d"(low)
1600                                         : [amount] "a"(cc_dep2)
1601                                         : "cc", "r2", "r3");
1602       return psw >> 28;   /* cc */
1603    }
1604 
1605    case S390_CC_OP_INSERT_CHAR_MASK_32: {
1606       Int inserted = 0;
1607       Int msb = 0;
1608 
1609       if (cc_dep2 & 1) {
1610          inserted |= cc_dep1 & 0xff;
1611          msb = 0x80;
1612       }
1613       if (cc_dep2 & 2) {
1614          inserted |= cc_dep1 & 0xff00;
1615          msb = 0x8000;
1616       }
1617       if (cc_dep2 & 4) {
1618          inserted |= cc_dep1 & 0xff0000;
1619          msb = 0x800000;
1620       }
1621       if (cc_dep2 & 8) {
1622          inserted |= cc_dep1 & 0xff000000;
1623          msb = 0x80000000;
1624       }
1625 
1626       if (inserted & msb)  // MSB is 1
1627          return 1;
1628       if (inserted > 0)
1629          return 2;
1630       return 0;
1631    }
1632 
1633    case S390_CC_OP_BFP_RESULT_32:
1634       return S390_CC_FOR_BFP_RESULT("ltebr", cc_dep1);
1635 
1636    case S390_CC_OP_BFP_RESULT_64:
1637       return S390_CC_FOR_BFP_RESULT("ltdbr", cc_dep1);
1638 
1639    case S390_CC_OP_BFP_RESULT_128:
1640       return S390_CC_FOR_BFP128_RESULT(cc_dep1, cc_dep2);
1641 
1642    case S390_CC_OP_BFP_32_TO_INT_32:
1643       return S390_CC_FOR_BFP_CONVERT("cfebr", cc_dep1, cc_dep2);
1644 
1645    case S390_CC_OP_BFP_64_TO_INT_32:
1646       return S390_CC_FOR_BFP_CONVERT("cfdbr", cc_dep1, cc_dep2);
1647 
1648    case S390_CC_OP_BFP_128_TO_INT_32:
1649       return S390_CC_FOR_BFP128_CONVERT("cfxbr", cc_dep1, cc_dep2, cc_ndep);
1650 
1651    case S390_CC_OP_BFP_32_TO_INT_64:
1652       return S390_CC_FOR_BFP_CONVERT("cgebr", cc_dep1, cc_dep2);
1653 
1654    case S390_CC_OP_BFP_64_TO_INT_64:
1655       return S390_CC_FOR_BFP_CONVERT("cgdbr", cc_dep1, cc_dep2);
1656 
1657    case S390_CC_OP_BFP_128_TO_INT_64:
1658       return S390_CC_FOR_BFP128_CONVERT("cgxbr", cc_dep1, cc_dep2, cc_ndep);
1659 
1660    case S390_CC_OP_BFP_TDC_32:
1661       return S390_CC_FOR_BFP_TDC("tceb", cc_dep1, cc_dep2);
1662 
1663    case S390_CC_OP_BFP_TDC_64:
1664       return S390_CC_FOR_BFP_TDC("tcdb", cc_dep1, cc_dep2);
1665 
1666    case S390_CC_OP_BFP_TDC_128:
1667       return S390_CC_FOR_BFP128_TDC(cc_dep1, cc_dep2, cc_ndep);
1668 
1669    case S390_CC_OP_SET:
1670       return cc_dep1;
1671 
1672    case S390_CC_OP_BFP_32_TO_UINT_32:
1673       return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb39c0000", cc_dep1, cc_dep2);
1674 
1675    case S390_CC_OP_BFP_64_TO_UINT_32:
1676       return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb39d0000", cc_dep1, cc_dep2);
1677 
1678    case S390_CC_OP_BFP_128_TO_UINT_32:
1679       return S390_CC_FOR_BFP128_UCONVERT(".insn rrf,0xb39e0000", cc_dep1,
1680                                          cc_dep2, cc_ndep);
1681 
1682    case S390_CC_OP_BFP_32_TO_UINT_64:
1683       return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb3ac0000", cc_dep1, cc_dep2);
1684 
1685    case S390_CC_OP_BFP_64_TO_UINT_64:
1686       return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb3ad0000", cc_dep1, cc_dep2);
1687 
1688    case S390_CC_OP_BFP_128_TO_UINT_64:
1689       return S390_CC_FOR_BFP128_UCONVERT(".insn rrf,0xb3ae0000", cc_dep1,
1690                                          cc_dep2, cc_ndep);
1691 
1692    case S390_CC_OP_DFP_RESULT_64:
1693       return S390_CC_FOR_DFP_RESULT(cc_dep1);
1694 
1695    case S390_CC_OP_DFP_RESULT_128:
1696       return S390_CC_FOR_DFP128_RESULT(cc_dep1, cc_dep2);
1697 
1698    case S390_CC_OP_DFP_TDC_32:  /* TDCET */
1699       return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000050", cc_dep1, cc_dep2);
1700 
1701    case S390_CC_OP_DFP_TDC_64:  /* TDCDT */
1702       return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000054", cc_dep1, cc_dep2);
1703 
1704    case S390_CC_OP_DFP_TDC_128: /* TDCXT */
1705       return S390_CC_FOR_DFP128_TD(".insn rxe, 0xed0000000058", cc_dep1,
1706                                    cc_dep2, cc_ndep);
1707 
1708    case S390_CC_OP_DFP_TDG_32:  /* TDGET */
1709       return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000051", cc_dep1, cc_dep2);
1710 
1711    case S390_CC_OP_DFP_TDG_64:  /* TDGDT */
1712       return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000055", cc_dep1, cc_dep2);
1713 
1714    case S390_CC_OP_DFP_TDG_128: /* TDGXT */
1715       return S390_CC_FOR_DFP128_TD(".insn rxe, 0xed0000000059", cc_dep1,
1716                                    cc_dep2, cc_ndep);
1717 
1718    case S390_CC_OP_DFP_64_TO_INT_32: /* CFDTR */
1719       return S390_CC_FOR_DFP_CONVERT(".insn rrf,0xb9410000", cc_dep1, cc_dep2);
1720 
1721    case S390_CC_OP_DFP_128_TO_INT_32: /* CFXTR */
1722       return S390_CC_FOR_DFP128_CONVERT(".insn rrf,0xb9490000", cc_dep1,
1723                                         cc_dep2, cc_ndep);
1724 
1725    case S390_CC_OP_DFP_64_TO_INT_64: /* CGDTR */
1726       return S390_CC_FOR_DFP_CONVERT(".insn rrf,0xb3e10000", cc_dep1, cc_dep2);
1727 
1728    case S390_CC_OP_DFP_128_TO_INT_64: /* CGXTR */
1729       return S390_CC_FOR_DFP128_CONVERT(".insn rrf,0xb3e90000", cc_dep1,
1730                                         cc_dep2, cc_ndep);
1731 
1732    case S390_CC_OP_DFP_64_TO_UINT_32: /* CLFDTR */
1733       return S390_CC_FOR_DFP_UCONVERT(".insn rrf,0xb9430000", cc_dep1, cc_dep2);
1734 
1735    case S390_CC_OP_DFP_128_TO_UINT_32: /* CLFXTR */
1736       return S390_CC_FOR_DFP128_UCONVERT(".insn rrf,0xb94b0000", cc_dep1,
1737                                          cc_dep2, cc_ndep);
1738 
1739    case S390_CC_OP_DFP_64_TO_UINT_64: /* CLGDTR */
1740       return S390_CC_FOR_DFP_UCONVERT(".insn rrf,0xb9420000", cc_dep1, cc_dep2);
1741 
1742    case S390_CC_OP_DFP_128_TO_UINT_64: /* CLGXTR */
1743       return S390_CC_FOR_DFP128_UCONVERT(".insn rrf,0xb94a0000", cc_dep1,
1744                                          cc_dep2, cc_ndep);
1745 
1746    case S390_CC_OP_PFPO_32: {
1747       __asm__ volatile(
1748            "ler 4, %[cc_dep1]\n\t"      /* 32 bit FR move */
1749            "lr  0, %[cc_dep2]\n\t"      /* 32 bit GR move */
1750            ".short 0x010a\n\t"          /* PFPO */
1751            "ipm %[psw]\n\t"             : [psw] "=d"(psw)
1752                                         : [cc_dep1] "f"(cc_dep1),
1753                                           [cc_dep2] "d"(cc_dep2)
1754                                         : "r0", "r1", "f4");
1755       return psw >> 28;  /* cc */
1756    }
1757 
1758    case S390_CC_OP_PFPO_64: {
1759       __asm__ volatile(
1760            "ldr 4, %[cc_dep1]\n\t"
1761            "lr  0, %[cc_dep2]\n\t"      /* 32 bit register move */
1762            ".short 0x010a\n\t"          /* PFPO */
1763            "ipm %[psw]\n\t"             : [psw] "=d"(psw)
1764                                         : [cc_dep1] "f"(cc_dep1),
1765                                           [cc_dep2] "d"(cc_dep2)
1766                                         : "r0", "r1", "f4");
1767       return psw >> 28;  /* cc */
1768    }
1769 
1770    case S390_CC_OP_PFPO_128: {
1771       __asm__ volatile(
1772            "ldr 4,%[cc_dep1]\n\t"
1773            "ldr 6,%[cc_dep2]\n\t"
1774            "lr  0,%[cc_ndep]\n\t"       /* 32 bit register move */
1775            ".short 0x010a\n\t"          /* PFPO */
1776            "ipm %[psw]\n\t"             : [psw] "=d"(psw)
1777                                         : [cc_dep1] "f"(cc_dep1),
1778                                           [cc_dep2] "f"(cc_dep2),
1779                                           [cc_ndep] "d"(cc_ndep)
1780                                         : "r0", "r1", "f0", "f2", "f4", "f6");
1781       return psw >> 28;  /* cc */
1782    }
1783 
1784    default:
1785       break;
1786    }
1787 #endif
1788    vpanic("s390_calculate_cc");
1789 }
1790 
1791 
1792 /* Note that this does *not* return a Boolean value. The result needs to be
1793    explicitly tested against zero. */
1794 UInt
s390_calculate_cond(ULong mask,ULong op,ULong dep1,ULong dep2,ULong ndep)1795 s390_calculate_cond(ULong mask, ULong op, ULong dep1, ULong dep2, ULong ndep)
1796 {
1797    UInt cc = s390_calculate_cc(op, dep1, dep2, ndep);
1798 
1799    return ((mask << cc) & 0x8);
1800 }
1801 
1802 /*------------------------------------------------------------*/
1803 /*--- spechelper for performance                           ---*/
1804 /*------------------------------------------------------------*/
1805 
1806 
1807 /* Convenience macros */
1808 #define unop(op,a1) IRExpr_Unop((op),(a1))
1809 #define binop(op,a1,a2) IRExpr_Binop((op),(a1),(a2))
1810 #define mkU64(v) IRExpr_Const(IRConst_U64(v))
1811 #define mkU32(v) IRExpr_Const(IRConst_U32(v))
1812 #define mkU8(v)  IRExpr_Const(IRConst_U8(v))
1813 
1814 
1815 static inline Bool
isC64(const IRExpr * expr)1816 isC64(const IRExpr *expr)
1817 {
1818    return expr->tag == Iex_Const && expr->Iex.Const.con->tag == Ico_U64;
1819 }
1820 
1821 
1822 /* The returned expression is NULL if no specialization was found. In that
1823    case the helper function will be called. Otherwise, the expression has
1824    type Ity_I32 and a Boolean value. */
1825 IRExpr *
guest_s390x_spechelper(const HChar * function_name,IRExpr ** args,IRStmt ** precedingStmts,Int n_precedingStmts)1826 guest_s390x_spechelper(const HChar *function_name, IRExpr **args,
1827                        IRStmt **precedingStmts, Int n_precedingStmts)
1828 {
1829    UInt i, arity = 0;
1830 
1831    for (i = 0; args[i]; i++)
1832       arity++;
1833 
1834 #  if 0
1835    vex_printf("spec request:\n");
1836    vex_printf("   %s  ", function_name);
1837    for (i = 0; i < arity; i++) {
1838       vex_printf("  ");
1839       ppIRExpr(args[i]);
1840    }
1841    vex_printf("\n");
1842 #  endif
1843 
1844    /* --------- Specialising "s390_calculate_cond" --------- */
1845 
1846    if (vex_streq(function_name, "s390_calculate_cond")) {
1847       IRExpr *cond_expr, *cc_op_expr, *cc_dep1, *cc_dep2;
1848       ULong cond, cc_op;
1849 
1850       vassert(arity == 5);
1851 
1852       cond_expr  = args[0];
1853       cc_op_expr = args[1];
1854 
1855       /* The necessary requirement for all optimizations here is that the
1856          condition and the cc_op are constant. So check that upfront. */
1857       if (! isC64(cond_expr))  return NULL;
1858       if (! isC64(cc_op_expr)) return NULL;
1859 
1860       cond    = cond_expr->Iex.Const.con->Ico.U64;
1861       cc_op   = cc_op_expr->Iex.Const.con->Ico.U64;
1862 
1863       vassert(cond <= 15);
1864 
1865       /*
1866         +------+---+---+---+---+
1867         | cc   | 0 | 1 | 2 | 3 |
1868         | cond | 8 | 4 | 2 | 1 |
1869         +------+---+---+---+---+
1870       */
1871       cc_dep1 = args[2];
1872       cc_dep2 = args[3];
1873 
1874       /* S390_CC_OP_SIGNED_COMPARE */
1875       if (cc_op == S390_CC_OP_SIGNED_COMPARE) {
1876          /*
1877             cc == 0  --> cc_dep1 == cc_dep2   (cond == 8)
1878             cc == 1  --> cc_dep1 <  cc_dep2   (cond == 4)
1879             cc == 2  --> cc_dep1 >  cc_dep2   (cond == 2)
1880 
1881             Because cc == 3 cannot occur the rightmost bit of cond is
1882             a don't care.
1883          */
1884          if (cond == 8 || cond == 8 + 1) {
1885             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
1886          }
1887          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
1888             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
1889          }
1890          if (cond == 4 || cond == 4 + 1) {
1891             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep1, cc_dep2));
1892          }
1893          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
1894             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, cc_dep2));
1895          }
1896          /* cc_dep1 > cc_dep2  ---->  cc_dep2 < cc_dep1 */
1897          if (cond == 2 || cond == 2 + 1) {
1898             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep2, cc_dep1));
1899          }
1900          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
1901             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep2, cc_dep1));
1902          }
1903          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
1904             return mkU32(1);
1905          }
1906          /* Remaining case */
1907          return mkU32(0);
1908       }
1909 
1910       /* S390_CC_OP_UNSIGNED_COMPARE */
1911       if (cc_op == S390_CC_OP_UNSIGNED_COMPARE) {
1912          /*
1913             cc == 0  --> cc_dep1 == cc_dep2   (cond == 8)
1914             cc == 1  --> cc_dep1 <  cc_dep2   (cond == 4)
1915             cc == 2  --> cc_dep1 >  cc_dep2   (cond == 2)
1916 
1917             Because cc == 3 cannot occur the rightmost bit of cond is
1918             a don't care.
1919          */
1920          if (cond == 8 || cond == 8 + 1) {
1921             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
1922          }
1923          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
1924             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
1925          }
1926          if (cond == 4 || cond == 4 + 1) {
1927             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
1928          }
1929          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
1930             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
1931          }
1932          /* cc_dep1 > cc_dep2  ---->  cc_dep2 < cc_dep1 */
1933          if (cond == 2 || cond == 2 + 1) {
1934             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
1935          }
1936          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
1937             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
1938          }
1939          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
1940             return mkU32(1);
1941          }
1942          /* Remaining case */
1943          return mkU32(0);
1944       }
1945 
1946       /* S390_CC_OP_LOAD_AND_TEST */
1947       if (cc_op == S390_CC_OP_LOAD_AND_TEST) {
1948          /*
1949             cc == 0  --> cc_dep1 == 0   (cond == 8)
1950             cc == 1  --> cc_dep1 <  0   (cond == 4)
1951             cc == 2  --> cc_dep1 >  0   (cond == 2)
1952 
1953             Because cc == 3 cannot occur the rightmost bit of cond is
1954             a don't care.
1955          */
1956          if (cond == 8 || cond == 8 + 1) {
1957             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
1958          }
1959          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
1960             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
1961          }
1962          if (cond == 4 || cond == 4 + 1) {
1963              /* Special case cc_dep < 0. Only check the MSB to avoid bogus
1964                memcheck complaints due to gcc magic. Fixes 343802
1965              */
1966             return unop(Iop_64to32, binop(Iop_Shr64, cc_dep1, mkU8(63)));
1967          }
1968          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
1969             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, mkU64(0)));
1970          }
1971          /* cc_dep1 > 0  ---->  0 < cc_dep1 */
1972          if (cond == 2 || cond == 2 + 1) {
1973             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, mkU64(0), cc_dep1));
1974          }
1975          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
1976             /* Special case cc_dep >= 0. Only check the MSB to avoid bogus
1977                memcheck complaints due to gcc magic. Fixes 308427
1978              */
1979             return unop(Iop_64to32, binop(Iop_Xor64,
1980                                           binop(Iop_Shr64, cc_dep1, mkU8(63)),
1981                                           mkU64(1)));
1982          }
1983          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
1984             return mkU32(1);
1985          }
1986          /* Remaining case */
1987          return mkU32(0);
1988       }
1989 
1990       /* S390_CC_OP_BITWISE */
1991       if (cc_op == S390_CC_OP_BITWISE) {
1992          /*
1993             cc_dep1 is the result of the boolean operation.
1994 
1995             cc == 0  --> cc_dep1 == 0   (cond == 8)
1996             cc == 1  --> cc_dep1 != 0   (cond == 4)
1997 
1998             Because cc == 2 and cc == 3 cannot occur the two rightmost bits of
1999             cond are don't cares. Therefore:
2000 
2001             cond == 00xx  -> always false
2002             cond == 01xx  -> not equal
2003             cond == 10xx  -> equal
2004             cond == 11xx  -> always true
2005          */
2006          if ((cond & (8 + 4)) == 8 + 4) {
2007             return mkU32(1);
2008          }
2009          if (cond & 8) {
2010             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
2011          }
2012          if (cond & 4) {
2013             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
2014          }
2015          /* Remaining case */
2016          return mkU32(0);
2017       }
2018 
2019       /* S390_CC_OP_INSERT_CHAR_MASK_32
2020          Since the mask comes from an immediate field in the opcode, we
2021          expect the mask to be a constant here. That simplifies matters. */
2022       if (cc_op == S390_CC_OP_INSERT_CHAR_MASK_32) {
2023          ULong mask;
2024          UInt imask = 0, shift = 0;
2025          IRExpr *word;
2026 
2027          if (! isC64(cc_dep2)) goto missed;
2028 
2029          mask = cc_dep2->Iex.Const.con->Ico.U64;
2030 
2031          /* Extract the 32-bit value from the thunk */
2032 
2033          word = unop(Iop_64to32, cc_dep1);
2034 
2035          switch (mask) {
2036          case 0:  shift =  0; imask = 0x00000000; break;
2037          case 1:  shift = 24; imask = 0x000000FF; break;
2038          case 2:  shift = 16; imask = 0x0000FF00; break;
2039          case 3:  shift = 16; imask = 0x0000FFFF; break;
2040          case 4:  shift =  8; imask = 0x00FF0000; break;
2041          case 5:  shift =  8; imask = 0x00FF00FF; break;
2042          case 6:  shift =  8; imask = 0x00FFFF00; break;
2043          case 7:  shift =  8; imask = 0x00FFFFFF; break;
2044          case 8:  shift =  0; imask = 0xFF000000; break;
2045          case 9:  shift =  0; imask = 0xFF0000FF; break;
2046          case 10: shift =  0; imask = 0xFF00FF00; break;
2047          case 11: shift =  0; imask = 0xFF00FFFF; break;
2048          case 12: shift =  0; imask = 0xFFFF0000; break;
2049          case 13: shift =  0; imask = 0xFFFF00FF; break;
2050          case 14: shift =  0; imask = 0xFFFFFF00; break;
2051          case 15: shift =  0; imask = 0xFFFFFFFF; break;
2052          }
2053 
2054          /* Select the bits that were inserted */
2055          word = binop(Iop_And32, word, mkU32(imask));
2056 
2057          /* cc == 0  --> all inserted bits zero or mask == 0   (cond == 8)
2058             cc == 1  --> leftmost inserted bit is one          (cond == 4)
2059             cc == 2  --> leftmost inserted bit is zero and not (cond == 2)
2060                          all inserted bits are zero
2061 
2062             Because cc == 0,1,2 the rightmost bit of the mask is a don't care */
2063          if (cond == 8 || cond == 8 + 1) {
2064             return unop(Iop_1Uto32, binop(Iop_CmpEQ32, word, mkU32(0)));
2065          }
2066          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
2067             return unop(Iop_1Uto32, binop(Iop_CmpNE32, word, mkU32(0)));
2068          }
2069 
2070          /* Sign extend */
2071          if (shift != 0) {
2072             word = binop(Iop_Sar32, binop(Iop_Shl32, word, mkU8(shift)),
2073                          mkU8(shift));
2074          }
2075 
2076          if (cond == 4 || cond == 4 + 1) {  /* word < 0 */
2077             return unop(Iop_1Uto32, binop(Iop_CmpLT32S, word, mkU32(0)));
2078          }
2079          if (cond == 2 || cond == 2 + 1) {  /* word > 0 */
2080             return unop(Iop_1Uto32, binop(Iop_CmpLT32S, mkU32(0), word));
2081          }
2082          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
2083             return unop(Iop_1Uto32, binop(Iop_CmpLE32S, word, mkU32(0)));
2084          }
2085          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
2086             return unop(Iop_1Uto32, binop(Iop_CmpLE32S, mkU32(0), word));
2087          }
2088          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
2089             return mkU32(1);
2090          }
2091          /* Remaining case */
2092          return mkU32(0);
2093       }
2094 
2095       /* S390_CC_OP_TEST_UNDER_MASK_8
2096          Since the mask comes from an immediate field in the opcode, we
2097          expect the mask to be a constant here. That simplifies matters. */
2098       if (cc_op == S390_CC_OP_TEST_UNDER_MASK_8) {
2099          ULong mask16;
2100 
2101          if (! isC64(cc_dep2)) goto missed;
2102 
2103          mask16 = cc_dep2->Iex.Const.con->Ico.U64;
2104 
2105          /* Get rid of the mask16 == 0 case first. Some of the simplifications
2106             below (e.g. for OVFL) only hold if mask16 == 0.  */
2107          if (mask16 == 0) {   /* cc == 0 */
2108             if (cond & 0x8) return mkU32(1);
2109             return mkU32(0);
2110          }
2111 
2112          /* cc == 2 is a don't care */
2113          if (cond == 8 || cond == 8 + 2) {
2114             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
2115                                           binop(Iop_And64, cc_dep1, cc_dep2),
2116                                           mkU64(0)));
2117          }
2118          if (cond == 7 || cond == 7 - 2) {
2119             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
2120                                           binop(Iop_And64, cc_dep1, cc_dep2),
2121                                           mkU64(0)));
2122          }
2123          if (cond == 1 || cond == 1 + 2) {
2124             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
2125                                           binop(Iop_And64, cc_dep1, cc_dep2),
2126                                           cc_dep2));
2127          }
2128          if (cond == 14 || cond == 14 - 2) {  /* ! OVFL */
2129             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
2130                                           binop(Iop_And64, cc_dep1, cc_dep2),
2131                                           cc_dep2));
2132          }
2133          goto missed;
2134       }
2135 
2136       /* S390_CC_OP_TEST_UNDER_MASK_16
2137          Since the mask comes from an immediate field in the opcode, we
2138          expect the mask to be a constant here. That simplifies matters. */
2139       if (cc_op == S390_CC_OP_TEST_UNDER_MASK_16) {
2140          ULong mask16;
2141          UInt msb;
2142 
2143          if (! isC64(cc_dep2)) goto missed;
2144 
2145          mask16 = cc_dep2->Iex.Const.con->Ico.U64;
2146 
2147          /* Get rid of the mask16 == 0 case first. Some of the simplifications
2148             below (e.g. for OVFL) only hold if mask16 == 0.  */
2149          if (mask16 == 0) {   /* cc == 0 */
2150             if (cond & 0x8) return mkU32(1);
2151             return mkU32(0);
2152          }
2153 
2154          if (cond == 8) {
2155             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
2156                                           binop(Iop_And64, cc_dep1, cc_dep2),
2157                                           mkU64(0)));
2158          }
2159          if (cond == 7) {
2160             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
2161                                           binop(Iop_And64, cc_dep1, cc_dep2),
2162                                           mkU64(0)));
2163          }
2164          if (cond == 1) {
2165             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
2166                                           binop(Iop_And64, cc_dep1, cc_dep2),
2167                                           mkU64(mask16)));
2168          }
2169          if (cond == 14) {  /* ! OVFL */
2170             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
2171                                           binop(Iop_And64, cc_dep1, cc_dep2),
2172                                           mkU64(mask16)));
2173          }
2174 
2175          /* Find MSB in mask */
2176          msb = 0x8000;
2177          while (msb > mask16)
2178             msb >>= 1;
2179 
2180          if (cond == 2) {  /* cc == 2 */
2181             IRExpr *c1, *c2;
2182 
2183             /* (cc_dep & msb) != 0 && (cc_dep & mask16) != mask16 */
2184             c1 = binop(Iop_CmpNE64,
2185                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
2186             c2 = binop(Iop_CmpNE64,
2187                        binop(Iop_And64, cc_dep1, cc_dep2),
2188                        mkU64(mask16));
2189             return binop(Iop_And32, unop(Iop_1Uto32, c1),
2190                          unop(Iop_1Uto32, c2));
2191          }
2192 
2193          if (cond == 4) {  /* cc == 1 */
2194             IRExpr *c1, *c2;
2195 
2196             /* (cc_dep & msb) == 0 && (cc_dep & mask16) != 0 */
2197             c1 = binop(Iop_CmpEQ64,
2198                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
2199             c2 = binop(Iop_CmpNE64,
2200                        binop(Iop_And64, cc_dep1, cc_dep2),
2201                        mkU64(0));
2202             return binop(Iop_And32, unop(Iop_1Uto32, c1),
2203                          unop(Iop_1Uto32, c2));
2204          }
2205 
2206          if (cond == 11) {  /* cc == 0,2,3 */
2207             IRExpr *c1, *c2;
2208 
2209             c1 = binop(Iop_CmpNE64,
2210                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
2211             c2 = binop(Iop_CmpEQ64,
2212                        binop(Iop_And64, cc_dep1, cc_dep2),
2213                        mkU64(0));
2214             return binop(Iop_Or32, unop(Iop_1Uto32, c1),
2215                          unop(Iop_1Uto32, c2));
2216          }
2217 
2218          if (cond == 3) {  /* cc == 2 || cc == 3 */
2219             return unop(Iop_1Uto32,
2220                         binop(Iop_CmpNE64,
2221                               binop(Iop_And64, cc_dep1, mkU64(msb)),
2222                               mkU64(0)));
2223          }
2224          if (cond == 12) { /* cc == 0 || cc == 1 */
2225             return unop(Iop_1Uto32,
2226                         binop(Iop_CmpEQ64,
2227                               binop(Iop_And64, cc_dep1, mkU64(msb)),
2228                               mkU64(0)));
2229          }
2230          // vex_printf("TUM mask = 0x%llx\n", mask16);
2231          goto missed;
2232       }
2233 
2234       /* S390_CC_OP_UNSIGNED_SUB_64/32 */
2235       if (cc_op == S390_CC_OP_UNSIGNED_SUB_64 ||
2236           cc_op == S390_CC_OP_UNSIGNED_SUB_32) {
2237          /*
2238             cc_dep1, cc_dep2 are the zero extended left and right operands
2239 
2240             cc == 1  --> result != 0, borrow    (cond == 4)
2241             cc == 2  --> result == 0, no borrow (cond == 2)
2242             cc == 3  --> result != 0, no borrow (cond == 1)
2243 
2244             cc = (cc_dep1 == cc_dep2) ? 2
2245                                       : (cc_dep1 > cc_dep2) ? 3 : 1;
2246 
2247             Because cc == 0 cannot occur the leftmost bit of cond is
2248             a don't care.
2249          */
2250          if (cond == 1 || cond == 1 + 8) {  /* cc == 3   op2 < op1 */
2251             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
2252          }
2253          if (cond == 2 || cond == 2 + 8) {  /* cc == 2 */
2254             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
2255          }
2256          if (cond == 4 || cond == 4 + 8) {  /* cc == 1 */
2257             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
2258          }
2259          if (cond == 3 || cond == 3 + 8) {  /* cc == 2 || cc == 3 */
2260             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
2261          }
2262          if (cond == 6 || cond == 6 + 8) {  /* cc == 2 || cc == 1 */
2263             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
2264          }
2265 
2266          if (cond == 5 || cond == 5 + 8) {  /* cc == 3 || cc == 1 */
2267             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
2268          }
2269          if (cond == 7 || cond == 7 + 8) {
2270             return mkU32(1);
2271          }
2272          /* Remaining case */
2273          return mkU32(0);
2274       }
2275 
2276       /* S390_CC_OP_UNSIGNED_ADD_64 */
2277       if (cc_op == S390_CC_OP_UNSIGNED_ADD_64) {
2278          /*
2279             cc_dep1, cc_dep2 are the zero extended left and right operands
2280 
2281             cc == 0  --> result == 0, no carry  (cond == 8)
2282             cc == 1  --> result != 0, no carry  (cond == 4)
2283             cc == 2  --> result == 0, carry     (cond == 2)
2284             cc == 3  --> result != 0, carry     (cond == 1)
2285          */
2286          if (cond == 8) { /* cc == 0 */
2287             /* Both inputs are 0 */
2288             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
2289                                           binop(Iop_Or64, cc_dep1, cc_dep2),
2290                                           mkU64(0)));
2291          }
2292          if (cond == 7) { /* cc == 1,2,3 */
2293             /* Not both inputs are 0 */
2294             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
2295                                           binop(Iop_Or64, cc_dep1, cc_dep2),
2296                                           mkU64(0)));
2297          }
2298          if (cond == 8 + 2) {  /* cc == 0,2  -> result is zero */
2299             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
2300                                           binop(Iop_Add64, cc_dep1, cc_dep2),
2301                                           mkU64(0)));
2302          }
2303          if (cond == 4 + 1) {  /* cc == 1,3  -> result is not zero */
2304             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
2305                                           binop(Iop_Add64, cc_dep1, cc_dep2),
2306                                           mkU64(0)));
2307          }
2308          goto missed;
2309       }
2310 
2311       /* S390_CC_OP_UNSIGNED_ADD_32 */
2312       if (cc_op == S390_CC_OP_UNSIGNED_ADD_32) {
2313          /*
2314             cc_dep1, cc_dep2 are the zero extended left and right operands
2315 
2316             cc == 0  --> result == 0, no carry  (cond == 8)
2317             cc == 1  --> result != 0, no carry  (cond == 4)
2318             cc == 2  --> result == 0, carry     (cond == 2)
2319             cc == 3  --> result != 0, carry     (cond == 1)
2320          */
2321          if (cond == 8) { /* cc == 0 */
2322             /* Both inputs are 0 */
2323             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
2324                                           binop(Iop_Or64, cc_dep1, cc_dep2),
2325                                           mkU64(0)));
2326          }
2327          if (cond == 7) { /* cc == 1,2,3 */
2328             /* Not both inputs are 0 */
2329             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
2330                                           binop(Iop_Or64, cc_dep1, cc_dep2),
2331                                           mkU64(0)));
2332          }
2333          if (cond == 8 + 2) {  /* cc == 0,2  -> result is zero */
2334             return unop(Iop_1Uto32, binop(Iop_CmpEQ32,
2335                                           binop(Iop_Add32,
2336                                                 unop(Iop_64to32, cc_dep1),
2337                                                 unop(Iop_64to32, cc_dep2)),
2338                                           mkU32(0)));
2339          }
2340          if (cond == 4 + 1) {  /* cc == 1,3  -> result is not zero */
2341             return unop(Iop_1Uto32, binop(Iop_CmpNE32,
2342                                           binop(Iop_Add32,
2343                                                 unop(Iop_64to32, cc_dep1),
2344                                                 unop(Iop_64to32, cc_dep2)),
2345                                           mkU32(0)));
2346          }
2347          goto missed;
2348       }
2349 
2350       /* S390_CC_OP_SET */
2351       if (cc_op == S390_CC_OP_SET) {
2352          /* cc_dep1 is the condition code
2353 
2354             Return 1, if ((cond << cc_dep1) & 0x8) != 0 */
2355 
2356         return unop(Iop_1Uto32,
2357                     binop(Iop_CmpNE64,
2358                           binop(Iop_And64,
2359                                 binop(Iop_Shl64, cond_expr,
2360                                       unop(Iop_64to8, cc_dep1)),
2361                                 mkU64(8)),
2362                           mkU64(0)));
2363       }
2364 
2365       goto missed;
2366    }
2367 
2368    /* --------- Specialising "s390_calculate_cond" --------- */
2369 
2370    if (vex_streq(function_name, "s390_calculate_cc")) {
2371       IRExpr *cc_op_expr, *cc_dep1;
2372       ULong cc_op;
2373 
2374       vassert(arity == 4);
2375 
2376       cc_op_expr = args[0];
2377 
2378       /* The necessary requirement for all optimizations here is that
2379          cc_op is constant. So check that upfront. */
2380       if (! isC64(cc_op_expr)) return NULL;
2381 
2382       cc_op   = cc_op_expr->Iex.Const.con->Ico.U64;
2383       cc_dep1 = args[1];
2384 
2385       if (cc_op == S390_CC_OP_BITWISE) {
2386          return unop(Iop_1Uto32,
2387                      binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
2388       }
2389 
2390       if (cc_op == S390_CC_OP_SET) {
2391          return unop(Iop_64to32, cc_dep1);
2392       }
2393 
2394       goto missed;
2395    }
2396 
2397 missed:
2398    return NULL;
2399 }
2400 
2401 /*---------------------------------------------------------------*/
2402 /*--- end                                guest_s390_helpers.c ---*/
2403 /*---------------------------------------------------------------*/
2404