]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/VEX/priv/guest_s390_helpers.c
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / VEX / priv / guest_s390_helpers.c
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-2011
12
13    This program is free software; you can redistribute it and/or
14    modify it under the terms of the GNU General Public License as
15    published by the Free Software Foundation; either version 2 of the
16    License, or (at your option) any later version.
17
18    This program is distributed in the hope that it will be useful, but
19    WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    General Public License for more details.
22
23    You should have received a copy of the GNU General Public License
24    along with this program; if not, write to the Free Software
25    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26    02110-1301, USA.
27
28    The GNU General Public License is contained in the file COPYING.
29 */
30
31 /* Contributed by Florian Krohm */
32
33 #include "libvex_basictypes.h"
34 #include "libvex_emwarn.h"
35 #include "libvex_guest_s390x.h"
36 #include "libvex_ir.h"
37 #include "libvex.h"
38
39 #include "main_util.h"
40 #include "guest_generic_bb_to_IR.h"
41 #include "guest_s390_defs.h"
42
43 void
44 LibVEX_GuestS390X_initialise(VexGuestS390XState *state)
45 {
46 /*------------------------------------------------------------*/
47 /*--- Initialise ar registers                              ---*/
48 /*------------------------------------------------------------*/
49
50    state->guest_a0 = 0;
51    state->guest_a1 = 0;
52    state->guest_a2 = 0;
53    state->guest_a3 = 0;
54    state->guest_a4 = 0;
55    state->guest_a5 = 0;
56    state->guest_a6 = 0;
57    state->guest_a7 = 0;
58    state->guest_a8 = 0;
59    state->guest_a9 = 0;
60    state->guest_a10 = 0;
61    state->guest_a11 = 0;
62    state->guest_a12 = 0;
63    state->guest_a13 = 0;
64    state->guest_a14 = 0;
65    state->guest_a15 = 0;
66
67 /*------------------------------------------------------------*/
68 /*--- Initialise fpr registers                             ---*/
69 /*------------------------------------------------------------*/
70
71    state->guest_f0 = 0;
72    state->guest_f1 = 0;
73    state->guest_f2 = 0;
74    state->guest_f3 = 0;
75    state->guest_f4 = 0;
76    state->guest_f5 = 0;
77    state->guest_f6 = 0;
78    state->guest_f7 = 0;
79    state->guest_f8 = 0;
80    state->guest_f9 = 0;
81    state->guest_f10 = 0;
82    state->guest_f11 = 0;
83    state->guest_f12 = 0;
84    state->guest_f13 = 0;
85    state->guest_f14 = 0;
86    state->guest_f15 = 0;
87
88 /*------------------------------------------------------------*/
89 /*--- Initialise gpr registers                             ---*/
90 /*------------------------------------------------------------*/
91
92    state->guest_r0 = 0;
93    state->guest_r1 = 0;
94    state->guest_r2 = 0;
95    state->guest_r3 = 0;
96    state->guest_r4 = 0;
97    state->guest_r5 = 0;
98    state->guest_r6 = 0;
99    state->guest_r7 = 0;
100    state->guest_r8 = 0;
101    state->guest_r9 = 0;
102    state->guest_r10 = 0;
103    state->guest_r11 = 0;
104    state->guest_r12 = 0;
105    state->guest_r13 = 0;
106    state->guest_r14 = 0;
107    state->guest_r15 = 0;
108
109 /*------------------------------------------------------------*/
110 /*--- Initialise S390 miscellaneous registers              ---*/
111 /*------------------------------------------------------------*/
112
113    state->guest_counter = 0;
114    state->guest_fpc = 0;
115    state->guest_IA = 0;
116
117 /*------------------------------------------------------------*/
118 /*--- Initialise S390 pseudo registers                     ---*/
119 /*------------------------------------------------------------*/
120
121    state->guest_SYSNO = 0;
122
123 /*------------------------------------------------------------*/
124 /*--- Initialise generic pseudo registers                  ---*/
125 /*------------------------------------------------------------*/
126
127    state->guest_NRADDR = 0;
128    state->guest_TISTART = 0;
129    state->guest_TILEN = 0;
130    state->guest_IP_AT_SYSCALL = 0;
131    state->guest_EMWARN = EmWarn_NONE;
132
133 /*------------------------------------------------------------*/
134 /*--- Initialise thunk                                     ---*/
135 /*------------------------------------------------------------*/
136
137    state->guest_CC_OP = 0;
138    state->guest_CC_DEP1 = 0;
139    state->guest_CC_DEP2 = 0;
140    state->guest_CC_NDEP = 0;
141 }
142
143
144 /* Figure out if any part of the guest state contained in minoff
145    .. maxoff requires precise memory exceptions.  If in doubt return
146    True (but this is generates significantly slower code).  */
147 Bool
148 guest_s390x_state_requires_precise_mem_exns(Int minoff, Int maxoff)
149 {
150    Int lr_min = offsetof(VexGuestS390XState, guest_LR);
151    Int lr_max = lr_min + 8 - 1;
152    Int sp_min = offsetof(VexGuestS390XState, guest_SP);
153    Int sp_max = sp_min + 8 - 1;
154    Int fp_min = offsetof(VexGuestS390XState, guest_FP);
155    Int fp_max = fp_min + 8 - 1;
156    Int ia_min = offsetof(VexGuestS390XState, guest_IA);
157    Int ia_max = ia_min + 8 - 1;
158
159    if (maxoff < lr_min || minoff > lr_max) {
160       /* No overlap with LR */
161    } else {
162       return True;
163    }
164
165    if (maxoff < sp_min || minoff > sp_max) {
166       /* No overlap with SP */
167    } else {
168       return True;
169    }
170
171    if (maxoff < fp_min || minoff > fp_max) {
172       /* No overlap with FP */
173    } else {
174       return True;
175    }
176
177    if (maxoff < ia_min || minoff > ia_max) {
178       /* No overlap with IA */
179    } else {
180       return True;
181    }
182
183    return False;
184 }
185
186
187 #define ALWAYSDEFD(field)                             \
188     { offsetof(VexGuestS390XState, field),            \
189       (sizeof ((VexGuestS390XState*)0)->field) }
190
191 VexGuestLayout s390xGuest_layout = {
192
193    /* Total size of the guest state, in bytes. */
194    .total_sizeB = sizeof(VexGuestS390XState),
195
196    /* Describe the stack pointer. */
197    .offset_SP = offsetof(VexGuestS390XState, guest_SP),
198    .sizeof_SP = 8,
199
200    /* Describe the frame pointer. */
201    .offset_FP = offsetof(VexGuestS390XState, guest_FP),
202    .sizeof_FP = 8,
203
204    /* Describe the instruction pointer. */
205    .offset_IP = offsetof(VexGuestS390XState, guest_IA),
206    .sizeof_IP = 8,
207
208    /* Describe any sections to be regarded by Memcheck as
209       'always-defined'. */
210    .n_alwaysDefd = 9,
211
212    /* Flags thunk: OP and NDEP are always defined, whereas DEP1
213       and DEP2 have to be tracked.  See detailed comment in
214       gdefs.h on meaning of thunk fields. */
215    .alwaysDefd = {
216       /*  0 */ ALWAYSDEFD(guest_CC_OP),     /* generic */
217       /*  1 */ ALWAYSDEFD(guest_CC_NDEP),   /* generic */
218       /*  2 */ ALWAYSDEFD(guest_EMWARN),    /* generic */
219       /*  3 */ ALWAYSDEFD(guest_TISTART),   /* generic */
220       /*  4 */ ALWAYSDEFD(guest_TILEN),     /* generic */
221       /*  5 */ ALWAYSDEFD(guest_IP_AT_SYSCALL), /* generic */
222       /*  6 */ ALWAYSDEFD(guest_IA),        /* control reg */
223       /*  7 */ ALWAYSDEFD(guest_fpc),       /* control reg */
224       /*  8 */ ALWAYSDEFD(guest_counter),   /* internal usage register */
225    }
226 };
227
228 /*------------------------------------------------------------*/
229 /*--- Dirty helper for EXecute                             ---*/
230 /*------------------------------------------------------------*/
231 void
232 s390x_dirtyhelper_EX(ULong torun)
233 {
234    last_execute_target = torun;
235 }
236
237
238 /*------------------------------------------------------------*/
239 /*--- Dirty helper for Clock instructions                  ---*/
240 /*------------------------------------------------------------*/
241 #if defined(VGA_s390x)
242 ULong s390x_dirtyhelper_STCK(ULong *addr)
243 {
244    int cc;
245
246    asm volatile("stck %0\n"
247                 "ipm %1\n"
248                 "srl %1,28\n"
249                 : "+Q" (*addr), "=d" (cc) : : "cc");
250    return cc;
251 }
252
253 ULong s390x_dirtyhelper_STCKE(ULong *addr)
254 {
255    int cc;
256
257    asm volatile("stcke %0\n"
258                 "ipm %1\n"
259                 "srl %1,28\n"
260                 : "+Q" (*addr), "=d" (cc) : : "cc");
261    return cc;
262 }
263
264 ULong s390x_dirtyhelper_STCKF(ULong *addr)
265 {
266    int cc;
267
268    asm volatile(".insn s,0xb27c0000,%0\n"
269                 "ipm %1\n"
270                 "srl %1,28\n"
271                 : "+Q" (*addr), "=d" (cc) : : "cc");
272    return cc;
273 }
274 #else
275 ULong s390x_dirtyhelper_STCK(ULong *addr)  {return 3;}
276 ULong s390x_dirtyhelper_STCKF(ULong *addr) {return 3;}
277 ULong s390x_dirtyhelper_STCKE(ULong *addr) {return 3;}
278 #endif /* VGA_s390x */
279
280 /*------------------------------------------------------------*/
281 /*--- Helper for condition code.                           ---*/
282 /*------------------------------------------------------------*/
283
284 #define S390_CC_FOR_BINARY(opcode,cc_dep1,cc_dep2) \
285 ({ \
286    __asm__ volatile ( \
287         opcode " %[op1],%[op2]\n\t" \
288         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+d"(cc_dep1) \
289                                    : [op2] "d"(cc_dep2) \
290                                    : "cc");\
291    psw >> 28;   /* cc */ \
292 })
293
294 #define S390_CC_FOR_TERNARY_SUBB(opcode,cc_dep1,cc_dep2,cc_ndep) \
295 ({ \
296    /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
297       for rationale. */ \
298    cc_dep2 = cc_dep2 ^ cc_ndep; \
299    __asm__ volatile ( \
300         "lghi 0,1\n\t" \
301         "sr 0,%[op3]\n\t" /* borrow to cc */ \
302         opcode " %[op1],%[op2]\n\t" /* then redo the op */\
303         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \
304                                    : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
305                                    : "0", "cc");\
306    psw >> 28;   /* cc */ \
307 })
308
309 #define S390_CC_FOR_TERNARY_ADDC(opcode,cc_dep1,cc_dep2,cc_ndep) \
310 ({ \
311    /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
312       for rationale. */ \
313    cc_dep2 = cc_dep2 ^ cc_ndep; \
314    __asm__ volatile ( \
315         "lgfr 0,%[op3]\n\t" /* first load cc_ndep */ \
316         "aghi 0,0\n\t" /* and convert it into a cc */ \
317         opcode " %[op1],%[op2]\n\t" /* then redo the op */\
318         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \
319                                    : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
320                                    : "0", "cc");\
321    psw >> 28;   /* cc */ \
322 })
323
324
325 #define S390_CC_FOR_BFP_RESULT(opcode,cc_dep1) \
326 ({ \
327    __asm__ volatile ( \
328         opcode " 0,%[op]\n\t" \
329         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
330                                    : [op]  "f"(cc_dep1) \
331                                    : "cc", "f0");\
332    psw >> 28;   /* cc */ \
333 })
334
335 #define S390_CC_FOR_BFP128_RESULT(hi,lo) \
336 ({ \
337    __asm__ volatile ( \
338         "ldr   4,%[high]\n\t" \
339         "ldr   6,%[low]\n\t" \
340         "ltxbr 0,4\n\t" \
341         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
342                                    : [high] "f"(hi), [low] "f"(lo) \
343                                    : "cc", "f0", "f2", "f4", "f6");\
344    psw >> 28;   /* cc */ \
345 })
346
347 #define S390_CC_FOR_BFP_CONVERT(opcode,cc_dep1) \
348 ({ \
349    __asm__ volatile ( \
350         opcode " 0,0,%[op]\n\t" \
351         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
352                                    : [op]  "f"(cc_dep1) \
353                                    : "cc", "r0");\
354    psw >> 28;   /* cc */ \
355 })
356
357 #define S390_CC_FOR_BFP128_CONVERT(opcode,hi,lo) \
358 ({ \
359    __asm__ volatile ( \
360         "ldr   4,%[high]\n\t" \
361         "ldr   6,%[low]\n\t" \
362         opcode " 0,0,4\n\t" \
363         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
364                                    : [high] "f"(hi), [low] "f"(lo) \
365                                    : "cc", "r0", "f4", "f6");\
366    psw >> 28;   /* cc */ \
367 })
368
369 #define S390_CC_FOR_BFP_TDC(opcode,cc_dep1,cc_dep2) \
370 ({ \
371    __asm__ volatile ( \
372         opcode " %[value],0(%[class])\n\t" \
373         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
374                                    : [value] "f"(cc_dep1), \
375                                      [class] "a"(cc_dep2)  \
376                                    : "cc");\
377    psw >> 28;   /* cc */ \
378 })
379
380 #define S390_CC_FOR_BFP128_TDC(cc_dep1,cc_dep2,cc_ndep) \
381 ({ \
382    /* Recover the original DEP2 value. See comment near s390_cc_thunk_put1f128Z \
383       for rationale. */ \
384    cc_dep2 = cc_dep2 ^ cc_ndep; \
385    __asm__ volatile ( \
386         "ldr  4,%[high]\n\t" \
387         "ldr  6,%[low]\n\t" \
388         "tcxb 4,0(%[class])\n\t" \
389         "ipm  %[psw]\n\t"          : [psw] "=d"(psw) \
390                                    : [high] "f"(cc_dep1), [low] "f"(cc_dep2), \
391                                      [class] "a"(cc_ndep)  \
392                                    : "cc", "f4", "f6");\
393    psw >> 28;   /* cc */ \
394 })
395
396
397 /* Return the value of the condition code from the supplied thunk parameters.
398    This is not the value of the PSW. It is the value of the 2 CC bits within
399    the PSW. The returned value is thusly in the interval [0:3]. */
400 UInt
401 s390_calculate_cc(ULong cc_op, ULong cc_dep1, ULong cc_dep2, ULong cc_ndep)
402 {
403 #if defined(VGA_s390x)
404    UInt psw;
405
406    switch (cc_op) {
407
408    case S390_CC_OP_BITWISE:
409       return S390_CC_FOR_BINARY("ogr", cc_dep1, (ULong)0);
410
411    case S390_CC_OP_SIGNED_COMPARE:
412       return S390_CC_FOR_BINARY("cgr", cc_dep1, cc_dep2);
413
414    case S390_CC_OP_UNSIGNED_COMPARE:
415       return S390_CC_FOR_BINARY("clgr", cc_dep1, cc_dep2);
416
417    case S390_CC_OP_SIGNED_ADD_64:
418       return S390_CC_FOR_BINARY("agr", cc_dep1, cc_dep2);
419
420    case S390_CC_OP_SIGNED_ADD_32:
421       return S390_CC_FOR_BINARY("ar", cc_dep1, cc_dep2);
422
423    case S390_CC_OP_SIGNED_SUB_64:
424       return S390_CC_FOR_BINARY("sgr", cc_dep1, cc_dep2);
425
426    case S390_CC_OP_SIGNED_SUB_32:
427       return S390_CC_FOR_BINARY("sr", cc_dep1, cc_dep2);
428
429    case S390_CC_OP_UNSIGNED_ADD_64:
430       return S390_CC_FOR_BINARY("algr", cc_dep1, cc_dep2);
431
432    case S390_CC_OP_UNSIGNED_ADD_32:
433       return S390_CC_FOR_BINARY("alr", cc_dep1, cc_dep2);
434
435    case S390_CC_OP_UNSIGNED_ADDC_64:
436       return S390_CC_FOR_TERNARY_ADDC("alcgr", cc_dep1, cc_dep2, cc_ndep);
437
438    case S390_CC_OP_UNSIGNED_ADDC_32:
439       return S390_CC_FOR_TERNARY_ADDC("alcr", cc_dep1, cc_dep2, cc_ndep);
440
441    case S390_CC_OP_UNSIGNED_SUB_64:
442       return S390_CC_FOR_BINARY("slgr", cc_dep1, cc_dep2);
443
444    case S390_CC_OP_UNSIGNED_SUB_32:
445       return S390_CC_FOR_BINARY("slr", cc_dep1, cc_dep2);
446
447    case S390_CC_OP_UNSIGNED_SUBB_64:
448       return S390_CC_FOR_TERNARY_SUBB("slbgr", cc_dep1, cc_dep2, cc_ndep);
449
450    case S390_CC_OP_UNSIGNED_SUBB_32:
451       return S390_CC_FOR_TERNARY_SUBB("slbr", cc_dep1, cc_dep2, cc_ndep);
452
453    case S390_CC_OP_LOAD_AND_TEST:
454       /* Like signed comparison with 0 */
455       return S390_CC_FOR_BINARY("cgr", cc_dep1, (Long)0);
456
457    case S390_CC_OP_TEST_AND_SET:
458       /* Shift the sign bit into the LSB. Note, that the tested value is an
459          8-bit value which has been zero-extended to 32/64 bit. */
460       return cc_dep1 >> 7;
461
462    case S390_CC_OP_LOAD_POSITIVE_32:
463       __asm__ volatile (
464            "lpr  %[result],%[op]\n\t"
465            "ipm  %[psw]\n\t"            : [psw] "=d"(psw), [result] "=d"(cc_dep1)
466                                         : [op] "d"(cc_dep1)
467                                         : "cc");
468       return psw >> 28;   /* cc */
469
470    case S390_CC_OP_LOAD_POSITIVE_64:
471       __asm__ volatile (
472            "lpgr %[result],%[op]\n\t"
473            "ipm  %[psw]\n\t"            : [psw] "=d"(psw), [result] "=d"(cc_dep1)
474                                         : [op] "d"(cc_dep1)
475                                         : "cc");
476       return psw >> 28;   /* cc */
477
478    case S390_CC_OP_TEST_UNDER_MASK_8: {
479       UChar value  = cc_dep1;
480       UChar mask   = cc_dep2;
481
482       __asm__ volatile (
483            "bras %%r2,1f\n\t"             /* %r2 = address of next insn */
484            "tm %[value],0\n\t"            /* this is skipped, then EXecuted */
485            "1: ex %[mask],0(%%r2)\n\t"    /* EXecute TM after modifying mask */
486            "ipm %[psw]\n\t"             : [psw] "=d"(psw)
487                                         : [value] "m"(value), [mask] "a"(mask)
488                                         : "r2", "cc");
489       return psw >> 28;   /* cc */
490    }
491
492    case S390_CC_OP_TEST_UNDER_MASK_16: {
493       /* Create a TMLL insn with the mask as given by cc_dep2 */
494       UInt insn  = (0xA701 << 16) | cc_dep2;
495       UInt value = cc_dep1;
496
497       __asm__ volatile (
498            "lr   1,%[value]\n\t"
499            "lhi  2,0x10\n\t"
500            "ex   2,%[insn]\n\t"
501            "ipm  %[psw]\n\t"       : [psw] "=d"(psw)
502                                    : [value] "d"(value), [insn] "m"(insn)
503                                    : "r1", "r2", "cc");
504       return psw >> 28;   /* cc */
505    }
506
507    case S390_CC_OP_SHIFT_LEFT_32:
508       __asm__ volatile (
509            "sla  %[op],0(%[amount])\n\t"
510            "ipm  %[psw]\n\t"            : [psw] "=d"(psw), [op] "+d"(cc_dep1)
511                                         : [amount] "a"(cc_dep2)
512                                         : "cc");
513       return psw >> 28;   /* cc */
514
515    case S390_CC_OP_SHIFT_LEFT_64: {
516       Int high = (Int)(cc_dep1 >> 32);
517       Int low  = (Int)(cc_dep1 & 0xFFFFFFFF);
518
519       __asm__ volatile (
520            "lr   2,%[high]\n\t"
521            "lr   3,%[low]\n\t"
522            "slda 2,0(%[amount])\n\t"
523            "ipm %[psw]\n\t"             : [psw] "=d"(psw), [high] "+d"(high), [low] "+d"(low)
524                                         : [amount] "a"(cc_dep2)
525                                         : "cc", "r2", "r3");
526       return psw >> 28;   /* cc */
527    }
528
529    case S390_CC_OP_INSERT_CHAR_MASK_32: {
530       Int inserted = 0;
531       Int msb = 0;
532
533       if (cc_dep2 & 1) {
534          inserted |= cc_dep1 & 0xff;
535          msb = 0x80;
536       }
537       if (cc_dep2 & 2) {
538          inserted |= cc_dep1 & 0xff00;
539          msb = 0x8000;
540       }
541       if (cc_dep2 & 4) {
542          inserted |= cc_dep1 & 0xff0000;
543          msb = 0x800000;
544       }
545       if (cc_dep2 & 8) {
546          inserted |= cc_dep1 & 0xff000000;
547          msb = 0x80000000;
548       }
549
550       if (inserted & msb)  // MSB is 1
551          return 1;
552       if (inserted > 0)
553          return 2;
554       return 0;
555    }
556
557    case S390_CC_OP_BFP_RESULT_32:
558       return S390_CC_FOR_BFP_RESULT("ltebr", cc_dep1);
559
560    case S390_CC_OP_BFP_RESULT_64:
561       return S390_CC_FOR_BFP_RESULT("ltdbr", cc_dep1);
562
563    case S390_CC_OP_BFP_RESULT_128:
564       return S390_CC_FOR_BFP128_RESULT(cc_dep1, cc_dep2);
565
566    case S390_CC_OP_BFP_32_TO_INT_32:
567       return S390_CC_FOR_BFP_CONVERT("cfebr", cc_dep1);
568
569    case S390_CC_OP_BFP_64_TO_INT_32:
570       return S390_CC_FOR_BFP_CONVERT("cfdbr", cc_dep1);
571
572    case S390_CC_OP_BFP_128_TO_INT_32:
573       return S390_CC_FOR_BFP128_CONVERT("cfxbr", cc_dep1, cc_dep2);
574
575    case S390_CC_OP_BFP_32_TO_INT_64:
576       return S390_CC_FOR_BFP_CONVERT("cgebr", cc_dep1);
577
578    case S390_CC_OP_BFP_64_TO_INT_64:
579       return S390_CC_FOR_BFP_CONVERT("cgdbr", cc_dep1);
580
581    case S390_CC_OP_BFP_128_TO_INT_64:
582       return S390_CC_FOR_BFP128_CONVERT("cgxbr", cc_dep1, cc_dep2);
583
584    case S390_CC_OP_BFP_TDC_32:
585       return S390_CC_FOR_BFP_TDC("tceb", cc_dep1, cc_dep2);
586
587    case S390_CC_OP_BFP_TDC_64:
588       return S390_CC_FOR_BFP_TDC("tcdb", cc_dep1, cc_dep2);
589
590    case S390_CC_OP_BFP_TDC_128:
591       return S390_CC_FOR_BFP128_TDC(cc_dep1, cc_dep2, cc_ndep);
592
593    case S390_CC_OP_SET:
594       return cc_dep1;
595
596    default:
597       break;
598    }
599 #endif
600    vpanic("s390_calculate_cc");
601 }
602
603
604 UInt
605 s390_calculate_icc(ULong op, ULong dep1, ULong dep2)
606 {
607    return s390_calculate_cc(op, dep1, dep2, 0 /* unused */);
608 }
609
610
611 /* Note that this does *not* return a Boolean value. The result needs to be
612    explicitly tested against zero. */
613 UInt
614 s390_calculate_cond(ULong mask, ULong op, ULong dep1, ULong dep2, ULong ndep)
615 {
616    UInt cc = s390_calculate_cc(op, dep1, dep2, ndep);
617
618    return ((mask << cc) & 0x8);
619 }
620
621 /*------------------------------------------------------------*/
622 /*--- spechelper for performance                           ---*/
623 /*------------------------------------------------------------*/
624
625
626 /* Convenience macros */
627 #define unop(op,a1) IRExpr_Unop((op),(a1))
628 #define binop(op,a1,a2) IRExpr_Binop((op),(a1),(a2))
629 #define mkU64(v) IRExpr_Const(IRConst_U64(v))
630 #define mkU32(v) IRExpr_Const(IRConst_U32(v))
631 #define mkU8(v)  IRExpr_Const(IRConst_U8(v))
632
633
634 static inline Bool
635 isC64(IRExpr *expr)
636 {
637    return expr->tag == Iex_Const && expr->Iex.Const.con->tag == Ico_U64;
638 }
639
640
641 /* The returned expression is NULL if no specialization was found. In that
642    case the helper function will be called. Otherwise, the expression has
643    type Ity_I32 and a Boolean value. */
644 IRExpr *
645 guest_s390x_spechelper(HChar *function_name, IRExpr **args,
646                        IRStmt **precedingStmts, Int n_precedingStmts)
647 {
648    UInt i, arity = 0;
649
650    for (i = 0; args[i]; i++)
651       arity++;
652
653 #  if 0
654    vex_printf("spec request:\n");
655    vex_printf("   %s  ", function_name);
656    for (i = 0; i < arity; i++) {
657       vex_printf("  ");
658       ppIRExpr(args[i]);
659    }
660    vex_printf("\n");
661 #  endif
662
663    /* --------- Specialising "s390_calculate_cond" --------- */
664
665    if (vex_streq(function_name, "s390_calculate_cond")) {
666       IRExpr *cond_expr, *cc_op_expr, *cc_dep1, *cc_dep2;
667       ULong cond, cc_op;
668
669       vassert(arity == 5);
670
671       cond_expr  = args[0];
672       cc_op_expr = args[1];
673
674       /* The necessary requirement for all optimizations here is that the
675          condition and the cc_op are constant. So check that upfront. */
676       if (! isC64(cond_expr))  return NULL;
677       if (! isC64(cc_op_expr)) return NULL;
678
679       cond    = cond_expr->Iex.Const.con->Ico.U64;
680       cc_op   = cc_op_expr->Iex.Const.con->Ico.U64;
681
682       vassert(cond <= 15);
683
684       /*
685         +------+---+---+---+---+
686         | cc   | 0 | 1 | 2 | 3 |
687         | cond | 8 | 4 | 2 | 1 |
688         +------+---+---+---+---+
689       */
690       cc_dep1 = args[2];
691       cc_dep2 = args[3];
692
693       /* S390_CC_OP_SIGNED_COMPARE */
694       if (cc_op == S390_CC_OP_SIGNED_COMPARE) {
695          /*
696             cc == 0  --> cc_dep1 == cc_dep2   (cond == 8)
697             cc == 1  --> cc_dep1 <  cc_dep2   (cond == 4)
698             cc == 2  --> cc_dep1 >  cc_dep2   (cond == 2)
699
700             Because cc == 3 cannot occur the rightmost bit of cond is
701             a don't care.
702          */
703          if (cond == 8 || cond == 8 + 1) {
704             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
705          }
706          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
707             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
708          }
709          if (cond == 4 || cond == 4 + 1) {
710             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep1, cc_dep2));
711          }
712          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
713             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, cc_dep2));
714          }
715          /* cc_dep1 > cc_dep2  ---->  cc_dep2 < cc_dep1 */
716          if (cond == 2 || cond == 2 + 1) {
717             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep2, cc_dep1));
718          }
719          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
720             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep2, cc_dep1));
721          }
722          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
723             return mkU32(1);
724          }
725          /* Remaining case */
726          return mkU32(0);
727       }
728
729       /* S390_CC_OP_UNSIGNED_COMPARE */
730       if (cc_op == S390_CC_OP_UNSIGNED_COMPARE) {
731          /*
732             cc == 0  --> cc_dep1 == cc_dep2   (cond == 8)
733             cc == 1  --> cc_dep1 <  cc_dep2   (cond == 4)
734             cc == 2  --> cc_dep1 >  cc_dep2   (cond == 2)
735
736             Because cc == 3 cannot occur the rightmost bit of cond is
737             a don't care.
738          */
739          if (cond == 8 || cond == 8 + 1) {
740             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
741          }
742          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
743             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
744          }
745          if (cond == 4 || cond == 4 + 1) {
746             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
747          }
748          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
749             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
750          }
751          /* cc_dep1 > cc_dep2  ---->  cc_dep2 < cc_dep1 */
752          if (cond == 2 || cond == 2 + 1) {
753             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
754          }
755          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
756             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
757          }
758          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
759             return mkU32(1);
760          }
761          /* Remaining case */
762          return mkU32(0);
763       }
764
765       /* S390_CC_OP_LOAD_AND_TEST */
766       if (cc_op == S390_CC_OP_LOAD_AND_TEST) {
767          /*
768             cc == 0  --> cc_dep1 == 0   (cond == 8)
769             cc == 1  --> cc_dep1 <  0   (cond == 4)
770             cc == 2  --> cc_dep1 >  0   (cond == 2)
771
772             Because cc == 3 cannot occur the rightmost bit of cond is
773             a don't care.
774          */
775          if (cond == 8 || cond == 8 + 1) {
776             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
777          }
778          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
779             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
780          }
781          if (cond == 4 || cond == 4 + 1) {
782             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep1, mkU64(0)));
783          }
784          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
785             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, mkU64(0)));
786          }
787          /* cc_dep1 > 0  ---->  0 < cc_dep1 */
788          if (cond == 2 || cond == 2 + 1) {
789             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, mkU64(0), cc_dep1));
790          }
791          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
792             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, mkU64(0), cc_dep1));
793          }
794          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
795             return mkU32(1);
796          }
797          /* Remaining case */
798          return mkU32(0);
799       }
800
801       /* S390_CC_OP_BITWISE */
802       if (cc_op == S390_CC_OP_BITWISE) {
803          /*
804             cc_dep1 is the result of the boolean operation.
805
806             cc == 0  --> cc_dep1 == 0   (cond == 8)
807             cc == 1  --> cc_dep1 != 0   (cond == 4)
808
809             Because cc == 2 and cc == 3 cannot occur the two rightmost bits of
810             cond are don't cares. Therefore:
811
812             cond == 00xx  -> always false
813             cond == 01xx  -> not equal
814             cond == 10xx  -> equal
815             cond == 11xx  -> always true
816          */
817          if ((cond & (8 + 4)) == 8 + 4) {
818             return mkU32(1);
819          }
820          if (cond & 8) {
821             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
822          }
823          if (cond & 4) {
824             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
825          }
826          /* Remaining case */
827          return mkU32(0);
828       }
829
830       /* S390_CC_OP_INSERT_CHAR_MASK_32
831          Since the mask comes from an immediate field in the opcode, we
832          expect the mask to be a constant here. That simplifies matters. */
833       if (cc_op == S390_CC_OP_INSERT_CHAR_MASK_32) {
834          ULong mask;
835          UInt imask = 0, shift = 0;
836          IRExpr *word;
837
838          if (! isC64(cc_dep2)) goto missed;
839
840          mask = cc_dep2->Iex.Const.con->Ico.U64;
841
842          /* Extract the 32-bit value from the thunk */
843
844          word = unop(Iop_64to32, cc_dep1);
845
846          switch (mask) {
847          case 0:  shift =  0; imask = 0x00000000; break;
848          case 1:  shift = 24; imask = 0x000000FF; break;
849          case 2:  shift = 16; imask = 0x0000FF00; break;
850          case 3:  shift = 16; imask = 0x0000FFFF; break;
851          case 4:  shift =  8; imask = 0x00FF0000; break;
852          case 5:  shift =  8; imask = 0x00FF00FF; break;
853          case 6:  shift =  8; imask = 0x00FFFF00; break;
854          case 7:  shift =  8; imask = 0x00FFFFFF; break;
855          case 8:  shift =  0; imask = 0xFF000000; break;
856          case 9:  shift =  0; imask = 0xFF0000FF; break;
857          case 10: shift =  0; imask = 0xFF00FF00; break;
858          case 11: shift =  0; imask = 0xFF00FFFF; break;
859          case 12: shift =  0; imask = 0xFFFF0000; break;
860          case 13: shift =  0; imask = 0xFFFF00FF; break;
861          case 14: shift =  0; imask = 0xFFFFFF00; break;
862          case 15: shift =  0; imask = 0xFFFFFFFF; break;
863          }
864
865          /* Select the bits that were inserted */
866          word = binop(Iop_And32, word, mkU32(imask));
867
868          /* cc == 0  --> all inserted bits zero or mask == 0   (cond == 8)
869             cc == 1  --> leftmost inserted bit is one          (cond == 4)
870             cc == 2  --> leftmost inserted bit is zero and not (cond == 2)
871                          all inserted bits are zero
872
873             Because cc == 0,1,2 the rightmost bit of the mask is a don't care */
874          if (cond == 8 || cond == 8 + 1) {
875             return unop(Iop_1Uto32, binop(Iop_CmpEQ32, word, mkU32(0)));
876          }
877          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
878             return unop(Iop_1Uto32, binop(Iop_CmpNE32, word, mkU32(0)));
879          }
880
881          /* Sign extend */
882          if (shift != 0) {
883             word = binop(Iop_Sar32, binop(Iop_Shl32, word, mkU8(shift)),
884                          mkU8(shift));
885          }
886
887          if (cond == 4 || cond == 4 + 1) {  /* word < 0 */
888             return unop(Iop_1Uto32, binop(Iop_CmpLT32S, word, mkU32(0)));
889          }
890          if (cond == 2 || cond == 2 + 1) {  /* word > 0 */
891             return unop(Iop_1Uto32, binop(Iop_CmpLT32S, mkU32(0), word));
892          }
893          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
894             return unop(Iop_1Uto32, binop(Iop_CmpLE32S, word, mkU32(0)));
895          }
896          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
897             return unop(Iop_1Uto32, binop(Iop_CmpLE32S, mkU32(0), word));
898          }
899          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
900             return mkU32(1);
901          }
902          /* Remaining case */
903          return mkU32(0);
904       }
905
906       /* S390_CC_OP_TEST_UNDER_MASK_8
907          Since the mask comes from an immediate field in the opcode, we
908          expect the mask to be a constant here. That simplifies matters. */
909       if (cc_op == S390_CC_OP_TEST_UNDER_MASK_8) {
910          ULong mask16;
911
912          if (! isC64(cc_dep2)) goto missed;
913
914          mask16 = cc_dep2->Iex.Const.con->Ico.U64;
915
916          /* Get rid of the mask16 == 0 case first. Some of the simplifications
917             below (e.g. for OVFL) only hold if mask16 == 0.  */
918          if (mask16 == 0) {   /* cc == 0 */
919             if (cond & 0x8) return mkU32(1);
920             return mkU32(0);
921          }
922
923          /* cc == 2 is a don't care */
924          if (cond == 8 || cond == 8 + 2) {
925             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
926                                           binop(Iop_And64, cc_dep1, cc_dep2),
927                                           mkU64(0)));
928          }
929          if (cond == 7 || cond == 7 - 2) {
930             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
931                                           binop(Iop_And64, cc_dep1, cc_dep2),
932                                           mkU64(0)));
933          }
934          if (cond == 1 || cond == 1 + 2) {
935             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
936                                           binop(Iop_And64, cc_dep1, cc_dep2),
937                                           cc_dep2));
938          }
939          if (cond == 14 || cond == 14 - 2) {  /* ! OVFL */
940             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
941                                           binop(Iop_And64, cc_dep1, cc_dep2),
942                                           cc_dep2));
943          }
944          goto missed;
945       }
946
947       /* S390_CC_OP_TEST_UNDER_MASK_16
948          Since the mask comes from an immediate field in the opcode, we
949          expect the mask to be a constant here. That simplifies matters. */
950       if (cc_op == S390_CC_OP_TEST_UNDER_MASK_16) {
951          ULong mask16;
952          UInt msb;
953
954          if (! isC64(cc_dep2)) goto missed;
955
956          mask16 = cc_dep2->Iex.Const.con->Ico.U64;
957
958          /* Get rid of the mask16 == 0 case first. Some of the simplifications
959             below (e.g. for OVFL) only hold if mask16 == 0.  */
960          if (mask16 == 0) {   /* cc == 0 */
961             if (cond & 0x8) return mkU32(1);
962             return mkU32(0);
963          }
964
965          if (cond == 8) {
966             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
967                                           binop(Iop_And64, cc_dep1, cc_dep2),
968                                           mkU64(0)));
969          }
970          if (cond == 7) {
971             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
972                                           binop(Iop_And64, cc_dep1, cc_dep2),
973                                           mkU64(0)));
974          }
975          if (cond == 1) {
976             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
977                                           binop(Iop_And64, cc_dep1, cc_dep2),
978                                           mkU64(mask16)));
979          }
980          if (cond == 14) {  /* ! OVFL */
981             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
982                                           binop(Iop_And64, cc_dep1, cc_dep2),
983                                           mkU64(mask16)));
984          }
985
986          /* Find MSB in mask */
987          msb = 0x8000;
988          while (msb > mask16)
989             msb >>= 1;
990
991          if (cond == 2) {  /* cc == 2 */
992             IRExpr *c1, *c2;
993
994             /* (cc_dep & msb) != 0 && (cc_dep & mask16) != mask16 */
995             c1 = binop(Iop_CmpNE64,
996                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
997             c2 = binop(Iop_CmpNE64,
998                        binop(Iop_And64, cc_dep1, cc_dep2),
999                        mkU64(mask16));
1000             return binop(Iop_And32, unop(Iop_1Uto32, c1),
1001                          unop(Iop_1Uto32, c2));
1002          }
1003
1004          if (cond == 4) {  /* cc == 1 */
1005             IRExpr *c1, *c2;
1006
1007             /* (cc_dep & msb) == 0 && (cc_dep & mask16) != 0 */
1008             c1 = binop(Iop_CmpEQ64,
1009                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
1010             c2 = binop(Iop_CmpNE64,
1011                        binop(Iop_And64, cc_dep1, cc_dep2),
1012                        mkU64(0));
1013             return binop(Iop_And32, unop(Iop_1Uto32, c1),
1014                          unop(Iop_1Uto32, c2));
1015          }
1016
1017          if (cond == 11) {  /* cc == 0,2,3 */
1018             IRExpr *c1, *c2;
1019
1020             c1 = binop(Iop_CmpNE64,
1021                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
1022             c2 = binop(Iop_CmpEQ64,
1023                        binop(Iop_And64, cc_dep1, cc_dep2),
1024                        mkU64(0));
1025             return binop(Iop_Or32, unop(Iop_1Uto32, c1),
1026                          unop(Iop_1Uto32, c2));
1027          }
1028
1029          if (cond == 3) {  /* cc == 2 || cc == 3 */
1030             return unop(Iop_1Uto32,
1031                         binop(Iop_CmpNE64,
1032                               binop(Iop_And64, cc_dep1, mkU64(msb)),
1033                               mkU64(0)));
1034          }
1035          if (cond == 12) { /* cc == 0 || cc == 1 */
1036             return unop(Iop_1Uto32,
1037                         binop(Iop_CmpEQ64,
1038                               binop(Iop_And64, cc_dep1, mkU64(msb)),
1039                               mkU64(0)));
1040          }
1041          // vex_printf("TUM mask = 0x%llx\n", mask16);
1042          goto missed;
1043       }
1044
1045       /* S390_CC_OP_UNSIGNED_SUB_64/32 */
1046       if (cc_op == S390_CC_OP_UNSIGNED_SUB_64 ||
1047           cc_op == S390_CC_OP_UNSIGNED_SUB_32) {
1048          /*
1049             cc_dep1, cc_dep2 are the zero extended left and right operands
1050
1051             cc == 1  --> result != 0, borrow    (cond == 4)
1052             cc == 2  --> result == 0, no borrow (cond == 2)
1053             cc == 3  --> result != 0, no borrow (cond == 1)
1054
1055             cc = (cc_dep1 == cc_dep2) ? 2
1056                                       : (cc_dep1 > cc_dep2) ? 3 : 1;
1057
1058             Because cc == 0 cannot occur the leftmost bit of cond is
1059             a don't care.
1060          */
1061          if (cond == 1 || cond == 1 + 8) {  /* cc == 3   op2 < op1 */
1062             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
1063          }
1064          if (cond == 2 || cond == 2 + 8) {  /* cc == 2 */
1065             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
1066          }
1067          if (cond == 4 || cond == 4 + 8) {  /* cc == 1 */
1068             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
1069          }
1070          if (cond == 3 || cond == 3 + 8) {  /* cc == 2 || cc == 3 */
1071             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
1072          }
1073          if (cond == 6 || cond == 6 + 8) {  /* cc == 2 || cc == 1 */
1074             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
1075          }
1076
1077          if (cond == 5 || cond == 5 + 8) {  /* cc == 3 || cc == 1 */
1078             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
1079          }
1080          if (cond == 7 || cond == 7 + 8) {
1081             return mkU32(1);
1082          }
1083          /* Remaining case */
1084          return mkU32(0);
1085       }
1086
1087       /* S390_CC_OP_UNSIGNED_ADD_64 */
1088       if (cc_op == S390_CC_OP_UNSIGNED_ADD_64) {
1089          /*
1090             cc_dep1, cc_dep2 are the zero extended left and right operands
1091
1092             cc == 0  --> result == 0, no carry  (cond == 8)
1093             cc == 1  --> result != 0, no carry  (cond == 4)
1094             cc == 2  --> result == 0, carry     (cond == 2)
1095             cc == 3  --> result != 0, carry     (cond == 1)
1096          */
1097          if (cond == 8) { /* cc == 0 */
1098             /* Both inputs are 0 */
1099             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
1100                                           binop(Iop_Or64, cc_dep1, cc_dep2),
1101                                           mkU64(0)));
1102          }
1103          if (cond == 7) { /* cc == 1,2,3 */
1104             /* Not both inputs are 0 */
1105             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
1106                                           binop(Iop_Or64, cc_dep1, cc_dep2),
1107                                           mkU64(0)));
1108          }
1109          if (cond == 8 + 2) {  /* cc == 0,2  -> result is zero */
1110             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
1111                                           binop(Iop_Add64, cc_dep1, cc_dep2),
1112                                           mkU64(0)));
1113          }
1114          if (cond == 4 + 1) {  /* cc == 1,3  -> result is not zero */
1115             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
1116                                           binop(Iop_Add64, cc_dep1, cc_dep2),
1117                                           mkU64(0)));
1118          }
1119          goto missed;
1120       }
1121
1122       /* S390_CC_OP_UNSIGNED_ADD_32 */
1123       if (cc_op == S390_CC_OP_UNSIGNED_ADD_32) {
1124          /*
1125             cc_dep1, cc_dep2 are the zero extended left and right operands
1126
1127             cc == 0  --> result == 0, no carry  (cond == 8)
1128             cc == 1  --> result != 0, no carry  (cond == 4)
1129             cc == 2  --> result == 0, carry     (cond == 2)
1130             cc == 3  --> result != 0, carry     (cond == 1)
1131          */
1132          if (cond == 8) { /* cc == 0 */
1133             /* Both inputs are 0 */
1134             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
1135                                           binop(Iop_Or64, cc_dep1, cc_dep2),
1136                                           mkU64(0)));
1137          }
1138          if (cond == 7) { /* cc == 1,2,3 */
1139             /* Not both inputs are 0 */
1140             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
1141                                           binop(Iop_Or64, cc_dep1, cc_dep2),
1142                                           mkU64(0)));
1143          }
1144          if (cond == 8 + 2) {  /* cc == 0,2  -> result is zero */
1145             return unop(Iop_1Uto32, binop(Iop_CmpEQ32,
1146                                           binop(Iop_Add32,
1147                                                 unop(Iop_64to32, cc_dep1),
1148                                                 unop(Iop_64to32, cc_dep2)),
1149                                           mkU32(0)));
1150          }
1151          if (cond == 4 + 1) {  /* cc == 1,3  -> result is not zero */
1152             return unop(Iop_1Uto32, binop(Iop_CmpNE32,
1153                                           binop(Iop_Add32,
1154                                                 unop(Iop_64to32, cc_dep1),
1155                                                 unop(Iop_64to32, cc_dep2)),
1156                                           mkU32(0)));
1157          }
1158          goto missed;
1159       }
1160
1161       /* S390_CC_OP_SET */
1162       if (cc_op == S390_CC_OP_SET) {
1163          /* cc_dep1 is the condition code
1164
1165             Return 1, if ((cond << cc_dep1) & 0x8) != 0 */
1166
1167         return unop(Iop_1Uto32,
1168                     binop(Iop_CmpNE64,
1169                           binop(Iop_And64,
1170                                 binop(Iop_Shl64, cond_expr,
1171                                       unop(Iop_64to8, cc_dep1)),
1172                                 mkU64(8)),
1173                           mkU64(0)));
1174       }
1175
1176       /* S390_CC_OP_TEST_AND_SET */
1177       if (cc_op == S390_CC_OP_TEST_AND_SET) {
1178          /* cc_dep1 is the zero-extended loaded value
1179
1180             cc == 0  --> leftmost bit is zero  (cond == 8)
1181             cc == 1  --> leftmost bit is one   (cond == 4)
1182
1183             As cc is either 0 or 1, only the two leftmost bits of the mask
1184             are relevant. */
1185          IRExpr *bit = binop(Iop_Shr64, cc_dep1, mkU8(7));
1186
1187          switch (cond & (8 + 4)) {
1188          case 0:     return mkU32(0);
1189          case 4:     return unop(Iop_1Uto32, binop(Iop_CmpNE64, bit, mkU64(0)));
1190          case 8:     return unop(Iop_1Uto32, binop(Iop_CmpEQ64, bit, mkU64(0)));
1191          case 8 + 4: return mkU32(1);
1192          }
1193          /* not reached */
1194       }
1195
1196 missed:
1197       ;
1198    }
1199
1200    return NULL;
1201 }
1202
1203 /*---------------------------------------------------------------*/
1204 /*--- end                                guest_s390_helpers.c ---*/
1205 /*---------------------------------------------------------------*/