📄 ppc_fadd.s
字号:
/* */
/* 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 + -