Conclusion : the computation of the V flag in qemu is correct, and their is
no special case to consider if the C flag is set or not :-)
For tomorrow, the formal proof of the correctness of the whole qemu code
;-)
Thanks for the superb analysis!
Now it's time to check if real hardware works according to theory.
In this addition, there is a carry from lower 32 bits as well as sign
change:
./addx -1 0x7fffffff 1 0
7fffffffffffffff + 1 = 8000000000000000, NZVC: 10
qemu-sparc ./addx -1 0x7fffffff 1 0
7fffffffffffffff + 1 = 8000000000000000, NZVC: 10
Here, no carry:
./addx -1 0x7fffffff 0 1
7fffffffffffffff + 100000000 = 80000000ffffffff, NZVC: 10
qemu-sparc ./addx -1 0x7fffffff 0 1
7fffffffffffffff + 100000000 = 80000000ffffffff, NZVC: 10
Another case:
./addx 0 0x80000000 0 0x80000000
8000000000000000 + 8000000000000000 = 0, NZVC: 7
qemu-sparc ./addx 0 0x80000000 0 0x80000000
8000000000000000 + 8000000000000000 = 0, NZVC: 7
Looks fine to me. There was a sign extension problem in the test program,
fixed version attached.
_________________________________________________________________
Express yourself instantly with MSN Messenger! Download today it's FREE!
http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/
#include <stdlib.h>
#include <stdio.h>
void addx_test(unsigned int a, unsigned int b, unsigned int c, unsigned int d)
{
unsigned int flags, result1, result2;
asm ("addcc %3,%5,%1\n\t"
"addxcc %4,%6,%2\n\t"
"mov 0, %0\n\t"
"bcc 1f\n\t"
" nop\n\t"
"mov 1, %0\n\t"
"1: \n\t"
"bvc 1f\n\t"
" nop\n\t"
"or %0, 2, %0\n\t"
"1: \n\t"
"bnz 1f\n\t"
" nop\n\t"
"or %0, 4, %0\n\t"
"1: \n\t"
"bpos 1f\n\t"
" nop\n\t"
"or %0, 8, %0\n\t"
"1: \n\t"
: "=r" (flags), "=r" (result1), "=r" (result2) : "r" (a), "r" (b), "r" (c), "r" (d));
printf("%llx + %llx = %llx, NZVC: %d\n", ((unsigned long long)b << 32) | (unsigned long long)a,
((unsigned long long)d << 32) | (unsigned long long)c,
((unsigned long long)result2 << 32) | (unsigned long long)result1,
flags);
}
int main(int argc, const char **argv)
{
unsigned int a, b, c, d;
if (argc != 5)
return 1;
a = strtoul(argv[1], NULL, 0);
b = strtoul(argv[2], NULL, 0);
c = strtoul(argv[3], NULL, 0);
d = strtoul(argv[4], NULL, 0);
addx_test(a, b, c, d);
return 0;
}
_______________________________________________
Qemu-devel mailing list
Qemu-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/qemu-devel