Merge zizzer:/bk/sparcfs
[gem5.git] / src / base / compression / lzss_compression.cc
1 /*
2 * Copyright (c) 2003-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: Erik Hallnor
29 */
30
31 /** @file
32 * LZSSCompression definitions.
33 */
34
35 #include <assert.h>
36
37 #include "base/compression/lzss_compression.hh"
38
39 #include "base/misc.hh" //for fatal
40
41 void
42 LZSSCompression::findSubString(uint8_t *src, int back, int size, uint16_t &L,
43 uint16_t &P)
44 {
45 int front = 0;
46 int max_length = size - back;
47 L = 0;
48 P = back - 1;
49 while (front < back) {
50 while (src[front] != src[back] && front < back) ++front;
51 if (front >= back) {
52 return;
53 }
54 int i = 1;
55 while (src[front+i] == src[back+i] && i < max_length) ++i;
56 if (i >= L) {
57 L = i;
58 P = front;
59 }
60 if (src[front+i] != src[back+i-1]) {
61 // can't find a longer substring until past this point.
62 front += i;
63 } else {
64 ++front;
65 }
66 }
67 }
68
69 int
70 LZSSCompression::emitByte(uint8_t *dest, uint8_t byte)
71 {
72 if ((byte >> 5 & 0x7) == 0 || (byte >> 5 & 0x7) == 7) {
73 // If the top 3 bits are the same, emit 00<6bits>
74 dest[0] = byte & 0x3f;
75 return 1;
76 } else {
77 // emit 01XXXXXX <8 bits>
78 dest[0] = 0x40;
79 dest[1] = byte;
80 return 2;
81 }
82 }
83
84 void
85 LZSSCompression::emitString(uint8_t *dest, uint16_t P, uint16_t L)
86 {
87 // Emit 1<7P> <5P><3L> <8L>
88 dest[0] = 1<<7 | (P >> 5 & 0x7f);
89 dest[1] = ((P & 0x1f) << 3) | (L>>8 & 0x3);
90 dest[2] = L & 0xFF;
91 }
92
93 int
94 LZSSCompression::compress(uint8_t *dest, uint8_t *src, int size)
95 {
96 if (size > 4096) {
97 fatal("Compression can only handle block sizes of 4096 bytes or less");
98 }
99
100 // Encode the first byte.
101 int dest_index = emitByte(dest, src[0]);
102 int i = 1;
103 // A 11 bit field
104 uint16_t L;
105 // A 12 bit field
106 uint16_t P = 0;
107
108 while (i < size && dest_index < size) {
109 L = 0;
110
111 if (dest_index+3 >= size) {
112 dest_index = size;
113 continue;
114 }
115
116 if (i == size - 1) {
117 // Output the character
118 dest_index += emitByte(&dest[dest_index], src[i]);
119 ++i;
120 continue;
121 }
122 findSubString(src, i, size, L, P);
123 if (L > 1) {
124 // Output the string reference
125 emitString(&dest[dest_index], P, L);
126 dest_index += 3;
127 i = i+L;
128 } else {
129 // Output the character
130 dest_index += emitByte(&dest[dest_index], src[i]);
131 ++i;
132 }
133 }
134
135 if (dest_index >= size) {
136 // Have expansion instead of compression, just copy.
137 memcpy(dest,src,size);
138 return size;
139 }
140 return dest_index;
141 }
142
143 int
144 LZSSCompression::uncompress(uint8_t *dest, uint8_t *src, int size)
145 {
146 int index = 0;
147 int i = 0;
148 while (i < size) {
149 if (src[i] & 1<<7 ) {
150 // We have a string
151 // Extract P
152 int start = (src[i] & 0x3f)<<5 | ((src[i+1] >> 3) & 0x1f);
153 // Extract L
154 int len = (src[i+1] & 0x07)<<8 | src[i+2];
155 i += 3;
156 for (int j = start; j < start+len; ++j) {
157 dest[index++] = dest[j];
158 }
159 } else {
160 // We have a character
161 if (src[i] & 1<<6) {
162 // Value is in the next byte
163 dest[index++] = src[i+1];
164 i += 2;
165 } else {
166 // just extend the lower 6 bits
167 dest[index++] = (src[i] & 0x3f) | ((src[i] & 1<<5) ? 0xC0 : 0);
168 ++i;
169 }
170 }
171 }
172 return index;
173 }