/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 2003-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* http://www.eclipse.org/org/documents/epl-v10.html *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Phong Vo <kpv@research.att.com> *
* *
***********************************************************************/
#include "vcdhdr.h"
/* Functions to encode/decode COPY addresses based on the caches.
**
** Written by Kiem-Phong Vo (kpv@research.att.com)
*/
#if __STD_C
void vcdkaclose(Vcdcache_t* ka)
#else
void vcdkaclose(ka)
Vcdcache_t* ka;
#endif
{
if(ka)
free(ka);
}
/* initialize address caches */
#if __STD_C
Vcdcache_t* vcdkaopen(ssize_t s_near, ssize_t s_same)
#else
Vcdcache_t* vcdkaopen(s_near, s_same)
ssize_t s_near;
ssize_t s_same;
#endif
{
Vcdcache_t* ka;
ssize_t sz;
sz = sizeof(Vcdcache_t) + s_near*sizeof(ssize_t) + s_same*256*sizeof(ssize_t);
if(!(ka = (Vcdcache_t*)calloc(1,sz)) )
return NIL(Vcdcache_t*);
ka->c_same = ka->c_near = NIL(ssize_t*);
if((ka->s_near = s_near) > 0)
ka->c_near = (ssize_t*)(ka+1);
if((ka->s_same = s_same) > 0)
ka->c_same = ((ssize_t*)(ka+1)) + s_near;
return ka;
}
#if __STD_C
void vcdkaclear(Vcdcache_t* ka)
#else
void vcdkaclear(ka)
Vcdcache_t* ka;
#endif
{
ssize_t i;
if(ka)
{ for(i = 0; i < ka->s_near; ++i)
ka->c_near[i] = 0;
ka->n = 0;
for(i = 0; i < ka->s_same*256; ++i)
ka->c_same[i] = 0;
}
}
/* update address caches */
#if __STD_C
static void vcdkaupdate(Vcdcache_t* ka, ssize_t addr)
#else
static void vcdkaupdate(ka, addr)
Vcdcache_t* ka;
ssize_t addr;
#endif
{
if(ka)
{ if(ka->s_near > 0)
{ ka->c_near[ka->n] = addr;
if((ka->n += 1) >= ka->s_near)
ka->n = 0;
}
if(ka->s_same > 0)
ka->c_same[addr % (ka->s_same*256)] = addr;
}
}
/* compute encoding for COPY addresses */
#if __STD_C
ssize_t vcdkasetaddr(Vcdcache_t* ka, ssize_t addr, ssize_t here, ssize_t* mode)
#else
ssize_t vcdkasetaddr(ka, addr, here, mode)
Vcdcache_t* ka;
ssize_t addr; /* matching address to be encoded */
ssize_t here; /* current location */
ssize_t* mode; /* to return the coded address */
#endif
{
ssize_t i, d, sz, bestd, bestm, bestsz;
bestd = addr;
bestm = VCD_SELF;
if((bestsz = vcsizeu(bestd)) == 1)
goto done;
d = here-addr;
if((sz = vcsizeu(d)) < bestsz)
{ bestd = d;
bestm = VCD_HERE;
if((bestsz = sz) == 1)
goto done;
}
if(ka)
{ for(i = 0; i < ka->s_near; ++i)
{ if((d = addr - ka->c_near[i]) < 0)
continue;
if((sz = vcsizeu(d)) < bestsz)
{ bestd = d;
bestm = (VCD_HERE+1) + i;
if((bestsz = sz) == 1)
goto done;
}
}
if(ka->s_same > 0 && ka->c_same[d = addr%(ka->s_same*256)] == addr)
{ bestd = d%256;
bestm = (VCD_HERE+1) + ka->s_near + d/256;
}
}
done: vcdkaupdate(ka, addr);
*mode = bestm;
return bestd;
}
#if __STD_C
ssize_t vcdkagetaddr(Vcdcache_t* ka, Vcio_t* addr, ssize_t here, ssize_t mode)
#else
ssize_t vcdkagetaddr(ka, addr, here, mode)
Vcdcache_t* ka;
Vcio_t* addr;
ssize_t here;
ssize_t mode;
#endif
{
ssize_t a, m;
if(mode == VCD_SELF)
a = vciogetu(addr);
else if(mode == VCD_HERE)
a = here - vciogetu(addr);
else if(ka)
{ if((m = mode - (VCD_HERE+1)) >= 0 && m < ka->s_near)
a = ka->c_near[m] + vciogetu(addr);
else if((m = mode - (VCD_HERE+1+ka->s_near)) >= 0 && m < ka->s_same)
a = ka->c_same[vciogetc(addr) + m*256];
else return -1;
}
else return -1;
vcdkaupdate(ka, a);
return a;
}