Index: generic/src/cpu/cpu.c
===================================================================
--- generic/src/cpu/cpu.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/cpu/cpu.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cpu.h>
+#include <arch.h>
+#include <arch/cpu.h>
+#include <mm/heap.h>
+#include <mm/page.h>
+#include <mm/frame.h>
+#include <arch/types.h>
+#include <config.h>
+#include <panic.h>
+#include <typedefs.h>
+#include <memstr.h>
+#include <list.h>
+
+cpu_t *cpus;
+
+/** Initialize CPUs
+ *
+ * Initialize kernel CPUs support.
+ *
+ */
+void cpu_init(void) {
+	int i, j;
+	
+	#ifdef __SMP__
+	if (config.cpu_active == 1) {
+	#endif /* __SMP__ */
+		cpus = (cpu_t *) malloc(sizeof(cpu_t) * config.cpu_count);
+		if (!cpus)
+			panic("malloc/cpus");
+
+		/* initialize everything */
+		memsetb((__address) cpus, sizeof(cpu_t) * config.cpu_count, 0);
+
+		for (i=0; i < config.cpu_count; i++) {
+			cpus[i].stack = (__u8 *) frame_alloc(FRAME_KA | FRAME_PANIC);
+			if (!cpus[i].stack)
+				panic("malloc/cpus[%d].stack\n", i);
+			
+			cpus[i].id = i;
+			
+			#ifdef __SMP__
+			waitq_initialize(&cpus[i].kcpulb_wq);
+			#endif /* __SMP */
+			
+			for (j = 0; j < RQ_COUNT; j++) {
+				list_initialize(&cpus[i].rq[j].rq_head);
+			}
+		}
+		
+	#ifdef __SMP__
+	}
+	#endif /* __SMP__ */
+
+	CPU = &cpus[config.cpu_active-1];
+	
+	CPU->active = 1;
+	CPU->tlb_active = 1;
+	
+	cpu_identify();
+	cpu_arch_init();
+}
Index: generic/src/debug/print.c
===================================================================
--- generic/src/debug/print.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/debug/print.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <putchar.h>
+#include <print.h>
+#include <synch/spinlock.h>
+#include <arch/arg.h>
+#include <arch/asm.h>
+#include <arch/fmath.h>
+
+#include <arch.h>
+
+static char digits[] = "0123456789abcdef"; /**< Hexadecimal characters */
+static spinlock_t printflock;              /**< printf spinlock */
+
+#define DEFAULT_DOUBLE_PRECISION 16
+#define DEFAULT_DOUBLE_BUFFER_SIZE 128
+
+void print_double(double num, __u8 modifier, __u16 precision) 
+{
+	double intval,intval2;
+	int counter;
+	int exponent,exponenttmp;
+	unsigned char buf[DEFAULT_DOUBLE_BUFFER_SIZE];
+	unsigned long in1,in2;	
+	
+
+	if (fmath_is_nan(num)) {
+		print_str("NaN");
+		return;
+	}
+	
+	if (num<0.0) {
+		putchar('-');
+		num=num*-1.0;
+	}
+
+
+	if (fmath_is_infinity(num)) {
+		print_str("Inf");
+		return;
+	}
+
+	if ((modifier=='E')||(modifier=='e')) {
+		intval2=fmath_fint(fmath_get_decimal_exponent(num),&intval);
+		exponent=intval;
+		if ((intval2<0.0)) exponent--;
+		num = num / ((fmath_dpow(10.0,exponent)));
+		
+		print_double(num,modifier+1,precision); /* modifier+1 = E => F or e => f */
+		putchar(modifier);
+		if (exponent<0) {
+			putchar('-');
+			exponent*=-1;
+		}
+		print_number(exponent,10);
+		return;
+	}
+		
+	/* TODO: rounding constant - when we got fraction >= 0.5, we must increment last printed number */
+
+	/* 
+	 * Here is a problem with cumulative error while printing big double values -> we will divide
+	 * the number with a power of 10, print new number with better method for small numbers and
+	 * then print decimal point at correct position.
+	 */
+	
+	fmath_fint(fmath_get_decimal_exponent(num),&intval);
+	
+	exponent=(intval>0.0?intval:0);
+	
+	precision+=exponent;
+	
+	if (exponent>0) num = num / ((fmath_dpow(10.0,exponent)));
+		
+	num=fmath_fint(num,&intval);
+	
+	if (precision>0) {
+		counter=precision-1;
+		if (exponent>0) counter++;
+		
+		if (counter>=DEFAULT_DOUBLE_BUFFER_SIZE) {
+			counter=DEFAULT_DOUBLE_BUFFER_SIZE;
+		}
+		exponenttmp=exponent;
+		while(counter>=0) {
+			num *= 10.0;
+			num = fmath_fint(num,&intval2);
+			buf[counter--]=((int)intval2)+'0';
+			exponenttmp--;
+			if ((exponenttmp==0)&&(counter>=0)) buf[counter--]='.';
+		}
+		counter=precision;
+		if ((exponent==0)&&(counter<DEFAULT_DOUBLE_BUFFER_SIZE)) buf[counter]='.';
+		counter++;	
+	} else {
+		counter=0;	
+	}
+	
+	in1=intval;
+	if (in1==0.0) {
+		if (counter<DEFAULT_DOUBLE_BUFFER_SIZE) buf[counter++]='0';
+	} else {
+		while(( in1>0 )&&(counter<DEFAULT_DOUBLE_BUFFER_SIZE)) {
+			
+			in2=in1;
+			in1/=10;
+			buf[counter]=in2-in1*10 + '0';
+			counter++;
+		}
+	}
+	
+	counter = (counter>=DEFAULT_DOUBLE_BUFFER_SIZE?DEFAULT_DOUBLE_BUFFER_SIZE:counter);
+	while (counter>0) {
+		putchar(buf[--counter]);
+	}
+	return;
+}
+
+/** Print NULL terminated string
+ *
+ * Print characters from str using putchar() until
+ * \\0 character is reached.
+ *
+ * @param str Characters to print.
+ *
+ */
+void print_str(const char *str)
+{
+	int i = 0;
+	char c;
+	
+	while (c = str[i++])
+		putchar(c);
+}
+
+
+/** Print hexadecimal digits
+ *
+ * Print fixed count of hexadecimal digits from
+ * the number num. The digits are printed in
+ * natural left-to-right order starting with
+ * the width-th digit.
+ *
+ * @param num   Number containing digits.
+ * @param width Count of digits to print.
+ *
+ */
+void print_fixed_hex(const __u64 num, const int width)
+{
+	int i;
+    
+	for (i = width*8 - 4; i >= 0; i -= 4)
+	    putchar(digits[(num>>i) & 0xf]);
+}
+
+
+/** Print number in given base
+ *
+ * Print significant digits of a number in given
+ * base.
+ *
+ * @param num  Number to print.
+ * @param base Base to print the number in (should
+ *             be in range 2 .. 16).
+ *
+ */
+void print_number(const __native num, const unsigned int base)
+{
+	int val = num;
+	char d[sizeof(__native)*8+1];		/* this is good enough even for base == 2 */
+	int i = sizeof(__native)*8-1;
+	
+	do {
+		d[i--] = digits[val % base];
+	} while (val /= base);
+	
+	d[sizeof(__native)*8] = 0;	
+	print_str(&d[i + 1]);
+}
+
+
+/** General formatted text print
+ *
+ * Print text formatted according the fmt parameter
+ * and variant arguments. Each formatting directive
+ * begins with \% (percentage) character and one of the
+ * following character:
+ *
+ * \%    Prints the percentage character.
+ *
+ * s    The next variant argument is treated as char*
+ *      and printed as a NULL terminated string.
+ *
+ * c    The next variant argument is treated as a single char.
+ *
+ * p    The next variant argument is treated as a maximum
+ *      bit-width integer with respect to architecture
+ *      and printed in full hexadecimal width.
+ *
+ * P    As with 'p', but '0x' is prefixed.
+ *
+ * q    The next variant argument is treated as a 64b integer
+ *      and printed in full hexadecimal width.
+ *
+ * Q    As with 'q', but '0x' is prefixed.
+ *
+ * l    The next variant argument is treated as a 32b integer
+ *      and printed in full hexadecimal width.
+ *
+ * L    As with 'l', but '0x' is prefixed.
+ *
+ * w    The next variant argument is treated as a 16b integer
+ *      and printed in full hexadecimal width.
+ *
+ * W    As with 'w', but '0x' is prefixed.
+ *
+ * b    The next variant argument is treated as a 8b integer
+ *      and printed in full hexadecimal width.
+ *
+ * B    As with 'b', but '0x' is prefixed.
+ *
+ * d    The next variant argument is treated as integer
+ *      and printed in standard decimal format (only significant
+ *      digits).
+ *
+ * x    The next variant argument is treated as integer
+ *      and printed in standard hexadecimal format (only significant
+ *      digits).
+ *
+ * X    As with 'x', but '0x' is prefixed.
+ *
+ * .    The decimal number following period will be treated as precision
+ *      for printing floating point numbers. One of 'e', 'E', 'f' or 'F'
+ *      must follow.
+ *
+ * e    The next variant argument is treated as double precision float
+ *      and printed in exponent notation with only one digit before decimal point
+ *      in specified precision. The exponent sign is printed as 'e'.
+ *
+ * E    As with 'e', but the exponent sign is printed as 'E'.
+ *
+ * f    The next variant argument is treated as double precision float
+ *      and printed in decimal notation in specified precision.
+ *
+ * F    As with 'f'.
+ *
+ * All other characters from fmt except the formatting directives
+ * are printed in verbatim.
+ *
+ * @param fmt Formatting NULL terminated string.
+ */
+void printf(const char *fmt, ...)
+{
+	int irqpri, i = 0;
+	va_list ap;
+	char c;	
+	
+	__u16 precision;
+	
+	va_start(ap, fmt);
+
+	irqpri = interrupts_disable();
+	spinlock_lock(&printflock);
+
+	while (c = fmt[i++]) {
+		switch (c) {
+
+		    /* control character */
+		    case '%':
+			precision = DEFAULT_DOUBLE_PRECISION;
+			if (fmt[i]=='.') {
+				precision=0;
+				c=fmt[++i];
+				while((c>='0')&&(c<='9')) {
+					precision = precision*10 + c - '0';
+					c=fmt[++i];
+				}
+			}
+		    
+			switch (c = fmt[i++]) {
+
+			    /* percentile itself */
+			    case '%':
+				break;
+
+			    /*
+			     * String and character conversions.
+			     */
+			    case 's':
+				print_str(va_arg(ap, char_ptr));
+				goto loop;
+
+			    case 'c':
+				c = (char) va_arg(ap, int);
+				break;
+
+			    /*
+		             * Hexadecimal conversions with fixed width.
+		             */
+			    case 'P': 
+				print_str("0x");
+			    case 'p':
+	    			print_fixed_hex(va_arg(ap, __native), sizeof(__native));
+				goto loop;
+
+			    case 'Q': 
+				print_str("0x");
+			    case 'q':
+		    		print_fixed_hex(va_arg(ap, __u64), INT64);
+				goto loop;
+
+			    case 'L': 
+				print_str("0x");
+			    case 'l':
+		    		print_fixed_hex(va_arg(ap, __native), INT32);
+				goto loop;
+
+			    case 'W':
+				print_str("0x");
+			    case 'w':
+		    		print_fixed_hex(va_arg(ap, __native), INT16);
+				goto loop;
+
+			    case 'B':
+				print_str("0x");
+			    case 'b':
+		    		print_fixed_hex(va_arg(ap, __native), INT8);
+				goto loop;
+
+			    /*
+		             * Floating point conversions.
+		             */
+			    case 'F':
+		    		print_double(va_arg(ap, double),'F',precision);
+				goto loop;
+					
+			    case 'f':
+		    		print_double(va_arg(ap, double),'f',precision);
+				goto loop;
+				
+			    case 'E':
+		    		print_double(va_arg(ap, double),'E',precision);
+				goto loop;
+			    case 'e':
+		    		print_double(va_arg(ap, double),'e',precision);
+				goto loop;
+				
+			    /*
+		             * Decimal and hexadecimal conversions.
+		             */
+			    case 'd':
+		    		print_number(va_arg(ap, __native), 10);
+				goto loop;
+
+			    case 'X':
+				print_str("0x");
+			    case 'x':
+		    		print_number(va_arg(ap, __native), 16);
+				goto loop;
+	    
+			    /*
+			     * Bad formatting.
+			     */
+			    default:
+				goto out;
+			}
+
+		    default: putchar(c);
+		}
+	
+loop:
+		;
+	}
+
+out:
+	spinlock_unlock(&printflock);
+	interrupts_restore(irqpri);
+	
+	va_end(ap);
+}
Index: generic/src/debug/symtab.c
===================================================================
--- generic/src/debug/symtab.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/debug/symtab.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2005 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <symtab.h>
+#include <typedefs.h>
+#include <arch/byteorder.h>
+
+/** Return entry that seems most likely to correspond to address
+ *
+ * Return entry that seems most likely to correspond
+ * to address passed in the argument.
+ *
+ * @param addr Address.
+ *
+ * @return Pointer to respective symbol string on success, NULL otherwise.
+ */
+char * get_symtab_entry(__native addr)
+{
+	count_t i;
+
+	for (i=1;symbol_table[i].address_le;++i) {
+		if (addr < __u64_le2host(symbol_table[i].address_le))
+			break;
+	}
+	if (addr >= __u64_le2host(symbol_table[i-1].address_le))
+		return symbol_table[i-1].symbol_name;
+	return NULL;
+}
Index: generic/src/fb/font-8x16.c
===================================================================
--- generic/src/fb/font-8x16.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/fb/font-8x16.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,4642 @@
+/*
+ * Copyright (C) 2005 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <fb/font-8x16.h>
+
+unsigned char fb_font[FONT_GLIPHS * FONT_SCANLINES] = {
+
+	/* 0 0x00 '^@' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 1 0x01 '^A' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7e, /* 01111110 */
+	0x81, /* 10000001 */
+	0xa5, /* 10100101 */
+	0x81, /* 10000001 */
+	0x81, /* 10000001 */
+	0xbd, /* 10111101 */
+	0x99, /* 10011001 */
+	0x81, /* 10000001 */
+	0x81, /* 10000001 */
+	0x7e, /* 01111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 2 0x02 '^B' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7e, /* 01111110 */
+	0xff, /* 11111111 */
+	0xdb, /* 11011011 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xc3, /* 11000011 */
+	0xe7, /* 11100111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0x7e, /* 01111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 3 0x03 '^C' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x6c, /* 01101100 */
+	0xfe, /* 11111110 */
+	0xfe, /* 11111110 */
+	0xfe, /* 11111110 */
+	0xfe, /* 11111110 */
+	0x7c, /* 01111100 */
+	0x38, /* 00111000 */
+	0x10, /* 00010000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 4 0x04 '^D' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x10, /* 00010000 */
+	0x38, /* 00111000 */
+	0x7c, /* 01111100 */
+	0xfe, /* 11111110 */
+	0x7c, /* 01111100 */
+	0x38, /* 00111000 */
+	0x10, /* 00010000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 5 0x05 '^E' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x3c, /* 00111100 */
+	0xe7, /* 11100111 */
+	0xe7, /* 11100111 */
+	0xe7, /* 11100111 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 6 0x06 '^F' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x7e, /* 01111110 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0x7e, /* 01111110 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 7 0x07 '^G' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x3c, /* 00111100 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 8 0x08 '^H' */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xe7, /* 11100111 */
+	0xc3, /* 11000011 */
+	0xc3, /* 11000011 */
+	0xe7, /* 11100111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+
+	/* 9 0x09 '^I' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x3c, /* 00111100 */
+	0x66, /* 01100110 */
+	0x42, /* 01000010 */
+	0x42, /* 01000010 */
+	0x66, /* 01100110 */
+	0x3c, /* 00111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 10 0x0a '^J' */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xc3, /* 11000011 */
+	0x99, /* 10011001 */
+	0xbd, /* 10111101 */
+	0xbd, /* 10111101 */
+	0x99, /* 10011001 */
+	0xc3, /* 11000011 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+
+	/* 11 0x0b '^K' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x1e, /* 00011110 */
+	0x0e, /* 00001110 */
+	0x1a, /* 00011010 */
+	0x32, /* 00110010 */
+	0x78, /* 01111000 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0x78, /* 01111000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 12 0x0c '^L' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x3c, /* 00111100 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x3c, /* 00111100 */
+	0x18, /* 00011000 */
+	0x7e, /* 01111110 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 13 0x0d '^M' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x3f, /* 00111111 */
+	0x33, /* 00110011 */
+	0x3f, /* 00111111 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x70, /* 01110000 */
+	0xf0, /* 11110000 */
+	0xe0, /* 11100000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 14 0x0e '^N' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7f, /* 01111111 */
+	0x63, /* 01100011 */
+	0x7f, /* 01111111 */
+	0x63, /* 01100011 */
+	0x63, /* 01100011 */
+	0x63, /* 01100011 */
+	0x63, /* 01100011 */
+	0x67, /* 01100111 */
+	0xe7, /* 11100111 */
+	0xe6, /* 11100110 */
+	0xc0, /* 11000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 15 0x0f '^O' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0xdb, /* 11011011 */
+	0x3c, /* 00111100 */
+	0xe7, /* 11100111 */
+	0x3c, /* 00111100 */
+	0xdb, /* 11011011 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 16 0x10 '^P' */
+	0x00, /* 00000000 */
+	0x80, /* 10000000 */
+	0xc0, /* 11000000 */
+	0xe0, /* 11100000 */
+	0xf0, /* 11110000 */
+	0xf8, /* 11111000 */
+	0xfe, /* 11111110 */
+	0xf8, /* 11111000 */
+	0xf0, /* 11110000 */
+	0xe0, /* 11100000 */
+	0xc0, /* 11000000 */
+	0x80, /* 10000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 17 0x11 '^Q' */
+	0x00, /* 00000000 */
+	0x02, /* 00000010 */
+	0x06, /* 00000110 */
+	0x0e, /* 00001110 */
+	0x1e, /* 00011110 */
+	0x3e, /* 00111110 */
+	0xfe, /* 11111110 */
+	0x3e, /* 00111110 */
+	0x1e, /* 00011110 */
+	0x0e, /* 00001110 */
+	0x06, /* 00000110 */
+	0x02, /* 00000010 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 18 0x12 '^R' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x7e, /* 01111110 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x7e, /* 01111110 */
+	0x3c, /* 00111100 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 19 0x13 '^S' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x00, /* 00000000 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 20 0x14 '^T' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7f, /* 01111111 */
+	0xdb, /* 11011011 */
+	0xdb, /* 11011011 */
+	0xdb, /* 11011011 */
+	0x7b, /* 01111011 */
+	0x1b, /* 00011011 */
+	0x1b, /* 00011011 */
+	0x1b, /* 00011011 */
+	0x1b, /* 00011011 */
+	0x1b, /* 00011011 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 21 0x15 '^U' */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0x60, /* 01100000 */
+	0x38, /* 00111000 */
+	0x6c, /* 01101100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x6c, /* 01101100 */
+	0x38, /* 00111000 */
+	0x0c, /* 00001100 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 22 0x16 '^V' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfe, /* 11111110 */
+	0xfe, /* 11111110 */
+	0xfe, /* 11111110 */
+	0xfe, /* 11111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 23 0x17 '^W' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x7e, /* 01111110 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x7e, /* 01111110 */
+	0x3c, /* 00111100 */
+	0x18, /* 00011000 */
+	0x7e, /* 01111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 24 0x18 '^X' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x7e, /* 01111110 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 25 0x19 '^Y' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x7e, /* 01111110 */
+	0x3c, /* 00111100 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 26 0x1a '^Z' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x0c, /* 00001100 */
+	0xfe, /* 11111110 */
+	0x0c, /* 00001100 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 27 0x1b '^[' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x30, /* 00110000 */
+	0x60, /* 01100000 */
+	0xfe, /* 11111110 */
+	0x60, /* 01100000 */
+	0x30, /* 00110000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 28 0x1c '^\' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xfe, /* 11111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 29 0x1d '^]' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x28, /* 00101000 */
+	0x6c, /* 01101100 */
+	0xfe, /* 11111110 */
+	0x6c, /* 01101100 */
+	0x28, /* 00101000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 30 0x1e '^^' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x10, /* 00010000 */
+	0x38, /* 00111000 */
+	0x38, /* 00111000 */
+	0x7c, /* 01111100 */
+	0x7c, /* 01111100 */
+	0xfe, /* 11111110 */
+	0xfe, /* 11111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 31 0x1f '^_' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfe, /* 11111110 */
+	0xfe, /* 11111110 */
+	0x7c, /* 01111100 */
+	0x7c, /* 01111100 */
+	0x38, /* 00111000 */
+	0x38, /* 00111000 */
+	0x10, /* 00010000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 32 0x20 ' ' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 33 0x21 '!' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x3c, /* 00111100 */
+	0x3c, /* 00111100 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 34 0x22 '"' */
+	0x00, /* 00000000 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x24, /* 00100100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 35 0x23 '#' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x6c, /* 01101100 */
+	0x6c, /* 01101100 */
+	0xfe, /* 11111110 */
+	0x6c, /* 01101100 */
+	0x6c, /* 01101100 */
+	0x6c, /* 01101100 */
+	0xfe, /* 11111110 */
+	0x6c, /* 01101100 */
+	0x6c, /* 01101100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 36 0x24 '$' */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xc2, /* 11000010 */
+	0xc0, /* 11000000 */
+	0x7c, /* 01111100 */
+	0x06, /* 00000110 */
+	0x06, /* 00000110 */
+	0x86, /* 10000110 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 37 0x25 '%' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xc2, /* 11000010 */
+	0xc6, /* 11000110 */
+	0x0c, /* 00001100 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x60, /* 01100000 */
+	0xc6, /* 11000110 */
+	0x86, /* 10000110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 38 0x26 '&' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x38, /* 00111000 */
+	0x6c, /* 01101100 */
+	0x6c, /* 01101100 */
+	0x38, /* 00111000 */
+	0x76, /* 01110110 */
+	0xdc, /* 11011100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0x76, /* 01110110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 39 0x27 ''' */
+	0x00, /* 00000000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x60, /* 01100000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 40 0x28 '(' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x0c, /* 00001100 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x18, /* 00011000 */
+	0x0c, /* 00001100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 41 0x29 ')' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x30, /* 00110000 */
+	0x18, /* 00011000 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 42 0x2a '*' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x66, /* 01100110 */
+	0x3c, /* 00111100 */
+	0xff, /* 11111111 */
+	0x3c, /* 00111100 */
+	0x66, /* 01100110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 43 0x2b '+' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x7e, /* 01111110 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 44 0x2c ',' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 45 0x2d '-' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfe, /* 11111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 46 0x2e '.' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 47 0x2f '/' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x02, /* 00000010 */
+	0x06, /* 00000110 */
+	0x0c, /* 00001100 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x60, /* 01100000 */
+	0xc0, /* 11000000 */
+	0x80, /* 10000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 48 0x30 '0' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x38, /* 00111000 */
+	0x6c, /* 01101100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xd6, /* 11010110 */
+	0xd6, /* 11010110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x6c, /* 01101100 */
+	0x38, /* 00111000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 49 0x31 '1' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x38, /* 00111000 */
+	0x78, /* 01111000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x7e, /* 01111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 50 0x32 '2' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0x06, /* 00000110 */
+	0x0c, /* 00001100 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x60, /* 01100000 */
+	0xc0, /* 11000000 */
+	0xc6, /* 11000110 */
+	0xfe, /* 11111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 51 0x33 '3' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0x06, /* 00000110 */
+	0x06, /* 00000110 */
+	0x3c, /* 00111100 */
+	0x06, /* 00000110 */
+	0x06, /* 00000110 */
+	0x06, /* 00000110 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 52 0x34 '4' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x0c, /* 00001100 */
+	0x1c, /* 00011100 */
+	0x3c, /* 00111100 */
+	0x6c, /* 01101100 */
+	0xcc, /* 11001100 */
+	0xfe, /* 11111110 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x1e, /* 00011110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 53 0x35 '5' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfe, /* 11111110 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xfc, /* 11111100 */
+	0x06, /* 00000110 */
+	0x06, /* 00000110 */
+	0x06, /* 00000110 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 54 0x36 '6' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x38, /* 00111000 */
+	0x60, /* 01100000 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xfc, /* 11111100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 55 0x37 '7' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfe, /* 11111110 */
+	0xc6, /* 11000110 */
+	0x06, /* 00000110 */
+	0x06, /* 00000110 */
+	0x0c, /* 00001100 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 56 0x38 '8' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 57 0x39 '9' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x7e, /* 01111110 */
+	0x06, /* 00000110 */
+	0x06, /* 00000110 */
+	0x06, /* 00000110 */
+	0x0c, /* 00001100 */
+	0x78, /* 01111000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 58 0x3a ':' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 59 0x3b ';' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 60 0x3c '<' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x06, /* 00000110 */
+	0x0c, /* 00001100 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x60, /* 01100000 */
+	0x30, /* 00110000 */
+	0x18, /* 00011000 */
+	0x0c, /* 00001100 */
+	0x06, /* 00000110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 61 0x3d '=' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7e, /* 01111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7e, /* 01111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 62 0x3e '>' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x60, /* 01100000 */
+	0x30, /* 00110000 */
+	0x18, /* 00011000 */
+	0x0c, /* 00001100 */
+	0x06, /* 00000110 */
+	0x0c, /* 00001100 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x60, /* 01100000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 63 0x3f '?' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x0c, /* 00001100 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 64 0x40 '@' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xde, /* 11011110 */
+	0xde, /* 11011110 */
+	0xde, /* 11011110 */
+	0xdc, /* 11011100 */
+	0xc0, /* 11000000 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 65 0x41 'A' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x10, /* 00010000 */
+	0x38, /* 00111000 */
+	0x6c, /* 01101100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xfe, /* 11111110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 66 0x42 'B' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfc, /* 11111100 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x7c, /* 01111100 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0xfc, /* 11111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 67 0x43 'C' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x3c, /* 00111100 */
+	0x66, /* 01100110 */
+	0xc2, /* 11000010 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc2, /* 11000010 */
+	0x66, /* 01100110 */
+	0x3c, /* 00111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 68 0x44 'D' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xf8, /* 11111000 */
+	0x6c, /* 01101100 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x6c, /* 01101100 */
+	0xf8, /* 11111000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 69 0x45 'E' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfe, /* 11111110 */
+	0x66, /* 01100110 */
+	0x62, /* 01100010 */
+	0x68, /* 01101000 */
+	0x78, /* 01111000 */
+	0x68, /* 01101000 */
+	0x60, /* 01100000 */
+	0x62, /* 01100010 */
+	0x66, /* 01100110 */
+	0xfe, /* 11111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 70 0x46 'F' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfe, /* 11111110 */
+	0x66, /* 01100110 */
+	0x62, /* 01100010 */
+	0x68, /* 01101000 */
+	0x78, /* 01111000 */
+	0x68, /* 01101000 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0xf0, /* 11110000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 71 0x47 'G' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x3c, /* 00111100 */
+	0x66, /* 01100110 */
+	0xc2, /* 11000010 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xde, /* 11011110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x66, /* 01100110 */
+	0x3a, /* 00111010 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 72 0x48 'H' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xfe, /* 11111110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 73 0x49 'I' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x3c, /* 00111100 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 74 0x4a 'J' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x1e, /* 00011110 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0x78, /* 01111000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 75 0x4b 'K' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xe6, /* 11100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x6c, /* 01101100 */
+	0x78, /* 01111000 */
+	0x78, /* 01111000 */
+	0x6c, /* 01101100 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0xe6, /* 11100110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 76 0x4c 'L' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xf0, /* 11110000 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0x62, /* 01100010 */
+	0x66, /* 01100110 */
+	0xfe, /* 11111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 77 0x4d 'M' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xc6, /* 11000110 */
+	0xee, /* 11101110 */
+	0xfe, /* 11111110 */
+	0xfe, /* 11111110 */
+	0xd6, /* 11010110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 78 0x4e 'N' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xc6, /* 11000110 */
+	0xe6, /* 11100110 */
+	0xf6, /* 11110110 */
+	0xfe, /* 11111110 */
+	0xde, /* 11011110 */
+	0xce, /* 11001110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 79 0x4f 'O' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 80 0x50 'P' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfc, /* 11111100 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x7c, /* 01111100 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0xf0, /* 11110000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 81 0x51 'Q' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xd6, /* 11010110 */
+	0xde, /* 11011110 */
+	0x7c, /* 01111100 */
+	0x0c, /* 00001100 */
+	0x0e, /* 00001110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 82 0x52 'R' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfc, /* 11111100 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x7c, /* 01111100 */
+	0x6c, /* 01101100 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0xe6, /* 11100110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 83 0x53 'S' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x60, /* 01100000 */
+	0x38, /* 00111000 */
+	0x0c, /* 00001100 */
+	0x06, /* 00000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 84 0x54 'T' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7e, /* 01111110 */
+	0x7e, /* 01111110 */
+	0x5a, /* 01011010 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 85 0x55 'U' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 86 0x56 'V' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x6c, /* 01101100 */
+	0x38, /* 00111000 */
+	0x10, /* 00010000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 87 0x57 'W' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xd6, /* 11010110 */
+	0xd6, /* 11010110 */
+	0xd6, /* 11010110 */
+	0xfe, /* 11111110 */
+	0xee, /* 11101110 */
+	0x6c, /* 01101100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 88 0x58 'X' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x6c, /* 01101100 */
+	0x7c, /* 01111100 */
+	0x38, /* 00111000 */
+	0x38, /* 00111000 */
+	0x7c, /* 01111100 */
+	0x6c, /* 01101100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 89 0x59 'Y' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x3c, /* 00111100 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 90 0x5a 'Z' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfe, /* 11111110 */
+	0xc6, /* 11000110 */
+	0x86, /* 10000110 */
+	0x0c, /* 00001100 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x60, /* 01100000 */
+	0xc2, /* 11000010 */
+	0xc6, /* 11000110 */
+	0xfe, /* 11111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 91 0x5b '[' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x3c, /* 00111100 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x3c, /* 00111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 92 0x5c '\' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x80, /* 10000000 */
+	0xc0, /* 11000000 */
+	0xe0, /* 11100000 */
+	0x70, /* 01110000 */
+	0x38, /* 00111000 */
+	0x1c, /* 00011100 */
+	0x0e, /* 00001110 */
+	0x06, /* 00000110 */
+	0x02, /* 00000010 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 93 0x5d ']' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x3c, /* 00111100 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x3c, /* 00111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 94 0x5e '^' */
+	0x10, /* 00010000 */
+	0x38, /* 00111000 */
+	0x6c, /* 01101100 */
+	0xc6, /* 11000110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 95 0x5f '_' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xff, /* 11111111 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 96 0x60 '`' */
+	0x00, /* 00000000 */
+	0x30, /* 00110000 */
+	0x18, /* 00011000 */
+	0x0c, /* 00001100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 97 0x61 'a' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x78, /* 01111000 */
+	0x0c, /* 00001100 */
+	0x7c, /* 01111100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0x76, /* 01110110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 98 0x62 'b' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xe0, /* 11100000 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0x78, /* 01111000 */
+	0x6c, /* 01101100 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 99 0x63 'c' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 100 0x64 'd' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x1c, /* 00011100 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x3c, /* 00111100 */
+	0x6c, /* 01101100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0x76, /* 01110110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 101 0x65 'e' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xfe, /* 11111110 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 102 0x66 'f' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x1c, /* 00011100 */
+	0x36, /* 00110110 */
+	0x32, /* 00110010 */
+	0x30, /* 00110000 */
+	0x78, /* 01111000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x78, /* 01111000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 103 0x67 'g' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x76, /* 01110110 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0x7c, /* 01111100 */
+	0x0c, /* 00001100 */
+	0xcc, /* 11001100 */
+	0x78, /* 01111000 */
+	0x00, /* 00000000 */
+
+	/* 104 0x68 'h' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xe0, /* 11100000 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0x6c, /* 01101100 */
+	0x76, /* 01110110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0xe6, /* 11100110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 105 0x69 'i' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x38, /* 00111000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 106 0x6a 'j' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x06, /* 00000110 */
+	0x06, /* 00000110 */
+	0x00, /* 00000000 */
+	0x0e, /* 00001110 */
+	0x06, /* 00000110 */
+	0x06, /* 00000110 */
+	0x06, /* 00000110 */
+	0x06, /* 00000110 */
+	0x06, /* 00000110 */
+	0x06, /* 00000110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x3c, /* 00111100 */
+	0x00, /* 00000000 */
+
+	/* 107 0x6b 'k' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xe0, /* 11100000 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0x66, /* 01100110 */
+	0x6c, /* 01101100 */
+	0x78, /* 01111000 */
+	0x78, /* 01111000 */
+	0x6c, /* 01101100 */
+	0x66, /* 01100110 */
+	0xe6, /* 11100110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 108 0x6c 'l' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x38, /* 00111000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 109 0x6d 'm' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xec, /* 11101100 */
+	0xfe, /* 11111110 */
+	0xd6, /* 11010110 */
+	0xd6, /* 11010110 */
+	0xd6, /* 11010110 */
+	0xd6, /* 11010110 */
+	0xc6, /* 11000110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 110 0x6e 'n' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xdc, /* 11011100 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 111 0x6f 'o' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 112 0x70 'p' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xdc, /* 11011100 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x7c, /* 01111100 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0xf0, /* 11110000 */
+	0x00, /* 00000000 */
+
+	/* 113 0x71 'q' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x76, /* 01110110 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0x7c, /* 01111100 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x1e, /* 00011110 */
+	0x00, /* 00000000 */
+
+	/* 114 0x72 'r' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xdc, /* 11011100 */
+	0x76, /* 01110110 */
+	0x66, /* 01100110 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0xf0, /* 11110000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 115 0x73 's' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0x60, /* 01100000 */
+	0x38, /* 00111000 */
+	0x0c, /* 00001100 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 116 0x74 't' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x10, /* 00010000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0xfc, /* 11111100 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x36, /* 00110110 */
+	0x1c, /* 00011100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 117 0x75 'u' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0x76, /* 01110110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 118 0x76 'v' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x6c, /* 01101100 */
+	0x38, /* 00111000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 119 0x77 'w' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xd6, /* 11010110 */
+	0xd6, /* 11010110 */
+	0xd6, /* 11010110 */
+	0xfe, /* 11111110 */
+	0x6c, /* 01101100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 120 0x78 'x' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xc6, /* 11000110 */
+	0x6c, /* 01101100 */
+	0x38, /* 00111000 */
+	0x38, /* 00111000 */
+	0x38, /* 00111000 */
+	0x6c, /* 01101100 */
+	0xc6, /* 11000110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 121 0x79 'y' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x7e, /* 01111110 */
+	0x06, /* 00000110 */
+	0x0c, /* 00001100 */
+	0xf8, /* 11111000 */
+	0x00, /* 00000000 */
+
+	/* 122 0x7a 'z' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfe, /* 11111110 */
+	0xcc, /* 11001100 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x60, /* 01100000 */
+	0xc6, /* 11000110 */
+	0xfe, /* 11111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 123 0x7b '{' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x0e, /* 00001110 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x70, /* 01110000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x0e, /* 00001110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 124 0x7c '|' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 125 0x7d '}' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x70, /* 01110000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x0e, /* 00001110 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x70, /* 01110000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 126 0x7e '~' */
+	0x00, /* 00000000 */
+	0x76, /* 01110110 */
+	0xdc, /* 11011100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 127 0x7f '' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x10, /* 00010000 */
+	0x38, /* 00111000 */
+	0x6c, /* 01101100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xfe, /* 11111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 128 0x80 '' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x3c, /* 00111100 */
+	0x66, /* 01100110 */
+	0xc2, /* 11000010 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc2, /* 11000010 */
+	0x66, /* 01100110 */
+	0x3c, /* 00111100 */
+	0x18, /* 00011000 */
+	0x70, /* 01110000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 129 0x81 '' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xcc, /* 11001100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0x76, /* 01110110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 130 0x82 '' */
+	0x00, /* 00000000 */
+	0x0c, /* 00001100 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xfe, /* 11111110 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 131 0x83 '' */
+	0x00, /* 00000000 */
+	0x10, /* 00010000 */
+	0x38, /* 00111000 */
+	0x6c, /* 01101100 */
+	0x00, /* 00000000 */
+	0x78, /* 01111000 */
+	0x0c, /* 00001100 */
+	0x7c, /* 01111100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0x76, /* 01110110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 132 0x84 '' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xcc, /* 11001100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x78, /* 01111000 */
+	0x0c, /* 00001100 */
+	0x7c, /* 01111100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0x76, /* 01110110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 133 0x85 '
+' */
+	0x00, /* 00000000 */
+	0x60, /* 01100000 */
+	0x30, /* 00110000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x78, /* 01111000 */
+	0x0c, /* 00001100 */
+	0x7c, /* 01111100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0x76, /* 01110110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 134 0x86 '' */
+	0x00, /* 00000000 */
+	0x38, /* 00111000 */
+	0x6c, /* 01101100 */
+	0x38, /* 00111000 */
+	0x00, /* 00000000 */
+	0x78, /* 01111000 */
+	0x0c, /* 00001100 */
+	0x7c, /* 01111100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0x76, /* 01110110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 135 0x87 '' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x18, /* 00011000 */
+	0x70, /* 01110000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 136 0x88 '' */
+	0x00, /* 00000000 */
+	0x10, /* 00010000 */
+	0x38, /* 00111000 */
+	0x6c, /* 01101100 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xfe, /* 11111110 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 137 0x89 '' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xc6, /* 11000110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xfe, /* 11111110 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 138 0x8a '' */
+	0x00, /* 00000000 */
+	0x60, /* 01100000 */
+	0x30, /* 00110000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xfe, /* 11111110 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 139 0x8b '' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x66, /* 01100110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x38, /* 00111000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 140 0x8c '' */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x66, /* 01100110 */
+	0x00, /* 00000000 */
+	0x38, /* 00111000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 141 0x8d '' */
+	0x00, /* 00000000 */
+	0x60, /* 01100000 */
+	0x30, /* 00110000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x38, /* 00111000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 142 0x8e '' */
+	0x00, /* 00000000 */
+	0xc6, /* 11000110 */
+	0x00, /* 00000000 */
+	0x10, /* 00010000 */
+	0x38, /* 00111000 */
+	0x6c, /* 01101100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xfe, /* 11111110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 143 0x8f '' */
+	0x38, /* 00111000 */
+	0x6c, /* 01101100 */
+	0x38, /* 00111000 */
+	0x10, /* 00010000 */
+	0x38, /* 00111000 */
+	0x6c, /* 01101100 */
+	0xc6, /* 11000110 */
+	0xfe, /* 11111110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 144 0x90 '' */
+	0x0c, /* 00001100 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0xfe, /* 11111110 */
+	0x66, /* 01100110 */
+	0x62, /* 01100010 */
+	0x68, /* 01101000 */
+	0x78, /* 01111000 */
+	0x68, /* 01101000 */
+	0x62, /* 01100010 */
+	0x66, /* 01100110 */
+	0xfe, /* 11111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 145 0x91 '' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xec, /* 11101100 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x7e, /* 01111110 */
+	0xd8, /* 11011000 */
+	0xd8, /* 11011000 */
+	0x6e, /* 01101110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 146 0x92 '' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x3e, /* 00111110 */
+	0x6c, /* 01101100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xfe, /* 11111110 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xce, /* 11001110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 147 0x93 '' */
+	0x00, /* 00000000 */
+	0x10, /* 00010000 */
+	0x38, /* 00111000 */
+	0x6c, /* 01101100 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 148 0x94 '' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xc6, /* 11000110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 149 0x95 '' */
+	0x00, /* 00000000 */
+	0x60, /* 01100000 */
+	0x30, /* 00110000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 150 0x96 '' */
+	0x00, /* 00000000 */
+	0x30, /* 00110000 */
+	0x78, /* 01111000 */
+	0xcc, /* 11001100 */
+	0x00, /* 00000000 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0x76, /* 01110110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 151 0x97 '' */
+	0x00, /* 00000000 */
+	0x60, /* 01100000 */
+	0x30, /* 00110000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0x76, /* 01110110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 152 0x98 '' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xc6, /* 11000110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x7e, /* 01111110 */
+	0x06, /* 00000110 */
+	0x0c, /* 00001100 */
+	0x78, /* 01111000 */
+	0x00, /* 00000000 */
+
+	/* 153 0x99 '' */
+	0x00, /* 00000000 */
+	0xc6, /* 11000110 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 154 0x9a '' */
+	0x00, /* 00000000 */
+	0xc6, /* 11000110 */
+	0x00, /* 00000000 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 155 0x9b '' */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 156 0x9c '' */
+	0x00, /* 00000000 */
+	0x38, /* 00111000 */
+	0x6c, /* 01101100 */
+	0x64, /* 01100100 */
+	0x60, /* 01100000 */
+	0xf0, /* 11110000 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0xe6, /* 11100110 */
+	0xfc, /* 11111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 157 0x9d '' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x3c, /* 00111100 */
+	0x18, /* 00011000 */
+	0x7e, /* 01111110 */
+	0x18, /* 00011000 */
+	0x7e, /* 01111110 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 158 0x9e '' */
+	0x00, /* 00000000 */
+	0xf8, /* 11111000 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xf8, /* 11111000 */
+	0xc4, /* 11000100 */
+	0xcc, /* 11001100 */
+	0xde, /* 11011110 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xc6, /* 11000110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 159 0x9f '' */
+	0x00, /* 00000000 */
+	0x0e, /* 00001110 */
+	0x1b, /* 00011011 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x7e, /* 01111110 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0xd8, /* 11011000 */
+	0x70, /* 01110000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 160 0xa0 ' ' */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x60, /* 01100000 */
+	0x00, /* 00000000 */
+	0x78, /* 01111000 */
+	0x0c, /* 00001100 */
+	0x7c, /* 01111100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0x76, /* 01110110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 161 0xa1 '¡' */
+	0x00, /* 00000000 */
+	0x0c, /* 00001100 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x00, /* 00000000 */
+	0x38, /* 00111000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 162 0xa2 '¢' */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x60, /* 01100000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 163 0xa3 '£' */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x60, /* 01100000 */
+	0x00, /* 00000000 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0x76, /* 01110110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 164 0xa4 '¤' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x76, /* 01110110 */
+	0xdc, /* 11011100 */
+	0x00, /* 00000000 */
+	0xdc, /* 11011100 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 165 0xa5 '¥' */
+	0x76, /* 01110110 */
+	0xdc, /* 11011100 */
+	0x00, /* 00000000 */
+	0xc6, /* 11000110 */
+	0xe6, /* 11100110 */
+	0xf6, /* 11110110 */
+	0xfe, /* 11111110 */
+	0xde, /* 11011110 */
+	0xce, /* 11001110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 166 0xa6 '¦' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x3c, /* 00111100 */
+	0x6c, /* 01101100 */
+	0x6c, /* 01101100 */
+	0x3e, /* 00111110 */
+	0x00, /* 00000000 */
+	0x7e, /* 01111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 167 0xa7 '§' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x38, /* 00111000 */
+	0x6c, /* 01101100 */
+	0x6c, /* 01101100 */
+	0x38, /* 00111000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 168 0xa8 '¨' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x00, /* 00000000 */
+	0x30, /* 00110000 */
+	0x30, /* 00110000 */
+	0x60, /* 01100000 */
+	0xc0, /* 11000000 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x7c, /* 01111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 169 0xa9 '©' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfe, /* 11111110 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 170 0xaa 'ª' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfe, /* 11111110 */
+	0x06, /* 00000110 */
+	0x06, /* 00000110 */
+	0x06, /* 00000110 */
+	0x06, /* 00000110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 171 0xab '«' */
+	0x00, /* 00000000 */
+	0x60, /* 01100000 */
+	0xe0, /* 11100000 */
+	0x62, /* 01100010 */
+	0x66, /* 01100110 */
+	0x6c, /* 01101100 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x60, /* 01100000 */
+	0xdc, /* 11011100 */
+	0x86, /* 10000110 */
+	0x0c, /* 00001100 */
+	0x18, /* 00011000 */
+	0x3e, /* 00111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 172 0xac '¬' */
+	0x00, /* 00000000 */
+	0x60, /* 01100000 */
+	0xe0, /* 11100000 */
+	0x62, /* 01100010 */
+	0x66, /* 01100110 */
+	0x6c, /* 01101100 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x66, /* 01100110 */
+	0xce, /* 11001110 */
+	0x9a, /* 10011010 */
+	0x3f, /* 00111111 */
+	0x06, /* 00000110 */
+	0x06, /* 00000110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 173 0xad '­' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x3c, /* 00111100 */
+	0x3c, /* 00111100 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 174 0xae '®' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x36, /* 00110110 */
+	0x6c, /* 01101100 */
+	0xd8, /* 11011000 */
+	0x6c, /* 01101100 */
+	0x36, /* 00110110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 175 0xaf '¯' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xd8, /* 11011000 */
+	0x6c, /* 01101100 */
+	0x36, /* 00110110 */
+	0x6c, /* 01101100 */
+	0xd8, /* 11011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 176 0xb0 '°' */
+	0x11, /* 00010001 */
+	0x44, /* 01000100 */
+	0x11, /* 00010001 */
+	0x44, /* 01000100 */
+	0x11, /* 00010001 */
+	0x44, /* 01000100 */
+	0x11, /* 00010001 */
+	0x44, /* 01000100 */
+	0x11, /* 00010001 */
+	0x44, /* 01000100 */
+	0x11, /* 00010001 */
+	0x44, /* 01000100 */
+	0x11, /* 00010001 */
+	0x44, /* 01000100 */
+	0x11, /* 00010001 */
+	0x44, /* 01000100 */
+
+	/* 177 0xb1 '±' */
+	0x55, /* 01010101 */
+	0xaa, /* 10101010 */
+	0x55, /* 01010101 */
+	0xaa, /* 10101010 */
+	0x55, /* 01010101 */
+	0xaa, /* 10101010 */
+	0x55, /* 01010101 */
+	0xaa, /* 10101010 */
+	0x55, /* 01010101 */
+	0xaa, /* 10101010 */
+	0x55, /* 01010101 */
+	0xaa, /* 10101010 */
+	0x55, /* 01010101 */
+	0xaa, /* 10101010 */
+	0x55, /* 01010101 */
+	0xaa, /* 10101010 */
+
+	/* 178 0xb2 '²' */
+	0xdd, /* 11011101 */
+	0x77, /* 01110111 */
+	0xdd, /* 11011101 */
+	0x77, /* 01110111 */
+	0xdd, /* 11011101 */
+	0x77, /* 01110111 */
+	0xdd, /* 11011101 */
+	0x77, /* 01110111 */
+	0xdd, /* 11011101 */
+	0x77, /* 01110111 */
+	0xdd, /* 11011101 */
+	0x77, /* 01110111 */
+	0xdd, /* 11011101 */
+	0x77, /* 01110111 */
+	0xdd, /* 11011101 */
+	0x77, /* 01110111 */
+
+	/* 179 0xb3 '³' */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+
+	/* 180 0xb4 '´' */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0xf8, /* 11111000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+
+	/* 181 0xb5 'µ' */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0xf8, /* 11111000 */
+	0x18, /* 00011000 */
+	0xf8, /* 11111000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+
+	/* 182 0xb6 '¶' */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0xf6, /* 11110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+
+	/* 183 0xb7 '·' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfe, /* 11111110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+
+	/* 184 0xb8 '¸' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xf8, /* 11111000 */
+	0x18, /* 00011000 */
+	0xf8, /* 11111000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+
+	/* 185 0xb9 '¹' */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0xf6, /* 11110110 */
+	0x06, /* 00000110 */
+	0xf6, /* 11110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+
+	/* 186 0xba 'º' */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+
+	/* 187 0xbb '»' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfe, /* 11111110 */
+	0x06, /* 00000110 */
+	0xf6, /* 11110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+
+	/* 188 0xbc '¼' */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0xf6, /* 11110110 */
+	0x06, /* 00000110 */
+	0xfe, /* 11111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 189 0xbd '½' */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0xfe, /* 11111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 190 0xbe '¾' */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0xf8, /* 11111000 */
+	0x18, /* 00011000 */
+	0xf8, /* 11111000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 191 0xbf '¿' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xf8, /* 11111000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+
+	/* 192 0xc0 'À' */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x1f, /* 00011111 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 193 0xc1 'Á' */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0xff, /* 11111111 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 194 0xc2 'Â' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xff, /* 11111111 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+
+	/* 195 0xc3 'Ã' */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x1f, /* 00011111 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+
+	/* 196 0xc4 'Ä' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xff, /* 11111111 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 197 0xc5 'Å' */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0xff, /* 11111111 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+
+	/* 198 0xc6 'Æ' */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x1f, /* 00011111 */
+	0x18, /* 00011000 */
+	0x1f, /* 00011111 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+
+	/* 199 0xc7 'Ç' */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x37, /* 00110111 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+
+	/* 200 0xc8 'È' */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x37, /* 00110111 */
+	0x30, /* 00110000 */
+	0x3f, /* 00111111 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 201 0xc9 'É' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x3f, /* 00111111 */
+	0x30, /* 00110000 */
+	0x37, /* 00110111 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+
+	/* 202 0xca 'Ê' */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0xf7, /* 11110111 */
+	0x00, /* 00000000 */
+	0xff, /* 11111111 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 203 0xcb 'Ë' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xff, /* 11111111 */
+	0x00, /* 00000000 */
+	0xf7, /* 11110111 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+
+	/* 204 0xcc 'Ì' */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x37, /* 00110111 */
+	0x30, /* 00110000 */
+	0x37, /* 00110111 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+
+	/* 205 0xcd 'Í' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xff, /* 11111111 */
+	0x00, /* 00000000 */
+	0xff, /* 11111111 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 206 0xce 'Î' */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0xf7, /* 11110111 */
+	0x00, /* 00000000 */
+	0xf7, /* 11110111 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+
+	/* 207 0xcf 'Ï' */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0xff, /* 11111111 */
+	0x00, /* 00000000 */
+	0xff, /* 11111111 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 208 0xd0 'Ð' */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0xff, /* 11111111 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 209 0xd1 'Ñ' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xff, /* 11111111 */
+	0x00, /* 00000000 */
+	0xff, /* 11111111 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+
+	/* 210 0xd2 'Ò' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xff, /* 11111111 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+
+	/* 211 0xd3 'Ó' */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x3f, /* 00111111 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 212 0xd4 'Ô' */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x1f, /* 00011111 */
+	0x18, /* 00011000 */
+	0x1f, /* 00011111 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 213 0xd5 'Õ' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x1f, /* 00011111 */
+	0x18, /* 00011000 */
+	0x1f, /* 00011111 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+
+	/* 214 0xd6 'Ö' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x3f, /* 00111111 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+
+	/* 215 0xd7 '×' */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0xff, /* 11111111 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+
+	/* 216 0xd8 'Ø' */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0xff, /* 11111111 */
+	0x18, /* 00011000 */
+	0xff, /* 11111111 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+
+	/* 217 0xd9 'Ù' */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0xf8, /* 11111000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 218 0xda 'Ú' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x1f, /* 00011111 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+
+	/* 219 0xdb 'Û' */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+
+	/* 220 0xdc 'Ü' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+
+	/* 221 0xdd 'Ý' */
+	0xf0, /* 11110000 */
+	0xf0, /* 11110000 */
+	0xf0, /* 11110000 */
+	0xf0, /* 11110000 */
+	0xf0, /* 11110000 */
+	0xf0, /* 11110000 */
+	0xf0, /* 11110000 */
+	0xf0, /* 11110000 */
+	0xf0, /* 11110000 */
+	0xf0, /* 11110000 */
+	0xf0, /* 11110000 */
+	0xf0, /* 11110000 */
+	0xf0, /* 11110000 */
+	0xf0, /* 11110000 */
+	0xf0, /* 11110000 */
+	0xf0, /* 11110000 */
+
+	/* 222 0xde 'Þ' */
+	0x0f, /* 00001111 */
+	0x0f, /* 00001111 */
+	0x0f, /* 00001111 */
+	0x0f, /* 00001111 */
+	0x0f, /* 00001111 */
+	0x0f, /* 00001111 */
+	0x0f, /* 00001111 */
+	0x0f, /* 00001111 */
+	0x0f, /* 00001111 */
+	0x0f, /* 00001111 */
+	0x0f, /* 00001111 */
+	0x0f, /* 00001111 */
+	0x0f, /* 00001111 */
+	0x0f, /* 00001111 */
+	0x0f, /* 00001111 */
+	0x0f, /* 00001111 */
+
+	/* 223 0xdf 'ß' */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0xff, /* 11111111 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 224 0xe0 'à' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x76, /* 01110110 */
+	0xdc, /* 11011100 */
+	0xd8, /* 11011000 */
+	0xd8, /* 11011000 */
+	0xd8, /* 11011000 */
+	0xdc, /* 11011100 */
+	0x76, /* 01110110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 225 0xe1 'á' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x78, /* 01111000 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xcc, /* 11001100 */
+	0xd8, /* 11011000 */
+	0xcc, /* 11001100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xcc, /* 11001100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 226 0xe2 'â' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfe, /* 11111110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0xc0, /* 11000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 227 0xe3 'ã' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfe, /* 11111110 */
+	0x6c, /* 01101100 */
+	0x6c, /* 01101100 */
+	0x6c, /* 01101100 */
+	0x6c, /* 01101100 */
+	0x6c, /* 01101100 */
+	0x6c, /* 01101100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 228 0xe4 'ä' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfe, /* 11111110 */
+	0xc6, /* 11000110 */
+	0x60, /* 01100000 */
+	0x30, /* 00110000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x60, /* 01100000 */
+	0xc6, /* 11000110 */
+	0xfe, /* 11111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 229 0xe5 'å' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7e, /* 01111110 */
+	0xd8, /* 11011000 */
+	0xd8, /* 11011000 */
+	0xd8, /* 11011000 */
+	0xd8, /* 11011000 */
+	0xd8, /* 11011000 */
+	0x70, /* 01110000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 230 0xe6 'æ' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x7c, /* 01111100 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0xc0, /* 11000000 */
+	0x00, /* 00000000 */
+
+	/* 231 0xe7 'ç' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x76, /* 01110110 */
+	0xdc, /* 11011100 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 232 0xe8 'è' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7e, /* 01111110 */
+	0x18, /* 00011000 */
+	0x3c, /* 00111100 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x3c, /* 00111100 */
+	0x18, /* 00011000 */
+	0x7e, /* 01111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 233 0xe9 'é' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x38, /* 00111000 */
+	0x6c, /* 01101100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xfe, /* 11111110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x6c, /* 01101100 */
+	0x38, /* 00111000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 234 0xea 'ê' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x38, /* 00111000 */
+	0x6c, /* 01101100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x6c, /* 01101100 */
+	0x6c, /* 01101100 */
+	0x6c, /* 01101100 */
+	0x6c, /* 01101100 */
+	0xee, /* 11101110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 235 0xeb 'ë' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x1e, /* 00011110 */
+	0x30, /* 00110000 */
+	0x18, /* 00011000 */
+	0x0c, /* 00001100 */
+	0x3e, /* 00111110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x66, /* 01100110 */
+	0x3c, /* 00111100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 236 0xec 'ì' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7e, /* 01111110 */
+	0xdb, /* 11011011 */
+	0xdb, /* 11011011 */
+	0xdb, /* 11011011 */
+	0x7e, /* 01111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 237 0xed 'í' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x03, /* 00000011 */
+	0x06, /* 00000110 */
+	0x7e, /* 01111110 */
+	0xdb, /* 11011011 */
+	0xdb, /* 11011011 */
+	0xf3, /* 11110011 */
+	0x7e, /* 01111110 */
+	0x60, /* 01100000 */
+	0xc0, /* 11000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 238 0xee 'î' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x1c, /* 00011100 */
+	0x30, /* 00110000 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0x7c, /* 01111100 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0x60, /* 01100000 */
+	0x30, /* 00110000 */
+	0x1c, /* 00011100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 239 0xef 'ï' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7c, /* 01111100 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0xc6, /* 11000110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 240 0xf0 'ð' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfe, /* 11111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfe, /* 11111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0xfe, /* 11111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 241 0xf1 'ñ' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x7e, /* 01111110 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7e, /* 01111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 242 0xf2 'ò' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x30, /* 00110000 */
+	0x18, /* 00011000 */
+	0x0c, /* 00001100 */
+	0x06, /* 00000110 */
+	0x0c, /* 00001100 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x00, /* 00000000 */
+	0x7e, /* 01111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 243 0xf3 'ó' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x0c, /* 00001100 */
+	0x18, /* 00011000 */
+	0x30, /* 00110000 */
+	0x60, /* 01100000 */
+	0x30, /* 00110000 */
+	0x18, /* 00011000 */
+	0x0c, /* 00001100 */
+	0x00, /* 00000000 */
+	0x7e, /* 01111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 244 0xf4 'ô' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x0e, /* 00001110 */
+	0x1b, /* 00011011 */
+	0x1b, /* 00011011 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+
+	/* 245 0xf5 'õ' */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0xd8, /* 11011000 */
+	0xd8, /* 11011000 */
+	0xd8, /* 11011000 */
+	0x70, /* 01110000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 246 0xf6 'ö' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x7e, /* 01111110 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 247 0xf7 '÷' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x76, /* 01110110 */
+	0xdc, /* 11011100 */
+	0x00, /* 00000000 */
+	0x76, /* 01110110 */
+	0xdc, /* 11011100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 248 0xf8 'ø' */
+	0x00, /* 00000000 */
+	0x38, /* 00111000 */
+	0x6c, /* 01101100 */
+	0x6c, /* 01101100 */
+	0x38, /* 00111000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 249 0xf9 'ù' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 250 0xfa 'ú' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x18, /* 00011000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 251 0xfb 'û' */
+	0x00, /* 00000000 */
+	0x0f, /* 00001111 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0x0c, /* 00001100 */
+	0xec, /* 11101100 */
+	0x6c, /* 01101100 */
+	0x6c, /* 01101100 */
+	0x3c, /* 00111100 */
+	0x1c, /* 00011100 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 252 0xfc 'ü' */
+	0x00, /* 00000000 */
+	0x6c, /* 01101100 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x36, /* 00110110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 253 0xfd 'ý' */
+	0x00, /* 00000000 */
+	0x3c, /* 00111100 */
+	0x66, /* 01100110 */
+	0x0c, /* 00001100 */
+	0x18, /* 00011000 */
+	0x32, /* 00110010 */
+	0x7e, /* 01111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 254 0xfe 'þ' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x7e, /* 01111110 */
+	0x7e, /* 01111110 */
+	0x7e, /* 01111110 */
+	0x7e, /* 01111110 */
+	0x7e, /* 01111110 */
+	0x7e, /* 01111110 */
+	0x7e, /* 01111110 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+	/* 255 0xff 'ÿ' */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+	0x00, /* 00000000 */
+
+};
Index: generic/src/lib/func.c
===================================================================
--- generic/src/lib/func.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/lib/func.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <func.h>
+#include <print.h>
+#include <cpu.h>
+#include <arch/asm.h>
+#include <arch.h>
+
+__u32	haltstate = 0; /**< Halt flag */
+
+
+/** Halt wrapper
+ *
+ * Set halt flag and halt the cpu.
+ *
+ */
+void halt(void)
+{
+	haltstate = 1;
+	interrupts_disable();
+	if (CPU)
+		printf("cpu%d: halted\n", CPU->id);
+	else
+		printf("cpu: halted\n");
+	cpu_halt();
+}
+
+
+/** Compare two NULL terminated strings
+ *
+ * Do a char-by-char comparment of two NULL terminated strings.
+ * The strings are considered equal iff they have the same
+ * length and consist of the same characters.
+ *
+ * @param src First string to compare.
+ * @param dst Second string to compare.
+ *
+ * @return 0 if the strings are equal, 1 otherwise.
+ *
+ */
+int strcmp(const char *src, const char *dst)
+{
+	int i;
+	
+	i = 0;
+	while (src[i] == dst[i]) {
+		if (src[i] == '\0')
+			return 0;
+		i++;
+	}
+	return 1;
+}
+
Index: generic/src/lib/list.c
===================================================================
--- generic/src/lib/list.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/lib/list.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <list.h>
+
+
+/** Check for membership
+ *
+ * Check whether link is contained in the list head.
+ * The membership is defined as pointer equivalence.
+ *
+ * @param link Item to look for.
+ * @param head List to look in.
+ *
+ * @return true if link is contained in head, false otherwise.
+ *
+ */
+bool list_member(const link_t *link, const link_t *head)
+{
+	bool found = false;
+	link_t *hlp = head->next;
+	
+	while (hlp != head) {
+		if (hlp == link) {
+			found = true;
+			break;
+		}
+		hlp = hlp->next;
+	}
+	
+	return found;
+}
+
+
+/** Concatenate two lists
+ *
+ * Concatenate lists head1 and head2, producing a single
+ * list head1 containing items from both (in head1, head2
+ * order) and empty list head2.
+ *
+ * @param head1 First list and concatenated output
+ * @param head2 Second list and empty output.
+ *
+ */
+void list_concat(link_t *head1, link_t *head2)
+{
+	if (list_empty(head2))
+		return;
+
+	head2->next->prev = head1->prev;
+	head2->prev->next = head1;	
+	head1->prev->next = head2->next;
+	head1->prev = head2->prev;
+	list_initialize(head2);
+}
Index: generic/src/lib/memstr.c
===================================================================
--- generic/src/lib/memstr.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/lib/memstr.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <memstr.h>
+#include <arch/types.h>
+
+
+/** Copy block of memory
+ *
+ * Copy cnt bytes from src address to dst address.
+ * The copying is done byte-by-byte. The source
+ * and destination memory areas cannot overlap.
+ *
+ * @param src Origin address to copy from.
+ * @param dst Origin address to copy to.
+ * @param cnt Number of bytes to copy.
+ *
+ */
+void *_memcpy(void * dst, const void *src, size_t cnt)
+{
+	int i;
+	
+	for (i=0; i<cnt; i++)
+		*((__u8 *) (dst + i)) = *((__u8 *) (src + i));
+		
+	return (char *)src;
+}
+
+/** Fill block of memory
+ *
+ * Fill cnt bytes at dst address with the value x.
+ * The filling is done byte-by-byte.
+ *
+ * @param dst Origin address to fill.
+ * @param cnt Number of bytes to fill.
+ * @param x   Value to fill.
+ *
+ */
+void _memsetb(__address dst, size_t cnt, __u8 x)
+{
+	int i;
+	__u8 *p = (__u8 *) dst;
+	
+	for(i=0; i<cnt; i++)
+		p[i] = x;
+}
+
+/** Fill block of memory
+ *
+ * Fill cnt words at dst address with the value x.
+ * The filling is done word-by-word.
+ *
+ * @param dst Origin address to fill.
+ * @param cnt Number of words to fill.
+ * @param x   Value to fill.
+ *
+ */
+void _memsetw(__address dst, size_t cnt, __u16 x)
+{
+	int i;
+	__u16 *p = (__u16 *) dst;
+	
+	for(i=0; i<cnt; i++)
+		p[i] = x;	
+}
Index: generic/src/lib/sort.c
===================================================================
--- generic/src/lib/sort.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/lib/sort.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2005 Sergey Bondari
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <mm/heap.h>
+#include <memstr.h>
+#include <sort.h>
+#include <panic.h>
+
+#define EBUFSIZE	32
+
+void _qsort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b), void *tmp, void *pivot);
+void _bubblesort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b), void *slot);
+
+/** Quicksort wrapper
+ *
+ * This is only a wrapper that takes care of memory allocations for storing
+ * the pivot and temporary elements for generic quicksort algorithm.
+ * 
+ * @param data Pointer to data to be sorted.
+ * @param n Number of elements to be sorted.
+ * @param e_size Size of one element.
+ * @param cmp Comparator function.
+ * 
+ */
+void qsort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b))
+{
+	__u8 buf_tmp[EBUFSIZE];
+	__u8 buf_pivot[EBUFSIZE];
+	void * tmp = buf_tmp;
+	void * pivot = buf_pivot;
+
+	if (e_size > EBUFSIZE) {
+		pivot = (void *) malloc(e_size);
+		tmp = (void *) malloc(e_size);
+	
+		if (!tmp || !pivot) {
+			panic("Cannot allocate memory\n");
+		}
+	}
+
+	_qsort(data, n, e_size, cmp, tmp, pivot);
+	
+	if (e_size > EBUFSIZE) {
+		free(tmp);
+		free(pivot);
+	}
+}
+
+/** Quicksort
+ *
+ * Apply generic quicksort algorithm on supplied data, using pre-allocated buffers.
+ * 
+ * @param data Pointer to data to be sorted.
+ * @param n Number of elements to be sorted.
+ * @param e_size Size of one element.
+ * @param cmp Comparator function.
+ * @param tmp Pointer to scratch memory buffer e_size bytes long.
+ * @param pivot Pointer to scratch memory buffer e_size bytes long.
+ * 
+ */
+void _qsort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b), void *tmp, void *pivot)
+{
+	if (n > 4) {
+		int i = 0, j = n - 1;
+
+		memcpy(pivot, data, e_size);
+
+		while (1) {
+			while ((cmp(data + i * e_size, pivot) < 0) && i < n) i++;
+			while ((cmp(data + j * e_size, pivot) >=0) && j > 0) j--;
+			if (i<j) {
+				memcpy(tmp, data + i * e_size, e_size);
+				memcpy(data + i * e_size, data + j * e_size, e_size);
+				memcpy(data + j * e_size, tmp, e_size);
+			} else {
+				break;
+			}
+		}
+
+		_qsort(data, j + 1, e_size, cmp, tmp, pivot);
+		_qsort(data + (j + 1) * e_size, n - j - 1, e_size, cmp, tmp, pivot);
+	} else {
+		_bubblesort(data, n, e_size, cmp, tmp);
+	}
+}
+
+/** Bubblesort wrapper
+ *
+ * This is only a wrapper that takes care of memory allocation for storing
+ * the slot element for generic bubblesort algorithm.
+ * 
+ * @param data Pointer to data to be sorted.
+ * @param n Number of elements to be sorted.
+ * @param e_size Size of one element.
+ * @param cmp Comparator function.
+ * 
+ */
+void bubblesort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b))
+{
+	__u8 buf_slot[EBUFSIZE];
+	void * slot = buf_slot;
+	
+	if (e_size > EBUFSIZE) {
+		slot = (void *) malloc(e_size);
+		
+		if (!slot) {
+			panic("Cannot allocate memory\n");
+		}
+	}
+
+	_bubblesort(data, n, e_size, cmp, slot);
+	
+	if (e_size > EBUFSIZE) {
+		free(slot);
+	}
+}
+
+/** Bubblesort
+ *
+ * Apply generic bubblesort algorithm on supplied data, using pre-allocated buffer.
+ * 
+ * @param data Pointer to data to be sorted.
+ * @param n Number of elements to be sorted.
+ * @param e_size Size of one element.
+ * @param cmp Comparator function.
+ * @param slot Pointer to scratch memory buffer e_size bytes long.
+ * 
+ */
+void _bubblesort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b), void *slot)
+{
+	bool done = false;
+	void * p;
+
+	while (!done) {
+		done = true;
+		for (p = data; p < data + e_size * (n - 1); p = p + e_size) {
+			if (cmp(p, p + e_size) == 1) {
+				memcpy(slot, p, e_size);
+				memcpy(p, p + e_size, e_size);
+				memcpy(p + e_size, slot, e_size);
+				done = false;
+			}
+		}
+	}
+
+}
+
+/*
+ * Comparator returns 1 if a > b, 0 if a == b, -1 if a < b
+ */
+int int_cmp(void * a, void * b)
+{
+	return (* (int *) a > * (int*)b) ? 1 : (*(int *)a < * (int *)b) ? -1 : 0;
+}
+
+int __u8_cmp(void * a, void * b)
+{
+	return (* (__u8 *) a > * (__u8 *)b) ? 1 : (*(__u8 *)a < * (__u8 *)b) ? -1 : 0;
+}
+
+int __u16_cmp(void * a, void * b)
+{
+	return (* (__u16 *) a > * (__u16 *)b) ? 1 : (*(__u16 *)a < * (__u16 *)b) ? -1 : 0;
+}
+
+int __u32_cmp(void * a, void * b)
+{
+	return (* (__u32 *) a > * (__u32 *)b) ? 1 : (*(__u32 *)a < * (__u32 *)b) ? -1 : 0;
+}
Index: generic/src/main/kinit.c
===================================================================
--- generic/src/main/kinit.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/main/kinit.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+#include <arch.h>
+#include <main/kinit.h>
+#include <main/uinit.h>
+#include <proc/scheduler.h>
+#include <proc/task.h>
+#include <proc/thread.h>
+#include <panic.h>
+#include <func.h>
+#include <cpu.h>
+#include <arch/asm.h>
+#include <mm/page.h>
+#include <arch/mm/page.h>
+#include <mm/vm.h>
+#include <print.h>
+#include <memstr.h>
+
+#ifdef __SMP__
+#include <arch/smp/mps.h>
+#endif /* __SMP__ */
+
+#include <synch/waitq.h>
+#include <synch/spinlock.h>
+
+#ifdef __TEST__
+#include <test.h>
+#endif /* __TEST__ */
+
+#include <mm/frame.h>
+
+void kinit(void *arg)
+{
+	vm_t *m;
+	vm_area_t *a;
+	task_t *u;
+	thread_t *t;
+	int i;
+
+	interrupts_disable();
+
+#ifdef __SMP__		 	
+	if (config.cpu_count > 1) {
+		/*
+		 * Create the kmp thread and wait for its completion.
+		 * cpu1 through cpuN-1 will come up consecutively and
+		 * not mess together with kcpulb threads.
+		 * Just a beautification.
+		 */
+		if (t = thread_create(kmp, NULL, TASK, 0)) {
+			spinlock_lock(&t->lock);
+			t->flags |= X_WIRED;
+			t->cpu = &cpus[0];
+			spinlock_unlock(&t->lock);
+			thread_ready(t);
+			waitq_sleep(&kmp_completion_wq);
+		}
+		else panic("thread_create/kmp");
+	}
+#endif /* __SMP__ */
+	/*
+	 * Now that all CPUs are up, we can report what we've found.
+	 */
+	for (i = 0; i < config.cpu_count; i++) {
+		if (cpus[i].active)
+			cpu_print_report(&cpus[i]);
+		else
+			printf("cpu%d: not active\n", i);
+	}
+
+#ifdef __SMP__
+	if (config.cpu_count > 1) {
+		/*
+		 * For each CPU, create its load balancing thread.
+		 */
+		for (i = 0; i < config.cpu_count; i++) {
+
+			if (t = thread_create(kcpulb, NULL, TASK, 0)) {
+				spinlock_lock(&t->lock);			
+				t->flags |= X_WIRED;
+				t->cpu = &cpus[i];
+				spinlock_unlock(&t->lock);
+				thread_ready(t);
+			}
+			else panic("thread_create/kcpulb");
+
+		}
+	}
+#endif /* __SMP__ */
+
+	interrupts_enable();
+
+#ifdef __USERSPACE__
+	/*
+	 * Create the first user task.
+	 */
+	m = vm_create(NULL);
+	if (!m)	panic("vm_create");
+	u = task_create(m);
+	if (!u)	panic("task_create");
+	t = thread_create(uinit, NULL, u, THREAD_USER_STACK);
+	if (!t) panic("thread_create");
+
+	/*
+	 * Create the text vm_area and copy the userspace code there.
+	 */	
+	a = vm_area_create(m, VMA_TEXT, 1, UTEXT_ADDRESS);
+	if (!a) panic("vm_area_create: vm_text");
+	vm_area_map(a, m);
+	memcpy((void *) PA2KA(a->mapping[0]), (void *) utext, utext_size < PAGE_SIZE ? utext_size : PAGE_SIZE);
+
+	/*
+	 * Create the data vm_area.
+	 */
+	a = vm_area_create(m, VMA_STACK, 1, USTACK_ADDRESS);
+	if (!a) panic("vm_area_create: vm_stack");
+	vm_area_map(a, m);	
+	
+	thread_ready(t);
+#endif /* __USERSPACE__ */
+
+#ifdef __TEST__
+	test();
+#endif /* __TEST__ */
+
+
+	while (1) {
+		thread_usleep(1000000);
+		printf("kinit... ");
+	}
+
+}
Index: generic/src/main/main.c
===================================================================
--- generic/src/main/main.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/main/main.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch/asm.h>
+#include <context.h>
+#include <print.h>
+#include <panic.h>
+#include <config.h>
+#include <time/clock.h>
+#include <proc/scheduler.h>
+#include <proc/thread.h>
+#include <proc/task.h>
+#include <main/kinit.h>
+#include <cpu.h>
+#include <align.h>
+
+#ifdef __SMP__
+#include <arch/smp/apic.h>
+#include <arch/smp/mps.h>
+#endif /* __SMP__ */
+
+#include <smp/smp.h>
+
+#include <arch/mm/memory_init.h>
+#include <mm/heap.h>
+#include <mm/frame.h>
+#include <mm/page.h>
+#include <mm/tlb.h>
+#include <mm/vm.h>
+
+#include <synch/waitq.h>
+
+#include <arch/arch.h>
+#include <arch.h>
+#include <arch/faddr.h>
+
+#include <typedefs.h>
+
+char *project = "SPARTAN kernel";
+char *copyright = "Copyright (C) 2001-2005 Jakub Jermar\nCopyright (C) 2005 HelenOS project";
+
+config_t config;
+context_t ctx;
+
+/*
+ * These 'hardcoded' variables will be intialised by
+ * the linker or the low level assembler code with
+ * appropriate sizes and addresses.
+ */
+__address hardcoded_load_address = 0;
+size_t hardcoded_ktext_size = 0;
+size_t hardcoded_kdata_size = 0;
+
+/*
+ * Size of memory in bytes taken by kernel and heap.
+ */
+static size_t kernel_size;
+
+/*
+ * Size of heap.
+ */
+static size_t heap_size;
+
+
+/*
+ * Extra space between heap and stack
+ * enforced by alignment requirements.
+ */
+static size_t heap_delta;
+
+void main_bsp(void);
+void main_ap(void);
+
+/*
+ * These two functions prevent stack from underflowing during the
+ * kernel boot phase when SP is set to the very top of the reserved
+ * space. The stack could get corrupted by a fooled compiler-generated
+ * pop sequence otherwise.
+ */
+static void main_bsp_separated_stack(void);
+static void main_ap_separated_stack(void);
+
+/** Bootstrap CPU main kernel routine
+ *
+ * Initializes the kernel by bootstrap CPU.
+ *
+ * Assuming interrupts_disable().
+ *
+ */
+void main_bsp(void)
+{
+	config.cpu_count = 1;
+	config.cpu_active = 1;
+	config.base = hardcoded_load_address;
+	config.memory_size = get_memory_size();
+
+	heap_size = CONFIG_HEAP_SIZE + (config.memory_size/FRAME_SIZE)*sizeof(frame_t);
+	kernel_size = ALIGN(hardcoded_ktext_size + hardcoded_kdata_size + heap_size, PAGE_SIZE);
+	heap_delta = kernel_size - (hardcoded_ktext_size + hardcoded_kdata_size + heap_size);
+	
+	config.kernel_size = kernel_size + CONFIG_STACK_SIZE;
+	
+	context_save(&ctx);
+	early_mapping(config.base + hardcoded_ktext_size + hardcoded_kdata_size, CONFIG_STACK_SIZE + heap_size + heap_delta);
+	context_set(&ctx, FADDR(main_bsp_separated_stack), config.base + kernel_size, CONFIG_STACK_SIZE);
+	context_restore(&ctx);
+	/* not reached */
+}
+
+
+/** Bootstrap CPU main kernel routine stack wrapper
+ *
+ * Second part of main_bsp().
+ *
+ */
+void main_bsp_separated_stack(void) 
+{
+	vm_t *m;
+	task_t *k;
+	thread_t *t;
+	
+	the_initialize(THE);
+	
+	arch_pre_mm_init();
+	early_heap_init(config.base + hardcoded_ktext_size + hardcoded_kdata_size, heap_size + heap_delta);
+	frame_init();
+	page_init();
+	tlb_init();
+	arch_post_mm_init();
+
+	printf("%s\n%s\n", project, copyright);
+	printf("%P: hardcoded_ktext_size=%dK, hardcoded_kdata_size=%dK\n",
+		config.base, hardcoded_ktext_size/1024, hardcoded_kdata_size/1024);
+
+	arch_late_init();
+	
+	smp_init();
+	printf("config.memory_size=%dM\n", config.memory_size/(1024*1024));
+	printf("config.cpu_count=%d\n", config.cpu_count);
+
+	cpu_init();
+
+	calibrate_delay_loop();
+	
+	timeout_init();
+	scheduler_init();
+	task_init();
+	thread_init();
+
+	/*
+	 * Create kernel vm mapping.
+	 */
+	m = vm_create(GET_PTL0_ADDRESS());
+	if (!m)
+		panic("can't create kernel vm address space\n");
+
+	/*
+	 * Create kernel task.
+	 */
+	k = task_create(m);
+	if (!k)
+		panic("can't create kernel task\n");
+		
+	/*
+	 * Create the first thread.
+	 */
+	t = thread_create(kinit, NULL, k, 0);
+	if (!t)
+		panic("can't create kinit thread\n");
+	thread_ready(t);
+	/*
+	 * This call to scheduler() will return to kinit,
+	 * starting the thread of kernel threads.
+	 */
+	scheduler();
+	/* not reached */
+}
+
+
+#ifdef __SMP__
+/** Application CPUs main kernel routine
+ *
+ * Executed by application processors, temporary stack
+ * is at ctx.sp which was set during BP boot.
+ *
+ * Assuming interrupts_disable()'d.
+ *
+ */
+void main_ap(void)
+{
+	/*
+	 * Incrementing the active CPU counter will guarantee that the
+	 * pm_init() will not attempt to build GDT and IDT tables again.
+	 * Neither frame_init() will do the complete thing. Neither cpu_init()
+	 * will do.
+	 */
+	config.cpu_active++;
+
+	/*
+	 * The THE structure is well defined because ctx.sp is used as stack.
+	 */
+	the_initialize(THE);
+	
+	arch_pre_mm_init();
+	frame_init();
+	page_init();
+	tlb_init();
+	arch_post_mm_init();
+	
+	cpu_init();
+	
+	calibrate_delay_loop();
+
+	l_apic_init();
+	l_apic_debug();
+
+	the_copy(THE, (the_t *) CPU->stack);
+
+	/*
+	 * If we woke kmp up before we left the kernel stack, we could
+	 * collide with another CPU coming up. To prevent this, we
+	 * switch to this cpu's private stack prior to waking kmp up.
+	 */
+	context_set(&CPU->saved_context, FADDR(main_ap_separated_stack), (__address) CPU->stack, CPU_STACK_SIZE);
+	context_restore(&CPU->saved_context);
+	/* not reached */
+}
+
+
+/** Application CPUs main kernel routine stack wrapper
+ *
+ * Second part of main_ap().
+ *
+ */
+void main_ap_separated_stack(void)
+{
+	/*
+	 * Configure timeouts for this cpu.
+	 */
+	timeout_init();
+
+	waitq_wakeup(&ap_completion_wq, WAKEUP_FIRST);
+	scheduler();
+	/* not reached */
+}
+#endif /* __SMP__*/
Index: generic/src/main/uinit.c
===================================================================
--- generic/src/main/uinit.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/main/uinit.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2005 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <main/uinit.h>
+#include <arch/types.h>
+#include <proc/thread.h>
+#include <userspace.h>
+#include <print.h>
+
+
+void uinit(void *arg)
+{
+	printf("USER task, uinit thread: kernel mode\n");
+	userspace();
+}
Index: generic/src/mm/buddy.c
===================================================================
--- generic/src/mm/buddy.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/mm/buddy.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2005 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <mm/buddy.h>
+#include <mm/frame.h>
+#include <mm/heap.h>
+#include <arch/types.h>
+#include <typedefs.h>
+#include <list.h>
+#include <debug.h>
+
+/** Create buddy system
+ *
+ * Allocate memory for and initialize new buddy system.
+ *
+ * @param max_order The biggest allocable size will be 2^max_order.
+ * @param op Operations for new buddy system.
+ *
+ * @return New buddy system.
+ */
+buddy_system_t *buddy_system_create(__u8 max_order, buddy_system_operations_t *op)
+{
+	buddy_system_t *b;
+	int i;
+
+	ASSERT(max_order < BUDDY_SYSTEM_INNER_BLOCK);
+
+	ASSERT(op->find_buddy);
+	ASSERT(op->set_order);
+	ASSERT(op->get_order);
+	ASSERT(op->bisect);
+	ASSERT(op->coalesce);
+
+	/*
+	 * Allocate memory for structure describing the whole buddy system.
+	 */	
+	b = (buddy_system_t *) early_malloc(sizeof(buddy_system_t));
+	
+	if (b) {
+		/*
+		 * Allocate memory for all orders this buddy system will work with.
+		 */
+		b->order = (link_t *) early_malloc(max_order * sizeof(link_t));
+		if (!b->order) {
+			early_free(b);
+			return NULL;
+		}
+	
+		for (i = 0; i < max_order; i++)
+			list_initialize(&b->order[i]);
+	
+		b->max_order = max_order;
+		b->op = op;
+	}
+	
+	return b;
+}
+
+/** Allocate block from buddy system.
+ *
+ * Allocate block from buddy system.
+ *
+ * @param b Buddy system pointer.
+ * @param i Returned block will be 2^i big.
+ *
+ * @return Block of data represented by link_t.
+ */
+link_t *buddy_system_alloc(buddy_system_t *b, __u8 i)
+{
+	link_t *res, *hlp;
+
+	ASSERT(i < b->max_order);
+
+	/*
+	 * If the list of order i is not empty,
+	 * the request can be immediatelly satisfied.
+	 */
+	if (!list_empty(&b->order[i])) {
+		res = b->order[i].next;
+		list_remove(res);
+		return res;
+	}
+	
+	/*
+	 * If order i is already the maximal order,
+	 * the request cannot be satisfied.
+	 */
+	if (i == b->max_order - 1)
+		return NULL;
+
+	/*
+	 * Try to recursively satisfy the request from higher order lists.
+	 */	
+	hlp = buddy_system_alloc(b, i + 1);
+	
+	/*
+	 * The request could not be satisfied
+	 * from higher order lists.
+	 */
+	if (!hlp)
+		return NULL;
+		
+	res = hlp;
+	
+	/*
+	 * Bisect the block and set order of both of its parts to i.
+	 */
+	hlp = b->op->bisect(res);
+	b->op->set_order(res, i);
+	b->op->set_order(hlp, i);
+	
+	/*
+	 * Return the other half to buddy system.
+	 */
+	buddy_system_free(b, hlp);
+	
+	return res;
+	
+}
+
+/** Return block to buddy system.
+ *
+ * Return block to buddy system.
+ *
+ * @param b Buddy system pointer.
+ * @param block Block to return.
+ */
+void buddy_system_free(buddy_system_t *b, link_t *block)
+{
+	link_t *buddy, *hlp;
+	__u8 i;
+	
+	/*
+	 * Determine block's order.
+	 */
+	i = b->op->get_order(block);
+
+	ASSERT(i < b->max_order);
+
+	if (i != b->max_order - 1) {
+		/*
+		 * See if there is any buddy in the list of order i.
+		 */
+		buddy = b->op->find_buddy(block);
+		if (buddy) {
+
+			ASSERT(b->op->get_order(buddy) == i);
+		
+			/*
+			 * Remove buddy from the list of order i.
+			 */
+			list_remove(buddy);
+		
+			/*
+			 * Invalidate order of both block and buddy.
+			 */
+			b->op->set_order(block, BUDDY_SYSTEM_INNER_BLOCK);
+			b->op->set_order(buddy, BUDDY_SYSTEM_INNER_BLOCK);
+		
+			/*
+			 * Coalesce block and buddy into one block.
+			 */
+			hlp = b->op->coalesce(block, buddy);
+
+			/*
+			 * Set order of the coalesced block to i + 1.
+			 */
+			b->op->set_order(hlp, i + 1);
+
+			/*
+			 * Recursively add the coalesced block to the list of order i + 1.
+			 */
+			buddy_system_free(b, hlp);
+			return;
+		}
+	}
+
+	/*
+	 * Insert block into the list of order i.
+	 */
+	list_append(block, &b->order[i]);
+
+}
Index: generic/src/mm/frame.c
===================================================================
--- generic/src/mm/frame.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/mm/frame.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <typedefs.h>
+#include <arch/types.h>
+#include <mm/heap.h>
+#include <mm/frame.h>
+#include <mm/vm.h>
+#include <panic.h>
+#include <debug.h>
+#include <list.h>
+#include <synch/spinlock.h>
+#include <arch/asm.h>
+#include <arch.h>
+
+spinlock_t zone_head_lock;       /**< this lock protects zone_head list */
+link_t zone_head;                /**< list of all zones in the system */
+
+/** Initialize physical memory management
+ *
+ * Initialize physical memory managemnt.
+ */
+void frame_init(void)
+{
+	if (config.cpu_active == 1) {
+		zone_init();
+	}
+
+	frame_arch_init();
+	
+	if (config.cpu_active == 1) {
+                frame_region_not_free(config.base, config.base + config.kernel_size + CONFIG_STACK_SIZE);
+        }	
+}
+
+/** Allocate a frame
+ *
+ * Allocate a frame of physical memory.
+ *
+ * @param flags Flags for host zone selection and address processing.
+ *
+ * @return Allocated frame.
+ */
+__address frame_alloc(int flags)
+{
+	ipl_t ipl;
+	link_t *cur, *tmp;
+	zone_t *z;
+	zone_t *zone = NULL;
+	frame_t *frame = NULL;
+	__address v;
+	
+loop:
+	ipl = interrupts_disable();
+	spinlock_lock(&zone_head_lock);
+	
+	/*
+	 * First, find suitable frame zone.
+	 */
+	for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {
+		z = list_get_instance(cur, zone_t, link);
+		
+		spinlock_lock(&z->lock);
+		/*
+		 * Check if the zone has any free frames.
+		 */
+		if (z->free_count) {
+			zone = z;
+			break;
+		}
+		spinlock_unlock(&z->lock);
+	}
+	
+	if (!zone) {
+		if (flags & FRAME_PANIC)
+			panic("Can't allocate frame.\n");
+		
+		/*
+		 * TODO: Sleep until frames are available again.
+		 */
+		spinlock_unlock(&zone_head_lock);
+		interrupts_restore(ipl);
+
+		panic("Sleep not implemented.\n");
+		goto loop;
+	}
+		
+	tmp = zone->free_head.next;
+	frame = list_get_instance(tmp, frame_t, link);
+
+	frame->refcount++;
+	list_remove(tmp);			/* remove frame from free_head */
+	zone->free_count--;
+	zone->busy_count++;
+	
+	v = zone->base + (frame - zone->frames) * FRAME_SIZE;
+	
+	if (flags & FRAME_KA)
+		v = PA2KA(v);
+	
+	spinlock_unlock(&zone->lock);
+	
+	spinlock_unlock(&zone_head_lock);
+	interrupts_restore(ipl);
+	
+	return v;
+}
+
+/** Free a frame.
+ *
+ * Find respective frame structrue for supplied addr.
+ * Decrement frame reference count.
+ * If it drops to zero, move the frame structure to free list.
+ *
+ * @param addr Address of the frame to be freed. It must be a multiple of FRAME_SIZE.
+ */
+void frame_free(__address addr)
+{
+	ipl_t ipl;
+	link_t *cur;
+	zone_t *z;
+	zone_t *zone = NULL;
+	frame_t *frame;
+	
+	ASSERT(addr % FRAME_SIZE == 0);
+	
+	ipl = interrupts_disable();
+	spinlock_lock(&zone_head_lock);
+	
+	/*
+	 * First, find host frame zone for addr.
+	 */
+	for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {
+		z = list_get_instance(cur, zone_t, link);
+		
+		spinlock_lock(&z->lock);
+		
+		if (IS_KA(addr))
+			addr = KA2PA(addr);
+		
+		/*
+		 * Check if addr belongs to z.
+		 */
+		if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) {
+			zone = z;
+			break;
+		}
+		spinlock_unlock(&z->lock);
+	}
+	
+	ASSERT(zone != NULL);
+	
+	frame = &zone->frames[(addr - zone->base)/FRAME_SIZE];
+	ASSERT(frame->refcount);
+
+	if (!--frame->refcount) {
+		list_append(&frame->link, &zone->free_head);	/* append frame to free_head */
+		zone->free_count++;
+		zone->busy_count--;
+	}
+	
+	spinlock_unlock(&zone->lock);	
+	
+	spinlock_unlock(&zone_head_lock);
+	interrupts_restore(ipl);
+}
+
+/** Mark frame not free.
+ *
+ * Find respective frame structrue for supplied addr.
+ * Increment frame reference count and remove the frame structure from free list.
+ *
+ * @param addr Address of the frame to be marked. It must be a multiple of FRAME_SIZE.
+ */
+void frame_not_free(__address addr)
+{
+	ipl_t ipl;
+	link_t *cur;
+	zone_t *z;
+	zone_t *zone = NULL;
+	frame_t *frame;
+	
+	ASSERT(addr % FRAME_SIZE == 0);
+	
+	ipl = interrupts_disable();
+	spinlock_lock(&zone_head_lock);
+	
+	/*
+	 * First, find host frame zone for addr.
+	 */
+	for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {
+		z = list_get_instance(cur, zone_t, link);
+		
+		spinlock_lock(&z->lock);
+		
+		if (IS_KA(addr))
+			addr = KA2PA(addr);
+		
+		/*
+		 * Check if addr belongs to z.
+		 */
+		if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) {
+			zone = z;
+			break;
+		}
+		spinlock_unlock(&z->lock);
+	}
+	
+	ASSERT(zone != NULL);
+	
+	frame = &zone->frames[(addr - zone->base)/FRAME_SIZE];
+
+	if (!frame->refcount) {
+		frame->refcount++;
+
+		list_remove(&frame->link);			/* remove frame from free_head */
+		zone->free_count--;
+		zone->busy_count++;
+	}
+	
+	spinlock_unlock(&zone->lock);	
+	
+	spinlock_unlock(&zone_head_lock);
+	interrupts_restore(ipl);
+}
+
+/** Mark frame region not free.
+ *
+ * Mark frame region not free.
+ *
+ * @param start First address.
+ * @param stop Last address.
+ */
+void frame_region_not_free(__address start, __address stop)
+{
+        __address a;
+
+        start /= FRAME_SIZE;
+        stop /= FRAME_SIZE;
+        for (a = start; a <= stop; a++)
+                frame_not_free(a * FRAME_SIZE);
+}
+
+
+/** Initialize zonekeeping
+ *
+ * Initialize zonekeeping.
+ */
+void zone_init(void)
+{
+	spinlock_initialize(&zone_head_lock);
+	list_initialize(&zone_head);
+}
+
+/** Create frame zone
+ *
+ * Create new frame zone.
+ *
+ * @param start Physical address of the first frame within the zone.
+ * @param size Size of the zone. Must be a multiple of FRAME_SIZE.
+ * @param flags Zone flags.
+ *
+ * @return Initialized zone.
+ */
+zone_t *zone_create(__address start, size_t size, int flags)
+{
+	zone_t *z;
+	count_t cnt;
+	int i;
+	
+	ASSERT(start % FRAME_SIZE == 0);
+	ASSERT(size % FRAME_SIZE == 0);
+	
+	cnt = size / FRAME_SIZE;
+	
+	z = (zone_t *) early_malloc(sizeof(zone_t));
+	if (z) {
+		link_initialize(&z->link);
+		spinlock_initialize(&z->lock);
+	
+		z->base = start;
+		z->flags = flags;
+
+		z->free_count = cnt;
+		list_initialize(&z->free_head);
+
+		z->busy_count = 0;
+		
+		z->frames = (frame_t *) early_malloc(cnt * sizeof(frame_t));
+		if (!z->frames) {
+			early_free(z);
+			return NULL;
+		}
+		
+		for (i = 0; i<cnt; i++) {
+			frame_initialize(&z->frames[i], z);
+			list_append(&z->frames[i].link, &z->free_head);
+		}
+		
+	}
+	
+	return z;
+}
+
+/** Attach frame zone
+ *
+ * Attach frame zone to zone list.
+ *
+ * @param zone Zone to be attached.
+ */
+void zone_attach(zone_t *zone)
+{
+	ipl_t ipl;
+	
+	ipl = interrupts_disable();
+	spinlock_lock(&zone_head_lock);
+	
+	list_append(&zone->link, &zone_head);
+	
+	spinlock_unlock(&zone_head_lock);
+	interrupts_restore(ipl);
+}
+
+/** Initialize frame structure
+ *
+ * Initialize frame structure.
+ *
+ * @param frame Frame structure to be initialized.
+ * @param zone Host frame zone.
+ */
+void frame_initialize(frame_t *frame, zone_t *zone)
+{
+	frame->refcount = 0;
+	link_initialize(&frame->link);
+}
Index: generic/src/mm/heap.c
===================================================================
--- generic/src/mm/heap.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/mm/heap.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <mm/heap.h>
+#include <synch/spinlock.h>
+#include <func.h>
+#include <memstr.h>
+#include <panic.h>
+#include <arch/types.h>
+#include <arch/asm.h>
+#include <arch.h>
+
+/*
+ * First-fit algorithm.
+ * Simple, but hopefully correct.
+ * Chunks being freed are tested for mergability with their neighbours.
+ */
+
+static chunk_t *chunk0;
+static spinlock_t heaplock;
+
+void early_heap_init(__address heap, size_t size)
+{
+	spinlock_initialize(&heaplock);
+	memsetb(heap, size, 0);
+	chunk0 = (chunk_t *) heap;
+	chunk0->used = 0;
+	chunk0->size = size - sizeof(chunk_t);
+	chunk0->next = NULL;
+	chunk0->prev = NULL;
+}
+
+/*
+ * Uses first-fit algorithm.
+ */
+void *early_malloc(size_t size)
+{
+	ipl_t ipl;
+	chunk_t *x, *y, *z;
+
+	if (size == 0)
+		panic("zero-size allocation request");
+		
+	x = chunk0;
+	ipl = interrupts_disable();
+	spinlock_lock(&heaplock);		
+	while (x) {
+		if (x->used || x->size < size) {
+			x = x->next;
+			continue;
+		}
+		
+		x->used = 1;
+    
+		/*
+		 * If the chunk exactly matches required size or if truncating
+		 * it would not provide enough space for storing a new chunk
+		 * header plus at least one byte of data, we are finished.
+		 */
+		if (x->size < size + sizeof(chunk_t) + 1) {
+			spinlock_unlock(&heaplock);
+			interrupts_restore(ipl);
+			return &x->data[0];
+		}
+
+		/*
+		 * Truncate x and create a new chunk.
+		 */
+		y = (chunk_t *) (((__address) x) + size + sizeof(chunk_t));
+		y->used = 0;
+		y->size = x->size - size - sizeof(chunk_t);
+		y->prev = x;
+		y->next = NULL;
+		
+		if (z = x->next) {
+			z->prev = y;
+			y->next = z;
+		}
+		
+		x->size = size;
+		x->next = y;
+		spinlock_unlock(&heaplock);
+		interrupts_restore(ipl);
+
+		return &x->data[0];
+	}
+	spinlock_unlock(&heaplock);
+	interrupts_restore(ipl);
+	return NULL;
+}
+
+void early_free(void *ptr)
+{
+	ipl_t ipl;
+	chunk_t *x, *y, *z;
+
+	if (!ptr)
+		panic("free on NULL");
+
+
+	y = (chunk_t *) (((__u8 *) ptr) - sizeof(chunk_t));
+	if (y->used != 1)
+		panic("freeing unused/damaged chunk");
+
+	ipl = interrupts_disable();
+	spinlock_lock(&heaplock);
+	x = y->prev;
+	z = y->next;
+	/* merge x and y */
+	if (x && !x->used) {
+		x->size += y->size + sizeof(chunk_t);
+		x->next = z;
+		if (z)
+			z->prev = x;
+		y = x;
+	}
+	/* merge y and z or merge (x merged with y) and z */
+	if (z && !z->used) {
+		y->size += z->size + sizeof(chunk_t);
+		y->next = z->next;
+		if (z->next)  {
+			/* y is either y or x */
+			z->next->prev = y;
+		}
+	}
+	y->used = 0;
+	spinlock_unlock(&heaplock);
+	interrupts_restore(ipl);
+}
Index: generic/src/mm/page.c
===================================================================
--- generic/src/mm/page.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/mm/page.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <mm/page.h>
+#include <mm/frame.h>
+#include <arch/mm/page.h>
+#include <arch/types.h>
+#include <typedefs.h>
+#include <arch/asm.h>
+#include <memstr.h>
+
+void page_init(void)
+{
+	page_arch_init();
+	map_page_to_frame(0x0, 0x0, PAGE_NOT_PRESENT, 0);
+}
+
+/** Map memory structure
+ *
+ * Identity-map memory structure
+ * considering possible crossings
+ * of page boundaries.
+ *
+ * @param s Address of the structure.
+ * @param size Size of the structure.
+ */
+void map_structure(__address s, size_t size)
+{
+	int i, cnt, length;
+
+	length = size + (s - (s & ~(PAGE_SIZE-1)));
+	cnt = length/PAGE_SIZE + (length%PAGE_SIZE>0);
+
+	for (i = 0; i < cnt; i++)
+		map_page_to_frame(s + i*PAGE_SIZE, s + i*PAGE_SIZE, PAGE_NOT_CACHEABLE, 0);
+
+}
+
+/** Map page to frame
+ *
+ * Map virtual address 'page' to physical address 'frame'
+ * using 'flags'. Allocate and setup any missing page tables.
+ *
+ * @param page Virtual address of the page to be mapped.
+ * @param frame Physical address of memory frame to which the mapping is done.
+ * @param flags Flags to be used for mapping.
+ * @param root Explicit PTL0 address.
+ */
+void map_page_to_frame(__address page, __address frame, int flags, __address root)
+{
+	pte_t *ptl0, *ptl1, *ptl2, *ptl3;
+	__address newpt;
+
+	ptl0 = (pte_t *) PA2KA(root ? root : (__address) GET_PTL0_ADDRESS());
+
+	if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) {
+		newpt = frame_alloc(FRAME_KA);
+		memsetb(newpt, PAGE_SIZE, 0);
+		SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt));
+		SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC);
+	}
+
+	ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
+
+	if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) {
+		newpt = frame_alloc(FRAME_KA);
+		memsetb(newpt, PAGE_SIZE, 0);
+		SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt));
+		SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC);
+	}
+
+	ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
+
+	if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) {
+		newpt = frame_alloc(FRAME_KA);
+		memsetb(newpt, PAGE_SIZE, 0);
+		SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt));
+		SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC);
+	}
+
+	ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
+
+	SET_FRAME_ADDRESS(ptl3, PTL3_INDEX(page), frame);
+	SET_FRAME_FLAGS(ptl3, PTL3_INDEX(page), flags);
+}
+
+/** Find mapping for virtual page
+ *
+ * Find mapping for virtual page.
+ *
+ * @param page Virtual page.
+ * @param root PTL0 address if non-zero.
+ *
+ * @return NULL if there is no such mapping; entry from PTL3 describing the mapping otherwise.
+ */
+pte_t *find_mapping(__address page, __address root)
+{
+	pte_t *ptl0, *ptl1, *ptl2, *ptl3;
+
+	ptl0 = (pte_t *) PA2KA(root ? root : (__address) GET_PTL0_ADDRESS());
+
+	if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT)
+		return NULL;
+
+	ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
+
+	if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT)
+		return NULL;
+
+	ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
+
+	if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT)
+		return NULL;
+
+	ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
+
+	return &ptl3[PTL3_INDEX(page)];
+}
Index: generic/src/mm/tlb.c
===================================================================
--- generic/src/mm/tlb.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/mm/tlb.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <mm/tlb.h>
+#include <arch/mm/tlb.h>
+#include <smp/ipi.h>
+#include <synch/spinlock.h>
+#include <typedefs.h>
+#include <arch/atomic.h>
+#include <arch/interrupt.h>
+#include <config.h>
+#include <arch.h>
+
+#ifdef __SMP__
+static spinlock_t tlblock;
+#endif
+
+void tlb_init(void)
+{
+	if (config.cpu_active == 1)
+		spinlock_initialize(&tlblock);
+
+	tlb_init_arch();
+}
+
+#ifdef __SMP__
+/* must be called with interrupts disabled */
+void tlb_shootdown_start(void)
+{
+	int i;
+
+	CPU->tlb_active = 0;
+	spinlock_lock(&tlblock);
+	tlb_shootdown_ipi_send();
+	tlb_invalidate(0); /* TODO: use valid ASID */
+	
+busy_wait:	
+	for (i = 0; i<config.cpu_count; i++)
+		if (cpus[i].tlb_active)
+			goto busy_wait;
+}
+
+void tlb_shootdown_finalize(void)
+{
+	spinlock_unlock(&tlblock);
+	CPU->tlb_active = 1;
+}
+
+void tlb_shootdown_ipi_send(void)
+{
+	ipi_broadcast(VECTOR_TLB_SHOOTDOWN_IPI);
+}
+
+void tlb_shootdown_ipi_recv(void)
+{
+	CPU->tlb_active = 0;
+	spinlock_lock(&tlblock);
+	spinlock_unlock(&tlblock);
+	tlb_invalidate(0);	/* TODO: use valid ASID */
+	CPU->tlb_active = 1;
+}
+#endif /* __SMP__ */
Index: generic/src/mm/vm.c
===================================================================
--- generic/src/mm/vm.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/mm/vm.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <mm/vm.h>
+#include <mm/page.h>
+#include <mm/frame.h>
+#include <mm/tlb.h>
+#include <mm/heap.h>
+#include <arch/mm/page.h>
+#include <arch/mm/asid.h>
+#include <arch/mm/vm.h>
+#include <arch/types.h>
+#include <typedefs.h>
+#include <synch/spinlock.h>
+#include <config.h>
+#include <list.h>
+#include <panic.h>
+#include <arch/asm.h>
+#include <debug.h>
+#include <memstr.h>
+#include <arch.h>
+
+#define KAS_START_INDEX		PTL0_INDEX(KERNEL_ADDRESS_SPACE_START)
+#define KAS_END_INDEX		PTL0_INDEX(KERNEL_ADDRESS_SPACE_END)
+#define KAS_INDICES		(1+(KAS_END_INDEX-KAS_START_INDEX))
+
+vm_t *vm_create(pte_t *ptl0)
+{
+	vm_t *m;
+
+	m = (vm_t *) malloc(sizeof(vm_t));
+	if (m) {
+		spinlock_initialize(&m->lock);
+		list_initialize(&m->vm_area_head);
+
+		m->asid = asid_get();
+
+		/*
+		 * Each vm_t is supposed to have its own page table.
+		 * It is either passed one or it has to allocate and set one up.
+		 */
+		m->ptl0 = ptl0;
+		if (!m->ptl0) {
+			pte_t *src_ptl0, *dst_ptl0;
+		
+			src_ptl0 = (pte_t *) PA2KA((__address) GET_PTL0_ADDRESS());
+			dst_ptl0 = (pte_t *) frame_alloc(FRAME_KA | FRAME_PANIC);
+
+//			memsetb((__address) dst_ptl0, PAGE_SIZE, 0);
+//			memcpy((void *) &dst_ptl0[KAS_START_INDEX], (void *) &src_ptl0[KAS_START_INDEX], KAS_INDICES);
+			
+			memcpy((void *) dst_ptl0,(void *) src_ptl0, PAGE_SIZE);
+
+			m->ptl0 = (pte_t *) KA2PA((__address) dst_ptl0);
+		}
+	}
+
+	return m;
+}
+
+void vm_destroy(vm_t *m)
+{
+}
+
+vm_area_t *vm_area_create(vm_t *m, vm_type_t type, size_t size, __address addr)
+{
+	ipl_t ipl;
+	vm_area_t *a;
+	
+	if (addr % PAGE_SIZE)
+		panic("addr not aligned to a page boundary");
+	
+	ipl = interrupts_disable();
+	spinlock_lock(&m->lock);
+	
+	/*
+	 * TODO: test vm_area which is to be created doesn't overlap with an existing one.
+	 */
+	
+	a = (vm_area_t *) malloc(sizeof(vm_area_t));
+	if (a) {
+		int i;
+	
+		a->mapping = (__address *) malloc(size * sizeof(__address));
+		if (!a->mapping) {
+			free(a);
+			spinlock_unlock(&m->lock);
+			interrupts_restore(ipl);
+			return NULL;
+		}
+		
+		for (i=0; i<size; i++)
+			a->mapping[i] = frame_alloc(0);
+		
+		spinlock_initialize(&a->lock);
+			
+		link_initialize(&a->link);			
+		a->type = type;
+		a->size = size;
+		a->address = addr;
+		
+		list_append(&a->link, &m->vm_area_head);
+
+	}
+
+	spinlock_unlock(&m->lock);
+	interrupts_restore(ipl);
+	
+	return a;
+}
+
+void vm_area_destroy(vm_area_t *a)
+{
+}
+
+void vm_area_map(vm_area_t *a, vm_t *m)
+{
+	int i, flags;
+	ipl_t ipl;
+	
+	ipl = interrupts_disable();
+	spinlock_lock(&m->lock);
+	spinlock_lock(&a->lock);
+
+	switch (a->type) {
+		case VMA_TEXT:
+			flags = PAGE_EXEC | PAGE_READ | PAGE_USER | PAGE_PRESENT | PAGE_CACHEABLE;
+			break;
+		case VMA_DATA:
+		case VMA_STACK:
+			flags = PAGE_READ | PAGE_WRITE | PAGE_USER | PAGE_PRESENT | PAGE_CACHEABLE;
+			break;
+		default:
+			panic("unexpected vm_type_t %d", a->type);
+	}
+
+	ASSERT(m->ptl0);
+	for (i=0; i<a->size; i++)
+		map_page_to_frame(a->address + i*PAGE_SIZE, a->mapping[i], flags, (__address) m->ptl0);
+		
+	spinlock_unlock(&a->lock);
+	spinlock_unlock(&m->lock);
+	interrupts_restore(ipl);
+}
+
+void vm_area_unmap(vm_area_t *a, vm_t *m)
+{
+	int i;
+	ipl_t ipl;
+	
+	ipl = interrupts_disable();
+	spinlock_lock(&m->lock);
+	spinlock_lock(&a->lock);
+
+	ASSERT(m->ptl0);
+	for (i=0; i<a->size; i++)		
+		map_page_to_frame(a->address + i*PAGE_SIZE, 0, PAGE_NOT_PRESENT, (__address) m->ptl0);
+	
+	spinlock_unlock(&a->lock);
+	spinlock_unlock(&m->lock);
+	interrupts_restore(ipl);
+}
+
+void vm_install(vm_t *m)
+{
+	link_t *l;
+	ipl_t ipl;
+	
+	ipl = interrupts_disable();
+
+	tlb_shootdown_start();
+	spinlock_lock(&m->lock);
+
+	ASSERT(m->ptl0);
+	SET_PTL0_ADDRESS(m->ptl0);
+
+	spinlock_unlock(&m->lock);
+	tlb_shootdown_finalize();
+
+	interrupts_restore(ipl);
+
+	vm_install_arch(m);
+	
+	VM = m;
+}
Index: generic/src/preempt/preemption.c
===================================================================
--- generic/src/preempt/preemption.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/preempt/preemption.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2005 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <preemption.h>
+#include <arch.h>
+#include <arch/asm.h>
+#include <arch/barrier.h>
+#include <debug.h>
+
+/** Increment preemption disabled counter. */
+void preemption_disable(void)
+{
+	THE->preemption_disabled++;
+	memory_barrier();
+}
+
+/** Decrement preemption disabled counter. */
+void preemption_enable(void)
+{
+	ASSERT(THE->preemption_disabled);
+	memory_barrier();
+	THE->preemption_disabled--;
+}
Index: generic/src/proc/scheduler.c
===================================================================
--- generic/src/proc/scheduler.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/proc/scheduler.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,623 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <proc/scheduler.h>
+#include <proc/thread.h>
+#include <proc/task.h>
+#include <mm/heap.h>
+#include <mm/frame.h>
+#include <mm/page.h>
+#include <mm/vm.h>
+#include <arch/asm.h>
+#include <arch/faddr.h>
+#include <arch/atomic.h>
+#include <synch/spinlock.h>
+#include <config.h>
+#include <context.h>
+#include <func.h>
+#include <arch.h>
+#include <list.h>
+#include <panic.h>
+#include <typedefs.h>
+#include <cpu.h>
+#include <print.h>
+#include <debug.h>
+
+volatile count_t nrdy;
+
+
+/** Take actions before new thread runs
+ *
+ * Perform actions that need to be
+ * taken before the newly selected
+ * tread is passed control.
+ *
+ */
+void before_thread_runs(void)
+{
+	before_thread_runs_arch();
+#ifdef FPU_LAZY
+	if(THREAD==CPU->fpu_owner) 
+		fpu_enable();
+	else
+		fpu_disable(); 
+#else
+	fpu_enable();
+	if (THREAD->fpu_context_exists)
+		fpu_context_restore(&(THREAD->saved_fpu_context));
+	else {
+		fpu_init();
+		THREAD->fpu_context_exists=1;
+	}
+#endif
+}
+
+#ifdef FPU_LAZY
+void scheduler_fpu_lazy_request(void)
+{
+	fpu_enable();
+	if (CPU->fpu_owner != NULL) {  
+		fpu_context_save(&CPU->fpu_owner->saved_fpu_context);
+		/* don't prevent migration */
+		CPU->fpu_owner->fpu_context_engaged=0; 
+	}
+	if (THREAD->fpu_context_exists)
+		fpu_context_restore(&THREAD->saved_fpu_context);
+	else {
+		fpu_init();
+		THREAD->fpu_context_exists=1;
+	}
+	CPU->fpu_owner=THREAD;
+	THREAD->fpu_context_engaged = 1;
+}
+#endif
+
+/** Initialize scheduler
+ *
+ * Initialize kernel scheduler.
+ *
+ */
+void scheduler_init(void)
+{
+}
+
+
+/** Get thread to be scheduled
+ *
+ * Get the optimal thread to be scheduled
+ * according to thread accounting and scheduler
+ * policy.
+ *
+ * @return Thread to be scheduled.
+ *
+ */
+struct thread *find_best_thread(void)
+{
+	thread_t *t;
+	runq_t *r;
+	int i, n;
+
+	ASSERT(CPU != NULL);
+
+loop:
+	interrupts_disable();
+
+	spinlock_lock(&CPU->lock);
+	n = CPU->nrdy;
+	spinlock_unlock(&CPU->lock);
+
+	interrupts_enable();
+	
+	if (n == 0) {
+		#ifdef __SMP__
+		/*
+		 * If the load balancing thread is not running, wake it up and
+		 * set CPU-private flag that the kcpulb has been started.
+		 */
+		if (test_and_set(&CPU->kcpulbstarted) == 0) {
+			waitq_wakeup(&CPU->kcpulb_wq, 0);
+			goto loop;
+		}
+		#endif /* __SMP__ */
+		
+		/*
+		 * For there was nothing to run, the CPU goes to sleep
+		 * until a hardware interrupt or an IPI comes.
+		 * This improves energy saving and hyperthreading.
+		 * On the other hand, several hardware interrupts can be ignored.
+		 */
+		 cpu_sleep();
+		 goto loop;
+	}
+
+	interrupts_disable();
+	
+	i = 0;
+retry:
+	for (; i<RQ_COUNT; i++) {
+		r = &CPU->rq[i];
+		spinlock_lock(&r->lock);
+		if (r->n == 0) {
+			/*
+			 * If this queue is empty, try a lower-priority queue.
+			 */
+			spinlock_unlock(&r->lock);
+			continue;
+		}
+
+		/* avoid deadlock with relink_rq() */
+		if (!spinlock_trylock(&CPU->lock)) {
+			/*
+			 * Unlock r and try again.
+			 */
+			spinlock_unlock(&r->lock);
+			goto retry;
+		}
+		CPU->nrdy--;
+		spinlock_unlock(&CPU->lock);
+
+		atomic_dec((int *) &nrdy);
+		r->n--;
+
+		/*
+		 * Take the first thread from the queue.
+		 */
+		t = list_get_instance(r->rq_head.next, thread_t, rq_link);
+		list_remove(&t->rq_link);
+
+		spinlock_unlock(&r->lock);
+
+		spinlock_lock(&t->lock);
+		t->cpu = CPU;
+
+		t->ticks = us2ticks((i+1)*10000);
+		t->priority = i;	/* eventually correct rq index */
+
+		/*
+		 * Clear the X_STOLEN flag so that t can be migrated when load balancing needs emerge.
+		 */
+		t->flags &= ~X_STOLEN;
+		spinlock_unlock(&t->lock);
+
+		return t;
+	}
+	goto loop;
+
+}
+
+
+/** Prevent rq starvation
+ *
+ * Prevent low priority threads from starving in rq's.
+ *
+ * When the function decides to relink rq's, it reconnects
+ * respective pointers so that in result threads with 'pri'
+ * greater or equal 'start' are moved to a higher-priority queue.
+ *
+ * @param start Threshold priority.
+ *
+ */
+void relink_rq(int start)
+{
+	link_t head;
+	runq_t *r;
+	int i, n;
+
+	list_initialize(&head);
+	spinlock_lock(&CPU->lock);
+	if (CPU->needs_relink > NEEDS_RELINK_MAX) {
+		for (i = start; i<RQ_COUNT-1; i++) {
+			/* remember and empty rq[i + 1] */
+			r = &CPU->rq[i + 1];
+			spinlock_lock(&r->lock);
+			list_concat(&head, &r->rq_head);
+			n = r->n;
+			r->n = 0;
+			spinlock_unlock(&r->lock);
+		
+			/* append rq[i + 1] to rq[i] */
+			r = &CPU->rq[i];
+			spinlock_lock(&r->lock);
+			list_concat(&r->rq_head, &head);
+			r->n += n;
+			spinlock_unlock(&r->lock);
+		}
+		CPU->needs_relink = 0;
+	}
+	spinlock_unlock(&CPU->lock);				
+
+}
+
+
+/** The scheduler
+ *
+ * The thread scheduling procedure.
+ *
+ */
+void scheduler(void)
+{
+	volatile ipl_t ipl;
+
+	ASSERT(CPU != NULL);
+
+	ipl = interrupts_disable();
+
+	if (haltstate)
+		halt();
+
+	if (THREAD) {
+		spinlock_lock(&THREAD->lock);
+#ifndef FPU_LAZY
+		fpu_context_save(&(THREAD->saved_fpu_context));
+#endif
+		if (!context_save(&THREAD->saved_context)) {
+			/*
+			 * This is the place where threads leave scheduler();
+			 */
+			before_thread_runs();
+			spinlock_unlock(&THREAD->lock);
+			interrupts_restore(THREAD->saved_context.ipl);
+			return;
+		}
+
+		/*
+		 * Interrupt priority level of preempted thread is recorded here
+		 * to facilitate scheduler() invocations from interrupts_disable()'d
+		 * code (e.g. waitq_sleep_timeout()). 
+		 */
+		THREAD->saved_context.ipl = ipl;
+	}
+
+	/*
+	 * Through the 'THE' structure, we keep track of THREAD, TASK, CPU
+	 * and preemption counter. At this point THE could be coming either
+	 * from THREAD's or CPU's stack.
+	 */
+	the_copy(THE, (the_t *) CPU->stack);
+
+	/*
+	 * We may not keep the old stack.
+	 * Reason: If we kept the old stack and got blocked, for instance, in
+	 * find_best_thread(), the old thread could get rescheduled by another
+	 * CPU and overwrite the part of its own stack that was also used by
+	 * the scheduler on this CPU.
+	 *
+	 * Moreover, we have to bypass the compiler-generated POP sequence
+	 * which is fooled by SP being set to the very top of the stack.
+	 * Therefore the scheduler() function continues in
+	 * scheduler_separated_stack().
+	 */
+	context_save(&CPU->saved_context);
+	context_set(&CPU->saved_context, FADDR(scheduler_separated_stack), (__address) CPU->stack, CPU_STACK_SIZE);
+	context_restore(&CPU->saved_context);
+	/* not reached */
+}
+
+
+/** Scheduler stack switch wrapper
+ *
+ * Second part of the scheduler() function
+ * using new stack. Handling the actual context
+ * switch to a new thread.
+ *
+ */
+void scheduler_separated_stack(void)
+{
+	int priority;
+
+	ASSERT(CPU != NULL);
+
+	if (THREAD) {
+		switch (THREAD->state) {
+		    case Running:
+			THREAD->state = Ready;
+			spinlock_unlock(&THREAD->lock);
+			thread_ready(THREAD);
+			break;
+
+		    case Exiting:
+			frame_free((__address) THREAD->kstack);
+			if (THREAD->ustack) {
+				frame_free((__address) THREAD->ustack);
+			}
+
+			/*
+			 * Detach from the containing task.
+			 */
+			spinlock_lock(&TASK->lock);
+			list_remove(&THREAD->th_link);
+			spinlock_unlock(&TASK->lock);
+
+			spinlock_unlock(&THREAD->lock);
+    
+			spinlock_lock(&threads_lock);
+			list_remove(&THREAD->threads_link);
+			spinlock_unlock(&threads_lock);
+
+			spinlock_lock(&CPU->lock);
+			if(CPU->fpu_owner==THREAD) CPU->fpu_owner=NULL;
+			spinlock_unlock(&CPU->lock);
+
+			free(THREAD);
+
+			break;
+    
+		    case Sleeping:
+			/*
+			 * Prefer the thread after it's woken up.
+			 */
+			THREAD->priority = -1;
+
+			/*
+			 * We need to release wq->lock which we locked in waitq_sleep().
+			 * Address of wq->lock is kept in THREAD->sleep_queue.
+			 */
+			spinlock_unlock(&THREAD->sleep_queue->lock);
+
+			/*
+			 * Check for possible requests for out-of-context invocation.
+			 */
+			if (THREAD->call_me) {
+				THREAD->call_me(THREAD->call_me_with);
+				THREAD->call_me = NULL;
+				THREAD->call_me_with = NULL;
+			}
+
+			spinlock_unlock(&THREAD->lock);
+
+			break;
+
+		    default:
+			/*
+			 * Entering state is unexpected.
+			 */
+			panic("tid%d: unexpected state %s\n", THREAD->tid, thread_states[THREAD->state]);
+			break;
+		}
+		THREAD = NULL;
+	}
+
+
+	THREAD = find_best_thread();
+	
+	spinlock_lock(&THREAD->lock);
+	priority = THREAD->priority;
+	spinlock_unlock(&THREAD->lock);	
+
+	relink_rq(priority);		
+
+	spinlock_lock(&THREAD->lock);	
+
+	/*
+	 * If both the old and the new task are the same, lots of work is avoided.
+	 */
+	if (TASK != THREAD->task) {
+		vm_t *m1 = NULL;
+		vm_t *m2;
+
+		if (TASK) {
+			spinlock_lock(&TASK->lock);
+			m1 = TASK->vm;
+			spinlock_unlock(&TASK->lock);
+		}
+
+		spinlock_lock(&THREAD->task->lock);
+		m2 = THREAD->task->vm;
+		spinlock_unlock(&THREAD->task->lock);
+		
+		/*
+		 * Note that it is possible for two tasks to share one vm mapping.
+		 */
+		if (m1 != m2) {
+			/*
+			 * Both tasks and vm mappings are different.
+			 * Replace the old one with the new one.
+			 */
+			vm_install(m2);
+		}
+		TASK = THREAD->task;	
+	}
+
+	THREAD->state = Running;
+
+	#ifdef SCHEDULER_VERBOSE
+	printf("cpu%d: tid %d (priority=%d,ticks=%d,nrdy=%d)\n", CPU->id, THREAD->tid, THREAD->priority, THREAD->ticks, CPU->nrdy);
+	#endif	
+
+	/*
+	 * Copy the knowledge of CPU, TASK, THREAD and preemption counter to thread's stack.
+	 */
+	the_copy(THE, (the_t *) THREAD->kstack);
+	
+	context_restore(&THREAD->saved_context);
+	/* not reached */
+}
+
+
+#ifdef __SMP__
+/** Load balancing thread
+ *
+ * SMP load balancing thread, supervising thread supplies
+ * for the CPU it's wired to.
+ *
+ * @param arg Generic thread argument (unused).
+ *
+ */
+void kcpulb(void *arg)
+{
+	thread_t *t;
+	int count, i, j, k = 0;
+	ipl_t ipl;
+
+loop:
+	/*
+	 * Sleep until there's some work to do.
+	 */
+	waitq_sleep(&CPU->kcpulb_wq);
+
+not_satisfied:
+	/*
+	 * Calculate the number of threads that will be migrated/stolen from
+	 * other CPU's. Note that situation can have changed between two
+	 * passes. Each time get the most up to date counts.
+	 */
+	ipl = interrupts_disable();
+	spinlock_lock(&CPU->lock);
+	count = nrdy / config.cpu_active;
+	count -= CPU->nrdy;
+	spinlock_unlock(&CPU->lock);
+	interrupts_restore(ipl);
+
+	if (count <= 0)
+		goto satisfied;
+
+	/*
+	 * Searching least priority queues on all CPU's first and most priority queues on all CPU's last.
+	 */
+	for (j=RQ_COUNT-1; j >= 0; j--) {
+		for (i=0; i < config.cpu_active; i++) {
+			link_t *l;
+			runq_t *r;
+			cpu_t *cpu;
+
+			cpu = &cpus[(i + k) % config.cpu_active];
+
+			/*
+			 * Not interested in ourselves.
+			 * Doesn't require interrupt disabling for kcpulb is X_WIRED.
+			 */
+			if (CPU == cpu)
+				continue;				
+
+restart:		ipl = interrupts_disable();
+			r = &cpu->rq[j];
+			spinlock_lock(&r->lock);
+			if (r->n == 0) {
+				spinlock_unlock(&r->lock);
+				interrupts_restore(ipl);
+				continue;
+			}
+		
+			t = NULL;
+			l = r->rq_head.prev;	/* search rq from the back */
+			while (l != &r->rq_head) {
+				t = list_get_instance(l, thread_t, rq_link);
+				/*
+				 * We don't want to steal CPU-wired threads neither threads already stolen.
+				 * The latter prevents threads from migrating between CPU's without ever being run.
+				 * We don't want to steal threads whose FPU context is still in CPU.
+				 */
+				spinlock_lock(&t->lock);
+				if ( (!(t->flags & (X_WIRED | X_STOLEN))) && (!(t->fpu_context_engaged)) ) {
+				
+					/*
+					 * Remove t from r.
+					 */
+
+					spinlock_unlock(&t->lock);
+					
+					/*
+					 * Here we have to avoid deadlock with relink_rq(),
+					 * because it locks cpu and r in a different order than we do.
+					 */
+					if (!spinlock_trylock(&cpu->lock)) {
+						/* Release all locks and try again. */ 
+						spinlock_unlock(&r->lock);
+						interrupts_restore(ipl);
+						goto restart;
+					}
+					cpu->nrdy--;
+					spinlock_unlock(&cpu->lock);
+
+					atomic_dec((int *)&nrdy);
+
+					r->n--;
+					list_remove(&t->rq_link);
+
+					break;
+				}
+				spinlock_unlock(&t->lock);
+				l = l->prev;
+				t = NULL;
+			}
+			spinlock_unlock(&r->lock);
+
+			if (t) {
+				/*
+				 * Ready t on local CPU
+				 */
+				spinlock_lock(&t->lock);
+				#ifdef KCPULB_VERBOSE
+				printf("kcpulb%d: TID %d -> cpu%d, nrdy=%d, avg=%d\n", CPU->id, t->tid, CPU->id, CPU->nrdy, nrdy / config.cpu_active);
+				#endif
+				t->flags |= X_STOLEN;
+				spinlock_unlock(&t->lock);
+	
+				thread_ready(t);
+
+				interrupts_restore(ipl);
+	
+				if (--count == 0)
+					goto satisfied;
+					
+				/*
+				 * We are not satisfied yet, focus on another CPU next time.
+				 */
+				k++;
+				
+				continue;
+			}
+			interrupts_restore(ipl);
+		}
+	}
+
+	if (CPU->nrdy) {
+		/*
+		 * Be a little bit light-weight and let migrated threads run.
+		 */
+		scheduler();
+	} 
+	else {
+		/*
+		 * We failed to migrate a single thread.
+		 * Something more sophisticated should be done.
+		 */
+		scheduler();
+	}
+		
+	goto not_satisfied;
+
+satisfied:
+	/*
+	 * Tell find_best_thread() to wake us up later again.
+	 */
+	CPU->kcpulbstarted = 0;
+	goto loop;
+}
+
+#endif /* __SMP__ */
Index: generic/src/proc/task.c
===================================================================
--- generic/src/proc/task.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/proc/task.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <proc/thread.h>
+#include <proc/task.h>
+#include <mm/vm.h>
+#include <mm/heap.h>
+
+#include <synch/spinlock.h>
+#include <arch.h>
+#include <panic.h>
+#include <list.h>
+
+spinlock_t tasks_lock;
+link_t tasks_head;
+
+
+/** Initialize tasks
+ *
+ * Initialize kernel tasks support.
+ *
+ */
+void task_init(void)
+{
+	TASK = NULL;
+	spinlock_initialize(&tasks_lock);
+	list_initialize(&tasks_head);
+}
+
+
+/** Create new task
+ *
+ * Create new task with no threads.
+ *
+ * @param m Task's virtual memory structure.
+ *
+ * @return New task's structure on success, NULL on failure.
+ *
+ */
+task_t *task_create(vm_t *m)
+{
+	ipl_t ipl;
+	task_t *ta;
+	
+	ta = (task_t *) malloc(sizeof(task_t));
+	if (ta) {
+		spinlock_initialize(&ta->lock);
+		list_initialize(&ta->th_head);
+		list_initialize(&ta->tasks_link);
+		ta->vm = m;
+		
+		ipl = interrupts_disable();
+		spinlock_lock(&tasks_lock);
+		list_append(&ta->tasks_link, &tasks_head);
+		spinlock_unlock(&tasks_lock);
+		interrupts_restore(ipl);
+	}
+	return ta;
+}
+
Index: generic/src/proc/the.c
===================================================================
--- generic/src/proc/the.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/proc/the.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2005 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <typedefs.h>
+
+
+/** Initialize THE structure
+ *
+ * Initialize THE structure passed as argument.
+ *
+ * @param the THE structure to be initialized.
+ */
+void the_initialize(the_t *the)
+{
+	the->preemption_disabled = 0;
+	the->cpu = NULL;
+	the->thread = NULL;
+	the->task = NULL;
+	the->vm = NULL;
+}
+
+/** Copy THE structure
+ *
+ * Copy the source THE structure to the destination THE structure.
+ *
+ * @param src The source THE structure.
+ * @param dst The destination THE structure.
+ */
+void the_copy(the_t *src, the_t *dst)
+{
+	*dst = *src;
+}
Index: generic/src/proc/thread.c
===================================================================
--- generic/src/proc/thread.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/proc/thread.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <proc/scheduler.h>
+#include <proc/thread.h>
+#include <proc/task.h>
+#include <mm/heap.h>
+#include <mm/frame.h>
+#include <mm/page.h>
+#include <arch/asm.h>
+#include <arch.h>
+#include <synch/synch.h>
+#include <synch/spinlock.h>
+#include <synch/waitq.h>
+#include <synch/rwlock.h>
+#include <cpu.h>
+#include <func.h>
+#include <context.h>
+#include <list.h>
+#include <typedefs.h>
+#include <time/clock.h>
+#include <list.h>
+#include <config.h>
+#include <arch/interrupt.h>
+#include <smp/ipi.h>
+#include <arch/faddr.h>
+#include <arch/atomic.h>
+#include <memstr.h>
+
+char *thread_states[] = {"Invalid", "Running", "Sleeping", "Ready", "Entering", "Exiting"}; /**< Thread states */
+
+spinlock_t threads_lock;
+link_t threads_head;
+
+static spinlock_t tidlock;
+__u32 last_tid = 0;
+
+
+/** Thread wrapper
+ *
+ * This wrapper is provided to ensure that every thread
+ * makes a call to thread_exit() when its implementing
+ * function returns.
+ *
+ * interrupts_disable() is assumed.
+ *
+ */
+void cushion(void)
+{
+	void (*f)(void *) = THREAD->thread_code;
+	void *arg = THREAD->thread_arg;
+
+	/* this is where each thread wakes up after its creation */
+	before_thread_runs();
+
+	spinlock_unlock(&THREAD->lock);
+	interrupts_enable();
+
+	f(arg);
+	thread_exit();
+	/* not reached */
+}
+
+
+/** Initialize threads
+ *
+ * Initialize kernel threads support.
+ *
+ */
+void thread_init(void)
+{
+	THREAD = NULL;
+	nrdy = 0;
+	spinlock_initialize(&threads_lock);
+	list_initialize(&threads_head);
+}
+
+
+/** Make thread ready
+ *
+ * Switch thread t to the ready state.
+ *
+ * @param t Thread to make ready.
+ *
+ */
+void thread_ready(thread_t *t)
+{
+	cpu_t *cpu;
+	runq_t *r;
+	ipl_t ipl;
+	int i, avg, send_ipi = 0;
+
+	ipl = interrupts_disable();
+
+	spinlock_lock(&t->lock);
+
+	i = (t->priority < RQ_COUNT -1) ? ++t->priority : t->priority;
+	
+	cpu = CPU;
+	if (t->flags & X_WIRED) {
+		cpu = t->cpu;
+	}
+	spinlock_unlock(&t->lock);
+	
+	/*
+	 * Append t to respective ready queue on respective processor.
+	 */
+	r = &cpu->rq[i];
+	spinlock_lock(&r->lock);
+	list_append(&t->rq_link, &r->rq_head);
+	r->n++;
+	spinlock_unlock(&r->lock);
+
+	atomic_inc((int *) &nrdy);
+	avg = nrdy / config.cpu_active;
+
+	spinlock_lock(&cpu->lock);
+	if ((++cpu->nrdy) > avg) {
+		/*
+		 * If there are idle halted CPU's, this will wake them up.
+		 */
+		ipi_broadcast(VECTOR_WAKEUP_IPI);
+	}	
+	spinlock_unlock(&cpu->lock);
+
+	interrupts_restore(ipl);
+}
+
+
+/** Create new thread
+ *
+ * Create a new thread.
+ *
+ * @param func  Thread's implementing function.
+ * @param arg   Thread's implementing function argument.
+ * @param task  Task to which the thread belongs.
+ * @param flags Thread flags.
+ *
+ * @return New thread's structure on success, NULL on failure.
+ *
+ */
+thread_t *thread_create(void (* func)(void *), void *arg, task_t *task, int flags)
+{
+	thread_t *t;
+	__address frame_ks, frame_us = NULL;
+
+	t = (thread_t *) malloc(sizeof(thread_t));
+	if (t) {
+		ipl_t ipl;
+	
+		spinlock_initialize(&t->lock);
+	
+		frame_ks = frame_alloc(FRAME_KA);
+		if (THREAD_USER_STACK & flags) {
+			frame_us = frame_alloc(FRAME_KA);
+		}
+
+		ipl = interrupts_disable();
+		spinlock_lock(&tidlock);
+		t->tid = ++last_tid;
+		spinlock_unlock(&tidlock);
+		interrupts_restore(ipl);
+		
+		memsetb(frame_ks, THREAD_STACK_SIZE, 0);
+		link_initialize(&t->rq_link);
+		link_initialize(&t->wq_link);
+		link_initialize(&t->th_link);
+		link_initialize(&t->threads_link);
+		t->kstack = (__u8 *) frame_ks;
+		t->ustack = (__u8 *) frame_us;
+		
+		context_save(&t->saved_context);
+		context_set(&t->saved_context, FADDR(cushion), (__address) t->kstack, THREAD_STACK_SIZE);
+		
+		the_initialize((the_t *) t->kstack);
+
+		ipl = interrupts_disable();
+		t->saved_context.ipl = interrupts_read();
+		interrupts_restore(ipl);
+		
+		t->thread_code = func;
+		t->thread_arg = arg;
+		t->ticks = -1;
+		t->priority = -1;		/* start in rq[0] */
+		t->cpu = NULL;
+		t->flags = 0;
+		t->state = Entering;
+		t->call_me = NULL;
+		t->call_me_with = NULL;
+		
+		timeout_initialize(&t->sleep_timeout);
+		t->sleep_queue = NULL;
+		t->timeout_pending = 0;
+		
+		t->rwlock_holder_type = RWLOCK_NONE;
+		
+		t->task = task;
+		
+		t->fpu_context_exists=0;
+		t->fpu_context_engaged=0;
+		
+		/*
+		 * Register this thread in the system-wide list.
+		 */
+		ipl = interrupts_disable();		
+		spinlock_lock(&threads_lock);
+		list_append(&t->threads_link, &threads_head);
+		spinlock_unlock(&threads_lock);
+
+		/*
+		 * Attach to the containing task.
+		 */
+		spinlock_lock(&task->lock);
+		list_append(&t->th_link, &task->th_head);
+		spinlock_unlock(&task->lock);
+
+		interrupts_restore(ipl);
+	}
+
+	return t;
+}
+
+
+/** Make thread exiting
+ *
+ * End current thread execution and switch it to the exiting
+ * state. All pending timeouts are executed.
+ *
+ */
+void thread_exit(void)
+{
+	ipl_t ipl;
+
+restart:
+	ipl = interrupts_disable();
+	spinlock_lock(&THREAD->lock);
+	if (THREAD->timeout_pending) { /* busy waiting for timeouts in progress */
+		spinlock_unlock(&THREAD->lock);
+		interrupts_restore(ipl);
+		goto restart;
+	}
+	THREAD->state = Exiting;
+	spinlock_unlock(&THREAD->lock);
+	scheduler();
+}
+
+
+/** Thread sleep
+ *
+ * Suspend execution of the current thread.
+ *
+ * @param sec Number of seconds to sleep.
+ *
+ */
+void thread_sleep(__u32 sec)
+{
+	thread_usleep(sec*1000000);
+}
+
+
+/** Thread usleep
+ *
+ * Suspend execution of the current thread.
+ *
+ * @param usec Number of microseconds to sleep.
+ *
+ */	
+void thread_usleep(__u32 usec)
+{
+	waitq_t wq;
+				  
+	waitq_initialize(&wq);
+
+	(void) waitq_sleep_timeout(&wq, usec, SYNCH_NON_BLOCKING);
+}
+
+
+/** Register thread out-of-context invocation
+ *
+ * Register a function and its argument to be executed
+ * on next context switch to the current thread.
+ *
+ * @param call_me      Out-of-context function.
+ * @param call_me_with Out-of-context function argument.
+ *
+ */
+void thread_register_call_me(void (* call_me)(void *), void *call_me_with)
+{
+	ipl_t ipl;
+	
+	ipl = interrupts_disable();
+	spinlock_lock(&THREAD->lock);
+	THREAD->call_me = call_me;
+	THREAD->call_me_with = call_me_with;
+	spinlock_unlock(&THREAD->lock);
+	interrupts_restore(ipl);
+}
Index: generic/src/smp/ipi.c
===================================================================
--- generic/src/smp/ipi.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/smp/ipi.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2005 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef __SMP__
+
+#include <smp/ipi.h>
+#include <config.h>
+
+
+/** Broadcast IPI message
+ *
+ * Broadcast IPI message to all CPUs.
+ *
+ * @param ipi Message to broadcast.
+ *
+ */
+void ipi_broadcast(int ipi)
+{
+	/*
+	 * Provisions must be made to avoid sending IPI:
+	 * - before all CPU's were configured to accept the IPI
+	 * - if there is only one CPU but the kernel was compiled with __SMP__
+	 */
+
+	if ((config.cpu_active > 1) && (config.cpu_active == config.cpu_count))
+		ipi_broadcast_arch(ipi);
+}
+
+#endif /* __SMP__ */
Index: generic/src/synch/condvar.c
===================================================================
--- generic/src/synch/condvar.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/synch/condvar.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <synch/condvar.h>
+#include <synch/mutex.h>
+#include <synch/waitq.h>
+#include <synch/synch.h>
+
+/** Initialize condition variable
+ *
+ * Initialize condition variable.
+ *
+ * @param cv Condition variable.
+ */
+void condvar_initialize(condvar_t *cv)
+{
+	waitq_initialize(&cv->wq);
+}
+
+/** Signal the condition has become true
+ *
+ * Signal the condition has become true
+ * to the first waiting thread by waking it up.
+ *
+ * @param cv Condition variable.
+ */
+void condvar_signal(condvar_t *cv)
+{
+	waitq_wakeup(&cv->wq, WAKEUP_FIRST);
+}
+
+/** Signal the condition has become true
+ *
+ * Signal the condition has become true
+ * to all waiting threads by waking them up.
+ *
+ * @param cv Condition variable.
+ */
+void condvar_broadcast(condvar_t *cv)
+{
+	waitq_wakeup(&cv->wq, WAKEUP_ALL);
+}
+
+/** Wait for the condition becoming true
+ *
+ * Wait for the condition becoming true.
+ *
+ * @param cv Condition variable.
+ * @param mtx Mutex.
+ * @param usec Timeout value in microseconds.
+ * @param trywait Blocking versus non-blocking operation mode switch.
+ *
+ * For exact description of possible combinations of
+ * 'usec' and 'trywait', see comment for waitq_sleep_timeout().
+ *
+ * @return See comment for waitq_sleep_timeout().
+ */
+int _condvar_wait_timeout(condvar_t *cv, mutex_t *mtx, __u32 usec, int trywait)
+{
+	int rc;
+
+	mutex_unlock(mtx);
+	rc = waitq_sleep_timeout(&cv->wq, usec, trywait);
+	mutex_lock(mtx);
+	return rc;
+}
Index: generic/src/synch/mutex.c
===================================================================
--- generic/src/synch/mutex.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/synch/mutex.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <synch/mutex.h>
+#include <synch/semaphore.h>
+#include <synch/synch.h>
+
+/** Initialize mutex
+ *
+ * Initialize mutex.
+ *
+ * @param mtx Mutex.
+ */
+void mutex_initialize(mutex_t *mtx)
+{
+	semaphore_initialize(&mtx->sem, 1);
+}
+
+/** Acquire mutex
+ *
+ * Acquire mutex.
+ * Timeout mode and non-blocking mode can be requested.
+ *
+ * @param mtx Mutex.
+ * @param usec Timeout in microseconds.
+ * @param trylock Switches between blocking and non-blocking mode.
+ *
+ * For exact description of possible combinations of
+ * 'usec' and 'trylock', see comment for waitq_sleep_timeout().
+ *
+ * @return See comment for waitq_sleep_timeout().
+ */
+int _mutex_lock_timeout(mutex_t *mtx, __u32 usec, int trylock)
+{
+	return _semaphore_down_timeout(&mtx->sem, usec, trylock);
+}
+
+/** Release mutex
+ *
+ * Release mutex.
+ *
+ * @param mtx Mutex.
+ */
+void mutex_unlock(mutex_t *mtx)
+{
+	semaphore_up(&mtx->sem);
+}
Index: generic/src/synch/rwlock.c
===================================================================
--- generic/src/synch/rwlock.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/synch/rwlock.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*
+ * Reader/Writer locks
+ */
+
+/*
+ * These locks are not recursive.
+ * Neither readers nor writers will suffer starvation.
+ *
+ * If there is a writer followed by a reader waiting for the rwlock
+ * and the writer times out, all leading readers are automatically woken up
+ * and allowed in.
+ */
+
+/*
+ * NOTE ON rwlock_holder_type
+ * This field is set on an attempt to acquire the exclusive mutex
+ * to the respective value depending whether the caller is a reader
+ * or a writer. The field is examined only if the thread had been
+ * previously blocked on the exclusive mutex. Thus it is save
+ * to store the rwlock type in the thread structure, because
+ * each thread can block on only one rwlock at a time.
+ */
+ 
+#include <synch/rwlock.h>
+#include <synch/spinlock.h>
+#include <synch/mutex.h>
+#include <synch/waitq.h>
+#include <synch/synch.h>
+#include <list.h>
+#include <typedefs.h>
+#include <arch/asm.h>
+#include <arch.h>
+#include <proc/thread.h>
+#include <panic.h>
+
+#define ALLOW_ALL		0
+#define ALLOW_READERS_ONLY	1
+
+static void let_others_in(rwlock_t *rwl, int readers_only);
+static void release_spinlock(void *arg);
+
+/** Initialize reader/writer lock
+ *
+ * Initialize reader/writer lock.
+ *
+ * @param rwl Reader/Writer lock.
+ */
+void rwlock_initialize(rwlock_t *rwl) {
+	spinlock_initialize(&rwl->lock);
+	mutex_initialize(&rwl->exclusive);
+	rwl->readers_in = 0;
+}
+
+/** Acquire reader/writer lock for reading
+ *
+ * Acquire reader/writer lock for reading.
+ * Timeout and willingness to block may be specified.
+ *
+ * @param rwl Reader/Writer lock.
+ * @param usec Timeout in microseconds.
+ * @param trylock Switches between blocking and non-blocking mode.
+ *
+ * For exact description of possible combinations of
+ * 'usec' and 'trylock', see comment for waitq_sleep_timeout().
+ *
+ * @return See comment for waitq_sleep_timeout().
+ */
+int _rwlock_write_lock_timeout(rwlock_t *rwl, __u32 usec, int trylock)
+{
+	ipl_t ipl;
+	int rc;
+	
+	ipl = interrupts_disable();
+	spinlock_lock(&THREAD->lock);
+	THREAD->rwlock_holder_type = RWLOCK_WRITER;
+	spinlock_unlock(&THREAD->lock);	
+	interrupts_restore(ipl);
+
+	/*
+	 * Writers take the easy part.
+	 * They just need to acquire the exclusive mutex.
+	 */
+	rc = _mutex_lock_timeout(&rwl->exclusive, usec, trylock);
+	if (SYNCH_FAILED(rc)) {
+
+		/*
+		 * Lock operation timed out.
+		 * The state of rwl is UNKNOWN at this point.
+		 * No claims about its holder can be made.
+		 */
+		 
+		ipl = interrupts_disable();
+		spinlock_lock(&rwl->lock);
+		/*
+		 * Now when rwl is locked, we can inspect it again.
+		 * If it is held by some readers already, we can let
+		 * readers from the head of the wait queue in.
+		 */
+		if (rwl->readers_in)
+			let_others_in(rwl, ALLOW_READERS_ONLY);
+		spinlock_unlock(&rwl->lock);
+		interrupts_restore(ipl);
+	}
+	
+	return rc;
+}
+
+/** Acquire reader/writer lock for writing
+ *
+ * Acquire reader/writer lock for writing.
+ * Timeout and willingness to block may be specified.
+ *
+ * @param rwl Reader/Writer lock.
+ * @param usec Timeout in microseconds.
+ * @param trylock Switches between blocking and non-blocking mode.
+ *
+ * For exact description of possible combinations of
+ * 'usec' and 'trylock', see comment for waitq_sleep_timeout().
+ *
+ * @return See comment for waitq_sleep_timeout().
+ */
+int _rwlock_read_lock_timeout(rwlock_t *rwl, __u32 usec, int trylock)
+{
+	int rc;
+	ipl_t ipl;
+	
+	ipl = interrupts_disable();
+	spinlock_lock(&THREAD->lock);
+	THREAD->rwlock_holder_type = RWLOCK_READER;
+	spinlock_unlock(&THREAD->lock);	
+
+	spinlock_lock(&rwl->lock);
+
+	/*
+	 * Find out whether we can get what we want without blocking.
+	 */
+	rc = mutex_trylock(&rwl->exclusive);
+	if (SYNCH_FAILED(rc)) {
+
+		/*
+		 * 'exclusive' mutex is being held by someone else.
+		 * If the holder is a reader and there is no one
+		 * else waiting for it, we can enter the critical
+		 * section.
+		 */
+
+		if (rwl->readers_in) {
+			spinlock_lock(&rwl->exclusive.sem.wq.lock);
+			if (list_empty(&rwl->exclusive.sem.wq.head)) {
+				/*
+				 * We can enter.
+				 */
+				spinlock_unlock(&rwl->exclusive.sem.wq.lock);
+				goto shortcut;
+			}
+			spinlock_unlock(&rwl->exclusive.sem.wq.lock);
+		}
+
+		/*
+		 * In order to prevent a race condition when a reader
+		 * could block another reader at the head of the waitq,
+		 * we register a function to unlock rwl->lock
+		 * after this thread is put asleep.
+		 */
+		thread_register_call_me(release_spinlock, &rwl->lock);
+				 
+		rc = _mutex_lock_timeout(&rwl->exclusive, usec, trylock);
+		switch (rc) {
+			case ESYNCH_WOULD_BLOCK:
+				/*
+				 * release_spinlock() wasn't called
+				 */
+				thread_register_call_me(NULL, NULL);				 
+				spinlock_unlock(&rwl->lock);
+			case ESYNCH_TIMEOUT:
+				/*
+				 * The sleep timeouted.
+				 * We just restore interrupt priority level.
+				 */
+			case ESYNCH_OK_BLOCKED:		
+				/*
+				 * We were woken with rwl->readers_in already incremented.
+				 * Note that this arrangement avoids race condition between
+				 * two concurrent readers. (Race is avoided if 'exclusive' is
+				 * locked at the same time as 'readers_in' is incremented.
+				 * Same time means both events happen atomically when
+				 * rwl->lock is held.)
+				 */
+				interrupts_restore(ipl);
+				break;
+			case ESYNCH_OK_ATOMIC:
+				panic("_mutex_lock_timeout()==ESYNCH_OK_ATOMIC");
+				break;
+			dafault:
+				panic("invalid ESYNCH");
+				break;
+		}
+		return rc;
+	}
+
+shortcut:
+
+	/*
+	 * We can increment readers_in only if we didn't go to sleep.
+	 * For sleepers, rwlock_let_others_in() will do the job.
+	 */
+	rwl->readers_in++;
+	
+	spinlock_unlock(&rwl->lock);
+	interrupts_restore(ipl);
+
+	return ESYNCH_OK_ATOMIC;
+}
+
+/** Release reader/writer lock held by writer
+ *
+ * Release reader/writer lock held by writer.
+ * Handoff reader/writer lock ownership directly
+ * to waiting readers or a writer.
+ *
+ * @param rwl Reader/Writer lock.
+ */
+void rwlock_write_unlock(rwlock_t *rwl)
+{
+	ipl_t ipl;
+	
+	ipl = interrupts_disable();
+	spinlock_lock(&rwl->lock);
+	let_others_in(rwl, ALLOW_ALL);
+	spinlock_unlock(&rwl->lock);
+	interrupts_restore(ipl);
+	
+}
+
+/** Release reader/writer lock held by reader
+ *
+ * Release reader/writer lock held by reader.
+ * Handoff reader/writer lock ownership directly
+ * to a waiting writer or don't do anything if more
+ * readers poses the lock.
+ *
+ * @param rwl Reader/Writer lock.
+ */
+void rwlock_read_unlock(rwlock_t *rwl)
+{
+	ipl_t ipl;
+
+	ipl = interrupts_disable();
+	spinlock_lock(&rwl->lock);
+	if (!--rwl->readers_in)
+		let_others_in(rwl, ALLOW_ALL);
+	spinlock_unlock(&rwl->lock);
+	interrupts_restore(ipl);
+}
+
+
+/** Direct handoff
+ *
+ * Direct handoff of reader/writer lock ownership
+ * to waiting readers or a writer.
+ *
+ * Must be called with rwl->lock locked.
+ * Must be called with interrupts_disable()'d.
+ *
+ * @param rwl Reader/Writer lock.
+ * @param readers_only See the description below.
+ *
+ * If readers_only is false: (unlock scenario)
+ * Let the first sleeper on 'exclusive' mutex in, no matter
+ * whether it is a reader or a writer. If there are more leading
+ * readers in line, let each of them in.
+ *
+ * Otherwise: (timeout scenario)
+ * Let all leading readers in.
+ */
+void let_others_in(rwlock_t *rwl, int readers_only)
+{
+	rwlock_type_t type = RWLOCK_NONE;
+	thread_t *t = NULL;
+	int one_more = 1;
+	
+	spinlock_lock(&rwl->exclusive.sem.wq.lock);
+
+	if (!list_empty(&rwl->exclusive.sem.wq.head))
+		t = list_get_instance(rwl->exclusive.sem.wq.head.next, thread_t, wq_link);
+	do {
+		if (t) {
+			spinlock_lock(&t->lock);
+			type = t->rwlock_holder_type;
+			spinlock_unlock(&t->lock);			
+		}
+	
+		/*
+		 * If readers_only is true, we wake all leading readers
+		 * if and only if rwl is locked by another reader.
+		 * Assumption: readers_only ==> rwl->readers_in
+		 */
+		if (readers_only && (type != RWLOCK_READER))
+			break;
+
+
+		if (type == RWLOCK_READER) {
+			/*
+			 * Waking up a reader.
+			 * We are responsible for incrementing rwl->readers_in for it.
+			 */
+			 rwl->readers_in++;
+		}
+
+		/*
+		 * Only the last iteration through this loop can increment
+		 * rwl->exclusive.sem.wq.missed_wakeup's. All preceeding
+		 * iterations will wake up a thread.
+		 */
+		/* We call the internal version of waitq_wakeup, which
+		 * relies on the fact that the waitq is already locked.
+		 */
+		_waitq_wakeup_unsafe(&rwl->exclusive.sem.wq, WAKEUP_FIRST);
+		
+		t = NULL;
+		if (!list_empty(&rwl->exclusive.sem.wq.head)) {
+			t = list_get_instance(rwl->exclusive.sem.wq.head.next, thread_t, wq_link);
+			if (t) {
+				spinlock_lock(&t->lock);
+				if (t->rwlock_holder_type != RWLOCK_READER)
+					one_more = 0;
+				spinlock_unlock(&t->lock);	
+			}
+		}
+	} while ((type == RWLOCK_READER) && t && one_more);
+
+	spinlock_unlock(&rwl->exclusive.sem.wq.lock);
+}
+
+/** Release spinlock callback
+ *
+ * This is a callback function invoked from the scheduler.
+ * The callback is registered in _rwlock_read_lock_timeout().
+ *
+ * @param arg Spinlock.
+ */
+void release_spinlock(void *arg)
+{
+	spinlock_unlock((spinlock_t *) arg);
+}
Index: generic/src/synch/semaphore.c
===================================================================
--- generic/src/synch/semaphore.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/synch/semaphore.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <synch/semaphore.h>
+#include <synch/waitq.h>
+#include <synch/spinlock.h>
+#include <synch/synch.h>
+#include <arch/asm.h>
+#include <arch.h>
+
+/** Initialize semaphore
+ *
+ * Initialize semaphore.
+ *
+ * @param s Semaphore.
+ * @param val Maximal number of threads allowed to enter critical section.
+ */
+void semaphore_initialize(semaphore_t *s, int val)
+{
+	ipl_t ipl;
+	
+	waitq_initialize(&s->wq);
+	
+	ipl = interrupts_disable();
+
+	spinlock_lock(&s->wq.lock);
+	s->wq.missed_wakeups = val;
+	spinlock_unlock(&s->wq.lock);
+
+	interrupts_restore(ipl);
+}
+
+/** Semaphore down
+ *
+ * Semaphore down.
+ * Conditional mode and mode with timeout can be requested.
+ *
+ * @param s Semaphore.
+ * @param usec Timeout in microseconds.
+ * @param trydown Switches between blocking and non-blocking mode.
+ *
+ * For exact description of possible combinations of
+ * 'usec' and 'trydown', see comment for waitq_sleep_timeout().
+ *
+ * @return See comment for waitq_sleep_timeout().
+ */
+int _semaphore_down_timeout(semaphore_t *s, __u32 usec, int trydown)
+{
+	return waitq_sleep_timeout(&s->wq, usec, trydown); 
+}
+
+/** Semaphore up
+ *
+ * Semaphore up.
+ *
+ * @param s Semaphore.
+ */
+void semaphore_up(semaphore_t *s)
+{
+	waitq_wakeup(&s->wq, WAKEUP_FIRST);
+}
Index: generic/src/synch/spinlock.c
===================================================================
--- generic/src/synch/spinlock.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/synch/spinlock.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <synch/spinlock.h>
+#include <arch/atomic.h>
+#include <arch/barrier.h>
+#include <arch.h>
+#include <preemption.h>
+#include <print.h>
+#include <debug.h>
+
+#ifdef __SMP__
+
+/** Initialize spinlock
+ *
+ * Initialize spinlock.
+ *
+ * @param sl Pointer to spinlock_t structure.
+ */
+void spinlock_initialize(spinlock_t *sl)
+{
+	sl->val = 0;
+}
+
+#ifdef DEBUG_SPINLOCK
+/** Lock spinlock
+ *
+ * Lock spinlock.
+ * This version has limitted ability to report 
+ * possible occurence of deadlock.
+ *
+ * @param sl Pointer to spinlock_t structure.
+ */
+void spinlock_lock(spinlock_t *sl)
+{
+	int i = 0;
+	__address caller = ((__u32 *) &sl)[-1];
+
+	preemption_disable();
+	while (test_and_set(&sl->val)) {
+		if (i++ > 300000) {
+			printf("cpu%d: looping on spinlock %X, caller=%X\n", CPU->id, sl, caller);
+			i = 0;
+		}
+	}
+
+	/*
+	 * Prevent critical section code from bleeding out this way up.
+	 */
+	CS_ENTER_BARRIER();
+
+}
+
+#else
+
+/** Lock spinlock
+ *
+ * Lock spinlock.
+ *
+ * @param sl Pointer to spinlock_t structure.
+ */
+void spinlock_lock(spinlock_t *sl)
+{
+	preemption_disable();
+
+	/*
+	 * Each architecture has its own efficient/recommended
+	 * implementation of spinlock.
+	 */
+	spinlock_arch(&sl->val);
+
+	/*
+	 * Prevent critical section code from bleeding out this way up.
+	 */
+	CS_ENTER_BARRIER();
+}
+#endif
+
+/** Lock spinlock conditionally
+ *
+ * Lock spinlock conditionally.
+ * If the spinlock is not available at the moment,
+ * signal failure.
+ *
+ * @param sl Pointer to spinlock_t structure.
+ *
+ * @return Zero on failure, non-zero otherwise.
+ */
+int spinlock_trylock(spinlock_t *sl)
+{
+	int rc;
+	
+	preemption_disable();
+	rc = !test_and_set(&sl->val);
+
+	/*
+	 * Prevent critical section code from bleeding out this way up.
+	 */
+	CS_ENTER_BARRIER();
+
+	if (!rc)
+		preemption_enable();
+	
+	return rc;
+}
+
+/** Unlock spinlock
+ *
+ * Unlock spinlock.
+ *
+ * @param sl Pointer to spinlock_t structure.
+ */
+void spinlock_unlock(spinlock_t *sl)
+{
+	ASSERT(sl->val != 0);
+
+	/*
+	 * Prevent critical section code from bleeding out this way down.
+	 */
+	CS_LEAVE_BARRIER();
+	
+	sl->val = 0;
+	preemption_enable();
+}
+
+#endif
Index: generic/src/synch/waitq.c
===================================================================
--- generic/src/synch/waitq.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/synch/waitq.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <synch/waitq.h>
+#include <synch/synch.h>
+#include <synch/spinlock.h>
+#include <proc/thread.h>
+#include <proc/scheduler.h>
+#include <arch/asm.h>
+#include <arch/types.h>
+#include <time/timeout.h>
+#include <arch.h>
+#include <context.h>
+#include <list.h>
+
+/** Initialize wait queue
+ *
+ * Initialize wait queue.
+ *
+ * @param wq Pointer to wait queue to be initialized.
+ */
+void waitq_initialize(waitq_t *wq)
+{
+	spinlock_initialize(&wq->lock);
+	list_initialize(&wq->head);
+	wq->missed_wakeups = 0;
+}
+
+/** Handle timeout during waitq_sleep_timeout() call
+ *
+ * This routine is called when waitq_sleep_timeout() timeouts.
+ * Interrupts are disabled.
+ *
+ * It is supposed to try to remove 'its' thread from the wait queue;
+ * it can eventually fail to achieve this goal when these two events
+ * overlap. In that case it behaves just as though there was no
+ * timeout at all.
+ *
+ * @param data Pointer to the thread that called waitq_sleep_timeout().
+ */
+void waitq_interrupted_sleep(void *data)
+{
+	thread_t *t = (thread_t *) data;
+	waitq_t *wq;
+	int do_wakeup = 0;
+
+	spinlock_lock(&threads_lock);
+	if (!list_member(&t->threads_link, &threads_head))
+		goto out;
+
+grab_locks:
+	spinlock_lock(&t->lock);
+	if (wq = t->sleep_queue) {
+		if (!spinlock_trylock(&wq->lock)) {
+			spinlock_unlock(&t->lock);
+			goto grab_locks; /* avoid deadlock */
+		}
+
+		list_remove(&t->wq_link);
+		t->saved_context = t->sleep_timeout_context;
+		do_wakeup = 1;
+		
+		spinlock_unlock(&wq->lock);
+		t->sleep_queue = NULL;
+	}
+	
+	t->timeout_pending = 0;
+	spinlock_unlock(&t->lock);
+	
+	if (do_wakeup) thread_ready(t);
+
+out:
+	spinlock_unlock(&threads_lock);
+}
+
+/** Sleep until either wakeup or timeout occurs
+ *
+ * This is a sleep implementation which allows itself to be
+ * interrupted from the sleep, restoring a failover context.
+ *
+ * Sleepers are organised in FIFO fashion in a structure called wait queue.
+ *
+ * This function is really basic in that other functions as waitq_sleep()
+ * and all the *_timeout() functions use it.
+ *
+ * @param wq Pointer to wait queue.
+ * @param usec Timeout in microseconds.
+ * @param nonblocking Blocking vs. non-blocking operation mode switch.
+ *
+ * If usec is greater than zero, regardless of the value of nonblocking,
+ * the call will not return until either timeout or wakeup comes.
+ *
+ * If usec is zero and nonblocking is zero (false), the call
+ * will not return until wakeup comes.
+ *
+ * If usec is zero and nonblocking is non-zero (true), the call will
+ * immediately return, reporting either success or failure.
+ *
+ * @return Returns one of: ESYNCH_WOULD_BLOCK, ESYNCH_TIMEOUT,
+ *         ESYNCH_OK_ATOMIC, ESYNCH_OK_BLOCKED.
+ *
+ * ESYNCH_WOULD_BLOCK means that the sleep failed because at the time
+ * of the call there was no pending wakeup.
+ *
+ * ESYNCH_TIMEOUT means that the sleep timed out.
+ *
+ * ESYNCH_OK_ATOMIC means that the sleep succeeded and that there was
+ * a pending wakeup at the time of the call. The caller was not put
+ * asleep at all.
+ * 
+ * ESYNCH_OK_BLOCKED means that the sleep succeeded; the full sleep was 
+ * attempted.
+ */
+int waitq_sleep_timeout(waitq_t *wq, __u32 usec, int nonblocking)
+{
+	volatile ipl_t ipl; /* must be live after context_restore() */
+	
+	
+restart:
+	ipl = interrupts_disable();
+	
+	/*
+	 * Busy waiting for a delayed timeout.
+	 * This is an important fix for the race condition between
+	 * a delayed timeout and a next call to waitq_sleep_timeout().
+	 * Simply, the thread is not allowed to go to sleep if
+	 * there are timeouts in progress.
+	 */
+	spinlock_lock(&THREAD->lock);
+	if (THREAD->timeout_pending) {
+		spinlock_unlock(&THREAD->lock);
+		interrupts_restore(ipl);		
+		goto restart;
+	}
+	spinlock_unlock(&THREAD->lock);
+	
+	spinlock_lock(&wq->lock);
+	
+	/* checks whether to go to sleep at all */
+	if (wq->missed_wakeups) {
+		wq->missed_wakeups--;
+		spinlock_unlock(&wq->lock);
+		interrupts_restore(ipl);
+		return ESYNCH_OK_ATOMIC;
+	}
+	else {
+		if (nonblocking && (usec == 0)) {
+			/* return immediatelly instead of going to sleep */
+			spinlock_unlock(&wq->lock);
+			interrupts_restore(ipl);
+			return ESYNCH_WOULD_BLOCK;
+		}
+	}
+
+	
+	/*
+	 * Now we are firmly decided to go to sleep.
+	 */
+	spinlock_lock(&THREAD->lock);
+	if (usec) {
+		/* We use the timeout variant. */
+		if (!context_save(&THREAD->sleep_timeout_context)) {
+			/*
+			 * Short emulation of scheduler() return code.
+			 */
+			before_thread_runs();
+			spinlock_unlock(&THREAD->lock);
+			interrupts_restore(ipl);
+			return ESYNCH_TIMEOUT;
+		}
+		THREAD->timeout_pending = 1;
+		timeout_register(&THREAD->sleep_timeout, (__u64) usec, waitq_interrupted_sleep, THREAD);
+	}
+
+	list_append(&THREAD->wq_link, &wq->head);
+
+	/*
+	 * Suspend execution.
+	 */
+	THREAD->state = Sleeping;
+	THREAD->sleep_queue = wq;
+
+	spinlock_unlock(&THREAD->lock);
+
+	scheduler(); 	/* wq->lock is released in scheduler_separated_stack() */
+	interrupts_restore(ipl);
+	
+	return ESYNCH_OK_BLOCKED;
+}
+
+
+/** Wake up first thread sleeping in a wait queue
+ *
+ * Wake up first thread sleeping in a wait queue.
+ * This is the SMP- and IRQ-safe wrapper meant for
+ * general use.
+ *
+ * Besides its 'normal' wakeup operation, it attempts
+ * to unregister possible timeout.
+ *
+ * @param wq Pointer to wait queue.
+ * @param all If this is non-zero, all sleeping threads
+ *        will be woken up and missed count will be zeroed.
+ */
+void waitq_wakeup(waitq_t *wq, int all)
+{
+	ipl_t ipl;
+
+	ipl = interrupts_disable();
+	spinlock_lock(&wq->lock);
+
+	_waitq_wakeup_unsafe(wq, all);
+
+	spinlock_unlock(&wq->lock);	
+	interrupts_restore(ipl);	
+}
+
+/** Internal SMP- and IRQ-unsafe version of waitq_wakeup()
+ *
+ * This is the internal SMP- and IRQ-unsafe version
+ * of waitq_wakeup(). It assumes wq->lock is already
+ * locked and interrupts are already disabled.
+ *
+ * @param wq Pointer to wait queue.
+ * @param all If this is non-zero, all sleeping threads
+ *        will be woken up and missed count will be zeroed.
+ */
+void _waitq_wakeup_unsafe(waitq_t *wq, int all)
+{
+	thread_t *t;
+
+loop:	
+	if (list_empty(&wq->head)) {
+		wq->missed_wakeups++;
+		if (all) wq->missed_wakeups = 0;
+		return;
+	}
+
+	t = list_get_instance(wq->head.next, thread_t, wq_link);
+	
+	list_remove(&t->wq_link);
+	spinlock_lock(&t->lock);
+	if (t->timeout_pending && timeout_unregister(&t->sleep_timeout))
+		t->timeout_pending = 0;
+	t->sleep_queue = NULL;
+	spinlock_unlock(&t->lock);
+
+	thread_ready(t);
+
+	if (all) goto loop;
+}
Index: generic/src/time/clock.c
===================================================================
--- generic/src/time/clock.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/time/clock.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <time/clock.h>
+#include <time/timeout.h>
+#include <arch/types.h>
+#include <config.h>
+#include <synch/spinlock.h>
+#include <synch/waitq.h>
+#include <func.h>
+#include <proc/scheduler.h>
+#include <cpu.h>
+#include <print.h>
+#include <arch.h>
+#include <list.h>
+#include <arch/atomic.h>
+#include <proc/thread.h>
+
+/** Clock routine
+ *
+ * Clock routine executed from clock interrupt handler
+ * (assuming interrupts_disable()'d). Runs expired timeouts
+ * and preemptive scheduling.
+ *
+ */
+void clock(void)
+{
+	link_t *l;
+	timeout_t *h;
+	timeout_handler_t f;
+	void *arg;
+
+	/*
+	 * To avoid lock ordering problems,
+	 * run all expired timeouts as you visit them.
+	 */
+	spinlock_lock(&CPU->timeoutlock);
+	while ((l = CPU->timeout_active_head.next) != &CPU->timeout_active_head) {
+		h = list_get_instance(l, timeout_t, link);
+		spinlock_lock(&h->lock);
+		if (h->ticks-- != 0) {
+			spinlock_unlock(&h->lock);
+			break;
+		}
+		list_remove(l);
+		f = h->handler;
+		arg = h->arg;
+		timeout_reinitialize(h);
+		spinlock_unlock(&h->lock);	
+		spinlock_unlock(&CPU->timeoutlock);
+
+		f(arg);
+
+		spinlock_lock(&CPU->timeoutlock);
+	}
+	spinlock_unlock(&CPU->timeoutlock);
+
+	/*
+	 * Do CPU usage accounting and find out whether to preempt THREAD.
+	 */
+
+	if (THREAD) {
+		__u64 ticks;
+		
+		spinlock_lock(&CPU->lock);
+		CPU->needs_relink++;
+		spinlock_unlock(&CPU->lock);	
+	
+		spinlock_lock(&THREAD->lock);
+		if (ticks = THREAD->ticks)
+			THREAD->ticks--;
+		spinlock_unlock(&THREAD->lock);
+		
+		if (!ticks && !PREEMPTION_DISABLED) {
+			scheduler();
+		}
+	}
+
+}
Index: generic/src/time/delay.c
===================================================================
--- generic/src/time/delay.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/time/delay.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <time/delay.h>
+#include <arch/types.h>
+#include <cpu.h>
+#include <arch/asm.h>
+#include <arch.h>
+
+/** Active delay
+ *
+ * Delay the execution for the given number
+ * of microseconds (or slightly more). The delay
+ * is implemented as CPU calibrated active loop.
+ *
+ * @param usec Number of microseconds to sleep.
+ */
+void delay(__u32 usec)
+{
+	ipl_t ipl;
+	
+	/* 
+	 * The delay loop is calibrated for each and every
+	 * CPU in the system. Therefore it is necessary to
+	 * call interrupts_disable() before calling the
+	 * asm_delay_loop().
+	 */
+	ipl = interrupts_disable();
+	asm_delay_loop(usec * CPU->delay_loop_const);
+	interrupts_restore(ipl);
+}
Index: generic/src/time/timeout.c
===================================================================
--- generic/src/time/timeout.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
+++ generic/src/time/timeout.c	(revision 169c408f8774661800aa0a9685c9914cbb5a974c)
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <time/timeout.h>
+#include <typedefs.h>
+#include <arch/types.h>
+#include <config.h>
+#include <panic.h>
+#include <synch/spinlock.h>
+#include <func.h>
+#include <cpu.h>
+#include <print.h>
+#include <arch/asm.h>
+#include <arch.h>
+#include <print.h>
+
+
+/** Initialize timeouts
+ *
+ * Initialize kernel timeouts.
+ *
+ */
+void timeout_init(void)
+{
+	spinlock_initialize(&CPU->timeoutlock);
+	list_initialize(&CPU->timeout_active_head);
+}
+
+
+/** Reinitialize timeout 
+ *
+ * Initialize all members except the lock.
+ *
+ * @param t Timeout to be initialized.
+ *
+ */
+void timeout_reinitialize(timeout_t *t)
+{
+	t->cpu = NULL;
+	t->ticks = 0;
+	t->handler = NULL;
+	t->arg = NULL;
+	link_initialize(&t->link);
+}
+
+
+/** Initialize timeout
+ *
+ * Initialize all members including the lock.
+ *
+ * @param t Timeout to be initialized.
+ *
+ */
+void timeout_initialize(timeout_t *t)
+{
+	spinlock_initialize(&t->lock);
+	timeout_reinitialize(t);
+}
+
+
+/** Register timeout
+ *
+ * Insert timeout handler f (with argument arg)
+ * to timeout list and make it execute in
+ * time microseconds (or slightly more).
+ *
+ * @param t    Timeout structure.
+ * @param time Number of usec in the future to execute
+ *             the handler.
+ * @param f    Timeout handler function.
+ * @param arg  Timeout handler argument.
+ *
+ */
+void timeout_register(timeout_t *t, __u64 time, timeout_handler_t f, void *arg)
+{
+	timeout_t *hlp;
+	link_t *l, *m;
+	ipl_t ipl;
+	__u64 sum;
+
+	ipl = interrupts_disable();
+	spinlock_lock(&CPU->timeoutlock);
+	spinlock_lock(&t->lock);
+
+	if (t->cpu)
+		panic("t->cpu != 0");
+
+	t->cpu = CPU;
+	t->ticks = us2ticks(time);
+	
+	t->handler = f;
+	t->arg = arg;
+
+	/*
+	 * Insert t into the active timeouts list according to t->ticks.
+	 */
+	sum = 0;
+	l = CPU->timeout_active_head.next;
+	while (l != &CPU->timeout_active_head) {
+		hlp = list_get_instance(l, timeout_t, link);
+		spinlock_lock(&hlp->lock);
+		if (t->ticks < sum + hlp->ticks) {
+			spinlock_unlock(&hlp->lock);
+			break;
+		}
+		sum += hlp->ticks;
+		spinlock_unlock(&hlp->lock);
+		l = l->next;
+	}
+
+	m = l->prev;
+	list_prepend(&t->link, m); /* avoid using l->prev */
+
+	/*
+	 * Adjust t->ticks according to ticks accumulated in h's predecessors.
+	 */
+	t->ticks -= sum;
+
+	/*
+	 * Decrease ticks of t's immediate succesor by t->ticks.
+	 */
+	if (l != &CPU->timeout_active_head) {
+		spinlock_lock(&hlp->lock);
+		hlp->ticks -= t->ticks;
+		spinlock_unlock(&hlp->lock);
+	}
+
+	spinlock_unlock(&t->lock);
+	spinlock_unlock(&CPU->timeoutlock);
+	interrupts_restore(ipl);
+}
+
+
+/** Unregister timeout
+ *
+ * Remove timeout from timeout list.
+ *
+ * @param t Timeout to unregister.
+ *
+ * @return true on success, false on failure.
+ */
+bool timeout_unregister(timeout_t *t)
+{
+	timeout_t *hlp;
+	link_t *l;
+	ipl_t ipl;
+
+grab_locks:
+	ipl = interrupts_disable();
+	spinlock_lock(&t->lock);
+	if (!t->cpu) {
+		spinlock_unlock(&t->lock);
+		interrupts_restore(ipl);
+		return false;
+	}
+	if (!spinlock_trylock(&t->cpu->timeoutlock)) {
+		spinlock_unlock(&t->lock);
+		interrupts_restore(ipl);		
+		goto grab_locks;
+	}
+	
+	/*
+	 * Now we know for sure that t hasn't been activated yet
+	 * and is lurking in t->cpu->timeout_active_head queue.
+	 */
+
+	l = t->link.next;
+	if (l != &t->cpu->timeout_active_head) {
+		hlp = list_get_instance(l, timeout_t, link);
+		spinlock_lock(&hlp->lock);
+		hlp->ticks += t->ticks;
+		spinlock_unlock(&hlp->lock);
+	}
+	
+	list_remove(&t->link);
+	spinlock_unlock(&t->cpu->timeoutlock);
+
+	timeout_reinitialize(t);
+	spinlock_unlock(&t->lock);
+
+	interrupts_restore(ipl);
+	return true;
+}
