]> git.sesse.net Git - x264/blob - common/x86/cabac-a.asm
c70c671c9d7fbb08dc85006a1974664ac7856818
[x264] / common / x86 / cabac-a.asm
1 ;*****************************************************************************
2 ;* cabac-a.asm: x86 cabac
3 ;*****************************************************************************
4 ;* Copyright (C) 2008-2010 x264 project
5 ;*
6 ;* Authors: Loren Merritt <lorenm@u.washington.edu>
7 ;*          Fiona Glaser <fiona@x264.com>
8 ;*          Holger Lubitz <holger@lubitz.org>
9 ;*
10 ;* This program is free software; you can redistribute it and/or modify
11 ;* it under the terms of the GNU General Public License as published by
12 ;* the Free Software Foundation; either version 2 of the License, or
13 ;* (at your option) any later version.
14 ;*
15 ;* This program is distributed in the hope that it will be useful,
16 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ;* GNU General Public License for more details.
19 ;*
20 ;* You should have received a copy of the GNU General Public License
21 ;* along with this program; if not, write to the Free Software
22 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
23 ;*
24 ;* This program is also available under a commercial proprietary license.
25 ;* For more information, contact us at licensing@x264.com.
26 ;*****************************************************************************
27
28 %include "x86inc.asm"
29
30 SECTION .text
31
32 cextern cabac_range_lps
33 cextern cabac_transition
34 cextern cabac_renorm_shift
35
36 ; t3 must be ecx, since it's used for shift.
37 %ifdef WIN64
38     DECLARE_REG_TMP 3,1,2,0,4,5,6,10,2
39     %define pointer resq
40 %elifdef ARCH_X86_64
41     DECLARE_REG_TMP 0,1,2,3,4,5,6,10,6
42     %define pointer resq
43 %else
44     DECLARE_REG_TMP 0,4,2,1,3,5,6,2,2
45     %define pointer resd
46 %endif
47
48 struc cb
49     .low: resd 1
50     .range: resd 1
51     .queue: resd 1
52     .bytes_outstanding: resd 1
53     .start: pointer 1
54     .p: pointer 1
55     .end: pointer 1
56     align 16, resb 1
57     .bits_encoded: resd 1
58     .state: resb 460
59 endstruc
60
61 %macro LOAD_GLOBAL 4
62 %ifdef PIC
63     ; this would be faster if the arrays were declared in asm, so that I didn't have to duplicate the lea
64     lea   r11, [%2]
65     %ifnidn %3, 0
66     add   r11, %3
67     %endif
68     movzx %1, byte [r11+%4]
69 %else
70     movzx %1, byte [%2+%3+%4]
71 %endif
72 %endmacro
73
74 cglobal cabac_encode_decision_asm, 0,7
75     movifnidn t0,  r0mp
76     movifnidn t1d, r1m
77     mov   t5d, [t0+cb.range]
78     movzx t4d, byte [t0+cb.state+t1]
79     mov   t3d, t5d
80     mov   t6d, t4d
81     shr   t5d, 6
82     shr   t4d, 1
83     movifnidn t2d, r2m
84     LOAD_GLOBAL t5d, cabac_range_lps-4, t5, t4*4
85     LOAD_GLOBAL t4d, cabac_transition, t2, t6*2
86     and   t6d, 1
87     sub   t3d, t5d
88     cmp   t6d, t2d
89     mov   t6d, [t0+cb.low]
90     lea   t7,  [t6+t3]
91     cmovne t3d, t5d
92     cmovne t6d, t7d
93     mov   [t0+cb.state+t1], t4b
94 ;cabac_encode_renorm
95     mov   t4d, t3d
96     shr   t3d, 3
97     LOAD_GLOBAL t3d, cabac_renorm_shift, 0, t3
98     shl   t4d, t3b
99     shl   t6d, t3b
100     add   t3d, [t0+cb.queue]
101     mov   [t0+cb.range], t4d
102     jge cabac_putbyte
103 .update_queue_low:
104     mov   [t0+cb.low], t6d
105     mov   [t0+cb.queue], t3d
106     RET
107
108 cglobal cabac_encode_bypass_asm, 0,3
109     movifnidn  t0, r0mp
110     movifnidn t3d, r1m
111     neg       t3d
112     mov       t8d, [t0+cb.low]
113     and       t3d, [t0+cb.range]
114     lea       t8d, [t8*2+t3]
115     mov       t3d, [t0+cb.queue]
116     inc       t3d
117 %ifdef UNIX64 ; .putbyte compiles to nothing but a jmp
118     jge cabac_putbyte
119 %else
120     jge .putbyte
121 %endif
122     mov   [t0+cb.low], t8d
123     mov   [t0+cb.queue], t3d
124     RET
125 .putbyte:
126     PROLOGUE 0,7
127     movifnidn t6d, t8d
128     jmp cabac_putbyte
129
130 cglobal cabac_encode_terminal_asm, 0,3
131     movifnidn  t0, r0mp
132     sub  dword [t0+cb.range], 2
133 ; shortcut: the renormalization shift in terminal
134 ; can only be 0 or 1 and is zero over 99% of the time.
135     test dword [t0+cb.range], 0x100
136     je .renorm
137     REP_RET
138 .renorm:
139     shl  dword [t0+cb.low], 1
140     shl  dword [t0+cb.range], 1
141     inc  dword [t0+cb.queue]
142     jge .putbyte
143     REP_RET
144 .putbyte:
145     PROLOGUE 0,7
146     mov t3d, [t0+cb.queue]
147     mov t6d, [t0+cb.low]
148     jmp cabac_putbyte
149
150 cabac_putbyte:
151     ; alive: t0=cb t3=queue t6=low
152 %ifdef WIN64
153     DECLARE_REG_TMP 3,4,1,0,2,5,6,10
154 %endif
155     mov   t1d, -1
156     add   t3d, 10
157     mov   t2d, t6d
158     shl   t1d, t3b
159     shr   t2d, t3b ; out
160     not   t1d
161     sub   t3d, 18
162     and   t6d, t1d
163     mov   t5d, [t0+cb.bytes_outstanding]
164     cmp   t2b, 0xff ; FIXME is a 32bit op faster?
165     jz    .postpone
166     mov   t1,  [t0+cb.p]
167     add   [t1-1], dh ; t2h
168     dec   dh
169 .loop_outstanding:
170     mov   [t1], dh
171     inc   t1
172     dec   t5d
173     jge .loop_outstanding
174     mov   [t1-1], t2b
175     mov   [t0+cb.p], t1
176 .postpone:
177     inc   t5d
178     mov   [t0+cb.bytes_outstanding], t5d
179     jmp mangle(x264_cabac_encode_decision_asm.update_queue_low)