Revision fc8d72c2 target-s390x/op_helper.c

b/target-s390x/op_helper.c
352 352
    HELPER_LOG("\n");
353 353
}
354 354

  
355
/* 64/64 -> 128 unsigned multiplication */
356
void HELPER(mlg)(uint32_t r1, uint64_t v2)
357
{
358
#if HOST_LONG_BITS == 64 && defined(__GNUC__)
359
    /* assuming 64-bit hosts have __uint128_t */
360
    __uint128_t res = (__uint128_t)env->regs[r1 + 1];
361

  
362
    res *= (__uint128_t)v2;
363
    env->regs[r1] = (uint64_t)(res >> 64);
364
    env->regs[r1 + 1] = (uint64_t)res;
365
#else
366
    mulu64(&env->regs[r1 + 1], &env->regs[r1], env->regs[r1 + 1], v2);
367
#endif
368
}
369

  
370
/* 128 -> 64/64 unsigned division */
371
void HELPER(dlg)(uint32_t r1, uint64_t v2)
372
{
373
    uint64_t divisor = v2;
374

  
375
    if (!env->regs[r1]) {
376
        /* 64 -> 64/64 case */
377
        env->regs[r1] = env->regs[r1 + 1] % divisor;
378
        env->regs[r1 + 1] = env->regs[r1 + 1] / divisor;
379
        return;
380
    } else {
381
#if HOST_LONG_BITS == 64 && defined(__GNUC__)
382
        /* assuming 64-bit hosts have __uint128_t */
383
        __uint128_t dividend = (((__uint128_t)env->regs[r1]) << 64) |
384
            (env->regs[r1 + 1]);
385
        __uint128_t quotient = dividend / divisor;
386
        __uint128_t remainder = dividend % divisor;
387

  
388
        env->regs[r1 + 1] = quotient;
389
        env->regs[r1] = remainder;
390
#else
391
        /* 32-bit hosts would need special wrapper functionality - just abort if
392
           we encounter such a case; it's very unlikely anyways. */
393
        cpu_abort(env, "128 -> 64/64 division not implemented\n");
394
#endif
395
    }
396
}
397

  
398 355
static inline uint64_t get_address(int x2, int b2, int d2)
399 356
{
400 357
    uint64_t r = d2;
......
677 634
    return cc;
678 635
}
679 636

  
680
/* absolute value 32-bit */
681
uint32_t HELPER(abs_i32)(int32_t val)
682
{
683
    if (val < 0) {
684
        return -val;
685
    } else {
686
        return val;
687
    }
688
}
689

  
690
/* negative absolute value 32-bit */
691
int32_t HELPER(nabs_i32)(int32_t val)
692
{
693
    if (val < 0) {
694
        return val;
695
    } else {
696
        return -val;
697
    }
698
}
699

  
700
/* absolute value 64-bit */
701
uint64_t HELPER(abs_i64)(int64_t val)
702
{
703
    HELPER_LOG("%s: val 0x%" PRIx64 "\n", __func__, val);
704

  
705
    if (val < 0) {
706
        return -val;
707
    } else {
708
        return val;
709
    }
710
}
711

  
712
/* negative absolute value 64-bit */
713
int64_t HELPER(nabs_i64)(int64_t val)
714
{
715
    if (val < 0) {
716
        return val;
717
    } else {
718
        return -val;
719
    }
720
}
721

  
722
/* add with carry 32-bit unsigned */
723
uint32_t HELPER(addc_u32)(uint32_t cc, uint32_t v1, uint32_t v2)
724
{
725
    uint32_t res;
726

  
727
    res = v1 + v2;
728
    if (cc & 2) {
729
        res++;
730
    }
731

  
732
    return res;
733
}
734

  
735 637
/* store character under mask high operates on the upper half of r1 */
736 638
void HELPER(stcmh)(uint32_t r1, uint64_t address, uint32_t mask)
737 639
{
......
936 838
    return cc;
937 839
}
938 840

  
939
/* subtract unsigned v2 from v1 with borrow */
940
uint32_t HELPER(slb)(uint32_t cc, uint32_t r1, uint32_t v2)
941
{
942
    uint32_t v1 = env->regs[r1];
943
    uint32_t res = v1 + (~v2) + (cc >> 1);
944

  
945
    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | res;
946
    if (cc & 2) {
947
        /* borrow */
948
        return v1 ? 1 : 0;
949
    } else {
950
        return v1 ? 3 : 2;
951
    }
952
}
953

  
954
/* subtract unsigned v2 from v1 with borrow */
955
uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2)
956
{
957
    uint64_t res = v1 + (~v2) + (cc >> 1);
958

  
959
    env->regs[r1] = res;
960
    if (cc & 2) {
961
        /* borrow */
962
        return v1 ? 1 : 0;
963
    } else {
964
        return v1 ? 3 : 2;
965
    }
966
}
967

  
968
/* find leftmost one */
969
uint32_t HELPER(flogr)(uint32_t r1, uint64_t v2)
970
{
971
    uint64_t res = 0;
972
    uint64_t ov2 = v2;
973

  
974
    while (!(v2 & 0x8000000000000000ULL) && v2) {
975
        v2 <<= 1;
976
        res++;
977
    }
978

  
979
    if (!v2) {
980
        env->regs[r1] = 64;
981
        env->regs[r1 + 1] = 0;
982
        return 0;
983
    } else {
984
        env->regs[r1] = res;
985
        env->regs[r1 + 1] = ov2 & ~(0x8000000000000000ULL >> res);
986
        return 2;
987
    }
988
}
989

  
990 841
/* checksum */
991 842
void HELPER(cksm)(uint32_t r1, uint32_t r2)
992 843
{
......
1026 877
        ((uint32_t)cksm + (cksm >> 32));
1027 878
}
1028 879

  
1029
uint64_t HELPER(cvd)(int32_t bin)
1030
{
1031
    /* positive 0 */
1032
    uint64_t dec = 0x0c;
1033
    int shift = 4;
1034

  
1035
    if (bin < 0) {
1036
        bin = -bin;
1037
        dec = 0x0d;
1038
    }
1039

  
1040
    for (shift = 4; (shift < 64) && bin; shift += 4) {
1041
        int current_number = bin % 10;
1042

  
1043
        dec |= (current_number) << shift;
1044
        bin /= 10;
1045
    }
1046

  
1047
    return dec;
1048
}
1049

  
1050 880
void HELPER(unpk)(uint32_t len, uint64_t dest, uint64_t src)
1051 881
{
1052 882
    int len_dest = len >> 4;

Also available in: Unified diff