Home | History | Annotate | Download | only in cpu_ref
      1 /*
      2  * Copyright (C) 2013-2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define ENTRY(f) .text; .align 4; .globl f; .type f,#function; f: .fnstart
     18 #define END(f) .fnend; .size f, .-f;
     19 
     20 #define BLEND_LIST(X) \
     21     X(0, CLEAR) \
     22     X(1, SRC) \
     23     X(2, DST) \
     24     X(3, SRC_OVER) \
     25     X(4, DST_OVER) \
     26     X(5, SRC_IN) \
     27     X(6, DST_IN) \
     28     X(7, SRC_OUT) \
     29     X(8, DST_OUT) \
     30     X(9, SRC_ATOP) \
     31     X(10, DST_ATOP) \
     32     X(11, XOR) \
     33     X(14, MULTIPLY) \
     34     X(21, DIFFERENCE) \
     35     X(34, ADD) \
     36     X(35, SUBTRACT)
     37 
     38 .eabi_attribute 25,1 @Tag_ABI_align8_preserved
     39 .arm
     40 
     41 /* For every blend operation supported, define a macro with just the arithmetic
     42  * component.  The rest can be handled later on.
     43  *
     44  * At entry q0-q3 contain the RGBA data from the destination buffer, and q8-q11
     45  * contain the data from the source buffer.  Both have already been split out
     46  * into one colour component per register (if necessary).  q3 and q11 contain
     47  * the alpha components.
     48  *
     49  * At the same time as defining the assembly macro, define a corresponding
     50  * preprocessor macro indicating any other requirements.
     51  *    zipped=0 -- The macro does not require the RGBA components to be
     52  *                separated.
     53  *    lddst=0  -- The macro does not require data from the destination buffer.
     54  *    ldsrc=0  -- The macro does not require data from the source buffer.
     55  *    nowrap=1 -- The macro requires no wrapper at all, and should simply be
     56  *                inserted without any surrounding load/store or loop code.
     57  */
     58 
     59 #define params_CLEAR zipped=0, lddst=0, ldsrc=0
     60 .macro blend_kernel_CLEAR
     61         vmov.i8 q0, #0
     62         vmov.i8 q1, #0
     63         vmov.i8 q2, #0
     64         vmov.i8 q3, #0
     65 .endm
     66 
     67 #define params_SRC zipped=0, lddst=0
     68 .macro blend_kernel_SRC
     69         vmov    q0, q8
     70         vmov    q1, q9
     71         vmov    q2, q10
     72         vmov    q3, q11
     73 .endm
     74 
     75 #define params_DST nowrap=1
     76 .macro blend_kernel_DST
     77         /* nop */
     78 .endm
     79 
     80 #define params_SRC_OVER zipped=1
     81 .macro blend_kernel_SRC_OVER
     82         vmvn        q7, q11
     83 
     84         vmull.u8    q12, d15, d1
     85         vmull.u8    q0,  d14, d0
     86         vmull.u8    q13, d15, d3
     87         vmull.u8    q1,  d14, d2
     88         vmull.u8    q14, d15, d5
     89         vmull.u8    q2,  d14, d4
     90         vmull.u8    q15, d15, d7
     91         vmull.u8    q3,  d14, d6
     92 
     93         vrshrn.u16  d8,  q0,  #8
     94         vrshrn.u16  d9,  q12, #8
     95         vrshrn.u16  d10, q1,  #8
     96         vrshrn.u16  d11, q13, #8
     97         vrshrn.u16  d12, q2,  #8
     98         vrshrn.u16  d13, q14, #8
     99         vrshrn.u16  d14, q3,  #8
    100         vrshrn.u16  d15, q15, #8
    101 
    102         vaddw.u8    q0,  d8
    103         vaddw.u8    q12, d9
    104         vaddw.u8    q1,  d10
    105         vaddw.u8    q13, d11
    106         vaddw.u8    q2,  d12
    107         vaddw.u8    q14, d13
    108         vaddw.u8    q3,  d14
    109         vaddw.u8    q15, d15
    110 
    111         vrshrn.u16  d0, q0,  #8
    112         vrshrn.u16  d1, q12, #8
    113         vrshrn.u16  d2, q1,  #8
    114         vrshrn.u16  d3, q13, #8
    115         vrshrn.u16  d4, q2,  #8
    116         vrshrn.u16  d5, q14, #8
    117         vrshrn.u16  d6, q3,  #8
    118         vrshrn.u16  d7, q15, #8
    119 
    120         vqadd.u8    q0, q8
    121         vqadd.u8    q1, q9
    122         vqadd.u8    q2, q10
    123         vqadd.u8    q3, q11
    124 .endm
    125 
    126 #define params_DST_OVER zipped=1
    127 .macro blend_kernel_DST_OVER
    128         vmvn        q7, q3
    129 
    130         vmull.u8    q12, d15, d17
    131         vmull.u8    q8,  d14, d16
    132         vmull.u8    q13, d15, d19
    133         vmull.u8    q9,  d14, d18
    134         vmull.u8    q14, d15, d21
    135         vmull.u8    q10, d14, d20
    136         vmull.u8    q15, d15, d23
    137         vmull.u8    q11, d14, d22
    138 
    139         vrshrn.u16  d8,  q0,  #8
    140         vrshrn.u16  d9,  q12, #8
    141         vrshrn.u16  d10, q1,  #8
    142         vrshrn.u16  d11, q13, #8
    143         vrshrn.u16  d12, q2,  #8
    144         vrshrn.u16  d13, q14, #8
    145         vrshrn.u16  d14, q3,  #8
    146         vrshrn.u16  d15, q15, #8
    147 
    148         vaddw.u8    q8,  d8
    149         vaddw.u8    q12, d9
    150         vaddw.u8    q9,  d10
    151         vaddw.u8    q13, d11
    152         vaddw.u8    q10, d12
    153         vaddw.u8    q14, d13
    154         vaddw.u8    q11, d14
    155         vaddw.u8    q15, d15
    156 
    157         vrshrn.u16  d16, q8,  #8
    158         vrshrn.u16  d17, q12, #8
    159         vrshrn.u16  d18, q9,  #8
    160         vrshrn.u16  d19, q13, #8
    161         vrshrn.u16  d20, q10, #8
    162         vrshrn.u16  d21, q14, #8
    163         vrshrn.u16  d22, q11, #8
    164         vrshrn.u16  d23, q15, #8
    165 
    166         vqadd.u8    q0, q8
    167         vqadd.u8    q1, q9
    168         vqadd.u8    q2, q10
    169         vqadd.u8    q3, q11
    170 .endm
    171 
    172 #define params_SRC_IN zipped=1
    173 .macro blend_kernel_SRC_IN
    174         vmull.u8    q12, d7, d17
    175         vmull.u8    q0,  d6, d16
    176         vmull.u8    q13, d7, d19
    177         vmull.u8    q1,  d6, d18
    178         vmull.u8    q14, d7, d21
    179         vmull.u8    q2,  d6, d20
    180         vmull.u8    q15, d7, d23
    181         vmull.u8    q3,  d6, d22
    182 
    183         vrshrn.u16  d8,  q0,  #8
    184         vrshrn.u16  d9,  q12, #8
    185         vrshrn.u16  d10, q1,  #8
    186         vrshrn.u16  d11, q13, #8
    187         vrshrn.u16  d12, q2,  #8
    188         vrshrn.u16  d13, q14, #8
    189         vrshrn.u16  d14, q3,  #8
    190         vrshrn.u16  d15, q15, #8
    191 
    192         vaddw.u8    q0,  d8
    193         vaddw.u8    q12, d9
    194         vaddw.u8    q1,  d10
    195         vaddw.u8    q13, d11
    196         vaddw.u8    q2,  d12
    197         vaddw.u8    q14, d13
    198         vaddw.u8    q3,  d14
    199         vaddw.u8    q15, d15
    200 
    201         vrshrn.u16  d0, q0,  #8
    202         vrshrn.u16  d1, q12, #8
    203         vrshrn.u16  d2, q1,  #8
    204         vrshrn.u16  d3, q13, #8
    205         vrshrn.u16  d4, q2,  #8
    206         vrshrn.u16  d5, q14, #8
    207         vrshrn.u16  d6, q3,  #8
    208         vrshrn.u16  d7, q15, #8
    209 .endm
    210 
    211 #define params_DST_IN zipped=1
    212 .macro blend_kernel_DST_IN
    213         vmull.u8    q12, d1, d23
    214         vmull.u8    q0,  d0, d22
    215         vmull.u8    q13, d3, d23
    216         vmull.u8    q1,  d2, d22
    217         vmull.u8    q14, d5, d23
    218         vmull.u8    q2,  d4, d22
    219         vmull.u8    q15, d7, d23
    220         vmull.u8    q3,  d6, d22
    221 
    222         vrshrn.u16  d8,  q0,  #8
    223         vrshrn.u16  d9,  q12, #8
    224         vrshrn.u16  d10, q1,  #8
    225         vrshrn.u16  d11, q13, #8
    226         vrshrn.u16  d12, q2,  #8
    227         vrshrn.u16  d13, q14, #8
    228         vrshrn.u16  d14, q3,  #8
    229         vrshrn.u16  d15, q15, #8
    230 
    231         vaddw.u8    q0,  d8
    232         vaddw.u8    q12, d9
    233         vaddw.u8    q1,  d10
    234         vaddw.u8    q13, d11
    235         vaddw.u8    q2,  d12
    236         vaddw.u8    q14, d13
    237         vaddw.u8    q3,  d14
    238         vaddw.u8    q15, d15
    239 
    240         vrshrn.u16  d0, q0,  #8
    241         vrshrn.u16  d1, q12, #8
    242         vrshrn.u16  d2, q1,  #8
    243         vrshrn.u16  d3, q13, #8
    244         vrshrn.u16  d4, q2,  #8
    245         vrshrn.u16  d5, q14, #8
    246         vrshrn.u16  d6, q3,  #8
    247         vrshrn.u16  d7, q15, #8
    248 .endm
    249 
    250 #define params_SRC_OUT zipped=1
    251 .macro blend_kernel_SRC_OUT
    252         vmvn        q3, q3
    253         blend_kernel_SRC_IN
    254 .endm
    255 
    256 
    257 #define params_DST_OUT zipped=1
    258 .macro blend_kernel_DST_OUT
    259         vmvn        q11, q11
    260         blend_kernel_DST_IN
    261 .endm
    262 
    263 #define params_SRC_ATOP zipped=1
    264 .macro blend_kernel_SRC_ATOP
    265         vmvn        q11, q11
    266 
    267         vmull.u8    q12, d23, d1
    268         vmull.u8    q0,  d22, d0
    269         vmull.u8    q13, d23, d3
    270         vmull.u8    q1,  d22, d2
    271         vmull.u8    q14, d23, d5
    272         vmull.u8    q2,  d22, d4
    273 
    274         vmull.u8    q4,  d7, d17
    275         vmull.u8    q8,  d6, d16
    276         vmull.u8    q5,  d7, d19
    277         vmull.u8    q9,  d6, d18
    278         vmull.u8    q6,  d7, d21
    279         vmull.u8    q10, d6, d20
    280 
    281         vqadd.u16   q12, q4
    282         vqadd.u16   q0,  q8
    283         vqadd.u16   q13, q5
    284         vqadd.u16   q1,  q9
    285         vqadd.u16   q14, q6
    286         vqadd.u16   q2,  q10
    287 
    288         vrshr.u16   q8,  q0,  #8
    289         vrshr.u16   q4,  q12, #8
    290         vrshr.u16   q9,  q1,  #8
    291         vrshr.u16   q5,  q13, #8
    292         vrshr.u16   q10, q2,  #8
    293         vrshr.u16   q6,  q14, #8
    294 
    295         vqadd.u16   q0,  q8
    296         vqadd.u16   q12, q4
    297         vqadd.u16   q1,  q9
    298         vqadd.u16   q13, q5
    299         vqadd.u16   q2,  q10
    300         vqadd.u16   q14, q6
    301 
    302         vqrshrn.u16 d0, q0,  #8
    303         vqrshrn.u16 d1, q12, #8
    304         vqrshrn.u16 d2, q1,  #8
    305         vqrshrn.u16 d3, q13, #8
    306         vqrshrn.u16 d4, q2,  #8
    307         vqrshrn.u16 d5, q14, #8
    308 .endm
    309 
    310 #define params_DST_ATOP zipped=1
    311 .macro blend_kernel_DST_ATOP
    312         vmvn        q3, q3
    313 
    314         vmull.u8    q12, d23, d1
    315         vmull.u8    q0,  d22, d0
    316         vmull.u8    q13, d23, d3
    317         vmull.u8    q1,  d22, d2
    318         vmull.u8    q14, d23, d5
    319         vmull.u8    q2,  d22, d4
    320 
    321         vmull.u8    q4,  d7, d17
    322         vmull.u8    q8,  d6, d16
    323         vmull.u8    q5,  d7, d19
    324         vmull.u8    q9,  d6, d18
    325         vmull.u8    q6,  d7, d21
    326         vmull.u8    q10, d6, d20
    327 
    328         vqadd.u16   q12, q4
    329         vqadd.u16   q0,  q8
    330         vqadd.u16   q13, q5
    331         vqadd.u16   q1,  q9
    332         vqadd.u16   q14, q6
    333         vqadd.u16   q2,  q10
    334 
    335         vrshr.u16   q8,  q0,  #8
    336         vrshr.u16   q4,  q12, #8
    337         vrshr.u16   q9,  q1,  #8
    338         vrshr.u16   q5,  q13, #8
    339         vrshr.u16   q10, q2,  #8
    340         vrshr.u16   q6,  q14, #8
    341 
    342         vqadd.u16   q0,  q8
    343         vqadd.u16   q12, q4
    344         vqadd.u16   q1,  q9
    345         vqadd.u16   q13, q5
    346         vqadd.u16   q2,  q10
    347         vqadd.u16   q14, q6
    348 
    349         vqrshrn.u16 d0, q0,  #8
    350         vqrshrn.u16 d1, q12, #8
    351         vqrshrn.u16 d2, q1,  #8
    352         vqrshrn.u16 d3, q13, #8
    353         vqrshrn.u16 d4, q2,  #8
    354         vqrshrn.u16 d5, q14, #8
    355 
    356         vmov        q3, q11
    357 .endm
    358 
    359 #define params_MULTIPLY zipped=0
    360 .macro blend_kernel_MULTIPLY
    361         vmull.u8    q12, d1, d17
    362         vmull.u8    q0,  d0, d16
    363         vmull.u8    q13, d3, d19
    364         vmull.u8    q1,  d2, d18
    365         vmull.u8    q14, d5, d21
    366         vmull.u8    q2,  d4, d20
    367         vmull.u8    q15, d7, d23
    368         vmull.u8    q3,  d6, d22
    369 
    370         vrshrn.u16  d8,  q0,  #8
    371         vrshrn.u16  d9,  q12, #8
    372         vrshrn.u16  d10, q1,  #8
    373         vrshrn.u16  d11, q13, #8
    374         vrshrn.u16  d12, q2,  #8
    375         vrshrn.u16  d13, q14, #8
    376         vrshrn.u16  d14, q3,  #8
    377         vrshrn.u16  d15, q15, #8
    378 
    379         vaddw.u8    q0,  d8
    380         vaddw.u8    q12, d9
    381         vaddw.u8    q1,  d10
    382         vaddw.u8    q13, d11
    383         vaddw.u8    q2,  d12
    384         vaddw.u8    q14, d13
    385         vaddw.u8    q3,  d14
    386         vaddw.u8    q15, d15
    387 
    388         vrshrn.u16  d0, q0,  #8
    389         vrshrn.u16  d1, q12, #8
    390         vrshrn.u16  d2, q1,  #8
    391         vrshrn.u16  d3, q13, #8
    392         vrshrn.u16  d4, q2,  #8
    393         vrshrn.u16  d5, q14, #8
    394         vrshrn.u16  d6, q3,  #8
    395         vrshrn.u16  d7, q15, #8
    396 .endm
    397 
    398 #define params_ADD zipped=0
    399 .macro blend_kernel_ADD
    400         vqadd.u8 q0, q0, q8
    401         vqadd.u8 q1, q1, q9
    402         vqadd.u8 q2, q2, q10
    403         vqadd.u8 q3, q3, q11
    404 .endm
    405 
    406 #define params_SUBTRACT zipped=0
    407 .macro blend_kernel_SUBTRACT
    408         vqsub.u8 q0, q0, q8
    409         vqsub.u8 q1, q1, q9
    410         vqsub.u8 q2, q2, q10
    411         vqsub.u8 q3, q3, q11
    412 .endm
    413 
    414 #define params_DIFFERENCE zipped=0
    415 .macro blend_kernel_DIFFERENCE
    416         vabd.u8 q0, q0, q8
    417         vabd.u8 q1, q1, q9
    418         vabd.u8 q2, q2, q10
    419         vabd.u8 q3, q3, q11
    420 .endm
    421 
    422 #define params_XOR zipped=0
    423 .macro blend_kernel_XOR
    424         veor    q0, q0, q8
    425         veor    q1, q1, q9
    426         veor    q2, q2, q10
    427         veor    q3, q3, q11
    428 .endm
    429 
    430 
    431 /* Define the wrapper code which will load and store the data, iterate the
    432  * correct number of times, and safely handle the remainder at the end of the
    433  * loop.  Various sections of assembly code are dropped or substituted for
    434  * simpler operations if they're not needed.
    435  */
    436 .macro wrap_line kernel, nowrap=0, zipped=1, lddst=1, ldsrc=1, pld=1
    437 .if \nowrap
    438         \kernel
    439 .else
    440         vpush   {d8-d15}
    441         subs    r2, #64
    442         b       2f
    443         .align 4
    444 1:
    445   .if \lddst
    446     .if \zipped
    447         vld4.8  {d0,d2,d4,d6}, [r0]!
    448         vld4.8  {d1,d3,d5,d7}, [r0]!
    449     .else
    450         vld1.8  {d0-d3}, [r0]!
    451         vld1.8  {d4-d7}, [r0]!
    452     .endif
    453         sub     r0, #64
    454   .endif
    455   .if \ldsrc
    456     .if \zipped
    457         vld4.8  {d16,d18,d20,d22}, [r1]!
    458         vld4.8  {d17,d19,d21,d23}, [r1]!
    459     .else
    460         vld1.8  {d16-d19}, [r1]!
    461         vld1.8  {d20-d23}, [r1]!
    462     .endif
    463   .endif
    464   .if \pld
    465     .if \lddst ; pld [r0, #192] ; .endif
    466     .if \ldsrc ; pld [r1, #192] ; .endif
    467   .endif
    468 
    469         \kernel
    470 
    471         subs    r2, #64
    472   .if \zipped
    473         vst4.8  {d0,d2,d4,d6}, [r0]!
    474         vst4.8  {d1,d3,d5,d7}, [r0]!
    475   .else
    476         vst1.8  {d0-d3}, [r0]!
    477         vst1.8  {d4-d7}, [r0]!
    478   .endif
    479 
    480 2:      bge     1b
    481         adds    r2, #64
    482         beq     2f
    483 
    484         /* To handle the tail portion of the data (something less than 64
    485          * bytes) load small power-of-two chunks into working registers.  It
    486          * doesn't matter where they end up in the register; the same process
    487          * will store them back out using the same positions and the operations
    488          * don't require data to interact with its neighbours.
    489          */
    490         vmov.i8 q0, #0
    491         vmov.i8 q1, #0
    492         vmov.i8 q2, #0
    493         vmov.i8 q3, #0
    494 
    495         vmov.i8 q8, #0
    496         vmov.i8 q9, #0
    497         vmov.i8 q10, #0
    498         vmov.i8 q11, #0
    499 
    500         tst     r2, #32
    501         beq     1f
    502   .if \lddst ; vld1.64 {d4-d7}, [r0]!   ; .endif
    503   .if \ldsrc ; vld1.64 {d20-d23}, [r1]! ; .endif
    504 1:      tst     r2, #16
    505         beq     1f
    506   .if \lddst ; vld1.64 {d2-d3}, [r0]!   ; .endif
    507   .if \ldsrc ; vld1.64 {d18-d19}, [r1]! ; .endif
    508 1:      tst     r2, #8
    509         beq     1f
    510   .if \lddst ; vld1.64 {d1}, [r0]!      ; .endif
    511   .if \ldsrc ; vld1.64 {d17}, [r1]!     ; .endif
    512 1:      tst     r2, #4
    513         beq     1f
    514   .if \lddst ; vld1.32 {d0[1]}, [r0]!   ; .endif
    515   .if \ldsrc ; vld1.32 {d16[1]}, [r1]!  ; .endif
    516 1:      tst     r2, #2
    517         beq     1f
    518   .if \lddst ; vld1.16 {d0[1]}, [r0]!   ; .endif
    519   .if \ldsrc ; vld1.16 {d16[1]}, [r1]!  ; .endif
    520 1:      tst     r2, #1
    521         beq     1f
    522   .if \lddst ; vld1.8  {d0[1]}, [r0]!   ; .endif
    523   .if \ldsrc ; vld1.8  {d16[1]}, [r1]!  ; .endif
    524 1:
    525   .if \lddst ; sub     r0, r2           ; .endif
    526 
    527   .if \zipped
    528         /* One small impediment in the process above is that some of the load
    529          * operations can't perform byte-wise structure deinterleaving at the
    530          * same time as loading only part of a register.  So the data is loaded
    531          * linearly and unpacked manually at this point.
    532          */
    533         vuzp.8  q0, q1
    534         vuzp.8  q2, q3
    535         vuzp.8  q0, q2
    536         vuzp.8  q1, q3
    537 
    538         vuzp.8  q8, q9
    539         vuzp.8  q10, q11
    540         vuzp.8  q8, q10
    541         vuzp.8  q9, q11
    542 
    543         \kernel
    544 
    545         vzip.8  q0, q2
    546         vzip.8  q1, q3
    547         vzip.8  q0, q1
    548         vzip.8  q2, q3
    549   .else
    550         \kernel
    551   .endif
    552 
    553         tst     r2, #32
    554         beq     1f
    555         vst1.64 {d4-d7}, [r0]!
    556 1:      tst     r2, #16
    557         beq     1f
    558         vst1.64 {d2-d3}, [r0]!
    559 1:      tst     r2, #8
    560         beq     1f
    561         vst1.64 {d1}, [r0]!
    562 1:      tst     r2, #4
    563         beq     1f
    564         vst1.32 {d0[1]}, [r0]!
    565 1:      tst     r2, #2
    566         beq     1f
    567         vst1.16 {d0[1]}, [r0]!
    568 1:      tst     r2, #1
    569         beq     2f
    570         vst1.8  {d0[1]}, [r0]!
    571 2:      vpop    {d8-d15}
    572 .endif
    573         mov     r0, #0
    574         bx      lr
    575 .endm
    576 
    577 
    578 /* produce list of blend_line_XX() functions; each function uses the wrap_line
    579  * macro, passing it the name of the operation macro it wants along with
    580  * optional parameters to remove unnecessary operations.
    581  */
    582 #define BLEND_X(d, n) ENTRY(blend_line_##n) ; wrap_line blend_kernel_##n, params_##n ; END(blend_line_##n) ;
    583     BLEND_LIST(BLEND_X)
    584 #undef BLEND_X
    585 
    586 
    587 /*  int rsdIntrinsicBlend_K(
    588  *          uchar4 *out,        // r0
    589  *          uchar4 const *in,   // r1
    590  *          int slot,           // r2
    591  *          size_t xstart,      // r3
    592  *          size_t xend);       // [sp]
    593  */
    594 ENTRY(rsdIntrinsicBlend_K)
    595     adr     ip, blend_functions
    596     cmp     r2, #(blend_functions_end - blend_functions) >> 2
    597     ldrlo   ip, [ip, r2, LSL #2]
    598     movhs   ip, #0
    599     ldr     r2, [sp]
    600     add     r0, r3, LSL #2
    601     add     r1, r3, LSL #2
    602     sub     r2, r3
    603     mov     r2, r2, LSL #2
    604     cmp     ip, #0
    605     addne   ip, ip, pc
    606     bxne    ip
    607 1:  mov     r0, #-1
    608     bx      lr
    609 
    610 blend_functions:
    611 .set off,0
    612 #define BLEND_X(d, n) .rept d-off ; .word 0 ; .endr ; .word blend_line_##n-1b ; .set off, d+1 ;
    613         BLEND_LIST(BLEND_X)
    614 #undef BLEND_X
    615 blend_functions_end:
    616 
    617 END(rsdIntrinsicBlend_K)
    618