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