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