📄 ccmmath_cpu.s
字号:
/* * @(#)ccmmath_cpu.S 1.112 06/10/10 * * Portions Copyright 2000-2008 Sun Microsystems, Inc. All Rights * Reserved. Use is subject to license terms. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. *//* * Copyright 2005 Intel Corporation. All rights reserved. */#include "javavm/include/asmmacros_cpu.h"#include "javavm/include/porting/endianness.h"#include "javavm/include/iai_opt_config.h"#ifdef __RVCT__#define OR2(x,y) ((x) :OR: (y))#define OR3(x,y,z) ((x) :OR: (y) :OR: (z))#define OR4(x,y,z,p) ((x) :OR: (y) :OR: (z) :OR: (p))#else#define OR2(x,y) ((x) | (y))#define OR3(x,y,z) ((x) | (y) | (z))#define OR4(x,y,z,p) ((x) | (y) | (z) | (p))#endif/* * NOTE: Some linker such as the ARM RVCT (v2.2) linker sorts * sections by attributes and section name. To make sure * the CCM copied code in the same order as they are included * in ccmcodecachecopy_cpu.S, we need to name the sections * in alphabetical order. */ SET_SECTION_EXEC(s4_ccmmath_cpu)/************************************* * Float helpers start here! *************************************/ /* * Entry point for comparing floats. * NOTE: The result is in the condition codes that have been set by various * comparisons. Even though the C prototype for this helper indicates * that the helper is to return an integer status in a register, this * assembly version returns the result in the CPU condition code * register (thus effectively making the return type of the function * void). This is OK because the ARM specific rules which emits calls * to this helper function will be expecting the result to be in the * condition code register. This method of returning the result is * done for optimization purposes. */ ENTRY(CVMCCMruntimeFCmp)ENTRY1 ( CVMCCMruntimeFCmp ) ENTRY(CVMCCMruntimeFCmp_C)ENTRY1 ( CVMCCMruntimeFCmp_C ) /* r0 = a1 = float1 * r1 = a2 = float2 * r2 = a3 = return value if nan. * v1 = jfp * v2 = jsp * sp = ccee */ /* uses r0, r1, r2, r3 */#define FLOAT1 r0#define FLOAT2 r1#define NAN_RESULT r2 /* Extract exponent1 and check float1 for a NaN: */ mov r3, #0xff and r3, r3, FLOAT1, LSR #23 /* Extract exponent1. */ cmp r3, #0xff /* Check for infinity or nan. */ beq _fcmpFloat1CheckForNanLABEL(_fcmpFloat1IsNotNan) /* Extract exponent2 and check float2 for a NaN: */ mov r3, #0xff and r3, r3, FLOAT2, LSR #23 /* Extract exponent2. */ cmp r3, #0xff /* Check for infinity or nan. */ beq _fcmpFloat2CheckForNanLABEL(_fcmpFloat2IsNotNan) /* Check if the 2 floats have the same sign bit: */ eor r2, FLOAT1, FLOAT2 /* Check to see if the sign bit is the */ tst r2, #0x80000000 /* same. */ bne _fcmpEvaluateResultBasedOnSigns /* If we get here, then the sign bits are the same. Next, check if the sign bits are negative: */ tst FLOAT1, #0x80000000 /* Check for negative sign bit. */ bic FLOAT1, FLOAT1, #0x80000000 /* Remove float1's sign. */ bic FLOAT2, FLOAT2, #0x80000000 /* Remove float2's sign. */ bne _fcmpDoNegativeChecks /* Do positive version of comparing the floats: */ cmp FLOAT1, FLOAT2 mov pc, lr /* Return to the caller. */LABEL(_fcmpDoNegativeChecks) /* Do negative version of comparing the floats: */ cmp FLOAT2, FLOAT1 mov pc, lr /* Return to the caller. */LABEL(_fcmpEvaluateResultBasedOnSigns) /* Check for the special case where the 2 numbers are zeroes. If so, the two are still equal even if their signs are not: */ mov r3, #0 cmp r3, FLOAT1, LSL #1 /* Check if float1 w/o sign is 0. */ bne _fcmpNotBothZeroes cmp r3, FLOAT2, LSL #1 /* Check if float2 w/o sign is 0. */ /* If it's a zero, then both numbers are 0s and equal. The condition code is already set correctly. Just return to the caller: */ moveq pc, lr /* Return the result. */LABEL(_fcmpNotBothZeroes) cmp FLOAT1, FLOAT2 /* Compare the signs. */ mov pc, lr /* Return the result. */LABEL(_fcmpFloat1CheckForNan) /* Check if the mantissa is 0 (i.e. float1 is an infinity): */ mov r3, FLOAT1, LSL #9 /* mantissa1 = float1 << 9. */ cmp r3, #0 /* Check if mantissa1 is 0. */ beq _fcmpFloat1IsNotNan /* If is infinity, resume in main code.*/ cmp NAN_RESULT, #0 /* Else, is NaN. Return the desired */ mov pc, lr /* condition code result. */LABEL(_fcmpFloat2CheckForNan) /* Check if the mantissa is 0 (i.e. float2 is an infinity): */ mov r3, FLOAT2, LSL #9 /* mantissa2 = float2 << 9. */ cmp r3, #0 /* Check if mantissa2 is 0. */ beq _fcmpFloat2IsNotNan /* If is infinity, resume in main code.*/ cmp NAN_RESULT, #0 /* Else, is NaN. Return the desired */ mov pc, lr /* condition code result. */#undef FLOAT1#undef FLOAT2#undef NAN_RESULT/* * NOTE: FAdd, FSub, and FMul all use the same register designations. */#define FLOAT1 r0#define FLOAT2 r1#define EXP1 r2#define EXP2 r3#define MANT1 r6#define MANT2 r7#define EMASK r12#define MMASK r12#define FLOAT_SAVE_SET {r6-r7, lr}#define FLOAT_RESTORE_SET {r6-r7, pc}#ifndef __RVCT__#define FLOAT_RETURN_TO_CALLER_IF(cond) \ ldm/**/cond/**/fd sp!, FLOAT_RESTORE_SET#else#define FLOAT_RETURN_TO_CALLER_IF(cond) \ ldm##cond##fd sp!, FLOAT_RESTORE_SET#endif#define FLOAT_RETURN_TO_CALLER \ FLOAT_RETURN_TO_CALLER_IF(al)/* * Entry point for subtracting floats. * NOTE: The result is in r0. */ ENTRY(CVMCCMruntimeFSub)ENTRY1 ( CVMCCMruntimeFSub ) ENTRY(CVMCCMruntimeFSub_C)ENTRY1 ( CVMCCMruntimeFSub_C ) /* r0 = a1 = float1 */ /* r1 = a2 = float2 */ /* v1 = jfp */ /* v2 = jsp */ /* sp = ccee */ eor r1, r1, #0x80000000 /* Negate float2. */ /* Fall through to CVMCCMruntimeFAdd: *//* * Entry point for adding floats. * NOTE: The result is in r0. */ ENTRY(CVMCCMruntimeFAdd)ENTRY1 ( CVMCCMruntimeFAdd ) ENTRY(CVMCCMruntimeFAdd_C)ENTRY1 ( CVMCCMruntimeFAdd_C ) /* r0 = a1 = float1 * r1 = a2 = float2 * v1 = jfp * v2 = jsp * sp = ccee *//* IAI - 16 */#ifdef IAI_WMMX_FADD#define FEXP1 r2#define FEXP2 r3#define FMANT1 ip#define FMANT2 r1 @ arrange for the larger summand to be in FLOAT1 mov ip, FLOAT1, LSL #1 cmp ip, FLOAT2, LSL #1 tmcrrlo wR0, FLOAT1, FLOAT2 tmrrclo FLOAT2, FLOAT1, wR0 /* exchage FLOAT1 and FLOAT2 */LABEL(_fadd_noxchng) mov EMASK, #0xff /* Setup the pre-shifted exponent mask. */ ands FEXP2, EMASK, FLOAT2, LSR #23 /* Extract exponent2. */ beq _fadd_fexp2_equal_0 and FEXP1, EMASK, FLOAT1, LSR #23 /* Extract exponent1. */ cmp FEXP1, EMASK cmpne FEXP2, EMASK beq _fadd_fexp_equal_emask sub r3, FEXP1, FEXP2 /* exp1 = exp1 - exp2. */ cmp r3, #25 /* difference too large, return */ movhi pc, lr teq FLOAT1, FLOAT2 bic FMANT2, FLOAT2, #0xff000000 /* Extract mantissa2. */ orr FMANT2, FMANT2, #0x00800000 bmi _fadd_sub LABEL(_fadd_add) bic FMANT1, FLOAT1, #0xff000000 /* Extract mantissa1. */ orr FMANT1, FMANT1, #0x00800000 add ip, FMANT1, FMANT2, LSR r3 /* {hi<ip>,lo<r1>} = FMANT1 + FMANT2. */ rsb r3, r3, #32 mov FMANT2, FMANT2, LSL r3 LABEL(_fadd_process_result) tst ip, #0x01000000 addne FEXP1, FEXP1, #1 movnes ip, ip, lsr #1 moveqs r1, r1, lsl #1 adc ip, ip, #0 bcs _fadd_process_result_round /* r1 = #0x8xxxxxxx */LABEL(_fadd_process_result_done) tst ip, #0x01000000 addne FEXP1, FEXP1, #1 cmp FEXP1, #0xff and r0, r0, #0x80000000 orr r0, r0, FEXP1, lsl #23 bicne ip, ip, #0x01800000 orrne r0, ip, r0 mov pc, lr /* normalized result returned. */LABEL(_fadd_process_result_round) teq r1, #0 biceq ip, ip, #1 b _fadd_process_result_doneLABEL(_fadd_fexp2_equal_0) ands FEXP1, EMASK, FLOAT1, LSR #23 /* Extract exponent1. */ beq _fadd_fexp1_equal_0 cmp FEXP1, EMASK moveq pc, lr teq FLOAT1,FLOAT2 bic FMANT2, FLOAT2, #0x80000000 sub r3, FEXP1, #1 bpl _fadd_add LABEL(_fadd_sub) bic FMANT1, FLOAT1, #0x7f000000 /* Extract mantissa1. */ orr FMANT1, FMANT1, #0x00800000 rsb r0, r3, #32 mov r0, FMANT2, LSL r0 rsbs r0, r0, #0 sbc ip, FMANT1, FMANT2, LSR r3 /* {hi<ip>,lo<r0>} = FMANT1 - FMANT2. */ tst ip, #0x00800000 beq _fadd_sub_result_need_shift cmp r0, #0x80000000 addhs ip, ip, #1 biceq ip, ip, #1 bic r0, ip, #0x00800000 orr r0, r0, FEXP1, lsl #23 mov pc, lrLABEL(_fadd_sub_result_need_shift) bic r3, ip, #0x80000000 orrs r1, r3, r0 moveq r0, #0 moveq pc, lr /* FLOAT1 = - FLOAT2, return 0 */ clz r1, r3 sub r1, r1, #8 cmp FEXP1, r1 suble r1, FEXP1, #1 movle FEXP1, ip, LSR #23 subgt FEXP1, FEXP1, r1 orrgt FEXP1, FEXP1, ip, LSR #23 mov ip, r3, LSL r1 /* need shift left */ rsb r3, r1, #32 orr ip, ip, r0, LSR r3 mov r0, r0, LSL r1 cmp r0, #0x80000000 addhs ip, ip, #1 biceq ip, ip, #1 tst ip, #0x01000000 addne FEXP1, FEXP1, #1 bic ip, ip, #0x01800000 orr r0, ip, FEXP1, LSL #23 mov pc, lr LABEL(_fadd_fexp1_equal_0) eors r3, FLOAT1, FLOAT2 bic r2, FLOAT2, #0x80000000 addpl r0, FLOAT1, r2 movpl pc, lr teq r3, #0x80000000 moveq r0, #0 subne r0, FLOAT1, r2 mov pc, lr LABEL(_fadd_fexp_equal_emask) cmp FEXP1, EMASK movne r0, FLOAT2 cmpeq FEXP2, EMASK movne pc, lr eors r2, FLOAT1, FLOAT2 orr r0, FLOAT1, FLOAT2 movpl pc, lr mov r0, #0x7f000000 orr r0, r0, #0x00c00000 mov pc, lr #else /* IAI - 16 */LABEL(_faddStart) /* The following saves registers that we're going to use and extracts exponents and mantissas 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, #0xc0000000 and MANT1, MMASK, FLOAT1, LSL #7 /* Extract mantissa1. */ and MANT2, MMASK, FLOAT2, LSL #7 /* Extract mantissa2. */ /* Check if float1 or float2 is NaN or infinity: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -