📄 ccmmath_cpu.s
字号:
cmp EXP1, #0xff /* Check float1 for infinity or nan. */ cmpne EXP2, #0xff /* Check float2 for infinity or nan. */ beq _faddFloatCheckForNanOrInfinity /* If we get here, then both float1 and float2 are not infinities nor NaNs. From this point forth, we'll use r12 for scratch regs instead of EMASK and MMASK. */ /* Check for zeroes or denormalized numbers: */ cmp EXP1, #0 beq _faddCheckFloat1ForZero orr MANT1, MANT1, #0x40000000 /* Else, set implied high bit. */LABEL(_faddFloat1IsNotZero) cmp EXP2, #0 beq _faddCheckFloat2ForZero orr MANT2, MANT2, #0x40000000 /* Else, set implied high bit. */LABEL(_faddFloat2IsNotZero) /* Make sure the magnitude of float1 is larger than the magnitude of float2. If not, then swap the two:*/ cmp EXP1, EXP2 /* Compare exponents. */ cmpeq MANT1, MANT2 /* Compare mantissas. */ blt _faddSwapFloat1AndFloat2LABEL(_faddFloat1IsGreaterThanFloat2) /* At this point, the mantissas should be fixed point numbers where the binary point is between bit 30 and 29: */ /* Prepare float1 and float2 for addition: */ sub r12, EXP1, EXP2 /* r12 = order of magniture difference. */ cmp r12, #7 /* At this point, EXP2 i.e. r3 is free to be used as a scratch. */ /* Adjust float2 to the same order of magnitude as float1 if OK to do so: */ movle MANT2, MANT2, LSR r12 ble _faddReadyToAddOrSubtract /* Save the excess bits shifted out from MANT2. All we care about is whether they are 0 or not: */ cmp r12, #32 rsblt r3, r12, #32 movlt r3, MANT2, LSL r3 movge r3, MANT2 /* Adjust float2 to the same order of magnitude as float1: */ mov MANT2, MANT2, LSR r12 cmp r3, #0 orrne MANT2, MANT2, #0x10 /* Adjust for rounding later. */LABEL(_faddReadyToAddOrSubtract) /* Set the result sign in r0: */ and r0, FLOAT1, #0x80000000 /* Set r0 = result sign. */ /* We now move the implied binary point to between bit 31 and 30 (i.e. left by one). We need to compensate for this by incrementing the exponent: */ add EXP1, EXP1, #1 /* Check if the signs are the same: */ eors r12, FLOAT1, FLOAT2 /* Check if the sign bit is the same. */ bpl _faddDoAdd /* High bit will not be set if same. */LABEL(_faddDoSub) subs MANT1, MANT1, MANT2 /* Subtract and set condition codes. */ beq _faddReturnZero /* If zero, then go return zero. */LABEL(_faddNormalizeResult) /* If we get here, then we know MANT1 is not zero. It's OK to keep shifting until we find a bit because there is bound to be 1 within the 32 bits of MANT1: */LABEL(_faddNormalizing) cmp EXP1, #1 /* Else, normalized if necessary. */ beq _floatRoundResult /* Cannot normalize, go wrap-up. */ adds MANT1, MANT1, MANT1 /* Shift left by 1. */ sub EXP1, EXP1, #1 bpl _faddNormalizing /* If implied high bit is not found, */ /* continue looking. */ b _floatRoundResult /* then go do rounding. */LABEL(_faddDoAdd) /* If we get here, the signs are the same. We can just add both numbers as if they are positive numbers, and then reapply the original when we're done. */ adds MANT1, MANT1, MANT2 /* Add and set condition codes. */ bpl _faddNormalizeResult /* If high bit is not set, go normalize. */ b _floatRoundResult /* Go round result. */LABEL(_faddSwapFloat1AndFloat2) /* Swap the values in { float1, exponent1, mantissa1 } with the values in { float2, exponent2, mantissa2 }: */ mov r12, EXP1 mov EXP1, EXP2 mov EXP2, r12 mov r12, MANT1 mov MANT1, MANT2 mov MANT2, r12 mov r12, FLOAT1 mov FLOAT1, FLOAT2 mov FLOAT2, r12 b _faddFloat1IsGreaterThanFloat2LABEL(_faddCheckFloat1ForZero) cmp MANT1, #0 /* Check to see if float1 is a zero. */ beq _faddFloat1IsZero mov EXP1, #1 /* Else, not zero. Adjust EXP1 because */ b _faddFloat1IsNotZero /* it is implied to be 1. */LABEL(_faddFloat1IsZero) /* Check if float2 is also zero: */ cmp EXP2, #0 bne _faddReturnFloat2 /* float2 not zero. Return float2. */ cmp MANT2, #0 bne _faddReturnFloat2 /* float2 not zero. Return float2. */ /* Fall through to _faddReturnZero. */LABEL(_faddReturnZero) /* If the signs are the same, return the zero of said sign. Else, return positive 0: */ and r0, FLOAT1, FLOAT2 /* Massage the signs. */ and r0, r0, #0x80000000 /* Else return 0 with sign of the */ FLOAT_RETURN_TO_CALLER /* larger number (magnitude-wise). */LABEL(_faddCheckFloat2ForZero) /* If we get here, then we know that float1 is not zero because _faddFloat1IsZero would have already taken care of it otherwise. */ cmp MANT2, #0 /* check to see if float2 is zero. */ FLOAT_RETURN_TO_CALLER_IF(eq) /* If 0, return float1 in r0. */ mov EXP2, #1 /* Else, not zero. Adjust EXP2 because */ b _faddFloat2IsNotZero /* it is implied to be 1. */LABEL(_faddFloatCheckForNanOrInfinity) /* Check if float1 is NaN or infinity: */ cmp EXP1, #0xff /* Check for infinity or nan. */ beq _faddFloat1CheckForNanOrInfinity /* Else, float2 is NaN or infinity: */LABEL(_faddFloat2CheckForNanOrInfinity) /* If we get here, then we know that float1 is finite. The result will be what ever is in float2 (i.e. infinity or NaN): */LABEL(_faddReturnFloat2) mov r0, FLOAT2 /* result = float2. */ FLOAT_RETURN_TO_CALLER /* Return the result. */LABEL(_faddFloat1CheckForNanOrInfinity) cmp MANT1, #0 /* Check if float1 is an infinity. */ /* If not an infinity, then must be a NaN: */ /* The return value in r0 is a NaN already because r0 contains the value of float1 which is a Nan. */ FLOAT_RETURN_TO_CALLER_IF(ne) /* result = NaN + ? => NaN. */ /* If we get here, than float1 is an infinity. We must return check if float2 is a NaN or an infinity or finite: */ cmp EXP2, #0xff /* Check if float2 is NaN or infinity. */ /* If is finite (i.e. not NaN or infinity), then just return the infinity value in float1 which is already in r0: */ FLOAT_RETURN_TO_CALLER_IF(ne) /* Return the result. */ cmp MANT2, #0 /* Check if float2 is an infinity. */ /* If not an infinity, then must be a NaN: */ movne r0, FLOAT2 /* Return the NaN in float2. */ FLOAT_RETURN_TO_CALLER_IF(ne) /* Return the result. */ /* We have 2 infinities: */ eor r12, FLOAT1, FLOAT2 /* NOTE: MMASK<r12> is no longer needed. */ tst r12, #0x80000000 /* Check if the sign bit is the same. */ /* If the sign bit is the same, then just return the infinity already in r0 (i.e. float1): */ FLOAT_RETURN_TO_CALLER_IF(eq) /* Return the result. */ /* Else, return a NaN: */ ldr r0, floatNaN /* result = NaN (0x7f800000). */ FLOAT_RETURN_TO_CALLER /* Return the result. */#endif/* IAI - 16 *//* * Entry point for multiplying floats. * NOTE: The result is in r0. */ ENTRY(CVMCCMruntimeFMul)ENTRY1 ( CVMCCMruntimeFMul ) ENTRY(CVMCCMruntimeFMul_C)ENTRY1 ( CVMCCMruntimeFMul_C ) /* r0 = a1 = float1 * r1 = a2 = float2 * v1 = jfp * v2 = jsp * sp = ccee *//* IAI - 16 */#ifdef IAI_WMMX_FMUL#define FEXP1 r2#define FEXP2 r3#define FMANT1 ip#define FMANT2 r1#define SIGN r3 eor SIGN, FLOAT1, FLOAT2 /* Positive if same, else negative. */ tmcr wCASF, SIGN /* move SIGN to WMMX register */ mov EMASK, #0xff000000 /* Setup the pre-shifted exponent mask. */ ands FEXP1, EMASK, FLOAT1, LSL #1 /* Extract exponent1. */ beq fmul_fexp1_equal_0 ands FEXP2, EMASK, FLOAT2, LSL #1 /* Extract exponent2. */ beq fmul_fexp1_not_equal_0_fexp2_equal_0 cmp FEXP1, EMASK cmpne FEXP2, EMASK beq fmul_fexp_equal_emask adds FEXP1, FEXP1, FEXP2 /* exp1 = exp1 + exp2. */ bcs fmul_fexp_too_big bpl fmul_result_denormal_pre1 /* result needs to be donormalized */LABEL(fmul_result_normal) eor FMANT2, FEXP2, FLOAT2, LSL #1 /* Extract mantissa1. */ mov FMANT1, FLOAT1, LSL #8 /* Extract mantissa2. */ orr FMANT2, FMANT2, #0x01000000 orr FMANT1, FMANT1, #0x80000000 umull r3, r0, FMANT1, FMANT2 /* {hi<r0>,lo<r3>} = FMANT1 * FMANT2. */ sub FEXP1, FEXP1, #0x7f000000 /* exp1 -= 127 (i.e. the bias). */ cmp FEXP1, #0xfe000000 bhs fmul_result_too_bigLABEL(fmul_process_result) tst r0, #0x01000000 addne FEXP1, FEXP1, #0x01000000 movnes r0, r0, lsr #1 moveqs r3, r3, lsl #1 adc r0, r0, #0 bcs fmul_process_result_round /* r3 = #0x8xxxxxxx */LABEL(fmul_process_result_done) tst r0, #0x01000000 addne FEXP1, FEXP1, #0x01000000 textrcb R15, #7 bic r0, r0, #0x01800000 orrmi r0, r0, #0x80000000 orr r0, r0, FEXP1, lsr #1 mov pc, lr /* normalized result returned. */LABEL(fmul_process_result_round) teq r3, #0 biceq r0, r0, #1 b fmul_process_result_doneLABEL(fmul_fexp1_equal_0) movs r3, FLOAT1, LSL #8 beq fmul_float1_equal_0 clz FEXP1, r3 mov FLOAT1, FLOAT1, LSL FEXP1 rsb FEXP1, FEXP1, #0 mov FEXP1, FEXP1, LSL #24 /* Normalize FLOAT1 and compute FEXP1 */ ands FEXP2, EMASK, FLOAT2, LSL #1 /* Extract exponent2. */ beq fmul_return_zero cmp FEXP2, EMASK beq fmul_float2_0_or_fexp2_emask adds FEXP1, FEXP1, FEXP2 /* exp1 = exp1 + exp2. */ bpl fmul_result_denormal_pre2 addcs FEXP1, FEXP1, #0x01000000 /* exp1 = exp1 + 1 for normalized result */ bcs fmul_result_normalLABEL(fmul_return_zero) textrcb R15, #7 mov r0, #0x0 orrmi r0, r0, #0x80000000 mov pc, lrLABEL(fmul_float1_equal_0) and FEXP2, EMASK, FLOAT2, LSL #1 /* Extract exponent2. */ cmp FEXP2, EMASK moveq r0, #0x7f000000 addeq r0, r0, #0x00c00000 /* return NaN */ andne r1, r1, #0x80000000 eorne r0, FLOAT1, FLOAT2 @ return +/- 0 mov pc, lrLABEL(fmul_fexp1_not_equal_0_fexp2_equal_0) cmp FEXP1, EMASK beq fmul_fexp1_emask_fexp2_0 movs r3, FLOAT2, LSL #8 beq fmul_float2_0_or_fexp2_emask clz FEXP2, r3 mov FLOAT2, FLOAT2, LSL FEXP2 subs FEXP1, FEXP1, FEXP2, LSL #24 /* exp1 = exp1 + exp2. */ bpl fmul_result_denormal_pre3 bcc fmul_return_zeroLABEL(fmul_fexp1_not_equal_0_fexp2_equal_0_process) mov FMANT1, FLOAT1, LSL #8 /* Extract mantissa2. */ mov FMANT2, FLOAT2, LSL #1 orr FMANT1, FMANT1, #0x80000000 umull r3, r0, FMANT1, FMANT2 /* {hi<r0>,lo<r3>} = FMANT1 * FMANT2. */ sub FEXP1, FEXP1, #0x7e000000 /* exp1 -= 126 (i.e. the bias). */ b fmul_process_resultLABEL(fmul_fexp1_emask_fexp2_0) movs r3, FLOAT2, LSL #8 moveq r0, #0x7f000000 addeq r0, r0, #0x00c00000 /* return NaN */ andne r1, r1, #0x80000000 /* return +/- 0 */ eorne r0, r0, r1 mov pc, lrLABEL(fmul_fexp_equal_emask) cmp FEXP1, EMASK bne fmul_float2_0_or_fexp2_emask cmp FEXP2, EMASK beq fmul_fexp1_and_fexp2_equal_emask and r1, r1, #0x80000000 eor r0, r0, r1 mov pc, lrLABEL(fmul_fexp1_and_fexp2_equal_emask) orr FLOAT1, FLOAT1, FLOAT2 textrcb R15, #7 bicpl r0, FLOAT1, #0x80000000 /* return +/- inf or NaN */ mov pc, lrLABEL(fmul_float2_0_or_fexp2_emask) textrcb R15, #7 bicpl r0, FLOAT2, #0x80000000 orrmi r0, FLOAT2, #0x80000000 /* return +/- 0 or inf or NaN */ mov pc, lrLABEL(fmul_result_denormal_pre3) cmp FEXP1, #0x7f000000 /* special case */ beq fmul_fexp1_not_equal_0_fexp2_equal_0_process b fmul_result_denormalLABEL(fmul_result_denormal_pre2) cmp FEXP1, #0x7f000000 /* special case */ addeq FEXP1, FEXP1, #0x01000000 beq fmul_result_normal b fmul_result_denormalLABEL(fmul_result_denormal_pre1) sub FEXP1, FEXP1, #1LABEL(fmul_result_denormal) subs FEXP1, FEXP1, #0x66000000 /* fexp1 < -25 */ blt fmul_return_zero mov FMANT2, FLOAT2, LSL #8 /* Extract mantissa1. */ mov FMANT1, FLOAT1, LSL #8 /* Extract mantissa2. */ mov FMANT2, FMANT2, LSR #3 mov FMANT1, FMANT1, LSR #4 orr FMANT2, FMANT2, #0x10000000 orr FMANT1, FMANT1, #0x08000000 mov FEXP1, FEXP1, LSR #24 rsb FEXP1, FEXP1, #25
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -