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