📄 gccmathalib.s
字号:
/* gccMathALib.s - math support routines for gcc *//* Copyright 1984-2001 Wind River Systems, Inc. */ .data .globl copyright_wind_river .long copyright_wind_river/* * This file has been developed or significantly modified by the * MIPS Center of Excellence Dedicated Engineering Staff. * This notice is as per the MIPS Center of Excellence Master Partner * Agreement, do not remove this notice without checking first with * WR/Platforms MIPS Center of Excellence engineering management. *//*modification history--------------------01f,02aug01,mem Diab integration01e,16jul01,ros add CofE comment01d,03jan01,pes Update to MIPS32/MIPS64 architectures01c,10sep99,myz added CW4000_16 support01b,10jun97,mem moved decl of mdu_present here.01a,10apr96,mem original version.*//*DESCRIPTIONThis library contains various support routines for using gcc. Thecompiler will generate subroutine calls to the functions in this filewhen the -mno-mdu option is used (for the CW4000). The function names are those which are automatically generated by the gcc compiler.UPDATE (3jan01,pes): these functions are no longer needed, because the -mno-mdu option is no longer supported. The div and mod routines "know" a bit about the other's register use inorder to avoid creating a extra stack frame.These routines will make use of the MDU if it is present. Otherwise, theneeded operation is done in software.If STATS is defined below, statistic collection is enabled.Counts are kept for each call to the functions below. The *_allvariables represent the total number of calls, the *_soft variablesrepresent the number of times the s/w implementation needed to be used.This information might be of use to customers who are trying to decideif their ASIC should include the MDU or not.Because the division routines are used for the mod routines, mod operationscount as 2 (1 mod and 1 div). Analysis of the statistics should take thisinto account.AUTHORNOMANUAL*/#define _ASMLANGUAGE#include "vxWorks.h"#include "asm.h"#if FALSE#undef STATS#ifdef STATS .comm mulsi3_all,4 .comm umulsi3_all,4 .comm divsi3_all,4 .comm udivsi3_all,4 .globl mulsi3_all .globl umulsi3_all .globl divsi3_all .globl udivsi3_all .comm mulsi3_soft,4 .comm umulsi3_soft,4 .comm divsi3_soft,4 .comm udivsi3_soft,4 .globl mulsi3_soft .globl umulsi3_soft .globl divsi3_soft .globl udivsi3_soft#define STAT_INC(x) \ lw t0, x; addu t0, t0, 1; sw t0, x#else /* STATS */#define STAT_INC(x)#endif /* STATS */ #if (CPU==CW4000 || CPU==CW4000_16) .globl __divsi3 .globl __udivsi3 .globl __modsi3 .globl __umodsi3#endif /* CPU==CW4000 */ .globl gccMathInit#endif /* FALSE */ .text .set reorder /******************************************************************************** gccMathInit - This routine will cause this module to be included in* the vxWorks build.** RETURNS: ** NOMANUAL*/ .ent gccMathInitgccMathInit: j ra .end gccMathInit #if FALSE #if (CPU==CW4000 || (CPU==CW4000_16))/******************************************************************************** mulsi3 - long integer multiplication routine for gcc** RETURNS: signed 32-bit multiplication result.** NOMANUAL*/ .ent __mulsi3__mulsi3: STAT_INC(mulsi3_all) lw t0, _mdu_present beqz t0, 0f mult a0, a1 mflo v0 j ra0: STAT_INC(mulsi3_soft) /* A = a0, B = a1, P = a2 */ move a2, zero /* zero P */ li t1, 32 /* load count */1: andi t0, a0, 1 /* isolate bit 0 */ move t3, zero /* zero carry flag */ beqz t0, 0f /* branch if A[0] == 0 */ srl t4, a1, 1 /* t4 = B >> 1 */ srl t5, a2, 1 /* t5 = P >> 1 */ addu t4, t4, t5 /* t4 = (B >> 1) + (P >> 1) */ bgez t4, 2f /* branch if no carry out */ lui t3, 0x8000 /* set carry flag */2: addu a2, a2, a1 /* P = B + P */0: sll t2, a2, 31 /* prep P[0] for insertion into A */ srl a2, a2, 1 /* shift P down */ or a2, a2, t3 /* insert carry out */ srl a0, a0, 1 /* shift A down */ subu t1, t1, 1 /* decrement count */ or a0, a0, t2 /* insert low bit of P into high bit */ bgtz t1, 1b /* loop */ move v0, a0 /* return low order bits */ j ra .end __mulsi3/******************************************************************************** umulsi3 - unsigned long integer multiplication routine for gcc.** RETURNS: unsigned 32-bit multiplication result.** NOMANUAL*/ .ent __umulsi3__umulsi3: STAT_INC(umulsi3_all) lw t0, _mdu_present beqz t0, 0f multu a0, a1 mflo v0 j ra0: STAT_INC(umulsi3_soft) /* A = a0, B = a1, P = a2 */ move a2, zero /* zero P */ /* 31 iterations */ li t1, 31 /* load count */1: andi t0, a0, 1 /* isolate bit 0 */ srl a0, a0, 1 /* shift A down */ beqz t0, 0f /* branch if A[0] == 0 */ addu a2, a2, a1 /* P = B + P */0: sll t2, a2, 31 /* prep P[0] for insertion into A */ srl a2, a2, 1 /* shift P down */ subu t1, t1, 1 /* decrement count */ or a0, a0, t2 /* insert low bit of P into high bit */ bgtz t1, 1b /* loop */ /* now do the restore step */ andi t0, a0, 1 /* isolate bit 0 */ srl a0, a0, 1 /* shift A down */ beqz t0, 0f /* branch if A[0] == 0 */ subu a2, a2, a1 /* P = P - B */0: sll t2, a2, 31 /* prep P[0] for insertion into A */ or a0, a0, t2 /* insert low bit of P into high A */ move v0, a0 /* return low order bits */ j ra .end __umulsi3/******************************************************************************** divsi3 - long integer division routine for gcc.** This routine uses the unsigned division routine below to do most of* the work. We bend the calling convention a bit here and depend on* 3 registers (t5, t6 and t7) being preserved across the call to __udivsi3.* If __udivsi3 is changed, this function should be re-inspected.** RETURNS: signed 32-bit division result.* v0 quotient* v1 remainder** NOMANUAL*/ .ent __divsi3__divsi3: STAT_INC(divsi3_all) lw t0, _mdu_present beqz t0, 0f div v0, a0, a1 mfhi v1 j ra0: STAT_INC(divsi3_soft) move t5, zero /* quotient negative flag */ move t6, zero /* remainder negative flag */ bgez a0, 1f /* branch if A positive */ or t5, t5, 1 /* set quotient flag */ or t6, t6, 1 /* set remainder flag */ subu a0, zero, a0 /* A = -A */1: bgez a1, 1f /* branch if B positive */ xori t5, t5, 1 /* toggle quotient flag */ subu a1, zero, a1 /* B = -B */1: move t7, ra /* preserve our return address */ jal __udivsi3 /* do unsigned divide */ move ra, t7 /* restore our return address */ beqz t5, 1f subu v0, zero, v0 /* fixup quotient */1: beqz t6, 1f subu v1, zero, v1 /* fixup remainder */1: j ra .end __divsi3/******************************************************************************** udivsi3 - unsigned long integer division routine for gcc a0/a1** This function is called by __divsi3 to handle signed division as well,* The code in __divsi3 depends on t5, t6 and t7 being preserved across* this call.** RETURNS: unsigned 32-bit division result.* v0 quotient* v1 remainder** NOMANUAL*/ .ent __udivsi3__udivsi3: STAT_INC(udivsi3_all) lw t0, _mdu_present beqz t0, 0f divu v0, a0, a1 mfhi v1 j ra0: STAT_INC(udivsi3_soft) bnez a1, 1f break 7 /* Divide by zero trap */ j ra1: bgeu a0, a1, 1f /* branch if a0 >= a1 */ move v1, a0 /* remainder = a0 */ move v0, zero /* quotient = 0 */ j ra1: /* A = a0, B = a1, P = v1 */ move v1, zero /* zero P */ li t1, 31 /* load count */1: sll v1, v1, 1 /* shift P left */ bgez a0, 2f /* branch if A[31] == 0 */ or v1, v1, 1 /* set low bit in P */2: sll a0, a0, 1 /* shift A left */ bltu v1, a1, 2f /* branch if P < B (unsigned) */ subu v1, v1, a1 /* P = P - B */ or a0, a0, 1 /* note bit in result */2: subu t1, t1, 1 /* decrement count */ bgez t1, 1b /* loop */ move v0, a0 /* quotient */ j ra .end __udivsi3/******************************************************************************** modsi3 - long integer modulo routine for gcc** RETURNS: signed 32-bit modulo result.** NOMANUAL*/ .ent __modsi3__modsi3: move t8, ra /* preserve our return address */ jal __divsi3 move ra, t8 /* restore our return address */ move v0, v1 /* make remainder the return value */ j ra .end __modsi3/******************************************************************************** umodsi3 - unsigned long integer modulo routine for gcc.** RETURNS: unsigned 32-bit modulo result.** NOMANUAL*/ .ent __umodsi3__umodsi3: move t8, ra /* preserve our return address */ jal __udivsi3 move ra, t8 /* restore our return address */ move v0, v1 /* make remainder the return value */ j ra .end __umodsi3#endif /* CPU==CW4000 */#endif /* FALSE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -