Index: uspace/kbd/Makefile
===================================================================
--- uspace/kbd/Makefile	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/kbd/Makefile	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -33,4 +33,5 @@
 SOFTINT_PREFIX = ../softint
 include $(LIBC_PREFIX)/Makefile.toolchain 
+include ../../Makefile.config
 
 CFLAGS += -Iinclude -I../libadt/include
@@ -71,4 +72,10 @@
 		genarch/src/kbd.c
 endif
+ifeq ($(ARCH), arm32)
+ifeq ($(MACHINE), gxemul_testarm)
+	ARCH_SOURCES += \
+		arch/$(ARCH)/src/kbd_gxemul.c
+endif
+endif
 
 
Index: uspace/kbd/arch/arm32/include/kbd.h
===================================================================
--- uspace/kbd/arch/arm32/include/kbd.h	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/kbd/arch/arm32/include/kbd.h	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2007 Michal Kebrt
  * All rights reserved.
  *
@@ -27,10 +27,9 @@
  */
 
-/** @addtogroup kbdarm32 arm32
- * @brief	HelenOS arm32 arch dependent parts of uspace keyboard handler.
- * @ingroup  kbd
+/** @addtogroup kbdarm32
  * @{
  */ 
 /** @file
+ *  @brief Empty.
  */
 
Index: uspace/kbd/arch/arm32/src/kbd.c
===================================================================
--- uspace/kbd/arch/arm32/src/kbd.c	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/kbd/arch/arm32/src/kbd.c	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2006 Martin Decky
+ * Copyright (c) 2007 Michal Kebrt
  * All rights reserved.
  *
@@ -33,22 +33,7 @@
  */ 
 /** @file
+ *  @brief Empty, required by generic Makefile.
  */
 
-#include <arch/kbd.h>
-#include <ipc/ipc.h>
-#include <sysinfo.h>
-#include <kbd.h>
-#include <keys.h>
-
-int kbd_arch_init(void)
-{
-	return 0;
-}
-
-
-int kbd_arch_process(keybuffer_t *keybuffer, ipc_call_t *call) 
-{
-	return 1;
-}
 
 /** @}
Index: uspace/kbd/arch/arm32/src/kbd_gxemul.c
===================================================================
--- uspace/kbd/arch/arm32/src/kbd_gxemul.c	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
+++ uspace/kbd/arch/arm32/src/kbd_gxemul.c	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -0,0 +1,424 @@
+/*
+ * Copyright (c) 2007 Michal Kebrt
+ * 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.
+ */
+
+/** @addtogroup kbdarm32gxemul GXemul
+ * @brief	HelenOS arm32 GXEmul uspace keyboard handler.
+ * @ingroup  kbdarm32
+ * @{
+ */ 
+/** @file
+ *  @brief GXemul uspace keyboard handler.
+ */
+
+#include <ipc/ipc.h>
+#include <sysinfo.h>
+#include <kbd.h>
+#include <keys.h>
+#include <bool.h>
+
+
+/* GXemul key codes in no-framebuffer mode. */
+#define GXEMUL_KEY_F1  0x504f1bL
+#define GXEMUL_KEY_F2  0x514f1bL
+#define GXEMUL_KEY_F3  0x524f1bL
+#define GXEMUL_KEY_F4  0x534f1bL
+#define GXEMUL_KEY_F5  0x35315b1bL
+#define GXEMUL_KEY_F6  0x37315b1bL
+#define GXEMUL_KEY_F7  0x38315b1bL
+#define GXEMUL_KEY_F8  0x39315b1bL
+#define GXEMUL_KEY_F9  0x30325b1bL
+#define GXEMUL_KEY_F10 0x31325b1bL
+#define GXEMUL_KEY_F11 0x33325d1bL
+#define GXEMUL_KEY_F12 0x34325b1bL 
+
+/** Start code of F5-F12 keys. */
+#define GXEMUL_KEY_F5_F12_START_CODE 0x7e
+
+/* GXemul key codes in framebuffer mode. */
+#define GXEMUL_FB_KEY_F1 0x504f5b1bL
+#define GXEMUL_FB_KEY_F2 0x514f5b1bL
+#define GXEMUL_FB_KEY_F3 0x524f5b1bL
+#define GXEMUL_FB_KEY_F4 0x534f5b1bL
+#define GXEMUL_FB_KEY_F5 0x35315b1bL
+#define GXEMUL_FB_KEY_F6 0x37315b1bL
+#define GXEMUL_FB_KEY_F7 0x38315b1bL
+#define GXEMUL_FB_KEY_F8 0x39315b1bL
+#define GXEMUL_FB_KEY_F9 0x38325b1bL
+#define GXEMUL_FB_KEY_F10 0x39325b1bL
+#define GXEMUL_FB_KEY_F11 0x33325b1bL
+#define GXEMUL_FB_KEY_F12 0x34325b1bL
+
+
+/** Function keys start code (F1=0x101) */
+#define FUNCTION_KEYS 0x100
+
+static irq_cmd_t gxemul_cmds[] = {
+	{ 
+		CMD_MEM_READ_1, 
+		(void *) 0, 
+		0, 
+		2
+	}
+};
+
+static irq_code_t gxemul_kbd = {
+	1,
+	gxemul_cmds
+};
+
+
+/** Framebuffer switched on. */
+static bool fb;
+
+
+/*
+// Please preserve this code (it can be used to determine scancodes)
+int to_hex(int v) 
+{
+        return "0123456789ABCDEF"[v];
+}
+*/
+
+
+/** Process data sent when a key is pressed (in no-framebuffer mode).
+ *  
+ *  @param keybuffer Buffer of pressed key.
+ *  @param scan_code Scan code.
+ *
+ *  @return Always 1.
+ */
+static int gxemul_kbd_process_no_fb(keybuffer_t *keybuffer, int scan_code)
+{
+	// holds at most 4 latest scan codes
+	static unsigned long buf = 0;
+
+	// number of scan codes in #buf
+	static int count = 0;	
+
+	/*
+	// Preserve for detecting scan codes. 
+	keybuffer_push(keybuffer, to_hex((scan_code>>4)&0xf));
+	keybuffer_push(keybuffer, to_hex(scan_code&0xf));
+	keybuffer_push(keybuffer, 'X');
+	keybuffer_push(keybuffer, 'Y');
+	return 1;
+	*/
+
+	if (scan_code == '\r') {
+		scan_code = '\n';
+	}
+	
+	if (scan_code == GXEMUL_KEY_F5_F12_START_CODE) {
+		switch (buf) {
+		case GXEMUL_KEY_F5:
+			keybuffer_push(keybuffer,FUNCTION_KEYS | 5);
+			buf = count = 0;
+			return 1;
+		case GXEMUL_KEY_F6:
+			keybuffer_push(keybuffer,FUNCTION_KEYS | 6);
+			buf = count = 0;
+			return 1;
+		case GXEMUL_KEY_F7:
+			keybuffer_push(keybuffer,FUNCTION_KEYS | 7);
+			buf = count = 0;
+			return 1;
+		case GXEMUL_KEY_F8:
+			keybuffer_push(keybuffer,FUNCTION_KEYS | 8);
+			buf = count = 0;
+			return 1;
+		case GXEMUL_KEY_F9:
+			keybuffer_push(keybuffer,FUNCTION_KEYS | 9);
+			buf = count = 0;
+			return 1;
+		case GXEMUL_KEY_F10:
+			keybuffer_push(keybuffer,FUNCTION_KEYS | 10);
+			buf = count = 0;
+			return 1;
+		case GXEMUL_KEY_F11:
+			keybuffer_push(keybuffer,FUNCTION_KEYS | 11);
+			buf = count = 0;
+			return 1;
+		case GXEMUL_KEY_F12:
+			keybuffer_push(keybuffer,FUNCTION_KEYS | 12);
+			buf = count = 0;
+			return 1;
+		default:
+			keybuffer_push(keybuffer, buf & 0xff);
+			keybuffer_push(keybuffer, (buf >> 8)  & 0xff);
+			keybuffer_push(keybuffer, (buf >> 16) & 0xff);
+			keybuffer_push(keybuffer, (buf >> 24) & 0xff);
+			keybuffer_push(keybuffer, scan_code);
+			buf = count = 0;
+			return 1;
+		}
+	}
+
+	// add to buffer
+	buf |= ((unsigned long) scan_code) << (8 * (count++));
+	
+	if ((buf & 0xff) != (GXEMUL_KEY_F1 & 0xff)) {
+		keybuffer_push(keybuffer, buf);
+		buf = count = 0;
+		return 1;
+	}
+
+	if (count <= 1) { 
+		return 1;
+	}
+
+	if ((buf & 0xffff) != (GXEMUL_KEY_F1 & 0xffff) 
+		&& (buf & 0xffff) != (GXEMUL_KEY_F5 & 0xffff) ) {
+
+		keybuffer_push(keybuffer, buf & 0xff);
+		keybuffer_push(keybuffer, (buf >> 8) &0xff);
+		buf = count = 0;
+		return 1;
+	}
+
+	if (count <= 2) {
+		return 1;
+	}
+
+	switch (buf) {
+	case GXEMUL_KEY_F1:
+		keybuffer_push(keybuffer,FUNCTION_KEYS | 1);
+		buf = count = 0;
+		return 1;
+	case GXEMUL_KEY_F2:
+		keybuffer_push(keybuffer,FUNCTION_KEYS | 2);
+		buf = count = 0;
+		return 1;
+	case GXEMUL_KEY_F3:
+		keybuffer_push(keybuffer,FUNCTION_KEYS | 3);
+		buf = count = 0;
+		return 1;
+	case GXEMUL_KEY_F4:
+		keybuffer_push(keybuffer,FUNCTION_KEYS | 4);
+		buf = count = 0;
+		return 1;
+	}
+
+
+	if ((buf & 0xffffff) != (GXEMUL_KEY_F5 & 0xffffff)
+		&& (buf & 0xffffff) != (GXEMUL_KEY_F9 & 0xffffff)) {
+
+		keybuffer_push(keybuffer, buf & 0xff);
+		keybuffer_push(keybuffer, (buf >> 8) & 0xff);
+		keybuffer_push(keybuffer, (buf >> 16) & 0xff);
+		buf = count = 0;
+		return 1;
+	}
+
+	if (count <= 3) {
+		return 1;
+	}
+	
+	switch (buf) {
+	case GXEMUL_KEY_F5:
+	case GXEMUL_KEY_F6:
+	case GXEMUL_KEY_F7:
+	case GXEMUL_KEY_F8:
+	case GXEMUL_KEY_F9:
+	case GXEMUL_KEY_F10:
+	case GXEMUL_KEY_F11:
+	case GXEMUL_KEY_F12:
+		return 1;
+	default:
+		keybuffer_push(keybuffer, buf & 0xff);
+		keybuffer_push(keybuffer, (buf >> 8)  & 0xff);
+		keybuffer_push(keybuffer, (buf >> 16) & 0xff);
+		keybuffer_push(keybuffer, (buf >> 24) & 0xff);
+		buf = count = 0;
+		return 1;
+	}
+
+	return 1;
+}
+
+
+/** Process data sent when a key is pressed (in framebuffer mode).
+ *  
+ *  @param keybuffer Buffer of pressed keys.
+ *  @param scan_code Scan code.
+ *
+ *  @return Always 1.
+ */
+static int gxemul_kbd_process_fb(keybuffer_t *keybuffer, int scan_code)
+{
+	// holds at most 4 latest scan codes
+	static unsigned long buf = 0;
+
+	// number of scan codes in #buf
+	static int count = 0;	
+
+	/*
+	// Please preserve this code (it can be used to determine scancodes)
+	keybuffer_push(keybuffer, to_hex((scan_code>>4)&0xf));
+	keybuffer_push(keybuffer, to_hex(scan_code&0xf));
+	keybuffer_push(keybuffer, ' ');
+	keybuffer_push(keybuffer, ' ');
+	return 1;
+	*/
+	
+	if (scan_code == '\r') {
+		scan_code = '\n';
+	}
+	
+	// add to buffer
+	buf |= ((unsigned long) scan_code) << (8*(count++));
+	
+	
+	if ((buf & 0xff) != (GXEMUL_FB_KEY_F1 & 0xff)) {
+		keybuffer_push(keybuffer, buf);
+		buf = count = 0;
+		return 1;
+	}
+
+	if (count <= 1) {
+		return 1;
+	}
+
+	if ((buf & 0xffff) != (GXEMUL_FB_KEY_F1 & 0xffff)) {
+		keybuffer_push(keybuffer, buf & 0xff);
+		keybuffer_push(keybuffer, (buf >> 8) &0xff);
+		buf = count = 0;
+		return 1;
+	}
+
+	if (count <= 2) {
+		return 1;
+	}
+
+	if ((buf & 0xffffff) != (GXEMUL_FB_KEY_F1 & 0xffffff)
+		&& (buf & 0xffffff) != (GXEMUL_FB_KEY_F5 & 0xffffff)
+		&& (buf & 0xffffff) != (GXEMUL_FB_KEY_F9 & 0xffffff)) {
+
+		keybuffer_push(keybuffer, buf & 0xff);
+		keybuffer_push(keybuffer, (buf >> 8) & 0xff);
+		keybuffer_push(keybuffer, (buf >> 16) & 0xff);
+		buf = count = 0;
+		return 1;
+	}
+
+	if (count <= 3) {
+		return 1;
+	}
+
+	switch (buf) {
+	case GXEMUL_FB_KEY_F1:
+		keybuffer_push(keybuffer,FUNCTION_KEYS | 1 );
+		buf = count = 0;
+		return 1;
+	case GXEMUL_FB_KEY_F2:
+		keybuffer_push(keybuffer,FUNCTION_KEYS | 2 );
+		buf = count = 0;
+		return 1;
+	case GXEMUL_FB_KEY_F3:
+		keybuffer_push(keybuffer,FUNCTION_KEYS | 3 );
+		buf = count = 0;
+		return 1;
+	case GXEMUL_FB_KEY_F4:
+		keybuffer_push(keybuffer,FUNCTION_KEYS | 4 );
+		buf = count = 0;
+		return 1;
+	case GXEMUL_FB_KEY_F5:
+		keybuffer_push(keybuffer,FUNCTION_KEYS | 5 );
+		buf = count = 0;
+		return 1;
+	case GXEMUL_FB_KEY_F6:
+		keybuffer_push(keybuffer,FUNCTION_KEYS | 6 );
+		buf = count = 0;
+		return 1;
+	case GXEMUL_FB_KEY_F7:
+		keybuffer_push(keybuffer,FUNCTION_KEYS | 7 );
+		buf = count = 0;
+		return 1;
+	case GXEMUL_FB_KEY_F8:
+		keybuffer_push(keybuffer,FUNCTION_KEYS | 8 );
+		buf = count = 0;
+		return 1;
+	case GXEMUL_FB_KEY_F9:
+		keybuffer_push(keybuffer,FUNCTION_KEYS | 9 );
+		buf = count = 0;
+		return 1;
+	case GXEMUL_FB_KEY_F10:
+		keybuffer_push(keybuffer,FUNCTION_KEYS | 10 );
+		buf = count = 0;
+		return 1;
+	case GXEMUL_FB_KEY_F11:
+		keybuffer_push(keybuffer,FUNCTION_KEYS | 11 );
+		buf = count = 0;
+		return 1;
+	case GXEMUL_FB_KEY_F12:
+		keybuffer_push(keybuffer,FUNCTION_KEYS | 12 );
+		buf = count = 0;
+		return 1;
+	default:
+		keybuffer_push(keybuffer, buf & 0xff );
+		keybuffer_push(keybuffer, (buf >> 8)  & 0xff);
+		keybuffer_push(keybuffer, (buf >> 16) & 0xff);
+		keybuffer_push(keybuffer, (buf >> 24) & 0xff);
+		buf = count = 0;
+		return 1;
+	}
+
+	return 1;
+}
+
+
+/** Initializes keyboard handler. */
+int kbd_arch_init(void)
+{
+	fb = (sysinfo_value("fb.kind") == 1);
+	gxemul_cmds[0].addr = (void *) sysinfo_value("kbd.address.virtual");
+	ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), 0, &gxemul_kbd);
+	return 0;
+}
+
+
+/** Process data sent when a key is pressed.
+ *  
+ *  @param keybuffer Buffer of pressed keys.
+ *  @param call      IPC call.
+ *
+ *  @return Always 1.
+ */
+int kbd_arch_process(keybuffer_t *keybuffer, ipc_call_t *call) 
+{
+	int scan_code = IPC_GET_ARG2(*call);
+
+	if (fb) {
+		return gxemul_kbd_process_fb(keybuffer, scan_code);
+	} else {
+		return gxemul_kbd_process_no_fb(keybuffer, scan_code);
+	}
+
+}
+
+/** @}
+ */
Index: uspace/libc/arch/arm32/Makefile.inc
===================================================================
--- uspace/libc/arch/arm32/Makefile.inc	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/libc/arch/arm32/Makefile.inc	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -1,4 +1,4 @@
 #
