It seems the macro assignment is somehow broken if several asm statements follow each other. The code works well on GCC 3.4.3 and older but does not compile any more on 4.0.3. The register usage seems somehow messed up. I tried with and without register for tp in the following code. (I am not sure, where the exact error lied, only that tp has the wrong value after one interation.
# 1 "simdraw16.c" # 1 "/home/prissi/sim//" # 1 "<built-in>" # 1 "<command line>" # 1 "simdraw16.c" typedef unsigned short PIXVAL; extern PIXVAL *textur; extern int disp_width; void display_img_nc(int h, const int xp, const int yp, const PIXVAL *sp) { if(h > 0) { # 44 "simdraw16.c" register PIXVAL *tp asm("eax"); tp = textur + xp + yp*disp_width; register const PIXVAL *img_p asm("esi"); img_p = sp; asm( "cld\n\t" ); do { register unsigned long runlen asm ("ecx"); register PIXVAL *p asm ("edi"); p = tp; asm( "xorl %%ecx,%%ecx\n\t" "movw (%%esi),%%cx\n\t" "addl $2,%%esi" : "=c" (runlen), "=S" (img_p) : "S" (img_p) ); do { asm( "leal (%%edi,%%ecx,2),%%edi\n\t" "movw (%%esi),%%cx\n\t" "addl $2,%%esi\n\t" "testb $1,%%cl\n" "je .Lrlev\n\t" "movsw\n\t" ".Lrlev:\n\t" "shrw %%cx\n\t" "rep\n\t" "movsd\n\t" "movw (%%esi),%%cx\n\t" "addl $2,%%esi\n\t" : "=D" (p), "=S" (img_p) : "c" (runlen), "D" (p), "S" (img_p) : "cc" ); } while(runlen); tp += disp_width; } while(--h); } } As a hack I use the C-variant of the code if GNUC>=4 in the moment (which is sadly about 20-25% slower). -- Summary: x86 inline assembler do not keep register assignment if there are several asm() blocks in a statement Product: gcc Version: 4.0.3 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: prissi at physik dot tu-berlin dot de GCC build triplet: Debian 4.0.3-1 GCC host triplet: i486-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27512