1fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil/*
2fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil * Copyright (c) 2017 Imagination Technologies.
3fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil *
4fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil * All rights reserved.
5fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil *
6fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil * Redistribution and use in source and binary forms, with or without
7fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil * modification, are permitted provided that the following conditions
8fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil * are met:
9fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil *
10fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil *      * Redistributions of source code must retain the above copyright
11fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil *        notice, this list of conditions and the following disclaimer.
12fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil *      * Redistributions in binary form must reproduce the above copyright
13fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil *        notice, this list of conditions and the following disclaimer
14fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil *        in the documentation and/or other materials provided with
15fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil *        the distribution.
16fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil *      * Neither the name of Imagination Technologies nor the names of its
17fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil *        contributors may be used to endorse or promote products derived
18fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil *        from this software without specific prior written permission.
19fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil *
20fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil */
32fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
33fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#include <string.h>
34fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
35fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#if !defined(UNALIGNED_INSTR_SUPPORT)
36fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil/* does target have unaligned lw/ld/ualw/uald instructions? */
37fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#define UNALIGNED_INSTR_SUPPORT 0
38fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#if __mips_isa_rev < 6 && !__mips1
39fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#undef UNALIGNED_INSTR_SUPPORT
40fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#define UNALIGNED_INSTR_SUPPORT 1
41fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#endif
42fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#endif
43fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
44fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#if !defined(HW_UNALIGNED_SUPPORT)
45fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil/* Does target have hardware support for unaligned accesses?  */
46fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#define HW_UNALIGNED_SUPPORT 0
47fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#if __mips_isa_rev >= 6
48fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#undef HW_UNALIGNED_SUPPORT
49fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#define HW_UNALIGNED_SUPPORT 1
50fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#endif
51fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#endif
52fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
53fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#define ENABLE_PREFETCH     1
54fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
55fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#if ENABLE_PREFETCH
56fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#define PREFETCH(addr)  __builtin_prefetch (addr, 0, 1);
57fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#else
58fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#define PREFETCH(addr)
59fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#endif
60fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
61fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#if _MIPS_SIM == _ABIO32
62fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patiltypedef unsigned long reg_t;
63fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patiltypedef struct
64fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil{
65fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  reg_t B0:8, B1:8, B2:8, B3:8;
66fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil} bits_t;
67fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#else
68fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patiltypedef unsigned long long reg_t;
69fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patiltypedef struct
70fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil{
71fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  reg_t B0:8, B1:8, B2:8, B3:8, B4:8, B5:8, B6:8, B7:8;
72fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil} bits_t;
73fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#endif
74fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
75fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patiltypedef union
76fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil{
77fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  reg_t v;
78fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  bits_t b;
79fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil} bitfields_t;
80fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
81fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#define DO_BYTE(a, i)   \
82fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  a[i] = bw.b.B##i;     \
83fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  len--;                \
84fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  if(!len) return ret;  \
85fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
86fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil/* This code is called when aligning a pointer, there are remaining bytes
87fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil   after doing word compares, or architecture does not have some form
88fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil   of unaligned support.  */
89fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patilstatic inline void * __attribute__ ((always_inline))
90fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patildo_bytes (void *a, const void *b, unsigned long len, void *ret)
91fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil{
92fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  unsigned char *x = (unsigned char *) a;
93fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  unsigned char *y = (unsigned char *) b;
94fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  unsigned long i;
95fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
96fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  /* 'len' might be zero here, so preloading the first two values
97fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil     before the loop may access unallocated memory.  */
98fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  for (i = 0; i < len; i++) {
99fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    *x = *y;
100fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    x++;
101fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    y++;
102fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  }
103fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  return ret;
104fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil}
105fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
106fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil/* This code is called to copy only remaining bytes within word or doubleword */
107fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patilstatic inline void * __attribute__ ((always_inline))
108fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patildo_bytes_remaining (void *a, const void *b, unsigned long len, void *ret)
109fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil{
110fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  unsigned char *x = (unsigned char *) a;
111fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
112fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  if(len > 0) {
113fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    bitfields_t bw;
114fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    bw.v = *((reg_t*) b);
115fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
116fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#if __mips64
117fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    DO_BYTE(x, 0);
118fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    DO_BYTE(x, 1);
119fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    DO_BYTE(x, 2);
120fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    DO_BYTE(x, 3);
121fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    DO_BYTE(x, 4);
122fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    DO_BYTE(x, 5);
123fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    DO_BYTE(x, 6);
124fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    DO_BYTE(x, 7);
125fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#else
126fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    DO_BYTE(x, 0);
127fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    DO_BYTE(x, 1);
128fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    DO_BYTE(x, 2);
129fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    DO_BYTE(x, 3);
130fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#endif
131fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  }
132fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
133fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    return ret;
134fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil}
135fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
136fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#if !HW_UNALIGNED_SUPPORT
137fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#if UNALIGNED_INSTR_SUPPORT
138fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil/* for MIPS GCC, there are no unaligned builtins - so this struct forces
139fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil   the compiler to treat the pointer access as unaligned.  */
140fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patilstruct ulw
141fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil{
142fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  reg_t uli;
143fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil} __attribute__ ((packed));
144fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
145fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil/* first pointer is not aligned while second pointer is.  */
146fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patilstatic void *
147fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patilunaligned_words (struct ulw *a, const reg_t * b,
148fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil                 unsigned long words, unsigned long bytes, void *ret)
149fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil{
150fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#if ((_MIPS_SIM == _ABIO32) || _MIPS_TUNE_I6400)
151fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  unsigned long i, words_by_8, words_by_1;
152fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  words_by_1 = words % 8;
153fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  words_by_8 = words >> 3;
154fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  for (; words_by_8 > 0; words_by_8--) {
155fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    if(words_by_8 != 1)
156fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil      PREFETCH (b + 8);
157fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    reg_t y0 = b[0], y1 = b[1], y2 = b[2], y3 = b[3];
158fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    reg_t y4 = b[4], y5 = b[5], y6 = b[6], y7 = b[7];
159fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[0].uli = y0;
160fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[1].uli = y1;
161fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[2].uli = y2;
162fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[3].uli = y3;
163fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[4].uli = y4;
164fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[5].uli = y5;
165fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[6].uli = y6;
166fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[7].uli = y7;
167fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a += 8;
168fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    b += 8;
169fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  }
170fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#else
171fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  unsigned long i, words_by_4, words_by_1;
172fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  words_by_1 = words % 4;
173fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  words_by_4 = words >> 2;
174fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil   for (; words_by_4 > 0; words_by_4--) {
175fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    if(words_by_4 != 1)
176fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil      PREFETCH (b + 4);
177fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    reg_t y0 = b[0], y1 = b[1], y2 = b[2], y3 = b[3];
178fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[0].uli = y0;
179fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[1].uli = y1;
180fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[2].uli = y2;
181fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[3].uli = y3;
182fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a += 4;
183fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    b += 4;
184fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  }
185fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#endif
186fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
187fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  /* do remaining words.  */
188fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  for (i = 0; i < words_by_1; i++) {
189fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a->uli = *b;
190fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a += 1;
191fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    b += 1;
192fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  }
193fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
194fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  /* mop up any remaining bytes.  */
195fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  return do_bytes_remaining (a, b, bytes, ret);
196fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil}
197fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#else
198fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil/* no HW support or unaligned lw/ld/ualw/uald instructions.  */
199fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patilstatic void *
200fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patilunaligned_words (reg_t * a, const reg_t * b,
201fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil                 unsigned long words, unsigned long bytes, void *ret)
202fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil{
203fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  unsigned long i;
204fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  unsigned char *x = (unsigned char *) a;
205fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
206fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  for (i = 0; i < words; i++) {
207fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    bitfields_t bw;
208fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    bw.v = *((reg_t*) b);
209fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    x = (unsigned char *) a;
210fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#if __mips64
211fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    x[0] = bw.b.B0;
212fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    x[1] = bw.b.B1;
213fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    x[2] = bw.b.B2;
214fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    x[3] = bw.b.B3;
215fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    x[4] = bw.b.B4;
216fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    x[5] = bw.b.B5;
217fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    x[6] = bw.b.B6;
218fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    x[7] = bw.b.B7;
219fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#else
220fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    x[0] = bw.b.B0;
221fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    x[1] = bw.b.B1;
222fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    x[2] = bw.b.B2;
223fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    x[3] = bw.b.B3;
224fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#endif
225fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a += 1;
226fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    b += 1;
227fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  }
228fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
229fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  /* mop up any remaining bytes */
230fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  return do_bytes_remaining (a, b, bytes, ret);
231fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil}
232fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#endif /* UNALIGNED_INSTR_SUPPORT */
233fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#endif /* HW_UNALIGNED_SUPPORT */
234fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
235fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil/* both pointers are aligned, or first isn't and HW support for unaligned.  */
236fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patilstatic void *
237fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patilaligned_words (reg_t * a, const reg_t * b,
238fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil               unsigned long words, unsigned long bytes, void *ret)
239fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil{
240fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#if ((_MIPS_SIM == _ABIO32) || _MIPS_TUNE_I6400)
241fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  unsigned long i, words_by_8, words_by_1;
242fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  words_by_1 = words % 8;
243fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  words_by_8 = words >> 3;
244fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  for (; words_by_8 > 0; words_by_8--) {
245fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    if(words_by_8 != 1)
246fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil      PREFETCH (b + 8);
247fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    reg_t x0 = b[0], x1 = b[1], x2 = b[2], x3 = b[3];
248fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    reg_t x4 = b[4], x5 = b[5], x6 = b[6], x7 = b[7];
249fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[0] = x0;
250fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[1] = x1;
251fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[2] = x2;
252fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[3] = x3;
253fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[4] = x4;
254fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[5] = x5;
255fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[6] = x6;
256fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[7] = x7;
257fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a += 8;
258fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    b += 8;
259fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  }
260fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#else
261fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  unsigned long i, words_by_4, words_by_1;
262fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  words_by_1 = words % 4;
263fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  words_by_4 = words >> 2;
264fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  for (; words_by_4 > 0; words_by_4--) {
265fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    if(words_by_4 != 1)
266fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil      PREFETCH (b + 4);
267fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    reg_t x0 = b[0], x1 = b[1], x2 = b[2], x3 = b[3];
268fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[0] = x0;
269fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[1] = x1;
270fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[2] = x2;
271fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a[3] = x3;
272fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a += 4;
273fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    b += 4;
274fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  }
275fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#endif
276fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
277fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  /* do remaining words.  */
278fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  for (i = 0; i < words_by_1; i++) {
279fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    *a = *b;
280fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a += 1;
281fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    b += 1;
282fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  }
283fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
284fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  /* mop up any remaining bytes.  */
285fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  return do_bytes_remaining (a, b, bytes, ret);
286fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil}
287fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
288fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patilvoid *
289fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patilmemcpy (void *a, const void *b, size_t len) __overloadable
290fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil{
291fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  unsigned long bytes, words;
292fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  void *ret = a;
293fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
294fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  /* shouldn't hit that often.  */
295fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  if (len < sizeof (reg_t) * 4) {
296fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    return do_bytes (a, b, len, a);
297fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  }
298fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
299fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  /* Align the second pointer to word/dword alignment.
300fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil     Note that the pointer is only 32-bits for o32/n32 ABIs. For
301fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil     n32, loads are done as 64-bit while address remains 32-bit.   */
302fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  bytes = ((unsigned long) b) % sizeof (reg_t);
303fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  if (bytes) {
304fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    bytes = sizeof (reg_t) - bytes;
305fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    if (bytes > len)
306fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil      bytes = len;
307fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    do_bytes (a, b, bytes, ret);
308fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    if (len == bytes)
309fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil      return ret;
310fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    len -= bytes;
311fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    a = (void *) (((unsigned char *) a) + bytes);
312fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    b = (const void *) (((unsigned char *) b) + bytes);
313fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  }
314fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil
315fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  /* Second pointer now aligned.  */
316fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  words = len / sizeof (reg_t);
317fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  bytes = len % sizeof (reg_t);
318fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#if HW_UNALIGNED_SUPPORT
319fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  /* treat possible unaligned first pointer as aligned.  */
320fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  return aligned_words (a, b, words, bytes, ret);
321fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#else
322fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  if (((unsigned long) a) % sizeof (reg_t) == 0) {
323fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil    return aligned_words (a, b, words, bytes, ret);
324fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  }
325fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  /* need to use unaligned instructions on first pointer.  */
326fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil  return unaligned_words (a, b, words, bytes, ret);
327fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil#endif
328fcb877ac4b05e65f64b9b3199d71dfeaae299177Prashant Patil}
329