Imported Upstream version 3.0.1
[platform/upstream/libjpeg-turbo.git] / simd / x86_64 / jquanti-sse2.asm
1 ;
2 ; jquanti.asm - sample data conversion and quantization (64-bit SSE2)
3 ;
4 ; Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
5 ; Copyright (C) 2009, 2016, D. R. Commander.
6 ; Copyright (C) 2018, Matthias Räncker.
7 ;
8 ; Based on the x86 SIMD extension for IJG JPEG library
9 ; Copyright (C) 1999-2006, MIYASAKA Masaru.
10 ; For conditions of distribution and use, see copyright notice in jsimdext.inc
11 ;
12 ; This file should be assembled with NASM (Netwide Assembler),
13 ; can *not* be assembled with Microsoft's MASM or any compatible
14 ; assembler (including Borland's Turbo Assembler).
15 ; NASM is available from http://nasm.sourceforge.net/ or
16 ; http://sourceforge.net/project/showfiles.php?group_id=6208
17
18 %include "jsimdext.inc"
19 %include "jdct.inc"
20
21 ; --------------------------------------------------------------------------
22     SECTION     SEG_TEXT
23     BITS        64
24 ;
25 ; Load data into workspace, applying unsigned->signed conversion
26 ;
27 ; GLOBAL(void)
28 ; jsimd_convsamp_sse2(JSAMPARRAY sample_data, JDIMENSION start_col,
29 ;                     DCTELEM *workspace);
30 ;
31
32 ; r10 = JSAMPARRAY sample_data
33 ; r11d = JDIMENSION start_col
34 ; r12 = DCTELEM *workspace
35
36     align       32
37     GLOBAL_FUNCTION(jsimd_convsamp_sse2)
38
39 EXTN(jsimd_convsamp_sse2):
40     push        rbp
41     mov         rbp, rsp
42     collect_args 3
43     push        rbx
44
45     pxor        xmm6, xmm6              ; xmm6=(all 0's)
46     pcmpeqw     xmm7, xmm7
47     psllw       xmm7, 7                 ; xmm7={0xFF80 0xFF80 0xFF80 0xFF80 ..}
48
49     mov         rsi, r10
50     mov         eax, r11d
51     mov         rdi, r12
52     mov         rcx, DCTSIZE/4
53 .convloop:
54     mov         rbxp, JSAMPROW [rsi+0*SIZEOF_JSAMPROW]  ; (JSAMPLE *)
55     mov         rdxp, JSAMPROW [rsi+1*SIZEOF_JSAMPROW]  ; (JSAMPLE *)
56
57     movq        xmm0, XMM_MMWORD [rbx+rax*SIZEOF_JSAMPLE]  ; xmm0=(01234567)
58     movq        xmm1, XMM_MMWORD [rdx+rax*SIZEOF_JSAMPLE]  ; xmm1=(89ABCDEF)
59
60     mov         rbxp, JSAMPROW [rsi+2*SIZEOF_JSAMPROW]  ; (JSAMPLE *)
61     mov         rdxp, JSAMPROW [rsi+3*SIZEOF_JSAMPROW]  ; (JSAMPLE *)
62
63     movq        xmm2, XMM_MMWORD [rbx+rax*SIZEOF_JSAMPLE]  ; xmm2=(GHIJKLMN)
64     movq        xmm3, XMM_MMWORD [rdx+rax*SIZEOF_JSAMPLE]  ; xmm3=(OPQRSTUV)
65
66     punpcklbw   xmm0, xmm6              ; xmm0=(01234567)
67     punpcklbw   xmm1, xmm6              ; xmm1=(89ABCDEF)
68     paddw       xmm0, xmm7
69     paddw       xmm1, xmm7
70     punpcklbw   xmm2, xmm6              ; xmm2=(GHIJKLMN)
71     punpcklbw   xmm3, xmm6              ; xmm3=(OPQRSTUV)
72     paddw       xmm2, xmm7
73     paddw       xmm3, xmm7
74
75     movdqa      XMMWORD [XMMBLOCK(0,0,rdi,SIZEOF_DCTELEM)], xmm0
76     movdqa      XMMWORD [XMMBLOCK(1,0,rdi,SIZEOF_DCTELEM)], xmm1
77     movdqa      XMMWORD [XMMBLOCK(2,0,rdi,SIZEOF_DCTELEM)], xmm2
78     movdqa      XMMWORD [XMMBLOCK(3,0,rdi,SIZEOF_DCTELEM)], xmm3
79
80     add         rsi, byte 4*SIZEOF_JSAMPROW
81     add         rdi, byte 4*DCTSIZE*SIZEOF_DCTELEM
82     dec         rcx
83     jnz         short .convloop
84
85     pop         rbx
86     uncollect_args 3
87     pop         rbp
88     ret
89
90 ; --------------------------------------------------------------------------
91 ;
92 ; Quantize/descale the coefficients, and store into coef_block
93 ;
94 ; This implementation is based on an algorithm described in
95 ;   "How to optimize for the Pentium family of microprocessors"
96 ;   (http://www.agner.org/assem/).
97 ;
98 ; GLOBAL(void)
99 ; jsimd_quantize_sse2(JCOEFPTR coef_block, DCTELEM *divisors,
100 ;                     DCTELEM *workspace);
101 ;
102
103 %define RECIPROCAL(m, n, b) \
104   XMMBLOCK(DCTSIZE * 0 + (m), (n), (b), SIZEOF_DCTELEM)
105 %define CORRECTION(m, n, b) \
106   XMMBLOCK(DCTSIZE * 1 + (m), (n), (b), SIZEOF_DCTELEM)
107 %define SCALE(m, n, b) \
108   XMMBLOCK(DCTSIZE * 2 + (m), (n), (b), SIZEOF_DCTELEM)
109
110 ; r10 = JCOEFPTR coef_block
111 ; r11 = DCTELEM *divisors
112 ; r12 = DCTELEM *workspace
113
114     align       32
115     GLOBAL_FUNCTION(jsimd_quantize_sse2)
116
117 EXTN(jsimd_quantize_sse2):
118     push        rbp
119     mov         rbp, rsp
120     collect_args 3
121
122     mov         rsi, r12
123     mov         rdx, r11
124     mov         rdi, r10
125     mov         rax, DCTSIZE2/32
126 .quantloop:
127     movdqa      xmm4, XMMWORD [XMMBLOCK(0,0,rsi,SIZEOF_DCTELEM)]
128     movdqa      xmm5, XMMWORD [XMMBLOCK(1,0,rsi,SIZEOF_DCTELEM)]
129     movdqa      xmm6, XMMWORD [XMMBLOCK(2,0,rsi,SIZEOF_DCTELEM)]
130     movdqa      xmm7, XMMWORD [XMMBLOCK(3,0,rsi,SIZEOF_DCTELEM)]
131     movdqa      xmm0, xmm4
132     movdqa      xmm1, xmm5
133     movdqa      xmm2, xmm6
134     movdqa      xmm3, xmm7
135     psraw       xmm4, (WORD_BIT-1)
136     psraw       xmm5, (WORD_BIT-1)
137     psraw       xmm6, (WORD_BIT-1)
138     psraw       xmm7, (WORD_BIT-1)
139     pxor        xmm0, xmm4
140     pxor        xmm1, xmm5
141     pxor        xmm2, xmm6
142     pxor        xmm3, xmm7
143     psubw       xmm0, xmm4              ; if (xmm0 < 0) xmm0 = -xmm0;
144     psubw       xmm1, xmm5              ; if (xmm1 < 0) xmm1 = -xmm1;
145     psubw       xmm2, xmm6              ; if (xmm2 < 0) xmm2 = -xmm2;
146     psubw       xmm3, xmm7              ; if (xmm3 < 0) xmm3 = -xmm3;
147
148     paddw       xmm0, XMMWORD [CORRECTION(0,0,rdx)]  ; correction + roundfactor
149     paddw       xmm1, XMMWORD [CORRECTION(1,0,rdx)]
150     paddw       xmm2, XMMWORD [CORRECTION(2,0,rdx)]
151     paddw       xmm3, XMMWORD [CORRECTION(3,0,rdx)]
152     pmulhuw     xmm0, XMMWORD [RECIPROCAL(0,0,rdx)]  ; reciprocal
153     pmulhuw     xmm1, XMMWORD [RECIPROCAL(1,0,rdx)]
154     pmulhuw     xmm2, XMMWORD [RECIPROCAL(2,0,rdx)]
155     pmulhuw     xmm3, XMMWORD [RECIPROCAL(3,0,rdx)]
156     pmulhuw     xmm0, XMMWORD [SCALE(0,0,rdx)]       ; scale
157     pmulhuw     xmm1, XMMWORD [SCALE(1,0,rdx)]
158     pmulhuw     xmm2, XMMWORD [SCALE(2,0,rdx)]
159     pmulhuw     xmm3, XMMWORD [SCALE(3,0,rdx)]
160
161     pxor        xmm0, xmm4
162     pxor        xmm1, xmm5
163     pxor        xmm2, xmm6
164     pxor        xmm3, xmm7
165     psubw       xmm0, xmm4
166     psubw       xmm1, xmm5
167     psubw       xmm2, xmm6
168     psubw       xmm3, xmm7
169     movdqa      XMMWORD [XMMBLOCK(0,0,rdi,SIZEOF_DCTELEM)], xmm0
170     movdqa      XMMWORD [XMMBLOCK(1,0,rdi,SIZEOF_DCTELEM)], xmm1
171     movdqa      XMMWORD [XMMBLOCK(2,0,rdi,SIZEOF_DCTELEM)], xmm2
172     movdqa      XMMWORD [XMMBLOCK(3,0,rdi,SIZEOF_DCTELEM)], xmm3
173
174     add         rsi, byte 32*SIZEOF_DCTELEM
175     add         rdx, byte 32*SIZEOF_DCTELEM
176     add         rdi, byte 32*SIZEOF_JCOEF
177     dec         rax
178     jnz         near .quantloop
179
180     uncollect_args 3
181     pop         rbp
182     ret
183
184 ; For some reason, the OS X linker does not honor the request to align the
185 ; segment unless we do this.
186     align       32