ARM: Decode the 8/16 bit signed/unsigned add/subtract half instructions.
[gem5.git] / src / base / circlebuf.cc
1 /*
2 * Copyright (c) 2002-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Nathan Binkert
29 */
30
31 #include <algorithm>
32 #include <cstdio>
33 #include <cstring>
34 #include <string>
35
36 #include "base/atomicio.hh"
37 #include "base/circlebuf.hh"
38 #include "base/cprintf.hh"
39 #include "base/intmath.hh"
40
41 using namespace std;
42
43 CircleBuf::CircleBuf(int l)
44 : _rollover(false), _buflen(l), _size(0), _start(0), _stop(0)
45 {
46 _buf = new char[_buflen];
47 }
48
49 CircleBuf::~CircleBuf()
50 {
51 if (_buf)
52 delete [] _buf;
53 }
54
55 void
56 CircleBuf::dump()
57 {
58 cprintf("start = %10d, stop = %10d, buflen = %10d\n",
59 _start, _stop, _buflen);
60 fflush(stdout);
61 atomic_write(STDOUT_FILENO, _buf, _buflen);
62 atomic_write(STDOUT_FILENO, "<\n", 2);
63 }
64
65 void
66 CircleBuf::flush()
67 {
68 _start = 0;
69 _stop = 0;
70 _rollover = false;
71 }
72
73 void
74 CircleBuf::read(char *b, int len)
75 {
76 _size -= len;
77 if (_size < 0)
78 _size = 0;
79
80 if (_stop > _start) {
81 len = min(len, _stop - _start);
82 memcpy(b, _buf + _start, len);
83 _start += len;
84 }
85 else {
86 int endlen = _buflen - _start;
87 if (endlen > len) {
88 memcpy(b, _buf + _start, len);
89 _start += len;
90 }
91 else {
92 memcpy(b, _buf + _start, endlen);
93 _start = min(len - endlen, _stop);
94 memcpy(b + endlen, _buf, _start);
95 }
96 }
97 }
98
99 void
100 CircleBuf::read(int fd, int len)
101 {
102 _size -= len;
103 if (_size < 0)
104 _size = 0;
105
106 if (_stop > _start) {
107 len = min(len, _stop - _start);
108 atomic_write(fd, _buf + _start, len);
109 _start += len;
110 }
111 else {
112 int endlen = _buflen - _start;
113 if (endlen > len) {
114 atomic_write(fd, _buf + _start, len);
115 _start += len;
116 }
117 else {
118 atomic_write(fd, _buf + _start, endlen);
119 _start = min(len - endlen, _stop);
120 atomic_write(fd, _buf, _start);
121 }
122 }
123 }
124
125 void
126 CircleBuf::read(int fd)
127 {
128 _size = 0;
129
130 if (_stop > _start) {
131 atomic_write(fd, _buf + _start, _stop - _start);
132 }
133 else {
134 atomic_write(fd, _buf + _start, _buflen - _start);
135 atomic_write(fd, _buf, _stop);
136 }
137
138 _start = _stop;
139 }
140
141 void
142 CircleBuf::read(ostream &out)
143 {
144 _size = 0;
145
146 if (_stop > _start) {
147 out.write(_buf + _start, _stop - _start);
148 }
149 else {
150 out.write(_buf + _start, _buflen - _start);
151 out.write(_buf, _stop);
152 }
153
154 _start = _stop;
155 }
156
157 void
158 CircleBuf::readall(int fd)
159 {
160 if (_rollover)
161 atomic_write(fd, _buf + _stop, _buflen - _stop);
162
163 atomic_write(fd, _buf, _stop);
164 _start = _stop;
165 }
166
167 void
168 CircleBuf::write(char b)
169 {
170 write(&b, 1);
171 }
172
173 void
174 CircleBuf::write(const char *b)
175 {
176 write(b, strlen(b));
177 }
178
179 void
180 CircleBuf::write(const char *b, int len)
181 {
182 if (len <= 0)
183 return;
184
185 _size += len;
186 if (_size > _buflen)
187 _size = _buflen;
188
189 int old_start = _start;
190 int old_stop = _stop;
191
192 if (len >= _buflen) {
193 _start = 0;
194 _stop = _buflen;
195 _rollover = true;
196 memcpy(_buf, b + (len - _buflen), _buflen);
197 return;
198 }
199
200 if (_stop + len <= _buflen) {
201 memcpy(_buf + _stop, b, len);
202 _stop += len;
203 } else {
204 int end_len = _buflen - old_stop;
205 _stop = len - end_len;
206 memcpy(_buf + old_stop, b, end_len);
207 memcpy(_buf, b + end_len, _stop);
208 _rollover = true;
209 }
210
211 if ((old_start > old_stop && old_start < _stop) ||
212 (old_start < old_stop && _stop < old_stop))
213 _start = _stop + 1;
214 }