Initial maemo platform support
[maemo-rb.git] / firmware / target / mips / memcpy-mips.S
blob2e7f245c69c4bbc639e2af8481b8904825e7221e
1 /***************************************************************************
2  *             __________               __   ___.
3  *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
4  *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
5  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
6  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
7  *                     \/            \/     \/    \/            \/
8  * $Id$
9  *
10  * Copyright (C) 2002, 2003 Free Software Foundation, Inc.
11  * This file was originally part of the GNU C Library
12  * Contributed to glibc by Hartvig Ekner <hartvige@mips.com>, 2002
13  * Adapted for Rockbox by Maurus Cuelenaere, 2009
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21  * KIND, either express or implied.
22  *
23  ****************************************************************************/
25 #include "config.h"
26 #include "mips.h"
28 /* void *memcpy(void *s1, const void *s2, size_t n);  */
30 #ifdef ROCKBOX_BIG_ENDIAN
31 # define LWHI  lwl                /* high part is left in big-endian        */
32 # define SWHI  swl                /* high part is left in big-endian        */
33 # define LWLO  lwr                /* low part is right in big-endian        */
34 # define SWLO  swr                /* low part is right in big-endian        */
35 #else
36 # define LWHI  lwr                /* high part is right in little-endian    */
37 # define SWHI  swr                /* high part is right in little-endian    */
38 # define LWLO  lwl                /* low part is left in little-endian      */
39 # define SWLO  swl                /* low part is left in little-endian      */
40 #endif
42     .section   .icode, "ax", %progbits
44     .global    memcpy
45     .type      memcpy, %function
46     
47     .set       noreorder
49 memcpy:
50     slti       t0, a2, 8                # Less than 8?
51     bne        t0, zero, last8
52     move       v0, a0                   # Setup exit value before too late
54     xor        t0, a1, a0               # Find a0/a1 displacement
55     andi       t0, 0x3
56     bne        t0, zero, shift          # Go handle the unaligned case
57     subu       t1, zero, a1
58     andi       t1, 0x3                  # a0/a1 are aligned, but are we
59     beq        t1, zero, chk8w          # starting in the middle of a word?
60     subu       a2, t1
61     LWHI       t0, 0(a1)                # Yes we are... take care of that
62     addu       a1, t1
63     SWHI       t0, 0(a0)
64     addu       a0, t1
66 chk8w:       
67     andi       t0, a2, 0x1f             # 32 or more bytes left?
68     beq        t0, a2, chk1w
69     subu       a3, a2, t0               # Yes
70     addu       a3, a1                   # a3 = end address of loop
71     move       a2, t0                   # a2 = what will be left after loop
72 lop8w:       
73     lw         t0,  0(a1)               # Loop taking 8 words at a time
74     lw         t1,  4(a1)
75     lw         t2,  8(a1)
76     lw         t3, 12(a1)
77     lw         t4, 16(a1)
78     lw         t5, 20(a1)
79     lw         t6, 24(a1)
80     lw         t7, 28(a1)
81     addiu      a0, 32
82     addiu      a1, 32
83     sw         t0, -32(a0)
84     sw         t1, -28(a0)
85     sw         t2, -24(a0)
86     sw         t3, -20(a0)
87     sw         t4, -16(a0)
88     sw         t5, -12(a0)
89     sw         t6, -8(a0)
90     bne        a1, a3, lop8w
91     sw         t7, -4(a0)
93 chk1w:       
94     andi       t0, a2, 0x3              # 4 or more bytes left?
95     beq        t0, a2, last8
96     subu       a3, a2, t0               # Yes, handle them one word at a time
97     addu       a3, a1                   # a3 again end address
98     move       a2, t0
99 lop1w:       
100     lw         t0, 0(a1)
101     addiu      a0, 4
102     addiu      a1, 4
103     bne        a1, a3, lop1w
104     sw         t0, -4(a0)
106 last8:       
107     blez       a2, lst8e                # Handle last 8 bytes, one at a time
108     addu       a3, a2, a1
109 lst8l:       
110     lb         t0, 0(a1)
111     addiu      a0, 1
112     addiu      a1, 1
113     bne        a1, a3, lst8l
114     sb         t0, -1(a0)
115 lst8e:       
116     jr         ra                       # Bye, bye
117     nop
119 shift:       
120     subu       a3, zero, a0             # Src and Dest unaligned 
121     andi       a3, 0x3                  #  (unoptimized case...)
122     beq        a3, zero, shft1
123     subu       a2, a3                   # a2 = bytes left
124     LWHI       t0, 0(a1)                # Take care of first odd part
125     LWLO       t0, 3(a1)
126     addu       a1, a3
127     SWHI       t0, 0(a0)
128     addu       a0, a3
129 shft1:       
130     andi       t0, a2, 0x3
131     subu       a3, a2, t0
132     addu       a3, a1
133 shfth:       
134     LWHI       t1, 0(a1)                # Limp through, word by word
135     LWLO       t1, 3(a1)
136     addiu      a0, 4
137     addiu      a1, 4
138     bne        a1, a3, shfth
139     sw         t1, -4(a0)
140     b          last8                    # Handle anything which may be left
141     move       a2, t0
143     .set       reorder