162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Implement fast CRC32C with PCLMULQDQ instructions. (x86_64) 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * The white papers on CRC32C calculations with PCLMULQDQ instruction can be 562306a36Sopenharmony_ci * downloaded from: 662306a36Sopenharmony_ci * http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/crc-iscsi-polynomial-crc32-instruction-paper.pdf 762306a36Sopenharmony_ci * http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-paper.pdf 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Copyright (C) 2012 Intel Corporation. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * Authors: 1262306a36Sopenharmony_ci * Wajdi Feghali <wajdi.k.feghali@intel.com> 1362306a36Sopenharmony_ci * James Guilford <james.guilford@intel.com> 1462306a36Sopenharmony_ci * David Cote <david.m.cote@intel.com> 1562306a36Sopenharmony_ci * Tim Chen <tim.c.chen@linux.intel.com> 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * This software is available to you under a choice of one of two 1862306a36Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 1962306a36Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 2062306a36Sopenharmony_ci * COPYING in the main directory of this source tree, or the 2162306a36Sopenharmony_ci * OpenIB.org BSD license below: 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or 2462306a36Sopenharmony_ci * without modification, are permitted provided that the following 2562306a36Sopenharmony_ci * conditions are met: 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * - Redistributions of source code must retain the above 2862306a36Sopenharmony_ci * copyright notice, this list of conditions and the following 2962306a36Sopenharmony_ci * disclaimer. 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * - Redistributions in binary form must reproduce the above 3262306a36Sopenharmony_ci * copyright notice, this list of conditions and the following 3362306a36Sopenharmony_ci * disclaimer in the documentation and/or other materials 3462306a36Sopenharmony_ci * provided with the distribution. 3562306a36Sopenharmony_ci * 3662306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 3762306a36Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 3862306a36Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 3962306a36Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 4062306a36Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 4162306a36Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 4262306a36Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 4362306a36Sopenharmony_ci * SOFTWARE. 4462306a36Sopenharmony_ci */ 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#include <linux/linkage.h> 4762306a36Sopenharmony_ci#include <asm/nospec-branch.h> 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci## ISCSI CRC 32 Implementation with crc32 and pclmulqdq Instruction 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci.macro LABEL prefix n 5262306a36Sopenharmony_ci.L\prefix\n\(): 5362306a36Sopenharmony_ci.endm 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci.macro JMPTBL_ENTRY i 5662306a36Sopenharmony_ci.quad .Lcrc_\i 5762306a36Sopenharmony_ci.endm 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci.macro JNC_LESS_THAN j 6062306a36Sopenharmony_ci jnc .Lless_than_\j 6162306a36Sopenharmony_ci.endm 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci# Define threshold where buffers are considered "small" and routed to more 6462306a36Sopenharmony_ci# efficient "by-1" code. This "by-1" code only handles up to 255 bytes, so 6562306a36Sopenharmony_ci# SMALL_SIZE can be no larger than 255. 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#define SMALL_SIZE 200 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci.if (SMALL_SIZE > 255) 7062306a36Sopenharmony_ci.error "SMALL_ SIZE must be < 256" 7162306a36Sopenharmony_ci.endif 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci# unsigned int crc_pcl(u8 *buffer, int len, unsigned int crc_init); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci.text 7662306a36Sopenharmony_ciSYM_FUNC_START(crc_pcl) 7762306a36Sopenharmony_ci#define bufp rdi 7862306a36Sopenharmony_ci#define bufp_dw %edi 7962306a36Sopenharmony_ci#define bufp_w %di 8062306a36Sopenharmony_ci#define bufp_b %dil 8162306a36Sopenharmony_ci#define bufptmp %rcx 8262306a36Sopenharmony_ci#define block_0 %rcx 8362306a36Sopenharmony_ci#define block_1 %rdx 8462306a36Sopenharmony_ci#define block_2 %r11 8562306a36Sopenharmony_ci#define len %rsi 8662306a36Sopenharmony_ci#define len_dw %esi 8762306a36Sopenharmony_ci#define len_w %si 8862306a36Sopenharmony_ci#define len_b %sil 8962306a36Sopenharmony_ci#define crc_init_arg %rdx 9062306a36Sopenharmony_ci#define tmp %rbx 9162306a36Sopenharmony_ci#define crc_init %r8 9262306a36Sopenharmony_ci#define crc_init_dw %r8d 9362306a36Sopenharmony_ci#define crc1 %r9 9462306a36Sopenharmony_ci#define crc2 %r10 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci pushq %rbx 9762306a36Sopenharmony_ci pushq %rdi 9862306a36Sopenharmony_ci pushq %rsi 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci ## Move crc_init for Linux to a different 10162306a36Sopenharmony_ci mov crc_init_arg, crc_init 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci ################################################################ 10462306a36Sopenharmony_ci ## 1) ALIGN: 10562306a36Sopenharmony_ci ################################################################ 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci mov %bufp, bufptmp # rdi = *buf 10862306a36Sopenharmony_ci neg %bufp 10962306a36Sopenharmony_ci and $7, %bufp # calculate the unalignment amount of 11062306a36Sopenharmony_ci # the address 11162306a36Sopenharmony_ci je .Lproc_block # Skip if aligned 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci ## If len is less than 8 and we're unaligned, we need to jump 11462306a36Sopenharmony_ci ## to special code to avoid reading beyond the end of the buffer 11562306a36Sopenharmony_ci cmp $8, len 11662306a36Sopenharmony_ci jae .Ldo_align 11762306a36Sopenharmony_ci # less_than_8 expects length in upper 3 bits of len_dw 11862306a36Sopenharmony_ci # less_than_8_post_shl1 expects length = carryflag * 8 + len_dw[31:30] 11962306a36Sopenharmony_ci shl $32-3+1, len_dw 12062306a36Sopenharmony_ci jmp .Lless_than_8_post_shl1 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci.Ldo_align: 12362306a36Sopenharmony_ci #### Calculate CRC of unaligned bytes of the buffer (if any) 12462306a36Sopenharmony_ci movq (bufptmp), tmp # load a quadward from the buffer 12562306a36Sopenharmony_ci add %bufp, bufptmp # align buffer pointer for quadword 12662306a36Sopenharmony_ci # processing 12762306a36Sopenharmony_ci sub %bufp, len # update buffer length 12862306a36Sopenharmony_ci.Lalign_loop: 12962306a36Sopenharmony_ci crc32b %bl, crc_init_dw # compute crc32 of 1-byte 13062306a36Sopenharmony_ci shr $8, tmp # get next byte 13162306a36Sopenharmony_ci dec %bufp 13262306a36Sopenharmony_ci jne .Lalign_loop 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci.Lproc_block: 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci ################################################################ 13762306a36Sopenharmony_ci ## 2) PROCESS BLOCKS: 13862306a36Sopenharmony_ci ################################################################ 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci ## compute num of bytes to be processed 14162306a36Sopenharmony_ci movq len, tmp # save num bytes in tmp 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci cmpq $128*24, len 14462306a36Sopenharmony_ci jae .Lfull_block 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci.Lcontinue_block: 14762306a36Sopenharmony_ci cmpq $SMALL_SIZE, len 14862306a36Sopenharmony_ci jb .Lsmall 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci ## len < 128*24 15162306a36Sopenharmony_ci movq $2731, %rax # 2731 = ceil(2^16 / 24) 15262306a36Sopenharmony_ci mul len_dw 15362306a36Sopenharmony_ci shrq $16, %rax 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci ## eax contains floor(bytes / 24) = num 24-byte chunks to do 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci ## process rax 24-byte chunks (128 >= rax >= 0) 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci ## compute end address of each block 16062306a36Sopenharmony_ci ## block 0 (base addr + RAX * 8) 16162306a36Sopenharmony_ci ## block 1 (base addr + RAX * 16) 16262306a36Sopenharmony_ci ## block 2 (base addr + RAX * 24) 16362306a36Sopenharmony_ci lea (bufptmp, %rax, 8), block_0 16462306a36Sopenharmony_ci lea (block_0, %rax, 8), block_1 16562306a36Sopenharmony_ci lea (block_1, %rax, 8), block_2 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci xor crc1, crc1 16862306a36Sopenharmony_ci xor crc2, crc2 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci ## branch into array 17162306a36Sopenharmony_ci leaq jump_table(%rip), %bufp 17262306a36Sopenharmony_ci mov (%bufp,%rax,8), %bufp 17362306a36Sopenharmony_ci JMP_NOSPEC bufp 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci ################################################################ 17662306a36Sopenharmony_ci ## 2a) PROCESS FULL BLOCKS: 17762306a36Sopenharmony_ci ################################################################ 17862306a36Sopenharmony_ci.Lfull_block: 17962306a36Sopenharmony_ci movl $128,%eax 18062306a36Sopenharmony_ci lea 128*8*2(block_0), block_1 18162306a36Sopenharmony_ci lea 128*8*3(block_0), block_2 18262306a36Sopenharmony_ci add $128*8*1, block_0 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci xor crc1,crc1 18562306a36Sopenharmony_ci xor crc2,crc2 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci # Fall thruogh into top of crc array (crc_128) 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci ################################################################ 19062306a36Sopenharmony_ci ## 3) CRC Array: 19162306a36Sopenharmony_ci ################################################################ 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci i=128 19462306a36Sopenharmony_ci.rept 128-1 19562306a36Sopenharmony_ci.altmacro 19662306a36Sopenharmony_ciLABEL crc_ %i 19762306a36Sopenharmony_ci.noaltmacro 19862306a36Sopenharmony_ci ENDBR 19962306a36Sopenharmony_ci crc32q -i*8(block_0), crc_init 20062306a36Sopenharmony_ci crc32q -i*8(block_1), crc1 20162306a36Sopenharmony_ci crc32q -i*8(block_2), crc2 20262306a36Sopenharmony_ci i=(i-1) 20362306a36Sopenharmony_ci.endr 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci.altmacro 20662306a36Sopenharmony_ciLABEL crc_ %i 20762306a36Sopenharmony_ci.noaltmacro 20862306a36Sopenharmony_ci ENDBR 20962306a36Sopenharmony_ci crc32q -i*8(block_0), crc_init 21062306a36Sopenharmony_ci crc32q -i*8(block_1), crc1 21162306a36Sopenharmony_ci# SKIP crc32 -i*8(block_2), crc2 ; Don't do this one yet 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci mov block_2, block_0 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci ################################################################ 21662306a36Sopenharmony_ci ## 4) Combine three results: 21762306a36Sopenharmony_ci ################################################################ 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci lea (K_table-8)(%rip), %bufp # first entry is for idx 1 22062306a36Sopenharmony_ci shlq $3, %rax # rax *= 8 22162306a36Sopenharmony_ci pmovzxdq (%bufp,%rax), %xmm0 # 2 consts: K1:K2 22262306a36Sopenharmony_ci leal (%eax,%eax,2), %eax # rax *= 3 (total *24) 22362306a36Sopenharmony_ci subq %rax, tmp # tmp -= rax*24 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci movq crc_init, %xmm1 # CRC for block 1 22662306a36Sopenharmony_ci pclmulqdq $0x00, %xmm0, %xmm1 # Multiply by K2 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci movq crc1, %xmm2 # CRC for block 2 22962306a36Sopenharmony_ci pclmulqdq $0x10, %xmm0, %xmm2 # Multiply by K1 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci pxor %xmm2,%xmm1 23262306a36Sopenharmony_ci movq %xmm1, %rax 23362306a36Sopenharmony_ci xor -i*8(block_2), %rax 23462306a36Sopenharmony_ci mov crc2, crc_init 23562306a36Sopenharmony_ci crc32 %rax, crc_init 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci ################################################################ 23862306a36Sopenharmony_ci ## 5) Check for end: 23962306a36Sopenharmony_ci ################################################################ 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ciLABEL crc_ 0 24262306a36Sopenharmony_ci ENDBR 24362306a36Sopenharmony_ci mov tmp, len 24462306a36Sopenharmony_ci cmp $128*24, tmp 24562306a36Sopenharmony_ci jae .Lfull_block 24662306a36Sopenharmony_ci cmp $24, tmp 24762306a36Sopenharmony_ci jae .Lcontinue_block 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci.Lless_than_24: 25062306a36Sopenharmony_ci shl $32-4, len_dw # less_than_16 expects length 25162306a36Sopenharmony_ci # in upper 4 bits of len_dw 25262306a36Sopenharmony_ci jnc .Lless_than_16 25362306a36Sopenharmony_ci crc32q (bufptmp), crc_init 25462306a36Sopenharmony_ci crc32q 8(bufptmp), crc_init 25562306a36Sopenharmony_ci jz .Ldo_return 25662306a36Sopenharmony_ci add $16, bufptmp 25762306a36Sopenharmony_ci # len is less than 8 if we got here 25862306a36Sopenharmony_ci # less_than_8 expects length in upper 3 bits of len_dw 25962306a36Sopenharmony_ci # less_than_8_post_shl1 expects length = carryflag * 8 + len_dw[31:30] 26062306a36Sopenharmony_ci shl $2, len_dw 26162306a36Sopenharmony_ci jmp .Lless_than_8_post_shl1 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci ####################################################################### 26462306a36Sopenharmony_ci ## 6) LESS THAN 256-bytes REMAIN AT THIS POINT (8-bits of len are full) 26562306a36Sopenharmony_ci ####################################################################### 26662306a36Sopenharmony_ci.Lsmall: 26762306a36Sopenharmony_ci shl $32-8, len_dw # Prepare len_dw for less_than_256 26862306a36Sopenharmony_ci j=256 26962306a36Sopenharmony_ci.rept 5 # j = {256, 128, 64, 32, 16} 27062306a36Sopenharmony_ci.altmacro 27162306a36Sopenharmony_ciLABEL less_than_ %j # less_than_j: Length should be in 27262306a36Sopenharmony_ci # upper lg(j) bits of len_dw 27362306a36Sopenharmony_ci j=(j/2) 27462306a36Sopenharmony_ci shl $1, len_dw # Get next MSB 27562306a36Sopenharmony_ci JNC_LESS_THAN %j 27662306a36Sopenharmony_ci.noaltmacro 27762306a36Sopenharmony_ci i=0 27862306a36Sopenharmony_ci.rept (j/8) 27962306a36Sopenharmony_ci crc32q i(bufptmp), crc_init # Compute crc32 of 8-byte data 28062306a36Sopenharmony_ci i=i+8 28162306a36Sopenharmony_ci.endr 28262306a36Sopenharmony_ci jz .Ldo_return # Return if remaining length is zero 28362306a36Sopenharmony_ci add $j, bufptmp # Advance buf 28462306a36Sopenharmony_ci.endr 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci.Lless_than_8: # Length should be stored in 28762306a36Sopenharmony_ci # upper 3 bits of len_dw 28862306a36Sopenharmony_ci shl $1, len_dw 28962306a36Sopenharmony_ci.Lless_than_8_post_shl1: 29062306a36Sopenharmony_ci jnc .Lless_than_4 29162306a36Sopenharmony_ci crc32l (bufptmp), crc_init_dw # CRC of 4 bytes 29262306a36Sopenharmony_ci jz .Ldo_return # return if remaining data is zero 29362306a36Sopenharmony_ci add $4, bufptmp 29462306a36Sopenharmony_ci.Lless_than_4: # Length should be stored in 29562306a36Sopenharmony_ci # upper 2 bits of len_dw 29662306a36Sopenharmony_ci shl $1, len_dw 29762306a36Sopenharmony_ci jnc .Lless_than_2 29862306a36Sopenharmony_ci crc32w (bufptmp), crc_init_dw # CRC of 2 bytes 29962306a36Sopenharmony_ci jz .Ldo_return # return if remaining data is zero 30062306a36Sopenharmony_ci add $2, bufptmp 30162306a36Sopenharmony_ci.Lless_than_2: # Length should be stored in the MSB 30262306a36Sopenharmony_ci # of len_dw 30362306a36Sopenharmony_ci shl $1, len_dw 30462306a36Sopenharmony_ci jnc .Lless_than_1 30562306a36Sopenharmony_ci crc32b (bufptmp), crc_init_dw # CRC of 1 byte 30662306a36Sopenharmony_ci.Lless_than_1: # Length should be zero 30762306a36Sopenharmony_ci.Ldo_return: 30862306a36Sopenharmony_ci movq crc_init, %rax 30962306a36Sopenharmony_ci popq %rsi 31062306a36Sopenharmony_ci popq %rdi 31162306a36Sopenharmony_ci popq %rbx 31262306a36Sopenharmony_ci RET 31362306a36Sopenharmony_ciSYM_FUNC_END(crc_pcl) 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci.section .rodata, "a", @progbits 31662306a36Sopenharmony_ci ################################################################ 31762306a36Sopenharmony_ci ## jump table Table is 129 entries x 2 bytes each 31862306a36Sopenharmony_ci ################################################################ 31962306a36Sopenharmony_ci.align 4 32062306a36Sopenharmony_cijump_table: 32162306a36Sopenharmony_ci i=0 32262306a36Sopenharmony_ci.rept 129 32362306a36Sopenharmony_ci.altmacro 32462306a36Sopenharmony_ciJMPTBL_ENTRY %i 32562306a36Sopenharmony_ci.noaltmacro 32662306a36Sopenharmony_ci i=i+1 32762306a36Sopenharmony_ci.endr 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci ################################################################ 33162306a36Sopenharmony_ci ## PCLMULQDQ tables 33262306a36Sopenharmony_ci ## Table is 128 entries x 2 words (8 bytes) each 33362306a36Sopenharmony_ci ################################################################ 33462306a36Sopenharmony_ci.align 8 33562306a36Sopenharmony_ciK_table: 33662306a36Sopenharmony_ci .long 0x493c7d27, 0x00000001 33762306a36Sopenharmony_ci .long 0xba4fc28e, 0x493c7d27 33862306a36Sopenharmony_ci .long 0xddc0152b, 0xf20c0dfe 33962306a36Sopenharmony_ci .long 0x9e4addf8, 0xba4fc28e 34062306a36Sopenharmony_ci .long 0x39d3b296, 0x3da6d0cb 34162306a36Sopenharmony_ci .long 0x0715ce53, 0xddc0152b 34262306a36Sopenharmony_ci .long 0x47db8317, 0x1c291d04 34362306a36Sopenharmony_ci .long 0x0d3b6092, 0x9e4addf8 34462306a36Sopenharmony_ci .long 0xc96cfdc0, 0x740eef02 34562306a36Sopenharmony_ci .long 0x878a92a7, 0x39d3b296 34662306a36Sopenharmony_ci .long 0xdaece73e, 0x083a6eec 34762306a36Sopenharmony_ci .long 0xab7aff2a, 0x0715ce53 34862306a36Sopenharmony_ci .long 0x2162d385, 0xc49f4f67 34962306a36Sopenharmony_ci .long 0x83348832, 0x47db8317 35062306a36Sopenharmony_ci .long 0x299847d5, 0x2ad91c30 35162306a36Sopenharmony_ci .long 0xb9e02b86, 0x0d3b6092 35262306a36Sopenharmony_ci .long 0x18b33a4e, 0x6992cea2 35362306a36Sopenharmony_ci .long 0xb6dd949b, 0xc96cfdc0 35462306a36Sopenharmony_ci .long 0x78d9ccb7, 0x7e908048 35562306a36Sopenharmony_ci .long 0xbac2fd7b, 0x878a92a7 35662306a36Sopenharmony_ci .long 0xa60ce07b, 0x1b3d8f29 35762306a36Sopenharmony_ci .long 0xce7f39f4, 0xdaece73e 35862306a36Sopenharmony_ci .long 0x61d82e56, 0xf1d0f55e 35962306a36Sopenharmony_ci .long 0xd270f1a2, 0xab7aff2a 36062306a36Sopenharmony_ci .long 0xc619809d, 0xa87ab8a8 36162306a36Sopenharmony_ci .long 0x2b3cac5d, 0x2162d385 36262306a36Sopenharmony_ci .long 0x65863b64, 0x8462d800 36362306a36Sopenharmony_ci .long 0x1b03397f, 0x83348832 36462306a36Sopenharmony_ci .long 0xebb883bd, 0x71d111a8 36562306a36Sopenharmony_ci .long 0xb3e32c28, 0x299847d5 36662306a36Sopenharmony_ci .long 0x064f7f26, 0xffd852c6 36762306a36Sopenharmony_ci .long 0xdd7e3b0c, 0xb9e02b86 36862306a36Sopenharmony_ci .long 0xf285651c, 0xdcb17aa4 36962306a36Sopenharmony_ci .long 0x10746f3c, 0x18b33a4e 37062306a36Sopenharmony_ci .long 0xc7a68855, 0xf37c5aee 37162306a36Sopenharmony_ci .long 0x271d9844, 0xb6dd949b 37262306a36Sopenharmony_ci .long 0x8e766a0c, 0x6051d5a2 37362306a36Sopenharmony_ci .long 0x93a5f730, 0x78d9ccb7 37462306a36Sopenharmony_ci .long 0x6cb08e5c, 0x18b0d4ff 37562306a36Sopenharmony_ci .long 0x6b749fb2, 0xbac2fd7b 37662306a36Sopenharmony_ci .long 0x1393e203, 0x21f3d99c 37762306a36Sopenharmony_ci .long 0xcec3662e, 0xa60ce07b 37862306a36Sopenharmony_ci .long 0x96c515bb, 0x8f158014 37962306a36Sopenharmony_ci .long 0xe6fc4e6a, 0xce7f39f4 38062306a36Sopenharmony_ci .long 0x8227bb8a, 0xa00457f7 38162306a36Sopenharmony_ci .long 0xb0cd4768, 0x61d82e56 38262306a36Sopenharmony_ci .long 0x39c7ff35, 0x8d6d2c43 38362306a36Sopenharmony_ci .long 0xd7a4825c, 0xd270f1a2 38462306a36Sopenharmony_ci .long 0x0ab3844b, 0x00ac29cf 38562306a36Sopenharmony_ci .long 0x0167d312, 0xc619809d 38662306a36Sopenharmony_ci .long 0xf6076544, 0xe9adf796 38762306a36Sopenharmony_ci .long 0x26f6a60a, 0x2b3cac5d 38862306a36Sopenharmony_ci .long 0xa741c1bf, 0x96638b34 38962306a36Sopenharmony_ci .long 0x98d8d9cb, 0x65863b64 39062306a36Sopenharmony_ci .long 0x49c3cc9c, 0xe0e9f351 39162306a36Sopenharmony_ci .long 0x68bce87a, 0x1b03397f 39262306a36Sopenharmony_ci .long 0x57a3d037, 0x9af01f2d 39362306a36Sopenharmony_ci .long 0x6956fc3b, 0xebb883bd 39462306a36Sopenharmony_ci .long 0x42d98888, 0x2cff42cf 39562306a36Sopenharmony_ci .long 0x3771e98f, 0xb3e32c28 39662306a36Sopenharmony_ci .long 0xb42ae3d9, 0x88f25a3a 39762306a36Sopenharmony_ci .long 0x2178513a, 0x064f7f26 39862306a36Sopenharmony_ci .long 0xe0ac139e, 0x4e36f0b0 39962306a36Sopenharmony_ci .long 0x170076fa, 0xdd7e3b0c 40062306a36Sopenharmony_ci .long 0x444dd413, 0xbd6f81f8 40162306a36Sopenharmony_ci .long 0x6f345e45, 0xf285651c 40262306a36Sopenharmony_ci .long 0x41d17b64, 0x91c9bd4b 40362306a36Sopenharmony_ci .long 0xff0dba97, 0x10746f3c 40462306a36Sopenharmony_ci .long 0xa2b73df1, 0x885f087b 40562306a36Sopenharmony_ci .long 0xf872e54c, 0xc7a68855 40662306a36Sopenharmony_ci .long 0x1e41e9fc, 0x4c144932 40762306a36Sopenharmony_ci .long 0x86d8e4d2, 0x271d9844 40862306a36Sopenharmony_ci .long 0x651bd98b, 0x52148f02 40962306a36Sopenharmony_ci .long 0x5bb8f1bc, 0x8e766a0c 41062306a36Sopenharmony_ci .long 0xa90fd27a, 0xa3c6f37a 41162306a36Sopenharmony_ci .long 0xb3af077a, 0x93a5f730 41262306a36Sopenharmony_ci .long 0x4984d782, 0xd7c0557f 41362306a36Sopenharmony_ci .long 0xca6ef3ac, 0x6cb08e5c 41462306a36Sopenharmony_ci .long 0x234e0b26, 0x63ded06a 41562306a36Sopenharmony_ci .long 0xdd66cbbb, 0x6b749fb2 41662306a36Sopenharmony_ci .long 0x4597456a, 0x4d56973c 41762306a36Sopenharmony_ci .long 0xe9e28eb4, 0x1393e203 41862306a36Sopenharmony_ci .long 0x7b3ff57a, 0x9669c9df 41962306a36Sopenharmony_ci .long 0xc9c8b782, 0xcec3662e 42062306a36Sopenharmony_ci .long 0x3f70cc6f, 0xe417f38a 42162306a36Sopenharmony_ci .long 0x93e106a4, 0x96c515bb 42262306a36Sopenharmony_ci .long 0x62ec6c6d, 0x4b9e0f71 42362306a36Sopenharmony_ci .long 0xd813b325, 0xe6fc4e6a 42462306a36Sopenharmony_ci .long 0x0df04680, 0xd104b8fc 42562306a36Sopenharmony_ci .long 0x2342001e, 0x8227bb8a 42662306a36Sopenharmony_ci .long 0x0a2a8d7e, 0x5b397730 42762306a36Sopenharmony_ci .long 0x6d9a4957, 0xb0cd4768 42862306a36Sopenharmony_ci .long 0xe8b6368b, 0xe78eb416 42962306a36Sopenharmony_ci .long 0xd2c3ed1a, 0x39c7ff35 43062306a36Sopenharmony_ci .long 0x995a5724, 0x61ff0e01 43162306a36Sopenharmony_ci .long 0x9ef68d35, 0xd7a4825c 43262306a36Sopenharmony_ci .long 0x0c139b31, 0x8d96551c 43362306a36Sopenharmony_ci .long 0xf2271e60, 0x0ab3844b 43462306a36Sopenharmony_ci .long 0x0b0bf8ca, 0x0bf80dd2 43562306a36Sopenharmony_ci .long 0x2664fd8b, 0x0167d312 43662306a36Sopenharmony_ci .long 0xed64812d, 0x8821abed 43762306a36Sopenharmony_ci .long 0x02ee03b2, 0xf6076544 43862306a36Sopenharmony_ci .long 0x8604ae0f, 0x6a45d2b2 43962306a36Sopenharmony_ci .long 0x363bd6b3, 0x26f6a60a 44062306a36Sopenharmony_ci .long 0x135c83fd, 0xd8d26619 44162306a36Sopenharmony_ci .long 0x5fabe670, 0xa741c1bf 44262306a36Sopenharmony_ci .long 0x35ec3279, 0xde87806c 44362306a36Sopenharmony_ci .long 0x00bcf5f6, 0x98d8d9cb 44462306a36Sopenharmony_ci .long 0x8ae00689, 0x14338754 44562306a36Sopenharmony_ci .long 0x17f27698, 0x49c3cc9c 44662306a36Sopenharmony_ci .long 0x58ca5f00, 0x5bd2011f 44762306a36Sopenharmony_ci .long 0xaa7c7ad5, 0x68bce87a 44862306a36Sopenharmony_ci .long 0xb5cfca28, 0xdd07448e 44962306a36Sopenharmony_ci .long 0xded288f8, 0x57a3d037 45062306a36Sopenharmony_ci .long 0x59f229bc, 0xdde8f5b9 45162306a36Sopenharmony_ci .long 0x6d390dec, 0x6956fc3b 45262306a36Sopenharmony_ci .long 0x37170390, 0xa3e3e02c 45362306a36Sopenharmony_ci .long 0x6353c1cc, 0x42d98888 45462306a36Sopenharmony_ci .long 0xc4584f5c, 0xd73c7bea 45562306a36Sopenharmony_ci .long 0xf48642e9, 0x3771e98f 45662306a36Sopenharmony_ci .long 0x531377e2, 0x80ff0093 45762306a36Sopenharmony_ci .long 0xdd35bc8d, 0xb42ae3d9 45862306a36Sopenharmony_ci .long 0xb25b29f2, 0x8fe4c34d 45962306a36Sopenharmony_ci .long 0x9a5ede41, 0x2178513a 46062306a36Sopenharmony_ci .long 0xa563905d, 0xdf99fc11 46162306a36Sopenharmony_ci .long 0x45cddf4e, 0xe0ac139e 46262306a36Sopenharmony_ci .long 0xacfa3103, 0x6c23e841 46362306a36Sopenharmony_ci .long 0xa51b6135, 0x170076fa 464