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 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 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 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 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 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 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 282 ULong s390x_dirtyhelper_STCK(ULong *addr) {return 3;} 283 ULong s390x_dirtyhelper_STCKF(ULong *addr) {return 3;} 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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