Initial revision
diff --git a/src/lib9/u64.c b/src/lib9/u64.c
new file mode 100644
index 0000000..a17bdf1
--- /dev/null
+++ b/src/lib9/u64.c
@@ -0,0 +1,126 @@
+#include <lib9.h>
+
+enum {
+	INVAL=	255
+};
+
+static uchar t64d[256] = {
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,   62,INVAL,INVAL,INVAL,   63,
+      52,   53,   54,   55,   56,   57,   58,   59,   60,   61,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,    0,    1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,
+      15,   16,   17,   18,   19,   20,   21,   22,   23,   24,   25,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,   26,   27,   28,   29,   30,   31,   32,   33,   34,   35,   36,   37,   38,   39,   40,
+      41,   42,   43,   44,   45,   46,   47,   48,   49,   50,   51,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL
+};
+static char t64e[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+int
+dec64(uchar *out, int lim, char *in, int n)
+{
+	ulong b24;
+	uchar *start = out;
+	uchar *e = out + lim;
+	int i, c;
+
+	b24 = 0;
+	i = 0;
+	while(n-- > 0){
+ 
+		c = t64d[*(uchar*)in++];
+		if(c == INVAL)
+			continue;
+		switch(i){
+		case 0:
+			b24 = c<<18;
+			break;
+		case 1:
+			b24 |= c<<12;
+			break;
+		case 2:
+			b24 |= c<<6;
+			break;
+		case 3:
+			if(out + 3 > e)
+				goto exhausted;
+
+			b24 |= c;
+			*out++ = b24>>16;
+			*out++ = b24>>8;
+			*out++ = b24;
+			i = -1;
+			break;
+		}
+		i++;
+	}
+	switch(i){
+	case 2:
+		if(out + 1 > e)
+			goto exhausted;
+		*out++ = b24>>16;
+		break;
+	case 3:
+		if(out + 2 > e)
+			goto exhausted;
+		*out++ = b24>>16;
+		*out++ = b24>>8;
+		break;
+	}
+exhausted:
+	return out - start;
+}
+
+int
+enc64(char *out, int lim, uchar *in, int n)
+{
+	int i;
+	ulong b24;
+	char *start = out;
+	char *e = out + lim;
+
+	for(i = n/3; i > 0; i--){
+		b24 = (*in++)<<16;
+		b24 |= (*in++)<<8;
+		b24 |= *in++;
+		if(out + 4 >= e)
+			goto exhausted;
+		*out++ = t64e[(b24>>18)];
+		*out++ = t64e[(b24>>12)&0x3f];
+		*out++ = t64e[(b24>>6)&0x3f];
+		*out++ = t64e[(b24)&0x3f];
+	}
+
+	switch(n%3){
+	case 2:
+		b24 = (*in++)<<16;
+		b24 |= (*in)<<8;
+		if(out + 4 >= e)
+			goto exhausted;
+		*out++ = t64e[(b24>>18)];
+		*out++ = t64e[(b24>>12)&0x3f];
+		*out++ = t64e[(b24>>6)&0x3f];
+		*out++ = '=';
+		break;
+	case 1:
+		b24 = (*in)<<16;
+		if(out + 4 >= e)
+			goto exhausted;
+		*out++ = t64e[(b24>>18)];
+		*out++ = t64e[(b24>>12)&0x3f];
+		*out++ = '=';
+		*out++ = '=';
+		break;
+	}
+exhausted:
+	*out = 0;
+	return out - start;
+}