aboutsummaryrefslogtreecommitdiff
path: root/target/ppc/int_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/ppc/int_helper.c')
-rw-r--r--target/ppc/int_helper.c116
1 files changed, 111 insertions, 5 deletions
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index 105b626..3ae03f7 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -789,7 +789,7 @@ static int64_t ger_rank8(uint32_t a, uint32_t b, uint32_t mask)
int64_t psum = 0;
for (int i = 0; i < 8; i++, mask >>= 1) {
if (mask & 1) {
- psum += sextract32(a, 4 * i, 4) * sextract32(b, 4 * i, 4);
+ psum += (int64_t)sextract32(a, 4 * i, 4) * sextract32(b, 4 * i, 4);
}
}
return psum;
@@ -811,7 +811,8 @@ static int64_t ger_rank2(uint32_t a, uint32_t b, uint32_t mask)
int64_t psum = 0;
for (int i = 0; i < 2; i++, mask >>= 1) {
if (mask & 1) {
- psum += sextract32(a, 16 * i, 16) * sextract32(b, 16 * i, 16);
+ psum += (int64_t)sextract32(a, 16 * i, 16) *
+ sextract32(b, 16 * i, 16);
}
}
return psum;
@@ -1162,6 +1163,112 @@ void helper_XXPERMX(ppc_vsr_t *t, ppc_vsr_t *s0, ppc_vsr_t *s1, ppc_vsr_t *pcv,
*t = tmp;
}
+void helper_VDIVSQ(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b)
+{
+ Int128 neg1 = int128_makes64(-1);
+ Int128 int128_min = int128_make128(0, INT64_MIN);
+ if (likely(int128_nz(b->s128) &&
+ (int128_ne(a->s128, int128_min) || int128_ne(b->s128, neg1)))) {
+ t->s128 = int128_divs(a->s128, b->s128);
+ } else {
+ t->s128 = a->s128; /* Undefined behavior */
+ }
+}
+
+void helper_VDIVUQ(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b)
+{
+ if (int128_nz(b->s128)) {
+ t->s128 = int128_divu(a->s128, b->s128);
+ } else {
+ t->s128 = a->s128; /* Undefined behavior */
+ }
+}
+
+void helper_VDIVESD(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b)
+{
+ int i;
+ int64_t high;
+ uint64_t low;
+ for (i = 0; i < 2; i++) {
+ high = a->s64[i];
+ low = 0;
+ if (unlikely((high == INT64_MIN && b->s64[i] == -1) || !b->s64[i])) {
+ t->s64[i] = a->s64[i]; /* Undefined behavior */
+ } else {
+ divs128(&low, &high, b->s64[i]);
+ t->s64[i] = low;
+ }
+ }
+}
+
+void helper_VDIVEUD(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b)
+{
+ int i;
+ uint64_t high, low;
+ for (i = 0; i < 2; i++) {
+ high = a->u64[i];
+ low = 0;
+ if (unlikely(!b->u64[i])) {
+ t->u64[i] = a->u64[i]; /* Undefined behavior */
+ } else {
+ divu128(&low, &high, b->u64[i]);
+ t->u64[i] = low;
+ }
+ }
+}
+
+void helper_VDIVESQ(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b)
+{
+ Int128 high, low;
+ Int128 int128_min = int128_make128(0, INT64_MIN);
+ Int128 neg1 = int128_makes64(-1);
+
+ high = a->s128;
+ low = int128_zero();
+ if (unlikely(!int128_nz(b->s128) ||
+ (int128_eq(b->s128, neg1) && int128_eq(high, int128_min)))) {
+ t->s128 = a->s128; /* Undefined behavior */
+ } else {
+ divs256(&low, &high, b->s128);
+ t->s128 = low;
+ }
+}
+
+void helper_VDIVEUQ(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b)
+{
+ Int128 high, low;
+
+ high = a->s128;
+ low = int128_zero();
+ if (unlikely(!int128_nz(b->s128))) {
+ t->s128 = a->s128; /* Undefined behavior */
+ } else {
+ divu256(&low, &high, b->s128);
+ t->s128 = low;
+ }
+}
+
+void helper_VMODSQ(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b)
+{
+ Int128 neg1 = int128_makes64(-1);
+ Int128 int128_min = int128_make128(0, INT64_MIN);
+ if (likely(int128_nz(b->s128) &&
+ (int128_ne(a->s128, int128_min) || int128_ne(b->s128, neg1)))) {
+ t->s128 = int128_rems(a->s128, b->s128);
+ } else {
+ t->s128 = int128_zero(); /* Undefined behavior */
+ }
+}
+
+void helper_VMODUQ(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b)
+{
+ if (likely(int128_nz(b->s128))) {
+ t->s128 = int128_remu(a->s128, b->s128);
+ } else {
+ t->s128 = int128_zero(); /* Undefined behavior */
+ }
+}
+
void helper_VPERM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
{
ppc_avr_t result;
@@ -1307,14 +1414,13 @@ XXGENPCV(XXGENPCVDM, 8)
#define VBPERMQ_INDEX(avr, i) ((avr)->u8[(i)])
#define VBPERMD_INDEX(i) (i)
#define VBPERMQ_DW(index) (((index) & 0x40) != 0)
-#define EXTRACT_BIT(avr, i, index) (extract64((avr)->u64[i], index, 1))
#else
#define VBPERMQ_INDEX(avr, i) ((avr)->u8[15 - (i)])
#define VBPERMD_INDEX(i) (1 - i)
#define VBPERMQ_DW(index) (((index) & 0x40) == 0)
-#define EXTRACT_BIT(avr, i, index) \
- (extract64((avr)->u64[1 - i], 63 - index, 1))
#endif
+#define EXTRACT_BIT(avr, i, index) \
+ (extract64((avr)->VsrD(i), 63 - index, 1))
void helper_vbpermd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
{