-# Copyright (c) 2005 Martin Decky
+# Copyright (c) 2007 Michal Kebrt, Pavel Jancik
 # All rights reserved.
 #
@@ -32,5 +32,5 @@
 TARGET = arm-linux-gnu
 TOOLCHAIN_DIR = /usr/local/arm/bin
-CFLAGS += 
+CFLAGS += -ffixed-r9 -mtp=soft 
 LFLAGS += -N ../softint/libsoftint.a
 AFLAGS += 
@@ -39,5 +39,5 @@
 		arch/$(ARCH)/src/psthread.S \
 		arch/$(ARCH)/src/thread.c \
-		arch/$(ARCH)/src/dummy.S
+		arch/$(ARCH)/src/eabi.S
 
 BFD_NAME = elf32-little
Index: uspace/libc/arch/arm32/_link.ld.in
===================================================================
--- uspace/libc/arch/arm32/_link.ld.in	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/libc/arch/arm32/_link.ld.in	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -8,23 +8,20 @@
 
 SECTIONS {
-	. = 0x2000;
+	. = 0x1000;
 
-	.init ALIGN(0x2000): SUBALIGN(0x2000) {
+	.init ALIGN(0x1000): SUBALIGN(0x1000) {
 		*(.init);
 	} : text
 	.text : {
 		*(.text);
-		*(.rodata*);
+        *(.rodata*);
 	} :text
-
-	.got ALIGN(0x2000) : SUBALIGN(0x2000) {
-		_gp = .;
-		*(.got*);
-	} :data	
-	.data : {
+	
+	.data ALIGN(0x1000) : SUBALIGN(0x1000) {
 		*(.opd);
 		*(.data .data.*);
 		*(.sdata);
 	} :data
+
 	.tdata : {
 		_tdata_start = .;
@@ -32,4 +29,5 @@
 		_tdata_end = .;
 	} :data
+
 	.tbss : {
 		_tbss_start = .;
@@ -37,16 +35,18 @@
 		_tbss_end = .;
 	} :data
+
 	.bss : {
 		*(.sbss);
 		*(.scommon);
-		*(COMMON);
-		*(.bss);
+        *(COMMON);
+        *(.bss);
 	} :data
-
-	. = ALIGN(0x2000);
+	
+	. = ALIGN(0x1000);
 	_heap = .;
- 
+	
 	/DISCARD/ : {
 		*(*);
-        }
+	}
+
 }
Index: uspace/libc/arch/arm32/include/atomic.h
===================================================================
--- uspace/libc/arch/arm32/include/atomic.h	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/libc/arch/arm32/include/atomic.h	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2005 Jakub Jermar
+ * Copyright (c) 2007 Michal Kebrt
  * All rights reserved.
  *
@@ -31,4 +31,5 @@
  */
 /** @file
+ *  @brief Atomic operations.
  */
 
@@ -38,23 +39,77 @@
 /** Atomic addition.
  *
- * @param val Atomic value.
- * @param imm Value to add.
+ * @param val Where to add.
+ * @param i   Value to be added.
  *
  * @return Value after addition.
  */
-static inline long atomic_add(atomic_t *val, int imm)
+static inline long atomic_add(atomic_t *val, int i)
 {
-	/* TODO */
-	return (val->count += imm);
+	int ret;
+	volatile long * mem = &(val->count);
+
+	asm volatile (
+		"1:                 \n"
+		"ldr r2, [%1]       \n"
+		"add r3, r2, %2     \n"
+		"str r3, %0         \n"
+		"swp r3, r3, [%1]   \n"
+		"cmp r3, r2         \n"
+		"bne 1b             \n"
+
+		: "=m" (ret)
+		: "r" (mem), "r" (i)
+		: "r3", "r2"
+	);
+
+	return ret;
 }
 
+
+/** Atomic increment.
+ *
+ * @param val Variable to be incremented.
+ */
 static inline void atomic_inc(atomic_t *val) { atomic_add(val, 1); }
+
+
+/** Atomic decrement.
+ *
+ * @param val Variable to be decremented.
+ */
 static inline void atomic_dec(atomic_t *val) { atomic_add(val, -1); }
 
-static inline long atomic_preinc(atomic_t *val) { return atomic_add(val, 1) + 1; }
-static inline long atomic_predec(atomic_t *val) { return atomic_add(val, -1) - 1; }
 
-static inline long atomic_postinc(atomic_t *val) { return atomic_add(val, 1); }
-static inline long atomic_postdec(atomic_t *val) { return atomic_add(val, -1); }
+/** Atomic pre-increment.
+ *
+ * @param val Variable to be incremented.
+ * @return    Value after incrementation.
+ */
+static inline long atomic_preinc(atomic_t *val) { return atomic_add(val, 1); }
+
+
+/** Atomic pre-decrement.
+ *
+ * @param val Variable to be decremented.
+ * @return    Value after decrementation.
+ */
+static inline long atomic_predec(atomic_t *val) { return atomic_add(val, -1); }
+
+
+/** Atomic post-increment.
+ *
+ * @param val Variable to be incremented.
+ * @return    Value before incrementation.
+ */
+static inline long atomic_postinc(atomic_t *val) { return atomic_add(val, 1) - 1; }
+
+
+/** Atomic post-decrement.
+ *
+ * @param val Variable to be decremented.
+ * @return    Value before decrementation.
+ */
+static inline long atomic_postdec(atomic_t *val) { return atomic_add(val, -1) + 1; }
+
 
 #endif
Index: uspace/libc/arch/arm32/include/config.h
===================================================================
--- uspace/libc/arch/arm32/include/config.h	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/libc/arch/arm32/include/config.h	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -30,5 +30,6 @@
  * @{
  */
-/** @file
+/** @file  
+ *  @brief Configuration constants.
  */
 
Index: uspace/libc/arch/arm32/include/endian.h
===================================================================
--- uspace/libc/arch/arm32/include/endian.h	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/libc/arch/arm32/include/endian.h	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -30,5 +30,6 @@
  * @{
  */
-/** @file
+/** @file 
+ *  @brief Endianness definition.
  */
 
Index: uspace/libc/arch/arm32/include/faddr.h
===================================================================
--- uspace/libc/arch/arm32/include/faddr.h	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/libc/arch/arm32/include/faddr.h	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2005 Jakub Jermar
+ * Copyright (c) 2007 Michal Kebrt
  * All rights reserved.
  *
@@ -30,5 +30,6 @@
  * @{
  */
-/** @file
+/** @file 
+ *  @brief Function address conversion.
  */
 
@@ -38,11 +39,7 @@
 #include <libarch/types.h>
 
-/** 
- *
- * Calculate absolute address of function
- * referenced by fptr pointer.
+/** Calculate absolute address of function referenced by fptr pointer.
  *
  * @param f Function pointer.
- *
  */
 #define FADDR(f)	 (f)
Index: uspace/libc/arch/arm32/include/limits.h
===================================================================
--- uspace/libc/arch/arm32/include/limits.h	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/libc/arch/arm32/include/limits.h	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2007 Michal Kebrt
  * All rights reserved.
  *
@@ -30,6 +30,6 @@
  * @{
  */
-/** @file
- * @ingroup libcarm32	
+/** @file 
+ *  @brief Limits declarations.
  */
 
@@ -37,8 +37,8 @@
 #define LIBC_arm32__LIMITS_H_
 
-# define LONG_MIN MIN_INT32
-# define LONG_MAX MAX_INT32
-# define ULONG_MIN MIN_UINT32
-# define ULONG_MAX MAX_UINT32
+#define LONG_MIN MIN_INT32
+#define LONG_MAX MAX_INT32
+#define ULONG_MIN MIN_UINT32
+#define ULONG_MAX MAX_UINT32
 
 #endif
Index: uspace/libc/arch/arm32/include/psthread.h
===================================================================
--- uspace/libc/arch/arm32/include/psthread.h	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/libc/arch/arm32/include/psthread.h	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2006 Ondrej Palkovsky
+ * Copyright (c) 2007 Michal Kebrt
  * All rights reserved.
  *
@@ -30,6 +30,6 @@
  * @{
  */
-/** @file
- * @ingroup libcarm32	
+/** @file 
+ *  @brief psthread related declarations.
  */
 
@@ -38,12 +38,50 @@
 
 #include <types.h>
+#include <align.h>
+#include "thread.h"
 
-#define SP_DELTA	0	/* TODO */
+/** Size of a stack item */
+#define STACK_ITEM_SIZE		4
 
+/** Stack alignment - see <a href="http://www.arm.com/support/faqdev/14269.html">ABI</a> for details */
+#define STACK_ALIGNMENT		8
+
+#define SP_DELTA	(0 + ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT))
+
+
+/** Sets data to the context. 
+ *  
+ *  @param c     Context (#context_t).
+ *  @param _pc   Program counter.
+ *  @param stack Stack address.
+ *  @param size  Stack size.
+ *  @param ptls  Pointer to the TCB.
+ */
+#define context_set(c, _pc, stack, size, ptls) 			\
+	(c)->pc = (sysarg_t) (_pc);				\
+	(c)->sp = ((sysarg_t) (stack)) + (size) - SP_DELTA; 	\
+        (c)->tls = ((sysarg_t)(ptls)) + sizeof(tcb_t) + ARM_TP_OFFSET;
+
+
+/** Thread context. 
+ *
+ *  Only registers preserved accross function calls are included. r9 is used 
+ *  to store a TLS address. -ffixed-r9 gcc forces gcc not to use this
+ *  register. -mtp=soft forces gcc to use #__aeabi_read_tp to obtain
+ *  TLS address.
+ */
 typedef struct  {
 	uint32_t sp;
 	uint32_t pc;
+	uint32_t r4;
+	uint32_t r5;
+	uint32_t r6;
+	uint32_t r7;
+	uint32_t r8;
 	uint32_t tls;
+	uint32_t r10;
+	uint32_t r11;
 } context_t;
+
 
 #endif
Index: uspace/libc/arch/arm32/include/stackarg.h
===================================================================
--- uspace/libc/arch/arm32/include/stackarg.h	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/libc/arch/arm32/include/stackarg.h	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2007 Michal Kebrt
  * All rights reserved.
  *
@@ -31,4 +31,5 @@
  */
 /** @file
+ *  @brief Empty.
  */
 
Index: uspace/libc/arch/arm32/include/syscall.h
===================================================================
--- uspace/libc/arch/arm32/include/syscall.h	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/libc/arch/arm32/include/syscall.h	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2005 Martin Decky
+ * Copyright (c) 2007 Michal Kebrt
  * All rights reserved.
  *
@@ -27,9 +27,9 @@
  */
 
-/** @addtogroup libc
+/** @addtogroup libcarm32
  * @{
  */
-/**
- * @file
+/** @file
+ *  @brief Empty.
  */
 
Index: uspace/libc/arch/arm32/include/thread.h
===================================================================
--- uspace/libc/arch/arm32/include/thread.h	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/libc/arch/arm32/include/thread.h	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2006 Jakub Jermar
+ * Copyright (c) 2007 Pavel Jancik, Michal Kebrt
  * All rights reserved.
  *
@@ -27,8 +27,9 @@
  */
 
-/** @addtogroup libcia64	
+/** @addtogroup libcarm32
  * @{
  */
 /** @file
+ *  @brief Uspace threads and TLS.
  */
 
@@ -38,21 +39,58 @@
 #include <unistd.h>
 
+/** Stack initial size. */
 #define THREAD_INITIAL_STACK_PAGES_NO 1
 
+/** Offsets for accessing __thread variables are shifted 8 bytes higher. */
+#define ARM_TP_OFFSET	(-8)
+
+/** TCB (Thread Control Block) struct. 
+ *
+ *  TLS starts just after this struct.
+ */
 typedef struct {
+	/** psthread data. */
 	void *pst_data;
-	/* TODO */
 } tcb_t;
 
+
+/** Sets TLS address to the r9 register.
+ *
+ *  @param tcb TCB (TLS starts behind)
+ */
 static inline void __tcb_set(tcb_t *tcb)
 {
-	/* TODO */
+	void *tls = (void *)tcb;
+	tls += sizeof(tcb_t) + ARM_TP_OFFSET;
+	asm volatile (
+		"mov r9, %0"
+		:
+		: "r"(tls)
+	);
 }
 
+
+/** Returns TCB address.
+ *
+ * @return TCB address (starts before TLS which address is stored in r9 register).
+ */
 static inline tcb_t *__tcb_get(void)
 {
-	/* TODO */
-	return NULL;
+	void *ret;
+	asm volatile (
+		"mov %0, r9"
+		: "=r"(ret)
+	);
+	return (tcb_t *)(ret - ARM_TP_OFFSET - sizeof(tcb_t));
 }
+
+
+/** Returns TLS address stored.
+ *
+ *  Implemented in assembly.
+ *
+ *  @return TLS address stored in r9 register
+ */
+extern uintptr_t __aeabi_read_tp(void);
 
 #endif
Index: uspace/libc/arch/arm32/include/types.h
===================================================================
--- uspace/libc/arch/arm32/include/types.h	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/libc/arch/arm32/include/types.h	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -30,6 +30,6 @@
  * @{
  */
-/** @file
- * @ingroup libcarm32
+/** @file 
+ *  @brief Definitions of basic types like #uintptr_t.
  */
 
Index: uspace/libc/arch/arm32/src/dummy.S
===================================================================
--- uspace/libc/arch/arm32/src/dummy.S	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ 	(revision )
@@ -1,35 +1,0 @@
-#
-# Copyright (c) 2007 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.
-#
-
-.text
-
-.global __aeabi_read_tp
-__aeabi_read_tp:
-
-0:
-	b 0b
Index: uspace/libc/arch/arm32/src/eabi.S
===================================================================
--- uspace/libc/arch/arm32/src/eabi.S	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
+++ uspace/libc/arch/arm32/src/eabi.S	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2007 Pavel Jancik
+# 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.
+#
+
+.text
+
+.global __aeabi_read_tp
+
+__aeabi_read_tp:
+	mov r0, r9
+	mov pc, lr
Index: uspace/libc/arch/arm32/src/entry.s
===================================================================
--- uspace/libc/arch/arm32/src/entry.s	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/libc/arch/arm32/src/entry.s	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -1,4 +1,4 @@
 #
-# Copyright (c) 2006 Jakub Jermar
+# Copyright (c) 2007 Michal Kebrt, Pavel Jancik
 # All rights reserved.
 #
@@ -29,4 +29,6 @@
 .section .init, "ax"
 
+.org 0
+
 .global __entry
 .global __entry_driver
@@ -36,6 +38,12 @@
 #
 __entry:
+	bl __main
+	bl __io_init
+	bl main
+	bl __exit
 
-#
-# TODO
-#
+__entry_driver:
+	bl __main
+	bl main
+	bl __exit
+
Index: uspace/libc/arch/arm32/src/psthread.S
===================================================================
--- uspace/libc/arch/arm32/src/psthread.S	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/libc/arch/arm32/src/psthread.S	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -1,4 +1,4 @@
 #
-# Copyright (c) 2005 Jakub Jermar
+# Copyright (c) 2007 Michal Kebrt
 # All rights reserved.
 #
@@ -33,6 +33,17 @@
 
 context_save:
-	/* TODO */
+	stmia r0!, {sp, lr}
+	stmia r0!, {r4-r11}
+
+	# return 1
+	mov r0, #1
+	mov pc, lr
 
 context_restore:
-	/* TODO */
+	ldmia r0!, {sp, lr}
+	ldmia r0!, {r4-r11}
+
+	#return 0
+	mov r0, #0
+	mov pc, lr
+
Index: uspace/libc/arch/arm32/src/syscall.c
===================================================================
--- uspace/libc/arch/arm32/src/syscall.c	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/libc/arch/arm32/src/syscall.c	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2005 Martin Decky
+ * Copyright (c) 2007 Pavel Jancik
  * All rights reserved.
  *
@@ -31,14 +31,42 @@
  */
 /** @file
-  * @ingroup libcarm32	
+ *  @brief Syscall routine.
  */
 
 #include <libc.h>
 
+
+/** Syscall routine.
+ *
+ *  Stores p1-p4, id to r0-r4 registers and calls <code>swi</code>
+ *  instruction. Returned value is read from r0 register.
+ *
+ *  @param p1 Parameter 1.
+ *  @param p2 Parameter 2.
+ *  @param p3 Parameter 3.
+ *  @param p4 Parameter 4.
+ *  @param id Number of syscall.
+ *
+ *  @return Syscall return value.
+ */
 sysarg_t __syscall(const sysarg_t p1, const sysarg_t p2, const sysarg_t p3,
     const sysarg_t p4, const syscall_t id)
 {
-	/* TODO */
-	return 0;
+	register sysarg_t __arm_reg_r0 asm("r0") = p1;
+	register sysarg_t __arm_reg_r1 asm("r1") = p2;
+	register sysarg_t __arm_reg_r2 asm("r2") = p3;
+	register sysarg_t __arm_reg_r3 asm("r3") = p4;
+	register sysarg_t __arm_reg_r4 asm("r4") = id;
+
+	asm volatile ( "swi"
+		: "=r" (__arm_reg_r0)
+		: "r"  (__arm_reg_r0),
+		  "r"  (__arm_reg_r1),
+		  "r"  (__arm_reg_r2),
+		  "r"  (__arm_reg_r3),
+		  "r"  (__arm_reg_r4)
+	);
+
+	return __arm_reg_r0;
 }
 
Index: uspace/libc/arch/arm32/src/thread.c
===================================================================
--- uspace/libc/arch/arm32/src/thread.c	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/libc/arch/arm32/src/thread.c	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2006 Ondrej Palkovsky
+ * Copyright (c) 2007 Pavel Jancik
  * All rights reserved.
  *
@@ -33,4 +33,5 @@
  */
 /** @file
+ *  @brief Uspace threads and TLS.
  */
 
@@ -38,18 +39,27 @@
 #include <malloc.h>
 
-/** Allocate TLS & TCB for initial module threads
+/** Allocates TLS & TCB.
  *
- * @param data Start of data section
- * @return pointer to tcb_t structure
+ * @param data Start of data section (output parameter).
+ * @param size Size of (tbss + tdata) sections.
+ * @return     Pointer to the allocated #tcb_t structure.
  */
 tcb_t * __alloc_tls(void **data, size_t size)
 {
-	/* TODO */
-	return NULL;
+	tcb_t *result;
+
+	result = malloc(sizeof(tcb_t) + size);
+	*data = ((void *)result) + sizeof(tcb_t);
+	return result;
 }
 
+/** Deallocates TLS & TCB.
+ *
+ * @param tcb TCB structure to be deallocated (along with corresponding TLS).
+ * @param size Not used.
+ */
 void __free_tls_arch(tcb_t *tcb, size_t size)
 {
-	/* TODO */
+	free(tcb);
 }
 
Index: uspace/libc/arch/arm32/src/thread_entry.s
===================================================================
--- uspace/libc/arch/arm32/src/thread_entry.s	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/libc/arch/arm32/src/thread_entry.s	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -35,6 +35,3 @@
 #
 __thread_entry:
-
-#
-# TODO
-#
+        b __thread_main
Index: uspace/softfloat/arch/arm32/include/functions.h
===================================================================
--- uspace/softfloat/arch/arm32/include/functions.h	(revision cb4afd8bbf37def6ce88be49db41f1a2fd01c053)
+++ uspace/softfloat/arch/arm32/include/functions.h	(revision c03ee1c304c982b593d8043411e6b003dd1c155a)
@@ -29,8 +29,9 @@
 /** @addtogroup softfloatarm32 arm32	
  * @ingroup sfl
- * @brief softfloat architecture dependent definitions 
+ * @brief Softfloat architecture dependent definitions.
  * @{
  */
-/** @file
+/** @file 
+ *  @brief Softfloat architecture dependent definitions.
  */
 
