Back to index

glibc  2.9
div_libc.h
Go to the documentation of this file.
00001 /* Copyright (C) 2004 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.  */
00018 
00019 /* Common bits for implementing software divide.  */
00020 
00021 #include <sysdep.h>
00022 #ifdef __linux__
00023 # include <asm/gentrap.h>
00024 # include <asm/pal.h>
00025 #else
00026 # include <machine/pal.h>
00027 #endif
00028 
00029 /* These are not normal C functions.  Argument registers are t10 and t11;
00030    the result goes in t12; the return address is in t9.  Only t12 and AT
00031    may be clobbered.  */
00032 #define X     t10
00033 #define Y     t11
00034 #define RV    t12
00035 #define RA    t9
00036 
00037 /* The secureplt format does not allow the division routines to be called
00038    via plt; there aren't enough registers free to be clobbered.  Avoid 
00039    setting the symbol type to STT_FUNC, so that the linker won't be tempted
00040    to create a plt entry.  */
00041 #define funcnoplt notype
00042 
00043 /* None of these functions should use implicit anything.  */
00044        .set   nomacro
00045        .set   noat
00046 
00047 /* Code fragment to invoke _mcount for profiling.  This should be invoked
00048    directly after allocation of the stack frame.  */
00049 .macro CALL_MCOUNT
00050 #ifdef PROF
00051        stq    ra, 0(sp)
00052        stq    pv, 8(sp)
00053        stq    gp, 16(sp)
00054        cfi_rel_offset (ra, 0)
00055        cfi_rel_offset (pv, 8)
00056        cfi_rel_offset (gp, 16)
00057        br     AT, 1f
00058        .set   macro
00059 1:     ldgp   gp, 0(AT)
00060        mov    RA, ra
00061        lda    AT, _mcount
00062        jsr    AT, (AT), _mcount
00063        .set   nomacro
00064        ldq    ra, 0(sp)
00065        ldq    pv, 8(sp)
00066        ldq    gp, 16(sp)
00067        cfi_restore (ra)
00068        cfi_restore (pv)
00069        cfi_restore (gp)
00070        /* Realign subsequent code with what we'd have without this
00071           macro at all.  This means aligned with one arithmetic insn
00072           used within the bundle.  */
00073        .align 4
00074        nop
00075 #endif
00076 .endm
00077 
00078 /* In order to make the below work, all top-level divide routines must
00079    use the same frame size.  */
00080 #define FRAME 64
00081 
00082 /* Code fragment to generate an integer divide-by-zero fault.  When
00083    building libc.so, we arrange for there to be one copy of this code
00084    placed late in the dso, such that all branches are forward.  When
00085    building libc.a, we use multiple copies to avoid having an out of
00086    range branch.  Users should jump to DIVBYZERO.  */
00087 
00088 .macro DO_DIVBYZERO
00089 #ifdef PIC
00090 #define DIVBYZERO    __divbyzero
00091        .section .gnu.linkonce.t.divbyzero, "ax", @progbits
00092        .globl __divbyzero
00093        .type  __divbyzero, @function
00094        .usepv __divbyzero, no
00095        .hidden       __divbyzero
00096 #else
00097 #define DIVBYZERO    $divbyzero
00098 #endif
00099 
00100        .align 4
00101 DIVBYZERO:
00102        cfi_startproc
00103        cfi_return_column (RA)
00104        cfi_def_cfa_offset (FRAME)
00105 
00106        mov    a0, RV
00107        unop
00108        lda    a0, GEN_INTDIV
00109        call_pal PAL_gentrap
00110 
00111        mov    RV, a0
00112        clr    RV
00113        lda    sp, FRAME(sp)
00114        cfi_def_cfa_offset (0)
00115        ret    $31, (RA), 1
00116 
00117        cfi_endproc
00118        .size  DIVBYZERO, .-DIVBYZERO
00119 .endm
00120 
00121 /* Like the ev6 instructions, but fall back to stack use on prior machines.  */
00122 
00123        .arch  ev6
00124 
00125 .macro _ITOFS  gr, fr, slot
00126 #ifdef __alpha_fix__
00127        itofs	\gr, \fr
00128 #else
00129        stl	\gr, \slot(sp)
00130        lds    \fr, \slot(sp)
00131 #endif
00132 .endm
00133 
00134 .macro _ITOFT  gr, fr, slot
00135 #ifdef __alpha_fix__
00136        itoft	\gr, \fr
00137 #else
00138        stq	\gr, \slot(sp)
00139        ldt    \fr, \slot(sp)
00140 #endif
00141 .endm
00142 
00143 .macro _FTOIT  fr, gr, slot
00144 #ifdef __alpha_fix__
00145        ftoit	\fr, \gr
00146 #else
00147        stt	\fr, \slot(sp)
00148        ldq    \gr, \slot(sp)
00149 #endif
00150 .endm
00151 
00152 /* Similarly, but move two registers.  Schedules better for pre-ev6.  */
00153 
00154 .macro _ITOFT2 gr1, fr1, slot1, gr2, fr2, slot2
00155 #ifdef __alpha_fix__
00156        itoft	\gr1, \fr1
00157        itoft	\gr2, \fr2
00158 #else
00159        stq	\gr1, \slot1(sp)
00160        stq    \gr2, \slot2(sp)
00161        ldt    \fr1, \slot1(sp)
00162        ldt    \fr2, \slot2(sp)
00163 #endif
00164 .endm