/* x86_convert.c - convert RImage to XImage with x86 optimizations * * Raster graphics library * * Copyright (c) 2000 Alfredo K. Kojima * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #ifdef ASM_X86 #ifdef ASM_X86_MMX int x86_check_mmx() { static int result = -1; if (result >= 0) return result; result = 0; asm volatile ("pushal \n" // please dont forget this in any asm "pushfl \n" // check whether cpuid supported "pop %%eax \n" "movl %%eax, %%ebx \n" "xorl $(1<<21), %%eax \n" "pushl %%eax \n" "popfl \n" "pushfl \n" "popl %%eax \n" "xorl %%ebx, %%eax \n" "andl $(1<<21), %%eax \n" "jz .NotPentium \n" "xorl %%eax, %%eax \n" // no eax effect because of the movl below // except reseting flags. is it needed? "movl $1, %%eax \n" "cpuid \n" "test $(1<<23), %%edx \n" "jz .NotMMX \n" "popal \n" // popal needed because the address of "movl $1, %0 \n" // variable %0 may be kept in a register "jmp .noPop \n" ".NotMMX: \n" ".NotPentium: \n" "popal \n" ".noPop: \n" : "=m" (result)); return result; } /* * TODO: * 32/8 24/8 32/16 24/16 32/24 24/24 * PPlain YES YES * MMX DONE * * * - try to align stack (local variable space) into quadword boundary */ void x86_mmx_TrueColor_32_to_16(unsigned char *image, // 8 unsigned short *ximage, // 12 short *err, // 16 short *nerr, // 20 short *rtable, // 24 short *gtable, // 28 short *btable, // 32 int dr, // 36 int dg, // 40 int db, // 44 unsigned int roffs, // 48 unsigned int goffs, // 52 unsigned int boffs, // 56 int width, // 60 int height, // 64 int line_offset) // 68 { /* int x; //-4 long long rrggbbaa;// -16 long long pixel; //-24 short *tmp_err; //-32 short *tmp_nerr; //-36 */ asm volatile ( "subl $128, %esp \n" // alloc some more stack "pushal \n" // pack dr, dg and db into mm6 "movl 36(%ebp), %eax \n" "movl 40(%ebp), %ebx \n" "movw %ax, -16(%ebp) \n" "movw %bx, -14(%ebp) \n" "movl 44(%ebp), %eax \n" "movw $0, -10(%ebp) \n" "movw %ax, -12(%ebp) \n" "movq -16(%ebp), %mm6 \n" // dr dg db 0 // pack 4|4|4|4 into mm7, for shifting (/16) "movl $0x00040004, -16(%ebp) \n" "movl $0x00040004, -12(%ebp) \n" "movq -16(%ebp), %mm7 \n" // store constant values for using with mmx when dithering "movl $0x00070007, -16(%ebp) \n" "movl $0x00070007, -12(%ebp) \n" "movq -16(%ebp), %mm5 \n" "movl $0x00050005, -16(%ebp) \n" "movl $0x00050005, -12(%ebp) \n" "movq -16(%ebp), %mm4 \n" "movl $0x00030003, -16(%ebp) \n" "movl $0x00030003, -12(%ebp) \n" "movq -16(%ebp), %mm3 \n" // process 1 pixel / cycle, each component treated as 16bit "movl 8(%ebp), %esi \n" // esi = image->data ".LoopYa: \n" "movl 60(%ebp), %eax \n" "movl %eax, -4(%ebp) \n" // x = width "movl 64(%ebp), %eax \n" "decl %eax \n" // y-- "movl %eax, 64(%ebp) \n" "js .Enda \n" // if y < 0, goto end "andl $1, %eax \n" "jz .LoopY_1a \n" // if (y&1) goto LoopY_1 ".LoopY_0a: \n" "movl 16(%ebp), %ebx \n" // ebx = err "movl %ebx, -36(%ebp) \n" // [-36] = err "movl 20(%ebp), %eax \n" // "movl %eax, -32(%ebp) \n" // [-32] = nerr "jmp .LoopXa \n" ".LoopY_1a: \n" "movl 20(%ebp), %ebx \n" // ebx = nerr "movl %ebx, -36(%ebp) \n" // [-36] = nerr "movl 16(%ebp), %eax \n" // "movl %eax, -32(%ebp) \n" // [-32] = eerr ".align 16 \n" ".LoopXa: \n" // calculate errors and pixel components // depend on ebx, esi, mm6 "movq (%ebx), %mm1 \n" // mm1 = error[0..3] "punpcklbw (%esi), %mm0 \n" // mm0 = image->data[0..3] "psrlw $8, %mm0 \n" // fixup mm0 "paddusb %mm1, %mm0 \n" // mm0 = mm0 + mm1 (sat. to 255) "movq %mm0, -24(%ebp) \n" // save the pixel "movzwl -24(%ebp), %ecx \n" // ecx = pixel.red "movl 24(%ebp), %edi \n" // edi = rtable //agi "leal (%edi, %ecx, 2), %eax \n" // eax = &rtable[pixel.red] // agi "movw (%eax), %dx \n" // dx = rtable[pixel.red] "movw %dx, -16(%ebp) \n" // save rr "movzwl -22(%ebp), %ecx \n" // ecx = pixel.green "movl 28(%ebp), %edi \n" // edi = gtable //agi "leal (%edi, %ecx, 2), %eax \n" // eax = >able[pixel.green] //agi "movw (%eax), %dx \n" // dx = gtable[pixel.green] "movw %dx, -14(%ebp) \n" // save gg "movzwl -20(%ebp), %ecx \n" // ecx = pixel.blue "movl 32(%ebp), %edi \n" // ebx = btable //agi "leal (%edi, %ecx, 2), %eax \n" // eax = &btable[pixel.blue] //agi "movw (%eax), %dx \n" // dx = btable[pixel.blue] "movw %dx, -12(%ebp) \n" // save bb "movw $0, -10(%ebp) \n" // save dummy aa "movq -16(%ebp), %mm1 \n" // load mm1 with rrggbbaa "pmullw %mm6, %mm1 \n" // mm1 = rr*dr|... "psubsw %mm1, %mm0 \n" // error = pixel - mm1 // distribute the error // depend on mm0, mm7, mm3, mm4, mm5 "movl -36(%ebp), %ebx \n" "movq %mm0, %mm1 \n" "pmullw %mm5, %mm1 \n" // mm1 = mm1*7 "psrlw %mm7, %mm1 \n" // mm1 = mm1/16 "paddw 8(%ebx), %mm1 \n" "movq %mm1, 8(%ebx) \n" // err[x+1,y] = rer*7/16 "movl -32(%ebp), %ebx \n" "movq %mm0, %mm1 \n" "pmullw %mm4, %mm1 \n" // mm1 = mm1*5 "psrlw %mm7, %mm1 \n" // mm1 = mm1/16 "paddw -8(%ebx), %mm1 \n" "movq %mm1, -8(%ebx) \n" // err[x-1,y+1] += rer*3/16 "movq %mm0, %mm1 \n" "pmullw %mm3, %mm1 \n" // mm1 = mm1*3 "psrlw %mm7, %mm1 \n" // mm1 = mm1/16 "paddw 8(%ebx), %mm1 \n" "movq %mm1, (%ebx) \n" // err[x,y+1] += rer*5/16 "psrlw %mm7, %mm0 \n" // mm0 = mm0/16 "movq %mm0, 8(%ebx) \n" // err[x+1,y+1] = rer/16 // calculate final pixel value and store "movl 48(%ebp), %ecx \n" "movw -16(%ebp), %ax \n" "shlw %cl, %ax \n" //NP* ax = r<data += 4 "decl -4(%ebp) \n" // x-- "jnz .LoopXa \n" // if x>0, goto .LoopX // depend on edx "addl 68(%ebp), %edx \n" // add extra offset to ximage "movl %edx, 12(%ebp) \n" "jmp .LoopYa \n" ".Enda: \n" // THE END "emms \n" "popal \n" ); } void x86_mmx_TrueColor_24_to_16(unsigned char *image, // 8 unsigned short *ximage, // 12 short *err, // 16 short *nerr, // 20 short *rtable, // 24 short *gtable, // 28 short *btable, // 32 int dr, // 36 int dg, // 40 int db, // 44 unsigned int roffs, // 48 unsigned int goffs, // 52 unsigned int boffs, // 56 int width, // 60 int height, // 64 int line_offset) // 68 { /* int x; //-4 long long rrggbbaa;// -16 long long pixel; //-24 short *tmp_err; //-32 short *tmp_nerr; //-36 * int w1; // -64 int w2; // -68 */ asm volatile ( "subl $128, %esp \n" // alloc some more stack "pushal \n" "movl 60(%ebp), %eax \n" // eax = width "movl %eax, %ebx \n" "shrl $2, %eax \n" "movl %eax, -64(%ebp) \n" // w1 = width / 4 "andl $3, %ebx \n" "movl %ebx, -68(%ebp) \n" // w2 = width % 4 ".LoopYc: \n" "movl 60(%ebp), %eax \n" "movl %eax, -4(%ebp) \n" // x = width "decl 64(%ebp) \n" // height-- "js .Endc \n" // if height < 0 then end "movl 64(%ebp), %eax \n" "decl %eax \n" // y-- "movl %eax, 64(%ebp) \n" "js .Endc \n" // if y < 0, goto end "andl $1, %eax \n" "jz .LoopY_1c \n" // if (y&1) goto LoopY_1 ".LoopY_0c: \n" "movl 16(%ebp), %ebx \n" // ebx = err "movl %ebx, -36(%ebp) \n" // [-36] = err "movl 20(%ebp), %eax \n" // "movl %eax, -32(%ebp) \n" // [-32] = nerr "jmp .LoopX_1c \n" ".LoopY_1c: \n" "movl 20(%ebp), %ebx \n" // ebx = nerr "movl %ebx, -36(%ebp) \n" // [-36] = nerr "movl 16(%ebp), %eax \n" // "movl %eax, -32(%ebp) \n" // [-32] = eerr ".align 16 \n" "movl %eax, -4(%ebp) \n" // x = w1 ".LoopX_1c: \n" "decl -4(%ebp) \n" // x-- "js .Xend1_c \n" // if x < 0 then end // do conversion of 4 pixels "movq 16(%ebp), %mm0 \n" // mm0 = err "jmp .LoopX_1c \n" ".Xend1_c: \n" "movl -68(%ebp), %eax \n" "movl %eax, -4(%ebp) \n" // x = w2 ".LoopX_2c: \n" "decl -4(%ebp) \n" // x-- "js .Xend2_c \n" // // do conversion "jmp .LoopX_2c \n" ".Xend2_c: \n" "movl -64(%ebp), %eax \n" "jmp .LoopYc \n" ".Endc: \n" // THE END "emms \n" "popal \n" ); } #endif /* ASM_X86_MMX */ void x86_PseudoColor_32_to_8(unsigned char *image, // 8 unsigned char *ximage, // 12 char *err, // 16 char *nerr, // 20 short *ctable, // 24 int dr, // 28 int dg, // 32 int db, // 36 unsigned long *pixels, // 40 int cpc, // 44 int width, // 48 int height, // 52 int bytesPerPixel, // 56 int line_offset) // 60 { /* * int x; -4 * int cpcpc; -8 * * int rr; -12 * int gg; -16 * int bb; -20 * * char ndr; -21 * char ndg; -22 * char ndb; -23 * * char *err; -32 * char *nerr; -36 * */ asm volatile ( "subl $128, %esp \n" // alloc some stack space "pushal \n" "movl 44(%ebp), %eax \n" "mulb 44(%ebp) \n" "movl %eax, -8(%ebp) \n" // cpcpc = cpc*cpc // eax will always be <= 0xffff // process 1 pixel / cycle, each component treated as 16bit "movl 8(%ebp), %esi \n" // esi = image->data ".LoopYb: \n" "movl 48(%ebp), %ecx \n" "movl %ecx, -4(%ebp) \n" // x = width "movl 52(%ebp), %ecx \n" "decl %ecx \n" // y-- "movl %ecx, 52(%ebp) \n" "js .Endb \n" // if y < 0, goto end "andl $1, %ecx \n" "jz .LoopY_1b \n" // if (y&1) goto LoopY_1 ".LoopY_0b: \n" "movl 16(%ebp), %ebx \n" // ebx = err //useless "movl %ebx, -36(%ebp) \n" // [-36] = err "movl 20(%ebp), %ecx \n" // "movl %ecx, -32(%ebp) \n" // [-32] = nerr "movl $0, (%ecx) \n" // init error of nerr[0] to 0 "jmp .LoopXb \n" ".LoopY_1b: \n" "movl 20(%ebp), %ebx \n" // ebx = nerr //useless "movl %ebx, -36(%ebp) \n" // [-36] = nerr "movl 16(%ebp), %ecx \n" // "movl %ecx, -32(%ebp) \n" // [-32] = err "movl $0, (%ecx) \n" // init error of nerr[0] to 0 ".align 16 \n" ".LoopXb: \n" "movl 24(%ebp), %edi \n" // edi = ctable "xorl %edx, %edx \n" // zero the upper word on edx // RED // depends on ebx==err, esi==image->data, edi "movzbw (%esi), %dx \n" // dx = image->data[0] "movsbw (%ebx), %ax \n" // ax = error[0] "addw %ax, %dx \n" // pixel.red = data[0] + error[0] "testb %dh, %dh \n" // test if pixel.red < 0 or > 255 "jz .OKRb \n" // 0 <= pixel.red <= 255 "js .NEGRb \n" // pixel.red < 0 "movw $0xff, %dx \n" // pixel.red > 255 "jmp .OKRb \n" ".NEGRb: \n" "xorw %dx, %dx \n" ".OKRb: \n" //partial reg "leal (%edi, %edx, 2), %ecx \n" // ecx = &ctable[pixel.red] //agi "movl (%ecx), %eax \n" // ax = ctable[pixel.red] "movw %ax, -12(%ebp) \n" // save rr "mulb 28(%ebp) \n" // ax = rr*dr "subw %ax, %dx \n" // rer = dx = dx - rr*dr "movswl %dx, %eax \n" // save rer // distribute error "leal (, %eax, 8), %ecx \n" "subw %dx, %cx \n" // cx = rer * 7 "sarw $4, %cx \n" // cx = rer * 7 / 16 "addb %cl, 4(%ebx) \n" // err[x+1] += rer * 7 / 16 "movl -32(%ebp), %ecx \n" // ecx = nerr "leaw (%eax, %eax, 4), %dx \n" // dx = rer * 5 "sarw $4, %dx \n" // dx = rer * 5 / 16 "addb %dl, (%ecx) \n" // nerr[x] += rer * 5 / 16 "leaw (%eax, %eax, 2), %dx \n" // dx = rer * 3 "sarw $4, %dx \n" // dx = rer * 3 / 16 "addb %dl, -4(%ecx) \n" // nerr[x-1] += rer * 3 / 16 "sarw $4, %ax \n" // ax = rer / 16 "movb %al, 4(%ecx) \n" // nerr[x+1] = rer / 16 // GREEN // depends on ebx, esi, edi "movzbw 1(%esi), %dx \n" // dx = image->data[1] "movsbw 1(%ebx), %ax \n" // ax = error[1] "addw %ax, %dx \n" // pixel.grn = data[1] + error[1] "testb %dh, %dh \n" // test if pixel.grn < 0 or > 255 "jz .OKGb \n" // 0 <= pixel.grn <= 255 "js .NEGGb \n" // pixel.grn < 0 "movw $0xff, %dx \n" // pixel.grn > 255 "jmp .OKGb \n" ".NEGGb: \n" "xorw %dx, %dx \n" ".OKGb: \n" // partial reg "leal (%edi, %edx, 2), %ecx \n" // ecx = &ctable[pixel.grn] //agi "movw (%ecx), %ax \n" // ax = ctable[pixel.grn] "movw %ax, -16(%ebp) \n" // save gg "mulb 28(%ebp) \n" // ax = gg*dg "subw %ax, %dx \n" // ger = dx = dx - gg*dg "movswl %dx, %eax \n" // save ger // distribute error "leal (, %eax, 8), %ecx \n" "subw %dx, %cx \n" // cx = ger * 7 "sarw $4, %cx \n" // cx = ger * 7 / 16 "addb %cl, 5(%ebx) \n" // err[x+1] += ger * 7 / 16 "movl -32(%ebp), %ecx \n" // ecx = nerr "leaw (%eax, %eax, 4), %dx \n" // dx = ger * 5 "sarw $4, %dx \n" // dx = ger * 5 / 16 "addb %dl, 1(%ecx) \n" // nerr[x] += ger * 5 / 16 "leaw (%eax, %eax, 2), %dx \n" // dx = ger * 3 "sarw $4, %dx \n" // dx = ger * 3 / 16 "addb %dl, -3(%ecx) \n" // nerr[x-1] += ger * 3 / 16 "sarw $4, %ax \n" // ax = ger / 16 "movb %al, 5(%ecx) \n" // nerr[x+1] = ger / 16 // BLUE // depends on ebx, esi "movzbw 2(%esi), %dx \n" // dx = image->data[2] "movsbw 2(%ebx), %ax \n" // ax = error[2] "addw %ax, %dx \n" // pixel.grn = data[2] + error[2] "testb %dh, %dh \n" // test if pixel.blu < 0 or > 255 "jz .OKBb \n" // 0 <= pixel.blu <= 255 "js .NEGBb \n" // pixel.blu < 0 "movw $0xff, %dx \n" // pixel.blu > 255 "jmp .OKBb \n" ".NEGBb: \n" "xorw %dx, %dx \n" ".OKBb: \n" //partial reg "leal (%edi, %edx, 2), %ecx \n" // ecx = &ctable[pixel.blu] //agi "movw (%ecx), %ax \n" // ax = ctable[pixel.blu] "movw %ax, -20(%ebp) \n" // save bb "mulb 28(%ebp) \n" // ax = bb*db "subw %ax, %dx \n" // ber = dx = dx - bb*db "movswl %dx, %eax \n" // save ber // distribute error "leal (, %eax, 8), %ecx \n" "subw %dx, %cx \n" // cx = ber * 7 "sarw $4, %cx \n" // cx = ber * 7 / 16 "addb %cl, 6(%ebx) \n" // err[x+1] += ber * 7 / 16 "movl -32(%ebp), %ecx \n" // ecx = nerr "leaw (%eax, %eax, 4), %dx \n" // dx = ber * 5 "sarw $4, %dx \n" // dx = ber * 5 / 16 "addb %dl, 2(%ecx) \n" // nerr[x] += ber * 5 / 16 "leaw (%eax, %eax, 2), %dx \n" // dx = ber * 3 "sarw $4, %dx \n" // dx = ber * 3 / 16 "addb %dl, -4(%ecx) \n" // nerr[x-1] += ber * 3 / 16 "sarw $4, %ax \n" // ax = ber / 16 "movb %al, 6(%ecx) \n" // nerr[x+1] = ber / 16 "andl $0xffff, %eax \n" // depends on eax & 0xffff0000 == 0 // calculate the index of the value of the pixel "movw -12(%ebp), %ax \n" // ax = rr "mulb -8(%ebp) \n" // ax = cpcpc*rr "movw %ax, %cx \n" "movw -16(%ebp), %ax \n" // ax = gg "mulb 44(%ebp) \n" // ax = cpc*gg "addw %cx, %ax \n" // ax = cpc*gg + cpcpc*rr "addw -20(%ebp), %ax \n" // ax = cpcpc*rr + cpc*gg + bb "movl 40(%ebp), %ecx \n" //agi "leal (%ecx, %eax, 4), %edx \n" //agi "movb (%edx), %cl \n" // cl = pixels[ax] // store the pixel "movl 12(%ebp), %eax \n" "movb %cl, (%eax) \n" // *ximage = cl "incl 12(%ebp) \n" // ximage++ // prepare for next iteration on X "addl $4, -32(%ebp) \n" // nerr += 4 "addl $4, %ebx \n" // err += 4 "addl 56(%ebp), %esi \n" // image->data += bpp "decl -4(%ebp) \n" // x-- "jnz .LoopXb \n" // if x>0, goto .LoopX "movl 60(%ebp), %eax \n" "addl %eax, 12(%ebp) \n" // add extra offset to ximage "jmp .LoopYb \n" ".Endb: \n" "emms \n" "popal \n" ); } #endif /* ASM_X86 */