]>
Commit | Line | Data |
---|---|---|
568035b7 | 1 | /* Copyright (C) 2004-2013 Free Software Foundation, Inc. |
08e3c578 RH |
2 | This file is part of the GNU C Library. |
3 | ||
4 | The GNU C Library is free software; you can redistribute it and/or | |
5 | modify it under the terms of the GNU Lesser General Public | |
6 | License as published by the Free Software Foundation; either | |
7 | version 2.1 of the License, or (at your option) any later version. | |
8 | ||
9 | The GNU C Library is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | Lesser General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU Lesser General Public | |
ab84e3ff PE |
15 | License along with the GNU C Library. If not, see |
16 | <http://www.gnu.org/licenses/>. */ | |
08e3c578 RH |
17 | |
18 | /* Common bits for implementing software divide. */ | |
19 | ||
20 | #include <sysdep.h> | |
21 | #ifdef __linux__ | |
22 | # include <asm/gentrap.h> | |
23 | # include <asm/pal.h> | |
24 | #else | |
25 | # include <machine/pal.h> | |
26 | #endif | |
27 | ||
28 | /* These are not normal C functions. Argument registers are t10 and t11; | |
29 | the result goes in t12; the return address is in t9. Only t12 and AT | |
30 | may be clobbered. */ | |
31 | #define X t10 | |
32 | #define Y t11 | |
33 | #define RV t12 | |
34 | #define RA t9 | |
35 | ||
685896ef RH |
36 | /* The secureplt format does not allow the division routines to be called |
37 | via plt; there aren't enough registers free to be clobbered. Avoid | |
38 | setting the symbol type to STT_FUNC, so that the linker won't be tempted | |
39 | to create a plt entry. */ | |
40 | #define funcnoplt notype | |
41 | ||
08e3c578 RH |
42 | /* None of these functions should use implicit anything. */ |
43 | .set nomacro | |
44 | .set noat | |
45 | ||
46 | /* Code fragment to invoke _mcount for profiling. This should be invoked | |
47 | directly after allocation of the stack frame. */ | |
48 | .macro CALL_MCOUNT | |
49 | #ifdef PROF | |
50 | stq ra, 0(sp) | |
51 | stq pv, 8(sp) | |
52 | stq gp, 16(sp) | |
53 | cfi_rel_offset (ra, 0) | |
54 | cfi_rel_offset (pv, 8) | |
55 | cfi_rel_offset (gp, 16) | |
56 | br AT, 1f | |
57 | .set macro | |
58 | 1: ldgp gp, 0(AT) | |
59 | mov RA, ra | |
60 | lda AT, _mcount | |
61 | jsr AT, (AT), _mcount | |
62 | .set nomacro | |
63 | ldq ra, 0(sp) | |
64 | ldq pv, 8(sp) | |
65 | ldq gp, 16(sp) | |
66 | cfi_restore (ra) | |
67 | cfi_restore (pv) | |
68 | cfi_restore (gp) | |
69 | /* Realign subsequent code with what we'd have without this | |
70 | macro at all. This means aligned with one arithmetic insn | |
71 | used within the bundle. */ | |
72 | .align 4 | |
73 | nop | |
74 | #endif | |
75 | .endm | |
76 | ||
77 | /* In order to make the below work, all top-level divide routines must | |
78 | use the same frame size. */ | |
a61c91b0 | 79 | #define FRAME 64 |
08e3c578 RH |
80 | |
81 | /* Code fragment to generate an integer divide-by-zero fault. When | |
82 | building libc.so, we arrange for there to be one copy of this code | |
83 | placed late in the dso, such that all branches are forward. When | |
84 | building libc.a, we use multiple copies to avoid having an out of | |
85 | range branch. Users should jump to DIVBYZERO. */ | |
86 | ||
87 | .macro DO_DIVBYZERO | |
88 | #ifdef PIC | |
89 | #define DIVBYZERO __divbyzero | |
90 | .section .gnu.linkonce.t.divbyzero, "ax", @progbits | |
91 | .globl __divbyzero | |
92 | .type __divbyzero, @function | |
93 | .usepv __divbyzero, no | |
94 | .hidden __divbyzero | |
95 | #else | |
96 | #define DIVBYZERO $divbyzero | |
97 | #endif | |
98 | ||
99 | .align 4 | |
100 | DIVBYZERO: | |
101 | cfi_startproc | |
102 | cfi_return_column (RA) | |
103 | cfi_def_cfa_offset (FRAME) | |
104 | ||
105 | mov a0, RV | |
106 | unop | |
107 | lda a0, GEN_INTDIV | |
108 | call_pal PAL_gentrap | |
109 | ||
110 | mov RV, a0 | |
111 | clr RV | |
112 | lda sp, FRAME(sp) | |
113 | cfi_def_cfa_offset (0) | |
114 | ret $31, (RA), 1 | |
115 | ||
116 | cfi_endproc | |
117 | .size DIVBYZERO, .-DIVBYZERO | |
118 | .endm | |
de47cb70 RH |
119 | |
120 | /* Like the ev6 instructions, but fall back to stack use on prior machines. */ | |
121 | ||
122 | .arch ev6 | |
123 | ||
124 | .macro _ITOFS gr, fr, slot | |
125 | #ifdef __alpha_fix__ | |
126 | itofs \gr, \fr | |
127 | #else | |
48a7f702 RH |
128 | stl \gr, \slot(sp) |
129 | lds \fr, \slot(sp) | |
de47cb70 RH |
130 | #endif |
131 | .endm | |
132 | ||
133 | .macro _ITOFT gr, fr, slot | |
134 | #ifdef __alpha_fix__ | |
135 | itoft \gr, \fr | |
136 | #else | |
48a7f702 RH |
137 | stq \gr, \slot(sp) |
138 | ldt \fr, \slot(sp) | |
de47cb70 RH |
139 | #endif |
140 | .endm | |
141 | ||
142 | .macro _FTOIT fr, gr, slot | |
143 | #ifdef __alpha_fix__ | |
144 | ftoit \fr, \gr | |
145 | #else | |
48a7f702 RH |
146 | stt \fr, \slot(sp) |
147 | ldq \gr, \slot(sp) | |
de47cb70 RH |
148 | #endif |
149 | .endm | |
150 | ||
151 | /* Similarly, but move two registers. Schedules better for pre-ev6. */ | |
152 | ||
153 | .macro _ITOFT2 gr1, fr1, slot1, gr2, fr2, slot2 | |
154 | #ifdef __alpha_fix__ | |
155 | itoft \gr1, \fr1 | |
156 | itoft \gr2, \fr2 | |
157 | #else | |
48a7f702 RH |
158 | stq \gr1, \slot1(sp) |
159 | stq \gr2, \slot2(sp) | |
160 | ldt \fr1, \slot1(sp) | |
161 | ldt \fr2, \slot2(sp) | |
de47cb70 RH |
162 | #endif |
163 | .endm |