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