⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ppc_fadd.s

📁 powerpc 405 优化过的硬浮点库
💻 S
📖 第 1 页 / 共 2 页
字号:
/*                                                                              */
/* If we get here, the exponent is known to be within range             */
/*   Reason:  "big" must have had a finite exponent, and the only       */
/*   place the result exponent can be bumped is just above.                     */
/*   Further, potential underflow is being handled in the                       */
/*   unnormalized sum code.                                                     */
/*                                                                              */
do_round:
     addis     r0,r0,0x8000          /* get word with only sign bit on */
     cmpl      cr7,r11,r0            /* test bits to be discarded */
     cmpi      cr6,r12,0             /* check low-order word */
     rlwimi    r9,r5,20,0x7FF00000   /* insert final exponent */
     blt       cr7,do_sign           /* <1/2.. no change */
     addi      r0,r0,1               /* get a 1 in R0 */
     bgt       cr7,add_1             /* >1/2.. round up */
     bne       cr6,add_1             /* > 1/2 */
     rlwinm    r0,r10,0,0x1          /* get last bit of fraction */
add_1:
     addc      r10,r10,r0            /* round. */
     addze     r9,r9                 /* carry.  (carry into exp is correct) */
/*                                                                              */
/* Common exit point.  Final DP value is in r9.r10, except for the sign bit. */
/*                                                                              */
do_sign:
     mfcr      r6                    /* copy CR to r6 */
     rlwimi    r9,r6,16,0x80000000   /* final sign bit is in CR4 lt (bit 16) */
do_store:
     mfctr     r7                    /* get saved CR */
     mtcr      r7                    /* restore saved     CR */
     mr        r3,r9                 /* high word already in r3 */
     mr        r4,r10                /* store low word */
     blr                             /* and return */
/*                                                                              */
/*                                                                              */
ret_big:
     mr        r9,r8                 /* just return "big" */
     mr        r10,r7   
     rlwimi    r9,r5,20,0x7FF00000   /* jam in the exponent for big */
     b         do_sign
/*                                                                      */
/* Here when signs differ and a subtract must be performed              */
/*                                                                      */
do_sub:
     subfic    r12,r12,0             /* yes. subtract "small" from "big" */
     subfze    r11,r11
     subfe     r10,r10,r7
     subfe.    r9,r9,r8
     bge       cr0,sign_ok           /* was "small" actually > "big"? */
                                     /* NB: r11,r12 must be zero */
                                     /* and r9 becomes all zero */
     subfic    r10,r10,0
     subfze    r9,r9
     crnor     cr4_lt,cr4_lt,cr4_lt  /* flip sign of result */
     addi      r7,0,32               /* load leading bit count */
     b         unnorm_res              /* must have at least 20 leading zero bits */
/*                                                                              */
sign_ok:
     or        r0,r11,r12            /* first step in zero check */
     bgt       cr0,normalize         /* if > 0, then it's not Zero */
     or.       r0,r0,r10             /* if r9 is zero, and all the others too */
     beq       cr0,res_Zero          /* result is exactly zero */
/*                                                                              */
normalize:
     cntlzw    r7,r9                 /* check leading zero bits */
     cmpwi     cr0,r7,11             /* */
     ble       cr0,do_round          /* just right.  round to double */
                                     /* (can only have diminished fraction) */
/*                                                                          */
/* Here when the result (fraction) is unnormalized.                         */
/*                                                                          */
unnorm_res:
     cmpwi     cr1,r7,32             /* see if first bit is in high word */
     cntlzw    r0,r10                /* count leading bits in low */
     addi      r7,r7,-11             /* get normalization shift amount */
     bne       cr1,getexp            /* is high == 0, then leading bit is in low */
     add       r7,r7,r0              /* get true count */
getexp:
     subfc     r5,r7,r5              /* get correct exponent */
     cmpwi     cr2,r5,1              /* check for minimum */
     bge       cr2,shift_ok          /* OK? */
     add       r7,r7,r5              /* No. add -ve exp to shift amount */
     addi      r7,r7,-1              /* account for min exp == 1 */
     addi      r5,0,0                /* new exp is minimum */
/*                                                                              */
shift_ok:
     cmpwi     cr0,r7,32             /* at least whole word? */
     rlwinm    r0,r7,0,0x1F          /* compute part-word shift count */
     blt       cr0,part_word         /* is shift at least 1 word? */
     ori       r9,r10,0              /* yes */
     ori       r10,r11,0
     xor       r11,r11,r11           /* zero r11 */
