162306a36Sopenharmony_ci| 262306a36Sopenharmony_ci| x_operr.sa 3.5 7/1/91 362306a36Sopenharmony_ci| 462306a36Sopenharmony_ci| fpsp_operr --- FPSP handler for operand error exception 562306a36Sopenharmony_ci| 662306a36Sopenharmony_ci| See 68040 User's Manual pp. 9-44f 762306a36Sopenharmony_ci| 862306a36Sopenharmony_ci| Note 1: For trap disabled 040 does the following: 962306a36Sopenharmony_ci| If the dest is a fp reg, then an extended precision non_signaling 1062306a36Sopenharmony_ci| NAN is stored in the dest reg. If the dest format is b, w, or l and 1162306a36Sopenharmony_ci| the source op is a NAN, then garbage is stored as the result (actually 1262306a36Sopenharmony_ci| the upper 32 bits of the mantissa are sent to the integer unit). If 1362306a36Sopenharmony_ci| the dest format is integer (b, w, l) and the operr is caused by 1462306a36Sopenharmony_ci| integer overflow, or the source op is inf, then the result stored is 1562306a36Sopenharmony_ci| garbage. 1662306a36Sopenharmony_ci| There are three cases in which operr is incorrectly signaled on the 1762306a36Sopenharmony_ci| 040. This occurs for move_out of format b, w, or l for the largest 1862306a36Sopenharmony_ci| negative integer (-2^7 for b, -2^15 for w, -2^31 for l). 1962306a36Sopenharmony_ci| 2062306a36Sopenharmony_ci| On opclass = 011 fmove.(b,w,l) that causes a conversion 2162306a36Sopenharmony_ci| overflow -> OPERR, the exponent in wbte (and fpte) is: 2262306a36Sopenharmony_ci| byte 56 - (62 - exp) 2362306a36Sopenharmony_ci| word 48 - (62 - exp) 2462306a36Sopenharmony_ci| long 32 - (62 - exp) 2562306a36Sopenharmony_ci| 2662306a36Sopenharmony_ci| where exp = (true exp) - 1 2762306a36Sopenharmony_ci| 2862306a36Sopenharmony_ci| So, wbtemp and fptemp will contain the following on erroneously 2962306a36Sopenharmony_ci| signalled operr: 3062306a36Sopenharmony_ci| fpts = 1 3162306a36Sopenharmony_ci| fpte = $4000 (15 bit externally) 3262306a36Sopenharmony_ci| byte fptm = $ffffffff ffffff80 3362306a36Sopenharmony_ci| word fptm = $ffffffff ffff8000 3462306a36Sopenharmony_ci| long fptm = $ffffffff 80000000 3562306a36Sopenharmony_ci| 3662306a36Sopenharmony_ci| Note 2: For trap enabled 040 does the following: 3762306a36Sopenharmony_ci| If the inst is move_out, then same as Note 1. 3862306a36Sopenharmony_ci| If the inst is not move_out, the dest is not modified. 3962306a36Sopenharmony_ci| The exceptional operand is not defined for integer overflow 4062306a36Sopenharmony_ci| during a move_out. 4162306a36Sopenharmony_ci| 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci| Copyright (C) Motorola, Inc. 1990 4462306a36Sopenharmony_ci| All Rights Reserved 4562306a36Sopenharmony_ci| 4662306a36Sopenharmony_ci| For details on the license for this file, please see the 4762306a36Sopenharmony_ci| file, README, in this same directory. 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ciX_OPERR: |idnt 2,1 | Motorola 040 Floating Point Software Package 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci |section 8 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#include "fpsp.h" 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci |xref mem_write 5662306a36Sopenharmony_ci |xref real_operr 5762306a36Sopenharmony_ci |xref real_inex 5862306a36Sopenharmony_ci |xref get_fline 5962306a36Sopenharmony_ci |xref fpsp_done 6062306a36Sopenharmony_ci |xref reg_dest 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci .global fpsp_operr 6362306a36Sopenharmony_cifpsp_operr: 6462306a36Sopenharmony_ci| 6562306a36Sopenharmony_ci link %a6,#-LOCAL_SIZE 6662306a36Sopenharmony_ci fsave -(%a7) 6762306a36Sopenharmony_ci moveml %d0-%d1/%a0-%a1,USER_DA(%a6) 6862306a36Sopenharmony_ci fmovemx %fp0-%fp3,USER_FP0(%a6) 6962306a36Sopenharmony_ci fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6) 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci| 7262306a36Sopenharmony_ci| Check if this is an opclass 3 instruction. 7362306a36Sopenharmony_ci| If so, fall through, else branch to operr_end 7462306a36Sopenharmony_ci| 7562306a36Sopenharmony_ci btstb #TFLAG,T_BYTE(%a6) 7662306a36Sopenharmony_ci beqs operr_end 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci| 7962306a36Sopenharmony_ci| If the destination size is B,W,or L, the operr must be 8062306a36Sopenharmony_ci| handled here. 8162306a36Sopenharmony_ci| 8262306a36Sopenharmony_ci movel CMDREG1B(%a6),%d0 8362306a36Sopenharmony_ci bfextu %d0{#3:#3},%d0 |0=long, 4=word, 6=byte 8462306a36Sopenharmony_ci cmpib #0,%d0 |determine size; check long 8562306a36Sopenharmony_ci beq operr_long 8662306a36Sopenharmony_ci cmpib #4,%d0 |check word 8762306a36Sopenharmony_ci beq operr_word 8862306a36Sopenharmony_ci cmpib #6,%d0 |check byte 8962306a36Sopenharmony_ci beq operr_byte 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci| 9262306a36Sopenharmony_ci| The size is not B,W,or L, so the operr is handled by the 9362306a36Sopenharmony_ci| kernel handler. Set the operr bits and clean up, leaving 9462306a36Sopenharmony_ci| only the integer exception frame on the stack, and the 9562306a36Sopenharmony_ci| fpu in the original exceptional state. 9662306a36Sopenharmony_ci| 9762306a36Sopenharmony_cioperr_end: 9862306a36Sopenharmony_ci bsetb #operr_bit,FPSR_EXCEPT(%a6) 9962306a36Sopenharmony_ci bsetb #aiop_bit,FPSR_AEXCEPT(%a6) 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci moveml USER_DA(%a6),%d0-%d1/%a0-%a1 10262306a36Sopenharmony_ci fmovemx USER_FP0(%a6),%fp0-%fp3 10362306a36Sopenharmony_ci fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 10462306a36Sopenharmony_ci frestore (%a7)+ 10562306a36Sopenharmony_ci unlk %a6 10662306a36Sopenharmony_ci bral real_operr 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cioperr_long: 10962306a36Sopenharmony_ci moveql #4,%d1 |write size to d1 11062306a36Sopenharmony_ci moveb STAG(%a6),%d0 |test stag for nan 11162306a36Sopenharmony_ci andib #0xe0,%d0 |clr all but tag 11262306a36Sopenharmony_ci cmpib #0x60,%d0 |check for nan 11362306a36Sopenharmony_ci beq operr_nan 11462306a36Sopenharmony_ci cmpil #0x80000000,FPTEMP_LO(%a6) |test if ls lword is special 11562306a36Sopenharmony_ci bnes chklerr |if not equal, check for incorrect operr 11662306a36Sopenharmony_ci bsr check_upper |check if exp and ms mant are special 11762306a36Sopenharmony_ci tstl %d0 11862306a36Sopenharmony_ci bnes chklerr |if d0 is true, check for incorrect operr 11962306a36Sopenharmony_ci movel #0x80000000,%d0 |store special case result 12062306a36Sopenharmony_ci bsr operr_store 12162306a36Sopenharmony_ci bra not_enabled |clean and exit 12262306a36Sopenharmony_ci| 12362306a36Sopenharmony_ci| CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE 12462306a36Sopenharmony_ci| 12562306a36Sopenharmony_cichklerr: 12662306a36Sopenharmony_ci movew FPTEMP_EX(%a6),%d0 12762306a36Sopenharmony_ci andw #0x7FFF,%d0 |ignore sign bit 12862306a36Sopenharmony_ci cmpw #0x3FFE,%d0 |this is the only possible exponent value 12962306a36Sopenharmony_ci bnes chklerr2 13062306a36Sopenharmony_cifixlong: 13162306a36Sopenharmony_ci movel FPTEMP_LO(%a6),%d0 13262306a36Sopenharmony_ci bsr operr_store 13362306a36Sopenharmony_ci bra not_enabled 13462306a36Sopenharmony_cichklerr2: 13562306a36Sopenharmony_ci movew FPTEMP_EX(%a6),%d0 13662306a36Sopenharmony_ci andw #0x7FFF,%d0 |ignore sign bit 13762306a36Sopenharmony_ci cmpw #0x4000,%d0 13862306a36Sopenharmony_ci bcc store_max |exponent out of range 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci movel FPTEMP_LO(%a6),%d0 14162306a36Sopenharmony_ci andl #0x7FFF0000,%d0 |look for all 1's on bits 30-16 14262306a36Sopenharmony_ci cmpl #0x7FFF0000,%d0 14362306a36Sopenharmony_ci beqs fixlong 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci tstl FPTEMP_LO(%a6) 14662306a36Sopenharmony_ci bpls chklepos 14762306a36Sopenharmony_ci cmpl #0xFFFFFFFF,FPTEMP_HI(%a6) 14862306a36Sopenharmony_ci beqs fixlong 14962306a36Sopenharmony_ci bra store_max 15062306a36Sopenharmony_cichklepos: 15162306a36Sopenharmony_ci tstl FPTEMP_HI(%a6) 15262306a36Sopenharmony_ci beqs fixlong 15362306a36Sopenharmony_ci bra store_max 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cioperr_word: 15662306a36Sopenharmony_ci moveql #2,%d1 |write size to d1 15762306a36Sopenharmony_ci moveb STAG(%a6),%d0 |test stag for nan 15862306a36Sopenharmony_ci andib #0xe0,%d0 |clr all but tag 15962306a36Sopenharmony_ci cmpib #0x60,%d0 |check for nan 16062306a36Sopenharmony_ci beq operr_nan 16162306a36Sopenharmony_ci cmpil #0xffff8000,FPTEMP_LO(%a6) |test if ls lword is special 16262306a36Sopenharmony_ci bnes chkwerr |if not equal, check for incorrect operr 16362306a36Sopenharmony_ci bsr check_upper |check if exp and ms mant are special 16462306a36Sopenharmony_ci tstl %d0 16562306a36Sopenharmony_ci bnes chkwerr |if d0 is true, check for incorrect operr 16662306a36Sopenharmony_ci movel #0x80000000,%d0 |store special case result 16762306a36Sopenharmony_ci bsr operr_store 16862306a36Sopenharmony_ci bra not_enabled |clean and exit 16962306a36Sopenharmony_ci| 17062306a36Sopenharmony_ci| CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE 17162306a36Sopenharmony_ci| 17262306a36Sopenharmony_cichkwerr: 17362306a36Sopenharmony_ci movew FPTEMP_EX(%a6),%d0 17462306a36Sopenharmony_ci andw #0x7FFF,%d0 |ignore sign bit 17562306a36Sopenharmony_ci cmpw #0x3FFE,%d0 |this is the only possible exponent value 17662306a36Sopenharmony_ci bnes store_max 17762306a36Sopenharmony_ci movel FPTEMP_LO(%a6),%d0 17862306a36Sopenharmony_ci swap %d0 17962306a36Sopenharmony_ci bsr operr_store 18062306a36Sopenharmony_ci bra not_enabled 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cioperr_byte: 18362306a36Sopenharmony_ci moveql #1,%d1 |write size to d1 18462306a36Sopenharmony_ci moveb STAG(%a6),%d0 |test stag for nan 18562306a36Sopenharmony_ci andib #0xe0,%d0 |clr all but tag 18662306a36Sopenharmony_ci cmpib #0x60,%d0 |check for nan 18762306a36Sopenharmony_ci beqs operr_nan 18862306a36Sopenharmony_ci cmpil #0xffffff80,FPTEMP_LO(%a6) |test if ls lword is special 18962306a36Sopenharmony_ci bnes chkberr |if not equal, check for incorrect operr 19062306a36Sopenharmony_ci bsr check_upper |check if exp and ms mant are special 19162306a36Sopenharmony_ci tstl %d0 19262306a36Sopenharmony_ci bnes chkberr |if d0 is true, check for incorrect operr 19362306a36Sopenharmony_ci movel #0x80000000,%d0 |store special case result 19462306a36Sopenharmony_ci bsr operr_store 19562306a36Sopenharmony_ci bra not_enabled |clean and exit 19662306a36Sopenharmony_ci| 19762306a36Sopenharmony_ci| CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE 19862306a36Sopenharmony_ci| 19962306a36Sopenharmony_cichkberr: 20062306a36Sopenharmony_ci movew FPTEMP_EX(%a6),%d0 20162306a36Sopenharmony_ci andw #0x7FFF,%d0 |ignore sign bit 20262306a36Sopenharmony_ci cmpw #0x3FFE,%d0 |this is the only possible exponent value 20362306a36Sopenharmony_ci bnes store_max 20462306a36Sopenharmony_ci movel FPTEMP_LO(%a6),%d0 20562306a36Sopenharmony_ci asll #8,%d0 20662306a36Sopenharmony_ci swap %d0 20762306a36Sopenharmony_ci bsr operr_store 20862306a36Sopenharmony_ci bra not_enabled 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci| 21162306a36Sopenharmony_ci| This operr condition is not of the special case. Set operr 21262306a36Sopenharmony_ci| and aiop and write the portion of the nan to memory for the 21362306a36Sopenharmony_ci| given size. 21462306a36Sopenharmony_ci| 21562306a36Sopenharmony_cioperr_nan: 21662306a36Sopenharmony_ci orl #opaop_mask,USER_FPSR(%a6) |set operr & aiop 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci movel ETEMP_HI(%a6),%d0 |output will be from upper 32 bits 21962306a36Sopenharmony_ci bsr operr_store 22062306a36Sopenharmony_ci bra end_operr 22162306a36Sopenharmony_ci| 22262306a36Sopenharmony_ci| Store_max loads the max pos or negative for the size, sets 22362306a36Sopenharmony_ci| the operr and aiop bits, and clears inex and ainex, incorrectly 22462306a36Sopenharmony_ci| set by the 040. 22562306a36Sopenharmony_ci| 22662306a36Sopenharmony_cistore_max: 22762306a36Sopenharmony_ci orl #opaop_mask,USER_FPSR(%a6) |set operr & aiop 22862306a36Sopenharmony_ci bclrb #inex2_bit,FPSR_EXCEPT(%a6) 22962306a36Sopenharmony_ci bclrb #ainex_bit,FPSR_AEXCEPT(%a6) 23062306a36Sopenharmony_ci fmovel #0,%FPSR 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci tstw FPTEMP_EX(%a6) |check sign 23362306a36Sopenharmony_ci blts load_neg 23462306a36Sopenharmony_ci movel #0x7fffffff,%d0 23562306a36Sopenharmony_ci bsr operr_store 23662306a36Sopenharmony_ci bra end_operr 23762306a36Sopenharmony_ciload_neg: 23862306a36Sopenharmony_ci movel #0x80000000,%d0 23962306a36Sopenharmony_ci bsr operr_store 24062306a36Sopenharmony_ci bra end_operr 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci| 24362306a36Sopenharmony_ci| This routine stores the data in d0, for the given size in d1, 24462306a36Sopenharmony_ci| to memory or data register as required. A read of the fline 24562306a36Sopenharmony_ci| is required to determine the destination. 24662306a36Sopenharmony_ci| 24762306a36Sopenharmony_cioperr_store: 24862306a36Sopenharmony_ci movel %d0,L_SCR1(%a6) |move write data to L_SCR1 24962306a36Sopenharmony_ci movel %d1,-(%a7) |save register size 25062306a36Sopenharmony_ci bsrl get_fline |fline returned in d0 25162306a36Sopenharmony_ci movel (%a7)+,%d1 25262306a36Sopenharmony_ci bftst %d0{#26:#3} |if mode is zero, dest is Dn 25362306a36Sopenharmony_ci bnes dest_mem 25462306a36Sopenharmony_ci| 25562306a36Sopenharmony_ci| Destination is Dn. Get register number from d0. Data is on 25662306a36Sopenharmony_ci| the stack at (a7). D1 has size: 1=byte,2=word,4=long/single 25762306a36Sopenharmony_ci| 25862306a36Sopenharmony_ci andil #7,%d0 |isolate register number 25962306a36Sopenharmony_ci cmpil #4,%d1 26062306a36Sopenharmony_ci beqs op_long |the most frequent case 26162306a36Sopenharmony_ci cmpil #2,%d1 26262306a36Sopenharmony_ci bnes op_con 26362306a36Sopenharmony_ci orl #8,%d0 26462306a36Sopenharmony_ci bras op_con 26562306a36Sopenharmony_ciop_long: 26662306a36Sopenharmony_ci orl #0x10,%d0 26762306a36Sopenharmony_ciop_con: 26862306a36Sopenharmony_ci movel %d0,%d1 |format size:reg for reg_dest 26962306a36Sopenharmony_ci bral reg_dest |call to reg_dest returns to caller 27062306a36Sopenharmony_ci| ;of operr_store 27162306a36Sopenharmony_ci| 27262306a36Sopenharmony_ci| Destination is memory. Get <ea> from integer exception frame 27362306a36Sopenharmony_ci| and call mem_write. 27462306a36Sopenharmony_ci| 27562306a36Sopenharmony_cidest_mem: 27662306a36Sopenharmony_ci leal L_SCR1(%a6),%a0 |put ptr to write data in a0 27762306a36Sopenharmony_ci movel EXC_EA(%a6),%a1 |put user destination address in a1 27862306a36Sopenharmony_ci movel %d1,%d0 |put size in d0 27962306a36Sopenharmony_ci bsrl mem_write 28062306a36Sopenharmony_ci rts 28162306a36Sopenharmony_ci| 28262306a36Sopenharmony_ci| Check the exponent for $c000 and the upper 32 bits of the 28362306a36Sopenharmony_ci| mantissa for $ffffffff. If both are true, return d0 clr 28462306a36Sopenharmony_ci| and store the lower n bits of the least lword of FPTEMP 28562306a36Sopenharmony_ci| to d0 for write out. If not, it is a real operr, and set d0. 28662306a36Sopenharmony_ci| 28762306a36Sopenharmony_cicheck_upper: 28862306a36Sopenharmony_ci cmpil #0xffffffff,FPTEMP_HI(%a6) |check if first byte is all 1's 28962306a36Sopenharmony_ci bnes true_operr |if not all 1's then was true operr 29062306a36Sopenharmony_ci cmpiw #0xc000,FPTEMP_EX(%a6) |check if incorrectly signalled 29162306a36Sopenharmony_ci beqs not_true_operr |branch if not true operr 29262306a36Sopenharmony_ci cmpiw #0xbfff,FPTEMP_EX(%a6) |check if incorrectly signalled 29362306a36Sopenharmony_ci beqs not_true_operr |branch if not true operr 29462306a36Sopenharmony_citrue_operr: 29562306a36Sopenharmony_ci movel #1,%d0 |signal real operr 29662306a36Sopenharmony_ci rts 29762306a36Sopenharmony_cinot_true_operr: 29862306a36Sopenharmony_ci clrl %d0 |signal no real operr 29962306a36Sopenharmony_ci rts 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci| 30262306a36Sopenharmony_ci| End_operr tests for operr enabled. If not, it cleans up the stack 30362306a36Sopenharmony_ci| and does an rte. If enabled, it cleans up the stack and branches 30462306a36Sopenharmony_ci| to the kernel operr handler with only the integer exception 30562306a36Sopenharmony_ci| frame on the stack and the fpu in the original exceptional state 30662306a36Sopenharmony_ci| with correct data written to the destination. 30762306a36Sopenharmony_ci| 30862306a36Sopenharmony_ciend_operr: 30962306a36Sopenharmony_ci btstb #operr_bit,FPCR_ENABLE(%a6) 31062306a36Sopenharmony_ci beqs not_enabled 31162306a36Sopenharmony_cienabled: 31262306a36Sopenharmony_ci moveml USER_DA(%a6),%d0-%d1/%a0-%a1 31362306a36Sopenharmony_ci fmovemx USER_FP0(%a6),%fp0-%fp3 31462306a36Sopenharmony_ci fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 31562306a36Sopenharmony_ci frestore (%a7)+ 31662306a36Sopenharmony_ci unlk %a6 31762306a36Sopenharmony_ci bral real_operr 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_cinot_enabled: 32062306a36Sopenharmony_ci| 32162306a36Sopenharmony_ci| It is possible to have either inex2 or inex1 exceptions with the 32262306a36Sopenharmony_ci| operr. If the inex enable bit is set in the FPCR, and either 32362306a36Sopenharmony_ci| inex2 or inex1 occurred, we must clean up and branch to the 32462306a36Sopenharmony_ci| real inex handler. 32562306a36Sopenharmony_ci| 32662306a36Sopenharmony_cick_inex: 32762306a36Sopenharmony_ci moveb FPCR_ENABLE(%a6),%d0 32862306a36Sopenharmony_ci andb FPSR_EXCEPT(%a6),%d0 32962306a36Sopenharmony_ci andib #0x3,%d0 33062306a36Sopenharmony_ci beq operr_exit 33162306a36Sopenharmony_ci| 33262306a36Sopenharmony_ci| Inexact enabled and reported, and we must take an inexact exception. 33362306a36Sopenharmony_ci| 33462306a36Sopenharmony_citake_inex: 33562306a36Sopenharmony_ci moveb #INEX_VEC,EXC_VEC+1(%a6) 33662306a36Sopenharmony_ci movel USER_FPSR(%a6),FPSR_SHADOW(%a6) 33762306a36Sopenharmony_ci orl #sx_mask,E_BYTE(%a6) 33862306a36Sopenharmony_ci moveml USER_DA(%a6),%d0-%d1/%a0-%a1 33962306a36Sopenharmony_ci fmovemx USER_FP0(%a6),%fp0-%fp3 34062306a36Sopenharmony_ci fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 34162306a36Sopenharmony_ci frestore (%a7)+ 34262306a36Sopenharmony_ci unlk %a6 34362306a36Sopenharmony_ci bral real_inex 34462306a36Sopenharmony_ci| 34562306a36Sopenharmony_ci| Since operr is only an E1 exception, there is no need to frestore 34662306a36Sopenharmony_ci| any state back to the fpu. 34762306a36Sopenharmony_ci| 34862306a36Sopenharmony_cioperr_exit: 34962306a36Sopenharmony_ci moveml USER_DA(%a6),%d0-%d1/%a0-%a1 35062306a36Sopenharmony_ci fmovemx USER_FP0(%a6),%fp0-%fp3 35162306a36Sopenharmony_ci fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 35262306a36Sopenharmony_ci unlk %a6 35362306a36Sopenharmony_ci bral fpsp_done 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci |end 356