Skip to content

Commit

Permalink
target-alpha: overflow condition for sublv and subqv
Browse files Browse the repository at this point in the history
The conditions to detect overflow in sub operations was wrong.

This patch is necessary to boot Tru64.

Signed-off-by: Tristan Gingold <[email protected]>
Signed-off-by: Aurelien Jarno <[email protected]>

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7073 c046a42c-6fe2-441c-8c8c-71466251a162
  • Loading branch information
aurel32 committed Apr 10, 2009
1 parent 68238a9 commit ecbb5ea
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 8 deletions.
16 changes: 8 additions & 8 deletions target-alpha/op_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,22 +158,22 @@ uint64_t helper_addlv (uint64_t op1, uint64_t op2)

uint64_t helper_subqv (uint64_t op1, uint64_t op2)
{
uint64_t tmp = op1;
op1 -= op2;
if (unlikely(((~tmp) ^ op1 ^ (-1ULL)) & ((~tmp) ^ op2) & (1ULL << 63))) {
uint64_t res;
res = op1 - op2;
if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) {
helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
}
return op1;
return res;
}

uint64_t helper_sublv (uint64_t op1, uint64_t op2)
{
uint64_t tmp = op1;
op1 = (uint32_t)(op1 - op2);
if (unlikely(((~tmp) ^ op1 ^ (-1UL)) & ((~tmp) ^ op2) & (1UL << 31))) {
uint32_t res;
res = op1 - op2;
if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) {
helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
}
return op1;
return res;
}

uint64_t helper_mullv (uint64_t op1, uint64_t op2)
Expand Down
3 changes: 3 additions & 0 deletions tests/alpha/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ test-cmov.o: test-cond.c
test-cmov: test-cmov.o crt.o
$(LINK)

test-ovf: test-ovf.o crt.o
$(LINK)

check: $(TESTS)
for f in $(TESTS); do $(SIM) $$f || exit 1; done

Expand Down
29 changes: 29 additions & 0 deletions tests/alpha/test-ovf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
static long test_subqv (long a, long b)
{
long res;

asm ("subq/v %1,%2,%0"
: "=r" (res) : "r" (a), "r" (b));
return res;
}
static struct {
long (*func)(long, long);
long a;
long b;
long r;
} vectors[] =
{
{test_subqv, 0, 0x7d54000, 0xfffffffff82ac000L}
};

int main (void)
{
int i;

for (i = 0; i < sizeof (vectors)/sizeof(vectors[0]); i++)
if ((*vectors[i].func)(vectors[i].a, vectors[i].b) != vectors[i].r) {
write(1, "Failed\n", 7);
}
write(1, "OK\n", 3);
return 0;
}

0 comments on commit ecbb5ea

Please sign in to comment.