part_word:                           /* r0 contains part-word norm shift count */
     cmpwi     cr3,r7,1              /* was shift amount == 1? */
     subfic    r8,r0,32              /* get complementary amount */
     slw       r9,r9,r0              /* shift     high word */
     srw       r6,r10,r8
     or        r9,r9,r6              /* */
     slw       r10,r10,r0
     srw       r6,r11,r8
     or        r10,r10,r6
     slw       r11,r11,r0            /* shifted <r9, r10, r11> left by (r0) */
/*                                                                              */
     beq       cr3,do_round          /* norm count == 1. just do usual rounding */
     rlwimi    r9,r5,20,0x7FF00000   /* insert final exponent */
     b         do_sign                 /* there     can be no bits to round */
/*                                                                           */
/*                                                                           */
/* When result is exactly zero, there can be two reasons:                    */
/*     - the operands were identical, but of opposite signs, in              */
/*       which case the result must be +0                                    */
/*     - the operands were both zero to begin with.  x + x is required       */
/*       have the same     sign as x, so (+0) + (+0) => +0, and              */
/*          (-0) + (-0) => -0, but                                           */
/*          (+0) + (-0) => +0                                                */
/* the lt bit of CR4 is the sign of the "big" operand, and the eq bit        */
/* is set on iff the operand signs were different.  We must always return +0 */
/* when the signs are different, and otherwise the sign of the "big" operand */
/*                                                                           */
res_Zero:
     crandc    cr4_lt,cr4_lt,cr4_eq  /* fiddle the sign of the result */
     b         do_sign               /* and finish up */
/*                                                                              */
/* Here when final exponent before rounding is too big                          */
/*                                                                              */
out_of_range:
     addis     r9,0,0x7FF0           /* return a INF */
     xor       r10,r10,r10           /* */
     b         do_sign               /* with sign of "big" */
/*                                                                              */
/* A is INF or NaN (B might be also)                                            */
/*                                                                              */
A_is_spec:
     mr        r10,r4                /* get low word of A */
     rlwinm    r9,r8,0,0x000FFFFF    /* get fraction (high) */
     or.       r0,r9,r10             /* check for NaN */
     oris      r9,r8,0x0008          /* assume A is a NaN.  Quiesce it */
     bne       cr0,do_store          /* A is NaN. Just finish */
/*                                                                              */
     ori       r9,r8,0               /* A is INF.  Set up <r9,r10> with A */
     bne       cr1,do_store          /* all done if B is finite */
     mr        r10,r6                /* get low part of B */
                                     /*   doesn't hurt - either it's a NaN (low) */
                                     /*   or it's zero like A (low) */
     rlwinm    r11,r7,0,0x000FFFFF   /* get B fraction (high) */
     cmpwi     cr7,r7,0              /* CR7_lt == frb sign bit */
     or.       r0,r11,r10            /* any non-zero bits? */
/*                                                                              */
     xor       r0,r7,r8              /* both A and B are INF. INF - INF => NaN */
                         /*   Assume that r10 == 0, and both r7 and r8 are INFs */
                         /*   so either result is same as A(INF) or is NaN (if */
                         /*   signs are different */
     rlwimi    r9,r0,20,0x00080000   /* generate either INF or NaN from A (r9 set up earlier) */
     crand     cr4_lt,cr6_lt,cr7_lt  /* sign is sign of A if same, else + */
     beq       cr0,do_sign           /* if B was INF, we're done */
/*                                                                              */
     mr        r9,r5                 /* get high part of B */
     oris      r9,r9,0x0008          /* rats! quiesce the NaN */
     b         do_store              /* finish up */

/*                                                                              */
/* here when B is either INF or NaN (but A is neither)                  */
/*                                                                              */
B_is_spec:
     mr        r10,r6                /* get low part of B */
     rlwinm    r11,r7,0,0x000FFFFF   /* get B fraction (high) */
     or.       r0,r11,r10            /* any non-zero bits? */
     beq       B_is_inf
     mr        r9,r5                 /* get high part of B */
     oris      r9,r9,0x0008          /* quiesce NaN */
     b         do_store

B_is_inf:
     ori       r9,r7,0               /* B is INF */
     b         do_store              /* done */

function_epilog(__adddf3)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -