OpenCores
URL https://opencores.org/ocsvn/amber/amber/trunk

Subversion Repositories amber

[/] [amber/] [trunk/] [sw/] [mini-libc/] [libc_asm.S] - Blame information for rev 31

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 csantifort
/*----------------------------------------------------------------
2
//                                                              //
3
//  libc_asm.S                                                  //
4
//                                                              //
5
//  This file is part of the Amber project                      //
6
//  http://www.opencores.org/project,amber                      //
7
//                                                              //
8
//  Description                                                 //
9
//  Assembly routines for the mini-libc library.                //
10
//                                                              //
11
//  Author(s):                                                  //
12
//      - Conor Santifort, csantifort.amber@gmail.com           //
13
//                                                              //
14
//////////////////////////////////////////////////////////////////
15
//                                                              //
16
// Copyright (C) 2010 Authors and OPENCORES.ORG                 //
17
//                                                              //
18
// This source file may be used and distributed without         //
19
// restriction provided that this copyright statement is not    //
20
// removed from the file and that any derivative work contains  //
21
// the original copyright notice and the associated disclaimer. //
22
//                                                              //
23
// This source file is free software; you can redistribute it   //
24
// and/or modify it under the terms of the GNU Lesser General   //
25
// Public License as published by the Free Software Foundation; //
26
// either version 2.1 of the License, or (at your option) any   //
27
// later version.                                               //
28
//                                                              //
29
// This source is distributed in the hope that it will be       //
30
// useful, but WITHOUT ANY WARRANTY; without even the implied   //
31
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
32
// PURPOSE.  See the GNU Lesser General Public License for more //
33
// details.                                                     //
34
//                                                              //
35
// You should have received a copy of the GNU Lesser General    //
36
// Public License along with this source; if not, download it   //
37
// from http://www.opencores.org/lgpl.shtml                     //
38
//                                                              //
39
----------------------------------------------------------------*/
40
 
41
#include "amber_registers.h"
42
 
43
 
44
/* _testfail: Used to terminate execution in Verilog simulations */
45
/* On the board just puts the processor into an infinite loop    */
46
        .section .text
47
        .globl _testfail
48
_testfail:
49
        ldr     r11, AdrTestStatus
50
        str     r0, [r11]
51
        b       _testfail
52
 
53
 
54
/* _testpass: Used to terminate execution in Verilog simulations */
55
/* On the board just puts the processor into an infinite loop    */
56
        .globl _testpass
57
_testpass:
58
        ldr     r11, AdrTestStatus
59
        mov     r10, #17
60
        str     r10, [r11]
61
        b       _testpass
62
 
63
/* _outbyte: Output a single character through UART 0 */
64
        @ if the uart tx fifo is stuck full
65
        @ this routine will cycle forever
66
        .globl _outbyte
67
_outbyte:
68
        ldr     r1, AdrUARTDR
69
        ldr     r3, AdrUARTFR
70
        @ Check the tx_full flag
71
1:      ldr     r2, [r3]
72
        and     r2, r2, #0x20
73
        cmp     r2, #0
74
        streqb  r0, [r1]
75
        moveqs  pc, lr          @ return
76
        bne     1b
77
 
78
 
79
/* _inbyte: Input a single character from UART 0 */
80
        @ r0 is the timeout in mS
81
        .globl _inbyte
82
_inbyte:
83
        ldr     r2, AdrUARTDR @ data
84
        ldr     r3, AdrUARTFR @ flags
85
 
86
        @ Multiple delay value by 2560
87
        @ as the delay loop takes about 12 clock cycles running cached
88
        @ so that factor gives 1:1mS @33MHz
89
        mov     r1, r0, lsl #11
90
        add     r1, r1, r0, lsl #9
91
 
92
        @ Check the r2 empty flag
93
2:      ldr     r0, [r3]
94
        ands    r0, r0, #0x10
95
        ldreqb  r0, [r2]
96
        moveq   pc, lr
97
 
98
        @ decrement timeout
99
        subs    r1, r1, #1
100
        bne     2b
101
 
102
        mov     r0, #-1
103
        movs    pc, lr
104
 
105
 
106
/* _div: Integer division function */
107
        @ Divide r0 by r1
108
        @ Answer returned in r1
109
        .globl _div
110 31 csantifort
        .globl __aeabi_idiv
111
__aeabi_idiv:
112 2 csantifort
_div:
113
        stmdb   sp!, {r4, lr}
114
 
115
        @ divide r1 by r2, also use registers r0 and r4
116
        mov     r2, r1
117
        mov     r1, r0
118
 
119
        cmp      r2, #0
120
        beq      3f
121
 
122
        @ In order to divide r1 by r2, the first thing we need to do is to shift r2
123
        @ left by the necessary number of places. The easiest method of doing this
124
        @ is simply by trial and error - shift until we discover that r2 has become
125
        @ too big, then stop.
126
        mov      r0,#0     @ clear r0 to accumulate result
127
        mov      r3,#1     @ set bit 0 in r3, which will be
128
                           @ shifted left then right
129
 
130
1:      cmp      r3, #0    @ escape on error
131
        moveq    r3, #0x10000000
132
        beq      2f
133
        cmp      r2,r1
134
        movls    r2,r2,lsl#1
135
        movls    r3,r3,lsl#1
136
        bls      1b
137
        @ shift r2 left until it is about to be bigger than r1
138
        @ shift r3 left in parallel in order to flag how far we have to go
139
 
140
        @ r0 will be used to hold the result. The role of r3 is more complicated.
141
        @ In effect, we are using r3 to mark where the right-hand end of r2 has got to
142
        @ - if we shift r2 three places left, this will be indicated by a value of %1000
143
        @ in r3. However, we also add it to r0 every time we manage a successful subtraction,
144
        @ since it marks the position of the digit currently being calculated in the answer.
145
        @ In the binary example (50 ÷ 10) above, we shifted the '10' two places left,
146
        @ so at the time of the first subtraction, r3 would have been %100, at the time
147
        @ of the second (which failed) it would have been %10, and at the time of the
148
        @ third %1. Adding it to r0 after each successful subtraction would have
149
        @ given us, once again, the answer of %101!
150
 
151
        @ Now for the loop that actually does the work:
152
2:      cmp       r1,r2      @ carry set if r1>r2 (don't ask why)
153
        subcs     r1,r1,r2   @ subtract r2 from r1 if this would
154
                             @ give a positive answer
155
        addcs     r0,r0,r3   @ and add the current bit in r3 to
156
                             @ the accumulating answer in r0
157
 
158
        @ In subtraction (a cmp instruction simulates a subtraction in
159
        @ order to set the flags), if r1 - r2 gives a positive answer and no 'borrow'
160
        @ is required, the carry flag is set. This is required in order to make SBC
161
        @ (Subtract with Carry) work properly when used to carry out a 64-bit subtraction,
162
        @ but it is confusing!
163
 
164
        @ In this case, we are turning it to our advantage. The carry flag is set to
165
        @ indicate that a successful subtraction is possible, i.e. one that doesn't
166
        @ generate a negative result, and the two following instructions are carried
167
        @ out only when the condition Carry Set applies. Note that the 'S' on the end
168
        @ of these instructions is part of the 'CS' condition code and does not mean
169
        @ that they set the flags!
170
 
171
        movs      r3,r3,lsr #1    @ Shift r3 right into carry flag
172
        movcc     r2,r2,lsr #1    @ and if bit 0 of r3 was zero, also
173
                                  @ shift r2 right
174
        bcc       2b              @ If carry not clear, r3 has shifted
175
                                  @ back to where it started, and we
176
                                  @ can end
177
3:      ldmia   sp!, {r4, pc}^
178
 
179
 
180 31 csantifort
/* strcpy: String copy function
181
    char * strcpy ( char * destination, const char * source );
182
    destination is returned
183
*/
184 2 csantifort
        @ r0 points to destination
185
        @ r1 points to source string which terminates with a 0
186
        .globl strcpy
187 31 csantifort
strcpy:
188
        stmdb   sp!, {r4-r7, lr}
189
        mov     r6, r0
190
        @ get relative alignment of strings
191
        and     r2, r6, #3
192
        and     r3, r1, #3
193
        @ only if both strings are zero-aligned use the fast 'aligned' algorithm
194
        orrs    r2, r3
195
        bne     strcpy_slow
196
 
197
strcpy_fast:
198
        @ process strings 12 bytes at a time
199
        ldmia   r1!, {r2-r5}
200
 
201
        @ check for a zero byte
202
        @ only need to examine one of the strings because
203
        @ they are equal up to this point!
204
        ands    r7, r2, #0xff
205
        andnes  r7, r2, #0xff00
206
        andnes  r7, r2, #0xff0000
207
        andnes  r7, r2, #0xff000000
208
        strne   r2, [r6], #4
209
        subeq   r1, r1, #4
210
 
211
        andnes  r7, r3, #0xff
212
        andnes  r7, r3, #0xff00
213
        andnes  r7, r3, #0xff0000
214
        andnes  r7, r3, #0xff000000
215
        strne   r3, [r6], #4
216
        subeq   r1, r1, #4
217
 
218
        andnes  r7, r4, #0xff
219
        andnes  r7, r4, #0xff00
220
        andnes  r7, r4, #0xff0000
221
        andnes  r7, r4, #0xff000000
222
        strne   r4, [r6], #4
223
        subeq   r1, r1, #4
224
 
225
        andnes  r7, r5, #0xff
226
        andnes  r7, r5, #0xff00
227
        andnes  r7, r5, #0xff0000
228
        andnes  r7, r5, #0xff000000
229
        strne   r5, [r6], #4
230
        subeq   r1, r1, #4
231
 
232
        @ loop back to look at next 12 bytes
233
        bne     strcpy_fast
234
 
235
        @ the source string contains a zero character
236
 
237
strcpy_slow:
238
        @ unroll the loop 4 times
239 2 csantifort
        ldrb    r3, [r1], #1
240 31 csantifort
        strb    r3, [r6], #1
241 2 csantifort
        cmp     r3, #0
242 31 csantifort
        ldmeqia sp!, {r4-r7, pc}^
243
 
244
        ldrb    r3, [r1], #1
245
        strb    r3, [r6], #1
246
        cmp     r3, #0
247
        ldmeqia sp!, {r4-r7, pc}^
248
 
249
        ldrb    r3, [r1], #1
250
        strb    r3, [r6], #1
251
        cmp     r3, #0
252
        ldmeqia sp!, {r4-r7, pc}^
253
 
254
        ldrb    r3, [r1], #1
255
        strb    r3, [r6], #1
256
        cmp     r3, #0
257
        ldmeqia sp!, {r4-r7, pc}^
258
 
259
        b       strcpy_slow
260 2 csantifort
 
261
 
262 31 csantifort
/* int strcmp ( const char * str1, const char * str2 );
263
   A value greater than zero indicates that the first character
264
   that does not match has a greater value in str1 than in str2;
265
   And a value less than zero indicates the opposite.
266
*/
267
        .globl strcmp
268
strcmp:
269
        stmdb   sp!, {r4-r8, lr}
270
 
271
        @ only if both strings are zero-aligned use the fast 'aligned' algorithm
272
        orr     r2, r0, r1
273
        ands    r2, r2, #3
274
        bne     strcmp_slow
275
 
276
strcmp_fast:
277
        @ process strings 12 bytes at a time
278
        ldmia   r0!, {r2-r4}
279
        ldmia   r1!, {r5-r7}
280
        cmp     r2, r5
281
        bne     1f
282
        cmpeq   r3, r6
283
        bne     2f
284
        cmpeq   r4, r7
285
        bne     3f
286
 
287
        @ strings are equal - find a zero byte
288
        @ only need to examine one of the strings because
289
        @ they are equal up to this point!
290
        ands    r8, r2, #0xff
291
        andnes  r8, r2, #0xff00
292
        andnes  r8, r2, #0xff0000
293
        andnes  r8, r2, #0xff000000
294
 
295
        andnes  r8, r3, #0xff
296
        andnes  r8, r3, #0xff00
297
        andnes  r8, r3, #0xff0000
298
        andnes  r8, r3, #0xff000000
299
 
300
        andnes  r8, r4, #0xff
301
        andnes  r8, r4, #0xff00
302
        andnes  r8, r4, #0xff0000
303
        andnes  r8, r4, #0xff000000
304
 
305
        @ loop back to look at next 12 bytes
306
        bne     strcmp_fast
307
 
308
        @ the first string contains a zero character
309
        @ the strings are the same, so both strings end
310
        moveq   r0, #0
311
        ldmeqia sp!, {r4-r8, pc}^
312
 
313
 
314
        @ Roll back the string pointers to before the mismatch
315
        @ then handle the remaining part byte by byte
316
1:      sub     r0, r0, #12
317
        sub     r1, r1, #12
318
 
319
strcmp_slow:
320
        ldrb    r2, [r0], #1
321
        ldrb    r3, [r1], #1
322
        eors    r4, r2, r3          @ are the bytes equal ?
323
        bne     bytes_different
324
        ldrb    r5, [r0], #1
325
        ldrb    r6, [r1], #1
326
        cmp     r2, #0              @ are they equal and zero ?
327
        beq     bytes_zero
328
        eors    r7, r5, r6          @ are the bytes equal ?
329
        bne     bytes_different
330
        ldrb    r2, [r0], #1
331
        ldrb    r3, [r1], #1
332
        cmp     r5, #0              @ are they equal and zero ?
333
        beq     bytes_zero
334
        eors    r4, r2, r3          @ are the bytes equal ?
335
        bne     bytes_different
336
        ldrb    r5, [r0], #1
337
        ldrb    r6, [r1], #1
338
        cmp     r2, #0              @ are they equal and zero ?
339
        beq     bytes_zero
340
        eors    r7, r5, r6          @ are the bytes equal ?
341
        bne     bytes_different
342
        cmp     r5, #0              @ are they equal and zero ?
343
        beq     bytes_zero
344
 
345
        bne     strcmp_slow
346
 
347
 
348
 
349
@ Skipping first 4 bytes so just check they
350
@ don't contain an end of string 0 character
351
2:      ands    r8, r2, #0xff
352
        andnes  r8, r2, #0xff00
353
        andnes  r8, r2, #0xff0000
354
        andnes  r8, r2, #0xff000000
355
        beq     bytes_zero
356
 
357
        @ start looking at 5th byte
358
        sub     r0, r0, #8
359
        sub     r1, r1, #8
360
 
361
        ldrb    r2, [r0], #1
362
        ldrb    r3, [r1], #1
363
        eors    r4, r2, r3          @ are the bytes equal ?
364
        bne     bytes_different
365
        ldrb    r5, [r0], #1
366
        ldrb    r6, [r1], #1
367
        cmp     r2, #0              @ are they equal and zero ?
368
        beq     bytes_zero
369
        eors    r7, r5, r6          @ are the bytes equal ?
370
        bne     bytes_different
371
        ldrb    r2, [r0], #1
372
        ldrb    r3, [r1], #1
373
        cmp     r5, #0              @ are they equal and zero ?
374
        beq     bytes_zero
375
        eors    r4, r2, r3          @ are the bytes equal ?
376
        bne     bytes_different
377
        ldrb    r5, [r0], #1
378
        ldrb    r6, [r1], #1
379
        cmp     r2, #0              @ are they equal and zero ?
380
        beq     bytes_zero
381
        eors    r7, r5, r6          @ are the bytes equal ?
382
        bne     bytes_different
383
        cmp     r5, #0              @ are they equal and zero ?
384
        beq     bytes_zero
385
 
386
        bne     strcmp_slow
387
 
388
@ Skipping first 8 bytes so just check they
389
@ don't contain an end of string 0 character
390
3:      ands    r8, r2, #0xff
391
        andnes  r8, r2, #0xff00
392
        andnes  r8, r2, #0xff0000
393
        andnes  r8, r2, #0xff000000
394
 
395
        andnes  r8, r3, #0xff
396
        andnes  r8, r3, #0xff00
397
        andnes  r8, r3, #0xff0000
398
        andnes  r8, r3, #0xff000000
399
        beq     bytes_zero
400
 
401
        sub     r0, r0, #4
402
        sub     r1, r1, #4
403
        ldrb    r2, [r0], #1
404
        ldrb    r3, [r1], #1
405
        eors    r4, r2, r3          @ are the bytes equal ?
406
        bne     bytes_different
407
        ldrb    r5, [r0], #1
408
        ldrb    r6, [r1], #1
409
        cmp     r2, #0              @ are they equal and zero ?
410
        beq     bytes_zero
411
        eors    r7, r5, r6          @ are the bytes equal ?
412
        bne     bytes_different
413
        ldrb    r2, [r0], #1
414
        ldrb    r3, [r1], #1
415
        cmp     r5, #0              @ are they equal and zero ?
416
        beq     bytes_zero
417
        eors    r4, r2, r3          @ are the bytes equal ?
418
        bne     bytes_different
419
        ldrb    r5, [r0], #1
420
        ldrb    r6, [r1], #1
421
        cmp     r2, #0              @ are they equal and zero ?
422
        beq     bytes_zero
423
        eors    r7, r5, r6          @ are the bytes equal ?
424
        bne     bytes_different
425
        cmp     r5, #0              @ are they equal and zero ?
426
        beq     bytes_zero
427
 
428
        bne     strcmp_slow
429
 
430
 
431
bytes_zero:
432
        moveq   r0, #0              @ if equal and zero, return zero
433
        ldmeqia sp!, {r4-r8, pc}^
434
 
435
 
436
bytes_different:
437
        sub     r0, r5, r6
438
        ldmia   sp!, {r4-r8, pc}^
439
 
440
 
441
 
442
        /* void *malloc(size_t size); */
443
        .globl malloc
444
malloc:
445
        ldr     r1, AdrMalloc
446
        ldr     r0, [r1]
447
        add     r0, r0, #0x10000
448
        str     r0, [r1]
449
        mov     pc, lr
450
 
451
 
452
        .globl times
453
times:
454
@ TODO
455
        mov     r0, #0
456
        mov     pc, lr
457
 
458
 
459 2 csantifort
/* strncpy: String copy function */
460
        @ r0 points to destination
461
        @ r1 points to source string
462
        @ r2 is the number of bytes to copy
463
        .globl strncpy
464
strncpy:
465
        stmdb   sp!, {r4, lr}
466
        cmp     r2, #0
467
        beq     2f
468
        mov     r4, #0
469
1:      ldrb    r3, [r1], #1
470
        strb    r3, [r0], #1
471
        add     r4,  r4,  #1
472
        cmp     r2,  r4
473
        beq     2f
474
        b       1b
475
2:      ldmia   sp!, {r4, pc}^
476
 
477
 
478
/* strncpy: String compare function */
479
        @ return the difference if the strings don't match
480
        .globl strncmp
481
strncmp:
482
        stmdb   sp!, {r4, r5, r6, lr}
483
 
484
        @ check for 0 length
485
        cmp     r2, #0
486
        moveq   r0, #1
487
        beq     2f
488
 
489
        mov     r3, #0
490
 
491
1:      add     r3, r3,   #1
492
        ldrb    r4, [r0], #1
493
        ldrb    r5, [r1], #1
494
 
495
        subs    r6, r4, r5
496
        movne   r0, r6
497
        bne     2f
498
 
499
        cmp     r3, r2
500
        moveq   r0, #0
501
        beq     2f
502
 
503
        b       1b
504
2:      ldmia   sp!, {r4, r5, r6, pc}^
505
 
506
 
507 31 csantifort
AdrMalloc:      .word  0x7000000
508 2 csantifort
AdrTestStatus:  .word  ADR_AMBER_TEST_STATUS
509
AdrUARTDR:      .word  ADR_AMBER_UART0_DR
510
AdrUARTFR:      .word  ADR_AMBER_UART0_FR
511
/* ========================================================================= */
512
/* ========================================================================= */
513
 
514
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.