home *** CD-ROM | disk | FTP | other *** search
/ Spidla DivX / DivX.bin / LocoCodec / lococodec_a.asm < prev    next >
Encoding:
Assembly Source File  |  2003-03-30  |  9.0 KB  |  486 lines

  1. ;
  2. ; lococodec v0.1 based on:
  3. ;
  4. ; Huffyuv v2.1.1, by Ben Rudiak-Gould.
  5. ; http://www.math.berkeley.edu/~benrg/huffyuv.html
  6. ;
  7. ; This file is copyright 2000 Ben Rudiak-Gould, and distributed under
  8. ; the terms of the GNU General Public License, v2 or later.  See
  9. ; http://www.gnu.org/copyleft/gpl.html.
  10. ;
  11.  
  12. ;
  13. ; This file makes heavy use of macros to define a bunch of almost-identical
  14. ; functions -- see lococodec_a.h.
  15. ;
  16.  
  17.     .586
  18.     .mmx
  19.     .model    flat
  20.  
  21. ; alignment has to be 'page' so that I can use 'align 32' below
  22.  
  23. _TEXT64    segment    page public use32 'CODE'
  24.  
  25. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  26.  
  27.  
  28. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  29.  
  30.     PUBLIC    C _mmx_RowDiff
  31.  
  32. ;void __cdecl mmx_RowDiff(
  33. ;    [esp+ 4] unsigned char* src,
  34. ;    [esp+ 8] unsigned char* dst,
  35. ;    [esp+12] unsigned char* src_end,
  36. ;    [esp+16] int stride);
  37.  
  38. _mmx_RowDiff    PROC
  39.  
  40.     push    ebp
  41.     push    edi
  42.     push    esi
  43.     push    ebx
  44.  
  45.     mov    esi,[esp+4+16]
  46.     mov    edi,[esp+8+16]
  47.     mov    ecx,[esp+16+16]
  48.     add    ecx,esi
  49.  
  50.     cmp    esi,edi
  51.     je    diff
  52.  
  53.     ; make sure we're 8-byte aligned
  54. loop0:
  55.     test    edi,7
  56.     jz    endloop0
  57.     mov    al,[esi]
  58.     inc    esi
  59.     mov    [edi],al
  60.     inc    edi
  61.     jmp    loop0
  62. endloop0:
  63.  
  64.     ; copy the (rest of the) first row
  65. loop1:
  66.     movq    mm0,[esi]
  67.     movq    mm1,[esi+8]
  68.     add    esi,16
  69.     movq    [edi],mm0
  70.     movq    [edi+8],mm1
  71.     add    edi,16
  72.     cmp    esi,ecx
  73.     jb    loop1
  74.  
  75.     ; diff the remaining rows
  76. diff:
  77.     mov    esi,[esp+12+16]
  78.     mov    ecx,[esp+4+16]
  79.     mov    edi,[esp+8+16]
  80.     mov    ebx,[esp+16+16]
  81.     add    edi,esi
  82.     sub    edi,ecx
  83.     add    ecx,ebx
  84.     neg    ebx
  85.  
  86.     ; align again (sigh...)
  87. loop2:
  88.     test    edi,7
  89.     jz    endloop2
  90.     mov    al,[esi-1]
  91.     sub    al,[esi+ebx-1]
  92.     dec    esi
  93.     mov    [edi-1],al
  94.     dec    edi
  95.     jmp    loop2
  96. endloop2:
  97.  
  98.     mov    edx,32
  99.     sub    esi,edx
  100.     sub    edi,edx
  101.     align    32
  102. loop3:
  103.     movq    mm3,[esi+24]
  104.     movq    mm2,[esi+16]
  105.     movq    mm6,[esi+ebx+16]
  106.     psubb    mm3,[esi+ebx+24]    ; 2
  107.     psubb    mm2,mm6
  108.     movq    mm1,[esi+8]
  109.     movq    [edi+24],mm3        ; 2
  110.     movq    mm5,[esi+ebx+8]
  111.     movq    mm0,[esi]
  112.     movq    [edi+16],mm2        ; 2
  113.     psubb    mm1,mm5
  114.     psubb    mm0,[esi+ebx]        ; 2
  115.     sub    esi,edx
  116.     movq    [edi+8],mm1        ; 2
  117.     cmp    esi,ecx
  118.     movq    [edi],mm0        ; 2
  119.     lea    edi,[edi-32]
  120.     jae    loop3
  121.  
  122.     ; and more alignment
  123.     add    esi,edx
  124.     add    edi,edx
  125. loop4:
  126.     cmp    esi,ecx
  127.     jbe    endloop4
  128.     mov    al,[esi-1]
  129.     sub    al,[esi+ebx-1]
  130.     dec    esi
  131.     mov    [edi-1],al
  132.     dec    edi
  133.     jmp    loop4
  134. endloop4:
  135.  
  136.     emms
  137.     pop    ebx
  138.     pop    esi
  139.     pop    edi
  140.     pop    ebp
  141.     retn
  142.  
  143. _mmx_RowDiff    ENDP
  144.  
  145. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  146.  
  147.     PUBLIC    C _mmx_RowAccum
  148.  
  149. ;void __cdecl mmx_RowAccum(
  150. ;    [esp+ 4] unsigned char* buf,
  151. ;    [esp+ 8] unsigned char* buf_end,
  152. ;    [esp+12] int stride);
  153.  
  154. _mmx_RowAccum    PROC
  155.  
  156.     push    ebp
  157.     push    esi
  158.     push    ebx
  159.  
  160.     mov    esi,[esp+4+12]
  161.     mov    ebx,[esp+12+12]
  162.     add    esi,ebx
  163.     neg    ebx
  164.  
  165. loop0:
  166.     test    esi,7
  167.     jz    endloop0
  168.     mov    al,[esi+ebx]
  169.     add    [esi],al
  170.     inc    esi
  171.     jmp    loop0
  172. endloop0:
  173.  
  174.     mov    ecx,[esp+8+12]
  175.     sub    ecx,32
  176.     align    32
  177. loop1:
  178.     movq    mm0,[esi]
  179.     movq    mm1,[esi+8]
  180.     movq    mm5,[esi+ebx+24]
  181.     paddb    mm0,[esi+ebx]
  182.     movq    mm2,[esi+16]
  183.     movq    mm4,[esi+ebx+16]
  184.     paddb    mm1,[esi+ebx+8]
  185.     movq    mm3,[esi+24]
  186.     paddb    mm2,mm4
  187.     movq    [esi],mm0
  188.     paddb    mm3,mm5
  189.     movq    [esi+8],mm1
  190.     movq    [esi+16],mm2
  191.     movq    [esi+24],mm3
  192.     add    esi,32
  193.     cmp    esi,ecx
  194.     jbe    loop1
  195.  
  196.     ; cleanup end in case of misalignment
  197.     add    ecx,32
  198. loop2:
  199.     cmp    esi,ecx
  200.     jae    endloop2
  201.     mov    al,[esi+ebx]
  202.     add    [esi],al
  203.     inc    esi
  204.     jmp    loop2
  205. endloop2:
  206.  
  207.     emms
  208.     pop    ebx
  209.     pop    esi
  210.     pop    ebp
  211.     retn
  212.  
  213. _mmx_RowAccum    ENDP
  214.  
  215. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  216.  
  217. YUV_SHIFT    MACRO    mmb,mma,uyvy    ; clobbers mm4,5
  218.  
  219. ; mma:mmb = ABCDEFGHIJKLMNOP (VYUYVYUY...) - backwards from mem order
  220. ;   we want mmb = EDGFIHKJ (prev pixel of same channel)
  221.  
  222.     movq    mm4,mmb
  223.     punpcklbw    mmb,mma        ; mm4:mmb = AIBJCKDLEMFNGOHP
  224.     punpckhbw    mm4,mma
  225.     movq    mm5,mmb
  226.     punpcklbw    mmb,mm4        ; mm5:mmb = AEIMBFJNCGKODHLP
  227.     punpckhbw    mm5,mm4
  228.     movq    mm4,mmb
  229.     punpcklbw    mmb,mm5        ; mm4:mmb = ACEGIKMOBDFHJLNP
  230.     punpckhbw    mm4,mm5
  231.     psllq    mmb,8+8*&uyvy        ; mm4:mmb = EGIKMO__DFHJLNP_
  232.     psllq    mm4,16-8*&uyvy
  233.     punpckhbw    mmb,mm4        ; mmb = EDGFIHKJ (for YUY2; different for UYVY)
  234.  
  235.     ENDM
  236.  
  237. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  238.  
  239.  
  240.  
  241.  
  242.  
  243. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  244.  
  245.     PUBLIC    C _asm_SwapFields
  246.  
  247. _asm_SwapFields    PROC
  248.  
  249. ;void __cdecl asm_SwapFields(
  250. ;    [esp+ 4] unsigned char* buf,
  251. ;    [esp+ 8] unsigned char* buf_end,
  252. ;    [esp+12] int stride);
  253.  
  254.     push    ebp
  255.     push    esi
  256.     push    ebx
  257.  
  258.     mov    esi,[esp+4+12]
  259.     mov    ebp,[esp+8+12]
  260.     mov    ebx,[esp+12+12]
  261.  
  262. loop0:
  263.     mov    ecx,ebx
  264.     shr    ecx,2
  265. loop1:
  266.     mov    eax,[esi]
  267.     mov    edx,[esi+ebx]
  268.     dec    ecx
  269.     mov    [esi+ebx],eax
  270.     mov    [esi],edx
  271.     lea    esi,[esi+4]
  272.     jnz    loop1
  273.     add    esi,ebx
  274.     cmp    esi,ebp
  275.     jb    loop0
  276.  
  277.     pop    ebx
  278.     pop    esi
  279.     pop    ebp
  280.     retn
  281.  
  282. _asm_SwapFields    ENDP
  283.  
  284. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  285.  
  286.     align    8
  287.  
  288. yuv2rgb_constants:
  289.  
  290. x0000_0000_0010_0010    dq    00000000000100010h
  291. x0080_0080_0080_0080    dq    00080008000800080h
  292. x00FF_00FF_00FF_00FF    dq    000FF00FF00FF00FFh
  293. x00002000_00002000    dq    00000200000002000h
  294. cy            dq    000004A8500004A85h
  295. crv            dq    03313000033130000h
  296. cgu_cgv            dq    0E5FCF377E5FCF377h
  297. cbu            dq    00000408D0000408Dh
  298.  
  299. ofs_x0000_0000_0010_0010 = 0
  300. ofs_x0080_0080_0080_0080 = 8
  301. ofs_x00FF_00FF_00FF_00FF = 16
  302. ofs_x00002000_00002000 = 24
  303. ofs_cy = 32
  304. ofs_crv = 40
  305. ofs_cgu_cgv = 48
  306. ofs_cbu = 56
  307.  
  308. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  309.  
  310. GET_Y    MACRO    mma,uyvy
  311. IF &uyvy
  312.     psrlw        mma,8
  313. ELSE
  314.     pand        mma,[edx+ofs_x00FF_00FF_00FF_00FF]
  315. ENDIF
  316.     ENDM
  317.  
  318. GET_UV    MACRO    mma,uyvy
  319.     GET_Y        mma,1-uyvy
  320.     ENDM
  321.  
  322. YUV2RGB_INNER_LOOP    MACRO    uyvy,rgb32,no_next_pixel
  323.  
  324. ;; This YUV422->RGB conversion code uses only four MMX registers per
  325. ;; source dword, so I convert two dwords in parallel.  Lines corresponding
  326. ;; to the "second pipe" are indented an extra space.  There's almost no
  327. ;; overlap, except at the end and in the two lines marked ***.
  328.  
  329.     movd        mm0,[esi]
  330.      movd         mm5,[esi+4]
  331.     movq        mm1,mm0
  332.     GET_Y        mm0,&uyvy    ; mm0 = __________Y1__Y0
  333.      movq         mm4,mm5
  334.     GET_UV        mm1,&uyvy    ; mm1 = __________V0__U0
  335.      GET_Y         mm4,&uyvy
  336.     movq        mm2,mm5        ; *** avoid reload from [esi+4]
  337.      GET_UV         mm5,&uyvy
  338.     psubw        mm0,[edx+ofs_x0000_0000_0010_0010]
  339.      movd         mm6,[esi+8-4*(no_next_pixel)]
  340.     GET_UV        mm2,&uyvy    ; mm2 = __________V2__U2
  341.      psubw         mm4,[edx+ofs_x0000_0000_0010_0010]
  342.     paddw        mm2,mm1
  343.      GET_UV         mm6,&uyvy
  344.     psubw        mm1,[edx+ofs_x0080_0080_0080_0080]
  345.      paddw         mm6,mm5
  346.     psllq        mm2,32
  347.      psubw         mm5,[edx+ofs_x0080_0080_0080_0080]
  348.     punpcklwd    mm0,mm2        ; mm0 = ______Y1______Y0
  349.      psllq         mm6,32
  350.     pmaddwd        mm0,[edx+ofs_cy]    ; mm0 scaled
  351.      punpcklwd     mm4,mm6
  352.     paddw        mm1,mm1
  353.      pmaddwd     mm4,[edx+ofs_cy]
  354.      paddw         mm5,mm5
  355.     paddw        mm1,mm2        ; mm1 = __V1__U1__V0__U0 * 2
  356.     paddd        mm0,[edx+ofs_x00002000_00002000]
  357.      paddw         mm5,mm6
  358.     movq        mm2,mm1
  359.      paddd         mm4,[edx+ofs_x00002000_00002000]
  360.     movq        mm3,mm1
  361.      movq         mm6,mm5
  362.     pmaddwd        mm1,[edx+ofs_crv]
  363.      movq         mm7,mm5
  364.     paddd        mm1,mm0
  365.      pmaddwd     mm5,[edx+ofs_crv]
  366.     psrad        mm1,14        ; mm1 = RRRRRRRRrrrrrrrr
  367.      paddd         mm5,mm4
  368.     pmaddwd        mm2,[edx+ofs_cgu_cgv]
  369.      psrad         mm5,14
  370.     paddd        mm2,mm0
  371.      pmaddwd     mm6,[edx+ofs_cgu_cgv]
  372.     psrad        mm2,14        ; mm2 = GGGGGGGGgggggggg
  373.      paddd         mm6,mm4
  374.     pmaddwd        mm3,[edx+ofs_cbu]
  375.      psrad         mm6,14
  376.     paddd        mm3,mm0
  377.      pmaddwd     mm7,[edx+ofs_cbu]
  378.        add           esi,8
  379.        add           edi,12+4*rgb32
  380. IFE &no_next_pixel
  381.        cmp           esi,ecx
  382. ENDIF
  383.     psrad        mm3,14        ; mm3 = BBBBBBBBbbbbbbbb
  384.      paddd         mm7,mm4
  385.     pxor        mm0,mm0
  386.      psrad         mm7,14
  387.     packssdw    mm3,mm2    ; mm3 = GGGGggggBBBBbbbb
  388.      packssdw     mm7,mm6
  389.     packssdw    mm1,mm0    ; mm1 = ________RRRRrrrr
  390.      packssdw     mm5,mm0    ; *** avoid pxor mm4,mm4
  391.     movq        mm2,mm3
  392.      movq         mm6,mm7
  393.     punpcklwd    mm2,mm1    ; mm2 = RRRRBBBBrrrrbbbb
  394.      punpcklwd     mm6,mm5
  395.     punpckhwd    mm3,mm1    ; mm3 = ____GGGG____gggg
  396.      punpckhwd     mm7,mm5
  397.     movq        mm0,mm2
  398.      movq         mm4,mm6
  399.     punpcklwd    mm0,mm3    ; mm0 = ____rrrrggggbbbb
  400.      punpcklwd     mm4,mm7
  401. IFE &rgb32
  402.     psllq        mm0,16
  403.      psllq         mm4,16
  404. ENDIF
  405.     punpckhwd    mm2,mm3    ; mm2 = ____RRRRGGGGBBBB
  406.      punpckhwd     mm6,mm7
  407.     packuswb    mm0,mm2    ; mm0 = __RRGGBB__rrggbb <- ta dah!
  408.      packuswb     mm4,mm6
  409.  
  410. IF &rgb32
  411.     movd    [edi-16],mm0    ; store the quadwords independently
  412.      movd     [edi-8],mm4    ; (and in pieces since we may not be aligned)
  413.     psrlq    mm0,32
  414.      psrlq     mm4,32
  415.     movd    [edi-12],mm0
  416.      movd     [edi-4],mm4
  417. ELSE
  418.     psrlq    mm0,8        ; pack the two quadwords into 12 bytes
  419.     psllq    mm4,8        ; (note: the two shifts above leave
  420.     movd    [edi-12],mm0    ; mm0,4 = __RRGGBBrrggbb__)
  421.     psrlq    mm0,32
  422.     por    mm4,mm0
  423.     movd    [edi-8],mm4
  424.     psrlq    mm4,32
  425.     movd    [edi-4],mm4
  426. ENDIF
  427.  
  428.     ENDM
  429.  
  430. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  431.  
  432. YUV2RGB_PROC    MACRO    procname,uyvy,rgb32
  433.  
  434.     PUBLIC    C _&procname
  435.  
  436. ;;void __cdecl procname(
  437. ;;    [esp+ 4] const unsigned char* src,
  438. ;;    [esp+ 8] unsigned char* dst,
  439. ;;    [esp+12] const unsigned char* src_end,
  440. ;;    [esp+16] int stride);
  441.  
  442. _&procname    PROC
  443.  
  444.     push    esi
  445.     push    edi
  446.  
  447.     mov    eax,[esp+16+8]
  448.     mov    esi,[esp+12+8]        ; read source bottom-up
  449.     mov    edi,[esp+8+8]
  450.     mov    edx,offset yuv2rgb_constants
  451.  
  452. loop0:
  453.     lea    ecx,[esi-8]
  454.     sub    esi,eax
  455.  
  456.     align 32
  457. loop1:
  458.     YUV2RGB_INNER_LOOP    uyvy,rgb32,0
  459.     jb    loop1
  460.  
  461.     YUV2RGB_INNER_LOOP    uyvy,rgb32,1
  462.  
  463.     sub    esi,eax
  464.     cmp    esi,[esp+4+8]
  465.     ja    loop0
  466.  
  467.     emms
  468.     pop    edi
  469.     pop    esi
  470.     retn
  471.  
  472. _&procname    ENDP
  473.  
  474.     ENDM
  475.  
  476. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  477.  
  478. YUV2RGB_PROC    mmx_YUY2toRGB24,0,0
  479. YUV2RGB_PROC    mmx_YUY2toRGB32,0,1
  480. YUV2RGB_PROC    mmx_UYVYtoRGB24,1,0
  481. YUV2RGB_PROC    mmx_UYVYtoRGB32,1,1
  482.  
  483. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  484.  
  485.     END
  486.