divsi3.s

来自「linux 内核源代码」· S 代码 · 共 220 行

S
220
字号
/* * File:         arch/blackfin/lib/divsi3.S * Based on: * Author: * * Created: * Description:  16 / 32 bit signed division. *                 Special cases : *                      1)  If(numerator == 0) *                             return 0 *                      2)  If(denominator ==0) *                             return positive max = 0x7fffffff *                      3)  If(numerator == denominator) *                             return 1 *                      4)  If(denominator ==1) *                             return numerator *                      5)  If(denominator == -1) *                             return -numerator * *                 Operand         : R0 - Numerator   (i) *                                   R1 - Denominator (i) *                                   R0 - Quotient    (o) *                 Registers Used : R2-R7,P0-P2 * * Modified: *               Copyright 2004-2006 Analog Devices Inc. * * Bugs:         Enter bugs at http://blackfin.uclinux.org/ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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 for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see the file COPYING, or write * to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */.global   ___divsi3;.type ___divsi3, STT_FUNC;#ifdef CONFIG_ARITHMETIC_OPS_L1.section .l1.text#else.text#endif.align 2;___divsi3 :  R3 = R0 ^ R1;  R0 = ABS R0;  CC = V;  r3 = rot r3 by -1;  r1 = abs r1;      /* now both positive, r3.30 means "negate result",                    ** r3.31 means overflow, add one to result                    */  cc = r0 < r1;  if cc jump .Lret_zero;  r2 = r1 >> 15;  cc = r2;  if cc jump .Lidents;  r2 = r1 << 16;  cc = r2 <= r0;  if cc jump .Lidents;  DIVS(R0, R1);  DIVQ(R0, R1);  DIVQ(R0, R1);  DIVQ(R0, R1);  DIVQ(R0, R1);  DIVQ(R0, R1);  DIVQ(R0, R1);  DIVQ(R0, R1);  DIVQ(R0, R1);  DIVQ(R0, R1);  DIVQ(R0, R1);  DIVQ(R0, R1);  DIVQ(R0, R1);  DIVQ(R0, R1);  DIVQ(R0, R1);  DIVQ(R0, R1);  DIVQ(R0, R1);  R0 = R0.L (Z);  r1 = r3 >> 31;    /* add overflow issue back in */  r0 = r0 + r1;  r1 = -r0;  cc = bittst(r3, 30);  if cc r0 = r1;  RTS;/* Can't use the primitives. Test common identities.** If the identity is true, return the value in R2.*/.Lidents:  CC = R1 == 0;                   /* check for divide by zero */  IF CC JUMP .Lident_return;  CC = R0 == 0;                   /* check for division of zero */  IF CC JUMP .Lzero_return;  CC = R0 == R1;                  /* check for identical operands */  IF CC JUMP .Lident_return;  CC = R1 == 1;                   /* check for divide by 1 */  IF CC JUMP .Lident_return;  R2.L = ONES R1;  R2 = R2.L (Z);  CC = R2 == 1;  IF CC JUMP .Lpower_of_two;  /* Identities haven't helped either.  ** Perform the full division process.  */  P1 = 31;                        /* Set loop counter   */  [--SP] = (R7:5);                /* Push registers R5-R7 */  R2 = -R1;  [--SP] = R2;  R2 = R0 << 1;                   /* R2 lsw of dividend  */  R6 = R0 ^ R1;                   /* Get sign */  R5 = R6 >> 31;                  /* Shift sign to LSB */  R0 = 0 ;                        /* Clear msw partial remainder */  R2 = R2 | R5;                   /* Shift quotient bit */  R6 = R0 ^ R1;                   /* Get new quotient bit */  LSETUP(.Llst,.Llend)  LC0 = P1;   /* Setup loop */.Llst:   R7 = R2 >> 31;            /* record copy of carry from R2 */        R2 = R2 << 1;             /* Shift 64 bit dividend up by 1 bit */        R0 = R0 << 1 || R5 = [SP];        R0 = R0 | R7;             /* and add carry */        CC = R6 < 0;              /* Check quotient(AQ) */                                  /* we might be subtracting divisor (AQ==0) */        IF CC R5 = R1;            /* or we might be adding divisor  (AQ==1)*/        R0 = R0 + R5;             /* do add or subtract, as indicated by AQ */        R6 = R0 ^ R1;             /* Generate next quotient bit */        R5 = R6 >> 31;                                  /* Assume AQ==1, shift in zero */        BITTGL(R5,0);             /* tweak AQ to be what we want to shift in */.Llend:  R2 = R2 + R5;             /* and then set shifted-in value to                                  ** tweaked AQ.                                  */  r1 = r3 >> 31;  r2 = r2 + r1;  cc = bittst(r3,30);  r0 = -r2;  if !cc r0 = r2;  SP += 4;  (R7:5)= [SP++];                 /* Pop registers R6-R7 */  RTS;.Lident_return:  CC = R1 == 0;                   /* check for divide by zero  => 0x7fffffff */  R2 = -1 (X);  R2 >>= 1;  IF CC JUMP .Ltrue_ident_return;  CC = R0 == R1;                  /* check for identical operands => 1 */  R2 = 1 (Z);  IF CC JUMP .Ltrue_ident_return;  R2 = R0;                        /* assume divide by 1 => numerator */  /*FALLTHRU*/.Ltrue_ident_return:  R0 = R2;                        /* Return an identity value */  R2 = -R2;  CC = bittst(R3,30);  IF CC R0 = R2;.Lzero_return:  RTS;                            /* ...including zero */.Lpower_of_two:  /* Y has a single bit set, which means it's a power of two.  ** That means we can perform the division just by shifting  ** X to the right the appropriate number of bits  */  /* signbits returns the number of sign bits, minus one.  ** 1=>30, 2=>29, ..., 0x40000000=>0. Which means we need  ** to shift right n-signbits spaces. It also means 0x80000000  ** is a special case, because that *also* gives a signbits of 0  */  R2 = R0 >> 31;  CC = R1 < 0;  IF CC JUMP .Ltrue_ident_return;  R1.l = SIGNBITS R1;  R1 = R1.L (Z);  R1 += -30;  R0 = LSHIFT R0 by R1.L;  r1 = r3 >> 31;  r0 = r0 + r1;  R2 = -R0;                       // negate result if necessary  CC = bittst(R3,30);  IF CC R0 = R2;  RTS;.Lret_zero:  R0 = 0;  RTS;.size ___divsi3, .-___divsi3

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?