]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgcc/config/picochip/divmod15.S
Move libgcc2 to toplevel libgcc
[thirdparty/gcc.git] / libgcc / config / picochip / divmod15.S
1 // picoChip ASM file
2 //
3 // Support for 16-bit unsigned division/modulus.
4 //
5 // Copyright (C) 2003, 2004, 2005, 2008, 2009 Free Software Foundation, Inc.
6 // Contributed by Picochip Ltd.
7 // Maintained by Daniel Towner (daniel.towner@picochip.com)
8 //
9 // This file is free software; you can redistribute it and/or modify it
10 // under the terms of the GNU General Public License as published by the
11 // Free Software Foundation; either version 3, or (at your option) any
12 // later version.
13 //
14 // This file is distributed in the hope that it will be useful, but
15 // WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // General Public License for more details.
18 //
19 // Under Section 7 of GPL version 3, you are granted additional
20 // permissions described in the GCC Runtime Library Exception, version
21 // 3.1, as published by the Free Software Foundation.
22 //
23 // You should have received a copy of the GNU General Public License and
24 // a copy of the GCC Runtime Library Exception along with this program;
25 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
26 // <http://www.gnu.org/licenses/>.
27
28 .section .text
29
30 .global __divmod15
31 __divmod15:
32 _picoMark_FUNCTION_BEGIN=
33
34 // picoChip Function Prologue : &__divmod15 = 0 bytes
35
36 // The picoChip instruction set has a divstep instruction which
37 // is used to perform one iteration of a binary division algorithm.
38 // The instruction allows 16-bit signed division to be implemented.
39 // It does not directly allow 16-bit unsigned division to be
40 // implemented. Thus, this function pulls out the common division
41 // iteration for 15-bits unsigned, and then special wrappers
42 // provide the logic to change this into a 16-bit signed or
43 // unsigned division, as appropriate. This allows the two
44 // versions of division to share a common implementation, reducing
45 // code size when the two are used together. It also reduces
46 // the maintenance overhead.
47
48 // Input:
49 // r0 - dividend
50 // r1 - divisor
51 // Output:
52 // r0 - quotient
53 // r1 - remainder
54 // R5 is unused
55
56 // Check for special cases. The emphasis is on detecting these as
57 // quickly as possible, so that the main division can be started. If
58 // the user requests division by one, division by self, and so on
59 // then they will just have to accept that this won't be particularly
60 // quick (relatively), whereas a real division (e.g., dividing a
61 // large value by a small value) will run as fast as possible
62 // (i.e., special case detection should not slow down the common case)
63 //
64 // Special cases to consider:
65 //
66 // Division by zero.
67 // Division of zero.
68 // Inputs are equal
69 // Divisor is bigger than dividend
70 // Division by power of two (can be shifted instead).
71 // Division by 1 (special case of power of two division)
72 //
73 // Division/modulus by zero is undefined (ISO C:6.5.5), so
74 // don't bother handling this special case.
75 //
76 // The special cases of division by a power of 2 are ignored, since
77 // they cause the general case to slow down. Omitting these
78 // special cases also reduces code size considerably.
79
80 // Handle divisor >= dividend separately. Note that this also handles
81 // the case where the dividend is zero. Note that the flags must be
82 // preserved, since they are also used at the branch destination.
83 sub.0 r1,r0,r15
84 sbc r0,r2 \ bge divisorGeDividend
85 =-> sbc r1,r4
86
87 // Compute the shift count. The amount by which the divisor
88 // must be shifted left to be aligned with the dividend.
89 sub.0 r4,r2,r3
90
91 // Align the divisor to the dividend. Execute a divstep (since at
92 // least one will always be executed). Skip the remaining loop
93 // if the shift count is zero.
94 lsl.0 r1,r3,r1 \ beq skipLoop
95 =-> divstep r0,r1 \ add.1 r3,1,r2
96
97 // Execute the divstep loop until temp is 0. This assumes that the
98 // loop count is at least one.
99 sub.0 r3,1,r4
100 divLoop:
101 divstep r0,r1 \ bne divLoop
102 =-> sub.0 r4,1,r4
103
104 skipLoop:
105
106 // The top bits of the result are the remainder. The bottom
107 // bits are the quotient.
108 lsr.0 r0,r2,r1 \ sub.1 16,r2,r4
109 jr (lr ) \ lsl.0 r0,r4,r0
110 =-> lsr.0 r0,r4,r0
111
112 // Special case.
113
114 divisorGeDividend:
115 // The divisor is greater than or equal to the dividend. The flags
116 // indicate which of these alternatives it is. The COPYNE can be used
117 // to set the result appropriately, without introducing any more
118 // branches.
119 copy.0 r0,r1 \ copy.1 0,r0
120 jr (lr) \ copyeq r0,r1
121 =-> copyeq 1,r0
122
123 _picoMark_FUNCTION_END=
124 // picoChip Function Epilogue : __divmod15
125
126
127 //============================================================================
128 // All DWARF information between this marker, and the END OF DWARF
129 // marker should be included in the source file. Search for
130 // FUNCTION_STACK_SIZE_GOES_HERE and FUNCTION NAME GOES HERE, and
131 // provide the relevent information. Add markers called
132 // _picoMark_FUNCTION_BEGIN and _picoMark_FUNCTION_END around the
133 // function in question.
134 //============================================================================
135
136 //============================================================================
137 // Frame information.
138 //============================================================================
139
140 .section .debug_frame
141 _picoMark_DebugFrame=
142
143 // Common CIE header.
144 .unalignedInitLong _picoMark_CieEnd-_picoMark_CieBegin
145 _picoMark_CieBegin=
146 .unalignedInitLong 0xffffffff
147 .initByte 0x1 // CIE Version
148 .ascii 16#0# // CIE Augmentation
149 .uleb128 0x1 // CIE Code Alignment Factor
150 .sleb128 2 // CIE Data Alignment Factor
151 .initByte 0xc // CIE RA Column
152 .initByte 0xc // DW_CFA_def_cfa
153 .uleb128 0xd
154 .uleb128 0x0
155 .align 2
156 _picoMark_CieEnd=
157
158 // FDE
159 _picoMark_LSFDE0I900821033007563=
160 .unalignedInitLong _picoMark_FdeEnd-_picoMark_FdeBegin
161 _picoMark_FdeBegin=
162 .unalignedInitLong _picoMark_DebugFrame // FDE CIE offset
163 .unalignedInitWord _picoMark_FUNCTION_BEGIN // FDE initial location
164 .unalignedInitWord _picoMark_FUNCTION_END-_picoMark_FUNCTION_BEGIN
165 .initByte 0xe // DW_CFA_def_cfa_offset
166 .uleb128 0x0 // <-- FUNCTION_STACK_SIZE_GOES_HERE
167 .initByte 0x4 // DW_CFA_advance_loc4
168 .unalignedInitLong _picoMark_FUNCTION_END-_picoMark_FUNCTION_BEGIN
169 .initByte 0xe // DW_CFA_def_cfa_offset
170 .uleb128 0x0
171 .align 2
172 _picoMark_FdeEnd=
173
174 //============================================================================
175 // Abbrevation information.
176 //============================================================================
177
178 .section .debug_abbrev
179 _picoMark_ABBREVIATIONS=
180
181 .section .debug_abbrev
182 .uleb128 0x1 // (abbrev code)
183 .uleb128 0x11 // (TAG: DW_TAG_compile_unit)
184 .initByte 0x1 // DW_children_yes
185 .uleb128 0x10 // (DW_AT_stmt_list)
186 .uleb128 0x6 // (DW_FORM_data4)
187 .uleb128 0x12 // (DW_AT_high_pc)
188 .uleb128 0x1 // (DW_FORM_addr)
189 .uleb128 0x11 // (DW_AT_low_pc)
190 .uleb128 0x1 // (DW_FORM_addr)
191 .uleb128 0x25 // (DW_AT_producer)
192 .uleb128 0x8 // (DW_FORM_string)
193 .uleb128 0x13 // (DW_AT_language)
194 .uleb128 0x5 // (DW_FORM_data2)
195 .uleb128 0x3 // (DW_AT_name)
196 .uleb128 0x8 // (DW_FORM_string)
197 .initByte 0x0
198 .initByte 0x0
199
200 .uleb128 0x2 ;# (abbrev code)
201 .uleb128 0x2e ;# (TAG: DW_TAG_subprogram)
202 .initByte 0x0 ;# DW_children_no
203 .uleb128 0x3 ;# (DW_AT_name)
204 .uleb128 0x8 ;# (DW_FORM_string)
205 .uleb128 0x11 ;# (DW_AT_low_pc)
206 .uleb128 0x1 ;# (DW_FORM_addr)
207 .uleb128 0x12 ;# (DW_AT_high_pc)
208 .uleb128 0x1 ;# (DW_FORM_addr)
209 .initByte 0x0
210 .initByte 0x0
211
212 .initByte 0x0
213
214 //============================================================================
215 // Line information. DwarfLib requires this to be present, but it can
216 // be empty.
217 //============================================================================
218
219 .section .debug_line
220 _picoMark_LINES=
221
222 //============================================================================
223 // Debug Information
224 //============================================================================
225 .section .debug_info
226
227 //Fixed header.
228 .unalignedInitLong _picoMark_DEBUG_INFO_END-_picoMark_DEBUG_INFO_BEGIN
229 _picoMark_DEBUG_INFO_BEGIN=
230 .unalignedInitWord 0x2
231 .unalignedInitLong _picoMark_ABBREVIATIONS
232 .initByte 0x2
233
234 // Compile unit information.
235 .uleb128 0x1 // (DIE 0xb) DW_TAG_compile_unit)
236 .unalignedInitLong _picoMark_LINES
237 .unalignedInitWord _picoMark_FUNCTION_END
238 .unalignedInitWord _picoMark_FUNCTION_BEGIN
239 // Producer is `picoChip'
240 .ascii 16#70# 16#69# 16#63# 16#6f# 16#43# 16#68# 16#69# 16#70# 16#00#
241 .unalignedInitWord 0xcafe // ASM language
242 .ascii 16#0# // Name. DwarfLib expects this to be present.
243
244 .uleb128 0x2 ;# (DIE DW_TAG_subprogram)
245
246 // FUNCTION NAME GOES HERE. Use `echo name | od -t x1' to get the hex. Each hex
247 // digit is specified using the format 16#XX#
248 .ascii 16#5f# 16#64# 16#69# 16#76# 16#6d# 16#6f# 16#64# 16#31# 16#35# 16#0# // Function name `_divmod15'
249 .unalignedInitWord _picoMark_FUNCTION_BEGIN // DW_AT_low_pc
250 .unalignedInitWord _picoMark_FUNCTION_END // DW_AT_high_pc
251
252 .initByte 0x0 // end of compile unit children.
253
254 _picoMark_DEBUG_INFO_END=
255
256 //============================================================================
257 // END OF DWARF
258 //============================================================================
259
260 .section .endFile
261 // End of picoChip ASM file