1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 2003-2011 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                 Eclipse Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *          http://www.eclipse.org/org/documents/epl-v10.html           *
11 *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *                   Phong Vo <kpv@research.att.com>                    *
18 *                                                                      *
19 ***********************************************************************/
20 #include	"vcdhdr.h"
21 
22 /*	Functions to encode/decode COPY addresses based on the caches.
23 **
24 **	Written by Kiem-Phong Vo (kpv@research.att.com)
25 */
26 
27 #if __STD_C
vcdkaclose(Vcdcache_t * ka)28 void vcdkaclose(Vcdcache_t* ka)
29 #else
30 void vcdkaclose(ka)
31 Vcdcache_t*	ka;
32 #endif
33 {
34 	if(ka)
35 		free(ka);
36 }
37 
38 /* initialize address caches */
39 #if __STD_C
vcdkaopen(ssize_t s_near,ssize_t s_same)40 Vcdcache_t*  vcdkaopen(ssize_t s_near, ssize_t s_same)
41 #else
42 Vcdcache_t*  vcdkaopen(s_near, s_same)
43 ssize_t		s_near;
44 ssize_t		s_same;
45 #endif
46 {
47 	Vcdcache_t*	ka;
48 	ssize_t		sz;
49 
50 	sz = sizeof(Vcdcache_t) + s_near*sizeof(ssize_t) + s_same*256*sizeof(ssize_t);
51 
52 	if(!(ka = (Vcdcache_t*)calloc(1,sz)) )
53 		return NIL(Vcdcache_t*);
54 	ka->c_same = ka->c_near = NIL(ssize_t*);
55 
56 	if((ka->s_near = s_near) > 0)
57 		ka->c_near = (ssize_t*)(ka+1);
58 
59 	if((ka->s_same = s_same) > 0)
60 		ka->c_same = ((ssize_t*)(ka+1)) + s_near;
61 
62 	return ka;
63 }
64 
65 #if __STD_C
vcdkaclear(Vcdcache_t * ka)66 void vcdkaclear(Vcdcache_t* ka)
67 #else
68 void vcdkaclear(ka)
69 Vcdcache_t*	ka;
70 #endif
71 {
72 	ssize_t	i;
73 
74 	if(ka)
75 	{	for(i = 0; i < ka->s_near; ++i)
76 			ka->c_near[i] = 0;
77 		ka->n = 0;
78 		for(i = 0; i < ka->s_same*256; ++i)
79 			ka->c_same[i] = 0;
80 	}
81 }
82 
83 /* update address caches */
84 #if __STD_C
vcdkaupdate(Vcdcache_t * ka,ssize_t addr)85 static void vcdkaupdate(Vcdcache_t* ka, ssize_t addr)
86 #else
87 static void vcdkaupdate(ka, addr)
88 Vcdcache_t*	ka;
89 ssize_t		addr;
90 #endif
91 {
92 	if(ka)
93 	{	if(ka->s_near > 0)
94 		{	ka->c_near[ka->n] = addr;
95 			if((ka->n += 1) >= ka->s_near)
96 				ka->n = 0;
97 		}
98 		if(ka->s_same > 0)
99 			ka->c_same[addr % (ka->s_same*256)] = addr;
100 	}
101 }
102 
103 /* compute encoding for COPY addresses */
104 #if __STD_C
vcdkasetaddr(Vcdcache_t * ka,ssize_t addr,ssize_t here,ssize_t * mode)105 ssize_t vcdkasetaddr(Vcdcache_t* ka, ssize_t addr, ssize_t here, ssize_t* mode)
106 #else
107 ssize_t vcdkasetaddr(ka, addr, here, mode)
108 Vcdcache_t*	ka;
109 ssize_t		addr;	/* matching address to be encoded	*/
110 ssize_t		here;	/* current location			*/
111 ssize_t*	mode;	/* to return the coded address		*/
112 #endif
113 {
114 	ssize_t	i, d, sz, bestd, bestm, bestsz;
115 
116 	bestd = addr;
117 	bestm = VCD_SELF;
118 	if((bestsz = vcsizeu(bestd)) == 1)
119 		goto done;
120 
121 	d = here-addr;
122 	if((sz = vcsizeu(d)) < bestsz)
123 	{	bestd = d;
124 		bestm = VCD_HERE;
125 		if((bestsz = sz) == 1)
126 			goto done;
127 	}
128 
129 	if(ka)
130 	{	for(i = 0; i < ka->s_near; ++i)
131 		{	if((d = addr - ka->c_near[i]) < 0)
132 				continue;
133 			if((sz = vcsizeu(d)) < bestsz)
134 			{	bestd = d;
135 				bestm = (VCD_HERE+1) + i;
136 				if((bestsz = sz) == 1)
137 					goto done;
138 			}
139 		}
140 		if(ka->s_same > 0 && ka->c_same[d = addr%(ka->s_same*256)] == addr)
141 		{	bestd = d%256;
142 			bestm = (VCD_HERE+1) + ka->s_near + d/256;
143 		}
144 	}
145 
146 done:	vcdkaupdate(ka, addr);
147 
148 	*mode = bestm;
149 	return bestd;
150 }
151 
152 
153 #if __STD_C
vcdkagetaddr(Vcdcache_t * ka,Vcio_t * addr,ssize_t here,ssize_t mode)154 ssize_t vcdkagetaddr(Vcdcache_t* ka, Vcio_t* addr, ssize_t here, ssize_t mode)
155 #else
156 ssize_t vcdkagetaddr(ka, addr, here, mode)
157 Vcdcache_t*	ka;
158 Vcio_t*		addr;
159 ssize_t		here;
160 ssize_t		mode;
161 #endif
162 {
163 	ssize_t	a, m;
164 
165 	if(mode == VCD_SELF)
166 		a = vciogetu(addr);
167 	else if(mode == VCD_HERE)
168 		a = here - vciogetu(addr);
169 	else if(ka)
170 	{	if((m = mode - (VCD_HERE+1)) >= 0 && m < ka->s_near)
171 			a = ka->c_near[m] + vciogetu(addr);
172 		else if((m = mode - (VCD_HERE+1+ka->s_near)) >= 0 && m < ka->s_same)
173 			a = ka->c_same[vciogetc(addr) + m*256];
174 		else	return -1;
175 	}
176 	else	return -1;
177 
178 	vcdkaupdate(ka, a);
179 	return a;
180 }
181