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