; libgcc1 routines for ARC cpu. /* Copyright (C) 1995, 1997 Free Software Foundation, Inc. This file 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, or (at your option) any later version. In addition to the permissions in the GNU General Public License, the Free Software Foundation gives you unlimited permission to link the compiled version of this file with other programs, and to distribute those programs without any restriction coming from the use of this file. (The General Public License restrictions do apply in other respects; for example, they cover modification of the file, and distribution when not linked into another program.) This file 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 GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* As a special exception, if you link this library with other files, some of which are compiled with GCC, to produce an executable, this library does not by itself cause the resulting executable to be covered by the GNU General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU General Public License. */ #ifdef L_mulsi3 .section .text .align 4 #ifdef __base__ .cpu base .global ___mulsi3 ___mulsi3: /* This the simple version. while (a) { if (a & 1) r += b; a >>= 1; b <<= 1; } */ mov r2,0 ; Accumulate result here. .Lloop: sub.f 0,r0,0 ; while (a) nop beq.nd .Ldone and.f 0,r0,1 ; if (a & 1) add.nz r2,r2,r1 ; r += b lsr r0,r0 ; a >>= 1 b.d .Lloop lsl r1,r1 ; b <<= 1 .Ldone: j.d blink mov r0,r2 #endif #endif /* L_mulsi3 */ #ifdef L_umulsidi3 .section .text .align 4 #ifdef __base__ .cpu base .global ___umulsidi3 ___umulsidi3: /* This the simple version. while (a) { if (a & 1) r += b; a >>= 1; b <<= 1; } */ mov r2,0 ; Top part of b. mov r3,0 ; Accumulate result here. mov r4,0 .Lloop: sub.f 0,r0,0 ; while (a) nop beq.nd .Ldone and.f 0,r0,1 ; if (a & 1) add.nz r4,r4,r1 ; r += b adc.nz r3,r3,r2 lsr r0,r0 ; a >>= 1 lsl.f r1,r1 ; b <<= 1 b.d .Lloop rlc r2,r2 .Ldone: #ifdef __big_endian__ mov r1,r4 j.d blink mov r0,r3 #else mov r0,r4 j.d blink mov r1,r3 #endif #endif #endif /* L_umulsidi3 */ #ifdef L_divmod_tools ; Utilities used by all routines. .section .text .align 4 ; inputs: r0 = numerator, r1 = denominator ; outputs: positive r0/r1, ; r6.bit1 = sign of numerator, r6.bit0 = sign of result .global ___divnorm ___divnorm: mov r6,0 ; keep sign in r6 sub.f 0,r0,0 ; is numerator -ve? sub.lt r0,0,r0 ; negate numerator mov.lt r6,3 ; sign is -ve sub.f 0,r1,0 ; is denominator -ve? sub.lt r1,0,r1 ; negate denominator xor.lt r6,r6,1 ; toggle sign j.nd blink /* unsigned long udivmodsi4(int modwanted, unsigned long num, unsigned long den) { unsigned long bit = 1; unsigned long res = 0; while (den < num && bit && !(den & (1L<<31))) { den <<=1; bit <<=1; } while (bit) { if (num >= den) { num -= den; res |= bit; } bit >>=1; den >>=1; } if (modwanted) return num; return res; } */ ; inputs: r0 = numerator, r1 = denominator ; outputs: r0 = quotient, r1 = remainder, r2/r3 trashed .global ___udivmodsi4 ___udivmodsi4: mov r2,1 ; bit = 1 mov r3,0 ; res = 0 .Lloop1: sub.f 0,r1,r0 ; while (den < num nop bnc.nd .Lloop2 sub.f 0,r2,0 ; && bit nop bz.nd .Lloop2 lsl.f 0,r1 ; && !(den & (1<<31)) nop bc.nd .Lloop2 lsl r1,r1 ; den <<= 1 b.d .Lloop1 lsl r2,r2 ; bit <<= 1 .Lloop2: sub.f 0,r2,0 ; while (bit) nop bz.nd .Ldivmodend sub.f 0,r0,r1 ; if (num >= den) nop bc.nd .Lshiftdown sub r0,r0,r1 ; num -= den or r3,r3,r2 ; res |= bit .Lshiftdown: lsr r2,r2 ; bit >>= 1 b.d .Lloop2 lsr r1,r1 ; den >>= 1 .Ldivmodend: mov r1,r0 ; r1 = mod j.d blink mov r0,r3 ; r0 = res #endif #ifdef L_udivsi3 .section .text .align 4 #ifdef __base__ .cpu base .global ___udivsi3 ___udivsi3: mov r7,blink bl.nd ___udivmodsi4 j.nd r7 #endif #endif /* L_udivsi3 */ #ifdef L_divsi3 .section .text .align 4 #ifdef __base__ .cpu base .global ___divsi3 ___divsi3: mov r7,blink bl.nd ___divnorm bl.nd ___udivmodsi4 and.f 0,r6,1 sub.nz r0,0,r0 ; cannot go in delay slot, has limm value j.nd r7 #endif #endif /* L_divsi3 */ #ifdef L_umodsi3 .section .text .align 4 #ifdef __base__ .cpu base .global ___umodsi3 ___umodsi3: mov r7,blink bl.nd ___udivmodsi4 j.d r7 mov r0,r1 #endif #endif /* L_umodsi3 */ #ifdef L_modsi3 .section .text .align 4 #ifdef __base__ .cpu base .global ___modsi3 ___modsi3: mov r7,blink bl.nd ___divnorm bl.nd ___udivmodsi4 and.f 0,r6,2 sub.nz r1,0,r1 j.d r7 mov r0,r1 #endif #endif /* L_modsi3 */