📄 ccmmath_cpu.s
字号:
tmcr wCGR0, FEXP1 textrcb R15, #7 wzero wR0 tmia wR0, FMANT1, FMANT2 /* {wR0} = FMANT1 * FMANT2. */ wsrldg wR0, wR0, wCGR0 tmrrc r3, r0, wR0 movpl r1, #0 movmi r1, #0x80000000 cmp r3, #0x80000000 addhs r0, r0, #1 biceq r0, r0, #1 eor r0, r0, r1 mov pc, lrLABEL(fmul_result_too_big) tst r0, #0x01000000 /* if result has carry, return inf */ bne fmul_return_inf movs r3, r3, lsl #1 adc r0, r0, #0 bcs fmul_result_too_big_roundLABEL(fmul_result_too_big_round_done) tst r0, #0x01000000 /* if result has carry, return inf */ bne fmul_return_inf textrcb R15, #7 bic r0, r0, #0x01800000 orrmi r0, r0, #0x80000000 orr r0, r0, FEXP1, lsr #1 mov pc, lrLABEL(fmul_result_too_big_round) teq r3, #0 biceq r0, r0, #1 b fmul_result_too_big_round_doneLABEL(fmul_fexp_too_big) cmp FEXP1, #0x7e000000 blo fmul_result_normalLABEL(fmul_return_inf) textrcb R15, #7 mov r0, #0x7f000000 add r0, r0, #0x00800000 orrmi r0, r0, #0x80000000 mov pc, lr#undef FEXP1#undef FEXP2#undef FMANT1#undef FMANT2#undef SIGN#else /* The following saves registers that we're going to use and extracts exponents and mantissa from the floats. */ mov EMASK, #0xff /* Setup the pre-shifted exponent mask. */ stmfd sp!, FLOAT_SAVE_SET and EXP1, EMASK, FLOAT1, LSR #23 /* Extract exponent1. */ and EXP2, EMASK, FLOAT2, LSR #23 /* Extract exponent2. */ mvn MMASK, #0x80000000 and MANT1, MMASK, FLOAT1, LSL #8 /* Extract mantissa1. */ and MANT2, MMASK, FLOAT2, LSL #8 /* Extract mantissa2. */ /* NOTE: r12 is free now because MMASK is no longer needed. */ /* Set the sign bit in r0 and free up r1: */ eor r0, r0, r1 /* Positive if same, else negative. */ and r0, r0, #0x80000000 /* Zero out the other bits. */ /* Check if float1 or float2 is NaN or infinity: */ cmp EXP1, #0xff /* Check for infinity or nan. */ cmpne EXP2, #0xff /* Check for infinity or nan. */ beq _fmulFloatCheckForNaNOrInfinity /* Check float1 for 0 or denormalized number: */ cmp EXP1, #0 beq _fmulCheckFloat1ForZero orr MANT1, MANT1, #0x80000000 /* Set the implied high bit. */LABEL(_fmulFloat1IsNotZero) cmp EXP2, #0 beq _fmulCheckFloat2ForZero orr MANT2, MANT2, #0x80000000 /* Set the implied high bit. */LABEL(_fmulFloat2IsNotZero) /* Now we're ready to do the multiplication. First add the exponents together and store the result in EXP1. EXP2 is free after that: */ sub EXP1, EXP1, #126 /* exp1 -= 127 (i.e. the bias) + 1. */ add EXP1, EXP1, EXP2 /* exp1 = exp1 + exp2. */ /* After the multiplication, the resultant binary point will be 2 digits from the high end of the 64 bit number as follows: result = [xx.xx xxxx xxxx xxxx xxxx xxxx 0000 0000] But we want the binary point to be 1 from the high end. To do this we divide the number by 2 and add 1 to the exponent. Well, we don't actually have to divide the number by 2. We just know that the binary point is now 1 from the left. EXP1 is already incremented above. See how the bias is being subtracted from it. */ umull r3, r1, MANT1, MANT2 /* {hi<r1>,lo<r3>} = MANT1 * MANT2. */ /* NOTE: r6, r7, and r12 are now free again: */ /* Normalize the result: */ cmp EXP1, #1 blt _fmulDoGradualUnderflow0 /* Normalize the resultant mantissa if necessary: */ movs MANT1, r1 /* Put the mantissa in { r6, r3 } */ bmi _fmulCheckForStickyBit /* If high bit is set (i.e. already */ /* normalized, then move on. */LABEL(_fmulNormalizing) cmp EXP1, #1 /* See if exponent is down to 1. */ beq _fmulCheckForStickyBit /* Cannot normalize. Go wrap-up. */ /* Shift the 64bit number left by 1: */ movs r3, r3, LSL #1 /* Shift low-order word left by 1. */ sub EXP1, EXP1, #1 /* exponent--. */ adcs MANT1, MANT1, MANT1 /* Shift high-order word left by 1. */ bpl _fmulNormalizing /* If high bit not set, continue. */ /* Fall through to _fmulCheckForStickyBit. */#endif/* IAI - 16 */LABEL(_fmulCheckForStickyBit) /* Is already normalized. Check the sticky bit for rounding: */ cmp r3, #0 orrne MANT1, MANT1, #0x20 /* Set the sticky bit if necessary. */ b _floatRoundResult /* Go round the result and exit. */LABEL(_fmulDoGradualUnderflow0) mov MANT1, r1 /* Put the mantissa in { r6, r3 } */ /* Fall thru to _fmulDoGradualUnderflow: */LABEL(_fmulDoGradualUnderflow) /* Compute the number of bits we have to shift right by in order to bring EXP1 up to 1: */ rsb r7, EXP1, #1 cmp r7, #31 /* If we have to shift 31 or more bits, then the result must be an underflow to zero: */ FLOAT_RETURN_TO_CALLER_IF(ge) /* result = sign | 0. */ /* Else, shift right and let the rounding do gradual underflow: */ mov EXP1, #1 orr r3, r3, MANT1, LSL r7 /* Compute the sticky bit. */ mov MANT1, MANT1, LSR r7 /* Shift right be said bits. */ b _fmulCheckForStickyBit /* Go do rounding for the result. *//* IAI - 16 */#ifndef IAI_WMMX_FMULLABEL(_fmulCheckFloat1ForZero) /* If we get here, then float1 and float2 are finite: */ cmp MANT1, #0 /* Check for 0. */ FLOAT_RETURN_TO_CALLER_IF(eq) /* result = sign | 0. Return to caller. */ mov EXP1, #1 /* Adjust exponent for denormalized #. */ b _fmulFloat1IsNotZeroLABEL(_fmulCheckFloat2ForZero) /* If we get here, then float1 and float2 are finite: */ cmp MANT2, #0 /* Check for 0. */ FLOAT_RETURN_TO_CALLER_IF(eq) /* result = sign | 0. Return to caller. */ mov EXP2, #1 /* Adjust exponent for denormalized #. */ b _fmulFloat2IsNotZeroLABEL(_fmulFloatCheckForNaNOrInfinity) /* Check if float1 is NaN or infinity: */ cmp EXP1, #0xff /* Check for infinity or nan. */ beq _fmulFloat1CheckForNaNOrInfinity /* Else, float2 is NaN or infinity: */LABEL(_fmulFloat2CheckForNaNOrInfinity) /* If we get here, then float1 is not nan nor infinity: */ cmp MANT2, #0 /* Check for infinity. */ bne _floatReturnNaN /* finite * nan => nan. */ /* Else, float2 is an infinity. Check float1 for 0: */ orrs r12, EXP1, MANT1 /* Check for 0. */ beq _floatReturnNaN /* 0 * inf => nan. */ b _floatReturnInfinity /* finite * inf => inf. */LABEL(_fmulFloat1CheckForNaNOrInfinity) cmp MANT1, #0 /* Check for infinity. */ bne _floatReturnNaN /* nan * ? => nan. */ /* Else, float1 is an infinity. Check float2 for nan or infinity: */ cmp EXP2, #0xff bne _fmulFloat1CheckForZeroInFloat2 cmp MANT2, #0 /* Check for infinity. */ bne _floatReturnNaN /* inf * nan => nan. */ b _floatReturnInfinity /* inf * inf => inf. */LABEL(_fmulFloat1CheckForZeroInFloat2) orrs r12, EXP2, MANT2 /* Check for 0. */ beq _floatReturnNaN /* inf * 0 => nan. */ b _floatReturnInfinity /* inf * finite => inf. */#endif/* IAI - 16 *//* * The following are common to FAdd, FSub, and FMul: */LABEL(_floatRoundResult) /* NOTE: _floatRoundResult expects the sign in r0, the exponent in EXP1 (i.e. r2), and the normalized mantissa in MANT1 (i.e. r6) with the binary point between bit 31 and 30. */ /* Round the mantissa using IEEE 754 round to nearest mode: */ and r12, MANT1, #0xff /* Extract the low 8 bits for rounding. */ cmp r12, #0x80 blt _floatRoundingDone /* Round down. Nothing to do. */ bgt _floatRoundUp /* Go round up. */ /* Else round to the nearest 0 in the LSBit in the result mantissa: */ tst MANT1, #0x100 /* Check LSBit of result mantissa. */ beq _floatRoundingDone /* If already 0, then done rounding. */ /* Else, round up. */LABEL(_floatRoundUp) adds MANT1, MANT1, #0x80 /* After rounding, we have to re-check if we're normalized, and re- normalize if we're not: */ bcc _floatRoundingDone /* If we get here, then the high bit was in the carry. Move the carry back into the high bit and adjust the exponent accordingly: */ mov MANT1, MANT1, LSR #1 orr MANT1, MANT1, #0x80000000 add EXP1, EXP1, #1 /* Fall through to _floatRoundingDone. */LABEL(_floatRoundingDone) /* Now check for overflow to infinities: */ cmp EXP1, #255 bge _floatReturnInfinity /* Check to see if the result is a denormalized number: */ tst MANT1, #0x80000000 /* If the number is denormalized, mark it as so: */ moveq EXP1, #0 /* Indicate denormalized. */ /* Only do the following 2 inst if result is normalized: */ bicne MANT1, MANT1, #0x80000000 /* Clear the top bit. */ orrne r0, r0, EXP1, LSL #23 /* Set the exponent. */ mov MANT1, MANT1, LSR #8 /* Set the mantissa. */ orr r0, r0, MANT1 /* Fall through to _floatReturnToCaller. */LABEL(_floatReturnToCaller) /* Restore the saved registers: */ FLOAT_RETURN_TO_CALLER /* Return to caller. */LABEL(_floatReturnInfinity) mov r1, #0xff orr r0, r0, r1, LSL #23 /* result = sign | infinity. */ FLOAT_RETURN_TO_CALLER /* Return the result */LABEL(_floatReturnNaN) ldr r0, floatNaN /* result = nan. */ FLOAT_RETURN_TO_CALLER /* Return the result *//* * Entry point for dividing floats. * NOTE: The result is in r0. */ ENTRY(CVMCCMruntimeFDiv)ENTRY1 ( CVMCCMruntimeFDiv ) ENTRY(CVMCCMruntimeFDiv_C)ENTRY1 ( CVMCCMruntimeFDiv_C ) /* r0 = a1 = float1 * r1 = a2 = float2 * v1 = jfp * v2 = jsp * sp = ccee */#define QUOT r12#define ITER r3 /* The following saves registers that we're going to use and extracts exponents and mantissa from the floats. */ stmfd sp!, FLOAT_SAVE_SET mov EMASK, #0xff /* Setup the pre-shifted exponent mask. */ and EXP1, EMASK, FLOAT1, LSR #23 /* Extract exponent1. */ and EXP2, EMASK, FLOAT2, LSR #23 /* Extract exponent2. */ orr EMASK, EMASK, #0x100 bic MANT1, FLOAT1, EMASK, LSL #23 /* Extract mantissa1. */ bic MANT2, FLOAT2, EMASK, LSL #23 /* Extract mantissa2. */ /* Set the sign bit in r0 and free up r1: */ eor r0, r0, r1 /* Positive if same, else negative. */ and r0, r0, #0x80000000 /* Zero out the other bits. */ /* Check if float1 or float2 is NaN or infinity: */ cmp EXP1, #0xff /* Check for infinity or nan. */ cmpne EXP2, #0xff /* Check for infinity or nan. */ beq _fdivFloatCheckForNaNOrInfinity /* Check float1 for 0 or denormalized number: */ cmp EXP1, #0 beq _fdivCheckFloat1ForZero orr MANT1, MANT1, #0x800000 /* Set the implied high bit. */LABEL(_fdivFloat1IsNotZero) cmp EXP2, #0 beq _fdivCheckFloat2ForZero orr MANT2, MANT2, #0x800000 /* Set the implied high bit. */LABEL(_fdivFloat2IsNotZero) /* * Now we're ready to do the division. First subtract the exponents * and store the result in EXP1. EXP2 is free after that. * Ensure that the first digit of the quotient will be a '1' * by shifting MANT1 if necessary. Decrease exponent accordingly. * * Do the division as 25 successive divide steps * of MANT1 by MANT2, developing the quotient in QUOT. */ sub EXP1, EXP1, EXP2 /* exp1 = exp1 - exp2. */ add EXP1, EXP1, #127 /* exp1 += 127 (i.e. the bias) */ cmp MANT1, MANT2 movlt MANT1, MANT1, LSL #1 sublt EXP1, EXP1, #1 mov ITER, #25 mov QUOT, #0 /* loop unrolled by a factor of 5 */LABEL(_fdivIterationLoopTop) cmp MANT1, MANT2 subhs MANT1, MANT1, MANT2 adc QUOT, QUOT, QUOT mov MANT1, MANT1, LSL #1 cmp MANT1, MANT2 subhs MANT1, MANT1, MANT2 adc QUOT, QUOT, QUOT mov MANT1, MANT1, LSL #1 cmp MANT1, MANT2 subhs MANT1, MANT1, MANT2 adc QUOT, QUOT, QUOT mov MANT1, MANT1, LSL #1 cmp MANT1, MANT2 subhs MANT1, MANT1, MANT2 adc QUOT, QUOT, QUOT mov MANT1, MANT1, LSL #1 cmp MANT1, MANT2 subhs MANT1, MANT1, MANT2 adc QUOT, QUOT, QUOT mov MANT1, MANT1, LSL #1 subs ITER, ITER, #5 bgt _fdivIterationLoopTop /* adjust remainder: only for non-restoring. */ /* cmp MANT1, #0 */ /* addlt MANT1, MANT1, MANT2 */ /* * In order to share rounding and packing code with fmul, * move QUOT to MANT1, shifting left s.t. the high-order bit is set. * Also insert the sticky bit. */ cmp MANT1, #0 mov MANT1, QUOT, LSL #7
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -