On 05/12/2010 08:18 AM, Artyom Tarasenko wrote: > It is last year, but > 3e6ba503400c34cbe0f9ad6e289921688bf303a3
> The page 108 of the SPARC Version 8 Architecture Manual describes > that addcc and addxcc shall compute carry flag the same way. > The page 110 claims the same about subcc and subxcc instructions. > This patch fixes carry computation in corner cases and removes redundant > cod > The most visible effect of the patch is enabling Solaris boot when using > OBP I'll contradict you right there by asserting that the manual says no such thing about computing the carry flag "the same way". What it says is: p29: # Carry is set on addition if there is a carry out of bit 31. # Carry is set on subtraction if there is borrow into bit 31. p108: # ADDX and ADDXcc also add the PSR's carry (c) bit; that is # they compute "r[rs1] + r[rs2] + c"... How are the two computations "the same"? First, it says that carry is set if there is carry out. Second, it says that there is the extra addition of the (previous) C bit. If there is an extra addition, there must be an extra chance for carry, and thus the carry flag *cannot* be computed in the same way. Looking closely at the generation of the addx carry (with the attached test program), I see that the original definition of the ADDX carry, as still seen in the _xcc versions, does not generate correct values, and your definition of the carry does. However, that does not mean that we need to use your version of the carry for plain ADD, only for ADDX. I'll send a revised patch sequence shortly. r~
#include <stdio.h> static inline int test_rolw(unsigned short *s) { int i, start, end; asm volatile("rdtsc\n\t" "movl %%eax, %1\n\t" "movzwl %3,%2\n\t" "rolw $8, %w2\n\t" "addl $1,%2\n\t" "rdtsc" : "=&a"(end), "=r"(start), "=r"(i) : "m"(*s) : "edx"); return end - start; } static inline int test_bswap(unsigned short *s) { int i, start, end; asm volatile("rdtsc\n\t" "movl %%eax, %1\n\t" "movzwl %3,%2\n\t" "bswap %2\n\t" "shl $16,%2\n\t" "addl $1,%2\n\t" "rdtsc" : "=&a"(end), "=r"(start), "=r"(i) : "m"(*s) : "edx"); return end - start; } #define N 10 int main() { unsigned t_r[N], t_b[N]; unsigned short s = 0; int i; for (i = 0; i < N; ++i) t_r[i] = test_rolw(&s); for (i = 0; i < N; ++i) t_b[i] = test_bswap(&s); printf("rolw\t"); for (i = 0; i < N; ++i) printf("%5u", t_r[i]); printf("\nbswap\t"); for (i = 0; i < N; ++i) printf("%5u", t_b[i]); printf("\n"); }