0
|
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 Designs 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
|